【Netty】Selector空輪詢 解決 詳解


shadowLogo

前言:

在之前的博文中,本人講解了 Netty概念基本使用各種機制 以及 核心源碼

那么,在本篇博文中,本人將來講解一個 開發 中,很重要的問題 —— Selector空輪詢 的解決


首先,本人來講解下 什么是 Selector空輪詢

概念:

Selector空輪詢NIOAPIbug
NIO 中,使用 Selectorselect方法,來 輪詢當前是否有IO事件
根據 JDK 中對 NIOapi描述

Selectorselect方法 會 一直阻塞,直到 IO事件達到超時

但是在某些場景下,select方法直接返回
即使 沒有超時,並且也沒有IO事件到達,也會 直接返回

這就是 Selector空輪詢(epoll bug)

一般發生了 Selector空輪詢,就會 一直 空輪詢,陷入死循環,因此 CPU飆到100%

最終,線上問題頻頻,服務器崩潰!

可怕的是:到目前為止,JDK還是無法完全避免這個bug產生!

因此,所有使用 NIO成熟框架,都會對 這個bug 做出一些解決


現在,本人來講解下,在 Netty 中,Selector空輪詢(epoll bug) 是如何解決的:

Netty 中的 解決方案:

Netty 中,Selector空輪詢(epoll bug) 的解決,是在 select方法 中的:

Selector空輪詢 的解決 —— select方法:

1

2
我們可以看到,解決邏輯 是:

  • 每次調用后,selectCnt + 1
  • 超時(正常 跳出阻塞)
    重置selectCnt的值
  • 未超時(非正常 跳出阻塞)
    重新構造一個selector,並 重置selectCnt的值

那么,本人再來講解下,Netty 是如何 重新構造 Selector 的:

重新構造 Selector —— selectRebuildSelector方法:

重新構造

我們可以看到:

內部只是:

  • 重新構造 selector
  • 使用 新的selector,進行 阻塞式監聽

那么,我們來看看,rebuildSelector方法 是如何實現的:

rebuildSelector方法:

調用

我們可以看到:

內部只是:

  • 調用 rebuildSelector0方法,也就是 真正的 重建Selector邏輯

真正的 重建Selector邏輯 —— rebuildSelector0方法:

新建
轉移
換屆

我們可以看到:

內部只是:

  • 新建一個 Selector
  • 舊的Selector注冊的key全部 注冊新的Selector
  • 當前Selector 指向 新的Selector
  • 關閉 舊的Selector

那么,最后,本人來 總結 下 在 Netty 中,Selector空輪詢(epoll bug) 是怎樣解決的:

總結:

解決邏輯 為:

  • 每次調用后,selectCnt + 1
  • 超時(正常 跳出阻塞)
    重置selectCnt的值
  • 未超時(非正常 跳出阻塞)
    重新構造一個selector
  • 新建一個 Selector
  • 舊的Selector注冊的key全部 注冊新的Selector
  • 關閉 舊的Selector
  • 使用 新的selector,進行 阻塞式監聽

,並 重置selectCnt的值

最后,可能同學們會有疑問:

selectCnt 在 rebuild selector時 沒用啊,為什么要維護那個變量呢?

答曰:

系統日志輸出,方便開發人員進行分析優化處理


以上,就是 Netty 解決 Selector空輪詢(epoll bug) 的 核心邏輯
溜了溜了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM