activemq slow consumers block producer although producerFlowControl is false - jms

I have activemq used in my system and what i see is the following message:
TopicSubscription: consumer=...: Pending message cursor [org.apache.activemq.broker.region.cursors.VMPendingMessageCursor#1684f89c] is full, temp usage (0%) or memory usage (100%) limit reached, blocking message add() pending the release of resources.
This is because if i understand correct my consumer is slow while my producer is fast. The result out of it is that eventually my producer is blocked untill consumer reads the message and frees some memory. What i whant is that my producer is not blocked and also when memory is full old messages are being discurded.
Given my understanding of what i have read the following configuration should do the trick (messageEvictionStrategy, pendingMessageLimitStrategy) but it is not working for me and i cannot figure out why.
I have specified low memoryusage limit low (35Mb) to make issue apear faster for testing reasons, but the case is that i need it eventually when the problem apears for activemq to just drop old messages.
I have found one non satisfactory solution of setting in ActiveMQConnectionFactory useAsyncSend=true and specifying sendTimeout. This makes producer not blocked but in this way the newest message is dropped and not the olderst one.
Finally, i am talking for non durable topics.
Any help guys would pe perfect. Below i have activemq configuration
<destinationPolicy>
<policyMap>
<policyEntries>
<policyEntry topic=">" producerFlowControl="false" memoryLimit="35 Mb">
<pendingSubscriberPolicy>
<vmCursor />
</pendingSubscriberPolicy>
<messageEvictionStrategy>
<oldestMessageEvictionStrategy/>
</messageEvictionStrategy>
<pendingMessageLimitStrategy>
<constantPendingMessageLimitStrategy limit="10"/>
</pendingMessageLimitStrategy>
</policyEntry>
</policyEntries>
</policyMap>
</destinationPolicy>
<systemUsage>
<systemUsage sendFailIfNoSpace="true">
<memoryUsage>
<memoryUsage limit="35 mb"/>
</memoryUsage>
<storeUsage>
<storeUsage limit="1 gb"/>
</storeUsage>
<tempUsage>
<tempUsage limit="5000 mb"/>
</tempUsage>
</systemUsage>
</systemUsage>
activemq version 5.7.0
i use spring template to send messages:
<bean class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="pooledJmsConnectionFactory"/>
<property name="timeToLive" value="100"/>
</bean>
I transmit javax.jms.ObjectMessage, relativelly small in size.
I found the problem in customer premisses I have many toppics in my application but managed to reproduce it loccally sending from 1 thread, non-stop messages continiusly always to the same topic. The message send was just a small string.
I have only one producer and problem seems to appear when i have 1 (or more) slow consumer(s) -but one slow consumer is enough-. if no slow consumer exists, problem does not appear.
I do not think it makes any difference but i use
<transportConnectors>
<transportConnector name="openwire" uri="nio://0.0.0.0:33029?wireFormat.maxInactivityDuration=60000&wireFormat.maxInactivityDurationInitalDelay=60000"/>
</transportConnectors>

How can I recreate this? How many producers/consumers are attached to this topic? Is it only one topic?
Your settings look okay, but you don't need to set memoryLimit=35mb on the policy. It kinda doesn't make sense to set it the same as the overall system usage. The idea is that memory limit for all topics combined would equal the system memory limit. So for example, if you have two topics, each would use 35MB (2 * 35 == 70MB) and that would exceed the overall system memory settings. I don't think this is the specific cause of what you're seeing, but something to keep in mind.
Also what version of ActiveMQ is this? If you have some tests already written that can produce this, let me know.

It turns out that when using JmsTemplate in order to have asynchronous sent and then messages that cannot be delivered we need to enable explicitQosEnabled and set deliveryMode=1 (non persistent).
Also on client side, the consumer needs to have a smaller prefetch limit
server
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="pooledJmsConnectionFactory"/>
<property name="explicitQosEnabled" value="true"/>
<property name="deliveryMode" value="1"/>
</bean>
client
<jms:listener-container .. prefetch="1000">
...
</jms:listener-container>
dont ask me why... but this seems to have solved my problem.
Basically non 100% needed but if someone can explain this to me would be perfect

Related

Spring Message Listener - Connection Refresh

We have implemented a message listener with spring and the container configurations looks like below
<bean id="customContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="concurrentConsumers" value="${jms.customContainer.concurrentconsumers}" />
<property name="maxConcurrentConsumers" value="${jms.customContainer.maxconcurrentconsumers}" />
<property name="errorHandler" ref="errorHandler" />
<property name="connectionFactory" ref="jmsQueueConnectionFactory" />
<property name="destination" ref="listenerQueue" />
<property name="messageListener" ref="customContainerListener" />
<property name="receiveTimeout" value="1" />
<property name="sessionTransacted" value="true" />
<property name="transactionManager" ref="txManager" />
</bean>
Its deployed in Jboss and the server log shows the below connection refresh message frequently.
org.springframework.jms.listener.DefaultMessageListenerContainer] (customContainer-3849) Successfully refreshed JMS Connection
It's been reported a high MSU/MIPS utilization at mainframe side where the WebSphere MQ is hosted. Could this be a reason to cause frequent MQ GET calls and increase in utilization?
We haven't specified the message Reply To explicitly, will this be causing a reply to attempt to queue every time? Also the receive timeout is set to 1 ms, does that mean it will be actively polling the queue in every 1 ms? Could someone please explain the concept?
The DefaultMessageListenerContainer implements polling of the queue. This means that it issues a GET with a wait of the receiveTimeout. If you have a receiveTimeout of 1ms, that means that every GET call will return after 1ms if no message is on the queue and another GET call will be made. This would appear to the queue manager as back to back GET calls.
Two options:
You can increase receiveTimeout to a higher number which will cause get with wait of the specified value, for example, get with wait of 60000 ms would only do a get every 1 minute or after a message hits the queue. You still get messages off the queue as soon as they are PUT to the queue.
A slightly more efficient option if possible is to switch to the SimpleMessageListenerContainer which will use a native JMS async listener. For IBM MQ this is implemented with the MQ callback functionality. This means the listener registers the callback to the queue manager and the queue manager notifies the listener when new messages land on the queue, so there is no polling.
Please see https://marketaylor.synology.me/?p=668
Note that the 'contributions' to the CPU consumption - which ultimately impacts the MSU charges are driven by several things that should be controlled. The two biggest are:
The number of connects to/disconnects from the z/OS queue manager. These verbs are the most costly in terms of CPU use in MQ, and should be used judiciously on z/OS because of the cost model. A client application written to connect once and do many MQ actions is going to impact the CPU consumption, but that tends to be predictable and is as they say 'a cost of doing business.' A client application that connects, opens a queue, puts or gets a single message, then disconnects many, many times will drive up costs quickly ( we have seen instances of a 40% uplift in MSU charges in a single month). The latter is called a poorly behaved application.
The use of Temporary Dynamic queues. TD queues require a significant amount of overhead within the queue manager, as the queue infrastructure has to be built up for each new definition and then torn down when the queue is closed. This overhead can be avoided by using statically defined queues and retrieving messages via the correlation ID or message ID.
Note that while both these issues are not unique to MQ on z/OS it is the licensing/charging model that makes all the difference.
Good luck!

Handle out of sync point issue via IBM JMS from Mule

I am connecting MQ-8.x from Mule via JMS and recently I had faced an issue that seems like MQ write operation is going out of sync point range and due to this and also the huge inbound load, MQ went in to deadlock state.
<spring:bean id="ConnectionFactory" class="com.ibm.mq.jms.MQConnectionFactory" name="ConnectionFactory">
<spring:property name="hostName" value="xxxx" />
<spring:property name="port" value="xxxx"/>
<spring:property name="queueManager" value="xxxx"/>
<spring:property name="transportType" value="1"/>
<spring:property name="channel" value="xxxx"/>
</spring:bean>
<jms:connector name="JmsConsumer" username="xxxx" password="xxxx" specification="1.1" connectionFactory-ref="ConnectionFactory" numberOfConsumers="1" validateConnections="true" persistentDelivery="true" doc:name="JMS"/>
<jms:outbound-endpoint queue="xxxx" connector-ref="JmsConsumer" doc:name="Audits"/>
My operation volume will be move but its just a PUT operation, so I am really not sure whether XA or other Transaction manager to be needed in this.
This has been handled in MQ-9.x version that MQ itself will manage the out of sync point implicitly. MQ-9.x upgrade will be the solution for this kind of issue.
https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_9.0.0/com.ibm.mq.dev.doc/q026865_.html
This message is produced because persistent messages are being produced out side of a transaction. MQ is highly optimized to process transactional persistent messages and this warning is informing us that the queue isn't being processed as efficiently as possible. The system will receive a significant performance improvement if you make the actions inside a transaction/syncpoint or if non persistent is good enough turn the persistent flag off.

Spring integration JMS dropping random messages during reading?

I have a production application that seems to be losing messages intermittently. One example that I have identified is the sending system logs 3 messages that are sent milliseconds apart. The receiving system logs that it got message 1 and message 3...but not message 2. The queue's depth is 0. I see no errors in the logs of the application that reads the messages to indicate something bad happened.
I have verified that there are no other "rogue" clients creating a race condition for reading messages.
Here is my configuration; we have a primary and secondary/failover queue...
<bean id="primaryProficiencyInboundQueue" class="com.ibm.mq.jms.MQQueue">
<property name="baseQueueManagerName" value="${lsm.primary.outbound.manager}"/>
<property name="baseQueueName" value="${lsm.proficiency.inbound.queue}"/>
</bean>
<bean id="secondaryProficiencyInboundQueue" class="com.ibm.mq.jms.MQQueue">
<property name="baseQueueManagerName" value="${lsm.secondary.outbound.manager}"/>
<property name="baseQueueName" value="${lsm.proficiency.inbound.queue}"/>
</bean>
<int:channel id="inboundProficiencyChannel">
<int:interceptors>
<int:wire-tap channel="logger" />
</int:interceptors>
</int:channel>
<!-- adapter that connects the inbound proficiency queues to the inboundProficiencyChannel -->
<jms:message-driven-channel-adapter id="primaryProficiencyInboundAdapter"
connection-factory="primaryConnectionFactory"
destination="primaryProficiencyInboundQueue"
channel="inboundProficiencyChannel" />
<jms:message-driven-channel-adapter id="secondaryProficiencyInboundAdapter"
connection-factory="secondaryConnectionFactory"
destination="secondaryProficiencyInboundQueue"
channel="inboundProficiencyChannel" />
<int:service-activator id="proficiencyInboundActivator"
input-channel="inboundProficiencyChannel">
<bean class="com.myactivator.LSMInboundProficiencyActivator" />
</int:service-activator>
Is it possible that something is failing silently?
One other noteworthy thing is that there are two production servers that are both configured as above....meaning that there are two servers that have JMS adapters configured to read the messages. I mentioned above that I see message 1 and message 3 being read. In that case, I see server one process message one and server two process mesage two...so it seems that having two servers configured like above has no negative impact. Any other thoughts on what could be happening or how I can debug the case of the missing/dropped messages?
Version information:
Spring - 3.0.5.RELEASE
Spring Integration - 2.0.3.RELEASE
Nothing springs to mind that would cause lost messages; I don't recall that ever being reported; but 2.0.3 is quite ancient (3rd birthday coming up soon). We don't support 2.0.x any more but you should at least update to 2.0.6 which is the last release of 2.0.x. But preferably move up to the latest 3.0.0 release (or at least 2.2.6).

ACTIVEMQ - How can subscriber receive topic messages when started after publisher?

In my program, I have two modules :- Publisher and Subscriber which communicate via Topic.
I understand that in order to receive messages by subscriber, it should be started before publisher. But there may be a scenario where the subscriber goes down for some reason and needs to be restarted. Is there any way, by which if I start the Subscriber after Publisher, then also it should be able to receive message?
Adding a code example by using spring DMLC and durable subscribers. It's harder to achieve this with a plain JMSTemplate (you tagged this, so I guess you are using JMS Templates to receive?), since you have to grab the session from the template and create the durable consumer yourself. This is automatically handled for you if you use the DMLC approach.
<bean id="myDurableConsumer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="myCf" />
<property name="sessionTransacted" value="true" />
<property name="subscriptionDurable" value="true"/>
<property name="durableSubscriberName" value="myDurableNameThatIsUniqueForThisInstance" />
<property name="destinationName" value="someTopic" />
<property name="messageListener" ref="myListener" />
< /bean>
If you are only interested in the disconnect-reconnect scenario, I think a durable subscriber is what you are looking for.
http://activemq.apache.org/how-do-durable-queues-and-topics-work.html
In general if you want to account for a subscriber going offline and returning without missing any messages you would use JMS Durable Subscriptions. This allows your subscriber to receive any messages it missed while offline. Note that the caveat here is that is needs to have subscribed once first before it will start to collect offline messages.
Besides the standard JMS Durable consumer model ActiveMQ also provides the retroactive consumer. Another possibility is Virtual destinations.

No new consumers on activemq queue after a while

Since a month we have a reoccurring issue with activemq and spring. After a some time (between a day and a week) we have no more consumers and no new ones get started and the queue starts to fill up.
This setup ran for over a year, without any issues and as far as we can see nothing relevant has been changed.
An other queue we use also started to show the same behavior, but less frequent.
from the activemq webconsole ( as you can see lots of pending messages and no consumers)
Name ↑ Number Of Pending Messages Number Of Consumers Messages Enqueued Messages Dequeued Views Operations
queue.readresult 19595 0 40747 76651 Browse Active Consumers
contents of our bundle-context.xml
<!-- JMS -->
<bean id="jmsConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop">
<property name="maxConnections" value="5" />
<property name="maximumActive" value="5" />
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL">
<value>tcp://localhost:61616</value>
</property>
</bean>
</property>
</bean>
<bean id="ResultMessageConverter" class="com.bla.ResultMessageConverter" />
<jms:listener-container connection-factory="jmsConnectionFactory" destination-resolver="jmsDestinationResolver"
concurrency="2" prefetch="10" acknowledge="auto" cache="none" message-converter="ResultMessageConverter">
<jms:listener destination="queue.readresult" ref="ReaderRequestManager" method="handleReaderResult" />
</jms:listener-container>
There are no exception in any of the logs. Does anyone knows of a reason why after a while no new consumers could be started.
Thanks
I've run into issues before where "consumers stop consuming," but haven't seen consumers stop existing. You may be running out of memory and/or connections in the pool. Do you have to restart ActiveMQ to fix the problem or just your application?
Here are a couple suggestions:
Set the queue prefetch to 0
Add "useKeepAlive=false" on the connection string
Increase the memory limits for the queues
I can see no obvious reason in the config provided why it should fail. So you need to resort to classic trouble shooting.
Try to set logging to debug and recreate the issue. Then you should be able to see more and you might be able to detect the root cause of it.
Also, check out the JMS exception listener and try to attach it your implementation of it to get a grasp of the real problem.
http://docs.oracle.com/javaee/6/api/javax/jms/ExceptionListener.html

Resources