1、Sentinel 介绍
Sentinel是Spring Cloud Alibaba提供的一个专门用于服务容错、服务熔断、服务限流的微服务组件,它和hystrix组件的作用是类似的,但是Sentinel提供的功能比hystrix更加强大,Sentinel分为两部分,一部分是Sentinel核心库,另外一部分是Dashboard控制台,Dashboard控制台可以查看监控的信息,接口的调用情况等。 Sentinel是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量控制
、流量路由
、熔断降级
、系统自适应保护
等多个维度来帮助用户保障微服务的稳定性。
1. Sentinel特性
-
丰富的应用场景
阿里巴巴 10 年双十一积累的丰富流量场景,包括秒杀、双十一零点持续洪峰、热点商品探测、预热、消息队列削峰填谷等多样化的场景
-
易于使用,快速接入
简单易用,开源生态广泛,针对 Dubbo、Spring Cloud、gRPC、Zuul、Reactor、Quarkus 等框架只需要引入适配模块即可快速接入
-
多样化的流量控制
资源粒度、调用关系、指标类型、控制效果等多维度的流量控制
-
可视化的监控和规则管理
简单易用的 Sentinel 控制台
2. Sentinel 组成
-
核心库(Java 客户端):不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
-
控制台(Dashboard):基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器。
3. 基本概念
资源
资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。
只要通过 Sentinel API 定义的代码,就是资源,就能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名
,URL
,甚至服务名称
作为资源名来表示资源。
规则
围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。
所有规则可以动态实时调整。
2、主要功能
1. 流量控制
流量控制在网络传输中是一个常用的概念,它用于调整网络包的发送数据。然而,从系统稳定性角度考虑,在处理请求的速度上,也有非常多的讲究。任意时间到来的请求往往是随机不可控的,而系统的处理能力是有限的。我们需要根据系统的处理能力对流量进行控制。Sentinel 作为一个调配器,可以根据需要把随机的请求调整成合适的形状,如上图所示。
2. 熔断降级
除了流量控制以外,降低调用链路中的不稳定资源也是 Sentinel 的使命之一。由于调用关系的复杂性,如果调用链路中的某个资源出现了不稳定,最终会导致请求发生堆积。
当调用链路中某个资源出现不稳定,例如,表现为 timeout,异常比例升高的时候,则对这个资源的调用进行限制,并让请求快速失败,避免影响到其它的资源,避免产生雪崩的效果。
-
通过并发线程数进行限制
和资源池隔离的方法不同,Sentinel 通过限制资源并发线程的数量,来减少不稳定资源对其它资源的影响。这样不但没有线程切换的损耗,也不需要您预先分配线程池的大小。当某个资源出现不稳定的情况下,例如响应时间变长,对资源的直接影响就是会造成线程数的逐步堆积。当线程数在特定资源上堆积到一定的数量之后,对该资源的新请求就会被拒绝。堆积的线程完成任务后才开始继续接收请求。
-
通过响应时间对资源进行降级
除了对并发线程数进行控制以外,Sentinel 还可以通过响应时间来快速降级不稳定的资源。当依赖的资源出现响应时间过长后,所有对该资源的访问都会被直接拒绝,直到过了指定的时间窗口之后才重新恢复。
3. 系统负载保护 - 应用程序的外部环境
Sentinel 同时提供系统维度的自适应保护能力。防止雪崩,是系统防护中重要的一环。当系统负载较高的时候,如果还持续让请求进入,可能会导致系统崩溃,无法响应。在集群环境下,网络负载均衡会把本应这台机器承载的流量转发到其它的机器上去。如果这个时候其它的机器也处在一个边缘状态的时候,这个增加的流量就会导致这台机器也崩溃,最后导致整个集群不可用。
针对这个情况,Sentinel 提供了对应的保护机制,让系统的入口流量和系统的负载达到一个平衡,保证系统在能力范围之内处理最多的请求。
3、Sentinel 的安装与使用
1. Sentinel控制台
Sentinel 提供一个轻量级的开源控制台,它提供机器发现以及健康情况管理、监控(单机和集群),规则管理和推送的功能。
Sentinel 控制台是流量控制、熔断降级规则统一配置和管理的入口,它为用户提供了机器自发现、簇点链路自发现、监控、规则配置等功能。在 Sentinel 控制台上,我们可以配置规则并实时查看流量控制效果。
-
查看机器列表以及健康情况:收集 Sentinel 客户端发送的心跳包,用于判断机器是否在线。
-
监控 (单机和集群聚合):通过 Sentinel 客户端暴露的监控 API,定期拉取并且聚合应用监控信息,最终可以实现秒级的实时监控。
-
规则管理和推送:统一管理推送规则。
-
鉴权:生产环境中鉴权非常重要。这里每个开发者需要根据自己的实际情况进行定制。
注意:Sentinel 控制台目前仅支持单机部署。Sentinel 控制台项目提供 Sentinel 功能全集示例,不作为开箱即用的生产环境控制台,不提供安全可靠保障。若希望在生产环境使用请根据文档自行进行定制和改造。
2. Sentinel控制台的下载
下载地址:Tags · alibaba/Sentinel · GitHub
-
选择需要下载的版本
-
下载jar包
-
下载完成后,直接解压压缩包
3. Sentinel控制台的启动
-
进入Sentinel 安装目录,输入cmd,进入命令界面
-
启动jar包
java -jar -Dserver.port=9999 sentinel-dashboard-1.8.5.jar 指定端口启动 java -jar sentinel-dashboard-1.8.5.jar 默认端口启动
-
服务 Sentinel 控制台
用户名:sentinel
密 码:sentinel
4. 使用Sentinel 控制台
-
导入依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency>
-
配置 application.yml
server: port: 9007 spring: application: name: sentinel-service cloud: sentinel: transport: # 控制台地址 dashboard: localhost:9999 # 不统一请求人口,不将资源挂在 sentinel_spring_web_context 下 web-context-unify: false
-
编写测试接口,并访问
@RestController @RequestMapping("/flow") public class FlowController { @RequestMapping("/hello") public ResultVO<String> hello(){ return ResultVO.success("测试直接限流!"); } }
4、Sentinel的控制规则
1. 流量控制
一条限流规则主要由下面几个因素组成,我们可以组合这些元素来实现不同的限流效果:
-
resource
:资源名,即限流规则的作用对象,其实就是我们请求的资源路径 -
limitApp
:针对来源,这个是此流控规则对应哪些微服务进行流控管理,一般填写调用方的微服务名称,多个用“,”分割 -
grade
: 限流阈值类型:QPS(Queries Per Second)或 并发线程数-
QPS:QPS(Queries Per Second):每秒钟请求数,由
FlowRule.grade
字段来定义。其中,0 代表根据并发线程来限流,1 代表根据 QPS 来进行流量控制。当请求该资源的的QPS达到设定阈值时,进行限流 -
基于线程数:当请求该资源的线程数达到阈值时,进行限流;允许请求进入,但是如果没有空闲线程,则失败
-
-
count
: 限流阈值 -
strategy
: 流控模式 - 【如何做流控】-
直接:当 api 调用达到限流条件的时,直接限流
-
关联:当关联的资源请求达到阈值的时候,限流自己
-
链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,则进行限流)
-
-
controlBehavior
:流控效果 - 【如何处理被流控的请求】-
快速失败:直接失败
-
Warm Up:即预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过冷启动,让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个越热的时间,避免冷系统被压垮。sentinel客户端的默认冷加载因子 coldFactor = 3,即请求QPS从 threshold / 3 开始,经预热时长逐渐升至设定的QPS阈值
-
排队等待:匀速排队,让请求匀速通过,阈值类型必须设置为 QPS,否则无效
-
新增限流规则
资源名称就是我们的接口访问路径 然后我们一秒一次访问一下接口(正常)
接下来我们快速请求接口,一秒钟点击多次 发现已经被限流了
2. 熔断降级
除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。
一个服务常常会调用其它模块,它可能是另外的一个远程服务、数据库,或者第三方 API 等。
例如:支付的时候,可能需要远程调用银联提供的 API; 查询某个商品的价格,可能需要进行数据库查询。
然而,被依赖服务的稳定性是不能保证的。
如果依赖的服务出现了不稳定的情况,请求的响应时间变长,那么调用服务的方法的响应时间也会变长,线程会产生堆积,最终可能耗尽业务自身的线程池,服务本身也变得不可用。
现代微服务架构都是分布式的,由非常多的服务组成。不同服务之间相互调用,组成复杂的调用链路,以上的问题在链路调用中会产生放大的效果。复杂链路上的某一环不稳定,就可能会层层级联,最终导致整个链路都不可用。因此,我们需要对不稳定的弱依赖服务调用进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩。
熔断策略
-
慢调用比例 (
SLOW_REQUEST_RATIO
)
选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。
当单位统计时长(statIntervalMs
)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT,则结束熔断;若大于设置的慢调用 RT,则会再次被熔断。
异常比例 (ERROR_RATIO
)
当单位统计时长(statIntervalMs
)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0]
,代表 0% - 100%。
异常数 (ERROR_COUNT
)
当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。
5、自定义限流或降级返回结果
-
通过 @SentinelResource 定义的资源,使用它的
blockHandler
属性指定方法即可@SentinelResource(value = "nodeA",blockHandler = "nodeAHandler") public String commonResource(String from){ System.out.println("人口资源"+ from); return from; } public String nodeAHandler(String from, BlockException e){ System.out.println("限流资源"+from); return from+"---- 被限流了!"; }
-
对于 Spring MVC 的 URL 表示的资源,需要实现 BlockExceptionHandler
@Service public class MyBlockHandler implements BlockExceptionHandler { @Override public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception { String uri = request.getRequestURI(); response.setContentType("application/json;charset=utf-8"); ResultVO<Object> resultVO; if (e instanceof FlowException) { resultVO = ResultVO.failed(uri + "超过最大请求限制!"); } else if (e instanceof DegradeException) { resultVO = ResultVO.failed(uri + "被限流了!"); }else { resultVO = ResultVO.failed(); } String jsonStr = JSONUtil.toJsonStr(resultVO); PrintWriter writer = response.getWriter(); writer.println(jsonStr); writer.close(); } }
6、规则持久化
Sentinel 的理念是开发者只需要关注资源的定义,当资源定义成功后可以动态增加各种流控、降级规则。
Sentinel 提供两种方式修改规则:
-
通过 API 直接修改 (
loadRules
) -
通过
DataSource
适配不同数据源修改
手动修改规则(硬编码方式)一般仅用于测试和演示,生产上一般通过动态规则源的方式来动态管理规则。
我们推荐通过控制台设置规则后将规则推送到统一的规则中心,客户端实现 ReadableDataSource
接口端监听规则中心实时获取变更,流程如下:
DataSource
扩展常见的实现方式有:
-
拉模式:客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件,甚至是 VCS 等。这样做的方式是简单,缺点是无法及时获取变更;
-
推模式:规则中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用 Nacos、Zookeeper 等配置中心。这种方式有更好的实时性和一致性保证。
1. 持久化配置
Sentinel 针对 Nacos 作了适配,底层可以采用 Nacos 作为规则配置数据源。
-
创建项目
sentinel-nacos
,添加Maven依赖<!-- spring-boot-starter-web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- spring-cloud-starter-alibaba-nacos-discovery --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- spring-cloud-starter-alibaba-sentinel --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <!-- 新增 Nacos 持久化 sentinel-datasource-nacos --> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency>
-
在yml中配置nacos持久化
server: port: 9008 spring: application: name: sentinel-nacos cloud: nacos: discovery: server-addr: localhost:8848 sentinel: # 立即加载服务 eager: true # web-context-unify: true transport: dashboard: localhost:9999 # 规则数据源, 它接收一个Map<String, DataSourcePropertiesConfiguration> ### key 可以任意, value必须DataSourcePropertiesConfiguration的成员变量之一:file、nacos、redis、zk、consul、apollo datasource: flow:# 流控规则 # DataSourcePropertiesConfiguration的成员变量之一 ### nacos的值是NacosDataSourceProperties对象 nacos: # Nacos的地址 server-addr: ${spring.cloud.nacos.discovery.server-addr} # Group,默认就是DEFAULT_GROUP group-id: DEFAULT_GROUP # data id: 规则配置集 data-id: ${spring.application.name}-flow # data id 格式, json - json数组 data-type: json # 规则类型 enum RuleType { } rule-type: flow degrade: #熔断规则 nacos: # namespace: public server-addr: localhost:8848 dataId: ${spring.application.name}-degrade-rules groupId: DEFAULT_GROUP data-type: json rule-type: degrade
-
-
在nacos控制增加配置
流控规则
<span style="background-color:#f8f8f8"><span style="color:#333333">Json :
[
{ 流控规则
// 资源名
"resource": "/test1",
// 针对来源,若为 default 则不区分调用来源
"limitApp": "default",
// 限流阈值类型(1:QPS;0:并发线程数)
"grade": 1,
// 阈值
"count": 1,
// 是否是集群模式
"clusterMode": false,
// 流控效果(0:快速失败;1:Warm Up(预热模式);2:排队等待)
"controlBehavior": 0,
// 流控模式(0:直接;1:关联;2:链路)
"strategy": 0,
// 预热时间(秒,预热模式需要此参数)
"warmUpPeriodSec": 10,
// 超时时间(排队等待模式需要此参数)
"maxQueueingTimeMs": 500,
// 关联资源、入口资源(关联、链路模式)
"refResource": "rrr"
}
]
yml:
spring:
cloud:
sentinel:
datasource:
flow: #流控规则
nacos:
namespace: public
server-addr: localhost:8848
dataId: ${spring.application.name}-flow-rules
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow</span></span>
熔断规则
<span style="background-color:#f8f8f8"><span style="color:#333333">json:
[
{ 熔断规则
// 资源名
"resource": "/test2",
"limitApp": "default",
// 熔断策略(0:慢调用比例,1:异常比率,2:异常计数)
"grade": 0,
// 最大RT、比例阈值、异常数
"count": 200,
// 慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入)
"slowRatioThreshold": 0.2,
// 最小请求数
"minRequestAmount": 5,
// 当单位统计时长(类中默认1000)
"statIntervalMs": 1000,
// 熔断时长
"timeWindow": 10
}
]
yml:
spring:
cloud:
sentinel:
datasource:
degrade: #熔断规则
nacos:
namespace: public
server-addr: localhost:8848
dataId: ${spring.application.name}-degrade-rules
groupId: DEFAULT_GROUP
data-type: json
rule-type: degrade</span></span>
-
启动服务后,查看Sentinel控制台的限流规则