系统容量规划与性能压测实战:从估算到上线的一次完整推演
容量规划不是"买大点"就能解决的。本文从一次真实的启动决策出发,完整推演目标负载→选型估算→压测验证→灰度放量的全过程,覆盖 Web 服务、AI 推理和数据库三种典型场景。含负载估算公式和压测脚本。【点击查看完整推演过程】
先说结论:容量规划的终极目标不是”不宕机”,而是”知道什么时候会宕”
容量规划和性能压测是”防患于未然”中最容易被忽视的一环——不是因为大家不知道它重要,而是因为”估算一下”听起来太简单,而”压测太花时间不如先上线”的诱惑力太大。
但几乎所有线上事故中,有相当比例的根本原因都可以归结为一句话:没有在真实负载下验证过系统的极限在哪里。
本文不做理论推导,而是从一个真实场景出发:你接了一个新项目,预计上线后第一个月有 10 万注册用户、平均每天 5000 DAU、峰值 2000 并发。需要多少台服务器?数据库要什么配置?怎么验证它扛得住?
第一步:从业务指标反推技术指标
在碰服务器之前,先把业务语言翻译成技术语言。
| 业务指标 | 换算方式 | 技术指标 |
|---|---|---|
| 10 万注册用户 | ≈ 10% DAU 转化率 | 10,000 DAU |
| 5000 DAU | 每人日均 30 次请求 | 150,000 请求/天 |
| 峰值 2000 并发 | 推算系数 5 | 峰值 QPS ≈ 350 |
| AI 功能占比 30% | 50% 用户每日用 3 次 | AI 推理峰值 ≈ 50 QPS |
基准估算公式:
平均 QPS = 日请求数 / 86400 ≈ 1.7 QPS
峰值 QPS = 平均 QPS × 峰值系数(5-8) ≈ 350 QPS
这是你的技术目标——系统需要在不降级的前提下稳定处理 350 QPS。
第二步:分层的资源估算
Web 服务层
单台 4C8G 云服务器在小流量场景下大约能处理 200-400 QPS(取决于业务逻辑复杂度)。但这里有个常见的估算陷阱:不考虑慢查询和第三方依赖。
优化后的估算方法:
单机能力 = 1000ms / (平均处理时间 × 串行依赖数)
如果你的 API 平均耗时 20ms(含数据库查询和缓存),串行调用 2 个下游服务,那么:
单机能力 ≈ 1000 / (20 × 2) ≈ 25 QPS 每连接
对于 350 QPS,两台 4C8G 服务器做互备足够了。核心结论:瓶颈 90% 不在 Web 服务器本身,而在下游数据库和依赖。
数据库层
这是容量规划中最容易算错的一层。一个常见错误是:「我的表只有 10 万行,一个 SELECT 怎么可能慢?」
考虑这个查询:
SELECT orders.*, users.name, products.title
FROM orders
JOIN users ON orders.user_id = users.id
JOIN products ON orders.product_id = products.id
WHERE orders.status = 'pending'
ORDER BY orders.created_at DESC
LIMIT 20;
10 万行数据、三表 JOIN、无合适索引——单次查询耗时可能超过 500ms。在 350 QPS 下,数据库连接池只有 50 个连接,很快就会被慢查询耗尽。
数据库估算的三条原则:
- 每个查询独立测量:不要相信”这个查询应该很快”——实际 EXPLAIN 看一下
- 考虑连接池:350 QPS 需要评估连接池大小,以及每个连接处理耗时
- 预留写放大空间:一个 INSERT 可能引发索引更新、触发器、CDC 复制
对于 350 QPS 的场景,推荐起点配置:8C16G 数据库实例(PG/MySQL),连接池 50-80,缓存层用 Redis。
AI 推理层(如果你的系统涉及)
AI 推理的容量规划和传统 Web 完全不同——瓶颈在 GPU 显存和算力,而不是 CPU 和内存。
估算流程:
每请求显存 = 模型加载大小 + KV Cache 开销
单卡最大并发 = 可用显存 / 每请求显存 × 0.65(安全系数)
吞吐(Token/s) = 单卡算力 / 模型参数量 × 批处理大小
以一个常用的 14B 模型为例(FP16 约 28GB):
- 单张 A100 (80GB) 理论并发 ≈ (80 - 28) / 2×128K = 约 200 (理论,实际远低于此)
- 实际稳定并发 ≈ 40-60
- 每请求平均生成 500 Token → 40 并发下约 3-5 秒完成
AI 容量规划的特殊之处在于它不能靠加机器线性扩展——需要同时考虑显存带宽、跨卡通信效率、批处理调度策略。唯一可靠的验证方式是用真实数据和真实模型做压测。
第三步:压测——验证你的估算
估算完了,怎么知道算得对不对?压测。
压测金字塔
/ 全链路压测(端到端)
/ 模块级压测(单服务)
/ 组件级压测(单接口/单查询)
先底部后顶部:先分别压每个接口和每个查询,再压全链路。否则一个慢查询拖垮整个压测,你都不知道该优化哪里。
工具选型
| 场景 | 推荐工具 | 原因 |
|---|---|---|
| HTTP API 压测 | wrk 或 k6 | wrk 轻量级单机够用,k6 支持场景编排和指标输出 |
| 数据库查询 | pgbench / sysbench | 直接模拟查询负载,排除网络开销干扰 |
| AI 推理 | vLLM benchmark_serving.py | 官方工具,支持多种请求率和并发模式 |
| 全链路 | k6 + influxdb 或 locust | k6 脚本化场景更灵活,locust Python 生态更适合团队 |
一个完整的压测流程
# 1. 基线压测:单接口 100 QPS,持续 3 分钟
k6 run --vus 50 --duration 3m --rps 100 script.js
# 2. 极限压测:逐步增加 QPS,找到拐点
k6 run --vus 200 --duration 5m --rps 500 script.js
# 3. 持续压测:目标 QPS 维持 30 分钟,看是否平稳
k6 run --vus 100 --duration 30m --rps 350 script.js
# 4. 突发压测:模拟流量瞬间翻倍
k6 run --vus 200 --duration 1m --rps 700 script.js
必须记录的四个指标:
- P50 / P95 / P99 延迟——P99 超过 1000ms 且频率超过 5% 就预警
- 错误率——任何 5xx 都是问题,4xx 检查是否业务逻辑触发限流
- CPU 和内存趋势——正常的系统在持续压力下应该趋于平稳,不断上升说明有泄漏
- 数据库连接数和慢查询数——压测时的数据库状态最反映真实问题
第四步:从压测结果到容量决策
压测跑完了,怎么看结果?
典型结果解读矩阵
| 压测结果 | 可能原因 | 解决方案 |
|---|---|---|
| QPS 远低于目标,CPU 空闲 | I/O 瓶颈(数据库、网络、磁盘) | 检查慢查询、加索引、用连接池、升级 IOPS |
| QPS 接近目标但 P99 急剧恶化 | 资源竞争(连接池耗尽、锁等待) | 增加连接数、优化锁粒度、引入读写分离 |
| 持续压测 10 分钟后开始报错 | 内存泄漏或 GC 风暴 | 检查堆内存趋势、排查未释放资源、调 GC 参数 |
| 突发流量瞬间 5xx | 缺乏限流保护 | 加服务端限流(令牌桶/漏桶),降级非核心功能 |
| 数据库 CPU 100%,查询变慢 10x | 查询计划因数据量变化变差 | ANALYZE 更新统计信息、优化查询、增加索引或改分区键 |
上线前的容量决策清单
- 目标峰值 QPS 是多少?压测验证达到了吗?(留有 30% 余量)
- 单点故障是否考虑?至少 2 台互备
- 数据库连接池大小是否合理?350 QPS 建议 50-80 连接
- 缓存策略是否就位?热数据缓存命中率预计多少
- 限流和降级是否实现?超过目标 QPS 时的行为是限流 vs 降级 vs 熔断
- 扩容方案是否文档化?需要多少时间加一台机器
- AI 推理的显存和吞吐是否在预期范围内?TTFT 和 TPOT 达标吗
第五步:灰度放量——用真实流量验证
压测再逼真也只是模拟。上线当天的真实流量才是最终验证。
推荐灰度策略:
5% → 20% → 50% → 100%
每个阶段观察 30 分钟到 2 小时,确认延迟和错误率稳定后再继续。如果某阶段 P99 超过 1000ms,暂停放量,回去查原因。
上线后的第一天重点关注三个指标:
- 错误率——任何爬升趋势都要立刻介入
- P99 延迟是否能稳定在 500ms 以内
- 数据库连接数是否在预期范围
总结
容量规划的核心不是算出”准确数字”,而是建立一套从估算到验证的闭环:
业务指标 → 技术指标 → 资源估算 → 压测验证 → 容量决策 → 灰度确认
每上线一个新系统或大功能,走一遍这个流程。不需要每次都做全量压测——对于小改动,估算 + 单接口压测就够了。但对于涉及 AI 推理、数据库变更或新增外部依赖的改动,全链路压测是必要的。
你不会因为是压测而错过上线时间——你只会因为是没压测而线上事故。
正在设计系统容量?需要做一个完整的性能压测方案?联系我们获取免费咨询。
相关阅读:
- 企业私有知识库 RAG 落地实战 — RAG 场景的 GPU 显存与并发容量决策
- 云成本优化实战:从账单分析到架构治理 — 容量规划和成本优化是一个硬币的两面
- 监控与告警体系设计 — 系统上线后如何持续掌握运行状态
- Docker Compose 部署实战 — 中小项目的部署配置与容量管理
- 消息队列选型指南 — 异步削峰:用消息队列缓解突发流量
常见问题
容量规划应该从什么时候开始做?
最晚在上线前三周开始。第一周做估算和选型(确定目标 QPS 和资源基线),第二周搭环境和写压测脚本,第三周执行压测并调优。如果在灰度前一周才想到要看容量,一定来不及——你可能需要改代码、加索引、调参数,这些都需要时间。
压测的 QPS 目标设多少合适?
以线上实际流量的 3-5 倍为目标。如果还没有线上数据,按商业模式推导:日活 × 日均请求数 ÷ 86400 × 峰值系数。峰值系数建议取 5-8(取决于业务类型——电商取 8,SaaS 取 5,企业内部系统取 3)。不仅要测正常 QPS,还要测突发 QPS(瞬间 2 倍)和持续 QPS(半小时以上的恒定压力)。
为什么实际表现和估算差那么多?
最常见的三个原因:① 数据库查询不是 O(1)——估算时以为一个 SELECT 只要 2ms,实际 JOIN 了 5 张表花了 200ms;② 第三方依赖没考虑——你的 API 很快但下游写入 Elasticsearch 限流了;③ 冷启动 vs 热启动——刚重启的服务需要几十秒预热才能达到峰值性能。解决方法是:估算时对每个依赖做悲观假设(×3),压测时覆盖冷热两种状态。
AI 推理服务的容量规划有什么特殊之处?
AI 推理将容量规划问题放大了一个维度:GPU 显存决定了"能不能跑",算力决定了"跑多快",两者互相耦合。核心指标是 TTFT(首 Token 延迟)和 TPOT(每个 Token 的增量延迟)。估算方法:单卡并发 = 显存 ÷ 模型加载大小 ÷ KV Cache 每请求开销;实际能跑到的并发通常只有理论值的 60-70%。建议用 vLLM 或 TGI 等推理框架自带的压测工具(benchmark_serving.py)实测,不要只看理论值。