Celery結合bottle的實踐筆記

Celery.png

問:Celery 是什么?

答:Celery 是一個由 Python 編寫的簡單、靈活、可靠的用來處理大量信息的分布式系統,它同時提供操作和維護分布式系統所需的工具。
Celery 專注于實時任務處理,支持任務調度。(來源于網絡)

問:適用場景在哪里?

答:如圖示(來自:http://blog.csdn.net/xsj_blog/article/details/70181984

image.png

問:生產者和消費者模式定義是什么?

答:
(1)生產者->負責產生數據;
(2)消費者->負責數據處理;
(3)緩沖區->解耦生產者和消費者,減少依賴,主要是通過消息隊列來進行兩點之間的通訊處理。

圖示:


image.png

問:什么是任務隊列?

答:任務隊列是一種在線程或機器間分發任務的機制。

問:什么是消息隊列?

答:消息隊列的輸入是工作的一個單元,稱為任務,獨立的職程(Worker)進程持續監視隊列中是否有需要處理的新任務。

問:職程有什么作用?

答:Celery 用消息通信,通常使用中間人(Broker)在客戶端和職程間斡旋。這個過程從客戶端向隊列添加消息開始,之后中間人把消息派送給職程,職程對消息進行處理。如下圖所示:


image.png

問:Celery的架構三部分是哪幾個部分?

答:Celery的架構由三部分組成,消息中間件(message broker),任務執行單元(worker)和任務執行結果存儲(task result store)組成。

(1)消息中間件
PS: Celery本身不提供消息服務,但是可以方便的和第三方提供的消息中間件集成,包括,RabbitMQ,Redis,MongoDB等。

(2)任務執行單元
PS: Worker是Celery提供的任務執行的單元,worker并發的運行在分布式的系統節點中。

(3)任務結果存儲
PS: Task result store用來存儲Worker執行的任務的結果,Celery支持以不同方式存儲任務的結果,包括Redis,MongoDB,Django ORM,AMQP等。

(任務調度)Celery Beat:任務調度
Celery Beat:任務調度器,Beat 進程會讀取配置文件的內容,周期性地將配置中到期需要執行的任務發送給任務隊列。

來自網絡

消息分發與任務調度的實現機制(來自:http://blog.csdn.net/xsj_blog/article/details/70181984

image.png

1:—>producer發出調用請求(message包含所調用任務的相關信息)
2:—>celery服務啟動時,會產生一個或多個交換機(exchanges),對應的交換機 接收請求message
3:—>交換機根據message內容,將message分發到一個或多個符合條件的隊列(queue)
4:—>每個隊列上都有一個或多個worker在監聽,在監聽到符合條件的message到達后,worker負責進行任務處理,任務處理完被確認后,隊列中的message將被刪除。

注釋:Exchange和Queue都是Rabbitmq中的概念

Exchange:交換機,決定了消息路由規則;

Queue:消息隊列;

Channel:進行消息讀寫的通道;

Bind:綁定了Queue和Exchange,意即為符合什么樣路由規則的消息,將會放置入哪一個[消息隊列];

調圖流程圖示:(來自https://www.cnblogs.com/forward-wang/p/5970806.html

image.png

實踐步驟:

相關依賴:
image.png
第1步:首先搭建bottle客戶端端,進行任務委派:

main.py

#!/usr/bin/evn python
# coding=utf-8
"""
Author = zyx
@Create_Time: 2018/1/30 15:58
@version: v1.0.0
@File: main.py
@文件功能描述:
"""

from bottle import route, run

@route('/')
def index():
    return '訪問了首頁!'

run(host='127.0.0.1', port=8080, debug=True, reloader=True)

啟動wen服務應用訪問:


image.png
第2步:編寫對應Celery任務模塊celery_test
image.png
第3步:編寫對應Celery任務模塊啟動配置文件

setting.py配置(使用配置的方式來啟動相關worker來處理 任務):

# coding:utf-8
from datetime import timedelta
from kombu import Exchange, Queue

# 配置消息中間件Broker
BROKER_URL = 'redis://127.0.0.1:6379/0'  

# 配置結果存貯Backend
CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/1'

# 指定時區,默認是 UTC
CELERY_TIMEZONE = 'Asia/Shanghai'
CELERY_ENABLE_UTC = True

# # 不需要返回任務狀態,即設置以下參數為True
# 如果不需要某個任務的結果,應該確保Celery不去獲取這些結果。這是通過裝飾器@task(ignore_result=True)來做的。如果所有的任務結果都忽略了,就不必定義結果后臺。這可以讓性能大幅提高。
CELERY_IGNORE_RESULT = True

# 任務序列化和反序列化使用msgpack方案
CELERY_TASK_SERIALIZER = 'json'  

# 讀取任務結果一般性能要求不高,所以使用了可讀性更好的JSON
CELERY_RESULT_SERIALIZER = 'json'  

# CELERY_TASK_RESULT_EXPIRES = 60 * 60 * 24 # 任務過期時間,不建議直接寫86400,應該讓這樣的magic數字表述更明顯

# celery worker的并發數 也是命令行-c指定的數目,事實上實踐發現并不是worker也多越好,保證任務不堆積,加上一定新增任務的預留就可以
CELERYD_CONCURRENCY = 10 

# celery worker 每次去rabbitmq取任務的數量,我這里預取了4個慢慢執行,因為任務有長有短沒有預取太多
CELERYD_PREFETCH_MULTIPLIER = 4 

CELERY_ACCEPT_CONTENT = ['json']  # 指定接受的內容類型

# 默認的隊列,如果一個消息不符合其他的隊列就會放在默認隊列里面
CELERY_DEFAULT_QUEUE = "default" 

CELERY_QUEUES = (
    Queue('default', Exchange('default'), routing_key='default'),
    Queue('for_add', Exchange('for_task_add'), routing_key='for_task_add'),
    Queue('for_send_email', Exchange('for_task_email'), routing_key='for_task_email'),
)

CELERY_ROUTES = {
    'celery_test.tasks.add': {'queue': 'for_add', 'routing_key': 'for_task_add'},
    'celery_test.tasks.send_mail': {'queue': 'for_send_email', 'routing_key': 'for_task_email'},
}

CELERYBEAT_SCHEDULE = {
    'send_mail': {
        'task': 'celery_test.tasks.send_mail',
        'schedule': timedelta(seconds=30),
    },
    'add': {
        'task': 'celery_test.tasks.add',
        'schedule': timedelta(seconds=10),
        'args': (16, 16)

    }
}

PS:以下代碼就解釋:

CELERY_QUEUES = (
    Queue('default', Exchange('default'), routing_key='default'),# 這是上面指定的默認隊列 
    Queue('for_add', Exchange('for_task_add'), routing_key='for_task_add'), # 這是一個for_add隊列 凡是for_task_add開頭的routing key都會被放到這個隊列
    Queue('for_send_email', Exchange('for_task_email'), routing_key='for_task_email'),
# 這是一個or_send_email'隊列 凡是for_task_email開頭的routing key都會被放到這個隊列
)
第4步:編寫對應Celery實例

server.py

from  celery import Celery
app=Celery('celery_test',include=['celery_test.tasks'])
app.config_from_object('celery_test.setting')

if __name__=='__main__':
    app.start()
第5步:編寫對應任務

tasks.py

# coding:utf-8
from celery_test.server import app

@app.task(bind=True)
def add(self,x, y):
    return x + y


@app.task(bind=True)
def send_mail(self,x, y):
    return x - y
第6步:修改main.py進行任務調用

main.py

from bottle import route, run, redirect

from celery_test import tasks


# @route('/add')
# def index():
#     tasks.add.daley(888, 45)
#     return '訪問了add!'


@route('/send_mail')
def index():
    task = tasks.send_mail.delay(888, 45)
    print('訪問了send_mail!')
    return redirect('/tasks_status/' + task.id)  # 重定向到首頁(可以 )


@route('/tasks_status/<task_id>')
def index(task_id):
    # 獲取異步任務結果
    task = tasks.send_mail.AsyncResult(task_id)
    # 等待處理
    if task.state == 'PENDING':
        response = {'state': task.state, 'current': 0, 'total': 1}
        print('PENDING:', response)
    elif task.state != 'FAILURE':
        response = {'state': task.state, 'current': task.info.get('current', 0), 'total': task.info.get('total', 1)}
        # 處理完成
        if 'result' in task.info:
            response['result'] = task.info['result']
        print('處理完成:', response)
    else:
        # 后臺任務出錯
        response = {'state': task.state, 'current': 1, 'total': 1}
        print('后臺任務出錯:', response)


run(host='127.0.0.1', port=8080, debug=True, reloader=True)

第7步:啟動指定的隊列
 celery -A celery_test.server worker -l info -Q for_send_email
image.png

啟動成功如圖示:


image.png
第8步:啟動web服務調用對應的URL請求異步處理異步任務
調用:http://127.0.0.1:8080/send_mail
image.png

即時查看任務處理情況:

http://127.0.0.1:8080/tasks_status/0079d834-d918-4ad7-88dd-f23c5eeb09dc

查看對應的celery的運行 情況:

image.png

問:監控Celery任務執行情況?

答:Flower是基于web的監控和管理Celery的工具.
相關文檔:
http://flower-docs-cn.readthedocs.io/zh/latest/
安裝pip install flower
啟動flower(flower默認的端口是5555.)
celery flower --port=5555 --broker=redis://localhost:6379/0
celery flower --broker=amqp://guest:guest@192.168.xx.xxx:5672//
啟動任務查看
celery flower --port=5555 --broker=redis://localhost:6379/0

image.png

訪問:127.0.0.1:5555


image.png

進行任務執行:http://127.0.0.1:8080/send_mail
查看任務執行結果

image.png

PS其他命令

============================================================================
前臺啟動

啟動指定的隊列
 celery -A celery_test.server worker -l info -Q for_send_email

 celery -A celery_test.server worker -l info -Q for_add

啟動定時相關的任務隊列
 celery -A celery_test.server beat

 celery -A celery_test.server worker -l info -Q for_send_email

 celery -A celery_test.server worker -l info -Q for_add




============================================================================
后臺啟動
celery multi start w1 -A proj -l info
celery  multi restart w1 -A proj -l info

# 異步關閉 立即返回
celery multi stop w1 -A proj -l info
# 等待關閉操作完成
celery multi stopwait w1 -A proj -l info

調用任務:
add.apply_async((2, 2), queue='lopri', countdown=10)
# 指定要發送到哪個隊列 運行時間延遲countdown
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,835評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,676評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,730評論 0 380
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,118評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,873評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,266評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,330評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,482評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,036評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,846評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,025評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,575評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,279評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,684評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,953評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,751評論 3 394
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,016評論 2 375

推薦閱讀更多精彩內容