我在 AWS Fargate 上使用 Amazon ECS,我的实例可以访问互联网,但连接在 350 秒后断开。平均而言,在 100 次中,我的服务出现 ConnectionResetError: [Errno 104] Connection reset by peer 错误大约 5 次。我发现了一些解决服务器端代码问题的建议,请参阅here 和here
原因
如果使用 NAT 网关的连接空闲 350 秒或更长时间,则连接超时。
当连接超时时,NAT 网关会向 NAT 网关后面试图继续连接的任何资源返回一个 RST 数据包(它不会发送 FIN 数据包)。
解决方案
为防止连接断开,您可以通过连接启动更多流量。或者,您可以在实例上启用值小于 350 秒的 TCP keepalive。
现有代码:
url = "url to call http"
params = {
"year": year,
"month": month
}
response = self.session.get(url, params=params)
为了解决我目前使用的创可贴重试逻辑解决方案韧性,
@retry(
retry=(
retry_if_not_exception_type(
HTTPError
) # specific: requests.exceptions.ConnectionError
),
reraise=True,
wait=wait_fixed(2),
stop=stop_after_attempt(5),
)
def call_to_api():
url = "url to call HTTP"
params = {
"year": year,
"month": month
}
response = self.session.get(url, params=params)
所以我的基本问题是如何正确使用 python 请求来执行以下任何解决方案,
在 350 秒不活动之前关闭连接
为 TCP 连接启用 Keep-Alive
关于“在 350 秒不活动之前关闭连接”问题,似乎有一个 read timeout 参数可以传递给
session.get()
函数调用。
根据文档“这是客户端在从服务器发送的字节之间等待的秒数”。 对我来说,这看起来像是一个不活动超时。
为在 AWS Farget + NAT 上工作时将面临此问题的未来用户发布解决方案,
我们需要将 TCP keepalive 设置设置为服务器端配置指定的值,此 PR 对解决我的问题有很大帮助:https://github.com/customerio/customerio-python/pull/70/文件
import socket
from urllib3.connection import HTTPConnection
HTTPConnection.default_socket_options = ( HTTPConnection.default_socket_options + [
(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1),
(socket.SOL_TCP, socket.TCP_KEEPIDLE, 300),
(socket.SOL_TCP, socket.TCP_KEEPINTVL, 60)
]
)