You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 19:02:40