服务器如何模拟真实访问做压测
学完这篇,你能从零搭出一套「像真人一样访问」的压测方案:不再是 curl 循环刷一个接口,而是还原登录态、混合接口、思考时间和逐步加压,最终拿到可信的 QPS、P95 延迟和拐点数据。
第一步:先定指标,别急着敲命令
这一步要产出的是「一张压测目标表」,没有它,跑完你也不知道合格不合格。至少要写清四项:
- 目标 QPS:比如 800 req/s
- P95 延迟:比如 < 300ms
- 错误率:比如 < 0.1%
- 并发用户数:比如 200 VU(虚拟用户)
注意:P95 比平均值重要得多。平均 50ms 而 P95 是 2s,说明有 5% 的用户在骂人。
第二步:准备干净的环境和真实量级的数据
压测机不能和被测服务抢 CPU,数据量级要接近生产(比如生产 500 万条订单,你拿 1000 条测,缓存全命中,结果毫无意义)。
准备测试账号和 ID 池:
seq 1 50000 | shuf > uids.txt # 5 万个随机商品/用户 ID
注意:绝对不要直接压生产库。要么用独立压测环境,要么用只读影子库,否则压测写进去的垃圾订单清理起来很痛苦。
第三步:先用 ab 打一个基线
这一步要的是「单接口天花板」,方便后面和真实场景对比。用 ApacheBench 在压测机上执行:
ab -k -n 20000 -c 200 \
-H "Authorization: Bearer eyJhbGci..." \
-H "User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 17_0)" \
"http://10.0.0.5:8080/api/v1/items/1001"
-k开启长连接(不加就是 HTTP/1.0 短连接,结果偏低)-n总请求数,-c并发数
注意:ab 是单进程单线程,本机并发超过 500 时压测机自身可能先跑满 CPU。可用
top看一眼,压测机 CPU > 80% 时结果不可信。
第四步:用 k6 写「真人行为」脚本
这一步要的是最接近真实用户流量的脚本。k6 是单文件二进制,装完直接跑,脚本用 JavaScript 写。核心是把「随机参数 + 登录态 + 思考时间 + 混合请求」都写进去:
import http from 'k6/http';
import { sleep, check } from 'k6';
export const options = {
scenarios: {
real_user: {
executor: 'ramping-vus',
stages: [
{ duration: '1m', target: 50 },
{ duration: '2m', target: 100 },
{ duration: '2m', target: 200 },
{ duration: '1m', target: 0 },
],
},
},
thresholds: {
http_req_duration: ['p(95)<300'],
http_req_failed: ['rate<0.001'],
},
};
const BASE = 'http://10.0.0.5:8080';
export default function () {
// 随机商品 ID,避免缓存全命中
const id = Math.floor(Math.random() * 50000) + 1;
const res = http.get(`${BASE}/api/v1/items/${id}`, {
headers: {
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X)',
'Authorization': `Bearer ${__ENV.TOKEN}`,
'Accept': 'application/json',
},
});
check(res, { 'status is 200': (r) => r.status === 200 });
// 思考时间 1~3 秒,模拟人在看页面
sleep(Math.random() * 2 + 1);
// 10% 的用户会下单
if (Math.random() < 0.1) {
http.post(`${BASE}/api/v1/orders`,
JSON.stringify({ itemId: id, count: 1 }),
{ headers: { 'Content-Type': 'application/json',
'Authorization': `Bearer ${__ENV.TOKEN}` } });
}
sleep(1);
}
运行:
k6 run -e TOKEN=eyJhbGci... --out json=result.json loadtest.js
注意:
sleep()千万别省。没有思考时间的压测等于用机器人狂点,测出来的 QPS 会虚高好几倍,上线就雪崩。
第五步:阶梯加压,找拐点
k6 的 stages 已经帮你做了:50 → 100 → 200 VU 每档跑 2 分钟。重点盯三个指标随并发的变化曲线:
- QPS 涨不动了 → 到了容量拐点
- P95 突然从 200ms 跳到 1.5s → 队列开始堆积
- 错误率从 0 抬头 → 要么超时,要么连接池打满
同时登录被压服务器看 top、vmstat 1、GC 日志和数据库慢查询,确认瓶颈在 CPU、连接池还是慢 SQL。
第六步:记录并清理
把脚本、参数、目标表、监控截图一起归档,下次回归直接对比。压测产生的订单、账号用脚本按 create_time 批量删掉。
注意:如果服务开了限流或 WAF,压测流量会被拦截,错误率飙升却不代表服务有问题。压测前先在上游网关把你的压测机 IP 加白名单。
小结
- 先定指标(QPS、P95、错误率、并发),再动手压
- 数据量级和请求头要还原真实,ID 必须随机化,否则缓存骗你
- 思考时间
sleep()是真实感的灵魂,不能省 - 用 ab 打单接口基线,用 k6 做混合场景 + 阶梯加压
- 盯拐点而不是盯平均值,压测机自身 CPU 别超过 80%
- 环境隔离、数据清理、限流白名单,三件事提前做
原文链接:https://www.gj0.com/thread-866.html
转载请注明出处并保留本声明;内容仅代表作者观点,与本站立场无关。若本文涉嫌侵权,请联系本站处理。