分析阅读约 2 分钟

代理错误详解:407、429、502 与 504

识别代理错误由哪一层返回,检查身份验证和速率限制,并判断何时对失败的请求进行有限次数的重试才是安全的。附 curl 诊断命令和检查表。

本页内容

407 表示需要代理身份验证。429 表示速率限制,但仅凭响应无法知道哪些请求共享该限制。502 或 504 表示上游响应或超时问题。首先确定响应来自哪里,然后视情况检查身份验证、限制或连通性。

首先,确定响应来自哪一层

通过 HTTP 代理发出的 HTTPS 请求通常有两次交换:代理先应答 CONNECT 请求,然后客户端通过隧道与目标站点通信。HTTPS 代理会在 CONNECT 之前增加一次到代理的 TLS 连接。在没有 TLS 拦截的普通隧道中,目标站点 TLS 之后收到的响应来自目标站点的基础设施,其中可能包括 CDN 或反向代理。

下面的示例把 CONNECT 状态与 HTTP 响应状态分开打印。它需要 curl 8.3 或更高版本,并使用 Basic 代理身份验证。把 PROXY_URL 设为你的供应商提供的、不含凭据的 HTTP(S) 网关,并让密钥管理器在环境中填充 PROXY_USERNAMEPROXY_PASSWORD。请使用供应商文档中说明的身份验证方式。

将其保存为 proxy-status.sh,并在不开启 shell 跟踪的情况下运行 sh proxy-status.sh。它发出一个 GET 请求,丢弃响应体,并保留 curl 的退出状态。凭据由 curl 自行导入,因此 shell 不会把它们展开到命令参数中。

sh
: "${PROXY_URL:?Set a credential-free HTTP(S) proxy URL}"
case "$PROXY_URL" in
  http://*|https://*) ;;
  *) printf '%s\n' 'PROXY_URL must use http:// or https://' >&2; exit 2 ;;
esac
case "$PROXY_URL" in
  *'@'*|*'?'*|*'#'*)
    printf '%s\n' 'Keep credentials, queries and fragments out of PROXY_URL' >&2
    exit 2 ;;
esac

curl --disable --silent --fail --http1.1 \
  --noproxy '' --proxy "$PROXY_URL" --proxy-basic \
  --variable %PROXY_USERNAME --variable %PROXY_PASSWORD \
  --expand-proxy-user '{{PROXY_USERNAME}}:{{PROXY_PASSWORD}}' \
  --connect-timeout 5 --max-time 15 --retry 0 \
  --output /dev/null \
  --write-out 'exit=%{exitcode} http=%{http_code} connect=%{http_connect} seconds=%{time_total}\n' \
  'https://example.com/'

--disable 放在最前面以忽略 curlrc 设置,--noproxy '' 防止继承的排除规则绕过所选网关。五秒的连接预算和十五秒的总预算是这个小型诊断的起点。该命令既不跟随重定向也不重试,并且只打印数值结果而不输出详细跟踪。这些选项参见 curl 手册

curl 代理指南介绍了简单的 -x 形式、http_proxyhttps_proxy 变量,以及使用 socks5h 的 SOCKS5,它们决定了请求在这些状态码出现之前会被发往哪里。

要把这些字段放在一起解读。connect=407 表示代理在 CONNECT 期间发出了身份验证质询。connect=200 http=429 表示隧道已被接受,随后收到了 HTTP 429。http=000 表示这次传输没有记录到 HTTP 响应状态;请检查 CONNECT 状态和 curl 退出码。CONNECT 成功并不能证明 TLS 建立或响应体传输已完成。

对于纯 HTTP 目标站点,通常没有隧道。代理直接转发请求,因此返回的状态可能来自代理,也可能来自目标站点。供应商的请求头和带品牌标识的错误页可以提供线索,但仅凭外观无法确定发送方。当归属仍不确定时,请使用供应商文档中的错误说明或请求诊断。

407 Proxy Authentication Required

407 必须包含 Proxy-Authenticate 质询。客户端可以带上 Proxy-Authorization 重试;目标站点的 Authorization 请求头不提供代理身份验证。这些要求来自 RFC 9110 第 15.5.8 节

从以下检查开始:

  • 确认网关、用户名和密码与当前生效的供应商配置一致。
  • 检查凭据是否放在代理身份验证设置中,而不是目标站点身份验证设置中。
  • 如果供应商把国家或会话定向编码在用户名里,请核对其文档中的格式。格式错误的定向如何报告取决于供应商。
  • 如果库要求代理 URL 中包含凭据,请分别对用户名和密码进行编码,以免保留字符改变 URL 结构。

407 修复指南介绍了身份验证诊断。Python Requests 指南演示了显式代理配置和凭据编码。在添加重试之前,先遵循库文档中的格式。

429 Too Many Requests

429 报告的是速率限制。RFC 6585 第 4 节有意把用户识别和请求计数交给响应方服务决定。该限制可能作用于账号、凭据、会话、地址、资源或更大范围的服务。

发送方告诉你应该调查谁的策略。代理可能在执行套餐或并发限制;目标站点可能在执行自己的请求限制。两种情况都无法仅凭状态码确定作用范围。请阅读响应详情和文档中的限制,并在提供 Retry-After 时遵守它。

在受影响的范围内减少流量。对于共享的账号限制,这可能意味着协调使用该账号的所有工作进程。对于绑定到单个资源的限制,这可能意味着放慢对该资源的请求。如果范围未知,请在调查期间降低并发。更换出口并不能证明限制已经重置。

退避也需要上限:如果所需的等待时间超过任务剩余的截止时间,就停止或把工作安排到以后。在同一个限制窗口内反复重试只会增加负载,而不会解除限制。

502 与 504:上游故障或延迟

502 Bad Gateway 表示上游响应无效。504 Gateway Timeout 表示网关没有及时收到上游响应。它们的 HTTP 定义并不指明是哪个组件出了故障。

在代理池中,要调查出口、中间的网关和目标站点。使用供应商的诊断工具和一个小型的、经授权的对照请求来缩小故障范围。比较网关时保持目标站点和客户端设置一致,并且一次只改变一个变量。

三个客户端决策很重要:

  • **重复是否安全。**对于经批准、可以安全重复的请求,允许在总体截止时间内进行少量带退避的尝试。写操作的失败响应并不能证明写操作从未被应用。在重新提交之前,检查该操作的状态或文档中的幂等机制。参见 HTTP 重试语义
  • **任务能等多久。**根据任务的延迟预算设置截止时间。更短的客户端截止时间限制了等待,但不能修复上游故障。超时指南解释了连接、传输和整体任务预算。
  • **哪些故障在增加。**按网关、目标站点和地区分别跟踪 502 和 504,并与应用成功率并列。局限于某一条路由的变化是调查该路由的理由,而不是整个池不健康的证明。

只有当更换符合诊断结论和会话要求时,才使用新的连接或不同的出口。新的出口也会改变用户的会话上下文,因此它不是通用的重试策略。

403 以及内容不可用的 HTTP 200 响应

403 表示拒绝。它可能反映正向代理的访问策略,也可能是目标站点基础设施的拒绝。在更改凭据、请求头或地址之前,先检查响应来自哪一层及其文档中的原因。

更难检测的情况是 HTTP 200 响应中包含质询页、登录页或不完整的应用外壳。状态码记录的是 HTTP 结果;你的应用还必须验证它所需的内容。例如,商品数据任务应检查预期的商品标识符和必需字段,而不是只检查一个在错误页中也可能出现的词。

上面的诊断命令会丢弃响应体。Python 指南同样只演示配置和状态检查,因此生产环境的客户端需要自己针对目标站点的响应体验证。Amazon 与 Google 观测说明了为什么这项额外检查很重要。

选择下一项检查

在确定响应来自哪一层之后使用这张表。这些是起始检查项,不是根本原因的证明。

观察到的结果需要调查什么第一步动作
CONNECT 407代理身份验证检查质询、凭据配置和供应商账号。
CONNECT 429 或目标站点 429响应方服务的限制遵守 Retry-After,并在文档说明的范围内减少流量。
502 或 504上游响应或时序故障比较诊断结果;只在预算内重试可以安全重复的工作。
CONNECT 403 或目标站点 403访问策略或授权检查是哪一层拒绝了请求以及原因。
HTTP 200 但响应体不完整或不符合预期应用层成功标准在计入成功之前验证必需内容。
没有 HTTP 状态连接、隧道或 TLS 进度读取 curl 的退出码,并按照超时指南的分阶段检查进行。

对于重复测量,基准测试方法解释了传输日志、时序分布及其局限。把内容结果和供应商诊断与这些日志放在一起保存,这样状态码计数才不会变成缺乏依据的解释。

参考来源

  1. RFC 9110: HTTP authentication, gateway responses and retry semantics
  2. RFC 6585: section 4, 429 Too Many Requests
  3. curl manual: variables, CONNECT status and timeout options

标签:ProxiesTroubleshooting