Kafka Consumer
Message Consumption
Kafka Tutorial
Apache Kafka
Programming Tips

How to close kafka consumer once all messages are consumed?

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Apache Kafka is a popular distributed messaging system that excels at handling large volumes of real-time data efficiently. Kafka consumers read records from Kafka topics, but knowing when to shut down a consumer, particularly after all messages are consumed, can be challenging due to Kafka's nature of continuous data streaming. Here, we detail a methodology to gracefully close a Kafka consumer when it has consumed all currently available messages in a topic.

Understanding Kafka's Consumption Model

Kafka stores records in topics that can be split across multiple partitions, which can be read by multiple consumers concurrently. Each consumer maintains its offset, which refers to its position in the log of messages. Typically, Kafka consumers run in an endless loop, continuously polling for new messages. This design makes it inherently difficult to identify when all messages are "consumed" because new messages can be produced to the topic at any time.

Strategies for Closing a Kafka Consumer

  1. Time-Based Approach: Use a timeout to conclude no more messages are available at the moment. This is not foolproof as this might terminate the consumer while messages are still being published.
  2. Message Count Approach: If the expected number of messages or a termination message is known, the consumer can shut down after consuming the desired count or recognizing a specific message indicating the end.
  3. External Control Mechanism: Utilizing an external flag controlled by another part of the application (or manual intervention) to signal when the consumer should close.
  4. Partition EOF (End of File) Checking: Kafka 0.10.1.0 introduced a method to check if a consumer has reached the end of the log. This helps in determining if all available messages at the time of the check have been consumed.

Programming a Consumer to Close

Here's a sample implementation using the Partition EOF method in Java. This approach assumes that your application can tolerate closing the consumer when it reaches the end of all partitions it is reading from, and there are no new records being produced for a small window of time.

java
1import org.apache.kafka.clients.consumer.KafkaConsumer;
2import org.apache.kafka.clients.consumer.ConsumerRecords;
3import org.apache.kafka.clients.consumer.ConsumerRecord;
4import java.util.Arrays;
5import java.util.Properties;
6
7public class SafeConsumerShutdown {
8    public static void main(String[] args) {
9        Properties props = new Properties();
10        props.put("bootstrap.servers", "localhost:9092");
11        props.put("group.id", "test-group");
12        props.put("enable.auto.commit", "false");
13        props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
14        props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
15
16        try (KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props)) {
17            consumer.subscribe(Arrays.asList("my-topic"));
18
19            final int minBatchSize = 200; // Define minimum number of messages to process
20            boolean shouldRun = true;
21
22            while (shouldRun) {
23                ConsumerRecords<String, String> records = consumer.poll(100);
24                for (ConsumerRecord<String, String> record : records) {
25                    System.out.printf("offset = %d, key = %s, value = %s%n", record.offset(), record.key(), record.value());
26                }
27
28                if (records.count() < minBatchSize) {
29                    shouldRun = false;
30                }
31            }
32        }
33        System.out.println("Consumer closed");
34    }
35}

Points of Consideration

When implementing a Kafka consumer shutdown logic, consider the following checklist to ensure data consistency and application stability:

ConsiderationDescription
Consumer Group StabilityEnsure that closing a consumer does not destabilize consumer groups or lead to rebalancing issues.
Data LossEnsure no data loss by validating that all messages are processed before shutdown.
At-least-once ProcessingConsider the delivery semantics (at-least-once, exactly-once) to handle message processing.
Handling RebalancesGracefully handle consumer rebalances which may occur on consumer group changes.

In conclusion, while Kafka does not natively support an easy way to determine if all messages have been consumed from a topic, combining some of the above strategies like polling for no more records and checking partitions against latest offsets can ensure a consumer can be closed down gracefully without loss of messages.


Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.