vlambda博客
学习文章列表

还在为服务限流发愁?那必须解一下Sentinel了

前言

通过前几篇文章,我们对SpringCloudAlibaba及其组件有了一定的了解和使用,这篇文章就来带大家认识下另一个组件-Sentinel 。它是面向分布式服务架构的轻量级高可用流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来帮助用户保护服务的稳定性。

本文就从限流、熔断降级、热点、系统保护、授权等方面来介绍它的使用。

安装

Docker安装方式:

docker run --name sentinel \-d -p 8858:8858 \--restart=always -m 512m \bladex/sentinel-dashboard

也可下载Jar包,自己安装:

通过以下命令启动:

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了

项目配置集成

# 增加依赖

除了sentinel依赖,还需要增加持久化依赖。如果不持久化,服务每次重启后,规则策略都需要重新配置。sentinel提供的持久化配置中心有redis、nacos、zk、file等,此处选用的是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>

# 增加配置项 

其他规则配置,需要哪个就新增哪个即可,此处给出常用的几种配置。

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)规则配置:

还在为服务限流发愁?那必须解一下Sentinel了

[{ "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 对应。

还在为服务限流发愁?那必须解一下Sentinel了

# 注册埋点切面Bean

@Beanpublic 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控制台出现你的服务,说明整合没有问题。

还在为服务限流发愁?那必须解一下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.ruletypeValue: FLOW

还在为服务限流发愁?那必须解一下Sentinel了

至此Sentinel集成就好了,下面我们进行测试。

测试

此处通过Jemeter进行并发模拟测试。

# 接口限流测试

首先在nacos中添加相应接口规则配置,如下

还在为服务限流发愁?那必须解一下Sentinel了

jemeter测试如下,因为我们配置了1秒内2次的限流,jemeter配置了3的并发,所以可以看到有一次接口请求被拦截。

还在为服务限流发愁?那必须解一下Sentinel了

# 熔断降级测试

此处为了方便测试,选择异常数来模拟测试

还在为服务限流发愁?那必须解一下Sentinel了

接口模拟异常调整如下

还在为服务限流发愁?那必须解一下Sentinel了

此处设置10并发,由于熔断设置了当异常次数达到2次,进行5秒的熔断。所以可以看到,2次模拟异常后,其余都是被sentinel熔断掉了。

还在为服务限流发愁?那必须解一下Sentinel了

其余的系统保护,此处就不做具体测试了,有兴趣的小伙伴可以自定测试。

写在最后
通过集成Sentinel,你的服务就相当有了一层保护壳,通过压力测试,得到系统的最大承受能力,然后进行配置,这样不管什么时候,你的服务都不会因为访问量突增等因素莫名的挂掉。

通过结合Nacos,可以实现配置的热更新,即在Nacos调整完配置后,无需重启服务,配置即可生效。


「往期文章」



还在为服务限流发愁?那必须解一下Sentinel了

END

扫码二维码

获取更多精彩

JAVA识界