搭建Websphere MQ集群实现负载均衡(三)

图 11. 选择将信息发送至的完整仓储库队列管理器

最后需要在两个部分仓储库队列管理器上定义各自的集群队列 TEST_QUEUE。如图 12 所示,这里将缺省绑定类型设为不固定。

图 12.在两个部分仓储库队列管理器上定义集群队列

创建完两个集群队列后,可以在两个完整仓储库队列管理器 FULL_QM1 和 FULL_QM2 上看到两个集群队列 TEST_QUEUE。如图 13 所示。

图 13. 创建成功的两个集群队列

在之前显示建立的集群拓扑图中提到,本文只显示建立 PART_QM1 到完整仓储库队列管理器 FULL_QM1 的发送通道。而 PART_QM1 到 FULL_QM2 的发送通道是集群自动建立的。因此,在 PART_QM1 的集群发送通道中可以看到两个发送通道,如图 14 所示,其中 TO.FULL_QM1 发送通道是通过 MQ explorer 显式创建的,定义类型为自动显示集群发送方。而 TO.FULL_QM2 发送通道是系统自动创建的,定义类型为自动集群发送方。

图 14. 队列管理器 PART_QM1 的集群发送通道

________________________________________

使用示例应用程序演示 MQ 集群的负载平衡效果
创建完一个简单的集群后,通过配置可以实现群集的负载均衡效果。本文在集群中定义了集群队列 TEST_QUEUE 的两个同名队列实例,每个队列实例在不同的队列管理器上。当应用程序把消息发送到该集群队列时,MQ 使用负载平衡算法决定消息实际发送哪个队列管理器。
示例程序首先连接到一个完整仓储库队列管理器 FULL_QM1,将绑定的类型设定为 MQOO_BIND_AS_Q_DEF,然后将五个消息放入集群队列 TEST_QUEUE 中,如清单 8 所示。绑定类型设定为 MQOO_BIND_AS_Q_DEF 是把连接到队列的绑定类型指定为队列缺省的绑定类型,本例中为不固定,是在创建集群队列时,通过设置缺省绑定类型指定的,如图 12 所示。

清单 8. 将消息放入集群队列的示例程序
public class ClusterPut {
private static final String HOSTNAME = “127.0.0.1”;
private static final int PORT = 5000;
private static final String CHANNEL = “SYSTEM.DEF.SVRCONN”;
private static final int CCSID = 1208;

//we can also specify FULL_QM2 as queue manager
private static final String QM_NAME = “FULL_QM1”;
private static final String Q_NAME = “TEST_QUEUE”;

public static void main(String[] args) throws Exception {
// Set up WebSphere MQ environment
MQEnvironment.hostname = HOSTNAME;
MQEnvironment.port = PORT;
MQEnvironment.channel = CHANNEL;
MQEnvironment.CCSID = CCSID;

// Create a connection to the QueueManager
MQQueueManager qMgr = new MQQueueManager(QM_NAME);
// Specify the queue that we wish to open and the open options.
//MQOO_BIND_AS_Q_DEF option is specified here, so bind type is determined by
//default queue bind type
// We can also specify MQOO_BIND_ON_OPEN or MQOO_BIND_NOT_FIXED to cover
//default queue bind type
MQQueue queue = qMgr.accessQueue(Q_NAME, MQConstants.MQOO_BIND_AS_Q_DEF
+ MQConstants.MQOO_OUTPUT);
// Define a simple WebSphere MQ Message and write some text in UTF8 format
MQMessage msg = new MQMessage();
msg.writeUTF(“Hello World!”);
// Put five messages to the cluster queue with default put message options
queue.put(msg, new MQPutMessageOptions());
queue.put(msg, new MQPutMessageOptions());
queue.put(msg, new MQPutMessageOptions());
queue.put(msg, new MQPutMessageOptions());
queue.put(msg, new MQPutMessageOptions());
// Close the queue and disconnect from the QueueManager
queue.close();
qMgr.disconnect();
}
}

指定集群队列的缺省绑定类型为不固定,程序第一次运行后,五条消息分别放入部分仓储库队列管理器 PART_QM1 和 PART_QM2 的 TEST_QUEUE 队列中。如果不指定队列等级和优先级,程序运行后,在 PART_QM1 的 TEST_QUEUE 队列中有三条消息,在 PART_QM2 的 TEST_QUEUE 队列中有两条消息。
当集群队列的缺省绑定类型为打开时,如图 15 所示,程序第一次运行后,五条消息都放入 PART_QM1 的 TEST_QUEUE 队列中。程序第二次运行后,五条消息都放入 PART_QM2 的 TEST_QUEUE 队列中。指定为打开时,相当于在程序打开 TEST_QUEUE 集群队列时,就决定要使用哪一个部分仓储库队列管理器上的队列,之后,在程序断开与队列管理器的连接前,所有的消息都放到那个队列里。

图 15. 队列的缺省绑定类型

如果挂起 PART_QM1,则无论绑定类型指定为哪个选项,所有的消息都将发送到 PART_QM2 上的集群队列里。
accessQueue 函数还有另外两个选项 MQOO_BIND_NOT_FIXED 和 MQOO_BIND_ON_OPEN,缺省值为 MQOO_BIND_ON_OPEN。如果指定为 MQOO_BIND_ON_OPEN,消息只发送给某一队列实例,相当于之前把集群队列的缺省绑定类型设定为打开时。在程序中指定绑定的类型为 MQOO_BIND_NOT_FIXED 或者 MQOO_BIND_ON_OPEN 会覆盖集群队列的缺省绑定类型。
________________________________________

使用集群队列时需要注意的几点
如果对消息的逻辑处理有要求,或者对消息的处理顺序有要求,这时需要使用 MQOO_BIND_ON_OPEN 选项。例如,程序 A 向某个集群队列发送两条相互关联的消息,一条消息包含元数据,另一条消息包含实际数据内容,它们之间通过 groupId 相互联系。并且该集群队列在集群的两个队列管理器上各有一个同名集群队列实例。现在程序 B 需要从集群队列中取出相互关联的两条消息进行处理,如果这两条消息分别被发送到了两个不同的集群队列实例中,则程序 B 打开一个集群队列实例后,无法通过其中一条消息的 groupId,在同一个集群队列实例中找到另一条消息。要解决这个问题,可以将相互关联的消息发送到同一个集群队列实例上。在程序 A 将消息放入集群队列时,需要指定 MQOO_BIND_ON_OPEN 选项。
集群只在消息进入时实现负载平衡,一旦消息进入某个队列管理器上的集群队列,它就只能由该队列管理器处理。如果在消息被处理完之前,该队列管理器被挂起或 者发生故障,已经进入该集群队列的消息将不能被处理。即其他队列管理器无法处理该队列管理器上同名的集群队列实例。这一点和 z/OS 的共享队列不同。在 z/OS 平台上,如果使用共享队列,多个队列管理器使用的是同一个队列实例,即使某个队列管理器不工作,其他的队列管理器可以处理该共享队列上的消息。
________________________________________

以下文章点击率最高

Loading…

发表评论