MQRC_UNKNOWN_ALIAS_BASE_Q 使用 CCDT 连接 IBM MQ 集群时 Spring Boot JMSTemplate

MQRC_UNKNOWN_ALIAS_BASE_Q when connecting with IBM MQ cluster using CCDT and Spring Boot JMSTemplate

我有一个 Spring 启动应用程序,使用 JMSListener + IBMConnectionFactory + CCDT 连接 IBM MQ 集群。

A 设置以下连接属性: - url 指向生成的 ccdt 文件 - 用户名(不需要密码,因为测试环境) - queuemanager 名称未定义 - 因为它是集群的任务来决定,一些 google 结果,包括几个 Whosebug 的结果表明在我的情况下 qmgr 必须设置为空字符串。

当我的 Spring Boot JMSListener 尝试连接到队列时,出现以下 MQRC_UNKNOWN_ALIAS_BASE_Q 错误:

2019-01-29 11:05:00.329 WARN  [thread:DefaultMessageListenerContainer-44][class:org.springframework.jms.listener.DefaultMessageListenerContainer:892] - Setup of JMS message listener invoker failed for destination 'MY.Q.ALIAS' - trying to recover. Cause: JMSWMQ2008: Failed to open MQ queue 'MY.Q.ALIAS'.; nested exception is com.ibm.mq.MQException: JMSCMQ0001: IBM MQ call failed with compcode '2' ('MQCC_FAILED') reason '2082' ('MQRC_UNKNOWN_ALIAS_BASE_Q').
com.ibm.msg.client.jms.DetailedInvalidDestinationException: JMSWMQ2008: Failed to open MQ queue 'MY.Q.ALIAS'.
        at com.ibm.msg.client.wmq.common.internal.Reason.reasonToException(Reason.java:513)
        at com.ibm.msg.client.wmq.common.internal.Reason.createException(Reason.java:215)

在 MQ 错误日志中,我看到以下内容:

01/29/2019 03:08:05 PM - Process(27185.478) User(mqm) Program(amqrmppa)
                    Host(myhost) Installation(Installation1)
                    VRMF(9.0.0.5) QMgr(MyQMGR)

AMQ9999: Channel 'MyCHL' to host 'MyIP' ended abnormally.

EXPLANATION:
The channel program running under process ID 27185 for channel 'MyCHL'
ended abnormally. The host name is 'MyIP'; in some cases the host name
cannot be determined and so is shown as '????'.
ACTION:
Look at previous error messages for the channel program in the error logs to
determine the cause of the failure. Note that this message can be excluded
completely or suppressed by tuning the "ExcludeMessage" or "SuppressMessage"
attributes under the "QMErrorLog" stanza in qm.ini. Further information can be
found in the System Administration Guide.
----- amqrmrsa.c : 938 --------------------------------------------------------
01/29/2019 03:15:14 PM - Process(27185.498) User(mqm) Program(amqrmppa)
                    Host(myhost) Installation(Installation1)
                    VRMF(9.0.0.5) QMgr(MyQMGR)

AMQ9209: Connection to host 'MyIP' for channel 'MyCHL' closed.

EXPLANATION:
An error occurred receiving data from 'MyIP' over TCP/IP.  The connection
to the remote host has unexpectedly terminated.

The channel name is 'MyCHL'; in some cases it cannot be determined and so
is shown as '????'.
ACTION:
Tell the systems administrator.

由于MQ错误日志包含QMgr(MyQMGR),其中MyQMGR值我没有在连接属性中设置,我假设路由似乎没问题:MQ 集群找到了一个 qmgr 来使用。

别名存在并指向现有的 q。机器人目标 q 和别名通过 CLUSTER(clustname) 命令添加到集群。

有什么问题吗?

简答

  • MQ 集群 用于消费者应用程序查找要从中获取消息的队列。
  • MQ 集群 在生产者应用程序 PUT 消息以将其定向到目的地时使用。

进一步阅读

发送消息时使用集群来帮助为集群队列的多个实例提供负载平衡。在某些情况下,人们通过拥有两个队列实例并仅保留一个 PUT(ENABLED).

来将其用于 hot/cold 故障转移

如果应用程序是将消息放入集群队列的生产者,则它只需要连接到集群中的队列管理器并有权将消息放入该集群队列。基于许多不同事物的 MQ 将处理将该消息发送到哪里。


在 v7.1 之前,只有两种方法可以提供对远程集群队列的访问:

  1. 使用 QALIAS:

    • 定义一个本地 QALIAS,其 TARGET 设置为集群队列名称

      注意这个QALIAS本身不需要聚类。

    • 授予放置到本地的权限QALIAS
  2. 提供 PUT 到 SYSTEM.CLUSTER.TRANSMIT.QUEUE 的权限。

第一个选项允许为集群中的特定集群队列授予对应用程序的精细访问权限。第二个选项允许应用程序放入集群中的任何集群队列或集群中任何集群队列管理器上的任何队列。

在 7.1 中,IBM 添加了一个新的可选行为,这是通过 qm.iniSecurity 节中的设置 ClusterQueueAccessControl=RQMName 提供的。如果启用(这不是默认设置),那么您实际上可以为应用程序提供直接 PUT 到远程集群队列的权限,而无需本地 QALIAS


集群不是的是消费应用程序,例如您的 JMSListener 示例。

将从任何 QLOCAL(集群或非集群)使用的应用程序必须连接到定义 QLOCAL 的队列管理器。

如果您遇到 QLOCAL 的多个 PUT(ENABLED) 集群实例的情况,您需要确保您的消费者直接连接到托管实例的每个队列管理器上。


根据您的评论,您有一个 CCDT,其条目如下:

CHANNEL('MyCHL') CHLTYPE(CLNTCONN) QMNAME('MyQMGR') CONNAME('node1url(port1),node2url(port2)')

如果有两个具有不同队列管理器名称的不同队列管理器在 node1url(port1)node2url(port2) 上侦听,那么您可以通过不同的方式从应用程序端完成此操作。

当您指定 QMNAME 以连接到应用程序时,该名称将与您连接到的队列管理器相匹配,除非它满足以下条件之一:

  1. 如果您指定 *MyQMGR,它将找到带有 QMNAME('MyQMGR') 的一个或多个通道并选择一个并连接,并且不会强制要求远程队列管理器名称必须匹配。
  2. 如果在您的 CCDT 中您有 QNAME(''),它被设置为 NULL,那么在您的应用程序中您可以指定一个空的队列管理器名称或仅指定一个 space,它将在CCDT,并且不会强制要求远程队列管理器名称必须匹配。
  3. 在您的应用程序中,您将队列管理器名称指定为 *,MQ 将使用 CCDT 中的任何通道,并且不会强制要求远程队列管理器名称必须匹配。

CCDT 的一个限制是通道名称在 CCDT 中必须是唯一的。即使 QMNAME 不同,您也不能有第二个具有相同频道名称的条目。

当您连接时,您正在点击两个 CONNAME 的条目并连接到第一个 IP(port),如果在连接时,您只会到达第二个 IP(port)第一个不可用,MQ 将尝试第二个,或者如果您已连接并启用了重新连接,然后第一个出现故障,MQ 将尝试连接到第一个然后是第二个。

如果您想让两个集群队列 PUT(ENABLED) 接收流量,那么您希望能够专门连接到两个队列管理器中的每一个以读取这些队列。

我建议您在每个队列管理器上添加一个新通道,该通道具有不同的 QM 特定名称,该名称也不同于现有名称,如下所示:

CHANNEL('MyCHL1') CHLTYPE(CLNTCONN) QMNAME('MyQMGR1') CONNAME('node1url(port1)')
CHANNEL('MyCHL2') CHLTYPE(CLNTCONN) QMNAME('MyQMGR2') CONNAME('node2url(port2)')

这是对现有条目的补充。

对于放置组件,您可以继续使用可以连接到任一队列管理器的通道。

为了获取组件,您可以配置至少两个组件,一个使用新的队列管理器特定的 CCDT 条目连接到每个队列管理器,这样两个队列都被使用。