前言
通过前几篇文章,我们对SpringCloudAlibaba及其组件有了一定的了解和使用,这篇文章就来带大家认识下另一个组件-Sentinel 。它是面向分布式服务架构的轻量级高可用流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来帮助用户保护服务的稳定性。
本文就从限流、熔断降级、热点、系统保护、授权等方面来介绍它的使用。
安装
Docker安装方式:
docker run --name sentinel \
-d -p 8858:8858 \
--restart=always -m 512m \
bladex/sentinel-dashboard
也可下载Jar包,自己安装:
官方下载地址:https://github.com/alibaba/Sentinel/releases
通过以下命令启动:
nohup java -server -Xms256m -Xmx256m -jar -Dsentinel.dashboard.auth.username=sentinel -Dsentinel.dashboard.auth.password=sentinel -Dserver.port=9090 -Dserver.servlet.session.timeout=7200 sentinel-dashboard-1.7.0.jar > sentinel.log 2>&1 &
登录
安装完之后,通过服务器Ip+端口访问控制台。
http://localhost:8858
# 账号密码默认都是:sentinel
显示如上页面说明安装成功,下面我们就可以在项目中配置集成了。
项目配置集成
# 增加依赖
除了sentinel依赖,还需要增加持久化依赖。如果不持久化,服务每次重启后,规则策略都需要重新配置。sentinel提供的持久化配置中心有redis、nacos、zk、file等,此处选用的是Nacos,对Nacos不熟悉的请查看前一篇文章《原来Nacos这么好用,注册、配置中心全用它了》。
<!--sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--sentinel持久化到nacos-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
# 增加配置项
sentinel.transport.dashboard 配置上文安装的sentinel-dashboard的地址。
其他规则配置,需要哪个就新增哪个即可,此处给出常用的几种配置。
spring:
application:
name: admin
cloud:
# nacos-配置
nacos:
# 配置中心
config:
server-addr: xxx:8848
file-extension: yaml
encode: UTF-8
group: xxx
namespace: xxx
# sentinel 流控
sentinel:
# 取消Sentinel控制台懒加载
eager: true
# 控制台地址
transport:
port: 8719
dashboard: xxx:8858
# 持久化数据库-nacos
datasource:
# 限流
flow:
nacos:
dataId: ${spring.application.name}-sentinel-flow.json
groupId: GOURD
# 规则
ruleType: flow
server-addr: ${spring.cloud.nacos.config.server-addr}
# 熔断降级
degrade:
nacos:
dataId: ${spring.application.name}-sentinel-degrade.json
groupId: GOURD
# 规则
ruleType: degrade
server-addr: ${spring.cloud.nacos.config.server-addr}
# 系统保护
system:
nacos:
dataId: ${spring.application.name}-sentinel-system.json
groupId: GOURD
# 规则
ruleType: system
server-addr: ${spring.cloud.nacos.config.server-addr}
# 授权
authority:
nacos:
dataId: ${spring.application.name}-sentinel-authority.json
groupId: GOURD
# 规则
ruleType: authority
server-addr: ${spring.cloud.nacos.config.server-addr}
# 热点
hot:
nacos:
dataId: ${spring.application.name}-sentinel-hot.json
groupId: GOURD
# 规则
ruleType: param_flow
server-addr: ${spring.cloud.nacos.config.server-addr}
# Naocs配置
nacos中需要相应配置上面配置中的dataId规则。
# 限流(flow)规则配置:
[{
"resource": "resource",
"limitApp": "default",
"grade": 1,
"count": 2,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}]
# resource: 资源名
# limitApp-流控应用: default(所有)
# grade-阈值类型: qps(1),线程数(0)
# count-单机阈值: 每秒2次
# strategy-流控模式: 直接(0),关联(1),链路(2)
# controlBehavior-流控方式: 快速失败(0),Warm Up(1),排队等待(2)
# 熔断降级规则配置:
[{
"resource": "resource",
"limitApp": "default",
"count": 60000,
"grade": 0,
"timeWindow": 20,
"minRequestAmount": 5
}]
# grade-阈值类型: 慢调用比例(0),异常比例(1),异常数(2)
# count:
# grade为0,表示 最大 RT
# grade为1,表示 异常比列(取值0~1)
# grade为2,表示 异常数
# timeWindow-熔断时长:降级时间间隔, 单位秒
# minRequestAmount-最小请求数
# 热点规则配置:
[{
"resource": "hot-resource",
"limitApp": "default",
"grade": 1,
"paramIdx": 0,
"count": 1,
"controlBehavior": 0,
"maxQueueingTimeMs": 0,
"burstCount": 0,
"durationInSec": 1,
"paramFlowItemList": [],
"clusterMode": false
}]
# paramIdx:参数索引,从0开始
# durationInSec:统计窗口时长,默认1s
# paramFlowItemList:参数例外项
# 系统保护规则配置:
[{
"grade": 3,
"highestSystemLoad": -1
"qps": 200,
"avgRt": -1,
"maxThread": -1,
"highestCpuUsage": -1
}]
# grade: LOAD(0),RT(1),线程数(2),入口 QPS (3),CPU 使用率(4)
# -1表示失效
# 授权规则配置:
[{
"resource": "auth-resource",
"limitApp": "default",
"strategy": 0
}]
# strategy:授权规则,0-白名单(默认),1-黑名单
授权规则限制可以用一句话就说明:如果配置的策略是黑名单且requester在配置在limitApp中,则请求拦截;如果配置的策略是白名单且requester在配置不在limitApp中,则请求拦截;否则请求不拦截。
# 需要限流的接口通过 @SentinelResource 进行埋点,value值和配置中的 resource 对应。
# 注册埋点切面Bean
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
return new SentinelResourceAspect();
}
# 增加全局异常拦截
这样可以统一处理Sentinel 的相关异常,也可以自定义提示信息。
@Slf4j
@RestControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class SentinelExceptionHandler{
@ExceptionHandler(value = UndeclaredThrowableException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public static BaseResponse handleException(UndeclaredThrowableException ex) {
log.error(ex.getMessage(),ex);
Throwable undeclaredThrowable = ex.getUndeclaredThrowable();
if(undeclaredThrowable instanceof FlowException){
return BaseResponse.fail("限流啦!");
}else if(undeclaredThrowable instanceof DegradeException){
return BaseResponse.fail("熔断啦!");
}else if(undeclaredThrowable instanceof ParamFlowException){
return BaseResponse.fail("热点限流啦!");
}else if(undeclaredThrowable instanceof SystemBlockException){
return BaseResponse.fail("系统限流啦!");
}else if(undeclaredThrowable instanceof AuthorityException){
return BaseResponse.fail(ResponseEnum.UNAUTHORIZED,"授权限制了!");
}
return BaseResponse.fail("Sentinel系统保护!");
}
}
# 项目启动
项目成功启动后,如果在Sentinel控制台出现你的服务,说明整合没有问题。
# 个别异常
如果报以下错误,升级JDK版本为1.8.0_152以上
Failed to bind properties under 'spring.cloud.sentinel.datasource.flow.nacos.rule-type' to com.alibaba.cloud.sentinel.datasource.RuleType:
Property: spring.cloud.sentinel.datasource.flow.nacos.ruletype
Value: FLOW
至此Sentinel集成就好了,下面我们进行测试。
测试
此处通过Jemeter进行并发模拟测试。
# 接口限流测试
首先在nacos中添加相应接口规则配置,如下
jemeter测试如下,因为我们配置了1秒内2次的限流,jemeter配置了3的并发,所以可以看到有一次接口请求被拦截。
# 熔断降级测试
此处为了方便测试,选择异常数来模拟测试
接口模拟异常调整如下
此处设置10并发,由于熔断设置了当异常次数达到2次,进行5秒的熔断。所以可以看到,2次模拟异常后,其余都是被sentinel熔断掉了。
其余的系统保护,此处就不做具体测试了,有兴趣的小伙伴可以自定测试。
写在最后
通过集成Sentinel,你的服务就相当有了一层保护壳,通过压力测试,得到系统的最大承受能力,然后进行配置,这样不管什么时候,你的服务都不会因为访问量突增等因素莫名的挂掉。通过结合Nacos,可以实现配置的热更新,即在Nacos调整完配置后,无需重启服务,配置即可生效。
相关代码摘自本人开源项目:https://gitee.com/gourd-hu/spring-cloud-plus
「往期文章」
END
扫码二维码,获取更多精彩