ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

vLLM 并发性能测试指南:用 TaoToken 统一 Key 跑通压测配置

vLLM 并发性能测试指南:用 TaoToken 统一 Key 跑通压测配置 1. 为什么 vLLM 并发压测总在“最后一公里”翻车vLLM 的并发性能测试说白了就是回答两个问题这套推理服务在多少并发下还能稳住延迟以及吞吐的天花板到底卡在哪。很多开发者第一次跑benchmark_serving.py时单请求验证没问题一旦把 request-rate 拉到 30、40就开始出现超时、连接被拒、甚至脚本直接崩掉。问题往往不在 vLLM 本身而在测试链路的入口——鉴权、路由、限流、日志采集这几层没有统一。我见过最常见的场景是本地 vLLM 服务用--api-key起了压测脚本却忘了带 Authorization 头结果每个请求都返回 401脚本还傻乎乎地统计“错误率 100%”。另一种情况是测试流量和生产流量走不同通道压测结果根本没法复现到线上。这篇指南要解决的就是这件事用 TaoToken 统一 Key 和 API 通道把压测流量和真实调用收敛到同一条链路上让 QPS、TTFT、TPOT 这些指标真正可对比、可复现。适合谁看正在评估 vLLM 推理服务吞吐与延迟的开发者、需要给模型服务做容量规划的工程师、以及想把压测脚本沉淀成可重复流程的团队。下面从环境准备开始一步步给出可复制的配置骨架。2. TaoToken 前置统一 Key 与 API 通道怎么接TaoToken 在这里扮演的角色是“统一入口”。你不需要在每个压测脚本里硬编码不同的 endpoint 和 key而是通过一个统一的 API 通道把测试流量发出去。这样做的好处是压测配置和线上调用配置保持一致换模型、换并发梯度时只改参数不改链路。先拿到访问凭证。打开官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册后在控制台创建 API Key。控制台地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsole 。创建完 Key 后在 API Keys 页面可以查看和管理https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keys 。API 的基础地址是 https://taotoken.net/api 注意这个地址不带 UTM 参数直接用于代码里的 base_url。如果你用的是 OpenAI 兼容的客户端把 base_url 指向它、api_key 填 TaoToken 的 Key 即可。模型对话调试可以在 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodels 里先手动发一条请求确认 Key 和模型名都对得上再去跑压测脚本能省掉很多“脚本报错但不知道是 Key 还是模型名错”的排查时间。注意压测脚本里的并发梯度不要一上来就拉满。先用 1 个请求确认链路通再按 5、10、20、30 的梯度往上加每一步都记录指标这样瓶颈出现在哪一档一目了然。3. 可复制配置vLLM 服务 压测脚本骨架3.1 启动 vLLM 服务先确保没有旧进程占着端口然后启动服务。下面这段配置去掉了--api-key因为鉴权统一交给 TaoToken 通道处理本地服务只负责推理。kill $(ps aux | grep vllm serve | grep -v grep | awk {print $2}) 2/dev/null || echo No vLLM process found. /opt/conda/bin/vllm serve /models/DeepSeek-R1-Distill-Llama-70B \ --host 0.0.0.0 \ --port 8000 \ --tensor-parallel-size 4 \ --max-model-len 8192 \ --swap-space 16 \ --served-model-name MetaX-DeepSeek-R1-70B \ --gpu-memory-utilization 0.9 \ --disable-log-requests \ --trust-remote-code \ --dtype half启动后用一条最小请求确认服务活着curl http://localhost:8000/v1/completions \ -H Content-Type: application/json \ -d {model: MetaX-DeepSeek-R1-70B, prompt: Hello, max_tokens: 5}返回里有生成文本就说明推理服务正常。这一步别跳过否则后面压测报错你分不清是服务没起还是脚本写错。3.2 压测脚本骨架下面这个run_concurrency_test.sh把并发梯度、请求参数、结果落盘都固定下来。关键点是--base-url指向 TaoToken 的 API 通道--api-key用环境变量传入避免把 Key 写死在脚本里。#!/bin/bash set -e RESULT_DIR./benchmark_results/concurrency_test mkdir -p $RESULT_DIR LOG_FILE$RESULT_DIR/concurrency_test.log exec (tee -a $LOG_FILE) 21 echo 并发测试开始 $(date) REQUEST_RATES(5 10 20 30 40 50) COMMON_ARGS --backend openai --base-url https://taotoken.net/api --model MetaX-DeepSeek-R1-70B --tokenizer /models/DeepSeek-R1-Distill-Llama-70B --dataset-name random --random-input-len 512 --random-output-len 256 --num-prompts 200 --disable-tqdm --trust-remote-code --tokenizer-mode auto for rate in ${REQUEST_RATES[]}; do echo 开始测试: Request Rate $rate req/s RESULT_FILE$RESULT_DIR/result_rate_${rate}.json python benchmark_serving.py \ $COMMON_ARGS \ --request-rate $rate \ --result-dir $(dirname $RESULT_FILE) \ --result-filename $(basename $RESULT_FILE) echo 完成: $RESULT_FILE echo 等待 10 秒... sleep 10 done echo 所有并发测试完成结果保存在: $RESULT_DIR运行前把 Key 导出到环境变量export TAOTOKEN_API_KEY你的Key chmod x run_concurrency_test.sh ./run_concurrency_test.shbenchmark_serving.py会读取OPENAI_API_KEY或脚本里指定的 key 参数具体以你本地 vLLM 版本为准。如果脚本不认环境变量就在COMMON_ARGS里加--api-key $TAOTOKEN_API_KEY。3.3 指标采集项每个 JSON 结果文件里重点看这几个字段QPS、TTFT首 token 延迟、TPOT每 token 延迟、错误率。这四个指标组合起来才能判断“是吞吐上不去还是延迟崩了”。只看 QPS 容易误判因为高并发下 QPS 可能靠错误请求堆出来。指标含义关注点QPS每秒完成请求数是否随并发线性增长TTFT首 token 延迟用户感知的响应速度TPOT每 token 延迟长文本生成的流畅度Error Rate错误请求占比超过 5% 说明已过载4. 验证请求与成功结果长什么样跑完一轮后先看日志里有没有 401 或 429。401 通常是 Key 没传对429 是触发了限流。确认没有这两类错误后打开结果 JSON 看数值。一个健康的并发曲线大致是这样request-rate 从 5 加到 30 的过程中QPS 稳步上升TTFT 从 500ms 缓慢涨到 1800ms错误率保持在 2% 以内。到了 40、50 这一档QPS 不再增长甚至回落TTFT 跳到 3000ms 以上错误率飙到 15% 以上——这就是系统瓶颈点。用下面这段 Python 把结果画出来比盯 JSON 直观得多import matplotlib.pyplot as plt import json rates, qps_values, ttft_values, tpot_values, error_rates [], [], [], [], [] for rate in [5, 10, 20, 30, 40, 50]: with open(f./benchmark_results/concurrency_test/result_rate_{rate}.json) as f: data json.load(f) rates.append(rate) qps_values.append(data[qps]) ttft_values.append(data[median_ttft_ms]) tpot_values.append(data[median_tpot_ms]) error_rates.append(data.get(error_rate, 0)) plt.figure(figsize(10, 6)) plt.plot(rates, qps_values, labelQPS) plt.plot(rates, ttft_values, labelTTFT (ms)) plt.plot(rates, tpot_values, labelTPOT (ms)) plt.xlabel(Request Rate (req/s)) plt.ylabel(Metrics) plt.title(Concurrency Test Results) plt.legend() plt.grid(True) plt.show()如果曲线在某一档突然拐头那一档就是你要重点排查的并发阈值。接下来可以针对这一档做单变量实验固定 request-rate只改--random-input-len或--random-output-len看是输入长度敏感还是输出长度敏感。5. 本篇常见错排查Unauthorized / 401最常见。检查--api-key是否传进了benchmark_serving.py以及 base_url 是否写成了https://taotoken.net/api而不是带路径的地址。用 curl 先手动打一条请求验证 Key 有效。Token indices sequence length 报错tokenizer 和模型不匹配。确认--tokenizer指向的路径和--model是同一个模型--trust-remote-code已加上。连接被拒 / Connection refusedvLLM 服务没起来或者端口被占。用curl http://localhost:8000/v1/completions确认服务活着再跑压测。QPS 上不去但错误率为 0可能是--num-prompts太小请求提前跑完了。把--num-prompts调到 500 以上让每个并发档位有足够样本。结果波动大两次跑同一档位结果差很多通常是 GPU 显存碎片或后台有其他进程。跑之前用nvidia-smi确认显存干净每档之间 sleep 时间加到 15 秒。提示压测期间用nvidia-smi -l 1实时看 GPU 利用率。如果 GPU 利用率已经 95% 以上但 QPS 不涨瓶颈在算力如果 GPU 利用率不高但 QPS 上不去瓶颈在请求链路或调度。6. 把压测沉淀成可重复流程跑通一轮不代表什么能重复跑出同样的曲线才有价值。建议把 Key 管理、脚本、结果目录都固定下来Key 走环境变量脚本进版本控制结果按日期分目录。这样下次换模型或调参数时直接对比新旧曲线就能看出改动的影响。如果你后续要把压测扩展到长期编码或 Agent 场景可以了解 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-plan 。接入细节和参数说明在文档里https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdoc 。Claude Code 相关的接入配置参考https://taotoken.net/claudecode-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentclaudecode-anthropic 。最后留一个实操建议每次压测前先跑一档 request-rate1 作为基线记录当时的 TTFT 和 TPOT。后面所有并发档位都跟这个基线比延迟涨了多少倍、QPS 涨了多少倍两个倍数的交叉点就是性价比最高的并发区间。这个动作花不了两分钟但能让你在容量规划时少拍很多脑袋。
返回列表