降级与熔断的关系

熔断是降级的手段之一
降级方式有很多,开关降级、限流降级、熔断降级。

当service a调用service b,失败多次,达到一定阀值,service a不会再去调service b,而是去执行本地的降级方案。

服务雪崩


service a流量波动较大时,流量经常会突然性增加。那么在这种情况下service a能扛得住,service b和service c未必能扛得住突发的请求。
此时,如果service c因为扛不住请求,变得不可用。那么service b的请求也会阻塞,慢慢耗尽service b的线程资源,service b就会变得不可用。紧接着,service a也会不可用,这一过程如下

如果一个服务失败,导致整个链路的服务都失败的情形,我们称之为雪崩。
服务熔断和服务降级就是解决服务雪崩的手段之一。

服务熔断

当下游服务因为某种原因变得不可用或者响应过慢,上游服务为了保证自己整体服务的可用性,不再继续调用目标服务,直接返回,快速释放资源。如果目标服务情况好转,则恢复调用。
熔断其实是一个框架级的处理,业内基本是用的断路器模式,如 Martin Fowler 提供的状态转换图

  • 最开始处于closed状态,一旦检测到错误到达一定阈值,便转为open状态;
  • 这时候会有个 reset timeout,到了这个时间了,会转移到half open状态;
  • 尝试放行一部分请求到后端,一旦检测成功便回归到closed状态,即恢复服务;
    Hystrix为例
//滑动窗口的大小,默认为20
circuitBreaker.requestVolumeThreshold 
//过多长时间,熔断器再次检测是否开启,默认为5000,即5s钟
circuitBreaker.sleepWindowInMilliseconds 
//错误率,默认50%
circuitBreaker.errorThresholdPercentage

每当20个请求中,有50%失败时,熔断器就会打开,此时再调用此服务,将会直接返回失败,不再调远程服务。直到5s钟之后,重新检测该触发条件,判断是否把熔断器关闭,或者继续打开。

这些属于框架层级的实现,我们只要实现对应接口就好!

服务降级

服务降级的两种场景:
– 当下游的服务因为某种原因响应过慢,下游服务主动停掉一些不太重要的业务,释放出服务器资源,增加响应速度!
– 当下游的服务因为某种原因不可用,上游主动调用本地的一些降级逻辑,避免卡顿,迅速返回给用户!

熔断和降级必定一起出现,当下游服务不可用的情况下,这时候为了对最终用户负责,就需要进入上游的降级逻辑。
上游简单代码事例:

try{
    //调用下游的helloWorld服务
    xxRpc.helloWorld();
}catch(Exception e){
    //因为熔断,所以调不通
    doSomething();
}

开关降级

服务降级大多是属于一种业务级别的处理。开关降级也是我们生产上常用的另一种降级方式!
做法很简单,做个开关,然后将开关放配置中心(如apollo配置中心)。
那么,在应用程序中布下开关的这个过程,业内也有一个名词,称为埋点

那接下来最关键的一个问题,哪些业务需要埋点?
一般有以下方法
1. 简化执行流程
自己梳理出核心业务流程和非核心业务流程。然后在非核心业务流程上加上开关,一旦发现系统扛不住,关掉开关,结束这些次要流程。

  1. 关闭次要功能
    一个微服务下肯定有很多功能,那自己区分出主要功能和次要功能。然后次要功能加上开关,需要降级的时候,把次要功能关了吧!

  2. 降低一致性
    假设,你在业务上发现执行流程没法简化了,愁啊!也没啥次要功能可以关了,桑心啊!那只能降低一致性了,即将核心业务流程的同步改异步,将强一致性改最终一致性!

自动降级

  1. 自己设一个阈值,例如几秒内失败多少次,就启动降级
  2. 自己做接口监控,达到阈值就走推送逻辑,修改配置
  3. 改完配置中心的配置后,应用就可以自动检测到配置的变化,进行降级
Scroll to Top