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

如何用Python Requests解决AWS Fargate中的TCP连接重置问题?

问题描述

在AWS Fargate上使用Amazon ECS时,实例可正常访问互联网,但连接会在350秒后断开。平均每100次调用中,服务约5次出现ConnectionResetError: [Errno 104] Connection reset by peer错误。

问题原因

使用NAT网关的连接若闲置350秒或更久,会触发超时。超时后,NAT网关会向后方尝试继续连接的资源返回RST包(不会发送FIN包),导致连接重置错误。

现有临时处理方式

目前使用tenacity实现了重试逻辑作为权宜之计:

@retry(
        retry=(
            retry_if_not_exception_type(
                HTTPError
            )  # 针对requests.exceptions.ConnectionError
        ),
        reraise=True,
        wait=wait_fixed(2),
        stop=stop_after_attempt(5),
)
def call_to_api():
    url = "要调用的HTTP地址"
    params = {
       "year": year,
       "month": month
    }
    response = self.session.get(url, params=params)

基础请求代码:

url = "要调用的HTTP地址"
params = {
   "year": year,
   "month": month
}
response = self.session.get(url, params=params)

核心需求

如何用Python requests实现以下任一方案:

  • 在闲置350秒前关闭连接
  • 启用TCP连接的Keep-Alive

方案一:闲置350秒前关闭连接

requests默认会复用连接,可通过以下方式主动关闭连接:

  1. 手动关闭响应对象:处理完响应后直接关闭
response = self.session.get(url, params=params)
# 处理响应逻辑
response.close()
  1. 使用上下文管理器自动关闭:离开代码块后自动释放连接
with self.session.get(url, params=params) as response:
    # 处理响应内容,比如解析JSON
    data = response.json()
# 离开with块后连接自动关闭
  1. 禁用连接复用(不推荐,会增加连接建立开销):通过适配器配置强制每次请求后关闭连接
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

adapter = HTTPAdapter(
    pool_connections=10,
    pool_maxsize=10,
    pool_block=False,
    max_retries=Retry(total=0)
)
self.session.mount("http://", adapter)
self.session.mount("https://", adapter)

# 后续请求不再复用连接
response = self.session.get(url, params=params)

方案二:启用TCP Keep-Alive并设置超时小于350秒

requests本身不直接暴露TCP keepalive配置,需通过底层urllib3实现:

方式1:自定义会话适配器(推荐,仅作用于目标会话)

import requests
from requests.adapters import HTTPAdapter
from urllib3 import PoolManager
import socket

class KeepAliveAdapter(HTTPAdapter):
    def init_poolmanager(self, connections, maxsize, block=False):
        self.poolmanager = PoolManager(
            num_pools=connections,
            maxsize=maxsize,
            block=block,
            socket_options=[
                (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1),
                # 闲置300秒后开始发送keepalive探测(小于350秒)
                (socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 300),
                # 每次探测间隔60秒
                (socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 60),
                # 最多探测5次
                (socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 5)
            ]
        )

# 给会话挂载自定义适配器
self.session = requests.Session()
self.session.mount("http://", KeepAliveAdapter())
self.session.mount("https://", KeepAliveAdapter())

# 正常发起请求
response = self.session.get(url, params=params)

方式2:全局设置Socket选项(作用于所有Python进程的连接)

import socket

# 全局启用TCP keepalive
socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 300)
socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 60)
socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 5)

# 后续使用requests会话发起请求
response = self.session.get(url, params=params)

补充建议

  • 优先选择启用TCP Keep-Alive的方案,既能保留连接复用的性能优势,又能避免NAT网关的超时重置
  • 若选择关闭连接的方案,需注意高并发场景下连接建立的额外开销
  • 保留tenacity的重试逻辑作为兜底,极端场景下仍可能出现连接重置

内容的提问来源于stack exchange,提问作者A l w a y s S u n n y

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 03:06:38