輕松完成異步任務(wù),一文搞懂Python Celery
雖然現(xiàn)代的網(wǎng)絡(luò)應(yīng)用比以往任何時候都更快速、更便捷,但仍有許多情況下,需要把繁重的任務(wù)轉(zhuǎn)移到系統(tǒng)的其他部分執(zhí)行,而不是在主線程上進行工作。
這些情況中的示例如下:
- 周期性任務(wù) —— 計劃在特定時間間隔內(nèi)運行的工作。例如,每日、每月的報告生成。
- 第三方工具 —— 應(yīng)用程序應(yīng)該快速向用戶返回響應(yīng),而不是等待其他任務(wù)先完成。例如,發(fā)送電子郵件、通知,將更新進度傳遞給內(nèi)部工具。
- 長時間運行的工作 —— 執(zhí)行復(fù)雜或資源昂貴的工作,并且用戶需要等待工作完成。例如。DAG工作流、基于Map-Reduce的任務(wù)、長時間運行的Spark作業(yè)等。
那么,如何處理這些情況呢?這時,Celery就派上用場了。
什么是Celery?
Celery是一個開源的任務(wù)隊列實現(xiàn),通常與基于Python的網(wǎng)絡(luò)框架(如Flask和Django)相結(jié)合,在典型的請求-響應(yīng)周期之外異步執(zhí)行任務(wù)。
因此,Celery本質(zhì)上是一個基于分布式消息傳遞的任務(wù)隊列。執(zhí)行單元或任務(wù)在一個或多個worker上使用多處理、gevent或Eventlet同時執(zhí)行。這些任務(wù)可以同步執(zhí)行(即等到準(zhǔn)備就緒)或異步執(zhí)行(即在后臺)。
Celery是如何工作的?
Celery是一個分布式任務(wù)隊列,基于生產(chǎn)者-消費者模式。
任務(wù)隊列是用于跨線程和機器分配工作的機制,本質(zhì)上是生產(chǎn)者(Web應(yīng)用程序)和消費者(Celery工作者)之間的消息中介。
Celery通過消息進行交互,代理(broker)在客戶(生產(chǎn)者)和工作者(消費者)之間充當(dāng)中間人。為了啟動任務(wù),客戶端將消息推送到隊列中,然后代理將該消息傳遞給工作者。
Celery系統(tǒng)可以由多個worker和broker組成,這為高可用性和橫向擴展提供了可能。
簡而言之,Celery客戶端是生產(chǎn)者,它通過消息代理向隊列中添加新的任務(wù)。然后,Celery工作者同樣通過消息代理從隊列中獲取新的任務(wù)。一旦處理完畢,結(jié)果就會存儲在結(jié)果后端。
工作實例
下面的例子將使用RedisMQ作為消息代理。
設(shè)置Redis
在linux/macOS系統(tǒng)上,通過以下命令在本地運行Redis服務(wù)器:
設(shè)置好Redis后,通過執(zhí)行以下命令運行Redis服務(wù)器:
該服務(wù)器在默認的6379端口運行。
設(shè)置應(yīng)用程序
首先,在本地設(shè)置Python項目。
Celery可以通過標(biāo)準(zhǔn)工具如pip或easy_install來安裝。通過以下命令安裝Celery和Redis:
現(xiàn)在需要一個Celery實例來運行應(yīng)用程序,Celery實現(xiàn)任何任務(wù)都是以實例開始,比如創(chuàng)建和管理任務(wù)等。
在項目中創(chuàng)建一個文件tasks.py:
這里定義了一個簡單的任務(wù)add(),返回兩個數(shù)字的總和。
運行Celery Worker
在終端上,切換到項目位置并用以下命令運行Celery worker:
關(guān)于Celery worker命令行的詳細信息,可以使用help:
調(diào)用任務(wù)
在Celery中,使用delay()方法來調(diào)用任務(wù)。
打開項目的另一個終端窗口并運行以下命令:
這將打開Python命令行。
這將返回一個AsyncResult實例,可以用來檢查任務(wù)狀態(tài),獲得其返回值,等待任務(wù)完成,也可以在失敗時獲得異常和回溯。
運行add.delay()命令后,任務(wù)會被推送到隊列中,然后被worker獲取。這可以在Celery worker終端上進行驗證,可以清楚地看到任務(wù)被接收,之后任務(wù)成功完成。