[英]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.