5.4、熔断规则
除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。我们需要对不稳定的弱依赖服务调用进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩,熔断降级作为保护自身的手段,通常在客户端(调用端进行配置)。
保护自身的的手段
- 并发控制(信号量隔离)
- 基于慢调用的比例熔断
- 基于异常的比例熔断
触发熔断后的处理逻辑实例
- 提供fallback实现(服务降级)
- 返回错误result
- 读缓存(DB访问降级)
5.4.1、慢调用比例
慢调用比例:选择以慢调用比例作为阈值,需要设置允许的慢调用RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值。
则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态,若接下来的一个请求响应时间小于设置的慢调用RT则结束熔断,若大于设置的慢调用RT则会再次被熔断。
1、添加方法
@RequestMapping("/test") @SentinelResource(value = "test",fallback = "testFallback") public String test() throws InterruptedException { Thread.sleep(101); return "正常访问"; } public String testFallback(Throwable e){ return "被熔断了"; }
2、添加规则
解释:10秒内有大于5个请求的访问,慢调用比例大于0.1就进行熔断。
测试:浏览器进行请求5次以上发现被熔断。
5.4.2、异常比例
1、添加接口
@RequestMapping("/errorTest") public String errorTest() { int i = 1/0; return "正常访问"; }
2、添加规则
解释:10秒内有大于5个请求的访问,异常比例大于0.1就进行熔断。
测试:浏览器进行请求5次以上发现被熔断。
5.4.3、异常数
1、添加规则
解释:10秒内有大于5个请求的访问,只有有一个异常就进行熔断。
测试:浏览器进行请求5次以上发现被熔断。
5.4.4、整合openFeign降级
在我们服务消费方去调用服务提供方的时候,由于提供方出现的错误,而导致我们的消费方也报错。这个时候就需要我们的sentinel进行整合降级处理。
问题演示:
1、服务提供方【加一个1/0的异常】
@RestController @RequestMapping("/stock") public class StockController { @Value("${server.port}") String value; @RequestMapping("/stockList") public String getStock(){ int i = 1/0; System.out.println("库存"); return "扣减库存"+value; } }
2、服务消费方
@FeignClient(value = "stock-server",path = "/stock") public interface StockFeignService { @RequestMapping("/stockList") public String getStock(); }
@RestController @RequestMapping("/order") public class OrderController { @Autowired StockFeignService stockFeignService; @GetMapping("/orderList") public String getOrder() { return stockFeignService.getStock(); } }
3、进行调用
1、这样就需要我们引入sentinel
依赖进行解决
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency>
2、application.yml
#对Feign的支持 feign: sentinel: enabled: true #添加feign对sentinel的支持
3、编写一个降级的类,去实现你的feign的service接口
@Component public class StockFeignServiceFallback implements StockFeignService{ @Override public String getStock() { return "降级了"; } }
4、接口添加fallback,对应你刚才编写的类
5、重启访问
5.5、热点参数流控
何为热点?热点即经常访问的数据,很多时候我们希望统计某个热点数据中访问频次最高的数据,并对其进行访问限制。
接口编辑:
@RequestMapping("/get/{id}") @SentinelResource(value = "getById",blockHandler = "hotBlockHandler") public String getById(@PathVariable("id") Integer id){ return "正常访问"; } public String hotBlockHandler(Integer id ,BlockException e) { return "热点异常处理"; }
添加规则:
单机阈值
- 情况一:假设参数大部分都是热点参数,那单机阈值就要对热点参数进行流控,后续额外对普通参数进行流控
- 情况二:假设参数大部分是普通参数,那单机阈值就要对普通参数进行流控,后续额外对热点参数进行流控
假设我们的参数是普通参数:
解释:设置一秒钟可以访问10次
保存完成后可以进行编辑,设置我们的热点参数:
解释:参数为1的,一秒只能访问两次。
结果:这个时候我们对id为1的进行访问,快速刷新访问就会被热点流控
5.6、系统规则
- 容量评估不到位,某个大流量接口限流配置不合理或没有配置,导致系统崩溃,来不及进行处理
- Load和cpu彪高,但是不知道什么原因造成的,来不及处理
- 一个机器挂了导致流量负载到另外的机器上,引起系统雪崩
- 希望有的兜底防护,即使缺乏容量评估也希望有一定的保护机制
一些指标:
- Load自适应(仅对Linux/Unix-like机器生效):系统的load1作为启发指标,进行自适应系统保护。
- CPU usage(1.5.0+版本):当系统CPU使用率超过阈值即触发系统保护(取值范围0.0-1.0),比较灵敏
- 平均RT: 当单台机器上所有入口流量的平均RT达到阈值即触发系统保护,单位是毫秒
- 并发线程数:当单台机器上所有入口流量的并发线程达到阈值触发系统保护
- 入口QPS:当单台机器上所有入口的QPS到达阈值即触发系统保护。
6、Sentinel规则持久化
我们实际开发环境中,肯定不希望我们重启后,这些规则就消失了,这个时候我们就需要持久化。
推模式:
生产环境下一班更常用的是push模式的数据源,对于push模式的数据源,如远程配置中心(ZooKeeper,Nacos,Apoll等等),推送的操作不应由Sentinel客户端进行,而应该经控制台统一进行管理,直接进行推送,数据源仅负责获取配置中心推送的配置并更新到本地。因此推送规则的正确做法应该是配置中心控制台/Sentinel控制台—>配置中心–>Sentinel数据源–>Sentinel,而不是经过Sentinel数据源推送至配置中心,这样的流程就非常清晰了。
6.1、基于Nacos配置中心控制台实现推送
引入依赖
<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency>
nacos中新建一个配置
Field | 说明 | 默认值 |
resource | 资源名,资源名是限流规则的作用对象 | |
count | 限流阈值 | |
grade | 限流阈值类型,QPS 模式(1)或并发线程数模式(0) | QPS 模式 |
limitApp | 流控针对的调用来源 | default ,代表不区分调用来源 |
strategy | 调用关系限流策略:直接、链路、关联 | 根据资源本身(直接) |
controlBehavior | 流控效果(直接拒绝/WarmUp/匀速+排队等待),不支持按调用关系限流 | 直接拒绝 |
clusterMode | 是否集群限流 | 否 |
yml配置
server: port: 8005 # 服务名称 spring: application: name: order-sentinel cloud: sentinel: transport: #配置sentinel的地址以及端口号 dashboard: 127.0.0.1:8010 web-context-unify: false # 默认将调用链路收敛 datasource: hello-rule: #可以自定义 nacos: #配置的名字 data-id: order-sentinel-hello-rule server-addr: 101.34.254.160:8847 data-type: json rule-type: flow
重启项目:
流控规则成功进来了,我们进行快速刷新接口,测试流控效果
流控效果也正常显示。