IO NIO AIO及常用框架概述


概述

nio

同步: 自己親自出馬持銀行卡到銀行取錢(使用同步IO時,Java自己處理IO讀寫)。

異步: 委托一小弟拿銀行卡到銀行取錢,然后給你(使用異步IO時,Java將IO讀寫委托給OS處理,需要將數據緩沖區地址和大小傳給OS(銀行卡和密碼),OS需要支持異步IO操作API)。

阻塞: ATM排隊取款,你只能等待(使用阻塞IO時,Java調用會一直阻塞到讀寫完成才返回)。

非阻塞: 櫃台取款,取個號,然后坐在椅子上做其它事,等號廣播會通知你辦理,沒到號你就不能去,你可以不斷問大堂經理排到了沒有,大堂經理如果說還沒到你就不能去 (使用非阻塞IO時,如果不能讀寫Java調用會馬上返回,當IO事件分發器會通知可讀寫時再繼續進行讀寫,不斷循環直到讀寫完成)。

一、IO NIO AIO

io、nio、aio的區別,類似於resin、apache、nginx在io處理上的區別,從多線程互不干擾的阻塞式執行(resin),到輪詢式的同步非阻塞式(apache),再到異步非阻塞式(nginx)。

現在這三種io都在jdk中予以了支持。

IO (BIO)

同步並阻塞,服務器實現模式為一個連接一個線程,每個線程親自處理io並且一直等待io的完成,即客戶端有連接請求時服務器端就需要啟動一個線程進行處理,如果這個連接不做任何事情會造成不必要的線程開銷,當然可以通過線程池機制改善。

IO的局限:IO是面向流的,阻塞式的,串行的一個過程。對每一個客戶端的socket連接,IO都需要一個線程來處理,而且在此期間,這個線程一直被占用,直到socket關閉。在這期間,tcp的連接、數據的讀取、數據的返回都是被阻塞的。也就是說這期間大量的浪費了cpu的時間片和線程占用的內存資源。

每建立一個Socket連接時,同時創建一個新線程對該Socket進行單獨通信(采用阻塞的方式通信)。這種方式具有很高的響應速度,並且控制起來也很簡單,在連接數較少的時候非常有效,但是如果對每一個連接都產生一個線程的無疑是對系統資源的一種浪費,如果連接數較多將會出現資源不足的情況。

NIO (new IO) 從jdk1.4開始

同步非阻塞,服務器實現模式為一個請求一個線程,每個線程親自處理io,但有另外的線程輪詢檢查是否io准備完畢,不必等待io完成,即客戶端發送的連接請求都會注冊到多路復用器上,多路復用器輪詢到連接有I/O請求時才啟動一個線程進行處理。

**NIO則是面向緩沖區的,非阻塞式的,基於選擇器的,用一個線程來輪詢監控多個數據傳輸通道,哪個通道准備好了(即有了一組可以處理的數據),就處理哪個通道。 **

服務器端保存一個Socket連接列表,然后對這個列表進行輪詢,如果發現某個Socket端口上有數據可讀時(讀就緒),則調用該socket連接的相應讀操作;如果發現某個 Socket端口上有數據可寫時(寫就緒),則調用該socket連接的相應寫操作;如果某個端口的Socket連接已經中斷,則調用相應的析構方法關閉 該端口。這樣能充分利用服務器資源,效率得到了很大提高。

AIO (Asynchronous io、NIO.2) 從jdk1.7開始

異步非阻塞,服務器實現模式為一個有效請求一個線程,客戶端的I/O請求都是由OS先完成了再通知服務器應用去啟動線程進行處理,每個線程不必親自處理io,而是委派os來處理,並且也不需要等待io完成了,如果完成后,os會通知的。

采用linux的epoll模型。

結論

在連接數不多的情況下,傳統IO編寫容易、方便使用。但是隨着連接數的增多,問題傳統IO就不行了。因為傳統IO處理每個連接都要消耗一個線程,而程序的效率當線程數不多時是隨着線程數的增加而增加,但是到一定的數量之后,是隨着線程數的增加而減少。所以傳統阻塞式IO的 瓶頸在於不能處理過多的連接。

非阻塞式IO的出現的目的就是為了解決這個瓶頸。而非阻塞式IO是怎么實現的呢?非阻塞IO處理連接的線程數和連接數沒有聯系,也就是說處理10000個 連接非阻塞IO不需要10000個線程,你可以用1000個也可以用2000個線程來處理。因為非阻塞IO處理連接是異步的。當某個連接發送請求到服務 器,服務器把這個連接請求當作一個請求"事件",並把這個"事件"分配給相應的函數處理。我們可以把這個處理函數放到線程中去執行,執行完就把線程歸還。 這樣一個線程就可以異步的處理多個事件。而阻塞式IO的線程的大部分時間都浪費在等待請求上了。

然后NIO的非阻塞,需要一直輪詢,也是一個比較耗資源的,所以出現AIO 。

BIO、NIO、AIO適用場景

** BIO方式適用於連接數目比較小且固定的架構,這種方式對服務器資源要求比較高,並發局限於應用中,JDK1.4以前的唯一選擇,但程序直觀簡單易理解。**

**NIO方式適用於連接數目多且連接比較短(輕操作)的架構,比如聊天服務器,並發局限於應用中,編程比較復雜,JDK1.4開始支持。 **

AIO方式使用於連接數目多且連接比較長(重操作)的架構,比如相冊服務器,充分調用OS參與並發操作,編程比較復雜,JDK7開始支持。

**ps:AIO、NIO是基於IO的,並不是取代IO的意思。 **

二、NIO的框架

IO的概念:

就IO而言:概念上有5中模型:blocking I/O,nonblocking I/O,I/O multiplexing (select and poll),signal driven I/O (SIGIO),asynchronous I/O (the POSIX aio_functions)。

然后呢 不同的操作系統對上述模型支持不同: unix支持io多路復用,不同系統叫法不同 :freebsd里面叫 kqueue;linux 是epoll。而windows: 2000的時候就誕生了IOCP支持最后一種異步I/O

java是一種跨平台語言,為了支持異步IO,誕生了nio,Java1.4引入的NIO 1.0是基於I/O復用的。在各個平台上會選擇不同的復用方式。Linux用的epoll,BSD上用kqueue,Windows上應該是重疊I/O(肯定不是IOCP)。

基於jdk的nio ,不同公司出了一堆框架:apache mina ,jboss的netty,sun的grizzly。 這些都是直接封裝傳輸層的tcp/udp。

nio直接使用比較難用,所以有了netty等針對網絡io部分(tcp/udp-傳輸層)的封裝(nio也有非網絡io部分),為了使nio更易用。 ** netty等只是一個nio框架,不需要web容器的額外支持,也就是說不限定web容器。**

3個NIO框架是:

Mina

Mina(Multipurpose Infrastructure for Network Applications) 是 Apache組織一個較新的項目,它為開發高性能和高可用性的網絡應用程序提供了非常便利的框架。當前發行的 Mina 版本2.04支持基於 JavaNIO 技術的 TCP/UDP 應用程序開發、串口通訊程序,Mina 所支持的功能也在進一步的擴展中。目前,正在使用Mina的應用包括:Apache Directory Project、AsyncWeb、AMQP(Advanced MessageQueuing Protocol)、RED5 Server(Macromedia? FlashMedia RTMP)、ObjectRADIUS、 Openfire等等。

Netty

Netty是一款異步的事件驅動的網絡應用框架和工具,用於快速開發可維護的高性能、高擴展性協議服務器和客戶端。也就是說,Netty是一個NIO客戶端/服務器框架,支持快速、簡單地開發網絡應用,如協議服務器和客戶端。它極大簡化了網絡編程,如TCP和UDP套接字服務器。

Grizzly

Grizzly是一種應用程序框架,專門解決編寫成千上萬用戶訪問服務器時候產生的各種問題。使用JAVANIO作為基礎,並隱藏其編程的復雜性。容易使用的高性能的API。帶來非阻塞socketd到協議處理層。利用高性能的緩沖和緩沖管理使用高性能的線程池。

Servlet3.0 vs NIO

servlet3.0是一個規范、或者協議,可以用IO實現,也可以用NIO實現,而NIO則只是一種技術實現。一個是架構,一個是具體技術。

相同:

都提供了異步功能。

不同:

jdk的nio直接使用比較難用,所以有了netty這些針對網絡io部分(tcp/udp-傳輸層)的封裝(nio也有非網絡io部分),為了使nio更易用而已。

servlet3.0是另外一個東西,不是對io的封裝,而是javaee6眾多規范中的一個。但凡javaee6的實現(或者像tomcat這種web容 器部分的實現),都會支持servlet3.0,servlet理論上可以支持多種應用層協議(不單單只是http),而servlet3.0以后提供的 異步特性與javase提供的nio或aio無直接關系,就是使用bio一樣可以實現servlet3.0中提供的異步特性。

總結


免責聲明!

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



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