如何在不杀死未完成的芹菜任务的情况下重新启动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应用程序的主要内容,如果未能解决你的问题,请参考以下文章