tyrus
tyrus copied to clipboard
Tyrus WebSocket sporadic client side disconnects
I'm using Tyrus client to connect to multiple WebSocket servers (around 10 connections) in parallel. The servers publish a lot of messages (hundreds of millions of messages per day). At some point, one of the connections begins to experience client side disconnects. The onClose
handlers is invoked with close reason CloseReason[1006,Closed abnormally.]
. The onError
handler is not invoked. After the error, the connection is re-established using the ReconnectHandler
.
Couple of facts regarding those disconnects/reconnects:
- It's always the connection to the same server that has issues. All other connections behave as expected.
- When I estalish the connection to just that one server that is having issues then no disconnects take place
- The first disconnect occurs after about an hour after the start of the application
- Then disconnects happen every few minutes
I also have the stack trace from the onError handler:
2020-11-16 16:23:03,347 3985311 [Grizzly(2)] INFO MyEndpoint - java.lang.Throwable
at MyEndpoint.onClose(MyEndpoint.scala:185)
at org.glassfish.tyrus.core.TyrusEndpointWrapper.onClose(TyrusEndpointWrapper.java:1235)
at org.glassfish.tyrus.core.TyrusWebSocket.onClose(TyrusWebSocket.java:110)
at org.glassfish.tyrus.core.ProtocolHandler.close(ProtocolHandler.java:481)
at org.glassfish.tyrus.core.TyrusWebSocket.close(TyrusWebSocket.java:244)
at org.glassfish.tyrus.client.TyrusClientEngine$2$1.close(TyrusClientEngine.java:613)
at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientFilter$CloseTask.execute(GrizzlyClientFilter.java:470)
at org.glassfish.tyrus.container.grizzly.client.TaskProcessor.processTask(TaskProcessor.java:91)
at org.glassfish.tyrus.container.grizzly.client.TaskProcessor.processTask(TaskProcessor.java:68)
at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientFilter.handleClose(GrizzlyClientFilter.java:197)
at org.glassfish.grizzly.filterchain.ExecutorResolver$4.execute(ExecutorResolver.java:50)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:248)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:181)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:121)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:99)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:51)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:510)
at org.glassfish.grizzly.nio.NIOConnection.preClose(NIOConnection.java:819)
at org.glassfish.grizzly.nio.transport.TCPNIOConnection.preClose(TCPNIOConnection.java:78)
at org.glassfish.grizzly.nio.NIOConnection.terminate0(NIOConnection.java:557)
at org.glassfish.grizzly.nio.transport.TCPNIOConnection.terminate0(TCPNIOConnection.java:249)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.read(TCPNIOTransport.java:596)
at org.glassfish.grizzly.nio.transport.TCPNIOTransportFilter.handleRead(TCPNIOTransportFilter.java:59)
at org.glassfish.grizzly.filterchain.TransportFilter.handleRead(TransportFilter.java:133)
at org.glassfish.grizzly.ssl.SSLBaseFilter$SSLTransportFilterWrapper.handleRead(SSLBaseFilter.java:919)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:88)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:248)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:181)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:121)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:99)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:51)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:510)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:82)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:83)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:34)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:101)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:535)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:515)
at java.base/java.lang.Thread.run(Thread.java:834)
Here is (roughly) the code I'm using
import jakarta.websocket._
class MyEndpoint extends Endpoint with LazyLogging {
def onOpen(session: Session, config: EndpointConfig): Unit = {
session.addMessageHandler(new MessageHandler.Whole[String] {
def onMessage(message: String): Unit = {
// handle message
}
override def onError(session: Session, thr: Throwable): Unit = {
logger.error(s"error occurred", thr)
super.onError(session, thr)
}
override def onClose(session: Session, closeReason: CloseReason): Unit = {
logger.error(s"closing due to $closeReason")
logger.info(ExceptionUtils.getStackTrace(new Throwable()))
super.onClose(session, closeReason)
}
}
}
}