如何在不杀死未完成的芹菜任务的情况下重新启动heroku应用程序

Posted

技术标签:

【中文标题】如何在不杀死未完成的芹菜任务的情况下重新启动heroku应用程序【英文标题】:How to restart heroku app without killing unfinished celery tasks 【发布时间】:2019-04-26 10:00:00 【问题描述】:

我在 heroku 上有一个 django Web 应用程序,其中可能在后台运行多个 celery 任务。 Redis 用作代理。

问题是,当我在执行某些任务时使用heroku restart 或使用heroku container:release 重新启动heroku 应用程序时,它们会被SIGTERM 杀死,这意味着任务永远不会完成。

2018-11-23T19:35:24.506833+00:00 heroku[beat.1]: Restarting
2018-11-23T19:35:24.507645+00:00 heroku[beat.1]: State changed from up to starting
2018-11-23T19:35:24.517551+00:00 heroku[web.1]: Restarting
2018-11-23T19:35:24.518013+00:00 heroku[web.1]: State changed from up to starting
2018-11-23T19:35:24.528684+00:00 heroku[worker.1]: Restarting
2018-11-23T19:35:24.529175+00:00 heroku[worker.1]: State changed from up to starting
2018-11-23T19:35:24.952139+00:00 app[worker.1]: 
2018-11-23T19:35:24.952156+00:00 app[worker.1]: worker: Warm shutdown (MainProcess)
2018-11-23T19:35:24.949622+00:00 heroku[worker.1]: Stopping all processes with SIGTERM
2018-11-23T19:35:24.996307+00:00 heroku[worker.1]: Process exited with status 143
2018-11-23T19:35:25.456920+00:00 heroku[web.1]: Stopping all processes with SIGTERM
2018-11-23T19:35:25.480748+00:00 app[web.1]: [2018-11-23 19:35:25 +0000] [16] [INFO] Handling signal: term
2018-11-23T19:35:25.481026+00:00 app[web.1]: [2018-11-23 19:35:25 +0000] [19] [INFO] Worker exiting (pid: 19)
2018-11-23T19:35:25.481491+00:00 app[web.1]: [2018-11-23 19:35:25 +0000] [20] [INFO] Worker exiting (pid: 20)
2018-11-23T19:35:25.481519+00:00 app[web.1]: [2018-11-23 19:35:25 +0000] [21] [INFO] Worker exiting (pid: 21)
2018-11-23T19:35:25.623274+00:00 heroku[web.1]: Process exited with status 143
2018-11-23T19:35:25.816061+00:00 heroku[beat.1]: Stopping all processes with SIGTERM
2018-11-23T19:35:25.928498+00:00 heroku[beat.1]: Process exited with status 143

根据我在互联网上的发现,由 SIGTERM 引起的热关机应该等待任务完成,但它没有发生。他们只是被杀了。

这是为什么呢? 我是否必须进行一些配置才能实现所需的行为?或者它只是不工作?

对于当前的行为,我不确定如何进行部署,除非我以某种方式检查没有任务正在运行,然后我重新启动。

【问题讨论】:

将其作为评论发布可能更有意义,因为它没有解释如何在不终止 celery 任务的情况下重新启动 heroku,但提供了一种解决方法:您可以配置 Celery 并启用 task_acks_late 和 @987654327 @ 这将确保队列仅在任务完成后接收和确认来自 celery 的信号,并且如果工作人员被杀死 task_reject_on_worker_lost 将确保消息重新排队,而不是标记为已完成。跨度> 感谢您的建议。不幸的是,这似乎不适用于 redis 进行一些阅读,仅适用于 rabbitmq (github.com/celery/celery/issues/3541)。该链接也提供了一些建议,这个似乎对我有用:gist.github.com/mlavin/6671079 所以经过一些测试,上述方法也不能完美运行。任务有时会在heroku restartw 后恢复,但有时需要重新启动heroku 几次才能重新安排任务。 【参考方案1】:

这里的问题是 heroku 向 celery 发送了错误的信号,它不会被热关机并且被杀死以重新启动。

从 Celery 4 开始(如果我没记错的话),您可以告诉 celery 听不同的信号。对我们来说,这很有效。

将您的 Procfile 更改为包含您的工作进程的 REMAP_SIGTERM=SIGQUIT

celeryworker: REMAP_SIGTERM=SIGQUIT  celery -A testproject worker

这将有芹菜,例如在本地排队的重新排队任务。

请记住: 大约 10 或 20 秒后仍然有硬杀。因此,如果您的任务运行时间更长,则必须调整 acks_late

【讨论】:

以上是关于如何在不杀死未完成的芹菜任务的情况下重新启动heroku应用程序的主要内容,如果未能解决你的问题,请参考以下文章

为啥创建了芹菜任务但未收到

用芹菜对特定任务设置时间限制

如何在不重新启动树莓派本身的情况下重新启动 ALSA?

是否可以在不重新启动服务器的情况下在远程 weblogic 上重新部署应用程序?

如何在不延迟任务的情况下优雅地重启 Celery

在应用程序被杀死后在应用程序启动时恢复未完成的多部分/表单数据上传任务