簡體   English   中英

自定義 Celery 任務初始化

[英]Custom Celery task initialisation

文檔說自定義任務只實例化一次,這是一種緩存所需數據(如所有任務調用的數據庫連接)的好方法。 但它似乎既發生在工人身上,也發生在調用者身上。 任務 MCVE:

# tasks.py

from celery import Celery, Task
from time import sleep

celery = Celery(
    broker="redis://127.0.0.1:6379/0",
    backend="redis://127.0.0.1:6379/0"
)


class PatternTask(Task):
    def __init__(self):
        print("Initialising task")
        sleep(10)
        self._pattern = "Hello, %s!"
        print("Initialised task")

    @property
    def pattern(self):
        return self._pattern

@celery.task(base=PatternTask)
def hello(who):
    sleep(2)
    return hello.pattern % who

和調用代碼:

# main.py

from tasks import hello

print(hello.delay("world").get())
print(hello.delay("you").get())

這將使工作人員和調用代碼都延遲 10 秒:

$ python main.py
Initialising task
# <10 seconds>
Initialised task
# <2 seconds>
Hello, world!
# <2 seconds>
Hello, you!

我知道這對於支持不涉及工人的hello("now")的情況是必要的。 但是,有沒有辦法 promise 我永遠不會這樣做,並且避免昂貴的sleep操作和巨大的時間浪費,memory 和 CPU 資源†在調用代碼中分配_pattern 如果不是,這種情況下推薦的解決方案是什么?


†) 實際用例是加載工人操作所需的千兆字節數據,調用代碼將無用。

解決方案是:Celery 信號。

# tasks.py

from celery import Celery, Task, signals
from time import sleep

celery = Celery(
    broker="redis://127.0.0.1:6379/0",
    backend="redis://127.0.0.1:6379/0"
)


class PatternTask(Task):
    def __init__(self):
        super().__init__()
        signals.worker_init.connect(self.on_worker_init)

    def on_worker_init(self, *args, **kwargs):
        print("Initialising task")
        sleep(10)
        self._pattern = "Hello, %s!"
        print("Initialised task")

    @property
    def pattern(self):
        return self._pattern

@celery.task(bind=True, base=PatternTask)
def hello(self, who):
    print(f"In hello {who}")
    sleep(2)
    print(f"Done hello {who}")
    return self.pattern % who

celery.signals.worker_init處理程序全部完成之前,工人顯然不會開始接受工作。 (我還使用bind=True使其更易於維護;這與解決方案無關。)

暫無
暫無

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

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