Spring Rabbit CachingConnectionFactory Thread Pool - spring-boot

I have around 10 different rabbit mq queues in 10 different virtual hosts to connect to. For each queue, a separate SimpleMessageListenerContainer bean is defined in my spring boot application and a separate Spring Integration flow is created using each specific SimpleMessageListenerContainer.
The concurrency for SimpleMessageListenerContainer is set to 1-3. Each of the SimpleMessageListenerContainer bean is using separate CachingConnectoryFacory beans. The Connection Factory mode is set as CHANNEL.
We also have another IntegrationFlow to publish messages to an outbound queue that is using a different connection factory. I am not setting any ThreadPool Task Executors in the ConnectionFactory, so it using the default one. While doing the Load test we are noticing that the multiple thread pool (prefixed with pool-) are getting crated and after a certain point application crashes may due to the high number of threads.
It looks like the default thread pool executor is having max value of Integer unbounded which may spinning up threads based on the demand. I tried setting custom Thread Pool task executors for each connection factory and I noticed that the threads are not growing like previously but from the java profiler it shows the SimpleMessageListenerContainer threads are getting BLOCKED frequently.
I want to know if there any best practices or to be followed while setting the custom thread pool task executors in the connection factory like a ratio between Lisneter threads and connection factory threads etc?

I have done some debugging; ...-1 gets renamed to, for example AMQP Connection 127.0.0.1:5672.
That thread is not from the pool, but it is created by the same thread factory.
Similarly, the scheduled executor (for heartbeats) uses the same thread factory, and gets ...-2.
Hence the pool starts at ...-3. So indeed, you have a fixed pool of 8 threads, an I/O thread, and a heartbeat thread for each factory.
With a large number of factories like that, you probably don't need so many threads; I would suggest a single pooled executor with sufficient threads to satisfy your workload; experimentation is probably the only way to determine the number, but I would guess it's something less than 88 (11x8).

Related

Running RabbitMQ consumer in different thread after consuming message

I need to know about the processing of consumed message(thread flow) via Spring SimpleMessageListenerContainer
I have following understanding
1) Messages consumed via consumer threads. (you can define the consumer thread pools via task executors).
2) the same consumer thread who receives the message process it and gets blocked until it does not finish the execution of handler method.
3) meanwhile other consumer threads gets created to consume the other messages and process those message. The interval to create those consumer threads is based on setStartConsumerMinInterval settings.
Please let me know if I am correct?
The next part is
I want to separate the consuming of message and processing of message in different threads(differnt pools for consuming and processing) how we can do that?
I have tried this way, I have made the handle message of handler as #Async to run it in different threads. Is it a correct way or any better way is available?
The last part is
in my Spring boot application I am both publishing and consuming messages, and I am using a single connection factory(CachingConnectionFactory). Should I use 2 connections factories 1 for publishing and other for consuming? and pass respecctive connection factory to the publishing and consuming beans?

Spring Integration: Message Driven Channel Adapter

As per the documentation int-jms:message-driven-channel-adapter uses SimpleAsyncTaskExecutor
SimpleAsyncTaskExecutor doesn't reuse threads and creates a new thread for each task. In case of message-driven-channel-adapter what is the definition of a task?
In case of message driven channel Adapter the task is a constantly polling loop. So, this is going to be a long- living resource which keeps thread active. Therefore we don’t care too much about source of threads. See Spring JMS for more information.

Spring JMS messaging with JmsListener - how it scales?

I'm trying to use Spring JMS messaging with #JmsListener in a scalable way, but I'm not seeing it happening. I have a ConnectionFactory bean that returns a factory that connects to an Oracle Advanced Queue through JMS and a database DataSource pool.
The problem starts as every #JmsListener receiver connects again to JMS (and hence to the database pool). My understand is that I can have many #JmsListener methods, one for each service, but in this way it's doing I'm very limited.
The shared connection is turned on, but since each #JmsListener creates a different DefaultMessageListenerContainer, each one have a database connection.
If I also want the services to handle messages concurrently and set container.setConcurrency("3-5"), then it opens 3 * numberOfListeners connections.
If I use container.setCacheLevel(DefaultMessageListenerContainer.CACHE_NONE) then from each second every listener container connects and disconnects from the JMS/database.
I want something that connects one time (or more, if there is concurrent jobs to process) to JMS/database, not to connect count-of-listener times nor to connect-disconnect at each second for every listener.
You can use a SingleConnectionFactory to wrap the vendor factory and all containers will use the same connection.

Spring RabbitMQ Connection and Resource Management Issues

I need to consume messages from Rabbit HA cluster via HAProxy so I switched to CacheMode.CONNECTION as it is recommended in spring-amqp-documentation. Moreover I need to consume messages from many queues so I create for each queue SimpleMessageListenerContainer with 4 concurrent consumers and I have few questions:
After few tests it looks that my approach is not efficient because each time when a new queue is added also new SimpleMessageListenerContainer is created with 4 threads. So I could set more queues for the given SimpleMessageListenerContainer what looks more efficient but maybe there is another better way?
Why when I have switched to CacheMode.CONNECTION for each consumer in SimpleMessageListenerContainer is created new connection? Can I set in some way one connection for all consumers in a given SimpleMessageListenerContainer or maybe it is not recommended?
How to handle exception
"org.springframework.amqp.rabbit.connection.AutoRecoverConnectionNotCurrentlyOpenException:
Auto recovery connection is not currently open"
I received it when one RabbitMQ node is down. Even when node is up again SimpleMessageListenerContainer cannot reconnect.
Thanks in advance for help.
The upcoming 2.0 release has a new DirectMessageListenerContainer that shares threads across containers documentation here.
The 2.0.0.M4 milestone is available now; the GA release is expected to be mid July.
If you want a single connection per container use the default cache mode and a separate connection factory for each container.
Disable the client's connection factory auto recovery mechanism; it is enabled by default in the 4.x client; Spring AMQP has its own recovery mechanism that will generally recover faster. Since version 1.7.1 Spring AMQP disables it by default, unless you configure your own Rabbit ConnectionFactory.

DefaultMessageListenerContainer and ActiveMQ thread management

I've done some tests with ActiveMQ and Spring JMS. I've configured DefaultMessageListenerContainer (DMLC) with WorkManagerTaskExecutor and CommonJ to manage the threads. I want to have control over the threads are running in the server.
I have made the decision of using DMLC based on a post written by Juergen Holler in Spring's forum: http://forum.spring.io/forum/other-spring-related/remoting/24208-what-s-the-best-practice-for-using-jms-in-spring?p=256420#post256420
In this post, he says "DMLC is the only listener container that does not impose the thread management onto the JMS provider, that is, does not use/block JMS provider threads." So I thought that all the threads would be managed by the server and there wouldn't be threads of ActiveMQ.
However, analysing the server's threads using JConsole, I've seen some threads of ActiveMQ that I didn't expect.
As you can see in the image, there are ActimeMQ threads (inactivity threads, transport threads, etc).
When I'm executing the tests, I see in the logs that the JMS messages are processed by CommonJ threads and not by ActiveMQ threads, so that's fine. However, I don't understand why are ActiveMQ threads are created if they are not used. Specially "ActiveMQ Transport" threads because for every queue I use I've got one thread "ActiveMQ Transport". Therefore if I'm consuming 50 queues, I've got 50 threads of "ActiveMQ Transport". Is it to keep the socket opened? Are these threads mandatory?
Details about the configuration:
ConnectionFactory used: org.apache.activemq.ActiveMQConnectionFactory
ActiveMQ version: 5.11.1
Transport protocol: TCP
Using DefaultMessageListenerContainer the client is in a loop invoking MessageConsumer.receive() method.
It seems a silly question and surely I've misunderstood some basic concepts.
Thanks to Rob Davies' explanation in this thread http://activemq.2283324.n4.nabble.com/ActimeMQ-Client-s-thread-management-td4705885.html, I've understood that all the interaction with ActiveMQ require a TCP thread per connection.
However, the amount of transport threads can be minimised replacing ActiveMQConnectionFactory with one of these ConnectionFactories:
PooledConnectionFactory (ActiveMQ)
SingleConnectionFactory (spring-jms)
CachingConnectionFactory (spring-jms)

Resources