我在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
分享到:
相关推荐
爱普生针式打印机设置乱了,有什么办法快速复原
大班主题头发乱了教案反思.docx
谁拿浮生乱了流年精选.doc
asp.net 后台弹出提示框之后,页面布局乱了,是因为net中使用response.write输出js会将js放在源代码的最前面,这样就可能出现破坏网页css的效果,让css失去效果。
右键修复工具,有时候右键乱了就用它
幼儿园大班主题教案《头发乱了》润新教育.txt
NULL 博文链接:https://wang5598.iteye.com/blog/1183329
为什么U盘里的电视剧在EVD上顺序乱了 简单点说就算用最笨的方法 一个一个复制 不要批量复制
QTe移植到jz2440开发板的详细过程,在网上找的知识太乱了,也纠结了很久,终于搞定了,分享一下从Linuxqt安装到arm qt安装的整个过程,有问题可以留言或者百度都行。
运行此程序将当前桌面上的图标位置保存到注册表中, 将来当桌面图标位置乱了时再运行此程序恢复。 如果恢复后一刷新桌面又乱了,可在刚恢复后手动微移某个图标再刷新一下即可。
1用户员可以在线修改,删除用户资料! 2用户可以初始化数据! 3用户可以可以在线压缩,备份,恢复数据库! 4统计分为年,月,周,日,软件统计等,还有总体数据,查看今年,今月,今周,今日,上月,昨日等统计
动画效果,如果综合使用,还能使用简单的代码简单实现jquery的各种插件的效果 本文参考《《浅谈jquery》一书,加以整理,并结合自己的实际经验而成,可以看做一个 学习手册吧 编辑的时候代码全乱了,重新整理了下,...
增加修正:
增加了UBB功能
电路 硬件工程师 单片机 通信技术 相关技术文档
v3.0修改BUG修改并优化了UBB代码 表情符号采用馒头符号,更加有趣 修改部分版面布局 修改英文不能换行以及插入表情符号不能换行的BUG 管理员和密码:mood8/mood8
功能:
在线修改密码在线管理:添加,编辑,删除支持HTML标记语言支持UBB标记语言,可插入飞行文字、FLASH、图片等,文字编排功能
Ocarina-of-Time-Cloudmodding-text-patches-or-fixed-scene-patches-Final:我固定了Oot房间的演员和对象。 我主要在MQ Debug版本上进行了更多的... 而且,该修补程序不能与MQ Debug的新beta保龄球演员娱乐txt修补程