Java SelectorImpl被阻止

Java SelectorImpl被阻止,java,selector,blocked,Java,Selector,Blocked,我用了很多客户端向服务器发送一个请求,大约每秒1000个请求一个客户端,服务器的CPU很快上升到600%(8个内核),并始终保持这种状态。当我使用jstack打印过程内容时,我发现SelectorImpl处于阻塞状态。记录如下: nioEventLoopGroup-4-1 prio=10 tid=0x00007fef28001800 nid=0x1dbf waiting for monitor entry [0x00007fef9eec7000] java.lang.Thread.State:

我用了很多客户端向服务器发送一个请求,大约每秒1000个请求一个客户端,服务器的CPU很快上升到600%(8个内核),并始终保持这种状态。当我使用jstack打印过程内容时,我发现SelectorImpl处于阻塞状态。记录如下:

nioEventLoopGroup-4-1 prio=10 tid=0x00007fef28001800 nid=0x1dbf waiting for monitor entry [0x00007fef9eec7000]
java.lang.Thread.State: BLOCKED (on object monitor)
at sun.nio.ch.EPollSelectorImpl.doSelect(Unknown Source)
- waiting to lock <0x00000000c01f1af8> (a java.lang.Object)
    at sun.nio.ch.SelectorImpl.lockAndDoSelect(Unknown Source)
    - locked <0x00000000c01d9420> (a io.netty.channel.nio.SelectedSelectionKeySet)
    - locked <0x00000000c01f1948> (a java.util.Collections$UnmodifiableSet)
    - locked <0x00000000c01d92c0> (a sun.nio.ch.EPollSelectorImpl)
    at sun.nio.ch.SelectorImpl.select(Unknown Source)
    at io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:635)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:319)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101)
    at java.lang.Thread.run(Unknown Source)
"nioEventLoopGroup-4-1" prio=10 tid=0x00007fef28001800 nid=0x1dbf waiting for monitor entry [0x00007fef9eec7000]
java.lang.Thread.State: BLOCKED (on object monitor)
at sun.nio.ch.EPollSelectorImpl.doSelect(Unknown Source)
- waiting to lock <0x00000000c01f1af8> (a java.lang.Object)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(Unknown Source)
- locked <0x00000000c01d9420> (a io.netty.channel.nio.SelectedSelectionKeySet)
- locked <0x00000000c01f1948> (a java.util.Collections$UnmodifiableSet)
- locked <0x00000000c01d92c0> (a sun.nio.ch.EPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(Unknown Source)
at io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:635)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:319)
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101)
at java.lang.Thread.run(Unknown Source)
//group.ShutdownGracely(); }

}

如果你能详细说明你的内特在做什么,这可能会有所帮助。无论如何-请确保您正在关闭频道。政府公告:

使用完频道后,调用close()或close(ChannelPromise)释放所有资源是很重要的。这可以确保以适当的方式释放所有资源,即文件句柄

如果你正在关闭通道,那么问题可能在于它自身运行到无限循环或类似的逻辑中——这可能可以解释CPU的高性能

高CPU与此有关吗

可能是。我将按照以下方式诊断此问题(在Linux设备上):

查找正在占用CPU的线程 使用
pidstat
我可以找到哪些线程正在消耗CPU以及在什么模式(用户/内核)下花费的时间

$ pidstat -p [java-process-pid] -tu 1 | awk '$9 > 50'
此命令显示线程占用至少50%的CPU时间。您可以使用
jstack
、VisualVM或Java Flight Recorder检查这些线程正在做什么

如果CPU饥饿线程和阻塞线程是相同的,CPU使用率似乎与争用有关

查找连接超时的原因 基本上,如果两个操作系统不能在给定的时间内完成TCP握手,您将获得连接超时。原因如下:

  • 网络链路饱和。可以使用
    sar-n DEV 1
    进行诊断,并将
    rxkB/s
    txkB/s
    列与链接的最大吞吐量进行比较
  • 服务器(Netty)在给定的超时时间内不响应
    accept()
    调用。此线程可能会被阻塞或耗尽CPU时间。您可以使用
    strace-f-e trace=accept-p[javapid]
    找到正在调用
    accept()
    (从而完成TCP握手)的线程。然后使用
    pidstat
    /
    jstack
    检查可能的原因

此外,您还可以使用
netstat-an | grep-c SYN_RECV

找到打开(但未确认)的连接请求的数量。我想,您已将相同的代码片段粘贴了两次。第二个片段与第一个片段相同,不是错误。至于阻塞选择器,这是正常的,而不是cpu高的原因。事实上,阻塞线程根本不使用任何cpu。
$ pidstat -p [java-process-pid] -tu 1 | awk '$9 > 50'