容量治理这件事,很多团队把它理解成大促前的一次性评估。提前两个月压测,算出单机能扛多少 QPS,按预估峰值乘个冗余系数机器拉满,大促结束再退掉。这套流程对付一年一两次的大促够用,但它解决不了一个更日常的矛盾,业务流量是动态变化的,而资源申请和释放是有滞后和成本的。配多了机器常年空转烧钱,配少了流量一波动就打满报警。真正成熟的容量治理,是把它从一次性活动变成日常的水位监控加弹性调节。
这个观念的转变,是我在 Matrix 那边经历大促保障之后才真正落地的。大促前的容量评估当然要做,但单靠它撑不住平时的波动。日常有突发热点,有业务增长,有定时任务跑批时的瞬时压力,这些都需要一个持续运转的容量机制去兜着。下面把这套机制拆开讲。
先把水位这个概念立起来
容量治理的起点是给资源使用率找一个统一的度量。我们用的是水位这个比喻。一台机器 CPU 跑到 60%,就说应用水位 60%。一个 Redis 内存用到 50%,就说缓存水位 50%。水位的好处是把不同维度的资源用率拉到同一个标尺上比较,便于一眼看出哪里紧张哪里空闲。
图:水位四区间——目标是把大多数资源维持在日常健康水位(30%~70%)
水位分几个区间。低于 30% 是低水位,资源浪费,这种状态长期存在说明配多了,可以缩容。30% 到 70% 是健康水位,资源利用合理,留有余量应对波动。70% 到 90% 是高水位,需要关注,准备扩容。90% 以上是危险水位,随时可能因为一个小波动而打满崩溃。容量治理的目标就是把大多数资源大多数时间维持在健康水位,既不浪费也不冒险。
这里有个容易忽略的点,水位要看的是峰值而不是均值。一台机器一天平均 CPU 30%,但午后流量高峰时飙到 85%,按均值看很健康,实际上高峰期已经在悬崖边。容量评估必须基于峰值水位,均值会掩盖真实压力。
多维监控,别只盯 CPU
光看应用 CPU 是不够的。容量瓶颈往往不在应用实例本身,而在它依赖的中间件和底层资源。所以水位监控要分几个维度一起看。
图:容量水位多维监控——应用/中间件/资源/业务四个维度,最忌只盯一个指标
应用水位是基础,CPU、内存、GC 频率这些指标反映应用实例本身的负荷。但真正容易先打满的,往往是中间件水位。数据库连接池的使用率,如果长期在 80% 以上,再多请求过来就要排队等连接,RT 直接劣化。缓存命中率,如果某天突然从 99% 掉到 40%(这正好是我们治理过的反例),说明缓存大面积失效,穿透压力全部打到 DB。MQ 消息堆积量,消费者跟不上生产速度,堆积到一定程度就是雪崩的前兆。
资源水位看磁盘、网络带宽、文件句柄数这些底层指标。业务水位看的是 QPS 相对于容量上限的比例,比如这个服务压测能扛 2000 QPS,当前跑 1600,业务水位就是 80%。业务水位的好处是它直接反映了离崩溃还有多远,而技术指标只能间接推断。
这些维度里任何一个长期高水位都是预警信号。容量治理最忌讳的是只盯一个指标,CPU 没满就以为没事,结果 DB 连接池先炸了。
弹性伸缩,听起来美好但有不少坑
水位监控告诉你该扩该缩,真正执行扩缩的是弹性伸缩机制。K8s 的 HPA(Horizontal Pod Autoscaler)是最常见的实现,它根据 CPU 或自定义指标自动增减 Pod 数量。原理不复杂,难点全在参数调优上。
最大的坑是抖动。流量是会瞬时波动的,一个流量尖峰可能只持续十几秒,如果 HPA 一看到高水位立刻扩容,扩容还没完成流量已经回落,新实例上来后无事可做,过一会又被缩掉。这种来回拉扯既浪费资源,又让系统状态不稳定。解法是加冷却时间,HPA 触发条件不能是瞬时超阈值,而是高水位持续 N 分钟才扩容,扩容后进入冷却期不再动作。这个 N 取多少是个权衡,取太短防不住抖动,取太长反应迟钝错过真高峰。一般 CPU 这类快指标取两三分钟,业务 QPS 这类慢指标可以放宽到十分钟。
缩容比扩容更敏感,也更难做好。扩容错了顶多多花点钱,缩容错了可能直接把容量缩到撑不住。所以缩容的判断要更保守,低水位持续时间要设得比扩容更长,而且要有保护机制,比如保留一个最低实例数,绝不缩到这个数以下。
扩容的快慢分层,不是所有服务都能秒级弹
弹性伸缩的前提是服务能快速扩出来。但不同类型的服务扩容速度天差地别,把它一刀切当成都能秒级弹的,是容量规划里很危险的想当然。
图:扩容速度分层——无状态应用可分钟级弹性,有状态服务必须提前规划留足余量
无状态应用是最理想的弹性伸缩对象。拉个镜像,启动个实例,预热几分钟就能接流量,分钟级别完成扩容。这类服务放开手用 HPA 自动伸缩就行。
有状态服务就完全是另一回事了。数据库主库,扩容意味着要加机器加分片,数据要重新分布,这是一场手术不是一次重启,根本不可能靠自动伸缩完成。Redis 单分片扛不住,集群化要改客户端配置和数据迁移。这些服务的容量必须提前规划,留足余量,因为出事时来不及扩。
这一条想单独强调。容量治理做到最后会发现,能靠加实例解决的问题都不是真问题,真正难搞的是加实例解决不了的单点。DB 主库是单点,缓存某个热点 key 所在的分片是单点,有状态服务无法多实例部署是单点,第三方依赖的限流是单点。这些才是容量的天花板,平时看不出,流量一来先在这崩。识别单点是容量治理里价值最高的一步,识别出来之后要专项治理,读写分离、分片、状态外置、多通道容灾,一个个啃掉。
主动预测比被动等告警更靠谱
弹性伸缩是被动的,等高水位告警触发再扩容,总有一段扩容延迟期,这段期间系统是在裸奔承受压力。更主动的做法是基于历史流量规律做预测。
大多数业务流量是有规律的。电商每天晚 8 到 10 点有流量高峰,每周一上午有业务高峰,每个月发薪日有特殊峰值。把这些规律摸清楚,在预测的高峰到来之前就提前扩容到位,高峰期平稳度过,高峰过后再缩回去。这套主动预热比被动响应稳得多,因为扩容动作发生在流量真正到来之前,不存在扩容延迟的窗口期。
预测要结合水位评估定期做。每周或每月固定跑一次容量评估,拿实际水位对比容量上限,看余量还剩多少。余量不足 30% 就要规划扩容,余量超过 70% 就可以考虑缩容降本。这个节奏让容量始终维持在健康区间,而不是等到打满才慌。
容量和成本的永恒拉扯
容量治理绕不开成本。配多了浪费,配少了危险,这是天然矛盾。弹性伸缩提供了这个矛盾的平衡点,峰值期自动扩容保稳定,低谷期自动缩容降成本。但它不是免费的午餐,弹性伸缩本身需要常备一部分缓冲实例来应对秒级需求,这部分就是用空间换时间。
最终容量治理要建立的是一套反馈闭环。容量事件,不管是接近打满还是真被打挂了,都要复盘。预测为什么不准,是流量模型过时了还是有新的流量来源没考虑到。伸缩为什么不及时,是冷却时间设太长还是指标选错了。单点瓶颈暴露了什么,是不是某个之前没识别到的依赖成了天花板。每次复盘把预案和模型更新一遍,容量治理才能越做越准。把容量当成日常指标持续监控,而不是出事才查,这套机制才能真正运转起来。








