Aiohttp RuntimeError: Event loop is closed问题求助(AWS Lambda Telegram Bot)
解决AWS Lambda上Aiogram Bot的"Event loop is closed"错误
问题核心原因
你的问题出在每次Lambda调用都动态创建新的Dispatcher(及内部Bot实例),Lambda的执行环境是会被复用的。当函数执行完毕事件循环被关闭后,新创建的Bot实例持有的aiohttp连接资源没有被正确清理,后续复用环境时就会触发"Event loop is closed"错误。而直接用全局变量时,Dispatcher和Bot只初始化一次,不会重复创建资源,所以没有问题。
另外你提到不能用asyncio.run(),是因为它会自动关闭事件循环,而Lambda的环境复用特性会导致后续调用循环已关闭的问题,你当前的lambda_handler写法是对的,需要保留手动管理循环的逻辑。
解决方案
1. 让Dispatcher/Bot成为全局单例
修改配置模块,让get_dp()返回全局单例,避免每次调用都重新创建:
# setting/setting.py from aiogram import Bot, Dispatcher from aiogram.client.default import DefaultBotProperties from aiogram.enums import ParseMode # 全局单例变量 _dp = None _bot = None async def get_dp(): global _dp, _bot if _dp is None: # 替换为你的Telegram Bot Token BOT_TOKEN = "YOUR_TELEGRAM_BOT_TOKEN" _bot = Bot(token=BOT_TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML)) _dp = Dispatcher() return _dp
2. 处理完事件后清理Bot会话
在main函数最后添加Bot会话关闭逻辑,确保aiohttp连接被正确释放:
async def main(event): dp = await get_dp() await register_handlers(dp) await process_event(event, dp) # 关键:关闭Bot的HTTP会话,清理连接资源 await dp.bot.session.close() return 'ok'
3. 优化lambda_handler的循环管理
简化循环逻辑,优先复用已存在的事件循环:
def lambda_handler(event): loop = asyncio.get_event_loop() if not loop.is_running(): loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) loop.run_until_complete(main(event))
完整修改后的代码
import asyncio from setting.setting import get_dp from handlers.reg_hand import register_handlers from aiogram import Bot, types, Dispatcher async def process_event(event, dp): Bot.set_current(dp.bot) update = types.Update.to_object(event) await dp.process_update(update) async def main(event): dp = await get_dp() await register_handlers(dp) await process_event(event, dp) # 清理Bot会话 await dp.bot.session.close() return 'ok' def lambda_handler(event): # 优先复用已存在的循环,不存在则创建新循环 loop = asyncio.get_event_loop() if not loop.is_running(): loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) loop.run_until_complete(main(event))
解决逻辑说明
- 单例模式确保Dispatcher和Bot只初始化一次,避免重复创建导致的资源泄漏和循环冲突。
- 手动关闭Bot会话,确保aiohttp的TCP连接被正确释放,不会在Lambda环境复用时出现"未关闭连接"的警告和后续错误。
- 复用已存在的事件循环,符合Lambda的执行环境特性,减少循环创建销毁的开销。
内容的提问来源于stack exchange,提问作者Old Japonec
相关产品推荐
相关产品推荐

