web網站包含前端和后端, 異步處理可以用在前端, 也可以用在后端. 前端 jquery 進行 ajax 請求時, 可設置 async 屬性為 true, 並為 success 設置一個 callback 函數, 在服務端返回之前, 瀏覽器可以執行 ajax 之后的代碼, 當服務器端返回后, jquery會執行 success 回調.
后端的視圖函數也可以引入這種異步處理機制, 發揚廣大的是nodejs了, nodejs web服務單線程異步處理方式, 一般來講, nodejs 框架的並發性要比Django/Flask 要好, 主要原因是 Django/Flask 都是基於 WSGI 同步處理模式的, WSGI 采用多線程方式來支持並發, 和協程相比, 多線程資源消耗要大的多, 所以並發性要差一些. 當然如果我們的 Django/Flask web應用配合 Gunicorn(高性能的WSGI服務器) 和 nginx(高性能Web服務器) 部署, 並發也會有一定的改善.
為了改善 flask 的並發, flask 社區主要嘗試了兩個方向:
1. 嘗試在 flask 中引入 async 機制, 比如 flask_aiohttp 項目, 在python 中 async 和 sync 編程分別屬於兩個世界, 所以整合起來難度和穩定性都成問題, 目前該方向已經被放棄.
2. 將耗時的視圖交由 celery 作異步處理, 其他視圖仍采用同步方式. celery 可以采用 redis 做 back end. 這個機制優缺點都很明顯, 優點是, 在沒有增加編碼復雜度的情形下, 可以明顯改善並發處理能力, 缺點是, 引入了兩個 celery 和 redis 兩個集群, 增加了部署和運維復雜度.
目前方向2應該是正解, 交由celery的異步視圖函數, 和使用 async-await 的異步還有有一些差異的, 最主要的是使用異步 celery task的視圖函數, 在觸發task后返回到視圖函數, 而調用async任務后, 視圖函數並不會馬上得到代碼執行權, 直到async任務完成后, 才能得到代碼執行權.
所以, 使用 celery 的異步api, 通常僅僅是觸發后台任務, 通常還有一個配套的api, 用來查詢后台任務的status.
詳見:
https://blog.miguelgrinberg.com/post/using-celery-with-flask
http://allynh.com/blog/flask-asynchronous-background-tasks-with-celery-and-redis/
windows 下的開發:
celery 采用 3.1.25 版本, 之后的 celery 不支持 window平台.
Redis-x64-3.0.504.msi 下載地址 https://github.com/MicrosoftArchive/redis/releases