속도 제한 아키텍처¶
라우터는 남용을 방지하고 클라이언트 간 공정한 리소스 할당을 보장하기 위해 정교한 속도 제한을 구현합니다.
아키텍처¶
속도 제한은 이중 윈도우 방식을 사용하여 HTTP 계층에서 구현됩니다:
pub struct ModelEndpointRateLimiter {
cache: Arc<DashMap<String, (Instant, u32, u32)>>, // (window_start, request_count, burst_count)
window_duration: Duration, // 지속 제한을 위한 60초
max_requests_per_window: u32, // 분당 100개 요청
burst_limit: u32, // 최대 20개 요청
burst_window: Duration, // 버스트 감지를 위한 5초
}
클라이언트 식별¶
시스템은 우선순위 기반 클라이언트 식별 전략을 사용합니다:
- API 키 (선호): Bearer 토큰의 처음 16자 사용
- IP 주소 (폴백): 다음 순서로 헤더에서 추출:
X-Forwarded-For(프록시/로드 밸런서 환경용)X-Real-IP(대체 헤더)- IP를 확인할 수 없는 경우 "unknown"으로 폴백
속도 제한 규칙¶
각 클라이언트는 다음과 같이 독립적으로 속도 제한됩니다:
- 지속 제한: 분당 100개 요청 (슬라이딩 윈도우)
- 버스트 보호: 5초 윈도우 내 최대 20개 요청
- 클라이언트별 격리: 각 API 키 또는 IP는 별도의 쿼터를 가짐
설정¶
rate_limiting:
enabled: true
# 전역 기본값
default:
requests_per_minute: 100
burst_limit: 20
burst_window_seconds: 5
# 엔드포인트별 오버라이드
endpoints:
/v1/chat/completions:
requests_per_minute: 60
burst_limit: 10
/v1/models:
requests_per_minute: 300
burst_limit: 50
# 클라이언트별 오버라이드 (API 키 접두사로)
clients:
sk-premium-*:
requests_per_minute: 500
burst_limit: 100
sk-free-*:
requests_per_minute: 20
burst_limit: 5
캐시 관리¶
속도 제한기에는 자동 정리 메커니즘이 포함됩니다:
- 메모리 효율성: 락프리 동시 접근을 위한 DashMap
- 자동 정리: 캐시 > 1000 항목 시 만료된 항목 제거
- TTL 차별화:
- 빈 모델 응답: 5초 캐시 TTL (DoS 방지)
- 일반 응답: 60초 캐시 TTL
보안 고려 사항¶
속도 제한 시스템은 여러 보안 문제를 해결합니다:
- DoS 방지: 빈 응답에 대한 짧은 TTL로 캐시 포이즈닝 방지
- 공정한 리소스 할당: 클라이언트별 제한으로 독점 방지
- 버스트 보호: 이중 윈도우 방식으로 지속적 공격과 버스트 공격 모두 포착
- 클라이언트 스푸핑 완화: IP 주소보다 API 키 우선
메트릭 및 모니터링¶
속도 제한은 메트릭 시스템과 통합됩니다:
pub struct ModelMetrics {
pub rate_limit_violations: AtomicU64, // 거부된 요청 추적
pub empty_responses_returned: AtomicU64, // 빈 응답 비율 모니터링
pub transient_errors: AtomicU64, // 네트워크/타임아웃 실패
pub permanent_errors: AtomicU64, // 인증/설정 실패
}
Prometheus 메트릭¶
# 속도 제한 위반
rate_limit_violations_total{client_id="sk-abc...", endpoint="/v1/chat/completions"} 15
# 현재 요청 수
rate_limit_current_requests{client_id="sk-abc...", window="minute"} 45
rate_limit_current_requests{client_id="sk-abc...", window="burst"} 8
# 속도 제한 상태
rate_limit_remaining{client_id="sk-abc...", window="minute"} 55
응답 헤더¶
속도 제한 정보는 응답 헤더에 포함됩니다:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 55
X-RateLimit-Reset: 1699574460
X-RateLimit-Burst-Limit: 20
X-RateLimit-Burst-Remaining: 12
오류 응답¶
속도 제한이 적용되면 API는 다음을 반환합니다:
{
"error": {
"message": "속도 제한 초과. 45초 후에 다시 시도하세요.",
"type": "rate_limit_exceeded",
"code": 429,
"details": {
"limit": 100,
"remaining": 0,
"reset_at": "2024-01-15T10:30:00Z",
"retry_after": 45
}
}
}
구현 세부 사항¶
속도 제한기는 싱글톤 서비스로 구현됩니다:
static MODEL_RATE_LIMITER: once_cell::sync::Lazy<ModelEndpointRateLimiter> =
once_cell::sync::Lazy::new(ModelEndpointRateLimiter::new);
이를 통해: - 단일 속도 제한 적용 지점 - 모든 요청 핸들러에서 일관된 상태 - 최소 메모리 오버헤드