4

我们正在尝试建立从 tomcat 到 IBM MQSeries 的 jms 连接,以建立连接池。

我们按照以下链接进行了操作,并提供了建议的解决方案:

使用 Tomcat 的 WebSphere MQ 连接池

我不知道我们如何使用建议的方法管理不同的 jms 连接,我们进行了测试,我们注意到 CachingConnectionFactory 管理不同的 jms 会话而不是 jms 连接。

我与您分享下面的链接,其中解释了 CachingConnectionFactory 不允许管理不同的 jms 连接,而只能管理 jms 会话!

https://jira.spring.io/browse/SPR-13586

我也和大家分享一下,两个文件 context.xml(datasource 和 services.xml(spring services 文件)

上下文.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="********" />

服务.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>

此致。

4

1 回答 1

5

概括

您需要升级到更高版本的 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 及更高版本中获得类似的功能。


如“ WebSphere MQ 使用 Java 版本 6.0 ”手册的第 504 页所述,v6 连接池是 MQ v6.0 JMS 中的默认设置:

setUseConnectionPooling

public void setUseConnectionPooling(boolean usePooling);

选择是否使用连接池。如果将此设置为 true,则 JMS 在通过 ConnectionFactory 创建的任何连接的生命周期内启用连接池。这也会影响使用设置为 false 的 usePooling 创建的连接;要禁用整个 JVM 的连接池,请确保 JVM 中使用的所有 ConnectionFactories 都将 usePooling 设置为 false。


事实上,在 IBM MQ v8.0 知识中心页面开发应用程序>开发 JMS 和 Java 平台,企业版应用程序>使用用于 JMS 的 IBM MQ 类>用于 JMS 的 IBM MQ 类中记录了在 MQ v7 中删除连接池的事实>类 MQConnectionFactory

setUseConnectionPooling

public void setUseConnectionPooling(boolean usePooling)

已弃用。JMS 不再使用连接池。任何连接池都应该使用 App Server 提供的工具来完成。在用于 JMS 的早期版本的 WebSphere MQ 类中设置 ConnectionPooling 的使用。保留此方法是为了与较旧的 MQJMS 应用程序兼容,但是,由于此连接池功能已从版本 7 中删除,因此设置此属性将无效。


要解释您今天看到的行为,您还需要了解 MQ v7.0 中添加的 MQ 客户端通道共享对话行为,您可以在 IBM MQ v8.0 知识中心页面迁移和升级>简介中阅读有关此内容IBM MQ 迁移>共存、兼容性和互操作性>MQI 客户端:客户端连接和服务器连接通道的默认行为。引用下面的一些细节:

在版本 7.0 中,客户端和服务器连接通道的默认设置更改为使用共享对话。此更改会影响心跳和通道退出的行为,并可能对性能产生影响。

在 7.0 版之前,每个对话都被分配到不同的频道实例。从版本 7.0 开始,客户端和服务器连接的默认设置是共享一个 MQI 通道。您使用 SHARECNV(共享会话)参数来指定可以通过特定 TCP/IP 客户端通道实例共享的最大会话数。可能的值如下:

SHARECNV(0)

  • 此值指定不通过 TCP/IP 套接字共享对话。通道实例的行为与 6.0 版服务器或客户端连接通道完全相同,并且当您将 SHARECNV 设置为 1 或更大时,您不会获得双向心跳等额外功能。仅当您将 SHARECNV 设置为 1 或更大时,如果存在无法正确运行的现有客户端应用程序,则仅使用值 0。


综上所述,您有一个具有以下设置的 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 知识中心页面开发应用程序>开发 JMS 和 Java 平台,企业版应用程序>将 IBM MQ 类用于 JMS>编写 IBM JMS 应用程序的 MQ 类>访问 IBM MQ 功能>在 JMS 的 IBM MQ 类中共享 TCP/IP 连接

JMS 应用程序创建的每个 JMS 连接和 JMS 会话都会创建自己的与队列管理器的对话。

在您的情况下,因为您为 JMS 使用 MQ v6.0 类,所以每个“对话”都是到队列管理器的 MQ 通道实例(TCP 连接)。


我建议您获取当前的 IBM MQ 类 Java 版本来使用,这将允许您拥有多达 90 个共享对话。如果争用是一个问题,您需要让您的 MQ 管理员增加MAXINST/MAXINSTC设置并减少SHARECNV

对于IBM MQ Classes for JMS,您可以在 IBM MQ v9 知识中心页面“ What is installed for IBM MQ classes for JMS ”上找到所需的文件列表:

可重定位 JAR 文件
在企业中,可以将以下文件移动到需要为 JMS 运行 IBM MQ 类的系统:

  • com.ibm.mq.allclient.jar
  • com.ibm.mq.traceControl.jar
  • jms.jar
  • fscontext.jar
  • providerutil.jar
  • Bouncy Castle 安全提供程序和 CMS 支持 jar

如果您的应用程序使用文件系统上下文执行 JNDI 查找,则需要 fscontext.jar 和 providerutil.jar 文件。

需要 Bouncy Castle 安全提供程序和 CMS 支持 jar 文件。有关更多信息,请参阅对非 IBM JRE 的支持。

请注意,只有com.ibm.mq.allclient.jarjms.jar和 Bouncy Castle 安全提供程序和 CMS 支持 jar 包含在 Redistributable 客户端中,但都包含在 Java All 客户端中。您也在运行 9.0.0.0,我建议您转到 9.0.0.5。您可以在Fix Central上找到 Redistributable 和 Java All 客户端。

于 2018-11-09T21:01:44.247 回答