簡體   English   中英

龍卷風芹菜整合黑客

[英]Tornado celery integration hacks

由於沒有人提供這個帖子的解決方案以及我迫切需要一個解決方法的事實,這里是我的情況和一些抽象的解決方案/想法供辯論。

我的堆棧:

  1. 龍卷風
  2. 芹菜
  3. MongoDB的
  4. Redis的
  5. 的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()

我偶然發現了這個問題並且反復對結果發出后果對我來說並不是最佳選擇。 所以我使用Unix套接字實現了類似於你的場景1的Mixin。

它會在任務完成后立即通知Tornado(准確地說,只要鏈中的下一個任務運行),並且只會在后端命中一次結果。 這是鏈接

現在, https://github.com/mher/tornado-celery來救援......

class GenAsyncHandler(web.RequestHandler):
    @asynchronous
    @gen.coroutine
    def get(self):
        response = yield gen.Task(tasks.sleep.apply_async, args=[3])
        self.write(str(response.result))
        self.finish()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM