Tomcat 将Xmpp消息发送回发件人时的SmackException NORESPONSEEException
预告:我检查了stackoverflow上的其他线程,没有发现类似的情况。 我们在生产服务器上面临有关xmpp的奇怪问题。环境是这样的: 2只雄猫(v7),1只明火(3.10),ngnix 我们有移动应用程序(android、ios)作为客户端,它们通过xmpp与我们的服务器进行对话。我们的服务器也是openfire的另一个用户(但具有管理员角色),通过SASL和自签名证书连接到openfire。它正在使用smack 4.1.0 所以我们有这个问题。在运行环境中一切都进行得很顺利。客户端和服务器正在通信。但是当我们需要进行新的部署时,我们会停止tomcat部署,并启动tomcat(对于每个tomcat,这样我们就不会有停机时间)。服务器初始化没有问题。Smack日志告诉我,连接是通过openfire建立的,并且经过身份验证。我还可以看到来自客户端的聊天信息。但不知何故,服务器无法将消息发送回客户端。 发送聊天信息时,不会抛出任何异常,就像发送成功一样。但是,在openfire上的节点上发布某些内容时(作为管理员角色),存在以下问题: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 所以我们有这个问题。在运行环境中一切都进行得很顺利。客户端和服务器
*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();
}