設計模式 in real world - 反應器模式(Reactor Pattern)

前言

從最先看的《Head First 設計模式》到後面看的一些書,裏面對於設計模式的講解大部分都是從抽象概念介紹一個設計模式是什麼和一些例子。這些例子大多都是買咖啡(head first真的喜歡以咖啡舉例),玩具鴨子之類的。我也看過相似《Javascript設計模式與開發實踐》,裏面舉例的時候會以一些做者實際開發中碰到的例子。這個系列是我平常學習中遇到設計模式的一個總結,但願能幫助到你們。前端

文章應該會在個人學習過程當中不斷更新。react

正文

今天在研究《Node.js design patterns 2nd》的時候提到了反應器模式,我總結下本身所學和研究並寫篇博客總結一下。linux

反應器模式的介紹

反應器設計模式(Reactor pattern)是一種爲處理服務請求併發 提交到一個或者多個服務處理程序的事件設計模式。當請求抵達後,服務處理程序使用解多路分配策略,而後同步地派發這些請求至相關的請求處理程序。web

The reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers. --GoF設計模式

反正咱們不玩定義。咱們先以一個餐飲店爲例,假設每個人來就餐就是一個I/O操做,他會先看一下菜單,而後點餐。就像一個網站會有不少的請求,要求服務器作一些事情。處理這些就餐事件的就是咱們須要解決的問題了。服務器

多線程的併發解決方案

在多線程處理的方式會是這樣的:網絡

一我的來就餐,一個服務員去服務,而後客人點菜。 服務員將菜單給後廚。多線程

十我的來就餐,十個服務員去服務……併發

這個就是多線程的處理方式,一個請求到來,就會有一個線程服務。很顯然這種方式在人少的狀況下會有很好的用戶體驗,每一個客人都感受本身是VIP,專人服務的。若是餐廳一直這樣同一時間最多來10個客人,這家餐廳是能夠很好的服務下去的。異步

那麼問題來了,若是這家餐廳生意很是好,同時就餐人數(網站併發訪問量)達到100人呢,給每一個分配個服務員那餐館怕不是要破產。

儘管能夠考慮使用相似線程池的方法,組成一個10個服務員的線程池,一個服務員服務完一我的後繼續去服務下一個。 可是這樣有一個比較嚴重的缺點就是,若是某個客人點菜很慢(讀寫文件,網路請求等操做和內存讀寫比起來很是的慢),其餘人可能就要等好長時間了。

事件驅動的解決方案

其實當客人在點菜的時候,大部服務員服務的時候都在等着客人的菜上好後纔去服務下一個(阻塞),其實幹的活不是太多。若是客人須要點餐的時候直接告訴服務員,我須要宮保雞丁,作好以後直接放到14桌,而後服務員就能夠去服務下一我的了,這樣是否是可以有效利用服務員的資源?

其實這就是基於事件的解決方案,「作好以後放到14桌」其實就是回調函數。

反應器模式

先直接貼一下Douglas C. Schmidt 大佬的論文 An Object Behavioral Pattern for Demultiplexing and Dispatching Handles for Synchronous Events.pdf

Node.js中的反應器模式(Reactor pattern)

Node.js 這幾年很是火,藉助 js 天生的事件驅動機制和 V8高性能引擎,讓編寫高併發的web應用門檻下降了許多,固然這背後還要得益於基於事件驅動的 Reactor 模式,讓自己只支持單線程執行的 js 可以勝任現在高併發環境下的服務端應用。

下面這張圖就是一個應用裏面使用Reactor模式的圖示

當應用使用Reactor模式的時候發生了以下過程:

  1. 應用經過向Event Demultiplexer提交一個請求生成一個新的I/O操做。應用同時指定一個handler,這個handler會在操做完成時被調用,其實就是回調函數或者叫事件處理函數。向Event Demultiplexer提交一個請求是非阻塞(non-blocking)的調用,會當即返回。
  2. 當一系列I/O操做完成後,Event Demultiplexer會把對應觸發的event的項推動Event Queue
  3. 與此同時,Event Loop會遍歷全部Event Queue裏面的每一項。
  4. 對於每一個事件event,相應的處理程序handler會被執行。
  5. 當處理程序handler執行完後會把控制流交還給Event Loop(5a),然而有可能處理程序中會產生新的異步操做(5b),致使在控制流回到Event Loop以前會向Event Demultiplexer中插入新的項。
  6. Event Queue中的全部項都執行完後,這個循環會在Event Demultiplexer中被關閉,當再次有新事件被加入Event Queue時再觸發另外一個循環。

前端的同窗對於Event Loop應該比較熟吧。

如今再來從新看一下定義是否是清晰了一點?

反應器設計模式(Reactor pattern)是一種爲處理服務請求併發 提交到一個或者多個服務處理程序的事件設計模式。當請求抵達後,服務處理程序使用解多路分配策略,而後同步地派發這些請求至相關的請求處理程序。

隨便扯扯

其實Event Demultiplexer以前我就有過一些瞭解不過沒有深刻,當時是在作計算機網絡大做業的時候,當時選題是作一個Web Server,相似Apache、Nginx那種。當時研究高併發模型的時候接觸到了I/O多路複用(multiplexing),其實就是事件驅動,當時用的libevent的庫,好像是基於的linux的epoll系統調用實現的。

相關文章
相關標籤/搜索