GitHub官方:https://github.com/alibaba/Sentinel
官方文档:https://sentinelguard.io/zh-cn/index.html
微服务SpringClout Alibaba——Nacos注册中心、配置中心和Nacos集群(2)
微服务SpringClout Alibaba——Sentinel流控、熔断、降级(3)
微服务SpringClout Alibaba——Seata分布式事务(4)
目录
一、Sentinel介绍
Sentinel 是面向分布式服务架构的流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统自适应保护等多个维度来帮助您保障微服务的稳定性。
Sentinel 具有以下特征:
- 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
- 完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
- 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
- 完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。
Sentinel主要特性:
二、基本使用
GitHub下载地址:https://github.com/alibaba/Sentinel/releases/tag/v1.8.0
Sentinel默认的端口是8080,根据需要更改端口运行:java -Dserver.port=8081 -jar sentinel-dashboard-1.8.0.jar
Sentinel的默认账号密码到时sentinel
建立一个简单的项目测试:
pom的引入:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 持久化 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
properties的配置:
server.port=8401
spring.application.name=springcloud-alibaba-sentinel
#nacos服务地址
spring.cloud.nacos.discovery.server-addr=192.168.226.137:81
#sentinel服务地址
spring.cloud.sentinel.transport.dashboard=localhost:8081
#默认8719,假如被占用了会自动从8719开始依次+1扫描。直至找到未被占用的端口
spring.cloud.sentinel.transport.port=8719
management.endpoints.web.exposure.include=*
Controller:
@RestController
public class FlowLimitController
{
@GetMapping("/testA")
public String testA() {
return "------testA";
}
@GetMapping("/testB")
public String testB() {
return "------testB";
}
}
启动项目:
发现sentinel没有监控到服务,别急,那是因为sentinel启用的赖加载的方式,当访问了项目的链接的时候就会触发,当访问一次之后:
三、流控规则
1、概述
流量控制(flow control),其原理是监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。
- 资源名:唯一名称,默认请求路劲
- 针对来源:Sentinel可以针对调用者进行限流,填写微服务名,默认default(不区分来源)
- 阈值类型/单机阈值
- QPS(每秒钟请求数量):当调用该API的QPS达到阈值的时候,进行限流
- 线程数:当调用该API的线程数达到阈值的时候,进行限流
- 是否集群:不需要集群
- 流量模式:
- 直接:API达到限流天剑时,直接限流
- 关联:当关联的资源达到阈值时,就限流自己
- 链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就进行限流)【API级别的针对来源】
- 流控效果:
- 快速失败:直接失败,抛异常
- Warm Up:根据codeFactor(冷加载因子,默认3)的值,从阈值/codeFactor,经过预热时长,才达到设置的QPS阈值,例如:运行5s后,能每秒可以访问10个,防止流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮(可运用到秒杀)
- 排队等待:匀速排队,让请求匀速的速度通过,阈值类型必须设置未QPS,否则无效
二、熔断降级
1、概述
除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。由于调用关系的复杂性,如果调用链路中的某个资源不稳定,最终会导致请求发生堆积。Sentinel 熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误。当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出 DegradeException
)。
2、熔断策略
- 慢调用比例 (
SLOW_REQUEST_RATIO
):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs
)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。
- 异常比例 (
DEGRADE_GRADE_EXCEPTION_RATIO
):当资源的每秒请求量 >= N(可配置),并且每秒异常总数占通过量的比值超过阈值(DegradeRule
中的count
)之后,资源进入降级状态,即在接下的时间窗口(DegradeRule
中的timeWindow
,以 s 为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是[0.0, 1.0]
,代表 0% - 100%。 - 异常数 (
DEGRADE_GRADE_EXCEPTION_COUNT
):当资源近 1 分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若timeWindow
小于 60s,则结束熔断状态后仍可能再进入熔断状态。
注意:异常降级仅针对业务异常,对 Sentinel 限流降级本身的异常(BlockException
)不生效。为了统计异常比例或异常数,需要通过 Tracer.trace(ex)
记录业务异常。
三、热点参数限流
1、概述——Overview
何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:
- 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
- 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
代码测试
1、基础配置
/**
* @SentinelResource:当某个方法出问题时,自定义对应的兜底降级方法,
* value:sentinel上热点规则的资源名,blockHandlerClass:具体是那个类(不配置则默认本类),blockHandler:兜底方法(不配置该方法将显示500页面),fallback:代码异常兜底,exceptionsToIgnore = {IllegalArgumentException.class}:忽略指定异常,即这些异常不用兜底方法处理
* @param p1
* @param p2
* @return
*/
@GetMapping("testHotKey")
@SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey")
public String testHotKey(@RequestParam(value = "p1",required = false) String p1,
@RequestParam(value = "p2",required = false) String p2){
return "--------testHotKey";
}
public String deal_testHotKey(String p1, String p2, BlockException blockException){
return "--------deal_testHotKey,自定义,兜底";
}
参数索引:0(即p1),1s中只允许限流1次:
结果:
2、高级配置——参数例外项
例如:当用户是VIP是就1s中限流200次,别的用户1s中限流1次
结果:
注意:@SentinelResource主管配置出错,运行出错该走异常走异常
四、系统自适应限流
Sentinel 系统自适应限流从整体维度对应用入口流量进行控制,结合应用的 Load、CPU 使用率、总体平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
系统规则
系统保护规则是从应用级别的入口流量进行控制,从单台机器的 load、CPU 使用率、平均 RT、入口 QPS 和并发线程数等几个维度监控应用指标,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量生效。入口流量指的是进入应用的流量(EntryType.IN
),比如 Web 服务或 Dubbo 服务端接收的请求,都属于入口流量。
系统规则支持以下的模式:
- Load 自适应(仅对 Linux/Unix-like 机器生效):系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的
maxQps * minRt
估算得出。设定参考值一般是CPU cores * 2.5
。 - CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。
- 平均 RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
- 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
- 入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
五、Sentinel服务熔断OpenFeign
Feign组件一般是消费侧
1、POM
<!--SpringCloud openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2、配置文件添加:
#激活Sentinel对Feign的支持
feign.sentinel.enabled=true
3、主启动类(main)添加:@EnableFeignClients
4、业务类:
带@Feignclient注解的业务接口,使用 fallback = OpenFeignFallbackService.class 进行兜底
/**
* @author 小懒虫
*/
@FeignClient(value = "springcloud-alibaba-payment",fallback = OpenFeignFallbackService.class)
public interface OpenFeignService {
@GetMapping(value = "/payment/nacos/{id}")
String getPayment(@PathVariable("id") Integer id);
}
/**
* @author 小懒虫
*/
@Component
public class OpenFeignFallbackService implements OpenFeignService {
@Override
public String getPayment(Integer id) {
return "服务降级返回,---OpenFeignFallbackService";
}
}
5、Controller层:
@Resource
private OpenFeignService openFeignService;
@GetMapping(value = "/consumer/payment/nacos/{id}")
public String getPayment(@PathVariable("id") Integer id){
return openFeignService.getPayment(id);
}
正常运行:
当服务端出问题时(即我们故意停掉),消费端则自动降级,进入兜底方法:
熔断框架比较
Sentinel | Hystrix | resilience4j | |
---|---|---|---|
隔离策略 | 信号量隔离(并发线程数限流) | 线程池隔商/信号量隔离 | 信号量隔离 |
熔断降级策略 | 基于响应时间、异常比率、异常数 | 基于异常比率 | 基于异常比率、响应时间 |
实时统计实现 | 滑动窗口(LeapArray) | 滑动窗口(基于RxJava) | Ring Bit Buffer |
动态规则配置 | 支持多种数据源 | 支持多种数据源 | 有限支持 |
扩展性 | 多个扩展点 | 插件的形式 | 接口的形式 |
基于注解的支持 | 支持 | 支持 | 支持 |
限流 | 基于QPS,支持基于调用关系的限流 | 有限的支持 | Rate Limiter |
流量整形 | 支持预热模式匀速器模式、预热排队模式 | 不支持 | 简单的Rate Limiter模式 |
系统自适应保护 | 支持 | 不支持 | 不支持 |
控制台 | 提供开箱即用的控制台,可配置规则、查看秒级监控,机器发观等 | 简单的监控查看 | 不提供控制台,可对接其它监控系统 |
六、Sentinel持久化
将限流配置规则持久化进Nacos保存
POM
<!--SpringCloud ailibaba sentinel-datasource-nacos 后续做持久化用到-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
配置文件添加:
#将sentinel配置到nacos中做持久化
spring.cloud.sentinel.datasource.ds1.nacos.server-addr=192.168.226.137:80
spring.cloud.sentinel.datasource.ds1.nacos.data-id=cloudalibaba-sentinel-service
spring.cloud.sentinel.datasource.ds1.nacos.group-id=DEFAULT_GROUP
spring.cloud.sentinel.datasource.ds1.nacos.data-type=json
spring.cloud.sentinel.datasource.ds1.nacos.rule-type=flow
nacos添加配置文件
配置内容解析
[{
"resource": "/testHotKey",
"IimitApp": "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:是否集群。
当访问一次后查看sentinel,持久化生效: