当前位置: 首页 > 图灵资讯 > 行业资讯> 如何修复Python aiohttp长连接(Keep-Alive)频繁断开的问题?

如何修复Python aiohttp长连接(Keep-Alive)频繁断开的问题?

来源:图灵python
时间: 2026-07-16 16:56:35
长连接频繁断开的主要原因是服务端拒绝Keep-Alive、客户端配置无效或中间设备切断;检查响应头conection字段,重用clientsesion、对齐各层加班,并添加应用层心跳。

长连接经常断开,不是 aiohttp “不支持”本身 Keep-Alive“相反,服务器拒绝连接和重用,客户端配置不生效,或者中间网络设备主动切断。关键取决于 Connection 响应头和连接池的实际行为。

检查服务端是否真的返回 keep-alive

即使你配了 TCPConnector,如果服务端响应头没有 Connection: keep-aliveKeep-Alive: timeout=XX,连接不可能重复使用。这是最常被忽视的第一步。

  • curl -v https://example.com 或者抓包工具(如 Wireshark)观察真正的响应头
  • 若响应中是 Connection: close,说明服务端明确拒绝保存-此时调大 limit 或加 keepalive_timeout 都无效
  • 某些 CDN(如 Cloudflare)或反向代理(如 Nginx 默认配置)会被抹去 Keep-Alive 头部需要在服务端显式打开 proxy_http_version 1.1proxy_set_header Connection ''
确认 TCPConnector 参数已正确使用,未被覆盖

TCPConnector 参数只有在 ClientSession 初始化时,传入生效;如果您在每个请求中都新建; ClientSession,所有的连接池配置都等于不写。

  • 同一个必须重用 ClientSession 例子,而不是在每个协程中 async with aiohttp.ClientSession() as session:
  • 推荐写法:
    connector = aiohttp.TCPConnector(
        limit=100,
        limit_per_host=30,
        keepalive_timeout=60,
        enable_cleanup_closed=True
    )
    session = aiohttp.ClientSession(connector=connector)
  • 注意 force_close=True 会强制禁用 keep-alive,务必设为 False(默认值)
  • Python 3.12+ 中 enable_cleanup_closed=True 可避免 Unclosed connector 警告,也减少了 fd 泄漏风险
调查中间网络设备的静默断连

Nginx、ELB、常见的防火墙等 60–90 秒空闲后发 RST 包,导致下一个请求直接抛出 ConnectionResetErrorServerDisconnectedError,而非超时。

Python 3.14.2

Python 3.14.2是Python编程语言于2025年12月5日发布的稳定版本,属于3.14系列的第二次维护更新。该版本包含18个修复项目,重点解决多过程、数据和正则表达模块的回归问题,修复CVE-2025-12084等安全漏洞。这个版本标志着Python发展的一个重要里程碑,即自由线程模式(删除GIL)正式得到官方支持。

下载

立即学习“Python免费学习笔记(深入);

  • 服务端和反向代理需要对齐超时:Nginx 的 keepalive_timeout、负载均衡器空闲时间超时,aiohttp 的 keepalive_timeout 最小值并留余量(如统一设置) 45s)
  • 仅靠系统级 TCP keepalive 不够 —— 它检测到底层 socket,而 HTTP keep-alive 是应用层协商的结果;两者应合作:socket 层保存防止中间设备断开,HTTP 重复使用,节省握手费用
  • 如果无法控制服务端,可以在客户端添加应用层心跳:定期发送关键域名 HEAD 请求,或在业余时间主动 await session.get(url, timeout=2) 保持活跃的连接
验证连接复用是否真的工作

光看代码配置并不等于生效。日志和连接状态中隐藏着真实的信号。

  • 启用 aiohttp 调试日志:logging.getLogger("aiohttp").setLevel(logging.DEBUG),观察是否发生 Reuse connectionClose connection
  • lsof -i :<port></port>(Linux/macOS)或 netstat -ano(Windows)查实际 ESTABLISHED 连接数,是否稳定 limit_per_host 附近而不是持续增长
  • 若日志频繁出现 Unclosed connector 或协程退出前未调整 await session.close(),连接会泄漏,最终触发 Too many open files

真正困难的不是如何填写参数,而是你永远不知道哪一层(CDN?LB?服务框架?内核?)悄悄关闭连接。盯着响应头,重复使用。 Session、对齐超时,再加一层心跳,四者缺一不可。