|
一、什么是架構(gòu) 1. 和架構(gòu)相關(guān)的幾個(gè)問(wèn)題域 架構(gòu)需要解決的非業(yè)務(wù)問(wèn)題域包括如下: A 系統(tǒng)目標(biāo):系統(tǒng)性能,穩(wěn)定性. B.項(xiàng)目目標(biāo):開(kāi)發(fā)成本,質(zhì)量 C.項(xiàng)目過(guò)程:需求的不確定性和開(kāi)發(fā)過(guò)程的團(tuán)隊(duì)協(xié)作性 不同的問(wèn)題域,解決之道也不相同!而同一問(wèn)題域的不同層次的要求,解決之道也不盡相同。 2. 什么是架構(gòu) 架構(gòu)到底是啥,愚以為下面的這段英文描述的很清楚。 That‘s like asking, what is culture? Culture is the way you do things in a group of people. Architecture is the way you do things in a software product. You could argue by analogy, then, that architecture is to a software product as culture is to a team. It is how that team has established and chosen its conventions, Which leads us inevitably to the question of “goodness”? How do you know if an architecture is good? Consider an architecture that isn‘t built using a strong domain model, and instead relies heavily on stored procedures. That might be OK, or it might not be OK. You could have decided that part of your architecture is to use a really strong domain model and not use stored procedures, right? So an architecture is some reasonable regularity about the structure of the system, the way the team goes about building its software, and how the software responds and adapts to its own environment. How well the architecture responds and adapts, and how well it goes through that construction process, is a measure of whether that architecture is any good. The system architecture determines how hard or easy it is to implement a given feature. Good architectures are those in which it is considered easy to create the features desired. In that the way to judge whether an architecture is good is whether the architecture is good for the purposes to which it is applied. The definition of goodness has to be related to fitness for purpose. Is this glove good? I don‘t know. What are you doing with the glove? Are you throwing snowballs, cooking barbeques, or playing golf? There‘s a set of changes that are going to occur to a software system over time. Probably the utilitarian or most useful definition of goodness is the answer to this question: are the changes that will keep this system successful in this domain in this product line relatively easy? If they are, then it‘s probably a good architecture. 3. 架構(gòu)的背后 為了實(shí)現(xiàn)架構(gòu)的目標(biāo)涉及到以下三個(gè)方面:技術(shù),組織和過(guò)程。這里舉例說(shuō)明。 1) 技術(shù)對(duì)開(kāi)發(fā)效率和運(yùn)行性能,以及組織和過(guò)程的影響。 案例A.映射的問(wèn)題。公司產(chǎn)品的一個(gè)重要需求是根據(jù)客戶輸入,映射到PDF文件上。技術(shù)上整體實(shí)現(xiàn)需要四個(gè)步驟:在PDF文件上畫(huà)好所有的數(shù)據(jù)域,通過(guò)讀入一個(gè)XML映射文件,獲得運(yùn)行數(shù)據(jù)并生成FDF,合并FDF和PDF生成目標(biāo)文件。后兩步工作都由代碼自動(dòng)化了,因而實(shí)現(xiàn)的主要工作在于前兩步。 在第一個(gè)實(shí)現(xiàn)版本里,XML映射文件的DTD太簡(jiǎn)單,致使一個(gè)xml文件至少在4000行左右,同時(shí)xml文件太verbose了。這樣的結(jié)果直接導(dǎo)致運(yùn)行系統(tǒng)在峰值時(shí),由于XML消耗了大量?jī)?nèi)存,1G的內(nèi)存根本吃不消;同時(shí)對(duì)XML解析執(zhí)行使用了CPU的大量時(shí)間;導(dǎo)致開(kāi)發(fā)人員需要做大量的工作,開(kāi)發(fā)效率降低了,通常需要盡一周才能完成一個(gè)xml文件,員工都不愿意做;也導(dǎo)致開(kāi)發(fā)過(guò)程的漫長(zhǎng), 開(kāi)發(fā)部門(mén)對(duì)于BA部門(mén)和ST部門(mén)的要求反應(yīng)變的緩慢。 在第二個(gè)版本的實(shí)現(xiàn)中,重新實(shí)現(xiàn)了DTD,加入了大量的關(guān)鍵字同時(shí)也消除了verbose,大量的縮小了XML大小,從4000多行減低到900多行。不僅減低了內(nèi)存使用,提高執(zhí)行效率;也提高了開(kāi)發(fā)效率,基本只要一天就可以完成一個(gè)映射文件。同時(shí)對(duì)BA部門(mén)和ST部門(mén)的反應(yīng)也快了。 案例B:腳本的問(wèn)題。產(chǎn)品在web層提供了腳本支持,出于方便開(kāi)發(fā)的目的。但是沒(méi)有對(duì)腳本的環(huán)境限制,腳本可以做系統(tǒng)程序的大部分工作。導(dǎo)致開(kāi)發(fā)人員偷懶,在web層混入了大量業(yè)務(wù)邏輯代碼。最終造成業(yè)務(wù)邏輯分散而不可控制。 2) 組織結(jié)構(gòu)對(duì)技術(shù),開(kāi)發(fā)效率和應(yīng)變能力的影響。 案例A.部門(mén)的分工問(wèn)題。開(kāi)發(fā)部門(mén)根據(jù)不同的職責(zé),分成A,B和C等數(shù)個(gè)小組。大部分開(kāi)發(fā)中互不相干。但也有時(shí)候,需要跨組的支持,比如B要實(shí)現(xiàn)某個(gè)需求,需要A在一定條件在記錄一個(gè)或多個(gè)信息。因?yàn)槊總€(gè)開(kāi)發(fā)人員各自負(fù)責(zé)一部分工作,導(dǎo)致跨組溝通的困難。同時(shí)由于整個(gè)開(kāi)發(fā)部采取任務(wù)績(jī)效,有時(shí)間壓力,加上只是一個(gè)小的要求。于是在A人員的同意下,B人員直接在A代碼中寫(xiě)入業(yè)務(wù)邏輯。每次都是這樣的小改動(dòng),不斷的發(fā)展后,代碼開(kāi)發(fā)變凌亂。 案例B.開(kāi)發(fā)的歷史問(wèn)題,當(dāng)某個(gè)開(kāi)發(fā)人員寫(xiě)下的代碼,有是問(wèn)題的,接手開(kāi)發(fā)人員由于文檔不全以及沒(méi)有測(cè)試用例,不愿意承擔(dān)變化的代價(jià),選擇小修小補(bǔ),這個(gè)小修小補(bǔ)有可能和有問(wèn)題的代碼混雜,導(dǎo)致更大的代碼。 3) 過(guò)程對(duì)開(kāi)發(fā)效率和應(yīng)變能力,以及組織的影響 案例A.過(guò)程的問(wèn)題。開(kāi)發(fā)部門(mén)的上下游部門(mén)BA部門(mén)和ST部門(mén)的合作關(guān)系。ST部門(mén)的績(jī)效考核,考核基于發(fā)現(xiàn)錯(cuò)誤的數(shù)量,導(dǎo)致ST為了完成任務(wù),提出一些非正常性要求。PM部門(mén)出于部門(mén)的方便通常提出一些實(shí)現(xiàn)難度比較大要求。開(kāi)發(fā)部門(mén)本身又存在時(shí)間壓力,導(dǎo)致一些需求的實(shí)現(xiàn)本應(yīng)在低一層的代碼中實(shí)現(xiàn)的,卻在高層用蹩足的方式實(shí)現(xiàn)。 案例B.幫助系統(tǒng)的問(wèn)題。幫助系統(tǒng)一開(kāi)始采用一個(gè)個(gè)單獨(dú)分散的靜態(tài)頁(yè)面。出于性能的考慮和部門(mén)負(fù)責(zé)考慮。幫助系統(tǒng)不斷改進(jìn)中,過(guò)程缺乏組織性,文件的命名規(guī)則隨意,存儲(chǔ)位置隨意,造成了管理的混亂。直接的后果是頁(yè)面的入口混亂和各自引用關(guān)系混亂。 在幫助系統(tǒng)的第二版,從靜態(tài)頁(yè)面轉(zhuǎn)成動(dòng)態(tài)頁(yè)面。采取統(tǒng)一分類(lèi)和命名規(guī)則,并統(tǒng)一了入口。同時(shí)采取分級(jí)管理引用關(guān)系,適度冗余。雖然減低了運(yùn)行性能。但提高了開(kāi)發(fā)效率和可維護(hù)性。 二、架構(gòu)的性能問(wèn)題解決討論 性能問(wèn)題——嗯,一個(gè)非常神圣而高深的問(wèn)題的。從我剛剛開(kāi)始工作的時(shí)候,至今依然是。然而我相信,一定存在一個(gè)基本的思路和方法,我以為解決性能問(wèn)題的工作還是在于分解,通過(guò)分解來(lái)確定問(wèn)題域。 先介紹三個(gè)公式性能問(wèn)題的公式: 總處理單量 = 總處理時(shí)間/ 單筆請(qǐng)求處理時(shí)間 * 總并發(fā)數(shù) 這個(gè)公式另一個(gè)寫(xiě)法為: 總處理時(shí)間 = 單筆請(qǐng)求處理時(shí)間 * 總處理單量 / 總并發(fā)數(shù) 不同的寫(xiě)法代表不同個(gè)關(guān)注點(diǎn),適合不同類(lèi)型的業(yè)務(wù)類(lèi)型, 一般說(shuō)前一種寫(xiě)法代表在線請(qǐng)求的,后一種寫(xiě)法代表后臺(tái)batch。 也有客戶給明確要求系統(tǒng)要支持xxx并發(fā),這個(gè)就需要了解客戶的這個(gè)并發(fā)數(shù)是如何計(jì)算得來(lái),需要通過(guò)分析客戶的業(yè)務(wù),而通常是根據(jù)總處理單量來(lái)確定客戶實(shí)際的并發(fā)數(shù)。 但無(wú)論如如何,四個(gè)變量中,總處理單量和總處理時(shí)間是先被確定的,換句話說(shuō)需要關(guān)注是單筆請(qǐng)求處理時(shí)間和并發(fā)數(shù),也就是降低單筆請(qǐng)求處理時(shí)間或者增加并發(fā)數(shù)。 對(duì)于單筆請(qǐng)求處理時(shí)間,其公式為: 單筆請(qǐng)求處理時(shí)間 = 數(shù)據(jù)計(jì)算時(shí)間 + 數(shù)據(jù)讀寫(xiě)時(shí)間+其它技術(shù)導(dǎo)致時(shí)間消耗 很顯然降低單筆請(qǐng)求處理時(shí)間就需要降低三個(gè)因素消耗的時(shí)間。 1.降低單筆請(qǐng)求處理時(shí)間第一原則是, 只計(jì)算一次.緩存計(jì)算結(jié)果 2.降低數(shù)據(jù)讀取時(shí)間,分三種 2.1. Global的,系統(tǒng)啟動(dòng)時(shí)加載 2.2. Long Time, 可采用LRU方式cache 2.2. Per operation. 第一次訪問(wèn)加載,operation結(jié)束后丟棄. 3.降低數(shù)據(jù)寫(xiě)入時(shí)間 例如文件寫(xiě)入通過(guò)buffer一次flush;對(duì)于SQL采用batch提交(hibernate的做法)。 4 .改進(jìn)計(jì)算時(shí)間,針對(duì)不同技術(shù)結(jié)構(gòu)采用不同手段。 4.1.讓計(jì)算支持并發(fā),提高性能,例如采用MapReduce的方式 4.2.改進(jìn)算法.例如數(shù)據(jù)庫(kù)中的SQL改進(jìn). 4.3.減少不必要計(jì)算時(shí)間. 5.減少其它技術(shù)原因?qū)е碌南?/span> 如JVM的GC導(dǎo)致性能消耗等 對(duì)于總并發(fā)數(shù),其公式為: 總并發(fā)數(shù) = 單機(jī)服務(wù)器并發(fā)能力 * 總并發(fā)服務(wù)器數(shù) 那么如何確定那些因素需要調(diào)整呢,在于兩個(gè)方面的分解: 1. 業(yè)務(wù)層面 業(yè)務(wù)層面只是指通過(guò)業(yè)務(wù)行為分析, 把性能問(wèn)題分解為不同的部分,每個(gè)部分面臨性能壓力現(xiàn)狀和目標(biāo),最終確定需要優(yōu)化的問(wèn)題域. 業(yè)務(wù)層面分解包括4個(gè)內(nèi)容: 功能, 內(nèi)容,時(shí)間和區(qū)域.最重要的是前三個(gè). 以ebay為例, ebay對(duì)于前端功能劃分劃分為70多個(gè)功能,不同的服務(wù)器處理不同的功能. 內(nèi)容是指內(nèi)容熱點(diǎn),比如對(duì)于search來(lái)說(shuō),就按體育,數(shù)碼,音樂(lè)等劃分,不同內(nèi)容有不同熱點(diǎn)數(shù)據(jù),以及不同搜索關(guān)鍵匹配. 時(shí)間, 時(shí)間是一個(gè)非常重要的因素,在一些特點(diǎn)是時(shí)間段呢,性能的要求會(huì)非常高.比如下半夜的訪問(wèn)點(diǎn)擊量和白天的就有不同.對(duì)于一些batch來(lái)說(shuō), 月末或者年末處理的單量就有明顯的提高,比如分紅險(xiǎn)的記息,平時(shí)每天只有7000單,而年末會(huì)有12w單. 地點(diǎn)劃分,不太常見(jiàn),不過(guò)也有助于分配計(jì)算資源. 業(yè)務(wù)層面的分析不僅是確定問(wèn)題所在,還是確定優(yōu)化的策略.比如有一個(gè)batch計(jì)算,執(zhí)行時(shí)間比較長(zhǎng),而通過(guò)業(yè)務(wù)分析,發(fā)現(xiàn)該計(jì)算只針對(duì)特定的業(yè)務(wù), 系統(tǒng)全部有效單量是12w單,而符合計(jì)算要求的只有3000單,只要加上一個(gè)前置判斷就可以免除無(wú)謂的計(jì)算,運(yùn)行時(shí)間減少數(shù)個(gè)小時(shí)(大約0.2秒一單). 2. 技術(shù)層面 系統(tǒng)建立時(shí)技術(shù)結(jié)構(gòu),通常一個(gè)系統(tǒng)結(jié)構(gòu)如下:接入網(wǎng)絡(luò),Web服務(wù)器,應(yīng)用服務(wù)器,以及數(shù)據(jù)庫(kù)服務(wù)器. 在這樣結(jié)構(gòu)下,要小心的分析和驗(yàn)證系統(tǒng)性能的瓶頸,需要優(yōu)化Web服務(wù)器,或者提高數(shù)據(jù)庫(kù)并發(fā)能力等等。這部分網(wǎng)上的資料非常多。 三、架構(gòu)的開(kāi)發(fā)成本以及品質(zhì)問(wèn)題解決討論 架構(gòu)一個(gè)重大關(guān)注點(diǎn)在于控制開(kāi)發(fā)成本,這點(diǎn)很重要,因?yàn)橥ǔVv維護(hù)成本是開(kāi)發(fā)成本的3倍。降低開(kāi)發(fā)成本核心,在于提高效率,這也意味著提高了開(kāi)發(fā)對(duì)需求的響應(yīng)時(shí)間,而時(shí)間對(duì)公司來(lái)說(shuō)是重要的。 提高開(kāi)發(fā)效率和品質(zhì)的基本手段是分解——即充分的分離系統(tǒng)中不同的關(guān)注點(diǎn),好處不用說(shuō)了,可以并發(fā)的工作,每個(gè)人面對(duì)的問(wèn)題都簡(jiǎn)單而容易操作。而與分解對(duì)應(yīng)的集成,只有提供了好的集成能力,分解才成為現(xiàn)實(shí),而只有分解了,才能清晰的提供業(yè)務(wù)更多適應(yīng)性。 分解和集成的手段分為編程語(yǔ)言和技術(shù)框架兩個(gè)層面。所謂語(yǔ)言就是強(qiáng)框架,而框架就是弱語(yǔ)言。 現(xiàn)代面向?qū)ο蟮恼Z(yǔ)言提供如下能力:抽象和派生能力,以及接口隔離能力。實(shí)際提供兩種分解和集成能力: 1. 把邏輯分解在兩個(gè)層次中,而通過(guò)繼承的方式把兩個(gè)部分集成在一起。 2. 把邏輯的外觀和實(shí)現(xiàn)分解在兩個(gè)地方,而通過(guò)接口實(shí)現(xiàn)的方式把兩部分集成在一起。 另一種語(yǔ)言AspectJ或者C#語(yǔ)言2.0之后提供的特性:把流程邏輯,分解在不同的地方,而通過(guò)簽名匹配,利用代碼生成的方式來(lái)把幾部分集成在一起。 然而語(yǔ)言提供的集成能力,畢竟底層,而且有限,擴(kuò)展起來(lái)也格外小心。因而技術(shù)框架提供另外的集成能力就格外重要: 1. 對(duì)象關(guān)聯(lián)關(guān)系的分解和集成,如Spring提供容器管理能力 2. 模塊間關(guān)聯(lián)關(guān)系的分解和集成,如OSGi,ESB等 3. 不同系統(tǒng)的類(lèi)型分解和集成,如Spring利用動(dòng)態(tài)代理提供的Exporter模式。 4. 流程邏輯的分解和集成,如Spring Web Flow以及jBPM。 討論完手段,現(xiàn)在要轉(zhuǎn)身看看我們面臨的問(wèn)題域了;問(wèn)題域可分解為兩種類(lèi)型,業(yè)務(wù)上和技術(shù)上。(又見(jiàn)分解,分而治之真是老祖宗傳下的靈丹妙藥啊) 1. 業(yè)務(wù)上。問(wèn)題域分解為,邏輯的縱向抽象層次,以及邏輯的橫向模塊分解和集成。 2. 技術(shù)上。問(wèn)題域分解為,縱向的技術(shù)主題,以及橫向的技術(shù)職責(zé)的分解和集成。 所以通常而言,領(lǐng)域模型設(shè)計(jì)中,模塊分解,抽象分層和職責(zé)分層都是重要手段。問(wèn)題域?yàn)椋毫鞒?,業(yè)務(wù)實(shí)體和計(jì)算(包括規(guī)則)。
BTW:通常語(yǔ)言做為架構(gòu)的基礎(chǔ)引入和更換是有巨大風(fēng)險(xiǎn)的;而通過(guò)提供強(qiáng)大的框架能力,框架盡可能多的完成技術(shù)問(wèn)題,并通過(guò)元數(shù)據(jù),模式以及約定降低業(yè)務(wù)和框架的耦合。避免因?yàn)榭蚣苌?jí)帶來(lái)不必要的成本。 從技術(shù)手段上,提高開(kāi)發(fā)效率的另外兩個(gè)手段是代碼生成和類(lèi)庫(kù)引用。但代碼生成和類(lèi)庫(kù)引用,都只解決了邏輯的分解能力,沒(méi)有提供集成能力,所以一般情況下需要提供框架集成,尤其代碼生成需要在系統(tǒng)的最外層,避免集成帶來(lái)的問(wèn)題。 對(duì)于開(kāi)發(fā)團(tuán)隊(duì)來(lái)說(shuō),額外面臨一個(gè)問(wèn)題,組織內(nèi)部的學(xué)習(xí)成本問(wèn)題。 1. 需要保持分解以及集成能力本身的簡(jiǎn)約性 這個(gè)……其實(shí)是一個(gè)culture問(wèn)題,不再羅唆! 2. 采用模式和約定是減少學(xué)習(xí)成本的另一種手段。ROR的興起就是最好的例證。 總結(jié)一下,解決架構(gòu)面臨開(kāi)發(fā)成本問(wèn)題需要如下幾個(gè)方面: 0. 問(wèn)題域 1. 分解與分層 2. 架構(gòu)與類(lèi)庫(kù),Spring,Hibernate。起支撐性作用。 3. 模式和技巧 4. 領(lǐng)域模型 5. 方法論 5.1.開(kāi)發(fā)方法:OO(設(shè)計(jì)模式),F(xiàn)P(函數(shù)式編程)。 5.2.設(shè)計(jì)方法:Domain Model Prototype和業(yè)務(wù)行為的分析模式。 架構(gòu)面臨的品質(zhì)問(wèn)題,則通過(guò)自動(dòng)化測(cè)試,代碼檢測(cè)工具來(lái)完成。 必須大量應(yīng)用自動(dòng)化測(cè)試,減少人工硬調(diào)試的復(fù)雜性,重復(fù)性和不確定性。 自動(dòng)化測(cè)試包括單元測(cè)試和集成測(cè)試。無(wú)論是單元測(cè)試還是集成測(cè)試對(duì)面臨需要脫離隔離依賴(lài)關(guān)系并保證開(kāi)發(fā)的并行性。 |
|
|
來(lái)自: joojo > 《構(gòu)架設(shè)計(jì)》