1. 介绍

为了保证系统不被突发流量击垮,进行容量保障是十分有必要的。从架构的稳定性角度看,在有限资源的情况下,所能提供的单位时间服务能力也是有限的。假如超过承受能力,可能会带来整个服务的停顿,应用的Crash,进而可能将风险传递给服务调用方造成整个系统的服务能力丧失,进而引发雪崩。另外,根据排队理论,具有延迟的服务随着请求量的不断提升,其平均响应时间也会迅速提升,为了保证服务的SLA,有必要控制单位时间的请求量。这就是限流为什么愈发重要的原因。

本文主要讨论内容为:

  1. 解决容量保障(雪崩效应)问题的三大方法——熔断、限流和降级相关的概念
  2. Hystrix的基本原理

2. 雪崩效应

分布式系统中经常会出现某个基础服务不可用造成整个系统不可用的情况, 这种现象被称为服务雪崩效应. 为了应对服务雪崩, 一种常见的做法是手动服务降级.

2.1 定义

雪崩效应:服务提供者 的不可用导致 服务调用者 的不可用,并将不可用 逐渐放大 的过程

下图从上到下看,可以发现随着A不可用,慢慢的B服务还有CD服务都不可用了。

2.2 雪崩效应形成的原因

我把服务雪崩的参与者简化为 服务提供者 和 服务调用者, 并将服务雪崩产生的过程分为以下三个阶段来分析形成的原因:

  1. 服务提供者不可用
  2. 重试加大流量
  3. 服务调用者不可用

2.2.1 服务提供者不可用原因

服务雪崩的每个阶段都可能由不同的原因造成, 比如造成 服务不可用 的原因有:

  1. 硬件故障: 硬件故障可能为硬件损坏造成的服务器主机宕机, 网络硬件故障造成的服务提供者的不可访问.
  2. 程序Bug
  3. 缓存击穿: 缓存击穿一般发生在缓存应用重启, 所有缓存被清空时,以及短时间内大量缓存失效时. 大量的缓存不命中, 使请求直击后端,造成服务提供者超负荷运行,引起服务不可用.
  4. 用户大量请求: 在秒杀和大促开始前,如果准备不充分,用户发起大量请求也会造成服务提供者的不可用.

2.2.2 重试加大流量

主要原因有:

  1. 用户重试:在服务提供者不可用后, 用户由于忍受不了界面上长时间的等待,而不断刷新页面甚至提交表单.
  2. 代码逻辑重试:服务调用端的会存在大量服务异常后的重试逻辑.

2.2.3 服务调用者不可用

主要原因是同步调用: 当服务调用者使用 同步调用 时, 会产生大量的等待线程占用系统资源. 一旦线程资源被耗尽,服务调用者提供的服务也将处于不可用状态, 于是服务雪崩效应产生了.

2.3 应对策略

  1. 熔断:通过 超时机制使得不可用服务的调用快速失败
  2. 限流:网关限流、用户交互限流、关闭重试、接口限流。在JAVA中实现接口限流可以用guava的RateLimiter,它实现了令牌桶算法和漏桶算法。
  3. 降级:调用服务线程池隔离、依赖服务分类(终止弱依赖服务)
  4. 服务自动扩容:

3. Hystrix

Hystrix是用于分布式场景下服务熔断、降级的开源JAVA库。在github地址为:Hystrix

此外Hystrix的官方文档也有小伙伴做了翻译,想直接看中文的可以点击:Hystrix中文文档

3.1 Hystrix的作用

官方文档说的更加细致,我这里按照理解,将其最主要的功能概括为:

  1. 依赖隔离: 将每个依赖服务分配独立的线程池进行资源隔离,这样如果某个服务出问题,也只会影响其单个线程池
  2. 熔断器:熔断器的开关能保证服务调用者在调用异常服务时, 快速返回结果, 避免大量的同步等待. 并且熔断器能在一段时间后继续侦测请求执行结果, 提供恢复服务调用的可能.
  3. 监控报警: 对服务调用失败、异常进行监控

3.2 Hystrix在spring boot中的使用

引入依赖:

<dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>

添加注解使用Hystrix
@EnableCircuitBreaker
@EnableHystrixDashboard

在需要使用熔断器的地方标记注解即可:

@HystrixCommand(groupKey = "xxx", fallbackMethod = "yyy")
public String doSomething() 

非spring boot的使用方式可以看下官方文档

参考资料:

  1. 阿里双11背后故事之万亿级数据洪峰下的分布式消息引擎
  2. 防雪崩利器:熔断器 Hystrix 的原理与使用
  3. 使用guava来做接口限流
  4. 跳闸了啊! 服务容灾:熔断器简介
  5. 接口限流算法总结