服务没报错但突然变慢?我查到了一个没人动过的配置
某天,用得好好的一个长上下文推理服务,"突然变慢"了。
变慢的场景很具体:两三万 token 的长提示词,首字延迟明显恶化,体验断崖式下滑。
而监控大盘,全绿。没有报错,没有告警,请求量持平。
服务"一切正常",就是慢。
这篇是完整的排查复盘。先说结论里最反直觉的一条:监控全绿不等于服务正常,它只等于"你知道怎么测的那些东西"正常。
为什么大家第一反应都不是配置
性能出问题,业内的常识排查顺序是:先查代码变更,再查流量负载,实在不行怀疑硬件。几乎没人第一反应去怀疑"没人动过的配置",配置又不长腿。
我当时的预期也一样:这种长提示词的首字延迟,大概率是负载涨了,或者某个上游依赖抖了。
预期和现实差了四层排查。
排查链:从最俗的可能性开始
性能排查最忌讳上来就怀疑玄学。我的顺序固定:
网络层,链路延迟有没有变?排除。
负载层,并发是不是涨了?排除,请求量持平。
资源层,GPU 利用率、显存、队列深度。发现线索:利用率没有异常升高,但每 token 延迟变高了。单位工作量的效率降低了,这是"环境变了"的指纹,不是"活变多了"的指纹。
配置层,服务配置和"上周正常时"比,有没有不一样?
这一层,抓到人了。
那笔调优的来龙去脉
要讲清楚真凶,得先讲我做过的一笔调优。
这个推理服务跑的是长上下文场景,vLLM 的 max-num-batched-tokens 出厂默认 256。部署的时候 vLLM 日志里有一条官方 WARNING,点名这个默认值太保守、会拖慢长提示词的 prefill。
我做了个严格的 A/B:固定同一段 23K token 的提示词、同一套测试脚本,单变量调参,测首字延迟:
| max-num-batched-tokens | 23K 提示词 TTFT | 备注 |
|---|---|---|
| 256(默认) | 71.1 秒 | 出厂基线 |
| 1024 | 54.3 秒 | 1.31 倍 |
| 4096 | 43.1 秒 | 1.65 倍,定为生产值 |
| 8192 | 启动即崩 | 中间激活 buffer 挤占 KV 池,vLLM 硬校验拒绝 |
4096 定稿前还做了正确性验证:一段 17K token 文档的精确检索 QA,答案完全正确,提速没有以牺牲正确性为代价。decode 侧有轻微波动带上移,换来 prefill 的 1.65 倍,这笔账划算。
注意 8192 那行:它崩得明明白白,启动时硬校验直接拒绝。这反而是好事,会大声失败的参数,比静默劣化的参数安全十倍。
真凶:调优被静默回滚
排查到配置层,把当前参数和历史快照一比:max-num-batched-tokens 回到了 256。
延迟自然回到 71 秒的水平。数字对上了,人赃俱获。
更值得玩味的是第二个发现:回滚的来源是一次非人工的静默操作,托管平台的例行机制覆盖了手工配置。没有任何通知,没有变更记录,服务照常重启。
大家在没优化的状态下跑了好几天,没人知道。
修复本身只花了十分钟:把参数改回去。
沉淀三制度
十分钟修复不值钱,值钱的是让这种事再也不需要排查。
配置每日快照 + 巡检 diff。所有关键服务的配置每天自动快照,巡检时比对相邻快照,任何无主变更直接暴露。每天几分钟机器时间,换"配置永远可知"。
性能基线 + 漂移告警。为一组标准请求录制性能基线,定期回放对比延迟分布。基线漂移超阈值就告警,哪怕所有监控都绿。要看分布不要只看均值:P50 正常而 P95 翻倍,就是这类问题的典型指纹。
变更日志强制化。任何参数调整必须留痕:谁、何时、为什么。变更不可怕,无感知的变更才可怕。
PM 视角:这是需求评审的老朋友
把这次排查抽象一层,它是产品里经典问题的工程版:"没人动过它,但它变了。"
转化率突然掉了,没人改过页面,真的吗?实验配置、投放参数、SDK 版本,都是"没人动过"的黑箱。
产品侧的解法和技术侧同构:配置快照(实验配置留痕)、性能基线(核心漏斗基准)、变更强制留痕(发布与实验日志)。
系统的当前状态必须永远可审计,否则你所有的判断都建立在"以为"之上。
真正值钱的从来不是那十分钟的修复,是之后再也不用花的那无数个十分钟。
同一类事故两个月后换了个更凶的形态复发(这次连备份都消失了),完整复盘见 两行配置提速一倍,然后被平台更新一夜打回原形;"慢"的归因框架见 慢的三层真相。