Vert.x架構學習之Reactor模式
前言
學習Vert.x之前,我們首先需要了解一下幾個概念,Reactor設計模式就是其中一個。
一、Reactor模式簡介
我們知道對於應用伺服器,通常會涉及到對檔案系統、資料庫系統或者網路進行IO操作,由於cpu的執行速度遠大於IO的速度,所以會發生這種情況:CPU可能會因為IO的操作而阻塞。我們當然不希望這種情況的發生,因為這大大降低了CPU的效率,因此,引進了多現程或多程序進行處理,即多個執行緒繫結多個IO事件,這樣雖然可以提高CPU的效率,但仍然存在程序切換帶來的弊端。
於是便引入了Reactor模式,首先,它是基於事件驅動,應用服務首先向一箇中間人註冊一個回撥(event handler)進行註冊,然後中間人輪詢在其上註冊過的服務,當有IO就緒時,中間人產生一個事件,並通知繫結的handler進行處理,這種回撥體現了"好萊塢原則"(“Don’t call us, we’ll call you”),在IOC(控制反轉)原則中也有相似的體現。這個中間人就是Reactor。
通俗的來說,在Reactor模式中,應用程式不是主動的呼叫某個API完成處理,而是逆置了事件處理流程,應用程式需要提供相應的事件介面並註冊到Reactor上,如果相應的事件發生,Reactor將主動呼叫應用程式註冊的介面,通過註冊的介面完成具體的事件處理。
二、.模式組成及處理流程
1、模式組成
Reactor模式由事件源、事件反應器、事件分離器、事件處理器等元件組成。
-
事件源(handle):由作業系統提供,用於識別每一個事件,如Socket描述符、檔案描述符等。在服務端系統中用一個整數表示。該事件可能來自外部,如來自客戶端的連線請求、資料等。也可能來自內部,如定時器事件。
-
事件反應器(reactor):定義和應用程式控制事件排程,以及應用程式註冊、刪除事件處理器和相關描述符相關的介面。它是事件處理器的排程核心,使用事件分離器來等待事件的發生。一旦事件發生,反應器先是分離每個事件,然後排程具體事件的事件處理器中的回撥函式處理事件。
-
事件分離器(demultiplexer):是一個有作業系統提供的I/O複用函式,在此我們選用epoll。用來等待一個或多個事件的發生。呼叫者將會被阻塞,直到分離器分離的描述符集上有事件發生。
-
事件處理器(even handler):事件處理程式提供了一組介面,每個介面對應了一種型別的事件,供reactor在相應的事件發生時呼叫,執行相應的事件處理。一般每個具體的事件處理器總是會繫結一個有效的描述符控制代碼,用來識別事件和服務。
2、處理流程
處理流程主要分為兩個部分,事件註冊部分和事件分發部分 ;
下面具體看一下Reactor結構圖
在事件註冊部分,應用程式首先將期待註冊的套接字描述符作為事件源,並將描述符和該事件對應的事件處理回撥函式封裝到具體的事件處理器中,並將該事件處理器註冊到事件反應器(Initialization Dispatcher)中。事件反應器接收到事件後,進行相應處理,並將註冊資訊再次註冊到事件分離器epoll中。最後在epoll分離器中,通過epoll_ctl進行新增描述符及其事件,並層層返回註冊結果。
在事件處理部分,首先事件反應器通過呼叫事件分離器的epoll_wait,使執行緒阻塞等待註冊事件發生。此時如果某註冊事件發生,epoll_wait將會返回,並將包含該註冊事件在內的事件集返回給事件反應器。反應器接收到該事件後,根據該事件源找到該事件的事件處理器,並判斷事件型別,根據事件型別在該事件處理器呼叫之前註冊時封裝的具體回撥函式,在這個具體回撥函式中完成事件處理。