[微服务感悟] 服务雪崩与熔断器

  • 2020 年 2 月 13 日
  • 筆記

文章目录

  • 什么是服务雪崩
  • 解决方式
  • 熔断器
  • 舱壁模式(服务隔离)

什么是服务雪崩

之前工作中出现了这样的一个问题,有一个业务服务,它的功能是政府某部门的文件流转柜。那个业务中原本每个外部请求都有一个独立的线程池去处理任务,后来听说spring支持全局的线程池。我们为了便于管理所有的线程,于是用spring建立一个全局现场池,让所有异步请求都从spring提供的全局线程池拿线程执行。当时的异步调用有发送短信,同步政府某部门业务数据等功能。有一天,我们的客户反馈投件之后没有发送短信,我们查看日志发现是线程池中堆积了很多同步政府业务数据的任务,日志显示所有的同步数据的请求都超时了。考虑这个外部请求只会在一些极少数的校验业务中出现,不是主要业务,于是我们紧急的停掉了这个政府接口调用,重新上线,用户又可以收到短信了

这就是一个因为下游系统不可用导致服务资源池被耗尽问题。如果这个问题扩散一下,又有上游系统采用全局资源池调用这个业务系统的某些接口,这些接口又恰好同步的使用了线程池导致请求操时,这个上游系统就也会出现请求任务堆积资源池的情况,假设这个上游系统还有其他系统调用。。。,最会迅速导致这个微服务集群中,所有系统都像多米诺骨牌一样,一个一个的资源耗尽返回操时,整个服务群都不可用了。

实际上导致一个服务节点不可用的原因有很多,网络原因,bug,运维事务,数据库/redis资源耗尽等,且随着服务节点越多,其中一个节点出现不可用的概率就越大,直到无限等于1。

服务雪崩效应是一种因“服务提供者的不可用”(原因)导致“服务调用者不可用”(结果),并将不可用逐渐放大的现象

解决方式
熔断器

熔断器是对于一段时间内超时请求数超过设定值的服务器,之后对它的请求不访问,直接返回失败信息,以防止大量操时请求任务堆积。一般熔断器还要设定一个过期时间,过期之后的的请求正常去请求。

if (outCount() < FuseThreshold) {    callRemote(url, params, headers);  } else {    throw new CallRemoteFailedException();  }

对于上个案例,我们后来使用redis的定时key特性实现了一个熔断器。

大部分微服务架构都自带熔断器功能,只用配置一下就可以使用,如springCloud的Hystrix,建议先看看架构中是否存在熔断器功能,不要自建轮子。

舱壁模式(服务隔离)

舱壁模式是服务的公用资源隔离开,一旦一个资源池耗尽,不会影响其他资源池的任务。比如案例的中最初的做法,一个外部调用一个线程池,一个外部调用不可用不会影响其他外部调用都不可用。

大部分微服务架构也自带该功能,比如springCloud的Hystrix。