现象
线上仍会出现生图一次 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-ray 与 server: cloudflare,
两个信号缺一即判否。加这条 AND 是为了排掉「中继把上游的 cf-ray 拷进自己的错误响应」,
但代价是判据在真实链路上过严。
实测该网关的响应头(含一次成功的 200):
/v1/chat/completions 404 server=APISIX cf-ray=无
/v1/models 404 server=APISIX cf-ray=无
真实 200 响应 server=APISIX
而 522 发生时具体带了哪些头,现在无从得知——那条路径不打日志。这本身是缺口:
判据依赖响应头,却没有在判否时把响应头记下来,于是线上失败无法复盘,只能猜。
建议
- 判据改回按状态码:521 / 522 / 523 是 Cloudflare 专有码,语义都是「边缘没能连上源站」,
收到它本身就是强信号;520 / 524 仍然排除(连接已建立、请求可能正在源站处理,重发会重复计费)。
- 遇到 52x 而决定不重试时,把状态码与关键响应头记进日志,让下一次可复盘而不是再猜一轮。
同一类判据在 _tc3.call 里也有(#270 已按「重发一次的代价」重新划过档),可参照。
现象
线上仍会出现生图一次 522 就失败,报的是 httpx 原文:
#271 为这个场景加了重试,但那次修复在生产环境一次都没触发过。
证据
生产日志里有 522 的
HTTPStatusError,却没有任何一条_post重试时会打的图像服务返回 %d,第 %d/%d 次请求warning。重试若触发过,最终抛的应当是_retry_exhausted_message(「图像网关未能连上上游(HTTP 522),已重试 N 次」),而不是 httpx 原文。两者都指向同一结论:
retryable恒为 False。原因
_from_cloudflare_edge()要求响应同时带cf-ray与server: cloudflare,两个信号缺一即判否。加这条 AND 是为了排掉「中继把上游的 cf-ray 拷进自己的错误响应」,
但代价是判据在真实链路上过严。
实测该网关的响应头(含一次成功的 200):
而 522 发生时具体带了哪些头,现在无从得知——那条路径不打日志。这本身是缺口:
判据依赖响应头,却没有在判否时把响应头记下来,于是线上失败无法复盘,只能猜。
建议
收到它本身就是强信号;520 / 524 仍然排除(连接已建立、请求可能正在源站处理,重发会重复计费)。
同一类判据在
_tc3.call里也有(#270 已按「重发一次的代价」重新划过档),可参照。