> For the complete documentation index, see [llms.txt](https://gitbook.fantasticmao.cn/tech/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://gitbook.fantasticmao.cn/tech/fen-bu-shi-xi-tong/fen-bu-shi-xi-tong-de-tan-xing-she-ji.md).

# 分布式系统的弹性设计

## 熔断

熔断的目的是防止应用不断尝试可能会执行失败的操作，从而使得应用可以继续执行而不用等待异常情况的修复，或者浪费时间来等待长时间的超时操作。当异常已经修复的时候，应用会再次尝试执行操作。

熔断模式类似于容易失败操作的一种代理，它能够记录和统计最近执行失败的次数，然后决定是否继续执行，或者是立即返回错误。

实现熔断模式需要考虑以下三个状态：

1. 闭合状态：熔断器会定义一个执行操作失败的计数器，在执行操作连续失败或者高频失败时，计数器数值会自增。如果计数器值大于某个阈值，则熔断器会切换到断开状态，同时熔断器会设置一个计时器，在经过一段时间之后会切换到半开状态；
2. 断开状态：在断开状态下，应用执行操作会立即返回失败，或者可以在当本地缓存中没有数据时返回失败；
3. 半开状态：在半开状态下，应用会被允许执行一次或者一些操作。如果这些操作执行成功，熔断器则会切换到闭合状态，同时会重置计数器。如果这些操作继续执行失败，熔断器则会重新切换到断开状态，同时会重置计时器。

## 限流

限流的目的是通过对并发访问进行限速。一般来说，限流的行为如下：

1. 把多出来的请求拒绝掉；
2. 关闭或者降级后端服务；
3. 把有限资源分配给重要用户；
4. 使用队列来削去请求高峰；
5. 通过自动化运维的方式，实现服务的自动化伸缩。

限流的经典实现方式有基于计数器、漏斗算法、令牌桶算法。

### 计数器

使用计数器来实现限流的算法如下：

1. 准备执行一个请求时，计数器加一；
2. 执行完毕一个请求时，计数器减一；
3. 当计数器值大于某个阈值时，开始限流。

在基于计数器的限流算法中，请求是以「次数」而不是以「频率」来被限制。

### 漏斗算法

漏斗算法的具体步骤如下：

1. 用一个队列（在漏斗中接水）来堆积请求；
2. Processor（从漏斗中出水）从队列中消费请求；
3. 如果队列满了，则开始限流。

```
         +-----------+ accept  +-----------+
-------->| | | | | | |-------->| Processor |
         +-----------+         +-----------+
               |
               | rejected
               v
            Discard
```

在漏斗算法中，请求是以 Processor 最大消费能力的频率来执行的。

### 令牌桶算法

令牌桶算法的具体步骤如下：

1. 以恒定的速率产生 token，放入至一个集合（承担令牌桶角色）中；
2. 准备执行一个请求时，从集合中获取一个 token；
3. 当集合中没有 token 时，则开始限流。

```
    +-----------+  add token
    | | | | | | |<-----------
    +-----------+
          ^
get token |
          | accept
          |        +-----------+
----------+------->| Processor |
          |        +-----------+
          | rejected
          v
       Discard
```

在令牌桶算法中，当令牌桶中有堆积的 token 时，请求可以被允许高频率地执行。

## 降级

降级的本质是为了解决在资源不足时，系统访问量过大的问题。当资源和访问量出现矛盾时，在资源有限的情况下，为了能够扛住大量的请求，而对系统进行降级操作。

一般来说，系统降级的策略有：

1. 降低系统对一致性的要求；
2. 完全停止次要功能，或者限制次要功能流量；
3. 简化功能，例如只返回页面或者接口的部分信息。

一般来说，控制降级的形式是：

1. 主动推送：开启系统配置；
2. 由上游系统驱动：对外 API 的参数。
