繁体   English   中英

celery、celerybeat 和 django-celery-beat 是否可以在运行时动态添加/删除任务而无需重新启动 celerybeat?

[英]Can celery,celerybeat and django-celery-beat dynamically add/remove tasks in runtime without restart celerybeat?

我尝试了所有我能找到的东西,包括:

堆栈溢出

如何动态添加/删除定期任务到 Celery (celerybeat)

celery celerybeat 可以在运行时动态添加/删除任务吗?

Github 问题

如何动态地向 celerybeat 添加或删除任务?

我从上面得到的是,如果我只使用 celery 和 celery 节拍,我必须在添加/删除任务后重新启动 celery 节拍。 但如果我结合 django-celery-beat,我就不必重新启动它。

我一步一步地遵循文档

from celery import Celery
from celery.schedules import crontab

app = Celery('tasks')
app.config_from_object('celeryconfig')
app.conf.timezone = 'UTC'

@app.on_after_configure.connect
def setup_periodic_tasks(sender, **kwargs):
    # Calls test('hello') every 10 seconds.
    sender.add_periodic_task(10.0, test.s('hello'), name='add every 10')

    # Calls test('world') every 30 seconds
    sender.add_periodic_task(30.0, test.s('world'), expires=10)

    # Executes every Monday morning at 7:30 a.m.
    sender.add_periodic_task(
        crontab(hour=7, minute=30, day_of_week=1),
        test.s('Happy Mondays!'),
    )

@app.task
def test(arg):
    print(arg)

我的芹菜配置

BROKER_URL = 'amqp://rabbit'
CELERY_RESULT_BACKEND = 'rpc://rabbit'
CELERY_RESULT_PERSISTENT = True
# CELERY_ACKS_LATE = True
CELERY_DEFAULT_DELIVERY_MODE = 2
CELERY_TASK_RESULT_EXPIRES = 3600
CELERYBEAT_SCHEDULER ="django_celery_beat.schedulers:DatabaseScheduler"

我的 celery 击败运行命令

celery -A tasks beat -l info -S django

这很好用,任务按预期运行。之后,我编写了一个脚本来在运行时添加任务

import django
django.setup()
from tasks import app, setup_periodic_tasks
from django_celery_beat.models import PeriodicTask, CrontabSchedule


crontab = CrontabSchedule.objects.create(
       minute='*/1',
       hour='*',
       day_of_week='*',
   )

period = PeriodicTask.objects.create(
       name='testfasd',
       kwargs={},
       crontab=crontab,
       task='tasks.test',
   )

setup_periodic_tasks(app)

当我查看数据库时,我得到了预期的结果,新记录以及 last_update 字段已更新。celery 中的日志也证明了这一点

[2016-12-20 17:37:21,796: INFO/MainProcess] Writing entries...
[2016-12-20 17:37:21,840: INFO/MainProcess] Scheduler: Sending due task add every 10 (tasks.test)
[2016-12-20 17:37:31,848: INFO/MainProcess] DatabaseScheduler: Schedule changed.
[2016-12-20 17:37:31,851: INFO/MainProcess] Writing entries...
[2016-12-20 17:37:31,930: INFO/MainProcess] Scheduler: Sending due task add every 10 (tasks.test)

我的问题是虽然 celery 知道数据库已经改变,但它仍然发送旧任务并且不发送新任务给工人。 任何想法?

更新

我为我的项目使用 docker,也许它是相关的。

这个github问题

[你不能在celerybeat中添加或删除任务]目前,你必须重启beat。

不。为了刷新芹菜[beat]内的任务或任务时间,你必须重新启动celery [beat]实例。 任务在运行时加载到内存中。 要更改/添加任务,您必须刷新实例。

您可以考虑使用自定义任务,使用自定义计时和条件执行。 例:

from datetime import timedelta
from celery import shared_task

@shared_task
def check_conditions():
    # Do some db-level code
    if condition:
        check_conditions.apply_async(eta=timedelta(hours=6))

我在生产中使用它并且表现良好。

如果你需要重新加载任务,只需以编程方式重启celery [beat]:

@shared_task
def autoreload():
    if condition:
        execute_shell_code_to_restart_celery()

我没有使用它,也不能保证它的可用性,但理论上应该可行。

这个github问题

我必须重新加载节拍才能让这个更改在工作人员上更新...使用django-celery-beat ...这个问题仍然存在于4.0.2和主人,测试[2016年12月21日]。

警告

如果您更改 Django TIME_ZONE 设置,您的定期任务计划仍将基于旧时区。

要解决这个问题,您必须为每个周期性任务重置“上次运行时间”:

 from django_celery_beat.models import PeriodicTask, PeriodicTasks
 PeriodicTask.objects.all().update(last_run_at=None)
 for task in PeriodicTask.objects.all():
     PeriodicTasks.changed(task)

我遇到了和你完全一样的问题。 问题出在 django-celery-beat package 中,它使用DatabaseScheduler及其实现方式,如果你想动态管理周期性任务(添加、删除、更新)而无需在每次添加任务时重新启动 celery 节拍,并且如果你愿意要使用Redis也可以使用这个库https://pypi.org/project/celery-redbeat/ 如果你想更好地控制你的任务,我也写了一个基于它的库,并在本地使用Django https://pypi.org/project/django-redbeat/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM