Websphere MQ 集群工作负载平衡:消息进入死信队列

Websphere MQ Cluster Workload Balancing: messages going to dead letter queue

我创建了一个包含 3 个 QMgr 的 WMQ 集群。 2 个完整存储库和 1 个部分存储库。这是使用的mqsc

crtmqm GW
strmqm GW
runmqsc GW
alter qmgr deadq('SYSTEM.DEAD.LETTER.QUEUE')
define listener(gw.listener) trptype(TCP) port(1416) ipaddr(xx.xx.xx.xx)
start listener(gw.listener)
define channel(SYSTEM.ADMIN.SVRCONN) chltype(svrconn)
ALTER QMGR CHLAUTH(DISABLED)
end

runmqsc QM01
alter qmgr repos('DEVELOPMENT.CLUSTER')
end

runmqsc QM02
alter qmgr repos('DEVELOPMENT.CLUSTER')
end

runmqsc QM01
define chl(to.QM01) chltype(clusrcvr) trptype(tcp) +
       conname('xx.xx.xx.xx(1414)') cluster(DEVELOPMENT.CLUSTER) 
end

runmqsc QM02
define chl(to.QM02) chltype(clusrcvr) trptype(tcp) +
       conname('xx.xx.xx.xx(1415)') cluster(DEVELOPMENT.CLUSTER) 
end

runmqsc GW
define chl(to.GW) chltype(clusrcvr) trptype(tcp) +
       conname('xx.xx.xx.xx(1416)') cluster(DEVELOPMENT.CLUSTER) 
end

runmqsc QM01
DEFINE CHANNEL(TO.QM02) CHLTYPE(CLUSSDR) TRPTYPE(TCP) +
       CONNAME('xx.xx.xx.xx(1415)') CLUSTER(DEVELOPMENT.CLUSTER)
end

runmqsc QM02
DEFINE CHANNEL(TO.QM01) CHLTYPE(CLUSSDR) TRPTYPE(TCP) +
       CONNAME('xx.xx.xx.xx(1414)') CLUSTER(DEVELOPMENT.CLUSTER)
end

runmqsc GW
DEFINE CHANNEL(TO.QM01) CHLTYPE(CLUSSDR) TRPTYPE(TCP) +
       CONNAME('xx.xx.xx.xx(1414)') CLUSTER(DEVELOPMENT.CLUSTER)
DEFINE CHANNEL(TO.QM02) CHLTYPE(CLUSSDR) TRPTYPE(TCP) +
       CONNAME('xx.xx.xx.xx(1415)') CLUSTER(DEVELOPMENT.CLUSTER)
end

runmqsc QM02
define qlocal('BACKUP') CLUSTER(DEVELOPMENT.CLUSTER)
define qlocal('PROVIDER') CLUSTER(DEVELOPMENT.CLUSTER)
define qlocal('RESPONSE') CLUSTER(DEVELOPMENT.CLUSTER)
define qlocal('STORE') CLUSTER(DEVELOPMENT.CLUSTER)
REFRESH CLUSTER(DEVELOPMENT.CLUSTER) REPOS(YES) 
end

runmqsc QM01
define qlocal('BACKUP') CLUSTER(DEVELOPMENT.CLUSTER)
define qlocal('PROVIDER') CLUSTER(DEVELOPMENT.CLUSTER)
define qlocal('RESPONSE') CLUSTER(DEVELOPMENT.CLUSTER)
define qlocal('STORE') CLUSTER(DEVELOPMENT.CLUSTER)
REFRESH CLUSTER(DEVELOPMENT.CLUSTER) REPOS(YES)
end

现在我正在向队列 PROVIDER 上的 QMgr GW 发送消息。请注意 GW 不托管此队列。它由 QM01QM02

主持
amqsput PROVIDER GW

遗憾的是,所有消息都将进入 QMgr GW 的死信队列。

请帮助解决这个问题。任何调试建议都会有很大帮助。

这里有几个可能的问题。

渠道的定义不尽相同。有些有 mixed-case 个名字,有些有全大写的名字。如果您指望缺少引号以确保 QMgr 将它们全部折叠为大写,则此 可能 有效。但是,这些命令显然已经过编辑,至少就 CONNAME 值而言是这样,所以我不假设生成的 objects 匹配。

创建集群后,是否检查所有通道都显示为AUTO-EXPLICIT?这就是您知道集群已正确启动的方式。

也有可能是 REFRESH CLUSTER 命令导致了中断。这在定义 new objects 时不是必需的,实际上非常具有破坏性。它等待通道重新启动,并且在您是 运行 命令的时间点,通告新 objects 的命令已发送到存储库但未返回。然后 REFRESH CLUSTER 请求通道停止,可能在 mid-batch, queues up 命令让集群删除它刚刚收到但尚未回复的信息,然后发送新的命令向集群发布 objects 它刚刚删除的广告。如果这听起来令人困惑,请考虑存储库上的集群命令服务器的感觉。

从 queue 定义脚本中删除 REFRESH CLUSTER 命令。

一旦确定通道已全部前进到 AUTO-EXPLICIT 并删除了 REFRESH CLUSTER,您就可以开始实际调试了。在这些情况下,查看死消息的 DLQ header 以找出列出的原因代码确实很有帮助。这通常提供了足够的信息来查找问题。您还可以启用各种 QMgr 诊断事件并使用事件查看工具之一查看它们,或者查看通道两端 QMgrs 上的错误日志。


接下来的这些建议与您的诊断无关,除了使用最佳实践构建的 QMgr 通常更不容易出错并且更容易调试。下面是一些未经请求的 MQ 集群最佳实践建议。

  • 放弃TO.[QMGR]频道名称!请改用 [cluster].[qmgr] 名称,例如 DEVCLUS.QM01。这确保您始终拥有专用于每个集群的通道,即使您有重叠的集群。但是,这确实意味着集群名称中不能包含 .,并且必须小于 10 个字符。
  • 对于不是完整存储库的东西,只对一个存储库定义一个显式 CLUSSDR。如果您拥有两个以上的存储库(例如在迁移期间),集群成员将能够通过这种方式找到它。
  • 始终在定义中使用引号。如果您在使某些东西起作用时遇到问题,那么只有一种可能解释的定义是解决问题的捷径。
  • 在定义新的集群通道时给通道一些时间来稳定,并验证它是否启动并进入正确的状态。
  • 使用AMQSPUT 打开新定义的remotely-hosted 簇queue 用于输出,但实际上并没有向它们发送消息。确保在打开期间没有错误(即 queues 解析),然后确保集群通道已启动。 然后执行amqsput并发送消息。
  • REFRESH CLUSTER 是用于部分存储库的命令,而 RESET CLUSTER 是用于完整存储库的命令。在这种情况下,该命令使用不当并且在错误类型的集群节点上使用。期待问题。
  • 希望在现实生活中没有应用程序 queue 托管在完整的存储库 QMgrs 上。您可以为集群做的最好的事情是将完整的存储库托管在专用 QMgrs 上——即使这些是与应用程序 QMgrs 在同一主机上的额外 QMgrs。将它们分开可确保集群操作流量和应用程序流量永远不会穿过相同的通道。它还可以在应用程序 QMgrs 之前修补或升级存储库。