Skip to content

生图 522 重试在生产环境从未触发,判据过严且不可复盘 #296

Description

@johnnyzhang-eng

现象

线上仍会出现生图一次 522 就失败,报的是 httpx 原文:

httpx.HTTPStatusError: Server error '522 Connection Timeout with Origin Server'
for url 'https://api.qnaigc.com/v1/chat/completions'

#271 为这个场景加了重试,但那次修复在生产环境一次都没触发过

证据

生产日志里有 522 的 HTTPStatusError,却没有任何一条 _post 重试时会打的
图像服务返回 %d,第 %d/%d 次请求 warning。重试若触发过,最终抛的应当是
_retry_exhausted_message(「图像网关未能连上上游(HTTP 522),已重试 N 次」),
而不是 httpx 原文。两者都指向同一结论:retryable 恒为 False。

原因

_from_cloudflare_edge() 要求响应同时cf-rayserver: cloudflare
两个信号缺一即判否。加这条 AND 是为了排掉「中继把上游的 cf-ray 拷进自己的错误响应」,
但代价是判据在真实链路上过严。

实测该网关的响应头(含一次成功的 200):

/v1/chat/completions  404  server=APISIX  cf-ray=无
/v1/models            404  server=APISIX  cf-ray=无
真实 200 响应              server=APISIX

而 522 发生时具体带了哪些头,现在无从得知——那条路径不打日志。这本身是缺口:
判据依赖响应头,却没有在判否时把响应头记下来,于是线上失败无法复盘,只能猜。

建议

  1. 判据改回按状态码:521 / 522 / 523 是 Cloudflare 专有码,语义都是「边缘没能连上源站」,
    收到它本身就是强信号;520 / 524 仍然排除(连接已建立、请求可能正在源站处理,重发会重复计费)。
  2. 遇到 52x 而决定不重试时,把状态码与关键响应头记进日志,让下一次可复盘而不是再猜一轮。

同一类判据在 _tc3.call 里也有(#270 已按「重发一次的代价」重新划过档),可参照。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions