本文詳細(xì)介紹了典型的生產(chǎn)環(huán)境的 CRUD 應(yīng)用程序從 Flask 到 Quart 的轉(zhuǎn)換,并展示相關(guān)的性能改進(jìn)優(yōu)勢(shì)。
將這個(gè) Flask-pyscopg2 應(yīng)用程序升級(jí)到 Quart-asyncpg 應(yīng)用程序可以提高 3 倍的性能,而且不需要對(duì)代碼進(jìn)行重大的重寫(xiě)或調(diào)整。
如上所示,在針對(duì)單個(gè)資源詳情的請(qǐng)求下,F(xiàn)lask每秒請(qǐng)求為330個(gè),而quart能達(dá)到1160個(gè)。以此類推,Quart 相比于 Flask 平均性能提高3倍。
這個(gè)比較,我使用了一個(gè)簡(jiǎn)單的只提供一個(gè) RESTful 接口的應(yīng)用程序,這是微服務(wù)架構(gòu)中的常見(jiàn)用例。
該應(yīng)用程序有三個(gè)路由。這些路由分別是:
- 單個(gè)電影詳情:GET /films/pk/
- 所有電影:GET /films/
- 添加新評(píng)論:POST /reviews/
源代碼可以在以下網(wǎng)址找到:
https://github.com/pgjones/faster_than_flask_article
有兩個(gè) commit ,分別是一個(gè) Flask 版本和一個(gè)Quart 版本。
1. 從 Flask 到 Quart
從 Flask 改用 Quart 很容易,只需要一點(diǎn)點(diǎn)改變,特別是 from flask 改為 from quart,函數(shù)變成異步函數(shù)。
def add_review():
data = request.get_json()
...
變成
async def add_review():
data = await request.get_json()
...
**
2.數(shù)據(jù)庫(kù)連接,從 psycopg2 到 asyncpg**
從 psycopg2 改用 asyncpg 比較麻煩,因?yàn)閮烧哂胁煌挠梅ā?/p>
為了簡(jiǎn)化區(qū)別,我們?cè)?Flask 應(yīng)用程序中使用了 PoolWrapper,使得 psycopg2 可以使用與 asyncpg 相同的 API 進(jìn)行上下文管理,即:
with pool.acquire() as connection:
這將允許通過(guò)with更改為async with來(lái)使用asyncpg。
當(dāng)然,除了連接之外,Asyncpg和psycopg2還在游標(biāo)使用、事務(wù)、執(zhí)行參數(shù)和查詢格式方面存在差異。這些差異是你在遷移過(guò)程中需要注意的。
3.部署
Flask 應(yīng)用程序往往不能直接在生產(chǎn)環(huán)境中直接暴露給用戶,這是因?yàn)镕lask 本身一次只能處理一個(gè)請(qǐng)求。因此,常常用WSGI服務(wù)器與某種異步 worker 結(jié)合使用,例如 帶 eventlet 的Gunicorn。
Quart 也可以用 Gunicorn 部署,它允許使用相同的命令來(lái)運(yùn)行 Flask 和 Quart 應(yīng)用程序:
$ gunicorn --config gunicorn.py 'run:create_app()'
針對(duì) Flask 和 Quart 的性能測(cè)試是基于 Gunicorn 進(jìn)行的。
4.添加測(cè)試數(shù)據(jù)
除了添加一個(gè)簡(jiǎn)單的 review 表之外,Postgresql 示例數(shù)據(jù)庫(kù)還要為應(yīng)用程序提供一些用于 CRUD的數(shù)據(jù)。
CREATE TABLE review (
film_id INTEGER REFERENCES film(film_id),
rating INTEGER
);
5.性能測(cè)試
為了測(cè)量應(yīng)用程序的性能,我們使用了wrk。它被配置為使用20個(gè)連接,以匹配數(shù)據(jù)庫(kù)連接池的大小(確保最高的吞吐量,20是我使用過(guò)的典型值)。命令如下:
測(cè)試 GET 請(qǐng)求的命令是
$ wrk --connections 20 --duration 5m http://localhost:5000/${PATH}/
測(cè)試 POST 請(qǐng)求的命令是
$ wrk --connections 20 --duration 5m --script post.lua http://localhost:5000/${PATH}/
測(cè)試使用的 post.lua 文件如下:
wrk.method = "POST"
wrk.body = '{"film_id": 995, "rating": 4}'
wrk.headers["Content-Type"] = "application/json"
6.系統(tǒng)信息與結(jié)果
系統(tǒng)信息:
Postgres (9.5.10),wrk (4.0.0),Python (3.6.3),asyncpg (0.13.0),F(xiàn)lask (0.12.2),Gunicorn (19.7.1),psycopg2 (2.7.3.2), Quart (0.3.1)
全部運(yùn)行在一臺(tái) AWS c4.large 機(jī)器上。
結(jié)果
請(qǐng)注意,Quart 服務(wù)器的平均等待時(shí)間減少了 2 至 3.5 倍,每秒的請(qǐng)求數(shù)量增加了 2 至 3.5 倍。
7.結(jié)論
Flask 應(yīng)用程序升級(jí)到 Quart 應(yīng)用程序是相當(dāng)簡(jiǎn)單的,因?yàn)榇蟛糠?API 是共享的,所以主要工作就是在正確的位置寫(xiě)async
和await
。然而,如果使用 SQLAlchemy(或其他 ORM),則從psycopg2 到 asyncpg 的改變會(huì)比較復(fù)雜,并且可能會(huì)很麻煩。
這個(gè) demo 應(yīng)用程序的性能顯著提高,這個(gè)改進(jìn)主要是由于 Quart 使用了 asyncpg 和 uvloop,據(jù)估計(jì),僅 Quart 就能提供 1.5 倍的提升。
總之,從 Flask-psycopg2 應(yīng)用程序升級(jí)到 Quart-asyncpg 應(yīng)用程序的比較簡(jiǎn)單,并擁有非常合理的性能改進(jìn)。這可能會(huì)擴(kuò)展到其他基于 asyncio 的庫(kù),意味著將 Flask 應(yīng)用程序轉(zhuǎn)換到 asyncio 生態(tài)系統(tǒng),Quart 只需要很小的工作量。
-
接口
+關(guān)注
關(guān)注
33文章
8694瀏覽量
151928 -
應(yīng)用程序
+關(guān)注
關(guān)注
38文章
3292瀏覽量
57918 -
flask
+關(guān)注
關(guān)注
0文章
16瀏覽量
3634
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論