Kafka Listener
Dynamic Topics
Programming
Data Streaming
Software Development

How to pass topics dynamically to a kafka listener?

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, a distributed streaming platform, allows for building real-time data pipelines and streaming applications. A core feature of Kafka is its use of topics to categorize and manage messages efficiently. As developers, there may be scenarios where you need a Kafka consumer to dynamically subscribe to various topics based on runtime decisions or external configurations, rather than subscribing to a static list defined at startup. This capability is especially useful in multi-tenant environments, configurable systems, or applications that must adjust to changes in the data landscape dynamically.

Understanding the Basics

Before diving into how to handle dynamic topic subscriptions in Kafka listeners, let's clarify a few basic concepts:

  • Kafka Consumer: A consumer pulls data from Kafka topics. It subscribes to one or more Kafka topics and reads data from them.
  • Kafka Topic: A topic is a category or feed to which records are published. Topics in Kafka are multi-subscriber, and they can have zero or many consumers that subscribe to the data.

Implementing Dynamic Topic Subscriptions

In many Kafka clients, including popular ones in Java, Python, and more, consumers usually subscribe to topics as they initialize. Adjusting this to accommodate dynamic topics requires additional considerations.

1. Using Spring Kafka

In the Java world, Spring Kafka provides robust integration with the Apache Kafka ecosystem. Below is a practical example using Spring Kafka to dynamically adjust topic subscriptions.

Example Code:

java
1import org.springframework.beans.factory.annotation.Autowired;
2import org.springframework.kafka.annotation.KafkaListener;
3import org.springframework.kafka.config.KafkaListenerEndpointRegistry;
4import org.springframework.stereotype.Component;
5
6@Component
7public class DynamicKafkaConsumer {
8
9    @Autowired
10    private KafkaListenerEndpointRegistry registry;
11
12    // Method to add new topic at runtime
13    public void addTopic(String newTopic) {
14        KafkaListenerEndpoint endpoint = registry.getListenerContainer("myListenerId");
15        Collection<String> topics = new ArrayList<>(endpoint.getAssignedPartitions());
16        topics.add(newTopic);
17        endpoint.stop();
18        endpoint.simulateQueueDeclaration(topics);
19        endpoint.resume();
20    }
21
22    @KafkaListener(id = "myListenerId", topics = {"staticTopic1"})
23    public void listen(String message) {
24        System.out.println("Received: " + message);
25    }
26}

This code showcases a Spring component with a Kafka listener that starts listening to a predefined topic ("staticTopic1"). It includes a method (addTopic) to dynamically add new topics to the subscription list. The listener can be adjusted at runtime without needing to stop the entire application.

2. Poll Loop Management in Native Kafka Clients

When not using Spring or similar frameworks, you may manage the Kafka consumer directly. This involves a loop where you poll the server for new data. To subscribe to new topics dynamically, use the consumer API as shown below:

Example Code:

java
1Properties props = new Properties();
2props.put("bootstrap.servers", "localhost:9092");
3props.put("group.id", "test");
4props.put("enable.auto.commit", "true");
5props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
6props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
7
8try (KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props)) {
9    consumer.subscribe(Arrays.asList("initialTopic"));
10    while (true) {
11        ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
12        for (ConsumerRecord<String, String> record : records) {
13            System.out.println(record.value());
14        }
15        
16        // Add a condition to check for new topics to subscribe
17        if (newTopicsAvailable()) {
18            List<String> newTopics = fetchNewTopics();
19            List<String> currentTopics = new ArrayList<>(consumer.subscription());
20            currentTopics.addAll(newTopics);
21            consumer.subscribe(currentTopics); // re-subscribe with updated topic list
22        }
23    }
24}

This polling loop checks for new topics and updates the subscription dynamically. newTopicsAvailable() and fetchNewTopics() should be implemented according to your application's logic to obtain new topic names.

Summary

Here's a quick recap of key points discussed:

FeatureDescription
Static SubscriptionKafka listeners can subscribe to pre-defined static topics upon initialization.
Dynamic SubscriptionUsing mechanisms like Spring Kafka or the native Kafka API, listeners can subscribe to new topics dynamically at runtime.
ImplementationIn dynamic implementations, you must manage the consumer's subscription list carefully, especially considering synchronization and state consistency.

Conclusion

Dynamic subscription to topics in Kafka allows applications to be responsive and adaptive to changes in data requirements and system configurations. It flexibly adjusts to new business needs and data sources, making it a powerful feature for robust, scalable applications.


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