JDK NIO中Epoll空轮询Bug产生的原因以及Netty中是如何解决的
产生原因
正常情况下,selector.select()操作是阻塞的,只有被监听的fd有读写操作时,才被唤醒。但是,在这个bug中,没有任何fd有读写请求,但是select()操作依旧被唤醒很显然,这种情况下,selectedKeys()返回的是个空数组,然后按照逻辑执行到while(true)处,循环执行,导致死循环。
Netty的解决方法
- 对Selector的select操作周期进行统计,每完成一次空的select操作进行一次计数。
- 若在某个周期内连续发生N次空轮询,则触发了epoll死循环bug。
- 重建Selector,判断是否是其他线程发起的重建请求,若不是则将原SocketChannel从旧的Selector上去除注册,重新注册到新的Selector上,并将原来的Selector关闭。