FastAPI에서 서버 요청 부하를 줄여보자

Dev Smile·2024년 7월 14일
1

FastAPI

목록 보기
3/10

많은 트래픽이 발생하는 상황에서 서버가 과부하에 걸리면 서비스 제공이 어려워질 수 있습니다. 서버 부하를 관리하는 것은 웹 애플리케이션의 성능과 신뢰성을 유지하는 데 중요합니다. 이러한 문제를 해결하기 위해 "Rate Limiting"이라는 개념이 도입되었습니다. 이번 글에서는 Rate Limiting의 개념과 FastAPI에서 이를 구현하는 방법을 살펴보겠습니다.

Rate Limiting이란 무엇인가?

Rate Limiting은 일정 기간 동안 서버에 대한 요청 수를 제한하는 기술입니다. 초당, 분당 또는 시간당 서버가 처리할 수 있는 요청 수에 제한을 두어 서버 과부하를 방지하고 원활한 사용자 경험을 보장할 수 있습니다. 예를 들어, 초당 요청 수를 제한하여 서버가 처리할 수 있는 최대 용량을 넘지 않도록 하는 것이죠.

Rate Limiting의 주요 목적은 다음과 같습니다:

  • 서버 안정성 유지: 서버에 과도한 부하가 걸리는 것을 방지하여 안정적인 서비스 제공합니다.
  • 공정한 자원 분배: 특정 사용자나 클라이언트가 서버 자원을 독점하지 않도록 합니다.
  • 보안 강화: DDoS 공격 등 악의적인 트래픽을 줄이는 데 기여합니다.

서버 부하를 줄이는 속도 제한 방법

효과적으로 속도 제한을 구현하려면 서버 용량과 사용자의 일반적인 트래픽 패턴을 이해해야 합니다.
다음은 서버 부하를 줄이기 위한 몇 가지 모범 사례입니다:

  • 용량 기반 한계 설정: 서버의 처리 용량을 반영하는 현실적인 한계를 설정하세요. 피크 트래픽 시간과 평균 사용자 행동을 고려하세요.
  • 점진적 저하 사용: 초과 요청을 즉시 거부하는 대신, 한계에 도달했을 때 요청을 대기시키거나 속도를 늦추는 시스템을 구현하는 것을 고려하세요.
  • 모니터링 및 조정: 트래픽 패턴을 지속적으로 모니터링하고 사용량 변화에 맞춰 한계를 조정하세요.

FastAPI에서 Rate Limiting 구현하기

FastAPI-Limiter라는 라이브러리를 사용하면 FastAPI에서 손쉽게 Rate Limiting을 적용할 수 있습니다.

FastAPI-Limiter 소개

FastAPI-Limiter는 FastAPI 애플리케이션에 Rate Limiting 기능을 추가하기 위한 라이브러리입니다. 이 라이브러리는 RateLimiter라는 종속성을 통해 특정 경로에 Rate Limiting을 적용할 수 있도록 합니다.

예제 코드

다음은 FastAPI에서 FastAPI-Limiter를 사용하여 경로 /에 5초당 2번의 요청을 허용하는 예제입니다:

from fastapi import FastAPI, Depends
from fastapi_limiter import FastAPILimiter
from fastapi_limiter.depends import RateLimiter

@asynccontextmanager
async def lifespan(_: FastAPI):
    redis_connection = redis.from_url(REDIS_URL, encoding="utf8")
    await FastAPILimiter.init(
        redis=redis_connection,
        identifier=service_name_identifier,
        http_callback=custom_callback,
    )
    yield
    await FastAPILimiter.close()

app = FastAPI(lifespan=lifespan)

async def service_name_identifier(request: Request):
    service = request.headers.get("Service-Name")
    return service
    
async  def  custom_callback ( request: Request, response: Response, pexpire: int ): 
    """ 
    요청이 너무 많을 때의 기본 콜백 
    :param request: 
    :param pexpire: 남은 밀리초 
    :param response: 
    :return: 
    """
     expire = ceil(pexpire / 1000 ) 

    raise HTTPException( 
        status.HTTP_429_TOO_MANY_REQUESTS, 
        f"요청이 너무 많습니다. {expire} 초 후에 다시 시도하세요." , 
        headers={ "Retry-After" : str (expire)}, 
    )

@app.get("/", dependencies=[Depends(RateLimiter(times=2, seconds=5))])
async def read_root():
    return {"message": "Hello, World!"}

예제 설명

  • Redis 설정: FastAPI-Limiter는 Redis를 사용하여 요청 수를 관리합니다.
    • identifier는 경로 제한에 대한 식별자입니다. 기본적으로 제한은 IP를 기반으로 적용됩니다.
    • http_callback은 액세스가 금지될 때의 콜백입니다. 기본값은 상태 코드 429를 HTTPException와 함께 발생시키는 것입니다.
  • RateLimiter 사용: RateLimiter를 사용하여 경로 /에 대해 5초당 2번의 요청을 허용하도록 설정합니다. 이는 dependencies 매개변수를 통해 적용됩니다.

특장점

FastAPI-Limiter를 사용하면 다음과 같은 장점이 있습니다:

  • 간단한 설정: 몇 줄의 코드만으로 Rate Limiting을 적용할 수 있습니다.
  • 유연성: 다양한 경로에 대해 서로 다른 Rate Limiting 규칙을 적용할 수 있습니다.
  • 확장성: Redis를 사용하여 확장성이 뛰어난 Rate Limiting을 구현할 수 있습니다.

결론

Rate Limiting은 서버 부하를 줄이고 안정적인 서비스를 제공하기 위한 기술입니다. FastAPI에서 FastAPI-Limiter를 사용하면 간단하고 효율적으로 Rate Limiting을 구현할 수 있습니다. 속도 제한을 구현하는 데는 설정을 적절히 맞추기 위한 몇 번의 시행착오가 필요할 수 있지만, 안정적이고 응답성이 좋은 서버를 구축하는 데 그 이점은 충분히 가치가 있을 것입니다. 서버 성능을 최적화하고 사용자 경험을 개선하기를 원하신다면 Rate Limiting을 도입해보세요.


0개의 댓글

관련 채용 정보