我们正在尝试建立从tomcat到IBM MQSeries的jms连接,并考虑建立连接池。
我们点击了以下链接,并提出了建议的解决方案:
WebSphere MQ connection pooling with Tomcat
我不知道如何使用建议的方法来管理不同的jms连接,我们进行了测试,并且注意到CachingConnectionFactory管理不同的jms会话而不是jms连接。
我与您分享下面的链接,其中解释了CachingConnectionFactory不允许管理不同的jms连接,而只能管理jms会话!
https://jira.spring.io/browse/SPR-13586
我还与您分享了这两个文件context.xml(数据源和services.xml( Spring 服务文件)
context.xml
<Resource name="jms/AN8.NOTI.MOBILE.01" auth="Container" type="org.springframework.jms.connection.CachingConnectionFactory"
factory="com.cl.fwk.jms.utilities.RSFCachingMQQueueConnectionFactoryFactory"
description="JMS Queue Connection Factory for sending messages" HOST="**********"
PORT="****" CHAN="******" TRAN="*" QMGR="***" />
<Resource name="jms/MQAN8.NOTI.MOBILE.01" auth="Container"
type="com.ibm.mq.jms.MQQueue" factory="com.ibm.mq.jms.MQQueueFactory"
description="JMS Queue for receiving messages from Dialog" QU="********" />
services.xml
<!-- Ressource JNDI pour la connexion MQSeries-->
<bean id="xxxx.jmsRefConnectionFactory.mqseries" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jms/AN8.NOTI.MOBILE.01" />
<property name="resourceRef" value="true" />
</bean>
<!-- Ressource JNDI pour la file d'attente du broker MQSeries-->
<bean id="xxxx.jmsRefQueue.mqseries" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jms/MQAN8.NOTI.MOBILE.01" />
<property name="resourceRef" value="true" />
</bean>
<!-- A cached connection to wrap the MQSeries connection -->
<bean id="xxxx.jmsConnectionFactory.mqseries" class="org.springframework.jms.connection.CachingConnectionFactory">
<!-- <constructor-arg ref="xxxx.jmsRefConnectionFactory.mqseries" /> -->
<property name="targetConnectionFactory" ref="xxxx.jmsRefConnectionFactory.mqseries"/>
<property name="sessionCacheSize" value="10" />
</bean>
<bean id="xxxx.jmsDestinationResolver.amq" class="org.springframework.jms.support.destination.DynamicDestinationResolver" />
<bean id="xxxx.jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="xxxx.jmsConnectionFactory.mqseries" />
<property name="defaultDestination" ref="xxxx.jmsRefQueue.mqseries" />
<property name="destinationResolver" ref="xxxx.jmsDestinationResolver.amq" />
<property name="sessionTransacted" value="true" />
<property name="sessionAcknowledgeMode" value="#{T(javax.jms.Session).AUTO_ACKNOWLEDGE}" />
</bean>
最好的祝福。
最佳答案
摘要
您需要升级到JMS的MQ类的更高版本,或者让您的MQ管理员增加MAXINST / MAXINSTC设置以允许更多通道实例。
请注意,您使用的版本自2012年以来就不再受支持,因此建议您升级。
Product Version Release End of Service
============ ======= ========== =================
Websphere MQ 6.0 2005-06-24 2012-09-30
来自评论的背景信息
根据您在注释中提供的内容,可以了解有关当前设置的以下信息:
IBM MQ Server version: 8.0.0.? (specific maintenance level unknown)
IBM MQ jar names: mq-7.0.0.jar and mqjms-7.0.0.jar
IBM MQ jar version: 6.0.2.11
SVRCONN Channel settings: SHARECNV(10) MAXINST(9) MAXINSTC(9)
请注意,即使jar文件的名称包含字符串7.0.0,它们实际上还是来自IBM MQ v6.0.2.11(在当时,它在技术上被称为Websphere MQ)。
您所指向的另一个StackOveflow问题“WebSphere MQ connection pooling with Tomcat”是指v7.0之前的IBM MQ(例如v6.0)提供了连接池这一事实,但是在MQ v7.0上已将其删除,并询问如何获取。 v7.0及更高版本中的类似功能。
v6连接池是MQ v6.0 JMS中的默认设置,如《 WebSphere MQ Using Java Version 6.0》手册的第504页所述:
setUseConnectionPooling
public void setUseConnectionPooling(boolean usePooling);
选择是否使用连接池。如果将其设置为true,
JMS在所有连接的生命周期内启用连接池
通过ConnectionFactory创建的。这也会影响连接
使用usePooling设置为false创建;禁用连接池
在整个JVM中,请确保在
JVM将usePooling设置为false。
实际上,IBM MQ v8.0知识中心页面Developing applications>Developing JMS and Java Platform, Enterprise Edition applications>Using IBM MQ classes for JMS>IBM MQ classes for JMS>Class MQConnectionFactory中记录了在MQ v7中删除了连接池的事实。
setUseConnectionPooling
public void setUseConnectionPooling(boolean usePooling)
已弃用。 JMS不再使用连接池。 任何连接池
应该使用App Server提供的功能来完成。设置使用
早期版本的WebSphere MQ类中的ConnectionPooling
JMS。 保留此方法是为了与较旧的MQJMS兼容
应用程序,但是,因为此连接池功能具有
已从版本7中删除,设置此属性将没有
影响。
为了解释您今天看到的行为,您还需要了解MQ v7.0中添加的MQ客户机通道共享对话行为,您可以在IBM MQ v8.0知识中心页面Migrating and upgrading>Introduction to IBM MQ migration>Coexistence, compatibility, and interoperability>MQI client: Default behavior of client-connection and server-connection channels中了解此内容。在下面引用一些细节:
在7.0版中,客户端和服务器连接的默认设置
频道已更改为使用共享对话。此更改会影响
心跳和通道的行为退出,并可能对
性能。
在7.0版之前,每个会话都分配给一个不同的会话
频道实例。从7.0版开始,客户端和服务器的默认设置
连接是共享一个MQI通道。您使用SHARECNV(共享
会话)参数,以指定
可以通过特定的TCP / IP客户端共享的对话
频道实例。可能的值如下:
SHARECNV(0)
6.0服务器或客户端连接通道,并且您没有获得额外的功能,例如双向心跳,当您使用
将SHARECNV设置为1或更大。仅在有以下情况时才使用值0
设置时无法正确运行的现有客户端应用程序
SHARECNV为1或更大。
放在一起,您将拥有一个具有以下设置的SVRCONN通道:
SHARECNV(10)
MAXINST(9)
MAXINSTC(9)
这些设置与MQ v7.0和更高版本的客户端一起使用时,意味着您在客户端和队列管理器之间可以有9个通道实例(TCP连接),并且每个实例可以有10个共享对话,总共最多90个对话。
因为您正在使用用于JMS的MQ v6.0类,所以通道的运行就像是在进行以下设置:
SHARECNV(0)
MAXINST(9)
MAXINSTC(9)
这意味着在客户端和队列管理器之间可以有9个通道实例(TCP连接),并且每个实例仅支持一个对话。
在JMS的MQ v6.0类上,每个基础JMS连接以及在JMS连接之上创建的每个JMS会话都将向队列管理器分配一个通道实例。
要了解有关连接和会话如何相互交互以及如何使用SHARECNV设置进行交互的更多信息,请参阅IBM MQ v8.0知识中心页面Developing applications>Developing JMS and Java Platform, Enterprise Edition applications>Using IBM MQ classes for JMS>Writing IBM MQ classes for JMS applications>Accessing IBM MQ features>Sharing a TCP/IP connection in IBM MQ classes for JMS:
JMS应用程序创建的每个JMS连接和JMS会话都会与队列管理器创建自己的对话。
在您的情况下,因为您正在为JMS使用MQ v6.0类,所以每个“对话”都是到队列管理器的MQ通道实例(TCP连接)。
我建议您获取要用于Java版本的当前IBM MQ类,这样一来,您最多可以进行90个共享对话。如果争用是一个问题,则需要让您的MQ管理员增加
MAXINST
/ MAXINSTC
设置并减少SHARECNV
。对于,JMS的IBM MQ类可以在IBM MQ v9知识中心页面“What is installed for IBM MQ classes for JMS”上找到所需的文件列表:
可重定位的JAR文件
在企业内部,可以将以下文件移动到需要为JMS运行IBM MQ类的系统:
如果您的应用程序使用文件系统上下文执行JNDI查找,则需要fscontext.jar和providerutil.jar文件。
需要Bouncy Castle安全提供程序和CMS支持jar文件。有关更多信息,请参阅对非IBM JRE的支持。
请注意,可重新分发客户端中仅包括
com.ibm.mq.allclient.jar
,jms.jar
以及Bouncy Castle安全提供程序和CMS支持jar,而Java All客户端中均包括所有这些。您也正在运行9.0.0.0,建议您转到9.0.0.5。您可以在Fix Central上找到Redistributable和Java All客户端。