「
这是 2026 年的第二篇技术手记。承接上一篇的基准测试,本篇聚焦负载测试验证与瓶颈定位方法论。
—— 疯狂输出
📋 本篇导读
01 一次“翻车”实践:从 400m CPU 到 13% 错误率的踩坑记录
02 指标之间的“因果”:输入→处理→输出的完整因果链
03 问题排查五步法:从错误率到内存占用的系统排查
在上一篇《服务上线前,怎么估算 Pod 资源?》中,我们通过基准测试推算出了 APISIX 网关的初始资源配置。但估算值到底靠不靠谱,还得靠负载测试来验证。
所以本文主要是对压测时那些指标的解释和瓶颈的判断,并从此次压测过程总结一套可复用的方法论。
PRACTICE
一开始没有进行基准测试,参考了一个不同类型的服务然后直接分配资源400m CPU / 512Mi 内存,经过三轮压测下来:
并发数 | QPS | 错误率 | 现象 |
|---|---|---|---|
100 | 859 | 0.08% | 还行,但远低于目标 |
500 | 1080 | 0.46% | QPS 卡住上不去 |
1000 | 1360 | 13.09% | 错误率飙到 13.09% |
QPS 才 1000 出头,目标是 4000。完全没有达到预期,而且错误率也达到13.09%。查看压测日志发现大部分失败请求响应结果出现大量 500 的错误。内存占用也很高。
排查问题之前需要先学会看指标以及前后的因果关系,这样才能更清晰地定位问题以及分配合适资源额度。
· · ·
CAUSALITY
压测时我们关注的 9 个指标是有一条因果链,前置输入影响后置的结果输出。如果从端到端的性能视角出发,压测过程就可抽象成输入 → 处理 → 输出三个核心环节。
压力输入层 处理时资源消耗层 用户体验层
┌──────────┐ ┌──────────────┐ ┌──────────────┐
│ 并发数 │─────────────▶│ CPU 使用率 │────────────▶│ 平均响应时间 │
│ QPS/TPS │ │ CPU throttle │ │ P95/P99 │
│ │ │ 内存占用 │ │ 错误率 │
│ │ │ │ │ │
└──────────┘ └──────────────┘ └──────────────┘
• 输入层:目标 QPS 达到 4000 和压测时输入的并发数。
• 压测处理时资源消耗:CPU 使用率、CPU throttle、内存占用。
• 用户体验层结果表现:平均响应时间、P95/P99、错误率。
瓶颈判断的核心思路:从结果表现看异常,然后查看资源消耗去排查原因,最终确认是压力输入过载还是资源不足。
· · ·
TROUBLESHOOT
第一步:查看错误率
根据错误率的值识别问题。
错误率 | 状态 | 含义 |
|---|---|---|
< 0.1% | 正常 | 偶发错误,可忽略 |
0.1-1% | 需关注 | 可能有局部瓶颈 |
1-5% | 异常 | 服务已过载或配置有问题 |
> 5% | 严重 | 必须立即处理 |
错误率 >= 0.1% 时都需要关注,要查看日志信息排查问题:
• 错误信息是5XX,说明服务端处理失败,需要查看后端日志。
• 错误信息是429,说明触发了限流。在测试网关的限流功能时,就发生了 429 的错误信息。
• 错误信息是timeout,说明连接池、数据库存在瓶颈。
• 错误信息是connect refused,说明无法达到后端或者后端已达到最大连接数。
所以看到错误率高,要先查看错误信息,定位错误原因。若后端日志有数据库失败,可能就是后端服务的数据库连接池瓶颈,不是网关问题。
第二步:查看平均响应时间
平均响应时间只能用来判断当前服务大概的响应情况。先通过公式计算预估响应时间 = 并发数 / 预估 QPS。比如目标 QPS=4000,并发 100 时,预估响应时间 = 100/4000 = 0.025ms,但压测时平均响应时间是 0.925ms。
如果实测平均响应时间 >> 预估响应时间,说明请求在排队等待,系统已经出现积压。
第三步:查看 P95 / P99 响应时间
P95 表示 95% 的请求在此时间内完成,P99 表示 99% 的请求在此时间内完成。注意:这里的响应时间不是说 99%/95% 的请求都是这个响应时间,而是指这个响应时间内。
比如 99% 响应时间是 900ms,那说明有 1% 的响应时间超出 900ms,说明是少数请求有问题。
• 平均响应时间 VS 预估响应时间:可以判断系统是否出现大面积积压问题。
• P95/P99:能判断少数请求是否异常慢(尾部延迟信号)。
• 两者配合:平均正常但 P99 异常 → 尾部慢请求;平均和 P99 都异常 → 大面积过载。
第四步:查看 CPU 使用率
CPU 使用率 | 状态 | 含义 |
|---|---|---|
< 50% | 空闲 | 资源过剩,可以降配 |
50-70% | 健康 | 日常运行的最佳区间 |
70-80% | 偏高 | 峰值可接受,但日常运行需关注 |
80-90% | 紧张 | 接近极限,需评估是否扩容 |
> 90% | 危险 | 随时可能 throttle 或响应变慢 |
所以日常运行时只要 CPU 使用率 < 70%,峰值 CPU 使用率 < 80% 基本满足正常需求,但是超过 80%,就需要进行扩容或优化。
警惕发生 CPU throttle
发生 CPU throttle 现象是:CPU 使用率 < 100%,但是超过 limits 设置的值时,K8s 会通过 CFS 周期性限制进程的 CPU 时间,就会发生 QPS 一直无法上升,但是P99 一直在上升。
value = cpu_cfs_throttled_periods / cpu_cfs_periods,当 value > 0 时说明发生 throttle,值越高说明越严重。
最佳解决方案:
• 提高limits配置。
• 提高requests,保证有足够 CPU 资源用于调度。
• 直接设置 requests = limits,非必要不要这样配置。
第五步:查看内存占用
内存占用 | 状态 | 含义 |
|---|---|---|
< 50% | 空闲 | 资源过剩 |
50-70% | 健康 | 日常运行安全区间 |
70-80% | 偏高 | 峰值可接受 |
80-90% | 紧张 | 接近 OOM Kill 风险线 |
> 90% | 危险 | 随时可能被 OOM Kill |
所以正常运行只要保证 50% < 内存 < 70%,峰值时也要保证 < 80%。如果内存达到 100% 就可能发生OOM Kill,服务就挂掉了,相当于发生P0 级故障。
警惕发生内存泄漏
压测过程内存占用先涨后降回原来的位置,说明没有发生内存泄漏。
要测试出有没有发生内存泄漏,至少要进行多次压测(如 3-5 次),每轮压测结束都能正常回落,再次压测能再次上升。还要注意隐形泄漏,如果每轮压测内存占用不一样、差距比较大,也可能有内存泄漏。
每次压测 3 分钟、5 分钟可能不会暴露问题,至少要进行一次长时间的压测。
· · ·
CASES
踩坑一:错误率达到 15.32%
发生这个问题时,查看了压测日志看到很多错误码是 500,网关接口转发是没有问题的,所以查看业务服务日志发现有很多数据库查询发生超时了,原因应该就是并发太高,导致数据库连接池打满了,优化后重新压测就正常了。
经验总结:要关注背后真正的错误原因。
踩坑二:P99 约 600ms
发生 P99 约 300ms,不确定是网关还是后端的问题。直接对后端的接口进行压测,不经过网关,P99 是 653ms,说明性能瓶颈主要在后端服务。
经验总结:网关压测要关注是业务服务的问题还是网关服务的问题。
· · ·
NOTES
• 混合接口场景:线上真实流量是多种接口混合的。如果只压单一最轻的接口,QPS 可能是理想值;线上混合流量下可能退化 30-50%。建议先测裸转发,再测带插件场景,对比退化幅度。
• 多 Pod 节点 QPS 非线性叠加:1 个 Pod 能扛 3000 QPS,2 个 Pod 不一定能扛 6000。共享资源(后端数据库、缓存)会成为新的瓶颈。水平扩展后必须再压一轮验证。
• 网关依赖:网关会配置鉴权、限流、日志等插件,以及一些认证服务,必须重新压测验证。
• 压测时长要够:5 分钟能看基本性能,但测不出长时间运行的内存泄漏和 GC 问题。关键服务建议至少跑 30 分钟。
指标速查表
指标 | 健康水位 | 警戒水位 | 危险水位 | 判断要点 |
|---|---|---|---|---|
CPU 使用率 | < 70% | 70-80% | > 80% | 还要查 throttle 比率 |
CPU throttle | < 5% | 5-20% | > 20% | 比率 > 0 就要关注 |
内存使用率 | < 70% | 70-80% | > 80% | 超限直接 OOM Kill |
错误率 | < 0.1% | 0.1-1% | > 1% | 先看错误信息分类 |
P99 | 业务相关 | - | - | 必须拆分:网关 vs 后端 |
如果你觉得今天这篇有收获,欢迎 点赞、在看、转发 三连,我们下篇见