在python程式設計中,通過協程實現的非同步程式設計號稱能夠提高IO密集型任務的並行量。本系列比較web伺服器同步框架和非同步框架的效能差異,包括無IO介面和常見IO操作,如檔案、mysql、redis等。使用壓測工具locust測試相同條件下兩種程式設計模式能夠處理請求的速度。
主題:單純比較非同步框架和同步框架的效能,無任何IO
python版本:python 3.8
壓測工具:locust
web框架:同步:flask 非同步:aiohttp、starlette
請求並行量: 模擬10個使用者
伺服器設定: Intel(R) i7-12700F
使用者端設定:Intel(R) i7-8700 3.20GHz
flask是python中輕量級web框架,特點是靈活、輕量級、擴充套件性高。flask同時是一個同步框架,flask誕生的時候python的非同步程式設計體系還不成熟,當然截止到目前flask肯定是支援非同步框架的。但是讓其作為同步框架的代表,參加pk。
from flask import Flask, request
app = Flask(__name__)
@app.route('/index')
def index():
return "hello world"
if __name__ == '__main__':
app.run(port=5000, host="0.0.0.0")
locust是一個python語言開發的壓力測試工具,有圖形化介面,基於協程並行,能夠支援在單臺機器中支援數以千計的模擬使用者,也支援分散式壓測。
使用locust壓測,並行模擬10個使用者,10個使用者儘可能快的傳送請求,並行量RPS取決於請求返回的速度,也就是伺服器端的處理速度。
from locust import HttpUser, task
class UserBehavior(HttpUser):
# 請求host的/index介面
@task(1)
def stress_index(self):
self.client.get("/index")
locust -f locust_stress.py
存取 127.0.0.1:8098,啟動服務,按照10個模擬使用者傳送請求
並行量:463
aiohttp 是一個基於 asyncio 的非同步 HTTP 網路模組,它既提供了伺服器端,又提供了使用者端。所以可以將aiohttp用於web框架的伺服器端,監聽http請求。
from aiohttp import web
routes = web.RouteTableDef()
@routes.get("/index")
async def index(request):
return web.Response(text="Hello World")
if __name__ == '__main__':
app = web.Application()
app.add_routes(routes)
web.run_app(app)
並行量:1455
starlette 是當下火熱的非同步框架fastapi依賴的唯二模組之一,主要用於非同步請求的處理。
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route
from uvicorn.main import run
async def index(request):
return JSONResponse({'hello': 'world'})
app = Starlette(debug=True, routes=[Route('/index', index),])
if __name__ == "__main__":
run(app, host="0.0.0.0")
並行量:1539
並行曲線圖對比:
引數對比:
框架 | 並行量 | 延遲 |
---|---|---|
flask | 463 | 19 ms |
aiohttp | 1455 | 6 ms |
starlette | 1539 | 5 ms |
可以看出非同步框架的效能是同步框架的3倍多還不止,資料如此誇張的原因是同步框架的處理所有請求都是按照順序執行的,當請求有阻塞時需要等待。而非同步框架處理請求遇到阻塞可以轉而處理別的請求,所以相同時間非同步框架能夠處理的請求數遠高於同步。
瞭解了純框架的並行能力之後,下一篇來看看介面中有IO任務的並行對比。
準備連載一系列關於python非同步程式設計的文章。包括同非同步框架效能對比、非同步事情驅動原理等。首發微信公眾號,歡迎關注第一時間閱讀。