WebSphere MQ 高连接数问题

WebSphere MQ High Connection Count Issue

根据我们的配置,我们的 WAS 版本是 8.5.5.1,IBM MQ 版本是 7.5.0.3。我们使用 2 个通道连接到 WMQ,一个 MAXINST 设置为 250,一个设置为 500。两者的 SHARECNV 都设置为 10。现在我们有在队列管理器中建立最多 1600 个连接的上限,但在 WAS 服务器连续 运行 3-4 天后我们最终超过了该限制。

我想了解 WAS 端的参数如何影响此计数。我们正在使用 Queue Connection Factory 和 Act Spec 来建立连接,我们每个都有 23 个。在这 22 个中,Act Spec 和 QCF 中的设置保持默认设置,例如最大服务器会话 = 10,连接池中的最大连接 = 10,会话池中的最大会话设置为 10。此服务的 tps 非常低,约为 15-20每分钟请求。它们中的所有 22 个都使用相同的通道连接到队列管理器,MAXINST 设置为 250。1 获得相当高的负载,峰值为每秒 80 个请求(每个服务器大约 40 个),其中最大服务器会话 = 40,连接池中的最大连接 = 40,会话池中的最大会话设置为 10.Connection 超时、获取时间、未使用超时和过时超时值均保持默认值。

通过这些设置,在连续 运行 2-3 天后,我们最终在 22 个服务使用的频道上建立了大约 1200 个连接,在另一个频道上建立了大约 500 个连接。这些在一段时间内积累起来。 现在我想调整这些设置,这样我们就不会超过连接计数限制,也不会最终没有可用连接。 所以我有几个问题:

  1. 从性能的角度来看,什么是更好的选择 - 减少连接池中的最大连接数或会话池中的最大会话数。前面提到的负载的理想值应该是多少。

  2. 连接池和会话池的未使用超时的理想值应该是多少,默认设置为 30 分钟。如果我们将它减少到 5 分钟,它对无法获得连接的性能有什么影响。

  3. 是否可以在 WMQ 端进行一些设置,以便关闭 idle/unused 连接,或者这只能在客户端发生。

  4. DISCINT 参数值设置为零,HBINT 设置为 300。理想值应该是多少。

我运行下面命令查看连接

echo "DIS CONN(*) TYPE(*) CONNAME CHANNEL OBJNAME OBJTYPE" | mqsc -e -m     QM-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"] } } /^\w+:/ { printValues(); delete p; next } { p[] =  } END { printValues() }' | grep MYCHANNEL

MYCHANNEL,,10.215.161.65,,,,,,,NONE
MYCHANNEL,,10.215.161.65,,,,,,,SUSPENDED
    MYCHANNEL,,10.215.161.65,,,,,MYQUEUE01,QUEUE,ACTIVE

我可以看到很多处于 None 和挂起状态的连接,它们没有关联任何 OBJNAME 或 OBJTYPE。 我已经尝试在测试中模拟问题,同样的事情发生了,并且随着我们不断满足请求,这些连接不断增加。有人能告诉我为什么要创建这些连接吗?此外,应用程序似乎永远不会使用这些连接。

这是在应用程序中建立和关闭连接的方式: 我们有一个抽象 bean class,它由所有 MDB

扩展
@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);
}

我还没有添加 class 的其他方法 marshalling/unmarshalling 和其他东西。

IBM developerWorks 博客 post “Avoiding run-away numbers of channels” 作者 @MoragHughson 详细介绍了队列管理器上的各种设置,以限制整个队列管理器的总最大通道数 (MaxChannels in qm.ini)、单个通道 (MAXINST) 和连接到通道 (MAXINSTC) 的单个客户端计算机。

@MoragHughson 也有 MQGem 软件博客 post“MaxChannels vs DIS QMSTATUS CONNS”(感谢 Morag 的帮助 posts)详细介绍了连接 (DIS CONN) 和通道 (DIS CHS) 之间的区别。

下面是一些可以帮助协调事物的命令(注意我已经在 Linux 上测试了这些命令,如果你在另一个 OS 上 运行 而他们没有工作让我知道,我将尝试为此提供一个工作示例 OS):

下面的命令将显示连接标识符、与连接关联的通道名称(如果有)和 IP 地址(如果有),输出为 CONN,CHANNEL,CONNAME

echo "DIS CONN(*) CHANNEL CONNAME"|runmqsc <QMGR> | grep -o '^\w\+:\|\w\+[(][^)]\+[)]' | awk -F '[()]' -v OFS="," 'function printValues() { if ("CONN" in p) { print p["CONN"], p["CHANNEL"], p["CONNAME"] } } /^\w+:/ { printValues(); delete p; next } { p[] =  } END { printValues() }'

下面的命令将显示每个 运行 频道实例、共享对话的数量以及连接到频道的 IP 地址,输出为 CHANNEL,CURSHCNV,CONNAME.

echo "DIS CHS(*) 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[] =  } END { printValues() }'

以上两个命令都可以修改为使用您在评论中展示的 mqsc 程序。

在进行更多分析并尝试不同的 WAS 和 MQ 设置后,我们排除了配置和代码方面的任何问题。在研究时发现以下 link http://www-01.ibm.com/support/docview.wss?uid=swg21605479。问题出在用于监控 WAS 服务器的 Wily Introscope 工具,它正在与 MQ 建立连接而不是释放它们。我们从服务器上删除了监控,从那以后它运行良好。在此感谢大家的支持。

我们有一个类似的问题,一旦应用程序保持活动数小时,连接数就会达到其限制。

我们的收获是调用队列管理器的 disconnect() post 入队或出队,而不是 close()。所以确保你的 finally 块看起来像这样。

finally 
{
    queue.close();
    qMgr.disconnect();     //rather than qMgr.close();      
}