DefaultMessageListenerContainer and ActiveMQ thread management - spring

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)

Related

Spring Rabbit CachingConnectionFactory Thread Pool

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).

Performance issues with ActiveMQ Artemis and Spring JmsTemplate

While doing some load tests with the ActiveMQ Artemis broker and my Spring Boot application I am getting into performance issues.
What I am doing is, sending e.g. 12,000 messages per second to the broker with JMSeter and the application receives them and saves them to a DB. That works fine. But when I extend my application by a filter mechanism, which forwards events after saving to DB, back to the broker using jmsTemplate.send(destination, messageCreator) it goes very slow.
I first used ActiveMQ 5.x and there this mechanism works fine. There you could configure the ActiveMQConnectionFactory with setAsyncSend(true) to tune performance. For the ActiveMQ Artemis ConnectionFactory implementation there is no such a possibility. Is there another way to tune performance like in ActiveMQ 5.x?
I am using Apache ActiveMQ Artemis 2.16.0 (but also tried 2.15.0), artemis-jms-client 2.6.4, and Spring Boot 1.5.16.RELEASE.
The first thing to note is that you need to be very careful when using Spring's JmsTemplate to send messages as it employs a well-known anti-pattern that can really kill performance. It will actually create a new JMS connection, session, and producer for every message it sends. I recommend you use a connection pool like this one which is based on the ActiveMQ 5.x connection pool implementation but now supports JMS 2. For additional details about the danger of using JmsTemplate see the ActiveMQ documentation. This is also discussed in an article from Pivotal (i.e. the "owners" of Spring).
The second point here is that you can tune if persistent JMS messages are sent synchronously or not using the blockOnDurableSend URL property, e.g.:
tcp://localhost:61616?blockOnDurableSend=false
This will ensure that persistent JMS messages are sent asynchronously. This is discussed further in the ActiveMQ Artemis documentation.

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.

Pooled Connection Factory for ActiveMQ Artemis

Is there an equivalent to the ActiveMQ 5 PooledConnectionFactory for Artemis? Why is it available in one and not the other?
Spring, for example, offers a generic CachingConnectionFactory. This is great, but it implements the SingleConnectionFactory and only "pools" one connection.
It would be key to have a similar mechanism in the Artemis client that actually pooled greater than one connections.
Another thought is that maybe it's not implemented because a single connection supports concurrent sessions! I haven't tested the performance of a using a new connection per session. Is the performance the same or similar?
The PooledConnectionFactory in the ActiveMQ 5.x code-base is generic and can actually be used with ActiveMQ Artemis so there was no reason to port it into the Artemis code-base. That said, the JMS connection pool implementation has been pulled out of the ActiveMQ 5.x code-base, cleaned up, modified to support JMS 2, and made available here.
I'm not clear on what you mean by "concurrent sessions." Do you mean that the connection supports concurrently creating session or that the sessions themselves support concurrent use? The former is supported, but the latter is not.
In terms of performance, you'd have to benchmark your specific use-case. There are too many variables to simply say one is better than the other.

How to configure OpenMQ to not store all in-flight messages in memory?

I've load testing different JMS implementations for our notification service.
No one of ActiveMQ, HornetQ and OpenMQ behave as expected (issues with reliability and message prioritization). But as now I've best results with OpenMQ. Expect two issues that's probably just missconfiguration (I hope). One with JDBC storage
Test scenario:
2 producers with one queue send messages with different priority. 1 consumer consuming from queue with constant speed that is slightly lower than producers produce. OpenMQ is running standalone and uses PostgreSQL as persistence storage. All messages are sended and consumed from Apache Camel route and it's all persistent.
Issues:
After about 50000 messages I see warnings and errors in OpenMQ log about low memory (default cinfiguration with 256Mb Heap size). Producing is throutled by broker and after some time broker stop dispatching at all. Broker JVM memory usage is on maximum.
How I must configure broker to achieve that goal:
Broker do not depend on queue size (up to 1 000 000 msgs) and on memory limit. Performance is not issue - only reliability.
Thats possible?
I can not help with OpenMQ but perhaps with Camel and ActiveMQ. What issues do you face with ActiveMQ? Can you post your camel route and eventually spring context and the activemq config?

Resources