Tyrus 端点阻止 Glassfish (Payara) 中的线程
Tyrus Endpoint Blocks Thread in Glassfish (Payara)
我遇到了一个奇怪的问题。
我的应用程序(适用于 Payara 4.1.1.163)使用 Websockets 在客户端之间发送消息。 TyrusRemoteEndpoint 用于此功能。
部署后大约 3-4 天运行良好,然后(如果这次没有部署或重新部署应用程序)tyrus 在调用函数时突然阻塞线程(甚至线程):
session.getBasicRemote().sendObject(obj);
我使用 VisualVM 转储了所有线程并看到以下内容:
"http-thread-pool(56)" - Thread t@209
java.lang.Thread.State: WAITING
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <6929ab6a> (a java.util.concurrent.CountDownLatch$Sync)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:997)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1304)
at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:231)
at org.glassfish.tyrus.core.TyrusFuture.get(TyrusFuture.java:77)
at org.glassfish.tyrus.core.TyrusRemoteEndpoint$Basic.sendObject(TyrusRemoteEndpoint.java:183)
看来这个帖子要永远等待了。不为此客户端发送消息。
如果我使用同步块,它甚至会导致死锁并且所有 http 线程池(涉及 websockets)都被阻塞。
什么会导致这样的问题?我该如何应对?我还需要提供其他东西吗?
提前致谢!
P.S。我正在使用有关线程池的默认 Payara 设置(如果有帮助的话)。
似乎这是 tyrus-websocket 库中的 bug。
至少可以通过使用
恢复应用程序来解决
getAsyncRemote()
而不是
getBasicRemote()
通过以下方式:
Future<Void> f = session.getAsyncRemote().sendObject(...)
try {
f.get(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new IOException(e);
} catch (ExecutionException e) {
Throwable cause = e.getCause();
if (cause instanceof IOException) {
throw (IOException) cause;
} else if (cause instanceof EncodeException) {
throw (EncodeException) cause;
} else {
throw new IOException(e);
}
} catch (TimeoutException e) {
throw new IOException(e);
}
在这种情况下,我们使用超时,至少确保我们的应用程序可以在该问题之后恢复。
我还检查了 this repository 最新版本的 tyrus,不能说他们已经解决了问题。可能它应该作为 Payara 或 Glassfish 的错误发布。
我遇到了一个奇怪的问题。
我的应用程序(适用于 Payara 4.1.1.163)使用 Websockets 在客户端之间发送消息。 TyrusRemoteEndpoint 用于此功能。
部署后大约 3-4 天运行良好,然后(如果这次没有部署或重新部署应用程序)tyrus 在调用函数时突然阻塞线程(甚至线程):
session.getBasicRemote().sendObject(obj);
我使用 VisualVM 转储了所有线程并看到以下内容:
"http-thread-pool(56)" - Thread t@209
java.lang.Thread.State: WAITING
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <6929ab6a> (a java.util.concurrent.CountDownLatch$Sync)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:997)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1304)
at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:231)
at org.glassfish.tyrus.core.TyrusFuture.get(TyrusFuture.java:77)
at org.glassfish.tyrus.core.TyrusRemoteEndpoint$Basic.sendObject(TyrusRemoteEndpoint.java:183)
看来这个帖子要永远等待了。不为此客户端发送消息。
如果我使用同步块,它甚至会导致死锁并且所有 http 线程池(涉及 websockets)都被阻塞。
什么会导致这样的问题?我该如何应对?我还需要提供其他东西吗? 提前致谢!
P.S。我正在使用有关线程池的默认 Payara 设置(如果有帮助的话)。
似乎这是 tyrus-websocket 库中的 bug。
至少可以通过使用
恢复应用程序来解决getAsyncRemote()
而不是
getBasicRemote()
通过以下方式:
Future<Void> f = session.getAsyncRemote().sendObject(...)
try {
f.get(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new IOException(e);
} catch (ExecutionException e) {
Throwable cause = e.getCause();
if (cause instanceof IOException) {
throw (IOException) cause;
} else if (cause instanceof EncodeException) {
throw (EncodeException) cause;
} else {
throw new IOException(e);
}
} catch (TimeoutException e) {
throw new IOException(e);
}
在这种情况下,我们使用超时,至少确保我们的应用程序可以在该问题之后恢复。
我还检查了 this repository 最新版本的 tyrus,不能说他们已经解决了问题。可能它应该作为 Payara 或 Glassfish 的错误发布。