Sentinel 是由阿里巴巴开源的一款流量控制和熔断降级组件,旨在通过灵活的流量控制和熔断降级机制,帮助开发者保护微服务架构中的应用和服务。
官网:home | Sentinel (sentinelguard.io)
一、安装sentinel
1.方式一:用docker-compose 安装
docker-compose.yml 如下所示
# 参考链接:https://blog.51cto.com/chaim/4582366
# Compose 版本 Version 2支持更多的指令。Version 1将来会被弃用。
version: "3"
# 定义服务
services:
# 为project定义服务
sentinel:
image: bladex/sentinel-dashboard:1.8.6
ports:
- 18858:8858
environment:
# 是否开启登录鉴权,仅用于日常测试,生产上不建议关闭, 默认true
auth.enabled: "true"
# 登录控制台的用户名,默认为 sentinel
sentinel.dashboard.auth.username: znak
# 登录控制台的密码,默认为 sentinel
sentinel.dashboard.auth.password: znak2020
# 用于指定 Spring Boot 服务端 session 的过期时间,如 7200 表示 7200 秒;60m 表示 60 分钟,默认为 30 分钟;
server.servlet.session.timeout: 7200
restart: always
container_name: sentinel
privileged: true
2.方式二:离线下载jar包,手动构建镜像
从github上下载 1.8.6版本jar包
新建Dockerfile文件
#java 版本
FROM openjdk:8-jre
##挂载的docker卷
VOLUME /data/sentinel/tmp
# 定义jar包名称
# ENV JAR_FILE *.jar # 这里因为只有一个 jar 包,简便我就直接写 *.jar 了
# 拷贝 jar 包到容器内
ADD sentinel-dashboard-1.8.6.jar sentinel-dashboard.jar
# 定义时区参数
ENV TZ=Asia/Shanghai
# 设置时区
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo '$TZ' > /etc/timezone
# 配置启动命令
ENTRYPOINT ["java", "-Dsentinel.dashboard.auth.username=znak", "-Dsentinel.dashboard.auth.password=znak2020", "-jar", "/sentinel-dashboard.jar"]
执行build-run.sh脚本,如下所示
# 构建镜像
docker build -t sentinel-dashboard:1.8.6 .
# 运行容器
docker run --name sentinel-dashboard -p 18080:8080 --restart=always --privileged=true -d sentinel-dashboard:1.8.6
3.验证
访问http://IP:18080/ 可以看到sentinel的控制台页面,账号密码为刚刚Dockerfile里或docker-compose.yml里设置的
二、集成Spring Cloud
1.添加依赖
集成Spring Cloud需要注意版本关系,可参考
版本说明 · alibaba/spring-cloud-alibaba Wiki · GitHub
<!-- SpringCloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2021.0.5.0</version>
</dependency>
2.修改配置
yml:
spring:
cloud:
sentinel:
transport:
port: 20240 #任意,不冲突即可
dashboard: 192.168.100.52:18080
3.初体验
启动sentinel,并且对某个微服务做好上述的配置后,启动微服务,并且对服务的接口进行访问(sentinel是懒加载机制),此时查看sentinel控制台,可看到已经监控到了流量
此时可以进入流控规则和熔断规则去手动添加流控规则和熔断规则
但是在这里添加的规则只是临时生效,重启了微服务就会清空了,所以后续我们需要还需要集成nacos将流控规则和熔断规则写在nacos配置文件里,实现规则永久化和可实时修改
1.限流降级
controller层
@ApiOperation("分页查询危险作业信息列表")
@PostMapping("/page")
@SentinelResource(value = "constructionWorkSearchPage", blockHandlerClass = SentinelCommonService.class, blockHandler = "constructionWorkSearchPageBlock")
public ResponseResult<PageResult<ConstructionWorkExcelVO>> page(@RequestBody @Validated ConstructionWorkDTO constructionWorkDTO) {
return ResponseResult.success(constructionWorkService.searchPage(constructionWorkDTO));
}
在接口上添加@SentinelResource注解,参数分别是value 资源名(注意不要和接口路径一样,听说是会导致走不到降级方法里);blockHandlerClass 降级方法所在类(写在本类则不用加该参数);blockHandler 降级方法名
@SentinelResource也可以加在service方法上(实现类),效果则是针对方法限流(熔断同理)
SentinelCommonService.java
public class SentinelCommonService {
/**
* 分页查询危险作业信息列表 降级方法,需包含限流方法的所有参数和BlockException参数,且返回值要保持一致
* @param dto
* @param e
*/
public static ResponseResult<PageResult<ConstructionWorkExcelVO>> constructionWorkSearchPageBlock(ConstructionWorkDTO dto, BlockException e) {
log.info("分页查询危险作业信息列表请求被限流:{}", dto);
throw new ServicesException(ResultStatus.SENTINEL_FLOW_LIMIT);
}
}
- 注意限流降级方法(熔断同理)需要包含BlockException e参数,返回值也要保持一致
- 参数列表中可以把限流方法(熔断同理)的参数加上,这样就可以在降级方法中获取原请求参数做日志等操作了
- 注意如果降级方法写在与限流方法(熔断同理)不同的类里,需要加上static修饰符,否则会识别不到
效果
去sentinel控制台手动添加一个与上述资源对应的流控规则
如上图,表示当qps达到1(1次/秒)时,会快速失败,进入到降级方法中
还有其他的规则,例如warm up是预热,如下,则表示允许在10秒内达到qps是1,也就是至少10秒之后才会限流(适用于秒杀等瞬间高并发场景)
2.熔断降级
sentinel的熔断降级和feign的熔断降级类似,都是服务发生异常的时候,让他流量不在进入,而走向兜底方法;不过一个是针对外界访问的,一个是针对服务之间远程调用的
controller层
/**
* 测试熔断
* @return
*/
@Override
@ApiOperation(value = "测试熔断", notes = "测试熔断", httpMethod = "GET")
@GetMapping(ConstructionProviderConstant.TEST_FEIGN)
@SentinelResource(value = ConstructionProviderConstant.TEST_FEIGN, fallbackClass = ConstructionProviderFallback.class, fallback = "testFeign")
public ResponseResult<String> testFeign() {
//线程休眠12500ms,模拟超时
try {
Thread.sleep(12500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return ResponseResult.success("---------------testFeign接口正常------------------");
}
参数分别是value 资源名(同上);fallbackClass 降级方法所在类(同上);fallback 降级方法名
由于该项目对异常基本都做了全局捕获处理,所以测试熔断改用模拟超时来实现
ConstructionProviderFallback.java
public class ConstructionProviderFallback {
public static ResponseResult<String> testFeign() {
log.info("testFeign请求熔断");
throw new ServicesException(ResultStatus.SENTINEL_DEGRADE);
}
}
注意事项同上
效果
表示在1000ms(1秒)内达到1个请求以上,且响应超100ms的数量占比超过1(100%),就会触发熔断,熔断时长3秒【如果未配置降级方法,则会直接抛异常,配置了则会走自定义的降级方法】
三、集成Nacos
1.添加依赖
<!-- sentinel + nacos -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<version>1.8.6</version>
</dependency>
2.修改配置
spring:
cloud:
sentinel:
datasource: #sentinel用nacos作为数据源的配置
ds1: #流控规则管理(这个名称可以自定义)
nacos: # 告诉sentinel用nacos作为数据源
data-id: sentinel-spmp-gateway
group-id: spmp-system
server-addr: 192.168.100.53:8848
username: nacos
password: nacos
rule-type: flow
data-type: json
namespace: 17a4ea5e-f549-4e4a-97a4-52ee2a9f466c
degree: #熔断规则管理(同上)
nacos:
data-id: sentinel-spmp-degrade
group-id: spmp-system
server-addr: 192.168.100.53:8848
username: nacos
password: nacos
rule-type: degrade
data-type: json
namespace: 17a4ea5e-f549-4e4a-97a4-52ee2a9f466c
注意这里的data-id、group-id、namespace,指定了nacos上的一个配置文件,如下,以限流规则为例:
[{
"resource": "spmp-auth",
"count": 500,
"grade": 1,
"limitApp": "default",
"strategy": 0,
"controlBehavior": 0
},
{
"resource": "constructionWorkSearchPage",
"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:是否集群。
此时重新查看sentinel控制台,会读取nacos的配置文件获取流控规则了,如图所示:
熔断同理,配置json解释如下
// 资源名
"resource": "/test1",
"limitApp": "default",
// 熔断策略(0:慢调用比例,1:异常比率,2:异常计数)
"grade": 0,
// 最大RT、比例阈值、异常数
"count": 200,
// 慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入)
"slowRatioThreshold": 0.2,
// 最小请求数
"minRequestAmount": 5,
// 当单位统计时长(类中默认1000)
"statIntervalMs": 1000,
// 熔断时长
"timeWindow": 10