NIO的epoll空轮询bug

JDK NIO的bug,例如epoll bug,它会导致Selector空轮询,最终导致CPU 100%。

Selector BUG出现的原因

若Selector的轮询结果为空,也没有wakeup或新消息处理,则发生空轮询,CPU使用率100%

这个bug的描述内容为,在NIO的selector中,即使是关注的select轮询事件的key为0的话,NIO照样不断的从select本应该阻塞的

情况中wake up出来,也就是下图中的红色阻塞的部分:

NIO的epoll空轮询bug_第1张图片

 

然后,因为selector的select方法,返回numKeys是0,所以下面本应该对key值进行遍历的事件处理根本执行不了,又回到最上面的while(true)循环,循环往复,不断的轮询,直到linux系统出现100%的CPU情况,其它执行任务干不了活,最终导致程序崩溃。

从这个bug上来看,这个绝对是JDK中的问题,select方法就应该是阻塞的,没有key事件过来,那么就不应该返回,和应用程序的写法没有任何的关系

Netty的解决办法

1) 根据该BUG的特征,首先侦测该BUG是否发生

   侦测方法:对Selector的select操作周期进行统计,每完成一次空的select操作进行一次计数;

                  若在某个周期内连续发生N次空轮询,则触发了epoll死循环bug, netty默认是512次

2) 将问题Selector上注册的Channel转移到新建的Selector上;

3) 老的问题Selector关闭,使用新建的Selector替换。

下面具体看下代码,首先检测是否发生了该BUG:

epoll bug 检测:

NIO的epoll空轮询bug_第2张图片

一旦检测发生该BUG,则重建Selector,代码如下:

NIO的epoll空轮询bug_第3张图片

重建完成之后,替换老的Selector,代码如下:

NIO的epoll空轮询bug_第4张图片

 

大量生产系统的运行表明,Netty的规避策略可以解决epoll bug 导致的IO线程CPU死循环问题。

netty的解决代码在package io.netty.channel.nio.NioEventLoop这个类下面

 

转载于:https://www.cnblogs.com/cherish010/p/9044776.html

你可能感兴趣的:(NIO的epoll空轮询bug)