长期运行的aiohttp应用出现Unclosed相关报错求解决方案
解决aiohttp长期运行应用中"Unclosed connector/session"警告问题
你遇到的这个警告,本质是aiohttp的内部检测机制发现ClientSession或TCPConnector对象被垃圾回收前没有被显式关闭——即便容器销毁时会回收系统资源,aiohttp依然会抛出这类资源未正确释放的提示。
复用单例ClientSession确实是aiohttp的最佳实践(能避免重复创建连接池、减少TCP握手开销),但这和显式关闭会话并不冲突,以下是几种可行的处理方案:
1. 在应用 shutdown 阶段显式关闭会话
长期运行的异步应用(比如FastAPI、异步Django)通常都有生命周期钩子,你可以在应用停止前调用await session.close(),彻底释放连接池资源:
from fastapi import FastAPI import aiohttp # 为不同服务商维护全局复用的ClientSession api_sessions = { "service_a": aiohttp.ClientSession(), "service_b": aiohttp.ClientSession() } app = FastAPI() @app.on_event("shutdown") async def cleanup_sessions(): for session in api_sessions.values(): await session.close()
2. 优化TCPConnector参数,减少连接泄漏风险
给TCPConnector设置合理的连接存活超时和最大连接数,避免连接长期占用不释放,从根源降低警告出现的概率:
connector = aiohttp.TCPConnector( limit=100, # 每个域名的最大并发连接数 keepalive_timeout=300, # 连接保持存活的超时时间(秒) force_close=False # 允许连接复用,仅在超时后关闭 ) session = aiohttp.ClientSession(connector=connector)
3. 屏蔽警告(不推荐,仅临时应急)
如果确认容器销毁会彻底清理所有资源,且不想修改核心逻辑,可以通过日志配置屏蔽aiohttp的这类警告:
import logging # 将aiohttp的日志级别设为WARNING,忽略INFO级别的未关闭警告 logging.getLogger("aiohttp").setLevel(logging.WARNING)
需要明确的是:复用会话是正确的,但显式关闭是aiohttp的规范要求——不仅能消除警告,还能避免极端场景下的连接泄漏(比如应用频繁重启时,未关闭的连接可能残留占用端口)。
内容的提问来源于stack exchange,提问作者Tomer Vainshtok
相关产品推荐
相关产品推荐

