当前位置: 首页 > news >正文

压力测试实战:基于Locust的高并发场景稳定性验证

所有的架构设计和代码优化,最终都要在压力测试的烈火中接受检验。对于DeepSeek推理服务,我们不能简单地用abwrk这种针对静态网页的工具来测,因为大模型的请求是长连接,且计算负载与Prompt长度高度相关。

Locust是一个基于Python的开源压测工具,它允许我们编写Python代码来模拟真实用户的行为,非常适合测试复杂的AI接口。本文将介绍如何使用Locust对DeepSeek服务进行全方位的性能与稳定性验证。

1. 为什么不能用ab/wrk?

ab(Apache Bench) 和wrk是Web服务器压测的神器,但在LLM场景下,它们有几个致命缺陷:

  1. 无法模拟流式响应:它们只关注HTTP状态码和整体耗时,无法解析SSE流,无法统计TTFT (Time To First Token)这一关键指标。
  2. 请求内容静态:大模型对输入长度极其敏感。处理10个Token和1000个Token的负载天差地别。ab只能发送固定的Payload,无法模拟真实世界中长短不一的对话分布。
  3. 缺乏思考时间:真实用户在发完一句话后,会阅读、思考、再发下一句。wrk是无脑轰炸,这会导致并发压力虚高,无法反映真实的系统承载能力(Capacity)。

2. 模拟真实负载:Locustfile编写指南

我们需要模拟真实的业务流量分布。根据OpenAI的公开数据,典型的对话长度分布服从泊松分布

  • 10%的用户只发短问题(<50 Token)。
  • 80%的用户进行中等长度对话(500 Token)。
  • 10%的用户上传长文档(>5k Token)。

创建一个locustfile.py

fromlocustimportHttpUser,task,between,eventsimportjsonimporttimeimportrandomclassDeepSeekUser(HttpUser):# 模拟用户思考时间:1到5秒之间wait_time=between(1,5)@task(10)# 权重10,短对话defchat_short(self):self.send_request(prompt_len=50,output_len=100)@task(1)# 权重1,长文档defchat_long(self):self.send_request(prompt_len=5000,output_len=500)defsend_request(self,prompt_len,output_len):# 构造伪数据,实际测试中可以使用真实语料库prompt="test "*prompt_len payload={"prompt":prompt,"max_new_tokens":output_len,"temperature":0.7,"stream":True# 开启流式}start_time=time.time()first_token_time=Nonetoken_count=0# 使用catch_response手动处理结果withself.client.post("/generate",json=payload,stream=True,catch_response=True)asresponse:ifresponse.status_code!=200:response.failure(f"Status code:{response.status_code}")return# 模拟接收流式响应try:forlineinresponse.iter_lines():ifnotline:continue# 记录首字时间ifnotfirst_token_time:first_token_time=time.time()ttft=(first_token_time-start_time)*1000# 自定义上报TTFT指标events.request.fire(request_type="grpc",name="TTFT",response_time=ttft,response_length=0)token_count+=1total_time=time.time()-start_time# 计算生成速度tps=token_count/(total_time-(first_token_time-start_time))exceptExceptionase:response.failure(f"Stream error:{e}")

3. 核心指标解读与分析

运行压测命令:locust -f locustfile.py --host http://localhost:8000 --headless -u 50 -r 1

在控制台或Web UI中,我们需要重点关注以下指标,并学会透过数据看本质:

3.1 RPS vs TPS

  • RPS (Requests Per Second):对于长任务,RPS可能很低(比如0.5)。这不代表性能差,因为一个Request可能持续20秒。
  • TPS (Tokens Per Second):这是衡量LLM服务吞吐量的黄金指标。需要在服务端统计,或者像上面代码那样在Locust端估算。
    • 正常曲线:随着并发用户数增加,TPS应该线性增长,直到达到显存带宽瓶颈,然后趋于平稳。
    • 异常曲线:如果并发增加,TPS反而下降,说明发生了严重的资源争抢(如Python GIL锁竞争、Cache Thrashing)。

3.2 Latency: P99 vs Average

  • 平均延迟:毫无意义,千万别看。因为长短任务混杂,平均值会被长任务拉高,掩盖了短任务的性能问题。
  • P99 Latency:尾部延迟。如果P99飙升,说明系统内部出现了排队(Queuing)
    • 排队原因:Dynamic Batching的等待队列满了,或者是KV Cache显存不足导致Swap。

3.3 Failure Rate

  • Timeout:Nginx或客户端设置的超时时间太短。
  • Connection Reset:服务端进程崩溃(OOM)。
  • 503 Service Unavailable:负载均衡器主动拒绝了请求(熔断)。

4. 稳定性测试(Soak Testing)

除了测极限性能(Stress Test),还需要测长期稳定性。让Locust以中等负载(比如60%峰值)连续运行24小时。

重点观察对象

  1. 显存泄漏(Memory Leak)
    • 使用npu-smi info监控。显存占用应该在一定范围内波动。如果发现显存占用随时间呈现锯齿状上升,且低谷越来越高,说明有Tensor未释放。
  2. 僵尸进程
    • 检查ps -ef | grep python。是否有处理完请求但未退出的孤儿进程。
  3. 温度墙(Thermal Throttling)
    • 长时间满载可能导致NPU温度过高(>80度),触发硬件降频。这会导致推理速度突然变慢。

5. 混沌测试(Chaos Testing)

进阶玩家还可以尝试“搞破坏”,验证系统的高可用性(HA)。

  • 断网演练:在压测过程中,模拟网络丢包(iptables -I INPUT -m statistic --mode random --probability 0.1 -j DROP),看客户端SDK是否能自动重连。
  • 杀节点:随机Kill掉一个推理Pod,看负载均衡器能否快速(<3秒)剔除故障节点,并将流量转移到健康节点。
  • 显存碎片化模拟:发送大量长度极其怪异的请求(如[1, 8192, 3, 4000]),通过极端分布测试PagedAttention的内存碎片整理能力。

6. 总结

压测不是为了生成一份漂亮的报告,而是为了发现系统的崩溃点(Breaking Point)

  • 如果不测TTFT,你就不知道用户等待首字的焦虑。
  • 如果不测长文档并发,你就不知道显存什么时候会OOM。
  • 如果不做24小时稳定性测试,你就不知道内存泄漏会在深夜搞垮服务。

通过基于Locust的全方位实战验证,我们不仅能摸清DeepSeek服务的性能边界(Capacity Planning),还能提前暴露那些只在极端并发下才会出现的Race Condition和资源竞争Bug,确保上线即稳如磐石。

http://www.jsqmd.com/news/327362/

相关文章:

  • dify 教程目录
  • 必看!2026年单北斗GNSS水库变形监测TOP五大推荐产品
  • 精选的优秀法证分析工具和资源列表
  • Astral3D 教程目录
  • Clipper2 教程目录
  • Docker 到底变成了什么?从“容器之王”到“开发者工具箱+AI 基建+安全公司”的奇妙漂流
  • Clipper1 教程目录
  • 金融科技创新对传统金融业的冲击与机遇
  • 独家分享:一线提示工程架构师用Agentic AI解决金融客户留存问题的实战技巧
  • Maven 引入外部依赖
  • Java毕设项目:基于Java Web的毕业设计选题管理系统的设计与实现(源码+文档,讲解、调试运行,定制等)
  • 使用 JTS 快速检测狭窄多边形
  • 【毕业设计】基于Java Web的毕业设计选题管理系统的设计与实现(源码+文档+远程调试,全bao定制等)
  • PDF一机一码加密大师1.1.0更新至2026最新版, 强力加密PDF, 无需额外安装阅读器, 附CSDN下载地址
  • 链表 part02
  • [豪の算法奇妙冒险] 代码随想录算法训练营第三十七天 | 完全背包理论基础、518-零钱兑换Ⅱ、377-组合总和Ⅳ
  • AppML 案例未来
  • Python 循环嵌套
  • 期末考小记
  • 10404_基于Springboot的校园网络安全防御系统
  • 【Week6_Day28】【软件测试学习记录与反思】【阶段四 Python, 收集问题, 反思改进,写博客】
  • Java多线程编程技巧:面试必看的几种实现方式!
  • 第16章 - 与 QGIS 集成
  • “信息安全”与“网络安全”区别
  • 《文明6》Leaders.xml 文件标签解析指南
  • 文明六MOD入门:从零开始制作一个巫师文明
  • 实用指南:虚拟现实与增强现实:改变我们的数字体验
  • Skills精选
  • 第16章:性能优化与最佳实践
  • 开题报告_基于知识图谱的个性化学习微信小程序设计与开发