ホームページ  >  記事  >  バックエンド開発  >  FastAPI エンドポイントで同時 HTTP 呼び出しを行うときに、リソースの負担とクラッシュの可能性を回避するにはどうすればよいですか?

FastAPI エンドポイントで同時 HTTP 呼び出しを行うときに、リソースの負担とクラッシュの可能性を回避するにはどうすればよいですか?

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-11-15 22:02:02414ブラウズ

How can I avoid resource strain and potential crashes when making concurrent HTTP calls in a FastAPI endpoint?

FastAPI エンドポイントでの HTTPX による非同期呼び出し

FastAPI での ThreadPoolExecutor の使用に関する懸念

あなたFastAPI エンドポイントで concurrent.futures.ThreadPoolExecutor を使用することの影響、特にスレッドの作成、ホストの枯渇、アプリケーションのクラッシュに関する懸念を表明しました。過度のスレッド作成はリソースに負担をかけ、パフォーマンスの問題を引き起こす可能性があるため、これらの懸念は正当です。

推奨事項: HTTPX 非同期 API

これらの潜在的な落とし穴を回避するには、次のことをお勧めします。 concurrent.futures.ThreadPoolExecutor の代わりに HTTPX ライブラリの非同期機能を利用します。 HTTPX は、明示的なスレッド管理を必要とせずに HTTP リクエストを作成できる効率的な非同期 API を提供します。このアプローチには、いくつかの利点があります。

  • 制御された接続プーリング: HTTPX を使用すると、接続プールのサイズを制御でき、最適なパフォーマンスを得るために適切な数の接続が確実に維持されます。
  • 非同期リクエスト: 非同期リクエストはイベント ループをブロックせず、リソースを他の操作に解放するため、パフォーマンスのボトルネックを防ぎます。
  • 正常なシャットダウン: HTTPX を使用すると、AsyncClient インスタンスを明示的に閉じて、適切なクリーンアップを確保し、リソース リークを防ぐことができます。

作業例

次のコードスニペットは、FastAPI エンドポイントで HTTPX を使用して非同期 HTTP リクエストを実装する方法を示しています:

from fastapi import FastAPI, Request
from contextlib import asynccontextmanager
import httpx
import asyncio

URLS = ['https://www.foxnews.com/',
        'https://edition.cnn.com/',
        'https://www.nbcnews.com/',
        'https://www.bbc.co.uk/',
        'https://www.reuters.com/']

@asynccontextmanager
async def lifespan(app: FastAPI):
    # customise settings
    limits = httpx.Limits(max_keepalive_connections=5, max_connections=10)
    timeout = httpx.Timeout(5.0, read=15.0)  # 15s timeout on read. 5s timeout elsewhere.

    # Initialise the Client on startup and add it to the state
    async with httpx.AsyncClient(limits=limits, timeout=timeout) as client:
        yield {'client': client}
        # The Client closes on shutdown 

app = FastAPI(lifespan=lifespan)

async def send(url, client):
    return await client.get(url)

@app.get('/')
async def main(request: Request):
    client = request.state.client
    tasks = [send(url, client) for url in URLS]
    responses = await asyncio.gather(*tasks)
    return [r.text[:50] for r in responses]  # for demo purposes, only return the first 50 chars of each response

代替: RAM の使用を回避するためのストリーミング応答

応答本文全体を読み取る場合RAM への書き込みが懸念される場合は、FastAPI の StreamingResponse:

... # (same as previous code snippet)

async def iter_content(responses):
     for r in responses:
        async for chunk in r.aiter_text():
            yield chunk[:50]  # for demo purposes, return only the first 50 chars of each response and then break the loop
            yield '\n\n'
            break
        await r.aclose()

@app.get('/')
async def main(request: Request):
    client = request.state.client
    tasks = [send(url, client) for url in URLS]
    responses = await asyncio.gather(*tasks)
    return StreamingResponse(iter_content(responses), media_type='text/event-stream')
とともに HTTPX のストリーミング レスポンスを利用することを検討してください。

以上がFastAPI エンドポイントで同時 HTTP 呼び出しを行うときに、リソースの負担とクラッシュの可能性を回避するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。