當前位置:編程學習大全網 - 編程語言 - Netty原理-從NIO開始

Netty原理-從NIO開始

Netty是基於NIO的異步通信框架(曾經引入過AIO,後來放棄),故要說Netty原理我們要先從NIO開始。

NIO 是JAVA在JDK4中引入的同步非阻塞通信模型,在NIO出現之前(JDK4之前)市場上只有壹個BIO模型顧名思義BLOCKING IO (同步阻塞通信模型)

BIO(BLOCKING I/O):

BIO 為壹個連接 壹個線程的模式,當有連接時服務器會開啟壹個線程來處理請求

若此請求啥都不想幹此時線程會怎麽樣?

此線程會進入阻塞模式(BLOCKING)!---啥也不幹,幹等著zzZZ~

這種壹連接,壹線程的模式會造成服務器資源不必要的開銷並且在大量連接訪問時 服務器會發生什麽?車道(線程)不足,車太多--我堵車了

由此就出現了NIO

NIO(new/NONBLOCKING I/O):

NIO為同步非阻塞通信模型,Select(多路復用器)為此模型的核心,實現了多個連接壹個線程

當有客戶端連接請求時 此連接請求會被註冊至select上,當select檢測到此連接有I/O請求時才會打開壹個線程去對此I/O請求進行處理-----單線程模型

這個時候有人問了:這麽多操作都在壹個線程裏,線程忙不過來怎麽辦?

此時 由於網絡請求、I/O讀寫、業務操作都在壹個線程下,會導致在高並發的情況下存在性能瓶頸 於是乎有人就提出來 將業務操作丟到另壹個線程怎麽樣?

於是出現了第三種reactor模型-使用線程池進行操作網絡請求、IO在壹個線程,業務操作在另個壹個線程 的業務分離----線程池模型

從此圖中可以看出此時 模型中使用壹個線程池來進行網絡請求、IO讀取

當讀取完成後將業務操作綁定在線程池中另外的線程上-------網絡IO與業務操作可以同步進行了!壹切都完美了起來!

但是!事情還沒完!!這個時候又有人提出問題:在高並發的時候咋辦?會不會有性能瓶頸

因為網絡IO是非常消耗CPU的,當網絡請求與網絡IO在同個線程中時,造C10K的情況下單個線程並不足以支撐起所有的IO操作!因此也形成了在高並發狀態下的性能瓶頸

於是大佬們就想著,如果把IO拆出來讓單個線程池去接收網絡請求,用另壹個線程池來進行IO與業務操作會不會更好

於是第四種Reactor模型應運而生--主從Reactor多線程模型

此模型中 mainReactor只用於接收網絡請求,而subReactor中為壹個線程池,線程池中每個線程上綁定壹個select

當mainReactor接收到請求時(壹個描述符) 系統會生成壹個新的描述符代表此連接生效,此時mainReactor會將新的描述符通過壹個算法在線程池中選定壹個線程 將此描述符綁定至此線程池上的select上,由此線程來對請求進行I/O 與業務操作

從此百萬連接高並發不是問題

寫到這 我們是不是想起了Netty的啟動過程

1、聲明兩個EventLoopGroup壹個為boss(mainReactor)壹個為worker(subReactor)

EventLoopGroup(線程池)初始化的時候會生成(懶加載)指定數量的EventLoop(線程)若無指定 則會生成CPU數X2的線程

2、聲明壹個啟動輔助類Bootstrap並將EventLoopGroup註冊到啟動輔助類BootStrap上(bootStrap.group)

接著再給bootstrap指定channel模型等屬性,再添加上業務流水線(channelpipeline)並且在pipeline中添加上業務操作handler,(通過channelpipeline可以對傳入數據為所欲為)

3、綁定端口

Netty啟動完成

這時候可能有人會問了:這和妳上面說的reactor?NIO有啥關系?

這個時候我們要這麽看

若我們將boss與worker線程池設置為相同的壹個線程池,那麽會發生什麽事?

此時關註壹下第三個Reactor模型時就會發現 當BOSS=WORKER時候 netty實現的就是第三種Reactor模型 使用線程池模型

而當boss不等於worker的時候使用的就是第四種 主從多線程模型

Netty就是基於Reactor模型來對NIO進行了易用化封裝,從Netty源碼中就可以看出來其實底層還都是NIO的接口

此次處為自己讀源碼之後的理解 如有誤請指正

感恩

反手拿下第壹個贊

  • 上一篇:應屆生簡歷怎麽寫?
  • 下一篇:前端會有未來嗎?
  • copyright 2024編程學習大全網