原文連接:http://xueliang.org/article/detail/20200712234015993promise
在Netty的線程模型中,對於一個TCP鏈接的讀寫操做,都是由一個單線程完成的,對於剛入門Netty的新手,這徹底顛覆咱們熟知的多線程可以加快處理速度,縮短處理時間的常規思路。
實際上,Netty採用了異步通訊模式,一個IO 線程能夠併發處理N 個客戶端鏈接和讀寫操做,這從根本上解決了傳統同步阻塞IO 一鏈接一線程模型,架構的性能、彈性伸縮能力和可靠性都獲得了極大的提高。多線程
將 Channel
註冊到 Worker 線程組上架構
調用 NioEventLoopGroup
的 next()
從 Worker 線程組中獲取一個 eventLoop
併發
根據線程組個數不一樣,會調用 PowerOfTwoEventExecutorChooser
或者 GenericEventExecutorChooser
的 next()
方法,若是線程數是 2 的 N 次方,就選用 PowerOfTwoEventExecutorChooser
這個 EventLoop
選擇類,使用位運算提升效率異步
調用選取的 eventLoop
的 register()
方法,能夠看到,將 this
也就是當前 EventLoop
當作參數傳入 promise.channel().unsafe().register()
方法oop
繼續進到 promise.channel().unsafe().register
方法,到這裏,終於將 eventLoop
賦值給了 Channel
,即 Channel
與 eventLoop
創建了綁定關係。性能
但Channel還未與線程綁定,繼續往下看,當咱們平時在Handler裏調用 ctx
(即 ChannelHandlerContext
類對象)的 write()
時,實際是獲取 ctx
的 executor
執行寫操縱事件,若未給 ctx
指定 executor
,則 ctx
會使用 對應的 channel
的 eventLoop
this
執行 eventLoop
的 execute()
方法spa
進到 execute()
方法內,先經過調用 inEventLoop()
方法,判斷當前線程是不是 eventLoop
綁定的那個線程線程
若是不是,則可能 eventLoop
尚未綁定線程,則調用 startThread
方法建立一個線程
最終調用 eventLoop
的 doStartThread()
,由 executor
指定建立線程的任務。
到此,Channel - EventLoop - Thread 綁定在了一塊兒,同時也能看出多個 Channel 可能綁定到 一個EventLoop上
Netty將一個TCP鏈接和一個固定的線程綁定,不須要進行線程切換以及線程同步,即節省資源又提升吞吐效率,除此以外咱們在閱讀源碼的過程當中,從EventLoop的選取,根據不一樣的線程數,使用不一樣的輪詢器,能夠看出Netty對於高性能的極致追求。