Netty整體架構解析

MuXinu發表於2024-03-23

一、整理架構

下圖是Netty官網上給出的整體功能模組:
0

1. Core 核心層

Core核心層是Netty最精華的部分了,它提供了底層網路通訊的抽象和實現,包括可擴充套件的事件模式、通用的通訊API和支援零複製的ByteBuf

2. Protocol Support 協議支援層

協議支援層上基本覆蓋了現在主流協議的編解碼實現,例如HTTP、WebSocket、SSL、Protobuf、壓縮、大檔案傳輸等主流協議,此外Netty還支援自定義應用層協議。Netty豐富的協議支援降低了使用的開發成本,基於Netty可以快速開始HTTP、WebSocket等服務。

3. Transport Service 傳輸服務層

傳輸服務層提供了網路傳輸能力的定義和實現方法。它支援Socket、HTTP隧道和虛擬機器通道等傳輸方式。Netty對TCP、UDP等資料闡述做了抽象和封裝,開發者可以聚焦在業務邏輯的實現上,而不必關心底層資料傳輸的細節。
Netty的模組化設計具有較高的通用性和可擴充套件性,Netty不僅是一個有效的網路框架,還可以作為網路程式設計的工具箱。

二、Netty 的邏輯架構

Netty 的邏輯處理架構是典型的網路分層架構設計的,分別為網路通訊層、事件排程層和服務編排層。每一層各司其職,如下圖所示:
0

1. 網路通訊層

網路通訊層的職責就是執行網路I/O的操作。它支援多種網路協議和I/O模型的連線操作。當網路資料讀取到核心緩衝區後,會觸發各種網路事件,這些網路事件會分發給事件排程層來處理。網路通訊層有三個核心元件:Bootstrap、ServerBootstrap和Channel。
0
  • Bootstrap 和 ServerBootstrap
Bootstrap和ServerBootstrap都繼承於AbstractBootstrap,在功能上很相似。Bootstrap是用於連線服務端的,一般用於Client的開發上;ServerBootstrap則是用於服務端啟動繫結本地埠,一般繫結兩個EventLoopGroup(主從多執行緒Reactor),一個稱為boss,另外一個成為worker。
Bootstrap/ServerBootstrap元件更加方便我們配置和啟動Netty程式,它是整個Netty程式的入口,串聯了Netty所有核心元件的初始化工作。
  • Channel
我們平常用到基本的 I/O 操作(bind()、connect()、read()和 write()),其本質都依賴於底層網路傳輸所提供的原語,在Java中就是Socket類。
Netty 的 Channel 接 口所提供的 API,大大地降低了直接使用Socket 類的複雜性。另外Channel 提供非同步的網路 I/O 操作(如建立連線,讀寫,繫結埠),非同步呼叫意味著任何 I/O 呼叫都將立即返回,並且不保證在呼叫結束時所請求的 I/O 操作已完成。
在呼叫結束後立即返回一個 ChannelFuture 例項,透過註冊監聽器到 ChannelFuture 上,支援 在I/O 操作成功、失敗或取消時立馬回撥通知呼叫方。
此外,Channel 也是擁有許多預定義的、專門化實現的廣泛類層次結構的根,比如:
  • LocalServerChannel:用於本地傳輸的ServerChannel ,允許 VM 通訊。
  • EmbeddedChannel:以嵌入式方式使用的 Channel 實現的基類。
  • NioSocketChannel:非同步的客戶端 TCP 、Socket 連線。
  • NioServerSocketChannel:非同步的伺服器
  • NioDatagramChannel: 非同步的 UDP 連線。
  • NioSctpChannel:非同步的客戶端 Sctp 連線,它使用非阻塞模式並允許將SctpMessage讀/寫到底層SctpChannel。
  • NioSctpServerChannel:非同步的 Sctp 伺服器端連線,這些通道涵蓋了 UDP 和 TCP 網路 IO 以及檔案 IO。
Channel事件狀態:
出站事件
0
進站事件
0

2. 事件排程層

事件排程層透過Reactor執行緒模型對各類事件進行聚合處理,透過Selector主迴圈執行緒整合多種事件(I/O事件、訊號事件、定時事件等),實際的業務處理邏輯交給服務編排層的ChannelHandler來處理。
事件排程層最核心的元件就是EventLoop和EventLoopGroup:EventLoopGroup實質上是Netty基於JDK執行緒池的抽象,本質就是執行緒池,主要負責接收I/O請求,並分配執行緒執行處理。而EventLoop可以理解成一個執行緒,EventLoop建立出來之後會跟一個執行緒繫結並且處理Channel中的事件。如下圖所示:
0
1、一個EventLoopGroup包含一個或者多個EventLoop。EventLoop用於處理Channel生命週期的所有I/O事件。
2、EventLoop在同一時間只會跟一個執行緒繫結。每個EventLoop負責處理多個Channel。
3、每個新建的Channel,EventLoopGroup會選擇一個EventLoop與其繫結。該Channel在生命週期內都可以對EventLoop及進行多次繫結和解綁。
Netty中不同的I/O模型有對應的EventLoop實現,下面是常用NioEventLoop的家族圖譜:
0
EventLoopGroup是Netty Reactor執行緒模型的具體實現方式,Netty透過建立不同的EventLoopGroup引數配置就可以支援Reactor的三種執行緒模型:
  1. Reactor單執行緒模型:EventLoopGroup 只包含一個 EventLoop,Boss 和 Worker 使用同一個EventLoopGroup
  2. 非主從Reactor多執行緒模型:EventLoopGroup 包含多個 EventLoop,Boss 和 Worker 使用同一個EventLoopGroup
  3. 主從Reactor多執行緒模型:EventLoopGroup 包含多個 EventLoop,Boss 是主 Reactor,Worker 是從 Reactor,它們分別使用不同的 EventLoopGroup,主 Reactor 負責新的網路連線 Channel 建立,然後把 Channel 註冊到從 Reactor
0

3. 服務編排層

服務編排的職責是組裝各類服務,它是Netty的核心處理鏈,用以實現網路事件的動態編排和有序傳播。
服務編排的核心元件有:ChannelPipeline、ChannelHandler、ChannelHandlerContext。

1、ChannelPipeline

Netty的核心編排元件,負責組裝各類的ChannelHandler,實際資料的編解碼以及加工處理的操作是由ChannelHandler來完成的。ChannelPipeline內部透過雙向連結串列將不同的ChannelHandler連結在一起。當I/O讀寫事件觸發時,ChannelPipeline會一次呼叫ChannelHandler列表對Channel的資料進行攔截和處理。
ChannelPipeline是執行緒安全的,因為每一個新的Channel都會對應一個新的ChannelPipeline。一個ChannelPipeline關聯一個EventLoop,一個EventLoop只會繫結一個執行緒。如下如圖擷取來自ChannelPipeline類註釋中:
可以看得出來,ChannelPipeline中包含入站ChannelInboundHandler和出戰的ChannelOutboundHandler兩種處理器,結合服務端和客戶端的資料收發來看,如下圖:
0
客戶端和服務端都有自己的ChannelPipeline。
從客戶端來看
1.資料從客戶端發出到達Channel,該過程稱為出站,反之由Channel到達客戶端則稱為入站;
2.出站會觸發一系列OutBoundHandler處理,入站會觸發InBoundHandler處理,我們經常使用的編碼 Encoder 是出站操作,解碼 Decoder 是入站操作。
從服務端來看
1.資料從Channel到達服務端,該過程稱為入站,反之由服務端到達Channel則稱為出站;
2.服務端接收到客戶端資料後,需要先經過 Decoder 入站處理後,再透過 Encoder 出站通知客戶端;
所以客戶端和服務端一次完整的請求應答過程可以分為四個步驟:
  1. 客戶端出站(請求資料)
  2. 服務端入站(解析資料並執行業務邏輯)
  3. 服務端出站(響應結果)
  4. 客戶端入站(解析資料並執行業務邏輯)
InBoundHandler和OutBoundHandler的執行順序如下圖,進站時根據InBoundHandler的新增順序執行,出站時OutBoundHandler則是逆序執行。
0

2、ChannelHandler 和 ChannelHandlerContext

每建立一個 Channel 都會繫結一個新的 ChannelPipeline,ChannelPipeline 中每加入一個 ChannelHandler 都會繫結一個 ChannelHandlerContext。由此可見,ChannelPipeline、ChannelHandlerContext、ChannelHandler 三個元件的關係是密切相關的。
ChannelHandlerContext 用於儲存 ChannelHandler 上下文,透過 ChannelHandlerContext 我們可以知道 ChannelPipeline 和 ChannelHandler 的關聯關係。ChannelHandlerContext 可以實現 ChannelHandler 之間的互動,ChannelHandlerContext 包含了 ChannelHandler 生命週期的所有事件,如 connect、bind、read、flush、write、close 等。
如下如圖:
0

三、服務端主從Reactor模式工作流程

3.1 Server工作流程圖

0

3.2 Server工作流程分析

  1. server端啟動時繫結本地某個埠,初始化NioServerSocketChannel.
  2. 將自己NioServerSocketChannel註冊到某個BossNioEventLoopGroup的selector上。
    • server端包含1個Boss NioEventLoopGroup和1個Worker NioEventLoopGroup,
    • Boss NioEventLoopGroup專門負責接收客戶端的連線,Worker NioEventLoopGroup專門負責網路的讀寫
    • NioEventLoopGroup相當於1個事件迴圈組,這個組裡包含多個事件迴圈NioEventLoop,每個NioEventLoop包含1個selector和1個事件迴圈執行緒。
  1. BossNioEventLoopGroup迴圈執行的任務:
    • 輪詢accept事件;
    • 處理accept事件,將生成的NioSocketChannel註冊到某一個WorkNioEventLoopGroup的Selector上。
    • 處理任務佇列中的任務,runAllTasks。任務佇列中的任務包括使用者呼叫eventloop.execute或schedule執行的任務,或者其它執行緒提交到該eventloop的任務。
  1. WorkNioEventLoopGroup迴圈執行的任務:
    • 輪詢read和Write事件
    • 處理IO事件,在NioSocketChannel可讀、可寫事件發生時,回撥(觸發)ChannelHandler進行處理。
    • 處理任務佇列的任務,即 runAllTasks
參考:
https://juejin.cn/post/7176589585042899004
https://cloud.tencent.com/developer/article/2146079

相關文章