概念:

因服务提供者的不可用导致服务调用者的不可用,并将不可用逐渐放大的过程,就是服务雪崩效应
image.png
一个服务失败,导致整条链路的服务都失败的情形,我们称之为服务雪崩,请求被卡在一个子服务上,导致线程池被沾满
总结一句话:大量的请求线程同步等待 造成的资源耗尽

什么时候会发生雪崩效应:

  • 硬件故障:如服务器宕机,机房断电,光纤被挖断等。
  • 流量激增:如异常流量,重试加大流量等。
  • 缓存穿透:一般发生在应用重启,所有缓存失效时,以及短时间内大量缓存失效时。大量的缓存不命中,使请求直击后端服务,造成服务提供者超负荷运行,引起服务不可用。
  • 程序BUG:如程序逻辑导致内存泄漏,JVM长时间FullGC等。
  • 同步等待:服务间采用同步调用模式,同步等待造成的资源耗尽。

综上所述,如果一个应用不能对来自依赖的故障进行隔离,那该应用本身就处在被拖垮的风险中。 因此,为了构建稳定、可靠的分布式系统,我们的服务应当具有自我保护能力,当依赖服务不可用时,当前服务启动自我保护功能,从而避免发生雪崩效应

举例:

在服务提供者处有两个接口:

  1. /**
  2. * 正常访问
  3. *
  4. * @param id
  5. * @return
  6. */
  7. @GetMapping("/payment/hystrix/ok/{id}")
  8. public String paymentInfo_OK(@PathVariable("id") Integer id) {
  9. String result = paymentService.paymentInfo_OK(id);
  10. log.info("*****result:" + result);
  11. return result;
  12. }
  13. /**
  14. * 超时访问
  15. *
  16. * @param id
  17. * @return
  18. */
  19. @GetMapping("/payment/hystrix/timeout/{id}")
  20. public String paymentInfo_TimeOut(@PathVariable("id") Integer id) {
  21. String result = paymentService.paymentInfo_TimeOut(id);
  22. log.info("*****result:" + result);
  23. return result;
  24. }

正常测试下是没有任何问题的,但是用压力测试20000个都去访问延时的接口,然后再来一个单独访问正常接口,发现正常接口也变慢了

为什么?

tomcat的默认工作线程数被打满了,没有多余的线程来分解压力和处理

解决雪崩的四种方式:

资源隔离:
超时机制:
服务降级:
服务限流:
服务熔断:
image.png