I am using jms:outbound-channel-adapter.
We noticed that application server is starting way too many MQ connections. Application ultimately exhausts the maxChannel limit of MQ Server and starts getting :
Caused by: com.ibm.mq.MQException: JMSCMQ0001: WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2537' ('MQRC_CHANNEL_NOT_AVAILABLE')
I am using MQTopicConnectionFactory, CachingConnectionFactory, outbound-channel-adapter.
Current configuration:
<bean id="mqQueueConnectionFactory" class="com.ibm.mq.jms.MQTopicConnectionFactory">
<property name="SSLCipherSuite" value="${mq.sslCipherSuite}"/>
<property name="hostName" value="${mq.hostName}"/>
<property name="port" value="${mq.port}"/>
<property name="channel" value="${mq.channel}"/>
<property name="transportType" value="1"/>
</bean>
<bean id="cachedConnectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory"
p:targetConnectionFactory-ref="jmsTConnectionFactory"
p:reconnectOnException="true" p:sessionCacheSize="10"
p:cacheProducers="true" />
<bean id="senderTopic" class="com.ibm.mq.jms.MQTopic" >
<constructor-arg value="${mq.topicName}"/>
</bean>
<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory">
<ref bean="cachedConnectionFactory" />
</property>
<property name="defaultDestination">
<ref bean="senderTopic" />
</property>
</bean>
Outbound-channel-adapter:
<int-jms:outbound-channel-adapter
id="jmsOutToNE" channel="umpAlertNotificationJMSChannel"
destination="senderTopic" jms-template="jmsQueueTemplate">
<!-- <int:retry-advice/> -->
</int-jms:outbound-channel-adapter>
Spring integration flow having 250 concurrent threads, however, there are 2000+ MQ connections starting during peak load.
What is the significance of sessionCacheSize="10" in CachingConnectionFactory if the connections are exceeding 500?
How can I limit the MQ connections?
Can't JMS reuse the MQ connection from the a pool the way DB connections work?
Related
I have a QueueChannel which is an output channel for my aggregator. The code works just fine on a single node cluster. The moment, I deploy it on 2 node cluster, the partitionStep is not completed and remains in STARTED state forever. Looking at PartitionStep it seems it waiting in the receive method and never marks the step COMPLETED. Below is the configuration that I am using.
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
<prop key="java.naming.provider.url">${oag_wl_nodes_url}</prop>
</props>
</property>
</bean>
<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate" ref="jndiTemplate" />
<property name="jndiName" value="jmsConnectionFactory" />
</bean>
<int:channel id="requestsChannel" />
<bean id="reqQueue" class="org.springframework.jndi.JndiObjectFactoryBean"
lazy-init="true" scope="prototype">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>masterRequestQueue</value>
</property>
</bean>
<int-jms:outbound-channel-adapter
connection-factory="connectionFactory" channel="requestsChannel" destination="reqQueue" />
<int:channel id="replyChannel" />
<bean id="replyQueue" class="org.springframework.jndi.JndiObjectFactoryBean"
lazy-init="true" scope="prototype">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>masterReplyQueue</value>
</property>
</bean>
<int-jms:message-driven-channel-adapter connection-factory="connectionFactory" destination="replyQueue"
channel="replyChannel" acknowledge="transacted" />
<int:channel id="aggregatedReplyChannel">
<int:queue />
</int:channel>
<int:aggregator ref="partitionHandler"
input-channel="replyChannel" output-channel="aggregatedReplyChannel" />
You are using a common reply queue replyQueue; that won't work because the two instances are competing for the replies and the reply might be consumed by the non-master node.
You need a separate reply destination for each.
That said, I don't see you setting up the replyTo at all on the outbound message, so I assume your replyTo is hard-coded on the consumer side..
You might find it easier to use an outbound gateway instead of a pair of channel adapters; the gateway will create a temporary reply queue (by default) for each request.
I am using spring integration to connect with the IBM MQ. My spring integration application is connecting successfully with IBM MQ. Now the MQ team made the MQ manager as the clustered manager i.e. queue manager is containing 2 host one active and one passive because if one host is down the passive one will up and running.
Below is my spring integration configuration for MQ and I can pass only one host.
<bean id="mqQueueConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
<property name="hostName" value=""/>
<property name="port" value=""/>
<property name="channel" value=""/>
<property name="queueManager" value=""/>
<property name="transportType" value="1"/>
</bean>
Is there any way by which we can pass both the active and passive host's from the configuration. I tried with the comma in host but that is not supported .
Please suggest
You should specify the hosts under the property connectionNameList, don't use hostName and port.
http://www-01.ibm.com/support/docview.wss?uid=swg21397867
Multi Instance MQ set up
The ConnectionNameList will allow to pass the active and passive host
<bean id="mqQueueConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
<property name="connectionNameList" value="activeHost(port),passiveHost(port)"/>
<property name="channel" value="channel Name"/>
<property name="queueManager" value="Queue Manager name"/>
<property name="transportType" value="transport type"/>
</bean>
We are using Spring Integration in our project and we have a requirement where If IBM MQ goes down then we will have to auto connect to IBM MQ when it is up. We have done this implementation using recoveryInterval option of org.springframework.jms.listener.DefaultMessageListenerContainer class. We have given recovery interval value to try to recover the MQ connection. But it is not recovering the connection after MQ restart. Below was my existing configuration:
<jms:message-driven-channel-adapter id="adapterId" channel="raw-channel" container="messageListenerContainer" />
<bean id="messageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="customQueueCachingConnectionFactory" />
<property name="destination" ref="requestQueue" />
<property name="recoveryInterval" value="60000" />
</bean>
Below is the Current Connection Factory :
<bean id="queueCachingConnectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="queueConnectionFactory" />
<property name="sessionCacheSize" value="10" />
<property name="cacheProducers" value="false" />
<!-- <property name="reconnectOnException" value="true" /> -->
<!-- <property name="exceptionListener" ref="MQExceptionListener"></property> -->
</bean>
<jee:jndi-lookup id="queueConnectionFactory" jndi-name="MQConnectionFactory"
expected-type="javax.jms.ConnectionFactory" lookup-on-startup="true"></jee:jndi-lookup>
<jee:jndi-lookup id="queue" jndi-name="Queue"
expected-type="javax.jms.Queue" lookup-on-startup="true"/>
ERROR [task-scheduler-4] LoggingHandler:145 -org.springframework.jms.IllegalStateException: MQJCA1019: The connection is closed.; nested exception is com.ibm.msg.client.jms.DetailedIllegalStateException: MQJCA1019: The connection is closed.
The application attempted to use a JMS connection after it had closed the connection.
Modify the application so that it closes the JMS connection only after it has finished using the connection.
Thanks in Advance!!
The default message listening container should reference the caching connection factory:
<!-- caching connection factory fascade, also implements exception listener -->
<bean id="cachingConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="connectionFactory"/>
<property name="sessionCacheSize" value="10"/>
<property name="reconnectOnException" value="true"/>
</bean>
<!-- this is the Message Driven POJO (MDP) -->
<bean id="messageDrivenPOJO" class="com.redhat.gss.spring.MessageDrivenPOJO" />
<!-- The message listener container -->
<bean id="messageListener" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="sessionTransacted" value="true"/>
<property name="concurrentConsumers" value="1"/>
<property name="cacheLevelName" value="CACHE_CONSUMER"/>
<property name="receiveTimeout" value="10000"/>
<property name="sessionAcknowledgeMode" value="2"/>
<property name="messageListener" ref="messageDrivenPOJO"/>
<property name="connectionFactory" ref="cachingConnectionFactory"/>
<property name="exceptionListener" ref="cachingConnectionFactory"/>
<property name="destination" ref="jbossQueue"/>
</bean>
I want to block the retry from my of service activator, incase of any exception thrown.
Below is my configuration,
<http:inbound-gateway id="inboundGW"
request-channel="getCustInfo" supported-methods="GET"
error-channel="errorHandlerRouterChannel"
path="/Messages/{cust}" reply-channel="msgRetrival">
<http:header name="cust" expression="#pathVariables.cust" />
</http:inbound-gateway>
<int:service-activator input-channel="getCustInfo"
output-channel="msgRetrival" ref="createService" method="processCustInfo">
<int:request-handler-advice-chain>
<ref bean="retryWithBackoffAdviceSession"></ref>
</int:request-handler-advice-chain>
</int:service-activator>
<bean id="retryWithBackoffAdviceSession" class="org.springframework.integration.handler.advice.RequestHandlerRetryAdvice">
<property name="retryTemplate">
<bean class="org.springframework.retry.support.RetryTemplate">
<property name="retryPolicy">
<bean class="org.springframework.retry.policy.SimpleRetryPolicy">
<property name="maxAttempts" value="1" />
</bean>
</property>
</bean>
</property>
<property name="recoveryCallback">
<bean class="org.springframework.integration.handler.advice.ErrorMessageSendingRecoverer">
<constructor-arg ref="errorHandlerRouterChannel"/>
</bean>
</property>
</bean>
Exception thrown from my service activator doesn't get caught by the error-channel specified in the http:inbound-gateway
Spring integration config file was loaded twice in the deployment descriptor. After fixing this the issue was resolved.
Your question is not clear.
If you want to throw the exception after retries are exhausted, remove the recoveryCallback.
Does GridGain support SSL connection between each cluster member? If yes, can you show me how to do that?
Thanks,
Bill
GridGain supports SSL only for client connections (GridGain provides .NET and C++ thin clients), but not for communication between nodes.
To enable SSL for client connections, configure your server nodes like this:
<bean id="grid.cfg" class="org.gridgain.grid.GridConfiguration">
<!-- Enable REST. -->
<property name="restEnabled" value="true"/>
<!-- Client connection configuration. -->
<property name="clientConnectionConfiguration">
<bean class="org.gridgain.grid.GridClientConnectionConfiguration">
<!-- Enable SSL. -->
<property name="restTcpSslEnabled" value="true"/>
<!-- Provide SSL context factory (required). -->
<property name="restTcpSslContextFactory">
<bean class="org.gridgain.client.ssl.GridSslBasicContextFactory">
<property name="keyStoreFilePath" "keystore/server.jks"/>
<property name="keyStorePassword" value="123456"/>
<property name="trustStoreFilePath" "keystore/trust.jks"/>
<property name="trustStorePassword" value="123456"/>
</bean>
</property>
</bean>
</property>
</bean>
You will also need to provide SSL context factory on client configuration.
Ignite (and GridGain) allows you to use SSL for all possible connections.
To use SSL connection between nodes define property sslContextFactory in IgniteConfiguration.
<bean id="cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
<property name="sslContextFactory">
<bean class="org.apache.ignite.ssl.SslContextFactory">
<property name="keyStoreFilePath" value="keystore/server.jks"/>
<property name="keyStorePassword" value="123456"/>
<property name="trustStoreFilePath" value="keystore/trust.jks"/>
<property name="trustStorePassword" value="123456"/>
</bean>
</property>
</bean>
You can also check official security documentation.
https://apacheignite.readme.io/docs/ssltls