将异步协程作为celery任务运行

时间:2019-09-03 13:50:54

标签: python async-await celery tornado python-asyncio

我希望能够在我的芹菜任务中使用异步代码。它适用于异步或龙卷风。我发现我可以做这样的事情


from tornado.ioloop import IOLoop

from celery._state import _task_stack

from . import celery


class AsyncTask(celery.Task):

    def __call__(self, *args, **kwargs):
        _task_stack.push(self)
        self.push_request(args=args, kwargs=kwargs)
        try:
            IOLoop.current().run_sync(lambda: self.run(*args, **kwargs))
        finally:
            self.pop_request()
            _task_stack.pop()

然后像这样使用它

from .celery import celery
from tornado.httpclient import AsyncHTTPClient

@celery.task(base=AsyncTask)
async def test_async_celery_task(x, y):
    result = await AsyncHTTPClient().fetch(request='https://google.com.ua')
    print('Async IS OKAY: {}'.format(result))

或者我可以直接在任务中使用run_sync,这不是可取的

我想知道是否可以执行上述操作,还是应该在worker中启动事件循环并通过add_future启动我的任务。还有其他人做了类似的事情吗?我可以希望性能有所提高吗?

我需要这个,因为我需要能够使用项目其他部分的异步代码,例如数据库调用ets

1 个答案:

答案 0 :(得分:0)

不是正确地使用ioloop会使事情变得复杂,但是让Celery知道它可以并且应该使用异步任务。 Celery与Pools一起运营,可以在此安排您的工作。 Celery知道(通过配置)池可以是线程的,可以是多进程的,它具有X个进程,Y个线程,Z个工作器,其中有多少个有作业或空闲状态。但是从技术上来说,Celery在ATM上能够接收和运行协程,但是开箱即用无法计数它们来追踪其中有多少工作或免费工作。如果您想看一下它的外观-有a development code of future Celery's Asyncpool