Search code examples
springspring-amqpspring-rabbitspring-messaging

Which component is creating null-consumerMonitor-# threads?


Recently we started to test the Direct Container Factory in one of our microservices, the main motivation to change container factory is we want to reduce the thread number that process messages from queues.

Usually, when this microservice boots using the Simple Container Factory, we see a thread group called "pool-1-thread-#" which is the pool used by Rabbit consumers. Now that we have changed to Direct Container Factory, we see two thread groups called "pool-1-thread-#" and "null-consumerMonitor-#".

We have been playing with application and listeners configuration but we haven't been able to remove this "problem". This is our configuration, could it have a problem?

enter image description here

This is one of our listeners:

enter image description here

Also we are using the RabbitListenerConfigurer to configure a AfterReceivePostProcessor to factory, but we think it shouldn't provoque this behavior.

Could this be a bug? We weren't expecting that two thread groups were created and the "null" in the name either.


Solution

  • These threads are used to monitor the consumers (e.g. retrying after failures, handle queue changes etc).

    The name's a bug (https://github.com/spring-projects/spring-amqp/issues/1433); we should be using getListenerId() (which falls back to getBeanName()) instead of getBeanName() - containers created for the annotation are not beans.

    https://github.com/spring-projects/spring-amqp/blob/909ba571bb096ed8acf77fed43e944f7b8ebb471/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/listener/DirectMessageListenerContainer.java#L394

    Use this as a work around...

    @SpringBootApplication
    public class So71468360Application {
    
        public static void main(String[] args) {
            SpringApplication.run(So71468360Application.class, args);
        }
    
        @RabbitListener(id = "myListener", queues = "foo")
        void listen(String in ) {
    
        }
    
    }
    
    @Configuration
    class Fixer {
    
        Fixer(AbstractRabbitListenerContainerFactory<?> factory) {
            factory.setContainerCustomizer(container -> container.setBeanName(container.getListenerId()));
        }
    
    }
    

    Or, use setTaskScheduler() on the factory to use a shared scheduler across multiple containers.