ENGINEERING GUIDE

代理错误、超时与重试排查

先确定错误发生在代理链路还是目标站点。把DNS、TCP、TLS、代理认证、目标HTTP响应和业务解析混在一起,会导致无效换IP、无限重试或错误关闭安全校验。

排查层级6 层重点状态407 / 403 / 429重试有预算的退避安全保持TLS校验
打开提取代理 查看服务状态
01
FAILURE LAYERS

按请求链路逐层定位

层级典型现象优先检查
DNS无法解析代理网关或目标域名解析器、服务器网络、网关域名拼写
TCPConnection refused、reset或连接超时HOST、PORT、防火墙、出口网络和服务状态
TLS证书、握手、SNI或协议版本错误系统时间、CA、客户端版本和代理协议
代理认证HTTP 407代理用户、密码、完整路由用户名和套餐白名单
目标响应403、404、429、5xx目标授权、请求频率、Retry-After和目标状态
业务解析HTTP成功但字段为空或页面结构不符响应内容、登录状态、渲染方式和选择器
02
MINIMUM DIAGNOSTIC

先用 cURL 分离代理与框架问题

使用与程序相同的代理网关和账密访问简单测试目标。--verbose 可显示CONNECT、认证和TLS阶段;日志中不要长期保存完整代理密码。

export PROXY_USER="YOUR_PROXY_USER"
export PROXY_PASS="YOUR_PROXY_PASSWORD"

curl --verbose --fail-with-body   --proxy "http://proxy.123proxy.cn:36923"   --proxy-user "${PROXY_USER}:${PROXY_PASS}"   --connect-timeout 15   --max-time 30   "https://httpbin.org/status/200"
cURL成功而框架失败

继续检查框架代理参数、环境变量覆盖、连接池、浏览器代理作用域和URL编码,不要先更换代理产品。

03
STATUS CODES

不同状态码对应不同处理动作

状态含义正确动作
407代理网关拒绝认证修复账密、完整用户名或套餐白名单,不盲目换出口
403目标站点拒绝当前请求或身份确认访问授权、请求头、账号状态、地区与目标规则
429目标站点或接口触发频率限制读取Retry-After,降低单域名并发并执行退避
5xx目标服务或中间链路临时失败只对安全请求执行有限重试,并记录目标域名
04
TIMEOUT BUDGET

区分连接超时、读取超时和任务截止时间

连接超时

限制解析、TCP连接、代理CONNECT与TLS握手等待。建议单独设置,例如15秒。

读取超时

限制连接建立后等待响应数据的时间。大文件下载应按对象大小调整。

任务截止时间

限制包含重试在内的整个页面或对象处理时长,防止队列被少量慢任务占满。

超时不是越长越稳定

过长超时会让失败请求长期占用并发线程;过短则会把正常慢响应误判为失败。应根据p95与对象大小设置,并给重试留下总预算。

05
BOUNDED RETRY

只重试可恢复且幂等的请求

GET与HEAD通常可以在有限预算内重试;会创建订单、分配静态IP或修改状态的请求不能因为结果未知就自动重复提交。

# python -m pip install requests
import random
import time

import requests

RETRYABLE = {429, 500, 502, 503, 504}


def get_with_backoff(session, url, proxies, attempts=4):
    for attempt in range(attempts):
        try:
            response = session.get(
                url,
                proxies=proxies,
                timeout=(15, 30),
            )
            if response.status_code not in RETRYABLE:
                response.raise_for_status()
                return response

            retry_after = response.headers.get("Retry-After")
            if retry_after and retry_after.isdigit():
                delay = min(float(retry_after), 60)
            else:
                delay = min(2 ** attempt + random.random(), 30)
        except (requests.ConnectTimeout, requests.ReadTimeout):
            delay = min(2 ** attempt + random.random(), 30)

        if attempt == attempts - 1:
            raise RuntimeError("request exhausted retry budget")
        time.sleep(delay)

    raise RuntimeError("unreachable")
限制最大尝试次数常见起点为首次请求加2-3次重试。
指数退避并加入随机抖动避免多个worker在同一时刻再次冲击目标。
尊重 Retry-After目标明确给出等待时间时优先使用,并设置合理上限。
保留总任务截止时间单次超时与多次重试之和不能无限增长。
06
CONNECTIONS & TLS

连接池与TLS不要用错误的捷径处理

复用稳定连接同一目标和SESSION可减少握手;监控空闲连接被关闭后的重建。
需要换路由时重建连接更改地区、SESSION或轮转参数后关闭旧HTTP隧道。
保留证书校验修复CA、系统时间、SNI或客户端协议,不默认verify=false。
区分代理错误与目标证书错误记录失败阶段、目标域名和客户端错误类型。
07
SAFE LOGGING

记录足够排查但不泄露凭证

request_id跨worker关联一次任务及其重试
target_host定位单一目标站点的错误率与限速
proxy_product记录产品和套餐标识,不记录代理密码
session_id可脱敏记录SESSION,排查粘性路由
status / error_type区分HTTP状态与客户端异常
attempt / duration_ms观察重试次数与每次耗时
08
FAQ

常见问题

代理返回 407 时是否应该更换出口 IP?

通常不应该。407 是代理认证失败,应先检查代理用户、密码、完整地区或SESSION用户名,以及套餐白名单是否绑定到当前服务器公网IPv4。更换出口不会修复错误账密。 查看代理认证

403 和 429 是否代表代理网关故障?

通常不是。403 与429一般来自目标站点,分别表示拒绝访问或频率限制。应先记录响应头和目标域名,再检查授权、请求频率、Retry-After、账号状态和访问规则。 计算目标站点并发与QPS

遇到 TLS 错误能否直接关闭证书校验?

不建议。关闭校验会失去服务器身份验证。应先确认系统时间、CA证书、SNI、代理协议和目标证书链,再判断是否为受控测试环境中的临时诊断。