负载测试
施加真实和峰值流量,找到吞吐上限和第一个崩点。
为什么
性能问题在低流量下不出现。一个查询一个用户 50ms,1000 并发用户打同一未索引列就 50 秒,数据库连接池在 200 并发请求时耗尽而非 10。负载测试是在用户之前发现这些上限的唯一方式——在发布、营销推送、病毒时刻。目标不是为幻灯片产一个大数字;而是找到第一个瓶颈,理解为何崩,决定修它还是用自动扩缩和限流绕过它。
何时使用
任何发布前,任何可能引爆流量的营销事件前,以及作为周期性基线(每月)抓性能漂移。任何重大架构变更后(新缓存层、数据库迁移)也要跑。
如何做
1. 从真实分析定义负载画像,非猜测 - 从 APM 拉最近 30 天的 p50、p95、p99 请求率 - 确定峰值小时和端点混合(60% GET /products、20% POST /orders…) - 设目标:"持续 2x 峰值 10 分钟,p95 < 500ms" 2. 选能产生该量的工具 - k6(JS、开发者友好、支持 10k+ VU)或 Locust(Python) - Gatling(Scala、报告丰富)用于企业场景 - 从真能产生负载的机器跑(非你的笔记本) 3. 渐进爬升,别猛砸 - 0 → 100 VU 用 2 分钟,保持 100 五分钟,爬到 500 用 2 分钟,保持 - 突然尖峰啥也看不出——你分不清上限和冷启动 4. 负载下监控系统,非仅看测试结果 - 看 CPU、内存、DB 连接、缓存命中率、错误率、p99 延迟 - 第一个飙升的指标就是瓶颈;记下当时的 VU 数 5. 找到上限后停下分析 - 加负载直到错误率 > 1% 或 p95 > 目标——那就是上限 - profile 瓶颈(慢查询、连接池、GC 暂停、锁竞争) - 修或扩容,再测确认上限移动
示例
// k6 脚本: load-test-checkout.js
import http from "k6/http";
import { check, sleep } from "k6";
import { Rate, Trend } from "k6/metrics";
const errorRate = new Rate("checkout_errors");
const latency = new Trend("checkout_latency");
export const options = {
stages: [
{ duration: "2m", target: 100 }, // 爬到 100 VU
{ duration: "5m", target: 100 }, // 保持 100
{ duration: "2m", target: 500 }, // 爬到 500
{ duration: "5m", target: 500 }, // 保持 500——找上限
{ duration: "2m", target: 0 }, // 降下
],
thresholds: {
http_req_duration: ["p(95)<500"], // 95% 请求低于 500ms
checkout_errors: ["rate<0.01"], // < 1% 错误
},
};
export default function () {
const res = http.post("https://staging.example.com/api/checkout", JSON.stringify({
product_id: 42, qty: 1, token: __ENV.TEST_TOKEN,
}), { headers: { "Content-Type": "application/json" } });
errorRate.add(res.status !== 200);
latency.add(res.timings.duration);
check(res, { "状态 200": (r) => r.status === 200 });
sleep(1); // 1 秒思考时间
}
// 运行: k6 run --env TEST_TOKEN=xxx load-test-checkout.js常见问题
- ⚠从单台笔记本跑负载测试无法产生目标量——测试报"达到 5000 RPS"但笔记本网络是瓶颈,真实系统能扛 50k。
- ⚠用均匀随机数据而非真实分布意味着每个请求打不同商品,缓存永远不热,你测的是冷读性能而非真实混合负载。
- ⚠瞬间砸 1000 VU 而非爬升——你看到崩但分不清是冷启动(连接池初始化)、稳态负载还是真上限。
- ⚠只测快乐路径不测错误路径(支付拒绝、缺货)意味着错误处理路径在负载下未测,而它们自己可能就是瓶颈。
最佳实践
- ✓从有足够 CPU 和网络带宽的机器跑负载生成器——与目标同区域的云 VM,或 10k+ VU 用分布式 k6 集群。
- ✓从真实 APM 数 据(请求混合、峰值小时、思考时间)推导负载画像,使测试复现真实生产负载而非合成均匀打。
- ✓测试中监控目标系统内部(DB 连接、缓存命中率、GC 时间)——测试结果告诉你它崩了,监控告诉你为何。
- ✓把第一次负载测试当基线测量而非通过/失败——记下上限和瓶颈,每次优化后再测确认改善。