限流为了防止过度使用资源造成系统不稳,熔断是为了识别出”坏”资源,避免好的资源受牵连(雪崩效应),是保证系统稳定性的关键,也是资源有效使用的关键,sentinel熔断插槽名称Degrade(降级),本人觉得应该改为熔断,降级是熔断的补偿措施,因此本文使用"熔断"
下图是熔断参与的类互动图,熔断做两件事:一,识别坏资源,设置断开状态;二,适时探测坏资源是否已好,恢复闭合状态
上图是参与熔断的类互动图
CircutBreaker 熔断器,有两个实现,使用异常指标和使用rt指标,两者内嵌LeapArray实现,统计相关指标,这里先放个疑问,为什么不使用指标统计插槽?我翻看1.8.0之前的版本,熔断的指标使用ClusterNode计算,ClusterNode的数据来源是统计插槽
概念
指标
降级依赖的指标,响应时间(超时请求/超时请求比例);异常比例/异常数
状态
断路器的状态,
断开,请求不能通过;
半开,定时放行请求,测试资源是否正常;
闭合,请求可通过
熔断检查分析
上图熔断检查方法,断路器闭合,请求通过;断路器断开,若到达尝试时间,进入半开状态,让请求通过,测试一下资源是否可用
首先设置为半开状态,设置terminate处理器,该处理器重新设置资源状态为断开,意味着该处理器在请求被block时执行;返回true,让请求通过。从这里可以大概猜到,熔断逻辑在调用完成后执行。
资源执行有两种情况,不通过,抛出BlockException;通过,无抛出BlockException,下面分别分析
抛出BlockException
下图是CtSph获取Entry的方法,在Context和Entry那篇介绍过,该方法捕获和处理BlockException,调用Entry的exit
下图是CtEntry的exit方法,这里就是执行上面的terminate处理器,测试不通过,重新设为断开状态
无抛出BlockException异常
下图红框是熔断插槽exit方法,无BlockException分支的代码,资源执行完,需要对返回时间,有没有资源抛出的异常进行统计
CircuitBreaker有两个实现,ResponseTimeCircuitBreaker和ExceptionCircuitBreaker,前者对返回时间判别和统计,后者对资源执行中的异常统计,下面以ResponseTimeCircuitBreaker为例分析
逻辑比较简单,如果对统计不熟悉可以参看插槽统计那篇文章
计算两个指标,返回时间(rt) 和超时请求比例,rt用于半开状态下,是断开还是闭合;超时比例用于在闭合状态下,是否断开
另外,有两点值得注意
List<SlowRequestCounter> counters = slidingCounter.values();
计算超时请求比例使用整个统计时长的数据,而不像限流那样使用统计是滑动窗口时长内的数据,原有rt/rt超时比例是两个策略,现版本柔合在一起,查了一下文档,
文档上描述也是用整个统计时长,还记得开始时哪个问题,为什么不使用指标统计插槽?
到这里,我觉得有答案,"节奏"不一样,相对于限流需要细粒度时间,获得更精确的控制,熔断需要更稳健的控制,防止闪开闪合
其他
本系列没有分析:热点参数限流, dashboard,AuthoritySlot,SystemSlot , 适配器,集群流控
热点参数限流
SystemSlot
dashboard 在改造一文分析过,本文不重复介绍
AuthoritySlot 来源黑白名单,我觉得这个跟流控没有关系,调用来源控制应该交给权限模块
适配器 sentinel提供众多适配器,覆盖大部分的常用技术组件,因地制宜地置入sentinel的逻辑,通常是拦截器机制或者代理机制,本文就不一一分析
集群流控 关于集群流控,没有找到token服务集群的方案,没有必要分析,之前使用redis-lua开发分布式限流,可以参看
分布式限流/动态限流设计与实现(附源码)_动态限流下分布式调出限流设计与实现-CSDN博客,
估计技术基础大概是redis差不多
展望
Sentinel提供丰富的限流熔断功能,但有点最关键,规则阀值怎么定?一般是通过压测得到系统各业指标,场景是sentinel提供,sentinel是不是可以提供这样的压测工具, 通过动态递增或递减指标阀值,获取指标设定最佳