Celery包含一个能够使用amqp或其他一些芹菜后端发出异步HTTP请求的模块。我正在使用tornado-celery生产者进行异步消息发布。据我所知tornado-celery使用鼠兔为此。问题是如何使celery.task.http.URL适应龙卷风(使其无阻塞)。基本上有两个地方需要改进:
HttpDispatch.make_request()
必须使用tornado async http client实现; URL.get_async(**kw)
或URL.post_async(**kw)
。例如:
class NonBlockingURL(celery.task.http.URL):
@gen.coroutine
def post_async(self, **kwargs):
async_res = yield gen.Task(self.dispatcher.delay,
str(self), 'POST', **kwargs)
raise gen.Return(async_res)
但我无法理解如何以恰当和简洁的方式做到这一点。如何使其完全像非异步的非阻塞?顺便说一下,我正在使用amqp后端。
请给我一个很好的指导,甚至更好,一个例子。
答案 0 :(得分:1)
实际上,你必须决定是否使用Tornado的异步方法,或者你是否使用像cellery这样的队列。没有使用两者的意义,因为队列快速回答队列的状态,所以在等待队列响应时没有龙卷风做其他事情。为了在两种解决方案之间做出决定,我会说:
芹菜:更多的模块化,易于分发到不同的核心或不同的机器,任务可以被别人使用而不是龙卷风,你必须安装并继续运行softare(amqp,cellery workers ......)
Tornado中的异步:更多单片,一个程序可以执行所有操作,更短的代码,一个程序可以运行
要使用Tornado的异步方法,请参阅文档。 这是一个使用芹菜和龙卷风的简短解决方案:
from celery import Celery,current_task
import time
celery=Celery('tasks',backend='amqp',result_backend='amqp')
@celery.task
def MyTask(url,resid):
for i in range(10):
time.sleep(1)
current_task.update_state(state='running',meta={'i': i})
return 'done'
import tasks
from tornado import RequestHandler,....
from tornado.web import Application
dictasks={}
class runtask(RequestHandler):
def post(self):
i=len(dictasks)
dictasks[i]=task.MyTask.delay()
self.write(i)
class chktask(RequestHandler):
def get(self,i):
i=int(i)
if dictasks[i].ready():
self.write(dictasks[i].result)
del dictasks[i]
else:
self.write(dictasks[i].state + ' i:' + dictasks[i].info.get('i',-1))
Application = Application([
(r"/runtask", runtask}),
(r"/chktask/([0-9]+)", chktask),
etc.