引言
好久沒有寫博客了,近期準備把Netty原始碼啃一遍,在這之前本想直接看原始碼,但是看到后面發現其實效率不高,
有些概念還是有必要回頭再細啃的,特別是其執行緒模型以及EventLoop的概念,
當然在開始之前還是有務必要對IO模型要有清晰準確的認識, 傳送門
事件回圈機制(EventLoop)
Netty執行緒模型中一個非常重要的概念: 事件回圈機制(EventLoop)
這個概念在JS上體現的也非常淋漓盡致,下面在開始介紹netty的執行緒模型之前,允許我簡單的介紹下事件回圈機
制在JS中的體現
JS的語言性質: 單執行緒非阻塞,單執行緒意味著,js代碼在執行的任何時候,都只有一個主執行緒來處理所有的任務>,非阻塞則意味著,在進行異步IO任務時不會阻塞主執行緒,主執行緒會掛起這個任務,等待異步任務完成再執行對應>的回呼,
那么JS是如何實作單執行緒非阻塞的呢?JS引擎遇到一個異步事件后并不會一直等待其回傳結果,而是會將此事件>掛起(例如交給瀏覽器去執行請求),主執行緒會繼續執行方法堆疊中的其他任務,之后當異步任務回傳結果后,(可>能是瀏覽器?)會將回呼函式加入到事件佇列(Task Queue)中,那么什么時候會從事件佇列中取出回呼函式執行>呢?當前執行堆疊中的所有任務都執行完畢,主執行緒處于閑置狀態時會去查找事件佇列是否有任務待執行,如果有則>將回呼函式加入到主執行緒的方法執行堆疊中執行,如此反復,我們就把這個回圈程序稱為事件回圈機制(EventLoop),
不知道介紹了JS的件回圈機制,大家有沒有對Event Loop有了一個初步的認識,下面我將會著重介紹我們主角Netty的執行緒模型及其與Event Loop的聯系,
Netty執行緒模型
Netty的執行緒模型基于Reactor,Reactor的核心在于事件分發,它有三種經典的執行緒模型(單執行緒模型,多執行緒>模型,主從多執行緒模型),下面我們會結合Netty的EventLoop機制一一介紹
Reactor單執行緒模型
單執行緒模型全域只有一個執行緒在作業,也就意味著請求的接收,分發,IO讀取寫入等操作都在一個執行緒中完成,該>模型算得上是最經典的執行緒模型了,例如redis也是采用的此種單執行緒模型了,

可以看到上圖中,我們把一個Reactor執行緒可以認為是一個EventLoop IO執行緒,一個事件回圈機制,
由于其執行緒中的IO讀寫都是基于NIO,理論上所有的IO讀寫操作都不會阻塞EventLoop執行緒,所以即使是該單執行緒>模型,也是足以應付絕大多數的場景,
那么為什么又會延伸出Reactor多執行緒模型呢?
當應用并發量非常大時,例如一個Reactor NIO 執行緒需要同時處理成百上千的連接時,雖然IO讀寫是非阻塞的,>但是訊息的編碼解碼都是需要同步阻塞的,這就導致NIO執行緒處理速度變慢,最終導致訊息積壓,出現性能瓶頸,
基于以上原因也就演進出了第二種模型Reactor多執行緒模型
Reactor多執行緒模型
Reactor多執行緒模型與Reactor單執行緒模型最大的區別就是,有一組Reactor NIO執行緒(也就是一組 EventLoop)來處理IO操作

通過上圖,可以比較清晰的看到,IO的讀寫操作都由一個Reactor NIO執行緒池(對應到EventLoop也就是EventLoopGroup)來完成的,而請求的監聽和Accept則是由另一個單獨的Reactor執行緒來完成,
注意Reactor NIO執行緒池中的每一個執行緒都是處理N條鏈路,但是一個鏈路只能有一個執行緒來處理
多執行緒的Reactor模型可以滿足絕大部分的應用場景,通常情況下,我們使用Netty使用這種執行緒模型就OK(創建>兩個NioEventLoopGroup,bossGroup大小為1,workGroup大小為CPU*2),但是有可能會存在某些極少數的情況,一
個Reactor執行緒處理請求的Accept可能會產生性能瓶頸,例如上百萬的并發連接請求,這時候我們可能就需要采
用第三種模型Reactor主從多執行緒模型
Reactor主從多執行緒模型
Reactor主從多執行緒模型和Reactor多執行緒模型的區別在于原本是一個Reactor執行緒處理請求的Accept,變成了
一組Reactor執行緒,

對于Reactor主從多執行緒模型,其實大多數情況下我們并不需要,即使我們給BossGroup指定了多個執行緒,最終也>只會選擇其中的一個作為Accepor的NIO執行緒,除非在服務端系結了多個埠的情況下才會啟用BossGroup的多個線
程,
尾言
把Netty的執行緒模型以及EventLoop理解清楚,個人覺得最好的方法還是順著Netty的原始碼一步一步看,看多了
也就理解了這幾種執行緒模型分別對應了哪幾種情況,后面的文章我應該會根據原始碼來進一步理解netty
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/188607.html
標籤:Java
上一篇:簡單了解一下 EasyExcel
