Netty:核心組件淺嘗

下文中介紹的是Netty應用程序的全部基本構建模塊,其中客戶端和服務器也包含在內。

基本組件概念

1.BOOTSTRAP(啓動)

Netty 應用程序通過設置 bootstrap(引導)類的開始,該類提供了一個 用於應用程序網絡層配置的容器。

2.CHANNEL(通道)

底層網絡傳輸 API 必須給應用提供 I/O操作的接口,如讀,寫,連接,綁定等等。對於我們來說,這是結構幾乎總是會成爲一個“socket”。 Netty 中的接口 Channel 定義了與 socket 豐富交互的操作集:bind, close, config, connect, isActive, isOpen, isWritable, read, write 等等。

Netty 提供大量的 Channel 實現來專門使用。這些包括 AbstractChannel,AbstractNioByteChannel,AbstractNioChannel,EmbeddedChannel, LocalServerChannel,NioSocketChannel 等等。
在這裏插入圖片描述

3.CHANNELHANDLER(通道處理器)

ChannelHandler 支持很多協議,並且提供用於數據處理的容器, ChannelHandler 由特定事件觸發。
ChannelHandler 可專用於幾乎所有的動作,包括將一個對象轉爲字節(或相反),執行過程中拋出的異常處理。

在這裏插入圖片描述

3.1ChannelHandler

核心實現:ChannelInboundHandler 和 ChannelOutboundHandler 繼承自父接口 ChannelHandler。 Netty 中有兩個方向的數據流,下圖顯示的入站(ChannelInboundHandler)和出站(ChannelOutboundHandler)之間有一個明顯的區別:若數據是從用戶應用程序到遠程主機則是“出站(outbound)”,相反若數據時從遠程主機到用戶應用程序則是“入站(inbound)”。

**爲了使數據從一端到達另一端,一個或多個 ChannelHandler 將以某種方式操作數據。**這些 ChannelHandler 會在程序的“引導”階段被添加ChannelPipeline中,並且被添加的順序將決定處理數據的順序。
在這裏插入圖片描述
圖中 同樣展示了進站和出站的處理器都可以被安裝在相同的 pipeline。本例子中,如果消息或任何其他入站事件被讀到,將從 pipeline 頭部開始,傳遞到第一個 ChannelInboundHandler。該處理器可能會或可能不會實際修改數據,取決於其特定的功能,在這之後 該數據將被傳遞到鏈中的下一個 ChannelInboundHandler。最後,將數據 到達 pipeline 的尾部,此時所有處理結束。

數據的出站運動(即,數據被“寫入”)在概念上是相同的。在這種情況下的數據從尾部流過 ChannelOutboundHandlers 的鏈,直到它到達頭部。超過這點,出站數據將到達的網絡傳輸,在這裏顯示爲一個 socket。通常,這將觸發一個寫入操作。

3.2 ChannelInboundHandlerAdapter 和hannelOutboundHandlerAdapter

在當前的鏈(chain)中,事件可以通過 ChanneHandlerContext 傳遞給下一個 handler。Netty 爲此提供了抽象基類ChannelInboundHandlerAdapter 和 hannelOutboundHandlerAdapter,用來處理你想要的事件。 在實際應用中,您可以按需覆蓋相應的方法即可。

4.CHANNELPIPELINE(通道流水線)

ChannelPipeline 是一系列的ChannelHandler 實例,流經一個 Channel 的入站和出站事件可以被ChannelPipeline 攔截,ChannelPipeline能夠讓用戶自己對入站/出站事件的處理邏輯,以及pipeline裏的各個Handler之間的交互進行定義。

每當一個新的Channel被創建了,都會建立一個新的 ChannelPipeline,並且這個新的 ChannelPipeline 還會綁定到Channel上。這個關聯是永久性的;Channel 既不能附上另一個 ChannelPipeline 也不能分離當前這個。這些都由Netty負責完成,,而無需開發人員的特別處理。
ChannelHandler 是如何註冊到 ChannelPipeline?
主要是實現了ChannelHandler 的抽象 ChannelInitializer,ChannelInitializer子類 通過 ServerBootstrap 進行註冊。當它的方法 initChannel() 被調用時,這個對象將註冊自定義的 ChannelHandler 集到 pipeline。當這個操作完成時,ChannelInitializer 子類則 從 ChannelPipeline 自動刪除自身。
根據它的起源,一個事件將由 ChannelInboundHandler 或 ChannelOutboundHandler 處理。隨後它將調用 ChannelHandlerContext 實現轉發到下一個相同的超類型的處理程序。
ChannelPipeline 對於ChannelHandler的基本處理
在這裏插入圖片描述
一個 ChannelPipeline 是用來保存關聯到一個 Channel 的ChannelHandler
可以修改 ChannelPipeline 通過動態添加和刪除 ChannelHandler
ChannelPipeline 有着豐富的API調用動作來回應入站和出站事件。(https://www.w3cschool.cn/essential_netty_in_action/essential_netty_in_action-p5dk28bp.html)

5.EVENTLOOP(事件循環)

EventLoop 用於處理 Channel 的 I/O 操作。一個單一的 EventLoop通常會處理多個 Channel 事件。一個 EventLoopGroup 可以含有多於一個的 EventLoop 和 提供了一種迭代用於檢索清單中的下一個。

6.CHANNELFUTURE(通道回調處理)

Netty 所有的 I/O 操作都是異步。因爲一個操作可能無法立即返回,我們需要有一種方法在以後確定它的結果。出於這個目的,Netty 提供了接口 ChannelFuture,它的 addListener 方法註冊了一個 ChannelFutureListener ,當操作完成時,可以被通知(不管成功與否)。
ChannelFuture 對象作爲一個未來執行操作結果的佔位符。何時執行取決於幾個因素,因此不可能預測與精確。但我們可以肯定的是,它會被執行。此外,所有的操作返回 ChannelFuture 對象和屬於同一個 Channel 將在以正確的順序被執行。

Channel, Event 和 I/O的關係

Netty是一個異步事件驅動的NIO框架,Netty的所有IO操作都是異步非阻塞的。Netty 實際上是使用 Threads(多線程)處理 I/O 事件,熟悉多線程編程的讀者可能會需要關注同步代碼。Netty 的設計保證程序處理事件不會有同步。圖 Figure 3.1 展示了,你不需要在 Channel 之間共享 ChannelHandler 實例的原因:

在這裏插入圖片描述
該圖顯示,一個 EventLoopGroup 具有一個或多個 EventLoop。EventLoop 作爲一個 Thread 給 Channel 執行工作。 當創建一個 Channel,Netty 向 Channel註冊了一個單獨的 EventLoop 實例

Bootstrapping的作用

Bootstrapping(引導) 是出現在Netty 配置程序的過程中,Bootstrapping在給服務器綁定指定窗口或者要連接客戶端的時候會使用到。Bootstrapping 有以下兩種類型:一種是用於客戶端的Bootstrap;一種是用於服務端的ServerBootstrap。
不管程序使用哪種協議,創建的是一個客戶端還是服務器,“引導”都是必須要使用到的。

1.面向連接 vs. 無連接

TCP 協議,它是“面向連接”的。這樣協議保證該連接的端點之間的消息的有序輸送。無連接協議發送的消息,無法保證順序和成功性。

兩種 Bootstrapping 之間有一些相似之處,也有一些不同。Bootstrap 和 ServerBootstrap 之間的差異如下:
在這裏插入圖片描述
ServerBootstrap服務器監聽一個端口輪詢客戶端的“Bootstrap”或DatagramChannel是否連接服務器。
通常“Bootstrap”類需要調用connect()方法,但是也可以先調用bind()再調用connect()進行連接,之後使用的Channel包含在bind()返回的ChannelFuture中。

一個 ServerBootstrap 可以認爲有2個 Channel 集合:

  1. 第一個集合包含一個單例 ServerChannel,代表持有一個綁定了本地端口的 socket
  2. 第二集合包含所有創建的Channel,處理服務器所接收到的客戶端進來的連接
    下圖形象的描述了這種情況:
    在這裏插入圖片描述
    與 ServerChannel 相關 EventLoopGroup 分配一個 EventLoop 負責創建 Channels (Accepted Channel)用於傳入的連接請求。一旦建立了連接,第二個EventLoopGroup 就會在 Accepted Channel註冊一個 EventLoop。

2.ChannelHandlerContext

當ChannelHandler 添加到 ChannelPipeline 時會創建一個ChannelHandlerContext的實例,它代表了 ChannelHandler 和ChannelPipeline 之間的關聯。

接口ChannelHandlerContext 主要是對同一個 ChannelPipeline 中關聯的 ChannelHandler 之間的交互進行管理。它通常是安全保存ChannelHandler的引用,除了當協議中的使用的是不面向連接(例如,UDP)。而該對象可以被用來獲得 底層 Channel,它主要是用來寫出站數據。

ChannelHandlerContext 中包含了有許多方法,其中一些方法也出現在 Channel 和ChannelPipeline 本身。如果您通過Channel 或ChannelPipeline 的實例來調用這些方法,他們就會在整個 pipeline中傳播 。相比之下,一樣的方法在 ChannelHandlerContext 的實例上調用, 就只會從當前的 ChannelHandler 開始並傳播到相關管道中的下一個有處理事件能力的 ChannelHandler 。
在這裏插入圖片描述
在這裏插入圖片描述

//清單:6.6
ChannelHandlerContext ctx = context;
//1得到與 ChannelHandlerContext 關聯的 Channel 的引用
Channel channel = ctx.channel();  
//2通過 Channel 寫緩存
channel.write(Unpooled.copiedBuffer("Netty in Action",
        CharsetUtil.UTF_8));  
// 清單:6.7
ChannelHandlerContext ctx = context;
//1得到與 ChannelHandlerContext 關聯的 ChannelPipeline 的引用
ChannelPipeline pipeline = ctx.pipeline(); 
//2通過 ChannelPipeline 寫緩衝區
pipeline.write(Unpooled.copiedBuffer("Netty in Action", CharsetUtil.UTF_8));  

在這裏插入圖片描述
在這裏插入圖片描述
參考:https://www.w3cschool.cn/essential_netty_in_action/essential_netty_in_action-plhs289r.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章