首頁  >  文章  >  後端開發  >  在 FastAPI 端點中進行並發 HTTP 呼叫時,如何避免資源緊張和潛在的崩潰?

在 FastAPI 端點中進行並發 HTTP 呼叫時,如何避免資源緊張和潛在的崩潰?

Mary-Kate Olsen
Mary-Kate Olsen原創
2024-11-15 22:02:02412瀏覽

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

FastAPI 端點中使用HTTPX 的非同步呼叫

關於在FastAPI 中使用ThreadPoolExecutor 的擔憂關於在FastAPI 中使用ThreadPoolExecutor 的擔憂

您表達了對使用影響的擔憂FastAPI端點中的並發.futures.ThreadPoolExecutor,特別是關於線程創建、主機飢餓和應用程式崩潰。這些擔憂是合理的,因為過多的執行緒創建可能會導致資源緊張,並可能導致效能問題。

建議:HTTPX Async API

為了避免這些潛在的陷阱,建議利用 HTTPX 庫的非同步功能而不是並發.futures.ThreadPoolExecutor。 HTTPX 提供了高效的非同步 API,可讓您發出 HTTP 請求,而無需明確的執行緒管理。這種方法有幾個優點:

  • 受控連接池: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 是一個問題,考慮利用 HTTPX 的 Streaming 回應以及 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')

以上是在 FastAPI 端點中進行並發 HTTP 呼叫時,如何避免資源緊張和潛在的崩潰?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn