# 在客户生产环境里干活的 FDE，该读《Release It!》

> 客户 API 每次卡 30 秒，5 秒就能耗尽线程池；Nygard 的模式在设计阶段就能截断这种级联故障。

原文: https://fdetimes.net/zh/books-courses/release-it-nygard-production-stability-fde/

据出版社介绍，软件项目生命周期 80% 的成本发生在生产环境，但愿意认真写这个阶段的书寥寥无几。Michael Nygard 的《Release It!》正是为填补这块空白而写。

对前线部署工程师（FDE）来说，这句话几乎就是岗位描述。你不是部署到自己团队掌控的干净集群，而是部署进客户的环境：遗留 API、没人敢碰的数据库、时好时坏的内网。周围一切都在出问题时，如何让系统继续站着，很少有书讲得像这本一样透彻。

## 写给怕半夜被告警叫醒的人

第一版出版于 2007 年。目前的版本是《Release It! Second Edition: Design and Deploy Production-Ready Software》，由 Pragmatic Bookshelf 于 2018 年 1 月出版，共 376 页（ISBN 9781680502398）。出版社介绍，Nygard 做职业程序员和架构师已超过 15 年。

出版社的宣传语很直白：如果你是开发者，不想每天夜里被告警叫醒，这本书就是为你写的。书中通过案例研究和可以立即上手的建议来讲解。第二版把稳定性反模式的目录扩展到了大规模场景下的系统性问题。

反模式目录包括 Integration Points、Cascading Failures、Blocked Threads、Slow Responses 和 Unbounded Result Sets。模式部分则有 Timeouts、Circuit Breaker、Bulkheads、Fail Fast 和 Shed Load。Martin Fowler 认为，正是 Nygard 本人让 Circuit Breaker 流行起来，这一模式用于阻止故障在服务之间级联扩散。

从这份目录中，有三个观点值得带进每一次客户项目。

## 观点一：每个集成点都可能出故障

对 FDE 来说，Integration Points 是最值得细读的反模式。每一个对接客户系统的连接，从 CRM、数据仓库到认证 API，对面都不在你的掌控之中。

设想你部署了一个读取客户订单数据的 Agent。在预发环境，订单表只有 100 行；到了生产环境，同样的查询返回好几年的历史数据，服务内存直接耗尽。这就是 Unbounded Result Sets：问题不在代码里，只有碰到真实数据才会暴露。

最简单的防御，是给每一条查询客户系统的语句加上行数上限和分页。更宏观地看，到现场后的第一件事，是画出所有集成点，再对每个集成点问三个问题：对方挂了会怎样？对方变慢会怎样？对方返回的数据量大得离谱又会怎样？

**要点:** 设计时要考虑对方响应变慢的情况，而不只是对方彻底宕机的情况。

## 观点二：慢比挂掉更危险

直接挂掉的服务会立刻返回错误，慢服务却会把你拖住。算一笔账：你的服务有 50 个线程的线程池，每秒收到 10 个请求，每个请求都要调用一个客户 API，正常响应时间是 200ms。

某天早上这个 API 变慢了，每次调用都卡住 30 秒。每秒新增 10 个卡住的线程，只需 5 秒，50 个线程就全部在等待。你的服务自己的健康检查也没有线程可用，负载均衡器把它标记为宕机，所有依赖你的系统也开始变慢。

这条链路依次经过 Slow Responses、Blocked Threads，最后是 Cascading Failures。第一道、也是成本最低的防线是 Timeouts。设置 2 秒超时，线程就会回到线程池，而不是卡上 30 秒；再配合 Fail Fast 立即报错，不让用户一直干等。

## 观点三：隔离故障，别让一处坏掉拖垮全局

超时只能切断单次调用。Circuit Breaker 更进一步，Fowler 这样概括它的原理：把受保护的调用包进一个熔断器对象，由它监控失败情况。失败次数超过阈值后，熔断器跳闸，后续请求直接被拒绝，不再反复去敲一个快要挂掉的 API。

剩下的交给 Bulkheads。回到上面的例子，如果调用客户 API 只能使用一个专用的 10 线程池，那么这个 API 卡住时，其余 40 个线程仍能继续支撑其他功能。Shed Load 是最后一步：过载时主动拒绝一部分请求，而不是让所有请求一起变慢。

## 谁该读，按什么顺序读？

这本书适合有两年以上经验、至少被事故搅过一次睡眠的开发者。第二版出版于 2018 年，比较合理的做法是把书和作者的两次访谈结合起来看。

第一步：收听 2023 年 GOTO Book Club 中 Nygard 与 Trisha Gee 的对谈，其中讨论了 2007 年版之后出现的模式和反模式。先听这期节目，能知道书中哪些内容依然成立，哪些需要放到新的背景下理解。

第二步：读反模式目录，每读一条，就在自己当前运维的系统里找一个对应的例子。先在自己的代码里认出病症，才能选对药方。

第三步：读模式部分，每个模式都记下它能挡住你清单上的哪种反模式。第四步：收听 2018 年 Cognicast 第 141 期，其中深入讨论了熔断器和 dogpile 效应（大量请求在同一时刻挤向同一处）。

想转型做 FDE 的开发者，别只在简历上写“读过 Release It!”。要写一句带有自己工作中真实数字的话，比如“为合作方 API 调用加上 2 秒超时和熔断器，把事故持续时间从 X 小时缩短到 Y 分钟”。

如果岗位描述里提到“production-ready”或“reliability”，就准备一个恰好沿着上面那条链路展开的故事：变慢、线程卡死、级联故障。

客户不会记得你的演示有多顺畅。他们会记得的，是那天早上他们的 API 变慢了，而你的系统照常运行。

**本周动手试试:**

- 列出手头某个项目里所有对外调用，记下每个调用当前的超时设置；没有设置的，就是你的风险点
- 用一个熔断器库包装一次外部 API 调用，模拟该 API 30 秒后才响应，观察系统如何反应
- 读第一章之前，先听 2023 年 GOTO Book Club 中 Michael Nygard 与 Trisha Gee 的那期对谈

## 信源

- [Release It! Second Edition: Design and Deploy Production-Ready Software (Pragmatic Bookshelf)](https://pragprog.com/titles/mnee2/release-it-second-edition/)

- [Circuit Breaker (Martin Fowler's bliki)](https://martinfowler.com/bliki/CircuitBreaker.html)

- [Release It! • Michael Nygard & Trisha Gee (GOTO Book Club)](https://goto.buzzsprout.com/1714721/12258934)

- [Michael Nygard - Cognicast Episode 141](https://cognitect.com/cognicast/141)
