Netty框架的架構設計
介紹完 Netty 相關一些理論,下面從功能特性、模塊組件、運作過程來介紹 Netty 的架構設計。
1.1功能特性
Netty 功能特性如下:
- 1)傳輸服務:支持 BIO 和 NIO;
- 2)容器集成:支持 OSGI、JBossMC、Spring、Guice 容器;
- 3)協議支持:HTTP、Protobuf、二進制、文本、WebSocket 等一系列常見協議都支持。還支持通過實行編碼解碼邏輯來實現自定義協議;
- 4)Core 核心:可擴展事件模型、通用通信 API、支持零拷貝的 ByteBuf 緩衝對象。
1.2模塊組件
【Bootstrap、ServerBootstrap】:
Bootstrap 意思是引導,一個 Netty 應用通常由一個 Bootstrap 開始,主要作用是配置整個 Netty 程序,串聯各個組件,Netty 中 Bootstrap 類是客戶端程序的啟動引導類,ServerBootstrap 是服務端啟動引導類。
【Future、ChannelFuture】:
正如前面介紹,在 Netty 中所有的 IO 操作都是異步的,不能立刻得知消息是否被正確處理。
但是可以過一會等它執行完成或者直接註冊一個監聽,具體的實現就是通過 Future 和 ChannelFutures,他們可以註冊一個監聽,當操作執行成功或失敗時監聽會自動觸發註冊的監聽事件。
【Channel】:
Netty 網絡通信的組件,能夠用於執行網絡 I/O 操作。Channel 為用戶提供:
- 1)當前網絡連接的通道的狀態(例如是否打開?是否已連接?)
- 2)網絡連接的配置參數 (例如接收緩衝區大小)
- 3)提供異步的網絡 I/O 操作(如建立連接,讀寫,綁定端口),異步調用意味著任何 I/O 調用都將立即返回,並且不保證在調用結束時所請求的 I/O 操作已完成。
- 4)調用立即返回一個 ChannelFuture 實例,通過註冊監聽器到 ChannelFuture 上,可以 I/O 操作成功、失敗或取消時回調通知調用方。
- 5)支持關聯 I/O 操作與對應的處理程序。
不同協議、不同的阻塞類型的連接都有不同的 Channel 類型與之對應。
下面是一些常用的 Channel 類型:
- NioSocketChannel,異步的客戶端 TCP Socket 連接。
- NioServerSocketChannel,異步的服務器端 TCP Socket 連接。
- NioDatagramChannel,異步的 UDP 連接。
- NioSctpChannel,異步的客戶端 Sctp 連接。
- NioSctpServerChannel,異步的 Sctp 服務器端連接,這些通道涵蓋了 UDP 和 TCP 網絡 IO 以及文件 IO。
【Selector】:
Netty 基於 Selector 對象實現 I/O 多路複用,通過 Selector 一個線程可以監聽多個連接的 Channel 事件。
當向一個 Selector 中註冊 Channel 後,Selector 內部的機制就可以自動不斷地查詢(Select) 這些註冊的 Channel 是否有已就緒的 I/O 事件(例如可讀,可寫,網絡連接完成等),這樣程序就可以很簡單地使用一個線程高效地管理多個 Channel 。
【NioEventLoop】:
NioEventLoop 中維護了一個線程和任務隊列,支持異步提交執行任務,線程啟動時會調用 NioEventLoop 的 run 方法,執行 I/O 任務和非 I/O 任務:
- I/O 任務,即 selectionKey 中 ready 的事件,如 accept、connect、read、write 等,由 processSelectedKeys 方法觸發。
- 非 IO 任務,添加到 taskQueue 中的任務,如 register0、bind0 等任務,由 runAllTasks 方法觸發。
兩種任務的執行時間比由變量 ioRatio 控制,默認為 50,則表示允許非 IO 任務執行的時間與 IO 任務的執行時間相等。
【NioEventLoopGroup】:
NioEventLoopGroup,主要管理 eventLoop 的生命週期,可以理解為一個線程池,內部維護了一組線程,每個線程(NioEventLoop)負責處理多個 Channel 上的事件,而一個 Channel 只對應於一個線程。
【ChannelHandler】:
ChannelHandler 是一個接口,處理 I/O 事件或攔截 I/O 操作,並將其轉發到其 ChannelPipeline(業務處理鏈)中的下一個處理程序。
ChannelHandler 本身並沒有提供很多方法,因為這個接口有許多的方法需要實現,方便使用期間,可以繼承它的子類:
- ChannelInboundHandler 用於處理入站 I/O 事件。
- ChannelOutboundHandler 用於處理出站 I/O 操作。
或者使用以下適配器類:
- ChannelInboundHandlerAdapter 用於處理入站 I/O 事件。
- ChannelOutboundHandlerAdapter 用於處理出站 I/O 操作。
- ChannelDuplexHandler 用於處理入站和出站事件。
【ChannelHandlerContext】:
保存 Channel 相關的所有上下文信息,同時關聯一個 ChannelHandler 對象。
【ChannelPipline】:
保存 ChannelHandler 的 List,用於處理或攔截 Channel 的入站事件和出站操作。
ChannelPipeline 實現了一種高級形式的攔截過濾器模式,使用戶可以完全控制事件的處理方式,以及 Channel 中各個的 ChannelHandler 如何相互交互。
下圖引用 Netty 的 Javadoc 4.1 中 ChannelPipeline 的說明,描述了 ChannelPipeline 中 ChannelHandler 通常如何處理 I/O 事件。
I/O 事件由 ChannelInboundHandler 或 ChannelOutboundHandler 處理,並通過調用 ChannelHandlerContext 中定義的事件傳播方法。
例如:ChannelHandlerContext.fireChannelRead(Object)和 ChannelOutboundInvoker.write(Object)轉發到其最近的處理程序。
入站事件由自下而上方向的入站處理程序處理,如圖左側所示。入站 Handler 處理程序通常處理由圖底部的 I/O 線程生成的入站數據。
通常通過實際輸入操作(例如 SocketChannel.read(ByteBuffer))從遠程讀取入站數據。
出站事件由上下方向處理,如圖右側所示。出站 Handler 處理程序通常會生成或轉換出站傳輸,例如 write 請求。
I/O 線程通常執行實際的輸出操作,例如 SocketChannel.write(ByteBuffer)。
在 Netty 中每個 Channel 都有且僅有一個 ChannelPipeline 與之對應,它們的組成關係如下:
一個 Channel 包含了一個 ChannelPipeline,而 ChannelPipeline 中又維護了一個由 ChannelHandlerContext 組成的雙向鏈表,並且每個 ChannelHandlerContext 中又關聯著一個 ChannelHandler。
入站事件和出站事件在一個雙向鏈表中,入站事件會從鏈表 head 往後傳遞到最後一個入站的 handler,出站事件會從鏈表 tail 往前傳遞到最前一個出站的 handler,兩種類型的 handler 互不干擾。
摘自:http://www.52im.net/thread-2043-1-1.html
閱讀更多 物聯網開發者之家 的文章