《Netty權威指南》筆記


第1章 Java的I/O演進之路
1.1 Linux網絡I/O模型
fd:file descriptor,文件描述符。linux內核將所有外部設備都看作一個文件來操作,對文件的讀寫會調用內核提供的命令,返回一個文件描述符。對一個socket的讀寫也會有相應的socket fd。描述符就是一個指向內核中結構體的數字。
Unix I/O模型分為5類:
①阻塞IO模型
文件操作的默認模型。進程空間調用recvfrom函數,直到數據包到達且被復制到應用進程的緩沖區中或者發生錯誤時才返回,在此期間,進程會被阻塞一直等待。
②非阻塞IO模型
recvfrom函數當發現內核緩沖區沒有數據時,直接返回一個EWOULDBLOCK錯誤,一般通過輪詢檢查這個狀態,看是否有數據到來。
③IO復用模型
linux提供select/poll,進程通過將一個或多個fd傳遞給select或poll系統調用,阻塞在select操作上,這樣select/poll可以通過順序掃描多個fd幫我們偵測是否處於就緒狀態。但支持的fd數量有限。
linux還提供了epoll系統調用,基於事件驅動方式代替順序掃描,性能更高。當有fd就緒時,立即回掉函數rollback。
④信號驅動IO模型
首先開啟套接口信號驅動IO功能,並通過系統調用sigaction執行一個非阻塞信號處理函數。當數據准備就緒時,就為該進程生成一個SIGIO信號,通過信號回調通知應用程序調用recvfrom來讀取數據,並通知主循環函數處理數據。
⑤異步IO模型
告知內核啟動某個操作,並讓內核在整個操作完成后(包括將數據從內核復制到用戶自己的緩沖區)通知我們。
這種模型與信號驅動模型的主要區別是:信號驅動IO由內核通知我們何時可以開始一個IO操作;而異步IO模型由內核通知我們IO操作何時已經完成。
 
1.2 I/O多路復用技術
java NIO 的核心類庫多路復用器Selector就是基於epoll的多路復用技術實現。
當需要同時處理多個客戶端接入請求時,可以利用多線程或IO多路復用技術實現。
IO多路復用:通過把多個IO的阻塞復用到同一個select的阻塞上,從而使得系統在單線程的情況下也可以同時處理多個客戶端請求。
IO多路復用最大優勢:系統開銷小。即系統不需要創建新的額外進程或線程,也不需要維護這些這些進程和線程的運行,降低了系統的維護工作量,節省了系統資源。
IO多路復用主要應用場景:①服務器需要同時處理多個處於監聽或連接狀態的套接字。②服務器需要同時處理多種網絡協議的套接字。
 
支持IO多路復用的系統調用有select、pselect、poll、epoll。在linux網絡編程中,很長時間使用select,但最終選擇epoll。用來克服select/poll缺點的方法不只有epoll,epoll只是一種linux實現方案,在freeBSD下有kqueue。
 
epoll改進的select缺點如下:
①支持一個進程打開的socket描述符(FD)不受限制(僅受限於操作系統的最大文件句柄數)。
select最大缺陷是單個進程打開的FD是有限制的,默認值1024個,太多網絡效率會下降。而epoll在1G內存大概支持10萬個。
②IO效率不會隨着FD數目的增加而線性下降。
因為select/poll每次調用都會線性掃描全部的集合,導致效率呈現線性下降。而epoll只有活躍的socket才會主動調用callback函數,epoll實現了一個偽AIO。極端情況當全部socket都活躍時,epoll和select性能差不多。
③使用mmap加速內核與用戶空間的消息傳遞。
內核需要把FD消息通知給用戶空間,epoll通過內核和用戶空間mmap同一塊內存來避免不必要的內存復制。
④epoll的API更加簡單。
包括創建一個epoll描述符、添加監聽事件、阻塞等待所監聽的事件發生、關閉epoll描述符等。
 
1.3 Java的I/O演進
在JDK 1.4推出Java NIO之前,java都是使用同步阻塞模式(BIO),而這一時期C和C++語言的大型應用都直接使用操作系統提供的異步IO或AIO能力。
JDK 1.4新增了個java.nio包,提供了進行異步IO開發的API和類庫,主要類和接口如下:進行異步IO操作的緩沖區ByteBuffer、管道Pipe、各種異步或同步的通道Channel、實現非阻塞IO操作的多路復用器Selector等。但NIO 1.0版仍然存在不足,主要問題為:沒有統一的文件屬性、API能力比較弱、底層存儲系統的一些高級API無法使用、所有文件操作都是同步阻塞調用,不支持異步文件讀寫操作。
JDK1.7 對NIO做了升級,被稱為NIO 2.0版,主要改進三個方面如下:
①提供批量獲取文件屬性API。
②提供AIO功能,支持基於文件的異步IO操作和針對網絡套接字的異步操作。
③完善通道功能,包括對配置和多播數據報的支持等。
 
 
第2章 NIO入門
2.1 傳統的BIO編程
ServerSocket負責綁定IP地址,啟動監聽端口;Socket負責發起連接操作。經過三次握手,連接成功之后,Client和Server雙方通過輸入流和輸出流進行同步阻塞式通信。
同步阻塞IO服務端通信模型:稱做一個客戶端連接一個線程。通常由一個獨立的Acceptor線程負責監聽客戶端的連接,它接收到連接請求后為每個客戶端創建一個新的線程進行鏈路處理,處理完成之后,通過輸出流返回應答給客戶端,線程銷毀。
該模型最大問題:缺乏彈性伸縮能力,服務端線程數和客戶端訪問數呈1:1的正比關系,當線程數膨脹,性能急劇下降,導致宕機和僵死。
 
2.2 偽異步IO編程
是對傳統BIO一個連接一個線程的簡單優化,服務端通過一個線程池來處理多個客戶端的請求接入,形成客戶端個數M:線程池最大線程數N的比例關系,M可以遠遠大於N。由於底層依然使用同步阻塞IO,所以被稱為“偽異步”。
優點:資源占用是可控的,不會導致耗盡和宕機。
缺點:只是簡單優化,無法從根本上解決同步IO導致的通信線程阻塞問題。
 
2.3 NIO編程
官方叫法是New I/O。而被大多數人接受的更准確叫法是非阻塞IO(Non-block I/O)。
(1)NIO類庫簡介
①緩沖區Buffer
緩沖區實質是一個數組,提供對數據的結構化訪問以及維護讀寫位置等。所有數據都是用緩沖區處理,任何時候訪問NIO中的數據,都是通過緩沖區進行操作。常見緩沖區類有7個:ByteBuffer(最常用)、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer。而java bio是面向流操作的。
②通道Channel
Channel是一個全雙工的雙向通道,可以讀寫操作同時進行,能更好的映射底層操作系統的API,因為Unix底層操作系統通道都是全雙工的。而java bio 流是單向的,一個流必須是InputStream或OutputString的子類。
Channel可以分為兩大類:用於網絡多寫的SelectableChannel和用於文件操作的FileChannel。ServerSocketChannel和SocketChannel都是SelectableChannel的子類。
③多路復用器Selector
多路復用器提供選擇以及就緒的任務的能力。Selector會不斷地輪詢注冊在其上地Channel,如果某個Channel上面發生讀或寫事件,這個Channel就處於就緒狀態,會被Selector輪詢出來,然后通過SelectionKey可以獲取就緒Channel的集合,進行后續的IO操作。JDK使用epoll實現。
 
(2)NIO編程優缺點
缺點:NIO編程難度比BIO大很大,編碼復雜。
優點:①客戶端發起的連接操作都是異步的,通過在多路復用器注冊OP_CONNECT等待后續結果。
②SocketChannel的讀寫操作都是異步的。
③線程模型的優化,一個Selector線程可以同時處理成千上萬個客戶端連接。
 
2.4 AIO編程
JDK1.7(NIO 2.0)引入了新的異步通道的概念,並提供了異步文件通道和異步套接字通道的實現,是真正的異步IO(因此NIO2.0也稱作異步非阻塞IO,而NIO 1.0稱作非阻塞IO)。其中異步套接字通道是真正的異步非阻塞IO,對應於Unix網絡編程中的事件驅動IO(AIO)。它不需要通過多路復用器Selector對注冊的通道進行輪詢操作即可實現異步讀寫,從而簡化了NIO的編程模型。主要類有AsynchronousSocketChannel和CompletionHandler(異步操作回調通知接口)。
 
2.5 四種IO模型對比
 
 
第3章 TCP粘包和拆包
3.1 TCP粘包/拆包
TCP是個“流”協議,所謂流,就是沒有界限的一串數據。就像河里的流水,它們連成一片,其間並沒有分界線。
粘包:上層業務的多個小包被封裝成一個大的數據包發送。
拆包:上層業務的一個完整的包被拆分成多個數據包發送。
3.2 TCP粘包/拆包解決方案
主要有四種解決方案:
①消息定長。例如每個報文的大小為固定長度200字節,如果不夠,空位補空格。
②在包尾增加回車換行符進行分割。例如FTP協議。
③將消息分為消息頭和消息體,消息頭中包含表示消息總長度的字段。
④更復雜的應用層協議。
 
為了解決TCP粘包/拆包導致的半包讀寫問題,Netty默認提供了多種編解碼器用於處理半包。
 
第4章 編解碼技術
4.1 Java序列化缺點
java序列化缺點如下:
①無法跨語言
②序列化后的碼流太大
③序列化性能太低
 
4.2 業界主流編解碼框架
Protobuf:google開源,高效的編解碼性能,語言無關和平台無關,文本化的數據結構描述語言。
Thrift:facebook開源給apache,支持壓縮和可選優化等二進制編解碼。
 
 
第5章 HTTP協議
5.1 HTTP請求消息
http請求由三部分組成:
①HTTP請求行
請求行以一個方法夫開頭,以空格分開,后面跟着URI和協議版本,格式為:Method Request-URI HTTP-Version CRLF(回車和換行)。
②HTTP消息頭
③HTTP請求正文
 
5.2 HTTP響應消息
http響應由三部分組成:
①狀態行
狀態行格式:HTTP-Version Status-Code(狀態碼) Reason-Phrase CRLF。
②消息報頭
③響應正文
 
5.3 HTTP協議缺點
http協議缺點如下:
①HTTP協議為半雙工協議。
半雙工協議指數據可以在客戶端和服務器兩個方向傳輸,但是不能同時傳輸。即同一時刻,只有一個方向上的數據傳送。
②HTTP消息冗長而繁瑣。
采用文本方式傳輸,比二進制通信協議冗長繁瑣。
③開銷大,不適用於低延遲應用。
容易針對服務器長連接推送的黑客攻擊。例如長時間輪詢,消耗大量服務器帶寬。
 
 
第6章 WebSocket協議
6.1 WebSocket入門
WebSocket是HTML5開始提供的一種瀏覽器與服務器間進行全雙工通信的網路技術,瀏覽器和服務器只需要做一個握手動作,然后,瀏覽器和服務器之間就形成了一條快速通道,兩者就可以直接互相傳送數據了。
WebSocket特點如下:
①單一的TCP連接,基於TCP的全雙工模式通信。
②對代理、防火牆和路由器透明。
③無頭部信息、Cookie和身份驗證。
④無安全開銷。
⑤通過“ping/pong”幀保持鏈路激活。
⑥服務器可以主動傳遞消息給客戶端,不再需要客戶端輪詢。
 
 
第7章 私有協議棧開發
7.1 私有協議介紹
私有協議也稱非標准協議,就是未經國際和國家標准化組織采納和批准,由某個企業自己制定。
7.2 Netty協議棧開發
Netty私有協議棧開發主要有如下步驟:
①數據結構定義
②消息編解碼
③握手和安全認證
④心跳檢測機制
⑤斷連重連
⑥客戶端代碼
⑦服務端代碼
 
 
第8章 Reactor線程模型
8.1 Reactor單線程模型
是指所有的IO操作都在同一個NIO線程上完成,這個唯一NIO線程的職責如下:
①做為NIO服務器,接收客戶端的TCP連接。
②做為NIO客戶端,向服務器發起TCP連接。
③讀取通信對端的請求或者應答消息。
④向通信對端發送消息或者應答消息。
 
通過Acceptor類接收客戶端的TCP連接請求消息,當鏈路建立成功之后,通過Dispatch將對應的ByteBuffer派發到指定的Handler上,進行消息解碼,用戶線程消息編碼后通過NIO線程將消息發送給客戶端。
單線程模型只適用於小容量應用場景,對於高負載、大並發應用場景不適用,原因如下:
①一個NIO線程同時處理成百上千的鏈路,性能上無法支撐,無法滿足海量消息的編碼、解碼、讀取和發送。
②當NIO線程負載過重時,處理速度變慢,會導致大量客戶端連接超時,而超時重發會進一步加重負載。
③可靠性問題,一旦NIO線程崩潰或死循環,會導致整個系統通信模塊不可用。
 
8.2 Reactor多線程模型
用一組NIO線程來處理IO操作。多線程模型特點如下:
①有專門一個NIO線程Acceptor線程用於監聽服務端,接收客戶端的TCP連接請求。
②網路IO操作讀寫等由一個NIO線程池負責。
 
不足:單獨一個Acceptor線程可能會存在性能不足問題。
8.3 主從Reactor多線程模型
用一個Acceptor線程池來處理客戶端TCP連接請求,握手,安全認證等。一旦鏈路建立成功,就將鏈路注冊到后端Reactor線程池的IO線程上,由IO線程負責后續IO操作。
 
 
第9章 高性能之道
9.1 傳統RPC調用性能分析
傳統RPC調用性能差的三宗罪:
①網絡傳輸方式采用同步阻塞I/O。
②序列化性能差。
③線程模型問題。即1:1占用服務器線程資源。
 
9.2 IO通信性能三原則
從架構層面,影響IO通信性能主要有三個要素:傳輸方式、通信協議、線程模型。
 
9.3 Netty高性能之道
netty高性能之道如下:
①異步非阻塞通信。
②高效的Reactor線程模型。
③無鎖化的串行設計。
避免鎖競爭帶來的性能損耗。
④高效的並發編程。
⑤高性能的序列框架。
netty默認提供了對google Protobuf的支持。
⑥零拷貝。
netty的接收和發送byteBuffer采用Direct Buffer,使用堆外直接內存進行socket讀寫,不需要進行緩沖區二次拷貝。
⑦內存池。
netty提供了基於內存池的緩沖區重用機制,來進行對象的分配和回收。
⑧靈活的TCP參數配置能力。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM