流量防卫兵Sentinel

流量防卫兵Sentinel

前言

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性

  • Sentinel (分布式系统的流量防卫兵) 是阿里开源的一套用于服务容错的综合性解决方案.
  • Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量控制、流量路由、熔断降级、系统自适应保护等多个维度来帮助用户保障微服务的稳定性.

Sentinel的功能

流量控制

流量控制在网络传输中是一个常用的概念,它用于调整网络包的发送数据。
然而,从系统稳定性角度考虑,在处理请求的速度上,也有非常多的讲究。
任意时间到来的请求往往是随机不可控的,而系统的处理能力是有限的。
我们需要根据系统的处理能力对流量进行控制。
Sentinel 作为一个调配器,可以根据需要把随机的请求调整成合适的形状,如下图所示:
1

  • 限流方式
    • 资源的调用关系,例如资源的调用链路,资源和资源之间的关系
    • 运行指标,例如 QPS、线程池、系统负载等
    • 控制的效果,例如直接限流、冷启动、排队等

熔断, 服务降级

由于调用关系的复杂性,如果调用链路中的某个资源出现了不稳定,最终会导致请求发生堆积, 最终拖垮整条链路.
降低调用链路中的不稳定资源也是 Sentinel 的使命之一(和Hydrix类似)
2

Sentinel进行熔断的方式:

  • 限制并发线程数
    • 通过限制资源并发线程的数量,来减少不稳定资源对其它资源的影响。
    • 这样不但没有线程切换的损耗,也不需要预先分配线程池的大小。
    • 当某个资源出现不稳定的情况下,例如响应时间变长,对资源的直接影响就是会造成线程数的逐步堆积。
    • 当线程数在特定资源上堆积到一定的数量之后,对该资源的新请求就会被拒绝。
    • 堆积的线程完成任务后才开始继续接收请求
  • 通过响应时间对服务进行降级
    • 当依赖的资源出现响应时间过长后,所有对该资源的访问都会被直接拒绝,直到过了指定的时间窗口之后才重新恢复

系统负载保护

Sentinel 同时提供系统维度的自适应保护能力。
防止雪崩,是系统防护中重要的一环。
当系统负载较高的时候,如果还持续让请求进入,可能会导致系统崩溃,无法响应。
在集群环境下,网络负载均衡会把本应这台机器承载的流量转发到其它的机器上去。
如果这个时候其它的机器也处在一个边缘状态的时候,这个增加的流量就会导致这台机器也崩溃,最后导致整个集群不可用。

针对这个情况,Sentinel 提供了对应的保护机制,让系统的入口流量和系统的负载达到一个平衡,保证系统在能力范围之内处理最多的请求。


Sentinel的基本工作机制

  • 对主流框架提供适配或者显示的 API,来定义需要保护的资源,并提供设施对资源进行实时统计和调用链路分析
  • 根据预设的规则,结合对资源的实时统计信息,对流量进行控制, 同时Sentinel 提供开放的接口,方便定义及改变规则
  • Sentinel 提供实时的监控系统,方便快速了解目前系统的状态

在 Sentinel 里面,所有的资源都对应一个资源名称以及一个 Entry.
Entry 可以通过对主流框架的适配自动创建,也可以通过注解的方式或调用 API 显式创建.
每一个 Entry 创建的时候,同时也会创建一系列功能插槽(slot chain), 这些插槽有不同的职责,例如:

  • NodeSelectorSlot 负责收集资源的路径,并将这些资源的调用路径,以树状结构存储起来,用于根据调用路径来限流降级;
  • ClusterBuilderSlot 则用于存储资源的统计信息以及调用者信息,例如该资源的 RT, QPS, thread count 等等,这些信息将用作为多维度限流,降级的依据;
  • StatisticSlot 核心功能之一, 用于记录、统计不同纬度的 runtime 指标监控信息;
  • FlowSlot 则用于根据预设的限流规则以及前面 slot 统计的状态,来进行流量控制;
  • AuthoritySlot 则根据配置的黑白名单和调用来源信息,来做黑白名单控制.
  • DegradeSlot 主要针对资源的平均响应时间(RT)以及异常比率,来决定资源是否在接下来的时间被自动熔断掉.
  • SystemSlot 根据对于当前系统的整体情况,对入口资源的调用进行动态调配。其原理是让入口的流量和当前系统的预计容量达到一个动态平衡.

Sentinel的使用

Sentinel 的使用可以分为两个部分:

  • 核心库(Java 客户端):

    不依赖任何框架/库,能够运行于 Java 8 及以上的版本的运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持.
  • 控制台(Dashboard):

    Dashboard 主要负责管理推送规则、监控、管理机器信息等.

核心库

1. 引入 Sentinel 依赖

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-core</artifactId>
    <version>1.8.6</version>
</dependency>

2. 定义资源

资源 是 Sentinel 中的核心概念之一.
最常用的资源是我们代码中的 Java 方法.
把需要控制流量的代码用 Sentinel API SphU.entry("HelloWorld") 和 entry.exit() 包围起来即可

public static void main(String[] args) {
    // 配置规则.
    initFlowRules();
    while (true) {
        try (Entry entry = SphU.entry("HelloWorld")) {
            // 被保护的逻辑
            System.out.println("hello world");
	} catch (BlockException ex) {
            // 处理被流控的逻辑
	    System.out.println("blocked!");
	}
    }
}

3. 定义规则

通过流控规则来指定允许该资源通过的请求次数

private static void initFlowRules(){
    List<FlowRule> rules = new ArrayList<>();
    FlowRule rule = new FlowRule();
    rule.setResource("HelloWorld");
    rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
    // 每秒请求次数限制为20
    rule.setCount(20);
    rules.add(rule);
    FlowRuleManager.loadRules(rules);
}

Sentinel控制台

Sentinel 提供一个轻量级的开源控制台,它提供机器发现以及健康情况管理、监控(单机和集群),规则管理和推送的功能

  • 查看机器列表以及健康情况:
    收集 Sentinel 客户端发送的心跳包,用于判断机器是否在线
  • 监控 (单机和集群聚合):
    通过 Sentinel 客户端暴露的监控 API,定期拉取并且聚合应用监控信息,最终可以实现秒级的实时监控
  • 规则管理和推送:
    统一管理推送规则

下载Sentinel控制台jar包或者从源代码自行构建: https://github.com/alibaba/Sentinel/releases

1. 启动控制台

控制台地址默认为http://localhost:8080/
默认账号密码为sentinel

java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar

2. 客户端接入控制台

客户端需要引入 Transport 模块来与 Sentinel 控制台进行通信

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-transport-simple-http</artifactId>
    <version>x.y.z</version>
</dependency>

客户端启动时加入 JVM 参数 -Dcsp.sentinel.dashboard.server=consoleIp:port 指定控制台地址和端口
待客户端触发请求后, 在Sentinel控制台页面会初始化此客户端应用, 并开始向控制台发送心跳包

  • 根据适配的框架不同, 客户端接入控制台的方式也不同, 如适配SpringCloud框架:
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

且在Spring配置文件中配置Sentinel控制台信息以及使用哪个端口与控制台进行交互:

spring:
  cloud:
    sentinel:
      transport:
        # 如果8719端口冲突, 会自动向下探测可用端口
        port: 8719
        dashboard: localhost:8080

3. 查看机器列表以及监控状况

待应用在Sentinel控制台初始化后, 可以在看到应用所在机器列表以及机器状态
3

4. 实时监控

  • 多次发起调用, 在Sentinel DashBoard控制台对应的服务中点击实时监控, 可以看到当前被调用的接口的实时QPS, 请求成功率以及响应时间等
  • 同一个服务下的所有机器5分钟内的簇点信息被汇总显示, 有相关API支持获取监控数据进行持久化
    4

5. 规则管理以及规则推送

在核心库中需要编写规则对资源调度进行限流, 而在Sentinel控制台可以进行可视化配置
4
5
此过程的规则推送是通过相关API与应用内进行交互, 属于内存态, 一旦应用重启就会失效
5

  • 原始推送模式
    API 将规则推送至客户端并直接更新到内存中,扩展写数据源

    • 优点: 简单,无任何依赖
    • 缺点: 不保证一致性;规则保存在内存中,重启即消失
  • Pull模式
    扩展写数据源(WritableDataSource), 客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件等

    • 优点: 简单,无任何依赖;规则持久化
    • 缺点: 不保证一致性;实时性不保证,拉取过于频繁也可能会有性能问题
  • Push模式
    扩展读数据源(ReadableDataSource),规则中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用 Nacos、Zookeeper 等配置中心。这种方式有更好的实时性和一致性保证。生产环境下一般采用 push 模式的数据源

    • 优点: 规则持久化;一致性;快速
    • 缺点: 引入第三方依赖

参考

生产环境使用Sentinel

Sentinel快速开始

开源框架适配

SpringCloudAlibabaSentinel