如何解决 JDK epoll 空轮询问题?

这个 BUG 是指 Java 的 NIO 在 Linux 下进行 selector.select() 时,本来如果轮询的结果为空并且不调用 wakeup 方法的话,这个 selector.select() 应该是一直阻塞的,但是 Java 却会打破阻塞,继续执行,导致程序无限空转,造成 CPU 使用率 100%。(这个问题只存在 Linux 是因为 Linux 的 NIO 是基于 epoll 实现的,而 Java 实现的 epoll 存在 BUG,windows 下 NIO 基于 poll 就不存在此问题)

Netty 的解决方案:

为 Selector 的 select 操作设置超时时间,同时定义可以跳出阻塞的四种情况

  • 有事件发生
  • wakeup
  • 超时
  • 空轮询 BUG

而前两种返回值不为 0,可以跳出循环,超时有时间戳记录,所以每次空轮询,有专门的计数器进行 +1,如果空轮询的次数超过了 512 次(默认),就认为其触发了空轮询 BUG。

当触发 BUG 后,Netty 直接重建一个 Selector,将原来的 Channel 重新注册到新的 Selector 上,并将旧的 Selector 关掉。

发表评论

后才能评论