Python 调用海外 API 超时排查实录:从 DNS 到出口 IP
最近在做一个项目,需要调用海外某 SaaS 服务的 REST API。本地开发环境测试一切正常,但部署到腾讯云的 Ubuntu 服务器后,接口开始频繁超时。超时不是必现,大概每 10 次请求会有 2-3 次失败,错误信息是 `requests.exceptions.ReadTimeout`。 排查了两天,最终定位到出口 IP 的问题。这篇文章把整个过程整理出来,包括排查思路、定位方法和解决方案。 ### 一、初步排查:不是 API 的问题 第一步先确认目标 API 本身是否正常。用 `curl` 带 `-w` 参数统计各阶段耗时: ``` curl -o /dev/null -s -w "DNS: %{time_namelookup}s\nTCP: %{time_connect}s\nTLS: %{time_appconnect}s\nTTFB: %{time_starttransfer}s\nTotal: %{time_total}s\n" \ "https://api.example.com/health" ``` 结果发现: - DNS 解析正常,10ms 左右 - TCP 连接正常,30ms 左右 - TLS 握手正常,80ms 左右 - TTFB 偶尔飙到 5s 以上,甚至直接超时 问题出在**服务端响应阶段**,不是本地网络连不上。 ### 二、深入排查:出口 IP 被限速了 用 `mtr` 跟踪到目标 API 的路由: ``` mtr -r -c 100 api.example.com ``` 发现中间节点有轻微丢包,但不严重。继续检查出口 IP 的“身份”。 用 `curl` 访问 IP 检测服务,查看当前出口 IP 的 ASN 归属: ``` curl -s https://ipinfo.io/json | jq '.org, .asn' ``` 结果显示:ASN 属于某云服务商,是典型的数据中心 IP 段。 很多海外 API 服务对数据中心 IP 有**速率限制或信誉降级**。原因是这些 IP 段常被用于爬虫、滥用和自动化攻击,服务商为了保障正常用户的体验,会主动对机房 IP 做限制。表现就是:能连上,但响应慢,偶尔直接超时。 这也解释了为什么本地开发环境(家用宽带)正常,而云服务器上频繁超时。 ### 三、验证:更换出口 IP 后恢复 为了验证这个判断,我将请求通过住宅 IP 出口发出。住宅 IP 的 ASN 归属于当地运营商,在 API 服务商的信誉体系中优先级更高,不会被当作机房流量限速。 配置方式如下: ``` # ============================================ # 使用住宅 IP 作为请求出口示例 # 住宅 IP 服务:1024Proxy # 官网:https://1024proxy.com/?kwd=hyj-txy # ============================================ import requests from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry # 从服务商后台获取的代理信息 proxy_url = "http://用户名:密码@gateway.1024proxy.com:端口" # 创建 Session 并配置代理 session = requests.Session() session.proxies.update({ "http": proxy_url, "https": proxy_url }) # 配置重试机制 retry = Retry( total=3, backoff_factor=1, status_forcelist=[500, 502, 503, 504], allowed_methods=["GET", "POST"] ) adapter = HTTPAdapter(max_retries=retry) session.mount("http://", adapter) session.mount("https://", adapter) # 请求示例 try: response = session.get( "https://api.example.com/data", timeout=(5, 30) # 连接超时 5s,读取超时 30s ) print(response.json()) except requests.exceptions.Timeout: print("请求超时,重试或切换出口") ``` 切换到住宅 IP 后,同样的 API、同样的调用频率,超时率从 20% 降到接近 0。后续连续跑了一周,没有再出现批量超时。 ### 四、其他优化建议 **设置合理的超时时间**:连接超时和读取超时要分开设置。连接超时建议 3-5 秒,读取超时根据 API 的响应时间调整,一般 30 秒足够。 **加入指数退避重试**:偶发的网络抖动可以通过重试解决。`urllib3` 的 `Retry` 类支持退避策略,避免短时间内密集重试。 **监控出口 IP 的可用性**:定期用 `curl` 或 `ping` 检测出口 IP 的连通性,如果发现持续异常,及时切换。 **DNS 解析优化**:如果 DNS 解析慢,可以改用公共 DNS 或本地 hosts,减少解析阶段的耗时。 ### 五、小结 调用海外 API 频繁超时,不一定是代码问题,也不一定是目标服务宕机。**出口 IP 的类型**往往是容易被忽略的关键因素。数据中心 IP 在海外服务的信誉体系中天然处于劣势,更换为住宅 IP 出口通常能显著改善稳定性。 排查顺序建议:先测 DNS 和 TCP 连接,再看 TLS 和 TTFB,最后检查出口 IP 的 ASN 归属。如果确认是机房 IP 且目标服务有限速策略,切换到住宅 IP 是成本较低、见效较快的方案。 --- *本文仅做技术交流,请遵守相关平台规则与法律法规。*