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

部署在Heroku的Telegram Bot使用Webhook时定时任务失效问题

问题解决:Webhook模式下Telegram Bot定时任务停止运行的修复方案

核心原因

使用start_webhook时,它会自行管理异步事件循环,你之前在__main__中创建的check任务没有被正确关联到Webhook启动的事件循环中,导致任务执行到第一个await asyncio.sleep后就被挂起,无法继续循环。

修复步骤

1. 将定时任务移至on_startup回调中

Webhook启动时会触发on_startup函数,此时事件循环已完全初始化,在这里创建定时任务才能被正确纳入循环管理。同时要保存任务引用,避免被垃圾回收:

import asyncio
from aiogram import Dispatcher

# 全局变量保存定时任务引用
check_task = None

async def on_startup(dp: Dispatcher):
    global check_task
    # 启动每分钟检查的定时任务
    check_task = asyncio.create_task(check(60))
    # 保留你原有的Webhook初始化逻辑(比如设置Telegram Webhook地址)
    await setup_webhook(dp)

async def on_shutdown(dp: Dispatcher):
    global check_task
    # 关闭定时任务
    if check_task:
        check_task.cancel()
        try:
            await check_task
        except asyncio.CancelledError:
            pass
    # 保留你原有的关闭逻辑
    await dp.storage.close()
    await dp.storage.wait_closed()

2. 优化check函数,避免阻塞事件循环

如果你的parsing()是同步函数,必须用run_in_executor包装,防止阻塞Webhook的事件循环(Webhook需要实时响应Telegram的请求,阻塞会导致服务异常):

async def check(wait_for):
    print("Debug: check is awaited")
    while True:
        print("Debug: inside while")
        await asyncio.sleep(wait_for)
        print("after sleep")
        # 用线程池执行同步的parsing函数
        loop = asyncio.get_running_loop()
        transactions = await loop.run_in_executor(None, parsing)
        # 这里添加交易处理逻辑(比如发送Telegram消息)

3. 启动Webhook的代码保持不变

start_webhook(
    dispatcher=dp,
    webhook_path=WEBHOOK_PATH,
    on_startup=on_startup,
    on_shutdown=on_shutdown,
    skip_updates=True,
    host=WEBAPP_HOST,
    port=WEBAPP_PORT
)

额外注意事项

  • Heroku的Web服务有请求超时限制,确保所有异步操作都不会长时间阻塞事件循环。
  • 如果parsing()涉及网络请求,建议改用异步请求库(如aiohttp)替代同步库,进一步提升性能。

内容的提问来源于stack exchange,提问作者Valerii

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 09:45:46