Search code examples
javaspring-bootapache-kafkaspring-kafkamicrometer

Spring-Kafka with Micrometer throws NullPointerException during app shutdown


We have spring-boot app with multiple nodes, and use KafkaTemplate for producing kafka messages. On classpath we have both org.springframework.kafka:spring-kafka and io.micrometer:micrometer-core. In our case, messages produced continuously, around a few thousand per second per topic (topics with multiple partitions). During app graceful shutdown (either during redeployment or automatic downscaling) we frequently have NPE errors:

[kafka-producer-network-thread | producer-1] ERROR org.apache.kafka.clients.producer.internals.ProducerBatch - Error executing user-provided callback on message for topic-partition 'xxx-1'
java.lang.NullPointerException
    at io.micrometer.core.instrument.Timer$Sample.stop(Timer.java:280)
    at org.springframework.kafka.support.micrometer.MicrometerHolder.success(MicrometerHolder.java:93)
    at org.springframework.kafka.core.KafkaTemplate.lambda$buildCallback$4(KafkaTemplate.java:587)
    at org.springframework.kafka.core.DefaultKafkaProducerFactory$CloseSafeProducer$1.onCompletion(DefaultKafkaProducerFactory.java:764)
    at org.apache.kafka.clients.producer.KafkaProducer$InterceptorCallback.onCompletion(KafkaProducer.java:1348)
    at org.apache.kafka.clients.producer.internals.ProducerBatch.completeFutureAndFireCallbacks(ProducerBatch.java:227)
    at org.apache.kafka.clients.producer.internals.ProducerBatch.done(ProducerBatch.java:196)
    at org.apache.kafka.clients.producer.internals.Sender.completeBatch(Sender.java:707)
    at org.apache.kafka.clients.producer.internals.Sender.completeBatch(Sender.java:688)
    at org.apache.kafka.clients.producer.internals.Sender.handleProduceResponse(Sender.java:596)
    at org.apache.kafka.clients.producer.internals.Sender.access$100(Sender.java:74)
    at org.apache.kafka.clients.producer.internals.Sender$1.onComplete(Sender.java:798)
    at org.apache.kafka.clients.ClientResponse.onComplete(ClientResponse.java:109)
    at org.apache.kafka.clients.NetworkClient.completeResponses(NetworkClient.java:569)
    at org.apache.kafka.clients.NetworkClient.poll(NetworkClient.java:561)
    at org.apache.kafka.clients.producer.internals.Sender.runOnce(Sender.java:335)
    at org.apache.kafka.clients.producer.internals.Sender.run(Sender.java:244)
    at java.base/java.lang.Thread.run(Thread.java:834)

I checked implementation of class org.springframework.kafka.support.micrometer.MicrometerHolder, and see, that it happens only if destroy method invoked earlier than success. So it seems here we have a race condition. I guess success method implementation should somehow handle cases when destroy method already invoked. Is it a bug of spring-kafka?

spring-kafka version 2.5.1; micrometer-core version 1.5.1.


Solution

  • if was a bug Spring-Kafka with Micrometer throws NullPointerException during app shutdown #1531 in version 2.5.1. since spring-kafka version 2.6.0 issue is fixed.

    meanwhile, if you don't need to have micrometer metrics for KafkaTemplate, we could disable it:

    kafkaTemplate.setMicrometerEnabled(false);