沒有進(jìn)行架構(gòu)設(shè)計(jì)的應(yīng)用程序通常是緊耦合的溶诞、玻璃心陨亡,難以改變舵稠。沒有頭緒。如果不理解應(yīng)用的各個(gè)組件的內(nèi)部工作方式的話很難看清它的架構(gòu)特征嗓违。關(guān)于部署和維護(hù)的問(wèn)題都很難回答:架構(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)過(guò)每一層才能到達(dá)最底下一層多望。

為什么不允許展示層直接訪問(wèn)數(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è)例子帶來(lái)一個(gè)問(wèn)題菱属,因?yàn)槊恳粚觼G失封閉的,業(yè)務(wù)層不得不通過(guò)服務(wù)層訪問(wèn)持久層恋捆,這沒有天理啊照皆。 所以有時(shí)候你會(huì)創(chuàng)建一個(gè)開放的層重绷。這意味著上一層可以繞過(guò)這一層直接訪問(wèn)下一層沸停。

架構(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)模式候醒,可以用來(lái)設(shè)計(jì)規(guī)模很大的應(yīng)用程序能颁。基于這種架構(gòu)模式應(yīng)用可大可小倒淫。它由高度解耦的伙菊,單一目的的事件處理組件組成,可以異步地接口和處理事件敌土。
它包括兩個(gè)主要的拓?fù)浣Y(jié)構(gòu):mediator 和 broker镜硕。Mediator拓?fù)浣Y(jié)構(gòu)需要你在一個(gè)事件通過(guò)mediator時(shí)精心安排好幾個(gè)步驟,而broker拓?fù)浣Y(jié)構(gòu)無(wú)需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)中,它用來(lái)將事件傳送給event mediator音榜。Event mediator收到初始的事件后庞瘸,會(huì)發(fā)送額外的一些異步事件給event channels來(lái)執(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)起來(lái)通過(guò)一個(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)延遲加劇鸠澈。后來(lái)新浪微薄改用異步推拉結(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)起來(lái)相對(duì)復(fù)雜,主要是由于它的異步和分布式特性甲脏。這可能會(huì)帶來(lái)一些分布式的問(wèn)題眶熬,比如遠(yuǎn)程處理的可用性,缺乏響應(yīng)块请,broker重連等問(wèn)題娜氏。
一個(gè)考慮是這種模式對(duì)于單一的邏輯缺乏原子事務(wù)。所以你需要將原子事務(wù)交給一個(gè)事件處理器執(zhí)行墩新,跨事件處理器的原子事務(wù)是很困難的贸弥。
最困難的設(shè)計(jì)之一是事件處理器的創(chuàng)建,維護(hù)和管理海渊。事件通常有特殊的約定(數(shù)據(jù)值和格式)绵疲。
模式分析
總體靈活性: 高
發(fā)布易用性: 高
可測(cè)試性: 低
性能: 高
規(guī)模擴(kuò)展性: 高
開發(fā)容易度: 低