官网:https://sentinelguard.io/zh-cn/docs/introduction.html
github文档:https://github.com/alibaba/Sentinel/wiki
Sentinel 是一款面向分布式服务架构的轻量级流量控制组件,主要以流量为切入点,从流量控制、
熔断降级
、系统自适应保护等多个维度来保障服务的稳定性,核心思想是:根据对应资源配置的规则来为资源执行相应的流控/
降级
/
系统保护策略。
Sentinel 功能和设计理念
流量控制
其原理是监控应用流量的 QPS
或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。
熔断降级
什么是熔断降级?
除了流量控制以外,降低调用链路中的不稳定资源也是 Sentinel
的使命之一。由于调用关系的复杂性, 如果调用链路中的某个资源出现了不稳定,最终会导致请求发生堆积。这个问题和
Hystrix
里面描述的问题是一样的 。
Sentinel 和
Hystrix
的原则是一致的
:
当调用链路中某个资源出现不稳定,例如,表现为
timeout
,异常比例升高的时候,则对这个资源的调用进行限制,并让请求快速失败,避免影响到其它的资源,最终产生雪崩的效果。
熔断降级设计理念
在限制的手段上,Sentinel 和
Hystrix
采取了完全不一样的方法。
Hystrix
通过
线程池
的方式,来对依赖
(
在我们的概念中对应资源
)
进行了隔离。这样做的好处是资源和资源之间做到了最彻底的隔离。缺点是除了增加了线程切换的成本,还需要预先给各个资源做线程池大小的分配。
Sentinel
对这个问题采取了两种手段
:
- 通过并发线程数进行限制
和资源池隔离的方法不同,Sentinel 通过限制资源并发线程的数量,来减少不稳定资源对其它资源的影响。这样不但没有线程切换的损耗,也不需要您预先分配线程池的大小。当某个资源出现不稳定的情况下,例如响应时间变长,对资源的直接影响就是会造成线程数的逐步堆积。当线程数在特定资源上堆积到一定的数量之后,对该资源的新请求就会被拒绝。堆积的线程完成任务后才开始继续接收请求。
- 通过相应时间对资源进行降级
除了对并发线程数进行控制以外,Sentinel 还可以通过响应时间来快速降级不稳定的资源。当依赖的资源出现响应时间过长后,所有对该资源的访问都会被直接拒绝,直到过了指定的时间窗口之后才重新恢复。
Sentinel
是如何工作的
Sentinel的主要工作机制如下:
- 对主流框架提供适配或者显示的 API,来定义需要保护的资源,并提供设施对资源进行实时统计和调用链路分析。
- 根据预设的规则,结合对资源的实时统计信息,对流量进行控制。同时,Sentinel 提供开放的接口,方便您定义及改变规则。
- Sentinel 提供实时的监控系统,方便您快速了解目前系统的状态。
Sentinel 分为两个部分
- 核心库(Java 客户端)不依赖任何框架/库,能够运行于 Java 8 及以上的版本的运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
- 控制台(Dashboard)基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器,Dashboard 主要负责管理推送规则、监控、管理机器信息等。
Sentinel 基本概念
资源是 Sentinel 的关键概念。它可以是 Java应用程序中的任何内容,
例如,由应用程序提供的服务,
或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。
Sentinel 与
Hystrix 对比:
Sentinel 下载与安装
官网下载地址:Releases · alibaba/Sentinel · GitHub
下载后编写启动类等(或者直接命令启动),运行
输入对应地址进入:
账号密码均为sentinel:
SpringBoot 整合 sentinel-dashboard
引入依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>${spring-cloud-alibaba-version}</version>
</dependency>
编写yml配置文件,如图所示:
启动运行:
流量控制
一条限流规则主要由下面几个因素组成,我们可以组合这些元素来实现不同的限流效果:
- resource :资源名,即限流规则的作用对象 (访问路径)
- count : 限流阈值(最大接受数,超过阈值拒绝访问)
- grade : 限流阈值类型(QPS 或并发线程数)
- limitApp : 流控针对的调用来源,若为 default 则不区分调用来源(那个服务调用资源名时进
- 行限流,default不区分)
- strategy : 调用关系限流策略
- controlBehavior : 流量控制效果(直接拒绝、Warm Up、匀速排队)
流量控制:
运行测试:我们会发现当每秒发送多次请求时,系统报错
注意:除了设置
QPS
外,也可以设置线程数。(可让业务代码进行休眠,或使用压力测试工具就
jmeter
)
当设置线程数为
1
时,
jmeter
测试,
5
个线程同一时刻发送。
关联(反向关联):
当
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 逻辑中,而是会原样抛出。