新聞中心
一、 Reactor and Proactor

IO讀寫時,多路復用機制都會依賴對一個事件多路分離器,負責把源事件的IO 事件分離出來,分別到相應(yīng)的read/write事件分離器。涉及到事件分離器的兩種模式分別就是 Reactor和Proactor,Reactor是基于同步IO的,Proactor是基于異步IO的。
在Reactor模式中,事件分離者等待某個事件或者可應(yīng)用或個操作的狀態(tài)發(fā)生(比如文件描述符可讀寫,或者是socket可讀寫),事件分離者就把這個事件傳給事先注冊的事件處理函數(shù)或者回調(diào)函數(shù),由后者來做實際的讀寫操作。
在Proactor模式中,事件處理者(或者代由事件分離者發(fā)起)直接發(fā)起一個異步讀寫操作(相當于請求),而實際的工作是由操作系統(tǒng)來完成的。發(fā)起時,需要提供的參數(shù)包括用于存放讀到數(shù)據(jù)的緩存區(qū),讀的數(shù)據(jù)大小,或者用于存放外發(fā)數(shù)據(jù)的緩存區(qū),以及這個請求完后的回調(diào)函數(shù)等信息。事件分離者得知了這個請求,它默默等待這個請求的完成,然后轉(zhuǎn)發(fā)完成事件給相應(yīng)的事件處理者或者回調(diào)。舉例來說,在Windows上事件處理者投遞了一個異步IO操作(稱有 overlapped的技術(shù)),事件分離者等IOCompletion事件完成. 這種異步模式的典型實現(xiàn)是基于操作系統(tǒng)底層異步API的,所以我們可稱之為“系統(tǒng)級別”的或者“真正意義上”的異步,因為具體的讀寫是由操作系統(tǒng)代勞的。
舉個例子,將有助于理解Reactor與Proactor二者的差異,以讀操作為例(類操作類似)。
在Reactor中實現(xiàn)讀:
- 注冊讀就緒事件和相應(yīng)的事件處理器
- 事件分離器等待事件
- 事件到來,激活分離器,分離器調(diào)用事件對應(yīng)的處理器。
- 事件處理器完成實際的讀操作,處理讀到的數(shù)據(jù),注冊新的事件,然后返還控制權(quán)。
與如下Proactor(真異步)中的讀過程比較:
- 處理器發(fā)起異步讀操作(注意:操作系統(tǒng)必須支持異步IO)。在這種情況下,處理器無視IO就緒事件,它關(guān)注的是完成事件。
- 事件分離器等待操作完成事件
- 在分離器等待過程中,操作系統(tǒng)利用并行的內(nèi)核線程執(zhí)行實際的讀操作,并將結(jié)果數(shù)據(jù)存入用戶自定義緩沖區(qū),最后通知事件分離器讀操作完成。
- 事件分離器呼喚處理器。
- 事件處理器處理用戶自定義緩沖區(qū)中的數(shù)據(jù),然后啟動一個新的異步操作,并將控制權(quán)返回事件分離器。
可以看出,兩個模式的相同點,都是對某個IO事件的事件通知(即告訴某個模塊,這個IO操作可以進行或已經(jīng)完成)。在結(jié)構(gòu)
上,兩者也有相同點:demultiplexor負責提交IO操作(異步)、查詢設(shè)備是否可操作(同步),然后當條件滿足時,就回調(diào)handler;
不同點在于,異步情況下(Proactor),當回調(diào)handler時,表示IO操作已經(jīng)完成;同步情況下(Reactor),回調(diào)handler時,表示
IO設(shè)備可以進行某個操作(can read or can write),handler這個時候開始提交操作。
二、BIO、NIO、AIO
NIO通常采用Reactor模式,AIO通常采用Proactor模式。AIO簡化了程序的編寫,stream的讀取和寫入都有OS來完成,不需要像NIO那樣子遍歷Selector。Windows基于IOCP實現(xiàn)AIO,Linux只有eppoll模擬實現(xiàn)了AIO。
Java7之前的JDK只支持NIO和BIO,從7開始支持AIO。
4種通信方式:TCP/IP+BIO, TCP/IP+NIO, UDP/IP+BIO, UDP/IP+NIO。
TCP/IP+BIO、
Socket和ServerSocket實現(xiàn),ServerSocket實現(xiàn)Server端端口監(jiān)聽,Socket用于建立網(wǎng)絡(luò)IO連接。
不適用于處理多個請求 1.生成Socket會消耗過多的本地資源。2. Socket連接的建立一般比較慢。
BIO情況下,能支持的連接數(shù)有限,一般都采取accept獲取Socket以后采用一個thread來處理,one connection one thread。無論連接是否有真正數(shù)據(jù)請求,都需要獨占一個thread。
可以通過設(shè)立Socket池來一定程度上解決問題,但是使用池需要注意的問題是:1. 競爭等待比較多。 2. 需要控制好超時時間。
TCP/IP+NIO
使用Channel(SocketChannel和ServerSocketChannel)和Selector。
Server端通常由一個thread來監(jiān)聽connect事件,另外多個thread來監(jiān)聽讀寫事件。這樣做的好處是這些連接只有在真是請求的時候才會創(chuàng)建thread來處理,one request one thread。這種方式在server端需要支持大量連接但這些連接同時發(fā)送請求的峰值不會很多的時候十分有效。
UDP/IP+BIO
DatagramSocket和DatagramPacket。DatagramSocket負責監(jiān)聽端口以及讀寫數(shù)據(jù),DatagramPacket作為數(shù)據(jù)流對象進行傳輸。
UDP/IP是無連接的,無法進行雙向通信,除非雙方都成為UDP Server。
UDP/IP+NIO
通過DatagramChannel和ByteBuffer實現(xiàn)。DatagramChannel負責端口監(jiān)聽及讀寫。ByteBuffer負責數(shù)據(jù)流傳輸。
如果要將消息發(fā)送到多臺機器,如果為每個目標機器都建立一個連接的話,會有很大的網(wǎng)絡(luò)流量壓力。這時候可以使用基于UDP/IP的Multicast協(xié)議傳輸,Java中可以通過MulticastSocket和DatagramPacket來實現(xiàn)。
Multicast一般多用于多臺機器的狀態(tài)同步,比如JGroups。SRM, URGCP都是Multicast的實現(xiàn)方式。eBay就采用SRM來實現(xiàn)將數(shù)據(jù)從主數(shù)據(jù)庫同步到各個搜索節(jié)點機器。
名稱欄目:詳解BIO與NIO的區(qū)別
文章網(wǎng)址:http://m.fisionsoft.com.cn/article/cceshhg.html


咨詢
建站咨詢
