Netty 核心組件
1. 前言
本節(jié)我們主要從整體上了解 Netty 有哪些核心組件,很多同學(xué)學(xué)習(xí)完 Netty 雖然會(huì)使用,但是只知道如何自定義 Handler 而已,根本不清楚 Netty 有哪些核心的組件。
本節(jié)的主要目的是,從整體上概括 Netty 的核心組件,有助于深入了解 Netty 以及關(guān)于 Netty 的面試。
2. 核心組件
Netty 的核心模塊組件主要分為以下:
組件模塊 | 說明 |
---|---|
Boostrap | Bootstrap 其實(shí)就是啟動(dòng)的意思,主要用來(lái)配置 Netty 的相關(guān)配置,串聯(lián)各個(gè)組件,針對(duì)客戶端。 |
ServerBootstrap | 同上,只是它是針對(duì)服務(wù)端。 |
線程模型 | 了解 Reactor 線程模型。 |
EventLoopGroup | 是一組 EventLoop 的抽象,可以簡(jiǎn)單理解就是線程池,一般分為 BossEventLoopGroup 和 WorkerEventLoopGroup。 |
ChannelFuture | Netty 的所有 IO 操作都是異步的,通過注冊(cè)監(jiān)聽器來(lái)監(jiān)聽執(zhí)行結(jié)果的返回。 |
Channel | Netty 的網(wǎng)絡(luò)通信組件,客戶端和服務(wù)端建立連接之后會(huì)維持一個(gè) Channel。 |
ChannelHandlerContext | 保存 Channel 對(duì)于的上下文,同時(shí)關(guān)聯(lián)一個(gè) ChannelHandler 對(duì)象。 |
ChannelHandler | 自定義業(yè)務(wù) Handler 需要實(shí)現(xiàn)它或它的子類,提供了一套生命周期的方法。 |
ChannelPipeline | ChannelPipeline 可認(rèn)為是一個(gè)管道,是管理業(yè)務(wù) Handler,通俗理解是保存 ChannelHandler 的 List 集合。 |
ByteBuf | ByteBuf 是一個(gè)字節(jié)容器,提供了常見 api。Netty 是面向 ByteBuf 來(lái)傳輸數(shù)據(jù)的。 |
編碼和解碼 | Netty 內(nèi)置了常見編解碼器,我們也可以自定義自己的編解碼器。并且可以把編解碼器封裝成獨(dú)立的 Handler,簡(jiǎn)化繁瑣的流程。 |
拆包和粘包問題 | 了解為什么會(huì)出現(xiàn)拆包和粘包問題,如何去解決它,以及 Netty 內(nèi)置了常見的拆包器。 |
總結(jié),以上組件(或者知識(shí)點(diǎn))是 Netty 知識(shí)體系里面的核心,并且也是面試當(dāng)中經(jīng)常問的內(nèi)容,有的只需要配置一下即可,很少需要我們?nèi)ス埽ㄈ纾篍ventLoopGroup);有的需要我們?nèi)プ远x擴(kuò)展。
核心組件架構(gòu)圖:
在真實(shí)開發(fā)當(dāng)中,需要我們?nèi)ソ鉀Q的問題,主要如下:
- 使用 ChannelPipeline 管理自定義 ChannelHandler;
- 業(yè)務(wù)實(shí)體和 ByteBuf 之間的轉(zhuǎn)換;
- 借助第三方序列化技術(shù)、自定義通信協(xié)議規(guī)則、反射等,自定義編碼和解碼器,使用通用實(shí)體;
- 如何解決拆包和粘包問題,其發(fā)生的原因是什么,如果解決。
3. 組件詳解
Netty 的它優(yōu)勢(shì)在于,它是配置化的開發(fā),僅僅靠簡(jiǎn)單的配置,背后就能實(shí)現(xiàn)很復(fù)雜的邏輯。但是通常情況下我們很難去了解其背后的原理。下面我們主要挑選開發(fā)當(dāng)中比較常見的組件進(jìn)行講解。
3.1 ChannelHandler
ChannelHandler 是一個(gè)接口,處理 IO 事件,可以簡(jiǎn)單的理解它是一個(gè)鏈表當(dāng)中的一個(gè)節(jié)點(diǎn),它的 UML 圖如下所示:
ChannelHandler 架構(gòu)圖說明:
- ChannelHandler 兩個(gè)子接口,分別是 ChannelInboundHandler 和 ChannelOutboundHandler;其中 ChannelInboundHandler 主要用于處理入站的 I/O 事件;ChannelOutboundHandler 用于處理出站的 I/O 事件;
- ChannelInboundHandler 的實(shí)現(xiàn)類 ChannelInboundHandlerAdapter 處理入站 I/O 事件;
- ChannelOutboundHandler 的實(shí)現(xiàn)類 ChannelOutboundHandlerAdapter 處理出站 I/O 事件;
在開發(fā)當(dāng)中,ChannelInboundHandlerAdapter
是使用最多的,其它很少直接使用。值得注意的是 I/O 入站和出站的執(zhí)行順序,這個(gè)跟 SpringMVC 的攔截器的執(zhí)行順序一樣。
3.2. ChannelPipeline
ChannelPipeline 是一個(gè)比較核心的知識(shí)點(diǎn),它底層設(shè)計(jì)是采用責(zé)任鏈設(shè)計(jì)模式,主要作用是管理 Handler 雙向鏈表,包括入站和出站,主要是攔截 inboud 和 outbound 事件,然后每個(gè) handler 節(jié)點(diǎn)負(fù)責(zé)處理具體邏輯。
關(guān)系梳理:
- 一個(gè)客戶端對(duì)應(yīng)一個(gè) Channel;
- 一個(gè) Channel 對(duì)應(yīng)一個(gè) ChannelPipeline;
- 一個(gè) ChannelPipeline 又維護(hù)了一個(gè)雙向鏈表,其中鏈表的節(jié)點(diǎn)是
ChannelHandlerContext
; - 一個(gè)
ChannelHandlerContext
則關(guān)聯(lián)一個(gè)ChannelHandler
(自定義 Handler); - ChannelHandler 則是自定義 Handler 的一個(gè)頂級(jí)抽象接口。
入站和出站的順序:
- 入站: 事件會(huì)從鏈表的頭部一直往后執(zhí)行,
ChannelInboundHandlerAdapter
子類會(huì)被觸發(fā); - 出站: 事件會(huì)從鏈表的尾部一直往前執(zhí)行,
ChannelOutboundHandlerAdapter
子類會(huì)被觸發(fā)。
4. 小結(jié)
本節(jié)內(nèi)容,主要讓大家從整體上了解 Netty 有哪些核心的組件構(gòu)成,每個(gè)主要的作用是什么,主要是方便后面章節(jié)深入學(xué)習(xí)。其中,核心掌握 ChannelHandler 和 ChannelPipeline 這兩個(gè)組件,平時(shí)開發(fā)當(dāng)中涉及比較多的就是這兩個(gè)組件。
- 掌握 ChannelHandler 的 UML 架構(gòu)關(guān)系;
- 掌握入站和出站分別繼承 ChannelInboundHandlerAdapter 和 ChannelOutboundHandlerAdapter;
- 掌握 ChannelPipeline 和 ChannelHandler 之間的關(guān)系;
- 掌握入站和出站的執(zhí)行順序。