ibmmq高可用java_第二章 实验一IBM MQ集群高可用+负载均衡接收消息

一、实验前言

场景一:MQ集群负载均衡接收消息

从QMFX发送消息到MYCLUSTER集群(QMFX->MYCLUSTER),使消息能够负载分发到2个节点上,并且在发送过程中2个网关(QMRGRECGC其中任意一个宕机不影响正常发送。

目的:1.能够达到负载均衡;2.达到网关高可用

在MyCluster集群中两个网关队列管理器(QMRGRECGC)是双活的,都能提供正常服务,因此在发送端配置连接信息时,可以利用MQ8.0以上自带的主备切换性能达到数据传输的高可用。

高可用负载均衡MQ架构图:

ibmmq高可用java_第二章 实验一IBM MQ集群高可用+负载均衡接收消息_第1张图片

二、高可用主备切换测试

先看发送端的MYCLUSTER.QLRECFX通道的配置,连接名称为192.168.153.129(1417),192.168.153.128(1417)

2.1 确认发送端通道连接信息

这样配置后就自动实现了优先连接192.168.153.129(1417),当第一个连接断开无法连接后会自动切换到192.168.153.128(1417)的连接。

ibmmq高可用java_第二章 实验一IBM MQ集群高可用+负载均衡接收消息_第2张图片

通过MYCLUSTER.QLRECFX通道的通道状态查看当前连接的是192.168.153.129(1417)

ibmmq高可用java_第二章 实验一IBM MQ集群高可用+负载均衡接收消息_第3张图片

进一步验证,在网关192.168.153.129上查看MYCLUSTER.QLRECFX接收通道的通道连接状态,可以看到192.168.153连接着。

网关192.168.153.129上查看MYCLUSTER.QLRECFX接收通道是RUNINNG状态

ibmmq高可用java_第二章 实验一IBM MQ集群高可用+负载均衡接收消息_第4张图片

通道内的连接信息正是192.168.153.1

ibmmq高可用java_第二章 实验一IBM MQ集群高可用+负载均衡接收消息_第5张图片

而此时另一个网关192.168.153.128:1417上的状态应该是“不活动”状态

注:不活动状态代表当前没有任务对象连接到该通道

ibmmq高可用java_第二章 实验一IBM MQ集群高可用+负载均衡接收消息_第6张图片

2.2 启动消息发送

下一步启动消息发送,从QMFX端发送到MyCluster,在发送过程中强制中断当前连接的192.168.153.129:1417上的通道,看是否会自动切换到192.168.153.128:1417上。

ibmmq高可用java_第二章 实验一IBM MQ集群高可用+负载均衡接收消息_第7张图片

2.3 停止主网关通道并观察发送端通道切换状态

手工停止192.168.153.129:1417上的MYCLUSTER.QLRECFX通道

ibmmq高可用java_第二章 实验一IBM MQ集群高可用+负载均衡接收消息_第8张图片

然后观察发送端的通道连接情况

从这里看已正常切换到192.168.153.128:1417

在自动切换过程中发送端的通道会自动重试10次与原来的通道连接,若是不同之后再进行切换,切换过程中,传输队列中是禁止取数据的,稍微有点积压消息(积压的消息量视通道切换完成的时间有关),当切换完成发送通道为运行状态后,传输通道中的消息才会正常发送。

ibmmq高可用java_第二章 实验一IBM MQ集群高可用+负载均衡接收消息_第9张图片

通道已切换成功,且把积压的消息发送完毕

ibmmq高可用java_第二章 实验一IBM MQ集群高可用+负载均衡接收消息_第10张图片

重试的次数是可以自定义配置的,如下图

ibmmq高可用java_第二章 实验一IBM MQ集群高可用+负载均衡接收消息_第11张图片

2.4 消息发送完毕确认负载均衡情况

程序设定发送100条报文后退出。

ibmmq高可用java_第二章 实验一IBM MQ集群高可用+负载均衡接收消息_第12张图片

此时在Mycluster集群的两个数据节点上看看消息的分布情况。

MQPROD1上的QLRECENTRY本地队列当前队列深度为50

ibmmq高可用java_第二章 实验一IBM MQ集群高可用+负载均衡接收消息_第13张图片

MQPROD2上的QLRECENTRY本地队列当前队列深度为50

ibmmq高可用java_第二章 实验一IBM MQ集群高可用+负载均衡接收消息_第14张图片

三、结论

从上面可以看出两个节点的消息分布是均匀的,达到了负载均衡的效果,且在网关故障切换后没有发送数据丢失情况

附:发送消息测试代码

package com.fx.jmstest;

import java.io.IOException;

import com.ibm.mq.MQC;

import com.ibm.mq.MQEnvironment;

import com.ibm.mq.MQException;

import com.ibm.mq.MQGetMessageOptions;

import com.ibm.mq.MQMessage;

import com.ibm.mq.MQPutMessageOptions;

import com.ibm.mq.MQQueue;

import com.ibm.mq.MQQueueManager;

import com.ibm.mq.constants.CMQC;

import com.ibm.mq.constants.MQConstants;

public class Test {

static MQQueueManager qMgr;

static int CCSID = 1381;

static String queueString = "TO.GA";

public static void connect() throws MQException {

MQEnvironment.hostname = "192.168.153.1";// MQ服务器IP

MQEnvironment.CCSID = 1381; // 字符编码

MQEnvironment.port = 1414; // 队列管理器的端口号

// //MQ中拥有权限的用户名

MQEnvironment.userID = "MUSR_MQADMIN";

//用户名对应的密码

MQEnvironment.password = "123456";

try {

qMgr = new MQQueueManager("QMFX");// 队列管理器名称

} catch (MQException e) {

e.printStackTrace();

}

}

public static void sendMsg(String msgStr) {

//设置将要连接的队列属性

int openOptions = MQConstants.MQOO_OUTPUT | MQConstants.MQOO_FAIL_IF_QUIESCING;

/*关闭了就重新打开*/

MQQueue queue = null;

try {

// 建立Q1通道的连接

queue = qMgr.accessQueue(queueString, openOptions, null, null, null);

MQMessage msg = new MQMessage();// 要写入队列的消息

msg.format = MQConstants.MQFMT_STRING;

msg.characterSet = CCSID;

msg.encoding = CCSID;

// msg.writeObject(msgStr); //将消息写入消息对象中;

boolean Flag;

Flag=true;

int count=1;

while(Flag)

{

msg.writeString(msgStr);

MQPutMessageOptions pmo = new MQPutMessageOptions();

msg.expiry = -1; // 设置消息永不过期

queue.put(msg, pmo);// 将消息放入队列

System.out.println("已发送:"+count);

if(count==100){

//设置发送100条报文就停止发送

Flag=false;

}

count++;

Thread.sleep(2000);

}

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

} finally {

if (queue != null) {

try {

queue.close();

} catch (MQException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

public static void receiveMsg() {

int openOptions = MQC.MQOO_INPUT_AS_Q_DEF | MQC.MQOO_OUTPUT | MQC.MQOO_INQUIRE;

MQQueue queue = null;

try {

queue = qMgr.accessQueue(queueString, openOptions, null, null, null);

System.out.println("该队列当前的深度为:" + queue.getCurrentDepth());

System.out.println("===========================");

int depth = queue.getCurrentDepth();

// 将队列的里的消息读出来

while (depth-- > 0) {

MQMessage msg = new MQMessage();// 要读的队列的消息

MQGetMessageOptions gmo = new MQGetMessageOptions();

queue.get(msg, gmo);

System.out.println("消息的大小为:" + msg.getDataLength());

System.out.println("消息的内容:\n" + msg.readStringOfByteLength(msg.getDataLength()));

System.out.println("---------------------------");

}

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

} finally {

if (queue != null) {

try {

queue.close();

} catch (MQException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

public static void main(String[] args) throws MQException {

connect();

sendMsg("我来测试一下");

// receiveMsg();

}

}

你可能感兴趣的:(ibmmq高可用java)