메시지 전달 스로틀링
메시지 전달 스로틀링 (Message Dispatch Throttling)
큰 메시지 페이로드가 쌓이면 메모리 사용량이 치솟아 성능이 떨어질 수 있어요. Pulsar는 메시지 전달(dispatch)에 속도 제한(rate-limit) 스로틀링 메커니즘을 적용해 트래픽 급증을 막고 메시지 전달성을 높여줘요. 이 글에서는 스로틀링이 무엇이고 왜 필요한지, 어떤 수준과 방식으로 설정하는지, 그리고 설정할 때 알아야 할 한계까지 정리해 드릴게요.
출처: 문서
본문
개요
메시지 전달 스로틀링이란 무엇인가요?
큰 메시지 페이로드는 메모리 사용량 급증을 일으켜 성능 저하로 이어질 수 있어요. Pulsar는 메시지 전달에 속도 제한 스로틀링 메커니즘을 채택해 트래픽 급증을 피하고 메시지 전달성을 높여요. 클라이언트에 전달할 수 있는 메시지 수와 엔트리의 바이트 크기를 제한하는 임계값을 설정할 수 있고, 단위 시간당 트래픽이 임계값을 초과하면 이후 전달을 차단해요.
예를 들어 전달 속도 제한을 초당 10개 메시지로 구성하면, 클라이언트에 초당 전달할 수 있는 메시지 수는 최대 10개예요.
왜 메시지 전달 스로틀링을 사용하나요?
메시지 전달 스로틀링은 자세히 보면 다음과 같은 이점을 제공해요:
- BookKeeper에 대한 브로커의 읽기 요청 부하 제한 메시지는 BookKeeper 클러스터에 영구 저장돼요. 캐시된 데이터로 많은 읽기 요청을 처리할 수 없으면 BookKeeper 클러스터가 응답하기에 너무 바빠질 수 있고, 브로커의 I/O나 CPU 리소스가 완전히 점유될 수 있어요. 메시지 전달 스로틀링 기능으로 데이터 흐름을 조절해 BookKeeper에 대한 브로커의 읽기 요청 부하를 제한할 수 있어요.
- 토픽/구독 수준에서 브로커 하드웨어 리소스 할당 균형화 브로커 인스턴스는 여러 토픽을 동시에 서비스해요. 토픽 하나가 요청으로 과부하되면 브로커의 I/O, CPU, 메모리 리소스를 거의 모두 소비해 다른 토픽을 읽지 못하게 할 수 있어요. 메시지 전달 스로틀링 기능으로 브로커 하드웨어 리소스가 토픽 간에 어떻게 할당되는지를 제한할 수 있어요.
- 토픽/구독 수준에서 클라이언트 하드웨어 리소스 할당 제한 소비할 백로그 메시지가 많으면 클라이언트가 짧은 시간에 많은 데이터를 받아 자신의 컴퓨팅 리소스를 독점할 수 있어요. 클라이언트에는 소비 속도를 능동적으로 제한하는 메커니즘이 없으므로, 메시지 전달 스로틀링 기능이 클라이언트 하드웨어 리소스의 할당도 조절할 수 있어요.
메시지 전달 스로틀링은 어떻게 동작하나요?
메시지 전달 스로틀링 과정은 다음 단계로 나눌 수 있어요:
- 브로커가 남은 할당량(quota)을 계산해 bookies에서 읽을 엔트리 수를 근사해요.
- 브로커가 bookies에서 메시지를 읽어요.
- 브로커가 클라이언트에 메시지를 전달하고 카운터를 갱신해 할당량을 줄여요. 예약된 작업이 스로틀링 주기가 끝나면 할당량을 새로 고쳐요.
참고
- 브로커는 데이터를 읽기 전까지 엔트리당 실제 메시지 수나 실제 엔트리 크기를 알 수 없으므로, 3단계 전에는 할당량을 줄일 수 없어요.
- seek이나 redeliver 같은 작업은 메시지를 클라이언트에 여러 번 전달할 수 있어요. 브로커는 이를 서로 다른 메시지로 계산해 카운터를 갱신해요.
개념
스로틀링 수준
스로틀 메시지 전달은 서로 다른 수준에서 설정할 수 있어요.
| 수준 | 설명 |
|---|---|
| 브로커별 (Per broker) | 단일 브로커의 모든 구독이 할당량을 공유해요. |
| 토픽별 (Per topic) | 같은 토픽의 모든 구독이 할당량을 공유해요. 비파티션 토픽이라면 할당량은 토픽이 단위 시간당 전달할 수 있는 최대 메시지 수와 같아요. 토픽에 여러 파티션이 있으면 할당량은 각 파티션이 단위 시간당 전달할 수 있는 최대 메시지 수를 의미해요. 즉 파티션 토픽의 실제 전달 속도 제한은 설정한 값의 N배가 돼요 (N은 토픽 안의 파티션 수). 예를 들어 토픽 t0에 두 개의 파티션이 있어요. 할당량을 10/s로 설정하면 t0-p0과 t0-p1의 속도 제한이 각각 10/s가 되고, t0의 전체 속도 제한은 20/s가 돼요. 할당량은 파티션 간에는 공유할 수 없지만, 파티션 안의 구독 간에는 공유할 수 있다는 점에 유의하세요. |
| 구독별 (Per subscription) | 비파티션 토픽이라면 속도 제한은 구독이 단위 시간당 클라이언트에 전달할 수 있는 최대 메시지 수를 의미해요. 구독 중인 토픽에 여러 파티션이 있으면 속도 제한은 구독이 단위 시간당 파티션별로 전달할 수 있는 최대 메시지 수를 의미해요. 즉 파티션 토픽에 대한 구독의 실제 전달 속도 제한은 설정한 값의 N배가 돼요 (N은 토픽 안의 파티션 수). 예를 들어 토픽 t1에 두 개의 파티션이 있고 구독 s1이 있어요. 속도 제한을 10/s로 설정하면 t1-p0과 t1-p1에서 s1의 속도 제한이 각각 10/s가 되고, s1의 전체 속도 제한은 20/s가 돼요. |
참고 여러 수준에서 구성된 전달 속도 제한은 동시에 적용돼요 (논리적 AND).
스로틀링 방식
다양한 수준에서 전달 속도 제한을 구성하기 위해 여러 스로틀링 방식을 사용할 수 있어요.
| 방식 | 클러스터별 | 토픽별 | 구독별 |
|---|---|---|---|
| 브로커 구성 또는 동적 브로커 구성 설정 | dispatchThrottlingRateInMsg``dispatchThrottlingRateInByte |
dispatchThrottlingRatePerTopicInMsg``dispatchThrottlingRatePerTopicInByte 클러스터의 모든 토픽에 적용돼요. |
dispatchThrottlingRatePerSubscriptionInMsg``dispatchThrottlingRatePerSubscriptionInByte 클러스터의 모든 구독에 적용돼요. |
| 네임스페이스 정책 설정 | N/A | 토픽 전달 스로틀링 구성 참조 | 구독 전달 스로틀링 구성 참조 |
| 토픽 정책 설정 | N/A | 토픽 수준 전달 속도 설정 참조 | 구독 수준 전달 속도 설정 참조. 토픽의 모든 구독에 적용돼요. |
참고 위 세 가지 방식을 통해 구성된 전달 속도 제한은 우선순위가 적용돼요. "토픽 정책" > "네임스페이스 정책" > "브로커 구성" 순서예요. 예를 들어 세 가지 방식을 모두 사용해 구독 전달 속도 제한을 구성했다면, "토픽 정책"으로 구성한 것만 적용돼요.
스로틀링 구성
다음 표는 conf/broker.conf 파일에서 메시지 전달 스로틀링에 대해 구성할 수 있는 파라미터를 정리한 거예요.
| 파라미터 | 설명 | 기본값 |
|---|---|---|
| dispatchThrottlingRateInMsg | 스로틀링 주기당 클러스터별로 전달할 수 있는 총 메시지 수예요. 토픽 수준이나 구독 수준을 설정하려면 dispatchThrottlingRatePerTopicInMsg 또는 dispatchThrottlingRatePerSubscriptionInMsg를 구성하세요. |
'-1', 제한 없음을 의미해요. |
| dispatchThrottlingRateInByte | 스로틀링 주기당 클러스터별로 전달할 수 있는 총 바이트 크기예요. 토픽 수준이나 구독 수준을 설정하려면 dispatchThrottlingRatePerTopicInByte 또는 dispatchThrottlingRatePerSubscriptionInByte를 구성하세요. |
'-1', 제한 없음을 의미해요. |
| ratePeriodInSecond | 전달 스로틀링 기간(초)이에요. 카운터는 주기가 끝날 때 초기화돼요. 예를 들어 속도 제한을 분당 10,000개 메시지로 구성하려면 ratePeriodInSecond를 60으로, dispatchThrottlingRateInMsg를 10,000으로 설정해야 해요. |
1 (초) |
| preciseDispatcherFlowControl | 전달 스로틀링에 정밀한 제어를 적용할지 여부예요. 기본적으로 비활성화되어 있으며, 이 경우 브로커는 남은 consumer.receiverQueueSize(기본 1000)와 dispatcherMaxReadBatchSize(기본 100) 중 최솟값을 사용해 bookies에서 읽을 메시지 수를 근사해요. true로 설정하면 브로커는 다음 방정식으로 bookies에서 읽을 엔트리 수를 근사해요: bookies에서 읽을 엔트리 수 = 읽을 메시지 수 / 엔트리당 평균 메시지 수. 예를 들어 속도 제한을 10/s로 설정했다고 해볼게요. 엔트리당 평균 메시지 수가 6이면 브로커가 초당 2개 엔트리를 읽는다는 뜻이고, 읽을 총 메시지 수가 할당량을 초과해요. 하지만 false로 설정하면 브로커가 10개 엔트리(약 60개 메시지)를 읽어 할당량을 훨씬 더 많이 초과해요. |
false |
| dispatchThrottlingOnBatchMessageEnabled | 메시지를 엔트리(배치) 단위로 계산할지 여부예요. 기본적으로 비활성화되어 있어요. true로 설정하면 총 메시지 수의 근사값이 부정확해질 수 있지만, bookies에 대한 안정적인 읽기 요청을 유지하면서 Pulsar의 처리량을 최대화할 수 있다는 점에 유의하세요. 예를 들어 속도 제한을 10/s로 설정했다고 해볼게요. dispatchThrottlingOnBatchMessageEnabled를 true로 설정하면 엔트리당 메시지 수와 무관하게 브로커는 초당 10개 엔트리만 읽어 클라이언트에 전달해요. |
false |
| dispatchThrottlingOnNonBacklogConsumerEnabled | 비백로그 소비자에 대한 전달 스로틀링을 활성화할지 여부예요. 기본적으로 활성화되어 있어요. false로 설정하면: 한 구독의 모든 소비자에게 백로그가 없으면 dispatchThrottlingRateInMsg와 dispatchThrottlingRateInByte가 구성되어 있어도 메시지 전달 스로틀링이 자동으로 꺼져요. 소비자 중 하나라도 백로그가 있으면 스로틀링이 자동으로 켜져요. |
true |
참고
- dispatchThrottlingRateInMsg와 dispatchThrottlingRateInByte를 동시에 사용할 수 있어요 (논리적 AND).
- preciseDispatcherFlowControl와 dispatchThrottlingOnBatchMessageEnabled는 상호 배타적이므로 한 번에 하나만 활성화해야 해요. 두 파라미터 모두 초과 전달 문제(한계 참조)를 개선하는 데 사용할 수 있어요. 차이점은: preciseDispatcherFlowControl가 활성화되면 Pulsar가 엔트리당 메시지 수를 고려해요. 이 파라미터는 브로커가 bookies에서 엔트리를 읽을 때 적용돼요. dispatchThrottlingOnBatchMessageEnabled가 활성화되면 Pulsar가 엔트리당 메시지 수를 무시해요. 이 파라미터는 브로커가 클라이언트에 메시지를 보낸 후 카운터를 갱신할 때 적용돼요.
메시지 전달 스로틀링의 한계
메시지 전달 스로틀링은 다음과 같은 이유로 단위 시간당 메시지가 초과 전달될 수 있어요:
- 브로커가 스로틀링 한도보다 더 많은 엔트리나 바이트를 bookies에서 읽을 수 있어요.
a) 클라이언트에 전달되는 메시지의 바이트 크기가 구성된 임계값을 초과할 수 있어요. 바이트/스로틀링-주기로 전달 속도 제한(
dispatchThrottlingRateInByte/ratePeriodInSecond)을 설정하면, 브로커는 다음 방정식으로 한 스로틀링 주기 안의bookies에서 읽을 엔트리 수를 계산해요:bookies에서 읽을 엔트리 수 = 읽을 총 바이트 크기 / 엔트리당 평균 바이트 크기.bookies에서 읽을 엔트리 수를 제어함으로써 브로커는 각 스로틀링 주기 안에읽을 총 바이트 크기를전달 속도아래로 제한하려 해요. 브로커는엔트리단위로 bookies에서 메시지를 읽으며, 읽기 전에는 각 엔트리의 정확한 바이트 크기를 모르므로 다음에 읽을 엔트리의 바이트를 근사해요. 브로커는 엔트리당 평균 바이트 크기를 얻기 위해 다음 두 지표를 사용해요:- 평균 게시 크기(
brk_ml_EntrySizeBuckets): 브로커가 게시 요청을 받았을 때 bookies에 저장된 엔트리당 평균 바이트 크기예요. - 평균 전달 크기(
entriesReadSize/entriesReadCount): bookies에서 읽은 엔트리당 평균 바이트 크기, 즉 클라이언트에 보낸 엔트리당 평균 바이트 크기예요. 브로커는 평균 전달 크기보다 평균 게시 크기를 우선 사용해요. 평균 게시 크기를 사용할 수 없으면 평균 전달 크기를 사용해요. 두 지표 모두 사용할 수 없으면 브로커는 첫 시도에서 엔트리 하나만 읽어요. b) 클라이언트에 전달되는 메시지 수가 구성된 임계값을 초과할 수 있어요. 메시지 수/스로틀링-주기로 전달 속도 제한(dispatchThrottlingRateInMsg/ratePeriodInSecond)을 설정하고 배칭(batch-send)이 활성화되면, 브로커는 엔트리를 하나의 메시지로 계산하고(엔트리당 메시지 수와 무관하게) 다음 방정식으로bookies에서 읽을 엔트리 수를 계산해요:bookies에서 읽을 엔트리 수 = 읽을 총 메시지 수 / 엔트리당 평균 메시지 수 (=1). 엔트리당 메시지가 여러 개이므로 클라이언트에 전달되는 메시지 수는 항상 구성된 임계값을 초과하거나 같아요. 해결 방법preciseDispatcherFlowControl또는dispatchThrottlingOnBatchMessageEnabled를 구성하면 초과 전달 문제를 완화할 수 있어요. 예를 들어preciseDispatcherFlowControl를 켜면 근사된 엔트리당 평균 메시지 수로 할당량을 미리 감소시켜 이 한계를 완화할 수 있어요. 자세한 내용은 스로틀링 구성을 보세요.
- 평균 게시 크기(
- 동시 스로틀링 프로세스가 할당량을 제때 줄이지 못할 수 있어요. 동작 방식에서 소개한 대로 전달 스로틀링 과정은
1.남은 할당량 얻기→2.데이터 로드→3.할당량 감소예요. 같은 구독에서 "재생 메시지 전달(process-R)"과 "비재생 메시지 전달(process-N)"이라는 두 프로세스가 동시에 실행되면, 그 스로틀링 과정이 다음 순서로 서로 엮일 수 있어요:- process-R:
1. 남은 할당량 얻기 - process-R:
2. 데이터 로드 - process-N:
1. 남은 할당량 얻기 - process-N:
2. 데이터 로드 - process-R:
3. 할당량 감소 - process-N:
3. 할당량 감소결과적으로 전달된 총 메시지 수가 할당량을 초과할 수 있어요.
참고 초과 전달이 발생해 현재 주기의 전달 메시지 수가 할당량을 초과하면 다음 주기의 할당량은 그만큼 줄어요. 예를 들어 속도 제한이
10/s로 설정되어 있는데 첫 주기에11개 메시지가 클라이언트에 전달되면, 다음 주기에는 최대9개 메시지만 전달할 수 있어요. 마지막 주기에 30개 메시지가 전달됐다면 다음 두 주기의 전달 메시지 수는0이에요. - process-R:
더 알아보기 (Learn more)
- 브로커 관리 API — 동적 브로커 구성으로 스로틀링 설정을 바꿔 보세요.
- 네임스페이스 관리 — 토픽·구독 전달 스로틀링 정책을 네임스페이스 수준에서 구성해요.
- 메시징 개념 — 파티션 토픽과 배칭의 기본 개념을 익혀요.