JDK NIO的bug,例如epoll bug,它會致使Selector空輪詢,最終致使CPU 100%。linux
Selector BUG出現的緣由
若Selector的輪詢結果爲空,也沒有wakeup或新消息處理,則發生空輪詢,CPU使用率100%oop
這個bug的描述內容爲,在NIO的selector中,即便是關注的select輪詢事件的key爲0的話,NIO照樣不斷的從select本應該阻塞的spa
狀況中wake up出來,也就是下圖中的紅色阻塞的部分:.net
而後,由於selector的select方法,返回numKeys是0,因此下面本應該對key值進行遍歷的事件處理根本執行不了,又回到最上面的while(true)循環,循環往復,不斷的輪詢,直到linux系統出現100%的CPU狀況,其它執行任務幹不了活,最終致使程序崩潰。線程
從這個bug上來看,這個絕對是JDK中的問題,select方法就應該是阻塞的,沒有key事件過來,那麼就不該該返回,和應用程序的寫法沒有任何的關係netty
Netty的解決辦法
1) 根據該BUG的特徵,首先偵測該BUG是否發生blog
偵測方法:對Selector的select操做週期進行統計,每完成一次空的select操做進行一次計數;事件
若在某個週期內連續發生N次空輪詢,則觸發了epoll死循環bug, netty默認是512次io
2) 將問題Selector上註冊的Channel轉移到新建的Selector上;class
3) 老的問題Selector關閉,使用新建的Selector替換。
下面具體看下代碼,首先檢測是否發生了該BUG:
epoll bug 檢測:
一旦檢測發生該BUG,則重建Selector,代碼以下:
重建完成以後,替換老的Selector,代碼以下:
大量生產系統的運行代表,Netty的規避策略能夠解決epoll bug 致使的IO線程CPU死循環問題。
netty的解決代碼在package io.netty.channel.nio.NioEventLoop這個類下面