API 속도 제한
API 속도 제한 (Rate limiting)
컨트롤러가 모든 API 요청을 처리하려고 하면 컨트롤러가 요청에 압도되는 상황이 생길 수 있어요. 컨트롤러가 리소스를 고갈시키거나, 데이터베이스 서버를 압도해서 그 리소스를 고갈시킬 수도 있죠. API 속도 제한을 사용하면 API 요청의 속도에 한도를 설정해서 리소스를 관리하고 압도당하는 것을 막을 수 있어요.
본문
할당량 (Quotas)
Boundary는 주어진 시간 동안의 요청 수를 추적하는 할당량을 만들어요. 기본적으로 Boundary는 인증 토큰별, IP 주소별, 그리고 전체 총계로 요청 수를 추적해요. Boundary는 갑작스러운 요청 폭주가 있을 때 메모리를 너무 많이 소비하지 않도록 할당량 추적을 위해 메모리의 일부를 예약해 둬요.
Boundary가 할당량을 저장할 수 없으면 503 HTTP 상태 코드로 요청을 제한해요. api_rate_limit_max_quotas 변수로 Boundary가 허용하는 최대 할당량 수를 설정할 수 있어요. 할당량 추적을 모니터링할 수 있는 두 가지 메트릭도 있어요.
boundary_controller_api_ratelimiter_quota_storage_capacityboundary_controller_api_ratelimiter_quota_storage_usage
기본 한도 (Default limits)
API 속도 제한은 컨트롤러에서 적용돼요. 리소스와 액션의 각 조합마다 별도의 설정 가능한 한도가 있어요. 기본적으로 list 액션의 한도는 다음과 같아요.
- 인증 토큰별 30초당 150개 요청
- IP 주소별 30초당 1,500개 요청
- 전체 30초당 1,500개 요청
다른 모든 액션의 기본 한도는 다음과 같아요.
- 인증 토큰별 30초당 3,000개 요청
- IP 주소별 30초당 30,000개 요청
- 전체 30초당 30,000개 요청
기본 설정을 덮어쓰고 다른 구체적 한도를 설정하려면 컨트롤러 구성의 api_rate_limit 스탠자를 사용해요.
속도 제한 HTTP 헤더 (Rate limiting HTTP headers)
컨트롤러 API에 요청하는 클라이언트는 HTTP 응답 헤더를 검사해서 설정된 한도와 현재 사용량을 이해할 수 있어요. 각 응답에는 RateLimit과 RateLimit-Policy 헤더가 포함돼요.
요청이 속도 제한되면 Boundary는 Retry-After 헤더와 함께 429 HTTP 상태 코드를 클라이언트에 보내요. Retry-After 헤더에는 클라이언트가 요청을 다시 보내기 전에 기다려야 하는 초 수가 들어 있어요.
자세한 내용은 HTTP 헤더를 참고해요.
더 알아보기 (More information)
구체적인 api_rate_limit 구성 옵션은 컨트롤러 스탠자 문서를 참고해요. 몇 가지 예시 구성은 아래와 같아요.
속도 제한 구성 예시 (Rate limiting configuration examples)
다음 예시는 모든 리소스와 액션에 동일한 한도를 적용하는 간단한 구성이에요.
controller {
# 모든 리소스와 액션의 총 한도
api_rate_limit {
resources = ["*"]
actions = ["*"]
per = "total"
limit = 500
period = "1s"
}
# 모든 IP 주소의 모든 리소스/액션 한도.
# 토큰을 위조하거나 인증되지 않은 엔드포인트를 스팸하는 악성 호스트를 막기 위함.
api_rate_limit {
resources = ["*"]
actions = ["*"]
per = "ip-address"
limit = 100
period = "1s"
}
# 모든 인증된 요청의 한도. 한 사용자가 총 한도를 모두 소비하는 것을 막기 위함.
api_rate_limit {
resources = ["*"]
actions = ["*"]
per = "auth-token"
limit = 100
period = "1s"
}
}
다음 예시는 속도 제한을 비활성화하는 구성이에요. 이미 리버스 프록시 같은 외부 시스템을 사용해서 속도 제한을 적용하고 있다면 속도 제한을 끄고 싶을 수 있어요.
controller {
api_rate_limit_disable = true
}
다음 예시는 대부분의 엔드포인트에 기본 설정을 사용하지만 단일 오버라이드를 구성해요.
controller {
api_rate_limit {
resources = ["target"]
actions = ["list"]
per = "auth-token"
limit = 10
period = "1s"
}
}
다음 예시는 더 복잡해요. 먼저 모든 리소스와 액션에 적용할 몇 가지 기본값을 설정하고, 그다음 서로 다른 한도를 가진 몇 가지 특정 엔드포인트를 구성해요.
controller {
# 모든 리소스와 액션의 총 한도
api_rate_limit {
resources = ["*"]
actions = ["*"]
per = "total"
limit = 500
period = "1s"
}
# 모든 list 작업의 총 한도.
# list 액션은 상대적으로 비용이 많이 들기 때문에 전체 상한을 설정.
api_rate_limit {
resources = ["*"]
actions = ["list"]
per = "total"
limit = 200
period = "1s"
}
# 모든 리소스/액션의 IP 주소 한도.
# 토큰을 위조하거나 인증되지 않은 엔드포인트를 스팸하는 악성 호스트를 막기 위함.
api_rate_limit {
resources = ["*"]
actions = ["*"]
per = "ip-address"
limit = 50
period = "1s"
}
# 모든 인증된 요청의 한도.
# 위에서 설정한 총 list 한도를 한 사용자가 모두 소비하지 못하도록
# 모든 인증 요청의 기본값을 실질적으로 설정. 뒤따르는 한도는
# 특정 리소스/액션 집합에 대해 기본값을 덮어쓸 수 있음.
api_rate_limit {
resources = ["*"]
actions = ["*"]
per = "auth-token"
limit = 100
period = "1s"
}
# 인증 토큰별 모든 list 작업의 한도.
# 일반적으로 더 비싸므로 합리적인 기본값을 설정.
api_rate_limit {
resources = ["*"]
actions = ["list"]
per = "auth-token"
limit = 50
period = "1s"
}
# 인증 토큰별 targets/sessions list 한도.
# 클라이언트가 자주 나열하길 원하지만 사용자당 수가 많으면 더 비쌀 수 있는
# 리소스들. 낮은 한도는 refresh 토큰과 캐싱 사용을 유도.
api_rate_limit {
resources = ["target", "session"]
actions = ["list"]
per = "auth-token"
limit = 20
period = "1s"
}
# 인증 토큰별 authorize-session 한도
api_rate_limit {
resources = ["target"]
actions = ["authorize-session"]
per = "auth-token"
limit = 150
period = "1s"
}
}