Netty完勝Java I/O與NIO?

前言

在面對很多當前的互聯網應用程序時,其核心底層功能大多需要高性能網絡編程來支撐,而對於Java來說是幸運的,因爲在這個領域已經有了一個正在不斷健壯的框架,他就是Netty(一款異步的事件驅動的網絡應用程序框架,支持快速地開發可維護的高性能的面向協議的服務器和客戶端)。

那麼這個框架入手容易嗎?

其實是有一定難度的,即使是一些例子(具備高性能的系統),想要了解並熟知,不僅需要一流的編程技巧,還需要幾個複雜領域(網絡編程、多線程處理和併發)的專業知識。

但是Netty確實提供了極爲豐富的網絡編程工具集,值得我們花大量時間來消化它。

其終究是框架

Netty的架構方法和設計原則是:每個小點都和它的技術性內容一樣重要,無比精妙。我們可以更關注以下幾點:

關注點分離——業務和網絡邏輯解耦
模塊化和可複用性
可測試性作爲首要的要求

瞭解Java I/O與NIO

代碼示例 阻塞I/O
ServerSocket serversocket = new ServerSocket(portNumber);
Socket clientSocket = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
String request, response;
while((request = in.readLine()) != null){
    if("Done".equals(request)){
        break;
    }
    response = processRequest(request);
    out.println(response);
}

恰如以上代碼就實現了Socket API的基本模式之一。或許你應該注意到以下幾點:

  • ServerSocket上的accept()方法將會一直阻塞到一個連接建立,隨後返回一個新的Socket用於客戶端和服務器之間的通信。該ServerSocket將繼續監聽傳入的連接。
  • BufferedReader和PrintWriter都衍生自Socket的輸入輸出流,前者從一個字符輸入流中讀取文本,後者打印對象的格式化的表示到文本輸出流。
  • readLine()方法將會阻塞,直到有一個換行符或者回車符結尾的字符串被讀取到。
  • processRequest()方法即服務端對客戶端的請求進行處理。
這段代碼是否存在弊端?
  • 其只能同時處理一個連接,要管理多個併發客戶端,需要爲每個新的客戶端Socket創建一個新的Thread。(如下圖所示)

圖片描述

那麼你或許可以考慮到以下幾點影響?
  • 1、在任何時候都可能有大量的線程處於休眠狀態,只是等待輸入或者輸出數據就緒,這可能算是一種資源浪費。
  • 2、爲每個線程的調用棧分配內存,根據操作系統默認值區間一般爲64KB到1MB。
  • 3、即使Java虛擬機(JVM)在物理上可以支持非常大數量的線程,但是遠在到達該極限之前,上下文切換所帶來的開銷就已經非常麻煩了。
結論是?

雖然以上對於支撐中小數量的客戶端來說還算可以接受,但是在面對100 000或更多併發連接資源使用它是很不理想的。

很幸運,你還可以使用NIO這種方式!(2002年Java引入對於非阻塞I/O的支持)
  • 使用setsocket()方法配置套接字,以便讀/寫調用在沒有數據的時候立即返回
  • 使用操作系統的事件通知API註冊一組非阻塞套接字,以確定它們中是否有任何的套接字已經有數據可供讀寫。
  • 以上兩點就字面理解可能比較困難,那麼你可以抽象記憶以下的觀點與流程圖!
使用Selector的非阻塞I/O

圖片描述

  • 上圖是一種非阻塞設計,Java.nio.channels.Selector是Java的非阻塞I/O實現的關鍵。
  • 它使用了事件通知API以確定在一組非阻塞套接字中有哪些已經就緒能夠進行I/O相關的操作。
  • 一個單一的線程便可以處理多個併發的連接。
相比之下,與阻塞I/O相比,它能更好的利用資源
  • 使用較少的線程便可以處理許多連接,減少了內存管理和上下文切換帶來的開銷
  • 當沒有I/O操作需要處理的時候,線程也可以被用於其他任務。

Netty的出場!!!

儘管你可以直接使用這些API進行直接構建應用程序(在高負載下可靠和高效的處理和調度I/O操作),但是要做到完全正確與安全是很難處理,那麼這是我們將工作留給高性能的網絡編程專家Netty或許更合適。

相關項目 By GitHub

項目名:InChat
項目地址:https://github.com/UncleCatMy...
項目介紹:基於Netty4與SpringBoot,聊天室WebSocket(文字圖片)加API調用Netty長鏈接執行發送消息(在線數、用戶列表)、Iot物聯網-MQTT協議、TCP/IP協議單片機通信,異步存儲聊天數據


如果本文對你有所幫助,歡迎關注個人技術公衆號

圖片描述

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