由于没有人提供这个帖子的解决方案以及我迫切需要一个解决方法的事实,这里是我的情况和一些抽象的解决方案/想法供辩论.
我的堆栈:
龙卷风
芹菜
MongoDB的
Redis的
的RabbitMQ
我的问题:为Tornado找到一种方法来调度芹菜任务(已解决),然后异步收集结果(任何想法?).
场景1 :(请求/响应黑客加上webhook)
Tornado接收(用户)请求,然后在本地内存(或Redis)中保存{jobID :(用户)请求}以记住传播响应的位置,并使用jobID触发芹菜任务
当芹菜完成任务时,它会在某个网址上执行webhook并告诉龙卷风这个jobID已经完成(加上结果)
Tornado检索(用户)请求并将响应转发给(用户)
这会发生吗?它有任何逻辑吗?
场景2 :(龙卷风加长轮询)
Tornado调度celery任务并将一些主json数据返回给客户端(jQuery)
jQuery在收到主json后进行一些长轮询,比方说,每隔x微秒,龙卷风根据某个数据库标志回复.当celery任务完成时,此数据库标志设置为True,然后jQuery"loop"结束.
这有效吗?
还有其他想法/架构吗?
我的解决方案涉及从龙卷风到芹菜的轮询:
class CeleryHandler(tornado.web.RequestHandlerr): @tornado.web.asynchronous def get(self): task = yourCeleryTask.delay(**kwargs) def check_celery_task(): if task.ready(): self.write({'success':True} ) self.set_header("Content-Type", "application/json") self.finish() else: tornado.ioloop.IOLoop.instance().add_timeout(datetime.timedelta(0.00001), check_celery_task) tornado.ioloop.IOLoop.instance().add_timeout(datetime.timedelta(0.00001), check_celery_task)
这是关于它的帖子.
这是我们解决问题的方法.由于我们在应用程序中查找了几个处理程序的结果,因此我们将芹菜查找为mixin类.
这也使得tornado.gen模式的代码更具可读性.
from functools import partial class CeleryResultMixin(object): """ Adds a callback function which could wait for the result asynchronously """ def wait_for_result(self, task, callback): if task.ready(): callback(task.result) else: # TODO: Is this going to be too demanding on the result backend ? # Probably there should be a timeout before each add_callback tornado.ioloop.IOLoop.instance().add_callback( partial(self.wait_for_result, task, callback) ) class ARemoteTaskHandler(CeleryResultMixin, tornado.web.RequestHandler): """Execute a task asynchronously over a celery worker. Wait for the result without blocking When the result is available send it back """ @tornado.web.asynchronous @tornado.web.authenticated @tornado.gen.engine def post(self): """Test the provided Magento connection """ task = expensive_task.delay( self.get_argument('somearg'), ) result = yield tornado.gen.Task(self.wait_for_result, task) self.write({ 'success': True, 'result': result.some_value }) self.finish()