最近趁着圈子里几位大佬慷慨分享,我也给自己的“自用小工具”库升级了一下,搞了个 MIMO(多输入多输出)来爽用。本来想着优化一下手写的 AI Adapter 系统,顺手加个模型别名功能,结果——好家伙,直接给自己挖了个坑。

事情是这样的:功能加上之前,服务跑得好好的,稳如老狗。但在部署完新代码后,服务开始“抽风”。不管是连 Codex 还是 Claude,一开始调用一切正常,跑着跑着就开始无脑报错,最后直接挂掉。

排查过程中的那些弯路

面对这种“间歇性抽风”的问题,最头疼的就是不好复现。一开始以为是并发量太大导致下游 API 限流,或者是网络波动。试了几次,发现问题很稳定:只要请求量稍微密集一点,必崩。

中间我还试着让 Codex 自己帮我查代码逻辑,结果这哥们一查服务器直接寄了,查个寂寞。那时候心态真的有点崩,感觉半天时间全花在重启服务看日志上了。

问题锁定:Post Body 读取的坑

折腾了半天,突然灵光一闪:会不会是服务器在读取 HTTP 请求的 Post Body 时出了问题?

MIMO BUG排查代码截图

问题代码中错误读取Post Body的逻辑片段

因为我这次改动的核心就是增加了模型别名解析,意味着请求进入后可能经过了多次转发或者预处理。如果代码里对流或者 Body 的读取逻辑没有处理好“只能读一次”的特性(特别是在某些框架下),一旦 Body 被提前消费,后续的逻辑读到的就是空数据或者 EOF,自然就报错了。

崩溃现场与服务日志

服务崩溃时的错误日志记录

根本原因:MIMO 实现的逻辑瑕疵

顺着这个思路去翻代码,果然!“凶手”就是这次加的 MIMO 实现逻辑。

简单说,就是在处理多路请求分发的时候,代码里有一处逻辑错误地尝试重复读取了请求体。这不仅导致数据丢失,还直接打断了正常的请求链路。看着那段左边写得花里胡哨的 MIMO 实现代码,我当时就想把键盘砸了——真就“有病一样”,一个简单的流读取问题,浪费了我大半天时间。

写在最后的避坑建议

这次踩坑虽然惨,但也给我们提了个醒:在做代理转发或者 Adapter 类开发时,尤其是涉及 POST 请求,一定要小心处理 Input Stream 或者 Body **的读取:

  1. 确保只读一次:大多数 HTTP 服务器的请求体流是不可回溯的,读一次就没了,如果后续逻辑还需要,必须先缓存。
  2. 警惕链式调用:在加了中间件、拦截器或者是像 MIMO 这种转发逻辑时,检查上下游是否都把 Body 当成了可以随便读的资源。
  3. 逐步测试:新功能上线前,一定要做压测。这次就是因为功能太简单,太自信,才导致上线后直接炸。

如果你也在折腾类似的 AI 路由或者镜像服务,遇到这种“莫名其妙”的挂机,不妨先去检查一下你的 Body 读取逻辑,大概率那儿藏着惊喜。

标签: none

评论已关闭