LLM fetch timeout 是否对得上

我会先给每个请求打一个 requestId,否则排查全靠感觉。

现象可能位置第一刀
浏览器等很久后失败客户端或 CDN看前端超时和状态码
Worker 日志有入口无出口Worker 内部等待记录每个 fetch 耗时
上游返回 524/5xx上游 API 慢加短超时和退避
流式输出到一半断stream 链路检查是否缓存完整响应

如果日志只有「请求失败」四个字,先补日志。至少记录:进入时间、上游 URL 分类、模型名、首 token 时间、总耗时、错误类型。

LLM fetch timeout:最短处理路径

第一步,给上游 fetch 加 AbortController。我的默认值是普通 JSON 请求 8-12 秒,LLM 首 token 15-25 秒。超过就返回可读错误,不让请求无限挂着。

第二步,流式请求要尽快把 ReadableStream 交给客户端。不要在 Worker 里等模型完整生成后再 return Response,这会同时吃掉运行时间和用户耐心。

第三步,重试只重试可重试错误。网络断开、502、503 可以退避;401、403、参数错误不要重试。每次重试都要带同一个业务 id,避免用户被重复扣量或重复创建任务。

第四步,拆掉串行调用。一个请求里先查数据库、再调支付、再调模型、再写日志,任何一段慢都会把总耗时拖长。能并发就并发,能异步就进队列。

为什么 LLM/API 中转更容易暴露超时?

普通 API 是短请求,失败了用户刷新一次就过去。LLM 请求既长又贵:首 token 慢、输出长、模型切换、限流退避都会叠加。Worker 很适合做轻量路由,但不适合把所有编排都塞进一个同步函数。

我自己的底线是:Worker 做鉴权、路由、计量、短缓存;长任务交给队列或后端服务。这样边缘层保持薄,排查也清楚。

LLM fetch timeout 继续排查清单

  • 是否在 Worker 里读取完整上游响应,导致无法真正 stream
  • 是否把 429 当 5xx 重试,越重试越慢
  • 是否没有记录首 token 时间,只记录总耗时
  • 是否在同一个请求里串行调用多个模型
  • 是否让前端、Worker、上游三层 timeout 互相打架
  • 是否没有 fallback 模型或空态结果

还有两个小细节我会单独看。第一是缓存:如果你把用户级请求错误地缓存到边缘,下一位用户可能拿到前一位的失败结果;如果完全不缓存,价格表、模型列表这类半静态接口又会反复打上游。第二是错误文案:不要把所有失败都写成「网络错误」。前端至少要能区分「上游忙」「参数错」「余额不足」「需要稍后重试」。这些文案看起来不工程,但能显著减少用户重复点击。

最后别忘了成本侧。超时请求如果已经打到模型,上游可能已经产生用量。前端看到失败,不代表账单没有增长。所以要把 request id、用户 id、模型名和计费结果关联起来。否则你只会看到用户抱怨失败,却不知道失败请求是不是已经烧掉预算。

还没恢复时,单独查 LLM fetch timeout

把最长的 LLM 任务切成异步:提交任务立即返回 id,Worker 只负责查状态和推送结果。对独立开发者来说,与其自己维护多家上游的超时、重试和账单,不如先接一个多模型统一计费的 API 中转做兜底,再把高频流量逐步迁回自有路由。

相关阅读