使用 Vegeta 对 vLLM 大模型进行性能压测实战
使用 Vegeta 对 vLLM 大模型进行性能压测实战记录
一、测试背景与目标
在之前使用 vllm bench serve 和 Locust 压测的基础上,本次引入 Vegeta 这一轻量级 HTTP 压测工具,针对 vLLM 部署的 Qwen2.5-7B-Instruct 模型进行性能测试。
核心目标:
- 掌握 Vegeta 在 vLLM 场景下的配置方法。
- 对比纯短文本、长短文本混合场景下的性能差异。
- 验证请求速率(RPS)对系统延迟的影响规律。
- 通过 Vegeta 的 HTML 可视化图表,直观定位性能瓶颈。
二、环境与工具准备
2.1 安装 Vegeta
# 下载并解压(以 v12.13.0 为例)
wget https://github.com/tsenart/vegeta/releases/download/v12.13.0/vegeta_12.13.0_linux_amd64.tar.gz
tar -zxvf vegeta_12.13.0_linux_amd64.tar.gz
sudo mv vegeta /usr/local/bin/
chmod +x /usr/local/bin/vegeta
# 验证
vegeta --version
2.2 vLLM 服务启动
source vllm_learn/bin/activate
python -m vllm.entrypoints.openai.api_server \
--model ./Qwen2.5-7B-Instruct \
--served-model-name qwen-7b \
--host 0.0.0.0 --port 8000
三、Vegeta 配置核心:Targets 文件格式
3.1 踩坑记录:JSON 格式 vs HTTP 格式
最初尝试使用标准 JSON 格式编写 target.json,导致报错 bad target: {。原因在于 Vegeta 要求 targets 文件必须是 JSON Lines(单行 JSON) 格式,不支持跨越多行的标准 JSON。
最终采用官方推荐的 HTTP 文本格式(最简洁、可读性最强):
target.json 内容:
# 第一个测试用例:基础文本生成
POST http://localhost:8000/v1/chat/completions
Content-Type: application/json
@./body.json
body.json 内容(短文本请求体):
{"model": "qwen-7b", "messages": [{"role": "user", "content": "你好"}], "max_tokens": 256, "stream": false}
3.2 长短文本混合配置(80% / 20%)
Vegeta 不直接支持权重比例设置,而是通过文件行数来控制概率。每行代表一个独立目标,Vegeta 每次请求时等概率随机选择一行。
- 实现 80% 短文本 + 20% 长文本:在
target.json中写 4 行短文本目标 + 1 行长文本目标(共 5 行,4/5 = 80%)。
body_short.json(短文本,max_tokens=50):
{"model": "qwen-7b", "messages": [{"role": "user", "content": "你好,请简单介绍一下你自己。"}], "max_tokens": 50, "stream": false}
body_long.json(长文本,max_tokens=500):
{"model": "qwen-7b", "messages": [{"role": "user", "content": "请详细解释一下大语言模型中的Transformer架构..."}], "max_tokens": 500, "stream": false}
target.json(混合配置):
# 短文本请求(占4/5,约80%流量)
POST http://localhost:8000/v1/chat/completions
Content-Type: application/json
@./body_short.json
POST http://localhost:8000/v1/chat/completions
Content-Type: application/json
@./body_short.json
POST http://localhost:8000/v1/chat/completions
Content-Type: application/json
@./body_short.json
POST http://localhost:8000/v1/chat/completions
Content-Type: application/json
@./body_short.json
# 长文本请求(占1/5,约20%流量)
POST http://localhost:8000/v1/chat/completions
Content-Type: application/json
@./body_long.json
四、核心测试过程与数据分析
4.1 测试一:纯短文本,rate=10,持续 60s
vegeta attack -targets=target.json -rate=10 -duration=60s -output=results.bin
vegeta report results.bin
| 指标 | 数值 |
|---|---|
| Requests | 600 |
| Throughput | 9.91 req/s |
| Mean Latency | 427 ms |
| P50 | 409 ms |
| P90 | 560 ms |
| P99 | 921 ms |
| Max | 1.503 s |
| Success | 100% |
结论:纯短文本场景下,系统极其健康,P99 < 1秒,成功率 100%。rate=10 完全在系统处理能力之内。
4.2 测试二:混合负载(80%短+20%长),rate=10,持续 60s
| 指标 | 数值 | 变化 |
|---|---|---|
| Throughput | 7.80 req/s | 下降 |
| Mean Latency | 5,536 ms | 恶化 13 倍 |
| P50 | 2,100 ms | 恶化 5 倍 |
| P90 | 19,931 ms | 恶化 35 倍 |
| P99 | 20,535 ms | 恶化 22 倍 |
| Max | 20,552 ms | — |
| Success | 100% | 稳定 |
结论:仅 20% 的长文本请求就导致 P90 延迟飙升至 20 秒。长任务长时间占用 GPU 资源,导致后续短任务被迫排队,形成“队头阻塞”。
4.3 测试三:混合负载,rate=2,持续 60s
| 指标 | 数值 | 变化 |
|---|---|---|
| Throughput | 1.58 req/s | 降 5 倍 |
| Mean Latency | 4,720 ms | 几乎没变 |
| P90 | 16,857 ms | 仅降 3 秒 |
| P99 | 17,046 ms | 仅降 3.5 秒 |
结论:降低请求速率并未显著改善延迟。根本原因是长任务(max_tokens=500,单次耗时约20秒)的到达速度(0.4 req/s)远超系统处理能力(约0.05 req/s),队列持续堆积。
4.4 测试四:混合负载,rate=1,持续 600s(10分钟)
vegeta attack -targets=target.json -rate=1 -duration=600s -output=results.bin
vegeta report results.bin
| 指标 | 数值 |
|---|---|
| Requests | 600 |
| Throughput | 0.97 req/s |
| Mean Latency | 4,684 ms |
| P50 | 1,716 ms |
| P90 | 16,633 ms |
| P99 | 16,657 ms |
| Max | 16,667 ms |
| Success | 100% |
结论:即使速率降到 1 RPS,P90 依然稳定在 16.6 秒。这说明瓶颈不在请求速率,而在于长任务本身的生成耗时。系统达到了“稳态排队”——进出速率平衡,队列不再增长。
五、Vegeta HTML 可视化图表解读
使用以下命令生成图表:
vegeta plot results.bin > plot.html

图表解读(以 rate=1 的 10 分钟测试为例):
- 横轴:时间(秒),纵轴:延迟(对数坐标)。
- 波谷(~1.7秒):代表 80% 的短文本请求,处理迅速。
- 规律性尖峰(~16.6秒):代表 20% 的长文本请求,每隔约 5 秒出现一次。
- 波形特征:呈完美的“梳齿状”,尖峰高度完全一致,说明系统处于稳态,没有出现延迟累积。
- 颜色:纯黄色(200 OK),无红色错误。
关键结论:图表直观证明了长短任务混合时的双峰延迟分布,并确认长任务排队时间稳定(16.6秒),系统未失控。
六、核心发现与生产建议
6.1 核心结论
- 长文本请求是性能杀手:仅 20% 的长任务(max_tokens=500)就能让 P90 延迟从 560ms 飙升至 20秒。
- 请求速率不是万能解药:将速率从 10 降到 1,P90 延迟仅从 20秒降至 16.6秒,改善极其有限。瓶颈在长任务的处理能力。
- 系统稳定性良好:所有测试中 Success 均为 100%,证明 vLLM 的 Continuous Batching 和 Chunked Prefill 机制有效避免了系统崩溃,但无法消除排队。
6.2 生产环境建议
- 限制单次生成长度:将
max_tokens控制在合理范围(如 200-300),可显著降低长任务延迟。 - 长短任务分离部署:为长文本请求(写文章、长文档摘要)分配独立实例,避免阻塞短问答请求。
- 引入优先级队列:长任务走低优先级队列,短任务走快速通道。
- 控制客户端速率:在网关层设置合理的限流阈值,避免请求堆积。
七、工具对比:Vegeta vs vLLM Bench vs Locust
| 工具 | 优势 | 劣势 | 适用场景 |
|---|---|---|---|
| Vegeta | 极简、轻量、HTTP层端到端测试、图表直观 | 不支持流式响应、无法测 TTFT/TPOT、比例控制靠行数 | 接口健康度基线测试、快速验证 |
| vLLM Bench | 专业、支持 TTFT/TPOT/Goodput、数据集灵活 | 配置稍复杂、侧重服务端指标 | 深度性能评测、SLO 达标分析 |
| Locust | 灵活、支持复杂业务逻辑、可模拟多轮对话 | 需自行编写脚本、指标计算靠自定义 | 模拟真实用户行为、业务场景测试 |
最佳实践:先用 Vegeta 做快速基线测试,再用 vLLM Bench 做深度性能分析,最后用 Locust 做业务场景验证。
测试环境:ModelScope 免费实例,vLLM 0.29.0,Qwen2.5-7B-Instruct,Vegeta v12.13.0。
浙公网安备 33010602011771号