关于WebSphere MQ异常:MQ 队列管理器立即关闭通道,关闭原因2009

hidden_wing 2006-12-27 02:52:26
请教各位大虾:
客户端连接到队列管理器所在的服务器进行消息接收时,如果长时间该队列中一直没有消息可以取,但是客户接收程序还继续运行,过一段时间MQ就会报如下异常:

com.ibm.mqservices.MQInternalException: MQJE001:发生 MQException:完成码 2,原因码 2009
MQJE016:连接期间,MQ 队列管理器立即关闭通道
关闭原因 = 2009

导致队列管理器的消息通道关闭,发送方无法再放置消息,除非将导致该通道关闭异常的客户端接收接收程序关闭,这样队列管理器就恢复正常了,但是我还不想让接收程序关闭,不知道怎样避免这种情况的发生,有什么解决方案?导致这种情况的原因是什么?

我的队列管理器是建在UNIX环境下,只定义了一个消息通道类型为SVRCONN:
DEFINE CHANNEL(S_QM_APSIS_TEST) CHLTYPE(SVRCONN) MAXMSGL(104857600) REPLACE
采用的通讯方式为将消息放置到Server端的本地队列中,客户端从到该Server端的本地队列中取得消息;当客户端需要返回消息给服务器端时,客户端发往服务器端的队列,不知道我的这个通道就是属于MQI通道类型?我看网上好多资料都是建立多个通道:发送方,接收方和服务器端通道,不知道这种通道什么情况下使用,对通道的类型及每种类型什么情况下使用不是很清楚,还望大家多多帮忙指教,谢谢!!:)
...全文
4259 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
strive 2010-06-08
  • 打赏
  • 举报
回复
上面的两位哥哥,我也曾碰见过这样的问题,现在我又碰见一个关于MQ的问题,希望二位看到能给予一定 的解答,就是我用命令建立的MQ的队列管理器以及队列,现在不知道如何设置将其队列管理器自动启动,比如服务器忽然断电,重启以后,我的MQ队列管理器能自动启动,这个MQ的命令是什么?
liusdream 2007-03-19
  • 打赏
  • 举报
回复
问题会不会是在于当抛出异常时qMgr.disconnect();这句无法执行,造成连接没有关掉,程序运行时间长了就连接数达到最大了,就无法再新建连接了,抛出最上面说到的异常?
hidden_wing 2006-12-31
  • 打赏
  • 举报
回复
祝愿所有坛中的朋友们新年快乐
bluemac 2006-12-29
  • 打赏
  • 举报
回复
是的,每次调用q.get就取出一条消息,如果你读消息的选项作了特别的设置,这次调用可以把多条消息取出来,组装成一条消息返回结你,这多条消息是在发送方发送时被分解开来的一组消息。对于MQ来说,它是不知道你的对象是什么东西的,它只知道返回一个字节流给你,就是一条消息,你喜欢说这个字节流是什么随你的便。

另外你这里的程序是代码的一部分吧,主程序是怎么个运行的?因为你这段程序每次连接MQ,取出所有消息就断开连接了,如果程序到这里就退出了,那你最初说的那个问题是怎么出现的呢?

最后谢谢你的鼓励,希望这个论坛能实现我的新年愿望:让使用IBM软件的人不再感到孤单。
hidden_wing 2006-12-29
  • 打赏
  • 举报
回复
下边是我的主程序的代码:

import java.util.logging.Logger;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class ThreadMain extends Thread
{
Log logger = LogFactory.getLog("ThreadMain");

public void run()
{
execute();
}

public synchronized void execute()
{
while (true)
{
RSVMonitorIndexReturnAction action = new RSVMonitorIndexReturnAction ();
action.start();
try
{
Thread.sleep(6000);
}
catch (InterruptedException e)
{
logger.info("InterruptedException:"+e.getMessage());
e.printStackTrace();
}
}
}
public static void main(String[] args)
{
//启动接收程序
try
{
ThreadMain threadmain = new ThreadMain();
threadmain.start();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
hidden_wing 2006-12-28
  • 打赏
  • 举报
回复
呵呵~~说“终于”是因为MQ的问题一般很少有人回复,蓝色机器哥哥不要介意,是因为难得才有如此感慨。先谢谢你的回复。
我看了一下错误日志,内容如下:
AMQ9513: Maximum number of channels reached.

EXPLANATION:
The maximum number of channels that can be in use simultaneously has been
reached. The number of permitted channels is a configurable parameter in the
queue manager configuration file.
ACTION:
Wait for some of the operating channels to close. Retry the operation when some
channels are available.

看日志说的好像跟网络没有关系,而且MQ的这个问题我已经测试过很多次了,才发现的这个规律,应该跟网络的关系比较小吧!日志的意思好像这个通道的数量已经达到最大值了,但是我的通道就一个啊,它的意思是指连接到该通道上的实例数吗?怎么看这个数量呢,或者这个数量可以设置吗?这个问题确实很头疼,不知道应该怎么解决。
象蓝色机器说的“做一次new QueueManager()的调用”,难道我还需要写这样单独一个程序,每当发现有这样的问题,我就要调用一下?
bluemac 2006-12-28
  • 打赏
  • 举报
回复
为什么要说“终于”?3点钟发的帖,5点半就有人答了,打IBM的技术支持热线都未必有这么快。
你的这个现象的确是非常罕见,服务器连接通道只是一个入口的名字,并没有一个真正的通道进程,所以这时最好检查一下MQ的错误日志,看一下有没有其他的系统错误,比如防火墙阻塞了连接,路由器重设了链接之类的。
所谓重新做一次连接操作,就是再做一次new QueueManager()的调用,用这个新的对象去操作队列,而不用那个前面产生的Qmgr对象,那个对象因为连接中断的原故,已经不能用了。
hidden_wing 2006-12-28
  • 打赏
  • 举报
回复
还得让大家帮帮忙,为了方便找出导致通道关闭的原因,现将接收消息的代码贴出来,如下:

import org.dom4j.Document;

import com.ibm.mq.*;

public class RSVMonitorIndexReturnAction extends Thread {

/**
* @function 以多线程的方式接收信息<br>
* @author hidden_wing<br>
*/

public void run() {
Document doc = null;
try {
String qName = QL;
//设置MQ的环境变量
MQEnvironment.hostname = 10.6.12.33;
MQEnvironment.channel = S_QM;
MQEnvironment.CCSID = 819;
MQEnvironment.port = 1414;

MQEnvironment.properties.put(MQC.TRANSPORT_PROPERTY,
MQC.TRANSPORT_MQSERIES_CLIENT);

// 连接到队列管理器
MQQueueManager qMgr = new MQQueueManager(qManager);

// 设置打开属性
int openOptions = MQC.MQOO_INPUT_SHARED
| MQC.MQOO_FAIL_IF_QUIESCING;

// 打开队列
MQQueue queue = qMgr.accessQueue(qName, openOptions, null, null,
null);

// 从消息读取用户数据
MQMessage msg = null;

//获取队列中的所有消息
while ((msg = fetchMsg(queue)) != null) {
doc = (Document) msg.readObject();
......
}

// 提交事务
qMgr.commit();
// 关闭队列和队列管理器对象
queue.close();
qMgr.disconnect();

} catch (MQException ex) {
log.info("接收MQ出现错误:" + ex.getMessage());
} catch (Exception e) {
if(e.getMessage()!=null){
log.info("出现错误:" + e.getMessage());
}
}
}

/**
* @function 获取队列中的消息<br>
* @author hidden_wing<br>
* @param MQQueue q --定义一个MQQueue类型的对象来获取消息缓冲区中的消息
*/

private MQMessage fetchMsg(MQQueue q) throws Exception {
MQGetMessageOptions mgo = new MQGetMessageOptions();
mgo.options |= MQC.MQGMO_NO_WAIT;
MQMessage msg = new MQMessage();
try {
//获取消息
q.get(msg, mgo);
} catch (MQException e) {
return null;
}
return msg;
}
}

说明:RSVMonitorIndexReturnAction 类是通过一个多线程的方式每隔6秒钟调用一次,在RSVMonitorIndexReturnAction 类中我通过一个while循环,来将队列中现有的消息一次取出,不知道这种实现方式在逻辑上是否有问题,是否存在一些没有释放的资源?

另外问个问题,q.get(msg, mgo)方法是调用一次就取一条消息吗?例如我的程序中消息是一个document对象,那么是不是每调用一次get方法就取出一个document对象,而不是多个?

再次谢谢蓝色机器的技术支持,你的精神实属伟大,向你学习,呵呵~~:)
bluemac 2006-12-28
  • 打赏
  • 举报
回复
这个最大通道数是可以调整的,每一次有一个客户机连接上来就认为开了一个通道,所以默认的参数100可能不足够,这个参数的名字是MaxChannels,修改的办法最好看一下文档,因为Windows和UNIX的办法很不一样,说起来费劲。
关于再做一次new QueueManager()的调用,逻辑是这样的,你运行一个程序,这个程序调用了这个方法一次,获得一个Qmgr对象,然后做队列操作,开始的时候还是可以的,可是到了后来,操作出错了,抛了个异常告诉你连接已经断开了。假设队列管理器一切正常,那你该怎么办?如果队列管理器本身又不正常,那又该怎么办?下面的不用我说了吧。
hidden_wing 2006-12-27
  • 打赏
  • 举报
回复
终于看到有人回复了,我的应用程序不是JMS,而是利用MQ的开发包开发的接收与发送程序。可能我没有描述清楚,关掉导致通道关闭的客户端接收程序,通道才能恢复正常,不是队列管理器恢复正常,因为我现在发送和接收消息都是用一个通道,所有的客户端要接收消息都要通过一个通道,所以其中有一个客户端的接收程序导致通道关闭,就会导致其它应用程序进行放置和接收消息时都不行,这个是我经过长期观察出来的,我也很郁闷,不知道为什么会出现这种情况??

不太明白楼上说的“让这个程序再做一次连接的操作,也不需要关闭程序”是怎样一个方式?
bluemac 2006-12-27
  • 打赏
  • 举报
回复
一般资料上说的MQ通道都是在两个队列管理器间建立的连接配置,只有服务器连接通道和客户机连接通道两种才适合你现在的环境,就是一台机器上有一个队列管理器,另一种说法就是MQ服务器,另一台机器上运行一个MQ应用程序,并没有运行队列管理器,这个MQ应用程序就是通过服务器连接通道连接队列管理器的。
2009代码表示和队列管理器的连接已经断开,看样子,你的应用程序是个JMS程序,不过要把程序关掉才能够“这样队列管理器就恢复正常了”就不太合常理了,一个连接断掉不会引起队列管理器发生问题,你要做的最多是让这个程序再做一次连接的操作,也不需要关闭程序。
hidden_wing 2006-12-27
  • 打赏
  • 举报
回复
自己顶一下,各位MQ高手、大虾帮帮忙啊!难道没有人碰到过类似的问题吗?

2,633

社区成员

发帖
与我相关
我的任务
社区描述
WebSphere 是 IBM 的软件平台。它包含了编写、运行和监视全天候的工业强度的随需应变 Web 应用程序和跨平台、跨产品解决方案所需要的整个中间件基础设施,如服务器、服务和工具。
社区管理员
  • WebSphere社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧