【问题标题】:How can I make celery die after there are no more tasks to be run?没有更多任务要运行后,如何使芹菜死亡?
【发布时间】:2016-05-11 20:43:17
【问题描述】:

我有一个 celery 任务是内存密集型的,我希望它在大部分时间都处于关闭状态的昂贵 AWS 服务器上运行。

celery beat 会每天安排一次任务,但也可以通过网络应用程序 (== django) 手动安排。

调度任务就是向兔子队列发送消息。

然后我想使用 AWS api 发出一个命令来打开我昂贵的服务器,并让它启动工作人员, 在没有更多任务后等待它们死亡,然后关闭(并节省一些钱,因为服务器已关闭)。

我知道如何编写 AWS 脚本来打开我的服务器。问题是:如何告诉 celery 运行任务直到队列为空然后死亡

有没有我可以给它的命令参数,还是我需要为此想出一些技巧?

【问题讨论】:

  • 为什么要通过 Celery 来做这件事?为什么不直接启动昂贵的进程并让它在完成后简单地退出?
  • 任务可能需要一段时间才能运行。当它正在运行一个运行另一个类似任务的请求时,可能会进来。它需要排队。
  • 明确一点:这里的目的是在不再需要服务器后关闭服务器(在 AWS 中省钱)

标签: django amazon-web-services celery django-celery


【解决方案1】:

芹菜工人只是一匹笨马。如果工作人员正在等待任务,则必须有其他东西监视工作人员并触发事件。

使用Flower 监控您的Celery 集群,使用their API 使用worker 活动。

Flower 有一个漂亮的仪表板,其中包含工人/任务数据,信息就在那里,而且他们有一个 API。

【讨论】:

  • 我不知道花。不错!
【解决方案2】:

我的建议:创建一个回调以在任务完成后运行。此回调将使用 AWS 实例信息向您的 Web 应用程序发出请求,并使用此信息将其关闭。

编辑:这假设您将每个任务路由到一台新机器上。例如,在等待销毁时,Celery worker 不应该接受任何新任务。

EDIT2:另一个好主意可能是让这个昂贵的任务本身将请求发送到网络应用程序以销毁 Amazon 实例并杀死 Celery 工作人员(检查http://www.pythondoc.com/celery-3.1.11/userguide/workers.html#stopping-the-worker)/

【讨论】:

    【解决方案3】:

    感谢@iurisilvio 和@douglas-camata 的回答。我想我利用你们的一些想法找到了一个理想的解决方案:-)

    我自己用这个 django 命令创建了一个简单的监视器(我的应用毕竟是 django)== wait_celery_idle.py

    import time
    from django.core.management.base import NoArgsCommand
    from core.celery_utils import celery_count_status as ccount
    import celery
    
    
    class Command(NoArgsCommand):
    
        help = "Waits until celery is idle"
    
        def handle(self, *args, **options):
            while _count() > 0:
                time.sleep(5)
    
    
    def _count():
        cinspect = celery.current_app.control.inspect()
        return ccount(cinspect.active()) + ccount(cinspect.scheduled()) + ccount(cinspect.reserved())
    
    def ccount(d):
        k = d.keys()[0]
        return len(d[k])
    

    然后我正常启动 celery 过程,例如:./manage.py celery worker -c 1 --pidfile /tmp/celery.pid

    然后我启动第二个进程 (wait_and_die.sh) 来监控 celery,如果它空闲太久就会死掉。

    #!/bin/bash
    # wait_and_die.sh
    
    ./manage.py wait_celery_idle
    kill $(cat /tmp/celery.pid)
    sleep 10
    sudo shutdown -h now
    

    PS:这仅在我使用 rabbit 作为队列基础结构时才有效 - 如果我使用 django db 作为队列,cinspect.* 方法返回 None(在 settings.py 中使用 CELERY_BROKER_URL='django://'

    【讨论】:

    • 一旦worker停止了,怎么重新启动它?我没有用过 celery beat,但是看着文档我没有看到它启动了工人。我是否以某种方式错过了它?
    猜你喜欢
    • 1970-01-01
    • 2023-01-31
    • 2016-08-19
    • 1970-01-01
    • 2019-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-25
    相关资源
    最近更新 更多