Spring Cloud Alibaba Sentinel
Sentinel 介绍
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。 Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。 Sentinel 具有以下特征: 丰富的应用场景: Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、实时熔断下游不可用应用等。 完备的实时监控: Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。 广泛的开源生态: Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。 完善的 SPI 扩展点: Sentinel 提供简单易用、完善的 SPI 扩展点。您可以通过实现扩展点,快速的定制逻辑。例如定制规则管理、适配数据源等。
同类型产品比较

引入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.9.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
Sentinel 控制台
Sentinel 控制台提供一个轻量级的控制台,它提供机器发现、单机资源实时监控、集群资源汇总,以及规则管理的功能。您只需要对应用进行简单的配置,就可以使用这些功能。
开启该功能需要3个步骤:
注意:下载的jar包要对应 Spring Cloud alibaba 的版本 
2.启动控制台
Sentinel 控制台是一个标准的 Spring Boot 应用,以 Spring Boot 的方式运行 jar 包即可。 Sentinel 控制台默认的端口为8080,为避免端口冲突可以通过自定义端口的命令启动.
java -jar sentinel-dashboard.jar
或
java -Dserver.port=自定义端口 -Dcsp.sentinel.dashboard.server=IP:自定义端口 -jar sentinel-dashboard.jar
默认用户名:sentinel 默认密码:sentinel  
3.配置控制台信息
server:
port: 8088
spring:
application:
name: sentinel-client
cloud:
sentinel:
transport:
dashboard: localhost:8080
Sentinel控制台规则配置详解
流控规则(通常在Provider 端配置)
流量控制在网络传输中是一个常用的概念,它用于调整网络包的发送数据。然而,从系统稳定性角度考虑,在处理请求的速度上,也有非常多的讲究。任意时间到来的请求往往是随机不可控的,而系统的处理能力是有限的。我们需要根据系统的处理能力对流量进行控制。Sentinel 作为一个调配器,可以根据需要把随机的请求调整成合适的形状. 其原理是监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。 流量控制主要有两种统计类型,一种是统计并发线程数,另外一种则是统计 QPS。类型由 FlowRule 的 grade 字段来定义。其中,0 代表根据并发数量来限流,1 代表根据 QPS 来进行流量控制。其中线程数、QPS 值,都是由 StatisticSlot 实时统计获取的。 
使用场景:
控制脉冲流量 针对不用调用来源进行流控 web接口流控 流量控制有以下几个角度: 资源的调用关系,例如资源的调用链路,资源和资源之间的关系; 运行指标,例如 QPS、线程池、系统负载等; 控制的效果,例如直接限流、冷启动、排队等。
如何配置规则:
梳理核心接口 通过事前压测评估核心接口的容量,配置QPS阈值
相关参数
一条限流规则主要由下面几个因素组成,我们可以组合这些元素来实现不同的限流效果:
Field | 说明 | 默认值 |
---|
resource | 资源名,资源名是限流规则的作用对象 | 直接拒绝 | count | 限流阈值 | | grade | 限流阈值类型,QPS(1) 或线程数模式(0) | QPS 模式 | limitApp | 流控针对的调用来源 | default,代表不区分调用来源 | strategy | 调用关系限流策略:直接、链路、关联 | 根据资源本身(直接) | controlBehavior | 流控效果(直接拒绝 / 排队等待 / 慢启动模式),不支持按调用关系限流 | 直接拒绝 |
控制台操作界面

阈值类型
QPS :指的是在一秒内同时服务的请求数 (并发数) 线程数 : 指同时在处理请求的线程数量
自定义流控返回
当配置了流程参数设置后,程序达到流控上限,会返回下面的提示  如果需要自定义放回或是需要在降级之后增加处理逻辑可以通过 @SentinelResource 实现
@SentinelResource
代码示例:
value 对应的是 resource 资源名 需要在控制台中设置流控参数自定义返回开会生效 blockHandler 块异常函数的名称 (使用blockHandler 指定的方法需要在定义在同一个类中) blockHandlerClass 指定的方法不在同一个类中可以使用blockHandlerClass来指定,但是方法必须声明为static 静态方法,
@RequestMapping(value = "/index",method = RequestMethod.GET)
@SentinelResource(value = "index",blockHandler = "testBlockHandler")
public CommonResult test(){
return new CommonResult("OK");
}
public CommonResult testBlockHandler(BlockException e){
return new CommonResult("流控");
}
sentinel统一异常处理
如果不想用 @SentinelResource 注解来处理,则可以采用统一异常处理,如果需要对不同的业务做不同的处理,建议使用 @SentinelResource 注解来处理. 一旦使用了@SentinelResource 注解来处理,统一异常处理就不会被使用,需要另外定义返回
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.car.hailing.saas.base.CommonResult;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Slf4j
@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
log.info("lockExceptionHandler============="+e.getRule());
CommonResult r = null;
if (e instanceof FlowException){
r = new CommonResult<>(100,"接口限流");
}else if (e instanceof DegradeException){
r = new CommonResult<>(101,"服务降级");
}else if (e instanceof ParamFlowException){
r = new CommonResult<>(102,"热点参数限流");
}else if (e instanceof SystemBlockException){
r = new CommonResult<>(103,"出发系统保护规则");
}else if (e instanceof AuthorityException){
r = new CommonResult<>(104,"授权规则不通过");
}
httpServletResponse.setStatus(500);
httpServletResponse.setCharacterEncoding("utf-8");
httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
new ObjectMapper().writeValue(httpServletResponse.getWriter(),r);
}
}
@JsonInclude(JsonInclude.Include.NON_NULL)
@Data
public class CommonResult<T> implements Serializable {
private int code;
private String msg;
private T data;
public CommonResult()
{
this.code = SystemResult.SUCCESS.code;
this.msg = SystemResult.SUCCESS.message;
}
public CommonResult(T t)
{
this.code = SystemResult.SUCCESS.code;
this.msg = SystemResult.SUCCESS.message;
this.data = t;
}
public CommonResult(SystemResult r)
{
this.code = r.code;
this.msg = r.message;
this.data = null;
}
public CommonResult(int r, String t)
{
this.code = r;
this.msg = t;
this.data = null;
}
}
3种流控模式
1.直接 模式: 直接模式就是对当前入口直接限流

2.关联 模式 : 当关联的资源达到阈值时就会对配置的资源进行限流 比如: 下单接口和查询订单接口,当我们对查询接口设置了流控规则并关联了下单接口,当下单接口的请求数量达到阈值时,就会对查询接口进行限流,这样就能保证下单接口的安全性

3.链路模式 : 对调用链路的入口进行限流,Sentinel不仅可以对接口入口进行限流还可以对方法进行限流. 例如 我们通过@SentinelResource 对 方法getUser 进行了限流,通过链路模式关联了接口A,在调用过程中,接口A和接口B都会调用getUser方法,当getUser方法达到调用阈值时,就会对关联的接口A进行限流,而接口B可以不受限制的进行调用.
 使用链路模式还需要配置一下web-context-unify配置,限流才会生效
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080
web-context-unify: false
3种流控效果
1.快速失败: 当并发量超过设置的阈值后,超出的请求会被直接拒绝.

- Warm Up(激增流量) : 流控预热模式有一个预热时长参数,当大量请求过来时,并不是直接处理相当于阈值数量的请求,而是在设置的预热时长内,逐渐递增式的处理请求,直到达到阈值数量.递增初始值的冷加载因子值为设置的阈值除以3.

- 排队等待(脉冲流量): 相当于队列,当大量请求过来时,超过阈值的请求不会马上拒绝,而是进行排队等待,并提供了一个设置超时时间的参数,在超时时间到期之前,如果前面的请求被出来完,排队等待中的请求会被继续处理

熔断降级(通常在consumer端组合配置)
除了流量控制以外,降低调用链路中的不稳定资源也是 Sentinel 的使命之一。由于调用关系的复杂性,如果调用链路中的某个资源出现了不稳定,最终会导致请求发生堆积。这个问题和 Hystrix 里面描述的问题是一样的。 
Sentinel 提供以下几种熔断策略:
慢调用比例 (SLOW_REQUEST_RATIO):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。 
异常比例 (ERROR_RATIO):当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。 
异常数 (ERROR_COUNT):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。 
注意异常降级仅针对业务异常,对 Sentinel 限流降级本身的异常(BlockException)不生效。为了统计异常比例或异常数,需要通过 Tracer.trace(ex) 记录业务异常。
相关参数
熔断降级规则说明 熔断降级规则(DegradeRule)包含下面几个重要的属性:
Field | 说明 | 默认值 |
---|
resource | 资源名,即规则的作用对象 | | grade | 熔断策略,支持慢调用比例/异常比例/异常数策略 | 慢调用比例 | count | 慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用);异常比例/异常数模式下为对应的阈值0~1之间的数 | | timeWindow | 熔断时长,单位为 s | | minRequestAmount | 熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断(1.7.0 引入) | 5 | statIntervalMs | 统计时长(单位为 ms),如 60*1000 代表分钟级(1.8.0 引入) | 1000 ms | slowRatioThreshold | 慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入) | |
整合Openfeign
1.添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.开启Openfeign对sentinel支持配置
feign:
sentinel:
enabled: true
3.添加对Openfeign接口的实现
public class UserFeignServuceFallback implements UserFeignServuce {
@Override
public String test() {
return null;
}
}
4.在Openfeign接口添加 fallback 属性,并指向实现类
@FeignClient(value = "manage-client",fallback = UserFeignServuceFallback.class)
public interface UserFeignServuce {
@RequestMapping(value = "/index/test")
String test();
}
热点参数限流
热点参数规则使用必须要配合 @SentinelResource 注解来处理

相关参数
热点参数规则(ParamFlowRule)类似于流量控制规则(FlowRule):
属性 | 说明 | 默认值 |
---|
resource | 资源名,必填 | | count | 限流阈值,必填 | | grade | 限流模式 | QPS 模式 | durationInSec | 统计窗口时间长度(单位为秒),1.6.0 版本开始支持 | 1s | controlBehavior | 流控效果(支持快速失败和匀速排队模式),1.6.0 版本开始支持 | 快速失败 | maxQueueingTimeMs | 最大排队等待时长(仅在匀速排队模式生效),1.6.0 版本开始支持 | 0ms | paramIdx | 热点参数的索引,必填,对应 SphU.entry(xxx, args) 中的参数索引位置 | | paramFlowItemList | 参数例外项,可以针对指定的参数值单独设置限流阈值,不受前面 count 阈值的限制。仅支持基本类型和字符串类型 | | clusterMode | 是否是集群参数流控规则 | false | clusterConfig | 集群流控相关配置 | |
控制台操作界面

系统保护规则
Sentinel 系统自适应保护从整体维度对应用入口流量进行控制,结合应用的 Load、总体平均 RT、入口 QPS 和线程数等几个维度的监控指标,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。 系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量生效。入口流量指的是进入应用的流量(EntryType.IN),比如 Web 服务或 Dubbo 服务端接收的请求,都属于入口流量。
相关参数
系统规则支持以下的阈值类型:
属性 | 说明 |
---|
Load(仅对 Linux/Unix-like 机器生效) | 当系统 load1 超过阈值,且系统当前的并发线程数超过系统容量时才会触发系统保护。系统容量由系统的 maxQps * minRt 计算得出。设定参考值一般是 CPU cores * 2.5 | CPU usage(1.5.0+ 版本) | 当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0) | RT | 当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒 | 线程数 | 当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护 | 入口 QPS | 当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护 |
控制台操作界面

Sentinel 规则持久化
(为什么要做持久化因为在控制台添加的配置是存在内存中的,当服务重启后会被清除掉)
当使用了nacos配置持久化参数后,如果要修改配置,要通过修改nacos config中添加的sentinel配置来更新,通过操作台添加的配置不能同步到nacos config中.
一般来说,规则的推送有下面三种模式:  生产环境一般推荐使用Push模式,通过Nacos来持久化配置
1.引入依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
2.在nacos上新建一个sentinel配置文件,默认为json格式 
[ { “resource”: “/api/test”, “count”:2, “grade”:1, “limitApp”:“default”, “strategy”:0, “controlBehavior”:0 } ]
3.yaml配置sentinel整合nacos持久化配置
spring:
application:
name: manage-client
cloud:
nacos:
server-addr: 127.0.0.1:8848
discovery:
username: nacos
password: nacos
namespace: public
sentinel:
transport:
dashboard: localhost:8080
web-context-unify: false
datasource:
nacos-sentinel:
nacos:
serverAddr: 127.0.0.1:8847
username: nacos
password: nacos
namespace: public
groupId: DEFAULT_GROUP
dataId: sentinel-config
ruleType: flow
|