RunPod 推理任务永久卡队列的排查方案
更换 MODEL_ID 后任务无限期卡在 IN_QUEUE,常见原因是 handler 异常而非队列问题;需要精准定位日志。
更换 MODEL_ID 后任务无限期卡在 IN_QUEUE,常见原因是 handler 异常而非队列问题;需要精准定位日志。
症状是:提交 job 后,它一直停留在 IN_QUEUE,始终没有进展。控制台中的 endpoint 看起来一切正常。Worker 不断启动又退出,因此看上去更像是队列出了问题,而不是发生了崩溃。
通常的建议是“检查 handler 日志”。这个方向没错,但它没有告诉你具体应该查什么。下面是一种让我浪费了不少时间、却一直没见有人记录过的具体故障模式。
如果你把模型权重直接烘焙进镜像,通常也会固定 revision,避免上游变更在你不知情的情况下悄悄替换权重。这很合理。问题在于,repo id 和 revision 往往分别由两个不同的地方管理:
repo id 来自 RunPod template 上的环境变量
revision 固定在代码中,放在 loader 旁边
如果只修改 repo id——比如把 MODEL_ID 指向原始 repo,而不是实际烘焙进镜像的量化镜像 repo——就会产生一个根本不存在的组合:使用只存在于镜像 repo 中的 commit hash,却向另一个 repo 请求这个 revision。
加载过程无法命中本地缓存,因为这个 repo 从未被烘焙进镜像,于是转而访问网络,请求一个该 repo 从未拥有过的 revision,并在启动期间收到 404。Worker 甚至还没执行到你的 handler 就已经退出了。
从外部来看,这完全不像一次崩溃。Endpoint 显示健康,Worker 不断重启,而 job 只是一直停留在队列中。
请打开某个 Worker 的日志,而不是查看 endpoint 状态。检查启动时是否尝试获取远程资源:如果一个已经烘焙权重的镜像仍在通过网络拉取权重,就说明之前已经有环节出了问题。然后对比 template 环境变量中的 repo id,与 Dockerfile 实际下载权重时使用的 repo 和 revision 是否完全一致。
如果权重已经烘焙进镜像,就应当把 repo id 和 revision 视为一个整体。要么在同一个地方同时固定两者,要么在运行时两者都不要设置。把它们拆开放在 template 环境变量和代码常量中,最终就可能导致系统请求一个从未在任何地方存在过的组合。
如需采取进一步措施,你可以考虑屏蔽此人和/或举报滥用行为。