FastAPI: API 呼び出しが並列ではなく逐次的に実行される理由
FastAPI は、両方の非同期を使用してエンドポイント (パス操作関数とも呼ばれます) を定義しますデフとデフ。概念的には async def は並列化を示唆しているかもしれませんが、FastAPI は実際にはこれらの関数を異なる方法で処理します:
async def で定義されたエンドポイント:
- イベント ループで直接実行。
- 他の非同期関数からのみ呼び出すことができ、実行前に一時停止 (待機) する必要がありますI/O などの非同期操作。
- イベント ループがブロックされておらず、他のタスクが同時に実行できることを確認します。
エンドポイント def で定義:
-
ではなくを直接実行しますイベント ループ内ではなく、外部スレッドプールからの別のスレッド内で実行されます。
- 非同期関数または非同期関数のいずれかから呼び出すことができます。
- イベント ループをブロックし、他のタスクの実行を妨げる可能性があります。非同期操作が一時停止せずに実行される場合。
- 特定の環境でパフォーマンスの最適化を提供します。
並列化への影響:
この理解に基づいて、コード例を調べてみましょう:
@app.get("/ping")
async def ping(request: Request):
print("Hello")
time.sleep(5) # This sleeps the event loop for 5 seconds
print("bye")
return {"ping": "pong!"}
ログイン後にコピー
この場合、次のことが発生します:
- /ping への 2 つのリクエストが送信されます。
- 非同期 defENDPOINT はイベント ループ内で直接実行されます。
- time.sleep(5) 呼び出しはイベント ループを 5 秒間一時停止します。
- この 5 秒間、2 番目のリクエストはキューに入れられ、イベント ループがブロックされているため処理できません。
- 5 後にイベント ループが再開されると、
その結果、応答はシリアルに出力されます。
Hello
bye
Hello
bye
ログイン後にコピー
並列化を有効にするには、time.sleep() などの非同期操作を使用します。非同期 def エンドポイントでは使用しないでください。代わりに、次のいずれかのアプローチを適用できます。
- run_in_threadpool() を使用してスレッドを生成し、イベント ループの外側でブロック操作を実行します。
- loop.run_in_executor() を使用します。または asyncio.to_thread() を使用してブロック操作を別のスレッドまたはプロセスで実行します。
- の使用を検討してください。 ThreadPoolExecutor または ProcessPoolExecutor は、計算負荷の高いタスクをオフプロセスで実行します。
以上がFastAPI が API 呼び出しを並列ではなく逐次実行するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。