Netty簡述
Netty是一個高性能的網絡編程框架。
上面提到了幾個關鍵的字眼,高性能,網絡編程,框架。這些概括Netty的本質。
Netty是一個NIO客戶端服務器框架,可以快速輕松地開發協議服務器和客戶端等網絡應用程序。它極大地簡化並簡化了TCP和UDP套接字服務器等網絡編程。
“快速簡便”並不意味着最終的應用程序會受到可維護性或性能問題的影響。Netty經過精心設計,具有豐富的協議,如FTP,SMTP,HTTP以及各種二進制和基於文本的傳統協議。因此,Netty成功地找到了一種在不妥協的情況下實現易於開發,性能,穩定性和靈活性的方法。
先來簡單看一下Netty官網的架構圖:

從圖中可以看出,Netty的架構分為三塊,核心(Core),通信服務(Transport Services)還有各種協議(Protocol Support)。我們想象將來要學習的內容都和這些有關系。通過架構圖對其有個基本印象。
Linux I/O 模型
在Linux中,將I/O模型分為五種類型:
阻塞式 I/O 模型
非阻塞式 I/O 模型
I/O 復用
信號驅動式 I/O
異步 I/O
Linux中的I/O流程概括來說可以分為兩步:
1、等待數據准備好(Waiting for the data to be ready)
2、從內核向進程復制數據(Copying the data from the kernel to the process)
來看下面的圖片:

從上面的流程可以看出,首先是內核空間把數據從硬件(磁盤)中讀到內核空間的緩沖區中,進行這一步操作時,數據處於內核態,通過磁盤驅動器,把數據從磁盤讀到內核緩沖區來。下一步是把數據從內核緩沖區拷貝到用戶空間的緩沖區,數據由內核態變為用戶態。
知識普及:Linux中的程序大致運行在兩個空間,自己的程序運行在用戶空間,用戶空間的權限有限,相對的另外一個空間是內核空間,比如驅動程序或者一些核心的系統調用都是在內核空間完成的。我們的I/O操作當在一個用戶空間做系統調用的時候,數據會自動從用戶態變到內核態來進行操作,完成了以后再從內核空間拷貝到用戶空間。這種狀態的切換是為了保證安全。比如在我們32位的操作系統中,大部分是4G的內存,一般前面一個G主要是內核態使用,后面三個G是用戶態使用。
阻塞式 I/O 模型

阻塞式I/O是我們最常見的一種IO,當我們發起一個IO請求之后,開始進行系統調用,數據變為內核態,這兩個階段是一直處於阻塞的。數據開始從磁盤拷貝到內核空間,處理完后再從內核空間拷貝到應用空間,數據變為用戶態。這整個的過程涉及到的所有程序線程都是在等待狀態。比如我們Java普通的Socket編程,就是這樣一個流程。整個過程中數據沒有完成前,接收方都是出於等待狀態,這就是阻塞式IO模型。明顯可見效率不會高。
非阻塞式 I/O 模型

這種方式的特點是調用的時候不會等待(也就是不會阻塞),系統如果沒有數據,就會立刻告訴你現在沒數據,會立刻返回,然后由調用方自己去問現在有沒有,如果沒有就下次再問有沒有,相當於不斷去輪詢結果,直到某個時刻被告知有結果了,這個時候數據已經從磁盤拷貝到內核空間了,數據也處於內核態,就差最后從內核態拷貝到用戶空間,但是,從內核空間拷貝到用戶空間,讓數據從內核態變為用戶態,這個過程在非阻塞式 I/O 模型中,也是阻塞的!所以效率也不會太高。
I/O 復用模型

復用的意思是,系統一次去查看多個io的進度,看哪一個有了結果,對於有結果的,就開始執行下面從內核空間拷貝到用戶空間的操作,這個模型和上面非阻塞式 I/O 模型的區別是,非阻塞式 I/O 模型一次只看一個結果好了沒有,而IO復用模型一次可以查看多個,一次監控一批系統調用好了沒有,這是復用模型的特點。在一定程度上,能提高一些效率。
信號驅動式 I/O 模型

在Linux系統中,有一種信號機制,也就是說調用方可以注冊一個信號,當系統調用完成之后,可以通知這個信號,那注冊信號的人就會知道這個請求已經完成了,這種信號機制應用在IO當中就是信號驅動式IO。這樣就不是查看結果是否好了,而是被通知的一種方式。不過通知后,從內核態到用戶態這個過程還是阻塞的。純異步的模型就是下面要說的這個。
異步 I/O模型

這種模型是真正的純異步的IO模型,當開始系統調用,數據從磁盤讀到內核空間,並且從內核態已經拷貝到了用戶態之后,整個流程已經完成了,然后在進行回調,通知調用方。主要的區別在於不是在內核空間中完成了就通知,而是由內核空間到了用戶空間后再通知,沒有任何阻塞的過程,是一種更加徹底的異步IO。
各種I/O模型之間的比較

阻塞式IO就是發起調用之后,就一直阻塞,在等着,直到整個IO完成。在這個過程當中,進程是不能干任何事情的。都在等待。
非阻塞式IO就是,進程會主動去問好了沒,好了沒,好了沒。。。直到得到回復好了,然后發起讀請求,把數據從內核空間拷貝到用戶空間。這個過程是阻塞的。
IO復用模型,就是每次都查看多個結果好了沒,如果發現n個當中有一兩個有了結果,就返回,有結果的這些開始拷貝。
信號驅動式IO模型,就是等數據拷貝到內核空間再通知,前面這段時間可以做別的事情,等內核空間准備好了,通知,再把數據從內核空間拷貝到用戶空間。
異步IO模型,就是發起調用后就徹底不管了,等數據好了后從內核空間拷貝到用戶空間了,再進行通知,整個過程沒有阻塞的步驟。
從比較重來看,異步IO從理論上來看是最好的,不存在任何阻塞的時間,系統資源理論上可以得到充分利用。
同步VS異步
lPOSIX標准將同步I/O和異步I/O定義為:
同步I/O操作:導致請求進程阻塞,直到I/O操作完成。
異步I/O操作:不導致請求進程阻塞。
從定義上看,只有最后的異步IO模型是真正的異步,前面四種都達不到真正的異步。但是目前來看,純異步的IO一直都不太成熟,比較混亂,沒有一個標准的解決方案。用的最多的還是IO復用模型,這個是目前為止比較成熟的一個模型。
在Java中,我們用的最多的Socket網絡編程,就是阻塞式IO模型,后來的NIO就是IO復用模型,在Java中不支持信號驅動模型。Java的NIO2.0,也叫AIO,提供了純異步的IO模型,但是現在的異步IO模型還不是很成熟,所以用的最多的就是NIO,也就是IO復用模型。
推薦書籍《Unix網絡編程》,推薦理由:網絡編程的經典之作,經歷了十年左右,內容基本變化不大,原理性書籍,是網絡編程的必看之書。
本文由博客一文多發平台 OpenWrite 發布!
