3. 性能基准测试:使用 wrk/locust 进行接口压测,建立基线
在优化延迟之前,必须建立可量化的性能基线。本章将指导你使用 wrk(轻量级 HTTP 压测工具)和 Locust(分布式负载测试框架)对模型评分接口进行压测,并记录关键指标作为后续优化的参照基准。
3.1 为什么需要性能基线
没有基线,优化就是盲目的。基线提供了三个核心价值:
- 量化起点:明确当前接口的 P50/P95/P99 延迟、吞吐量(RPS)和错误率。
- 回归检测:每次代码变更后,通过对比基线判断是否引入性能退化。
- 容量规划:根据基线数据推算单机承载能力,为扩缩容提供依据。
基线记录规范:每次压测结果应记录到版本控制系统的
perf/ 目录下,命名格式为 baseline_{日期}_{版本号}.json,确保可追溯。
3.2 工具选型对比
| 特性 | wrk | Locust |
|---|---|---|
| 定位 | 单机高并发压测 | 分布式、场景化压测 |
| 协议支持 | HTTP/1.1, HTTPS | HTTP, gRPC, WebSocket |
| 脚本语言 | Lua(可选) | Python |
| 实时监控 | 命令行输出 | Web UI + 图表 |
| 适用场景 | 快速获取延迟分布 | 模拟复杂用户行为 |
3.3 使用 wrk 建立快速基线
wrk 适合在开发环境快速验证接口性能。以下命令对评分接口进行 30 秒压测,使用 8 个线程、64 个连接:
wrk -t8 -c64 -d30s --latency \
http://localhost:8080/v1/score \
-s post.lua
其中 post.lua 脚本内容如下:
wrk.method = "POST"
wrk.body = '{"features": [0.1, 0.2, 0.3, 0.4, 0.5]}'
wrk.headers["Content-Type"] = "application/json"
典型输出示例:
Latency Distribution (HdrHistogram - Recorded Latency)
50.000% 8.12ms
75.000% 12.45ms
90.000% 18.76ms
99.000% 34.21ms
99.900% 52.80ms
Requests/sec: 1245.67
Transfer/sec: 1.23MB
关键指标解读:
- P50 (8.12ms):半数请求在 8ms 内完成,代表典型体验。
- P99 (34.21ms):1% 的请求超过 34ms,是长尾延迟的衡量标准。
- Requests/sec (1245.67):当前配置下的吞吐量上限。
- P50 (8.12ms):半数请求在 8ms 内完成,代表典型体验。
- P99 (34.21ms):1% 的请求超过 34ms,是长尾延迟的衡量标准。
- Requests/sec (1245.67):当前配置下的吞吐量上限。
3.4 使用 Locust 进行场景化压测
Locust 通过 Python 脚本定义用户行为,适合模拟真实调用模式。以下脚本模拟 100 个用户以 10 的生成率启动,持续 5 分钟:
from locust import HttpUser, task, between
import json
class ScoreUser(HttpUser):
wait_time = between(0.5, 2.0)
@task(3)
def score_normal(self):
payload = {"features": [0.1]*10}
self.client.post("/v1/score",
json=payload,
headers={"Content-Type": "application/json"})
@task(1)
def score_batch(self):
payload = {"instances": [[0.1]*10 for _ in range(5)]}
self.client.post("/v1/score_batch",
json=payload,
headers={"Content-Type": "application/json"})
启动命令:
locust -f locustfile.py --host=http://localhost:8080 \
--users=100 --spawn-rate=10 --run-time=5m \
--headless --csv=baseline_report
生成的 baseline_report_stats.csv 包含每个时间点的平均响应时间、RPS 和失败率,可直接导入图表工具。
3.5 基线记录模板
每次压测后,将以下信息记录到基线文档中:
| 指标 | 值 | 说明 |
|---|---|---|
| 测试日期 | 2025-03-20 | — |
| 服务版本 | v1.2.3 | Git commit hash |
| 硬件配置 | 4C8G, SSD | CPU/内存/磁盘 |
| 并发用户数 | 100 | Locust 峰值 |
| P50 延迟 | 8.12 ms | 中位数 |
| P99 延迟 | 34.21 ms | 长尾 |
| 吞吐量 (RPS) | 1245.67 | 每秒请求数 |
| 错误率 | 0.02% | 4xx/5xx 占比 |
3.6 压测流程与基线建立步骤
- 环境准备:确保服务独立部署,关闭日志输出、监控采集等干扰项。
- 预热:先发送 1000 个请求,让 JIT 编译和缓存达到稳态。
- 正式压测:使用 wrk 获取延迟分布,使用 Locust 获取场景化吞吐量。
- 数据收集:保存 wrk 的 HdrHistogram 输出和 Locust 的 CSV 报告。
- 基线归档:将结果存入
perf/baseline/目录,并更新 README。
常见陷阱:
- 不要在压测机上运行其他高负载进程(如浏览器、IDE)。
- 确保压测机与目标服务在同一内网,避免网络延迟干扰。
- 每次基线测试前,重启服务以清除前次测试的缓存影响。
- 不要在压测机上运行其他高负载进程(如浏览器、IDE)。
- 确保压测机与目标服务在同一内网,避免网络延迟干扰。
- 每次基线测试前,重启服务以清除前次测试的缓存影响。
3.7 基线建立流程示意图
下图展示了从环境准备到基线归档的完整流程:
3.8 基线对比与异常判定
建立基线后,后续每次优化迭代都应重新压测并与基线对比。以下表格给出异常判定阈值:
| 指标 | 正常波动范围 | 需关注 | 严重退化 |
|---|---|---|---|
| P50 延迟 | ±10% | +20% | +50% |
| P99 延迟 | ±15% | +30% | +80% |
| 吞吐量 (RPS) | ±10% | -20% | -40% |
| 错误率 | ≤0.1% | 0.5% | ≥1% |
自动化建议:将基线数据写入 Prometheus 或 InfluxDB,配合 Grafana 设置告警规则。当新版本的 P99 延迟超过基线 30% 时,自动触发 CI 流水线回滚。