【Netty】IO 模型简介 ( Netty 特点 | Netty 应用场景 | Java 三种 IO 模型 | BIO 模型 )
文章目錄
- I . Netty 簡介
- II . Netty 應用場景
- III . Java I/O 模型
- IV . BIO 概念
- V . BIO 開發流程
- VI . BIO 實例
- VII . BIO 模型實例分析
I . Netty 簡介
1 . Netty 是網絡開發框架 , 其有如下特點 ;
① 異步 : 與同步相對 , 操作之間 不產生阻塞 , 發出請求后可以不等待回應 , 繼續執行后面的代碼邏輯 ;
② 事件驅動 : 任何操作 , 都需要一個觸發事件 , 如按鈕點擊 , 回調操作等 ;
2 . Netty 作用 :
① 用途 : 開發 高并發 的 網絡 IO 程序 , 其性能 與 可靠性都很高 ;
② 服務器程序 : Netty 網絡應用部署在服務器中 , 主要是與客戶端進行高并發交互 ;
③ 點對點 ( P2P ) 程序 : 點對點數據傳輸 ;
3 . Netty 層次 : Netty 最底層是基于 TCP/IP 協議 , 然后封裝了原生的網絡編程及并發編程 , 在之上使用了 NIO 進行進一步封裝 , 最上層才是 Netty 提供的服務 ;
① 底層協議 : TCP 協議 ;
② 原生 API 封裝 : 該框架對原生的網絡編程及并發操作進行了封裝和優化 ;
③ 本質 : Netty 的本質是在 Java NIO 基礎上封裝的框架 , 適合開發網絡服務器 , 如游戲服務器等 ;
II . Netty 應用場景
1 . 遠程過程調用 ( RPC ) 框架 : 分布式系統中的遠程過程調用框架 , 看重 Netty 的 高并發 , 高性能 的能力 , 將其作為分布式遠程調用的網絡通信組件 ; 這些框架的底層都是使用 Netty 實現的 ;
2 . 游戲服務器 : 手游 / 大型網游 等后臺服務器基本都是基于 Netty 開發 , Netty 作為服務器 高性能 高并發 的通信模塊 , 提供了 TCP / UDP / HTTP 協議通信底層功能 , 在這個基礎上開發交互的業務邏輯 ;
III . Java I/O 模型
1 . Java IO 模型 : 收發數據的通道模式 , 工作模式 是 同步 還是 異步 , 等待機制是 阻塞 還是 非阻塞 ;
① IO 模型分類 : 根據上述特點可將 Java 中的網絡 IO 模型分為 BIO , NIO , AIO , 333 類 ;
② 三種模型性能對比 : 三種模型性能依次從低到高排列為 BIO <<< NIO <<< AIO ;
2 . BIO 模型 : 同步阻塞模型 , 在服務器端 , 針對每個客戶端的連接請求 , 都要啟動一個線程處理相關的業務邏輯 ;
① 適用場景 : 連接數 少 ;
② 最小 JDK 支持版本 : 1.4 ;
③ 弊端 : 對服務器資源占用高 , 如果客戶端只是連接 , 不做任何操作 , 那么也占用了服務器的資源 ;
④ 優點 : 程序簡單 , 容易理解 ;
⑤ 瓶頸 : 傳統的 BIO 處理大并發數據量時 , 有瓶頸 ;
⑥ BIO 模型中 客戶端 與 服務器端 交互 圖示 : 服務器端的線程數 與 客戶端一樣 ;
上圖中 , 如果有 1 萬個客戶端 , 那么對應的服務器端就會有 1 萬個線程 ;
3 . NIO 模型 : 同步非阻塞模型 , 在服務器端 , 一個線程處理多個客戶端連接 , 客戶端連接服務器時 , 會在多路復用器上注冊 , 多路復用器會一直輪訓是否有連接請求 , 如果有就處理 , 如果沒有不做任何操作 ;
① 適用場景 : 連接數 多 , 都是短連接 ; 如 : 聊天室 , 游戲服務器 等 ;
② 最小 JDK 支持版本 : 1.4 ;
③ 多路復用器 Selector : 可以理解成一個選擇器 ;
④ NIO 實現基礎 : 客戶端與服務器端不是時刻都在進行數據交互 , 而是間歇性的 , 大部分時間都是出于靜默 ( 非活動 ) 狀態 ;
⑤ NIO 模型中 客戶端 與 服務器端 交互 圖示 : 服務器端啟動一個線程 , 線程中維護 Selector 選擇器 , 該選擇器會維護多個通道 , 當某個通道有事件發生 , 即客戶端有請求進來 , 那么處理該事件 ;
4 . AIO 模型 : 異步非阻塞模型 , 引入異步通道概念 , 并調用操作系統參與并發任務 ;
① 適用場景 : 連接 的個數多 , 并且都是 長連接 ;
② 最小 JDK 支持版本 : 1.7 ;
③ 工作流程 : 先判定客戶端請求的有效性 , 有效請求才啟動線程 ;
④ 當前狀態 : NIO 的進階版 , 該技術是 JDK 1.7 引入 , 目前應用不是很廣 ; Netty 是基于 NIO 模型的 ;
IV . BIO 概念
BIO 簡介 : Blocking IO , 阻塞 IO , 傳統 Java IO 編程 ;
① 特點 : 同步阻塞 ;
② 連接 對應 線程 : 服務器端 每維護 一個連接 , 都要啟動一個相應的線程 ; 這樣就會造成性能浪費 ;
③ BIO 改進方案 : 使用線程池機制改進 BIO , 每個線程可以處理客戶端連接 ;
④ NIO 基礎 : BIO 是 NIO 的基礎 ;
V . BIO 開發流程
1 . 連接流程 : 以 TCP 連接為例 ;
① 服務器端 監聽 : 服務器端創建 ServerSocket , 監聽接口 ;
② 客戶端 連接 : 創建 Socket , 向服務器端申請連接 ;
③ 服務器端 線程 : 接受客戶端連接 , 創建一個線程 , 專門與該客戶端進行通信 ;
2 . 交互過程 :
① 客戶端請求 : 客戶端通過建立的連接 , 向服務器端發送請求 , 服務器端如果有線程響應該請求 , 那么處理該請求 , 如果沒有線程響應 , 那么等待 , 之后進行超時處理 ;
② 服務器端響應 : 服務器端響應了客戶端請求 , 客戶端在請求返回后 , 繼續執行后面的代碼邏輯 ;
VI . BIO 實例
1 . BIO 示例 :
① 服務器端 : 編寫服務器端 , 監聽 8888 端口 , 阻塞等待客戶端連接 , 連接成功后 , 創建線程 , 線程中阻塞等待客戶端發送請求數據 ;
② 客戶端 : 編寫一個客戶端 , 請求服務器的 8888 端口號 , 客戶端發送 “Hello World” 字符串給服務器端 ;
③ Telnet 客戶端 : 使用 Telnet 客戶端向上述服務器端 8888 端口 發送 “Hello World” 字符串請求 ;
2 . 服務器代碼示例 :
package kim.hsl.bio;import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;public class TCPServer {public static void main(String[] args) {try {//創建線程池ExecutorService threadPool = Executors.newCachedThreadPool();//創建服務器套接字ServerSocket serverSocket = new ServerSocket(8888);System.out.println("服務器啟動,監聽 8888 端口");while (true){//阻塞, 等待客戶端連接請求 ( 此處是第一個阻塞點 )Socket socket = serverSocket.accept();System.out.println("客戶端連接成功");//線程池啟動線程threadPool.execute(new ClientRquest(socket));}} catch (IOException e) {e.printStackTrace();}}/*** 與客戶端交互類*/static class ClientRquest implements Runnable {private Socket socket;public ClientRquest(Socket socket) {this.socket = socket;}@Overridepublic void run() {try {clientRequest();} catch (IOException e) {e.printStackTrace();} finally {//最終要將 Socket 關閉, 如果出異常繼續捕獲try {socket.close();} catch (IOException e) {e.printStackTrace();}}}public void clientRequest() throws IOException {//獲取輸入流, 讀取客戶端寫入的信息byte[] buffer = new byte[1024];InputStream is = socket.getInputStream();System.out.println("等到客戶端請求");//此處會阻塞等待客戶端的請求 ( 此處是第二個阻塞點 )int count = is.read(buffer);String request = new String(buffer, 0, count);System.out.println("客戶端請求到達 : " + request);}} }3 . 客戶端代碼示例 :
package kim.hsl.bio;import java.io.IOException; import java.net.Inet4Address; import java.net.InetSocketAddress; import java.net.Socket;public class TCPClient {public static void main(String[] args) {try {Socket socket = new Socket();InetSocketAddress inetSocketAddress =new InetSocketAddress(Inet4Address.getLocalHost(), //本機IP地址8888 //端口號);System.out.println("客戶端開始連接 ...");//此處會阻塞等待連接成功socket.connect(inetSocketAddress);System.out.println("客戶端連接成功");//連接成功后, 開始執行后續操作socket.getOutputStream().write("Hello World".getBytes());System.out.println("客戶端寫出 Hello World 成功");} catch (IOException e) {e.printStackTrace();}} }4 . 執行結果 :
① 啟動服務器 :
② 啟動客戶端 :
③ 使用 Telnet 客戶端測試 localhost 8888 端口 :
-
建立連接 : 在命令行工具中 , 使用 telnet localhost 8888 連接本機的 8888 端口 ;
-
連接成功后 , 按下 Ctrl + ] 快捷鍵 , 進入 Telnet 命令行 , 輸入 send Hello World 命令 , 向本機的 8888 端口發送 Hello World 字符串 ;
-
服務器端顯示 :
VII . BIO 模型實例分析
BIO 模型實例分析 : 針對上述 BIO 實例 , 從性能 , 線程個數 , 阻塞 等角度分析 BIO 模型 ;
① 線程維護個數 : 在服務器端 , 需要針對每個客戶端連接都創建一個線程 , 有多少連接 , 就需要有多少線程 ;
② 性能分析 : 如果客戶端數量很多 , 那么大量客戶端同時連接 , 其并發數量很大 , 對系統的資源占用較高 ;
③ 阻塞分析 : BIO 模型中 , 服務器端有兩處阻塞 , 一個是等待客戶端連接 , 一個是連接后 , 等待客戶端發出請求數據 , 后者的阻塞等待完全就是對資源的浪費 , 沒有數據交互 , 一直占用資源 ;
總結
以上是生活随笔為你收集整理的【Netty】IO 模型简介 ( Netty 特点 | Netty 应用场景 | Java 三种 IO 模型 | BIO 模型 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【计算理论】下推自动机 PDA ( 设计
- 下一篇: 【Netty】NIO 简介 ( NIO