非同期IOを使うことでシングルプロセス、シングルスレッドでも効率的に複数のHTTPリクエストの処理を行う。
サーバー側の準備
はじめに動作確認用に複数のリクエストを処理できるHTTPサーバプログラムを用意する。
このサーバープログラム自体も非同期IOで記述することで複数のリクエストを処理するサーバーを記述できるのだが、サーバー側とクライアント側で非同期IOの説明すると、今回の論点がぼやけてくるので、ひとまずリクエストを受け付けると3秒待ってからレスポンスを返すマルチスレッドなサーバーを用意した。このプログラムの説明は本題ではないので省略。
これを起動して、別の端末からcurlで同時に3リクエストを送ってみると、3秒後に3つのレスポンスが返る。
$ python wsgi-server.py
$ seq 1 3 | xargs -P 3 -I{} curl "localhost:8000/{}"
Hello World/1
Hello World/2
Hello World/3
非同期IOによるHTTPリクエスト
サードパーティライブラリのaiohttpを使用すると、非同期なHTTPClientをかんたんに記述できる。
import aiohttp
import asyncio
import time
async def get_request(session, no):
response = await session.get(f'http://localhost:8000/{no}')
content = await response.text()
print(f"{time.strftime('%X')} - {response.status} {content}", end='')
async def main():
tasks = []
print(f"{time.strftime('%X')} - Start")
async with aiohttp.ClientSession() as session:
for n in range(3):
tasks.append(get_request(session, n+1))
await asyncio.gather(*tasks)
print(f"{time.strftime('%X')} - Finish")
asyncio.run(main())
実行結果
18:03:56 - Start
18:03:59 - 200 Hello World/3
18:03:59 - 200 Hello World/2
18:03:59 - 200 Hello World/1
18:03:59 - Finish