Tomcat 将Xmpp消息发送回发件人时的SmackException NORESPONSEEException

Tomcat 将Xmpp消息发送回发件人时的SmackException NORESPONSEEException,tomcat,xmpp,openfire,smack,Tomcat,Xmpp,Openfire,Smack,预告:我检查了stackoverflow上的其他线程,没有发现类似的情况。 我们在生产服务器上面临有关xmpp的奇怪问题。环境是这样的: 2只雄猫(v7),1只明火(3.10),ngnix 我们有移动应用程序(android、ios)作为客户端,它们通过xmpp与我们的服务器进行对话。我们的服务器也是openfire的另一个用户(但具有管理员角色),通过SASL和自签名证书连接到openfire。它正在使用smack 4.1.0 所以我们有这个问题。在运行环境中一切都进行得很顺利。客户端和服务器

预告:我检查了stackoverflow上的其他线程,没有发现类似的情况。 我们在生产服务器上面临有关xmpp的奇怪问题。环境是这样的: 2只雄猫(v7),1只明火(3.10),ngnix

我们有移动应用程序(android、ios)作为客户端,它们通过xmpp与我们的服务器进行对话。我们的服务器也是openfire的另一个用户(但具有管理员角色),通过SASL和自签名证书连接到openfire。它正在使用smack 4.1.0

所以我们有这个问题。在运行环境中一切都进行得很顺利。客户端和服务器正在通信。但是当我们需要进行新的部署时,我们会停止tomcat部署,并启动tomcat(对于每个tomcat,这样我们就不会有停机时间)。服务器初始化没有问题。Smack日志告诉我,连接是通过openfire建立的,并且经过身份验证。我还可以看到来自客户端的聊天信息。但不知何故,服务器无法将消息发送回客户端。 发送聊天信息时,不会抛出任何异常,就像发送成功一样。但是,在openfire上的节点上发布某些内容时(作为管理员角色),存在以下问题:

*Unable to publish notification to node [NODENAME] , ex [org.jivesoftware.smack.SmackException$NoResponseException: No response received within reply timeout. Timeout was 30000ms (~30s). Used filter: IQReplyFilter: iqAndIdFilter (AndFilter: (OrFilter: (IQTypeFilter: type=error, IQTypeFilter: type=result), StanzaIdFilter: id=H0ttG-44)), : fromFilter (OrFilter: (FromMatchesFilter (full): pubsub.SERVERNAME.com)).], cause [null], class [org.jivesoftware.smack.SmackException$NoResponseException]*
此问题持续约20-25分钟。后来一切都变得正常了,客户端和服务器可以用这两种方式进行通信

连接侦听器上没有“连接丢失”或“重新连接”日志。我们发现没有什么有用的东西可以帮助我们20分钟的交流是一种方式,20-25分钟后就可以了

以下是我们的xmpp连接配置:

    // We are using two-way authentication with certificates
SASLAuthentication.registerSASLMechanism(new SASLExternalMechanism());
XmppTrustManager xmppTrustManager = null;
try {
    xmppTrustManager = new XmppTrustManager($truststore.path, $truststore.password);
} catch (final XMPPException e) {
    log.error("Unable to create trust manager", e);
    throw new...
}

final TrustManager[] trustManagers = new TrustManager[] { xmppTrustManager };
XmppKeyManager xmppKeyManager = null;
try {
    xmppKeyManager = new XmppKeyManager($keystore.path, $keystore.password);

} catch (final XMPPException e) {
    log.error("Unable to create key manager", e);
    throw new ...
}
final KeyManager[] keyManagers = new KeyManager[] { xmppKeyManager };

SSLContext sslContext = null;
try {
    sslContext = SSLContext.getInstance("TLS");
    sslContext.init(keyManagers, trustManagers, null);
} catch (final NoSuchAlgorithmException e) {
    log.error("Cannot create SSLContext instance", e);
} catch (final KeyManagementException e) {
    log.error("Cannot initialize SSLContext instance", e);
}

final XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()
        .setHost($host)
        .setPort($port)
        .setServiceName($domain).setCustomSSLContext(sslContext)
        .setHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(final String hostname, final SSLSession session) {
                return $domain.equals(hostname);
            }
        }).setDebuggerEnabled(false).allowEmptyOrNullUsernames().build();

final XMPPTCPConnection xmppConnection = new XMPPTCPConnection(config);
xmppConnection.setPacketReplyTimeout(30 * 1000);
// xmppConnection.addConnectionListener(connectionListener());
ReconnectionManager.getInstanceFor(xmppConnection).enableAutomaticReconnection();
xmppConnection.setUseStreamManagement(true);

xmppConnection.addConnectionListener(new ConnectionListener() {

    @Override
    public void reconnectionSuccessful() {
        log.info("Successfully reconnected to the XMPP server.");
    }

    @Override
    public void reconnectionFailed(final Exception e) {
        log.info("Failed to reconnect to the XMPP server ", e.toString());

    }

    @Override
    public void reconnectingIn(final int seconds) {
        log.debug("Reconnecting in " + seconds + " seconds.");
    }

    @Override
    public void connectionClosedOnError(final Exception e) {
        log.info("Connection to XMPP server was lost ", e.toString());
    }

    @Override
    public void connectionClosed() {
        log.info("Connection to XMPP server was closed");
    }

    @Override
    public void connected(final XMPPConnection connection) {
        log.info("connected to XMPP server");
    }

    @Override
    public void authenticated(final XMPPConnection connection, final boolean resumed) {
        log.info("Xmpp connected authenticated. is resumed: " + resumed);

    }
});

log.debug("xmppConnection bean is initialized");
return xmppConnection;
并且连接代码在ApplicationEvent(ContextRefreshedEvent事件)上:

任何帮助都将不胜感激。谢谢

    if (connecting) {
    return;
}
connecting = true;

try {
    xmppConnection.connect();
    xmppConnection.login("", "", "");
    log.debug("no exception occured during connection");
} catch (XMPPException | SmackException | IOException e) {
    // start a new thread that will try connecting every pingInterval seconds
    new Thread(new Runnable() {
        @Override
        public void run() {
            while (!xmppConnection.isConnected()) {
                log.debug("waiting for a while to attempt login again");
                try {
                    Thread.sleep(10 * 1000);
                    xmppConnection.connect();
                    xmppConnection.login("", "", "");                   
                } catch (XMPPException | SmackException | IOException | InterruptedException e) {
                    ...
                }
            }
        }
    }).start();
}