Netty:核心功能Transport

網絡應用程序讓人與系統或系統與系統可以進行通信,如何做到這一點取決於具體的網絡傳輸,本質都是:字節通過線路。傳輸的概念幫助我們抽象掉的底層數據轉移的機制。所有人都知道的是,字節在被髮送和接收。

統一的Transport

存在的問題:Java 的公開的網絡 API 處理NIO和OIO兩種情況有很大的不同(編程使用的API不同)。
解決:Netty 在傳輸層的API是統一的,這比你用 JDK 將OIO修改爲NIO更簡單。你無需重構整個代碼庫,然後將時間花到其他更值得去做的事情上。

傳輸的API

Transport API 的核心是 Channel 接口,用於所有的出站操作,見下圖
在這裏插入圖片描述
如上圖所示,每個 Channel 都會分配一個 ChannelPipeline 和ChannelConfig。ChannelConfig 負責設置並存儲 Channel 的配置,並允許在運行期間更新它們。傳輸一般有特定的配置設置,可能實現了 ChannelConfig的子類型。ChannelPipeline 容納了使用的 ChannelHandler 實例,這些ChannelHandler 將處理通道傳遞的“入站”和“出站”數據以及事件。ChannelHandler 的實現允許你改變數據狀態和傳輸數據。

Intercepting Filter(攔截過濾器) ChannelPipeline 實現了常用的 Intercepting Filter(攔截過濾器)設計模式。
同時,可以在運行時根據需要添加 ChannelHandler 實例到ChannelPipeline 或從 ChannelPipeline 中刪除,這能幫助我們構建高度靈活的 Netty 程序。

Transport的幾種方式

在這裏插入圖片描述

1.NIO-Nonblocking I/O

NIO傳輸是目前最常用的方式,它通過使用選擇器提供了完全異步的方式操作所有的 I/O,NIO 從Java 1.4才被提供。

NIO 中,我們可以註冊一個通道或獲得某個通道的狀態,
通道狀態有下面幾種改變:

  1. 一個新的 Channel 被接受並已準備好
  2. Channel 連接完成
  3. Channel 中有數據並已準備好讀取
  4. Channel
    發送數據出去

選擇器所支持的操作在 SelectionKey 中定義,具體如下:
在這裏插入圖片描述

Channel通道與Selector選擇器的關係遷移圖
在這裏插入圖片描述

  1. 新信道註冊到選擇器
  2. 選擇處理的狀態變化的通知
  3. 以前註冊的通道
  4. Selector.select()方法阻塞,直到新的狀態變化接收或配置的超時 已過
  5. 檢查是否有狀態變化
  6. 處理所有的狀態變化
  7. 在選擇器操作的同一個線程執行其他任務

2.OIO-Old blocking I/O

它通過了 Netty 的通用 API 訪問但不是異步,而是構建在 java.net 的阻塞實現上。

在 java.net API,你通常有一個線程接受新的連接到達監聽在ServerSocket,並創建一個新的線程來處理新的 Socket 。這是必需的,因爲在一個特定的 socket的每個 I/O 操作可能會阻塞在任何時間。在一個線程處理多個 socket 易造成阻塞操作,一個 socket 佔用了所有的其他人。
你可能想知道Netty是如何用相同的API來支持NIO的異步傳輸。Netty利用了Socket中的SO_TIMEOUT標誌。這timeout指定最大毫秒數量用於等待I/O的操作完成。如果操作在指定的時間內失敗,SocketTimeoutException會被拋出, Netty中捕獲該異常並繼續處理循環。在接下來的事件循環運行,它再次嘗試。像Netty的異步架構來支持OIO的話,這其實是唯一的辦法。當SocketTimeoutException拋出時,執行 stack trace。
在這裏插入圖片描述

  1. 給 Socket分配線程
  2. Socket連接到遠程
  3. 讀操作(可能會阻塞)
  4. 讀完成
  5. 處理可讀的字節
  6. 執行提交到 socket 的其他任務
  7. 再次嘗試讀

3.Local 同個 JVM 內的本地 Transport 通信

Netty 提供了“本地”傳輸,爲運行在同一個 Java 虛擬機上的服務器和客戶之間提供異步通信。此傳輸支持所有的 Netty 常見的傳輸實現的 API。
在此傳輸中,與服務器 Channel 關聯的 SocketAddress 不是“綁定”到一個物理網絡地址中,而是在服務器運行時它被存儲在註冊表中,當 Channel 關閉時它會註銷。由於該傳輸不是“真正的”網絡通信,它不能與其他傳輸實現互操作。因此,客戶端是希望連接到使用本地傳輸的的服務器時,要注意正確的用法。除此限制之外,它的使用是與其他的傳輸是相同的。

4.Embedded 內嵌 Transport

Netty中 還提供了可以嵌入 ChannelHandler 實例到其他的 ChannelHandler 的傳輸,使用它們就像輔助類,增加了靈活性的方法,使您可以與你的 ChannelHandler 互動。

該嵌入技術通常用於測試 ChannelHandler 的實現,但它也可用於將功能添加到現有的 ChannelHandler 而無需更改代碼。嵌入傳輸的關鍵是Channel 的實現,稱爲“EmbeddedChannel”。

傳輸方式應用場景:

  1. OIO-在低連接數、需要低延遲時、阻塞時使用
  2. NIO-在高連接數時使用
  3. Local-在同一個JVM內通信時使用
  4. Embedded-測試ChannelHandler時使用
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章