Files
llm-wiki/raw/company-tech-blogs/kafka-consumer-rebalance-cooperative-sticky-verygoodsecurity.md

87 lines
11 KiB
Markdown

---
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.ms` dot-notation)와 클라이언트 내부 구현(heartbeat thread 모델 등)이 다를 수 있어, 정확한 프로퍼티명·기본값은 별도 Apache Kafka 공식 consumer configs 문서로 재확인해야 한다.
- CooperativeStickyAssignor 의 "incremental rebalancing" 메커니즘 자체의 공식 사양(KIP-429) 세부는 이 문서에 없다 — 이 문서는 결과적 효과만 서술한다.
- 내 프로젝트에 적용하려면 추가 확인이 필요한 것:
- 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) — 이 문서는 산정 공식을 제공하지 않음
## 메모
- 인용 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 요약: (생성 시 링크)