一、实验前言

场景三:测试高可用,使用连接工厂(多地址连接方式),不通过虚地址实现单节点故障后自动连接备用节点(QMRGRECGC->QMFX)
目的:1.实现主节点故障后能够自动重连到备用节点实现消息不丢失,服务高可用

该架构图与实验二的架构图在两个网关前减少了HA的高可用软件。

具体不一样的是场景三不使用Keepalived作为高可用服务,而采用IBM MQ提供的连接工厂方式,实现程序的主备切换。

二、实验步骤

2.1队列管理器配置

各个队列管理的配置跟实验场景二一样,这里不再重复。

2.2启动回执发送程序

2.3模拟主网关故障

在程序运行过程中停止主网关的客户端连接通道MY.SVRCONN


停止之后,程序应该会抛出异常,并发起重连

已发送:15
已发送:16
已发送:17
已发送:18
====有异常=====
com.ibm.msg.client.jms.DetailedJMSException: JMSWMQ2007: 将消息发送至目标 'TO.HUIZHI' 失败。
JMS 尝试执行 MQPUT 或 MQPUT1;然而 WebSphere MQ 报告了错误。
使用链接的异常来确定此错误的原因。at com.ibm.msg.client.wmq.common.internal.Reason.reasonToException(Reason.java:578)at com.ibm.msg.client.wmq.common.internal.Reason.createException(Reason.java:214)at com.ibm.msg.client.wmq.internal.WMQMessageProducer.checkJmqiCallSuccess(WMQMessageProducer.java:1157)at com.ibm.msg.client.wmq.internal.WMQMessageProducer.checkJmqiCallSuccess(WMQMessageProducer.java:1114)at com.ibm.msg.client.wmq.internal.WMQMessageProducer.access$800(WMQMessageProducer.java:72)at com.ibm.msg.client.wmq.internal.WMQMessageProducer$SpiIdentifiedProducerShadow.sendInternal(WMQMessageProducer.java:843)at com.ibm.msg.client.wmq.internal.WMQMessageProducer$ProducerShadow.send(WMQMessageProducer.java:521)at com.ibm.msg.client.wmq.internal.WMQMessageProducer.send(WMQMessageProducer.java:1283)at com.ibm.msg.client.jms.internal.JmsMessageProducerImpl.sendMessage(JmsMessageProducerImpl.java:838)at com.ibm.msg.client.jms.internal.JmsMessageProducerImpl.synchronousSendInternal(JmsMessageProducerImpl.java:1967)at com.ibm.msg.client.jms.internal.JmsMessageProducerImpl.sendInternal(JmsMessageProducerImpl.java:1913)at com.ibm.msg.client.jms.internal.JmsMessageProducerImpl.send(JmsMessageProducerImpl.java:1469)at com.ibm.mq.jms.MQMessageProducer.send(MQMessageProducer.java:293)at com.datatech.jmstest.Test_CF.sendMsg2(Test_CF.java:202)at com.datatech.jmstest.Test_CF.main(Test_CF.java:171)
Caused by: com.ibm.mq.MQException: JMSCMQ0001: WebSphere MQ 调用失败,完成代码为 '2' ( 'MQCC_FAILED' ),原因为 '2009' ( 'MQRC_CONNECTION_BROKEN' )。at com.ibm.msg.client.wmq.common.internal.Reason.createException(Reason.java:202)... 13 more
Caused by: com.ibm.mq.jmqi.JmqiException: CC=2;RC=2009at com.ibm.mq.jmqi.remote.impl.RemoteSession.getConnection(RemoteSession.java:494)at com.ibm.mq.jmqi.remote.impl.RemoteSession.getMaximumMessageLength(RemoteSession.java:1802)at com.ibm.mq.jmqi.remote.api.RemoteFAP.jmqiPutMessageWithProps(RemoteFAP.java:9860)at com.ibm.mq.jmqi.remote.api.RemoteFAP.jmqiPut(RemoteFAP.java:8968)at com.ibm.mq.ese.jmqi.InterceptedJmqiImpl.jmqiPut(InterceptedJmqiImpl.java:624)at com.ibm.mq.ese.jmqi.ESEJMQI.jmqiPut(ESEJMQI.java:636)at com.ibm.msg.client.wmq.internal.WMQMessageProducer$SpiIdentifiedProducerShadow.sendInternal(WMQMessageProducer.java:831)... 9 more
Caused by: com.ibm.mq.jmqi.JmqiException: CC=2;RC=2202at com.ibm.mq.jmqi.remote.impl.RemoteRcvThread.run(RemoteRcvThread.java:441)at com.ibm.msg.client.commonservices.workqueue.WorkQueueItem.runTask(WorkQueueItem.java:263)at com.ibm.msg.client.commonservices.workqueue.SimpleWorkQueueItem.runItem(SimpleWorkQueueItem.java:99)at com.ibm.msg.client.commonservices.workqueue.WorkQueueItem.run(WorkQueueItem.java:284)at com.ibm.msg.client.commonservices.workqueue.WorkQueueManager.runWorkQueueItem(WorkQueueManager.java:312)at com.ibm.msg.client.commonservices.j2se.workqueue.WorkQueueManagerImplementation$ThreadPoolWorker.run(WorkQueueManagerImplementation.java:1193)
已发送:19
已发送:20
已发送:21
已发送:22
已发送:23
已发送:24
已发送:25
已发送:26
已发送:27
已发送:28
已发送:29

在代码

2.4 确认消息发送和接收数量

发动100个消息后程序停止,在主网关故障切换到备网关后,消息发送没有发生丢失,并正常发送。

三、结论

使用连接工厂方式可以减少高可用架构时候不用第三方的高可用软件,借用IBM MQ自身的方式就可以达到效果,减少一个环节就少一份风险,该代码还有很多优化的空间,本次只是测试是否能达到高可用服务状态,通过实验证明可以达到要求。
该代码中使用的是com.ibm.mq.jms.MQQueueConnectionFactory连接类

附:连接工厂方式测试代码

package com.datatech.jmstest;import java.io.IOException;import javax.jms.DeliveryMode;
import javax.jms.JMSException;
import javax.jms.QueueConnection;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage;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;
import com.ibm.mq.jms.MQQueueConnectionFactory;
import com.ibm.msg.client.wmq.WMQConstants;public class Test_CF {static MQQueueManager qMgr;static int CCSID = 1381;static String queueString = "TO.HUIZHI";static int openOptions = MQConstants.MQOO_OUTPUT | MQConstants.MQOO_FAIL_IF_QUIESCING;static MQQueue queue = null;public static void connect() throws MQException {MQEnvironment.hostname = "192.168.153.200";// MQ服务器IP      MQEnvironment.channel = "MY.SVRCONN";     // 队列管理器对应的服务器连接通道      MQEnvironment.CCSID = 1381;            // 字符编码      MQEnvironment.port = 1417;             // 队列管理器的端口号
//          //MQ中拥有权限的用户名MQEnvironment.userID = "mqm";//用户名对应的密码MQEnvironment.password = "123456";try {      qMgr = new MQQueueManager("QMRGRECGC");// 队列管理器名称      queue = qMgr.accessQueue(queueString, openOptions, null, null, null);} catch (MQException e) {      e.printStackTrace();      }      }public static void sendMsg(String msgStr) {//设置将要连接的队列属性//目标为远程队列,所有这里不可以用MQOO_INPUT_AS_Q_DEF属性//int openOptions = MQC.MQOO_INPUT_AS_Q_DEF | MQC.MQOO_OUTPUT;//以下选项可适合远程队列与本地队列//连接队列//MQQueue provides inquire, set, put and get operations for WebSphere MQ queues.//The inquire and set capabilities are inherited from MQManagedObject./*关闭了就重新打开*/// 建立Q1通道的连接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){try {MQPutMessageOptions pmo = new MQPutMessageOptions();msg.expiry = -1; // 设置消息用不过期msg.writeString(msgStr);queue.put(msg, pmo);// 将消息放入队列}catch(java.net.SocketException e){System.out.println("网络故障,正在切换备用服务");} catch(IOException e){System.out.println("IO故障");//msg.writeString(msgStr);} catch (MQException e) {System.out.println("===="+e.getCompCode()+"============");System.out.println("====网络故障,正在切换备用服务============");try {connect();MQPutMessageOptions pmo = new MQPutMessageOptions();msg.expiry = -1; // 设置消息用不过期try {msg.writeString(msgStr);} catch (IOException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}queue.put(msg, pmo);// 将消息放入队列} catch (MQException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}// TODO Auto-generated catch blocke.printStackTrace();} finally {}System.out.println("已发送:"+count);count++;try {Thread.sleep(2000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}if (queue != null) {try {queue.close();} catch (MQException e) {// TODO Auto-generated catch blocke.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 blocke.printStackTrace();} finally {if (queue != null) {try {queue.close();} catch (MQException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}public static void main(String[] args) throws MQException {connect();sendMsg2("我来测试一下");//  receiveMsg();}public static void sendMsg2(String msg){MQQueueConnectionFactory connectionFactory = null;QueueConnection queueConn = null;QueueSession queueSession = null;QueueSender queueSender = null;TextMessage message = null;try{System.out.println("===进入========");connectionFactory = new MQQueueConnectionFactory();connectionFactory.setConnectionNameList("192.168.153.128(1417), 192.168.153.129(1417)");connectionFactory.setTransportType(WMQConstants.WMQ_CM_CLIENT);connectionFactory.setQueueManager("QMRGRECGC");connectionFactory.setChannel("MY.SVRCONN"); queueConn = connectionFactory.createQueueConnection("mqm","123456");queueSession = queueConn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); queueSender = queueSession.createSender(queueSession.createQueue("TO.HUIZHI"));  queueSender.setDeliveryMode(DeliveryMode.NON_PERSISTENT);  message = queueSession.createTextMessage(msg);message.setJMSCorrelationID("12345");int count=1;while(true){try{queueSender.send(message);    System.out.println("已发送:"+count);count++;Thread.sleep(2000);} catch (Exception e){System.out.println("====有异常=====");queueConn = connectionFactory.createQueueConnection("mqm","123456");queueSession = queueConn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); queueSender = queueSession.createSender(queueSession.createQueue("TO.HUIZHI"));  queueSender.setDeliveryMode(DeliveryMode.NON_PERSISTENT);  message = queueSession.createTextMessage(msg);message.setJMSCorrelationID("12345");queueSender.send(message);    System.out.println("已发送:"+count);count++;}}} catch (Exception e){e.printStackTrace();}finally{if (queue != null) {try {queueSender.close();queue.close();} catch (MQException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (JMSException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}
}

第四章 实验三IBM MQ测试高可用,使用连接工厂(多地址连接方式)相关推荐

  1. 软件测试的硬件资源,实验三计算机硬件软件资源测试与浏览.docx

    实验三计算机硬件软件资源测试与浏览 PAGE \* MERGEFORMAT4 实验三 计算机硬件.软件资源查询与硬件测试 (一).实验教学目标 1.知道计算机系统的组成(软件.硬件),掌握查询计算机软 ...

  2. R语言入门第四集 实验三:数据可视化

    R语言入门第四集 实验三:数据可视化 一.资源 [R语言]R语言数据可视化--东北大学大数据班R实训第三次作业 在r中rowsums_R语言初级教程(15): 矩阵(下篇) R语言环境变量的设置 环境 ...

  3. linux虚拟机主从实验,主从模型的ipvs高可用集群实验

    主从模型的ipvs高可用集群实验 一.实验拓图 二.实验环境 本实验是keepalived+lvs-dr的高可用负载均衡实验 本实验是在虚拟机上完成,因此如上拓扑图需要准备至少四台虚拟机 1.各节点的 ...

  4. Linux 笔记 - 第十八章 Linux 集群之(三)Keepalived+LVS 高可用负载均衡集群

    一.前言 前两节分别介绍了 Linux 的高可用集群和负载均衡集群,也可以将这两者相结合,即 Keepalived+LVS 组成的高可用负载均衡集群,Keepalived 加入到 LVS 中的原因有以 ...

  5. 2022-3-1 王爽《汇编语言》第四章 实验

    一.调大窗口 原来的窗口太小了,快看瞎了,全屏又不好截图.下面是放大屏幕的方法. 在 dosbox 的配置文件中将 DOSBox 0.74-3 Options 当中的 改为: 参考文章:调整DOSBO ...

  6. 北京交通大学 管理信息系统 第四章.管理信息系统的应用 测试答案

    北京交通大学 管理信息系统 第四章 测试答案 1.ERP系统的核心功能模块是( ). A.BPR B.MIS C.MRPII D.CIMS 正确答案:C 2.闭环的MRP是在MRP的基础上发展起来的一 ...

  7. 白话SpringCloud | 第三章:服务注册与发现-高可用配置(Eureka)-下

    2019独角兽企业重金招聘Python工程师标准>>> 前言 上一章节,讲解了在单机模式下的服务注册与发现的相关知识点及简单示例.而在实际生产或者在这种微服务架构的分布式环境中,需要 ...

  8. Kafka学习之路 (三)Kafka的高可用

    一.高可用的由来 1.1 为何需要Replication 在Kafka在0.8以前的版本中,是没有Replication的,一旦某一个Broker宕机,则其上所有的Partition数据都不可被消费, ...

  9. Redis(三)主从复制实现高可用(redis—sentinel)

    1.哨兵模式 哨兵模式是redis高可用的实现方式之一.使用一个或者多个哨兵(Sentinel)实例组成的系统,对redis节点进行监控,在主节点出现故障的情况下,能将从节点中的一个升级为主节点,进行 ...

  10. 高并发负载均衡(四):基于keepalived的LVS高可用搭建

    LVS四层 & Nginx七层 对比 你要分清哪些程序是应用层的,哪些程序是内核的. LVS四层负载均衡服务器,是不会碰握手这一个步骤的. Nginx是基于反向代理(七层)的负载均衡服务器,要 ...

最新文章

  1. angular学习笔记(四)- input元素的ng-model属性
  2. mysql 主机类型_实现在别的电脑上访问主机的mysql
  3. 在Oracle 11g中用看Oracle的共享内存段---------IPCS
  4. 安装MySQL Workbench 6.3.4 CE (winx64)出错KERNELBASE.dll的解决方案
  5. oracle 10G windows启动与关闭另类方法
  6. 结对编程(黄金点游戏)
  7. apache2 配置php,Windows配置PHP5与Apache2
  8. 笑死了,打错一个字,竟然...
  9. middle函数C语言,C语言函数调用栈(三)
  10. 游三圣乡山中湖岛有感
  11. Linux i2c子系统驱动probe
  12. Java的文件流操作
  13. 数学大家闵嗣鹤:生死哥德巴赫猜想
  14. 14 [虚拟化] 虚存抽象;Linux进程的地址空间
  15. printf打印结构体_工程师:这道题80%初学者都没做对!你确定搞懂结构体内存对齐了?...
  16. header+php+xiazai_php通过header方法实现文件下载
  17. 软件工程实验报告:图书管理系统
  18. 人机交互技术:利用声波识别手势 Gesture Control System Uses Sound Alone
  19. java生成二维码海报,面经解析
  20. 采用头插法和尾插法建立单链表

热门文章

  1. 华为模拟器——eNSP安装教程
  2. Mimics和Amira在医学影像处理中的应用介绍
  3. FFmpeg 视频处理工具讲解
  4. oracle 密码过期处理
  5. Verilog:三段式状态机(数字钟)
  6. C语言存储误差,C语言实现测量数据误差处理
  7. oracle startup open ora 03113,oracle宕机,startup报错ora03113
  8. qt中使用mysql模糊查询_mysql数据库模糊查询简介
  9. 利用 nodejs 解析 m3u8 格式文件,并下 ts 合并为 mp4
  10. html5表格制作教程,html怎么做表格