芹菜连续部署

时间:2018-10-03 06:40:43

标签: python celery continuous-deployment

我有一个服务,该服务公开一个API,然后该API负责执行任务,它是通过Falcon(API)和Celery(任务管理)实现的。

具体来说,我的工作人员需要很长时间才能加载,并且他们的代码看起来像这样

class HeavyOp(celery.Task):
    def __init__(self):
        self._asset = get_heavy_asset()  # <-- takes long time

    @property
    def asset(self):
        return self._asset

@app.task(base=HeavyOp)
def my_task(data):

    return my_task.asset.do_something(data)

实际发生的情况是,在__init__函数中,从磁盘读取某些对象并将其保存在内存中的时间,直到工作人员生存为止。

有时候,我想更新该对象。

有没有一种方法可以在不停机的情况下重新加载工作程序?由于这都是API的背后功能,所以我不希望花这么几分钟来加载重对象作为停机时间。

我们可以假设主机具有1个以上的内核,但是解决方案必须是单个主机解决方案。

1 个答案:

答案 0 :(得分:0)

我认为您不需要自定义基本任务类。您想要实现的是一个单实例资产类,该类将在工作人员初始化之后加载,您可以从任务中重新加载。

此方法有效:

# worker.py
import os
import sys
import time

from celery import Celery
from celery.signals import worker_ready


app = Celery(include=('tasks',))

class Asset:

    def __init__(self):
        self.time = time.time()



class AssetLoader:
    __shared_state = {}

    def __init__(self):
        self.__dict__ = self.__shared_state
        if '_value' not in self.__dict__:
            self.get_heavy_asset()

    def get_heavy_asset(self):
        self._value = Asset()

    @property
    def value(self):
        return self._value


@worker_ready.connect
def after_worker_ready(sender, **kwargs):
    AssetLoader()

在这里,我使AssetLoader成为Borg类,但是您可以选择任何其他模式/策略来共享Asset的单个实例。出于说明目的,我只捕获了执行get_heavy_asset时的时间戳。

# tasks.py
from worker import app, AssetLoader


@app.task(bind=True)
def load(self):
    AssetLoader().get_heavy_asset()
    return AssetLoader().value.time

@app.task(bind=True)
def my_task(self):
    return AssetLoader().value.time

请记住,资产是按工作人员进程共享的,但不能跨工作人员共享。如果您使用concurrency=1进行运行,则没有任何区别,但是对于其他任何事情,它都可以。但是从我收集到的用例来看,无论哪种方式都应该很好。