如何使用redis作为经纪人和后端在Tornado中使用Celery?

时间:2017-08-18 01:50:39

标签: python celery tornado

当我尝试在Tornado4.2中使用celery3.1.11,tornado-celery0.3.5时,会产生异常。它的工作没有收益,但不能得到结果异步...当我使用rabbitmq作为经纪人时我也发现它有效,而redis会引发以下错误......

这是我的代码。

from mycelery import celery_task
import tcelery
tcelery.setup_nonblocking_producer()

token = yield tornado.gen.Task(celery_task.get_rongcloud_token.apply_async,args=[3])
print token

我的芹菜任务:

from celery import Celery, platforms
from celery.schedules import crontab
from celery.utils.log import get_task_logger
from celery.exceptions import SoftTimeLimitExceeded

platforms.C_FORCE_ROOT = True  # linux 下要root用户才不报错
broker = 'redis://:'+settings.REDIS_PASS+'@127.0.0.1:6379/5'
backend = 'redis://:'+settings.REDIS_PASS+'@127.0.0.1:6379/6'
app = Celery('tasks', broker=broker, backend=backend)

@app.task(name='mycelery.celery_task.get_rongcloud_token')
def get_rongcloud_token(user_id):
    print 'xxxxx'
    a = 'xxx'
    return a

这是错误:

 TypeError: <function wrapper at 0x5bd2c80> is not JSON serializable

哈,找到同样的问题:Tornado celery can't use gen.Task or CallBack

2 个答案:

答案 0 :(得分:0)

关于tcelery的有限文档并没有解释太多,您的示例也没有显示太多内容。从有限的文档中,看起来你似乎正在按预期使用它(除非我遗漏了一些东西)所以我不确定为什么你的代码不起作用。我使用以下方法取得了成功:

class CeleryTasks(web.RequestHandler):

    @gen.coroutine
    def get(self):
        future = concurrent.Future()
        celery_task = tasks.get_rongcloud_token.delay(3)
        check_status(celery_task, future)
        yield future
        self.write(future.result())
        #self.write(celery_task.result)


def check_status(celery_task, future):
    """
    Check the status of the celery task and set the result in the future
    """
    if not celery_task.ready():
        ioloop.IOLoop.current().call_later(
            1,
            check_status,
            celery_task,
            future)
    else:
        future.set_result(celery_task.result)

首先创建一个裸Future,它将产生,直到芹菜任务的结果可用。接下来像执行异步执行一样执行celery任务(例如task_fn.delay(*args)task_fn.apply_async(*args))。将celery_taskfuture传递给将检查任务是否“就绪”的函数(check_status),如果没有,则稍后递归调用自身并再次检查。然后yield Future,直到设置结果。任务完成并且结果可用后,将Future设置为结果,并对结果执行任何操作。

答案 1 :(得分:0)

基于臭名昭着。没有答案:

def check_status(celery_task, future):
    """
    celery状态检查辅助函数...
    Check the status of the celery task and set the result in the future
    """
    import tornado.ioloop
    if not celery_task.ready():
        tornado.ioloop.IOLoop.current().call_later(
            0.1,  # 100ms
            check_status,
            celery_task,
            future)
    else:
        future.set_result(celery_task.result)

@tornado.gen.coroutine
def celery_get_rongcloud_token(user_id, name='', portraitUri=''):
    from mycelery import celery_task
    import tornado.concurrent

    future = tornado.concurrent.Future()
    get_token_task = celery_task.get_rongcloud_token.delay(user_id, name, portraitUri)
    check_status(get_token_task, future)
    yield future
    token = future.result()
    raise tornado.gen.Return(token)

然后在你的代码中:

token = yield celery_get_rongcloud_token(user_id)