環境
- Python 3.10
- fastapi v0.75
やりたいこと
fastapiというPython製APIフレームワークがある
APIが外部の別のAPIを呼び出すことはよくある。fatsapiがネイティブで非同期(async)に対応していることもあり、 せっかくなのでHTTPリクエスト部分も非同期で書いてみたかった
コード
PythonでHTTPリクエストする場合はrequests使うのが一番多いと思うがasyncには対応してないのでHTTPXというライブラリを使う
pip install httpx
でインストール可能
例外処理も含めたサンプルコードが以下
import httpx from fastapi import HTTPException, status, FastAPI app = FastAPI() async def request(): async with httpx.AsyncClient() as client: response: httpx.Response = await client.get("https://httpbin.org/uuid") if response.status_code != httpx.codes.OK: raise HTTPException(status_code=status.HTTP_503_SERVICE_UNAVAILABLE) return response.json() @app.get('/httpx') async def bench_httpx(): return await request()
こんな感じに表示されるはず
{ "uuid": "8716ba20-8443-4857-bf30-4fcd39e7a909" }
せっかくなのでrequests版も作ってベンチマークとってみた
from fastapi import HTTPException, status, FastAPI import requests app = FastAPI() @app.get('/requests') def bench_requests(): response = requests.get('https://httpbin.org/uuid') if response.status_code != requests.codes.ok: raise HTTPException(status_code=status.HTTP_503_SERVICE_UNAVAILABLE) return response.json()
で結果 HTTPX版の方/
❯ hey http://localhost:3000/httpx -n 1000 -c 50 -t 2 Summary: Total: 4.8898 secs Slowest: 2.3744 secs Fastest: 0.7238 secs Average: 1.0300 secs Requests/sec: 40.9016 Total data: 9400 bytes Size/request: 47 bytes Response time histogram: 0.724 [1] |■ 0.889 [56] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1.054 [78] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1.219 [30] |■■■■■■■■■■■■■■■ 1.384 [21] |■■■■■■■■■■■ 1.549 [12] |■■■■■■ 1.714 [1] |■ 1.879 [0] | 2.044 [0] | 2.209 [0] | 2.374 [1] |■ Latency distribution: 10% in 0.8375 secs 25% in 0.8842 secs 50% in 0.9557 secs 75% in 1.1458 secs 90% in 1.2995 secs 95% in 1.4624 secs 99% in 1.5652 secs Details (average, fastest, slowest): DNS+dialup: 0.0002 secs, 0.7238 secs, 2.3744 secs DNS-lookup: 0.0001 secs, 0.0000 secs, 0.0021 secs req write: 0.0001 secs, 0.0000 secs, 0.0006 secs resp wait: 1.0296 secs, 0.7236 secs, 2.3720 secs resp read: 0.0001 secs, 0.0000 secs, 0.0002 secs Status code distribution: [200] 200 responses
以下はrequests版
❯ hey http://localhost:3000/requests -n 1000 -c 50 -t 2 Summary: Total: 5.5102 secs Slowest: 2.9772 secs Fastest: 0.6944 secs Average: 0.9763 secs Requests/sec: 36.2963 Total data: 9400 bytes Size/request: 47 bytes Response time histogram: 0.694 [1] | 0.923 [129] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1.151 [36] |■■■■■■■■■■■ 1.379 [9] |■■■ 1.608 [9] |■■■ 1.836 [7] |■■ 2.064 [1] | 2.292 [6] |■■ 2.521 [0] | 2.749 [0] | 2.977 [2] |■ Latency distribution: 10% in 0.7313 secs 25% in 0.7558 secs 50% in 0.8162 secs 75% in 1.0259 secs 90% in 1.5373 secs 95% in 1.8023 secs 99% in 2.9076 secs Details (average, fastest, slowest): DNS+dialup: 0.0007 secs, 0.6944 secs, 2.9772 secs DNS-lookup: 0.0004 secs, 0.0000 secs, 0.0019 secs req write: 0.0002 secs, 0.0000 secs, 0.0016 secs resp wait: 0.9752 secs, 0.6943 secs, 2.9770 secs resp read: 0.0001 secs, 0.0000 secs, 0.0012 secs Status code distribution: [200] 200 responses
あれ、あんまり変わらない。。。? それどころかHTTPX版のほうが遅いときもある