服务跑一会儿就开始刷 RuntimeError: Connector is closed,之后所有请求全部失败,重试也没用,重启进程才恢复,日志里报错点都在 session.get。乍看像缓存或者权限的锅,追下去往往不是。
session = aiohttp.ClientSession()
async def fetch(url):
async with session.get(url) as r:
return await r.text()
追下去是这么回事:ClientSession 被放进 with 块或者被显式 close,连接池随之关闭,其他协程还拿着同一个 session 继续发请求,一发出就被直接拒绝,只能撞上已关闭的连接器。
碰到「aiohttp 连接池关闭」这类问题,我习惯先把当前配置原样备份一份,改坏了立刻换回来,不用现场推。测试环境和线上的差别,往往就在版本号和那几行被忽略的配置上。
线上出问题先对时间点,跟发布、备份、任务执行的时刻排一排,能省掉一半功夫。
具体做法是,整个进程只建一个 ClientSession,放在启动处统一管理,不要随手关掉;把 session 作为参数传进业务函数,别在函数内部重新新建一个;确实需要关闭时先确认没有在途请求,再等一个超时周期。
验收就看一点,服务长时间运行不再出现 Connector is closed,请求成功率回到正常水平,连接数也不再上涨。
