6

I am trying to read messages from my kafka using spring-kafka in my spring boot project. I am using @KafkaListener but the issue is that my consumer is running always. As soon as I produce a message from console, It pops up in my application. I want to poll at regular intervals. How can I achieve this?

@Service
public class KafkaReciever {

private static final Logger LOGGER =
        LoggerFactory.getLogger(KafkaReciever.class);

private CountDownLatch latch = new CountDownLatch(1);

public CountDownLatch getLatch() {
    return latch;
}

@KafkaListener(topics = "test")
public void receive(String payload) {
    LOGGER.info("received payload='{}'", payload);
    latch.countDown();
}

}

And here is my consumer config:

@Bean
public Map<String, Object> consumerConfigs() {
    Map<String, Object> props = new HashMap<>();

    // list of host:port pairs used for establishing the initial connections to the Kafka cluster
    props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
    props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
    props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);

    // allows a pool of processes to divide the work of consuming and processing records
    props.put(ConsumerConfig.GROUP_ID_CONFIG, "foo1");

    // automatically reset the offset to the earliest offset
    props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");

    return props;
}

@Bean
public ConsumerFactory<String, String> consumerFactory() {
    return new DefaultKafkaConsumerFactory<>(consumerConfigs());
}

@Bean
public KafkaListenerContainerFactory<ConcurrentMessageListenerContainer<String, String>> kafkaListenerContainerFactory() {
    ConcurrentKafkaListenerContainerFactory<String, String> factory =
            new ConcurrentKafkaListenerContainerFactory<>();
    factory.setConsumerFactory(consumerFactory());

    return factory;
}
thatman
  • 333
  • 3
  • 14

2 Answers2

6

That's the way it was designed; it's a message-driven container (and is consistent with other Spring messaging technology abstractions - RabbitMQ, JMS, etc).

To fetch messages only on-demand, you have 2 choices:

  • use the consumer factory to create a consumer, subscribe to (or assign) topics/partitions and call poll()
  • use spring-integration-kafka's KafkaMessageSource and call receive()

In both cases, if you are using kafka group management, you need to pay attention to the max.poll.interval.ms to avoid a rebalance.

You can use a spring integration inbound channel adapter to poll the message source on a regular basis.

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • use this article to get complete information about consumer https://learning.oreilly.com/library/view/kafka-the-definitive/9781491936153/ch04.html – Srikanth Janapati Sep 28 '20 at 06:55
2

From 2.3 version, a new property named idleBetweenPolls is added.

Starting with version 2.3, the ContainerProperties provides an idleBetweenPolls option to let the main loop in the listener container to sleep between KafkaConsumer.poll() calls. An actual sleep interval is selected as the minimum from the provided option and difference between the max.poll.interval.ms consumer config and the current records batch processing time.

This way you can add interval between consumer poll.

Source: https://docs.spring.io/spring-kafka/reference/html

Radix
  • 2,527
  • 1
  • 19
  • 43