我们使用IBM MQ进行各种微服务之间的集成。应用程序非常关键,我们的目标是零停机时间。我们有一个由三个队列管理器组成的集群,每个队列管理器运行在不同的服务器上(在单独的AWS可用性区域上),例如QM1 on sever1, QM2 on server2 and QM3 on server3
。
我们配置三个ConnectionFactory
,如下所示(注意连接名称列表的差异):
var connectionFactory1 = new MQQueueConnectionFactory();
connectionFactory1.setConnectionNameList("server1,server2,server3");
conectionFactory1.setPort(1414);
....
var connectionFactory2 = new MQQueueConnectionFactory();
connectionFactory2.setConnectionNameList("server2,server3,server1");
conectionFactory2.setPort(1414);
....
var connectionFactory3 = new MQQueueConnectionFactory();
connectionFactory3.setConnectionNameList("server3,server1,server2");
conectionFactory3.setPort(1414);
....
此设置背后的思想是能够同时使用所有三个队列管理器,第一个连接工厂将使用QM1
,第二个连接工厂将使用QM2
,依此类推。
运行IBM Queue Manager的服务器有时需要打补丁并重新启动。当发生这种情况时,显然需要关闭队列管理器。当一个队列管理器关闭时,所有流量将通过集群中的其他两个队列管理器重定向,因此消息流永远不会停止。server1
关闭时:
connectionFactory1
切换到server2,server3
,因此从QM2
消耗connectionFactory2
切换到server2,server3
,因此从QM2
消耗connectionFactory3
切换到server3,server2
,因此从QM3
消耗
修补server 1后,我们启动QM 1。
我们遇到的问题是,三个连接工厂保持如上所述的切换状态,而根本不需要重新连接到QM1
。我们能够恢复所需状态的唯一方法是重新启动应用程序,这实际上不是一个好的/可接受的解决方案。
在我们的客户端代码中,我们实现了一些弹性模式,以确定QM 1何时恢复并重置connectionFactory1
(spring CachingConnectionFactory
Package 在MQQueueConnectionFactory
周围)以及停止和启动所有侦听器容器,这些侦听器容器作为首选队列管理器为QM 1消费,但这没有任何效果。唯一的方法就是重新启动Spring Application Context,但这与重新启动应用程序类似,当你有很多这样的应用程序时,这真的不是一个好的解决方案。
我注意到MQQueueConnectionFactory有一个方法setClientReconnectOptions(int options) throws javax.jms.JMSException
,但是阅读该方法的注解并没有让我很清楚它是否可以用于我们想要的东西。
提前感谢您的意见。
1条答案
按热度按时间h22fl7wq1#
重新连接选项用于在失败后重新建立连接。它不会因为连接集不平衡而影响重新建立连接。
有关可重新连接的客户机的更多信息,请参见IBM文档中的Reconnectable clients。
这不是一个容易从应用程序内部解决的问题,因为它不了解整个环境。这就是为什么IBM MQ现在有一个称为Uniform Clusters with Application Rebalancing的特性,它正好可以做到这一点。当您启动回收队列管理器时,该群集(其具有整套客户端连接的应用程序的图片)注意到不平衡并告诉一些应用程序去别处。它利用客户端应用程序的能力按照上述选项重新连接,但是移动到另一个队列管理器的驱动程序来自当前连接的队列管理器,而不是由客户端确定。
IBM MQ V9.1.2中添加了统一集群特性和应用程序平衡,并在随后的几个CD发行版中进行了增强,因此第一个提供该特性的LTS发行版将是IBM MQ V9.2.0。
有关统一集群的更多信息,请参见IBM文档中的About uniform clusters。