繁体   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