Reactor模式

反應器設計模式(Reator pattern)是一種基于事件驅動的設計模式梳虽,常用于高并發(fā)場景下宋舷,常見的像Node.js状植、Netty袍嬉、Vert.x中都有著Reactor模式的身影。本文對Reactor模式作了簡要介紹厅贪,結合對比Node.js線程模型進行分析蠢护。

單線程Reactor模式

Reactor模式是一種事件處理模式,單個或多個事件并發(fā)地投遞到事件處理服務养涮,事件處理服務將事件進行分離葵硕,同步的將他們分發(fā)到對應的事件處理器中眉抬。

模式結構

下圖是一張示意圖,結合了維基百科的定義:

  • Handle:句柄懈凹,是對資源在操作系統(tǒng)層面的抽象(unix中的fd)蜀变,可供系統(tǒng)輸入或輸出的資源。在網(wǎng)絡編程中介评,一般指的是一個連接库北,如socket,Java NIO中的Channel
  • Demultiplexer:同步事件分離器们陆,通常使用EventLoop來進行資源的阻塞等待寒瓦,當一個資源處于就緒狀態(tài)的時候,會被輪詢出來傳遞給分發(fā)器
  • Dispatcher:分發(fā)器坪仇,用來注冊杂腰、移除EventHandler,將資源分配到對應的處理器中同步執(zhí)行
  • EventHandler:事件處理器烟很,處理對應的事件颈墅,一般由分發(fā)器進行回調。

交互過程

  • 初始化Dispatcher
  • 注冊EventHandler到Dispatcher雾袱,每個事件處理器包含對應Handle的引用恤筛,這樣就可以建立Handle到EventHandler的映射
  • 啟動EventLoop,阻塞等待資源的某個事件發(fā)生
  • 當某些Handle的事件發(fā)生后芹橡,資源變?yōu)榫途w狀態(tài)毒坛,會被傳遞給Dispatcher,分發(fā)器通過開始注冊的資源映射關系林说,調用對應的EventHandler方法煎殷。

這就是最簡單的Reactor模式,它其實也是I/O多路復用的一種具現(xiàn)腿箩,用戶不需要考慮并發(fā)的問題豪直,直接交給了事件處理器進行,同時也減少了高并發(fā)情況下多線程對系統(tǒng)資源的消耗珠移。

在一些小容量的場景下弓乙,單線程的模式可以使用,但在高負載钧惧、大并發(fā)的場景下卻不適用暇韧,主要在于一個NIO線程無法支撐同時處理成百上千的鏈路處理,在編解碼消息時浓瞪,由于無法及時處理會造成消息堆積懈玻,進而形成請求超時等問題,而且單個線程也不利于程序的穩(wěn)定性乾颁,一旦線程崩了涂乌,整個程序就崩掉了艺栈。所以在實際應用中大部分都是多線程的Reactor模式。

Node.js線程模型

Node.js是一個采用事件驅動和異步非阻塞I/O骂倘,實現(xiàn)的單線程眼滤、高并發(fā)的JavaScript運行環(huán)境巴席,使用它可以編寫性能良好的web服務端历涝。筆者在學習Vert.x的時候發(fā)現(xiàn)它與Node.js的線程模型很類似,它并不是嚴格意義上的Reactor模式漾唉,這里用來與單線程的Reactor模式作對比荧库,加深理解。

眾所周知赵刑,I/O操作絕大部分都十分耗時分衫,傳統(tǒng)的方法是使用多線程來解決I/O耗時阻塞的問題,多路復用也可以實現(xiàn)同時處理多個任務的功能般此,那么單線程的IO是如何處理I/O的并發(fā)請求呢蚪战?

Node.js并不是單純的單線程,它用主線程處理所有請求铐懊,然后對I/O操作進行異步處理邀桑,交給其他線程去執(zhí)行,避免了頻繁創(chuàng)建科乎、銷毀和上下文切換帶來的系統(tǒng)開銷壁畸。下面來看Node.js的工作原理。

工作原理

從左到右茅茂,從上到下捏萍,Node.js 被分為了四層,分別是 應用層空闲、V8引擎層令杈、Node API層 和 LIBUV層。

  • 應用層: 即 JavaScript 交互層碴倾,常見的就是 Node.js 的模塊逗噩,比如 http,fs
  • V8引擎層: 即利用 V8 引擎來解析JavaScript 語法影斑,進而和下層 API 交互
  • NodeAPI層: 為上層模塊提供系統(tǒng)調用给赞,一般是由 C 語言來實現(xiàn),和操作系統(tǒng)進行交互
  • LIBUV層: 是跨平臺的底層封裝矫户,實現(xiàn)了 事件循環(huán)片迅、文件操作等,是 Node.js 實現(xiàn)異步的核心

Node.js在主線程維護了一個事件隊列皆辽,接收到請求后柑蛇,就將該請求作為一個事件放入Event Queue中芥挣,然后繼續(xù)接受其他請求,當主線程空閑(沒有請求接收) 的時候耻台,就開始輪詢事件隊列空免。這里要分兩種情況:

  • 普通任務,就由主線程親自執(zhí)行盆耽,并通過回調函數(shù)返回給上層調用
  • I/O任務蹋砚,就從線程池中拿出一個線程處理這個事件,指定回調函數(shù)摄杂,繼續(xù)輪詢事件隊列中的其他事件坝咐。當線程中的I/O任務完成以后,執(zhí)行回調函數(shù)析恢,并把這個完成的事件放在事件隊列的尾部墨坚,等待事件循環(huán),當主線程再次循環(huán)到該完成事件時映挂,再返回給上層調用泽篮。

Node.js的單線程并非整個環(huán)境都運行在單線程中,而是對JavaScript層面的任務處理是單線程的柑船。

像Node.js這種解決方案:將耗時少的短任務交給主線程來處理帽撑,將I/O操作或者一些CPU密集型任務交給其他線程來執(zhí)行,這樣不會阻塞EventLoop正常進行事件的循環(huán)椎组,是比較通用的解決方案油狂。例如在Vert.x中,對于普通的verticle寸癌,會運行在EventLoop線程中专筷,對于耗時長的任務則放在Worker Pool中的線程上運行。

多線程下的Reactor模式與Node.js這種解決方案很類似蒸苇,一個線程負責鏈路的監(jiān)聽磷蛹、建立,然后將I/O交給其它子線程來完成溪烤。后文會有介紹味咳。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市檬嘀,隨后出現(xiàn)的幾起案子槽驶,更是在濱河造成了極大的恐慌,老刑警劉巖鸳兽,帶你破解...
    沈念sama閱讀 223,002評論 6 519
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件掂铐,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機全陨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,357評論 3 400
  • 文/潘曉璐 我一進店門爆班,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人辱姨,你說我怎么就攤上這事柿菩。” “怎么了雨涛?”我有些...
    開封第一講書人閱讀 169,787評論 0 365
  • 文/不壞的土叔 我叫張陵枢舶,是天一觀的道長。 經(jīng)常有香客問我镜悉,道長祟辟,這世上最難降的妖魔是什么医瘫? 我笑而不...
    開封第一講書人閱讀 60,237評論 1 300
  • 正文 為了忘掉前任侣肄,我火速辦了婚禮,結果婚禮上醇份,老公的妹妹穿的比我還像新娘稼锅。我一直安慰自己,他們只是感情好僚纷,可當我...
    茶點故事閱讀 69,237評論 6 398
  • 文/花漫 我一把揭開白布矩距。 她就那樣靜靜地躺著,像睡著了一般怖竭。 火紅的嫁衣襯著肌膚如雪锥债。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,821評論 1 314
  • 那天痊臭,我揣著相機與錄音哮肚,去河邊找鬼。 笑死广匙,一個胖子當著我的面吹牛允趟,可吹牛的內容都是我干的。 我是一名探鬼主播鸦致,決...
    沈念sama閱讀 41,236評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼潮剪,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了分唾?” 一聲冷哼從身側響起抗碰,我...
    開封第一講書人閱讀 40,196評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎绽乔,沒想到半個月后弧蝇,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,716評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,794評論 3 343
  • 正文 我和宋清朗相戀三年捍壤,在試婚紗的時候發(fā)現(xiàn)自己被綠了骤视。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,928評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡鹃觉,死狀恐怖专酗,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情盗扇,我是刑警寧澤祷肯,帶...
    沈念sama閱讀 36,583評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站疗隶,受9級特大地震影響佑笋,放射性物質發(fā)生泄漏。R本人自食惡果不足惜斑鼻,卻給世界環(huán)境...
    茶點故事閱讀 42,264評論 3 336
  • 文/蒙蒙 一蒋纬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧坚弱,春花似錦蜀备、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,755評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至些楣,卻和暖如春脂凶,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背愁茁。 一陣腳步聲響...
    開封第一講書人閱讀 33,869評論 1 274
  • 我被黑心中介騙來泰國打工蚕钦, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人埋市。 一個月前我還...
    沈念sama閱讀 49,378評論 3 379
  • 正文 我出身青樓冠桃,卻偏偏與公主長得像,于是被迫代替她去往敵國和親道宅。 傳聞我的和親對象是個殘疾皇子食听,可洞房花燭夜當晚...
    茶點故事閱讀 45,937評論 2 361

推薦閱讀更多精彩內容