4.12 Standalone consumer — `assign()` instead of `subscribe()`
When: "Sometimes you know you have a single consumer that always needs to read data from all the partitions in a topic, or from a specific partition in a topic. In this case, there is no reason for groups or rebalances — just assign the consumer-specific topic and/or partitions, consume messages, and commit offsets on occasion."
⚠️ "although you still need to configure
group.idto commit offsets — without callingsubscribe, the consumer won't join any group."
A consumer can EITHER subscribe() to topics (and be part of a consumer group) OR assign() itself partitions — BUT NOT BOTH at the same time.
Duration timeout = Duration.ofMillis(100);
List<PartitionInfo> partitionInfos = null;
partitionInfos = consumer.partitionsFor("topic"); // ① ask the cluster
if (partitionInfos != null) {
for (PartitionInfo partition : partitionInfos)
partitions.add(new TopicPartition(partition.topic(),
partition.partition()));
consumer.assign(partitions); // ② assign, don't subscribe
while (true) {
ConsumerRecords<String, String> records = consumer.poll(timeout);
for (ConsumerRecord<String, String> record: records) {
/* process */
}
consumer.commitSync();
}
}⚠️ "Keep in mind that if someone adds new partitions to the topic, the consumer will NOT be notified. You will need to handle this by checking
consumer.partitionsFor()periodically, or simply by bouncing the application whenever partitions are added."*
Trade-off summary:
subscribe() + group | assign() standalone |
|---|---|
| ✓ automatic rebalancing | ✓ NO rebalances ever (deterministic) |
| ✓ automatic failover | ✓ full control over which partitions |
| ✓ horizontal scaling | ✗ NO failover — if it dies, nothing reads |
| ✗ rebalance pauses | ✗ NO notification of new partitions |
| ✗ assignment not in your control | ✗ you scale it yourself |