官网: https://sentinelguard.io/zh-cn/docs/introduction.html
github 文档: https://github.com/alibaba/Sentinel/wiki
Sentinel 介绍
在基于 SpringCloud 构建的微服务体系中,服务间的调用链路会随着系统的演进变得越来越长,这无疑
会增加了整个系统的不可靠因素。在并发流量比较高的情况下,由于网络调用之间存在一定的超时时
间,链路中的某个服务出现宕机都会大大增加整个调用链路的响应时间,而瞬间的流量洪峰则会导致这
条链路上所有服务的可用线程资源被打满,从而造成整体服务的不可用,这也就是我们常说的 “ 雪崩效
应 ” 。而在微服务系统设计的过程中,为了应对这样的糟糕情况,最常用的手段就是进行 ” 流量控制 “ 以
及对网络服务的调用实现 “ 熔断降级 ” 。因此, Sentinel 就因运而生了。
Sentinel 是一款面向分布式服务架构的轻量级流量控制组件,主要以流量为切入点,从流量控制、 熔断
降级 、系统自适应保护等多个维度来保障服务的稳定性,核心思想是:根据对应资源配置的规则来为资
源执行相应的流控 / 降级 / 系统保护策略
Sentinel 的历史
2012 年, Sentinel 诞生,主要功能为入口流量控制。
2013-2017 年, Sentinel 在阿里巴巴集团内部迅速发展,成为基础技术模块,覆盖了所有的核心
场景。 Sentinel 也因此积累了大量的流量归整场景以及生产实践。
2018 年, Sentinel 开源,并持续演进。 2019 年, Sentinel 朝着多语言扩展的方向不断探索,推出 C++ 原生版本 ,同时针对 Service
Mesh 场景也推出了 Envoy 集群流量控制支持 ,以解决 Service Mesh 架构下多语言限流的问题。
2020 年,推出 Sentinel Go 版本 ,继续朝着云原生方向演进。
2021 年, Sentinel 正在朝着 2.0 云原生高可用决策中心组件进行演进;同时推出了 Sentinel Rust
原生版本 。同时我们也在 Rust 社区进行了 Envoy WASM extension 及 eBPF extension 等场景探
索。
2022 年, Sentinel 品牌升级为流量治理,领域涵盖流量路由 / 调度、流量染色、流控降级、过载保
护 / 实例摘除等;同时社区将流量治理相关标准抽出到 OpenSergo 标准 中, Sentinel 作为流量治
理标准实现。
Sentinel 基本概念
资源
资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,
或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。
只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用
方法签名, URL ,甚至服务名称作为资源名来标示资源。
规则
围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则
可以动态实时调整。
Sentinel 功能和设计理念
流量控制
其原理是监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被
瞬时的流量高峰冲垮,从而保障应用的高可用性。
熔断降级
什么是熔断降级
除了流量控制以外,降低调用链路中的不稳定资源也是 Sentinel 的使命之一。由于调用关系的复杂性,
如果调用链路中的某个资源出现了不稳定,最终会导致请求发生堆积。这个问题和 Hystrix 里面描述的
问题是一样的。
Sentinel 和 Hystrix 的原则是一致的 : 当调用链路中某个资源出现不稳定,例如,表现为 timeout ,异常
比例升高的时候,则对这个资源的调用进行限制,并让请求快速失败,避免影响到其它的资源,最终产
生雪崩的效果。
熔断降级设计理念
在限制的手段上, Sentinel 和 Hystrix 采取了完全不一样的方法。
Hystrix 通过 线程池 的方式,来对依赖 ( 在我们的概念中对应资源 ) 进行了隔离。这样做的好处是资源和资
源之间做到了最彻底的隔离。缺点是除了增加了线程切换的成本,还需要预先给各个资源做线程池大小
的分配。
Sentinel 对这个问题采取了两种手段 :
通过并发线程数进行限制
和资源池隔离的方法不同, Sentinel 通过限制资源并发线程的数量,来减少不稳定资源对其它资源的影
响。这样不但没有线程切换的损耗,也不需要您预先分配线程池的大小。当某个资源出现不稳定的情况
下,例如响应时间变长,对资源的直接影响就是会造成线程数的逐步堆积。当线程数在特定资源上堆积
到一定的数量之后,对该资源的新请求就会被拒绝。堆积的线程完成任务后才开始继续接收请求。
通过响应时间对资源进行降级
除了对并发线程数进行控制以外, Sentinel 还可以通过响应时间来快速降级不稳定的资源。当依赖的资
源出现响应时间过长后,所有对该资源的访问都会被直接拒绝,直到过了指定的时间窗口之后才重新恢
复。
系统负载保护
Sentinel 同时提供 系统维度的自适应保护能力 。防止雪崩,是系统防护中重要的一环。当系统负载较高
的时候,如果还持续让请求进入,可能会导致系统崩溃,无法响应。在集群环境下,网络负载均衡会把
本应这台机器承载的流量转发到其它的机器上去。如果这个时候其它的机器也处在一个边缘状态的时
候,这个增加的流量就会导致这台机器也崩溃,最后导致整个集群不可用。
针对这个情况, Sentinel 提供了对应的保护机制,让系统的入口流量和系统的负载达到一个平衡,保证
系统在能力范围之内处理最多的请求。
Sentinel 是如何工作的
Sentinel 的主要工作机制如下:
对主流框架提供适配或者显示的 API ,来定义需要保护的资源,并提供设施对资源进行实时统计和
调用链路分析。
根据预设的规则,结合对资源的实时统计信息,对流量进行控制。同时, Sentinel 提供开放的接
口,方便您定义及改变规则。
Sentinel 提供实时的监控系统,方便您快速了解目前系统的状态。
快速开始
Sentinel 的使用可以分为两个部分 :
核心库( Java 客户端):不依赖任何框架 / 库,能够运行于 Java 8 及以上的版本的运行时环境,同
时对 Dubbo / Spring Cloud 等框架也有较好的支持。
控制台( Dashboard ): Dashboard 主要负责管理推送规则、监控、管理机器信息等。
Sentinel 控制台
下载 jar sentinel-dashboard-1.8.0.jar
使用以下命令直接运行 jar 包( JDK 版本必须 ≥ 1.8 ):
java - jar - Dserver.port=9999 sentinel - dashboard - 1.8.0.jar
控制台访问地址: http://localhost:9999 ,默认账号密码都为 sentinel/sentinel
SpringBoot 整合 sentinel-dashboard
基本搭建:
1、引入依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2.在alibaba-user-consumer-8090项目的application.yml编写代码
3.运行启动
流量控制:
一条限流规则主要由下面几个因素组成,我们可以组合这些元素来实现不同的限流效果:
resource :资源名,即限流规则的作用对象 (访问路径)
count : 限流阈值(最大接受数,超过阈值拒绝访问)
grade : 限流阈值类型( QPS 或并发线程数)
limitApp : 流控针对的调用来源,若为 default 则不区分调用来源(那个服务调用资源名时进
行限流, default 不区分)
strategy : 调用关系限流策略
controlBehavior : 流量控制效果(直接拒绝、 Warm Up 、匀速排队)
运行测试:我们会发现当每秒发送多次请求时,系统报错
流控模式与流控效果:
关联:(反向关联)
当demo1的阈值超过到1时,demo不可用。(吧demo的资源节省出来给demo1)
快速失败:抛异常
方式是默认的流量控制方式,当 QPS 超过任意规则的阈值后,新的请求就会被立即拒绝,拒绝方
式为抛出 FlowException 。这种方式适用于对系统处理能力确切已知的情况下,比如通过压测确
定了系统的准确水位时
WarmUp :慢慢增加到阈值
即预热 / 冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高
水位可能瞬间把系统压垮。通过 " 冷启动 " ,让通过的流量缓慢增加,在一定时间内逐渐增加到阈
值上限,给冷系统一个预热的时间,避免冷系统被压垮
排队等待:匀速排队处理
方式会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法 。
这种方式主要用于处理间隔性突发的流量,例如消息队列。想象一下这样的场景,在某一秒有大
量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处
理这些请求,而不是在第一秒直接拒绝多余的请求。
注意:匀速排队模式暂时不支持 QPS > 1000 的场景。
熔断降级:
现代微服务架构都是分布式的,由非常多的服务组成。不同服务之间相互调用,组成复杂的调用链路。
以上的问题在链路调用中会产生放大的效果。复杂链路上的某一环不稳定,就可能会层层级联,最终导
致整个链路都不可用。因此我们需要对不稳定的 弱依赖服务调用 进行熔断降级,暂时切断不稳定调用,
避免局部不稳定因素导致整体的雪崩。熔断降级作为保护自身的手段,通常在客户端(调用端)进行配
置
慢调用比例 ( SLOW_REQUEST_RATIO ) :选择以慢调用比例作为阈值,需要设置允许的慢调用
RT (即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长
( statIntervalMs )内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接
下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态( HALF-OPEN
状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用
RT 则会再次被熔断。
异常比例 ( ERROR_RATIO ) :当单位统计时长( statIntervalMs )内请求数目大于设置的最小请
求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔
断器会进入探测恢复状态( HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结
束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0] ,代表 0% - 100% 。
异常数 ( ERROR_COUNT ) :当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断
时长后熔断器会进入探测恢复状态( HALF-OPEN 状态),若接下来的一个请求成功完成(没有错
误)则结束熔断,否则会再次被熔断。
最大 RT: 默认毫秒,请求超出时长
熔断时长:降级多久后再次打开
比例阈值: 当每秒请求量 >=N( 可配置 ) ,并且每秒异常总数占通过量的比值超过阈值之后,进入降级状
态。取值范围 [0.0,1.0] 代表 0%-100% (如:设置为 0.2 ,如果请求异常数超过 2% 则进入降级)
最小请求数:请求数小于该值时即使异常比率超出阈值也不会熔断
热点参数限流:
访问资源参数索引(取第 1 个参数)为 0 ,类型为 int ,值为 3 ,达到阈值 10 时进行限流
需要在consumer中设置@SentinelResource注解
@SentinelResource注解
@SentinelResource 用于定义资源,并提供可选的异常处理和 fallback 配置项。 @SentinelResource
注解包含以下属性:
value :资源名称,必需项(不能为空)
entryType : entry 类型,可选项(默认为 EntryType.OUT )
blockHandler / blockHandlerClass : blockHandler 对应处理 BlockException 的函数名称,可
选项。 blockHandler 函数访问范围需要是 public ,返回类型需要与原方法相匹配,参数类型需要
和原方法相匹配并且最后加一个额外的参数,类型为 BlockException 。 blockHandler 函数默认需
要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的
类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
fallback : fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。 fallback
函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。
fallback 函数签名和位置要求:
返回值类型必须与原函数返回值类型一致;
方法参数列表需要和原函数一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异
常。
fallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定
fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
defaultFallback ( since 1.6.0 ):默认的 fallback 函数名称,可选项,通常用于通用的 fallback
逻辑(即可以用于很多服务或方法)。默认 fallback 函数可以针对所以类型的异常(除了
exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了 fallback 和
defaultFallback ,则只有 fallback 会生效。 defaultFallback 函数签名要求:
返回值类型必须与原函数返回值类型一致;
方法参数列表需要为空,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
defaultFallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定
fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
exceptionsToIgnore ( since 1.6.0 ):用于指定哪些异常被排除掉,不会计入异常统计中,也不会
进入 fallback 逻辑中,而是会原样抛出。
@RestController
public class DemoController {
//blockHandler 使用sentinel进行不同规则控制时的默认处理方案
// fallback:自定义业务出错时默认处理方案
// defaultFallback 指定一个业务错误时默认方案
@GetMapping("/demo")
@SentinelResource(value = "aaaa",blockHandler = "blockHandler",fallback =
"fallCustomer",defaultFallback = "defaultFall") //作用:代表这是一个sentinel资源
public String demo(Integer id){
log.info("demo ok...");
if(id<0){
throw new RuntimeException("id无效");
}
return "demo ok !!!";
}
@GetMapping("/test")
public String test(){
log.info("test ok...");
return "test ok !!!";
}
//
public String blockHandler(Integer id, BlockException e){
if(e instanceof FlowException){
return "当前请求过于火爆,您已被流控!!";
}
if(e instanceof DegradeException){
}
if(e instanceof ParamFlowException){
return "当前请求过于火爆,您已被热点参数限流!!";
}
return "服务器快爆了,请稍后再试!!!";
}
//
public String defaultFall(){
return "默认处理:服务器出错了!!!";
}
public String fallCustomer(Integer id){
return "自定义服务器出错啦!!!";
}
}
基于nacos配置中心进行规则持久化
使用 naocs 进行持久化
<!--sentinel利用nacos做持久化-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
在配置中心创建文件:
[{"resource" : "/bill/find" ,"limitApp" : "default" , resource :资源名称"grade" : 1 ,"count" : 2 ,"strategy" : 0 ,"controlBehavior" : 0 ,"clusterMode" : false},{"resource" : "/bill/find1" ,"limitApp" : "default" ,"grade" : 1 ,"count" : 1 ,"strategy" : 0 ,"controlBehavior" : 0 ,"clusterMode" : false}]
resource :资源名称
limitApp :来源应用
grade :阈值类型, 0 表示线程数, 1 表示 QPS
count :单机阈值
strategy :流控模式, 0 表示直接, 1 表示关联, 2 表示链路
controlBehavior :流控效果, 0 表示快速失败, 1 表示 Warm Up , 2 表示排队等待
clusterMode :是否集群
流量控制参数:
熔断降级配置:
0 慢调用比例 1 异常比例 2 异常数
热点参数配置:
注意:
项目中yaml配置
bill-consumer-7790-flow 配置
bill-consumer-7790-degrade配置
bill-consumer-7790-param-flow 配置
上述 JSON 示例中的各项含义如下:
resource :资源名称,对应到你在代码中要进行热点参数限流保护的业务逻辑方法或接口等的标
识,可以自定义,但要和代码中的设置一致。
paramIdx :热点参数的索引位置,从 0 开始计数,表示要基于哪个参数进行热点参数限流判断。
比如你的业务方法有多个参数,这里指定要关注哪个参数的热点情况。
count :限流阈值,即单位时间内允许通过的请求次数。
burst :突发量,允许在短时间内超过限流阈值的额外请求数量。
duration :统计的时间窗口单位,这里设置为 1 表示以秒为单位(也可以根据需要设置为其他时
间单位,如分钟等,对应的参数值不同)。
controlBehavior :流控效果, 0 表示快速失败(达到限流阈值直接拒绝后续请求),还有其他
可选值对应不同的流控策略(比如匀速排队等)。
maxQueueingTimeMs :最大排队等待时间(毫秒),当使用匀速排队等流控策略时生效,指定请
求在排队等待通过限流时的最大等待时长。