Search code examples
spring-rabbit

Spring RabbitMQ Concurrency: Channels vs. Consumers vs. Concurrency


I’m trying to wrap my head around these concepts (it’d also be nice to understand Listener and ListenerContainer) especially in regards to concurrency.

So a Connection is a physical TCP connection to the RabbitMQ server.

Because connections are expensive to open and close, the traffic is multiplexed using Channels. I'd initially thought this provides parallelism/multi-threading but it seems after some research that I'm wrong?

So now comes the concurrency parameter, specifically maxConcurrentConsumers which has a default of 1.

As I understand now, if I set this argument to 5 with a CachingConnectionFactory, it will auto scale between 1 and 5 consumers, and I will have 1-5 "instances" that will handle messages (assuming prefetch is 1). If I keep it at the default value, I will only have 1 single instance and I can only process 1 message at a time. Is that correct?

If so, then what is the purpose of (for example) setting an Executor with a ThreadPool of 25 when concurrency is 1? I will still only process only one message at a time, so what are the other 24 threads ever doing? Also, why would I ever need more than 2-3 channels if I only have 1 consumer?

There's also this old question that describes having 1 listener container and 10 listeners vs. 10 containers each with 1 listener, which is nicely answered but only adds to my confusion because it seems to add another way to achieve concurrency without the parameter itself?

Another thing Id love to understand is whether with a concurrency of 1, a new thread (and only one thread) is spawned for each new message, or is this thread reused? Because if it’s reused then it implies that things like threadLocal context should be reset manually.


Solution

  • I will still only process only one message at a time, so what are the other 24 threads ever doing?

    They would never be started.

    Also, why would I ever need more than 2-3 channels if I only have 1 consumer?

    You don't, generally; the cached channels are generally only used by producers. Container channels are long-lived and are never cached.

    It also depends on the container type; the SMLC has one dedicated thread per consumer; the amqp-client thread(s) hand the messages over to the container thread(s) via blocking queues.

    With the DMLC, the listener is invoked directly on the amqp-client's threads.

    See Choosing a Container for more information.