Use of receiveTimeout property in SimpleMessageListenerContainer - spring-amqp

I have a listener which listens to one queue, I want a listener in such a way that my listener need to consume one message after another message with delay of 1 min. I have seen receiveTimeout property for the listener container but i couldn't able to achieve the delay in message consumption. here is my listener container.
<!-- search message listener container -->
<bean id="listenerContainer" class="org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="queueNames">
<array>
<value>TEST_QUEUE</value>
</array>
</property>
<property name="messageListener" ref="messageListenerAdaptor" />
<property name="acknowledgeMode" value="AUTO" />
<property name="concurrentConsumers" value="1" />
<property name="receiveTimeout" value="60000" />
</bean>

There is no way to do what you want with the listener container configuration; the receiveTimeout is simply how long the container waits for a message before looking to see if, say, the container has been stopped.
You could play some games with an intermediate queue with dead-lettering and time-to live, but that will be complicated.
It would probably be easier to use RabbitTemplate.receive() (or receiveAndConvert()) if you want to get messages on a schedule rather than being event-driven.
There is a new plugin for RabbitMQ which might help you.

Related

Which is better CachingConnectionFactory.CacheMode Connection or Channel in Spring AMQP

Hi I have been using Spring AMQP with connection obtained from CachingConnectionFactory with the properties being shown below
<bean id="connectionFactory"
class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory">
<constructor-arg value="rabbit-server-fqdn" />
<property name="virtualHost" value="some-vhost" />
<property name="username" value="username" />
<property name="password" value="password " />
<property name="channelCacheSize" value="25" />
</bean>
Now i need to change my mode to Connection as i need to check open connection
<bean id="connectionFactory"
class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory">
<constructor-arg value="rabbit-server-fqdn" />
<property name="virtualHost" value="some-vhost" />
<property name="username" value="username" />
<property name="password" value="password " />
<property name="cacheMode" value="CONNECTION" />
<property name="channelCacheSize" value="25" />
</bean>
So
Q1. Will channelCacheSize will work ?
Q2. what will be default connection pool size in CachingConnectionFactory ?
Q3. Do i need to set additional property ?
The CHANNEL is better, because you don't need to create a new connection for each call, but reuse a shared one.
The Reference Manual has plenty of facts on the matter. One of them is when do you really need CONNECTION mode:
The use of separate connections might be useful in some environments, such as consuming from an HA cluster, in conjunction with a load balancer, to connect to different cluster members.
The shared connection is still can be traced for open/close state via ConnectionListener injected into that CachingConnectionFactory.

How to change the CachingConnectionFactory timeout setting

I have a use case where when the connectivity to rabbitmq goes down I need to manage the messages in different way.
I have a logic
RabbitTempate template // get template using API call
template.setReplyTimeout(10000);
template.convertAndSend(message);
But the problem is when the rabbitmq server connectivity goes down Spring AMQP automatically waits for connectivity to get resolved for 5 min
But because of that the client thread calling that particular logic waits for 5 min .
Is there any way i can change it , I am using CachingConnectionFactory
<bean id="connectionFactory"
class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory">
<constructor-arg value="rabbit-server-fqdn" />
<property name="virtualHost" value="vhost" />
<property name="username" value="username" />
<property name="password" value="password" />
<property name="cacheMode" value="CONNECTION" />
<property name="channelCacheSize" value="25" />
</bean>
Is there any way I can override these settings from 5 min so that client API does not need to wait for such huge amount of time ?

How does SimpleMessageListenerContainer handleMesage() works?

I have a question on how SimpleMessageListenerContainer handleMesage works? my problem scenario is, I have 1000 messages(m1, m2... m100) in queue then started consumer (5 concurrent consumers) and acknowledgeMode='NONE' in this scenario,
does handleMesage consume 5 messages at a time (m1,m2,m3,m4,m5) then next 5 messages, and so on... ?
Does container creates 5 Receiver instances?
Would like to know end of the handle message where control will goes?
Can you please let me know these.. because we couldn't able to see the messages as soon as Consumer starts in RMQ MNGMT console.... our code inside handleMesage method will take atleast some seconds to process each request.
<bean id="sampleListenerContainer"
class="org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="queueNames">
<array>
<value>TEST_QUEUE</value>
</array>
</property>
<property name="messageListener" ref="messageListenerAdaptor" />
<property name="acknowledgeMode" value="NONE" />
<property name="concurrentConsumers" value="5" />
</bean>
<!-- message listener -->
<bean id="messageListenerAdaptor"
class="org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter">
<property name="delegate" ref="listenerPojo" />
<property name="messageConverter" ref="messageConverter" />
</bean>
<bean id="listenerPojo"
class="com.amqp.consumer.Receiver" >
</bean>
With version 1.3 and later, each consumer gets prefetch messages at a time (the broker sends them round robin)
Yes but they're called consumers, not receivers
When the listener method exits, the consumer grabs the next message, this frees up the amqp-client thread so it can get another message from the broker.
With ackmode NONE, it depends on which version of Spring AMQP you are using how messages are delivered to the consumer.
With versions prior to 1.3, all 1000 messages would immediately be sent to the container (200 for each consumer).
After version 1.3.0, the number of messages sent to each consumer depends on the prefetchCount property (default 1); there will actually be prefetch+1 messages removed from the broker for each consumer.
Understand that AcknowledgeMode="NONE" means you can lose messages because the broker automatically acks the messages when they are sent to the consumer. Any messages sitting in the consumer (prefetch) will be lost if the server crashes.

Spring webflow using a lot of memory

Our Webflow (2.3.1) application is claiming a lot of memory for each new flow that we open through the browser.
The screenshot below shows our application's memory use. When the application starts it takes an initial 400 Mb. After that we open 4 individual, identical Webflow TEST pages in the browser which each claim about 90Mb of extra memory..
Each test page is started from its own simple flow definition:
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/webflow"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd" start-state="start">
<view-state id="start" view="test/test1">
</view-state>
<end-state id="end"/>
<bean-import resource="../flow-beans.xml"/>
</flow>
The JSP test pages are also very simple, just empty with one line of text.
When we currently set the JVM memory to 1.5Gb the application eventually crashes on the server with OutOfMemoryExceptions after opening about 15 different flows. 1.5 Gb seems a bit much, regarding the low complexity of our screens..
We are wondering if the amount of memory Webflow seems to claim for these simple flows/pages is expected and if we should therefore just assign more memory to the server JVM. If not, we would like to know how we can decrease this memory usage.
Below is our entire webflow configuration.
We have tried adding a flow-execution-repository tag and played around with the max-executions-snapshots and max-executions values, but even the most conservative settings don't change the memory usage we are seeing.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:webflow="http://www.springframework.org/schema/webflow-config"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/webflow-config
http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- Launches new flow executions and resumes existing executions. -->
<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry">
</webflow:flow-executor>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:our.properties" />
<property name="placeholderPrefix" value="$xxxx"></property>
</bean>
<tx:annotation-driven transaction-manager="$xxxx{txManager}" />
<!-- Creates the registry of flow definitions for this application -->
<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices">
<webflow:flow-location-pattern value="classpath:flows/**/*-flow.xml" />
</webflow:flow-registry>
<bean id="viewFactoryCreator" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
<property name="viewResolvers" ref="viewResolver" />
</bean>
<bean id="expressionParser" class="org.springframework.expression.spel.standard.SpelExpressionParser">
<constructor-arg name="configuration">
<bean class="org.springframework.expression.spel.SpelParserConfiguration">
<constructor-arg name="autoGrowCollections" value="true" />
<constructor-arg name="autoGrowNullReferences" value="false" />
</bean>
</constructor-arg>
</bean>
<bean id="webflowExpressionParser" class="org.springframework.webflow.expression.spel.WebFlowSpringELExpressionParser">
<constructor-arg name="expressionParser" ref="expressionParser" />
</bean>
<webflow:flow-builder-services id="flowBuilderServices" view-factory-creator="viewFactoryCreator" validator="validator" expression-parser="webflowExpressionParser"/>
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
<bean id="projectVersion" class="our.company.versions.ProjectVersionUtil">
<property name="xxxxVersion" value="$xxxx{xxxx.version}" />
<property name="systemConfigurationDao">
<ref bean="SystemConfigurationDao"/>
</property>
</bean>
</beans>
When Spring Web Flow starts a new flow it basically constructs a new BeanFactory which loads the xml file and imports any additional xml files. The newly constructed BeanFactory has the context of the DispatcherServlet as its parent.
Now the problem with this is that a the bean factory constructs instances of all the beans even those defined in imported XML files.
<bean-import resource="../flow-beans.xml"/>
If there are a lot of beans in there those will be duplicated for each flow instance. In general you don't want your all of your beans duplicated and stored in the users sessions.
Remove the singleton beans from the flow-beans.xml and put them in the normal application context, they are still referable from within the flow definition. Or you could simply add the flow-beans.xml to the list of files loaded at startup of your application.

c3p0 connection pool is not shrinking [duplicate]

This question already has an answer here:
c3p0 pool is not shrinking
(1 answer)
Closed 8 years ago.
I am using c3p0 connection pool with spring (with plain jdbc, NO hibernate). Here is my config
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="acquireIncrement" value="3"/>
<property name="minPoolSize" value="3"/>
<property name="maxPoolSize" value="25"/>
<property name="maxStatementsPerConnection" value="0"/>
<property name="numHelperThreads" value="6"/>
<property name="testConnectionOnCheckout" value="false" />
<property name="testConnectionOnCheckin" value="false" />
<property name="idleConnectionTestPeriod" value="10"/>
<property name="preferredTestQuery" value="select curdate()"/>
<property name="maxIdleTime" value="5" />
<property name="unreturnedConnectionTimeout" value="5" />
<property name="debugUnreturnedConnectionStackTraces" value="true" />
</bean>
I do see that connection pool hits max value of 25 connections but there shrinks back never shrinks back when load reduces.
I am missing some config here???
Please see the config parameters maxIdleTime and maxIdleTimeExcessConnections.
If you want to aggressively pare back pool size when load lightens, set a short maxIdleTimeExcessConnections. Leave just plain maxIdleTime fairly long, so you don't needlessly churn through Connections once your pool has hit minPoolSize.
If you don't care so much, then just set maxIdleTime and eventually the pool will shrink as idle Connections expire. But for reasonable values of maxIdleTime, this will happen slowly.
If neither maxIdleTime nor maxIdleTimeExcessConnections (nor maxConnectionAge) are set, these values all default to zero, meaning Connections never expire, and the pool will only shrink as Connections break and fail tests.

Resources