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

Celery Periodic Task在Heroku上按crontab配置不执行问题

解决Heroku上Celery定时任务部分不执行的问题

我之前在Heroku部署Celery定时任务时也碰到过几乎一模一样的情况,结合你的日志和配置,咱们一步步来排查解决:

1. 优先排查时区问题(这是Heroku上Celery定时任务最常见的坑)

从日志能看到服务器用的是UTC时区,而你的本地环境大概率是本地时区。你设置的invoice_simulation任务是每月3-11号的11:32执行,但这个时间如果是基于你本地时区定义的,到了UTC时区的Heroku服务器上,实际执行时间会偏移时区差,甚至可能不在你预期的日期范围内。

解决步骤:

  • 在Django的settings.py里明确配置时区:
    TIME_ZONE = 'Asia/Shanghai'  # 替换成你的实际时区,比如'Europe/London'
    USE_TZ = True
    
  • 让Celery同步使用Django的时区,在Celery配置文件(比如celery.py)里添加:
    from django.conf import settings
    app.conf.timezone = settings.TIME_ZONE
    

2. 拆分Celery Worker和Beat进程

你现在用celery -A mdn_core_engine worker -B在同一个dyno里同时跑Worker和Beat,但Heroku的dyno环境对进程管理有一定限制,可能导致Beat的调度逻辑不稳定,出现任务漏跑的情况。

解决步骤:

  • 单独创建两个dyno分别运行:
    • 一个专门跑Beat调度:celery -A mdn_core_engine beat --loglevel=info
    • 另一个跑任务执行Worker:celery -A mdn_core_engine worker --loglevel=info
  • 推荐使用持久化调度器,避免dyno重启后丢失调度状态:
    1. 安装依赖包:pip install django-celery-beat
    2. 将包添加到Django的INSTALLED_APPS:'django_celery_beat',
    3. 执行数据库迁移:python manage.py migrate
    4. 在Celery配置里指定调度器:
      app.conf.beat_scheduler = 'django_celery_beat.schedulers:DatabaseScheduler'
      

3. 验证任务本身的可执行性

虽然本地正常,但可以临时修改invoice_simulation的调度规则,改成每分钟执行一次,测试在Heroku上能不能触发:

from celery.utils.log import get_task_logger

logger = get_task_logger(__name__)

@periodic_task(run_every=(crontab(minute='*')), name="invoice_simulation", ignore_result=False)
def invoice_simulation():
    logger.info('---- invoice_simulation task started-----')
    # 执行相关操作

然后用heroku logs --tail --app 你的应用名称实时查看日志,确认任务是否有输出。

4. 核对crontab表达式的实际执行时间

再确认下crontab(day_of_month='3-11', hour=11, minute=32)在UTC时区下的实际时间。比如如果你的本地时区是UTC+8,服务器上的11:32 UTC对应你本地的19:32,如果你误以为任务会在本地11:32执行,那它其实会在你本地晚上运行,可能没注意到日志输出。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:06:55