任務隊列 與 Celery概覽


一、任務隊列(Task Queues)



1.1 什么是任務隊列?

任務隊列用於管理后台工作,通常這些后台工作必須在 HTTP請求-響應循環 之外執行。


1.2 為什么需要任務隊列?

對於那些不是由客戶端HTTP請求產生的任務,或是需要長時間運行的作業,會大大降低HTTP響應的性能,所以這些請求需要異步處理。


示例一:一個Web應用程序可以每10分鍾輪詢一次GitHub API,以收集前100個加星標存儲庫的名稱。任務隊列將處理調用代碼以調用GitHub API、處理結果、並將其存儲在持久數據庫中以供以后使用。

示例二:在HTTP請求-響應周期內數據庫查詢花費的時間太長時。查詢可以在后台以固定間隔執行,結果存儲在數據庫中。當收到一個需要這些結果的HTTP請求時,查詢將簡單地獲取預先計算的結果,而不是重新執行較長的查詢。這種預計算方案是任務隊列啟用的一種緩存形式。

任務隊列的其他類型的作業包括

  • 隨着時間的流逝散布大量獨立的數據庫插入,而不是一次插入所有內容

  • 以固定的時間間隔(例如每15分鍾)聚合收集的數據值

  • 安排諸如批處理之類的定期作業


1.2 常用的任務隊列

事實上的標准Python任務隊列是Celery。其他任務隊列項目的出現,主要是因為對於簡單的使用場景而言Clelery還是有點繁瑣。所以重點還是在Celery。

此外還可以使用第三方的任務隊列服務,用於解決在大規模部署分布式任務隊列時出現的復雜問題。

二、Celery架構及其工作原理概述

運行異步任務的問題可以輕松地映射到經典的生產者/消費者問題問題。生產者將作業排在隊列中。消費者然后檢查隊列中的頭以等待作業,選擇第一個並執行。

在上面的異步任務隊列中,生產者通常是web節點或其他發放任務的系統,隊列稱為broker,消費者稱為workers。而workers也可以發布任務到隊列中,這時候它就成了“生產者”。現在我們已經對任務隊列有一個概覽了,接下來再挖深一點。


2.1 Broker

broker也常譯為中間人,其實就是一個隊列。但是在計算機系統中實現一個隊列的方法有很多。最簡單的方式就是使用文本文件。文本文件可以包含要執行的一系列工作描述,因此,我們可以將它們用作系統的代理。文本文件的問題在於它們不能處理實際的應用程序問題,例如網絡和並發訪問。因此,我們需要更強大的功能。

另一方面,SQL數據庫能夠在網絡中運行並處理並發訪問。它們的問題在於它們太慢。相比之下,NoSQL數據庫的速度相當快,但是很多時候它們缺乏可靠性。

因此,在構建隊列時,我們應該使用快速,可靠,並發啟用的工具,例如RabbitMQRedisSQS

Celery完全支持RabbitMQ和Redis。盡管也可以使用SQS和Zookeeper,但它們提供的功能有限。


2.2 Web節點 和 Workers

web節點和workers都是普通的服務,他們的不同僅僅是:web節點接收客戶端請求,然后發布需要異步處理的任務;而workers服務接收這些任務,執行並提供反饋。

盡管他們的執行邏輯不同,但一般這兩者的代碼都放在同一個項目倉庫中,這樣做兩個應用程序都可以受益於共享模型和服務之類的東西,還可以防止這些模型和服務不一致。


2.3 執行一個異步任務


# worker node:

from celery import Celery

app = Celery(...)

@app.task
def add(a, b):
    return a + b

# web node:

from tasks import add

r = add.delay(4, 5).get()
print(r)  # 9

上面分別是 異步任務需要運行的代碼將作業放置在要運行的隊列中的代碼。在此示例中,Web節點放置一個作業,並等待直到結果可用。響應的結果到來后,將打印結果。


2.4 Results Backend

在前面的示例中,我們將一起調用delayget函數。實際上,它們是兩個獨立的事物。delay將任務放在隊列中並返回一個promise,該promise可用於監視狀態並在准備就緒時獲取結果。調用get該promise將阻塞執行(block the execution),直到結果可用為止。

這個add任務必須將結果存儲在某個位置,以便隨后觸發它的進程可以對其進行訪問。這意味着我們錯過了一部分架構。除了webbrokerworker組件,還有一個results backend

Results Backend 用於存儲任務結果。其實也可以使用另一個broker來存儲結果。除了受支持的代理選項以外,還有其他技術可以用作Celery中的Results Backend,但是根據使用的內容,會有一些差異。例如,在Postgres中,該get方法將進行輪詢以檢查結果是否准備就緒。對於其他工具,例如Redis,則是通過pub / sub協議完成的。


參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM