一个请求跑得飞快,五十个一起发出去就全乱了。同一个接口、同一段提示词、同一个模型,什么都没换。
所以模型不是问题,队列才是。我把计时对象从"请求"换成了"等待",数字才终于说人话。
每次调用其实有两个时钟,不是一个。一个是排队等槽位的时间,一个是真正干活的时间。多数跑分只报两者之和,而这个和恰好把队列藏了起来。
不妨先问自己一句:p99 翻倍的时候,是干活的时间翻倍了,还是等待的时间翻倍了?不把时钟拆开,这个问题根本没法回答。
先拆时钟,再谈调优
每次调用记三个时间戳:发出、首字节、完成。等待等于首字节减发出,服务时间等于完成减首字节。就这么简单。
如果等待平稳而服务时间在涨,说明后端慢,该扩容或者该砍请求体。如果等待在涨而服务时间不动,说明你撞上了队列——加更多工作线程救不了你,只会继续往队列里喂。
这个区分就是全部重点,剩下的都是测试脚手架的事。
我留下的那套脚手架
零依赖,只用标准库,所以它在哪都能跑,包括一台你没怎么配置过的免费服务器。
核心逻辑很朴素:用线程池按并发档位发请求,每档跑固定次数,记录成功数、错误数、每秒请求数,以及等待和服务时间的中位数与 p95。并发档位从 1 到 16 逐级往上扫,每档重复 20 次。
有两点让这组数据可信。第一,先跑一遍回环基线:把目标指向本地一个只做 sleep 的接口,那个数字就是你客户端自身的开销,减掉它,或者至少记住它。第二,请求体必须固定。如果各档位之间提示词长度在漂,你测的其实是自己打字的速度。
我留下的那张图很无聊,正因如此我才信它。横轴是并发,两条线:等待的 p95 和服务时间的中位数。绝对数值我不关心,我关心两条线在哪里交叉。
看交叉点,别看平均值
为什么拐点比均值重要?因为均值是你的空闲工作线程编出来的谎话,而 p95 才是流量尖峰时用户真正待着的地方。
有一个坑值得单独说:接口其实一点都不慢,它是在飞快地说"不",而我把那些空回答读成了延迟。这种情况在决策表里单独占一行,曾经帮我省下一个周末。
还有一处必须诚实交代:标准库的 urlopen 在响应头到达时就返回,而不是在第一个 token 到达时。对流失接口,应该只读一个分片而不是整个响应体,否则你那个"服务时间"实际上是"完整响应耗时"——这也没问题,前提是你自己清楚。
免费额度真正帮上忙的地方
这套扫描需要两样东西:token 和一台机器。五个档位、每档四十次调用,放在付费接口上可不便宜。这才是真正的摩擦点,不是代码。
免费模型接入的价值就在这里:它让你能在小规模上把扫描跑完,而不用先开一场预算讨论——于是你真的会去跑。免费服务器选项则让脚手架能挨着客户端放,一台休眠的笔记本或者糟糕的 wifi 就不会再污染你的等待列。我更看重后一点,客户端噪声是干净扫描被误读成服务商问题的最常见原因。
这里不报具体 token 数字。额度会变,博客里一个过期的数字比没有数字更糟。要用之前,去看项目页面上当前的额度和免费服务器的条款。
有一条规则不可选:绝不要对没有测试授权的接口跑压测。重复次数保持小。免费额度是共享的,你的一次扫描就是别人的一次变慢。
哪些人不该做这件事
如果你和供应商签了 p99 的合同指标,客户端扫描证明不了任何东西,你需要的是对方的容量数据和排队模型。
如果你的负载是每分钟一个大请求,并发扫描对你毫无意义,去剖析单次调用。而如果你还没法在日志里把两个时间戳拆开,先修这个——没有任何一张图能救一个拆不开的指标。
所以,你的拐点在哪,你上一次看它是什么时候?我的是在一次我以为毫不相关的部署之后移动的。它通常都会。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.