作者:Mark·Richards
簡介
架構模式幫助你定義應用程式的基本特征和行為,例如,一些架構模式會讓程式自己自然而然地朝著具有良好伸縮性的方向發展,而其他架構模式會讓程式朝著高度靈活的方向發展,知道了這些特點,了解架構模式的優點和缺點是非常必要的,它必須我們選擇一個適合自己特定的業務需求和目標的程式,
第一章 分層架構
1.1 模式分析
大多數的結果都分成四個層次:展示層、業務層、持久層和資料庫層,
分層架構中的每一層都著特定的角色和職能,舉個例子,展示層負責處理所有的界面展示以及互動邏輯,業務層負責處理請求對應的業務,架構里的層次是具體作業的高度抽象,它們都是為了實作某種特定的業務請求,比如說展示層并不需要關心怎樣得到用戶資料,它只需在螢屏上以特定的格式展示資訊,業務層并不關心要展示在螢屏上的用戶資料格式,也不關心這些用戶資料從哪里來,它只需要從持久層得到資料,執行與資料有關的相應業務邏輯,然后把這些資訊傳遞給展示層,

分層架構的一個突出特性是組件間關注點分離(separation of concerns),一個層中的組件只會處理本層的邏輯,比如說,展示層的組件只會處理展示邏輯,業務層中的組件只會去處理業務邏輯,多虧了組件分離,讓我們更容易構造有效的角色和強力的模型,這樣應用變的更好開發,測驗,管理和維護,
1.2 關鍵概念
層隔離:每一層都是封閉的,
污水池反模式(architecture sinkhole anti-pattern) :請求流簡單的穿過幾個層,每層里面基本沒有做任何業務邏輯,或者做了很少的業務邏輯,
每個分層架構或多或少都可能遇到這種場景,關鍵在于這樣的請求有多少,8-2原則可以幫助你確定架構是否處于反污水模式,大概有20%的請求僅僅是做簡單的穿越,80%的請求會做一些業務邏輯操作,然而,如果這個比例反過來,大部分的請求都是僅僅穿過層,不做邏輯操作,那么開放一些架構層會比較好,不過由于缺少了層次隔離,專案會變得難以控制,
1.3 模式分析
| 評級 | 分析 | |
|---|---|---|
| 整體靈活性 | 低 | 總體靈活性是回應環境變化的能力,盡管分層模式中的變化可以隔絕起來,想在這種架構中做一些也改變也是并且費時費力的,分層模式的笨重以及經常出現的組件之間的緊耦合是導致靈活性降低的原因 |
| 易于部署 | 低 | 這取決于你怎么發布這種模式,發布程式可能比較麻煩,尤其是很大的專案,一個組件的小小改動可能會影響到整個程式的發布(或者程式的大部分),發布必須是按照計劃,在非作業時間或者周末進行發布,因此,分層模式導致應用發布一點也不流暢,在發布上降低了靈活性, |
| 可測驗性 | 高 | 因為組件都處于各自的層次中,可以模擬其他的層,或者說直接去掉層,所以分層模式很容易測驗,開發者可以單獨模擬一個展示組件,對業務組件進行隔絕測驗,還可以模擬業務層來測驗某個展示功能, |
| 性能 | 低 | 盡管某些分層架構的性能表現的確不錯,但是這個模式的特點導致它無法帶來高性能,因為一次業務請求要穿越所有的架構層,做了很多不必要的作業, |
| 伸縮性 | 低 | 由于這種模式以緊密耦合的趨勢在發展,規模也比較大,用分層架構構建的程式都比較難以擴展,你可以把各個層分成單獨的物理模塊或者干脆把整個程式分成多個節點來擴展分層架構,但是總體的關系過于緊密,這樣很難擴展, |
| 易開發性 | 容易 | 在開發難度上面,分層架構得到了比較高的分數,因為這種架構對大家來說很熟悉,不難實作, |
康威定律(Conways Law)_ryanlll3的博客-CSDN博客
第二章 事件驅動架構
事件驅動架構模式是一種主流的異步分發事件架構模式,常用于設計高度可擴展的應用,當然了,它有很高的適應性,使得它在小型應用、大型應用、復雜應用中都能表現得很好,事件驅動架構模式由高度解耦、單一目的的事件處理組件構成,這種組件負責異步接收和處理事件,
事件驅動架構模式包含了兩種主要的拓撲結構:中介(mediator)拓撲結構和代理(broker)拓撲結構,
mediator拓撲結構通常在你需要在事件內使用一個核心中介分配、協調多個步驟間的關系、執行順序時使用;而代理拓撲結構則在你想要不通過一個核心中介將多個事件串聯在一起時使用,由于這兩種在結構特征和實作策略上有很大的差別,所以如果你想要在你的應用中使用它們的話,一定要深入理解兩者的技術實作細節,從而為你的實際使用場景選擇最合理的結構,
2.1 譯者注
假如現在我有一個事件/事件流需要被處理,那么使用mediator、broker、proxy處理事件的區別在哪里呢?
- 如果我們使用mediator,那就意味著我把事件流交給mediator,mediator會幫我把時間分解為多個步驟,并分析其中的執行邏輯,調整和分發事件(例如判斷哪些事件可以并行,哪些事件可以串行),然后根據mediator分解、調節的結果去執行事件中的每一個步驟,把所有步驟完成后,就能把需要處理的事件處理好,
- 如果我們使用broker,那就意味著我把時間交給broker,broker獲得事件后會把事件發出去(在本文中為:通知架構中所有可用的事件處理器),事件處理器接收到事件以后,判斷處理這個事件是否為自己的職責之一,如果不是則無視,與自己有關則把需要完成的作業完成,完成后如果事件還有后序需要處理的事件,則通過broker再次發布,再由相關的事件處理器接收、處理,以這樣的方式將事件不斷分解,沿著事件鏈一級一級地向下處理子事件,直到事件鏈中的所有時間被完成,我的事件也就處理好了,(訊息中間件 發布/訂閱)
- 如果我們使用proxy,那就意味著我自己對需要處理的事件進行了分解,然后把不同的子事件--一一委托給不同的proxy,由被委托的proxy幫我完成子事件,從而完成我要做的事件,
2.2 中介(mediator)拓撲結構
中介拓撲結構適合用于擁有多個步驟,并需要在處理事件時能通過某種程度的協調將事件分層的場景,舉例來說吧:假設你現在需要進行股票交易,那你首先需要證券所批準你進行交易,然后檢查進行這次交易是否違反了股票交易的某種規定,檢查完成后將它交給一個經紀人,計算傭金,最后與經紀人確認交易,以上所有步驟都需要通過中介進行某種程度的分配和協調,以決定各個步驟的執行順序,判斷哪些步驟可以并行,哪些步驟可以串行,
在中介拓撲結構中主要由四種組件:事件佇列(event queue),事件中介,事件通道(event channel),和事件處理器(event processor),當事件流需要被處理,客戶端將一個事件發送到某個事件佇列中,由訊息佇列將其運輸給事件中介進行處理和分發,事件中介接收到該訊息后,并通過將額外的異步事件發送給事件通道,讓事件通道執行該異步事件中的每一個步驟,使得事件中介能夠對事件進行分配、協調,同時,又因為事件處理器是事件通道的監聽器,所以事件通道對異步事件的處理會觸發事件處理器的監聽事件,使事件處理器能夠接收來自事件中介的事件,執行事件中具體的業務邏輯,從而完成對傳入事件的處理,事件驅動架構模式中的中介拓撲模式結構大體如下圖:

在事件驅動架構中擁有十幾個,甚至幾百個事件佇列是很常見的情況,該模式并沒有對事件佇列的實作有明確的要求,這就意味著事件佇列可以是訊息佇列,web服務端,或者其他類似的東西,
在事件驅動架構模式中主要有兩種事件:初始事件和待處理事件,初始事件是中介所接收到的最原始的事件,沒有經過其他組件的處理;而待處理事件是由事件中介生成,由事件處理器接收的組件,不能把待處理事件看作初始事件經過處理后得到的事件,兩者是完全不同的概念,
事件中介負責分配、協調初始事件中的各個待執行步驟,事件中介需要為每一個初始事件中的步驟發送一個特定的待處理事件到事件通道中,觸發事件處理器接收和處理該待處理事件,這里需要注意的是:事件中介沒有真正參與到對初始事件必須處理的業務邏輯的實作之中;相反,事件中介只是知道初始事件中有哪些步驟需要被處理,
事件中介通過事件通道將與初始事件每一個執行步驟相關聯的特定待處理事件傳遞給事件處理器,盡管我們通常在待處理事件能被多個事件處理器處理時才會在中介拓撲結構中使用訊息主題,但事件通道仍可以是訊息佇列或訊息主題,(但需要注意的是,盡管在使用訊息主題時待處理事件能被多個事件處理器處理,但由于接收到的待處理事件各異,所以對其處理的操作也各不相同)
為了能順利處理待處理事件,事件處理器組件中包含了應用的業務邏輯,此外,事件處理器作為事件驅動架構中的組件,不依賴于其他組件,獨立運作,高度解耦,在應用或系統中完成特定的任務,當事件處理器需要處理的事件從細粒度(例如:計算訂單的營業稅)變為粗粒度(例如:處理一項保險索賠事務),必須要注意的是:一般來說,每一個事件處理器組件都只完成一項唯一的業務作業,并且事件處理器在完成其特定的業務作業時不能依賴其他事件處理器,
雖然事件中介有很多方法可以實作,但作為一名架構工程師,你應該了解所有實作方式,以確保你能為你的實際需求選擇了最合適的事件中介,
事件中介最簡單、常見的實作就是使用開源框架,例如:spring integration,apache camel,或 mule esb,事件流在這些開源框架中通常用Java或域特定語言(dsl),在調節程序和業務流程都很復雜的使用場景下,你可以使用業務流程執行語言(bpel)結合類似開源框架 apache ode 的 bpel 引擎進行開發,bpel是一種基于xml的服務編制編程語言,它為處理初始事件時需要描述的資料和步驟提供了描述,對每一個擁有復雜業務流程(包括與用戶互動的執行步驟)的大型應用來說,你可以使用類似jbpm的業務處理管理系統(bpm)實作事件中介,
如果你需要使用中介拓撲結構,那么理解你的需求,并為其匹配恰當的事件中介實作是構建事件驅動架構程序中至關重要的一環,使用開源框架去解決非常復雜的業務處理、管理、調節事件,注定會失敗,因為開源框架只是用bpm的方式解決了一些簡單的事件分發邏輯,比起你的業務邏輯,其中的事件分發邏輯簡直是九牛一毛,
為了解釋清楚中介拓撲結構是怎么運作的,我假設你在某家保險公司買了保險,成為了受保人,然后你打算搬家,在這種情況下,初始事件就是重定位事件,或者其他類似的事件,與重定位事件相關的處理步驟就像下圖展示的那樣,處理事件中介之中,對每一個初始事件的傳人,事件中介都會創建一個待處理事件(例如:改變地址,重新計算保險報價,等等....),并將它發送給事件通道,等待發出回應的事件處理器處理待處理事件(例如:客戶改變地址的操作流程、報價計算流程,等等....),直到初始事件中的每一個需要處理的步驟完成了,這項處理才會繼續(例如:把所有手續都完成之后,保險公司才會幫你改變地址),事件中介中,重新報價和更新理賠步驟上面的直線表示這些步驟可以并行處理,

2.3 代理(broker)拓撲結構
代理拓撲結構與中介拓撲結果不同之處在于:代理拓撲結構中沒有核心的事件中介;相反,事件流在代理拓撲中通過一個輕量的訊息代理(例如:activeMQ,rabbitMQ等等....)將訊息串聯成鏈狀,分發至事件處理器組件中進行處理,代理拓撲結構使用場景大致上具有以下特征:你的事件處理流相對來說比較簡單,而且你不想(不需要)使用核心的事件分配、調節機制以提高你處理事件的效率,
在代理拓撲結構中主要兩種組件:代理和事件處理器,代理可被集中或相互關聯在一起使用,此外,代理中還可以包含所有事件流中使用的事件通道,
存在于代理組件中的事件通道可以使訊息佇列,訊息主題,或者是兩者的組合,
代理拓撲結構大致如下圖,如你所見,在這其中沒有一個核心的事件中介組件控制和分發初始事件;相反,每一個事件處理器只負責處理一個事件,并向外發送一個事件,以標明其剛剛執行的動作,例如,假設存在一個事件處理器用于平衡證券交易,那么事件處理器可能會接受一個拆分股票的初始事件,為了處理這項初始事件,事件處理器則需要重新平衡股票的投資金額,而這個重新平衡的事件將由另一個事件處理器接收、處理,在這其中有一個細節需要注意:處理初始事件后,由事件處理器發出的事件不被其他事件處理器接收、處理的情況時常會發生,尤其是你在為應用添加功能和進行功能拓展時,這種情況更為常見,

為了闡明代理拓撲結構的運行機制,我會用一個與講解中介拓撲結構時類似的例子(受報人旅行的例子)進行解釋,因為在代理拓撲結構中沒有核心事件中介接收初始事件,那么事件將由客戶處理組件直接接收,改變客戶的地址,并發出一個事件告知系統客戶的地址被其進行了改變(例如:改變地址的事件),在這個例子中:有兩個事件處理器會與改變地址的事件產生關聯:報價處理和索賠處理,報價事件處理器將根據受保人的新地址重新計算保險的金額,并發出事件告知系統該受保人的保險金額被其改變,而索賠事件處理器將接受到相同的改變地址事件,不同的是,它將更新保險的賠償金額,并發出一個更新索賠金額事件告知系統該受保人的賠償金額被其改變,當這些新的事件被其他事件處理器接收、處理,使事件鏈一環扣一環地交由系統處理,直到事件鏈上的所有事件都被處理完,初始事件的處理才算完成,

如上圖所示,代理拓撲結構的設計思想就是將對事件流的處理轉換為對事件鏈的業務功能處理,把代理拓撲結構看作是接力比賽是最好的理解方式:在一場4*100的接力比賽中,每一位運動員都需要拿著一根接力棒跑100米,運動員跑完自己的100米后需要將接力棒傳遞給下一位運動員,直到最后一位運動員拿到接力棒跑過終點線,整場接力比賽才算結束,根據這樣的邏輯我們還可以知道:在代理拓撲結構中,一旦某個事件處理器將事件傳遞給另一個事件處理器,那么這個事件處理器不會與該事件的后續處理產生任何聯系,
2.4 顧慮
實作事件驅動架構模式相對于實作其他架構模式會更困難一些,因為它通過異步處理進行事件分發,當你需要在你的應用中使用這種架構模式,你必須處理各種由事件分發處理帶來的問題,例如:遠程操作功能的可用性,缺少權限,以及在代理或中介中處理事件失敗時,用于處理這種情況的重連邏輯,如果你不能很好地解決這些問題,那你的應用一定會出現各種Bug,讓開發團隊痛苦不已,
在選擇事件驅動架構時還有一點需要注意:在處理單個業務邏輯時,這種架構模式不能處理細粒度的事務,因為事件處理器都高度解耦、并且廣泛分布,這使得在這些處理處理器中維持一個業務單元變得非常困難,因此,當你使用這種架構模式架構你的應用時,你必須不斷地考慮哪些事件能單獨被處理,哪些不能,并為此設計相應事件處理器的處理粒度,如果你發現你需要將一個業務單元切割成許多子單元,并一一匹配相應的事件處理器,那你就要為此進行代碼設計烈如歌你發現你用多個不同的事件處理器處理的哪些業務其實是可以合并到一個業務事件之中的,那么這種模式可能并不適合你的應用,又或者是你的設計出了問題,
使用事件驅動架構模式最困難的地方就在于架構的創建、維護、以及對事件處理器的管理,通常每一個事件都擁有其指定的事件處理協議(例如:傳遞給事件處理器的資料型別、資料格式),這就使得設下標準的資料格式成為使用事件驅動架構模式中至關重要的一環(例如:XML,JSON,Java物件等等....),并在架構創建之初就為這些資料格式授權,以便處理,
2.5 模式分析
| 評價 | 分析 | |
|---|---|---|
| 整體靈活性 | 高 | 整體靈活性用于評價架構能否在不斷改變的使用場景下快速回應,因為事件處理器組件使用目的單一、高度解耦、與其他事件處理器組件相互獨立,不相關聯,那么發生的改變對一個或多個事件處理器來說普遍都是獨立的,使得對改變的反饋非常迅速,不需要依賴其他事件處理器的回應做出處理 |
| 易于部署 | 高 | 總的來看,事件驅動架構模式由于其高度解耦的事件處理器組件的存在,對事件的部署相對來說比較容易,而使用代理拓撲結構比使用中介拓撲結果進行事件調度會更容易一些,主要是因為在中介拓撲結構中事件處理器與事件中介緊密地耦合在一起;事件處理器發生改變后,事件中介也隨之改變,如果我們需要改變某個被處理的事件,那么我們需要同時調度時間處理器和事件中介 |
| 可測驗性 | 低 | 雖然在事件驅動架構模式中進行單元測驗并不困難,但如果我們要進行單元測驗,我們就需要某種特定的測驗客戶端或者是測驗工具產生事件,為單元測驗提供初始值,此外,由于事件驅動架構模式是異步進行事件分發的,其異步處理的特性也為單元測驗帶來了一定的困難 |
| 性能 | 高 | 對訊息傳遞的架構可能會讓設計出來的事件驅動架構的表現不入我們的期望,但通常來說,該模式都能通過其異步處理的特性展示優秀的性能表現;換句話來說,高度解耦,異步并行操作大大減少了傳遞訊息程序中帶來的時間開銷 |
| 伸縮性 | 高 | 事件驅動架構中的高度解耦、相互獨立的事件處理器組件的存在,使得可拓展性成為該架構與生俱來的優點,架構的這些特定使得事件處理器能夠進行細粒度的拓展,使得每一個事件處理器都能單獨被拓展,而不影響其他事件處理器 |
| 易于開發 | 低 | 由于使用事件驅動架構進行開發需要考慮其異步處理機制、協議創建流程,并且開發者需要用代碼為事件處理器和操作失敗的代理提供優秀的錯誤控制環境,無疑使得用事件驅動架構進行開發會比使用其他架構進行開發要困難一些 |
第三章 微內核架構
微內核架構模式(也稱為插件化應用架構)對于基于產品的應用程式來說是一個很自然的選擇,基于產品的應用是指一個經過打包的、可以通過版本下載的一個典型的第三方產品,然而,很多公司也會開發和發布他們的內部商業軟體,完整的版本號、發布日志和可插拔的新特性,這些就非常符合微內核架構的思想,微內核架構模式可以通過插件的形式添加額外的的特性到核心系統中,這提供了很好的擴展性,也使得新特性與核心系統隔離開來,(比如eclipse和插件市場)
3.1 模式描述
微內核架構主要需要考慮兩個方面:核心系統和插件模塊,應用邏輯被劃分為獨立的插件模塊和核心系統,這樣就提供良好的可擴展性、靈活性,應用的新特性和自定義處理邏輯也會被隔離,圖3-1演示了基本的微內核架構,
微內核架構的核心系統一般情況下只包含一個能夠使系統運作起來的最小化模塊,很多作業系統的實作就是使用微內核架構,因此這也是該架構名字的由來,從商業應用的角度看,核心系統通常是為特定的使用場景、規則、或者復雜條件處理定義了通用的業務邏輯,而插件模塊根據這些規則實作了具體的業務邏輯,

插件模塊是一個包含專業處理、額外特性的獨立組件,自定義代碼意味著增加或者擴展核心系統以達到產生附加的業務邏輯的能力,通常,插件模塊之間應該是沒有任何依賴性的,但是你也可以設計一個需要依賴另一個插件的插件,但無論如何,使得插件之間可以通信的同時避免插件之間產生依賴又是一個特別重要的問題,
核心系統需要了解插件模塊的可用性以及如何獲取到它們,一個通用的實作方法是通過一組插件注冊表,這個插件注冊表含有每個插件模塊的資訊,包括它的名字、資料規約和遠程訪問協議(拒絕與插件如何與核心系統建立連接),例如,一個稅務軟體的用于標識高風險的稅務審計插件可能會有一個含有插件名(比如AuditChecker)的注冊入口,資料規約(輸入資料、輸出資料)和規約格式(比如xml),如果這個插件是通過SOAP服務訪問,那么它可能會包含一個WSDL,
插件模塊可以通過多種方式連接到核心系統,包括OSGI、訊息機制、web服務或者直接點對點的系結(比如物件實體化,即依賴注入),你使用的連接型別取決于你構建的應用型別和你的特殊需求(比如單機部署還是分布式部署),微內核架構本身沒有指定任何的實作方式,唯一的規定就是插件模塊之間不要產生依賴,
插件和核心系統的通信規范包含標準規范和自定義規范,自定義規范典型的使用場景是插件組件是被第三方構建的,在這種情況下,通常是在第三方插件規約和你的標準規范創建一個Adapter來使核心系統根本不需要知道每個插件的具體細節,當創建標準規范(通常是通過XML或者Java Map)時,從一開始就創建一個版本策略是非常重要的,
3.2 架構示例
eclipse IDE/Steam 創意工坊,一旦你開始添加插件,它就變成一個高度可定制化和非常有用的產品(前言(卷一) · 開源軟體架構 · 看云 (kancloud.cn)),瀏覽器是另一個使用微內核架構的產品示例,它由一個查看器和其它擴展的插件組成,
基于微內核架構的示例數不勝數,但是大型的商業應用呢?微內核應用架構也適用于這些情形,為了闡述這個觀點,讓我們來看看另一個保險公司的示例,但是這次的示例會設計保險賠償處理,
賠償處理是一個非常復雜的程序,每個州都有不同的關于保險賠償的規則和條文,例如一些州允許在你的擋風玻璃被石頭砸碎時免費進行替換,但是一些州則不是這樣,因為大家的標準都不一樣,因此賠償標準幾乎可以是無限的(還有可能變化(修改 新增 洗掉,舊的如何處理,應該有個執行時間),中央政府層面的調整,州政府也需跟著調整)
有很多保險賠償應用運用大型和復雜的規則處理引擎來處理不同規則帶來的復雜性,然而,可能是因為某條規則的改變而引起其他規則的改變而使得這些規則處理引擎變成一個大泥球,或者使簡單需求變更會需要一個很大的分析師、工程師、測驗工程師來進行處理,使用微內核架構能夠很好地解決這個問題,核心系統只知道根據配菜規則處理,但這個賠償規則是抽象的,系統將賠償規則作為一個插件規范,具體的規則有對應的實作,然而注入到系統中即可,
圖3-2中的一堆檔案夾代表了配菜處理核心系統,它包含一些處理保險配菜的基本業務邏輯,每一個插件模塊包含每個州的具體賠償規則,在這個例子中,插件模塊通過自定義源代碼實作或者分離規則引起實體,不管具體實作如何,實作就在于賠償規則和處理都從核心系統中分離,而這些規則和處理程序都可以被動態地添加、移除,而這些改變對于核心系統和其他插件只有很少的影響或者根本不產生影響,

3.3 注意事項
對于微內核架構來說一個很重要的一點就是它能夠被嵌入或者說作為另一種架構的一部分,例如,如果這個架構解決的是一個你應用中易變領域的特定的問題(譯者注:即插件化能夠解決你應用中的某個特定模塊的架構問題),你可能會發現你不能在整個應用中使用這個架構,在這種情況下,你可以將微內核架構嵌入到另一個架構模式中(比如分層架構),同樣地,在上一章節中描述的事件驅動架構中的事件處理器組件也可以使用微內核架構,
微內核架構對漸進式設計和增量開發提供了非常好的支持,你可以先構建一個單純的核心系統,隨著應用的演進,系統會逐漸添加越來越多的特性和功能,而這并不會引起核心系統的重大變化,
對基于產品的應用來說,微內核架構應該是你的第一選擇,特別是那些你會在后序開發中發布附加特性和控制哪些用戶能夠獲取哪些特性的應用,如果你在后序開發中發現這個架構不能滿足你的需求了,你能夠根據你的特殊需求將你的應用重構為另一個更好的架構,
3.4 模式分析
| 評價 | 分析 | |
|---|---|---|
| 整體靈活性 | 高 | 通過插件模塊的松耦合實作,可以將變化隔離起來,并且快速滿足需求,通常,微內核架構的核心系統很快趨于穩定,這樣系統就變得很健壯,隨著時間的推移它也不會發生多大改變 |
| 易于部署 | 高 | 根據實作方式,插件模塊能夠在運行時被動態地添加到核心系統中(比如:熱部署),把停機事件減到最小 |
| 可測驗性 | 高 | 插件模塊能夠被獨立的測驗,能夠非常簡單地被核心系統模擬出來進行演示,或者在對核心系統很小影響甚至沒有影響的情況下對一個特定的特性進行原型展示 |
| 性能 | 高 | 使用微內核架構不會自然而然地使你的應用變得高性能,通常,很多使用微內核架構的應用運行得很好,因為你能定制和簡化應用程式,使它只包含那些你需要的功能模塊,JBoss應用服務器就是這方面的優秀示例:依賴它的插件化架構,你可以只加載你需要的功能模塊,移除那些消耗資源但沒有使用的功能特性,比如遠程訪問,訊息傳遞,消耗記憶體、CPU的快取,以及執行緒,從而減小應用服務器的資源消耗, |
| 伸縮性 | 低 | 因為微內核架構的實作是基于產品的,它通常都比較小,它們以獨立單元的形式實作,因此沒有太高的伸縮性,此時,伸縮性就取決于你的插件模塊,有時你可以在插件級別上提供可伸縮性,但是總的來說這個架構并不是以構建高度伸縮性的應用而著稱的, |
| 易于開發 | 低 | 微內核架構需要考慮設計和規約管理,使它不會很難實作,規約的版本控制,內部的插件注冊, 插件粒度,豐富的插件連接的方式等是涉及到這個架構模式實作復雜度的重要因素, |
第四章 微服務架構
4.1 模式描述
服務組件(service component),不要考慮微服務架構內部的服務,而最好是考慮服務組件,從粒度上講它可以小到單一的模塊,或者大至一個應用程式,服務組件包含一個或多個模塊(如Java類),這些模塊可以提供一個單一功能(如,為特定的城市或城鎮提供天氣情況),或也可以作為一個大型商業應用的一個獨立部分(如,股票交易布局或測定汽車保險的費率),在微服務架構中,正確設計服務組件的粒度是一個很大的挑戰,在接下來的服務組件部分對這一挑戰進行了詳細的討論,

微服務架構模式的另一個關鍵概念是它是一個分布式的架構,這意味著架構內部的所有組件之間是完全解耦的,并通過某種遠程訪問協議(如,JMS,AMQP,REST,SOAP,RMI等)進行訪問,這種架構的分布式特性是它實作一些優越的可擴展性和部署特性的關鍵所在,
微服務架構另一個令人興奮的特性是它是由其他常見架構模式存在的問題演化來的,而不是作為一個解決方案被創造出來等待問題出現,微服務架構的演化有兩個主要來源:使用分層架構模式的單體應用和使用面向服務架構的分布式應用,
由單體應用(一個應用就是一個整體)到微服務的發展程序主要是由持續交付開發促成的,從開發到生產的持續部署管道概念,簡化了應用程式的部署,單體應用通常是由緊耦合的組件組成,這些組件同時又是另一個單一可部署單元的一部分,這使得它繁瑣,難以改變、測驗和部署應用(因此常見的"月度部署"周期出現并通常發生在大型IT商店專案),這些因素通常會導致應用變得脆弱以至于每次有一點新功能部署后應用就不能運行,微服務架構模式通過將應用分隔成多個可部署的單元(服務組件)的方法來解決這一問題,這些服務組件可以獨立于其他服務組件進行單獨開發、測驗和部署,
另一個導致微服務架構模式產生的演化程序是由面向服務架構模式(SOA)應用程式存在的問題引起的,雖然SOA模式非常強大,提供了無與倫比的抽象級別、異構連接、服務編排,并保證通過IT能力調整業務目標,但它仍然是復雜的,昂貴的,普遍存在,它很難理解和實作,對大多數應用程式來說過猶不及,微服務架構通過簡化服務概念,消除編排需求、簡化服務組件連接和訪問來解決復雜問題,
4.2 模式拓撲
雖然有很多方法來實作微服務架構模式,但三個主要的拓撲結構脫穎而出,最常見和流行的有:基于REST API的拓撲結構,基于REST的應用拓撲結構和集中式訊息拓撲結構,
1)基于REST的應用拓撲結構
基于REST的API拓撲適用于網站,通過某些API對外提供小型的、自包含的服務,這些拓撲結構,如圖4-2所示,由粒度很細的服務組件組成,這些服務組件包含一個或多個模塊并獨立于其他服務來執行特定業務功能,在這種拓撲結構中,這些細粒度的服務組件通常被 REST-based 的介面訪問,而這個介面是通過一個單獨部署的web API層實作的,此種拓撲的例子包含一些常見的專用的、基于云的 RESTful web service,

基于REST的應用拓撲結果與基于REST API的不同,它通過傳統的基于web的或胖客戶端業務應用來接收客戶端請求,而不是通過一個簡單的API層,如圖4-3所示,應用的用戶介面層(user interface layer)一個web應用,可以通過簡單的REST-based介面訪問單獨部署的服務組件(業務功能),該拓撲結構中的服務組件與API-REST-based拓撲結構中的不同,這些服務組件往往會更大、粒度更粗、代表整個業務應用程式的一小部分,而不是細粒度的、單一操作的服務,這種拓撲結構常見于中小型企業等復雜程度相對較低的應用程式,

2)集中式訊息拓撲結構
使用輕量級的集中式訊息代理,該拓撲中的輕量級訊息代理不執行任何編排,轉換,或復雜的路由;相反,它只是一個輕量級訪問服務組建的傳輸工具,
集中式訊息拓撲結果通常應用在較大的業務應用程式中,或對于某項對傳輸層到用戶介面層或者到服務組件層有較復雜的邏輯控制的應用程式中,該拓撲較之先前討論的簡單基于REST的拓撲結構,其好處是有先進的排隊機制、異步訊息傳遞、監控、錯誤處理和更好的負載均衡和可擴展性,與集中式代理相關的單點故障和架構瓶頸問題已通過代理集群和代理聯盟(將一個代理實體為分多個代理實體,把基于系統功能區域的吞吐量負載劃分分開處理)解決,

4.3 避免依賴和編排
微服務架構模式的主要挑戰之一就是決定服務組建的粒度級別,
如果你發現需要從應用內部的用戶介面或API層編排服務組件,那么很有可能你服務組件的粒度太細了,如果你發現你需要在服務組件之間執行服務間通信來處理這個單個請求,那么很有可能要么是你服務組件的粒度太細了,要么是沒有從業務功能角度正確劃分服務組件,
服務間通信,可能導致組件之間產生耦合,但可以通過共享資料庫進行處理,例如,若一個服務組件處理網路訂單而需要用戶資訊時,它可以去資料庫檢索必要的資料,而不是呼叫客戶服務組件的功能,
共享資料庫可以處理資訊需求,但是共享功能呢?如果一個服務組件需要的功能包含在另一個服務組件內,或是一個公共的功能,那么有時你可以將服務組建的共享功能復制一份(違反DRY),為了保持服務組件獨立和部署分離,微服務架構模式實作中會存在一小部分由重復的業務邏輯而造成的冗余,這在大多數業務應用程式中是一個相當常見的問題,
如果你發現就算不考慮服務組件粒度的級別,你仍不能避免服務組件編排,這是一個好跡象,可能此架構模式不適用于你的應用,由于這種模式的分布式特性,很難維護服務組件之間的單一作業事務單元,這種做法需要某種事務補償框架回滾事務,這對此相對簡單而優雅的架構模式來說,顯著增加了復雜性,
4.4 注意事項
微服務架構模式解決了很多單體應用和面向服務架構應用存在的問題,由于主要應用組件被分成更小的,單獨部署單元,使用微服務架構模式構建的應用程式通常更健壯,并提供更好的可擴展性,支持持續交付也更容易,
該模式的另一個優點是,它提供了實時生產部署能力,從而大大減少了傳統的月度或周末“大爆炸”生產部署的需求,因為變化通常被隔離成特定的服務組件,只有變化的服務組件才需要部署,
最后一個要重視的考慮是,由于微服務架構模式是分布式的架構,他與事件驅動架構模式具有一些共同的復雜的問題,包括約定的創建、維護和管理,遠程系統的可用性,遠程訪問身份驗證的授權,
4.5 模式分析
| 評價 | 分析 | |
|---|---|---|
| 整體靈活性 | 高 | 由于單獨部署單元的概念,變化通常被隔離成單獨的服務組件,使得部署變得快而簡單,同時,使用這種模式構建的應用往往是松耦合,也有助于促進改變 |
| 易于部署 | 高 | 整體來講,由于該模式的解耦特性和事件處理組件使得部署變得相對簡單,broker拓撲往往比mediator拓撲更易于部署,主要是因為event-mediator組件與事件處理器是緊耦合,事件處理器組件有一個變化可能導致event mediator跟著變化,有任何變化兩者都需要部署 |
| 可測驗性 | 高 | 可以在區域范圍內進行測驗 |
| 性能 | 低 | 雖然你可以從實作該模式來創建應用程式并可以很好的允許,整體來說,由于微服務架構模式的分布式特性,并不適用于高性能的應用程式 |
| 伸縮性 | 高 | 每個服務組件可以單獨擴展,并允許對應用程式進行擴展調整 |
| 易于開發 | 高 | 由于功能被分割成不同的服務組件,由于開發范圍更小且被隔離,開發變得更簡單 |
第五章 基于空間的架構
專門解決伸縮性和并發問題
5.1 模型介紹
基于空間的模型(有時也成為云架構模型)旨在減少限制應用伸縮的因素,模型的名字來源于分布式共享記憶體中的tuple space(陣列空間)概念,高伸縮性是通過去除中心資料庫的限制,并使用從記憶體中復制的資料框架來獲得的,保存在記憶體的應用資料被復制給所有運行的行程,行程可以動態的隨著用戶數量增減而啟動或結束,以此來解決伸縮性問題,這樣因為沒有了中心資料庫,資料庫瓶頸就此解決,伺候可以近乎無限制的擴展了,
大多數使用這個模型的應用都是標準的網站,它們接受來自瀏覽器的請求并進行相關操作,競價拍賣網站是一個很好地例子(12306),網站不停的接受來自瀏覽器的報價,應用受到對某一商品的報價,記錄下報價和時間,并且更新對商品的報價,將資訊回傳給瀏覽器,
這個架構中有兩個主要的模塊:處理單元****和虛擬化中間件,下圖展示了這個架構和里面的主要模塊,

處理單元包含了應用模塊(或者部分的應用模塊),具體來說就是包含了web組件以及后臺業務邏輯,處理單元的內容根據應用的型別而異--小型的web應用可能會部署到單一的處理單元,而大型一些的應用會將應用的不同功能模塊部署到不同的處理單元中,典型的處理單元包括應用模塊,以及保存在記憶體的資料框架和為應用失敗時準備的異步資料持久化模塊,它還包括復制引擎,使得虛擬化中間件可以將處理單元修改的資料復制到其他活動的處理單元,
虛擬化中間件負責保護自身以及通信,它包含用于資料同步和處理請求的模塊,以及通信框架,資料框架,處理框架和部署管理器,
5.2 組件間合作
虛擬化中間件有四個架構組件:通信框架,資料框架,處理框架和部署管理器,

1)通信框架

:管理輸入請求和會話資訊,當有請求進入虛擬化中間件,通信框架就決定有哪個處理單元可用,并將請求傳遞給這個處理單元,通信框架的復雜程度可以從簡單的round robin演算法到更復雜的用于監控哪個請求正在被哪個處理單元處理的next-available演算法,
2)資料框架

資料框架可能是這個架構中最重要和關鍵的組件,它與各個處理單元的資料復制引擎互動,在資料更新時來管理資料復制功能,由于通信框架可以將請求傳遞給任何可用的處理單元,所以每個處理單元完全一樣的記憶體中資料就很關鍵,圖中展示處理單元間如何同步資料復制,實際中是通過非常迅速的并行的異步復制來完成的,通常在微秒級(1s=1000毫秒 1毫秒=1000微秒)
3)處理框架
:可選組件,負責管理在多個處理單元時的分布式請求處理,每個處理單元可能只負責應用中的某個特定功能,如果請求需要處理單元間合作(比如,一個訂單處理單元和顧客處理單元),此時處理框架就充當處理單元間資料傳遞的媒介

4)部署管理器
:根據負載情況管理處理單元的動態啟動和關閉,它持續監測請求所需時間和在線用戶量,在負載增加時啟動新的處理單元,在負載下降時關閉處理單元,它是實作可變伸縮性需求的關鍵,
5.3 其他考慮
基于空間的架構是一個復雜和實作起來相對昂貴的框架,對于有可變伸縮性需求的小型web應用是很好地選擇,然而,對于擁有大量資料操作的傳統大規模關系型資料庫應用,并不那么適用,
從產品實作的角度講,這個架構中的很多組件都可以從第三方獲得,比如 GemFire、JavaSpace、GigaSpace、IBM Object Grid,nCache,和 Oracle Coherence,由于架構的實作根據工程的預算和需求而異,所以作為架構師,你應該在實作或選購第三方產品前首先明確你的目標和需求,
5.4 架構分析
| 評價 | 分析 | |
|---|---|---|
| 綜合能力 | 高 | 處理單元可以快速的啟動和關閉,整個應用可以根據用戶量和負載做出反應, |
| 易于部署 | 高 | 雖然基于空間的架構通常沒有解耦合并且功能分布,但他們是動態的,也是成熟的基于云的工具,允許應用輕松的部署到服務器 |
| 可測驗性 | 低 | 測驗高用戶負載既昂貴又耗時,所以在測驗架構的可伸縮性方面很困難 |
| 性能 | 高 | 通過記憶體中資料存取和架構中的快取機制可獲得高性能 |
| 伸縮性 | 高 | 高伸縮性是源于幾乎不依賴集中式的資料庫,從而去除了這個限制伸縮性的瓶頸 |
| 易于開發 | 低 | 主要是因為難以熟悉這個架構開發所需的工具和第三方產品,因此使用該架構需要較大的學習成本,而且,開發程序中還需要特別注意不要影響性能和可伸縮性 |
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/546882.html
標籤:架構設計
上一篇:應用程式之間的通信傳輸協議
下一篇:QQ音樂高可用架構體系
