摘要:企業(yè)應(yīng)用在某些方面要比電信軟件簡(jiǎn)單得多多線程問(wèn)題沒(méi)有那么困難,無(wú)需關(guān)注硬件設(shè)備與軟件的集成。但是,在某些方面,企業(yè)應(yīng)用又比電信軟件復(fù)雜得多企業(yè)應(yīng)用一般都涉及到大量復(fù)雜數(shù)據(jù),而且必須處理很多不合邏輯的業(yè)務(wù)規(guī)則。
構(gòu)建計(jì)算機(jī)系統(tǒng)并非易事。隨著系統(tǒng)復(fù)雜性的增大,構(gòu)建相應(yīng)軟件的難度將呈指數(shù)增大。
同其他行業(yè)一樣,我們只有在不斷的學(xué)習(xí)中進(jìn)步,從成功經(jīng)驗(yàn)中學(xué)習(xí),從失敗教訓(xùn)中學(xué)習(xí),才有望克服這些困難。
這本書(shū)的內(nèi)容就是這樣一些“學(xué)習(xí)”經(jīng)驗(yàn)。
只有通過(guò)模式的總結(jié)和學(xué)習(xí),才能更有效地與他人進(jìn)行交流。
—選自《企業(yè)應(yīng)用架構(gòu)模式》
0.1 架構(gòu)軟件業(yè)的人樂(lè)于做這樣的事——找一些詞匯,并把它們引申到大量微妙而又互相矛盾的含義。一個(gè)最大的受害者就是“架構(gòu)”(architecture)這個(gè)詞。我個(gè)人對(duì)“架構(gòu)”的感覺(jué)是,它是一個(gè)讓人印象深刻的詞,主要用來(lái)表示一些非常重要的東西。當(dāng)然,我也會(huì)小心,不讓這些對(duì)“系統(tǒng)結(jié)構(gòu)”的“不恭之詞”,影響到讀者對(duì)本書(shū)的興趣。
很多人都試圖給“架構(gòu)”下定義,而這些定義本身卻很難統(tǒng)一。能夠統(tǒng)一的內(nèi)容有兩點(diǎn):一點(diǎn)是“最高層次的系統(tǒng)分解”;另一點(diǎn)是“系統(tǒng)中不易改變的決定”。越來(lái)越多的人發(fā)現(xiàn):表述一個(gè)系統(tǒng)架構(gòu)的方法不只一種;一個(gè)系統(tǒng)中也可能有很多種不同的架構(gòu),而且,對(duì)于什么在架構(gòu)上意義重大的看法也會(huì)隨著系統(tǒng)的生命周期變化。
Ralph Johnson經(jīng)常在郵件列表上發(fā)帖,并提出一些令人關(guān)注的見(jiàn)解。就在我完成本書(shū)初稿的同時(shí),他又發(fā)表了一些關(guān)于“架構(gòu)”的觀點(diǎn)。他認(rèn)為,架構(gòu)是一種主觀上的東西,是專家級(jí)項(xiàng)目開(kāi)發(fā)人員對(duì)系統(tǒng)設(shè)計(jì)的一些可共享的理解。一般地,這種可共享的理解表現(xiàn)為系統(tǒng)中主要的組成部分以及這些組成間的交互關(guān)系。它還包括一些決定,開(kāi)發(fā)者們希望這些決定能及早做出,因?yàn)樵陂_(kāi)發(fā)者看來(lái)它們是難以改變的。架構(gòu)的主觀性也來(lái)源于此——如果你發(fā)現(xiàn)某些決定并不像你想象的那么難以改變,那么它就不再與架構(gòu)相關(guān)。到了最后,架構(gòu)自然就濃縮成一些重要的東西,不論這些東西是什么。
在本書(shū)中,我提出一些自己的理解,涉及企業(yè)應(yīng)用主要組成部分和我希望能盡早做出的決定。在這些架構(gòu)模式中,我最欣賞的就是“層次”,將在第1章中進(jìn)行詳細(xì)介紹。全書(shū)實(shí)際上就是關(guān)于如何將企業(yè)應(yīng)用組織成不同的層次,以及這些層次之間如何協(xié)同工作。大多數(shù)重要的企業(yè)應(yīng)用都是按照某種形式的層次分層設(shè)計(jì)的;當(dāng)然,在某些情況下,別的設(shè)計(jì)方式(如管道方式、過(guò)濾器方式等)也有它們自己的價(jià)值。在本書(shū)中我們將不會(huì)討論這些方式,而把注意力集中在層次方式上,因?yàn)樗菓?yīng)用最廣的設(shè)計(jì)方式。
本書(shū)中的一些模式毫無(wú)疑問(wèn)是關(guān)于架構(gòu)的,它們表示了企業(yè)應(yīng)用各主要組成部分間的重要決定;另外一些模式是關(guān)于設(shè)計(jì)的,有助于架構(gòu)的實(shí)現(xiàn)。我沒(méi)有刻意區(qū)分這兩類模式,因?yàn)檎缥覀兦懊嬗懻摰?,是否與架構(gòu)相關(guān)往往帶有主觀性。
0.2 企業(yè)應(yīng)用編寫計(jì)算機(jī)軟件的人很多,我們通常把這些活動(dòng)都稱為軟件開(kāi)發(fā)。但是軟件的種類是不同的,每種軟件都有自身的挑戰(zhàn)性和復(fù)雜性。我是在與幾個(gè)從事電信軟件開(kāi)發(fā)的朋友交談后,意識(shí)到這個(gè)問(wèn)題的。企業(yè)應(yīng)用在某些方面要比電信軟件簡(jiǎn)單得多——多線程問(wèn)題沒(méi)有那么困難,無(wú)需關(guān)注硬件設(shè)備與軟件的集成。但是,在某些方面,企業(yè)應(yīng)用又比電信軟件復(fù)雜得多——企業(yè)應(yīng)用一般都涉及到大量復(fù)雜數(shù)據(jù),而且必須處理很多“不合邏輯”的業(yè)務(wù)規(guī)則。雖然有些模式是適合所有軟件的,但是大多數(shù)模式都還只適合某些特定的領(lǐng)域和分支。
我的工作主要是關(guān)于企業(yè)應(yīng)用的,因此,這里所談及的模式也都是關(guān)于企業(yè)應(yīng)用的。(企業(yè)應(yīng)用還有一些其他的說(shuō)法,如“信息系統(tǒng)”或更早期的“數(shù)據(jù)處理”。)那么,這里的“企業(yè)應(yīng)用”具體指的是什么呢?我無(wú)法給出一個(gè)精確的定義,但是我可以羅列一些個(gè)人的理解。
先舉幾個(gè)例子。企業(yè)應(yīng)用包括工資單、患者記錄、發(fā)貨跟蹤、成本分析、信譽(yù)評(píng)估、保險(xiǎn)、供應(yīng)鏈、記賬、客戶服務(wù)以及外幣交易等。企業(yè)應(yīng)用不包括車輛加油、文字處理、電梯控制、化工廠控制器、電話交換機(jī)、操作系統(tǒng)、編譯器以及電子游戲等。
企業(yè)應(yīng)用一般都涉及到持久化數(shù)據(jù)。數(shù)據(jù)必須持久化是因?yàn)槌绦虻亩啻芜\(yùn)行都需要用到它們——實(shí)際上,有些數(shù)據(jù)需要持久化若干年。在此期間,操作這些數(shù)據(jù)的程序往往會(huì)有很多變化。這些數(shù)據(jù)的生命周期往往比最初生成它們的那些硬件、操作系統(tǒng)和編譯器還要長(zhǎng)。在此期間,數(shù)據(jù)本身的結(jié)構(gòu)一般也會(huì)被擴(kuò)展,使得它在不影響已有信息的基礎(chǔ)上,還能表示更多新信息。即使是有根本性的變化發(fā)生,或公司安裝了一套全新的軟件,這些數(shù)據(jù)也必須被“遷移”到這些全新的應(yīng)用上。
企業(yè)應(yīng)用一般都涉及到大量數(shù)據(jù)——一個(gè)中等規(guī)模的系統(tǒng)往往都包含1GB以上的數(shù)據(jù),這些數(shù)據(jù)是以百萬(wàn)條記錄的方式存在的。巨大的數(shù)據(jù)量導(dǎo)致數(shù)據(jù)的管理成為系統(tǒng)的主要工作。早期的系統(tǒng)使用的是索引文件系統(tǒng),如IBM的VSAM和ISAM?,F(xiàn)代的系統(tǒng)往往采用數(shù)據(jù)庫(kù),絕大多數(shù)是關(guān)系型數(shù)據(jù)庫(kù)。數(shù)據(jù)庫(kù)的設(shè)計(jì)和演化已使其本身成為新的技術(shù)領(lǐng)域。
企業(yè)應(yīng)用一般還涉及到很多人同時(shí)訪問(wèn)數(shù)據(jù)。對(duì)于很多系統(tǒng)來(lái)說(shuō),人數(shù)可能在100人以下,但是對(duì)于一些基于Web的系統(tǒng),人數(shù)會(huì)呈指數(shù)級(jí)增長(zhǎng)。要確保這些人都能夠正確地訪問(wèn)數(shù)據(jù),就一定會(huì)存在這樣或那樣的問(wèn)題。即使人數(shù)沒(méi)有那么多,要確保兩個(gè)人在同時(shí)操作同一數(shù)據(jù)項(xiàng)時(shí)不出現(xiàn)錯(cuò)誤,也是存在問(wèn)題的。事務(wù)管理工具可以處理這個(gè)問(wèn)題,但是它通常無(wú)法做到對(duì)應(yīng)用開(kāi)發(fā)者透明。
企業(yè)應(yīng)用還涉及到大量操作數(shù)據(jù)的用戶界面屏幕。有幾百個(gè)用戶界面是不足為奇的。用戶使用頻率的差異很大,他們也經(jīng)常沒(méi)什么技術(shù)背景。因此,為了不同的使用目的,數(shù)據(jù)需要很多種表現(xiàn)形式。系統(tǒng)一般都有很多批處理過(guò)程,當(dāng)專注于強(qiáng)調(diào)用戶交互的用例時(shí),這些批處理過(guò)程很容易被忽視。
企業(yè)應(yīng)用很少獨(dú)立存在,通常需要與散布在企業(yè)周圍的其他企業(yè)應(yīng)用集成。這些各式各樣的系統(tǒng)是在不同時(shí)期,采用不同技術(shù)構(gòu)建的,甚至連協(xié)作機(jī)制都不同:COBOL數(shù)據(jù)文件、CORBA系統(tǒng)或是消息系統(tǒng)。企業(yè)經(jīng)常希望能用一種統(tǒng)一的通信技術(shù)來(lái)集成所有系統(tǒng)。當(dāng)然,每次這樣的集成工作幾乎都很難真正實(shí)現(xiàn),所有留下來(lái)的就是一個(gè)個(gè)風(fēng)格各異的集成環(huán)境。當(dāng)商業(yè)用戶需要同其業(yè)務(wù)伙伴進(jìn)行應(yīng)用集成時(shí),情況就更糟糕。
即使是某個(gè)企業(yè)統(tǒng)一了集成技術(shù),它們也還是會(huì)遇到業(yè)務(wù)過(guò)程中的差異以及數(shù)據(jù)中概念的不一致性。一個(gè)部分可能認(rèn)為客戶是當(dāng)前簽有協(xié)議的人;而另外一個(gè)部門可能還要將那些以前有合同,但現(xiàn)在已經(jīng)沒(méi)有了的人計(jì)算在內(nèi)。再有,一個(gè)部門可能只關(guān)心產(chǎn)品銷售而不關(guān)心服務(wù)銷售。粗看起來(lái),這些問(wèn)題似乎容易解決,但是,一旦幾百個(gè)記錄中的每個(gè)字段都有可能存在著細(xì)微差別,問(wèn)題的規(guī)模就會(huì)形成不小的挑戰(zhàn)——就算唯一知道這些字段之間差別的員工還在公司任職(當(dāng)然,也許他在你察覺(jué)到之前就早已辭職不干了)。這樣,數(shù)據(jù)就必須被不停地讀取、合并、然后寫成各種不同語(yǔ)法和語(yǔ)義的格式。
再接下來(lái)的問(wèn)題是由“業(yè)務(wù)邏輯”帶來(lái)的。我認(rèn)為“業(yè)務(wù)邏輯”這個(gè)詞很滑稽,因?yàn)楹茈y找出什么東西比“業(yè)務(wù)邏輯”更加沒(méi)有邏輯。當(dāng)我們構(gòu)建一個(gè)操作系統(tǒng)時(shí),總是盡可能地使得系統(tǒng)中的各種事物符合邏輯。而業(yè)務(wù)邏輯生來(lái)就是那樣的,沒(méi)有相當(dāng)?shù)男姓Γ灰敫淖兯?,?dāng)然,它們都有自己的理由。你必須面對(duì)很多奇怪的條件。而且這些條件相互作用的方式也非常怪異。比如,某個(gè)銷售人員為了簽下其客戶幾百萬(wàn)美元的一張單,可能會(huì)在商務(wù)談判中與對(duì)方達(dá)成協(xié)議,將該項(xiàng)目的年度到賬時(shí)間推遲兩天,因?yàn)檫@樣才能與該客戶的賬務(wù)周期相吻合。成千上萬(wàn)的這類“一次特殊情況”最終導(dǎo)致了復(fù)雜的業(yè)務(wù)“無(wú)邏輯”,使得商業(yè)軟件開(kāi)發(fā)那么困難。在這種情況下,必須盡量將這些業(yè)務(wù)邏輯組織成有效的方式,因?yàn)槲覀兛梢源_定的是,這些“邏輯”一定會(huì)隨著時(shí)間不斷變化。
對(duì)于一些人來(lái)說(shuō),“企業(yè)應(yīng)用”這個(gè)詞指的是大型系統(tǒng)。但是 需要注意的是,并不是所有的企業(yè)應(yīng)用都是大型的,盡管它們可能都為企業(yè)提供巨大的價(jià)值。很多人認(rèn)為,由于小型系統(tǒng)的規(guī)模不大,可以不用太注意它們,而且在某種程度上,這種觀點(diǎn)能夠帶來(lái)一定的成本節(jié)約。如果一個(gè)小型系統(tǒng)失敗了,相對(duì)于大型系統(tǒng)的失敗,這種失敗就不會(huì)顯得那么起眼了。但是,我認(rèn)為這種思想沒(méi)有對(duì)小型項(xiàng)目的累積作用給予足夠的重視。試想,如果在小型項(xiàng)目上能夠進(jìn)行某些改善措施,那么一旦這些改善措施被成功運(yùn)用于大型項(xiàng)目,它帶來(lái)的效果就會(huì)非常大。實(shí)際上,最好是通過(guò)簡(jiǎn)化架構(gòu)和過(guò)程,將一個(gè)大型項(xiàng)目簡(jiǎn)化成小型項(xiàng)目。
0.3 企業(yè)應(yīng)用的種類在我們討論如何設(shè)計(jì)企業(yè)應(yīng)用以及使用哪些模式之前,明確這樣一個(gè)觀點(diǎn)是非常重要的,即企業(yè)應(yīng)用是多種多樣的,不同的問(wèn)題將導(dǎo)致不同的處理方法。如果有人說(shuō)“總是這樣做” 的時(shí)候,就應(yīng)該敲響警鐘了。我認(rèn)為,設(shè)計(jì)中最具挑戰(zhàn)性(也是我最感興趣)的地方就是了解有哪些候選的設(shè)計(jì)方法以及各種不同設(shè)計(jì)方法之間的優(yōu)劣比較。進(jìn)行選擇的控件很大,但我在這里只選三個(gè)方面。
考慮一個(gè)B2C(Business to Customer)的網(wǎng)上零售商:人們通過(guò)瀏覽器瀏覽,通過(guò)購(gòu)物車購(gòu)買商品。通過(guò)購(gòu)物車購(gòu)買商品。這樣一個(gè)系統(tǒng)必須能夠應(yīng)付大量的客戶,因此,其解決方案不但要考慮到資源利用的有效性,還要考慮到系統(tǒng)的可伸縮性,以便在用戶規(guī)模增大時(shí)能夠通過(guò)增加硬件的辦法加以解決。該系統(tǒng)的業(yè)務(wù)邏輯可以非常簡(jiǎn)單:獲取訂單,進(jìn)行簡(jiǎn)單的價(jià)格計(jì)算和發(fā)貨計(jì)算,給出發(fā)貨信息。我們希望任何人都能夠訪問(wèn)該系統(tǒng),因此用戶界面可以選用通用的Web表現(xiàn)方式,以支持各種不同的瀏覽器。數(shù)據(jù)源包括用來(lái)存放訂單的數(shù)據(jù)庫(kù),還可能包括某種與庫(kù)存系統(tǒng)的通信交流,以便獲得商品的可用性信息和發(fā)貨信息。
再考慮一個(gè)租約合同自動(dòng)處理系統(tǒng)。在某些方面,這樣的系統(tǒng)比起前面介紹的B2C系統(tǒng)要簡(jiǎn)單,因?yàn)樗挠脩魯?shù)很少(在特定時(shí)間內(nèi)不會(huì)超過(guò)100個(gè)),但是它的業(yè)務(wù)邏輯卻比較復(fù)雜。計(jì)算每個(gè)租約的月供,處理如提早解約和延遲付款這樣的事件,簽訂合同時(shí)驗(yàn)證各種數(shù)據(jù),這些都是非常復(fù)雜的任務(wù),因?yàn)樽饧s領(lǐng)域的許多競(jìng)爭(zhēng)都是以過(guò)去的交易為基礎(chǔ)稍加變化而出現(xiàn)的。正是因?yàn)橐?guī)則的隨意性很大,才使得像這樣一個(gè)復(fù)雜領(lǐng)域具有挑戰(zhàn)性。
這樣的系統(tǒng)在用戶界面(UI)上也很復(fù)雜。這就要求HTML界面要能提供更豐富的功能和更復(fù)雜的屏幕,而這些要求往往是HTML界面目前無(wú)法達(dá)到的,需要更常規(guī)的胖客戶界面。用戶交互的復(fù)雜性還會(huì)帶來(lái)事務(wù)行為的復(fù)雜性:簽訂租約可能要耗時(shí)1~2個(gè)小時(shí),這期間用戶要處于一個(gè)邏輯事務(wù)中。一個(gè)復(fù)雜的數(shù)據(jù)庫(kù)設(shè)計(jì)方案中可能也會(huì)涉及到200多個(gè)表以及一些有關(guān)資產(chǎn)評(píng)估和計(jì)價(jià)的軟件包。
第三個(gè)例子是一家小型公司使用的簡(jiǎn)單的“開(kāi)支跟蹤系統(tǒng)”。這個(gè)系統(tǒng)的用戶很少,功能簡(jiǎn)單,通過(guò)HTML表現(xiàn)方式可以很容易實(shí)現(xiàn),涉及的數(shù)據(jù)源表項(xiàng)也不多。盡管如此,開(kāi)發(fā)這樣的系統(tǒng)也不是沒(méi)有挑戰(zhàn)。一方面你必須快速地開(kāi)發(fā)出它,另一方面你又必須為它以后可能的發(fā)展考慮;也許以后會(huì)為它增加賠償校驗(yàn)的功能,也許它會(huì)被集成到工資系統(tǒng)中,也許還要增加關(guān)于稅務(wù)的功能,也許要為公司的CFO生成匯總報(bào)表,也許會(huì)被集成到一個(gè)航空訂票Web Service中,等等。如果在這個(gè)系統(tǒng)的開(kāi)發(fā)中,也試圖使用前面兩個(gè)例子中的一些架構(gòu),可能會(huì)影響開(kāi)發(fā)進(jìn)度。如果一個(gè)系統(tǒng)會(huì)帶來(lái)業(yè)務(wù)效益(如所有的企業(yè)應(yīng)用應(yīng)該的那樣),則系統(tǒng)進(jìn)度延誤同樣也是開(kāi)銷。如果現(xiàn)在不做決策又有可能影響系統(tǒng)未來(lái)的發(fā)展。但是,如果現(xiàn)在就考慮了這些靈活性但是考慮不得當(dāng),額外的復(fù)雜性又可能會(huì)影響到系統(tǒng)的發(fā)展,進(jìn)一步延誤系統(tǒng)部署,減少系統(tǒng)的效益。雖然這類系統(tǒng)很小,但是一個(gè)企業(yè)中往往有很多這樣的系統(tǒng),這些系統(tǒng)的架構(gòu)不良性累積起來(lái),后果將會(huì)非常可怕。
這三個(gè)企業(yè)應(yīng)用的例子都有難點(diǎn),而且難點(diǎn)各不相同。當(dāng)然,也不可能有一個(gè)適合于三者的通用架構(gòu)。選擇架構(gòu)時(shí),必須很清楚地了解面臨的問(wèn)題,在理解的基礎(chǔ)上再來(lái)選擇合適的設(shè)計(jì)。本書(shū)中也沒(méi)有一個(gè)通用的解決方案。實(shí)際上,很多模式僅僅是一些可選方案罷了。即使你選擇了某種模式,也需要進(jìn)一步根據(jù)面臨的問(wèn)題來(lái)修改模式。在構(gòu)建企業(yè)應(yīng)用時(shí),你不思考是不行的。所有書(shū)本知識(shí)只是給你提供信息,作為你做決定的基礎(chǔ)。
模式是這樣,工具也同樣如此。在系統(tǒng)開(kāi)發(fā)時(shí)應(yīng)該選取盡可能少的工具,同時(shí)也要注意,不同的工具擅長(zhǎng)處理的方面也不同,切記不要用錯(cuò)了工具,否則只會(huì)事倍功半。
0.4 關(guān)于性能的考慮很多架構(gòu)的設(shè)計(jì)決策和性能有關(guān)。對(duì)于大多數(shù)與性能相關(guān)的問(wèn)題,我的辦法是首先建立系統(tǒng),調(diào)試運(yùn)行,然后通過(guò)基于測(cè)量的嚴(yán)格的優(yōu)化過(guò)程來(lái)提高性能。但是,有一些架構(gòu)上的決策對(duì)性能的影響,可能是后期優(yōu)化難以彌補(bǔ)的。而且即使這種影響可以在后期很容易地彌補(bǔ),參與這個(gè)項(xiàng)目的人們?nèi)稳粫?huì)從一開(kāi)始就擔(dān)心這些決策。
在這樣的一本書(shū)中討論性能通常很困難。這是因?yàn)椤把垡?jiàn)為實(shí)”:所有那些關(guān)于性能的條條框框,不在你的具體系統(tǒng)中配置運(yùn)行一下,是很難有說(shuō)服力的。我也經(jīng)??吹揭恍┰O(shè)計(jì)方案因?yàn)樾阅芊矫娴目紤]而被接受或拒絕,但是一旦有人在真實(shí)的設(shè)置環(huán)境中做一些測(cè)量,就會(huì)證明這些考慮是錯(cuò)誤的。
本書(shū)將提出一些這方面的建議,包括盡量減少遠(yuǎn)程調(diào)用(它在很長(zhǎng)時(shí)間內(nèi)都被認(rèn)為是優(yōu)化性能的好建議)。盡管如此,還是建議讀者在運(yùn)用這些原則之前,在你的應(yīng)用中具體試一試。同樣,本書(shū)中的樣例代碼也有一些地方為了提高可讀性而犧牲了效率。在你的系統(tǒng)中,需要自行決定是否進(jìn)行優(yōu)化。在做性能優(yōu)化后,一定要與優(yōu)化前進(jìn)行測(cè)量對(duì)比,以確定真的得到了優(yōu)化,否則,你可能只是破壞了代碼的可讀性。
還有一個(gè)很重要的推論:配置上的重大變化會(huì)使得某些性能優(yōu)化失效。因此,在升級(jí)虛擬機(jī)、硬件、數(shù)據(jù)庫(kù)或其他東西到新的版本時(shí),必須重新確認(rèn)性能優(yōu)化工作的有效性。很多情況下,配置變更都會(huì)對(duì)性能優(yōu)化有影響,有時(shí)候你真的會(huì)發(fā)現(xiàn),以前為了提升性能做的優(yōu)化,在新環(huán)境下居然影響性能。
關(guān)于性能的另一個(gè)問(wèn)題是很多術(shù)語(yǔ)的使用不一致。最明顯的例子就是“可伸縮性”(scalability),它可能有6-7種含義。下面我使用其中一些術(shù)語(yǔ)。
響應(yīng)時(shí)間是系統(tǒng)完成一次外部請(qǐng)求處理所需要的時(shí)間。這些外部請(qǐng)求可能是用戶交互行為,例如按下一個(gè)按鈕,或是服務(wù)器API調(diào)用。
響應(yīng)性不同于請(qǐng)求處理,它是系統(tǒng)響應(yīng)請(qǐng)求的速度有多快。這個(gè)指標(biāo)在許多系統(tǒng)里非常重要,因?yàn)閷?duì)于一些系統(tǒng)而言,如果其響應(yīng)性太慢,用戶將難以忍受——盡管其響應(yīng)時(shí)間可能不慢。如果在請(qǐng)求處理期間,系統(tǒng)一直處于等待狀態(tài),則系統(tǒng)的響應(yīng)性和響應(yīng)時(shí)間是相同的。然而,如果能夠在處理真正完成之前就給用戶一些信息表明系統(tǒng)已經(jīng)接到請(qǐng)求,則響應(yīng)性就會(huì)好一些。例如,在文件拷貝過(guò)程中,為用戶提供一個(gè)“進(jìn)度條”,將會(huì)提高用戶界面的響應(yīng)性,但并不會(huì)提高響應(yīng)時(shí)間。
等待時(shí)間是獲得系統(tǒng)任何形式響應(yīng)的最小時(shí)間,即使應(yīng)該做的工作并不存在。通常它是遠(yuǎn)程系統(tǒng)中的大問(wèn)題。假設(shè)我們讓程序什么都不做,只是調(diào)用返回即可,則如果在本機(jī)上運(yùn)行程序,一般都會(huì)立即得到響應(yīng)。但是,如果在遠(yuǎn)程計(jì)算機(jī)上運(yùn)行程序,情況就不一樣,往往需要數(shù)秒的時(shí)間才能得到響應(yīng)。因?yàn)閺陌l(fā)出請(qǐng)求到得到響應(yīng)的數(shù)秒時(shí)間主要用于排除使信息在線路上傳輸?shù)睦щy。作為應(yīng)用開(kāi)發(fā)者,我經(jīng)常對(duì)等待時(shí)間無(wú)能為力。這也是為什么要盡量避免遠(yuǎn)程調(diào)用的原因。
吞吐率是給定時(shí)間內(nèi)能夠處理多大的請(qǐng)求量。如果考察的是文件拷貝,則吞吐率可以用每秒字節(jié)量來(lái)表示。對(duì)于企業(yè)應(yīng)用來(lái)說(shuō),吞吐率通常用每秒事務(wù)數(shù)(tps)來(lái)度量。這種方法的一個(gè)問(wèn)題是指標(biāo)依賴于事務(wù)的復(fù)雜程度。對(duì)于特定系統(tǒng)的測(cè)試,應(yīng)該選取普通的事務(wù)集合。
在這里,性能或指吞吐率,或者指響應(yīng)時(shí)間,由用戶自己決定。當(dāng)通過(guò)某種優(yōu)化技術(shù)后,使得系統(tǒng)的吞吐率提高了,但是響應(yīng)時(shí)間下降了,這時(shí)就不好說(shuō)系統(tǒng)的性能提高了,最好用更準(zhǔn)確的術(shù)語(yǔ)表示。從用戶角度而言,響應(yīng)性往往比響應(yīng)時(shí)間更重要,因此,為了提高響應(yīng)性而損失一些響應(yīng)時(shí)間或者吞吐率是值得的。
負(fù)載是關(guān)于系統(tǒng)當(dāng)前負(fù)荷的表述,也許可以用當(dāng)前有多少用戶與系統(tǒng)相連來(lái)表示。負(fù)載有時(shí)也作為其他指標(biāo)(如響應(yīng)時(shí)間)的背景。因此,我們可以說(shuō):在10個(gè)用戶的情況下,請(qǐng)求響應(yīng)時(shí)間是0.5秒,在20個(gè)用戶的情況下,請(qǐng)求響應(yīng)時(shí)間是2秒。
負(fù)載敏感度是指響應(yīng)時(shí)間隨負(fù)載變化的程度。假設(shè):系統(tǒng)A在10~20個(gè)用戶的情況下,請(qǐng)求響應(yīng)時(shí)間都是0.5秒;系統(tǒng)B在10個(gè)用戶的情況下,請(qǐng)求響應(yīng)時(shí)間是0.2秒,在20個(gè)用戶的情況下,請(qǐng)求響應(yīng)時(shí)間上升到2秒。此時(shí),系統(tǒng)A的負(fù)載敏感度比系統(tǒng)B低;我們還可以使用術(shù)語(yǔ)衰減(degradation),稱系統(tǒng)B衰減得比系統(tǒng)A快。
效率是性能除以資源。如果一個(gè)雙CPU系統(tǒng)的性能是30tps,另一個(gè)系統(tǒng)有4個(gè)同樣的CPU,性能是40tps,則前者效率高于后者。
系統(tǒng)的容量是指最大有效負(fù)載或吞吐率的指標(biāo)。它可以是一個(gè)絕對(duì)最大值或性能衰減至低于一個(gè)可接受的閾值之前的臨界點(diǎn)。
可伸縮性度量的是向系統(tǒng)中增加資源(通常是硬件)對(duì)系統(tǒng)性能的影響。一個(gè)可伸縮性的系統(tǒng)允許在增加了硬件后,能夠有性能上的合理提高。例如,為了使吞吐率提高一倍,要增加多少服務(wù)器等。垂直可伸縮性或稱垂直延展,通常指提高單個(gè)服務(wù)器的性能,例如增加內(nèi)存。水平可伸縮性或稱水平延展,通常指增加服務(wù)器的數(shù)目。
問(wèn)題是,設(shè)計(jì)決策對(duì)所有性能指標(biāo)的作用并不相同。比如,某個(gè)服務(wù)器上運(yùn)行著兩個(gè)軟件系統(tǒng):Swordfish的容量是20tps,而Camel的容量是40tps。哪一個(gè)的性能更高?哪一個(gè)的可伸縮性好??jī)H憑這些數(shù)據(jù),我們無(wú)法回答關(guān)于可伸縮性的問(wèn)題,我們只能說(shuō)Camel系統(tǒng)在單片機(jī)上的效率更高。假設(shè)又增加了一臺(tái)服務(wù)器后,我們發(fā)現(xiàn):Swordfish的容量是35tps,Camel的容量是50tps。盡管Camel的容量仍然大于Swordfish,但是后者在可伸縮性上卻顯得比前者更好。假設(shè)我們繼續(xù)增加服務(wù)器數(shù)目后發(fā)現(xiàn):Swordfish每增加一臺(tái)服務(wù)器提高15tps,Camel每增加一臺(tái)服務(wù)器提高10tps。在獲得了這些數(shù)據(jù)后,我們才可以說(shuō),Swordfish的水平可伸縮性比Camel好,盡管Camel在5個(gè)服務(wù)器以下會(huì)有更好的效率。
當(dāng)構(gòu)建企業(yè)應(yīng)用系統(tǒng)時(shí),關(guān)注硬件的可伸縮性往往比關(guān)注容量或效率更重要。如果需要,可伸縮性可以給予你獲得更好性能的選擇,可伸縮性也可以更容易實(shí)現(xiàn)。有時(shí),設(shè)計(jì)人員費(fèi)了九牛二虎之力才提高了少許容量,其開(kāi)銷還不如多買一些硬件。換句話說(shuō),假設(shè)Camel的費(fèi)用比Swordfish高,高出的部分正好可以買幾臺(tái)服務(wù)器,那么選擇Swordfish可能更合算,盡管你目前只需要40tps。現(xiàn)在人們經(jīng)常抱怨軟件對(duì)硬件的依賴性越來(lái)越大,有時(shí)為了運(yùn)行某些軟件就不得不對(duì)硬件進(jìn)行升級(jí),就像我一樣,為了用最新版本的Word,就必須不斷地升級(jí)筆記本電腦。但是總的來(lái)說(shuō),購(gòu)買新硬件還是比修改舊軟件來(lái)得便宜。同樣,增加更多的服務(wù)器也比增加更多的程序員來(lái)得便宜——只要你的系統(tǒng)有足夠的可伸縮性。
0.5 模式模式的概念早就有了。我在這里不想把這段歷史重新演繹一遍。只是想簡(jiǎn)單談?wù)勎覍?duì)模式和它們?yōu)槭裁词敲枋鲈O(shè)計(jì)的重要手段的一些看法。
模式?jīng)]有統(tǒng)一的定義??赡茏詈玫钠瘘c(diǎn)是Christopher Alexander給出的定義(這也是許多模式狂熱者的靈感來(lái)源):“每一個(gè)模式描述了一個(gè)在我們周圍不斷重復(fù)發(fā)生的問(wèn)題以及該問(wèn)題解決方案的核心。這樣,你就能一次又一次地使用該方案而不必做重復(fù)勞動(dòng)”[Alexander et al.]。盡管Alexander是建筑家,他談?wù)摰氖墙ㄖJ?,但其定義也能很好地適用于軟件業(yè)。模式的核心就是特定的解決方案,它有效而且有足夠的通用性,能解決重復(fù)出現(xiàn)的問(wèn)題,模式的另一種視角是把它看成一組建議,而創(chuàng)造模式的藝術(shù)則是將很多建議分解開(kāi)來(lái),形成相互獨(dú)立的組,在此基礎(chǔ)上可以相對(duì)獨(dú)立地討論它們。
模式的關(guān)鍵點(diǎn)是它們?cè)从趯?shí)踐。必須觀察人們的工作過(guò)程,發(fā)現(xiàn)其中好的設(shè)計(jì),并找出“這些解決方案的核心”。這并不是一個(gè)簡(jiǎn)單的過(guò)程,但是一旦發(fā)現(xiàn)了某個(gè)模式,他將是非常有價(jià)值的。對(duì)于我來(lái)說(shuō),價(jià)值之一是能夠撰寫這樣一本參考書(shū)。你不必通讀本書(shū)的全部?jī)?nèi)容,也不必通讀所有有關(guān)于模式的書(shū)。你只需要了解到這些模式都是干什么的,它們解決什么問(wèn)題,它們是如何解決問(wèn)題的,就足夠了。這樣,一旦碰到類似問(wèn)題,就可以從書(shū)中找出相應(yīng)的模式。那時(shí),再深入了解相應(yīng)的模式也不遲。
一旦需要使用模式,就必須知道如何將它運(yùn)用于當(dāng)前的問(wèn)題。使用模式的關(guān)鍵之一是不能盲目使用,這也是模式工具為什么都那么慘的原因。我認(rèn)為模式是一種“半生不熟品”,為了用好它,還必須在自己的項(xiàng)目中把剩下的那一半“火候”補(bǔ)上。我本人每次在使用模式時(shí),都會(huì)東改一點(diǎn)西改一點(diǎn)。因此你會(huì)多次看到同一解決方案,但沒(méi)有一次是完全相同的。
每個(gè)模式相對(duì)獨(dú)立,但又不彼此孤立。有時(shí)候它們相互影響,如影隨形。例如,如果在設(shè)計(jì)中使用了領(lǐng)域模型,那么經(jīng)常還會(huì)用到類表繼承。模式的邊界本來(lái)也是模糊的,我在本書(shū)中也盡量讓它們各自獨(dú)立。如果有人說(shuō)“使用工作單元”,你就可以直接去看工作單元這個(gè)模式如何使用,而不必閱讀全書(shū)。
如果你是一個(gè)有經(jīng)驗(yàn)的企業(yè)應(yīng)用設(shè)計(jì)師,也許會(huì)對(duì)大多數(shù)模式都很熟悉。希望本書(shū)不會(huì)給你帶來(lái)太大的失望。(實(shí)際上我在前言里面已經(jīng)提醒過(guò)了。)模式不是什么新鮮概念。因此,撰寫模式書(shū)籍的作者們也不會(huì)聲稱我們“發(fā)明”了某某模式,而是說(shuō)我們“發(fā)現(xiàn)”了某某模式。我們的職責(zé)是記錄通用的解決方案,找出其核心,并把最終的模式記錄下來(lái)。對(duì)于一個(gè)高級(jí)設(shè)計(jì)師,模式的價(jià)值并不在于它給予你一些新東西,而在于它能幫助你更好地交流。如果你和你的同事都明白什么是遠(yuǎn)程外觀,你就可以這樣非常簡(jiǎn)潔地交流大量信息:“這個(gè)類是一個(gè)遠(yuǎn)程外觀模式。”也可以對(duì)新人說(shuō):“用數(shù)據(jù)傳輸對(duì)象模式來(lái)解決這個(gè)問(wèn)題?!彼麄兙涂梢圆檎冶緯?shū)來(lái)搞清楚如何做。模式為設(shè)計(jì)提供了一套詞匯,這也是為什么模式的名字這么重要的原因。
本書(shū)的大多數(shù)模式是用來(lái)解決企業(yè)應(yīng)用的,基本模式一章(見(jiàn)第18章)則更通用一些。我把它們包含進(jìn)來(lái)的原因是:在前面的討論中,我引用了這些通用的模式。
0.5.1 模式的結(jié)構(gòu)每個(gè)作者都必須選擇表達(dá)模式的形式。一些人采用的表達(dá)基于模式的一些經(jīng)典教材如[Alexander et al.]、[Gang of Four]或[POSA]。另一些人用他們自己的方式。我在這個(gè)問(wèn)題上也斟酌了很久。一方面我不想象GOF一樣太精煉,另一方面我還要引用他們的東西。這就形成了本書(shū)的模式結(jié)構(gòu)。
第一部分是模式的名字。模式名非常重要,因?yàn)槟J降哪康闹痪褪菫樵O(shè)計(jì)者們交流提供一組詞匯。因此,如果我告訴你Web服務(wù)器是用前端控制器和轉(zhuǎn)換試圖構(gòu)建的,而你又了解這些模式,那么你對(duì)我的Web服務(wù)器的架構(gòu)就會(huì)非常清楚了。
接下來(lái)的兩部分是相關(guān)的:意圖和概要。意圖用一兩句話總結(jié)模式;概要是模式的一種可視化表示,通常是(但不總是)一個(gè)UML圖。這主要是想給模式一個(gè)簡(jiǎn)單的概況,以幫助記憶。如果你對(duì)模式已經(jīng)“心知肚明”,只是不知道它的名字,那么模式的意圖和概要這兩部分就能為你提供足夠的信息。
接下來(lái)的部分描述了模式的動(dòng)機(jī)。這可能不是該模式所能解決的唯一問(wèn)題,但卻是我認(rèn)為最具代表性的問(wèn)題。
“運(yùn)行機(jī)制”部分描述了解決方案。在這一部分,我會(huì)討論一些實(shí)現(xiàn)問(wèn)題以及我遇到的變化情況。我會(huì)盡可能獨(dú)立于平臺(tái)來(lái)討論——也有一個(gè)部分是針對(duì)平臺(tái)來(lái)討論的,如果不感興趣可以跳過(guò)這部分。為了便于解釋,我用了一些UML圖來(lái)輔助說(shuō)明。
“使用動(dòng)機(jī)”部分描述了模式何時(shí)被使用。這部分討論是使我選擇該模式而不是其他模式的權(quán)衡考慮。本書(shū)中很多模式都可以相互替代,例如頁(yè)面控制器和前端控制器可以相互替代。很少有什么模式是非它不可的。因此,每當(dāng)我選擇了一種模式之后,我總是問(wèn)自己“你什么時(shí)候不用它?”這個(gè)問(wèn)題也經(jīng)常驅(qū)使我選擇其他方案。
“進(jìn)一步閱讀”部分給出了與該模式相關(guān)的其他讀物。它并不完善。我只選擇我認(rèn)為有助于理解模式的參考文獻(xiàn),所以我去掉了對(duì)本書(shū)內(nèi)容沒(méi)有價(jià)值的任何討論,當(dāng)然其中也可能會(huì)遺漏一些我不知道的模式。我也沒(méi)有提到一些我認(rèn)為可能讀者無(wú)法找到的參考文獻(xiàn),再就是一些不太穩(wěn)定的Web鏈接。
我喜歡為模式增加一個(gè)或幾個(gè)例子。每個(gè)例子都非常簡(jiǎn)單,它們是用Java語(yǔ)言或C#語(yǔ)言編寫的。我之所以選擇兩種語(yǔ)言,是因?yàn)樗鼈兛赡苁悄壳敖^大多數(shù)專業(yè)程序員都能讀懂的語(yǔ)言。必須注意,例子本身不是模式。當(dāng)你使用模式時(shí),不要想當(dāng)然地認(rèn)為它會(huì)和例子一樣,也不要把例子看成某種形式的宏替換。我把例子編得盡量簡(jiǎn)單以突出其中模式相關(guān)的部分。當(dāng)然,省略的部分并不是不重要,只是它們一般都特定于具體環(huán)境,這也是為什么模式在使用時(shí)一般都必須做適當(dāng)調(diào)整的原因。
為了盡量使例子簡(jiǎn)單但是又能夠突出核心意思,我主要選擇那些簡(jiǎn)單而又明確的例子,而不是那些來(lái)自于系統(tǒng)中的復(fù)雜例子。當(dāng)然,在簡(jiǎn)單和過(guò)分之間掌握平衡是不容易的,但是我們必須記?。哼^(guò)分強(qiáng)調(diào)具體應(yīng)用環(huán)境反而會(huì)增加模式的復(fù)雜性,使得模式的核心內(nèi)容不易理解。
這就是為什么我在選擇例子時(shí)選取的是一些相互獨(dú)立的例子而不是相互關(guān)聯(lián)的例子的原因。獨(dú)立的例子有助于對(duì)模式的理解。但是在如何將這些模式聯(lián)合在一起使用上卻支持不多。相互關(guān)聯(lián)的例子則相反,它體現(xiàn)了模式間是如何相互作用的,但是對(duì)其中每個(gè)模式的理解卻依賴于對(duì)其他所有模式的理解。理論上,是可以構(gòu)造出既相互關(guān)聯(lián)又相互獨(dú)立的例子,但這是一項(xiàng)非常艱巨的工作——至少對(duì)于我來(lái)說(shuō)是這樣。因此,我選擇了相互獨(dú)立的例子。
例子中的代碼本身也主要用來(lái)增強(qiáng)對(duì)思想的理解。因此,在其他一些方面考慮可能不夠——特別是錯(cuò)誤處理,在這方面,我沒(méi)有花費(fèi)很多筆墨,因?yàn)榈侥壳盀橹?,我還沒(méi)有得出錯(cuò)誤處理方面的模式。在此,那些代碼純粹用來(lái)說(shuō)明模式,而并不是用來(lái)顯示如何對(duì)任何特定的業(yè)務(wù)問(wèn)題進(jìn)行建模。
正是由于這些原因,我沒(méi)有把這些代碼放到我的網(wǎng)站上供大家下載。為了讓那些基本的思想在應(yīng)用設(shè)置下有所意義,本書(shū)的每個(gè)樣例代碼都充滿著太多的“腳手架”來(lái)簡(jiǎn)化它們。
并不是每個(gè)模式中都包含上面所述的各個(gè)部分。如果我不能想出很好的例子或動(dòng)機(jī)等內(nèi)容,我就會(huì)把相應(yīng)部分省略。
0.5.2 模式的局限性正如我在前言中所述,對(duì)于企業(yè)應(yīng)用開(kāi)發(fā)而言,本書(shū)介紹的模式并不全面。我對(duì)本書(shū)的要求,不在于它是否全面,而在于它是否有用。模式這個(gè)領(lǐng)域太大了,單憑一個(gè)人的頭腦是無(wú)法做到面面俱到的,更不用說(shuō)是一本書(shū)了。
本書(shū)中所列的模式都是我在具體領(lǐng)域中遇到的,但這并不表明我已經(jīng)理解了每一個(gè)模式以及它們之間的關(guān)系。本書(shū)的內(nèi)容只是反映了我在寫書(shū)時(shí)的理解,在編寫本書(shū)的過(guò)程中,我對(duì)相關(guān)內(nèi)容的理解也不斷發(fā)展和加深,當(dāng)然,在本書(shū)發(fā)表之后,我仍然希望本人對(duì)模式的理解還能夠繼續(xù)發(fā)展。對(duì)于軟件開(kāi)發(fā)而言,有一點(diǎn)是可以肯定的,那是軟件開(kāi)發(fā)永遠(yuǎn)不會(huì)停止。
當(dāng)你使用模式時(shí)請(qǐng)記?。核鼈冎皇情_(kāi)始,而不是結(jié)束。任何作者去囊括項(xiàng)目開(kāi)發(fā)中的所有變化和技術(shù)是不可能的。我編寫本書(shū)的目的也只是作為一個(gè)開(kāi)始,希望它能夠把我自己的和我所了解的經(jīng)驗(yàn)和教訓(xùn)傳遞給讀者,你們可以在此基礎(chǔ)上繼續(xù)努力。請(qǐng)大家記住:所有模式都是不完備的,你們都有責(zé)任在自己的系統(tǒng)中完善它們,你們也會(huì)在這個(gè)過(guò)程中得到樂(lè)趣。
——選自:《企業(yè)應(yīng)用架構(gòu)模式》 [Patterns of Enterprise Application Architecture] [英] 福勒 著;王懷民,周斌 譯
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/30009.html
摘要:摘要隨著越來(lái)越多的業(yè)務(wù)接入云計(jì)算,云上擁有的各類資源也越來(lái)越多,用戶如何時(shí)時(shí)對(duì)其擁有的各類資源進(jìn)行統(tǒng)計(jì)分析成為一個(gè)難題。 摘要: 隨著越來(lái)越多的業(yè)務(wù)接入云計(jì)算,云上擁有的各類資源也越來(lái)越多,用戶如何時(shí)時(shí)對(duì)其擁有的各類資源進(jìn)行統(tǒng)計(jì)分析成為一個(gè)難題。ECS控制臺(tái)針對(duì)這一問(wèn)題,推出資源概覽功能,目前支持實(shí)例和存儲(chǔ)兩種云資源的統(tǒng)計(jì)和分析功能,如果您有其它任何的數(shù)據(jù)可視化需求,歡迎留言告訴我們。...
摘要:事實(shí)上,大多數(shù)企業(yè)會(huì)從兩家或更多的服務(wù)商那里采購(gòu)云服務(wù),這一趨勢(shì)將在年進(jìn)一步流行起來(lái),并將帶動(dòng)微軟阿里巴巴谷歌和甲骨文的收入。云計(jì)算實(shí)際上已經(jīng)成為了推動(dòng)數(shù)字化轉(zhuǎn)型和現(xiàn)代化IT組合的平臺(tái)。越來(lái)越多的企業(yè)正通過(guò)租用亞馬遜網(wǎng)絡(luò)服務(wù)(AWS)、微軟和谷歌等廠商提供的軟件,享受由此帶來(lái)的業(yè)務(wù)敏捷性或成本節(jié)約等優(yōu)勢(shì)。 事實(shí)上,大多數(shù)企業(yè)會(huì)從兩家或更多的服務(wù)商那里采購(gòu)云服務(wù),這一趨勢(shì)將在2019年進(jìn)...
摘要:事實(shí)上,大多數(shù)企業(yè)會(huì)從兩家或更多的服務(wù)商那里采購(gòu)云服務(wù),這一趨勢(shì)將在年進(jìn)一步流行起來(lái),并將帶動(dòng)微軟阿里巴巴谷歌和甲骨文的收入。 云計(jì)算實(shí)際上已經(jīng)成為了推動(dòng)數(shù)字化轉(zhuǎn)型和現(xiàn)代化IT組合的平臺(tái)。越來(lái)越多的企業(yè)正通過(guò)租用亞馬遜網(wǎng)絡(luò)服務(wù)(AWS)、微軟和谷歌等廠商提供的軟件,享受由此帶來(lái)的業(yè)務(wù)敏捷性或成本節(jié)約等優(yōu)勢(shì)。事...
摘要:什么是架構(gòu),什么是架構(gòu)師這似乎是聊架構(gòu)話題時(shí)永恒的問(wèn)題。代碼寫的好就是架構(gòu)嗎顯然不是。一個(gè)架構(gòu)師需要足夠的技術(shù)的寬度。 什么是架構(gòu),什么是架構(gòu)師?這似乎是聊架構(gòu)話題時(shí)永恒的問(wèn)題。代碼寫的好就是架構(gòu)嗎?顯然不是。代碼寫的好只是表象,做所有事情都需要規(guī)劃,尤其是一個(gè)復(fù)雜的軟件系統(tǒng),這更需要規(guī)劃,否則可能連一行代碼都寫不出。復(fù)雜...
閱讀 3523·2023-04-25 15:52
閱讀 590·2021-11-19 09:40
閱讀 2618·2021-09-26 09:47
閱讀 1037·2021-09-22 15:17
閱讀 3562·2021-08-13 13:25
閱讀 2247·2019-08-30 15:56
閱讀 3476·2019-08-30 13:56
閱讀 2113·2019-08-30 11:27