我们正在更改集群拓扑,并在“默认 I/O-x”线程 (org.xnio.nio.WorkerThread) 中面临 100% CPU 问题。
看起来像 ConduitStreamSinkChannel.write(..) 中的无限循环,但我不确定。
问题是间歇性的,不容易重现,需要重启才能停止。
每次进入此状态时,线程转储都是相同的:
"default I/O-2" #103 prio=5 os_prio=0 tid=0x00007fd0f83a4800 nid=0x6941 runnable [0x00007fd0e9be0000]
java.lang.Thread.State: RUNNABLE
at java.lang.Throwable.fillInStackTrace(Native Method)
at java.lang.Throwable.fillInStackTrace(Throwable.java:783)
- locked <0x00000007a2be6ec0> (a java.nio.channels.ClosedChannelException)
at java.lang.Throwable.(Throwable.java:250)
at java.lang.Exception.(Exception.java:54)
at java.io.IOException.(IOException.java:47)
at java.nio.channels.ClosedChannelException.(ClosedChannelException.java:52)
at org.xnio.ssl.JsseStreamConduit.write(JsseStreamConduit.java:1022)
at org.xnio.conduits.ConduitStreamSinkChannel.write(ConduitStreamSinkChannel.java:150)
at org.xnio.http.HttpUpgrade$HttpUpgradeState$StringWriteListener.handleEvent(HttpUpgrade.java:385)
at org.xnio.http.HttpUpgrade$HttpUpgradeState$StringWriteListener.handleEvent(HttpUpgrade.java:372)
at org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
at org.xnio.conduits.WriteReadyHandler$ChannelListenerHandler.writeReady(WriteReadyHandler.java:65)
at org.xnio.ssl.JsseStreamConduit.run(JsseStreamConduit.java:393)
at org.xnio.ssl.JsseStreamConduit.writeReady(JsseStreamConduit.java:524)
at org.xnio.ssl.JsseStreamConduit$1.writeReady(JsseStreamConduit.java:287)
at org.xnio.nio.NioSocketConduit.handleReady(NioSocketConduit.java:94)
at org.xnio.nio.WorkerThread.run(WorkerThread.java:567)
拓扑中的更改是添加更多服务器组并更改反向代理 (nginx),以便将每个 http 连接重定向(状态 301)到 https。
分析线程转储,似乎与 https 有关(包 org.xnio.ssl.*),但 nginx 背后的所有内容都是纯 http。
我们的应用程序提供了一个Websocket端点(通过nginx进行WSS)并对其他服务器进行大量EJB远程调用(http-remoting,直接到其他服务器而不通过nginx)。
此外,应用程序通过负载均衡器(nginx https,以避免 301 重定向)向集群中的其他服务器发出/接收一些 REST 调用 (RESTEasy)
这可能是什么原因造成的?
谢谢!
我希望现在提供答案还为时不晚。
我们遇到了与上述问题相同的问题。 EAP(Jboss) 版本为 7.0.x,EAP 实例处理来自多个设置为反向代理的 NGNIX 的 HTTPS 请求。
在特定流量情况下,我们注意到受影响的 EAP 实例消耗了 99% 的 CPU,并且其中的 Web 应用程序变得无法访问。
就好像 EAP 实例被冻结一样。我们捕获了日志,当与线程转储进行交叉检查时,下面的默认 I/O 线程消耗了最多的 CPU。
12:56:10,512 INFO [stdout] (default I/O-11) io.undertow.server.protocol.http.AlpnOpenListener$AlpnConnectionListener.handleEvent(AlpnOpenListener.java:356)
12:56:10,512 INFO [stdout] (default I/O-11) io.undertow.server.protocol.http.AlpnOpenListener$AlpnConnectionListener.handleEvent(AlpnOpenListener.java:341)
12:56:10,512 INFO [stdout] (default I/O-11) org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
12:56:10,512 INFO [stdout] (default I/O-11) org.xnio.conduits.ReadReadyHandler$ChannelListenerHandler.readReady(ReadReadyHandler.java:66)
12:56:10,512 INFO [stdout] (default I/O-11) io.undertow.protocols.ssl.SslConduit$SslReadReadyHandler.readReady(SslConduit.java:1291)
12:56:10,512 INFO [stdout] (default I/O-11) org.xnio.nio.NioSocketConduit.handleReady(NioSocketConduit.java:89)
12:56:10,512 INFO [stdout] (default I/O-11) org.xnio.nio.WorkerThread.run(WorkerThread.java:591)
10:14:29,798 INFO [stdout] (default I/O-21) io.undertow.protocols.ssl.SslConduit.doUnwrap(SslConduit.java:850)
10:14:29,798 INFO [stdout] (default I/O-21) io.undertow.protocols.ssl.SslConduit.read(SslConduit.java:587)
10:14:29,798 INFO [stdout] (default I/O-21) org.xnio.conduits.AbstractStreamSourceConduit.read(AbstractStreamSourceConduit.java:51)
该问题是由于线程池耗尽导致默认I/O线程无法从池中获取新线程造成的。下面的 RedHat 知识库链接捕获了此行为:-
https://access.redhat.com/solutions/7031598
一旦我们执行速率限制并将负载分配给更多的EAP实例,CPU高的问题就解决了。希望这有帮助