沒有進(jìn)行架構(gòu)設(shè)計(jì)的應(yīng)用程序通常是緊耦合的、玻璃心,難以改變。沒有頭緒。如果不理解應(yīng)用的各個(gè)組件的內(nèi)部工作方式的話很難看清它的架構(gòu)特征。關(guān)于部署和維護(hù)的問題都很難回答:架構(gòu)的規(guī)模如何?程序的性能如何?程序容易修改么?程序的部署模型是怎么樣?程序的響應(yīng)如何?
架構(gòu)模式可以幫助你定義程序的基本特征和行為。例如一些架構(gòu)模式很自然讓程序成為大規(guī)模(scalable)的程序。有些模式讓程序變得靈巧敏捷(agile)。知道這些架構(gòu)的特征,優(yōu)點(diǎn)和缺點(diǎn),你就可以根據(jù)你特定的業(yè)務(wù)需求和目標(biāo)從容的選擇一種架構(gòu)模式。
一、分層架構(gòu) (Layered Architecture)
它是最通用的架構(gòu),也被叫做N層架構(gòu)模式(n-tier architecture pattern)。這也是Java EE應(yīng)用經(jīng)常采用的標(biāo)準(zhǔn)模式?;旧鲜莻€(gè)程序員都知道它。這種架構(gòu)模式非常適合傳統(tǒng)的IT通信和組織結(jié)構(gòu),很自然地成為大部分應(yīng)用的第一架構(gòu)選擇。
在分層架構(gòu)中的組件被劃分成幾個(gè)層,每個(gè)層代表應(yīng)用的一個(gè)功能。分層架構(gòu)本身沒有規(guī)定要分成多少層,大部分的應(yīng)用會(huì)分成表現(xiàn)層,業(yè)務(wù)層,持久層和數(shù)據(jù)庫(kù)層。小的應(yīng)用有時(shí)候會(huì)將業(yè)務(wù)層和持久層合在一起,更大規(guī)模的應(yīng)用可能會(huì)劃分更多的層,比如調(diào)用外部服務(wù)的層。
分層架構(gòu)的一個(gè)特性就是關(guān)注分離(separation of concerns)。在層中的組件只負(fù)責(zé)本層的邏輯。組件的劃分很容易讓它們實(shí)現(xiàn)自己的角色和職責(zé),也比較容易地開發(fā),測(cè)試管理和維護(hù)。
關(guān)鍵概念
注意每一層都是封閉的。這意味著Request必須經(jīng)過每一層才能到達(dá)最底下一層。
為什么不允許展示層直接訪問數(shù)據(jù)庫(kù)層呢,這樣不是更快嗎?這就是分層架構(gòu)的另一個(gè)特征:層隔離(layers of isolation)。
層隔離的概念意味著你對(duì)任何一層的改變都不會(huì)影響其它層。這很好理解。
層隔離也意味著一個(gè)層的組件并不會(huì)了解其它層的實(shí)現(xiàn),或者知道很少。 比如業(yè)務(wù)層不需知道你持久層是由hibernate還是mybatis實(shí)現(xiàn)的。
分層架構(gòu)也很容易增加新的層。 比如你想將一些通用的服務(wù)重構(gòu)成一個(gè)服務(wù)層,比如通用圖片處理,遠(yuǎn)程賬戶審計(jì)等,可以在業(yè)務(wù)層下增加一個(gè)服務(wù)層。它不會(huì)對(duì)展示層造成影響,也不會(huì)改變持久層的代碼。
上面的這個(gè)例子帶來一個(gè)問題,因?yàn)槊恳粚觼G失封閉的,業(yè)務(wù)層不得不通過服務(wù)層訪問持久層,這沒有天理啊。 所以有時(shí)候你會(huì)創(chuàng)建一個(gè)開放的層。這意味著上一層可以繞過這一層直接訪問下一層。
架構(gòu)例子
我們看一下淘寶前幾年的架構(gòu)的例子
這是一個(gè)標(biāo)準(zhǔn)的分層的架構(gòu)。每一層中又可以詳細(xì)的分成更細(xì)的層,比如服務(wù)層。
模式分析
總體靈活性: 低
發(fā)布易用性: 低
可測(cè)試性: 高
性能: 低
規(guī)模擴(kuò)展性: 低
開發(fā)容易度: 高
二、事件驅(qū)動(dòng)架構(gòu)(Event-Driven Architecture)
事件驅(qū)動(dòng)架構(gòu)是流行的一個(gè)分布式異步機(jī)構(gòu)模式,可以用來設(shè)計(jì)規(guī)模很大的應(yīng)用程序?;谶@種架構(gòu)模式應(yīng)用可大可小。它由高度解耦的,單一目的的事件處理組件組成,可以異步地接口和處理事件。
它包括兩個(gè)主要的拓?fù)浣Y(jié)構(gòu):mediator 和 broker。Mediator拓?fù)浣Y(jié)構(gòu)需要你在一個(gè)事件通過mediator時(shí)精心安排好幾個(gè)步驟,而broker拓?fù)浣Y(jié)構(gòu)無需mediator,而是由你串聯(lián)起幾個(gè)事件。這兩種拓?fù)浼軜?gòu)的特征和實(shí)現(xiàn)有很大的不同,所以你需要知道哪一個(gè)適合你。
Mediator拓?fù)浣Y(jié)構(gòu)
Mediator拓?fù)浣Y(jié)構(gòu)適合有多個(gè)步驟的事件,需要安排處理層次。
例如購(gòu)買一只股票,首先會(huì)校驗(yàn)這個(gè)交易,校驗(yàn)股票交易是否符合各種規(guī)定,將它交給一個(gè)經(jīng)紀(jì)人,計(jì)算傭金,最后確認(rèn)交易。所有這些都安排好各個(gè)步驟的順序,決定它們是否串行還是并行。
它包括四個(gè)組件:event queues, an event mediator, event channels 和 event processors。
事件流是這樣開始的: 客戶端發(fā)送一個(gè)事件到事件隊(duì)列(event queues)中,它用來將事件傳送給event mediator。Event mediator收到初始的事件后,會(huì)發(fā)送額外的一些異步事件給event channels來執(zhí)行處理的每個(gè)步驟。Event processors監(jiān)聽event channels,接收事件并處理一些業(yè)務(wù)邏輯。
在事件驅(qū)動(dòng)架構(gòu)中有十幾個(gè)甚至幾百個(gè)事件隊(duì)列都很正常。模式本身沒有限定事件隊(duì)列的實(shí)現(xiàn)方式。它可能是一個(gè)消息隊(duì)列,一個(gè)web service或者其它。
這里有兩種事件:初始事件和處理事件。Mediator會(huì)將初始事件編排成處理事件。它沒有具體的業(yè)務(wù)邏輯,只是一個(gè)協(xié)調(diào)者,負(fù)責(zé)將初始事件轉(zhuǎn)化成一個(gè)或者多個(gè)處理事件。
event channels 既可以是消息隊(duì)列,也可以是消息topic,大部分是消息topic,這樣可以由多個(gè)消息處理器(event processor)處理同一個(gè)消息。
消息處理器包含實(shí)際的業(yè)務(wù)邏輯。每個(gè)消息處理器都是自包含的,獨(dú)立的,高度解耦的,執(zhí)行單一的任務(wù)。
這種模式可能有一些變種。作為架構(gòu)師,你應(yīng)該理解每個(gè)實(shí)現(xiàn)的細(xì)節(jié),確保這種解決方案適合你的需求。
有一些開源的框架實(shí)現(xiàn)了這種架構(gòu),如Spring Integration, Apache Camel, 或者 Mule ESB。
Broker拓?fù)浼軜?gòu)
Broker不同于上面的結(jié)構(gòu),它沒有中心的Mediator。所有的事件串聯(lián)起來通過一個(gè)輕量級(jí)的消息broker如RabbitMQ,ActiveMQ,HornetQ等。如果你的消息比較簡(jiǎn)單,不需要重新編排,就可以使用這種結(jié)構(gòu)。
如圖所示,它包含兩個(gè)組件broker和 event processor。
broker中的event channel可以是消息隊(duì)列,消息topic或者它們的復(fù)合形式。
每個(gè)event processor負(fù)責(zé)處理事件,發(fā)布新的事件。
架構(gòu)例子
在新浪微薄的早期架構(gòu)中,微薄發(fā)布使用同步推模式,用戶發(fā)表微薄后系統(tǒng)會(huì)立即將這條微薄插入到數(shù)據(jù)庫(kù)所有粉絲的訂閱列表中,當(dāng)用戶量比較大時(shí),特別是明星用戶發(fā)布微博時(shí),會(huì)引起大量的數(shù)據(jù)庫(kù)寫操作,超出數(shù)據(jù)庫(kù)負(fù)載,系統(tǒng)性能急劇下降,用戶響應(yīng)延遲加劇。后來新浪微薄改用異步推拉結(jié)合的模式,用戶發(fā)表微薄后系統(tǒng)將微薄寫入消息隊(duì)列后立即返回,用戶響應(yīng)迅速,消息隊(duì)列消費(fèi)者任務(wù)將微薄推送給所有當(dāng)前在線粉絲的訂閱列表中,非在線用戶登錄后再根據(jù)關(guān)注列表拉取微薄訂閱列表。
架構(gòu)考量
事件驅(qū)動(dòng)架構(gòu)模式實(shí)現(xiàn)起來相對(duì)復(fù)雜,主要是由于它的異步和分布式特性。這可能會(huì)帶來一些分布式的問題,比如遠(yuǎn)程處理的可用性,缺乏響應(yīng),broker重連等問題。
一個(gè)考慮是這種模式對(duì)于單一的邏輯缺乏原子事務(wù)。所以你需要將原子事務(wù)交給一個(gè)事件處理器執(zhí)行,跨事件處理器的原子事務(wù)是很困難的。
最困難的設(shè)計(jì)之一是事件處理器的創(chuàng)建,維護(hù)和管理。事件通常有特殊的約定(數(shù)據(jù)值和格式)。
模式分析
總體靈活性: 高
發(fā)布易用性: 高
可測(cè)試性: 低
性能: 高
規(guī)模擴(kuò)展性: 高
開發(fā)容易度: 低