출시·고도화 중
Algorithm
레이트 리미터는 사용자나 IP마다 일정 시간의 요청 수를 제한해 과부하와 남용을 막습니다. 토큰 버킷, 슬라이딩 윈도우, Redis 구현까지 다룹니다.
레이트 리미터(rate limiter)는 정해진 시간 동안 받아들이는 요청 수를 제한하는 장치입니다. "사용자마다 1분에 100번"처럼 키와 한도와 시간 창을 정해 두고, 이를 넘는 요청은 거절하거나 늦춥니다. 대표 알고리즘으로 고정 창, 슬라이딩 창 로그, 슬라이딩 창 카운터, 토큰 버킷, 리키 버킷이 있으며, 각각 정확도와 메모리, 버스트를 다루는 방식이 다릅니다.
공개 API, 로그인, 결제, 메시지 발송처럼 외부에 열린 기능은 거의 모두 레이트 리미터 뒤에 있습니다. 갑작스러운 트래픽과 잘못된 재시도 루프로부터 서버를 지키고, 한 사용자가 자원을 독점하지 못하게 하며, 무차별 대입 공격의 속도를 늦춥니다. 시스템 설계 면접의 단골 주제이기도 해서, 알고리즘의 장단점과 분산 환경에서의 구현을 설명할 수 있어야 합니다.
먼저 고정 창 카운터를 직접 만들어 창 경계에서 한도의 두 배가 통과하는 문제를 확인하고, 슬라이딩 창과 토큰 버킷으로 이를 고쳐 보세요. 그다음 시계를 주입해 테스트하는 법, HTTP 429와 Retry-After 응답, Redis의 INCR·EXPIRE와 Lua 스크립트로 여러 서버가 한도를 공유하는 방법으로 넓혀 가면 됩니다.
일정한 속도로 토큰이 차고 요청마다 하나씩 쓰는 방식으로, 평균 속도를 지키면서 용량만큼의 버스트를 허용합니다.
요청 시각 로그나 두 창의 카운터를 섞은 근사로, 고정 창의 경계 문제 없이 최근 일정 시간의 요청 수를 셉니다.
사용자 ID, API 키, IP, 엔드포인트별로 한도를 따로 세어 한 클라이언트가 자원을 독점하지 못하게 합니다.
Redis의 원자적 INCR과 Lua 스크립트로 여러 서버가 같은 한도를 경쟁 상태 없이 나눠 씁니다.
TokenBucket은 초당 rate개씩 토큰을 채우고 최대 capacity개까지 담습니다. allow()는 지난 호출 뒤 흐른 시간만큼 토큰을 한꺼번에 채운 뒤(게으른 리필) 토큰이 충분하면 하나를 쓰고 True를 돌려줍니다. 실행하면 처음 5번은 버스트로 통과하고 이어서 3번은 거절되며, 1.1초 쉰 뒤에는 다시 2번이 통과합니다. 뒤로 가지 않는 time.monotonic()으로 시간을 잽니다.
token_bucket.py
import time
class TokenBucket:
"""Allow bursts of up to `capacity` requests, refilled at `rate` tokens per second."""
def __init__(self, rate: float, capacity: float) -> None:
self.rate = rate
self.capacity = capacity
self.tokens = capacity
self.updated = time.monotonic()
def allow(self, cost: float = 1.0) -> bool:
now = time.monotonic()
self.tokens = min(self.capacity, self.tokens + (now - self.updated) * self.rate)
self.updated = now
if self.tokens >= cost:
self.tokens -= cost
return True
return False
if __name__ == "__main__":
bucket = TokenBucket(rate=2, capacity=5) # 2 requests per second, bursts of 5
print([bucket.allow() for _ in range(8)]) # 5 x True, then 3 x False
time.sleep(1.1) # about 2.2 tokens come back
print(bucket.allow(), bucket.allow(), bucket.allow()) # True True False
python token_bucket.py레이트 리미터 에 관해 묻고, 경험을 나누고, 의견을 주고받는 곳입니다.
아직 토론이 없습니다. 첫 이야기를 시작해 보세요.
댓글 0개
로그인 · 로그인하면 댓글을 남길 수 있습니다.
첫 댓글을 남겨 보세요.