别等系统被压垮了,才知道容量到底有多大

简介: 别等系统被压垮了,才知道容量到底有多大

别等系统被压垮了,才知道容量到底有多大

我是 Echo_Wish。

做运维久了,你会发现一个挺有意思的现象:

很多系统都有容量指标,但真正到了极限的时候,没人知道它到底能扛多少。

文档里写着:

最大支持 10 万 QPS。

监控面板里写着:

CPU 最高 70%。

架构图上写着:

Redis 集群、MySQL 主从、消息队列、K8s 自动扩容,一应俱全。

看起来很稳。

可一旦真的来了流量洪峰,可能第一件事不是扩容,而是:

CPU 直接干到 100%,数据库连接池耗尽,Redis 开始抖,消息队列堆积,接口响应时间从 200ms 变成 20 秒。

然后大家开始问:

“为什么之前压测明明没问题?”

这时候往往才发现:

我们测试的是系统“能不能跑”,而不是系统“跑到哪里会撑不住”。

所以我越来越觉得,容量测试不能只盯着传统压测。

有时候,真正应该做的是:

用混沌工程主动把系统推向边界,甚至故意把它推过边界。

这就是我今天想聊的——容量边界测试,也可以理解成一次黑天鹅预演。


一、容量测试最大的误区:测出一个数字,就以为知道容量了

先说一个特别常见的场景。

某个订单接口,压测结果如下:

QPS        CPU        RT        错误率
-----------------------------------------
2000       35%        80ms      0%
4000       48%        95ms      0%
6000       63%        120ms     0%
8000       76%        180ms     0%
10000      88%        350ms     0%

于是测试报告写:

系统最大支持 10000 QPS。

看起来非常专业。

但问题来了:

为什么是 10000?

是因为测试到这里结束了?

还是因为 10000 已经是系统真正的极限?

如果继续压到 12000、15000、20000,会发生什么?

没人知道。

更麻烦的是,生产环境里的流量从来不是这么优雅的。

正常情况下可能是:

3000
3200
3500
3300

突然某一天:

3500
4800
7200
11000
16000

这时候你会发现,系统最重要的不是:

“平时能处理多少请求?”

而是:

“从什么时候开始,它会明显变差?”

这两个问题完全不是一回事。


二、真正应该找的,是“容量悬崖”

我特别喜欢把容量问题理解成一条曲线。

刚开始流量增加的时候,系统可能非常从容。

例如:

QPS       RT
----------------
1000      50ms
2000      60ms
3000      70ms
4000      85ms
5000      100ms
6000      130ms
7000      180ms
8000      300ms
9000      800ms
10000     3000ms

你会发现一个非常明显的现象:

系统不是到了某个数字以后突然挂掉,而是先进入一个越来越危险的区域。

7000 QPS的时候,也许还可以正常工作。

8000 QPS开始出现明显延迟。

9000 QPS已经非常难受。

10000 QPS直接雪崩。

这中间存在一个非常关键的东西:

容量悬崖。

也就是:

再增加一点负载,系统性能突然发生断崖式下降。

而混沌工程真正有价值的地方,就是帮我们主动找到这条悬崖在哪里。


三、混沌工程不是“把生产环境搞挂”

很多人一听混沌工程,第一反应就是:

“这不就是故意搞事情吗?”

其实不是。

混沌工程真正的核心思想,我觉得可以用一句特别接地气的话解释:

平时主动找问题,总比事故的时候被问题找上门强。

传统压测更多关注:

“系统在正常压力下表现怎么样?”

混沌工程关注的是:

“如果突然发生一些我们预料不到的事情,系统还能不能扛住?”

比如:

  • 流量突然增加 2 倍
  • 流量突然增加 5 倍
  • 某个节点 CPU 持续 100%
  • 数据库连接池耗尽
  • Redis 响应变慢
  • 消息队列大量堆积
  • 下游接口响应时间突然增加
  • 某个服务实例大量重启
  • 网络延迟突然增加

这些事情平时可能觉得:

“应该不会发生吧。”

但黑天鹅最大的特点就是:

你觉得它不会发生,它偏偏可能发生。

所以容量边界测试,其实就是在问:

如果今天真的发生了,我的系统会怎么死?


四、第一步:别急着压,先定义“什么叫撑不住”

这是很多测试容易忽略的地方。

如果你只是不断增加 QPS,然后看服务器什么时候 CPU 100%,其实意义并没有那么大。

因为:

CPU 100% ≠ 系统不可用。

有些服务 CPU 90% 还能稳定跑。

有些服务 CPU 60%,数据库已经开始排队。

所以容量边界必须有明确的业务指标。

比如:

成功率 < 99.9%
P95 > 500ms
P99 > 2s
数据库连接池使用率 > 90%
消息队列堆积 > 10000
CPU > 90% 持续 5 分钟

这些指标组合起来,才是我们的“红线”。

例如:

def is_capacity_boundary(metrics):
    return (
        metrics.success_rate < 0.999
        or metrics.p95 > 0.5
        or metrics.p99 > 2
        or metrics.db_pool_usage > 0.9
    )

这时候测试的目标就很清晰了:

不是把服务器打爆,而是找到业务开始不可接受的那个点。


五、第二步:不要一步干到最大,要逐步加压

容量边界测试最忌讳:

一上来直接 5 倍流量。

这样虽然很刺激,但得到的信息其实很少。

你只知道:

“系统挂了。”

但你不知道:

“它到底从什么时候开始不行?”

更合理的方式是阶梯式加压。

比如:

1000 QPS
    ↓
2000 QPS
    ↓
3000 QPS
    ↓
4000 QPS
    ↓
5000 QPS
    ↓
6000 QPS
    ↓
7000 QPS
    ↓
8000 QPS

每一个阶段持续一段时间。

同时观察:

CPU
Memory
GC
线程池
连接池
RT
P95
P99
错误率
Redis
DB
MQ

然后继续增加。

甚至可以把压测程序写成自动探测:

qps = 1000

while True:
    result = run_test(qps)

    print(
        f"QPS={qps}, "
        f"P95={result.p95}, "
        f"P99={result.p99}, "
        f"Error={result.error_rate}"
    )

    if is_capacity_boundary(result):
        print(f"发现容量边界:{qps} QPS")
        break

    qps += 500

这样做以后,测试就不再是:

“压一下看看。”

而变成了:

“自动寻找系统容量边界。”

这才有点混沌工程的味道。


六、第三步:真正有意思的,是给系统增加“黑天鹅”

如果只做阶梯式 QPS 压测,其实还不够。

因为生产环境最危险的情况,往往不是单纯流量增加。

而是:

流量增加 + 某个依赖同时变慢。

例如:

正常:
用户请求
   ↓
订单服务
   ↓
库存服务
   ↓
数据库

平时一切正常。

但是突然:

用户流量 × 3
      ↓
订单服务
      ↓
库存服务响应时间 × 5
      ↓
线程大量等待
      ↓
连接池被占满
      ↓
请求开始排队
      ↓
超时
      ↓
重试
      ↓
流量进一步增加
      ↓
系统雪崩

这才是现实世界里非常典型的事故链。

所以容量边界测试真正应该做的是:

负载 + 故障组合。

例如:

experiment = {
   
    "traffic": {
   
        "qps": 8000
    },
    "dependency": {
   
        "inventory_api_latency": 2000
    },
    "duration": 300
}

然后观察:

8000 QPS + 下游延迟 2 秒的时候,系统还能不能活?

如果还能活,再测试:

8000 QPS + 下游延迟 5 秒
8000 QPS + Redis 延迟
8000 QPS + DB连接池限制
10000 QPS + 下游异常

这时候你测到的,才越来越接近真正的生产事故。


七、还有一个特别容易被忽略的问题:恢复能力

我一直认为:

容量测试不能只测试“什么时候挂”,还必须测试“挂了以后能不能回来”。

比如:

10:00  正常
10:05  流量增加
10:10  达到容量边界
10:12  开始大量超时
10:15  降低流量

然后问题来了:

10:20系统恢复了吗?

有时候并没有。

因为系统已经产生了:

MQ堆积
线程堆积
数据库慢查询
连接池耗尽
缓存击穿
大量重试
任务积压

流量恢复正常以后,这些历史债务还在那里。

于是出现一种特别经典的情况:

流量已经恢复了,系统为什么还没恢复?

这就是容量测试中非常值得关注的:

恢复边界。

可以进一步定义:

def recovery_check(metrics):
    return (
        metrics.error_rate < 0.001
        and metrics.p95 < 0.5
        and metrics.queue_depth < 100
    )

最终你应该得到的不只是:

最大容量 8000 QPS。

而应该是:

稳定容量:6000 QPS

风险区间:6000 ~ 7500 QPS

容量边界:约 7500 QPS

超过边界后的主要故障:
- DB连接池耗尽
- P99急剧上升
- MQ开始堆积

恢复时间:
流量恢复后约 8 分钟

这份结果对生产运维的价值,比单纯写一句“最大支持 8000 QPS”大得多。


八、最终要算的,其实不是“最大容量”,而是“安全容量”

这里我特别想强调一个观点。

生产环境不应该把系统跑在理论最大容量附近。

如果你的测试结果是:

最大容量:10000 QPS

然后生产环境规划:

长期运行:9500 QPS

我只能说:

胆子挺大。

因为生产环境还有很多你测试时没有考虑到的变量:

  • 突发流量
  • 网络抖动
  • GC
  • 数据库慢查询
  • 第三方接口异常
  • 节点故障
  • 发布
  • 定时任务
  • 批处理任务
  • 流量分布变化

所以我更推荐一个简单的容量模型:

安全容量 = 理论边界 × 安全系数

例如:

capacity = 10000
safety_factor = 0.7

safe_capacity = capacity * safety_factor

print(f"建议生产安全容量:{safe_capacity:.0f} QPS")

最后得到:

理论边界:10000 QPS
建议安全容量:7000 QPS

这样即使突然来一波流量,也还有喘息空间。


九、我更希望看到的,是一张“系统死亡地图”

如果让我设计一套完整的容量边界测试,我不会只要一份压测报告。

我更想要这样一张东西:

                  流量增加
                     ↑
                     │
        稳定区       │
                     │
      ┌──────────────┐
      │              │
      │    正常运行   │
      │              │
      └──────┬───────┘
             │
             ↓
       性能下降区
             │
       P99开始上涨
       DB开始排队
       MQ开始堆积
             │
             ↓
        容量危险区
             │
       超时 / 重试
       连接池耗尽
             │
             ↓
        系统雪崩区

然后再给每一个区域标注:

安全容量:6000 QPS

预警容量:7000 QPS

危险容量:7500 QPS

理论极限:8000 QPS

恢复时间:8分钟

第一故障点:数据库连接池

第二故障点:线程池

第三故障点:MQ堆积

这时候运维人员才真正知道:

这个系统到底能跑到哪里。


十、真正的黑天鹅预演,不是预测事故,而是提前认识自己的脆弱

最后说点我的感受。

很多公司做容量规划的时候,特别喜欢问:

“我们的系统能支撑多少用户?”

但我觉得这个问题本身就有点问题。

因为用户数并不能直接代表系统压力。

真正应该问的是:

“当压力超过设计能力以后,我们的系统会以什么方式失败?”

这是两个完全不同的问题。

系统不可能永远不出问题。

再牛的架构,也有容量上限。

再完善的高可用,也不可能覆盖所有故障组合。

真正成熟的运维,不应该追求:

“我们的系统绝对不会挂。”

而应该追求:

“我知道它什么时候会开始出问题,也知道它最先从哪里开始出问题,更知道出问题以后多久能恢复。”

这才是混沌工程真正有价值的地方。

我们不是为了把系统搞挂,而是趁它还没有真的挂之前,先问一遍:

如果今天真的来了一只黑天鹅,我们扛得住吗?

如果不知道答案,那就别等事故告诉你。

自己先把它压到边界。

因为生产事故最贵的地方,从来不是服务器挂了。

而是:

你明明有机会提前知道,却选择了相信“应该不会发生”。

这可能才是容量治理里,最值得我们警惕的一句话。

目录
相关文章
|
8天前
|
云安全 人工智能 运维
当攻击全面Agent化,你的安全防御能否跟上AI Speed?
多起客户侧AK泄露事件应急的真实观察
1320 6
|
6天前
|
人工智能 API 开发工具
DeepSeek Harness 神插件:白嫖 13 家大厂模型
`dsh-our-free-model` 是 DeepSeek Harness 神级插件:零配置、零API Key、零账号,聚合13家大厂免费模型(含DeepSeek V4.1 Flash、Kimi K3等),支持本地网关、用量看板与自动降级,真正实现“白嫖即用”。
1128 21
|
2天前
|
存储 人工智能 自然语言处理
阿里云千问办公官网登录入口:qwenwork.cn网页版免下载,注册送2000积分、登录每日再送100积分
千问办公(QwenWork)是阿里巴巴推出的一站式AI办公平台,定位"不止于对话,更注重交付"。它基于千问大模型,具备任务拆解与多步骤自动执行能力,用户一句话即可完成PPT生成、数据分析、网页搭建、视频剪辑、信息调研等复杂任务,覆盖网页端、桌面端及钉钉生态。网页版免下载,访问qwenwork.cn注册即得2000积分,每日登录再送100积分。个人版免费起用,另有付费版与企业版可选。
|
11天前
|
存储 人工智能 安全
千问办公官网入口网页版登录:qwenwork.cn 注册送2000积分、登录送100积分
阿里云千问办公(QwenWork)是AI智能工作平台,支持一句话生成PPT、表格、网页、视频及数据分析。个人免费版送2000积分+每日登录赠100分,含1GB存储、5个发布页;企业版198元/席/月起。阿里千问办公QwenWork官网:https://t.aliyun.com/U/0VCTGt 阿里AI工作平台,一句话完成数据分析、PPT 生成、视频剪辑、网页搭建等复杂任务
|
6天前
|
人工智能 开发者
Qoder CN 大使计划正式开启|无限创造,等你一起
全年免费积分、优先内测、活动支持与更多共创机会,邀请用 Qoder 把想法变成现实的你。
567 6
|
1月前
|
人工智能 JSON API
全网刷屏的 Jev 模型正式开放!一手实战测评 + 保姆级教程
全网爆火的 Jev 模型是什么?有什么用?怎么使用?怎么接入 AI 编程工具?效果真的好么?傻子可懂的 Jev 保姆级实战教程 + 项目实战测评来啦
10037 33
|
7天前
|
安全 Linux 芯片
【万字长文】Ollama下载、安装、配置、使用保姆级教程(2026最新图解)
Ollama 是一款免费开源的本地大模型运行工具,支持 DeepSeek、Qwen 等主流模型,一条命令即可下载运行。2026 最新版 v0.35.1 官方安装包(1.47GB)已提供国内直连下载,纯本地、离线可用、无广告、无隐私泄露风险。
685 1
|
17天前
|
存储 人工智能 并行计算
大模型本地部署终端选型方法论:以 Qwen3.8-27B 为例的四档分层完整流程
本文提出一套大模型本地部署终端选型方法论:定约束、定档位、定框架、定参数四步决策法,配合入门、主力、质量、无损四档分层模型。以 Qwen3.8-27B 实测数据为例,逐环节解读显存、带宽、存储、散热、系统、预算等要素,给出面向不同预算的优选方案、决策自查清单与市场观察框架。文末前瞻 AI 笔记本的 CPU+GPU 与统一内存两条路线,论证四步决策法在新品类上的延续性。
|
8天前
|
Web App开发 人工智能 JavaScript
太猛了,一个月干到15W+,给大家推荐一个最近爆火的开源逆向工具:REA
REA(Reverse Engineer Anything)是近期爆火的开源AI逆向工具,4月发布,1个月内斩获15万+ Star。它让AI Agent无需源码即可分析二进制、APK、JS/Electron、HAR包等17类目标,自动反编译、生成可运行代码,并强制返回带证据与局限的结论。全本地执行,MIT协议,支持Hopper/Ghidra/IDA等引擎,一行命令即可上手。
794 2
太猛了,一个月干到15W+,给大家推荐一个最近爆火的开源逆向工具:REA

热门文章

最新文章