前言:不斷學習就是程序員的宿命

  上一篇:Netty學習01記錄了Socket入門案例並對比Netty基本組件,這篇記錄一下Netty基本組件。好記性不如爛筆頭,沉澱記錄下來自己才會心安。

一、Netty基本組件

netty 需要依賴什麼容器啓動_基本組件

NioEventLoop:可以認為是Netty的“發動機”,它內部啓動2種類型線程,其中一種用於監聽客户端的連接,另一種處理客户端的讀寫。

Channel:簡單來説,就是對一個連接的封裝,基於這個Channel進行數據讀寫

Pipeline:數據讀寫可以認為一個邏輯處理鏈,這個邏輯處理鏈就叫Pipeline

ChannelHandler:邏輯處理鏈中的每個邏輯對應的就是ChannelHandler

ByteBuf:在一條Channel上數據流的讀寫都是基於ByteBuf緩衝區來操作

 二、Netty服務端啓動流程

Netty服務端啓動流程

netty 需要依賴什麼容器啓動_初始化_02

問題:

  ①服務端的socket在哪裏初始化

  ②在哪裏accept連接

1、創建服務端Channel

netty 需要依賴什麼容器啓動_基本組件_03

1.1 bind方法

netty 需要依賴什麼容器啓動_基本組件_04

1.2 initAndRegister()方法

netty 需要依賴什麼容器啓動_服務端_05

 通過ChannelFactory來獲取Channel,實際是通過反射來獲取Channel實例

netty 需要依賴什麼容器啓動_netty 需要依賴什麼容器啓動_06

 這裏的clazz指的就是我們在外部指定的NioServerSocketChannel.class(何以見得?)跟進這個工廠channelFactory是在哪裏初始化的?

netty 需要依賴什麼容器啓動_初始化_07

 跟進channel方法,發現netty將我們指定的ChannelClass封裝為ReflectiveChannelFactory,最後通過該channelFactory反射創建服務端Channel

netty 需要依賴什麼容器啓動_netty 需要依賴什麼容器啓動_08

 1.2.1反射創建服務端Channel過程

 

netty 需要依賴什麼容器啓動_初始化_09

 ①查看NioServerSocketChannel的構造方法,channelFactory通過反射創建Channel時會調用如下構造方法,進而調用newSocket()方法通過jdk底層來創建jdk底層Channel

netty 需要依賴什麼容器啓動_netty 需要依賴什麼容器啓動_10

 跟進newSocket(),調用jdk底層方法來創建jdk底層Channel

netty 需要依賴什麼容器啓動_初始化_11

② 再看NioServerSocketChannelConfig的創建(該配置類主要用於後續對該Channel的一些tcp底層參數相關的獲取)

netty 需要依賴什麼容器啓動_netty 需要依賴什麼容器啓動_12

 ③調用父類構造函數AbstractNioChannel()

netty 需要依賴什麼容器啓動_netty 需要依賴什麼容器啓動_13

④調用AbstractChannel()構造方法(客户端與服務端Channel都繼承此Channel) 

netty 需要依賴什麼容器啓動_初始化_14

 至此、服務端Channel創建完成

2、服務端Channel初始化

  服務端創建完Channel之後就會進行對其進行初始化,簡單來説,保存用户自定義的屬性,創建帶有這些屬性的連接接入器(特殊的ChannelHandler),連接接入器每次Accept新連接之後都會使用這些屬性對新的連接做一些配置.

netty 需要依賴什麼容器啓動_基本組件_15

2.1 init()方法入口

netty 需要依賴什麼容器啓動_基本組件_16

2.2 設置用户自定義屬性

netty 需要依賴什麼容器啓動_初始化_17

 創建連接接入器

 

netty 需要依賴什麼容器啓動_初始化_18

3、註冊Selector

  init()方法入口,首先將當前NIO線程和當前Channel做綁定;調用register0()實際註冊Selector,在這過程中做了3件事:①調用jdk底層註冊,將當前Channel作為一個Attachment綁定到Selector上;接下來會連續觸發2個事件(invokeHandlerAddedIfNeeded()、fireChannelRegitered()),通過這兩個事件最終傳播到用户的方法

netty 需要依賴什麼容器啓動_netty 需要依賴什麼容器啓動_19

1、register()方法入口

netty 需要依賴什麼容器啓動_初始化_20

2、register0()方法

  這裏是實際註冊Selector,主要包含以下3部分

netty 需要依賴什麼容器啓動_基本組件_21

 2.1 doRegister()方法

netty 需要依賴什麼容器啓動_服務端_22

2.2 invokeHandlerAddedIfNeeded()和fireChannelRegistered()方法

netty 需要依賴什麼容器啓動_初始化_23

4、端口綁定

netty 需要依賴什麼容器啓動_服務端_24