新聞中心
Reactor模式是處理并發(fā)I/O比較常見的一種模式,用于同步I/O,中心思想是將所有要處理的I/O事件注冊到一個中心I/O多路復(fù)用器上,同時主線程阻塞在多路復(fù)用器上;一旦有I/O事件到來或是準備就緒(區(qū)別在于多路復(fù)用器是邊沿觸發(fā)還是水平觸發(fā)),多路復(fù)用器返回并將相應(yīng)I/O事件分發(fā)到對應(yīng)的處理器中。

在朔州等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供成都網(wǎng)站建設(shè)、成都網(wǎng)站制作 網(wǎng)站設(shè)計制作按需定制網(wǎng)站,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站建設(shè),全網(wǎng)整合營銷推廣,外貿(mào)營銷網(wǎng)站建設(shè),朔州網(wǎng)站建設(shè)費用合理。
Reactor是一種事件驅(qū)動機制,和普通函數(shù)調(diào)用的不同之處在于:應(yīng)用程序不是主動的調(diào)用某個API完成處理,而是恰恰相反,Reactor逆置了事件處理流程,應(yīng)用程序需要提供相應(yīng)的接口并注冊到Reactor上,如果相應(yīng)的事件發(fā)生,Reactor將主動調(diào)用應(yīng)用程序注冊的接口,這些接口又稱為“回調(diào)函數(shù)”。用“好萊塢原則”來形容Reactor再合適不過了:不要打電話給我們,我們會打電話通知你。
Reactor模式與Observer模式在某些方面極為相似:當一個主體發(fā)生改變時,所有依屬體都得到通知。不過,觀察者模式與單個事件源關(guān)聯(lián),而反應(yīng)器模式則與多個事件源關(guān)聯(lián) 。
模式框架
1) Handle
Handle代表操作系統(tǒng)管理的資源,包括:網(wǎng)絡(luò)鏈接,打開的文件,計時器,同步對象等等。Linux上是文件描述符,Windows上就是Socket或者Handle了,這里統(tǒng)一稱為“句柄集”;程序在指定的句柄上注冊關(guān)心的事件,比如I/O事件。
2) Event Demultiplexer
事件分離器,由操作系統(tǒng)提供,在linux上一般是select, poll, epoll等系統(tǒng)調(diào)用,在一個Handle集合上等待事件的發(fā)生。接受client連接,建立對應(yīng)client的事件處理器(Event Handler),并向事件分發(fā)器(Reactor)注冊此事件處理器(Handler)。
3) Reactor(Initiation Dispatcher)
提供接口:注冊,刪除和派發(fā)Event Handler。Event Demultiplexer等待事件的發(fā)生,當檢測到新的事件,就把事件交給Initiation Dispatcher,它去回調(diào)Event Handler。
4) Event Handler
事件處理器,負責處理特定事件的處理函數(shù)。一般在基本的Handler基礎(chǔ)上還會有更進一步的層次劃分,用來抽象諸如decode,process和encoder這些過程。比如對Web Server而言,decode通常是HTTP請求的解析,process的過程會進一步涉及到Listner和Servlet的調(diào)用。為了簡化設(shè)計,Event Handler通常被設(shè)計成狀態(tài)機,按GoF的state pattern來實現(xiàn)。
5) Concrete Event Handler
繼承上面的類,實現(xiàn)鉤子方法。應(yīng)用把Concrete Event Handler注冊到Reactor,等待被處理的事件。當事件發(fā)生,這些方法被回調(diào)。
事件處理流程
模式模型
應(yīng)用場景舉例
場景:長途客車在路途上,有人上車有人下車,但是乘客總是希望能夠在客車上得到休息。
傳統(tǒng)做法:每隔一段時間(或每一個站),司機或售票員對每一個乘客詢問是否下車。
Reactor做法:汽車是乘客訪問的主體(Reactor),乘客上車后,到售票員(acceptor)處登記,之后乘客便可以休息睡覺去了,當?shù)竭_乘客所要到達的目的地后,售票員將其喚醒即可。
1) 單線程模型
這是最簡單的單Reactor單線程模型。Reactor線程是個多面手,負責多路分離套接字,Accept新連接,并分派請求到處理器鏈中。該模型適用于處理器鏈中業(yè)務(wù)處理組件能快速完成的場景。不過這種單線程模型不能充分利用多核資源,所以實際使用的不多。
2) 多線程模型(單Reactor)
相比上一種模型,該模型在事件處理器(Handler)鏈部分采用了多線程(線程池),也是后端程序常用的模型。
3) 多線程模型(多Reactor)
這個模型比起第二種模型,它是將Reactor分成兩部分,mainReactor負責監(jiān)聽并accept新連接,然后將建立的socket通過多路復(fù)用器(Acceptor)分派給subReactor。subReactor負責多路分離已連接的socket,讀寫網(wǎng)絡(luò)數(shù)據(jù);業(yè)務(wù)處理功能,其交給worker線程池完成。通常,subReactor個數(shù)上可與CPU個數(shù)等同。
優(yōu)缺點
優(yōu)點
響應(yīng)快,不必為單個同步時間所阻塞,雖然Reactor本身依然是同步的;
編程相對簡單,可以最大程度的避免復(fù)雜的多線程及同步問題,并且避免了多線程/進程的切換開銷;
可擴展性,可以方便的通過增加Reactor實例個數(shù)來充分利用CPU資源;
可復(fù)用性,Reactor框架本身與具體事件處理邏輯無關(guān),具有很高的復(fù)用性;
缺點
應(yīng)用受限制:Reactor模式只能應(yīng)用在支持Handle的操作系統(tǒng)上。雖然可以使用多線程模擬Reactor,但因為同步控制和上下文切換的要求,這種實現(xiàn)效率低,與Reactor模式出發(fā)點相違背。
非搶占模式:在單線程的實現(xiàn)這種情況下,事件的處理必須不能使用阻塞的I/O,因此,如果存在長期操作,比如傳輸大量的數(shù)據(jù)。使用主動對象,效率可能更好,主動對象可以并發(fā)的處理這些任務(wù)。
難以調(diào)試:使用Reactor模式的應(yīng)用程序可能會難以調(diào)試,因為程序運行的控制流會在框架和應(yīng)用相關(guān)的處理器之間跳轉(zhuǎn),不了解框架的應(yīng)用程序開發(fā)人員難一跟著調(diào)試。
相關(guān)庫
ACE
ACE是一個大型的中間件產(chǎn)品,代碼20萬行左右,過于宏大,一堆的設(shè)計模式,架構(gòu)了一層又一層,使用的時候,要根據(jù)情況,看從那一層來進行使用。支持跨平臺。
設(shè)計模式 :ACE主要應(yīng)用了Reactor,Proactor等;
層次架構(gòu) :ACE底層是C風格的OS適配層,上一層基于C++的wrap類,再上一層是一些框架 (Accpetor,Connector,Reactor,Proactor等),最上一層是框架上服務(wù);
可移植性 :ACE支持多種平臺,可移植性不存在問題,據(jù)說socket編程在linux下有不少bugs;
事件分派處理 :ACE主要是注冊handler類,當事件分派時,調(diào)用其handler的虛掛勾函數(shù)。實現(xiàn) ACE_Handler/ACE_Svc_Handler/ACE_Event_handler等類的虛函數(shù);
涉及范圍 :ACE包含了日志,IPC,線程池,共享內(nèi)存,配置服務(wù),遞歸鎖,定時器等;
線程調(diào)度 :ACE的Reactor是單線程調(diào)度,Proactor支持多線程調(diào)度;
發(fā)布方式 :ACE是開源免費的,不依賴于第三方庫,一般應(yīng)用使用它時,以動態(tài)鏈接的方式發(fā)布動態(tài)庫;開發(fā)難度 :基于ACE開發(fā)應(yīng)用,對程序員要求比較高,要用好它,必須非常了解其框架。在其框架下開發(fā),往往new出一個對象,不知在什么地方釋放好。
Libevent
libevent是一個C語言寫的網(wǎng)絡(luò)庫,官方主要支持的是類linux操作系統(tǒng),最新的版本添加了對windows的IOCP的支持。在跨平臺方面主要通過select模型來進行支持。
設(shè)計模式 :libevent為Reactor模式;
層次架構(gòu):livevent在不同的操作系統(tǒng)下,做了多路復(fù)用模型的抽象,可以選擇使用不同的模型,通過事件函數(shù)提供服務(wù);
可移植性 :libevent主要支持linux平臺,freebsd平臺,其他平臺下通過select模型進行支持,效率不是太高;
事件分派處理 :libevent基于注冊的事件回調(diào)函數(shù)來實現(xiàn)事件分發(fā);
涉及范圍 :libevent只提供了簡單的網(wǎng)絡(luò)API的封裝,線程池,內(nèi)存池,遞歸鎖等均需要自己實現(xiàn);
線程調(diào)度 :libevent的線程調(diào)度需要自己來注冊不同的事件句柄;
發(fā)布方式 :libevent為開源免費的,一般編譯為靜態(tài)庫進行使用;
開發(fā)難度 :基于libevent開發(fā)應(yīng)用,相對容易,具體可以參考memcached這個開源的應(yīng)用,里面使用了 libevent這個庫。
Libev
與 libevent 一樣,libev 系統(tǒng)也是基于事件循環(huán)的系統(tǒng),它在 poll()、select() 等機制的本機實現(xiàn)的基礎(chǔ)上提供基于事件的循環(huán)。libev 實現(xiàn)的開銷更低,能夠?qū)崿F(xiàn)更好的基準測試結(jié)果。
Reactor模式在DSS中的體現(xiàn)
Darwin流媒體服務(wù)器是由父進程及其fork出來的子進程構(gòu)成的,子進程就是核心服務(wù)器。父進程的職責就是等待子進程退出。如果子進程出錯退出,則父進程就會fork一個新的子進程,從而保證視頻服務(wù)器繼續(xù)提供服務(wù)。核心服務(wù)器的作用是充當VOD(視頻點播)客戶端與服務(wù)器模塊之間的接口,VOD客戶端采用RTP和RTSP協(xié)議向服務(wù)器發(fā)送請求并接收響應(yīng),服務(wù)器模塊負責處理VOD客戶端的請求并向VOD客戶端發(fā)送數(shù)據(jù)包。
在DSS中,除主線程以外,還有有三種類型的線程:
TaskThread:TaskThread通過運行Task類型對象的Run方法來完成相應(yīng)Task的處理。典型的Task類型是RTSPSession和RTPSession。TaskThread的個數(shù)是可配置的,缺省情況下TaskThread的個數(shù)與處理器的個數(shù)一致。等待被TaskThread調(diào)用并運行的Task放在隊列或者堆中。
EventThread:EventThread負責偵聽套接口事件,在DSS中,有兩種被偵聽的事件,分別是建立RTSP連接請求的到達和RTSP請求的到達。對于RTSP連接請求的事件,EventThread建立一個RTSP
Session,并啟動針對相應(yīng)的socket的偵聽。對于RTSP請求的事件,EventThread把對應(yīng)的RTSPSession類型的Task加入到TaskThread的隊列中,等待RTSP請求被處理。IdleTaskThread:IdleTaskThread管理IdleTask類型對象的隊列,根據(jù)預(yù)先設(shè)定的定時器觸發(fā)IdleTask的調(diào)度。TCPListenerSocket就是一個IdleTask的派生類,當并發(fā)連接數(shù)達到設(shè)定的最大值時,會把派生自TCPListenerSocket的RTSPListenerSocket加入到IdleTaskThread管理的IdleTask隊列中,暫時停止對RTSP端口的偵聽,直到被設(shè)定好的定時器觸發(fā)。
下圖是Darwin Streaming Server核心架構(gòu)的示意圖。在這個示意圖中有三種類型的要素,分別是線程,Task隊列或者堆,被偵聽的事件。
其中,事件線程(Event thread)是Event Demultiplexer(事件分離器),任務(wù)線程(Task threads)是Event Handler(事件處理器)。
這里的主線程(Main thread)就是Reactor模式中的Reactor(Initiation Dispatcher)。
E-Mail : Mike_Zhang@live.com
本文標題:Reactor模式及在DSS中的體現(xiàn)
標題URL:http://www.dlmjj.cn/article/cdoiipc.html


咨詢
建站咨詢
