稳定性与容灾设计:限流、熔断、降级与隔离
本文系统梳理分布式系统的稳定性保障体系:从限流(令牌桶/漏桶/滑动窗口)到熔断(Hystrix/Sentinel 原理)、降级策略、超时与重试(指数退避)、幂等设计、故障隔离(舱壁模式),再到灰度发布与压测容量规划,构建完整的稳定性防线。
目录
| 章节 | 说明 |
|---|---|
| 稳定性威胁来源 | 接口级故障的根因分析 |
| 限流 | 令牌桶 / 漏桶 / 滑动窗口算法 |
| 熔断 | Hystrix / Sentinel 原理与状态机 |
| 降级 | 丢车保帅,保核心业务 |
| 超时与重试 | 指数退避 / 重试风暴防护 |
| 幂等设计 | 保证重复请求不产生副作用 |
| 故障隔离:舱壁模式 | 隔离故障,防止级联雪崩 |
| 灰度发布 | 渐进式变更,降低发布风险 |
| 压测与容量规划 | 知道系统的极限在哪里 |
| 可观测性三支柱(周志明视角) | 日志/追踪/度量的定义、工具选型、OpenTelemetry |
| 事后复盘方法论(郭东白视角) | 安全氛围、假设检验、反事实推演、可行动改进点 |
| 容量评估与弹性伸缩(容量保障视角) | 水位线定义、弹性扩缩容策略、故障场景容量降级 |
稳定性威胁来源
接口级故障的典型表现:系统未宕机,但业务响应缓慢、大量超时或异常。
根本原因:系统压力过大,负载过高,无法快速处理请求,引发后续雪崩。
graph TD
A["内部原因"] --> F["接口级故障"]
B["外部原因"] --> F
A --> A1["程序 Bug 死循环"]
A --> A2["慢查询耗尽 DB 连接"]
A --> A3["内存泄漏"]
B --> B1["促销/秒杀带来超预期流量"]
B --> B2["第三方系统响应变慢"]
B --> B3["恶意攻击"]
F --> G["雪崩效应<br/>整体服务不可用"]
style F fill:#fcc,stroke:#c00
style G fill:#fcc,stroke:#c00
核心应对思想:
- 优先保证核心业务(丢车保帅)
- 优先保证绝大部分用户(放弃少数请求换取整体可用)
限流
限流:通过限制到达系统的并发请求数量,保证系统正常响应部分用户,对超出限制的流量拒绝服务。
限流维度
| 维度 | 示例 |
|---|---|
| 系统整体 | 整个服务每分钟最多处理 10 万请求 |
| 单个接口 | /order/create 每秒最多 1000 次 |
| 单个用户/IP/设备 | 同一 IP 1 分钟内最多 100 次请求 |
| 第三方 appKey | 每个接入方每秒最多 500 次 |
固定窗口算法
原理:统计当前时间窗口内的请求数,超过阈值则拒绝。
private AtomicInteger counter = new AtomicInteger(0);
// 每秒重置计数
ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor();
timer.scheduleAtFixedRate(() -> counter.set(0), 0, 1, TimeUnit.SECONDS);
public boolean isRateLimited(int limit) {
return counter.incrementAndGet() > limit;
}
缺陷:无法限制跨窗口边界的突发流量。
窗口1 最后 10ms:10 次请求(未触发限流)
窗口2 最前 10ms:10 次请求(未触发限流)
→ 20ms 内 20 次请求,实际超出阈值
滑动窗口算法
原理:将时间窗口细分为多个小窗口,统计过去 N 个小窗口的总请求量。
graph LR
W1["0.0s-0.2s<br/>3次"] --> W2["0.2s-0.4s<br/>2次"] --> W3["0.4s-0.6s<br/>4次"] --> W4["0.6s-0.8s<br/>1次"] --> W5["0.8s-1.0s<br/>2次"]
NOW["当前时刻 1.2s<br/>统计 0.2s~1.2s<br/>= 9次"]
优点:解决窗口边界突发问题。 缺点:仍无法平滑流量;需要额外存储各小窗口计数。
漏桶算法
原理:流量先进入漏桶,以固定速率流出到服务端。超出漏桶容量则丢弃。
graph TD
IN["突发流量输入"] --> BUCKET["漏桶<br/>(消息队列实现)"]
BUCKET -->|"固定速率流出"| SVC["服务处理"]
IN -->|"超出容量"| DROP["丢弃/拒绝"]
style DROP fill:#fcc,stroke:#c00
特点:流量绝对平滑,但面对突发流量会增加响应延迟(请求在桶中等待)。
实现:通常用消息队列作为漏桶,有限个消费者线程作为固定流出速率。
令牌桶算法
原理:以固定速率向桶中放入令牌;每次请求需先从桶中取令牌;桶满则不再放入。
graph LR
GEN["令牌生成器<br/>速率 = 1/N 秒/个"] -->|"放入令牌"| BUCKET["令牌桶<br/>最大容量 = M"]
REQ["请求到来"] -->|"取令牌"| BUCKET
BUCKET -->|"有令牌"| SVC["正常处理"]
BUCKET -->|"无令牌"| WAIT["等待或拒绝"]
style WAIT fill:#fcc,stroke:#c00
style SVC fill:#cfc,stroke:#060
与漏桶的关键区别:令牌桶允许短时突发(桶中积累的令牌可以一次性消耗),更适合互联网低延迟场景。
推荐:实际项目中优先使用令牌桶算法(Guava RateLimiter 即基于令牌桶)。
分布式限流
单机限流在多实例部署时无法控制整体流量,需使用 Redis 存储共享令牌数:
// 伪代码:基于 Redis 的令牌桶
public boolean tryAcquire(String key, int limit) {
// 批量获取令牌(减少 Redis 请求次数)
Long tokens = redisTemplate.opsForValue().decrement(key, BATCH_SIZE);
if (tokens != null && tokens >= 0) {
return true; // 获取成功
}
return false; // 令牌不足
}
每次单独请求 Redis 会增加约 1~2ms 延迟,可以批量获取令牌来降低频次。
熔断
熔断:当依赖的外部服务响应变慢或错误率升高时,主动切断对该服务的调用,避免本服务被拖垮。
与降级的区别:降级是应对自身故障,熔断是应对依赖方故障。
熔断状态机
stateDiagram-v2
[*] --> Closed: 初始状态,正常调用
Closed --> Open: 错误率超过阈值
Open --> HalfOpen: 经过 sleepWindow 后自动尝试
HalfOpen --> Closed: 探测请求成功
HalfOpen --> Open: 探测请求失败
Closed: Closed(关闭)
Open: Open(打开)
HalfOpen: Half-Open(半开)
| 状态 | 行为 |
|---|---|
| 关闭(Closed) | 正常调用,统计错误率 |
| 打开(Open) | 直接返回错误,不发起真实调用(快速失败) |
| 半开(Half-Open) | 放行少量请求探测服务是否恢复 |
熔断阈值设计
常见配置维度(以 Hystrix 为参考):
| 参数 | 说明 | 示例值 |
|---|---|---|
| 统计窗口 | 统计请求的时间范围 | 10s |
| 最小请求数 | 窗口内至少多少请求才触发熔断判断 | 20 次 |
| 错误率阈值 | 错误率超过此值触发熔断 | 50% |
| 休眠窗口 | 熔断后多久尝试半开 | 5s |
实践:阈值先根据分析确定,上线后观察效果,再逐步调优。
降级
降级:将某些业务或接口的功能降低,优先保证核心业务可用。
降级策略分类
| 策略 | 说明 | 示例 |
|---|---|---|
| 功能降级 | 关闭非核心功能 | 论坛降级为只读(不能发帖) |
| 接口降级 | 返回兜底数据 | 推荐接口故障时返回热门列表 |
| 服务降级 | 完全停掉某个服务 | App 日志上传接口停用 |
| 数据降级 | 返回缓存数据(可能过期) | DB 故障时返回 Redis 中的旧数据 |
降级实现方式
方式一:系统后门
- 提供降级 URL(带密码保护),访问后执行降级指令
- 优点:实现简单;缺点:多机器时需逐台操作
方式二:独立降级系统
- 统一的降级管理平台,支持批量操作和权限管理
- 配合配置中心(如 Apollo)实现动态开关
// 降级开关示例(配合配置中心)
@Value("${feature.recommend.enabled:true}")
private boolean recommendEnabled;
public List<Product> getRecommended(long userId) {
if (!recommendEnabled) {
return getHotProducts(); // 降级:返回热门商品
}
return recommendService.getPersonalized(userId);
}
超时与重试
超时设置
为什么必须设置超时:下游服务响应慢 → 调用方线程阻塞 → 线程池耗尽 → 整个服务不可用。
超时设置原则:
- 超时时间 = 下游服务 TP99 × 2(经验倍数)
- 每一层都要设置超时(HTTP Client、RPC Client、DB 连接超时、读超时)
- 超时时间不宜过短(误伤正常请求)也不宜过长(拖垮调用方)
重试策略
什么情况可以重试:幂等接口 + 超时/网络抖动导致的失败(非业务错误)。
指数退避(Exponential Backoff):
// 指数退避重试示例
public <T> T retryWithBackoff(Supplier<T> operation, int maxRetries) {
int attempt = 0;
while (attempt < maxRetries) {
try {
return operation.get();
} catch (RetryableException e) {
attempt++;
if (attempt >= maxRetries) throw e;
long waitMs = (long) Math.pow(2, attempt) * 100; // 100ms, 200ms, 400ms...
long jitter = ThreadLocalRandom.current().nextLong(waitMs / 2); // 随机抖动
Thread.sleep(waitMs + jitter);
}
}
throw new RuntimeException("Max retries exceeded");
}
加入随机抖动(Jitter)的原因:避免多个客户端同时重试,造成"重试风暴"再次压垮下游。
重试风暴防护
| 措施 | 说明 |
|---|---|
| 限制重试次数 | 通常不超过 3 次 |
| 只对幂等接口重试 | 非幂等接口重试可能产生副作用 |
| 加随机 Jitter | 分散重试时间点 |
| 熔断保护 | 错误率高时停止重试,直接熔断 |
幂等设计
幂等:同一请求执行一次和执行多次的结果相同,不产生额外副作用。
为什么需要幂等:网络重传、消息重复消费、用户重复点击都可能导致同一操作被执行多次。
常见幂等实现方案
| 场景 | 方案 |
|---|---|
| HTTP 接口 | 客户端生成唯一 requestId,服务端记录已处理的 requestId(Redis SET NX) |
| 数据库写入 | 唯一索引防重(INSERT IGNORE 或 ON DUPLICATE KEY) |
| 消息消费 | 消费前查询是否已处理(以消息 ID 为 key 查 DB/Redis) |
| 支付/扣款 | 订单号作为幂等键,状态机控制(未支付→已支付,不可逆) |
// 基于 Redis 的接口幂等实现
public Result processOrder(String requestId, OrderRequest request) {
String lockKey = "idempotent:" + requestId;
Boolean isNew = redisTemplate.opsForValue()
.setIfAbsent(lockKey, "1", 24, TimeUnit.HOURS); // SET NX EX
if (Boolean.FALSE.equals(isNew)) {
return Result.duplicate("重复请求,已处理");
}
// 执行业务逻辑
return doProcessOrder(request);
}
故障隔离:舱壁模式
舱壁模式(Bulkhead Pattern):将系统资源分隔成独立的"舱室",一个舱室故障不影响其他舱室,类比船舱的水密隔舱。
graph TD
subgraph "线程池隔离"
T1["服务A<br/>线程池(10个线程)"]
T2["服务B<br/>线程池(10个线程)"]
T3["服务C<br/>线程池(10个线程)"]
end
APP["应用"] --> T1
APP --> T2
APP --> T3
T2 -->|"服务B 故障<br/>线程耗尽"| X["❌ 服务B不可用"]
T1 --> OK1["✅ 服务A 正常"]
T3 --> OK3["✅ 服务C 正常"]
两种隔离方式:
| 方式 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 线程池隔离 | 每个依赖服务使用独立线程池 | 完全隔离,支持异步 | 线程开销大 |
| 信号量隔离 | 每个依赖服务使用独立计数器限制并发数 | 轻量,无线程切换开销 | 无法支持超时 |
Hystrix / Sentinel 中的舱壁实现:
- Hystrix:默认线程池隔离,每个 Command 对应一个线程池
- Sentinel:基于资源的流控规则,支持线程数隔离
灰度发布
灰度发布(Canary Release):将新版本先发布给少量用户,验证无问题后再全量推广。
graph LR
LB["负载均衡"] -->|"5% 流量"| NEW["新版本<br/>(金丝雀)"]
LB -->|"95% 流量"| OLD["旧版本"]
NEW -->|"验证通过"| FULL["全量发布<br/>100% 新版本"]
NEW -->|"发现问题"| ROLLBACK["快速回滚"]
style FULL fill:#cfc,stroke:#060
style ROLLBACK fill:#fcc,stroke:#c00
灰度策略:
| 策略 | 说明 |
|---|---|
| 按比例 | 5% → 10% → 50% → 100% 逐步放量 |
| 按用户 | 内部员工 → 测试用户 → 普通用户 |
| 按地域 | 先发布到某个城市/机房 |
| 按特征 | 按用户 ID 尾号、设备类型等 |
监控指标:灰度期间重点关注错误率、响应时间、业务成功率,与旧版本对比。
压测与容量规划
为什么需要压测
你不知道系统的极限在哪里,就无法设置合理的限流阈值,也无法预判流量高峰时是否会出问题。
压测类型
| 类型 | 目的 | 方法 |
|---|---|---|
| 单接口压测 | 找到单个接口的性能瓶颈 | 逐步加压,观察 TP99 和错误率 |
| 全链路压测 | 模拟真实流量,找到系统整体瓶颈 | 在生产环境打压测标记,影子库处理压测数据 |
| 稳定性测试 | 验证系统在持续高负载下的稳定性 | 维持 80% 峰值压力持续 30 分钟 |
容量规划流程
1. 评估业务增长预期(DAU × 增长率)
2. 估算峰值 QPS(平均 × 峰值倍数 × 设计余量)
3. 压测得到单机性能基准
4. 计算所需机器数量 = 峰值 QPS / 单机 QPS
5. 设置限流阈值 = 单机 QPS × 机器数 × 0.8(留 20% 余量)
6. 定期复测,随业务增长动态调整
常见性能瓶颈排查
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| CPU 使用率高 | 计算密集型逻辑;频繁 GC | 火焰图;GC 日志 |
| 内存持续增长 | 内存泄漏;缓存无限增长 | Heap Dump;缓存大小监控 |
| 数据库慢查询 | 缺少索引;大事务 | Slow Query Log;EXPLAIN |
| 线程池队列堆积 | 下游响应慢;线程数不足 | 线程池监控;下游 RT |
| 网络带宽打满 | 响应体过大;日志过多 | 网络监控;响应压缩 |
可观测性三支柱(周志明视角)
可观测性是分布式系统不可或缺的属性,而不是单体系统时代的附属边缘属性。它来自控制理论:"可以由系统的外部输出推断其内部状态的程度"。
三支柱的定义与关系
2017 年分布式追踪峰会后,Peter Bourgon 的文章《Metrics, Tracing, and Logging》系统定义了三者:
| 支柱 | 职责 | 主要目的 | 代表工具 |
|---|---|---|---|
| 日志(Logging) | 记录离散事件,事后分析程序行为 | 问题排查、审计 | ELK(Elasticsearch + Logstash + Kibana) |
| 追踪(Tracing) | 记录请求跨服务的完整调用轨迹 | 故障定位、性能分析 | Zipkin、Jaeger、SkyWalking |
| 度量(Metrics) | 对系统状态进行统计聚合 | 监控预警、趋势分析 | Prometheus + Grafana |
关键区别:日志看"发生了什么",追踪看"调用链路怎么走的",度量看"系统整体健康状况"。三者互补,不能互相替代。
日志:好的日志应该怎么写
不该出现的内容:
| 反模式 | 原因 |
|---|---|
| 敏感信息(密码、银行账号) | 日志会流向索引存储,清理极难 |
| 慢操作(远程调用、大量计算) | 打印日志本身会成为性能瓶颈 |
| 追踪诊断信息(方法入参、返回值) | 这是追踪系统的职责,日志不该承担 |
必须出现的内容:
- TraceID:贯穿整条调用链,用 MDC 自动注入;出错时用户可凭此快速定位
- 系统关键事件:操作记录、异常、定时任务执行情况
- 启动时配置信息:数据库连接、关键配置项(非敏感部分)
日志处理链路:
应用打印日志 → Filebeat 收集 → Kafka 缓冲 → Logstash 结构化处理
→ Elasticsearch 索引存储 → Kibana 可视化查询
分布式系统的日志不追求绝对完整精确,只追求在代价可承受的范围内尽可能保证数据质量。
追踪:分布式链路追踪
核心概念(来自 Google Dapper 论文,2010):
- Trace:一次完整请求从入口到返回的全过程
- Span:Trace 中的一次服务调用记录,包含时间戳、起止时间、TraceID、SpanID、父 SpanID
三种数据收集方式对比:
| 方式 | 侵入性 | 精准度 | 代表产品 |
|---|---|---|---|
| 基于日志 | 低(仅需打印 TraceID) | 较低(依赖日志归集时效) | Spring Cloud Sleuth |
| 基于服务(Agent 探针) | 中(Java Agent 注入) | 高(独立数据通道) | SkyWalking、Zipkin、Pinpoint |
| 基于边车代理 | 零(对应用完全透明) | 高(独立控制平面) | Envoy + Istio |
边车代理是最理想的追踪模型,但只能追踪服务间调用,无法做到 Pinpoint 那样的方法级调用追踪。
规范化进程:OpenTracing(CNCF 第三个项目)→ OpenCensus(Google 主导)→ 两者合并为 OpenTelemetry(2019),目标是统一日志、追踪、度量三大领域。
度量:Prometheus 体系
五种度量器类型:
| 类型 | 说明 | 示例 |
|---|---|---|
| Counter | 单调递增计数器 | 请求总数、错误总数 |
| Gauge | 瞬时值 | 当前在线人数、内存使用量 |
| Meter | 吞吐率(单位时间事件数) | QPS、TPS |
| Histogram | 二维统计图(样本分布) | 响应时间分布 |
| Summary(Quantile) | 分位数分布 | TP99、TP999 |
时序数据库的设计优化:度量数据的特征(只追加、不修改、热点集中在近期)允许做激进的存储策略:
- 使用 LSM-Tree 代替 B+Tree(写优化)
- 设置 TTL 自动删除过期数据
- 对历史数据做再采样(近期精确到秒,历史只需精确到天)
Prometheus 架构:Pull 模式(主动拉取指标)+ Push Gateway(兼容 Push 场景)+ Alert Manager(预警)+ Grafana(可视化)
事后复盘方法论(郭东白视角)
郭东白将复盘视为架构师成长的关键节点,也是架构活动的第八个节点(全面上线后)。
为什么复盘是架构师的核心能力
复盘的真正目的不是追责,而是为企业未来的架构活动提升成功概率。大多数架构活动以失败告终,而复盘是从失败中提取经验的唯一可靠途径。
有效复盘的关键要素
1. 搭建安全的复盘氛围
如果复盘变成了追责会议,参与者会本能地防御,隐藏真实信息。安全感是复盘能产生真正价值的前提。
2. 充足的前期准备
复盘不是即兴讨论,需要:
- 完整的架构活动历史记录(决策日志、变更记录)
- 预期目标与实际结果的量化对比
- 关键节点的时间线梳理
3. 区分"是什么"和"为什么"
大多数复盘只停留在"发生了什么",而有价值的复盘要深挖"为什么会这样"——找到深藏在流程和假设中的问题。
4. 发现可行动的改进点
复盘的输出不是报告,而是下一次架构活动能执行的具体改变。没有行动点的复盘是无效的。
复盘的思维工具
五个为什么(5 Whys):对每个问题连续追问"为什么",直到找到根本原因。
假设检验:找出架构活动开始时做出的假设,验证哪些假设是错的。很多架构失败不是执行问题,而是最初的假设就是错的。
反事实推演:如果当时做了不同的决策,结果会怎样?这有助于验证决策逻辑,而不仅仅是评判结果。
容量评估与弹性伸缩(容量保障视角)
来自《容量保障核心技术与实战》(吴骏龙)的稳定性视角补充:从容量角度看稳定性,核心是"在流量超预期时,如何保持系统不崩溃"。
容量水位线与稳定性的关系
稳定性问题的根源之一是容量不足——系统没有足够的弹性空间来应对突发流量。水位线体系将容量管理与稳定性保障连接起来:
正常状态(< 安全水位 60%):系统有充足弹性,突发流量可以吸收
警戒状态(60-75%):系统承压,需要提前准备扩容
危险状态(> 75%):系统接近极限,需要立即处置
崩溃临界(> 90%):系统随时可能崩溃,必须启动降级
水位线与稳定性手段的联动:
| 水位状态 | 对应稳定性手段 | 目的 |
|---|---|---|
| 警戒水位 | 触发限流(拒绝部分请求) | 保护现有容量,防止超载 |
| 红线水位 | 触发降级(关闭非核心功能) | 释放资源给核心业务 |
| 超红线 | 触发熔断 + 扩容 | 快速恢复,同时扩大容量 |
弹性扩缩容策略
扩容是稳定性的最后一道防线,在限流和降级都无法解决问题时,扩容是唯一出路。
扩容的三个时机:
| 时机 | 触发条件 | 响应速度 | 说明 |
|---|---|---|---|
| 预防性扩容 | 大促前、活动前提前扩容 | T-2 小时 | 最优,用户无感知 |
| 预测性扩容 | 历史规律预测,提前 15-30 分钟 | 15-30 分钟 | 较优,偶有冷启动延迟 |
| 响应性扩容 | 指标超阈值触发 | 1-5 分钟 | 有滞后,可能已影响用户 |
扩容的注意事项:
- 不要无脑扩容:扩容前先排查是否是代码问题(慢 SQL、连接池小、内存泄漏),否则扩容只是延缓崩溃
- 关注依赖链路:扩容应用服务时,确认下游数据库/缓存/消息队列也有足够容量
- 扩容有边际递减效应:当存在串行瓶颈(如数据库单点)时,继续扩容应用服务收益递减
反例(无脑扩容):
应用服务 CPU 80% → 扩容到 2 倍 → CPU 降到 40%
但数据库连接数已满 → 新实例无法建立连接 → 问题未解决
正例(系统性扩容):
应用服务 CPU 80% → 检查瓶颈 → 发现数据库连接池满
→ 先优化 SQL 减少连接占用 → 再扩容应用服务
→ 同时确认数据库 max_connections 足够
故障场景的容量降级
当系统遭遇故障时,通过主动降低功能来释放容量,保护核心业务:
容量降级决策树:
降级释放资源的量化参考:
| 降级操作 | 预期释放资源 | 业务影响 |
|---|---|---|
| 关闭推荐算法(返回热门列表) | CPU 降低 15-20% | 推荐精准度下降 |
| 关闭评论/UGC 写入 | DB 写入减少 30% | 用户无法发评论 |
| 关闭实时统计(延迟计算) | CPU/DB 降低 10% | 数据延迟 |
| 图片转低分辨率 | 带宽减少 60% | 图片质量下降 |
| 关闭 A/B 测试 | CPU 降低 5-10% | 实验数据丢失 |
容量保障的组织建设
来自吴骏龙的实践经验:容量保障不只是技术问题,组织建设同样关键。
Program 机制(跨团队协作):
- 由 CTO 直接牵头,对跨团队技术改造项目进行优先级评定
- 业务团队必须腾出一定比例时间进行技术升级(而非只做业务迭代)
- 定期例会追踪进展,公共团队提供方案和支持
全链路压测常态化:
- 每周固定时间(如周三晚间低峰期)执行全链路压测
- 技术人员必须值守,发现问题立即暂停
- 压测发现的容量问题按 P0/P1/P2 分级,有明确解决时限
容量问题分级规范:
| 等级 | 定义 | 解决时限 |
|---|---|---|
| P0 | 影响核心业务可用性 | 24 小时内 |
| P1 | 影响核心业务性能 | 72 小时内 |
| P2 | 影响非核心功能 | 1 周内 |
关键洞察:稳定性和容量是一体两面。稳定性保障(限流/熔断/降级)是在容量不足时的"防御",而容量保障(压测/扩容/水位管理)是从根本上解决"容量不足"这个问题。两者缺一不可。
参考资料
- 《高并发系统设计 40 问》— 唐扬(极客时间专栏,文档 ID:468134979)
- 《从0开始学架构》— 李运华(极客时间专栏,文档 ID:467070048)
- 周志明《凤凰架构》— 极客时间专栏,文档 ID:836338837(第 41-44 讲)
- 郭东白《架构课》— 极客时间专栏,文档 ID:1277713307(第 30 讲)
- 《容量保障核心技术与实战》— 吴骏龙(极客时间专栏,文档 ID:925934538)
- Hystrix 官方文档(github.com/Netflix/Hystrix/wiki)
- Sentinel 官方文档(sentinelguard.io/zh-cn)
- 《Release It!》— Michael T. Nygard(Pragmatic Bookshelf)
- Peter Bourgon: Metrics, Tracing, and Logging(peter.bourgon.org/blog/2017/02/21)
评论 (0)