先把一次请求的延迟拆成四段
访问一个海外站点,链路大致经历:本地到代理入口、代理入口到出口节点、出口到目标站、目标站返回到本地。总耗时是这四段之和,任何一段拖后腿,体感都会很差。很多人只盯着"代理在哪",却忽略了入口与出口的链路质量。
第一段:本地到代理入口
这一段取决于你与入口机房之间的网络。如果入口在境外而你在国内,这段本身就要经过国际出口,晚高峰抖动明显。选择离自己近的入口(例如同城或国内入口),往往比优化后面的段更有效。这也是部分供应商提供中转入口的原因。
第二段:入口到出口节点
这是最容易被忽视的一段。中转链路如果绕行(例如入口在美西、出口在美东却从欧洲中转),单程就能多出上百毫秒。判断方法很简单:对同一个目标站,固定出口地区,只换入口地区测三次,差异超过 150ms 就说明中间链路有问题。
第三段:出口到目标站
这一段由地理距离与目标站所在机房决定。要抓美国站点,用美国出口;要抓日本站点,用日本出口。跨大洲出口再快也快不过本地出口。同城市出口通常能压到几十毫秒。
第四段:返回路径与 TLS 握手
每次新建连接都要做 DNS 解析和 TLS 握手,海外链路光握手就可能几百毫秒。可优化项有三个:
- 连接复用:用长连接或 Session 复用,把握手成本摊到多次请求上。
- 就近 DNS:避免解析结果指向远端节点。
- 失败快速切断:把超时设短,坏节点立即放弃,不要等满默认超时。
怎么定位到底慢在哪一段
import time, requests
proxy = "http://user:pass@gate.example.com:8000"
target = "https://target-site.com/ping"
t0 = time.time()
requests.get("http://gate.example.com/health", proxies={"http": proxy}, timeout=10)
t1 = time.time()
requests.get(target, proxies={"http": proxy, "https": proxy}, timeout=20)
t2 = time.time()
print("入口耗时 %.0fms,端到端 %.0fms" % ((t1 - t0) * 1000, (t2 - t1) * 1000))
不同代理之间对比时,务必用同一目标站、同一时间段、同样次数取平均,单次测量受国际链路抖动影响极大。
延迟优化没有玄学:先用上面的方法定量拆开,再决定是换入口、换出口地区,还是改代码做连接复用。凭感觉换套餐大多花冤枉钱。
小结
海外代理的延迟由入口、中转、出口、握手四段组成。国内用户最该关注前两段,抓取目标的靠近性由第三段决定,代码层能改善的是第四段。三段之外的因素,靠调参数是解决不了的。