十四、使用Sentinal进行限流熔断
内容
- sentinal限流降级:限流是接口流量太大要进行限制,限制后的流量进行降级。
- sentinal熔断降级:熔断是A调用B,而B不靠谱,就熔断不调用,并降级。
- sentinal+nacos组合。
常见的限流算法
- 静态窗口限流
- 动态窗口限流
例如:当前是第2.5秒
静态:统计第2秒到现在的请求数
动态:统计第1.5秒到现在的请求数
- 漏桶限流:所有的请求放入队列,请求超出队列上限则失败
- 令牌桶算法:令牌桶放令牌,每秒按多少往桶里放令牌,请求进来就取令牌。
- 令牌大闸:在令牌桶的基础上做控制,初始给多少令牌。
初识sentinal
Sentinel 功能
流量控制
很多请求调用方法,而系统的处理能力是有限的。需要根据系统的处理能力对流量进行控制。只允许一定量的请求进入。流量控制是在被调用方,在接口入口限流。
熔断降级
某一服务不稳定,调用方要主动断开。
限流主要用在被调用方,熔断在调用方。
sentinel初体验
引入sentinel依赖
<!--限流熔断--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency>
启动类新增限流方法,默认qps限流
1 private static void initFlowRules(){ 2 List<FlowRule> rules = new ArrayList<>(); 3 FlowRule rule = new FlowRule(); 4 rule.setResource("doConfirm"); 5 rule.setGrade(RuleConstant.FLOW_GRADE_QPS); 6 // Set limit QPS to 1. 7 rule.setCount(1); 8 rules.add(rule); 9 FlowRuleManager.loadRules(rules); 10 }
还要对限流的线程进行处理,否则会抛出FlowException异常。
doConfirm增加注解,说明限流后怎么处理
@SentinelResource(value = "doConfirm", blockHandler = "doConfirmBlock")
public void doConfirmBlock(ConfirmOrderDoReq req, BlockException e) {
LOG.info("购票请求被限流:{}", req);
throw new BusinessException(BusinessExceptionEnum.CONFIRM_ORDER_FLOW_EXCEPTION);
}
}
使用sentinel控台监控流量
启动控制台命令
java -Dserver.port=18080 -Dcsp.sentinel.dashboard.server=localhost:18080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.6.jar
windows 要把-D命令放到-jar命令之后,否则会报错。
8719是固定的,18080可以在命令行更改
后台可以看到请求通过的数量。
使用Sentinel配置限流
之前的配置写在代码的启动类,还有之前的限流设置在方法里,也可以对某个接口进行限流。通过控台可以实现。
簇点链路
代码中不写死限流规则,通过控台来配置,但是控台配置后,重启会清空所有的配置。接口的资源名称不要和接口路径一致,会导致限流后走不到降级方法中
降级方法
/** 降级方法,需包含限流方法的所有参数和BlockException参数,且返回值要保持一致 * @param req * @param e */ public CommonResp<Object> doConfirmBlock(ConfirmOrderDoReq req, BlockException e) { LOG.info("ConfirmOrderController购票请求被限流:{}", req); // throw new BusinessException(BusinessExceptionEnum.CONFIRM_ORDER_FLOW_EXCEPTION); CommonResp<Object> commonResp = new CommonResp<>(); commonResp.setSuccess(false); commonResp.setMessage(BusinessExceptionEnum.CONFIRM_ORDER_FLOW_EXCEPTION.getDesc()); return commonResp; }
Sentinel+Nacos实现限流规则持久化
引入依赖
<!--sentinel+nacos--> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency>
客户端和nacos关联
# sentinel控台:https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel
spring.cloud.sentinel.transport.port=8719
spring.cloud.sentinel.transport.dashboard=localhost:18080
# sentinel + nacos
spring.cloud.sentinel.datasource.nacos.nacos.serverAddr=localhost:8848
spring.cloud.sentinel.datasource.nacos.nacos.namespace=train
spring.cloud.sentinel.datasource.nacos.nacos.groupId=TRAIN_GROUP
spring.cloud.sentinel.datasource.nacos.nacos.dataId=sentinel
spring.cloud.sentinel.datasource.nacos.nacos.ruleType=flow
配置限流规则
对应规则
通过nacos修改sentinel配置。
sentinel限流不同的流控效果 -- 快速失败 & Warm up & 排队等待
warm up可以选择预热时常,qps从阈值/3开始,经过预热时常升至QPS阈值。比如阈值是100,时长是10s,则从33开始经过10s上升到100.
500个线程,如果阈值是10,那么其他的线程在超时时间内就会排队等待。超过超时时间就会失败。
sentinel限流不同的流控模式 -- 关联&链路
关联:对目标的限流是有条件的,需要关联的资源限流时,目标才会限流。hello被限流,hello1才会限流。
链路:从指定路径进来才会限流。比如从hello访问hello1,hello1才会限流。而从hello2访问hello1则不限流。
sentinel+feign熔断初体验
如果businessFeign.hello调用不顺利,会影响整个功能使用。
那么businessHello从哪来?
构造一个备用的值(熔断降级)
1s中有30%的请求最大响应时间超过201,后面的11s都不会访问business。
sentinel+feign熔断后的降级处理
增加一个异常处理,不能添加SentinelResource注解
添加一个类,实现接口BusinessFeign接口,写备用方案
@Component public class BusinessFeignFallback implements BusinessFeign { @Override public String hello() { return "Fallback"; } @Override public CommonResp<Object> genDaily(Date date) { return null; } }
请求数超过6,每秒统计异常比例,如果30%出现异常,熔断。
请求数超过6,每秒统计异常比例,如果3次出现异常,熔断。