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