目录

  • 一、DegradeRule
  • 一、DegradeSlot
  • 三、ResponseTimeCircuitBreaker
  • 四、ExceptionCircuitBreaker

一、DegradeRule

     /*** 降级策略:慢调用比例、异常比例、异常数*/private int grade = RuleConstant.DEGRADE_GRADE_RT;/*** 阈值:最大RT、比例阈值、异常数*/private double count;/*** 降级恢复时间,多久后结束降级*/private int timeWindow;/*** 触达熔断的最小请求数量*/private int minRequestAmount = RuleConstant.DEGRADE_DEFAULT_MIN_REQUEST_AMOUNT;/*** RT 模式的慢比例阈值*/private double slowRatioThreshold = 1.0d;/*** 统计时长*/private int statIntervalMs = 1000;

一、DegradeSlot

1、entry( )

在entry方法中,对熔断规则的状态进行判断,CLOSE 状态通过规则,OPEN 状态时检验熔断时间是否已经过去,如果过去了则更新状态为 HALF_OPEN。

·(1)、entry( )

 @Overridepublic void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count,boolean prioritized, Object... args) throws Throwable {//执行熔断规则检查performChecking(context, resourceWrapper);//下一个节点fireEntry(context, resourceWrapper, node, count, prioritized, args);}

(2)、performChecking( )

 void performChecking(Context context, ResourceWrapper r) throws BlockException {//获取该资源的熔断规则List<CircuitBreaker> circuitBreakers = DegradeRuleManager.getCircuitBreakers(r.getName());if (circuitBreakers == null || circuitBreakers.isEmpty()) {return;}for (CircuitBreaker cb : circuitBreakers) {//规则检验if (!cb.tryPass(context)) {throw new DegradeException(cb.getRule().getLimitApp(), cb.getRule());}}}

(3)、tryPass( )

     @Overridepublic boolean tryPass(Context context) {// Template implementation.//熔断处于关闭状态,返回成功if (currentState.get() == State.CLOSED) {return true;}//熔断处于打开状态if (currentState.get() == State.OPEN) {// For half-open state we allow a request for probing.//校验降级时间是否已经过了,从打开状态转换成半开状态return retryTimeoutArrived() && fromOpenToHalfOpen(context);}return false;}

(4)、retryTimeoutArrived( )

 protected boolean retryTimeoutArrived() {return TimeUtil.currentTimeMillis() >= nextRetryTimestamp;}

(5)、fromOpenToHalfOpen( )

     protected boolean fromOpenToHalfOpen(Context context) {//更新状态,由 OPEN 到 HALF_OPENif (currentState.compareAndSet(State.OPEN, State.HALF_OPEN)) {//通知观察者状态变化notifyObservers(State.OPEN, State.HALF_OPEN, null);Entry entry = context.getCurEntry();//注册exitHandlers,在执行链 Slot chain 执行完退出后,会回调exitHandlersentry.whenTerminate(new BiConsumer<Context, Entry>() {@Overridepublic void accept(Context context, Entry entry) {// Note: This works as a temporary workaround for https://github.com/alibaba/Sentinel/issues/1638// Without the hook, the circuit breaker won't recover from half-open state in some circumstances// when the request is actually blocked by upcoming rules (not only degrade rules).//如果出现了BlockExceptionif (entry.getBlockError() != null) {// Fallback to OPEN due to detecting request is blocked//将状态恢复,由 HALF_OPEN 到 OPENcurrentState.compareAndSet(State.HALF_OPEN, State.OPEN);//通知监听者notifyObservers(State.HALF_OPEN, State.OPEN, 1.0d);}}});return true;}return false;}

2、exit( )

     public void exit(Context context, ResourceWrapper r, int count, Object... args) {Entry curEntry = context.getCurEntry();//出现异常,直接执行下一个节点if (curEntry.getBlockError() != null) {fireExit(context, r, count, args);return;}List<CircuitBreaker> circuitBreakers = DegradeRuleManager.getCircuitBreakers(r.getName());//没有熔断规则,直接执行下一个节点if (circuitBreakers == null || circuitBreakers.isEmpty()) {fireExit(context, r, count, args);return;}if (curEntry.getBlockError() == null) {// passed requestfor (CircuitBreaker circuitBreaker : circuitBreakers) {//调用每一个熔断规则的 onRequestComplete,分别有ResponseTimeCircuitBreaker、ExceptionCircuitBreakercircuitBreaker.onRequestComplete(context);}}//执行下一个节点fireExit(context, r, count, args);}

三、ResponseTimeCircuitBreaker

慢调用比例的处理逻辑,时间窗口使用的是SlowRequestLeapArray ,对应的bucket是 SlowRequestCounter

1、SlowRequestLeapArray

static class SlowRequestLeapArray extends LeapArray<SlowRequestCounter> {public SlowRequestLeapArray(int sampleCount, int intervalInMs) {super(sampleCount, intervalInMs);}@Overridepublic SlowRequestCounter newEmptyBucket(long timeMillis) {return new SlowRequestCounter();}@Overrideprotected WindowWrap<SlowRequestCounter> resetWindowTo(WindowWrap<SlowRequestCounter> w, long startTime) {w.resetTo(startTime);w.value().reset();return w;}}

2、SlowRequestCounter

 static class SlowRequestCounter {private LongAdder slowCount;private LongAdder totalCount;public SlowRequestCounter() {//慢请求数量this.slowCount = new LongAdder();//总请求数量this.totalCount = new LongAdder();}public LongAdder getSlowCount() {return slowCount;}public LongAdder getTotalCount() {return totalCount;}public SlowRequestCounter reset() {slowCount.reset();totalCount.reset();return this;}@Overridepublic String toString() {return "SlowRequestCounter{" +"slowCount=" + slowCount +", totalCount=" + totalCount +'}';}}

3、onRequestComplete( )

  public void onRequestComplete(Context context) {//当前时间窗口的慢请求计数器SlowRequestCounter counter = slidingCounter.currentWindow().value();Entry entry = context.getCurEntry();if (entry == null) {return;}long completeTime = entry.getCompleteTimestamp();if (completeTime <= 0) {completeTime = TimeUtil.currentTimeMillis();}//计算响应时间long rt = completeTime - entry.getCreateTimestamp();//大于阈值,为慢请求if (rt > maxAllowedRt) {counter.slowCount.add(1);}//总数量也加1counter.totalCount.add(1);//处理熔断规则状态handleStateChangeWhenThresholdExceeded(rt);}

4、handleStateChangeWhenThresholdExceeded( )

 private void handleStateChangeWhenThresholdExceeded(long rt) {//已经是打开状态if (currentState.get() == State.OPEN) {return;}//半开状态if (currentState.get() == State.HALF_OPEN) {// In detecting request// TODO: improve logic for half-open recoveryif (rt > maxAllowedRt) {//熔断时间过去后的下一次请求处于半开状态,此时又超时了,直接由半开变为打开fromHalfOpenToOpen(1.0d);} else {//没有超时,由半开变为关闭fromHalfOpenToClose();}return;}//获取窗口计数器List<SlowRequestCounter> counters = slidingCounter.values();long slowCount = 0;long totalCount = 0;for (SlowRequestCounter counter : counters) {//慢请求数量slowCount += counter.slowCount.sum();//总请求数量totalCount += counter.totalCount.sum();}//总数量 达不到 触达熔断的最小请求数量if (totalCount < minRequestAmount) {return;}//慢请求比例double currentRatio = slowCount * 1.0d / totalCount;if (currentRatio > maxSlowRequestRatio) {//打开熔断transformToOpen(currentRatio);}}

5、transformToOpen( )

     protected void transformToOpen(double triggerValue) {State cs = currentState.get();switch (cs) {case CLOSED:fromCloseToOpen(triggerValue);break;case HALF_OPEN:fromHalfOpenToOpen(triggerValue);break;default:break;}}

6、fromCloseToOpen( )

状态由 Close 到 Open

 protected boolean fromCloseToOpen(double snapshotValue) {State prev = State.CLOSED;if (currentState.compareAndSet(prev, State.OPEN)) {//更新熔断结束时间updateNextRetryTimestamp();//通知状态变化notifyObservers(prev, State.OPEN, snapshotValue);return true;}return false;}
 protected void updateNextRetryTimestamp() {//当前时间加上熔断恢复时间this.nextRetryTimestamp = TimeUtil.currentTimeMillis() + recoveryTimeoutMs;}

7、fromHalfOpenToOpen( )

状态由 HALF_OPEN 到 Open

  protected boolean fromHalfOpenToOpen(double snapshotValue) {if (currentState.compareAndSet(State.HALF_OPEN, State.OPEN)) {updateNextRetryTimestamp();notifyObservers(State.HALF_OPEN, State.OPEN, snapshotValue);return true;}return false;}

8、fromHalfOpenToClose( )

状态由 HALF_OPEN 到 Close

 protected boolean fromHalfOpenToClose() {if (currentState.compareAndSet(State.HALF_OPEN, State.CLOSED)) {//重置统计指标resetStat();notifyObservers(State.HALF_OPEN, State.CLOSED, null);return true;}return false;}
 public void resetStat() {// Reset current bucket (bucket count = 1).slidingCounter.currentWindow().value().reset();}
public SlowRequestCounter reset() {slowCount.reset();totalCount.reset();return this;}

四、ExceptionCircuitBreaker

异常比例、异常数 熔断规则的处理逻辑,时间窗口使用的是SimpleErrorCounterLeapArray,对应的bucket是 SimpleErrorCounter

1、SimpleErrorCounterLeapArray

static class SimpleErrorCounterLeapArray extends LeapArray<SimpleErrorCounter> {public SimpleErrorCounterLeapArray(int sampleCount, int intervalInMs) {super(sampleCount, intervalInMs);}@Overridepublic SimpleErrorCounter newEmptyBucket(long timeMillis) {return new SimpleErrorCounter();}@Overrideprotected WindowWrap<SimpleErrorCounter> resetWindowTo(WindowWrap<SimpleErrorCounter> w, long startTime) {// Update the start time and reset value.w.resetTo(startTime);w.value().reset();return w;}}

2、SimpleErrorCounter

 static class SimpleErrorCounter {//异常数量private LongAdder errorCount;//总数量private LongAdder totalCount;public SimpleErrorCounter() {this.errorCount = new LongAdder();this.totalCount = new LongAdder();}public LongAdder getErrorCount() {return errorCount;}public LongAdder getTotalCount() {return totalCount;}public SimpleErrorCounter reset() {errorCount.reset();totalCount.reset();return this;}@Overridepublic String toString() {return "SimpleErrorCounter{" +"errorCount=" + errorCount +", totalCount=" + totalCount +'}';}}

3、onRequestComplete( )

 public void onRequestComplete(Context context) {Entry entry = context.getCurEntry();if (entry == null) {return;}Throwable error = entry.getError();//当前时间窗口的慢请求计数器SimpleErrorCounter counter = stat.currentWindow().value();//有异常时,异常数量加1if (error != null) {counter.getErrorCount().add(1);}//总数量加1counter.getTotalCount().add(1);//处理熔断状态变化handleStateChangeWhenThresholdExceeded(error);}

4、handleStateChangeWhenThresholdExceeded( )

 private void handleStateChangeWhenThresholdExceeded(Throwable error) {//打开状态if (currentState.get() == State.OPEN) {return;}//半开状态if (currentState.get() == State.HALF_OPEN) {// In detecting requestif (error == null) {//没有异常,由半开变为关闭fromHalfOpenToClose();} else {//有异常,由半开变为打开fromHalfOpenToOpen(1.0d);}return;}//关闭状态//获取时间窗口异常计数器List<SimpleErrorCounter> counters = stat.values();long errCount = 0;long totalCount = 0;for (SimpleErrorCounter counter : counters) {//异常总数errCount += counter.errorCount.sum();//请求总数totalCount += counter.totalCount.sum();}//总数小于触达熔断的最小请求数量if (totalCount < minRequestAmount) {return;}double curCount = errCount;if (strategy == DEGRADE_GRADE_EXCEPTION_RATIO) {// Use errorRatio//异常比例curCount = errCount * 1.0d / totalCount;}//比较异常比例或者比较异常数if (curCount > threshold) {//打开熔断,跟ResponseTimeCircuitBreaker一样调用父类AbstractCircuitBreaker的方法transformToOpen(curCount);}}

spring cloud alibaba 学习(二十一)Sentinel服务熔断降级DegradeSlot相关推荐

  1. Spring cloud alibaba(二)nacos服务发现docker相同ip冲突

    引入服务发现其实比较简单 项目架构:同Spring cloud alibaba(一)多模块项目整合 spring cloud - pay - smdd - coupon - base - order- ...

  2. Spring Cloud Alibaba配置实例nacos+sentinel+dubbo实行服务注册、配置中心、熔断限流

    通过Spring Cloud Alibaba相关组件nacos+sentinel+dubbo实行服务注册.配置中心.熔断限流等功能 1.本机安装nacos和sentinel-dashboard服务端 ...

  3. Spring Cloud Alibaba 学无止境:下一代微服务架构的规划与展望

    终于到了课程的最后一讲,本讲我们将对整个微服务架构和 Spring Cloud Alibaba 进行总结和展望.Spring Cloud Alibaba 是优秀的国产微服务架构解决方案,在基于 Spr ...

  4. Spring Cloud Alibaba基础教程:Sentinel Dashboard中修改规则同步到Apollo

    在之前的两篇教程中我们分别介绍了如何将Sentinel的限流规则存储到Nacos和Apollo中.同时,在文末的思考中,我都指出了这两套整合方案都存在一个不足之处:不论采用什么配置中心,限流规则都只能 ...

  5. Spring Cloud Alibaba基础教程:Sentinel Dashboard中修改规则同步到Nacos

    上一篇我们介绍了如何通过改造Sentinel Dashboard来实现修改规则之后自动同步到Apollo.下面通过这篇,详细介绍当使用Nacos作为配置中心之后,如何实现Sentinel Dashbo ...

  6. Spring Cloud Alibaba学习指南

    文章目录 背景 介绍 主要功能 主要组件 参考文档 Spring Cloud Alibaba github Spring Boot & Spring Cloud & Spring Cl ...

  7. Spring Cloud Alibaba基础教程:Sentinel使用Nacos存储规则

    点击蓝色"程序猿DD"关注我哟 加个"星标",不忘签到哦 通过上一篇<使用Sentinel实现接口限流>的介绍,相信大家对Sentinel已经有了初 ...

  8. Spring Cloud Alibaba基础教程:Sentinel使用Apollo存储规则

    点击蓝色"程序猿DD"关注我哟 加个"星标",不忘签到哦 上一篇我们介绍了如何通过Nacos的配置功能来存储限流规则.Apollo是国内用户非常多的配置中心,所 ...

  9. Spring Cloud Alibaba搭建(二):Nacos注册中心

    官方文档地址:https://nacos.io/zh-cn/docs/quick-start-spring-cloud.html 一.核心功能: 服务注册:Nacos Client会通过发送REST请 ...

最新文章

  1. oracle找不到mts,oracle 11g启动时找不到OracleMTSRecoveryService的解决方法
  2. Direct I/O
  3. blog推荐 - 软件产品管理之Tyner Blain
  4. 44 Wild card Matching
  5. 基于 HTML5 Canvas 的交互式地铁线路图
  6. 大小端模式,stm32采用小端模式
  7. android accessibilityservice自动点击_【Android】无障碍服务(一)入门轻踩
  8. 安卓开发笔记——关于图片的三级缓存策略(内存LruCache+磁盘DiskLruCache+网络Volley)...
  9. Java Long类的valueOf()方法及示例
  10. spring2.5.4+hibernate3.2.6+struts2+jbpm3.2.2
  11. 5.7 Components — Sending Actions From Components to Your Application
  12. IPLAT62--新增
  13. JS 获取元素当前的样式信息
  14. mapxtreme 更改图元的位置
  15. Abaqus取消汉化(汉译英,英译汉)
  16. hadoop put命令的格式_【Hadoop篇】--Hadoop常用命令总结
  17. H3C华三交换机初始化配置V7版
  18. uva10246最短路 + 枚举 + 数组记忆
  19. 2022-2027年中国环锻件行业市场全景评估及发展战略规划报告
  20. 游戏服务器存储数据库选型

热门文章

  1. 【论文阅读】《Efficient and privacy-preserving range-max query in fog-based agricultural IoT》
  2. VisionMobile:电信运营商创新工具箱(八)第六章 不确定下的处理:探索式规划
  3. python 面向对象程序设计 1.3 请为学校图书管理系统设计一个管理员类和一个学生类。
  4. PotPlayer技巧总结
  5. 让你飞速成长的18个故事
  6. 十则Word2003打印设置经典技巧,让你从此不求人
  7. 简洁精美的企业单页门户网站(纯静态模板)
  8. 使用marven的方法
  9. 语音写字板 v1.01 我的第二个Android作品
  10. MSISDN(手机号)