`
阅读更多

 我在IBM MQ7和suse9的环境下做的开发。

 我在发送一个大文件消息时,使用分段的方式进行操作,处理完成后放到远程队列当中,到达下一个目的地。

 如果基于单独的mq的队列管理,如上的方法没有问题。但如果通过远程队列放到一个集群当中时,就会把一个完整的消息体四分五裂。在网上找N多资料,大都是要使用BIND_ON_OPEN做为打开的options。但每次都不管用。

 说下具体情况。

  QM_FIRST 表示要发送的队列管理器

  QM_PROXY 表示集群的代理服务器,也是一个队列管理器,属于集群ANT

       QM_EXE1 一个队列管理器,属于集群ANT,权重25%

       QM_EXE2 一个队列管理器,属于集群ANT,权重25%

       QM_EXE3 一个队列管理器,属于集群ANT,权重25%

       QM_EXE4 一个队列管理器,属于集群ANT,权重25%

 

      QM_FIRST通过对象UR_FIRST_TO_PROXY来完成于PROXY的发送。

 

  目前的效果。


 

  想要达到的效果。

 


 

      说明一下,远程队列的使用方式,远程队列通过一个别名队列QM_PROXY_ALIAS放在集群当中的本地队列当中。


 

  经过反复的论证和测试,发现这个问题的罪魁祸首就是这个远程队列,最后的解决方法是,弃用这个远程队列,直接连接到对方的集群当中的本地队列,也就是如上图的远程队列里。就可以了

  没有代码哟。大家可以自己直接写,比较简单,

 

  部分代码示例。
 private int SINGLE_MSG_MAX_LENGTH = 1048576; // 1M 默认是1M

/**
	 * 分段发送文件.
	 * 
	 * @param b
	 * @param queueName
	 * @throws QueueAccessException
	 */
	@SuppressWarnings("deprecation")
	public void putMessageMultiple(byte[] b, String queueName) throws QueueAccessException {

		MQQueue mqPut = null;
		try {
			mqPut = getPutQueue(queueName);

			int length, m, n;
			int packNum;

			length = b.length;

			m = length / SINGLE_MSG_MAX_LENGTH;
			n = length % SINGLE_MSG_MAX_LENGTH;

			if (n == 0) {
				packNum = m;
			} else {
				packNum = m + 1;
			}

			// second, put the msg to queue

			// 设置放消息时的参数
			for (int packCount = 1; packCount <= packNum; packCount++) {				
				MQMessage myMsg = new MQMessage();
				MQPutMessageOptions pmo = new MQPutMessageOptions();
				pmo.options = MQC.MQPMO_LOGICAL_ORDER + MQC.MQPMO_SYNCPOINT;
				if (packCount == packNum) {
					myMsg.messageFlags = MQC.MQMF_LAST_SEGMENT;
					if (n == 0) {						
						myMsg.write(b, (packCount - 1) * SINGLE_MSG_MAX_LENGTH, SINGLE_MSG_MAX_LENGTH);
					} else {						
						myMsg.write(b, (packCount - 1) * SINGLE_MSG_MAX_LENGTH, n);
					}
				} else {
					myMsg.messageFlags = MQC.MQMF_SEGMENT;
					
					myMsg.write(b, (packCount - 1) * SINGLE_MSG_MAX_LENGTH, SINGLE_MSG_MAX_LENGTH);
				}				
				mqPut.put(myMsg, pmo);
			}

		} catch (MQException e) {

			if (e.completionCode == MQException.MQCC_FAILED && e.reasonCode == MQException.MQRC_UNKNOWN_OBJECT_NAME) {
				throw new InvalidQueueException(queueName + " MQException occur  when getting the messsage.", e);
			} else {
				throw new QueueAccessException(queueName + " MQException occur  when sending  the messsage.", e);
			}

		} catch (IOException e) {

			throw new QueueAccessException(queueName + " IOException occur  when sending  the messsage.", e);
		}
	}

 

/**
	 * 得到发送消息队列的实例
	 */
	@SuppressWarnings("deprecation")
	private MQQueue getPutQueue(String queueName) throws MQException {
		MQQueue queue = null;
		queue = (MQQueue) putQueues.get(queueName);
		if (queue == null) {
			int openOptions = MQC.MQOO_OUTPUT | MQC.MQOO_FAIL_IF_QUIESCING;
			queue = qMgr.accessQueue(queueName, openOptions);
			putQueues.put(queueName, queue);
		}
		return queue;
	}

 

 

如上只是发送的代码。

 

 

如下是取出的代码。

 

 

/**
	 * 从队列中浏览分段消息
	 * 
	 * @param queueName
	 * @return byte[]
	 * @roseuid 447FA30301A0
	 */
	@SuppressWarnings("deprecation")
	public byte[] browseBigMessage(String queueName) throws QueueAccessException {

		byte[] b = null;
		byte[] retbb = null;

		ByteArrayOutputStream out = null;

		MQQueue browseQueue = null;
		try {
			browseQueue = getBrowseQueueBySeq(queueName);
			out = new ByteArrayOutputStream();
			MQMessage inMsg;

			// 设置取消息时的参数
			MQGetMessageOptions gmo = new MQGetMessageOptions();			
			
			gmo.options = MQC.MQGMO_LOGICAL_ORDER + MQC.MQGMO_SYNCPOINT + MQC.MQGMO_ALL_SEGMENTS_AVAILABLE;
			boolean isLastSegment = false;
			while (!isLastSegment) {
				inMsg = new MQMessage();
				browseQueue.get(inMsg, gmo);
				if (inMsg.messageFlags == MQC.MQMF_SEGMENT + MQC.MQMF_LAST_SEGMENT)
					isLastSegment = true;
				b = new byte[inMsg.getMessageLength()];
				inMsg.readFully(b);
				out.write(b);
				out.flush();
				b = null;
			}
			retbb = out.toByteArray();

		} catch (MQException e) {

			if (e.completionCode == MQException.MQCC_FAILED && e.reasonCode == MQException.MQRC_UNKNOWN_OBJECT_NAME) {
				throw new InvalidQueueException(queueName + " MQException occur  when browsing the messsage.", e);
			} else if (!(e.completionCode == 2 && e.reasonCode == 2033)) {
				throw new QueueAccessException(queueName + " MQException occur  when browsing the messsage.", e);
			}
		} catch (IOException e) {

			throw new QueueAccessException(queueName + " IOException occur  when browsing the messsage.", e);
		} catch (NumberFormatException e) {

			throw new QueueAccessException(queueName + " NumberFormatException occur  when browsing the messsage.", e);
		}
		return retbb;
	}


/**
	 * 得到浏览消息队列的实例,分段时实用
	 */
	@SuppressWarnings("deprecation")
	private MQQueue getBrowseQueueBySeq(String queueName) throws MQException {
		MQQueue queue = null;
		queue = (MQQueue) browseQueues.get(queueName);
		if (queue == null) {
			int openOptions = MQC.MQOO_INPUT_SHARED | MQC.MQOO_FAIL_IF_QUIESCING | MQC.MQOO_INQUIRE;// 本属性是browse and
			queue = qMgr.accessQueue(queueName, openOptions);
			browseQueues.put(queueName, queue);
		}
		return queue;
	}

 呵呵。

  • 大小: 39.3 KB
  • 大小: 37.5 KB
  • 大小: 3.9 KB
分享到:
评论

相关推荐

    头发乱了单用户访客统计系统&nbsp;

    《头发乱了单用户访客统计系统:深入解析计数器类的应用》 在数字化信息时代,网站和应用程序的用户行为分析变得至关重要。一个高效、精准的访客统计系统能够为运营者提供宝贵的数据支持,帮助他们理解用户的行为...

    Red5边源服务器集群部署

    通过集群部署,我们可以将Red5的服务扩展到多台服务器上,提高服务的稳定性和处理能力。 集群部署的核心目标是实现负载均衡,即将客户端请求分散到多台服务器,避免单点故障,提升整体系统性能。在Red5的集群部署中...

    乱了心情日记本 v1.01

    通过压缩包文件"QiHooDairyV1.01",我们可以推测这可能是该软件的安装包或者更新文件,用户下载后可以安装或升级到这个版本,享受UBB带来的新特性。为了确保软件的安全性和稳定性,用户应当从官方渠道获取,并遵循...

    乱了心情日记本 v1.02

    在“留言板类”这一标签中,我们可以理解到《乱了心情日记本 v1.02》可能包含了一个互动功能,让用户可以像在传统留言板一样留下自己的想法或者对软件的建议。这种设计不仅使得日记应用更具社交元素,也方便开发者...

    爱普生针式打印机设置乱了,如何快速复原

    在IT领域,打印机是办公环境中不可或缺的设备之一,而爱普生针式打印机以其耐用性和高打印质量在市场中占据了一席之地。然而,在长期使用过程中,由于各种原因,如软件冲突、操作不当或系统更新等,打印机的设置可能...

    知道了这些规则再看电路图就不感觉乱了 硬件工程师电路分析物联网模电单片机嵌入式技术.doc

    在示例中,无线信号从天线输入,经过多个处理阶段,最终通过扬声器输出。反馈电路,如AGC(自动增益控制),其走向与主电路相反,从输出返回输入。 2. **图形符号和画法**:元器件的图形符号可以自由旋转或翻转,以...

    大班主题头发乱了教案反思.docx

    【标签】"文档 互联网 资源"表明这是一份可以通过网络共享的教育资源文档,可能用于教育工作者之间的交流和学习。 **详细知识点:** 1. **主题活动设计**:教师根据自身的变化(烫发)和孩子们的兴趣,生成了...

    乱了心情日记本单用户 V2.1

    《乱了心情日记本单用户 V2.1》是一款专为个人用户设计的日记应用,致力于提供一个私密、安全的记录平台,帮助用户整理思绪,保存生活中的点滴。在这个版本V2.1中,我们可以期待一些关键的功能升级和优化。 首先,...

    乱了心情日记本单用户版 v3.0修正版

    《乱了心情日记本单用户版 v3.0修正版》是一款个人日记应用,主要针对中文用户设计,致力于提供一个私密、有趣的记录心情的空间。在这个修正版中,开发者着重解决了之前版本中存在的一些问题,提高了用户体验。 ...

    Xfire调用webservice无法接收到参数问题解决

    在Xfire中,客户端通过发送SOAP消息到服务端来调用服务,服务端处理请求后返回响应。 标题"Xfire调用webservice无法接收到参数问题解决"指出的核心问题是:当使用Xfire作为客户端调用Web服务时,服务端无法正确接收...

    乱了心情日记本单用户 v3.0

    《乱了心情日记本单用户 v3.0》是一款专为个人用户设计的在线日记管理软件,具备丰富的文本编辑和个性化展示功能。该版本v3.0在前代基础上进行了优化与升级,提供了更加便捷和安全的日记管理体验。下面我们将深入...

    乱了心情日记本单用户版 v3.0 修正版

    总的来说,“乱了心情日记本单用户版 v3.0 修正版”提供了一个全面且安全的环境,让用户能够安心记录和回顾自己的生活,同时通过持续的修正和升级,确保软件的稳定性和易用性。对于喜欢记录生活的人来说,这是一个...

    allegro修改位号回注orCAD原理图

    通过该方法,我们可以快速地将 Allegro 软件中的器件编号同步到 OrCAD 原理图中,从而提高设计效率和准确性。 本文介绍了一种反向回注的方法,旨在解决原理图元器件序号调整的问题。这款方法可以帮助设计者快速地...

    asp页面alert之后页面布局乱了该怎么办?

    asp.net 后台弹出提示框之后,页面布局乱了,是因为net中使用response.write输出js会将js放在源代码的最前面,这样就可能出现破坏网页css的效果,让css失去效果。

    右键修复工具,有时候右键乱了就用它

    右键修复工具,有时候右键乱了就用它

    幼儿园大班主题教案《头发乱了》润新教育.txt

    幼儿园大班主题教案《头发乱了》润新教育.txt

    python-21.均分纸牌-发牌发乱了是吧.py

    python-21.均分纸牌——发牌发乱了是吧.py

    linux5+oracle 10g RAC环境挂载双存储后盘符乱序问题解决办法.docx

    传统方法中依赖于操作系统在启动时扫描硬盘并自动分配盘符,这种方式存在不确定性,因此需要引入更可靠的绑定机制。下面介绍两种解决方案: 1. **使用SCSI_ID绑定裸设备** - 首先,需要通过`scsi_id -g -s /block/...

    谁拿浮生乱了流年精选.doc

    不过,我们可以从中提炼出一些与生活哲学、个人成长和心理状态相关的普遍性主题,这些主题在IT行业中的工作者同样会遇到,例如面对压力、决策和人生选择。 1. **生活与成长**:文档中的“流年”和“浮生”指的是...

Global site tag (gtag.js) - Google Analytics