引言:
當需要用python創建和完成定時任務時,第一個會想到的就是使用crontab庫,
但是crontab不支持Windows系統,於是我們可以使用一個支持Windows且功能強大的庫:Celery。
Celery-分佈式任務隊列:
Celery是一個簡單,靈活,可靠的分佈式系統,用於處理大量消息,同時爲操作提供維護此類系統所需的工具。
它是一個任務隊列,專注於實時處理,同時還支持任務調度。
Celery是開源的,並根據BSD許可授權。
Celery由Python語言實現。
Celery安裝:
celery的版本非常令人頭疼,它的版本無法做到完全上下兼容,且有些版本會與一些庫衝突,所以對於celery版本的選擇非常重要:
1、celery 4.0.0~4.2.0(latest) 目前最新的celery版本是官方的4.2.0 鏈接:http://docs.celeryproject.org/en/latest/
(1) celery 4.0.0及以上版本目前不兼容python3.7 由於在python3.7中 async變成了關鍵字 在運行celery worker的時候會報錯,
from . import async,base 此處出錯。
(2) django-celery是一個便於在django工程中管理celery的庫,但是django-celery不支持celery 4.0.0以上版本,如若要在django工程中
使用celery,請降低版本,比如celery 3.1.26
2、celery 3~4的版本之間 相對穩定 本人用的就是celery 3.1.26版本 推薦 pip install celery==3.1.26
Celery介紹:
上圖爲celery工作簡要流程,原諒我盜的圖...原作者po上:https://www.qikqiak.com/
1、application(task producer)"任務的生產者",我們通過代碼層面,產生任務然後發送給broker(task queue)
2、celery beat(task scheduler)"任務調度器",常見爲生成定時任務
3、broker(task queue)"任務隊列",我們需要將任務送往任務隊列去,官網強烈推薦的broker有:redis和rabbitmq
4、worker(taks consumer)"任務消費者",在任務送往broker後,worker從中進行操作,完成任務後生成result
5、result 完成任務後產生的結果
Broker的選擇:
broker我們可選的有redis和rabbitmq,官網推薦的兩種,我們這裏選redis,相對於rabbitmq更加輕量級,安裝方便。
所以我們需要安裝redis,redis很容易安裝,這裏就不細講了,po上github鏈接:https://github.com/MicrosoftArchive/redis/releases
與此同時 celery還需要python的redis依賴庫這裏注意版本 pip install redis==2.10 最好下2.10版本,這裏是爲了後續和django聯用
若下最新版本,可能會報以下錯:
任務的編寫:
主要的代碼層面來了,我們通過流程圖知道,我們需要生產任務,目錄結構如下圖:
1、其中__init__.py是通過啓動項目時,選擇的配置文件:
1 from celery import Celery
2
3 app = Celery('demo')
4 app.config_from_object('celery_app.celeryconfig')
2、celeryconfig.py裏面主要是celery的配置:
from datetime import timedelta
from celery.schedules import crontab
# 配置broker爲redis
BROKER_URL = 'redis://localhost:6379/1'
# 配置結果存儲至redis
CELERY_RESULT_BACKEND = 'redis://localhost:6379/2'
# 時區設置
CELERY_TIMEZONE='Asia/Shanghai'
# 導入任務
CELERY_IMPORTS = (
'celery_app.task1',
'celery_app.task2',
)
# 配置定時任務的調度器
CELERYBEAT_SCHEDULE={
# 任務名字
'task1':{
# 任務啓動的函數
'task':'celery_app.task1.add',
# 定時時間設置,每10秒一次
'schedule':timedelta(seconds=10),
# 傳遞的參數
'args':(2,8)
},
'task2':{
'task':'celery_app.task2.mul',
# 定時時間設置,16:45
'schedule':crontab(hour=16,minute=45),
'args':(4,5)
}
}
3、task1的任務:
import time
from celery_app import app
@app.task
def add(x, y):
# 阻塞測試
time.sleep(3)
return x + y
4、 task2的任務:
import time
from celery_app import app
@app.task
def mul(x, y):
time.sleep(3)
return x * y
運行任務:
1、打開redis服務器:
$ .\redis-server.exe .\redis.windows.conf
2、在celery_app文件的上一級 shift+右鍵 打開命令行窗口,win10打開powershell:
celery worker -A celery_app --pool=solo -l INFO
此命令打開worer 任務目標爲celery_app windows下需要加--pool=solo 日誌級別爲INFO
3、然後打開celery beat 啓動定時任務,另開一個命令行窗口:
celery beat -A celery_app -l INFO
4、結果如下:
可以看見celery beat一直在隔10秒發送任務
再來看worker:
第一次是處理了4秒 其餘是3秒,可以看出windows處理celery還是不太穩定。
結語:celery是一個強大的庫,能讓我們處理異步任務,不過最好還是於Linux上運行
常見錯誤:
在linux系統中使用root用戶常見錯誤:
Running a worker with superuser privileges when the
worker accepts messages serialized with pickle is a very bad idea!
If you really want to continue then you have to set the C_FORCE_ROOT
environment variable (but please think about this before you do).
from celery import Celery, platforms
platforms.C_FORCE_ROOT= True #加上這一行