系统运行一段时间后CPU会升高,升高后不会下降,只有重启服务CPU才会回归正常。经过top -H P,发现CPU过高的线程ID基本不变,CPU使用率接近100%。通过jstack快照查看是CPU过高的线程ID快照,发现全是XNIO线程,无业务在处理,快照信息如下:
"XNIO-1 I/O-4" #77 prio=5 os_prio=0 tid=0x00007fd5141ec800 nid=0x433e runnable [0x00007fd513dfc000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
- locked <0x00000005d3c01e38> (a sun.nio.ch.Util$3)
- locked <0x00000005d3c01e28> (a java.util.Collections$UnmodifiableSet)
- locked <0x00000005d3c01de0> (a sun.nio.ch.EPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:101)
at org.xnio.nio.WorkerThread.run(WorkerThread.java:532)
网上查了好多听说这是undertow使用NIO上的BUG,当某种未知的情况下会触发空跑,进入while(true)的空循环。
目前只有netty解决,求问在undertow下有什么解决办法,
“Devil组”引证GPT后的撰写:
该回答引用ChatGPT
您提到的问题可能是由于Undertow使用NIO线程池时遇到了一个已知的bug所导致的。根据您提供的信息,似乎是由于EPollSelectorImpl进入了无限循环状态,导致了CPU占用率的增加。这种情况下,只有重启服务才能恢复正常。
目前,这个问题已经被Undertow的开发人员确认,并已经在最新的版本中进行了修复。如果您的应用程序使用的是较旧的版本,建议升级到最新版本以解决此问题。
如果您无法升级到最新版本,可以尝试以下解决方法:
尝试在undertow的配置文件中设置worker-thread的数量,例如:
<http-listener name="default" socket-binding="http" worker-threads="50"/>
这将限制NIO线程池中的线程数量,并可能有助于减少CPU占用率。
尝试在启动应用程序时设置以下JVM参数:
-Djava.nio.channels.spi.SelectorProvider=sun.nio.ch.PollSelectorProvider
这将使用旧的PollSelectorProvider而不是EPollSelectorProvider,这可能会避免EPollSelectorImpl进入无限循环状态,但也可能会对性能产生一些影响。
由于Undertow是JBOSS的Web服务器,因此这个问题可能也会影响到您的应用程序。解决这个问题的一个可能的方法是升级您的Undertow版本。
如果您的Undertow版本已经是最新的,那么您可以尝试使用以下方法来解决这个问题:
1、调整Undertow的线程池配置
尝试调整Undertow的线程池配置。通过增加工作线程的数量,可以减轻线程的压力,从而减少CPU的使用率。
例如,在undertow-core模块中,您可以找到org.xnio.nio.WorkerThread类。在这个类中,您可以尝试增加工作线程的数量。
2、调整JVM的参数
您可以尝试调整JVM的参数。例如,尝试增加GC的频率、减少堆的大小等。这可能会降低CPU的使用率。
例如,您可以尝试增加以下参数:
-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=70
-XX:+UseCMSInitiatingOccupancyOnly
-Xmx4g
-Xms4g
这些参数可能需要根据您的应用程序的需求进行调整。
3、尝试使用Netty
如果您仍然无法解决问题,那么您可以尝试使用Netty来替换Undertow。Netty是一个高性能的NIO框架,它比Undertow更稳定、更可靠。如果您的应用程序需要高性能的Web服务器,那么Netty可能是一个更好的选择。
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
针对这个问题,可以尝试以下解决方案:
升级Undertow版本,升级到最新版本或者比较稳定的版本,看看是否有改善。
修改Undertow的配置文件,增加worker threads数量。可参考如下配置:
Undertow.builder()
.addHttpListener(8080, "localhost")
.setWorkerThreads(200)
.build();
Undertow.builder()
.addHttpListener(8080, "localhost")
.setIoThreads(Runtime.getRuntime().availableProcessors())
.setWorkerThreads(200)
.setHandler(handler)
.setServerOption(UndertowOptions.BLOCKING_IO_THREADS, 200)
.setServerOption(UndertowOptions.IOSHUTDOWN, false)
.build();
Xnio xnio = Xnio.getInstance();
XnioWorker xnioWorker = xnio.createWorker(OptionMap.builder().set(Options.WORKER_TASK_CORE_THREADS, 200)
.set(Options.WORKER_TASK_MAX_THREADS, 400)
.set(Options.TCP_NODELAY, true)
.set(Options.CORK, true)
.set(Options.BACKLOG, 20000)
.set(Options.TCP_OOB_INLINE, true)
.set(Options.KEEP_ALIVE, true)
.set(Options.ALLOW_BLOCKING, true)
.getMap());
希望这些解决方案能对你有所帮助。
如果我的回答解决了您的问题,请采纳!
参考GPT和自己的思路,您的问题描述与Undertow中已知的一个问题类似,可能是由于NIO处理器的问题导致的空跑现象,导致CPU占用率过高。这个问题可能是由于操作系统中的某些限制或不足引起的,比如EPoll的限制,或者是Undertow中的某些配置问题。
以下是几个可能的解决方案:
1 升级Undertow版本
如果您的Undertow版本比较老,可以尝试升级到最新版本,看是否可以解决问题。Undertow的最新版本可以从官方网站上下载。
2 调整线程池大小
您可以尝试调整Undertow线程池的大小,以减少NIO处理器的压力。您可以通过修改Undertow的配置文件或者在代码中设置相关参数来完成这个操作。具体而言,可以通过修改Worker和Accept线程池大小、阻塞队列长度等参数来实现。
3 使用Netty代替Undertow
如果上述两种方法都无法解决问题,您可以考虑使用Netty代替Undertow。Netty是另一个流行的Java网络框架,具有类似的功能,并且也是基于NIO的。与Undertow不同,Netty已经在处理NIO上面的问题上有一定的经验和成熟的解决方案,因此可能会更加稳定。
希望以上几个方法能够对您有所帮助,祝您好运!
可以尝试升级Undertow版本,或者调整相关Undertow参数,例如增加处理器线程池大小、减少空闲超时时间等;另外,排查是否存在Undertow的配置问题或者网络IO问题。如果以上方法仍然无法解决问题,可以考虑使用其他框架替换Undertow。