설계 속도 제한 기
1) 속도 제한 이유
속도 제한은 API의 가용성과 경제성을 보호합니다. 홍수 중지, 배상 버스트, 자격 증명 채우기, 고가의 운영 (돈 거래, 보고서 생성) 보호, 종속 시스템 (데이터베이스/공급자) 의로드를 부드럽게합니다. 좋은 디자인은 공정성, 대기 시간의 예측 가능성 및 명확한 SLO를 제공합니다.
주요 목표
RPS 안정성 및 백엔드 과부하 방지.
통제되는 "탄성" (버스트 허용).
고객 차별화 (사용자 당/조직 당/키 당/IP 당/지역당).
가치 모델: 거래마다 다른 "가격".
2) 제한 유형
RPS 제한: 초당/분당 요청.
인용문: 기간 당 총 예산 (일/월).
경쟁력: 동시 작업 (체크 아웃, 무거운 작업).
속도/줄무늬/초 (로드/언로드).
가중 한계: 복잡성 별 요청의 "비용" (예: GraphQL 복잡성, 배치 크기).
적응 형: 이상이있는 경우 강화 (의심스러운 활동/오류 401/403/5xx).
3) 알고리즘과 적용 시점
3. 1 고정 창 카운터
간단한: 간격 당 카운터 (예: 100 r/min).
장점: 최소 비용. 단점: 창문 경계에서 "가장자리 파열".
언제: 관리자 패널, 저렴한 정확도, 저렴한 비용.
3. 슬라이딩 창 2 개 (로그/카운터)
로그-정확하고 비싼 메모리 요청의 타임 스탬프를 저장합니다.
카운터: 인접한 두 개의 창 (롤링) 의 평균, 정확성 및 가격 손상.
언제: 중간 트래픽의 공용 API는 복잡한 수학없이 부드러움이 필요합니다.
3. 3 토큰 버킷
매개 변수: rate 'r' (토큰/초) 및 용량 'b' (버스트). 각 요청은 토큰을 "연소" 합니다.
장점: 자연적인 버스트 허용, 간단한 구현. 단점: 엄격한 균일성이 없습니다.
언제: 'b' 내에 "발리" 가 필요한 경우 거의 항상 RPS의 경우.
3. 4 새는 양동이 (물방울)
고정 속도로 "누출" 하는 큐.
장점: 출력 흐름. 단점: 더 많은 지연.
언제: 외부 "깨지기 쉬운" 공급자에게 스무딩.
3. 5 GCRA (일반화 된 세포율 알고리즘)
이론적 도착 시간 (TAT) 모델:- 'TAT _ nether= max (TAT _ 전류, 현재) + 1/r', '현재 <= TAT _ current + burst/r' 인 경우 요청이 수락됩니다.
- 장점: 엄격하고 정확하며 작은 메모리 (TAT를 키별로 유지). 단점: 이해하기 어렵다.
언제: 엄격한 제어와 부드러움, 분산 한계가 필요합니다.
3. 6 경쟁 세마포어
능동 작동 카운터; 입장 - "티켓" 이있는 경우; 종료-해제.
언제: 장기 실행 작업, 스레드, 웹 소켓, 다운로드.
4) 키 모델 제한
키 = 속성 조합:- 'client _ id '/' api _ key '/' user _ id '/' org _ id'
- 'IP/ASN/geo' (거친 보호)
- '엔드 포인트/방법' (핫 루트)
- '스코프/플랜/티어' (수익 창출)
- 'deidempotency _ key' (쓰기 작업)
- 계층 구조 사용: 먼저 키당 엄격한, 조직 당, 그리고 글로벌.
5) 비용 모델
"비용" '비용 (q)' 을 정의하십시오
GraphQL: 필드 복잡도 × 깊이.
REST: 응답/요청 크기, 작업 유형 (읽기 = 1, 쓰기 = 3, 보고 = 10).
배치: 'cost = min (n, cap)'.
"요청" 이 아닌 토큰을 제한합니다: '예산- = 비용 (q)'.
6) 분산 구현
6. 금고 1 개
프로세스 중: 초고속이지만 일반적인 제한은 아닙니다 (로컬 "소프트" 한계에 적합).
Redis: 사실상 표준. INCR/EXPIRE, Lua 스크립트 (원자), 슬라이딩 창 용 ZSET, TTL이있는 키.
특사/NGINX/Kong/Traefik: 내장 필터; 주변에 편리합니다.
서비스 메시: 사이드카 + 글로벌 동기화에 대한 로컬 제한.
6. 2 원자와 경주
Redis의 Lua: 한 단계에서 확인 및 증가.
GCRA: CAS/스크립트로 하나의 TAT를 저장하십시오.
시계 일관성: NTP, 모노톤 타이머.
샤딩: 키별로 일관된 해시; "뜨거운" 파편을 피하십시오.
6. 3 지리 분포
지역 클러스터 + 상위 글로벌 (거친) 에 대한 로컬 제한.
CRDT/복제-조심 (지연, 이중 소비). 마진이있는 지역 제한이 바람직합니다.
7) 정책 및 우선 순위
계획: 다른 'r', 'b', 할당량을 가진 무료/프로/엔터프라이즈.
우선 순위: "비싼" 경로는 제한이 적거나 더 많은 비용이 듭니다.
목록: 통합 허용 목록, ASN/프록시/TOP 거부.
확대: 다시 초과하면 한계를 낮추고 작업 증명/captcha/챌린지를 입력하십시오.
8) 구성 요소의 예
8. 1 특사 (HTP 속도 제한 필터, 의사)
yaml rate_limit:
domain: public-api descriptors:
- key: api_key rate_limit:
unit: second requests_per_unit: 50 burst: 100
- key: api_key value: payments. write rate_limit:
unit: second requests_per_unit: 5 burst: 10
8. 2 NGINX (lua + Redis, pseudo)
nginx lua_shared_dict limits 10m;
location /api/ {
access_by_lua_block {
local key = ngx. var. arg_apikey.. ":".. ngx. var. request_method.. ":".. ngx. var. uri
-- token bucket in Redis (evalsha)
local allowed, retry_after = ratelimit_allow(key, 50, 100) -- r=50/s, b=100 if not allowed then ngx. header["Retry-After"] = retry_after return ngx. exit(429)
end
}
proxy_pass http://backend;
}
8. 3 경쟁 제한 (의사 코드)
pseudo on_request_start(key):
if redis. incr_with_ttl("sem:" + key, ttl=60) > MAX_CONCURRENCY:
redis. decr("sem:" + key); reject(429)
on_request_finish(key):
redis. decr("sem:" + key)
8. 4 GCRA (유사 코드)
pseudo params: r tokens/sec, burst b tat = redis. get(key) or now allowed_time = tat - (b / r)
if now < allowed_time: reject(429, retry_after = allowed_time - now)
tat_next = max(tat, now) + 1/r redis. set(key, tat_next, ttl = ceil(b/r) + safety)
9) 배송, 타임 아웃 및 회로 차단기와의 통합
재시도 예산: 배송 비율을 주요 트래픽의 X% 로 제한하십시오.
지터: 백오프시 항상 지터를 추가하십시오-동기 버스트를 줄입니다.
회로 차단기: 높은 오류 ('5xx', 타임 아웃) 가있는 경우 제한을 낮추거나 일부 경로를 "읽기 전용" 으로 전송하십시오.
헤징: 깔끔한; 예산을 두 배로 늘리지 않기 위해 비용을 고려하십
10) 관찰 및 관리
(PHP 3 = 3.0.6, PHP 4)
레이블: 한계 키, 영역, 엔드 포인트, 계획.
결정 로그 (샘플링): 실패 원인, 현재 카운터, 키 TTL.
대시 보드: 키/엔드 포인트 별 히트 카드, "핫" 클라이언트.
경고: 중요 경로에서 429> 2-5% 의 성장, 할당량의 빈번한 "고갈", 파편의 불균형.
11) 테스트 및 검증
정책의 계약 테스트 (if-ton tables).
로딩: 버스트 (r에서 x10), 긴 고원, "더러운" 패턴 (느린 POST, 긴 연결).
혼돈 트래픽: 고르지 않은 스트림, 시계 드리프트, Redis/mesh 드롭.
A/B 포함: 포함 전에 카나리아 롤아웃 한계, 섀도우 솔루션 (로그이지만 차단하지 않음).
12) 가장자리 케이스 및 미묘함
시계 왜곡: 클라이언트 헤더가 아닌 단일 소스 (서버) 에서 'now ()' 를 사용하십시오.
Idempotency-Key: 쓰기-retras의 증폭을 줄입니다.
배치 작업: 배치 크기와 총 비용을 제한합니다.
롱 폴링/웹 소켓: 채널/구독 수와 지속 시간을 제한합니다.
콜드 스타트: 카운터/프리로드의 "따뜻한" 시작; 그렇지 않으면 거짓 429의 버스트.
전산적으로 비싼 요청: 비즈니스 논리 실행 제한.
TTL: 키의 TTL 경계는 창 + 안전 마진을 덮어야합니다.
13) 안티 봇 에스컬레이션
단계: 경고 → 429 + '재시도 후' → 챌린지 (captcha/puzzle) → 임시 블록.
신호: 장치 지문, 커서/타이밍 동작, TOR/프록시/호스팅.
법의학에 대한 정책은 결정 론적이고 재현 가능해야합니다.
14) 안전 및 준수
중요한 경로 (쓰기/금융) 에서 기본적으로 거부합니다.
감사: 규제 사례 및 사건 검토 제한에 대한 결정을 유지하십시오.
PII: 한계 키가 로그에 개인 데이터를 공개해서는 안됩니다.
15) Prod 준비 점검표
- 한계 키 및 비용 모델이 정의됩니다.
- 선택된 알고리즘 (토큰 버킷/GCRA) 및 스토리지 (Redis/게이트웨이).
- 계층 고객 정책 + 글로벌 퓨즈.
- 장기 거래에 대한 경쟁 제한.
- 예산 재조정, 지터와의 백오프, 회로 차단기와의 통합.
- 대시 보드/경고, 샘플링 된 의사 결정 로그.
- 카나리아 온 및 섀도우 모드.
- 버스트 테스트, 긴 고원, Redis 실패, 시계 왜곡.
- 고객 문서: 429, 'Reduction-After' 코드, 지수 백오프 예제.
16) TL; DR
Redis/gateway와 함께 토큰 버킷 또는 GCRA 사용, 설계 제한 키 및 요청 비용, 장기 작업을위한 경쟁 세마포어 추가, 재 시도 예산 및 회로 차단기와 통합, 429 및 "버스트 용량" 모니터 및 카나리아/섀도우를 통해 제한 테스트