上线前为什么值得做一次正经压测

很多人把“压测”理解成发布前临时跑一个脚本、看着数字还行就通过。但压测真正的价值是提前暴露瓶颈:一台 2 核 4G 的入门云服务器,50 并发时表现良好,加到 300 并发延迟可能直接翻十倍。与其让第一个真实用户来发现这个问题,不如在上线前用脚本把它逼出来。

下面这份清单把“压测”拆成四件事:定标准、选工具、跑真实场景、看监控证据。

第一步:先把“及格线”写下来

没有验收标准的压测等于没测。建议在压测前把下面这套阈值写进团队的验收文档,而不是压完再“看情况”:

指标 健康线 警戒线 失败线
CPU 峰值 < 60% 80% 90% 持续 5 分钟
内存峰值 < 70% 85% 90%+ 持续上涨不回落
95 分位响应时间 < 400ms 800ms 1200ms
错误率(5xx/超时) < 0.1% 0.5% 1%
磁盘 I/O 无排队 偶发阻塞 持续阻塞

需要注意,CPU 85%、内存 90% 这类数字不是“推荐负载”,而是“请立刻去查”的报警阈值。压测要回答的问题是“这台机器在什么负载下会开始变差”,而不是“它最多能扛多少”。

第二步:选对工具

常见压测工具有三档,按你的场景挑:

工具 特点 适合场景 学习成本
wrk 单机高并发、基于 C,性能极高 快速压测静态接口、Nginx
k6 脚本化、支持场景编排和阈值断言 模拟真实用户路径、CI 集成
Locust Python 编写、支持分布式 复杂业务流程、团队熟悉 Python

个人站和中小项目,用 k6 就够了:能写脚本模拟登录、浏览、下单这类真实路径,还能在脚本里直接写 thresholds,让压测失败自动报红。一个最小可用的 k6 脚本长这样:

import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  stages: [
    { duration: '2m', target: 50 },
    { duration: '2m', target: 100 },
    { duration: '2m', target: 300 },
    { duration: '2m', target: 500 },
    { duration: '2m', target: 0 },
  ],
  thresholds: {
    http_req_failed: ['rate<0.005'],
    http_req_duration: ['p(95)<800'],
  },
};

export default function () {
  const res = http.get('https://your-site.example/');
  check(res, { 'status is 200': (r) => r.status === 200 });
  sleep(1);
}

这段脚本会分四档把并发从 50 拉到 500,再缓缓降回 0,同时用两个阈值兜底:错误率低于 0.5%、95 分位响应低于 800ms。中途一旦越线,k6 会直接按失败退出。

第三步:按“真实访问”而不是“首页”来压

只压首页是最常见的偷懒。真实的访问是混合的:静态资源走 CDN、商品列表走缓存、下单接口直接打数据库。建议至少覆盖三类请求:

  • 静态资源(图片/CSS/JS):主要验证 CDN 回源和带宽;
  • 读接口(列表、详情):验证数据库查询和缓存命中;
  • 写接口(下单、提交表单):验证事务、锁、磁盘 IO。

给写接口压测时,别忘了同时观察慢查询日志连接池。很多压测“失败”其实不是机器不行,而是数据库连接数被写满,请求全部排队等连接。

第四步:用监控数据定位瓶颈

压测的同时要开着监控看。下面是一张常见的“症状 → 瓶颈”对照表:

症状 大概率瓶颈 看哪里
响应慢、CPU 高 应用逻辑或数据库查询 top、慢查询日志
内存持续上涨不回落 内存泄漏 进程 RSS、GC 日志
磁盘 I/O 阻塞 慢查询写放大、日志刷盘 iostatiotop
带宽先打满 静态资源未走 CDN iftop、CDN 回源统计
响应抖动、偶发超时 连接池耗尽、GC 停顿 连接池指标、GC 曲线

定位时记住一个原则:一次只改一个变量。把 Nginx 缓存打开、数据库加索引、PHP 换成 OPcache 这些改动混在一起做,压完你根本不知道是哪一项起了作用。

一个真实场景:双 11 前的临时加购高峰

假设你运营一个面向国内用户的电商小程序,往年双 11 当天晚 8 点会迎来一次并发陡增,平时峰值只有 200,当天可以冲到 1200。压测时就不要只按“日常 200 并发”来测,而是把时间拉到活动当晚的流量曲线:前 5 分钟快速爬升、高峰维持 30 分钟、尾段回落。

这种测试通常会暴露两类问题:一是数据库连接池按日常规模配置,高峰时连接被抢光,读接口大量超时;二是静态资源没有单独走 CDN 域名,图片请求把出口带宽打满,拖累接口响应。两者都能在压测报告里提前定位,而不是等用户截图投诉。

压测之后要交付什么

压测不只是为了“通过”,还要留下证据。一份合格的压测报告至少包含:

  1. 环境说明:机器规格、软件版本、压测工具与参数;
  2. 分阶段结果:每个并发档位的 QPS、P95/P99 延迟、错误率;
  3. 瓶颈清单:按影响排序的瓶颈和对应的证据(监控截图、慢查询);
  4. 建议动作:每一条建议都要能对应到具体的改动,而不是“建议优化性能”。

参考:k6 官方文档 https://grafana.com/docs/k6/latest/ ,wrk 仓库 https://github.com/wg/wrk

常见误区

最后列几个经常翻车的地方:拿本机压测代替线上(本机网络和缓存环境完全不同);只看平均响应时间不看 P95(平均被少数快请求拉低);压完不看慢查询(响应时间上升很大一部分都来自数据库);把压测机放在和被压服务器同一台机器上(互相干扰,结果失真)。