2016-04-15 90 views
2

我正在構建一個使用CherryPy進行數據迭代批處理的Web服務。理想的工作流程如下:如何從CherryPy BackgroundTask儘可能快地運行數據返回

  1. 用戶發佈的數據服務進行處理
  2. 當處理工作是免費的,它收集的排隊數據,並開始另一次迭代
  3. 雖然在處理作業,用戶正在將更多數據發佈到隊列以供下一次迭代使用
  4. 當前迭代完成後,結果會被傳回,以便用戶可以使用相同的API來獲取它們。
  5. 作業從下一批排隊的數據開始。

這裏關鍵的一點是,無論隊列中的數據量如何,處理都應該儘可能快地運行,每當前一次完成時就開始迭代。每次迭代可以持續多長時間沒有上限,所以我無法創建一個固定的時間表來運行。

有幾個使用BackgroundTasklike this one)的例子,但我還沒有找到一個處理返回數據的例子,或者一個處理儘可能快的任務而不是按照固定的時間表運行的例子。

我並不喜歡BackgroundTask解決方案,所以如果任何人都可以提供替代方案,我會非常高興。感覺就像框架內有一個解決方案。

回答

2

請勿使用BackgroundTask解決方案運行後臺任務,因爲它將運行在線程中,並且由於GIL,cherrypy將無法應答新請求。使用隊列解決方案在不同的進程中運行後臺任務,如CeleryRQ

我打算詳細介紹一個使用RQ的例子。 RQ使用Redis作爲消息代理,因此首先需要安裝並啓動Redis。

然後創建一個模塊(mytask在我的例子)與長時間運行的後臺方法:

import time 
def long_running_task(value): 
    time.sleep(15) 
    return len(value) 

開始一個(或不止一個,如果你想運行並行任務)RQ工人,這一點很重要該運行你的員工蟒蛇訪問您mytask模塊(運行工人之前導出PYTHONPATH如果你的模塊是不是已經在路徑):

# rq worker 

在上面,你有一個非常簡單的Web應用程序的CherryPy展示瞭如何使用RQ隊列:

import cherrypy 
from redis import Redis 
from rq import Queue  
from mytask import long_running_task 


class BackgroundTasksWeb(object): 

    def __init__(self): 
     self.queue = Queue(connection=Redis()) 
     self.jobs = [] 

    @cherrypy.expose 
    def index(self): 
     html = ['<html>', '<body>'] 
     html += ['<form action="job">', '<input name="q" type="text" />', '<input type="submit" />', "</form>"] 
     html += ['<iframe width="100%" src="/results" />'] 
     html += ['</body>', '</html>'] 
     return '\n'.join(html) 

    @cherrypy.expose 
    def results(self): 
     html = ['<html>', '<head>', '<meta http-equiv="refresh" content="2" >', '</head>', '<body>'] 
     html += ['<ul>'] 
     html += ['<li>job:{} status:{} result:{} input:{}</li>'.format(j.get_id(), j.get_status(), j.result, j.args[0]) for j in self.jobs] 
     html += ['</ul>'] 
     html += ['</body>', '</html>'] 
     return '\n'.join(html) 

    @cherrypy.expose 
    def job(self, q): 
     job = self.queue.enqueue(long_running_task, q) 
     self.jobs.append(job) 
     raise cherrypy.HTTPRedirect("/") 


cherrypy.quickstart(BackgroundTasksWeb()) 

在生產web應用程序,我會用Jinja2的模板引擎生成HTML,最有可能的WebSockets更新Web瀏覽器的工作狀態。

+0

很好的回答,謝謝!我最終用一種類似的架構對它進行了黑客攻擊,但幾乎沒有你所做的那麼整齊。我還沒有聽說過芹菜或RQ,但我會考慮將來使用它們。 – Mourndark