想象以下情形:長途客車在路途上,有人上車有人下車魔吐,但是乘客總是希望能夠在客車上得到休息扎筒。
傳統(tǒng)的做法是:每隔一段時間(或每一個站),司機或售票員對每一個乘客詢問是否下車酬姆。
Reactor模式做法是:汽車是乘客訪問的主體(Reactor)嗜桌,乘客上車后,到售票員(acceptor)處登記辞色,之后乘客便可以休息睡覺去了骨宠,當(dāng)?shù)竭_乘客所要到達的目的地后,售票員將其喚醒即可淫僻。
概念
Reactor模式是基于事件驅(qū)動的分發(fā)處理模型
有一個或多個并發(fā)輸入源诱篷,有一個Service Handler,有多個Request Handlers
這個Service Handler會同步的將輸入的請求(Event)多路復(fù)用的分發(fā)給相應(yīng)的Request Handler雳灵。如果用圖來表達:
思想:分而治之+事件驅(qū)動
1)分而治之
一個連接里完整的網(wǎng)絡(luò)處理過程一般分為accept、read闸盔、decode悯辙、process、encode、send這幾步躲撰。
Reactor模式將每個步驟映射為一個Task针贬,服務(wù)端線程執(zhí)行的最小邏輯單元不再是一次完整的網(wǎng)絡(luò)請求,而是Task拢蛋,且采用非阻塞方式執(zhí)行桦他。
2)事件驅(qū)動
每個Task對應(yīng)特定網(wǎng)絡(luò)事件。當(dāng)Task準(zhǔn)備就緒時谆棱,Reactor收到對應(yīng)的網(wǎng)絡(luò)事件通知快压,并將Task分發(fā)給綁定了對應(yīng)網(wǎng)絡(luò)事件的Handler執(zhí)行。
3)幾個角色
reactor:負(fù)責(zé)綁定管理事件和處理接口垃瞧;
selector:負(fù)責(zé)監(jiān)聽響應(yīng)事件蔫劣,將事件分發(fā)給綁定了該事件的Handler處理;
Handler:事件處理器个从,綁定了某類事件脉幢,負(fù)責(zé)執(zhí)行對應(yīng)事件的Task對事件進行處理;
Acceptor:Handler的一種嗦锐,綁定了connect事件嫌松。當(dāng)客戶端發(fā)起connect請求時,Reactor會將accept事件分發(fā)給Acceptor處理奕污。
Reactor模式結(jié)構(gòu)
- Handle 句柄萎羔;用來標(biāo)識socket連接或是打開文件;
- Synchronous Event Demultiplexer:同步事件多路分解器:由操作系統(tǒng)內(nèi)核實現(xiàn)的一個函數(shù)菊值;用于阻塞等待發(fā)生在句柄集合上的一個或多個事件外驱;(如select/epoll;)
- Event Handler:事件處理接口
- Concrete Event HandlerA:實現(xiàn)應(yīng)用程序所提供的特定事件處理邏輯腻窒;
- Reactor:反應(yīng)器昵宇,定義一個接口,實現(xiàn)以下功能:
1)供應(yīng)用程序注冊和刪除關(guān)注的事件句柄儿子;
2)運行事件循環(huán)瓦哎;
3)有就緒事件到來時,分發(fā)事件到之前注冊的回調(diào)函數(shù)上處理柔逼;
“反應(yīng)”即“倒置”蒋譬,“控制逆轉(zhuǎn)”
流程
舉例
登錄——Accept新鏈接
新連接Read和Write過程
實現(xiàn)
單線程Reactor
1)優(yōu)點:
不需要做并發(fā)控制,代碼實現(xiàn)簡單清晰愉适。
2)缺點:
a)不能利用多核CPU犯助;
b)一個線程需要執(zhí)行處理所有的accept、read维咸、decode剂买、process惠爽、encode、send事件瞬哼,處理成百上千的鏈路時性能上無法支撐婚肆;
c)一旦reactor線程意外跑飛或者進入死循環(huán),會導(dǎo)致整個系統(tǒng)通信模塊不可用坐慰。
多線程Reactor
特點:
a)有專門一個reactor線程用于監(jiān)聽服務(wù)端ServerSocketChannel较性,接收客戶端的TCP連接請求;
b)網(wǎng)絡(luò)IO的讀/寫操作等由一個worker reactor線程池負(fù)責(zé)结胀,由線程池中的NIO線程負(fù)責(zé)監(jiān)聽SocketChannel事件赞咙,進行消息的讀取、解碼把跨、編碼和發(fā)送人弓。
c)一個NIO線程可以同時處理N條鏈路,但是一個鏈路只注冊在一個NIO線程上處理着逐,防止發(fā)生并發(fā)操作問題崔赌。
主從多線程
在絕大多數(shù)場景下,Reactor多線程模型都可以滿足性能需求耸别;但是在極個別特殊場景中健芭,一個NIO線程負(fù)責(zé)監(jiān)聽和處理所有的客戶端連接可能會存在性能問題。
特點:
a)服務(wù)端用于接收客戶端連接的不再是個1個單獨的reactor線程秀姐,而是一個boss reactor線程池慈迈;
b)服務(wù)端啟用多個ServerSocketChannel監(jiān)聽不同端口時,每個ServerSocketChannel的監(jiān)聽工作可以由線程池中的一個NIO線程完成省有。
Ref:
【原論文】http://www.dre.vanderbilt.edu/~schmidt/PDF/reactor-siemens.pdf
http://www.voidcn.com/article/p-onnrusud-mz.html