Six consumers on two partitions under a consumer group, a share group with the default share.acquire.mode and a share group with record_limit; the three acknowledgement types and a record that is released until Kafka stops redelivering it; a new share group starting at latest; the ordering a share group gives up; and Spring Kafka's share containers in implicit and manual acknowledgement modes. Tests run against a real broker (scripts/broker-up.sh) and write output/. Co-Authored-By: Claude Sonnet 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Lm655hdgDo5xsSLNomgdsy
60 lines
3.2 KiB
Markdown
60 lines
3.2 KiB
Markdown
# share-groups
|
|
|
|
Companion code for *Queues for Kafka: Share Groups with Spring for Apache Kafka 4* on
|
|
[ankurm.com](https://ankurm.com/kafka-share-groups-spring-kafka-4-queues-for-kafka/).
|
|
|
|
What a Kafka **share group** (KIP-932) does differently from a consumer group, measured against a
|
|
real broker: how many consumers can share one partition, what the three acknowledgement types do to a
|
|
record, why a new share group sees nothing, and what ordering you give up. The same ideas are then run
|
|
through Spring Kafka's share containers.
|
|
|
|
## Versions
|
|
|
|
| Artifact | Version |
|
|
|---|---|
|
|
| Spring Boot | 4.1.1 (GA; `4.2.0-M2` is a milestone) |
|
|
| Spring Kafka | 4.1.1, managed by the Boot BOM (share consumer support is already in this GA release) |
|
|
| kafka-clients | 4.2.1, managed by the Boot BOM |
|
|
| Kafka broker | 4.3.1, started by `scripts/broker-up.sh` (`share.version` is finalized at level 1 by default; no feature flag was set) |
|
|
| JDK | 25 (LTS) |
|
|
|
|
## Quickstart
|
|
|
|
```
|
|
scripts/broker-up.sh # downloads Kafka 4.3.1 (checksum-verified), starts KRaft on localhost:9092
|
|
scripts/run-all.sh # runs every test and rewrites output/*.txt
|
|
scripts/broker-down.sh
|
|
```
|
|
|
|
The tests do not start a broker themselves. Use `-Dbroker=host:port` if yours is elsewhere. Each test
|
|
creates its own uniquely named topic and group, so reruns never see earlier records.
|
|
|
|
## What each test is
|
|
|
|
| Test | Role |
|
|
|---|---|
|
|
| `WorkSpreadTest` | 6 consumers, a 2-partition topic, 60 records at 50 ms each: consumer group, share group with the default `share.acquire.mode`, and share group with `record_limit` |
|
|
| `AckTypesTest` | ACCEPT, RELEASE and REJECT through the raw `KafkaShareConsumer`, including a record that is released every time |
|
|
| `OffsetResetTest` | A new share group starts at the latest offset; `share.auto.offset.reset=earliest` is a group config set through the Admin API |
|
|
| `OrderingTest` | One key, one partition, three consumers of different speed: arrival order is not produce order |
|
|
| `SpringShareListenerTest` | `ShareKafkaListenerContainerFactory` in implicit and manual acknowledgement modes with `@KafkaListener` |
|
|
|
|
`ShareConfig` is the hand-written configuration: Spring Boot 4.1.1 has no auto-configuration for share
|
|
consumers.
|
|
|
|
## Captured output (`output/`)
|
|
|
|
| File | What it captures |
|
|
|---|---|
|
|
| `01-work-spread.txt` | Which of six consumers received records under each of the three setups, with indicative timings |
|
|
| `02-ack-types.txt` | Every delivery of four records: accepted, released once, rejected, released until Kafka stops redelivering |
|
|
| `03-share-group-starts-at-latest.txt` | 3 records produced first: 0 received by default, 3 received after switching the group to earliest |
|
|
| `04-no-ordering-guarantee.txt` | The order 40 same-key records were processed in, and the number of out-of-order neighbours |
|
|
| `05-spring-share-listeners.txt` | Listener threads under implicit mode, and per-record release, reject and acknowledge under manual mode |
|
|
|
|
Timings and the exact split of records between consumers differ from run to run. The shape of each
|
|
result is stable; the milliseconds are not.
|
|
|
|
No `docs/` chapter directory in this repository -- the intermediate and reference-depth material is in
|
|
accordion sections inside the WordPress post.
|