java - 服务器连接 channel 的 mq 连接过多,这些连接不是由队列创建的

标签 java jms ibm-mq websphere-8 message-driven-bean

根据我们的配置,WAS 版本为 8.5.5.11,IBM MQ 版本为 7.5.0.3。我们使用 2 个 channel 连接到 WMQ,其中一个 channel 的 MAXINST 设置为 250,另一个 channel 设置为 500。两者的 SHARECNV 都设置为 10。现在,我们在队列管理器中设置了最多 2000 个连接的上限,但在 WAS 服务器连续运行 3-4 天后,我们最终超出了该限制。 经过一些分析后,我们可以看到在任何时间点我们都只有 120-160 个 Activity 连接。 DIS CONN 命令显示了许多 OBJNAME、OBJTYPE 为空且 ASTATE“NONE”的连接。即使这些连接是从我们的 WAS 服务器 IP 建立的,但它们似乎不是由队列创建的,因为 OBJTYPE 不是这些连接的队列。这些连接在一段时间内持续增长,最终达到 2000 个连接的限制。

有人可以帮助确定创建这些连接的原因并确保它们像正常的空闲连接一样关闭。 这就是应用程序中建立和关闭连接的方式:我们有一个由所有 MDB 扩展的抽象 bean 类。

@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue") })
public class TrackBeanV2 extends AbstractServiceBean implements MessageListener {//code}

abstrack bean 按以下方式处理连接的创建和关闭:

public abstract class AbstractServiceBean {
@Resource(name = "myQCF", type = QueueConnectionFactory.class, shareable =     true, description = "Reply Connection Factory")
private ConnectionFactory replyCF; 

@PostConstruct
private void postConstruct() {
    replyConnection = replyCF.createConnection();

}  catch (JMSException e) {
    throw new RuntimeException("Failed to create JMS Connection");
}

}
@PreDestroy
private void preDestroy() {
try {
    replyConnection.close();
} catch (JMSException e) {
    throw new RuntimeException("Failed to close JMS connection", e);
}
}

private void sendResponseMessage(String outputMessageText, String  jmsMessageID , Destination replyDestination) {
TextMessage replyMessage = null;
try {           
    createSession();    
    createProducer();
    replyMessage = createReplyMessage(outputMessageText , jmsMessageID);    
    sendReply(replyMessage, replyDestination);  
    closeProducer();
    closeSession();
} catch (JMSException exp) {
    handleException(exp);
}
}
private void createSession() throws JMSException{
replySession = replyConnection.createSession(true, 0);                  
}`
private void createProducer() throws JMSException{                              
replyProducer = replySession.createProducer(null);      
}

private void closeSession() throws JMSException {
if (replySession != null) {
    replySession.close();
}
}

private void closeProducer() throws JMSException{
if (replyProducer != null) {            
    replyProducer.close();          
}
}   
private void sendReply(TextMessage replyMessage, Destination replyDestination) throws JMSException {    
logMessages(replyMessage.getText(), "RESPONSE MESSAGE");
replyProducer.send(replyDestination, replyMessage);
}

以下命令的输出

echo "DIS CONN(*) TYPE(*) CONNAME CHANNEL OBJNAME OBJTYPE" | mqsc -e -m QPDC1GC2 -p width=1000 | grep -o '^\w\+:\|\w\+[(][^)]\+[)]' | awk -F '[()]' -v OFS="," 'function printValues() { if ("CHANNEL" in p) { print p["CHANNEL"], p["CURSHCNV"], p["CONNAME"],p["CHSTADA"],p["CHSTATI"],p["LSTMSGDA"],p["LSTMSGTI"],p["OBJNAME"],p["OBJTYPE"],p["ASTATE"],p["APPLDESC"],p["APPLTAG"] } } /^\w+:/ { printValues(); delete p; next } { p[$1] = $2 } END { printValues() }' | grep MYCHANNEL 

看起来像这样

A.QMGR1.MYCHANNEL,,10.217.278.15,,,,,VALIDATE_GET_01,QUEUE,ACTIVE,WebSphere MQ Channel,WebSphere MQ Client for Java
A.QMGR1.MYCHANNEL,,10.217.278.15,,,,,,,NONE,WebSphere MQ Channel,WebSphere MQ Client for Java
A.QMGR1.MYCHANNEL,,10.217.278.15,,,,,,,NONE,WebSphere MQ Channel,WebSphere MQ Client for Java
A.QMGR1.MYCHANNEL,,10.217.278.15,,,,,,,NONE,WebSphere MQ Channel,WebSphere MQ Client for Java
A.QMGR1.MYCHANNEL,,10.217.278.15,,,,,,,NONE,WebSphere MQ Channel,WebSphere MQ Client for Java
A.QMGR1.MYCHANNEL,,10.217.278.15,,,,,,,NONE,WebSphere MQ Channel,WebSphere MQ Client for Java
A.QMGR1.MYCHANNEL,,10.217.278.15,,,,,VALIDATE_GET_01,QUEUE,ACTIVE,WebSphere MQ Channel,WebSphere MQ Client for Java
A.QMGR1.MYCHANNEL,,10.217.278.15,,,,,GETDETAILSGET_01,QUEUE,NONE,WebSphere MQ Channel,WebSphere MQ Client for Java

这是qm.ini中的配置。

Channels:
MaxChannels=2000
MaxActiveChannels=2000

注释中提供的命令的输出:

   "841DD95801B5DC20","A.QMGR1.MYCHANNEL","10.217.278.15","GETDETAILSGET_01","QUEUE","ACTIVE","WebSphere MQ Channel","WebSphere MQ Client for Java","MQOO_INPUT_SHARED,MQOO_BROWSE,MQOO_INQUIRE,MQOO_SAVE_ALL_CONTEXT,MQOO_FAIL_IF_QUIESCING"
   "841DD958AB2CF820","A.QMGR1.MYCHANNEL","10.217.278.15","GETDETAILSGET_01","QUEUE","NONE","WebSphere MQ Channel","WebSphere MQ Client for Java","MQOO_INPUT_SHARED,MQOO_INQUIRE,MQOO_SAVE_ALL_CONTEXT,MQOO_FAIL_IF_QUIESCING,MQOO_NO_READ_AHEAD"

最佳答案

这些症状表明您的应用程序连接未正确关闭。我有 IBM MQ 管理员背景,而不是 Java 开发背景,但根据您迄今为止发布的内容,在我看来您正在尝试正确关闭连接。希望有更多 IBM MQ 类 JMS 开发背景的人可以看一下。 @罗杰?

<小时/>

以下脚本将显示特定 channel 名称的 channel 实例数。它还将显示该 channel 实例中的共享对话总数、唯一 CONN 的数量以及 CONN 打开的对象总数(包括未打开对象的 CONN)。请注意,当 IBM MQ 客户端进程连接到队列管理器时,将创建到队列管理器的唯一 CONN,如果该进程打开队列管理器、队列或主题等对象,DIS CONN 将显示这些打开的对象也是如此。

这可能有助于观察这些数字随着时间的推移而增加的情况,从而帮助您了解所遇到的连接/ channel 泄漏。

<小时/>

示例输出:

./mq-info.ksh MQ.CHANNEL.NAME QMGR.NAME
Total Number of channel instances: 53
Total shared conversations: 94
Unique CONNs: 94
Objects opened by CONNs:
     15 ""
     45 "QMGR"
    120 "QUEUE"

请注意,如果 channel 配置的 SHARECNV 至少为 1,则共享对话总数唯一 CONN 的值应始终匹配。

在示例输出中,共享对话的 15 个没有打开的对象。其余 70 个共享对话的队列管理器本身打开 45 次,队列对象打开 120 次。

<小时/>

mq-info.ksh 如下:

#!/bin/ksh

CHL=${1}
QMGR=${2}
echo "Total Number of channel instances: $(echo "DIS CHS(${CHL}) ALL"|runmqsc $QMGR| grep -o '^\w\+:\|\w\+[(][^)]\+[)]' | awk -F '[()]' -v OFS="," 'function printValues() { if ("CHANNEL" in p) { print p["CHANNEL"], p["CURSHCNV"], p["CONNAME"] } } /^\w+:/ { printValues(); delete p; next } { p[$1] = $2 } END { printValues() }'|wc -l)"
echo "Total shared conversations: $(expr $(echo $(echo "DIS CHS(${CHL}) ALL"|runmqsc $QMGR| grep -o '^\w\+:\|\w\+[(][^)]\+[)]' | awk -F '[()]' -v OFS="," 'function printValues() { if ("CHANNEL" in p) { print p["CHANNEL"], p["CURSHCNV"], p["CONNAME"] } } /^\w+:/ { printValues(); delete p; next } { p[$1] = $2 } END { printValues() }'|awk -F, '{print $2}')|sed -e 's/ / + /g'))"
echo "Unique CONNs: $(echo "dis conn(*) type(all) where(channel eq ${CHL})"|runmqsc $QMGR|grep -o '^\w\+:\|\w\+[(][^)]\+[)]' | awk -F '[()]' -v OFS='","' 'function printValues() { if ("CONN" in p) { print p["CONN"], p["CHANNEL"], p["CONNAME"], p["OBJNAME"], p["OBJTYPE"], p["ASTATE"], p["APPLDESC"], p["APPLTAG"], p["OPENOPTS"] } } /^\w+:/ { if (x !~ /YES/) {printValues()}; x = "NO"; delete p; next } { p[$1] = $2 } { if ("OPENOPTS" in p) { printValues() ; delete p["OPENOPTS"]; x = "YES"} } END { if (x !~ /YES/) {printValues()} }'|sed -e 's/^/"/g' -e 's/$/"/g'|awk -F, '{print $1}'|sort -u|wc -l)"
echo "Objects opened by CONNs:"
echo "dis conn(*) type(all) where(channel eq ${CHL})"|runmqsc $QMGR|grep -o '^\w\+:\|\w\+[(][^)]\+[)]' | awk -F '[()]' -v OFS='","' 'function printValues() { if ("CONN" in p) { print p["CONN"], p["CHANNEL"], p["CONNAME"], p["OBJNAME"], p["OBJTYPE"], p["ASTATE"], p["APPLDESC"], p["APPLTAG"], p["OPENOPTS"] } } /^\w+:/ { if (x !~ /YES/) {printValues()}; x = "NO"; delete p; next } { p[$1] = $2 } { if ("OPENOPTS" in p) { printValues() ; delete p["OPENOPTS"]; x = "YES"} } END { if (x !~ /YES/) {printValues()} }'|sed -e 's/^/"/g' -e 's/$/"/g'|awk -F, '{print $5}'|sort|uniq -c

关于java - 服务器连接 channel 的 mq 连接过多,这些连接不是由队列创建的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43070224/

相关文章:

java - 未能编译 Tomcat 的 index.jsp 示例

java - ActiveMQ 在 Spring Boot 中延迟传递消息

jms - JMS 是否可能出现 "fair queuing"

spring-integration - 使用 spring 集成向非 jms 客户端发送消息

java - 如何防止 JTextPane 水平增长...?

java - 如何在 Groovy MarkupBuilder 中禁用 pretty-print ?

java - 为什么 mathGPA 不能正常工作?

java - ActiveMQ 集群主题和生产者角度的故障安全

ibm-mq - MQ Explorer 在哪里保存通过 MQ Explorer 完成的所有事件的日志?

java - Websphere MQ 异步放置不起作用