Celery是由Python開發、簡單、靈活、可靠的分佈式
任務隊列,其本質是生產者消費者模型,生產者發送任務到消息隊列,消費者負責處理任務。Celery側重於實時操作,但對調度支持也很好,其每天可以處理數以百萬計的任務。特點:
簡單:熟悉celery的工作流程後,配置使用簡單
高可用:當任務執行失敗或執行過程中發生連接中斷,celery會自動嘗試重新執行任務
快速:一個單進程的celery每分鐘可處理上百萬個任務
靈活:幾乎celery的各個組件都可以被擴展及自定製
- Celery的應用場景:
- 當前執行任務,執行時間非常長,不需要實時返回結果
- 定時任務,每年生日、每個月帳單
爲什麼使用celery而非crontab => 10臺機器上設置一些不同的定時任務,使用celery管理更方便
原理圖
Celery的組成:
- 消息代理:Broker => 接收任務生產者發送過來的任務消息,存進隊列,由消費者讀取運行 => 消息隊列
- 任務調試器:Beat => 讀取配置文件,週期性地將配置中到期需要執行的任務發送到Broker中 => 生產者
- 任務執行: Worker => 執行任務的消息者,會讀取Broker中的任務,並進行執行 => 消費者
- 生產者:celery提供的API => 在代碼中發起任務 => 生產
- 結果存儲: Result Backend => 任務處理完後,保存狀態信息和結果,以供查詢
生產者消費者模型
部署
消息代理和結果存儲 => redis
#linux安裝運行redis
# 安裝
yum install redis
# 配置:修改監聽端口 =》
vim /etc/redis.conf
bind 0.0.0.0
# 啓動:
redis-server /etc/redis.conf &
# 重啓:
kilall redis-server
# 如果沒有killall命令,請這樣安裝
yum install psmisc -y
redis-server /etc/redis.conf &
=>port: 6379
Flask代碼處理=> flask+celery
1. 安裝依賴
pip install redis
pip install celery
2. 創建celery實例: celery_app/__init__.py
from celery import Celery
celery = Celery("celery_app")
# 從配置文件中讀取並配置celery
celery.config_from_object('config.celery_config')
3. 創建配置文件 config/celery_config.py
# 配置消息中間件的地址
BROKER_URL = "redis://192.168.189.200:6379/1"
# 結果存放地址
CELERY_RESULT_BACKEND = "redis://192.168.189.200:6379/2"
# 啓動Celery時,導入任務
CELERY_IMPORTS = (
'celery_app.tasks',
)
# 配置定時任務
4. 創建任務:celery_app/tasks.py
from . import celery
import time
import random
@celery.task
def celery_task(sth1):
"""輸出start, end, time.sleep"""
print("celery_app.task start")
delay_time = random.randint(5, 10)
time.sleep(delay_time)
print("celery_app.task end")
return sth1
# 調用任務
@view01_bp.route('/index/')
def index():
# 調用一個異步任務
from celery_app.tasks import celery_task
# 立即發送任務,立刻執行任務
celery_task.delay('hello world!')
# celery_task.apply_async() => 指定運行倒計時,發送到哪個隊列....
return "This is index"
"""
目標:
當觸發該任務時,web頁面能實時返回return的結果,而不是在等待
在worker看到任務被接收和處理
"""
5. 將celery配置啓動入口:manage.py
from celery_app import celery
以便通過 => manage.celery 啓動celery項目
6. 啓動:
1. flask-web => python server.py
2. worker => 1個或n個 => celery worker -A manage.celery --loglevel=info -n nodename
nodename指定的workd的名字(自己取)
3. beat => 如果有定時任務
celery4 windows不支持結果處理
pip install eventlet
然後啓動worker的時候加一個參數,如下:
celery -A <mymodule> worker -l info -P eventlet
也可從官方直接下載安裝包:https://pypi.python.org/pypi/celery/
tar xvfz celery-0.0.0.tar.gz
cd celery-0.0.0
python setup.py build
python setup.py install
如何把代碼同步到linux上來
1.在pycharm:Tool->Deployment-> + ->
設置一個名字, SFTP
配置Connection
配置Mappings
2. 創建虛擬環境
cd /opt/flaskproj/
python3 -m venv linuxvenv
source linuxvenv/bin/activate
pip install -r requirements.txt
3. 運行
cd /opt/flaskproj/ && source linuxvenv/bin/activate && cd operbench
# 運行flask
python server.py
# 運行celery worker
celery worker -A manage.celery --loglevel=info -n node1
### web方式查看celery的工作情況
cd /opt/flaskproj/ && source linuxvenv/bin/activate && cd operbench
pip install flower
flower -A manage.celery --loglevel=info --address=192.168.189.200 --port=5555
實例
- 編寫task.py
# tasks.py
import time
from celery import Celery
celery = Celery('tasks', broker='redis://localhost:6379/0')
@celery.task
def sendmail(mail):
print('sending mail to %s...' % mail['to'])
time.sleep(2.0)
print('mail sent.')
- 啓動Celery處理任務
$ celery -A tasks worker --loglevel=info
上面的命令行實際上啓動的是Worker,如果要放到後臺運行,可以扔給supervisor。
如何發送任務?
>>> from tasks import sendmail
>>> sendmail.delay(dict(to='[email protected]'))
<AsyncResult: 1a0a9262-7858-4192-9981-b7bf0ea7483b>