簡體   English   中英

在芹菜中,當工人即將關閉時,如何中止正在運行的任務?

[英]In celery, how to abort running tasks when workers are about to shut down?

我正在用芹菜做長期的工作。 該任務將使用subprocess.Popen創建一個子subprocess.Popen 為了使任務可中止,我編寫以下代碼:

from celery.contrib import abortable

@task(bind=True, base=abortable.AbortableTask)
def my_task(self, *args):
    p = subprocess.Popen([...])
    while True:
        try:
            p.wait(1)
        except subprocess.TimeoutExpired:
            if self.is_aborted():
                p.terminate()
                return
        else:
            break
    # Other codes...

我在控制台中嘗試了它,並且效果很好。 但是,當我決定通過按Ctrl+C來關閉工作程序時,程序會打印出'worker: Warm shutdown (MainProcess)'程序'worker: Warm shutdown (MainProcess)'並阻塞了很長時間,這不是我期望的。 工人即將關閉時,似乎不會發生任務中止。

從文檔中知道, 如果我想中止任務,則應該使用任務ID手動實例化AbortableAsyncResult並調用其.abort()方法。 但是我找不到任何地方可以放置此代碼,因為它需要所有正在運行的任務的ID,而我無法訪問這些ID。

那么,當工作人員即將關閉時,如何為所有正在運行的任務調用.abort() 還是有其他選擇?

我正在將celery 4.1.0和python 3.6.2。

您可以為此使用工作者信號 只需獲取所有正在運行的任務,然后對它們調用.abort()。

受@Ishaan答案的啟發,我自己使用以下代碼解決了該問題:

def my_task(*args):
    p = None
    from celery.platforms import signals

    def int_handler(signum, frame):
        if p is not None:
            p.kill()
            p.wait()

    signals['INT'] = int_handler

    p = subprocess.Popen([...])
    p.wait()
    # Other codes...

該解決方案基於以下考慮:

  • 任務的內部范圍是我可以找到每個工作人員執行的唯一位置。
  • 在任務內部,我可以輕松訪問創建的子流程。
  • SIGINT信號未由芹菜工作者處理,因此不會覆蓋芹菜的默認行為。
  • 一個工人一次只能執行一項任務,因此這種注冊是安全的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM