1. 程式人生 > >Netty原始碼閱讀之如何將TCP的讀寫操作和指定執行緒繫結

Netty原始碼閱讀之如何將TCP的讀寫操作和指定執行緒繫結

**原文連結**:[http://xueliang.org/article/detail/20200712234015993](http://xueliang.org/article/detail/20200712234015993) # 前言 在Netty的執行緒模型中,對於一個TCP連線的讀寫操作,都是由一個單執行緒完成的,對於剛入門Netty的新手,這完全顛覆我們熟知的多執行緒能夠加快處理速度,縮短處理時間的常規思路。 實際上,Netty採用了非同步通訊模式,一個IO 執行緒可以併發處理N 個客戶端連線和讀寫操作,這從根本上解決了傳統同步阻塞IO 一連線一執行緒模型,架構的效能、彈性伸縮能力和可靠性都得到了極大的提升。 # 原始碼閱讀 將 `Channel` 註冊到 Worker 執行緒組上 ![register()](http://image.xueliang.org/FrVq1Wm8crVJ5Rs017zbZesqPWsx) 呼叫 `NioEventLoopGroup` 的 `next()` 從 Worker 執行緒組中獲取一個 `eventLoop` ![next()](http://image.xueliang.org/FsmZ3jflXlJq8Sh9ogVLEDIh-m93) 根據執行緒組個數不同,會呼叫 `PowerOfTwoEventExecutorChooser` 或者 `GenericEventExecutorChooser` 的 `next()` 方法,如果執行緒數是 2 的 N 次方,就選用 `PowerOfTwoEventExecutorChooser` 這個 `EventLoop` 選擇類,使用位運算提高效率 ![choose executor](http://image.xueliang.org/FlGYFpHPhkge6rc8pVXWFodQJJGe) 呼叫選取的 `eventLoop` 的 `register()` 方法,可以看到,將 `this` 也就是當前 `EventLoop` 當做引數傳入 `promise.channel().unsafe().register()` 方法 ![eventLoop.register()](http://image.xueliang.org/FqiLO4yp1JdIXCo0-H9lXPM-UaA5) 繼續進到 `promise.channel().unsafe().register` 方法,到這裡,終於將 `eventLoop` 賦值給了 `Channel`,即 `Channel` 與 `eventLoop` 建立了繫結關係。 ![channel - eventloop](http://image.xueliang.org/Fpe2TekJSWWkC8BxUXGhRIRxG8S1) 但Channel還未與執行緒繫結,繼續往下看,當我們平時在Handler裡呼叫 `ctx` (即 `ChannelHandlerContext` 類物件)的 `write()` 時,實際是獲取 `ctx` 的 `executor` 執行寫操縱事件,若未給 `ctx` 指定 `executor`,則 `ctx` 會使用 對應的 `channel` 的 `eventLoop` ![ctx.eventLoop()](http://image.xueliang.org/FmCe4fvx91hwSxClLo7EalOLuxQN) 執行 `eventLoop` 的 `execute()` 方法 ![executor.execute()](http://image.xueliang.org/Fpdi-FcdIKXm9zz59P9x6LZA83Un) 進到 `execute()` 方法內,先通過呼叫 `inEventLoop()` 方法,判斷當前執行緒是否是 `eventLoop` 繫結的那個執行緒 ![eventLoop.inEventLoop()](http://image.xueliang.org/FuQ_q6ua8GNLBztfJR3X-0YxtzzF) 如果不是,則可能 `eventLoop` 還沒有繫結執行緒,則呼叫 `startThread` 方法建立一個執行緒 ![eventLoop.execute()](http://image.xueliang.org/FuWuY4fgXkTH-CUTiWptnOIKQwgT) 最終呼叫 `eventLoop` 的 `doStartThread()` ,由 `executor` 指定建立執行緒的任務。 ![eventLoop.doStartThread()](http://image.xueliang.org/FosdTYyXMVocyYIMJVU8t8CB-qox) 到此,Channel - EventLoop - Thread 繫結在了一起,同時也能看出多個 Channel 可能繫結到 一個EventLoop上 # 總結 Netty將一個TCP連線和一個固定的執行緒繫結,不需要進行執行緒切換以及執行緒同步,即節省資源又提高吞吐效率,除此之外我們在閱讀原始碼的過程中,從EventLoop的選取,根據不同的執行緒數,使用不同的輪詢器,可以看出Netty對於高效能的極致追求。 **原文連結**:[http://xueliang.org/article/detail/20200712234015993](http://xueliang.org/article/detail/2020071223