日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > asp.net >内容正文

asp.net

2种IO并发开发中的设计模式:Reactor and Proactor

發(fā)布時(shí)間:2023/12/15 asp.net 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2种IO并发开发中的设计模式:Reactor and Proactor 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Reactor and Proactor

[原文:http://blog.csdn.net/wenbingoon/article/details/9880365]

? ?? 1 概述

IO讀寫(xiě)時(shí),多路復(fù)用機(jī)制都會(huì)依賴對(duì)一個(gè)事件多路分離器,負(fù)責(zé)把源事件的IO 事件分離出來(lái),分別到相應(yīng)的read/write事件分離器。涉及到事件分離器的兩種模式分別就是 Reactor和Proactor,Reactor是基于同步IO的,Proactor是基于異步IO的。

在Reactor模式中,事件分離者等待某個(gè)事件或者可應(yīng)用或個(gè)操作的狀態(tài)發(fā)生(比如文件描述符可讀寫(xiě),或者是socket可讀寫(xiě)),事件分離者就把這個(gè)事件傳給事先注冊(cè)的事件處理函數(shù)或者回調(diào)函數(shù),由后者來(lái)做實(shí)際的讀寫(xiě)操作。Reactor模式主要是提高系統(tǒng)的吞吐量,理解反應(yīng)器模式的例子Reactor模式,或者叫反應(yīng)器模式

在Proactor模式中,事件處理者(或者代由事件分離者發(fā)起)直接發(fā)起一個(gè)異步讀寫(xiě)操作(相當(dāng)于請(qǐng)求),而實(shí)際的工作是由操作系統(tǒng)來(lái)完成的。發(fā)起時(shí),需要提供的參數(shù)包括用于存放讀到數(shù)據(jù)的緩存區(qū),讀的數(shù)據(jù)大小,或者用于存放外發(fā)數(shù)據(jù)的緩存區(qū),以及這個(gè)請(qǐng)求完后的回調(diào)函數(shù)等信息。事件分離者得知了這個(gè)請(qǐng)求,它默默等待這個(gè)請(qǐng)求的完成,然后轉(zhuǎn)發(fā)完成事件給相應(yīng)的事件處理者或者回調(diào)。舉例來(lái)說(shuō),在Windows上事件處理者投遞了一個(gè)異步IO操作(稱有 overlapped的技術(shù)),事件分離者等IOCompletion事件完成. 這種異步模式的典型實(shí)現(xiàn)是基于操作系統(tǒng)底層異步API的,所以我們可稱之為“系統(tǒng)級(jí)別”的或者“真正意義上”的異步,因?yàn)榫唧w的讀寫(xiě)是由操作系統(tǒng)代勞的。

舉個(gè)例子,將有助于理解Reactor與Proactor二者的差異,以讀操作為例(類操作類似)。

在Reactor中實(shí)現(xiàn)讀

- 注冊(cè)讀就緒事件和相應(yīng)的事件處理器

- 事件分離器等待事件

- 事件到來(lái),激活分離器,分離器調(diào)用事件對(duì)應(yīng)的處理器。

- 事件處理器完成實(shí)際的讀操作,處理讀到的數(shù)據(jù),注冊(cè)新的事件,然后返還控制權(quán)。

與如下Proactor(真異步)中的讀過(guò)程比較:

- 處理器發(fā)起異步讀操作(注意:操作系統(tǒng)必須支持異步IO)。在這種情況下,處理器無(wú)視IO就緒事件,它關(guān)注的是完成事件。

- 事件分離器等待操作完成事件

- 在分離器等待過(guò)程中,操作系統(tǒng)利用并行的內(nèi)核線程執(zhí)行實(shí)際的讀操作,并將結(jié)果數(shù)據(jù)存入用戶自定義緩沖區(qū),最后通知事件分離器讀操作完成。

- 事件分離器呼喚處理器。

- 事件處理器處理用戶自定義緩沖區(qū)中的數(shù)據(jù),然后啟動(dòng)一個(gè)新的異步操作,并將控制權(quán)返回事件分離器。

可以看出,兩個(gè)模式的相同點(diǎn),都是對(duì)某個(gè)IO事件的事件通知(即告訴某個(gè)模塊,這個(gè)IO操作可以進(jìn)行或已經(jīng)完成)。在結(jié)構(gòu)上,兩者也有相同點(diǎn):demultiplexor負(fù)責(zé)提交IO操作(異步)、查詢?cè)O(shè)備是否可操作(同步),然后當(dāng)條件滿足時(shí),就回調(diào)handler;

? 不同點(diǎn)在于,異步情況下(Proactor),當(dāng)回調(diào)handler時(shí),表示IO操作已經(jīng)完成;同步情況下(Reactor),回調(diào)handler時(shí),表示IO設(shè)備可以進(jìn)行某個(gè)操作(can read or can write),handler這個(gè)時(shí)候開(kāi)始提交操作。

2、Reactor模式

?? ??Reactor釋義“反應(yīng)堆”,是一種事件驅(qū)動(dòng)機(jī)制。和普通函數(shù)調(diào)用的不同之處在于:應(yīng)用程序不是主動(dòng)的調(diào)用某個(gè)API完成處理,而是恰恰相反,Reactor逆置了事件處理流程,應(yīng)用程序需要提供相應(yīng)的接口并注冊(cè)到Reactor上,如果相應(yīng)的時(shí)間發(fā)生,Reactor將主動(dòng)調(diào)用應(yīng)用程序注冊(cè)的接口,這些接口又稱為“回調(diào)函數(shù)”。使用Libevent也是想Libevent框架注冊(cè)相應(yīng)的事件和回調(diào)函數(shù);當(dāng)這些時(shí)間發(fā)聲時(shí),Libevent會(huì)調(diào)用這些回調(diào)函數(shù)處理相應(yīng)的事件(I/O讀寫(xiě)、定時(shí)和信號(hào))。
?? ?用“好萊塢原則”來(lái)形容Reactor再合適不過(guò)了:不要打電話給我們,我們會(huì)打電話通知你。
?


3、兩個(gè)模式簡(jiǎn)單對(duì)比

?? ? 兩個(gè)模式的相同點(diǎn):(1)都是對(duì)某個(gè)IO事件的事件通知(即告訴某個(gè)模塊,這個(gè)IO操作可以進(jìn)行或已經(jīng)完成)。(2)在結(jié)構(gòu)上的相同點(diǎn):demultiplexor負(fù)責(zé)提交IO操作(異步)、查詢?cè)O(shè)備是否可操作(同步),然后當(dāng)條件滿足時(shí),就回調(diào)handler。

?? ? 不同點(diǎn)在于:異步情況下(Proactor),當(dāng)回調(diào)handler時(shí),表示IO操作已經(jīng)完成;同步情況下(Reactor),回調(diào)handler時(shí),表示IO設(shè)備可以進(jìn)行某個(gè)操作(can read or can write),handler這個(gè)時(shí)候開(kāi)始提交操作。

?? ? 我的理解:兩者的根本區(qū)別就在于《Unix網(wǎng)絡(luò)編程第一卷:套接口API》第6章講解的五種I/O模型,Proactor是基于異步I/O,Reactor是同步I/O(一般是I/O復(fù)用)。但是現(xiàn)在的操作系統(tǒng)并不是都能很好的真正支持異步I/O,比如Windows里有真正的異步I/O——IOCP,而Unix、Linux并沒(méi)有真正實(shí)現(xiàn)異步I/O。所以考慮程序移植性以及現(xiàn)在很多服務(wù)器基于Unix,Linux;Proactor封裝了這種差異,在內(nèi)部異步事件分離器實(shí)現(xiàn)時(shí)根據(jù)系統(tǒng)的不同調(diào)用相應(yīng)的I/O模式。



二、BIO、NIO、AIO

?NIO通常采用Reactor模式,AIO通常采用Proactor模式。AIO簡(jiǎn)化了程序的編寫(xiě),stream的讀取和寫(xiě)入都有OS來(lái)完成,不需要像NIO那樣子遍歷Selector。Windows基于IOCP實(shí)現(xiàn)AIO,Linux只有eppoll模擬實(shí)現(xiàn)了AIO。

Java7之前的JDK只支持NIO和BIO,從7開(kāi)始支持AIO。

4種通信方式:TCP/IP+BIO, TCP/IP+NIO, UDP/IP+BIO, UDP/IP+NIO。

TCP/IP+BIO、

Socket和ServerSocket實(shí)現(xiàn),ServerSocket實(shí)現(xiàn)Server端端口監(jiān)聽(tīng),Socket用于建立網(wǎng)絡(luò)IO連接。

不適用于處理多個(gè)請(qǐng)求 1.生成Socket會(huì)消耗過(guò)多的本地資源。2. Socket連接的建立一般比較慢。

BIO情況下,能支持的連接數(shù)有限,一般都采取accept獲取Socket以后采用一個(gè)thread來(lái)處理,one connection one thread。無(wú)論連接是否有真正數(shù)據(jù)請(qǐng)求,都需要獨(dú)占一個(gè)thread。

可以通過(guò)設(shè)立Socket池來(lái)一定程度上解決問(wèn)題,但是使用池需要注意的問(wèn)題是:1. 競(jìng)爭(zhēng)等待比較多。 2. 需要控制好超時(shí)時(shí)間。

TCP/IP+NIO

使用Channel(SocketChannel和ServerSocketChannel)和Selector。

Server端通常由一個(gè)thread來(lái)監(jiān)聽(tīng)connect事件,另外多個(gè)thread來(lái)監(jiān)聽(tīng)讀寫(xiě)事件。這樣做的好處是這些連接只有在真是請(qǐng)求的時(shí)候才會(huì)創(chuàng)建thread來(lái)處理,one request one thread。這種方式在server端需要支持大量連接但這些連接同時(shí)發(fā)送請(qǐng)求的峰值不會(huì)很多的時(shí)候十分有效。

UDP/IP+BIO

DatagramSocket和DatagramPacket。DatagramSocket負(fù)責(zé)監(jiān)聽(tīng)端口以及讀寫(xiě)數(shù)據(jù),DatagramPacket作為數(shù)據(jù)流對(duì)象進(jìn)行傳輸。

UDP/IP是無(wú)連接的,無(wú)法進(jìn)行雙向通信,除非雙方都成為UDP Server。

UDP/IP+NIO

通過(guò)DatagramChannel和ByteBuffer實(shí)現(xiàn)。DatagramChannel負(fù)責(zé)端口監(jiān)聽(tīng)及讀寫(xiě)。ByteBuffer負(fù)責(zé)數(shù)據(jù)流傳輸。

如果要將消息發(fā)送到多臺(tái)機(jī)器,如果為每個(gè)目標(biāo)機(jī)器都建立一個(gè)連接的話,會(huì)有很大的網(wǎng)絡(luò)流量壓力。這時(shí)候可以使用基于UDP/IP的Multicast協(xié)議傳輸,Java中可以通過(guò)MulticastSocket和DatagramPacket來(lái)實(shí)現(xiàn)。

Multicast一般多用于多臺(tái)機(jī)器的狀態(tài)同步,比如JGroups。SRM, URGCP都是Multicast的實(shí)現(xiàn)方式。eBay就采用SRM來(lái)實(shí)現(xiàn)將數(shù)據(jù)從主數(shù)據(jù)庫(kù)同步到各個(gè)搜索節(jié)點(diǎn)機(jī)器。


------------------

就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)。

不同的操作系統(tǒng)對(duì)上述模型支持不同: unix支持io多路復(fù)用,不同系統(tǒng)叫法不同 :freebsd里面叫 kqueue;linux 是epoll。而windows: 2000的時(shí)候就誕生了IOCP支持最后一種異步I/O
java是一種跨平臺(tái)語(yǔ)言,為了支持異步IO,誕生了nio,Java1.4引入的NIO 1.0是基于I/O復(fù)用的。在各個(gè)平臺(tái)上會(huì)選擇不同的復(fù)用方式。Linux用的epoll,BSD上用kqueue,Windows上應(yīng)該是重疊I/O(肯定不是IOCP)。
?
NIO 2.0(Java1.7)里終于有AIO了,Linux上用AIO,Windows上用IOCP,都支持了概念上的最后一種IO -- asynchronous I/O?

-------------------

[原文: http://blog.sina.com.cn/s/blog_9a97a37c0101aahl.html]

Reactor and Proactor兩個(gè)模式的相同點(diǎn),都是對(duì)某個(gè)IO事件的事件通知(即告訴某個(gè)模塊,這個(gè)IO操作可以進(jìn)行或已經(jīng)完成)。在結(jié)構(gòu)上,兩者也有相同點(diǎn):demultiplexor負(fù)責(zé)提交IO操作(異步)、查詢?cè)O(shè)備是否可操作(同步),然后當(dāng)條件滿足時(shí),就回調(diào)handler。

不同點(diǎn)在于,異步情況下(Proactor),當(dāng)回調(diào)handler時(shí),表示IO操作已經(jīng)完成;同步情況下(Reactor),回調(diào)handler時(shí),表示IO設(shè)備可以進(jìn)行某個(gè)操作(can read or can write),handler這個(gè)時(shí)候開(kāi)始提交操作。

用select模型寫(xiě)個(gè)簡(jiǎn)單的reactor,大致為:

///
class?handler
{
public:
????
virtual?void?onRead()?=?0;
????
virtual?void?onWrite()?=?0;
????
virtual?void?onAccept()?=?0;
}
;?

class?dispatch
{
public:
????
void?poll()
????
{
????????
//?add?fd?in?the?set.
????????
//
????????
//?poll?every?fd
????????int?c?=?select(?0,?&read_fd,?&write_fd,?0,?0?);
????????
if(?c?>?0?)
????????
{
????????????
for?each?fd?in?the?read_fd_set
????????????
{????if?fd?can?read
????????????????????_handler
->onRead();
????????????????
if?fd?can?accept
????????????????????_handler
->onAccept();
????????????}
?

????????????
for?each?fd?in?the?write_fd_set
????????????
{
????????????????
if?fd?can?write
????????????????????_handler
->onWrite();
????????????}

????????}

????}
?

????
void?setHandler(?handler?*_h?)
????
{
????????_handler?
=?_h;
????}
?

private:
????handler?
*_handler;
}
;?

///?application
class?MyHandler?:?public?handler
{
public:
????
void?onRead()
????
{
????}
?

????
void?onWrite()
????
{
????}
?

????
void?onAccept()
????
{
????}

}
;?


在網(wǎng)上找了份Proactor模式比較正式的文檔,其給出了一個(gè)總體的UML類圖,比較全面:

根據(jù)這份圖我隨便寫(xiě)了個(gè)例子代碼:

class?AsyIOProcessor
{
public:
????
void?do_read()
????
{
????????
//send?read?operation?to?OS
????????
//?read?io?finished.and?dispatch?notification
????????_proactor->dispatch_read();
????}
?

private:
????Proactor?
*_proactor;
}
;?

class?Proactor
{
public:
????
void?dispatch_read()
????
{
????????_handlerMgr
->onRead();
????}
?

private:
????HandlerManager?
*_handlerMgr;
}
;?

class?HandlerManager
{
public:
????typedef?std::list
<Handler*>?HandlerList;?

public:
????
void?onRead()
????
{
????????
//?notify?all?the?handlers.
????????std::for_each(?_handlers.begin(),?_handlers.end(),?onRead?);
????}
?

private:
????HandlerList?
*_handlers;
}
;?

class?Handler
{
public:
????
virtual?void?onRead()?=?0;
}
;?

//?application?level?handler.
class?MyHandler?:?public?Handler
{
public:
????
void?onRead()?
????
{
????????
//?
????}
}
;?


Reactor通過(guò)某種變形,可以將其改裝為Proactor,在某些不支持異步IO的系統(tǒng)上,也可以隱藏底層的實(shí)現(xiàn),利于編寫(xiě)跨平臺(tái)
代碼。我們只需要在dispatch(也就是demultiplexor)中封裝同步IO操作的代碼,在上層,用戶提交自己的緩沖區(qū)到這一層,
這一層檢查到設(shè)備可操作時(shí),不像原來(lái)立即回調(diào)handler,而是開(kāi)始IO操作,然后將操作結(jié)果放到用戶緩沖區(qū)(讀),然后再
回調(diào)handler。這樣,對(duì)于上層handler而言,就像是proactor一樣。



----

其他參考:

兩種高性能I/O設(shè)計(jì)模式(Reactor/Proactor)的比較? http://blog.sina.com.cn/s/blog_5f435c130101ktl6.html


創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的2种IO并发开发中的设计模式:Reactor and Proactor的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。