芹菜生产优雅重启

时间:2017-03-15 14:06:56

标签: python celery

我需要重新启动celery守护程序,但是我需要它来告诉当前工作人员在他们的任务完成时关闭,然后在旧的工作人员仍然关闭的情况下启动一组新的工作人员。

守护程序上的当前正常选项在重新启动之前等待所有任务完成,这对于长时间运行的作业没有用。

请不要建议自动加载,因为它目前在4.0.2中没有记录。

3 个答案:

答案 0 :(得分:2)

好吧,我最终做的是使用supervisord和ansible来管理它。

[program:celery_worker]
# Max concurrent task you wish to run.
numprocs=5
process_name=%(program_name)s-%(process_num)s
directory=/opt/worker/main
# Ignore this unless you want to use virtualenvs.
environment=PATH="/opt/worker/main/bin:%(ENV_PATH)s"
command=/opt/worker/bin/celery worker -n worker%(process_num)s.%%h --app=python --time-limit=3600 -c 5 -Ofair -l debug --config=celery_config -E
stdout_logfile=/var/log/celery/%(program_name)s-%(process_num)s.log
user=worker_user
autostart=true
autorestart=true
startretries=99999
startsecs=10
stopsignal=TERM
stopwaitsecs=7200
killasgroup=false

您可以使用主管来停止/启动工作人员来加载新代码,但它会等待所有人再次启动它们之前停止,这对于长时间运行的作业来说效果不佳。最好只需要对MainProcesses进行TERM,这将告诉工人停止接受工作并在工作结束时关闭。

ps aux | grep *celery.*MainProcess | awk '{print $2}' | xargs kill -TERM

主管将在他们死后重新启动它们。

当然,在不完全停止所有工作人员的情况下更新依赖关系是非常不可能的,这使得使用像docker这样的东西非常好。 ;)

答案 1 :(得分:0)

在Celery4上,我必须修补基本Task类以使其起作用。 Source

import signal
from celery import Celery, Task
from celery.utils.log import get_task_logger
logger = get_task_logger('my_logger')

class MyBaseTask(Task):
    def __call__(self, *args, **kwargs):
        signal.signal(signal.SIGTERM,
                      lambda signum, frame: logger.info('SIGTERM received, 
                                            wait till the task finished'))
        return super().__call__(*args, **kwargs)

app = Celery('my_app')
app.Task = MyBaseTask

还有一个patch可以防止在警告关机时重新安排时间

答案 2 :(得分:0)

我们有可能要运行48小时的任务。当我们发布新版本并将新版本部署到生产环境时,您谈论的重启很正常。我们要做的只是向正在运行的工作程序发送SIGTERM(关机)信号,然后并行启动一组全新的工作程序。