FastAPI 엔드포인트에서 동시 HTTP 호출을 수행할 때 리소스 부담과 잠재적인 충돌을 방지하려면 어떻게 해야 합니까?

Mary-Kate Olsen
풀어 주다: 2024-11-15 22:02:02
원래의
411명이 탐색했습니다.

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

FastAPI 엔드포인트에서 HTTPX를 사용한 비동기 호출

FastAPI에서 ThreadPoolExecutor 사용에 대한 우려

귀하 사용으로 인한 영향에 대한 우려를 표명했습니다. 특히 스레드 생성, 호스트 부족 및 애플리케이션 충돌과 관련된 FastAPI 엔드포인트의 동시.futures.ThreadPoolExecutor. 과도한 스레드 생성은 리소스에 부담을 주고 잠재적으로 성능 문제를 일으킬 수 있으므로 이러한 우려는 타당합니다.

권장 사항: HTTPX Async 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와 함께 HPX의 스트리밍 응답을 활용해 보세요.

... # (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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿