190-容量保障核心技术与实战

开篇词 | 互联网时代，人人肩负容量保障的职责

你好，我是吴骏龙。欢迎你和我一起学习容量保障。

如果你现在还不知道“容量保障”到底是啥意思，那也不用着急。因为，容量保障其实就在你我身边。我们在使用的各种互联网应用，比如你点外卖使用的“饿了么”“美团外卖”等等，比如你使用的各种电商 App，它们的稳定运行，背后靠的都是各类技术保障工作。

而在这些技术保障工作中，最重要的就是质量保障和容量保障这两类：

质量保障，是确保服务功能正确，不出问题。比如，订单系统结算时，要保证金额正确。

容量保障，是要保证服务在大量用户访问时，依然可以正常工作。比如，在“双 11”购物节的超高访问量下，各电商网站依然能够稳定地运行。

而我，先后在 eBay 上海研发中心和阿里巴巴本地生活（前身是“饿了么”）工作近 8 年的时间，做的就是质量保障和容量保障相关的工作。

在 eBay 工作时，我主要负责质量保障工作，在部门内建立了完善的自动化测试体系和持续集成流水线，并将机器学习引入到软件测试工作中，解决了测试报告自动分析的难题。这些成果至今仍然是互联网行业的前沿研究方向。

后来我到了阿里本地生活，当时恰逢异地多活项目落地，随之而来的是全链路压测工作的启动。作为当时团队中的平台开发 Leader，我有幸参与了这项浩大的工程，并主导负责了整个全链路压测的自动化和规范化工作。这是我第一次系统接触容量保障工作的重要环节，它就像是我的孩子一样成长。直到现在，我们曾经的团队成员聚首，对此还会津津乐道。

在全链路压测走向正轨以后，我渐渐发现仅通过全链路压测是无法全面保障系统容量安全的。于是，我将工作重点从全链路压测这个专项，转向了整个容量保障的体系化建设，致力于推动高效和富有层次的容量保障实践，并带队攻克了多项容量预测难题。我自己也作为阿里本地生活的全局容量保障负责人，固守着这一片碧海蓝天。

目前，我在一家创业公司继续我的质量保障和容量保障事业，而容量保障是我深耕最多的领域，也是我投入巨大热情的地方。

那为什么我想要开设这样一门课呢？

在我的职业生涯中，能够非常深刻地感受到，容量保障对于一家互联网公司的重要性，因为几乎每时每刻我都在回答这些问题：我负责的软件系统目前运行的很好，但是公司业务增长迅猛，如果访问量增加 2 倍，系统还能支撑吗？如果无法支撑 2 倍的访问量，哪些服务会首先成为瓶颈？这些服务如果采取扩容措施，需要扩容多少量？大规模促销活动场景下，容量风险如何识别和预防？

与此同时，随着互联网应用复杂度和系统架构复杂度的不断增加，容量保障涉及的工作越来越多，随之而来的误区和困惑也越来越多。

我在多个场合进行容量保障分享时，也经常被问及这样的问题：

我们一直在做性能测试，为啥服务容量还是老出问题？

容量保障，有没有套路可循？

我们公司规模不大，没有专人去做容量保障，有没有成本低点的办法？

我公司规模不大，业务也没有什么大促场景，需要做容量保障吗？

别着急，这个专栏我们就是来解决上面的问题。我写这个专栏的最大初衷，也是希望把我在容量保障领域的经验，总结成方法论分享给你，帮助构建一个全局视角，使你不仅知道容量保障该怎么做，还能深入理解为什么要这样做。

在互联网行业飞速发展的今天，除非我们的系统有非常固定的用户规模和长期不变的业务逻辑，否则，容量保障应当是每个互联网公司都需要广泛关注的工作。无论你是性能测试人员、研发人员、架构师、运维人员，或是现在流行的 DevOps 或 SRE 人员，都应当具备容量保障技能，重视容量保障工作。

看到这里，你是否会有困惑，性能测试、压测、扩容……这些词就代表容量保障吗？容量保障到底是什么呢？在这里，我就给你下个定义吧。

到底什么是容量保障

我们拆开来看，容量保障 = 容量 + 保障。

容量是什么？容量是一个在生活中很常见的概念，我们喝水的杯子就有容量，我们每天上班搭载的地铁也有容量。广义的容量可以定义为：容器能够承载物质的量。杯子就是容器，水就是物质，杯子能够装多少水就是容量。

而从互联网技术视角出发，我们可以将软件系统或服务视为容器，流量或业务量视为物质，那么就可以得到互联网软件系统容量的概念，即“单位时间内软件系统能够承载的最大业务量”。

而容量保障，就是用各种方法保证软件系统的容量充足，预防容量隐患的重要工作。

容量保障对于系统稳定性至关重要，如果一辆货车核载 80 吨，而我们塞进了 100 吨的货物，后果可想而知。互联网历史上多家大厂也曾发生过多次因容量问题引发的线上事故，比如某年春晚某头部电商的摇一摇红包活动短暂宕机，微博在娱乐圈出现热门事件时的频繁宕机，都对用户造成了巨大影响。以至于网友纷纷调侃，衡量明星火不火，就看微博是否为他 / 她宕机过。

容量保障难不难？

也许你会问，既然容量就是系统能承载的业务量，那我多加点服务器不就行了吗？但我要告诉你，容量保障不是这么简单的，否则就不会有上面那么多困惑了。

互联网场景下的容量保障工作是一项系统性工程，它的难点主要体现在以下几个方面。

1. 容量的不确定性： 一辆货车在交付时已经标注了核载重量，而互联网服务的容量受服务器资源、架构设计、网络传输状况和业务场景等多种条件制约，会呈现出不同的容量表现，很难得到确定解。

2. 容量评估的复杂性： 随着微服务架构的日益盛行，服务链路变得越来越复杂，任何一个环节出现容量瓶颈都有可能放大到整条链路，这给容量评估工作带来了难度。

3. 容量测试的不准确性： 容量测试的场景需要尽可能逼近真实情况，还需要保证被测服务的环境（服务资源、规模、配置等）与真实环境对等，但实际上受制于各种原因，我们很难做到完全仿真，因此容量测量的准确性也是一个挑战。

此外，容量保障还会牵扯到成本管理的问题，这也是一个难点。因为工程师主要面对的是技术问题，更关注技术层面的目标，而公司的管理层则倾向于将项目成果和业务需求作为核心目标。在实际业务发展过程中，尤其是在业务进攻期，系统所需资源比如：服务器、内存、硬盘、网络带宽等，它们的成本很容易被工程师们忽略，或者在很晚才被考虑。

从全局来看，如果前期对研发资源成本缺乏规划，等到业务发展到了一定规模，拿到机器账单的时候，惊呼“机器怎么这么费钱”，再想立即降低成本，可能已经错过了最佳时机，因为技术改造本身是一个相对长期的过程。很多公司的成本管理意识可能就如下图所示，是不健康的。

因此，容量规划是容量保障的一个核心环节和难点，不仅要保证服务能够承载相应的流量，还要确保以尽可能少的资源来承载这些流量；更进一步的，在当今开源节流的大背景下，我们还希望以尽可能低的人力成本，保障容量安全。

说了那么多难点，那么如何将它们变得不难呢？这就是我的这个专栏希望带给你的价值。

课程是如何设计的

在这次的专栏中，我将从技术视角出发构建一个容量保障体系化的大图，覆盖容量保障工作的方方面面，逐个击破，尽可能全面地展现容量保障各项技术的全貌。具体来说，会有以下三个部分。

基础篇： 我将以容量保障工作的时间轴为主线，分别就目标、测量、分析、治理这几大工作展开，积累容量保障的通用方法，帮助你完成基础入门。

进阶篇： 我将分几个独立专项话题，对容量保障工作中的一些前沿技术进行深入剖析，包括全链路压测、分布式压测平台的研发工作，以及 AI 预测容量、云原生下的容量保障新趋势等。这其中部分话题在业界甚至是第一次公开，非常值得学习。

案例篇： 从案例场景出发，介绍双 11 大促场景下的容量保障工作如何做好，及小公司如何建立容量保障体系，并对容量保障组织建设给出我的建议。

在这里，我先为你总结一套较为适合互联网场景的容量保障方法论，如下图所示。先从“日常容量”和“大促容量”的目标出发，拆分出三个入口，分别对应计划事件（事先能够预知的新功能或大促活动）、突发事件（事先无法预知的紧急事件）和日常事件（常态化的容量表现）。再自上而下拆解出具体的策略（工作项、工具、规范、案例等），每一项策略再做具体细分，形成一个有机的整体。

在接下来的讲解中，我会再对这个方法论体系中的核心环节进行详细描述，帮助你更好地理解和落地。当然，这套方法论未必适合所有的场景和业务形态，但我认为，即便是在一个全新的领域，它也可以帮助你在最短的时间内，建立一套有效的容量保障体系。更重要的是，它提供了一种核心的思维方式。

最后，我想跟你分享一句我很喜欢的名言，来自列宁：“我们不需要死读硬记，我们需要用基本的知识来发展和增进每个学习者的思考力”。希望这个专栏能够引发你的思考，助你早日成为一名容量保障的“尖兵”。

01 | 容量保障的目标：容量保障的目标是什么？该如何度量？

你好，我是吴骏龙，欢迎和我一起学习容量保障。

俗话说万事开头难，在没有弄清楚目标和需求之前，很难进行容量保障，这就好比建筑图纸没有设计出来之前，你肯定不会开始砌墙。此外，不同角色看待容量的视角也是不一样的，对用户来说可能是想用的功能正常，访问速度快；而对技术人员来说，则是某个性能指标或可用性指标达到可靠的范围。

在今天这一讲中，我会着重和你讨论技术视角的目标，但同时也要明确，任何技术目标最终都是要体现到业务，也就是终端用户上的，脱离业务场景制定容量保障的目标，几乎肯定会跑偏。因为不同业务场景对于容量保障的要求是不一样的。

举一个极端的例子，如果我们面对的是企事业单位的某个内部系统，有着非常稳定的用户规模和几乎不变的产品功能，那么容量保障就是基于固定用户量的一次性保障工作。相反，如果是大型电商系统，业务场景有明显的流量峰值，且经常举办大促活动，容量保障就是一部“跌宕起伏的连续剧”。

容量保障的目标是什么？

那么，容量保障的目标究竟是什么呢？我们先来回答这个问题吧。

总结一下其实就两句话：

第一，以尽可能小的成本确保系统当前和未来的容量充足，即容量规划；

第二，解决已知的容量问题，预防未知的容量问题，即容量治理。

我们的这门课，就是围绕这两方面层层展开的。

你可以按这样的思路去理解容量保障的目标。首先，成本是容量保障的一个制约条件，容量保障不是无限保障，公司对服务器等 IT 资源的投入，对容量保障人力资源的投入等等，可能都会设置上限，这些都是成本上的约束。

在控制成本的基础上，我们要保障服务容量充足，即服务的各项资源消耗和业务指标保持在一个相对安全的范围内，这个范围可以是推算出来的，也可以是通过容量测试验证出来的，亦可以是真实流量体现出来的，我们将其称之为“安全水位”。

最后，分布式系统中充满了不确定性，网络可能抖三抖，硬盘可能崩一崩，我们一方面要尽可能在这种不可靠的环境下预防容量问题的发生，又要在出现容量问题时，有能力在短时间内消除影响，甚至是全自动的进行止损，这一点直接影响着服务可用性和用户体验。

做到了这些，容量保障的目标自然就达成了。

容量保障目标的量化

在明确了目标之后，我们需要拆解出一些具体的量化指标，以确保目标的有效达成。换言之，如果公司将容量保障的任务交给你来完成，你怎么证明自己的工作完成得好不好呢？

这时候，你就需要去量化目标，用数据说话。一个不能量化的目标，本身就是难以实施的目标，这也是为何我们在制定各种目标时都建议输出度量指标的原因，关键结果是由量化指标的形式呈现的。

那么，容量保障工作中有哪些关键的量化指标呢？

1. 服务等级协议（SLA）

通俗地说，SLA 就是对服务可用性的一个保证，它可以细分为 SLI 和 SLO。其中，SLI 定义测量的具体指标，如 QPS、带宽等；SLO 定义服务提供功能的期望状态，如 QPS 99 线≤100ms。

SLA 用一个简单的公式来描述就是：SLA = SLO + 后果。 这里的后果指的是不满足 SLO 情况下的补偿协议，比如赔款、延长使用期，等等。

可用性是互联网系统提供服务的根本，因此用 SLA 作为容量保障目标的量化指标也是非常常见的。当然，不止是容量问题，有很多因素都有可能影响 SLA，比如：线上漏测的 Bug、网络抖动、服务器断电等等，因此需要识别出影响 SLA 的容量问题，再判断是否满足目标。

举个具体的例子，我们要求系统整体可用性 SLA 为 4 个 9（99.99%），即每年不可用时长≤52.56 分钟（1 年：8760 小时 × 0.0001 = 52.56 分钟）。

基于这个整体 SLA 要求，并综合考虑历年容量问题对服务可用性的影响比例（比如占比为 1/5），最终设定容量问题造成的可用性损失不高于 10 分钟（52.26 / 5≈10 分钟），这就是一个明确的目标，基于这个目标拆解策略是可衡量的。

不过，虽然 SLA 是一个很好的指标，但也是众所周知的易量化、难测量。

举个例子，有一项 SLA 承诺了团队将在 24 小时内解决用户上报的问题，但它却没有讲清楚如果客户没有提供足够的信息，反复沟通的时间如何计算？24 小时是否包含这些时间？这些信息是必须要落实的，但其实很少有团队能将 SLA 描述细化到这个程度。因此，很多 SLA 的制定其实是不太切合实际的，我们应该用尽可能浅显易懂的语言，围绕业务或用户的实际需求，制定能测量、能理解、有效的 SLA。

上面说了一个反面教材，我针对容量保障工作再给你一个优秀的案例吧。

如下图所示，我们将交易链路下单接口的成功率≥95% 作为 SLA 的一部分，并且承诺低于该成功率的时长不超过 1 分钟，这就是一个容易理解且可测量的 SLA，通过对下单接口的监控就可以观测。交易链路的容量问题有导致下单成功率下跌的可能性，因此作为容量保障的目标也是合理的。

注释：图中 OOSLA = Out of SLA，指不满足 SLA 的时段

2. QPS/TPS

第二个关键的量化指标，QPS/TPS，我们先来复习一下它们的含义：

QPS（Queries per Second）指的是每秒查询率，是一台服务器每秒能够响应的查询次数，即 1 秒内完成的请求数量，一般针对读请求居多。

TPS（Transactions per Second）指的是每秒处理的事务数，一般针对写请求居多。

如果你觉得不够形象，可以想象一下百度的搜索页面，假设我们将这个页面的展示过程视为是一个事务，每秒对这个页面的请求就形成了 TPS，其中可能包含对若干页面内请求的 QPS，即 1TPS＝多 QPS。如果我们只是请求一个静态页面，页面加载不包含其他查询请求，那么这里 TPS 和 QPS 就是对等的，即 1TPS＝1QPS。

QPS/TPS 是容量保障目标中最常见的指标，我们通常说“系统容量是否足够”，一般就是指系统或服务能否在可接受的响应时间和成功率下支撑目标 QPS/TPS。

不过在实际工作中，我们有时可能无法直接给出 QPS/TPS 的目标值，比如说，针对某个将要上线的大促活动，业务方预估的活动热度往往是以业务指标的形式呈现的，如 PV（Page View）、UV（Unique View）、DAU（Daily Active User）等，我们需要将其转换为 QPS/TPS，才能作为容量保障可实施的技术目标。

为了加深理解，我来出一道应用题。

这里有一个活动页面，页面上分为 A、B 和 C 三个区域，进入页面分别调用 getAct()、getAct2() 和 getAct3() 接口各一次，这些接口的调用链路又会涉及 a()、b()、c() 三个接口，调用关系如图所示。这时，如果业务运营方给到这个页面在活动期间（1 天）的总 PV 预估是 1000 万，求 a() 接口的预估 QPS 是多少？

首先，1000 万 PV 是分布在整个活动期间的，但不一定是均匀分布的。假设我们根据二八原则，也就是 80% 的 PV 分布在 20% 的时间内，4.8 小时中将有 800 万 PV，平均每秒 463PV。

由于进入该页面（1 次 PV）对应 getAct() 和 getAct2() 接口各调用一次，那么对 a() 接口的调用总共就是 2 次，我们可以得出 a() 接口的预估 QPS 为 926，这就是该接口在活动期间的容量保障目标。

总结一下，不论是计算 QPS 还是 TPS，首先需要对服务调用链路非常熟悉，梳理出调用关系，最好能够形成类似上面例子中的调用关系图，这样会更清晰易读；其次，虽然针对页面入口的流量是等比例调用的，但根据上述例子我们也看到了，1 次 PV 转换到 a() 接口变成了 2 次调用，这意味着对下游服务的调用量很有可能会被放大，这些扩散比是需要重点计算的；最后，如果是针对局部活动的流量预估，还需要考虑到接口在其他链路上的背景流量，也需要一并计算在内，例子中的 c() 接口就存在这样的背景流量。

如果你感兴趣的话可以计算一下，对于 c() 接口的预估 QPS 应该是多少呢？

再多说一句，传统的互联网服务大多是计算密集型的，即并发量较大的类型，QPS/TPS 和响应时间比较适合作为容量目标。而对于数据存储型的服务，比如某些大数据服务，吞吐量和磁盘 IO 是比较合适的目标，因为这种类型的服务对计算量的要求不大，主要瓶颈在数据传输的速度上，具体你可以看这篇文章，解释比较全面了。可见，制定目标是要因地制宜的。

3. 用户体验

第三个关键指标是用户体验。有些容量问题尽管没有影响可用性，但会导致用户操作时响应延迟，页面打开缓慢等体验问题。想象一下，你工作了一天下班回到家，躺在床上打开某个电商 App 准备看一下有什么新品上市，结果每浏览一个商品详情页都会卡上好几秒，你会是啥心情呢？

其实，我们都希望系统始终能够为用户提供平稳、快速的用户体验，不仅要“可用”，还要“用得爽”。因此，用户体验完全可以作为容量保障更高级的目标。将用户体验做到极致，是咱们每个互联网技术人员都应该铭记的初心。

不过，用户体验问题的定性是相对困难的，一种手段是将客户投诉或内测版本反馈作为一个维度去跟踪。另外，绝大多数用户体验是可以与系统指标或业务指标挂钩的，这些指标就可以作为目标的一部分。比如，有用户反馈某个操作等待时间特别长，其涉及的接口背后的服务器 CPU 利用率、内存利用率、响应时间、调用的消息队列延迟等信息，就都可以作为参考维度。

总结

今天这一节课，我首先介绍了不同人群看待互联网服务容量的视角区别，并明确了从技术视角出发，结合业务场景的思路。

接下来，我重点解释了容量保障的目标，你可以将其拆解为容量规划和容量治理两部分。前者考虑在成本的约束下，将系统资源规划到最优水位；后者则主要致力于容量问题的事前防治和事后止损。

最后，我详细展开了容量保障目标的量化方式和指标选取，分别就 SLA、QPS/TPS 和用户体验三方面进行了阐述。SLA 是基于服务可用性的视角来量化容量保障目标的，QPS/TPS 则是以服务处理能力作为容量保障的度量维度，用户体验是最高级的度量指标，直接以用户的感受作为容量目标。

技术指标联系业务场景，量化目标结合用户体验，是我想传达的核心思想。 产品是做出来给人用的，容量保障的终极目的，也是竭尽所能给用户提供流畅的产品体验。互联网业务的快速发展对容量保障提出了越来越高的要求，今天制定的目标也许很快就会跟不上明天的发展方向，用户体验就是一个典型例子，直到今天都很少有人将其作为容量保障的目标，但它恰恰是一个产品的核心竞争力。我们应该以动态的眼光看待容量目标，不断精益求精，更好地服务用户。

课后讨论

在“QPS/TPS”小节中，我留了一个小问题，你可以计算一下 c() 接口的预估 QPS 是多少，注意考虑清楚所有的请求来源。欢迎你给我留言，也欢迎分享给更多的朋友一起阅读。

02 | 容量测试与验证：怎样科学实施容量测试？

你好，我是吴骏龙。今天我会和你分享容量测试与验证的话题。

相对于性能测试和压力测试这些耳熟能详的名词，“容量测试”这个词也许你是第一次听到。在百度、Google 上一搜，结果倒是不少，但很多解释过于陈旧，并没有跟上互联网的发展速度。比如：

容量测试就是以压力测试的方式对服务施压，在相关容量指标达到瓶颈时停止，这时探测到的系统水位就是最大容量。

这个解释本身没什么毛病，我们很多时候也会把容量测试直接叫做压力测试，但有几家公司在执行容量测试时会真的压到瓶颈呢？如果你以这样的定义践行容量测试，在微服务体系下几乎是落不了地的。因为很多时候，我们并不需要去探测服务的容量极限。

其实，问题的本质在于，传统对容量测试的认知都希望能够获得一个瓶颈点，这是以压测的视角来看待它的。但绝大多数时候，我们都是根据预先制定的容量目标，通过对服务施压来观察和验证服务能否承载这一目标，并不是非要压出极限值。

我个人非常喜欢阿里前任 CTO 行癫在 2018 年双 11 启动会上说的一句话：“容量测试是验证手段，不是测试手段”。 换句话说，我们应该先努力设计和建造出满足容量要求的服务，再通过容量测试去验证它，而不是靠容量测试去反复探测服务容量瓶颈，再去不停地优化服务或扩容。我认为这才是对容量测试的现代化理解。

说得更接地气些，容量测试不是极限保障。 你也可以形象的理解为，压力测试是先斩后奏，而容量测试则是有备而来。

下面我们就来具体展开，看一下容量测试该怎么做。

确定容量测试的范围

在进行容量测试前，我们先要弄清测试的范围。

容量测试的对象是服务，对于专项场景，比如大促活动场景，梳理出活动所涉及的服务和依赖服务，将其纳入到容量保障范围内就可以了。而对于日常场景，除非服务规模很小，否则不大可能将所有服务都全盘覆盖，这时就应有所取舍。

一种比较经济的方式是风险驱动，即针对容易产生容量风险的服务重点考虑进行容量测试。那么，问题来了，哪些服务最容易出现容量风险呢？下图为你做了一定的概括，我来展开讲解。

第一，关键路径上的核心服务肯定是重点保障对象。倒不是说这些服务就一定会有容量风险，而是一旦出现风险，影响会比较大。此外，被关键路径上的服务依赖且无法降级的服务，也应该看做是关键服务，它们是一条绳上的蚂蚱。

第二，有明显流量峰值特征的服务，比如高峰期和低峰期的流量差异非常大的服务，或者是经常举办活动会造成流量突增的服务。这种巨大的流量差异容易引发服务容量风险。

第三，对响应时间敏感的服务，有些底层服务经常被上游服务在同一次请求中调用好几次，一旦响应时间上升，汇聚到上游服务的总响应时间会被放大好几倍，这种服务的容量就要特别小心。当然，在链路调用中也要尽量避免这种多次调用的情况，尽量批处理。

第四，占用资源大的服务，比如占用大量带宽、占用大量内存等，容易造成资源耗尽的服务，就容易引发容量问题。

另外，除了关注容易产生容量风险的服务，对于历史上曾经发生过容量事故的服务、目前高峰期已经存在容量隐患的服务、新上线对容量情况未知的服务，也都要重点进行容量测试。

科学实施容量测试

确定了容量测试的范围，我们具体看一下如何实施容量测试。

容量测试工作一般可以由负责性能测试的技术人员或运维人员主导，拉通各个团队的协作，定义清楚流程规范，由业务团队配合做好事前方案、事中盯盘和事后分析。

当然，无论你是什么角色，都需要以全局视角看待容量测试工作，了解每个环节要做哪些事情，这样才能更好地相互协作。下图就是实施容量测试的全局流程图，基于这张图，我来具体展开每一个重点步骤。

1. 测试方案设计

也许你不太喜欢写测试方案，我猜一部分原因是程序员都更愿意写代码，而不是码字，我写这个专栏是个例外；另一部分原因大概是你很自信，认为即便不写测试方案也能完成测试工作。

但我想说的是，测试方案是写给自己，更是写给团队看的，这是你将信息通过一种形式传达给外部的过程，缺少这一过程，随之而来的就是潜在的误解和信息不对称，是有非常大的隐患的。

此外，测试方案是可以模式化的，其本质是经验的一种抽象和固化。比如说设计模式，现在你可以通过阅读各种资料去学习已经归纳好的设计模式，但这些设计模式可不是一开始就有的，我们的前辈在工作中不自觉地践行了一些好的做法，并将这些做法抽象提炼出来，才形成了现在看到的各种设计模式。

所以，对测试方案的实践，我建议也遵循同样的原理，先集众人所长，抽象总结出一份适合你团队和业务特征的模板，在测试方案设计时，照着这个模板填空就行了。

这样做的好处有很多。

首先，这份模板已经为你准备好了纲要，是带有备忘性质的，在大方向上你不会再遗漏一些重要的工作；其次，模板是标准化的，是一种潜在的“契约”，这能够降低团队的理解成本，在评审时特别有用；最后，这种形式也方便日后追溯和反查，相当于建立了一份档案。

我这里给出一个较为通用的容量测试方案设计模板，你可以基于它，结合实际情况进行再加工。需要注意的是，涉及到的降级方案和补偿方案等止损策略，一定要在线上提前演练过，否则真将业务压出问题来了，操作降级时却又发现无法降级，那麻烦就大了。

2. 测试方案评审

一个好汉三个帮，也许你非常善于容量测试，也精通业务场景，但人的疏忽是客观存在的，只是概率问题而已。评审工作的目的就是通过交叉审查的方式，尽可能避免个体的疏忽，降低这个概率。

在测试方案评审中，相关研发人员和测试人员都要参与评审，确保测试模型和数据合理，没有遗漏关键信息。对于关键服务、重大活动或复杂场景，建议有架构师进行二次复核。

为了避免评审过程枯燥乏味，我们提倡内容正式、形式轻松、集中精力、高效评审。当时在我的办公楼层，有一台可移动的电视机，我们把这台电视机推到茶水间门口的沙发边上，每人拿上一瓶饮料就开始评审了，除了主讲人以外其他人不允许带电脑，评审在一小时内完成，偶尔有超时的，另行预约时间。

你可以学习一下这种正式又轻松的评审方式，并不需要每次都把所有人拉到会议室，大家正襟危坐的轮流发言，这样反而很限制思维的迸发。

3. 测试准备

测试方案确认无误后，容量测试人员就可以开始着手进行准备工作了：根据评审过的场景撰写测试脚本，准备测试数据。准备完毕后，调试脚本和数据，确保能够正常执行，服务无异常。

关于测试脚本的编写，我在这里不做展开，不同的工具有不同的用法，而且常见的开源性能测试工具（JMeter、Gatling、nGrinder 等）的学习曲线都不是很陡峭，你可以直接去这些工具的官网查阅文档 ，都有完善的用户手册和使用案例。

关于测试数据的准备，你可能要问这样的问题，比如：准备多少测试用户？这些用户中有多少比例需要设置成会员？等等。诸如此类的问题，其核心其实就是一句话：“尽可能贴近真实的业务场景”。

上面提到的“准备多少测试用户”的问题，展开来说，由于真实生产环境中用户数据量较大，大多数情况下在数据库层面都会采取分库分表的做法，将用户 ID 散列后路由至多个分片表存储。

如果我们准备的压测用户数量过少，那么这些用户很容易就会集中到某几个分片表上，在压测时导致单片过热（某几个分片表的负载特别高），这就与真实场景相违背了，压测结论自然也就没有意义。因此，我们在准备压测用户时，需要达到一定的数量规模，至少要保证这些压测用户能够均匀分布到每个分片表中。

上面还提到，这些用户中有多少比例需要设置成会员呢？思路也是一样的，以真实业务场景为准。假设在实际业务中，会员与非会员的数量占比为 1：5，那么我们在设置压测用户的会员比例时，也可以遵循相同的比例关系。

4. 测试执行

准备工作一切就绪后，下一步就是执行容量测试。容量测试一般在线上执行居多，除非在线下能构建出完全对等的环境，否则即便将服务规模和硬件资源等比例缩放，容量的表现情况也不一定是线性的。

当然，线上测试的风险较大，我个人工作中也遇到过因测试数据不严谨（夹杂了真实数据）导致事故的情况，因此需要有严格的操作规范和止损预案。此外，线上测试如果涉及写流量（会写入数据的流量），还需要进行数据隔离、业务逻辑过滤等一系列工作，在进阶篇的全链路压测一讲中，我会再与你详细展开介绍。

无论使用何种测试工具，测试执行的流程和规范都是类似的，下面给出一个较为通用，且比较安全的推荐流程。

在这个流程中，容量测试是循序渐进的过程，逐步对目标服务施加压力，期间需要严密监控各项指标，一旦出现异常，应确保无风险的情况下才能继续施压。在达到容量目标值后，可以同时进行适当的摸高（在更高压力下维持一段时间）和脉冲（模拟瞬时的高并发场景），或对限流进行验证等工作。

由于我们事前并不知道系统实际是否能够承载预估的容量，所以容量测试是一种较为高危的验证过程。我再列举一些常见的容易导致测试过程影响线上业务的情况，你一定要多加注意：

直接压到容量预估峰值，风险极大；

只进行测试，不观察监控，出了问题也不知道；

单次测试时间过长，不符合实际情况；

没有止损预案，出了问题手忙脚乱；

对目标业务不熟悉，尤其是上下游链路，把生产环境作为试验场。

5. 测试反馈

容量测试结束后，要有明确结论，总结测试过程中的各项指标和数据，与各方确认数据结论是否正常以及是否达到预期，编写测试报告，输出结论。

这里有一些注意点：首先，测试数据要保证真实有效，有时候在测试中可能由于各种原因导致当轮测试没有跑完，数据不完整，那么就应该抛弃该数据。其次，测试结论要简明扼要，对于无法确诊的信息也要清晰描述，暴露风险。最后，如果因为一些可测性的原因，导致测试结果有一定的局限性，也应该在报告中明确告知。

总之，测试报告要力求在最小的篇幅内，给出人人都能看懂的结论。

6. 持续跟进

容量测试不是单纯的测完就好，暴露的问题需要有效跟进，并在一定时间内跟踪解决，改进后确定时间再次进行验收，确保改进措施有效。

好了，到这里为止，我已经讲解了容量测试工作的整个实施过程，其中涉及的点还是比较多的，你可以按照公司的实际情况和人员投入，对具体内容进行加工。

此外，这套流程在团队内要有效地运作起来，是需要有运营动作和配置制度的，在我的团队中，我会要求在项目技术方案评审阶段，甚至是需求阶段，容量测试人员就应介入熟悉业务场景，这样在评估目标后就能非常快速地设计出测试方案，尽早进入评审流程。容量测试结束后，针对发现的问题，相应的研发负责人必须在 3 个工作日内给出解决措施，并约定再次验证的时间。这些制度都是确保流程能够落实的必要手段。

另一种容量测试：基线容量测试

说完了传统的容量测试，我们来换换口味。

前面我提到了，容量测试最好是在线上环境实施，因为在线下很难构建对等的环境。不过，有一种方式可以让我们在测试环境以较低的成本先“定性”的识别出容量差异，以便提前发现可能存在的容量隐患，这种方式称之为基线容量测试。

基线容量测试在线下测试环境就能完成，具体的做法是，我们需要按照与线上相同的部署方式搭建这套测试环境（下称“基线环境”），包括所有的中间件和网络设施，不过资源规模可以等比例减少。之后，将当前各服务的主干版本部署在基线环境上，并通过容量测试的方式获取容量指标记录备案，这些指标就称之为“基线指标”。

我们假定基线指标是符合容量要求的，接下来当有服务准备发布新版本时，就可以在基线环境上部署这个新版本，再执行同样的容量测试，将所获得的指标与基线指标进行对比，如果出现关键指标的大幅异动，如响应时间暴增、CPU 利用率暴增等情况，就需要介入排查风险。

基线容量测试虽然没有办法对服务的容量进行定量分析，因为基线环境与生产环境不对等，但是可以一定程度上提前发现潜在的容量隐患，而问题早发现的修复和优化成本是最低的。基线容量测试的另一个好处是很容易自动化，也能够很轻易地与 CI/CD 流程打通，这又能进一步降低成本。

总结

这一讲我重点与你讨论了容量测试的定义、范围和实施过程，也就一些争议概念给出了我的观点。现代化的容量测试，提倡目标先行，将容量测试定位为验收手段，规避容量不足等潜在风险。

容量测试作为一项需要科学实施的工作，涉及多个环节，包括：测试方案设计、测试方案评审、测试准备、测试执行、测试反馈和持续跟进这六大工作内容。你可以按照实际情况，对我给出的方案进行加工。

另外，线上实施容量测试还是有一定成本的，为此我提供了另一种思路，通过在线下环境进行容量指标基线对比，能够在一定程度上提前发现明显的容量隐患。

希望今天的讲解能够帮助你在团队内建立一套科学高效的容量测试流程。

课后讨论

想一想，在你的团队中，如何实施基线容量测试的自动化，并将其集成至 CI/CD 流程中？欢迎你给我留言，也欢迎分享给更多的朋友一起阅读。

03 | 容量指标分析经典5问：响应时间真的是越短越好吗？

你好，我是吴骏龙。今天咱们多聊聊干货，我会与你分享和解答容量指标分析的几个经典问题。

有名言道“数据是钢，分析是铸造”，容量指标只是摆在桌面上的数据而已，要让这些数据产生价值，需要通过分析挖掘出背后深藏的容量隐患。如果能练就一双火眼金睛，从这些纷繁复杂的指标中快速识别出潜在的容量隐患，就能最大程度上规避可能发生的容量事故。你不仅将成为一名高手，还能为公司创造巨大的价值。

不过，在实践中我发现分析容量指标还真是一项极具挑战的任务，其中很大一部分原因在于，系统容量受制于多种因素，牵涉到多个指标，复杂程度远远超过想象。下图是我分类整理过的指标集合，你可以看到，分析容量指标需要对服务架构、中间件、服务链路等环节都有深入理解，这就导致很多人一上来就撞了南墙，颇有“从入门到放弃”的感觉，坚持下来的人也往往会遇到各种误区，艰难前行。

容量指标分析作为一项实践性很强的工作，是很难通过理论学习全面掌握的。因此在这一讲中，我会直接通过“问题驱动 + 案例分析”的方式进行讲解。这些问题都是我在实践中遇到的经典问题，也是很多初学者的高频困惑点，你可以结合这些思路，在实践中多去尝试，相信很快你就能成为容量分析的大牛。

闲言少叙，我们直接进入正题。

问题一：响应时间到底是关注平均值，还是分位线？

响应时间是指从发出请求开始到最后收到响应所需要的时间，作为服务容量最显著的反馈指标，响应时间是最需要引起我们重视和全面了解的。针对这个问题我先说结论，对于互联网服务，响应时间应更关注分位线，我们常说的 TP95、TP99 或 95 线、99 线这类称呼就是指分位线。分位线的概念不难理解，将所有请求的响应时间排序，取前 95% 中最后一个请求的响应时间，即为 95 线，它表示至少有 95% 的请求响应时间小于等于这个值。

关注分位线甚于平均值的主要原因在于，平均值很容易“冲淡”一些耗时较长的请求，导致容量问题被掩盖。

考虑一个场景，某服务的常态响应时间为 100ms，可接受的最大响应时间为 150ms，当服务负载升高至接近瓶颈时，有约 20% 的请求响应时间增加了一倍达到 200ms，也就是说大约有 20% 的用户有可能已经受到影响。我们简化一下问题，假设考虑 100 个请求，这时平均响应时间是 120ms[(80×100ms + 20×200ms) / 100=120ms]，看似还好，而 95 线已经达到了 200ms（排序后第 95 个请求响应时间为 200ms），显然，95 线更容易发现容量隐患。

以分位线作为响应时间关注点的本质在于，尽管只是小部分请求的响应时间增长，但服务容量已经处于不充足的萌芽状态了，这时候如果不加干预，很有可能服务容量会迅速恶化。因此，虽然这个问题是针对响应时间的，但其实可以推广到很多地方，比如数据库的读写耗时、缓存的读取耗时等等，都应当关注分位线。

问题二：响应时间一定越短越好吗？

这又是一个关于响应时间的问题，针对这个问题，你可能会说，响应时间作为一个直接能被用户感受到的外部指标，肯定是越短越好啊，真的是这样吗？我们来看一个案例。

下图展示了某服务在进行容量测试时的现场监控情况，可以看到服务的响应时间（95 线）始终保持在 35ms 以下，对于这个服务而言是非常理想的响应时间，但这时负责盯盘的运维人员却告诉我们，目标服务抛出了大量的异常，这是为什么呢？

当时负责测试的同学是一位新手，查看了压测日志才恍然大悟，原来几乎所有的请求都返回了错误的响应体（当然，服务本身的状态码设置也有问题，无论请求正常还是异常，一律都返回了 200）。进一步排查发现，测试数据存在问题，导致对该被测服务的测试请求始终会走入异常分支，主体的业务逻辑都没有经过，响应时间当然就短了。而这位测试同学也没有对响应体设置断言，未能在第一时间发现这个问题。

响应时间越短越好，是建立在场景正确，服务无异常的基础上的。 上述这个问题虽然不属于服务的容量问题，但是在容量测试过程中时常会出现，如果仅以响应时间为观察目标，就会得到错误的容量判断，最终无法达到容量保障的效果，这是初学者很容易犯的失误。

解决这个问题的思路也很简单，就是加强全方位的指标监控，关注响应时间的同时，还要关注错误率、TPS、请求成功率和异常率等指标。我的团队在每次进行容量测试前，就会与研发一起先将这些需要观察的指标配置成一个简单的监控面板，在执行测试时可以方便观察，这样就能最大化地预防这个问题的发生，你不妨可以参考学习。

问题三：CPU 利用率一定越低越好吗？

响应时间不是越低越好，那么 CPU 利用率是不是越低越好呢？

我们知道 CPU 是一个计算机的核心计算组件，CPU 利用率代表了 CPU 工作的饱和程度，指 CPU 工作时间占总时间的百分比。

那如果 CPU 利用率低，是不是服务就一定没有容量问题呢？答案是否定的，我们来看一个例子。

下面有两张监控指标图，展示了某服务在相同时间段的响应时间和 CPU 利用率情况。可以看到，在 09：00 - 09：35 这个时间段服务的响应时间暴增，已经严重影响了线上功能，但 CPU 利用率始终维持在一个较低的水位（图中纵轴为所有 CPU 核心的总利用率，该服务 CPU 共有 8 核，总计上限为 800），光看 CPU 利用率似乎没有观察到任何问题。

我们顺着服务链路继续排查，发现该服务有大量调用数据库的操作，而在发生问题的时候，数据库的查询耗时大幅增加，似乎问题已经有了眉目。

再往下深挖，我们发现该服务使用了线程池去处理业务，线程池使用了 ForkJoinPool，默认大小为 CPU 核数（8 核）。

CompletableFuture<Map<String, XXDTO>> future =
CompletableFuture.supplyAsync(
() -> xxService.getXX(id)); //未自定义线程池，默认使用ForkJoinPool

但处理的任务却伴随着大量数据库查询等 IO 操作。这时一旦数据库负载增加，耗时变长后，线程就会被长时间阻塞，由于线程池过小导致后续任务只能排队。遗憾的是，排队的队列又是一个无界队列，从而形成了恶性循环，响应时间暴增。

查到了根因，解决方法也就很简单了，将线程池的大小重新调整，并优化排队策略，就可以避免这一问题。

因此，CPU 利用率低只能说明 CPU 不忙，并不能说明在其他地方没有容量瓶颈。 在上面这个例子中，容量瓶颈发生在了数据库上，也许在其他场景中，瓶颈还会发生在缓存，或是对其他服务的同步调用上。因此看待这个问题的视角与“问题二”是类似的，需要联动多个指标一起去分析和排查，不要只关注单一指标。

问题四：压不上去了，就是服务容量达到瓶颈了吗？

在容量测试时，我们也会遇到一些指标判断的误区，比如，在提升了施压端的输出压力后，服务的 TPS 并没有明显提升，那是不是就可以说服务容量达到了瓶颈呢？

首先，我要明确的是，服务容量是否达到瓶颈，并不是靠施压端是否能“压上去”来判断的，而是依靠服务端的容量指标去判断的。怎么判断呢？很多资料会告诉你找拐点，但很遗憾，现实中这样的拐点不太会出现，除非你真的不惜代价地增加压力。

一般来说，如果服务一切正常，当增加压力时，TPS 是会呈比例上升的，同时响应时间比较稳定。如果 TPS 上升的速率开始变缓，这时候其实容量可能已经出现瓶颈了，你可以再结合响应时间和服务资源指标确诊。

那么，为什么不能靠施压端的现象去判断呢？道理也很简单，因为压不上去，不一定就是服务不行，有可能是施压端自身出现了瓶颈。

在容量测试过程中，如果你发现增加压力后，服务的 TPS 没有提升，但响应时间也没有明显的增加，可能还会有一些抖动，这时你一定要检查一下压测端的资源消耗情况。

类似 JMeter 这样的压测工具是基于传统的 BIO（阻塞式 IO）线程模型的，一个线程同时只能处理一个连接，而单机能够支撑的线程数总是有极限的，达到这个极限后，单纯调高施压端的线程数参数，实际并不会带来更高的真实线程数，也不会增加对服务端的压力。你可以检查压测端的 CPU 利用率来判断，如果 CPU 利用率已经打满，就需要增加新的压测节点了。

此外，带宽也是一个常见的制约压测端能力的指标，尤其是当响应的返回体很大的时候，就比较容易打满带宽，这种情况甚至会影响到正常服务的访问，一定要小心。涉及多数据中心的服务可能还会遇到跨地区专线带宽打满的问题，也都是需要关注的。

总结一下，在容量测试过程中如果遇到压不上去的情况，对施压端的资源消耗要留个心眼，不要轻易认为就是服务容量不足了。此外，在实践中，施压端瓶颈几乎都发生在压力机的 CPU 和带宽消耗上。因此，我在推动压测自动化实施过程中，将施压端的监控也纳入到了自动化体系里面，一旦施压端出现资源瓶颈，就会自动告警提示测试人员。如果你觉得这招不错，可以在你的实践中尝试一下。

问题五：指标只是偶尔“抖动”一下，要不要关注？

上面聊到的问题中，很多指标都是可以定量判断容量风险的，比如响应时间 99 线超过某阈值、CPU 利用率超过某水位，等等。但是，如果这些指标只是偶尔抖动一下，我们要不要关注呢？

当然要关注，抖动是一类很容易被忽视的场景，我曾经看到一个服务每隔一段时间，响应时间会突然飙升一个尖刺，询问了服务负责人，对方很不以为然，表示这种情况一直存在，从来没有造成过什么影响，觉得我有点小题大做，结果在高峰期这个服务还真出事了。

没有找到根因的抖动是很危险的，因为你根本不知道它未来会不会导致大事故的发生。我们再来看一个例子，如下图所示，同样是有一个服务的响应时间，每隔一段不固定周期就会出现一个尖刺，似乎也没有影响用户。但经过排查后，发现该服务会在一些特殊情况下调用某第三方服务，用作补偿数据，这次额外的调用会引发响应时间的增加。

这个逻辑本身其实没有什么问题，但隐患在于，服务与第三方调用是有配额限制的，但超出配额后没有兜底措施，一旦这种特殊场景增多，甚至遇到外部攻击，服务容量立刻就会雪崩。

因此，当你遇到容量指标抖动的情况，尤其是一些莫名其妙的抖动，不要忽视它，尽可能找到根因。如果服务内部排查不出问题，不妨检查一下有没有第三方同步调用，或者底层的基础设施和中间件有无问题。对于那些实在无法确定根因的抖动（在复杂微服务体系下，总会有那么些悬案），要加强监控，并制定故障恢复预案，以防出现容量问题时手忙脚乱。

总结

在安全领域，有一个著名的法则叫海恩法则，它告诉我们，每一起严重事故的背后，必然有 29 次轻微事故和 300 起未遂先兆，以及 1000 起事故隐患，事故的发生是量的积累的结果。海恩法则其实最终是想表达，任何不安全事故都是可以预防的。就像我们上面提到的 5 个经典问题，在容量保障领域，任何不安全事故也是可以预防的，你都学会了吗？

首先，容量指标分析不能仅关注单一指标，无论是响应时间还是 CPU 利用率，单个指标的优劣并不一定能完全说明问题，需要联动去看。从实践角度，建立监控大盘去汇总多个关联性指标，是一个不错的做法。

其次，做容量测试时如遇压不上去的情况，应及时关注施压端的资源消耗程度，CPU 利用率和带宽是常见的会影响施压能力的指标，我们同样可以通过监控告警的方式，自动暴露问题，减少人工判断的成本。

最后，我们不要轻易放过抖动情况，即便目前为止对系统功能没有影响，也要重视。抖动可以先从服务内部进行排查，看一下是不是有性能问题或是调用不合理之处，之后可以继续排查第三方同步调用和基础设施的问题，哪怕最终无法查到根因，我们也要制定预案，预防风险。

容量指标分析作为实践性极强的内容，所有这些知识点都需要你在实践中反复推敲和感受，方能融会贯通，正所谓神枪手都是子弹喂出来的，我只能帮助你少走弯路，但无法给到捷径。希望你能不断总结不断思考，形成属于你自己的容量指标分析最佳实践。

课后讨论

你在容量指标的分析过程中有遇到过我上面提到的，或者没有提到的困惑吗？如何解决的？如果你有一些自己的经验，也欢迎给我留言，我们一起交流。如果你觉得这一讲对你有帮助的话，欢迎把它分享给你的朋友。

04 | 容量治理的三板斧：扩容、限流与降级

你好，我是吴骏龙。

在前面几讲中，我谈到了容量测试和容量指标分析等工作，这些工作能够帮助你验证服务是否存在容量问题，并定位问题出现的原因。

找到问题以后，我们需要排除这些容量风险，确保服务的稳定性，这就是容量治理需要做的工作了。优秀的容量治理工作不仅仅能通过一系列手段解决已出现的容量问题，而且还能预防容量隐患，做到防患于未然。

下面，我们就来认识一下三个常见的容量治理手段：扩容、限流和降级，这三个手段分别基于不同的视角，在容量保障中发挥着各自的价值。在这些内容的讲解中，我会从我经历过的实际案例出发，告诉你一些实践中的难点和坑点，希望能带给你更多的收获。

扩容的实践要点

说到扩容，不得不提到在软件架构设计中经常出现的一个词，叫做“伸缩性”，更高端的说法叫“弹性”。以目前互联网服务的用户体量，已经不太可能通过单台服务器去支撑所有的流量，流行的做法是将多台服务器组成集群统一对外提供服务，伸缩性指的就是能够往这个集群中不断加入新的服务器资源，以应对流量增长的能力，而这个加入新的服务器的过程，就是扩容。

如果容量瓶颈发生在服务器资源层面，扩容恐怕是最直接也是最“暴力”的容量提升手段了，尤其是在服务容器化盛行的当下，拉起一个新服务实例，往往只需要秒级时间，扩容的成本得到了有效的降低，能够快速消除容量风险。

我对扩容的态度是：鼓励将快速扩容作为应急手段，但作为容量治理手段要谨慎，警惕无脑扩容和滥用扩容。

在实际工作中，很多业务研发一遇到自己的服务容量不足，第一个念头就是扩容，服务本身的优化工作，包括异步处理、读写分离、增加缓存、SQL 调优等等，往往会被忽略，这是有很大风险的。

首先，在开篇词中我就提到过，容量保障是要考虑成本的，如果纯粹依靠扩容去支撑性能低劣的服务，浪费的是大量的资源和金钱。其次，扩容也很容易触碰到边际递减效应，也就是说，服务资源达到一定规模后，再往上扩容的代价会大幅上升。

我在阿里本地生活推动容量风险改进时，说的最多的一句话就是：“不要无脑扩容！”。甚至每到大促活动期间，我都会与全局架构师进行合作，如果有业务方提交的扩容工单中仅仅提到了对扩容资源的需求，而没有考虑任何服务层面的性能优化措施，这样的工单会被直接拒绝。建立谨慎扩容的风气相当重要，如果大量的容量问题都靠“堆机器”去冲摊，服务资源的成本会越来越高。

除了避免无脑扩容，我还要提醒你注意的是，扩容不能只关注服务本身的资源占用情况，还应同时关注对底层资源的影响，如：数据库资源、中间件资源等。

举个简单的例子，某服务集群一共有 10 个容器实例，每个实例会建立约 100 个数据库连接，加起来就是约 1000 个连接，假设数据库总共支持的连接数为 1200 个，这是能够支撑现状的。但如果考虑到近期业务增长较快，会导致服务负载较大，需要扩容 5 个实例，那么总的数据库连接数大约会达到 1500 个，这就肯定支撑不住的，所以对服务进行扩容时，对数据库也需要同步扩容。

再分享一个稍复杂的例子，在微服务体系中有一项服务发现机制，每个服务可以通过该机制获取被调用服务的位置。服务发现机制的一种实现方式是，由一个注册中心建立对每个服务实例的长连接，并维护一个服务状态列表，这样一旦服务状态发生变化，注册中心能够第一时间感知到并对服务状态列表进行更新。

我们很容易想到，这些建立的大量长连接可能会产生瓶颈（主要是消耗内存），当我们对服务进行扩容时，实际上就是增加了服务实例，这会产生更多的长连接。因此在这种服务发现模式下进行扩容时，注册中心的容量也需要同步考虑。

如果你觉得扩容要考虑的点太多，一种通用的做法是，先梳理出被扩容服务的调用链路，看一看流量经过哪些地方，分析一下这些地方会不会受到扩容的影响，再去采取相应措施。

总结一下扩容的实践要点，首先，要建立服务性能优化胜过简单扩容的意识，努力通过性能优化腾出容量，避免不经思考直接扩容。其次，扩容要联动系统整体资源共同规划，不能只关注服务资源。

限流的实践要点

扩容的出发点是尽可能提供足够的资源保证服务容量充足，但正如我在第一讲中所提到的，容量保障是需要兼顾成本的，限流就是在控制成本的情况下对服务容量的一种保护措施。此外，即便进行了严密的容量规划和系统优化，我们依然无法保证线上流量一定百分百符合既定的预测范围，因为总会有这样那样的突发事件发生，如果流量峰值超过了系统能够承载的极限，相较于紧急扩容，提前设置合理的限流对系统进行过载保护，是更主动的方式。

那么，在提前设置限流时，我们应该选择什么样的限流策略，以及在什么位置进行限流呢？下面，我就从限流策略和限流位置两个角度，告诉你在选择策略和位置时应该注意的要点。

首先，从限流策略的角度，可以将常见的策略形象地归纳为“两窗两桶”，分别有：固定窗口、滑动窗口、漏桶算法和令牌桶算法。这些策略本身的实现方式和特点我就不多费笔墨了，网上已经有很好的学习资料，你可以点击查看。我会将讲解的重点放在如何选择合适的限流策略，以及如何建设有层次的限流体系上。

首先要与你分享的经验是，限流策略的选择和业务场景应当是高度挂钩的，不能想当然觉得复杂的策略就一定好。为了让你更深刻的理解这一点，我总结了上述四个限流策略中，与业务场景紧密相关的三大流量控制方式，分别是：流量整形、容忍突发流量和平滑限流，它们的含义如下：

流量整形： 指不管流量到达的速率多么不稳定，在接收流量后，都将其匀速输出的过程，即“乱进齐出”。

容忍突发流量： 指的是限流策略允许流量在短时间内突增，且在突增结束后不会影响后续流量的正常限流。

平滑限流： 指的是在限流周期内流量分布均匀，比如限制 10 秒内请求次数不超过 1000，平滑限流应做到分摊到每秒不超过 100 次请求。反之，不平滑限流有可能在第 1 秒就请求了 1000 次，后面 9 秒无法再发出任何请求。

基于这三个特点，结合不同限流策略对流量控制方式的具体支持情况，我汇总出了下面这张表格。

有了这张表格，你就可以根据业务场景去选择合适的限流策略了。比如说，固定窗口无法容忍突发流量，但它实现简单，资源消耗少，如果你的应用服务流量是平缓增长的形态，也没有流量整形的需求，这时采用固定窗口策略进行限流就不失为一种合理又经济的选择。

相反，如果你的应用服务经常需要应对诸如大促场景这样的突发流量，那么使用令牌桶算法进行限流往往会更适合，当然，这时你也得接受令牌桶策略实现的高复杂度。

总之，针对每个限流策略的特点，在具体业务场景合理使用，才能发挥它最大的价值。

好了，聊完了限流策略，接下来我们将视线切换到另一个维度，从限流位置的视角来探讨限流实践，这里想说明的核心理念是：良好的限流应该是分层次的。这就好比我国长江的防洪策略，有三峡这个“巨无霸”在上游作为挡板调控洪峰，下游有葛洲坝、溪洛渡这样的中型水电站进一步调节水量，再往下还有无数小型水库进行精细化控流，形成了全方位保护的机制。限流也是同样的道理。

根据不同的限流位置，限流可以划分为网关层限流、接入层限流、应用层限流、数据库层限流等。我们直接来看下面这张图，图中自上而下描述了服务的流量走向，非常清晰地体现出层次化的限流思路，每个位置都恰如其分地加入了相应的限流策略，下面我具体解读一下。

第一层，入口网关可以针对域名或 IP 进行粗放式限流，静态资源直接走 CDN（内容分发网络），同时在这一层还可以将一些不合法的请求拦截掉，不要流入下游，仅放过合法请求。

第二层，硬负载和接入层都可以实施负载均衡和限流措施，分担服务压力。它的粒度比入口网关层更细，但还没有办法对单个服务实例进行限流。

第三层，到了应用服务层，每个服务可以有自己的单机或集群限流，调用第三方服务时，也可以单独进行限流。

第四层，与数据库的交互，采用读写分离的方式，分流数据库压力，同时也可以针对数据库读写请求进行限流。

总之，在制定每一层的限流策略时，都应该抱着不信任上层限流的思维，这样即便某一层限流机制发生问题，也不至于引发全局问题，最终形成的限流体系才是最健壮、最可靠的。

总结一下，限流的核心思路是：第一，根据业务特点，比如是否有突发流量、输出流量，是否需要整形、是否需要平滑限流等，选择合适的限流策略，确保限流策略的健壮性和可靠性；第二，分层次，在不同的位置进行限流，多管齐下全方位完善限流体系。

降级的实践要点

前面提到的限流措施，是通过拒绝一部分服务流量来强行控制服务负载的手段，是从控制流量的视角来保证服务容量安全的；而降级则是从系统功能角度出发，人为或自动地将某些不重要的功能停掉或者简化，以降低服务负载，这部分释放的资源可以去支撑更核心的功能。简而言之，弃卒保帅。

降级在互联网行业的应用非常广泛，比如某大型电商在双 11 当天会将退货的功能降级，以确保核心交易链路的容量充足；某生鲜公司在遇到流量高峰期时，会将一部分个性化推荐的功能降级，以确保导购链路的工作正常，等等。抽象总结可以有以下几类策略，我同时提供了一些案例供你直观地理解它们。

降级的技术实现本质上不难，也是微服务系统的常见功能，绝大多数情况下，是通过设置开关，并将开关收口至配置中心的方式作集中式管理的。我想深入讲解的知识点是，如果你已经有了一套降级系统，该如何管理上面的众多降级开关，把它们真正有效地推行下去，在服务容量发生风险时，及时止损，或提前止损。

首先，降级需要平衡好自动触发和人工执行两种做法。根据预置的触发条件自动执行降级固然快速便捷，但某些场景的降级触发条件其实挺难判断的，比如在系统偶发抖动的情况下，到底是降还是不降，需要根据当时的业务情况做综合判断，这时候还是人工介入更靠谱。此外，还有一些降级会涉及到与第三方的合约，比如对支付宝、微信支付这类功能的降级，需要与对方确认后才能执行。

自动降级比较适合触发条件明确可控的场景，比如请求调用失败次数大于一定的阈值，或是服务接口超时等情况；还有一些旁路服务，比如审查日志记录等，如果压力过大也可以直接触发自动降级。我将这些要点总结为下面这张导图，供你参考。

其次，降级需要进行分级，因为降级操作都是有损的（如果无损，那你应该考虑一下被降级的功能是否还有存在的必要了），所以如果进行“温柔的”降级已经能够释放足够的容量，就没有必要过度降级。

基于这个理念，我们可以根据对业务的影响程度，制定降级的分级策略。比如在导购链路上，针对个性化推荐和滚动热词功能的降级就属于不太影响用户使用的范畴，可以定为 1 级降级；而不展示商品图片和评价内容这类降级，明显会对用户使用造成不便，应定为 2 级降级。在真实发生容量问题时，可以先执行 1 级降级，如果服务恢复，则无需执行 2 级降级。

最后，降级需要演练，而且是频繁的演练。有些服务的降级逻辑由来已久，随着服务代码的迭代更新，这些降级逻辑可能已经失效了，一旦服务出现问题真要降级时，这可是要命的。通过高频演练可以及时暴露这些无效的降级开关，防患于未然。

总结一下，降级与限流有明显的区别，前者依靠牺牲一部分功能或体验保住容量，而后者则是依靠牺牲一部分流量来保住容量。 一般来说，限流的通用性会更强一些，因为每个服务理论上都可以设置限流，但并不是每个服务都能降级，比如交易服务和库存服务，就不可能被降级（没有这两个服务，用户都没法购物了）。

降级的策略还是比较丰富的，因此需要从多个角度去化简。首先，将一部分判断条件简单的降级通过自动化手段去实现；其次，根据对业务的影响程度，对降级进行分级，达到有层次的降级效果；最后，通过高频演练，确保降级的有效性。

总结

这一讲，我主要介绍了容量治理的三个手段：扩容、限流和降级，将容量测试获得的数据和分析工作的价值真正落到实处，降低容量风险。

实际工作中，需要特别警惕无脑扩容，加强服务架构优化意识和根因分析能力；在扩容时，也应全面评估系统资源情况，做到资源平衡。

奥卡姆剃刀定律告诉我们：“如无必要，勿增实体”，简单的才是最有效的。限流策略的制定应充分考虑业务场景特征，选择最简单和最适合的限流策略，而不是盲目追求复杂的策略。同时，限流应当从全局视角看待，建立层次丰富可靠的限流体系。

降级的本质是为了解决服务资源不足和访问量增加的矛盾，而放弃一部分功能或体验。降级应当平衡好自动化降级和人工降级的关系，并通过分级的方式保证最小可用降级，最后辅以大量高频的验证，确保降级的有效性和熟练度。

容量保障，任重道远。没有无死角的容量治理手段，我们应当全方位、体系化地思考认识，多角度覆盖容量保障的方方面面。

课后讨论

现在有这样一个业务场景，它的主要工作是审阅、处理和发放工资。我们有一个服务系统支撑这个业务场景，其中，审阅和处理工资是由公司财务在系统上完成的，在每月的最后一周是高峰期，其他时间几乎没有请求；而发放工资的功能是对接银行的第三方接口实现的，这个接口非常脆弱，每秒只能处理 5 个请求。

请问，针对这样的一个服务系统，选取哪种限流策略比较合适？欢迎与我交流你的想法，在评论区给我留言。如果你觉得这一讲对你有帮助的话，欢迎把它分享给你的朋友。

05 | 全链路压测：系统整体容量保障的“核武器”（上）

你好，我是吴骏龙。

通过基础篇的学习，相信你对容量保障的相关知识已经有了基础的了解，知道了容量测试不能简单定义为压力测试，而是验证服务容量的手段；知道了容量指标分析不能只看单一指标，也学习了分析容量指标的 5 个经典问题；以及了解了容量治理可以采取扩容、限流和降级策略。

从今天开始，我们踏入进阶篇，进阶篇的所有内容都是比较前沿或创新的知识，希望通过大厂前沿经验和我的积累，帮你拓宽视角。在进阶篇，我们从关注度最高的全链路压测开始，与你分享我的实践经验。

你可能会问，到底什么是全链路压测？实施全链路压测要经过几个步骤？有哪些难点坑点？别急，因为内容较多，我会分成两讲，这一讲，先聊聊全链路压测的诞生，以及实施全链路压测前的三项改造工作。下一讲，我们再进一步聊聊两项具体的压测工作，把全链路压测的建设过程完整展示给你。

全链路压测的诞生

2013 年对阿里巴巴来说有着非凡的意义，因为那一年，全链路压测诞生了。这可是双 11 容量保障工作的福音，对守在电脑前的程序员们来说，流量洪峰终于不再那么可怕了。

虽然当时我还没有进入阿里体系内工作，但我作为一名用户亲身参与了从 2011 年开始的所有双 11 活动，我能深刻感受到双 11 系统稳定性的变迁。总体来说，2011 年和 2012 年给我的体验不太好，但 2013 年就有了很大的改观。

2011 年和 2012 年双 11 活动的整点，系统不可用的问题对我造成了很大的困扰，访问网页各种报错，连付款都困难，当时把我给着急的呀，生怕要买的东西被抢完了，如果你也经历过那时候的双 11，应该能够感同身受。

不过从 2013 年开始，虽然每年双 11 的规模都在大幅增长，但除了付款操作偶尔还会被限流以外，网页无法访问这种系统不可用的情况几乎碰不到了。直到后来我进入阿里体系内工作后才知道，当时的阿里人为此付出了大量的努力和汗水，在短短几个月的时间内，大刀阔斧地推动各项改造，构建压测模型，创造性地完成了全链路压测的建设工作，才得以保证双 11 的稳定进行。要知道，当年双 11 的流量峰值已经超过了每秒 4 万笔交易量，放眼全世界也是独树一帜的存在。

阿里的经验证明了一点，那就是对未来可能产生的流量峰值而言，任何预防性的稳定性保障手段，都不如把实际峰值场景模拟出来“看一看” 来的有效，这就好比建造三峡大坝，预计能抵挡千年一遇的洪水，但是否能达到这个目标，还是需要经历多次洪水考验才能证明的。全链路压测就是通过模拟这场千年一遇的洪水，来验证服务系统是否能承载预估的流量峰值。

在全链路压测诞生前，阿里双 11 的容量保障工作主要是对业务目标进行拆分，对各个服务链路单独进行压测，虽然也进行了大量的压测工作，但实际发生流量洪峰的时候，很多系统的容量还是会有问题。

为什么单链路压测无法排除系统整体容量风险呢，因为整体系统的容量不是由多条“单链路”的容量简单相加而得的。我们看一下下面这张图，它表达的含义是，应用服务的容量除了受自身影响，还受依赖服务的影响，而依赖服务又可能有其他调用方，甚至是一些外部服务，这些影响经过几层累积后，最终的影响面极难判断。

而全链路压测直接从全局视角出发，它的本质是基于线上真实环境和实际业务场景，通过模拟海量的用户请求，来对整个系统的容量进行评估的手段。当然，罗马不是一天建成的，全链路压测也不是一蹴而就的，有很多重点问题需要解决，我们可以从两方面思考。

首先，全链路压测本质上也是一种容量测试的手段，因此容量测试需要解决的问题也是全链路压测面对的重点问题，比如数据隔离、压测场景置信度、对正常业务的影响等，其中有些内容我在之前的讲解中也已经涉及到了。

其次，全链路压测的特点决定了它会存在一些独有的重点问题，由于全链路压测遵循与用户访问相同的流量轨迹，因此会涉及大量的服务链路，我们需要保证压测流量在这些链路中流动时的完整性和可识别性。此外，有别于单链路压测只需要制造局部流量，全链路压测需要制造大规模的整体流量，这也是需要重点考虑的。

可以说，解决了上面这些问题，就具备了全链路压测实施的基本条件，下面我就来具体展开讲解一下全链路压测的建设过程，其中包含三项改造工作和两项压测工作。

三项改造工作包括：数据隔离、中间件改造和应用服务改造，这些改造工作致力于解决上面提到的压测流量的完整性和可识别性、数据隔离以及对正常业务的影响这些重点问题。而两项压测工作则包括：压测模型构建和压测流量构造，对应上面提到的场景置信度和大规模流量制造这两个重点问题。关于两项压测工作，我们下一讲展开。

全链路压测应该如何建设

三项改造之数据隔离

为了避免环境不对等所造成的压测结果失真，全链路压测一般都是在生产环境展开，而线上压测就一定会涉及到数据隔离的问题，压测数据需要与真实数据有所区分，确保不影响真实用户的体验。因此，数据隔离是全链路压测建设过程中最重要，也是最必不可少的工作。

常见的数据隔离方式有两种，分别是：逻辑隔离和物理隔离。

逻辑隔离是指通过数据打标的方式区分真实数据和压测数据，在各实体（如用户、商户、订单等）中添加压测类型标识。比如针对用户这个实体，可以设置一个用户类型字段，其他系统或服务可以根据这个字段硬编码走相应的隔离逻辑。

enum UserType {
     NORMAL = 0,    # 普通用户
     PERF = 1,      # 压测用户
}

逻辑隔离实现简单，容易理解，但难以标准化，因为具体的字段设置是由业务技术方决定的。比如上面举例的用户数据中的压测标识字段是 UserType，但商户数据中的压测标识字段可能就变成了 ShopType，上游系统如果需要同时识别多种数据的压测标识时，会比较困扰。

第二种数据隔离方式是物理隔离，它的做法是先通过在压测流量中进行打标的方式，区分真实请求和压测请求，再将压测请求所涉及的数据存储到另一个与真实表数据结构对等的表中（俗称影子表），使压测数据在物理上与真实数据隔离。这就涉及两个重点工作，一是在压测流量中打标，二是建立影子表。

在压测流量中进行打标该如何做呢？通常情况下，流量入口大多是 HTTP 请求，压测流量标识可以置于 HTTP Header 中，进入内网后，相关中间件需要将 HTTP Header 中的压测流量标识转移至内部请求，如 RPC 请求的上下文中，如遇异步组件，如消息队列，也需要做特殊处理，具体我会在下文“中间件改造”那部分展开。

这个过程要确保压测流量标识能够一路透传（传输过程中不对标识进行改变）至数据层不丢失；最后，数据层，如数据库中间件通过对压测流量标识的识别，将数据写入影子表，完成整个物理隔离的全过程。

值得一提的是，物理隔离还有一个额外的好处，由于实现物理隔离必须构建统一的压测流量标识，那么分布式链路跟踪系统也可以根据该标识，直观地展示压测链路，这样比较方便监控和排查问题。

那么，影子表如何建立呢？为了使全链路压测对于数据库容量的评估准确，我们需要保证影子表的数据内容和规模与真实表一致，但又不能与真实表数据冲突，你可以参考以下过程建立影子表：

针对某张真实表建立相应的影子表，表名可以通过增加前缀或后缀区分，比如原表名为 User，影子表名可以设定为 User_T，其他影子表也都基于 _T 这个后缀建立。

将真实表的数据进行脱敏，部分 id 类字段需要进行偏移，以免增长后与真实表冲突，比如真实的订单号都是以 1 开头，那么影子表中的订单号可以偏移为以 9 开头。

脱敏和偏移后的数据导入到影子表中。

进行完整性检查（数据量、表结构等内容），确保数据无误。

逻辑隔离和物理隔离各有千秋，两者对比如下表所示。我的经验是，如果你公司的技术体系比较成熟，技术栈统一，也有固定的中间件团队支持，那么可以尝试使用影子表的方式进行数据的物理隔离；反之，如果技术体系不完整，或大量使用开源框架，二次开发成本高，那么可以采用逻辑隔离的方式。

三项改造之中间件改造

在数据隔离环节我已经提到，压测流量标识透传以及数据的物理隔离等工作，都需要对中间件进行改造，比较典型的有数据库中间件对影子表的支持，消息队列对压测流量标识传递的支持，等等。

数据库中间件对影子表的支持比较简单，上面也已经提到过，实现的机制是基于压测流量标识，数据库中间件接收到某个带有压测流量标识的请求需要操作数据库时，将这个操作的目的地重定向到影子表上。这些影子表的信息，以及与真实表的映射关系，可以维护在一个统一的地方做管控，同时供数据库中间件调用。

另外一个典型的中间件，消息队列，它是微服务体系中常见的中间件。消息队列对压测流量标识传递的支持，主要目标是保证在生产和消费数据时，压测流量标识不能丢失。具体来说，当有压测请求作为生产者将数据写入消息队列后，这个生产者的使命就完成了，当消费者去消息队列中消费出这条消息时（相当于另一次请求），我们已经无从知晓数据是压测数据还是真实数据了，这破坏了压测流量的可识别性。

因此，对消息队列需要进行改造，当接收到带有压测请求标识的生产者推送消息时，需要将压测标识转存至数据中，以免丢失，当异步服务消费数据时，再将该标识恢复至请求体或上下文中继续传递。

通过以上两个例子，你可能也发现了，中间件需要改造的地方基本上都是与压测数据打交道的地方，所以在中间件改造方案的制定中，我们需要对数据特别敏感，涉及到数据的地方可能都是潜在的改造点。

三项改造之应用服务改造

除了中间件改造，应用服务也需要进行一定的改造，确保压测请求能被反复执行，并且不影响真实场景，常见的应用服务改造点有：

绕开限制逻辑： 比如系统针对短时间内反复下单的用户将进行限制，这个逻辑针对压测流量需要放开。

数据隔离前置： 数据隔离前置能够减轻其他应用服务改造的工作量，比如大数据报表中需要对压测数据进行剔除，如果这些报表的数据源都在数据仓库里，那么我们完全可以在压测数据生成时就隔离掉不进数据仓库，这样大数据服务就无需改造了。

Mock 逻辑： 有些对外交互的服务是不太方便发起大量真实请求的，比如支付和清结算等，这些功能可以在识别到压测流量后走 Mock 服务，也就是模拟一个正常的返回，而不是直接调用真实服务。

除此之外，还有一些如风控拦截等安全性方面的限制也需要适当放开，以便压测请求能够重复执行。总之，所有可能会限制或阻碍压测请求流动的地方，都需要打通，如果无法打通，那就 Mock。

好了，到这里，数据隔离、中间件改造和应用服务改造都完成后，我们已经初步具备了实施全链路压测的条件。接下来就是压测实施层面的工作了。下一讲，我们主要来聊聊压测模型构建和压测流量构造两项工作。

总结

在这一讲中，我首先与你分享了全链路压测的诞生过程，正所谓“预见未来最好的方式就是实现未来”，阿里通过将全链路压测成功应用于双 11 活动的保障工作，证明了这一点，也为容量保障带来了一个强大的武器。

全链路压测通过模拟海量的用户请求，来对整个系统的容量进行评估，其建设过程涉及到的要点还是比较多的，今天我们主要讲的是三项改造工作，这里面有几个重点你可以关注：

数据隔离是全链路压测建设过程中最重要的工作，逻辑隔离和物理隔离是两种常见的数据隔离方式。

如果公司的技术体系比较成熟，基础设施统一且有专业团队维护，那么可以尝试使用影子表进行数据的物理隔离，这样数据风险更小；反之，如果基础设施改造成本太大，就建议采用逻辑隔离的方式。

在中间件改造方案的制定中，我们需要对数据特别敏感，涉及到数据的地方可能都是潜在的改造点。

常见的应用服务改造点有：绕开限制逻辑、数据隔离前置、Mock 逻辑等，这些改造工作能够确保压测请求的正常流动，也能更好的配合数据隔离。

课后讨论

在中间件改造的版块中，我详细讲解了消息队列的改造工作。如果你要在公司内实施全链路压测，你觉得还有没有其他和数据打交道的中间件需要做改造的？如果有的话，你会怎么设计改造方案？欢迎你给我留言，也欢迎分享给更多的朋友一起阅读。

06 | 全链路压测：系统整体容量保障的“核武器”（下）

你好，我是吴骏龙。

上一讲，我为你讲解了在正式实施全链路压测前，我们要做的三项改造工作，包括数据隔离、中间件改造和应用服务改造。这一讲，我们就正式进入两项压测工作：压测模型构建和压测流量构造，把全链路压测的建设过程完整展示给你。除了技术工作之外，在这一讲中我还会与你分享全链路压测的组织协调和运营工作，它们对全链路压测的完整落地同样起到至关重要的作用。

我们先看看如何构建压测模型。

两项压测工作：压测模型构建

构建压测模型的重点是准确度，如果模型与真实场景相差过大，那么压测结果的可参考性将会大打折扣，下面是一些典型的由于压测模型不准确导致压测结果无效的反面教材：

下单链路中，压测用户没有使用红包，导致对营销服务的压测结果偏优。

压测用户数据未考虑 sharding 分布，导致数据库单片过热。

压测用户数量过少，使用有限的压测用户反复下单后，导致单个用户订单量过多。

压测商户数量过少，压测时针对单个商户的操作过于密集，导致菜品扣减库存的锁争抢激烈。

压测模型包含业务模型和数据两部分，我再来通过几个实例讲解一下如何构建尽可能真实的场景。

实例一: 读请求

读请求由于不会对数据造成污染，因此可以直接使用真实请求和数据进行回放。

压测场景：商家列表及关键词查询。

业务模型：拉取线上日志，根据真实接口比例关系进行回放。

数据：拉取线上日志，使用真实数据。

实例二: 写请求

写请求一般需要单独构造压测模型，并做好数据隔离和清理工作。

压测场景：用户下单

业务模型：根据生产监控或日志，获取下单场景的链路信息，观察接口调用情况和上下游依赖，当然，你也可以写一个系统帮你做这个事。产品、研发和测试共同评审链路的完整性。另外，评估业务改造点，比如需要对支付和短信等环节进行 Mock。

数据：构建测试用户、测试商户、测试菜品等数据，数量上与线上真实情况等比例缩放；及时对压测数据进行清理，或使用影子表。

归纳一下，压测模型构建的核心要点是，要利用好生产环境的各种信息来帮助我们构建贴近真实业务的压测模型。生产环境是个聚宝盆，请求的依赖关系、调用比例、数据特征都是我们构建压测模型的素材，将这些数据抽取出来再进行精加工，即可得到贴合实际的压测模型。

两项压测工作：压测流量构造

有了压测模型和数据，最后临门一脚就是构造压测流量进行施压。全链路压测对于压测流量构造的技术选型主要取决于流量的规模，如果规模不大，传统的压测工具是可以支持的，如 JMeter、Locust、nGrinder 等；如果是大规模流量乃至超大规模流量（百万请求量级），成本就会比较高。对于后者，可以考虑自研一套压测平台，这也是很多大厂的做法，我在下一讲会专门展开这部分内容，敬请关注。

我们来总结一下，全链路压测的建设过程可以归纳为两个重点：首先，通过中间件改造和应用服务改造，保证压测流量的完整性和可识别性，并保证压测数据与真实数据隔离开；其次，利用生产环境的各类信息，构建贴近真实场景的压测模型，并通过构造大规模压测流量实施全链路压测。

这些工作都完成后，全链路压测在技术层面的建设就基本告一段落了。

全链路压测的组织协调和运营工作

说了那么多，也许你会觉得建设全链路压测的技术难度还是挺高的，但我想告诉你的是，除了技术工作，组织协调和运营工作其实更难。这就好比新冠肺炎疫情的防控，全世界都知道中国的成功经验，但有几个国家能成功复制中国的防疫举措呢？

关于全链路压测建设时会涉及到的组织协调工作，通过全链路压测的建设过程相信你也看到了，其中光中间件改造和业务改造两项工作，就几乎覆盖了大半个技术团队，要同时协调那么多团队的工作安排，难度不小吧？

我认为，推动全链路压测这样的“航空母舰”项目，是需要自上而下的，但不一定非要强推。我在阿里本地生活工作时，技术团队建立了 “Program 机制”，这是一种针对跨团队大型项目的推动机制，由 CTO 直接牵头和授权，对公司内部需要推动的技术改造类项目，进行必要性和优先级评定。

从项目跟进的角度来说，所有公共团队（如基础设施团队、大数据团队等）和业务团队的技术 Leader 需要定期参加会议，在会议上对这些项目的进展和风险进行讨论，业务团队必须在约定时间内完成公共团队的技术改造需求，而公共团队则需要提供合理的方案，并提供足够的支持。

Program 机制为基础设施团队推动技术改造类项目提供了一个强有力的抓手，动态平衡了业务实现与技术改造之间的关系，使得业务团队必须腾出一部分时间进行技术升级，而不是埋头沉迷于业务迭代。

全链路压测就是众多技术改造类项目的一员。在我目前所在的这家创业公司，同样是依托于类似的机制，仅仅 2 个多月的时间，便从 0 到 1 推动完成了全链路压测的核心改造工作，所以你也大可不必把全链路压测想的很难，可以尝试用类似的思路去推动它。

组织协调很难，另一个更有难度的问题是，在全链路压测建设完成后，如何将其有效地运营起来，明确每个参与团队要做什么事，做这些事的规范是什么，做的不好的后果是什么等等，这样才能将全链路压测的价值最大化地固化下来。

我的经验是，全链路压测是需要有一个集中式的团队去管理的，这个团队不需要很多人，但是需要被充分授权。可能你会问，光授权也没用啊，别人不听你的怎么办？这时候就需要通过一些规范去约束和管控了。

我在做全链路压测运营工作时，建立了两项规范，首先是全链路压测的常态化执行制度，每周三晚间低峰期执行全链路压测，核心链路的技术人员和运维人员必须现场值守，其余技术人员可以远程值守。值守人员需要严密关注业务指标，如果出现服务可用性问题或资损问题，及时报告压测团队暂停压测。

如果压测过程中出现服务瓶颈，我们有时候会执行一些降级操作以观察效果，这时候值守人员也应配合操作，如果因为未有效值守导致线上问题，需要承担连带责任。

此外，全链路压测能够暴露出整体系统的容量隐患，但仅仅将问题暴露出来还是不够的，我们需要确认这些问题得到重视和解决，才是真真正正地消除了容量风险，我建立的第二项规范，就是用来驱动全链路压测时所发现问题的及时改进，称之为容量问题分级规范。

这项规范根据容量风险的严重程度划定了不同的等级，每个等级对应不同的解决时限要求，越严重的风险，越是需要快速解决，或至少有临时措施。我们会定期统计问题解决的时长达标率，以此作为所有技术团队绩效考评的一个参考标准。

总结一下，推动全链路压测的落地，不仅仅是一项技术工作，组织协调和运营工作同样重要，否则还是很容易失败的。我比较倡导通过建立机制和流程规范的方式，自上而下去联动和管理多个团队之间的工作，定好的规范要及时跟进并督促执行，尽早暴露风险。

总结

关于全链路压测的内容比较多，我们来好好总结一下。全链路压测通过模拟未来流量峰值提前发生，将不确定问题转化为确定性问题，从而达到提前暴露系统整体容量问题的目的。

全链路压测的建设过程，涉及到数据隔离、中间件改造、业务服务改造、压测模型构建和压测流量构造这五项工作，有一定的技术难度和改造量，虽然我在讲解中提供了多种方案，但你在制定技术方案时还是需要平衡好投入产出比。

例如，公司大量采用开源技术作为基础设施，业务场景也比较简单，这时候完全可以不用去动这些基础设施，可以直接在业务层进行压测数据的逻辑隔离。构造流量也可以直接使用成熟的开源工具（JMeter、Locust 等）。一句话，适合的才是最好的。

全链路压测不是单一的技术问题，组织协调和运营工作也需要重点考虑，建立一支强有力的全链路压测团队，通过流程和机制的制定，去管理和规范各个团队的工作，是我给到的经验之谈。Program 机制、全链路压测常态化执行制度和容量问题分级规范，是我给出的三项具体可操作的方法，也是我推动或利用的比较成功的例子，希望能够给你带来一些启发。

最后，河有两岸，事有两面，全链路压测也不是银弹，无法解决所有问题，将所有容量问题全部交给全链路压测兜底，不再做单链路压测或单服务压测，是错误的实践。全链路压测的实施成本较高，因此其实施频率一般是远远低于业务变更频率的。

全链路压测的擅长点是定期摸底系统整体容量，而常态的容量保障工作应当覆盖每个业务各个接口，这些毛细血管依然需要单链路压测和单服务压测去保障。

课后讨论

假设我们通过全链路压测得到结论，系统整体能够承载 1000TPS（每秒下 1000 单）的负载，但实际业务达到这个负载时，系统却出现了不稳定的情况，你觉得在全链路压测工作中可能有哪些地方我们考虑的不够周全，从而导致了这一问题？欢迎在评论区与我交流你的想法。

07 | 工具进化：如何实现一个分布式压测平台

你好，我是吴骏龙。工欲善其事必先利其器，今天我将与你分享如何自己实现一个分布式压测平台。

现在只要是规模大一些的互联网公司，都在不遗余力地开发自己的压测平台，比如京东、美团、阿里、360。可能你会问，市面上已经有无数的开源压测工具和平台，比如 JMeter、Locust、nGrinder、Gatling 等，为什么要自己做呢？我在和一些大厂的同行交流经验时，发现对于常见开源压测工具的诟病不外乎有以下几点。

从开源压测工具和平台的这些缺点中，我们可以看出，对于企业来说，自研压测平台就是要满足以下三点需求：

1. 平台化： 企业需要一个平台化的压测工具，每个团队都可以在这个平台上协作，而开源工具大多是 C/S 类型（ 客户端 / 服务器体系结构），缺乏平台化支持。

2. 标准化： 企业需要一个统一的标准化压测平台，最好能够和公司的审批流程、管理平台等集成，而开源工具在这方面的扩展性一般不强。

3. 控制成本： 企业需要控制压测平台的维护成本，对于规模大的公司，自研优于使用开源。虽然开源压测工具由社区维护，但反馈较慢，自己维护的成本又比较高，不如重写一个或者二次开发。

在这一讲，我会介绍一套由我设计的基于 JMeter 的分布式压测平台实现方案，这套方案也兼顾了开源工具的一些成熟功能，目前已经在阿里本地生活团队使用了超过 4 年，能够支撑近百万压测并发量，累计输出了近 4000 亿次请求量，管理近 600 台压测机，依然没有出现明显瓶颈。这些成绩到底是怎么做到的，我们来一探究竟吧。

架构设计思路

首先，实现一个分布式压测平台，要能解决上面提到的绝大部分问题，需要实现的功能可以细化为以下几个方面：

用例管理： 用户建立测试用例，包含脚本文件、数据文件和插件，平台进行分类管理并持久化。

压测执行： 一键触发测试用例，可指定各种运行参数，可以指定多台压测机分布式执行，可以批量执行多个测试用例，压测过程中能够动态调节压测量。

实时结果（热数据）： 压测过程中，实时展示响应时间、吞吐量、错误率等概要数据。由于这些数据都是在压测时需要高频关注的，我们将其称之为“热数据”。

压测结果（冷数据）： 在压测结束后，展示平均响应时间、平均吞吐量，90/95/99 线等更详尽的数据。这部分数据主要是供压测后的分析工作使用，不需要实时获取，因此被称之为“冷数据”。

压测机管理： 平台能够与压测机进行交互，调度压测机完成压测执行工作。

安全保障： 平台应具备一定的监控机制，对压测过程中的一些异常情况进行干预。

我们建设分布式压测平台的理念是“取其精华去其糟粕”，尽可能复用已有开源工具的成熟功能，因为这部分功能相对稳定，不需要重复造轮子；对开源工具不成熟的功能应当规避，在压测平台中进行实现；对开源工具不具备的功能，则完全在压测平台中实现。

下图是分布式压测平台的顶层设计图，它是典型的 Java Web 项目，平台本身不执行测试只做调度，避免成为施压的瓶颈，后台均使用 JMeter 执行测试。平台会对挂载的压测机进行心跳检测，确保压测机是可用的。用例和数据文件可以存储在服务器本地，或者采用MinIO进行高可用的文件对象存储。压测期间产生的冷数据持久化至数据库，热数据持久化至时序数据库（InfluxDB）并定期清理。平台允许挂载外部监控模块，对压测过程进行干预。

这里，你需要注意，在使用 JMeter 进行压测时，如果并发量比较大，单机的资源配置可能无法支撑，这时需要联合多机进行分布式压测，然而 JMeter 自身的分布式压测功能是有一定缺陷的：

JMeter 的分布式执行和单机执行方式的差异较大，需要做很多额外配置，由此产生大量运维工作。

JMeter 分布式执行模式，master 节点通常不参与压测，而是收集 slave 节点的压测信息，这会造成一定程度上的资源浪费。

JMeter 分布式执行模式，slave 节点会将每个请求打点都实时回传给 master 节点，造成大量的带宽消耗。

这时候怎么办呢？上面我提到过，对开源工具不成熟的功能应当规避，因此，我们可以在每台压测机中植入一个 Agent，它能够与压测平台服务器通过长连接的方式建立通信，这样平台就可以直接对压测机进行调度。这种方案相当于我们在平台层重新实现了 JMeter 的分布式调度功能，两者的实现对比见下表。

这个方案也一并实现了压测过程中的冷热数据分离，冷数据在测试完成后才会传输，如果不需要压测端数据，甚至可以配置不存储冷数据，因此该方案的扩展性是非常友好的，理论上支持的 TPS 没有上限。

主要功能实现方案和原理

说完了需要实现的功能和架构设计思路，相信你对我们要实现的压测平台已经有了初步认识，下面我就从平台的 6 大功能实现方案和原理进行展开，沿着基础功能到高阶功能的顺序进行讲解，展开的粒度大约控制在让你稍加思考就能上手实现的程度，你可以选择擅长的编程语言及前后端框架去实现具体功能。

如果你希望能更直观地看到整个平台的功能全貌，我也制作了一个预览视频，在这一讲的最后我会提供给你。

1. 如何实现测试状态流转

测试状态流转是压测平台管理测试工作的核心，所以我放在第一个讲。和人类的生老病死一样，每一轮成功的测试工作会经历一个完整的生命周期，可以描绘成下面这条主线。

其中，我将配置、触发、运行、收集、清理定义为五大内部行为（平台内部逻辑管控），这五大内部行为都会改变测试的状态；同时，我们还会允许一些外部行为去干预测试工作，比如在运行过程中需要人为停止测试，外挂的监控组件判断异常后主动熔断测试等，这些外部行为也会改变测试的状态。你可以通过下面的表格，理解各个行为对测试状态的影响，以及对应的后续行为是什么。

将这些状态变换的触发条件和转换过程绘制成状态流转图，就是下面这个样子。

说白了，压测平台对测试状态的管理，就是通过代码实现出这张图的所有逻辑。其中的关键是，无论测试流程出现何种分支（正常或异常），最后都要能形成闭环（即起点一定最终要达到终点），这对系统的健壮性非常重要，因为如果测试状态卡在任何中间状态，本质都是平台对其失去了管理，测试的信息都丢失了。

2. 如何获取和展示实时数据（热数据）

上面我讲到了实现测试状态流转的整体思路，其中在“运行中”状态下，我们需要获取压测时的实时数据，以便实时观察压测情况。

我们这套分布式压测平台实现方案，是基于 JMeter 的，但遗憾的是，JMeter 本身并不提供图形化的实时数据展示功能，以往我们只能通过输出日志看到一些粗略的信息。在压测平台中，我们就对实时数据展示功能进行了实现，主要原理是通过 JMeter 的 Backend Listener 将测试结果实时发往 InfluxDB，同时平台向 InfluxDB 轮询查询数据，得到实时曲线并展示给用户。

当然，你也可以直接基于流行的开源数据可视化系统Grafana进行数据展示。

另外，补充一句，我在 2017 年为 JMeter 贡献了基于 UDP 协议与 InfluxDB 传输数据的 Backend Listener，比起当时官方支持的 HTTP 协议，传输效率更高，被列为 JMeter 3.3 的核心改进项，如果你也想使用这个 UDP 协议的 Backend Listener 的话，请确保 JMeter 版本 ≥ 3.3，欢迎你尝试。

3. 如何处理结果数据（冷数据）

实时数据要讲究快，能实时观察压测结果，比如，我们只要看到响应时间和错误率就可以基本了解压测当时的状态了。但对结果数据要更讲究全，目的是在压测结束后对压测结果做详细分析时，能精细到看到每个报错信息是什么。

由于压测平台自己实现了分布式压测模式，因此在拿到每台压测机的结果文件后，也需要自行对这些结果文件的内容进行合并和解析，并持久化记录下来。这里所谓的结果文件其实就是压测生成的 JTL 文件，我们先来看下 JTL 文件的一个片段。

timeStamp,elapsed,label,responseCode,responseMessage,threadName,dataType,success,failureMessage,bytes,sentBytes,grpThreads,allThreads,URL,Latency,IdleTime,Connect
1617696530005,81,HTTP请求,200,OK,线程组 1-1,text,true,,2497,118,1,1,http://www.baidu.com/,78,0,43
1617696530088,32,HTTP请求,200,OK,线程组 1-1,text,true,,2497,118,1,1,http://www.baidu.com/,32,0,0
1617696530120,32,HTTP请求,200,OK,线程组 1-1,text,true,,2497,118,1,1,http://www.baidu.com/,32,0,0
1617696530152,32,HTTP请求,200,OK,线程组 1-1,text,true,,2497,118,1,1,http://www.baidu.com/,32,0,0
1617696530184,31,HTTP请求,200,OK,线程组 1-1,text,true,,2497,118,1,1,http://www.baidu.com/,31,0,0
1617696530216,31,HTTP请求,200,OK,线程组 1-1,text,true,,2497,118,1,1,http://www.baidu.com/,31,0,0
1617696530248,31,HTTP请求,200,OK,线程组 1-1,text,true,,2497,118,1,1,http://www.baidu.com/,31,0,0
1617696530280,31,HTTP请求,200,OK,线程组 1-1,text,true,,2497,118,1,1,http://www.baidu.com/,31,0,0
1617696530312,31,HTTP请求,200,OK,线程组 1-1,text,true,,2497,118,1,1,http://www.baidu.com/,31,0,0
1617696530343,32,HTTP请求,200,OK,线程组 1-1,text,true,,2497,118,1,1,http://www.baidu.com/,31,0,0
1617696530375,32,HTTP请求,200,OK,线程组 1-1,text,true,,2497,118,1,1,http://www.baidu.com/,32,0,0

JTL 文件的特点很鲜明，可以看到，相对应每一行的单条结果数据的大小非常小（大约只有 100 多个字节），但总量很大（上面的例子只是片段，实际可能有几万到几百万条）。如果我们只是简单的将所有数据存储起来，将会占用大量的存储空间，因此结果数据需要做预聚合再存入。

预聚合是怎么做的呢？下面代码展示了聚合存储的数据结构，核心是以 label（JTL 中的 label）作大分类，维度（errorMsg、errorCode 等）作小分类，以时间作为聚合标准，interval 固定，固定聚合为 60 个点，从而保证存储大小不会过大。

{
    "label": "upload", -- 大分类，比如这条记录只针对upload label
    "totalCount": 428,
    "totalErrorCount": 12,
    "errorMsg": [ -- 维度字段，作小分类
        {
            "msg": "io.exception",
            "count": 12
        },... -- 固定聚合成60个点
    ],
    "errorCode": [
        {
            "code": "404",
            "count": 12
        },...
    ],
    "count": [
        12, …, 15
    ],
    "error": [
        12, …, 15
    ],
    "rt": [
        12, …, 15
    ],
    "minRt": [
        12, …, 15
    ],
    "maxRt": [
        12, …, 15
    ]
}

结果数据的这种存储方式，既保证了不会占用太大的存储空间，又能够汇总出丰富全面的数据。

4. 如何进行吞吐量限制与动态调节

测试状态流转、冷热数据的获取和处理是压测平台最基本的功能，下面我来介绍一些更高阶的功能，先从吞吐量控制与动态调节开始吧。在压测时，“控量”是非常重要的，JMeter 是根据线程数大小来控制压力强弱的，但我们制定的压测目标中的指标往往是吞吐量（QPS/TPS），这就给测试人员带来了不便之处，必须一边调整线程数，一边观察 QPS/TPS 达到什么量级了。

为了解决这个问题，JMeter 提供了吞吐量控制器的插件，我们可以通过设定吞吐量上限来限制 QPS/TPS，达到控量的效果。

上面的做法能够确保将吞吐量控制在一个固定值上，但这样还远远不够，实际工作中我们希望在每次压测执行时能够随时调节吞吐量，比如，在某个压力下服务容量没有问题，我们希望在不停止压测的情况下，再加一些压力，这样的功能该如何实现呢？

我提供的方案也很简单，依然是基于吞吐量控制器，基本的实现原理是将吞吐量限制值设为占位符（如下图中的 ${__P(throughput, 99999999)}，throughput 就是占位符），利用 JMeter 的 BeanShell 功能，通过执行外部命令的方式，在运行时注入具体值，达到动态调节吞吐量的目的。

上面提到的外部命令具体为：

java -jar <jmeter_path>/lib/bshclient.jar localhost 9000 update.bsh <qps>

其中，update.bsh 文件的内容为：

import org.apache.jmeter.util.JMeterUtils;

getprop(p){ // get a JMeter property
    return JMeterUtils.getPropDefault(p,"");
}

setprop(p,v){ // set a JMeter property
    print("Setting property '"+p+"' to '"+v+"'.");
    JMeterUtils.getJMeterProperties().setProperty(p, v);
}

setprop("throughput", args[0]);

压测平台将上述这些工作统一封装后提供出接口，前端界面只要留出输入框供用户填写吞吐量的参数，就可以方便的使用了。

5. 如何实现配置集功能

我们再来聊一个和压测运行相关的重要功能，称之为“配置集”。这个功能其实当初并不在平台设计的考虑范围内，但随着全链路压测规模的日益壮大，需要同时执行的用例数量越来越多，每次执行时都得一个一个去触发，手忙脚乱，有了这个痛点，引发了我们对配置集功能的探索。

配置集功能的本质是“批量运行多个测试用例”，如下图所示，用户只需提前在配置集中添加需要执行的测试用例，以及每个执行轮次的配置信息，比如线程数、持续时间等。配置集设定完成后，选择某个轮次，就能基于相应的配置一键触发所有测试用例。

从实现的角度来讲，配置集是映射多个用例的数据结构，而刚我们提到的“轮次”的概念，是指对同一个配置集设定多轮不同的配置项，每个配置项还是作用在测试用例上，目的是进一步提高可复用性。简而言之，记住这个公式：“配置集 1：N 测试用例；测试用例 1：N 轮次配置”，即一个配置集对应多个测试用例，一个测试用例对应多个轮次配置。再直观一些，你可以直接通过下面的代码理解这个逻辑。

{
    "_id" : ObjectId("603c7f8f587ca226d257b144"),
    "testPlanName" : "addTestPlan",
    "testPlanUnitList" : [ -- 一个配置集对应多个测试用例
    {
        "testcaseId" : "5fc4dd4ee9d7d7b19d0f5152",
        ……
        "testRoundList" : [ -- 一个测试用例对应多个轮次配置
        {
           "threadCount" : 1,
           "duration" : NumberLong(60),
           "rampUp" : 0,
           "detailLog" : true,
           "realTimeLog" : true,
           "throughput" : 100,
           "name" : "配置1",
           "qpsStep" : 0
       }， ……
       ]
    }
    ],
 ……
}

由于在配置集中同时管理着多个用例的所有信息，因此还可以实现一些高级操作，比如：某个用例先执行一段时间后，其他用例再启动，其本质就是单独先触发一个用例，等待固定时间后再触发其余用例；或是，运行时临时改变其中几个用例的 QPS 上限，其他用例保持不变，其本质就是对单个用例进行吞吐量调节，等等。

6. 监控模块

我已经介绍了很多关于压测运行和压测数据的功能模块，最后我们来学习一下监控模块，它同样也是压测平台非常重要的组成部分，也是几乎所有开源压测工具都缺乏的功能模块。监控模块可以分为两类，分别是内部监控模块和外部监控模块。

内部监控模块主要针对压测平台自身运行过程进行监控和干预，观察压测是否处于正常进行中，如果遇到异常情况，如线程异常终止、没有持续的测试数据流出、磁盘打满等，则立刻终止测试，反馈异常结果并记录日志供排查。

内部监控模块实现起来也很简单，在触发压测后，我们也同时启动一个任务对使用的压测机进行监控，监控的内容可以是磁盘使用量、压测数据流的状态等等，如果识别到异常，则触发相应的异常逻辑即可。

第二类监控为外部监控模块，主要用来对接外部监控系统，这个模块很重要，除了方便观察系统指标以外，其最关键的作用是能够反向干预压测工作，协助用户规避风险，尤其是针对线上压测这类高风险工作。比如，当监控到服务端的错误率达到一定阈值时，立刻停止当次测试。

外部监控模块的实现，需要与外部监控系统提供的接口对接，如果有些监控系统自带报警功能，那么就更好了，压测平台在获取到报警信息后可以立刻停止测试。

以对接 Grafana 监控为例，最简单的方式莫过于采用 Webhook 的方式，我们只需要指定一个接口并配置到 Grafana 中，在监控告警事件发生时，Grafana 就会回调这个接口，触发相应的停止测试的动作。当然，也可以触发其他动作，这取决于接口的逻辑。在Grafana 使用手册中提供了详细的对接案例，你可以进一步阅读，加深理解。

总结

工欲善其事必先利其器，压测平台作为容量保障的工具枢纽，其地位不言而喻。一个扩展性好、设计健壮、体验优秀的压测平台，能够对容量保障工作带来巨大帮助。

这一讲中，我介绍了一个基于 JMeter 的分布式压测平台的实现方案，它解决了企业对于压测工具的三个重要诉求：平台化、标准化和控制成本。如果你的团队已经习惯于使用流行的 JMeter 进行压测，那么上手这个平台几乎是没有什么成本的，因为它 100% 兼容 JMeter。

平台的主要功能可以分为几大部分去看，首先是测试状态，我们明确了测试行为和测试状态之间的流转关系，确保无论测试过程是正常执行还是异常终止，整个流程都能闭环完结。

其次是测试数据，我们将数据分为热数据和冷数据，分别对应实时数据和结果数据，并采用了完全不同的思路去实现，确保各自的特点能够充分发挥。

接下来，我们聊到了测试运行过程中的两个重要功能，吞吐量动态调节和配置集。其中，吞吐量动态调节利用了 JMeter BeanShell 的动态传参功能，我们只需要暴露吞吐量作为参数即可；而配置集则是平台对多测试用例运行的一种实现，能够方便我们批量执行大量测试用例。

最后，监控模块是压测工作安全性的重要保证，内部监控模块对压测本身的状态进行检查，如有异常及时反馈；外部监控模块则是对接外部监控系统，在服务出现异常时主动终止测试。

通过今天的学习，希望能够让你了解分布式压测平台实现的重点和难点，也期待你能够创造更多方便友好的功能，为容量保障工作的降本提效贡献一份力。

课后讨论

这里，我给出一个分布式压测平台的预览视频，包含这一讲提到的所有功能，它可以作为你的实现蓝本。如果观看了视频后，你有了什么新的思路或启发，欢迎分享给我，我们共同探讨。

Sorry, your browser doesn't support embedded videos.



00:00 / 00:00



08 | 容量预测（上）：第三只眼，通过AI预测服务容量瓶颈

你好，我是吴骏龙。在这一讲和下一讲中，我们来扮演一回预言家，看看容量预测是怎么做的。

我们先来看一个问题，也许在工作中你也会有这样的疑问：

“双 11 期间，网站需要举办大促活动，我们目前的服务器能不能承载这些大促活动所产生的访问量？如果不能，用多少服务器可以支撑，又不至于太浪费呢？”

回答这个问题，其实就是容量规划的过程，其中既体现了预测的思想，也体现了对成本的考虑。很显然，容量预测是容量规划中最重要的环节，没有之一，容量预测若不准确，容量规划的价值也会大打折扣。

明确了容量预测的重要性，那么该怎么做呢？很不幸的告诉你，在很长一段时间，即便是在阿里本地生活这样体量的公司，技术人员进行容量预测也靠的是“直觉”，不要觉得好笑，你或许也经历过这样的对话：

A：马上要双 11 了，服务器撑得住吗？

B：要搞大促了，肯定要扩容。

A：扩多少？

B：依我的经验，扩 1000 核吧。

A：要那么多吗？

B：呃…… 那 500 核吧。

这种将容量预测完全建立在个人经验上的做法，在大部分情况下都是没有什么道理的，在我的容量保障生涯中，就没见过拍脑袋能拍的准的，最后往往都是硬生生的把容量规划变成了一门“玄学”，而容量风险依然存在。

由此可见，我们需要的是一种科学的容量预测方式，它不能依赖于人的经验，而且必须足够准确。坦白说，这是非常困难的，因为影响服务容量的因素实在是太多了，我花了将近 1 年的时间带领团队做了大量的研究和探索，最终找到了一种通过 AI 手段进行容量预测的实践方案，并已经在实际工作中落地，现在我就把这项实践的核心技术分享给你，希望能给你带来帮助。

用 AI 进行容量预测的过程

首先，我们还是来构建一个场景，假设你是某个业务系统的技术负责人，这个业务系统在生产环境每时每刻的流量、CPU 利用率等数据你都是知道的，那么你是不是能通过对这些已有的数据进行分析，总结出某种规律，来预测当系统流量达到一个从未有过的量级时，CPU 利用率会是多少呢？

如果你暂时没有答案也没关系，我们来做一个小测验，下面有 8 个等式，请你通过分析这 8 个等式的规律，解答“8 1 3 = ？”。

如果你的答案是“8x1-3=5”，那么恭喜你，你已经成功完成了对这个问题的解答过程。用 AI 进行容量预测的本质，和这个问题的解答是类似的，只不过我们将等式前面的 3 个数字变成了影响容量的特征，而等式后面的 1 个数字则对应服务容量的结果。通过寻找规律来预测一个新的等式的结果，相当于预测服务在更高流量下的容量表现如何。

了解了原理之后，我们赶紧乘热打铁，看一下基于 AI 进行容量预测的三大步骤：

1. 特征选取： 选取会对服务容量产生影响的特征作为输入，即预测的条件；再选取一个能表示服务容量结果的特征作为输出，即预测的结果。

2. 建立模型： 也就是寻找某种规律，能够完整地描述已有的输入和输出。

3. 准确度评价： 检查结果是否正确，如果不正确，调整特征或模型，直到结果正确为止（术语叫“收敛”）。

这些步骤的关系可以用下面这张图来表示，建立出最终模型后，我们就可以进行预测工作了，输入特征值（如服务流量），得到容量结果（如 CPU 利用率）。

下面，我开始具体展开每个步骤的技术细节。

1. 特征选取

特征选取是容量预测的第一步，甚至可以说是最重要的部分，特征选择得不合适，会极大影响模型的准确性，甚至导致模型失效。

对于互联网服务，我认为，至少有三类特征会影响服务的容量：

服务的资源配置： 如 CPU 核数、内存大小、磁盘大小等。

服务的业务量： 如 TPS、并发量等。

服务的上下游依赖情况： 如依赖服务的 TPS 等。

我最终选择了将服务的 TPS，以及它所依赖的所有服务的 TPS 作为输入特征，将 CPU 利用率作为输出结果。作出这个选择的原因是，互联网服务的容量风险基本上都是随着流量增长而产生的，而体现流量增长最直观的指标就是 TPS；相应的，服务的 CPU 利用率是服务容量是否充足的一个重要表现，因此我更倾向于将 TPS 作为“因”，将 CPU 利用率作为“果”。

可能你还会有疑问，上面提到的影响服务容量的特征那么多，只考虑 TPS 会不会太片面？同样的，判断服务容量是否充足的特征也不止是 CPU 利用率，内存使用率和磁盘使用率都是啊，为什么没有考虑它们呢？

我要提醒你注意的是，特征的选取并不是越多越好的，过多的特征将很容易产生“过拟合”的情况，即通过这些特征能够构建一个自认为完美的模型，但它在解决实际问题时的表现又很差劲。用大白话说就是：“想多了，想得太复杂了”。

因此，尽可能选择对容量影响较大的少量特征才是正道。我们做了很多的调研工作，发现服务的绝大多数业务指标最终都会表现在 TPS 上，比如并发数上升，TPS 一般也会上升；再比如响应时间增加，TPS 很可能会降低，等等，因此采用 TPS 作为特征已经能够比较好的囊括其他特征了。

相应的，我们面对的绝大部分服务都是偏计算型的服务，CPU 利用率是评价容量的主要因素，因此考虑 CPU 利用率作为容量结果特征，也是具有普适性的。

到这里，我主要谈到了特征选取的一些基本方法和思考过程，我们应当选取尽可能少的，但具有代表性的特征。其中，我也为你提炼出了 TPS 和 CPU 利用率的这两大特征关系，针对绝大多数计算型的互联网服务都是有效的。在下一讲中，我还会就特征选取的方法进行更深入的探讨，提供一些更高级的策略，欢迎继续学习。

2. 模型建立

选完了特征，下一步就是基于已选取的特征建立合适的模型，这个模型必须具备以下特点：

1. 必须是回归模型，即能够建立输入和输出之间的关系，而且输出值必须是连续值，不能是离散值，因为我们需要输出的 CPU 利用率就是一个连续值。

2. 能够支持“多输入 - 单输出”的映射关系，因为我们需要输入的是服务的 TPS 和依赖服务的 TPS，为多输入；输出的是 CPU 利用率，为单输出。

3. 能够离线计算，生成的模型要能够持久化，不需要每次都重复计算，否则计算量太大。

满足这些条件的常见回归模型有线性回归、多项式回归、神经网络等。我们尝试下来，线性回归和多项式回归在实际应用中表现不佳，原因其实也很容易想明白，TPS 和 CPU 利用率的关系不一定是线性的，也无法用简单的多项式函数表示，这与两者之间的关联度有关，在“容量预测（下）”一讲中，我还会专门探讨下这个问题。

在实际工作中，我们采用了学习能力更强大的神经网络进行建模。如果你不是出身于机器学习相关专业，要深入理解它的原理可能会比较困难（需要有一定的数理基础和高等数学知识），但好在我们身处一个人工智能技术广泛应用的时代，有很多的工具和框架（TensorFlow、PyTorch、Spark MLlib 等）已经帮助我们封装了晦涩的底层理论，使神经网络成为一种可以开箱即用的技术，下面我直接从应用角度介绍一下如何使用神经网络进行建模工作。

下图左边部分是一个典型的神经元，我们将服务自身的 TPS、依赖服务的各 TPS 作为输入，引入神经元，每个输入需要乘以一定的权重 w 后进行求和，再与一个外部的偏置 b（可以认为是一个没有输入的权重）相加，得到最终的总和结果，将这个结果投入一个激活函数进行转换（用来保证结果落在规定的区间内），最终得到我们需要的输出，即服务的 CPU 利用率。

我们将多个这样的神经元组合起来，就得到了下图右边部分的神经网络，包含一层输入层，两层隐藏层和一层输出层。通过不断的样本训练，其实就是在不断地调整各层的权重，最终我们将所有的权重保存下来，就形成了可供预测的模型。

当然，神经网络远远不止上面描述的那样简单，但你暂时不需要了解太多细节，所有的建模过程在 TensorFlow 等工具中都有现成的方法供调用，比如 TensorFlow 的首页例子就是构建了一个简单的神经网络。如果你希望获得一些更偏工程化的例子，可以直接参考这个代码仓库，它提供了大量现成可用的代码供参考，而且几乎是傻瓜式的。

那么，训练出的模型效果到底如何呢？我们可以用一条拟合曲线来可视化观测模型的效果，下图中蓝色的曲线由训练样本构成，橙色的曲线代表训练出的模型，可以看到上半张图的曲线是高度贴合的，拟合较好，而下半张图则拟合不佳。这种可视化的方式非常重要，当我们需要调整模型参数或调整特征时，可以通过观察曲线来判断调整的效果。

总结一下，我们选择神经网络作为建模工具，寻找服务 TPS 及其依赖服务的 TPS 和 CPU 利用率之间的关系，最后得到的模型形式是一系列的权重值。整个过程可以基于流行的机器学习框架去编写，最后通过拟合可视化的方式进行优劣评价。

3. 准确度评价

紧接着上面谈到的内容，拟合可视化给到我们一个直观的视角去评判模型的优劣，但有时候我们也希望能够以更定量的方式去衡量模型的好坏。比如，通过编写自动化脚本来尝试用不同的特征组合进行建模时，需要从中选出准确度最高的特征组合，由于组合的种类非常多，这就很难做到每次都让人来评判模型的准确度，我们需要有一个科学的工具去衡量它。

下面，我介绍一个工程界经常使用的模型准确性评判方法，称为“K 折交叉验证”。如下图所示，K 折交叉验证的步骤可以分为五步：

将原始数据集（包含输入和输出）划分为相等的 K 部分（“折”）；

从划分出的 K 部分中，选取第 1 部分作为测试集，其余作为训练集；

用训练集训练模型，然后用测试集验证模型输出结果，计算模型的准确度；

每次用不同的部分作为测试集，重复步骤 2 和 3 K 次；

将平均准确率作为最终的模型准确度。

K 折交叉验证使用了无重复抽样技术，它的特点是每次迭代过程中，每个样本点只有一次被划入训练集或测试集的机会，因此得到的结论是比较稳定的。其中，对于 K 的取值，有理论证明 K 取 10 的通用效果最好[1]。 因此在实践中你也不妨采用 10 折交叉验证进行尝试。

K 折交叉验证的实现也比较简单，用伪代码可以描述如下：

list[k] = 样本集.split(k); //切分k份
for(int i = 0; i < k; i++) {
    test[] = list[i]; //第i份为测试集
    train[] = remove(list[k], i); //样本集去除第i份为训练集
    模型 = 训练(train[]); //用训练集建立模型
    结果 = 模型(test[]); //用测试集得到结果
    准确度[].add(比较(结果)); //比较结果的准确度，加入集合
}
result = average(准确度[]); //得到准确度的平均值，即所需结论

通过 K 折交叉验证的方法，我们可以对模型优劣进行定量分析，提升模型准确度的评判效率。

Badcase

至此，我们已经完成了基于 AI 模型的容量预测基础技术工作，但任何事物在开始时都不可能尽善尽美，我们建立的模型也是一样，总会有各种各样的问题，这时一定不能放过每一个“Badcase”，应该将这些 Badcase 抽象分析，归纳出通用缺陷并修正，这样才能有效提高模型的健壮性。

下面我们来看几个实践中遇到的真实的 Badcase，以及问题产生的原因。

上图的拟合情况非常糟糕，几乎是完全不拟合。通过排查，我们发现这个服务所依赖的服务 TPS 在某天有异常突增，且幅度很大，而当天的数据又恰好被“学习”进了模型，导致模型失效。

上图的拟合情况尚可，但显然不是最优。排查发现，原始的训练数据有很多毛刺点，对模型来说可以认为是噪点，这些噪点影响了模型的拟合程度。

上图的情况很诡异，随着 QPS 的增加，CPU 利用率始终保持在低位。经排查，发现是数据源的问题，CPU 利用率数据采集出错。

总结一下会发现，这些 Badcase 中都有一个共性，就是数据原因居多，有数据获取出错，也有数据存在噪点的问题。这就给我们带来了一个启示，要重视输入数据的准确性，及时进行数据清洗和数据去噪（去除无效和错误的数据），否则无论模型多么健壮，结果依然会大打折扣。

总结

这一讲，我主要介绍了基于 AI 模型进行容量预测的详细过程，它与人类学习知识和推理规律的过程高度相似，通过识别特征、建立模型和准确度评价这三项工作，来预测未来的服务容量情况。

其中，特征选取是最重要的环节，尽可能选择具有代表性的少量特征，不仅能减轻建模的复杂度，还能有效规避过拟合的情况。我在探索容量预测工作时，大量的时间都花在了选取合适的特征上，最后发现服务 TPS 和依赖服务的 TPS，是最具有代表性的特征，如果你的服务是计算型的，我极力推荐使用这些特征进行建模。

不过，虽然我一直谈到的是计算型服务，但对于 IO 密集型或其他类型服务，思路都是类似的，通过找到输入和输出的关系（也就是模型），对未来容量情况进行预测，无非是输入输出的特征变成了内存利用率、磁盘利用率，等等。

神经网络是我们用来建模的工具，它具有强大的学习能力，也满足容量预测对模型的要求。通过使用开源机器学习工具搭建神经网络，能够有效降低技术门槛，使你可以将注意力更多的放在特征选取和模型调优上，拟合可视化是评价模型优劣的一个广泛采用的手段。

K 折交叉验证是更为强大的模型准确度评价工具，通过切分数据集，每次取出不重复的一部分作为测试集，从而得到模型准确度的定量结果，这在一些辅助自动化模型评优的工作中会非常有用。

最后，我介绍了一些容量预测中的典型 Badcase，并归纳了问题发生最多的地方：数据，提醒你要注重数据清洗和数据去噪，防止对建模造成干扰。

参考文献

[1] Zhang, Y. and Yang, Y., 2015. Cross-validation for selecting a model selection procedure. Journal of Econometrics, 187(1), pp.95-112.

课后讨论

留一个作业给你，还记得上面我们提到过的一个 Badcase 吗？如下图所示，原始的训练数据有很多噪点，影响了模型的拟合程度。请你想一想，用什么方式可以尽可能消除这些噪点？欢迎分享你的思路，或 show 出你的代码。

09 | 容量预测（下）：为不同服务“画像”，提升容量预测准确性

你好，我是吴骏龙。

在容量预测的上篇中，我介绍了容量预测的基本过程和方法，在课后讨论环节也出了一道题目供你思考，你都学会了吗？掌握了这些基础知识后，在这一讲我们继续讨论容量预测中的一些进阶问题，这些问题都是我在实践中摸爬滚打提炼出来的，如果你想在工作中应用容量预测，那么这些问题也是绕不开的。

首先，虽然我们已经建立了理想化的模型，但现实情况是，这个模型可能针对某些服务的预测结果总是不那么准确，而且无论怎么调整模型的参数都收效甚微。这时候，我们应该回过头思考一下，当初选择的特征是否合适？

其次，服务是在不断迭代的，不断有新功能上线，这就意味着服务的容量始终处于变化的过程中，如果容量预测的模型也跟着高频变化，计算量就会非常大，怎么权衡好服务迭代和模型更新之间的关系呢？

最后，即便服务不变，业务场景的变化也会造成服务容量的变化，例如大促活动带来局部几个服务的流量突增，如果我们按照非大促期间业务场景的流量特征去建立模型，对容量进行预测，肯定是不准确的，那该如何应对呢？

别急，上面这三个问题，都是有解决方案的。我们赶紧来看一看这些问题都是如何解决的吧。

相关度分析与服务画像

在上一讲所提到的特征选取过程中，我比较“草率”地将服务的 TPS 和依赖服务的 TPS 作为输入，与 CPU 利用率建立模型。但实际情况下，CPU 利用率可能不仅仅受 TPS 制约，如果我们忽略其他特征的话，有很大可能就会影响模型的准确性。

下图展示了 TPS 和 CPU 利用率的可视化映射关系，通过左图可以看到，两者的关联是非常紧密的，这说明除 TPS 以外，其他因素对 CPU 利用率几乎没有什么影响，这是比较理想的情况；而右图则出现了不紧密的映射关系，甚至一个 TPS 会对应多个 CPU 利用率，很明显还有我们没有考虑到的因素在影响着 CPU 利用率，这会导致模型拟合不佳，那么如何解决这个问题呢？

首先，我们要能够对 TPS 和 CPU 利用率的相关度做定量分析，并根据相关度制定不同的应对策略，这是一切后续工作的基础。

那怎么做相关度的定量分析呢？在统计学中，皮尔逊相关系数（Pearson product-moment correlation coefficient）就是用于度量两个变量 X 和 Y 之间的相关程度的，其值介于 -1 和 1 之间。

我们可以对 TPS 和 CPU 利用率这两个变量计算皮尔逊相关系数，再进行分类：

皮尔逊相关系数的绝对值介于 0.5 - 1 之间，为强相关

皮尔逊相关系数的绝对值介于 0.1 - 0.5 之间，为弱相关

皮尔逊相关系数的绝对值介于 0 - 0.1 之间，为不相关

针对强相关的场景，意味着 CPU 利用率几乎只受 TPS 的影响，这时直接建立 TPS 和 CPU 利用率的模型就可以比较好的拟合出结果了。而不相关的场景，一般是一些批处理服务或任务型的服务，这些服务没有外部流量，可以特殊处理或直接过滤掉。我们重点来看一下弱相关的场景如何处理。

弱相关的场景下，CPU 利用率不仅仅受 TPS 制约，还伴有其他因素。我提供两种思路解决这个问题：第一，找出所有影响 CPU 利用率的特征，对服务进行画像，即针对每个服务选取不同的特征去表示它；第二，建立一个 TPS 映射 CPU 利用率的概率表，选取出现概率最大的 CPU 利用率值作为特征。下面我具体展开这两种思路的做法。

基于第一种服务画像的思路，我们需要考虑更多特征，从中选取对 CPU 利用率影响最大的一个 / 些去建模，或筛去一些无关的特征不去建模，以下是几种常见的方式：

1. 目测法： 将所有特征做归类，如果一个特征能从另一个特征推导出来，我们就叫它多余特征，无需考虑。如下图中，我们假设理想情况下内存、带宽、连接数等指标的变化最终都会反映到服务 TPS 上，那么服务 TPS 就称之为有效特征，其他指标就是多余特征。应用 Owner 是谁对服务容量没有影响，称为无关特征。我们最终只需要考虑有效特征。

2. 过滤法： 去掉取值变化小或不变的特征，这些特征虽然对容量有影响，但影响的程度保持不变，所以可以约简。比如某服务的成功率长期处于 100%，那么“成功率”这个特征就不需要考虑。

3. 包裹法： 每次选择若干特征或者排除若干特征，进行模型评优，直到选择出最佳的子集。这有点像是排列组合，去寻找一个最佳的特征组合，最准确的预测 CPU 利用率。

4. 嵌入法： 先使用某些机器学习的算法和模型进行训练，得到各个特征的权值系数，根据系数从大到小选择特征。类似于过滤法，只不过是通过训练来确定特征的优劣。Spark 中的featureImportance就是一个典型的嵌入法实现。

服务画像的关键点是，对 CPU 利用率影响较大的特征必须都包含在我们的选择范围内，否则只能是巧妇难为无米之炊，但有时候我们确实很难找全所有的特征，这时候可以换第二种思路，通过建立概率表的方式去解决问题。

具体做法是，建立一个 TPS 映射 CPU 利用率的概率表，根据概率表找出某个 TPS 区间内，CPU 利用率出现频率最高的值，供建模使用。下图展示了一个概率表的实例，通过左下角的图可以看到，TPS 处于某水位时 CPU 利用率的出现频率分布有多个极大值，但肯定只会有一个最大值，这就是我们要找的值；通过右边的表格能够更直观的看到，标注为红色的行就是对应 TPS 下的 CPU 利用率出现次数最多的值，在建立模型时只需要考虑这几行的数据即可。

概率表方式背后的思想是，出现频次最高的数据从概率角度往往是更可靠的，也最能够代表实际情况。

服务画像和概率表的方式各有利弊，当我们能够寻找到所有准确的特征时，服务画像的准确性是更高的；反之，可以通过概率表的方式曲线救国。

容量预测迭代与校准

解决了容量预测准确性的问题，我们进入下一个问题，前面谈到过，互联网服务是不断迭代向前的，这也就意味着服务画像是不断变化的，很有可能一次发布就会导致之前的预测结果失效，这就要求容量预测也要进行迭代，及时校准。

容量预测迭代和校准的一个困难点在于，由于服务变更前后的容量并不是递进的关系，因此我们很难采取增量的方式进行学习，大多数情况下还是得重新建模。一种看似比较简单的做法是，在服务发生变更（发布、修改配置、扩缩容等）后，对该服务重新进行一次建模，直接覆盖掉上一次结果。

到这里，你应该能够意识到这种方式有一个很大的弊端，即它没有考虑服务的变更对其他服务容量的影响，仅仅对该服务重新进行建模，没有解决其他服务的容量预测准确性问题。

我们依然顺着朴素的思想演进，那是不是可以在任一服务变更后，就对该服务上下游链路所涉及的所有服务都重新建模一遍呢？这种做法在一定程度上是可行的，前提是我们得依赖链路追踪系统找出服务依赖的网状结构，对于依赖方较多的服务，如下图所示，这个网状结构可能会很复杂，计算量依然很大。

在实践中，我们考虑换一种思路，在某个时间窗口内对所有服务重新建模，而不是一有服务变更就这么做，这个窗口期可以跟随服务发布期以滑动窗口的形式设置，窗口的大小根据容量结果的时效性进行设置。比如说，我们规定每周三为服务发布期，容量时效性为 3 天，可以设置一个跨度为 3 天的滑动窗口，在第 4 天需要再进行一次重新建模，窗口每次向前移动一周。

这套模式在阿里本地生活经过近 1 年的实践，很好的兼顾了服务迭代周期和预测模型更新频率，也没有过多牺牲容量预测的时效性，同时，扩展性比较好，例如服务在每周有两个发布窗口，那就设置两个滑动窗口就可以了。

警惕业务场景变化

上面我谈到了服务迭代对容量预测的影响，但它并不是唯一的影响因素，业务场景的变化也会导致容量预测失真。

考虑容量风险会随流量增高而放大，在进行容量预测时，我们一般会使用高峰期的数据进行建模，主要针对的也是高峰期的业务场景。这里就引出了一个问题，如果在未来某段时间内会有一些业务场景发生变化，比如下个月会进行一场大促活动，那么如何预测那时的服务容量呢？我们现在构建的模型，完全有可能不适合未来的场景。

解决这一问题的关键在于，如何获得未来场景的特征数据，以构建出逼近真实情况的模型，来进行预测。 问题的解法就是我之前讲到的全链路压测，通过对特定场景进行压测的方式，获取在高负载的情况下服务的各项指标数据，通过这些数据来构建模型。

当然，全链路压测也不是魔法，不可能做到与真实场景一模一样，为了尽可能减少差异，我们可以通过容量预测和全链路压测双向校准的方式，进行对齐，具体做法相对会复杂一些，请你参阅下图，并集中精力听我讲述。

针对容量预测对全链路压测的校准，需要在常态业务场景下对系统整体容量进行预测，方法是先在业务高峰期选取一个时间点，获取这个时间点下所有服务的 TPS，它们之间的比例关系称之为 “快照”。

接下去，我们可以在保持比例不变的情况下，不断增加每个服务的 TPS 值，并将其输入每个服务的模型进行预测，得到各自的 CPU 利用率，直到某一个关键服务的预测 CPU 利用率超过阈值（如 90%），这时就触及了整体系统能承载的最大容量，我们将所有服务对应的预测 CPU 利用率由高到低排序输出，就能得到一份高危服务的列表，如下表所示。

将这份列表中各服务的预测 CPU 利用率，与全链路压测达到相同 TPS 下的 CPU 利用率进行比对，若差距过大，则检查全链路压测场景是否有失真，这就完成了容量预测校准全链路压测的工作。

在保证常态业务场景的全链路压测模型无误后，加入或修改有变化的业务场景，更新全链路压测脚本后再次压测，压测过程中的数据指标输出给模型重新学习，这样就完成了全链路压测对容量预测的校准。在服务上线后，根据线上的真实数据，可以再进行几次模型的校准工作，就能达到良好的效果了。

总结一下，俗话说“唯一不变的是变化”，业务场景的变化是必然的结果，要迎合这些变化，保证容量预测的准确性，我们应该对预测模型定期进行校准。全链路压测是一个不错的数据校准的输入源，尤其针对未来发生的业务场景，可能还是唯一的数据源；同样的，容量预测的结果也可以反馈给全链路压测，检验压测模型的准确性，达到双向校准的效果。

总结

今天，我和你讨论了三个典型的容量预测中可能会遇到的高阶问题，针对每个问题，我都给出了不少实践方案，这些方案是经过血与火洗礼的，经过了成百上千个各式各样的服务的验证，不断改进和优化后才呈现出现在的效果，希望它们能帮助你少走一些弯路。

我首先给出了“皮尔逊相关系数”这个工具，对服务 TPS 和 CPU 利用率之间的相关度进行了定量分析，根据相关度的强弱，分别采取不同策略。其中，重点讲到了在两者弱相关时的应对策略，如果能够穷举出尽可能多的相关特征，可以通过特征选取的方式对服务进行画像，提升预测准确率；如果特征非常难找，那么可以依靠概率表的方式曲线救国。

随着服务不断迭代，容量也在不断变化，我与你分析的第二个问题，就是如何平衡好服务迭代和容量预测频率的关系。根据服务发布窗口（或其他变更时间点）建立滑动窗口机制，既保证了在服务变更后能够尽快地更新模型，又不至于带来大量的计算量，是一个不错的实践方式。

业务场景变化也会导致容量变化，针对这个问题，我结合之前提到的全链路压测工作，通过建立全链路压测和容量预测双向校准的机制，提前对变化的业务场景进行预测，识别容量风险。

到这里，容量预测的所有内容就讲完了，纸上得来终觉浅，希望你可以多多实践，遇到困难时可以再回顾一下这两讲的内容，相信你会有更多收获。

课后讨论

在“业务场景变化”这部分的讲解中，我提到了系统整体容量预测的过程，在建立快照后，保持比例不变并不断增加每个服务的 TPS 值输入模型进行预测，直到其中有服务的 CPU 利用率达到瓶颈，就认为是系统整体容量的瓶颈点。

这个过程可以理解为不断向上试探的过程，不过如果增幅太大，可能会出现同时有很多服务的 CPU 利用率预测结果超过阈值，这时对应的系统整体容量已经远远超过了瓶颈点；而增幅太小的话，需要预测的轮次又太多，计算量大且耗时长。请你想一想，有没有更好的策略能快速逼近结果？欢迎与我分享你的思路。

10 | 浅谈排队论：数学之美，通过建模计算容量

你好，我是吴骏龙。

我已经与你分享了不少容量保障实践中的干货，下面我们换换口味，来看看学术界对于容量保障有哪些有意思的研究方法，今天我想给你讲一讲排队论的一些基本概念以及在容量保障中的应用场景。

坦白说，在短短一讲中说明白排队论，是一件极具挑战的事情，高等院校往往需要一个学期讲授排队论，怎么也有 30 多个学时，而且学习门槛很高，需要具备很强的数学功底。更要命的是，市面上几乎所有的排队论学习资料面向的都是制造系统，或是一些排队服务场景，比如银行柜台服务、超市收银台之类的场景，导致很多想学习排队论的计算机从业人员都有无从下手的感觉。

其实，排队场景和互联网系统服务是有相似之处的，只不过后者是流量在排队，软件系统在服务罢了，排队论完全可以指导我们解决一些互联网场景下的实际问题。 今天这一讲我会全程从互联网视角出发，从排队论的基础知识、应用策略讲到它在容量保障中的应用。如果你学习了这一讲后，对排队论有了更浓厚的兴趣，我在最后也提供了一些参考资料，你可以进一步学习，加深理解，开阔眼界。

我们开始吧。

排队论的基础知识

我们先简单了解一下排队论的发展历史，排队论本质上是运筹学的一个研究方向，早在 1909 年就已有研究成果，当时被称为“话务理论”，解决了自动电话的设计问题[1]。随着研究范围的扩展，排队论逐渐演变成为专门研究带有随机因素产生拥挤现象的优化理论，是有关于服务设施与被服务者构成的排队服务系统的理论。

用更通俗易懂的话来说，我们每天都会遇到各种各样的排队现象，去超市买东西要排队，去银行取钱要排队等等。在很多情况下，排队都会带来负面影响，急诊室医生繁忙导致患者无法得到及时治疗，机场航班起飞时排队导致航程延误，都是活生生的例子。

排队论说白了，就是用数学方法来模拟这些排队场景，并协助我们做出优化的理论，比如针对上面的例子，排队论能够帮助我们解答，配备多少医生可以满足所有患者的治疗需求，怎样调度跑道能够使绝大多数飞机准时起飞。

下面，我们来看一个最简单的排队系统模型，如下图所示，它由服务机构、服务对象和队列组成，你可以把服务对象当作是用户请求，将服务机构想象为互联网服务，队列可以认为是请求来不及处理而处于等待状态（延迟），那么这个排队系统就可以类比为互联网系统提供服务的形态。

在整个排队系统中，需要关注几个要点：

1. 输入过程： 用户访问按照怎样的规律到达。比如用户访问时间的概率分布，在互联网场景下，我们一般认为各个用户的访问请求是独立的，且遵从同一概率分布。

2. 排队规则： 用户请求在系统中以什么形式排队等待处理，队列是单队列还是多队列，并行还是串行，容量是有界还是无界的等等，这会衍生出不同的排队模型。

3. 服务规则： 服务节点的数量、服务协议、处理请求的顺序，等等。

我们暂时先了解这些基础知识，下面我会介绍如何利用排队论进行建模，帮助你更好的将排队论应用到实际场景中。

排队论的应用策略：排队模型与公式

这部分内容请你重点关注，因为这是我花了大量时间将排队论在互联网领域的应用策略抽象到最精简的程度，甚至你都不需要具备数理分析基础，下面这 1000 多字就能帮助你掌握排队论应用的方法论。

我提供的应用策略非常简单，分两步走：首先，选择合适的排队系统模型；其次，利用模型中的各种公式计算出你要的容量结论。

先说排队模型，排队系统有很多模型，名称也是让人眼花缭乱，什么 M/M/s，M/M/s/s，M/G/1 等等，教你一个记忆的窍门，记住这个格式 A/B/n/S/Z 即可，具体的含义为：A - 请求到达的规律；B - 服务时间分布；n - 服务窗口数目；S - 系统容量限制；Z - 服务规则。

好像还是挺复杂的，那么我们再简化一下，既然排队论是用来预测系统容量的，那么可以先假定系统容量充足，即 S -> ∞；然后，我们默认绝大多数请求都是按顺序响应的，所以 Z 也可以定死就是先来先服务的规则（FCFS，First Come First Service)）。这样，我们讨论的排队系统模型可以简化为只考虑 A/B/n，这下是不是容易记了？

下面，我具体介绍在互联网场景中较为典型的排队系统模型：M/M/s 模型，以及其衍生的 M/M/1 模型。

M/M/s 排队模型如下图所示，其中，M 代表无记忆性分布，典型的有几何分布和指数分布，无记忆性指的是后面事件发生的概率与前面事件是否发生无关，比如我将要访问一个页面，这与你之前访问过这个页面无关，我们默认所有访问请求都是符合这一特点的。s 指的是 s 个服务器共享一个公用到达作业池，说大白话，就是 s 个服务节点都从一个队列中获取请求去处理，我们假定这个队列是无限的，请求是先来先服务的。

想象一下，如果你有一个集群对外提供某种服务，是不是挺符合 M/M/s 模型的？如果集群中只有一个节点，那么 M/M/s 模型就退化为 M/M/1 模型。

了解了 M/M/s 模型，接下去我们来看 M/M/s 模型的三大基本公式，分别是：系统利用率公式，资源需求公式和平均等待时间公式。

系统利用率公式 ρ = λ / sμ： 其中λ指的是到达率，每秒到达的请求数，也可以认为是流量。μ为服务率，也就是每秒能处理的请求数，sμ就是系统总共能处理的请求数。所以最后得到的系统利用率ρ，转换为互联网术语，其实就是指系统负载。

资源需求公式 R = λ / μ： 这个公式比较好理解了，到达请求数λ除以每秒能处理的请求数μ，就得到了资源的需求量 R，所以 R 也被称之为维持系统稳定的最小预期服务器数量。

平均等待时间公式 E[T] = 1 / (sμ - λ)： 一般也就是指平均响应时间。

上述这些公式的推导，还是需要具备一定理论基础的，不过我们不是搞学术的也不必深究，理解这些公式中各个参数的含义，在解决实际问题时能够灵活应用，就可以了。记得我给出的两步走策略：选取合适的模型，使用模型中的公式进行计算。

排队论在容量保障的应用

到这里，武器都已经交给你了，我们一起上战场操练一下吧。我会分享两个典型案例，分别是：设定负载水位风险阈值，以及排队论在容量规划中的应用。

1. 设定合理的 CPU 利用率水位预警阈值

我们时常会遇到这样的问题，如何评判一个服务的负载究竟到什么水位是有风险的？假设就以 CPU 利用率为例，这个问题我问过很多人，得到的回答颇为玄学，保守派认为 CPU 利用率达到 70% 就应该扩容了，激进派则认为 CPU 利用率达到 90% 还可以观察观察。有没有一种科学的方法能回答这个问题呢？排队论就可以解答。

上面刚学过的策略在这里可以应用起来了，第一步是选取合适的模型，为了简化问题，这里我们可以只考虑一台服务器的情况，使用 M/M/1 模型进行推算。

第二步，使用模型中的公式进行计算。首先，根据系统利用率公式ρ = λ / sμ，得到在 s=1 时的服务负载为ρ = λ / μ。

我们再使用平均响应时间公式 E[T] = 1 / (sμ - λ)，得到在 s=1 时请求的平均响应时间 E[T] = 1 / (μ - λ)，从公式ρ = λ / μ，我们可以得到λ = ρμ，代入后可以推导出 E[T] = 1 / μ(1 - ρ)，这表明了请求的平均响应时间 E[T]是与 1 / (1 - ρ) 成正比的，我们将 1 / (1 - ρ) 绘制成曲线，如下图所示。

图中横轴为 CPU 利用率，纵轴为请求的平均响应时间。你可以很明显的观察到，曲线在横轴值为 0.8 左右出现拐点，这就意味着 CPU 利用率超过 80% 后，平均响应时间会急剧上升，因此对于符合 M/M/1 模型的计算型服务，将 CPU 利用率水位风险阈值设定为 80% 是比较合理的。

当然，实际情况可能会复杂一些，比如有些服务可能是部署在容器上的，如果容器设置了超卖策略（某个容器实例的 CPU 配额用满后，可以在一定限度内抢占其他实例的 CPU 额度），那么这个阈值可以根据实际超卖比例适当提高一些，不必太教条。

2. 利用排队论进行容量规划

第二个想与你分享的案例是关于排队论在容量规划中的应用，这也是排队论的重要用武之地，我们来看一下具体的问题。这个问题改编自《计算机系统的性能建模与设计：排队论实战》[2]，我做了一定的优化和扩充，如果你对平方根配置规则中的公式推导感兴趣，不妨参阅该书第 15 章内容。

假设一个服务的平均流量为λ，它平均每秒能处理μ个请求，我们最多能够接受 20% 的请求处于排队状态，请问需要多少台服务器能够达到这个目标？

针对这个问题，还是相同的套路，先选取合适的模型。既然问题是“需要多少台服务器”，那么模型肯定得选取 M/M/s，其中 s 就是我们要计算的值。

第二步，选取合适的公式进行推导。这里我要介绍给你一个重要的定理，称之为“平方根配置规则”，内容是这样的。

给定一个 M/M/s 模型，资源需求公式 R = λ / μ，令 k 表示确保“请求排队概率小于α”所需的最少服务器数，则有 k≈R+c√R，其中 c 是方程的解 cΦ(c)/φ(c)=(1-α)/α，Φ(c) 表示标准正态的累积分布函数，φ(c) 表示它的概率密度函数。

我猜你可能要抓狂了，每个字我都认识，怎么合起来就看不懂呢…… 其实平方根配置规则是可以按照上面提到的三大基本公式推导出来的，只不过推导过程非常之复杂，这里我主要对两个关键点做一下解读，帮助你理解并能够投入实际使用。

第一个关键点是 k≈R+c√R 这个公式，你可能会有疑惑，既然 R 是到达请求数λ除以每秒能处理的请求数μ，那么使用 R 台服务器不就可以及时处理每个到达的情求，确保请求都不排队了吗？为什么还要加上个 c√R？

如果你有这样的疑问，那么说明你对 M/M/s 模型还没有理解透彻，可以回顾一下 M 是什么意思，它代表了请求到达时间是服从无记忆性分布的，我们不用管具体是哪种分布，它至少表明了请求到达时间不是均匀的，而是按照一定概率变化的。所以很显然，即便你有再多的服务器，请求依然有一定概率会排队，只不过服务器越多，排队的概率就越低而已，这个概率就体现在 c√R 中。

第二个关键点挺有意思的，我们发现 c 的取值只和α有关，而与 R 无关，这也就意味着只要确定了α，就能算出 c（尽管还是很难算，哈哈），下面我根据定理中的公式预先计算了一些值出来，你直接查表就行。

在我们最开始的问题中，最多能够接受 20% 的请求处于排队状态，即α=0.2，那么 c 的值差不多就是 1，于是得出 k≈R+√R，这就是我们想要的结论。

总结

排队论是一门非常强大的科学理论，具有悠久的历史，虽然互联网服务的复杂性远远超过其他排队场景，导致排队论在工程上的应用不太普遍，但我依然认为，排队论可以在一些特定的互联网问题上指导我们的工作，而且这种指导非常重要。

排队论不像全链路压测，可能会对生产环境带来一定风险，也不像容量预测，需要花费时间建模并调优，排队论为我们提供了一种数学武器，并且已经总结好了大量现成的模型和公式，我们要做的，就是应用好这些武器，为容量保障出力。

这一讲中，我先介绍了排队论的基础知识，并与互联网概念，包括流量、请求、服务器数量等做了结合，试图让你更快更好地理解排队论的常识。输入过程、排队规则和服务规则是排队系统的三个要点，它们决定了一个排队系统的形式和特点。

接着，我介绍了排队系统的应用策略，可以总结为：选取合适的模型和选取合适的公式进行计算，这两个步骤。我与你探讨了 M/M/s 和 M/M/1 模型，以及三大基本公式，同样的，我也将公式中的一些参数与互联网概念做了对应，帮助你更好的理解。

最后，我给出了两个排队论的应用案例，它们都是容量保障工作中经常会遇到的问题，我们通过排队论进行了科学的推导和解答，也对一些重点定理，如平方根配置规则和疑问做了解释，你都学会了吗？

参考

[1] The Theory of Probabilities and Telephone Conversations [J],K. Erlang,1909.

[2] 莫尔·哈肖尔 - 巴尔特. 计算机系统的性能建模与设计：排队论实战[M]. 方娟，蔡旻，张佳玥译. 机械工业出版社，2020：187-189.

课后讨论

针对我今天谈到的第一个案例：设定 CPU 利用率水位的预警阈值，如果所有服务都是容器部署，且每个容器实例都设置了相同的 CPU 超卖策略，我是不是可以直接将宿主机的 CPU 利用率 80% 作为预警阈值？欢迎与我交流你的想法。

11 | 与时俱进：云原生下的容量保障新趋势

你好，我是吴骏龙。今天，我将与你共同领略在云原生时代下，容量保障有哪些前沿实践与应用。

不知道你之前是否听说过“云原生”这个词，我先来聊一聊云原生的发展历程吧。2013 年春，Docker 技术的正式开源揭开了云计算的序幕，并迅速席卷全球，同年，Pivotal 公司的 Matt Stine 首次提出了云原生（Cloud Native）的概念，至今其实也不到 10 年的时间。

云原生还没有标准的定义，每个人的解读也都各不相同，目前比较权威的定义是由云原生计算基金会（CNCF）给出的，摘要如下。

云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中，构建和运行可弹性扩展的应用。云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式 API。这些技术能够构建容错性好、易于管理和便于观察的松耦合系统。结合可靠的自动化手段，云原生技术使工程师能够轻松地对系统作出频繁和可预测的重大变更。

这个定义中的术语比较多，用我的话来提炼，云原生其实就是云（Cloud）和原生（Native）的结合。Cloud 表示应用服务是部署在云上的，而不是传统的机房；Native 表示服务自始至终都是围绕着云的各项特性所设计的，两者结合起来，目的是最大化的发挥云的价值。

云原生的发展离不开计算机技术的进步，Docker 等容器技术首当其冲，它提供了一种优雅的抽象，让开发所需要的灵活性、开放性和运维所关注的标准化、自动化达成平衡。只要一个容器镜像，在任何操作系统上都可以秒级启动隔离环境，这就彻底解耦了应用服务和运行环境，而且是非常轻量级的，这是应用服务能够大规模上云的重要前提。

在此基础上，近几年盛行的无服务器计算（Serverless）进一步释放了云计算的能力，将弹性伸缩、高可用、安全等需求由基础设施实现。Serverless 将运行环境和配置做了更彻底的抽象，让开发人员可以将更多的精力放在应用程序的设计和优化上，而不是与基础架构相关的配置和管理上。 可以说，Serverless 将云原生推向了一个新的高度。

那么，在云原生逐渐映入我们眼帘的今天，云原生下的容量保障工作又有什么变化和发展趋势呢？我们一起来看看。

云原生容量保障利器：弹性伸缩

随着云原生技术的发展，容量保障工作也出现了不一样的特点，其中最明显的一项就是弹性伸缩，即根据业务需求和流量情况自动调整计算资源，如果弹性伸缩的速度足够快，我们甚至都不需要提前进行容量规划，直接实时扩容就可以了。现在各大云服务厂商都支持按需付费的模式，用户只需要根据应用实际消耗的资源进行付费即可，所以弹性伸缩还能为我们节省成本。

当然，要实现弹性伸缩的能力，基础设施需要有非常强大的资源调度能力，以及对应用各项指标如服务负载、并发量等有非常敏锐的感知能力，能知道在什么时机触发弹性伸缩；同时，还需要具备一定的容量预测能力，能够计算出弹性伸缩的量。

弹性伸缩的另一个好处是，将服务资源管理工作下沉到了基础设施，管控粒度更细，更具备实时性。与之相对的，传统的容量规划工作需要提前一段时间扩容，那么从扩容的时间点到实际产生流量峰值的时间点之间，服务资源是超过实际容量需求的，时间越长，资源浪费越多。

更现实的情况是，业务方一般只管扩容，对于缩容都比较谨慎，正所谓“借钱容易还钱难”，我在阿里本地生活时，全网服务的平均 CPU 利用率只有不到 20%，但推动缩容依然阻力重重，这里的本质问题在于，很多时候应用服务的研发人员自己都不知道需要多少资源是足够的，但又背着很高的稳定性指标，因此往往会选择堆积更多的资源求稳。

这时候弹性伸缩快速高效和底层管理的优势就体现出来了，业务方不需要关心服务资源，弹性伸缩能够帮助你将服务容量始终维持在安全水位，这几乎颠覆了传统的容量保障工作。

用一句话总结，有了云原生技术的加持，容量保障逐渐成为了云基础设施能力的一部分，通过弹性伸缩结合容量预测能力，能够更快速更经济的保障容量安全。

云原生容量保障案例：基于 AWS 的弹性伸缩策略

下面，我来给你举个例子，看看弹性伸缩策略怎么应用在容量保障上的。这里主要介绍 AWS 的一些优秀实践。AWS 是目前能够成功将容量预测和自动伸缩结合，并投入实际生产运行的云服务商之一，非常值得学习。

从云服务的部署、运维到管理，AWS 提供了全生命周期的服务，它把容量预测与弹性伸缩进行结合，然后根据服务资源的情况快速做出容量保障动作，最大化地减少人工成本。同时，如果我们要观察容量伸缩的情况，AWS 也提供可以进行特定配置的控制界面。

具体的操作方法是，我们可以通过配置“伸缩计划”对资源伸缩进行管理，伸缩计划分为“动态伸缩” 和“预测伸缩”两种模式，它们的目的都是在服务高负载时保证足够的计算力，而在服务低负载时释放不必要的计算力，下面我具体讲解一下这两种模式的特点。

动态伸缩模式更讲究实时性，能够根据资源利用率的实际变化情况调整容量，宗旨是确保有足够的容量来维持指定的资源利用率。通俗的讲，它有点类似于空调的控温方式，我们只需要设定一个温度，空调会自动调节最终将室温维持在这个温度。

实际场景中，如果我们以动态伸缩模式，设定某服务的 CPU 利用率目标值为 75%，那么当 CPU 利用率超过 75% 时，就会触发策略，自动为该服务增加实例，降低 CPU 利用率；而 CPU 利用率过低时，又会缩减实例，最终将 CPU 利用率维持在 75% 左右。

预测伸缩模式相对复杂一些，主要原理是通过机器学习的方式，分析 14 天范围内的历史负载数据，预测未来 2 天的负载指标和容量需求，每天预测一次，有点类似于天气预报，通过分析近期的气象数据来预测未来的天气走势。

预测伸缩模式会引入一个所谓的“伸缩规划”动作，在服务达到预测的容量时提前完成扩容操作。和动态伸缩模式类似，预测伸缩模式的目的也是将资源利用率维持在一定的水平线上。

针对预测伸缩模式，同样来看一个实际的例子，假设我们指定该模式下某服务的平均 CPU 利用率目标为 50%，AWS 通过机器学习预测每天上午 8 点会有一个流量尖刺，造成 CPU 利用率陡增，那么“伸缩计划”会创建一个“伸缩规划”动作，确保在这个时间点之前完成扩容，保证在未来出现流量尖刺时，CPU 利用率能维持在 50% 左右。

总结一下，AWS 为云上应用服务提供了丰富的弹性伸缩策略，现在市场上很多云服务商也基本都在借鉴 AWS 的做法，提供“动态伸缩”和“预测伸缩”两种自动弹性伸缩模式。对于可预测的场景，比如本地生活外卖场景，中午和晚上是常规的流量高峰期，其余时段为低峰期，这就比较适合采取预测伸缩模式；而对于一些可能有流量突增的市场营销活动场景，采取动态伸缩模式更为合适。

云原生容量保障展望

随着各大公司对云原生的持续投入和重视，我们有理由相信云原生技术在很长一段时间都会得到大力发展，因此容量保障也应与时俱进，跟上时代进步的节奏。

我在上面已经提到过，云原生对弹性伸缩的支持，极大地改变了容量保障的工作方式，但目前其实弹性伸缩的落地情况并不具备太大的规模，在阿里本地生活，我们充其量也就做到了错峰人工对一部分服务器执行“关机不收费”的操作，和云原生的弹性伸缩方式尚有距离。究其原因，我觉得主要有以下几点：

容量预测尚未发展到非常成熟的阶段，对容量的预估不够精确，无法支持大规模的自动化弹性伸缩。

弹性伸缩的风险较高，特别是缩容操作，有引发线上服务异常的可能性，甚至会直接导致事故的发生。

扩缩容速度不够快，无法满足快速弹性伸缩的要求。

对于这些问题，业内目前主要从两个方向在进行探索，第一是通过技术手段减少应用冷启动时间（重新启动服务进程，到服务完全可用的时间），真正实现实时伸缩；第二是结合传统的容量规划手段，准实时的进行扩缩容，当然，这对容量预测的要求也相应提高了。

减少冷启动时间，甚至能帮助做到毫秒级的自动伸缩，不仅能够大幅提升资源利用率，更是提升了运维效率，当流量高峰来的时候再扩容就好了。不过业界目前还没有真正意义上的无侵入式解决方案，看起来GraalVM是个比较有潜力的方向，Java 官方也推出了更彻底的 AOT（Ahead of Time，预先编译）等措施，都是在往这个方向努力。

而与容量规划相结合的策略，有点类似于我在容量预测的下篇中所提到的服务画像的方式，这个画像建立的越准确，预测的越及时，我们的伸缩动作就可以越逼近实时。这样，即使我们无法做到毫秒级的冷启动，至少也可以保证在较短的空档期内提前完成伸缩动作。

展望云原生时代下的容量保障，我们已经有了很好的实践和探索，相信随着技术的不断革新，应用服务不需要关心容量的梦想终究会得到实现。

总结

云原生时代下，所有的应用服务和基础设施“生在云上”，这意味着从研发模式到运维模式的全方位变革，我们会面对很多前所未有的挑战，但也会给我们带来了不少机遇和进步。对一名容量保障参与者来说，如何顺应云原生时代的技术浪潮，将容量保障工作提升到相应高度，为业务稳定保驾护航，是值得思考和沉淀的。

在这一讲中，我首先介绍了云原生容量保障的一把利器：弹性伸缩，节约成本和业务侵入小是它的两大优点，做到快速的弹性伸缩，甚至能够颠覆传统的容量保障模式。

同时，我也基于 AWS 介绍了目前业界对弹性伸缩的探索和落地经验，AWS 给出了完整的解决方案，支持“动态伸缩”和“预测伸缩”两种自动弹性伸缩模式，能够适配不同业务场景对容量保障的需求。

最后，我对云原生容量保障的发展现状和趋势做了解读，剖析了减少冷启动时间和结合容量规划手段这两种思路，以及行业的一些前沿动态，你也可以结合之前讲到的容量预测的内容，进一步拓展理解。

在云原生技术不断发展的过程中，传统容量保障工作依然重要，让我们一起努力，为容量保驾护航。

课后讨论

如果你正负责一个批处理服务，这个服务没有外部流量，只是周期性地执行某个任务，请问这样的服务适合“动态伸缩”还是“预测伸缩”模式？选择的理由又是什么呢？欢迎与我交流你的想法。

12 | 大促容量保障体系建设：怎样做好大促活动的容量保障工作（上）

你好，我是吴骏龙。

在我的容量保障生涯中，有很多属于自己的记录：完成了上百次全链路压测、发现和改进了近千个容量问题、编写的压测平台总共支撑了近万亿次请求量……这些记录仍在延续。但在这些记录背后，也有我的一把“辛酸泪”：有未能发现容量隐患挨骂的，有把生产环境压挂了背锅的，有几次甚至都想撂担子不干了。但如果你问我什么时候压力最大，那我的答案只有一个，在大促期间做容量保障工作的压力最大。

为什么压力会那么大，因为大促活动和平时的业务场景很不一样，归纳一下，主要有三个特点。

首先，大促活动有一些日常没有的特定场景，比如秒杀活动、特殊的营销活动等，在没有常态数据可供参考的情况下，增加了容量保障的难度。现在一些大厂会倾向于复用之前的活动策略，比如支付宝的五福、红包雨等等，每年都是类似的套路。这除了有营销运营方面的考虑外，也是希望能有历史数据的沉淀，更好地预测用户流量。否则，每次都是新的玩法，容量保障的难度是非常大的。

其次，在大促场景下，一些业务指标会发生悄然的变化，比如转化率就是一个明显的例子，进入活动会场的用户数量较平时大幅增加，但这些新增的用户不一定都会真正下单，这样转化率就会变低，这时容量测试的目标也需要进行相应调整。

最后，活动往往是一次性的，无法返场，没有补救的机会。一旦出现问题，舆论方面可能都会有很大的压力。

这些特点都对容量保障工作提出了极高的要求。我们看一家公司的容量保障做得好不好，就看大促活动时它挂不挂，大促活动是检验容量保障工作的一块试金石，非常考验团队的综合能力。

我接触过不少容量保障工作的参与者，这其中包括性能测试人员、研发人员、运维人员、架构师等等，还有现在比较流行的 SRE（网站可靠性工程师），他们都在各自的岗位上为容量保障事业发光发热并小有成就，但容量保障是一张大图，尤其是大促容量保障更是多角色互动的协作过程，要达到组织一场大促容量保障的能力，需要具备很强的全局视角，这是这些角色暂时缺乏但渴望了解的。

当然，每家公司的业务模式不同，技术体系不同，技术栈不同，我在阿里本地生活牵头双 11 容量保障工作时，平均要对接 10 多个业务方、20 多项活动，横跨集团多个事业部，直接和间接参与到整个保障工作中的有上千人。我觉得单纯列举我经历的案例细节也许并不能直接复用到你所在的公司，可能你能看懂，但还是会有无从下手的感觉。

因此，在这一讲，我会将我在大促容量保障中的多年经验抽象成方法论，总结出一个通用的框架，告诉你大促容量保障应该要做哪些事情，帮你搭一个架子。这样，你可以结合所在公司的特点进行填空，甚至也可以对一部分框架进行取舍或延伸，建设属于你的大促容量保障体系。

明确背景与目标

背景和目标永远是前置项，我在接到一个大促容量保障任务的时候，首先不是去输出技术方案，而是找到产品和业务方，了解大促的业务背景，最好能拿到 PRD（产品需求文档）和具体的业务指标，先了解一下到底要举办哪些活动，活动的策略是什么，希望达到的效果是什么，活动周期和预估访问量是多少，等等。

为什么要知道这些信息呢？回忆一下我在“容量保障的目标”一节中谈到了的核心理念：技术指标联系业务场景。只有明确了业务场景，才能制定合理的技术目标。

然后，我才会去对接相关的业务技术团队，看一下每个活动的技术方案是怎样的，上下游调用链路有什么特点，并以此判断容量保障的侧重点，同时将业务指标转换为技术指标。

总之，先理解业务目标，再切入技术目标。

为了给你一些感性的认识，我以阿里本地生活的某年双 11 活动作为背景，分享一下在目标阶段我都做了些什么。建议你根据自己公司的特点，深入思考。

首先说下大背景，本地生活服务指的是在一个小范围的地区，比如一个城市，或者一个商圈范围内，将一些实体服务（餐饮、娱乐、医药、商超等）从线下搬到线上的服务过程。像饿了么订餐、口碑的到店扫码消费、叮咚买菜的送菜到家，都属于本地生活服务的范畴。这个背景一般公司内部成员都是清楚的。

在高层确认双 11 活动战略后，我首先要去了解双 11 的业务目标。本地生活的双 11 大促活动业务目标主要是拉新和促进 GMV（网站成交总额），其中拉新的目标为新增 A 万用户，GMV 目标为增长 B 万。同时，我还要了解业务场景，即双 11 会举办哪些活动，每个活动的细分业务指标是什么，比如双 11 当天会进行红包雨活动，预计将发放 10 万个面值 5 元的红包，等等。记住，一定要获得量化的业务指标，没有也要让业务方拍个脑袋出来，原因我后面会提到。

最后，针对各类活动场景，我会拆解出容量保障的侧重点，说白了，就是将业务目标转换为容量保障的技术目标，同样举几个例子：

双 11 大促通过设置各种活动会场和页面，以吸引新用户参与，因此导购链路的流量会显著增高。这里的容量保障侧重点就是导购链路的流量增长和转化率。

双 11 大促中，券和权益相关的营销场景会非常多，因为一个人一天不可能吃 10 顿饭，通过券和权益的形式，可以把这些购买力转移至后期消化，带动 GMV 增长。针对这个场景，应侧重考虑券和权益涉及的新业务场景的流量预估，这些场景在日常业务中是没有的，这时候就需要根据之前拿到的业务指标去换算，看到量化业务指标的重要性了吧。

双 11 大促中，为制造一些轰动效应，会组织专场秒杀活动，或是类似“红包雨”这样的秒券活动。这里的侧重点就是高并发场景的容量保障。

到这里，我简单总结一下大促容量保障背景和目标的梳理思路，你可以看这张图。

明确了背景和目标后，我们具体展开大促容量保障的两项重要准备工作：重点链路梳理和服务架构治理。

重点链路梳理

大促活动一定会有一些重点链路，这些链路有的是新场景，有的是关键的老场景。归根结底，容量风险较大的链路，或是出现容量问题影响较大的链路都要涉及。我总结了以下几个侧重点：

1. 同步链路：同步链路指的是，链路上的服务是强依赖的，调用方需要等待被调用方执行完成后才能继续工作。在同步链路中，各服务的容量最容易互相影响，尤其是那些直接暴露给用户的入口接口，往往受制于众多下游接口的牵绊，需要协同看待。

比如，在双 11 活动中直接与买家交互的活动会场和导购页面，就是最靠近流量入口的同步链路。

2. 异步链路：异步链路与同步链路的概念正好相反，链路上的服务没有强依赖关系，调用方不需要等待被调用方执行完成，可以继续执行后续工作，被调用方在另一个线程内执行完成后，通过回调通知调用方。异步链路需要明确异步流量是从哪里过来的，异步流量的量级有多大，在大促期间我方应用是否要做蓄洪，是否会由于消息重投而引起雪崩效应，等等。

比如，双 11 活动券的核销就是一个典型的异步链路，在大促期间，核销量可能会非常大，那么对于消息队列的容量保障就是重点。

3. 旁支业务链路：平时流量不大的“小”业务在大促场景下，流量是否会放大，是否会有叠加。有时候可能一个很不起眼的业务，在特定的场景下被反复调用后，会形成很高的终端延时。对于这类链路，主要是从业务场景的角度出发，细致地层层筛查，分析调用关系后得出结论。

比如，营销券底层服务，在平时流量不高，但双 11 期间大量活动和发券场景都会调用它，就会导致服务压力陡增。

4. 高并发链路：类似秒杀和红包雨这类链路，可能瞬间会产生极高的并发量，这类链路要尽量做到集群物理隔离，分层过滤流量，再通过容量测试去检验效果。

我需要提醒你注意，在这些要点中，高并发链路是尤其容易出问题的，一方面高并发链路往往会涉及新的活动场景，另一方面对高并发链路的保障工作涉及面较广，架构设计、容量治理和监控告警等任何一环出现问题都可能导致失败。下面我以红包雨场景为你展开说明，如何来梳理这个高并发链路。

红包雨活动是双 11 期间的一个典型的高并发场景，在每场红包雨期间，会有 10 秒的时长，在屏幕上落下数个红包，用户点击可以获取红包，红包雨下完后，将获取的红包结算给用户，用户可以在后续下单时使用这些红包。

在梳理这个高并发链路时，首先我们需要识别出高并发的“爆点” 在哪？也就是说，哪个环节，哪个接口，承受了最高的并发量。很显然，同一时间段会有大量用户点击领取红包，计算用户是否中奖的接口和发放红包的接口会承受较大压力，这就是爆点。

识别出爆点后，下面就要从两方面考虑：爆点的逻辑是否合理，能不能减少爆点的容量压力？以及如何设计容量测试方案。

针对爆点逻辑，需要思考是否每次都有必要计算是否中奖，可不可以事先计算好放到缓存中预热，减轻服务和数据库的压力；发放红包的接口是否可以异步发放，避免影响主流程，如果可行，在页面上需要加一些文案提示用户，比如：“您的红包将在 1 小时内发放到您的账户，请注意查收”。

确定了合理的逻辑后，就可以规划容量测试方案了，方案需要尽可能与真实场景保持一致，比如上面提到的，使用缓存预热的方式判断用户是否中奖，那么在容量测试时也需要提前按照相同的策略先把数据加入缓存，再进行测试。

最后，根据容量测试的结论，对红包雨整体链路进行合理的限流，预防容量事故的发生。

总结一下，在大促活动的链路梳理工作中，我给出了四类重要的链路，根据我的经验，做好这四类链路的容量保障，服务容量几乎可以确保万无一失。无论是哪一类链路，梳理工作的思路都是类似的，先识别其中的容量风险（爆点），再看能不能通过优化链路设计减少容量压力，并结合容量测试不断接近目标，最后通过限流等手段合理控制容量风险。

服务架构治理

除了链路梳理以外，对服务底层实现的关注也是很必要的，因为服务架构是影响服务容量的根本，在一个不合理的架构体系上进行容量保障是一件很痛苦的事情。从这个角度来说，架构的治理应该是要落到平时去做好的工作。只不过在大促活动中，受成本和时间约束，我们主要聊聊如何把这一工作进行得更高效些。

这里，我们将服务架构治理分为两部分，一部分是新服务和新功能的架构治理，另一部分是针对存量服务的架构治理。

新服务和新功能的架构治理

对新服务和新功能的架构治理，倾向于通过绘制各种架构图（调用关系图、部署图、时序图，等等）的方式在架构评审时使用，以弱化文字。这样做的好处是，绘制这些图表能够倒逼你深入思考，特别是必须以体系化的思维方式去思考，能够在很大程度上避免低级的设计失误。此外，这些图表我们不规定必须以 UML（统一建模语言）的标准绘制，只要能表达清楚意义即可，重内容，轻形式。

下面我列举一些架构图表案例（为脱敏考虑，部分环节做了简化），以及为你解释一下它们的作用。

调用关系图：调用关系图表示服务之间主要模块的交互关系，以及与外部系统的交互关系。绘制调用关系图的目的是为了完整识别出服务的上下游和外部依赖，这是容量保障工作所需要的基础信息。

如下面的调用关系图所示，这是一个非常典型的电商业务形态的调用关系图，我对服务自身的调用进行了一定的简化，帮助你更清晰的看出跨领域的调用关系。整条链路经过了交易域、商品域、营销域、金融域和物流域五个领域，包含多个服务，获取到这些基础信息后，再进一步分析各个域之间的调用方式，和域内的细分链路，就不会有很大的信息遗漏。

部署图：部署图描述服务部署的物理拓扑结构，在容量评估时我们需要知道服务的部署情况，来判断容量保障的范围。

比如下图为大促营销服务的部署图，可以看到服务是双活模式（双机房部署同时工作）部署的，服务之间存在一定的跨机房调用，这种情况下容量保障就需要考虑跨机房的专线带宽和延迟等因素。

时序图：时序图描述服务对象之间的调用顺序，它可以帮助我们快速识别出同步调用和异步调用，在链路梳理时很有用。

下图是交易逆向链路的简化时序图，可以很明显的看到，逆向流程中取消订单的操作，对订单服务的调用就是异步的，订单服务并没有立刻给出返回，而是由逆向流程自己创建一系列资源回退任务，异步执行回退，并由一个 Job 去做兜底补偿。在这个案例中，我们需要重点关注的就是 MQ 的容量。

存量服务的架构治理

服务架构治理的另一部分是针对存量服务的治理，由于时间成本的约束，从性价比的角度考虑，可以优先梳理历史上发生过的事故和冒烟。这些历史风险如果在架构层面曾经存在隐患的，而且出事后没有得到有效解决的，就是定时炸弹，在大促前一定要从根上解决，防止层层打补丁，造成技术欠债越滚越多。

比如，某服务曾经发生过容量事故造成服务短时不可用的问题，原因是 Redis 使用时存在热 Key（大量请求访问某个特定 Key），那么我们就可以顺着这条线，排查一下其他服务是否也有类似的隐患，做到防患于未然。

另外，存量服务架构治理的另一个切入点是代码评审，通过对已有代码进行审查，发现潜在的隐患，同时制定改进策略。评审工作由架构师牵头，联合研发与测试一同进行，你可以按照以下脉络去实施。

下面这张表格是基于上述框架，我在大促期间推动服务架构治理中真实发现的具体问题和解决方案，供你参考。

针对存量服务的架构治理工作，我建议可以按业务领域打散到每个业务团队，以专项的形式进行，甚至是组织头脑风暴来尽可能全面的分析问题。在双 11 活动中，我们进行了一些专项试点，获得了不错的效果，有些隐藏很深的问题，或长期处于灰色地带无人问津的隐患（如上述提到的用数字代表业务含义的 code），都得到了重视和解决。

总结一下，大促服务架构治理，针对新服务和新功能，要善于使用架构图去进行全局思考；针对存量服务，可以基于历史上发生过的事故和冒烟，结合代码评审的方式，查遗补漏。

总结

这一讲，我为你构建了一个大促容量保障的框架，帮助你认识大促容量保障要做哪些事，以及如何做好这些事。

目标为先，大促活动的业务场景有其特殊性，我们需要相应调整容量保障的目标，使其能够满足活动举办时的实际需求。

重点链路梳理和服务架构治理，是两项大促容量保障期间的重要准备工作，将有限的时间投入在最核心的部分，基于历史风险进行分析，是我给到你的经验之谈。

希望文中的案例能够帮助你，在大促活动中更好的落实容量保障工作。

课后讨论

在服务架构治理板块中，我给了一些案例，请你也思考一下，目前你负责或参与的业务服务中存在哪些架构隐患，可能会影响到服务容量的？

13 | 大促容量保障体系建设：怎样做好大促活动的容量保障工作（下）

你好，我是吴骏龙。

在上一讲中，我提到了大促活动在业务场景和业务指标中的不同特点，并结合本地生活的双 11 大促活动案例做了讲解。同时，基于这些特点，我为你构建了一个大促容量保障的框架，并做了一定的展开，以便你能应用到具体工作中去填空。

上一讲主要涉及大促容量保障的两项准备工作：重点链路梳理和服务架构治理，这一讲，我们步入大促容量保障的进行时，看一看大促容量保障的三项重点步骤：大促流量预估、大促容量测试和大促容量保障预案。最后，我会为你总结一下整个大促容量保障的体系大图。

大促流量预估

大促流量预估是实施容量测试的前提，在“容量保障的目标”一讲中，我有谈到的一个服务流量扩散比计算的案例，这就是大促场景流量预估的一个很常见的方法。

具体再总结一下重点，如下图所示，在梳理出核心场景链路后，对各服务进行流量预估时，特别要注意对下游服务的流量预估，一方面需要从核心场景入手计算，另一方面还要考虑到上游其他服务的依赖。

这里提供一个不错的实践，也是我在双 11 容量保障工作中沉淀的一个做法，称之为上游负责制（又称入口服务负责制）。简单说，所有依赖方应负责预估对被依赖方的调用量，并及时通知下游进行保障。对于调用量很高，且非常关键的调用方，下游服务甚至可以切割出一个物理隔离的集群，专门为这个调用方服务，以降低容量相互影响的可能性。

我以双 11 活动的订单服务为例，订单服务是非常核心的服务，也是很多其他关键服务的下游，调用量非常大。如下图所示，有大量服务都会调用订单服务执行逻辑，这里我们屏蔽掉调用方式，只从调用量的角度出发，根据“上游负责制”，每个上游服务必须预估对订单服务的调用量，并确保超出时自身先进行限流，或者降级。

在订单服务得到这些信息后，也要做防御性容量保障，不能假定这些上游都按套路出牌。还是按照上图的场景来讲，我们拆分出两个服务：订单查询和订单创建，分别针对订单服务的读操作和写操作，提供对接用户和商户的功能封装，这是典型的读写分离的架构思路。

我们发现，订单查询对订单服务的调用量最大，而且订单查询是非常重要的服务，直接面对用户和商户，为了避免风险，对订单服务来说，就可以切分出一个独立的物理集群，专门为订单查询提供服务。

这样做的好处是，一旦订单查询对订单服务的调用量出现预料外的峰值，导致订单服务出现容量瓶颈，最差也不会影响到其他的调用方。当然，对于后续的容量测试工作，两个集群的容量也需要分别进行验证。

除了上面谈到的案例，我再教给你一些关于大促流量预估的诀窍：

大促期间的通用场景流量预估：这些场景不是大促活动所特有的，可能是日常业务场景，或者是之前已经举办过的活动场景。针对通用场景，我们可以依据常态的流量情况，结合业务指标加上一定的涨幅就可以了。需要注意的是一定要对比清楚场景，勿简单相加。

二八法则：流量的分布不是均匀的，如果大促场景没有明确限定时段，可以预期 80% 的流量会发生在 20% 的时间内，并依此评估峰值 TPS。

竞品对比：有些大促场景是全新制定的，在公司内没有任何历史经验可以借鉴，也没有靠谱的业务指标供转化。这时候可以了解一下竞对公司是否有进行过类似的活动，通过收集公开数据进行横向对比，也不失为一种流量预估的手段。

大促容量测试

完成大促流量预估后，我们就有了验收标准，下面进入大促容量测试工作。由于大促活动有其特定的业务场景形态，除了常态的全链路测试工作外，针对大促场景需要进行多次单链路压测，每次单链路压测都包含压测模型构建、压测数据准备、压测方案和计划准备、影响范围预估，以及监控和预案等步骤。

最重要的部分来了，在单链路压测通过后，需要再和全链路压测叠加进行混压，方能确保全局容量不出问题。 虽说混压的成本比较高，但它是必不可少的，单压没有问题只能说明局部最优，无法推导出全局最优。

一个案例：单压满足容量目标，但混压却都不达标？

为了说明这个问题，我们来看一个例子。在双 11 大促场景中，某大促活动涉及三个营销服务，我们分别对这三个服务进行单压，都满足容量目标，但在叠加混压时，全部都不达标，这是为什么呢？

我们先检查了一下这些服务的部署方式和调用关系，发现这些服务都是独立部署的，相互之间也没有直接调用关系，从服务链路层面似乎看不出什么问题。

于是，我们顺着链路向下挖掘，一直到最底下的数据库，发现了一些端倪。在单压时，各服务所涉及的数据库读写性能基本都在 10ms 这个级别，性能没有什么问题，但在混压时，这些数据库的读写性能都不约而同的集体变差了，上涨了近 10 倍。

这个现象非常奇怪，对这些数据库的调用除了上述 3 个营销服务外，在混压期间没有其他调用方，相互之间也没有交叉调用的情况，似乎不太会存在影响。

但不管怎么说，既然我们发现混压时主要的瓶颈在数据库上，必须拉上了 DBA（数据库管理员）一起排查，DBA 在观察到数据库服务器的高负载情况后，很快得到了结论。原来是这三个服务底层的数据库节点恰好是混部在一台服务器上的，结果就是，在混压时数据库无法承载各自单压时的叠加压力，造成容量不足。

在双 11 活动场景下，这三个营销服务肯定是同时处于高负载下的，因此只有通过混压的方式才能还原真实场景，发现这类问题。这个例子虽然经过了一定的简化，但已经充分体现了混压的重要性，哪怕是一些表现上看起来没有什么关联的服务，在底层也有可能会相互牵扯，影响各自的容量表现。因此，为准确评估双 11 期间的真实容量情况，必须进行混压工作。

从时间维度来说，可以在大促尚未开始的早期，就安排常态全链路压测，确保常态容量安全。大促场景的单链路压测可以穿插在大促准备期，根据服务上线的计划安排。在大促开始前一段时间会提前封版，确保所有服务不再变更后，密集组织若干次混压，保证全局容量安全。

大促容量保障预案

任何事前的容量保障预防措施都不可能完全规避问题，不能“把鸡蛋放在一个篮子里”，一旦在大促活动期间不幸还是发生容量问题，我们也要有相应的预案能够减少和避免损失。

在“容量治理”那一讲中我们已经谈到了一些常用手段，如扩容、限流、降级等。光有这些手段还是不够的，我们还需要将其通过预案的形式固化下来，真正落到实战中去。

预案是生活和工作中很常见的概念，下面这些描述都属于预案。

预案编写应非常具体，避免歧义，还要落实到具体的人。我国对应急预案制定有国家标准，在互联网行业我们可以简化一下，将预案组织为：负责人、服务对象、执行条件、预案内容与操作步骤、影响面等五大要素。下面是一个双 11 活动期间我们的预案实例，张三所负责的天气服务基于的是第三方天气供应商提供的数据，如果供应商服务出现异常，可以操作降级，效果是不显示天气，用户无法获取准确的天气信息。

完善预案覆盖率是保证业务快速恢复的有效手段，作为主动型的容量保障手段，我们需要保障预案是可执行的，人员能够熟练操作，且影响范围周知。做到这一点的落脚点是进行演练，而且是频繁的演练，通过演练提升人员操作熟练度，减少误判，防止预案腐化，这项工作一般会穿插在双 11 活动的准备期进行。

大促容量保障体系

到这里，大促容量保障进行时的三项重点工作就介绍完了。在这一讲的最后，基于上述大促活动的容量保障各项工作，我们将其抽象一层，得到大促容量保障的体系建设大图，你可以直接以它为蓝本，设计你的大促容量保障方案。

这张图里的不少环节，是我摸爬滚打后总结出来的，我也将这些经验与你分享一下。

首先，我们时常会发现一些单场景容量评估存在疏漏的情况，比如遗漏一条链路没有考虑到，或是调用量计算错误，这一类疏漏有时候不一定是人员的不细心造成的，而是因为缺乏足够的信息。为规避这一问题，我们在各个大促场景的容量预估完成后，组织了一次全局评审，全局评审的目的是拉齐各方之间的信息，查遗补漏，确实能发现一些单场景梳理缺失的信息。

其次，在一个超大规模技术团队内组织全场景混压也是很令人头疼的工作，需要协调各个团队的技术人员，协调测试数据和资源，还要制定可操作性强的流程，传统的文档说明和宣讲都很难保证每个人都知晓了整体流程。

为此，我们在全场景混压前 1 小时，安排了一次前置校对的环节，其实就是一个简单的流程通气会，会议的内容是串讲压测流程，并现场答疑，相当于是一次彩排的过程，彩排结束后，立刻进入实战。至于测试数据和资源协调工作，化整为零在线下逐业务团队异步完成，在彩排前可以先小流量进行调试，确保脚本和数据无误，资源足够。

如果你所在公司的技术团队很大，不妨也可以尝试这种做法。

最后，人的认知是螺旋式发展的，在大促活动完成后，应该及时组织复盘，总结经验，将不足之处尽可能多的暴露出来，以免将来再犯。

总结

这一讲，我主要谈到了大促容量保障的三项重点工作：大促流量预估、大促容量测试和大促容量保障预案，并进行了一定的体系化归纳。

相比常态流量，大促流量预估的难度较大，尤其是新上线的服务。对此，我给出了一些实际工作中总结的方法和技巧，以及比较有效的行为准则，如上游负责制、二八法则等。

大促容量测试的核心是混压，组织协调是关键，可以通过拆分出一系列的单链路压测，先行识别容量瓶颈，再通过混压的方式进行验收，达到验证全局容量的目的。

未雨绸缪早当先，居安思危谋长远。对于大促这样的一次性活动形态，除了要制定完善的容量治理手段，还要通过预案的方式进行固化，并通过演练避免无效的预案，保证活动期间一旦出现容量问题，能够快速止损。

最后，我将大促容量保障工作抽象出一张体系大图，并讲解了实际遇到的一些困境和解决方法，希望对你有所帮助。

课后讨论

请你根据今天的所学所得，试着编写一些容量保障的预案，并说一说如何组织演练？欢迎与我交流你的想法。

14 | 容量保障组织建设：容量保障需要什么样的团队？

你好，我是吴骏龙。

前面我们谈到的容量保障话题更多是集中在技术领域，其实容量保障本身并不是单一的技术命题，其背后的组织建设也是一个很重要的因素，因为它牵扯的团队和人员实在是太多了。

我以大促活动为例，通过下面这张图可以看到，互联网公司的主要职能角色几乎都参与到了大促容量保障的各项工作中，这其中还没有包含财务、HR 等支持性角色。那么多角色共同做同一件事，组织建设显然是非常重要的工作。

但现实情况是，有的公司对于容量保障的组织建设其实并不重视。我见过有创业公司直接粗暴地拉出一个独立的容量保障团队，并将所有容量相关的工作全部堆砌到这个团队，却不去考虑建立机制联动各个团队的力量，结果导致这个团队工作的非常痛苦，而容量保障的全员意识依然没有建立起来。

在今天这一讲中，我会与你分享一些大厂在容量保障组织建设中的优秀实践，也会解答一些典型的问题和困惑，希望通过今天的讲解，能让你对容量保障的组织建设有新的认识。

容量保障需要什么样的团队？

这是一个首当其冲的问题，我们究竟需要建立一支什么样的团队去保障容量呢？

顺着上面的讨论，我并不推荐去建立一个通吃所有容量保障工作的团队，达到所谓的闭环效果。虽然我自己长期负责的就是容量保障团队，但我的团队的工作重心除了全链路压测和容量预测以外，更多是通过制度建设和流程规范，去联动公司的各个技术团队共同进行容量保障，而不是单打独斗。

我所认同的优秀实践是：容量保障需要有团队去建设和统筹，这个团队最大的价值在于，通过自身的输出（工具、流程、规范等）去推动公司整体的容量保障水平和意识的提升。 这个团队的组织形式是多样的，基于 SRE 团队（Site Reliability Engineering，网站稳定性团队）和容量测试团队（或者叫性能测试团队）的做法在行业内都有一些成功的案例，下面我谈一下我的经历和思考。

1. 建立 GOC 团队

GOC 是由运维和技术运营所发展起来的独立团队，全称是 Global Operations Center，中文名叫“全球运营指挥中心”，承担全局应急、指挥和调度工作，这里的“全球”泛指全局的意思，不一定要跨国服务。

GOC 团队的组织形式在 2012 年由阿里巴巴开始进行尝试，将当时散落在各团队的监控体系、监控中心执行标准和流程规范进行了统一，取得了不错的效果。到了 2015 年，GOC 进一步明确了定位，负责管理生产环境所有问题，打通实时监控、发现、通告、快速恢复、事后复盘、落实全生命周期管控，注重监控运营效率与大数据分析，快速定位与恢复能力。

这里对 GOC 的部分解读我参考了阿里的分享，如果你感兴趣的话可以看看这篇文章。

GOC 是典型的“分久必合”的组织产物，各个业务团队的“小运维”形式在组织建设初期的效率和执行力是非常强的，但随着全公司团队规模的逐渐扩大，缺乏集中管控造成“重复造轮子”的现象就日益突出，直到有一天发现忍无可忍后，必须要有一个集中式的组织接管这些共性的工作部分，这种情况在互联网公司是非常常见的。

集中式组织管理形式最大的优势在于标准化，最大的劣势在于脱离一线，因此需要扬长避短。针对容量保障工作，GOC 比较适合作为作曲家和指挥家的角色，制定容量保障规范，统一跟进线上各种容量风险，在大促期间协调各个相关团队编写作战手册，组织预案演练，牵头快速应急等工作。当然，有的公司会组建 SRE 团队来做这些事情，其本质也是类似的。

如下图所示，我们以容量故障的线上应急为例，看一下 GOC 团队是如何与研发团队和客服团队联动工作的。

如果没有 GOC 团队作为大脑指挥，很难想象这样的流程能够顺畅执行。GOC 的组织形式很好的发挥了集中式团队的统一管理优势，GOC 本身并不直接介入技术细节，而是指导和推动相应的业务技术团队。

可以想象一下，老式的绿皮火车是由火车头作为动力源牵引各节车厢的，而新式的动车组列车的每节车厢都有动力源，车头的作用只是引导方向。GOC 就是这列动车组的车头，这非常符合我所提倡的“全民保障”的实践方式。

2. 是否需要独立的容量 / 性能测试团队？

我们顺着 GOC 团队的建设思路再进一步思考，容量测试团队是否也有必要化零为整，变成一个独立的横向支撑团队呢？我所经历过的公司有的是，有的不是，这个问题的本质其实是需要阶段性考量的，我把开篇词中的一张表格替换成容量保障意识的内容再回顾一下，来看一看有什么启发。

很幸运的是，我几乎经历过大型电商的所有这四个业务阶段，深深感受到了公司管理层对于容量保障工作的思维变迁。在业务探索期，所有人关心的都是业务行不行，我们能不能活下去；在业务进攻期，我们全站的平均 CPU 利用率还不到 10%，申请服务器从来不设卡；到了业务发展期，我讲的最多的话就是“不要简单扩容，先看看服务有没有优化的空间”；而到了业务变革期，CPU 利用率长期低于某个水位是要被挑战的，无脑的扩容申请一般都会被拒绝。

回到最初的问题，有没有必要建立一个集中式的容量测试团队，是需要根据业务发展的阶段做判断的。

我认为在探索期和进攻期，无论哪种形式都不会有太大的问题，在发展期可以考虑分而治之的思路，但在变革期一定要建立一个集中式的容量测试团队，因为服务优化和容量治理，必须要有一个有实权的团队牵头和监督，并提供统一工具支撑，否则很容易沦为上有政策下有对策的局面。当然，这个容量测试团队不一定要很大，甚至可以是 GOC 团队或 SRE 团队的一部分。

总结一下，容量保障工作需要有团队去建设和推动，将其辐射至整个公司。GOC 的组织形式是阿里应用的比较成功的例子，不仅仅能对接容量保障的各项工作，还能从制度和流程上进行规范。关于是否需要独立的容量测试团队，我们要用阶段性的眼光看待这个问题，希望能给你带来启发。

谁为容量负责？

有了团队，下面就要明确责任，那么谁来为容量负责呢？是不是由 GOC 或容量测试团队来负责呢？

首先，单一角色负责制一般是行不通的，除非团队很小，因为容量保障牵扯的角色太多了，很难有一个人或一个团队能 carry 全场，即便是上面提到的 GOC 或容量测试团队，也不可能单独解决所有容量问题，自然也无法为容量保障负全部责任，否则就违背了权责对等的原则，这是不长久的。

虚拟团队也许是一种思路，由 GOC 牵头，各个业务团队的架构师和容量测试人员共同参与，组成一个容量保障虚拟团队，共同完成容量保障工作。这个虚拟团队中的人员有一部分共同的 KPI，并受 GOC 统一管理。

在我的实际工作经验中，为了让容量保障团队更有抓手，采用过“虚实结合”的方式。每个业务技术团队确保有一个容量保障负责人，可以是架构师或资深研发人员，他们分别向业务负责人和 GOC 负责人双实线汇报，定义明确的目标和产出。

这位容量保障负责人遵循“首问负责制”，即对服务容量有第一手责任，为了支撑这个责任，每个业务技术团队约定不少于 15% 的人力由其统筹，作为开展工作的人力资源。容量保障的其他参与方依然保留在各业务团队的汇报关系，但有一部分 KPI 对应容量保障职责，由 GOC 团队根据客观数据进行打分。这样，就形成了有层次的团队负责制度，对各个职能角色也有一定的授权和约束。

这种“虚实结合”的方式，你可以参考，如果有条件，也可以试着在你的团队中应用。

如何运营好容量保障团队？

说完了团队和职责，我们再来聊聊如何经营好这个团队，其中我想与你分享两个不错的实践方式，分别是：激励措施和竞争模式。

无论容量保障团队以何种方式组织，激励措施（也包括惩罚措施）都是必不可少的部分，正确的激励手段能够激发团队的动力和上进心，使其产出最大化；适当的惩罚措施能够让团队及时纠正错误，在未来做得更好。

有一段时间，我们为了鼓励各业务团队投身服务性能优化，避免简单扩容，推行了一个政策：如果在一个大业务团队中，有一个服务通过优化手段能够缩容一定的资源，那么这部分资源不会被回收，而是可以用到这个大业务团队的其他服务中，甚至还会奖励一部分资源。

这种共享资源配额的激励做法，起到了立竿见影的效果，业务团队不再纠缠于为何不给我扩容资源，而是想尽办法榨取服务容量的可优化之处，以应对业务自然增长带来的服务资源压力。

定期组织一些轻松诙谐的仪式，将奖惩措施融入其中，也是不错的团队激励方式。比如，举办“红烂草莓”的评选活动，根据服务容量的表现情况，结合高等级评委的打分，评选出若干个做得好的“红草莓”和做得差的“烂草莓”，在部门例会时进行颁奖。在聚光灯下，做得好的员工能够保有高度的荣誉感，对做得不好的员工也能够有所警醒。

经营容量保障团队的第二个优秀实践是引入竞争模式，可以在各个业务域进行横向对比，但是要小心度量标准的公平性，比如有些业务服务可能不是 CPU 密集型的，如果以 CPU 利用率水位作为评判标准就不是一个好点子。

坦白说，依赖固定指标对容量保障工作的好与坏进行度量，很难做到完全没有偏颇，我的经验是直接以结果说话，先根据每个业务团队的规模和服务特点给予一定的容量事故配额，在一个时间周期内按照线上发生的容量类事故的个数和严重程度，进行相应的配额扣减，最终形成反映容量保障优劣的“容量健康分”，这个分数就是相对客观的度量标准，分值越接近配额的初始值，最终成绩就越好。

如果你是管理者，那么善用激励措施和竞争模式，就能够在团队内形成良性循环，将团队的战斗力最大化的发挥出来。

总结

容量保障作为一个多角色参与的工作，组织建设必不可少，在这一讲中，我与你分享了我的容量保障组织建设经验，也批判了一些不恰当的做法。

容量保障团队不应该是一个包干团队，它应该是一座桥梁，连接着各个技术团队和其他职能团队，协同各方共同保障容量安全。 基于这个理念，我与你探讨了 GOC 和容量测试团队的组织形式，并分析了在公司发展的不同阶段，容量测试团队的形式会有哪些不同。

接下来，从职责的角度，我分析了更大范围的组织建设形式，包括虚拟团队和双实线汇报的方式，它的目的，是在权责对等的情况下，更好的明确每个人的权利，以及所承担的责任。

最后，团队运营是重中之重，我介绍了激励措施和竞争模式这两个不错的实践方式。奖惩分明，良性竞争，有助于推动团队更好的输出力量。

课后讨论

你的公司目前是由哪个团队或哪些人来负责容量保障工作的，你觉得当前的组织形式有什么值得改进的地方吗？或者，有什么你认为做的特别好的地方，值得推广的吗？欢迎与我交流你的经验。

15 | 小公司也能做好容量保障：建设经济实用型的容量保障体系

你好，我是吴骏龙。今天我会与你探讨一下小公司如何做好容量保障。

首先，我想先明确一个前提，那就是小公司到底要不要进行容量保障，很多人会觉得小公司进行容量保障的必要性不大，理由无外乎有：

公司规模不大，业务量也不大

公司不搞促销活动，流量波动不大

公司用的是云基础设施，它们会负责容量安全

公司技术团队人太少了，肯定是先保证质量

我的观点是，是否要进行容量保障，和公司“大”与“小”无关，而是与业务形态和发展趋势相关。

我经历过一家初创型的电商公司，这家公司在早期整个技术团队不超过 30 人，服务都是单体应用的架构，业务以到家的形态为主，基础设施用的也是某大厂的云设施。传统认知上，这是一家典型的小公司，但随着业务的不断发展，业务高峰期间系统服务的压力越来越大，经常发生服务稳定性的问题，以至于高层很快决定将容量保障列为了技术团队最重要的工作之一。

这个例子完整的解答了对于容量保障工作必要性的讨论。

首先，是不是要做容量保障，和公司的规模其实没有什么关系，而是和公司的业务特点有关，比如我在开篇词中曾提到的一个关于某企事业单位内部系统的例子，它的用户量和用户群体都比较稳定，业务场景几乎不变，虽然这个单位的人员规模很大，容量保障的意义也比较有限。相反，如果是面向外部用户的互联网系统，业务场景有明显的流量峰值，再小的公司也一定会进行容量保障，只是做法不同罢了。

其次，容量保障和质量保障是同等重要的，因为它们都有可能会影响到服务的可用性，最终影响用户体验。两者之间不是“有你无我”的关系，而是“既要也要”的关系。

弄明白小公司进行容量保障的必要性以后，我再来解读下一个问题：如果你的公司规模不大，在容量保障工作中无法投入太大的成本，有没有什么经济实用的方法可以操作呢？答案当然是有的，下面我分别从四个不同的角度，具体展开讲解。

方法一：粗放式保障

对容量保障工作来说，投入和产出一般是呈正比的，在投入有限的情况下，我们自然不可能做到面面俱到，这时候就要抓大放小，去做那些性价比高的事情，适当牺牲掉一些细节，这就是粗放式保障的思维。

那具体怎么去实施呢？或者说，哪些环节可以粗放式保障呢？我可以给你一些启发。

在服务容量的观测能力方面，对容量指标的监控告警就可以是粗放式的，你可以针对服务的各项容量指标划定一个警戒值，比如 CPU 利用率≥80%，响应时间 99 线≥500ms，成功率≤95% 等，超过警戒值后，监控系统直接发出告警。

在我的经验里，大多数线上容量问题都是可以通过这些指标数值上的简单对比，在第一时间感知到的，性价比很高。而从另一个角度，对于那些趋势型的指标监控，还有带有业务语义的监控，实现的成本高，还要理解业务逻辑，就可以次要考虑。

容量测试也是一样，没有条件做全链路压测怎么办？那就加强基线容量测试，如果基线容量测试还没有人力去做，那就直接在生产环境的服务灰度阶段，通过对响应时间等指标进行同比，来发现容量隐患，这种变相的基线容量测试也可以一定程度上发现一些高危问题。发现问题后，可以先回滚服务，再对容量隐患进行排查，修复后重新上线。

粗放式的容量保障并不是无谓地放弃一些工作，而是有策略地选择性价比高的“大头”去优先保障，以较低的成本堵住最严重的容量风险。

方法二：善用云服务商的收费机制

如果你的公司的业务流量是有明显的高峰期和低峰期差异的，那么你就不得不面对容量保障里很头疼的一个问题，为了保证高峰期的容量充足，必须维持一定规模的服务器资源，但到了低峰期，这些资源又很富余，显得很浪费。无论公司大小，只要是类似的业务流量形态，都会面对这个问题。

小公司一般不太会投入重金去建设自有机房，使用云服务厂商提供的服务资源是普遍做法，幸运的是，各大云服务厂商都提供了一些机制，帮助我们节省容量保障的成本，而且几乎没有什么侵入性。

比如阿里云就提供了“停机不收费”的服务，通过计算力与存储分离的方式，我们可以将指定的计算资源在需要的时间段释放，同时保留存储内容，下次开机（即恢复计算力）时可以继续使用。对你来说，这就相当于在低峰期对服务进行缩容，你所要做的，仅仅是评估出在低峰期缩掉多少资源比较安全，这个成本是不高的，因为不需要很精确，而且可以演练。

那么，如果遇到大促活动，在成本有限无法实施精确的容量预测和容量规划的情况下，你也不想提前冗余很多的服务资源，这时候有什么好办法吗？

正如我在“云原生下的容量保障新趋势”一讲中所提到的，云服务商也提供了弹性伸缩的服务，通过设置伸缩规则，在业务流量增长时能够自动增加实例，以保证计算力充足，反之则自动缩减实例。弹性伸缩是可以计量收费的，也就是说，伸缩机制本身不会收费，只有实际创建的实例才会收费。

弹性伸缩机制对容量保障的成本节约主要体现在，它将一部分容量预测不准确所带来的潜在风险，用云基础设施的能力去承载。这有点像是买保险，用一个大池子去分摊个体的风险，对个体来说，只需要支出很少的费用，就能获得较大的保障。

方法三：用好开源工具

我们处在一个拥抱开源的繁荣时代，开源已经不仅仅是个人爱好的驱使，很多优秀公司都在通过开源的方式宣传和完善它们的产品。用好开源工具，不但能节省成本，还能推动行业的发展，毕竟，你也是开源的一份子。

在容量保障工作中，很多环节都是可以利用开源工具去实施的。最典型的，容量测试可以使用 JMeter 去完成，这是老牌的开源压测工具了，功能非常丰富，还支持通过插件扩展，纵使它的阻塞式 IO 施压模型较为陈旧，对资源消耗较大，但在并发量不大的情况下，这部分的劣势其实并不显著。相反，JMeter 强大的可扩展性，加上开源社区的支持，极大的降低了使用者的成本。

在容量预测和容量规划工作中，对服务容量建立模型的过程，也可以借助开源工具完成，常见的有 TensorFlow、PyTorch、Spark MLlib 等工具，小到多项式拟合，大到神经网络，都有现成的封装，这样你就可以把精力完全投入在调参和验证上了。

当然，开源工具的社区维护特点，决定了它不太可能快速支持一些特殊的定制化需求，如果这种定制化需求是你的刚需，那么建议可以考虑自己进行二次开发，相比于完全重新去编写一个工具，附加值依然是很高的。你会发现，很多大厂在工具建设的早期其实也是遵循这个思路的，比如京东的全链路军演系统 ForceBot 的第一代就是基于 nGrinder 定制的，360 的性能云测平台大白是基于 JMeter 定制的，等等。

方法四：购买解决方案

如果你公司的业务不是特别敏感的话，将容量保障工作外包，也不失为一种简单粗暴的方法。大型云服务商和一些专业的独立咨询机构，都有提供类似的服务，会有专属的团队介入对齐目标，分析容量现状，实施容量规划和验证，最后交付验收。花点钱，都帮你搞定了。

不过，如果你公司的业务流量在平时始终存在明显的峰谷特征，那么容量保障就是需要长期进行的常态化工作。在这种情况下，我个人就不太建议采用购买解决方案的方式了。

因为要做到可持续的容量保障，所有技术人员都必须具备良好的“容量意识”，比如在编写代码时就要考虑到高性能，在架构设计时就要考虑到减少容量瓶颈，等等，而容量意识是需要技术团队在实战中锻造出来的，甚至要经历过一些教训才能成长，这是购买解决方案所无法带给你的。

总结

今天我主要与你探讨了如何在小公司建立经济实用型的容量保障体系。需要明确的是，要不要做容量保障，与公司规模大小其实关系不大，而是和业务形态和业务特点有关；而怎么做容量保障，会关系到成本和人力投入，小公司可以有小公司的做法。

粗放式保障是小公司进行容量保障的基调，抓大头放小头，采用性价比最高的方式，堵住最可能发生的容量隐患。然后可以逐渐再去覆盖次重要的容量保障部分，慢慢地精细化。容量保障的各个方面都可以采取粗放式保障的思路，在这一讲中我列举了容量观测和容量测试的实践案例，你也可以思考一下在容量保障的其他环节怎样抓大放小。

各大云服务厂商针对服务容量提供了丰富的调整策略，“停机不收费”和“弹性伸缩”是目前应用得比较多的策略，合理利用这些策略，不仅能够保障容量安全，还能最大化地节省费用，降低投入。

在开源时代，容量保障工作的方方面面几乎都有各种开源工具能够支持，由于小公司队伍精简，组织扁平，对于工具平台化的需求一般不高，因此针对开源工具进行简单的二次开发，基本能够满足使用，性价比较高。

最后，如果容量保障不是日常需求，那么一次性投入购买解决方案也不失为一种选择。但如果公司的容量保障是长期工作，那么还是应当脚踏实地的做好积累，提升容量保障的技术水平和全员意识。

如果你恰好身处小公司，希望今天的讲解能够为你带来一些容量保障建设的落地思路；如果你身处大型公司，也希望今天的内容能够为你打开不一样的眼界和领悟。

课后讨论

今天我们聊到了不少粗放式容量保障的方法，你觉得容量保障还有哪些环节是可以循序渐进，逐步从粗放式发展到精细化的呢？欢迎与我分享你的想法和经历。

结束语 | 做时间的朋友，成功是持续累积而成的

你好，我是吴骏龙。到今天为止，我的专栏就要告一段落了。

坦白说，写专栏真的蛮辛苦的，我原本以为自己作为一名善于总结、文笔尚可、始终奋战在一线的技术管理人员，把自己的经验汇总成文分享出来，应该不是什么难事，但实际情况却远远超过我的想象。专栏写作几乎占用了我 3 个多月以来所有的业余时间，由于互联网行业众所周知的工作节奏，我每天下班回到家都要快 22 点了，熬夜写作成了常态，真真切切体会到了一把“痛并快乐着”。

刚开始构思这个专栏的时候，我考虑到容量保障是有一定门槛的技术内容，因此对它的定位是让参与过或从事过容量保障工作的技术人员能够学习到系统化的方法论，并适当拔高。但我与一些从业者深入交流后，发现其实很多群体都对容量保障工作抱有极大的热情，这才有了专栏的最终定位，无论你是从未接触过容量保障的新手，还是已经在容量保障领域小有成就的资深人员，这个专栏都能带给你帮助和启发。

不过，我并不希望我的专栏带给你的仅仅是速成的效果，而是致力于给到你容量保障的核心方法论和思维方式，这样即便多年以后你重新回顾这个专栏，依然能够时读时新，有不同的收获。

通过整个专栏的学习，你再回顾一下我在开篇词中给出的容量保障方法论大图，是不是觉得清晰了很多，也收获了很多？

专栏总有结尾，但学习永无止境，我想再和你分享几个我的成长体会，希望能让你今后的工作和学习道路受益。

全局视野

不谋全局者，不足以谋一隅。我见过不少技术人员在某一领域小有成就，但在职业生涯很长一段时间内都无法更进一步，其中一个很大的原因就是缺乏全局视野，所完成的工作只是达到了局部最优，没有实现全局最优。想象一下，在上面的容量保障方法论大图中，如果我们只是把压测工作挑出来做好，能全面保障服务容量不出问题吗？

全局视野的培养需要一定的积累和历练。我的做法是，每接到一个工作任务，或者我判断需要做的事情，我会先跳出这件事本身，站在更高的视角去思考，最后再回到细节中去。

举个例子，如果要建设全链路压测，我除了考虑全链路压测本身的技术方案以外，还会考虑它需要哪些团队参与技术改造？压测发现的问题谁来解决？压测相关人员值守该怎样组织？压测本身有什么局限性？需不需要其他工作辅助？等等，把这些条条框框都想明白了以后，再去看每个框架内具体要做些什么事情。

如果你坚持以这样的方式思考问题，久而久之，思维惯性就形成了。相信我，你会发现自己潜移默化地具备了全局视野。

跳出边界

目光短浅的人总是充满边界感的，喜欢给自己设定各种条条框框，比如：“我是测试，只负责暴露问题，问题让研发去分析”，又比如：“我服务的容量不足，是因为依赖的 B 服务响应时间上升了，我也改不了啊，不关我的事”。

任何的限制，都是从自己的内心开始的，很多时候我们不愿意跳出边界的原因在于惰性使然，但如果我们永远固守着自己擅长的领域，不愿跳出舒适圈，是很难成长的。

阿里本地生活的前任 CTO 张雪峰经常鼓励我们要跳出边界做事情，尤其是面对一些三不管的灰色地带更是如此，哪怕短期内出不了成绩。我们身边也有耳熟能详的正面案例，雷军身价已经超过百亿美元了，但依然在自己 51 岁时选择再次投入新的造车领域进行创业，这就是跳出边界的榜样。

可以说，跳出边界，是快速成长的第一驱动力。

实践先行

有句流行的名言叫“Talk is cheap, show me the code.”，我喜欢把它翻译成“纸上得来终觉浅，绝知此事要躬行”。实践是保持职场竞争力的有力手段，这也是我从事技术管理工作多年，依然将大部分工作精力投入在一线的原因，写写代码，搭搭框架，时而去解决一些疑难杂症，保持自己的技术热度。

推荐一个我很喜欢的实践做法，叫做 PoC（Proof of Concept，概念验证），指的是当你有一个想法时，可以通过一个简单的实现来证明它在技术上的可行性，这个实现可以是不完整的，但它会迫使你放弃纸上谈兵，充分贯彻实践先行的理念。现在流行的 MVP 策略（Minimum Viable Product，最小可行产品），也有异曲同工之妙，只是更偏向于产品和用户。

我在推动容量预测工作伊始，团队中很多同事都觉得这太难了，不相信能做成，于是我花了大约一周的时间写了一个 PoC，对一个服务成功进行了准确的容量预测。即便后面我们又遇到了很多困难，但大家本着实践的精神不断探索新方法和新思路，再也没有人打退堂鼓了。

再长的路，一步步都能走完，再短的路，不迈开双脚也无法到达。 努力实践，勇于实践，你就能将不可能变为可能。

说完了我的成长体会，最后以一句名言与你共勉：“成功不是将来才有的，而是从决定去做的那一刻起，持续累积而成”。希望你能持续学习，持续提升，做时间的朋友，迈向更高的山峰！

在课程的最后，我为你准备了一份结课问卷，希望你能花 1 分钟时间填写一下，我想听一听你对这门课的反馈。只要填写，就有机会获得一顶极简棒球帽或者是价值 99 元的课程阅码。期待你的畅所欲言。