压测与容量评估:场景、指标与限流验证
上线前最怕“看起来正常、流量一来就挂”。压测回答三个问题:系统能扛多少量、瓶颈在哪、限流/熔断是否按预期兜底。本章讲压测怎么做、看哪些指标、以及如何验证限流策略。
核心指标先对齐口径
| 指标 | 含义 | 关注点 |
|---|---|---|
| QPS/TPS | 每秒请求数/事务数 | 容量上限的直接刻度 |
| RT(avg/p99/p999) | 响应时间 | 平均值会骗人,重点看 p99:99% 请求在多少毫秒内 |
| 错误率 | 4xx/5xx/超时占比 | 容量拐点往往伴随错误率抬升 |
| 饱和度 | CPU/内存/线程池/连接池使用率 | 找瓶颈在谁身上 |
| 队列与等待 | 线程池排队数、GC 停顿 | 慢调用放大的前兆 |
经验法则:容量拐点 = 吞吐不再随并发上升(甚至下降)、RT 与错误率开始抬头。压测不是“打出一个最大数”,而是找出这条拐点曲线。
压测场景设计
按被测范围分层推进,避免“只压网关,下游全是假数据”的失真:
- 单接口压测:先摸清每个核心接口的容量基线(如下单接口单独能扛多少)。
- 单服务压测:mock 下游或压真实下游,观察线程池/连接池是否成为瓶颈。
- 全链路压测:网关→订单→库存→支付完整链路,按真实流量比例混合场景(读多写少等),这是上线前的关键依据。
- 异常场景压测:主动让一个下游变慢/宕机,验证熔断、降级、超时设置是否让系统优雅降级而不是雪崩。
工具选择:JMeter 适合协议复杂与断言丰富的场景;wrk/ab 适合单接口快速压测;Gatling/k6 适合脚本化与 CI 集成。压测流量要打标(如请求头带压测标识),避免污染线上业务数据与监控。
压测步骤与节奏
- 准备独立压测环境(或线上低峰+影子流量),数据量与线上同量级——数据量太小会高估容量(索引全在内存)。
- 阶梯加压:从低并发逐步抬升(如 100→200→400→800 QPS 每档稳定几分钟),记录每档的 RT/错误率/饱和度,找出拐点。
- 定位瓶颈:压测同时盯数据库慢 SQL、连接池、GC、Redis 命中率、下游服务,用监控把瓶颈定位到具体层。
- 回归验证:修复瓶颈后重测,对比优化前后曲线,沉淀容量基线数据。
# wrk 单接口压测示意(示例地址)
wrk -t8 -c200 -d60s --latency http://example.com/api/order/page
容量评估:从压测结果推算资源
容量规划 = 峰值流量 × 冗余系数 ÷ 单实例容量:
示例:下单峰值 800 QPS,单实例可扛 200 QPS,冗余系数 1.5
实例数 = 800 × 1.5 ÷ 200 = 6 个实例
- 峰值口径:日常峰值、大促峰值(双 11/秒杀)要分开评估。
- 冗余系数:通常 1.5~2 倍,还要给“单可用区故障切换”留余量。
- 评估要落到“实例数/内存/连接数”而不是抽象百分比,让运维可直接落地。
- 容量是动态的:每次大版本、数据量翻倍后要重新压测,基线数据要维护成文档。
限流与熔断验证
压测还承担“验证保护策略是否生效”的职责:
- 限流验证:压到超过限流阈值,确认多余的请求按预期被拒绝或排队。网关层集中限流(Redis RequestRateLimiter)看是否返回 429/提示文案;服务层限流(Resilience4j RateLimiter)看是否走降级逻辑。
- 熔断验证:让下游故障率超过阈值,确认熔断打开、上游快速失败而不是傻等;恢复后确认半开探测能自动闭合。
- 降级验证:熔断/限流触发后,降级返回是否符合预期(缓存兜底/默认值/友好提示),不能把错误直接透传给用户。
- 验证“保护本身不过度”:限流阈值设太低,正常流量被误杀;压测数据要反哺阈值调整。
# 示例:网关 Redis 限流阈值(按 KeyResolver 维度)
spring:
cloud:
gateway:
redis-rate-limiter:
replenish-rate: 200 # 每秒补充 200 个令牌
burst-capacity: 400 # 突发容量 400
小结
压测与容量评估的产出不是一份“最高 QPS”报告,而是一组可决策的数据:容量拐点曲线、瓶颈清单、限流熔断生效证明、实例数建议。把它做成发布流程的固定环节(版本压测门禁),容量风险就不会在线上爆发时才暴露。