老计聊SRE 09:容量规划,别等雪崩了才想起扩容
本系列的示例应用和脚本开源在 GitHub(仓库地址见文末)。本篇的压测数据来自对示例应用的真实实验。
本篇目标
上一篇我们让单个服务学会了自愈。但自愈解决的是"坏了怎么恢复",没解决"流量太大扛不住"。大促、热点、突发流量,这些不是故障,是容量问题。
容量规划要回答的核心问题是:你的系统到底能扛多少,瓶颈在哪,该怎么扩。学完本篇你将掌握:
- 为什么容量规划的第一步不是加机器,而是找瓶颈
- 怎么用压测测出真实的容量上限
- 用一组反直觉的真实数据,看清瓶颈到底在哪
- 找到瓶颈之后,扩容的正确方向
一、扩容不是无脑加机器
先说个很常见的误区。
服务慢了、卡了,很多人的第一反应是:加机器。加到不卡为止。有时候确实管用,但很多时候,钱花了,问题还在。
为什么?因为你可能加错了地方。一个系统的瓶颈可能在 CPU、可能在内存、可能在数据库连接数、可能在单进程的处理能力、也可能在某个第三方依赖。如果瓶颈在数据库,你把应用服务器加了十台,数据库照样是那个瓶颈,一点没缓解,只是白烧钱。
所以容量规划的第一步,从来不是加机器,而是:先搞清楚瓶颈到底在哪。找错了瓶颈,后面全是无用功。
怎么找?靠压测。
二、压测:把系统压到极限,看它先在哪断
压测就是主动给系统加压,一点点加大流量,观察它什么时候开始扛不住、以及是哪个环节先扛不住。
压测时主要盯两个东西:
- 吞吐量:系统每秒能处理多少个请求(req/s)。这是它的产能。
- 延迟:随着压力增大,请求变慢了多少(还是看 P95/P99,别看平均)。
理想情况是:流量加大,吞吐跟着涨,延迟基本稳定。直到某个点,吞吐涨不动了、或者延迟开始飙升、或者开始出错,那个点就是容量拐点,也暴露了瓶颈在哪。
关键是:压测要压到系统真的开始难受为止,只有压到极限,才能看清它的天花板在哪。压一半就停,你永远不知道它还能扛多少、会先在哪断。
三、动手:一组反直觉的真实压测
我们对示例应用做了一次压测,不断加大并发,看它的吞吐和延迟怎么变。先看并发从小到大的结果:
并发 1: 吞吐 134 req/s P99 1ms 并发 10: 吞吐 186 req/s P99 18ms 并发 50: 吞吐 ~185 req/s P99 ~18ms 并发 100: 吞吐 ~185 req/s P99 ~19ms并发从 1 加到 10,吞吐从 134 涨到了 186。但从 10 往上,不管加到 50 还是 100,吞吐都卡在 185 左右不动了。
我们继续往极限压,把并发一路加到 800:
并发 50 到 800: 吞吐稳定 181 到 186 req/s 零失败 P95/P99 稳定 14 到 22ms并发一路加到800,吞吐却死死卡在每秒185不动
这个结果第一眼看很反直觉:并发从 50 加到 800,翻了16倍,吞吐居然一点没涨,还是 185 左右,而且零失败、延迟也稳。
这说明什么?
四、看懂数据:瓶颈不是并发,是单进程吞吐
这组数据其实把瓶颈指得很清楚。
并发加到 800 都零失败、延迟也稳,说明这个服务承载并发连接的能力绰绰有余,瓶颈根本不在"能同时接多少请求"上。
真正的瓶颈是:吞吐死死卡在每秒 185 个请求。不管前面涌进来多少并发,它每秒就只能吐出 185 个。多出来的请求只是在排队,排到了就处理,所以不失败,但整体产能上不去。
原因是这个服务跑的是单进程,单进程的处理能力就这么大(这台是2核的小机器)。这时候你要是去加并发、加连接数,一点用都没有,因为瓶颈不在那。
正确的扩容方向是提升吞吐能力:比如把单进程改成多进程(多个 worker),或者部署多个实例用负载均衡分流。只有对着真正的瓶颈下手,扩容才有效果。
瓶颈在单进程吞吐,加并发没用,要加worker或多实例
这就是我开头说的:先找瓶颈,再扩容。如果没做这次压测,只看到"服务好像到量了",很可能就去加并发、加连接池,结果白忙一场。压测让我们看清了真正的天花板在哪。
五、容量规划不是一次性的
找到瓶颈、扩了容,也不是就一劳永逸了。容量规划是个持续的事。
- 留出余量(headroom):别把容量卡在刚好够用。流量有波动、有突发,通常要留一定的缓冲,比如让日常负载只占容量的一部分,给尖峰留空间。
- 结合业务预期:大促、活动、季节性高峰,这些能预见的流量高峰,要提前按预期规划容量,别到时候临时抱佛脚。
- 自动扩缩:对流量波动大的场景,可以用自动扩缩(根据负载自动增减实例),高峰自动扩、低谷自动缩,既扛得住又省钱。这也呼应了前面讲的健康检查,扩出来的新实例要健康检查通过才接流量。
- 定期重新压测:系统在迭代,依赖在变,今天的容量结论过几个月可能就变了,要定期重新测。
容量规划的目标是:在流量真正涨上来之前,就知道自己能扛多少、该怎么扩,而不是等雪崩了才手忙脚乱。
容量要留出余量,别把日常负载卡在天花板
六、小结
- 扩容第一步不是加机器,是找瓶颈,加错地方等于白烧钱
- 压测要把系统压到真正难受为止,盯住吞吐和延迟(P95/P99),找到容量拐点
- 真实数据反直觉:并发从50加到800都零失败,但吞吐死卡在185 req/s,说明瓶颈是单进程吞吐而非并发
- 对着真正的瓶颈扩容才有效:吞吐瓶颈要加 worker 或多实例,加并发没用
- 容量规划是持续的:留余量、结合业务预期、用自动扩缩、定期重新压测
下一篇:大部分线上故障其实都来自一次发布,变更管理,怎么让发布不再是故障的最大来源。
参考链接
- 本系列开源仓库(示例应用 + 压测脚本):https://github.com/Jich1123/sre-aws-lab
- Google SRE Book - Software Engineering in SRE(容量与压测):https://sre.google/sre-book/software-engineering-in-sre/
- Google SRE Book - Handling Overload(过载处理):https://sre.google/sre-book/handling-overload/
- Google SRE Workbook - Managing Load:https://sre.google/workbook/managing-load/