You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python长耗时POST请求服务端已返回但requests.post仍阻塞问题咨询

问题原因与解决方案

根因分析

  • 最核心的诱因是AWS NAT网关的默认空闲连接超时阈值为350秒(约5分50秒),刚好接近你请求的正常处理耗时。高负载场景下服务端处理耗时稍微波动,或者网络链路有轻微延迟,就会导致空闲连接超过350秒没有数据包交互,NAT网关会静默丢弃该连接,且不会向两端发送连接断开的通知。此时服务端虽然已经生成200响应并尝试回包,但对应的TCP连接已经被中间链路掐断,客户端收不到响应数据,会一直阻塞直到你设置的720秒超时触发重试。
  • 其次是requests默认未开启TCP keepalive,无法在连接空闲时发送探测包维持长连接的活跃状态,也无法及时感知中间链路的连接断开。
  • 你当前传递的timeout=720参数存在歧义:requests的timeout参数如果传入单个数值,会同时作用于连接超时和读取超时,而读取超时定义的是两次相邻数据包接收的间隔时长,并非总请求时长,极端场景下可能不符合你的预期。

修复方案

  • 调整AWS NAT网关的空闲连接超时阈值,将其设置为大于720秒的数值(建议设为900秒即15分钟),避免中间链路主动断开正常处理中的长连接。如果你的链路中还存在负载均衡、反向代理等中间设备,也要同步调整对应设备的空闲连接超时配置。
  • 为requests开启TCP keepalive配置,通过自定义HTTP适配器设置TCP保活参数,定期发送探测包维持连接活跃,同时可以及时感知链路断开。示例代码如下:
import requests
from requests.adapters import HTTPAdapter

class TCPKeepAliveAdapter(HTTPAdapter):
    def init_poolmanager(self, *args, **kwargs):
        socket_options = [
            *self.default_socket_options,
            # 开启TCP保活
            ("SO_KEEPALIVE", 1),
            # 连接空闲120秒后开始发送探测包
            ("TCP_KEEPIDLE", 120),
            # 探测包发送间隔30秒
            ("TCP_KEEPINTVL", 30),
            # 最多发送5次探测无响应则判定连接断开
            ("TCP_KEEPCNT", 5),
        ]
        kwargs["socket_options"] = socket_options
        super().init_poolmanager(*args, **kwargs)

# 使用时创建会话挂载适配器
session = requests.Session()
session.mount("http://", TCPKeepAliveAdapter())
session.mount("https://", TCPKeepAliveAdapter())

response = session.post(
    url=url,
    params=params,
    headers=self.headers,
    json=payload,
    # 明确指定连接超时30秒,读取超时720秒,避免参数歧义
    timeout=(30, 720)
)
  • 长期优化可以考虑将长耗时POST请求改为异步处理模式:服务端收到请求后先返回任务ID,客户端定期轮询任务结果,避免长连接带来的各类链路稳定性问题。

内容的提问来源于stack exchange,提问作者Jeremy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 16:45:03