W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
在學習Netty的異步和數(shù)據(jù)驅動之前,我們先來簡單的了解一下Netty
Netty 是一個利用 Java 的高級網(wǎng)絡的能力,隱藏了Java背后的復雜性然后提供了一個易于使用的 API 的客戶端/服務器框架。Netty 的高性能和可擴展性,可以作為你自己的獨特的應用,讓你更用心的花時間在你有興趣的東西上。
Netty處理一些高并發(fā)的網(wǎng)絡問題的時候會體現(xiàn)出怎樣的價值呢?想知道的話,答案就在本章中。本章除了解釋上述問題,還將為大家講解Netty的基本概念以及Netty的工具包的構成成分。在網(wǎng)絡發(fā)展初期,需要花很多時間來學習 socket 的復雜,尋址等等,在 C socket 庫上進行編碼,并需要在不同的操作系統(tǒng)上做不同的處理。
Java 早期版本(1995-2002)介紹了足夠的面向對象的糖衣來隱藏一些復雜性,但實現(xiàn)復雜的客戶端-服務器協(xié)議仍然需要大量的樣板代碼(和進行大量的監(jiān)視才能確保他們是對的)。
這些早期的 Java API(java.net)只能通過原生的 socket 庫來支持所謂的“blocking(阻塞)”的功能。一個簡單的例子
Listing 1.1 Blocking I/O Example
ServerSocket serverSocket = new ServerSocket(portNumber);//1
Socket clientSocket = serverSocket.accept(); //2
BufferedReader in = new BufferedReader( //3
new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out =
new PrintWriter(clientSocket.getOutputStream(), true);
String request, response;
while ((request = in.readLine()) != null) { //4
if ("Done".equals(request)) { //5
break;
}
}
response = processRequest(request); //6
out.println(response); //7
} //8
1.ServerSocket 創(chuàng)建并監(jiān)聽端口的連接請求
2.accept() 調(diào)用阻塞,直到一個連接被建立了。返回一個新的 Socket 用來處理 客戶端和服務端的交互
3.流被創(chuàng)建用于處理 socket 的輸入和輸出數(shù)據(jù)。BufferedReader 讀取從字符輸入流里面的文本。PrintWriter 打印格式化展示的對象讀到本文輸出流
4.處理循環(huán)開始 readLine() 阻塞,讀取字符串直到最后是換行或者輸入終止。
5.如果客戶端發(fā)送的是“Done”處理循環(huán)退出
6.執(zhí)行方法處理請求,返回服務器的響應
7.響應發(fā)回客戶端
8.處理循環(huán)繼續(xù)
顯然,這段代碼限制每次只能處理一個連接。為了實現(xiàn)多個并行的客戶端我們需要分配一個新的 Thread 給每個新的客戶端 Socket(當然需要更多的代碼)。但考慮使用這種方法來支持大量的同步,長連接。在任何時間點多線程可能處于休眠狀態(tài),等待輸入或輸出數(shù)據(jù)。這很容易使得資源的大量浪費,對性能產(chǎn)生負面影響。當然,有一種替代方案。
除了示例中所示阻塞調(diào)用,原生 socket 庫同時也包含了非阻塞 I/O 的功能。這使我們能夠確定任何一個 socket 中是否有數(shù)據(jù)準備讀或寫。我們還可以設置標志,因為讀/寫調(diào)用如果沒有數(shù)據(jù)立即返回;就是說,如果一個阻塞被調(diào)用后就會一直阻塞,直到處理完成。通過這種方法,會帶來更大的代碼的復雜性成本,其實我們可以獲得更多的控制權來如何利用網(wǎng)絡資源。
在 2002 年,Java 1.4 引入了非阻塞 API 在 java.nio 包(NIO)。
"New"還是"Nonblocking"?
NIO 最初是為 New Input/Output 的縮寫。然而,Java 的 API 已經(jīng)存在足夠長的時間,它不再是新的?,F(xiàn)在普遍使用的縮寫來表示Nonblocking I/O (非阻塞 I/O)。另一方面,一般(包括作者)指阻塞 I/O 為 OIO 或 Old Input/Output。你也可能會遇到普通 I/O。
我們已經(jīng)展示了在 Java 的 I/O 阻塞一例例子。圖 1.1 展示了方法 必須擴大到處理多個連接:給每個連接創(chuàng)建一個線程,有些連接是空閑的!顯然,這種方法的可擴展性將是受限于可以在 JVM 中創(chuàng)建的線程數(shù)。
Figure 1.1 Blocking I/O
當你的應用中連接數(shù)比較少,這個方案還是可以接受。當并發(fā)連接超過10000 時,context-switching(上下文切換)開銷將是明顯的。此外,每個線程都有一個默認的堆棧內(nèi)存分配了 128K 和 1M 之間的空間。考慮到整體的內(nèi)存和操作系統(tǒng)需要處理 100000 個或更多的并發(fā)連接資源,這似乎是一個不理想的解決方案。
相比之下,圖1.2 顯示了使用非阻塞I/O,主要是消除了這些方法 約束。在這里,我們介紹了“Selector”,這是 Java 的無阻塞 I/O 實現(xiàn)的關鍵。
Figure 1.2 Nonblocking I/O
Selector 最終決定哪一組注冊的 socket 準備執(zhí)行 I/O。正如我們之前所解釋的那樣,這 I/O 操作設置為非阻塞模式。通過通知,一個線程可以同時處理多個并發(fā)連接。(一個 Selector 由一個線程通常處理,但具體實施可以使用多個線程。)因此,每次讀或寫操作執(zhí)行能立即檢查完成??傮w而言,該模型提供了比 阻塞 I/O 模型 更好的資源使用,因為
如果你要直接使用這些 Java API 構建的 NIO 建立你的應用程序,只是這樣做正確和安全是無法保證的。實現(xiàn)可靠和可擴展的 event-processing(事件處理器)來處理和調(diào)度數(shù)據(jù)并保證盡可能有效地,這是一個繁瑣和容易出錯的任務,最好留給專家 - Netty。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: