python每周一練20191103:使用Flask骇两、Redis和Celery執(zhí)行異步任務

介紹

隨著Web應用程序的發(fā)展和使用的增加低千,用例也變得多樣化贩据。我們現(xiàn)在正在建設和使用網站來執(zhí)行比以往更復雜的任務饱亮。其中一些任務立即轉發(fā)給用戶舍沙,而其他任務則需要進行進一步處理后轉發(fā)拂铡。

Celery可以幫助我們分解復雜的工作感帅,并由不同的機器來完成,以減輕一臺機器上的負載或減少完成時間失球。

在本文中豺撑,我們將探討Celery在Flask應用程序中安排后臺任務的使用黔牵,以減輕資源密集型任務的負擔并確定對最終用戶的響應的優(yōu)先級猾浦。

image.png

Flask

Flask 是一個基于 Python 的輕量級 Web 框架金赦,WSGI 工具箱采用 Werkzeug素邪,模板引擎使用 Jinja2。由于其不依賴于特殊的工具或庫磨确,并且沒有數(shù)據抽象層乏奥、表單驗證或是其他任何已有多種庫可以勝任的功能邓了,從而保持核心簡單骗炉、易于擴展句葵,而被定義為"微"框架乍丈。但是轻专,F(xiàn)lask 可以通過擴展來添加應用功能请垛。并且 Flask 具有自帶開發(fā)用服務器和 debugger递览、集成單元測試和 RESTful 請求調度 (request dispatching)绞铃、支持 secure cookie 的特點儿捧。

Jinja2 是基于 Python 的模版引擎,支持 Unicode颓影,具有集成的沙箱執(zhí)行環(huán)境并支持選擇自動轉義碎浇。Jinja2 擁有強大的自動 HTML 轉移系統(tǒng)璃俗,可以有效的阻止跨站腳本攻擊苟穆;通過模版繼承機制雳旅,對所有模版使用相似布局攒盈;通過在第一次加載時將源碼轉化為 Python 字節(jié)碼從而加快模版執(zhí)行時間沦童。

Redis

Redis 是一個使用 ANSIC 語言編寫、遵守 BSD 協(xié)議驼壶、Key-Value 的存儲系統(tǒng)热凹。擁有支持數(shù)據持久化般妙、支持 string碟渺、map突诬、list苫拍、set、sorted set 等數(shù)據結構和支持數(shù)據備份的特點旺隙。

Redis 會周期性地把更新的數(shù)據寫入磁盤或把修改操作寫入追加的記錄文件绒极,并且在此基礎上實現(xiàn)主從(master-slave)同步,因此數(shù)據可以從主服務器向任意數(shù)量的從服務器上同步蔬捷,從服務器可以是關聯(lián)其他從服務器的主服務器垄提。而且由于 Redis 完全實現(xiàn)了發(fā)布/訂閱機制,使得從數(shù)據庫在任何地方同步樹時,可訂閱一個頻道并接收主服務器完整的消息發(fā)布記錄铡俐。

MQ

MQ 消息隊列是一種應用程序的通信方法摘昌,應用程序可通過讀寫出入對立的消息進行通信。MQ 是一種消費者-生產者 (Producer-Customer)模式的實現(xiàn)高蜂。生產者-消費者模式由生產者稿饰、消費者和緩存區(qū)三個模塊構成惭笑。緩存區(qū)作為一個中介的存在,生產者將數(shù)據放入緩存區(qū),消費者從緩存區(qū)取出數(shù)據。本系統(tǒng)中,F(xiàn)lask 作為生產者,Salesforce 作為消費者悬垃,而 MQ 則是中間的緩存區(qū)廊佩。應用生產者-消費者模式能夠有效的降低兩者之間的耦合茁计,減少互相之間的依賴娜膘;由于緩存區(qū)的存在,消費者無需直接從生產者處獲取數(shù)據颤枪,能夠支持并發(fā)任務春缕、減少阻塞。

RabbitMQ 則是由 erlang 開發(fā)的 AMQP(高級消息隊列協(xié)議)的開源實現(xiàn),作為一個消息隊列管理工具與 Celery 集成后惫确,負責處理服務器之間的通信任務。RabbitMQ 的使用過程如下:

  • 客端連接到消息隊列服務器并打開一個 channel。
  • 客戶端聲明一個 exchange稚配、一個 queue臊岸,并分別設置相關屬性逻住。
  • 客戶端使用 routing key 在 exchange 與 queue 之間綁定好關系。
  • 客戶端投遞消息到 exchange,exchange 根據消息的 key 和設置好的 binding锣吼,將消息投遞到隊列中隧膘。

RabbitMQ 常用的 Exchange Type 有以下三種:

  • Fanout:能夠將所有發(fā)送到該 exchange 的消息投遞到所有與它綁定的隊列中。
  • Direct:把消息投遞到那些 binding key 與 routing key 完全匹配的隊列中。
  • Topic:將消息路由到 binding key 與 routing key 模式匹配的隊列中。

什么是任務隊列丑孩?

任務隊列是一種分配小的工作單元或任務的機制,可以在不干擾大多數(shù)基于Web的應用程序的請求-響應周期的情況下執(zhí)行這些任務古拴。

任務隊列有助于委派工作盔然,否則將在等待響應時降低應用程序的速度鹅搪。它們還可以用于在主機或進程與用戶交互時處理資源密集型任務涂召。

這樣辅肾,與用戶的交互是一致的,及時的衰粹,并且不受工作量的影響。

什么是Celery笆怠?

Celery是一個異步任務隊列铝耻,它基于分布式消息傳遞來在計算機或線程之間分配工作負載。Celery由client蹬刷、broker瓢捉、worker組成频丘。

worker負責執(zhí)行放置在隊列中的任務或工作并轉發(fā)結果。使用Celery泡态,您可以同時擁有本地和遠程worker搂漠,這意味著可以通過Internet將工作委派給功能更強大的其他計算機。這樣兽赁,減輕了主機上的負載状答,并且有更多資源可用于處理用戶請求。

Celery的客戶端負責向worker發(fā)布作業(yè)刀崖,并使用消息代理與他們進行通信惊科。

此類消息代理的示例包括Redis和RabbitMQ。

為什么要使用Celery亮钦?

出于各種原因馆截,我們應該選擇Celery執(zhí)行我們的后臺任務。首先蜂莉,它具有很好的可擴展性蜡娶,允許按需添加更多的worker,以適應增加的負載或流量映穗。 Celery仍在積極開發(fā)中窖张,有簡潔的文檔和活躍的用戶社區(qū)。

另一個優(yōu)點是Celery易于集成到多個Web框架中蚁滋,其中大多數(shù)都具有促進集成的庫宿接。

它還提供了webhooks與其他Web應用程序交互。

Celery還可以使用各種消息代理辕录,這為我們提供了靈活性睦霎。建議使用RabbitMQ,但它也可以支持Redis和Beanstalk走诞。

我們將構建一個Flask應用程序副女,該應用程序允許用戶設置提醒,該提醒將在設定的時間傳遞到他們的電子郵件中蚣旱。

文件結構樹如下:

.
├── Pipfile                    # manage our environment
├── Pipfile.lock
├── README.md
├── __init__.py
├── app.py                     # main Flask application implementation
├── config.py                  # to host the configuration
├── requirements.txt           # store our requirements
└── templates
    └── index.html             # the landing page

1 directory, 8 files

參考資料

實現(xiàn)

image.png

我們將Redis用作消息代理,我們可以在其主頁上找到設置它的說明姻锁。 https://redis.io/topics/quickstart

實現(xiàn)

集成Celery

# Existing imports are maintained
from celery import Celery

# Flask app and flask-mail configuration truncated

# Set up celery client
client = Celery(app.name, broker=app.config['CELERY_BROKER_URL'])
client.conf.update(app.config)

# Add this decorator to our send_mail function
@client.task
def send_mail(data):
    # Function remains the same

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'GET':
        return render_template('index.html')

    elif request.method == 'POST':
        data = {}
        data['email'] = request.form['email']
        data['first_name'] = request.form['first_name']
        data['last_name'] = request.form['last_name']
        data['message'] = request.form['message']
        duration = int(request.form['duration'])
        duration_unit = request.form['duration_unit']

        if duration_unit == 'minutes':
            duration *= 60
        elif duration_unit == 'hours':
            duration *= 3600
        elif duration_unit == 'days':
            duration *= 86400

        send_mail.apply_async(args=[data], countdown=duration)
        flash(f"Email will be sent to {data['email']} in {request.form['duration']} {duration_unit}")

        return redirect(url_for('index'))

執(zhí)行

$ python app.py
$ celery worker -A app.client --loglevel=info       
image.png
image.png

在ubuntu 18調試通過枕赵,如果大家需要代碼或者技術支持,請加圖片上的群位隶。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市开皿,隨后出現(xiàn)的幾起案子涧黄,更是在濱河造成了極大的恐慌篮昧,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件笋妥,死亡現(xiàn)場離奇詭異懊昨,居然都是意外死亡,警方通過查閱死者的電腦和手機春宣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門酵颁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人月帝,你說我怎么就攤上這事躏惋。” “怎么了嚷辅?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵簿姨,是天一觀的道長。 經常有香客問我簸搞,道長扁位,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任趁俊,我火速辦了婚禮域仇,結果婚禮上,老公的妹妹穿的比我還像新娘寺擂。我一直安慰自己暇务,他們只是感情好,可當我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布沽讹。 她就那樣靜靜地躺著般卑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪爽雄。 梳的紋絲不亂的頭發(fā)上蝠检,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天,我揣著相機與錄音挚瘟,去河邊找鬼叹谁。 笑死,一個胖子當著我的面吹牛乘盖,可吹牛的內容都是我干的焰檩。 我是一名探鬼主播,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼订框,長吁一口氣:“原來是場噩夢啊……” “哼析苫!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤衩侥,失蹤者是張志新(化名)和其女友劉穎国旷,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體茫死,經...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡跪但,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了峦萎。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片屡久。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖爱榔,靈堂內的尸體忽然破棺而出被环,到底是詐尸還是另有隱情,我是刑警寧澤搓蚪,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布蛤售,位于F島的核電站,受9級特大地震影響妒潭,放射性物質發(fā)生泄漏悴能。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一雳灾、第九天 我趴在偏房一處隱蔽的房頂上張望漠酿。 院中可真熱鬧,春花似錦谎亩、人聲如沸炒嘲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽夫凸。三九已至,卻和暖如春阱持,著一層夾襖步出監(jiān)牢的瞬間夭拌,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工衷咽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留鸽扁,地道東北人。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓镶骗,卻偏偏與公主長得像桶现,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子鼎姊,可洞房花燭夜當晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內容