如何在aiohttp服务中优雅关闭aioredis连接池?
问题原因
出现sys:1: RuntimeWarning: coroutine 'Connection.disconnect' was never awaited警告的核心原因是连接池关闭逻辑写法错误:
- 你在finally块中用
loop.create_task()包装redis.close()调用,这个方法只会把关闭协程提交到事件循环的待执行队列,不会阻塞等待协程执行完成 - aiohttp执行完cleanup_ctx的所有清理逻辑后会立刻终止事件循环,提交的关闭任务还没来得及跑完、底层连接的
disconnect协程没被await就随循环一起被销毁,自然会触发警告。
修复方案
aioredis 2.x及以上版本的连接池close()方法本身就是可等待协程,不需要额外包装成事件循环任务,直接await即可,还可以搭配wait_closed()方法等待所有底层连接完全释放,彻底避免残留协程。
修改后的Redis连接池上下文代码如下:
async def create_redis_connection_pool(app) -> aioredis.Redis: redis = aioredis.from_url( "redis://localhost", encoding="utf-8", decode_responses=True, max_connections=10, ) app["redis"] = redis try: yield finally: # 直接等待连接池关闭执行完成,禁止用create_task包装关闭逻辑 await app["redis"].close() # 等待所有底层连接完成回收 await app["redis"].wait_closed()
aiohttp侧的清理上下文注册逻辑不需要改动,保持原有app.cleanup_ctx.append(create_redis_connection_pool)的写法就可以。修改后重启服务,发起过Redis调用的请求后再按Ctrl+C终止服务,就不会再出现未await协程的警告,连接池会完成优雅关闭。
内容的提问来源于stack exchange,提问作者Artiom Kozyrev
相关产品推荐
相关产品推荐

