《Netty權威指南》(二)NIO 入門

[TOC]java

 

2.1 同步阻塞 I/O

採用 BIO 通訊模型的服務器,一般由一個獨立的 Acceptor 線程負責監聽客戶端的鏈接,它接收到客戶端鏈接請求以後爲每一個客戶端建立一個新的線程進行處理,處理完成後,經過輸出流返回應答給客戶端,線程銷燬。編程

graph TD A1[Socket] -->|讀/寫| B(Acceptor 線程) A2[Socket] -->|讀/寫| B A3[Socket] -->|讀/寫| B B -->|建立| C1[Thread] B -->|建立| C2[Thread] B -->|建立| C3[Thread]

 

2.2 僞異步 I/O

採用 線程池任務隊列 能夠實現一種叫作 僞異步 I/O 通訊框架。 當有新的客戶端接入時,將客戶端的 Socket 封裝成一個 Task 投遞到後端的線程池中進行處理,JDK 的線程池維護着一個消息隊列和 N 個活躍線程,對消息隊列中的任務進行處理。因爲線程池能夠設置消息隊列的大小和最大線程數,所以它的資源佔用時可控的,不管多少個客戶端併發訪問,都不會致使資源的耗盡和宕機。後端

graph TD A1[Socket] -->|讀/寫| B(Acceptor 線程) A2[Socket] -->|讀/寫| B A3[Socket] -->|讀/寫| B B --> |提交 Task|P[Thread Pool] B --> |提交 Task|P B --> |提交 Task|P

 

2.3 NIO

NIO 官方稱爲 New I/O,目標是要讓 Java 支持非阻塞 I/O,因此一般也叫非阻塞 I/O(Non-blocking I/O)。api

阻塞模式使用很是簡單,可是性能和可靠性都很差,非阻塞模式則正好相反。通常來講,低負載、低併發的應用程序能夠選擇同步阻塞 I/O 以下降編程複雜度;對於高負載、高併發的網絡應用,須要使用 NIO 的非阻塞模式進行開發。安全

graph TD A1[Socket] -->|讀/寫| B(Selector) A2[Socket] -->|讀/寫| B A3[Socket] -->|讀/寫| B B --> P[Thread]

2.3.1 Buffer、Channel、Selector

1. 緩衝區 Buffer

Buffer 是一個對象,它包含一些要寫入或者要讀出的數據。在 NIO 庫中,全部數據都是用緩衝區處理的。在讀取數據時,它是直接從緩衝區讀取;在寫入數據時,寫入到緩衝區。服務器

2. 通道 Channel

網絡數據經過 Channel 讀取和寫入。通道與流的不一樣之處在於通道是雙向的,流只是在一個方向移動,而通道可用於讀、寫或者兩者同時進行。網絡

由於 Channel 是全雙工的,因此它能夠比流更好地映射底層操做系統的 API。併發

3. 多路複用器 Selector

多路複用器提供選擇已經就緒的任務的能力。Selector 會不斷地輪詢註冊在其上的 Channel,若是某個 Channel 上面發生讀或者寫事件,這個 Channel 就處於就緒狀態,會被 Selector 輪詢出來,而後經過 SelectionKey 能夠獲取就緒 Channel 的集合,進行後續的 I/O 操做。app

2.3.2 NIO 服務端序列圖

(1)打開 ServerSocketChannel框架

(2)綁定監聽地址 InetSocketAddress

(3)建立 Selector,啓動線程

(4)將 ServerSocketChannel 註冊到 Selector,監聽 ACCEPT

(5)Selector 輪詢註冊的 Key

(6)handleAccept() 處理新的客戶端接入

(7)設置新建客戶端鏈接的 Socket 參數

(8)向 Selector 註冊監聽讀操做 SelectionKey.OP_READ

(9)handleRead() 異步請求消息到 ByteBuffer,收到請求

(10)decode 請求消息

(11)異步寫 ByteBuffer 到 SocketChannel,發送響應

2.3.1 NIO 客戶端序列圖

(1)打開 SocketChannel

(2)設置 SocketChannel 爲非阻塞模式,同時設置 TCP 參數

(3)異步鏈接服務端

(4)判斷鏈接結果,若是鏈接成功,調到步驟10,不然執行步驟5

(5)向 Reactor 線程的多路複用器註冊 OP_CONNECT 事件

(6)建立 Selector,啓動線程

(7)Selector 輪詢就緒的 Key

(8)handleConnect()

(9)判斷鏈接是否完成,完成執行步驟10

(10)向多路複用器註冊讀事件 OP_READ

(11)encode 請求消息

(12)異步寫 ByteBuffer 到 SocketChannel,發送請求

(13)handleRead() 異步從 SocketChannel 讀 ByteBuffer,收到響應

 

2.4 AIO

NIO 2.0 引入了新的異步通道的概念,並提供了異步文件通道和異步套接字通道的實現。異步通道提供如下兩種方式獲取操做結果。

  1. 經過 java.util.concurrent.Future 類表示異步操做的結果;
  2. 在執行異步操做的時候傳入一個 java.nio.channels。

CompletionHandler 接口的實現類做爲操做完成的回調。

NIO 2.0 的異步套接字通道是真正的異步非阻塞 I/O,對應於 UNIX 網絡編程中的事件驅動 I/O(AIO)。它不須要經過多路複用器(Selector)對註冊的通道進行輪詢操做便可實現異步讀寫,從而簡化了 NIO 的編程模型。

 

2.5 4 種 I/O 的對比

同步阻塞I/O 僞異步I/O 非阻塞I/O(NIO) 異步I/O(AIO)
客戶端個數:I/O線程 1:1 M:N M:1 M:0
I/O(阻塞)類型 阻塞 阻塞 非阻塞 非阻塞
I/O(同步)類型 同步 同步 同步(I/O多路複用) 異步
API使用難度 簡單 簡單 複雜 通常
調試難度 簡單 簡單 複雜 複雜
可靠性 很是差 很是差
吞吐量

 

2.6 選擇 Netty 的理由

什麼是 Netty

Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients.

Netty 是一款異步的事件驅動的網絡應用程序框架,支持快速地開發可維護的高性能的面向協議的服務器和客戶端。

Netty 的優勢

  • 功能強大
  • 使用簡單
  • 性能高
  • 安全
  • 社區活躍
相關文章
相關標籤/搜索