- 처리율 제한 장치는 클라이언트로부터
유입 되는 요청 수를 조절하는 장치
이다 (임의의 요청 임계치에 도달하면 요청을 drop하는 것과 같은 후속 조치를 취할 수 있도록 한다) - 예시
- 사용자는 초당 2번 이상의 로그인 요청을 할 수 없다
- 사용자는 1분에 30개 이상의 댓글을 작성할 수 없다
- 장점
- DOS 공격에 의한
자원 고갈을 방지
할 수 있다 - 써드파티 api 요청으로 읺나 과금과 관련 된 요청의 수를 제한하면,
비용 절감의 효과
를 얻을 수 있다 서버의 과부하를 막을 수 있다
- DOS 공격에 의한
1단계 - 문제 이해 및 설계 범위 설정
클라이언트 측
에서 제한 해야 할까? 혹은서버 측
에서 제어 해야 할까?제한의 기준
은 무엇인가? IP? ID?시스템의 규모
는 어느정도여야 하나?? (요청 수는 얼마나 수용이 가능해야 하는가?)처리율 제한 장치는
분산 환경에서도 동작
해야 하는가?독립된 서비스
로 존재해야 하는가? 혹은어플리케이션의 코드에 포함
되어도 되는가?요구사항 요약
처리 응답 시간을 최소화
해야 한다- 처리 임계치에 도달했을 때 들어온 요청은 드랍하면 안된다.
후속 조치
가 있어야 한다 --> 서버측에서 드랍한다면, 클라이언트에게 적절한 후속 조치를 유도해야한다 (응답 헤더, 응답 코드 등등) - 처리율 제어를 클라이언트 사이드에서 하는 것은 서버측에서 하는 것보다 변수가 많으므로
서버측에서 제어
하도록 한다- 클라이언트는
위변조가 쉽다
. 따라서 모든 클라이언트의 구현을 통제하는 것은 어려울 수 있다
- 클라이언트는
- 처리율 제어를 하는 궁극적인 목적은 서버측에 걸리는 부하를 예상 가능한 범위로 제한하여
최대의 가용성을 유지
하는 것이라고 생각한다- 따라서 서버에서
감당 가능한 부하 범위
와, 실제DAU
와 같은지표를 분석
하는 것이 중요하다 - 처리율 제어 장치가
Peak
에도 감당이 가능하도록 설계되어야 할까?
- 따라서 서버에서
분산 환경
에서도 처리율 제어가 가능해야 한다- 결함이 발생하더라도
전체 시스템에 영향을 주어서는 안된다
- 요청이 제한되었을 때는
사용자에게 메세지를 분명하게 전달
해야 한다 (클라이언트의 요청이므로, 정상 응답을 받을 수 없는 이유를 요청자가 명확하게 알 수 있도록 해야한다) 시스템 자원 사용을 최소화
해야 한다 (메모리, CPU 등)
2단계 - 개략적인 설계안 제시 및 동의 구하기
처리율 제어 장치를 서버 사이드에 둘 경우
API gateway
를 사용할 경우 gateway에서 설정으로 제어가 가능하다- 설정으로 제어한 임계치를 넘었을 경우
429 응답
(too many request)을 클라이언트에게 돌려준다
- 설정으로 제어한 임계치를 넘었을 경우
처리율 제어 장치 고려 사항
- 프로그래밍
언어
,캐시 서비스
등 현재 사용중인기술 스택을 점검
하라. - 나에게 맞는
처리율 제어 알고리즘을 선택
하라 - 내 설계가 gateway를 이용하고 있는
마이크로서비스 환경
이라면 해당기능은 gateway에 포함
시켜야 할 수도 있다 - 처리율 제어 장치를 구현할 인력이 부족하다면
상용 api gateway
를 사용하는 것도 나쁘지 않은대안
이 될 수 있다
- 프로그래밍
처리율 제한 알고리즘
토큰 버킷
- 토큰을 보관하는 버킷이 있다
- 주기적으로 토큰을 버킷에 리필한다
- 토큰 버킷에 토큰이 꽉 차잇으면, 리필한 토큰은 그대로 버려진다 (overflow)
- 요청이 들어오면 토큰 버킷을 확인하고, 유휴 토큰이 있으면 해당 토큰을 들고 요청을 수행한다
- 요청이 들어오면 토큰 버킷을 확인하고, 유휴 토큰이 없으면 해당 패킷은 drop 된다
- 장점
- 구현이 쉽다
메모리 측면에서 효율적
이다- 토큰 버킷에 유휴 토큰이 존재하면 서버에 요청이 전달되기에,
짧은 시간에 몰리는 트래픽 대응이 가능
하다
- 단점
- 버킷 크기와 토큰 공급률 값을 튜닝하는 것이 까다로운 일이 될 수 있다
누출 버킷
- 버킷을 Queue로 표현한다
- 요청이 들어오면 버킷(Queue)가 꽉 찼는지 확인한다
- 버킷이 꽉 찼으면 요청을 drop한다
- 버킷(Queue)이 가득 차지 않았으면 요청을 Queue에 넣고 FIFO 처리한다
- 처리율 이라는 인자를 사용한다
- 지정된 시간에 얼마나 요청을 처리할 것인지 정의한다
- 장점
Queue의 크기가 지정
되어 있어메모리 사용량 측면에서 효율적
이다고정된 처리율
을 갖고 있기에안정적인 처리
가 필요할 경우 적합하다
- 단점
- 요청이 몰릴 때, Queue가 가득차면
최신 요청들이 drop
될 수 있다 버킷 크기
와처리율
이라는 인자를 사용하는데, 해당 인자들을 튜닝하기 까다로울 수 있다
- 요청이 몰릴 때, Queue가 가득차면
- 고정 윈도 카운터
- 타임라인을 고정된 윈도우(간격) 으로 나누고 요청이 올때마다 count를 증가시킨다
- count가 임계치에 돋라하면 해당 윈도우에 들어온 이후 요청은 모두 drop된다
- 윈도우 간의 경계에서 트래픽이 몰릴 수 있다
- 1분 윈도우, count 제한 5인 경우
- 0분 59초 ~ 1분 1초 사이에 10개의 트래픽이 올 경우
- 2초 동안 10개의 트래픽을 수용해야 한다
- 원래 예상대로라면 2분 동안 10개의 요청을 수용해야 한다 (평균적으로 12초에 1개의 요청!)
- 장점
메모리 효율이 좋다
- 이해하기 쉽다
- 윈도우가 닫히는 시점에 count를 초기화 하는 방식은 특정한 트래픽 패턴을 처리하기에 용이하다
- 단점
- 윈도우 경계 부분에서 트래픽이 몰릴 경우,
예상한 트래픽 처리량보다 많은 트래픽을 처리해야할 수도 있다
- 윈도우 경계 부분에서 트래픽이 몰릴 경우,
- 이동 윈도 로그
- 고정 윈도 카운터 알고리즘과 베이스는 같다
- 단 윈도우 범위가 동적이라는 것이 차이점이다
- 타임스탬프 로그를 기록한다
- 예시
- 1분 윈도우, count 제한 2인 경우
- 0:01, 0:30 에 요청이 들어온다 = 허용 (로그 기록)
- 0:31에 요청이 들어온다 = 타임스탬프 로그 기록 후 drop (이미 2개의 count가 존재)
- 1:31에 요청이 들어온다 => 0:01, 0:30의 로그는 이미 만료된 값이므로 로그를 삭제하고 요청을 허용한다. + 로그 기록
- 장점
- 윈도우를 바라보는
시점에 관게없이
동일한 처리율
을 보여준다
- 윈도우를 바라보는
- 단점
- 거부 된 요청의
타임스탬프 정보도 기록
하기 때문에,메모리 자원을 많이 소모
한다
- 거부 된 요청의
- 이동 윈도 카운터
- 고정 윈도 카운터 + 이동 윈도 로그 알고리즘의 혼합 형태
- 1분 윈도우일 때, 현재 count 처리 식
- 이전 윈도 요청 수 + 현재 윈도 요청수 * 직전 1분이 겹치는 비율
- 직전 1분이 겹치는 비율은 최초 윈도 로그가 찍힌 시점으로부터 1분으로 계산한다
- 이전 윈도 요청 수 + 현재 윈도 요청수 * 직전 1분이 겹치는 비율
- 장점
- 평균 처리율에 따라 현재 윈도의 상태를 계산하므로,
비교적 짧은 시간에 몰리는 트래픽 대응이 원활
하다 메모리 효율
이 좋다
- 평균 처리율에 따라 현재 윈도의 상태를 계산하므로,
- 단점
- 다소
느슨
할 수 있다
- 다소
개략적인 아키텍쳐 구상
카운터는 어떻게 구현하는 것이 바람직할까??
- 메모리 캐시 서비스를 이용해볼까?
- 메모리에서 동작하기에
성능도 빠르고
,캐시 만료 정책
을 포함하고 있기에 선택에 적합해 보인다- 상황
- api 요청이 들어온다
- 어플리케이션은 redis에서 count 값을 조회한 뒤 요청을 수락할 수 있는 상태인지 판단한다
- 요청 수락이 가능한 상태면 count 값을 증가시켜 다시 redis에 넣고 요청을 진행한다
- 요청 수락이 불가능한 상태이면 요청을 drop 한다
- 상황
- 메모리에서 동작하기에
- 메모리 캐시 서비스를 이용해볼까?
처리율 한도 초과 트래픽의 처리
- HTTP 429 응답 (too many request)을 이용하자
- 한도에 걸린 트래픽은 드랍하지 않고 Queue에 보관하여 처리가 가능할 때 처리한다
처리율 한도 초과 응답 헤더
- X-Ratelimit-Remaining : 처리 가능 counter 수
- X-Ratelimit-Limit : 전체 counter 수
- X-Ratelimit-Retry-after : 한도 제한에 걸리지 않기 위해 몇 초 뒤에 요청을 다시 보내야 하는지 알림
이 모든 과정은 처리율 제한 미들웨어 (api gateway) 에서 이뤄짐을 전제한다
분산 환경에서의 처리율 미들웨어 구현
- 경쟁 조건
- 락(Lock) 으로 해결 가능하지만 성능 저하 이슈로 추천하지 않는다
- 대안
- 루아 스크립트
- 정렬 집합
- 대안
- 락(Lock) 으로 해결 가능하지만 성능 저하 이슈로 추천하지 않는다
- 동기화
- 웹 계층은 무상태 계층이므로, 한 클라이언트의 연속적인 요청이 각기 다른 api 서버로 유입될 수 있다
- 따라서 Redis와 같은 중앙 집중형 저장소를 사용하는 것을 추천한다
- 성능 최적화
- 사용자의 트래픽을 가장 가까운 엣지 서버로 전달할 수 있게 만들어, 지연시간을 최소화한다
- 제한 장치 간에 데이터를 동기화 할 때,
최종 일관성 모델
을 적용한다
- 모니터링
- 처리율 제한 장치 도입 이후, 모니터링을 통해 현재 설정한 정책과 같은 항목들이 올바르게 측정되었는지 재검토 해본다
- 처리 규칙이 느슨한가?
- 혹은 처리 규칙이 너무 빡빡한가?
- 피크 시간에도 대응이 가능한가?
- 처리율 제한 장치 도입 이후, 모니터링을 통해 현재 설정한 정책과 같은 항목들이 올바르게 측정되었는지 재검토 해본다
처리율 제한을 회피하는 중요한 방법
클라이언트 캐시
를 이용하여api 호출을 최소화
한다처리율 제한 임계치
를 클라이언트와 서버모두 이해
하고, 규칙에 맞게메세지 발생과 처리를 설계
한다- 에러에는
에러 메세지를 반드시 포함
하여, 클라이언트가 처리 제한 상황 이후에대응할 수 있도록 유도
한다 요청 재시도
할 경우,충분한 시간
을 갖고 요청을 시도할 수 있도록 한다 (충분한back-off
시간)
반응형
'개발 > 대규모 시스템 설계' 카테고리의 다른 글
6. Key - Value Storage 설계 (0) | 2023.03.19 |
---|---|
5. 안정 해시 설계 (2) | 2023.03.12 |
3. 시스템 설계 interview (0) | 2023.02.26 |
2. 개략적인 규모 추정 (0) | 2023.02.19 |
1. 사용자 수에 따른 규모 확장성 (0) | 2023.02.12 |
댓글