Rate limiting
컴퓨터 네트워크에서 속도 제한은 네트워크 인터페이스 컨트롤러에서 보내거나 받는 요청의 속도를 제어하는 데 사용됩니다. DoS 공격을 방지하고 웹 스크래핑을 제한하는 데 사용할 수 있습니다.
왜 Rate Limit(사용량 제한)이 필요한가?
- 많은 참여자가 있는 트위치 채팅에서 스패머 한 명이 있을 때, 사용량 제한이 없다면 스패머가 대화를 지배할 수 있음.
- 사용량 제한을 통해 각 사용자가 공정하게 참여할 기회를 가질 수 있음.
- Rate Limiter(사용량 제한기)는 특정 기간 동안 설정된 한도를 초과하는 요청을 차단하여 서비스의 트래픽을 제어함. 이는 채팅에서의 스팸 조절 외에도 유용함
- 예를 들어, 로그인 폼에서 사용량 제한을 통해 브루트 포스 공격을 억제하면서도 소량의 잘못된 추측을 허용할 수 있음
- API 엔드포인트도 종종 사용량 제한이 적용되어 단일 사용자가 리소스를 독점하지 못하게 함
- 사용자가 비싼 API 엔드포인트를 분당 100번만 호출할 수 있도록 하면 카운터를 사용하여 분당 100번의 히트를 추적하고, 그 후의 요청은 차단
- 이는 가장 간단한 사용량 제한 알고리듬 중 하나인 고정 윈도우 제한기(Fixed Window Limiter)임
- 서비스 트래픽을 제어하는 일반적인 방법
Leaky Bucket
FIFO 형식의 Bucket(Queue)에 요청을 차례로 담아 크기가 다 차면 요청 제한
Fixed windows 알고리듬
- 고정된 시간 창(window) 내에서 요청 수가 제한됨
- 각 시간 창의 시작에 요청 카운터가 0으로 재설정됨
- 장점
- 구현과 이해가 쉬움
- 사용자에게 예측 가능함
- 시간 창 끝 무렵에 요청이 시작되면 제한의 최대 2배까지 요청 폭증(burst)이 허용될 수 있음
슬라이딩 윈도우(Sliding windows) 알고리듬
- 용량을 한 번에 모두 새로 고치는 대신, 슬라이딩 윈도우는 한 번에 하나의 요청씩 용량을 채움
- 장점
- 요청 트래픽의 분포를 부드럽게 함
- 높은 부하에 적합함
- 고정 시간 창보다 사용자에게 예측 가능성이 떨어짐
- 각 요청의 타임스탬프를 저장하는 것은 리소스 집약적임
토큰 버킷(Token buckets) 알고리듬
- 시간 창의 지속 시간 대신, 일정한 속도로 "토큰"으로 채워지는 버킷을 상상함
- 각 요청은 이 버킷에서 하나의 토큰을 인출하고, 버킷이 비어 있으면 다음 요청이 차단됨
- 버킷의 용량은 버스트가 지원할 수 있는 최대 요청 수를 나타냄
- 보충 간격은 장기 평균 허용 요청 간격을 나타냄
- 여러 개의 속도 제한기 없이 별개의 버스트 및 평균 용량을 가질 수 있다는 것이 이 알고리듬의 주요 이점 중 하나임
- 장점
- 높은 트래픽의 버스트를 허용하지만 장기 평균 요청 속도를 적용함
- 사용자에게 더 유연하여 허용 가능한 범위 내에서 트래픽 급증을 허용함
- 고정 시간 창보다 사용자에게 제한 사항과 보충 시간을 전달하기가 더 어려움
- Stripe는 사용자당 500개의 제한과 0.01초의 보충 간격을 가진 토큰 버킷을 사용하여 초당 100개의 요청을 지속적으로 허용하지만 최대 500개의 요청까지 버스트를 허용함
- OpenAI의 GPT-3.5 무료 티어는 200개의 제한과 86400초/200의 보충 간격을 가진 토큰 버킷을 사용하여 하루에 200개의 요청으로 제한됨
레이트 리밋 적용 시 고려 사항
- 레이트 리미터에 대한 영구 저장소를 만들어야 함
- 영구 저장소에 대한 서버의 연결이 실패하면 요청을 차단하지 않고 모두 허용하도록 해야 함
- 선택적으로 버스트 트래픽을 조절할 수 있음
- 적절한 키를 선택해야 함 (사용자 ID, API 키 등)
- 유용한 속도 제한 오류를 표시해야 함 (다음 요청까지 대기 시간, 429 HTTP 상태 코드, x-ratelimit-* 응답 헤더 등)