11 KiB
title: company-tech-blog / Very Good Security (VGS) — Solving Kafka Rebalancing Issues: A Case Study source_type: company-tech-blog url: https://www.verygoodsecurity.com/blog/posts/solving-kafka-rebalancing-issues-a-case-study archive_url: related_branches: [feature-kafka-consumer-inbox-contract] related_projects: [ca-skeleton] tags: [company-tech-blog, ca-skeleton, messaging, kafka] created: 2026-07-28
Very Good Security (VGS) — Solving Kafka Rebalancing Issues: A Case Study
Layer:
raw/— 외부 자료(대기업 기술 블로그)의 원문 발췌·출처 기록. 이 자료는 회사 사례(company-case-study) 다. 공식 Kafka best practice 로 취급하지 않는다 (CLAUDE.md §5). VGS 사례의 규모(100 consumers / 100 partitions / 3-broker 단일 클러스터, aiokafka Python 클라이언트)는 ca-skeleton 의 전제와 다를 수 있다 —## Usage Boundaries참조.
Parent / 활용 branch
| Branch | 이 자료가 정당화하는 결정 |
|---|---|
| raw/branch-notes/feature-kafka-consumer-inbox-contract | ca-skeleton consumer 가 cooperative-sticky 파티션 할당 전략과 max.poll.* 튜닝을 병행 채택할지의 운영 사례 근거 — 잦은 rebalance 로 consumer 가 그룹에서 이탈하고 커밋이 실패하던 환경에서 두 조치를 적용한 결과 |
출처
- 원본 URL: https://www.verygoodsecurity.com/blog/posts/solving-kafka-rebalancing-issues-a-case-study
- 아카이브 URL: (미제공)
- 저자 / 조직: Ramin Ranjbar (Sr. Software Engineer), Jimit Patel (Staff Software Engineer) — Very Good Security (VGS)
- 발행일: 2025-06-11
- 마지막 확인일: 2026-07-28
왜 저장했는지
feature-kafka-consumer-inbox-contract 브랜치가 검토 중인 "cooperative-sticky assignor + max.poll.* 튜닝" 병행 채택의 실제 운영 사례를 확보하기 위해 저장. 잦은 rebalance 로 인한 CommitFailedError/RequestTimedOutError 증상, 적용한 구체적 config 값, CooperativeSticky 전환이 "incremental rebalancing"으로 서술되는 방식, 그리고 처리량 개선 수치를 원문으로 고정한다.
핵심 인용
[§Step 1: Diagnosing the Rebalancing Problem] "Consumers frequently dropped out with CommitFailedError and RequestTimedOutError on JoinGroupRequest_v2 to the group coordinator (broker 2)." (line 140)
[§Fix 3: Increase max_poll_interval and Reduce max_poll_records] "Increased max_poll_interval_ms from 300,000ms to 600,000ms and reduced max_poll_records from 10 to 5. This allows more time for processing and reduces the batch size." (line 234)
[§Step 3: Switching to Cooperative Sticky Assignor — Why use Cooperative Sticky?] "Incremental Rebalancing: Consumers only release partitions they no longer own, keeping others active." (line 250)
[§Results (throughput)] "Before tuning the setting, due to rebalancing issues, we only serviced 13 req/second and the rate is volatile as depicted below:" [...] "After tuning the parameters and applying the above lessons, we have 10x the rate, to 135 req/second, and the load is sustained (i.e. not volatile)." (line 304, 306)
[§Lessons Learned] "Use Cooperative Sticky for Large Groups: With 100 consumers, the Cooperative Sticky Assignor significantly reduces rebalancing overhead." (line 300)
Claims Extracted
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|---|---|---|---|---|---|
| VGS-REBAL-C1 | 100-consumer aiokafka 기반 consumer group 에서 consumer 가 CommitFailedError/RequestTimedOutError 로 반복 이탈하고 group coordinator(broker 2)에 rebalancing 부하가 집중되는 증상이 관측되었다 |
"Consumers frequently dropped out with CommitFailedError and RequestTimedOutError on JoinGroupRequest_v2 to the group coordinator (broker 2)." | company-case-study |
VGS app-worker-webhook (aiokafka, Python, Kafka 2.8.1, 100 consumers / 100 partitions / 3 brokers) 환경의 관측 사실 |
이 증상이 ca-skeleton 의 (아직 미정인) consumer 규모·클라이언트(Java/Spring-Kafka 추정)에서도 동일하게 재현된다는 것은 증명하지 않음 — 이 원인(coordinator 부하 집중)을 Kafka 공식 문서가 설명한다는 근거도 이 인용 자체엔 없음 |
| VGS-REBAL-C2 | VGS 는 max_poll_interval_ms 를 300,000ms→600,000ms 로 늘리고 max_poll_records 를 10→5 로 줄여 poll 간 처리 시간 여유를 늘리고 batch 크기를 줄였다 |
"Increased max_poll_interval_ms from 300,000ms to 600,000ms and reduced max_poll_records from 10 to 5. This allows more time for processing and reduces the batch size." | company-case-study |
VGS 자체 워크로드(개별 메시지 처리 시간이 길어 poll 간격을 늘려야 했던 상황)에서의 구체 튜닝 값 | 이 정확한 수치(600,000ms / 5 records)가 ca-skeleton 의 어떤 워크로드에도 올바른 기본값이라는 것은 증명하지 않음 — 값은 poll 당 처리 시간에 의존적이며 이 문서는 산정 공식을 제공하지 않음 |
| VGS-REBAL-C3 | Cooperative Sticky Assignor 는 (round-robin Eager 방식과 달리) consumer 가 더 이상 소유하지 않는 파티션만 반납하고 나머지 파티션은 계속 active 상태로 유지하는 incremental rebalancing 을 제공한다 | "Incremental Rebalancing: Consumers only release partitions they no longer own, keeping others active." | company-case-study |
Kafka 2.4.0+ / aiokafka 0.12.0+ 에서 사용 가능한 CooperativeStickyAssignor 의 일반 동작 서술 | 이 노트 안에는 Kafka 공식 문서(KIP-429 또는 Apache Kafka consumer configs reference) 인용이 없으므로, 이 메커니즘을 "공식 Kafka best practice"로 격상할 수 없다(CLAUDE.md §5) — 별도 official-doc 보강 필요 |
| VGS-REBAL-C4 | 설정 튜닝 + CooperativeSticky 전환 이후 app-worker-webhook 처리량이 불안정한 13 req/sec 에서 안정적인 135 req/sec(약 10배)으로 개선되었다 |
"Before tuning the setting, due to rebalancing issues, we only serviced 13 req/second and the rate is volatile" [...] "After tuning the parameters and applying the above lessons, we have 10x the rate, to 135 req/second, and the load is sustained (i.e. not volatile)." | company-case-study |
VGS 자체 관측 처리량(before/after) 비교 | CPU/메모리 사용량이 "relatively the same" 유지된 채 처리량만 늘었다는 것 외의 세부 비용(latency percentile 등)은 이 인용 범위 밖 — 다른 규모/클라이언트에서 동일 배율 개선이 재현된다는 것도 증명하지 않음 |
| VGS-REBAL-C5 | VGS 는 100 consumer 규모의 "large consumer group" 맥락에서 Cooperative Sticky 채택을 권고한다 | "Use Cooperative Sticky for Large Groups: With 100 consumers, the Cooperative Sticky Assignor significantly reduces rebalancing overhead." | company-case-study |
100 consumers / 100 partitions 규모 전제 | ca-skeleton 처럼 파티션·컨슈머 수가 훨씬 적은(수 개~수십 개) 소규모 배포에서도 동일한 효과 배율이 나타난다는 것은 증명하지 않음 — 이 사례의 개선은 대규모 coordinator 부하 집중 문제에서 기인하므로, 소규모에서는 문제 자체가 약할 수 있음 |
Usage Boundaries
- 이 자료가 직접 증명하는 것:
VGS-REBAL-C1: 대규모(100 consumer) aiokafka consumer group 에서 잦은 rebalance 로 인한CommitFailedError/RequestTimedOutError증상과 coordinator 부하 집중이라는 VGS 의 관측 사실VGS-REBAL-C2: VGS 가 실제 적용한max_poll_interval_ms/max_poll_records구체 값VGS-REBAL-C3: CooperativeSticky 가 "일부 파티션만 반납"하는 incremental rebalancing 이라는 VGS 의 서술VGS-REBAL-C4: 이 두 조치를 병행 적용한 뒤 VGS 가 관측한 처리량 개선 수치(13→135 req/sec)VGS-REBAL-C5: VGS 가 이 조합을 "large consumer group"이라는 조건부로 권고한다는 것
- 이 자료가 증명하지 않는 것 (중요 — ca-skeleton 적용 전 반드시 확인):
- "공식 Kafka best practice"라는 것. 이 문서는
company-case-study등급이며, Kafka 공식 문서(KIP-429, Apache Kafka consumer configs reference)의 보강 인용이 이 노트 안에 없다.VGS-REBAL-C3를 "Kafka 가 공식적으로 권장하는 방식"으로 서술하면 CLAUDE.md §5·§11 위반(공식 문서와 기술 블로그 혼동)이다. - 규모 전제 불일치. VGS 사례는 100 consumers / 100 partitions / 3-broker 단일 클러스터 기준이다. ca-skeleton 이 실제로 이 규모(수백 파티션/컨슈머)를 전제로 하는지는 이 자료로 증명되지 않는다 — 소규모 배포에서는 rebalance 부하 자체가 미미해 "10x 개선"이 재현되지 않을 수 있다.
- 클라이언트 불일치. 이 사례는 Python
aiokafka클라이언트(snake_case 설정 키max_poll_interval_ms등) 기준이다. ca-skeleton 이 Java/Spring-Kafka 스택이라면 설정 키 표기(max.poll.interval.msdot-notation)와 클라이언트 내부 구현(heartbeat thread 모델 등)이 다를 수 있어, 정확한 프로퍼티명·기본값은 별도 Apache Kafka 공식 consumer configs 문서로 재확인해야 한다. - CooperativeStickyAssignor 의 "incremental rebalancing" 메커니즘 자체의 공식 사양(KIP-429) 세부는 이 문서에 없다 — 이 문서는 결과적 효과만 서술한다.
- "공식 Kafka best practice"라는 것. 이 문서는
- 내 프로젝트에 적용하려면 추가 확인이 필요한 것:
- ca-skeleton 이 실제로 채택할 Kafka client(Spring Kafka 등)에서
partition.assignment.strategy=CooperativeStickyAssignor사용 시의 공식 문서(Apache Kafka / Spring Kafka reference) 대조 - ca-skeleton 의 예상 파티션·컨슈머 규모가 이 사례의 "large group" 전제에 해당하는지 확인
max.poll.interval.ms/max.poll.records기본값 산정 근거(개별 메시지 처리 시간 profiling) — 이 문서는 산정 공식을 제공하지 않음
- ca-skeleton 이 실제로 채택할 Kafka client(Spring Kafka 등)에서
메모
- 인용 6개(quote4 는 elided 결합) 전부 Self-Grep 통과. fabrication 없음.
- WebFetch 1차 호출 결과는 도구가 모델로 재처리한 요약이라(WebFetch 는 fetch 후 별도 모델이 프롬프트를 적용해 응답을 생성) 문구가 원문과 미세하게 다를 위험이 있었다 (예: 1차 응답은 "available in Kafka 2.4.0+ and aiokafka 0.12.0+" 로 뭉뚱그렸으나, 원문은 "available in Kafka 2.4.0+ and aiokafka 0.12.0 for completed implementation" 이다). 이 차이를 발견한 뒤
curl로 원본 HTML 을 직접 재수집(vgs-raw.html, HTTP 200)해 파이썬html.parser로 텍스트를 추출했고, 이 verbatim 텍스트를 self-grep 대조 기준으로 사용했다 — 인용은 모두 이 원본 대조본에서만 채택했다. - 발행일은 페이지 본문에 "June 11, 2025" 로 명시되어 있어
needs-confirmation없이 확정.
관련
- 인접 official-doc (consumer offset/commit 시맨틱): raw/official-docs/kafka-consumer-offset-commit-semantics-apache-javadoc
- 인접 official-doc (Spring Kafka listener container backpressure): raw/official-docs/spring-kafka-listener-container-pause-resume-backpressure
- 같은 branch 의 인접 company-tech-blog (retry topic + DLQ 사례): raw/company-tech-blogs/kafka-multi-tier-retry-topic-dlq-uber
- 이 자료를 인용한 wiki 요약: (생성 시 링크)