将Xmpp消息发送回发件人的SmackException NoResponseException

时间:2016-08-30 11:45:23

标签: tomcat xmpp openfire smack

预先注意:我已经检查了stackoverflow上的其他线程,但没有找到类似的情况。 我们在生产服务器上面临着关于xmpp的奇怪问题。环境是这样的: 2个tomcats(v7),1个openfire(3.10),ngnix

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

所以我们遇到了这个问题。在运行环境中一切顺利。客户端 - 服务器正在通信。但是当我们需要进行新的部署时,我们停止tomcat-deploy war-start 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;

连接代码在onApplicationEvent(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();
}

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

0 个答案:

没有答案
相关问题