閱讀提示:本文是讀 kimmking 在 GitChat 上分享的文章 「軟件架構(gòu)發(fā)展歷程分享」后的一些總結(jié)俏险,黑體為段落主題,斜體為一些理解,歡迎批評(píng)指正和探討交流牢裳,如有侵權(quán)及時(shí)聯(lián)系刪除坯苹。文章來源:http://gitbook.cn/books/5a8d689decd7eb74c19ba962/index.html
背景
計(jì)算機(jī)科學(xué)和程序設(shè)計(jì)的飛速發(fā)展隆檀,使得軟件開發(fā)從單人開發(fā)小程序過度到大范圍協(xié)作的工程化時(shí)代,隨之引入了協(xié)作效率問題和軟件復(fù)雜度急速增長(zhǎng)的問題粹湃。協(xié)作效率問題和軟件復(fù)雜度的增長(zhǎng)使得軟件的生命周期中爆發(fā)了大量的不確定性恐仑,造成軟件質(zhì)量無法保證,軟件開發(fā)周期和成本無法控制为鳄。Fred Brooks在1975年出版的軟件工程圣經(jīng)《人月神話》中說過裳仆,沒有能解決所有問題的銀彈,所以人們通過項(xiàng)目研發(fā)過程管理來提高協(xié)作效率孤钦,通過發(fā)展軟件架構(gòu)設(shè)計(jì)方法來抑制由于復(fù)雜度增長(zhǎng)而造成的不確定性歧斟,通過不斷的實(shí)踐和總結(jié)來有效的指導(dǎo)軟件的開發(fā),保障軟件開發(fā)的質(zhì)量偏形、周期和成本静袖。
什么是架構(gòu)
架構(gòu)(Architecture)源于建筑領(lǐng)域,本身是建筑的意思壳猜,也是體系結(jié)構(gòu)的意思勾徽。維基百科中對(duì)(Architecture)的解釋是:規(guī)劃、設(shè)計(jì)和建造建筑物的過程及產(chǎn)物。規(guī)劃更傾向于框架結(jié)構(gòu)的確定喘帚,而設(shè)計(jì)更傾向于具體細(xì)節(jié)的確定畅姊。引入計(jì)算機(jī)領(lǐng)域后,軟件架構(gòu)成為了一個(gè)描述軟件規(guī)劃設(shè)計(jì)技術(shù)的專有名詞吹由,是有關(guān)軟件整體結(jié)構(gòu)(規(guī)劃)與組件(設(shè)計(jì))的抽象描述若未,用于指導(dǎo)大型軟件系統(tǒng)各個(gè)方面的開發(fā)(建造)。
比較公認(rèn)的軟件架構(gòu)定義是2000年的 ANSI(American National Standards Institute)/IEEE (Institute of Electrical and Electronics Engineers)1471 標(biāo)準(zhǔn)中的定義倾鲫。
架構(gòu)過程:在系統(tǒng)整個(gè)生命周期中構(gòu)思粗合、定義、表達(dá)乌昔、記錄隙疚、交流,驗(yàn)證合適實(shí)現(xiàn)磕道,維護(hù)和改進(jìn)架構(gòu)的過程供屉,也就是設(shè)計(jì)過程。
架構(gòu):一個(gè)系統(tǒng)體現(xiàn)在其環(huán)境中的元素溺蕉、關(guān)系的基本概念或?qū)傩粤尕ぃ约捌?b>設(shè)計(jì)和進(jìn)化原則。
架構(gòu)描述:表達(dá)一個(gè)架構(gòu)的工作產(chǎn)出物(通常指的是各種架構(gòu)圖和設(shè)計(jì)文檔)疯特。
架構(gòu)視圖:通過系統(tǒng)的某些關(guān)注點(diǎn)的視角哗魂,表達(dá)一個(gè)系統(tǒng)的工作產(chǎn)出物(例如部署視圖、開發(fā)視圖等)漓雅。
系統(tǒng):包含了一個(gè)或多個(gè)進(jìn)程录别、硬件、軟件故硅、工具與可以滿足需求的人的集合庶灿。
環(huán)境:決定了開發(fā)、操作吃衅、策略和其他影響系統(tǒng)的設(shè)置和條件。
在 UML (Unified Modeling Language 又稱統(tǒng)一建模語言或標(biāo)準(zhǔn)建模語言腾誉,是始于1997年一個(gè)OMG(Object Management Group)標(biāo)準(zhǔn))中徘层,架構(gòu)則被認(rèn)為是系統(tǒng)的組織結(jié)構(gòu)和相關(guān)行為。架構(gòu)可被分解為通過接口互聯(lián)部分的關(guān)系利职,以及相互作用趣效。通過接口相互作用的部分包括類、組件和子系統(tǒng)猪贪。這樣就可以通過 UML 的各種架構(gòu)圖來描述這些對(duì)象和關(guān)系跷敬,從而表達(dá)清楚一個(gè)系統(tǒng)的架構(gòu)。
總結(jié):軟件架構(gòu)是一個(gè)用于指導(dǎo)系統(tǒng)實(shí)現(xiàn)的草圖热押,這個(gè)草圖越詳細(xì)對(duì)于系統(tǒng)實(shí)現(xiàn)的指導(dǎo)意義越重大西傀,貫穿于軟件的整個(gè)生命周期斤寇。在建筑領(lǐng)域,大樓尚未建造前拥褂,就已經(jīng)存在于建筑師的腦海里娘锁;同樣地,系統(tǒng)開始編寫第一行代碼之前饺鹃,就已經(jīng)存在于軟件架構(gòu)師的心里莫秆。
幾個(gè)相關(guān)概念
模式(Pattern)
UML 中給出的解釋更通俗易懂:模式是對(duì)于普遍問題的普遍解決方案。我們可以把一類問題的共性抽象出來悔详,這樣就可以用同樣的處理辦法去解決這些問題镊屎,從而形成模式,所以模式是一些經(jīng)驗(yàn)的總結(jié)茄螃。
類庫(Library)
類庫是一組可復(fù)用的功能或工具的集合杯道,應(yīng)用系統(tǒng)通過調(diào)用它們從而達(dá)到復(fù)用功能的目的。例如责蝠,Windows 應(yīng)用開發(fā)里的各種靜態(tài)或動(dòng)態(tài)鏈接庫 DLL((Dynamic Link Library)文件党巾,Java 開發(fā)中項(xiàng)目里依賴的或者 Maven 中央庫里的各種 jar 包,都是 Library霜医,比如 Apache Commons IO齿拂、HttpClient,Log4j 等肴敛。
框架(Framework)
框架是基于一組類庫或工具署海,在特定領(lǐng)域里根據(jù)一定的規(guī)則組合成的、開放性的應(yīng)用骨架医男,比如 SSM/SSH 框架砸狞,更大范圍來說 Dotnet Framework、JDK 都算是一種框架镀梭。關(guān)于框架與架構(gòu)的關(guān)系刀森,Vasyl Boroviak 曾在 Stack Overflow 網(wǎng)站上通過兩張圖做了形象的對(duì)比:
模塊(Module)
模塊是業(yè)務(wù)或系統(tǒng)的安裝特定維度的一種切分,同時(shí)也可以看做是各種功能按照某種分類聚合的一種形式报账。例如我們的一個(gè)電商系統(tǒng)研底,可以從業(yè)務(wù)上劃分為用戶模塊、商品模塊透罢、訂單模塊榜晦、支付模塊、物流模塊羽圃、售后模塊等乾胶。另一方面,我們也可以說用戶模塊聚合了用戶注冊(cè)、用戶驗(yàn)證等業(yè)務(wù)功能识窿。(模式更側(cè)重于方法斩郎,方案,模塊更側(cè)重實(shí)體腕扶,對(duì)象)
組件(Component)
組件是一組可以復(fù)用的業(yè)務(wù)功能的集合孽拷,包含一些對(duì)象及其行為。組件可以直接被用做業(yè)務(wù)系統(tǒng)的組成部分半抱,粒度一般小于模塊脓恕,也是一種功能的聚合形式。比如日志組件窿侈、權(quán)限組件等炼幔。
服務(wù)(Service)
服務(wù)是一組對(duì)外提供業(yè)務(wù)處理能力的功能,服務(wù)需要使用明確的接口方式(比如 WebService 或 Rest 等)史简,服務(wù)描述里應(yīng)該包括約束和策略(比如參數(shù)乃秀、返回值,使用什么通訊協(xié)議和數(shù)據(jù)格式等)圆兵。
平臺(tái)(Platform)
平臺(tái)一般來說跺讯,是一個(gè)領(lǐng)域或方向上的生態(tài)系統(tǒng),是很多解決方案的集大成者殉农,提供了很多的服務(wù)刀脏、接口、規(guī)范超凳、標(biāo)準(zhǔn)愈污、功能、工具等轮傍。例如 J2EE 平臺(tái)暂雹,包含了企業(yè)級(jí)應(yīng)用開發(fā)里的各種基于 Java 語言和 JVM 虛擬機(jī)運(yùn)行時(shí)的技術(shù)能力。
知乎社區(qū)編程領(lǐng)域優(yōu)秀問題回答者 ze ran 說:
庫是工具箱创夜『脊颍框架是一套通用的解決方案。架構(gòu)是高度抽象的需求挥下,是系統(tǒng)中的不變量揍魂。平臺(tái)是所有可能做的事的集合。
從軟件的生命周期看架構(gòu)設(shè)計(jì)
設(shè)計(jì)期
在設(shè)計(jì)期棚瘟,軟件作為一個(gè)成品還不存在,所以我們可以稱之為概念形態(tài)喜最。此時(shí)架構(gòu)師偎蘸、產(chǎn)品經(jīng)理或需求分析師等人員利用自己的經(jīng)驗(yàn)?zāi)芰Γ瑢?duì)系統(tǒng)的業(yè)務(wù)需求進(jìn)行分析、拆解迷雪、抽象限书,形成業(yè)務(wù)文檔和技術(shù)文檔,以及技術(shù)驗(yàn)證代碼等章咧。這個(gè)階段倦西,架構(gòu)設(shè)計(jì)工作是重中之重,其中包括:
系統(tǒng)分拆:如何把系統(tǒng)拆解為不同的子系統(tǒng)赁严、模塊扰柠、業(yè)務(wù)單元;
技術(shù)選型:使用什么樣的基礎(chǔ)技術(shù)框架或腳手架疼约;
技術(shù)驗(yàn)證:確定核心技術(shù)難點(diǎn)如何解決卤档,檢驗(yàn)?zāi)芊駶M足期望指標(biāo);
接口規(guī)范:系統(tǒng)的內(nèi)部不同部分以何種形式確定接口契約和數(shù)據(jù)通信程剥;
集成方式:系統(tǒng)與外部其他業(yè)務(wù)系統(tǒng)如何進(jìn)行集成劝枣;
技術(shù)規(guī)范:如何規(guī)范開發(fā)、測(cè)試织鲸、部署和運(yùn)維的技術(shù)標(biāo)準(zhǔn)性舔腾;
部署方案:系統(tǒng)如何進(jìn)行物理部署,需要多少機(jī)器搂擦、什么配置稳诚,對(duì)網(wǎng)絡(luò)有什么要求;
運(yùn)維方案:系統(tǒng)如何進(jìn)行技術(shù)性運(yùn)維盾饮,如何日常監(jiān)控采桃、預(yù)警報(bào)警;
……
這個(gè)階段總結(jié)一下就是:業(yè)務(wù)為要丘损,架構(gòu)先行(包括業(yè)務(wù)架構(gòu)和技術(shù)架構(gòu))普办。
實(shí)現(xiàn)期
這個(gè)階段主要是編碼與測(cè)試,準(zhǔn)備部署上線徘钥,是軟件從代碼到最終的生產(chǎn)系統(tǒng)的過程衔蹲,我們可以稱之為代碼形態(tài)。此階段需要考慮的技術(shù)類工作包括:
確保各項(xiàng)技術(shù)規(guī)范和技術(shù)指標(biāo)的執(zhí)行落地呈础,保障高質(zhì)量的代碼舆驶;
指導(dǎo)研發(fā)人員和解決各類技術(shù)問題,提升研發(fā)團(tuán)隊(duì)效率而钞;
制定測(cè)試的技術(shù)性方案和基準(zhǔn)沙廉,自動(dòng)化、性能臼节、安全等撬陵;
配合準(zhǔn)備部署環(huán)境珊皿,運(yùn)維實(shí)施方案落地等。
運(yùn)行期
這個(gè)階段系統(tǒng)上線巨税、驗(yàn)收通過蟋定,已經(jīng)初步穩(wěn)定,然后進(jìn)入維護(hù)階段草添,成為了設(shè)計(jì)期架構(gòu)設(shè)計(jì)草圖的一個(gè)可用實(shí)例驶兜,我們可以稱之為實(shí)例形態(tài)。此時(shí)需要考慮:
發(fā)布上線相關(guān)基礎(chǔ)性工作远寸,包括是否使用持續(xù)集成(CI抄淑,Continuous Integration)、自動(dòng)化發(fā)布等技術(shù)而晒;
運(yùn)維基礎(chǔ)性工作蝇狼,自動(dòng)化運(yùn)維,監(jiān)控等相關(guān)技術(shù)倡怎。
架構(gòu)的形式與特點(diǎn)
設(shè)計(jì)文檔和代碼
我們一般說的架構(gòu)既包括架構(gòu)的設(shè)計(jì)過程迅耘,也包括設(shè)計(jì)的產(chǎn)出物,一般可以包括各類設(shè)計(jì)文檔监署、設(shè)計(jì)圖颤专,也可以包括一些技術(shù)驗(yàn)證代碼、Demo或者其他相關(guān)程序钠乏。文檔的目的在于準(zhǔn)確記錄我們的思維產(chǎn)物栖秕,在軟件尚未實(shí)現(xiàn)時(shí),作為指導(dǎo)藍(lán)圖晓避,盡量精確的描述清楚軟件簇捍。在軟件的實(shí)現(xiàn)過程中,可能隨時(shí)隨著我們的深入研究俏拱,根據(jù)具體情況對(duì)文檔做出局部的一些調(diào)整和修改暑塑。文檔作為結(jié)項(xiàng)或交接的一部分,也是整個(gè)軟件項(xiàng)目的產(chǎn)出物的一部分锅必,成為公司IT 資產(chǎn)的有機(jī)組成部分事格。
架構(gòu)服務(wù)于業(yè)務(wù)
正如19世紀(jì)的偉大建筑師路易斯?沙利文(Louis Sullivan)倡導(dǎo)的建筑設(shè)計(jì)著名格言:“功能決定形式(Form follows function)”,軟件架構(gòu)首先是要服務(wù)于業(yè)務(wù)功能的搞隐。
架構(gòu)影響研發(fā)團(tuán)隊(duì)的組織形式
業(yè)務(wù)拆分的方法和技術(shù)框架的選擇必然會(huì)影響到研發(fā)團(tuán)隊(duì)的組織形式驹愚。業(yè)務(wù)拆分的越細(xì)致,越有利于我們更好的對(duì)項(xiàng)目的各項(xiàng)指標(biāo)量化計(jì)算劣纲,更精確的估計(jì)工時(shí)和成本逢捺,從而指導(dǎo)我們每個(gè)小組應(yīng)該分配多少資源,使用什么樣的協(xié)同和任務(wù)確認(rèn)形式癞季。并且隨著項(xiàng)目的推進(jìn)蒸甜,計(jì)劃與實(shí)際情況之間的匹配程度也隨時(shí)可以進(jìn)一步精確調(diào)整棠耕,進(jìn)而影響到我們應(yīng)該對(duì)每一塊任務(wù)的投入資源進(jìn)行動(dòng)態(tài)調(diào)整余佛。
架構(gòu)存在于每一個(gè)系統(tǒng)
每一個(gè)已經(jīng)實(shí)現(xiàn)并運(yùn)行的系統(tǒng)柠新,都是特定架構(gòu)設(shè)計(jì)的載體。有些系統(tǒng)對(duì)應(yīng)的架構(gòu)辉巡,有詳細(xì)的設(shè)計(jì)文檔來描述恨憎;有些系統(tǒng)的設(shè)計(jì)文檔,殘缺不全郊楣,甚至還因?yàn)樵谙到y(tǒng)的發(fā)展變化的同時(shí)憔恳,文檔沒有更新,導(dǎo)致設(shè)計(jì)文檔與實(shí)際系統(tǒng)不符净蚤;有些系統(tǒng)干脆就沒有設(shè)計(jì)文檔钥组。但是這些系統(tǒng),都是基于一定的架構(gòu)來創(chuàng)建的今瀑。
每種架構(gòu)都有特定的架構(gòu)風(fēng)格
每種架構(gòu)方式程梦,每個(gè)具體系統(tǒng)內(nèi)所體現(xiàn)的架構(gòu)設(shè)計(jì),都是可以被工程師們理解橘荠,進(jìn)而提煉出來一些架構(gòu)思想和設(shè)計(jì)原則屿附,這些思想和原則就是這種架構(gòu)方式的風(fēng)格。依據(jù)這些風(fēng)格哥童,我們可以將各種架構(gòu)方式挺份,進(jìn)行分門別類,從而進(jìn)一步討論每種架構(gòu)風(fēng)格的特點(diǎn)贮懈。
架構(gòu)需要不斷的發(fā)展演進(jìn)
隨著計(jì)算機(jī)軟硬件的不斷發(fā)展匀泊,軟件架構(gòu)思想也在不斷的發(fā)展變化。另一方面朵你,軟件為其提供業(yè)務(wù)處理和服務(wù)能力的每個(gè)具體行業(yè)領(lǐng)域也在不斷發(fā)展變化各聘,業(yè)務(wù)處理流程、參與角色撬呢、業(yè)務(wù)形式不斷的推陳出新伦吠。這就要求我們?cè)谙到y(tǒng)架構(gòu)設(shè)計(jì)時(shí),保持終身學(xué)習(xí)的精神魂拦,持續(xù)吸收新思想新知識(shí)毛仪,保持貼近一線業(yè)務(wù)群體,隨時(shí)因地制宜芯勘,調(diào)整架構(gòu)設(shè)計(jì)箱靴,采取最適合當(dāng)下場(chǎng)景的解決方案。
架構(gòu)的目標(biāo)與方法
明確軟件系統(tǒng)架構(gòu)的一些通用目標(biāo)荷愕,可以使我們更明確如何考慮架構(gòu)的方向衡怀;而了解架構(gòu)的方法和方法論棍矛,則讓我們可以知道從哪些角度可以比較全面的描述清楚一個(gè)系統(tǒng)的架構(gòu)設(shè)計(jì)。
可控性與拆分
對(duì)于復(fù)雜問題的簡(jiǎn)化處理抛杨,一個(gè)簡(jiǎn)單辦法就是分而治之够委。按一定的粒度把目標(biāo)問題進(jìn)行分解,可以非常有效的提升目標(biāo)的可控性怖现,使得目標(biāo)變得更加可以量化茁帽、進(jìn)而優(yōu)化。系統(tǒng)按照合適的粒度拆分成不同模塊的過程屈嗤,我們一般稱為模塊化潘拨。模塊化也是軟件工程化的基礎(chǔ)。在這個(gè)基礎(chǔ)上才能夠?qū)崿F(xiàn)分工合作饶号。
復(fù)用性與抽象
復(fù)用性一直是軟件設(shè)計(jì)領(lǐng)域的一個(gè)很重要的指標(biāo)铁追。復(fù)用的一個(gè)關(guān)鍵是我們對(duì)于現(xiàn)有具體問題的抽象,找到各種不同問題中存在的不變性茫船,進(jìn)而作為一種通用結(jié)構(gòu)來統(tǒng)一處理琅束。
拆分是把整體變成很多局部,再對(duì)局部分開對(duì)待和研究其性質(zhì)透硝。反過來狰闪,我們按照高內(nèi)聚的指導(dǎo)思想把一些緊密聯(lián)系的功能聚合后,打包成一個(gè)可以整體復(fù)用的部分濒生,這就是組件埋泵,這個(gè)過程就是組件化。通過組件化罪治,我們可以得到抽象再組合出來很多業(yè)務(wù)組件丽声。這樣,在更大粒度上實(shí)現(xiàn)了功能的復(fù)用觉义。
非功能性需求九維目標(biāo)
(1)高性能
系統(tǒng)必須滿足預(yù)期的性能目標(biāo)雁社,在并發(fā)用戶數(shù)(Concurrent Users)、并發(fā)事務(wù)數(shù)(Transactions per Second晒骇,TPS)霉撵、吞吐量(Throughout)等指標(biāo)方面達(dá)到預(yù)估值,支撐使用人群的正常使用操作洪囤。
(2)可靠性
業(yè)務(wù)系統(tǒng)直接影響到用戶的經(jīng)營(yíng)和管理徒坡,因此必須是可靠的。
(3) 穩(wěn)定性
軟件系統(tǒng)必須是能夠在用戶的使用周期內(nèi)長(zhǎng)期穩(wěn)定運(yùn)行的瘤缩。這要求系統(tǒng)具有一定的容錯(cuò)能力喇完。
(4)可用性
可用性是指系統(tǒng)在指定時(shí)間內(nèi)的提供服務(wù)能力的概率值。我們一般采取集群剥啤、分布式等手段提升系統(tǒng)的可用性锦溪。高可用性是目前系統(tǒng)架構(gòu)設(shè)計(jì)方面的一個(gè)熱點(diǎn)不脯。
(5)安全性
用戶的業(yè)務(wù)數(shù)據(jù)是具有非常高的商業(yè)價(jià)值,如果被泄露或篡改將會(huì)帶來重大損失刻诊。安全性是軟件系統(tǒng)的一個(gè)重要的指標(biāo)防楷,也是架構(gòu)設(shè)計(jì)的一個(gè)重要目標(biāo)。
(6)靈活性
軟件系統(tǒng)應(yīng)該具備滿足不同特點(diǎn)的用戶群和目標(biāo)市場(chǎng)的能力坏逢,更靈活域帐。
(7)易用性
軟件系統(tǒng)必須擁有較好的用戶體驗(yàn),便于用戶使用是整。
(8)可擴(kuò)展性
業(yè)務(wù)和技術(shù)都在不斷的發(fā)展變化,軟件系統(tǒng)需要隨時(shí)根據(jù)變化擴(kuò)展改造的能力民假。
(9)可維護(hù)性
軟件系統(tǒng)的維護(hù)包括修復(fù)現(xiàn)有的錯(cuò)誤浮入,以及將新的需求和改進(jìn)添加到已有系統(tǒng)。因此一個(gè)易于維護(hù)的系統(tǒng)對(duì)于用戶提出的問題或改進(jìn)羊异,可以及時(shí)的實(shí)現(xiàn)高效的反饋和響應(yīng)支持事秀,同時(shí)有效降低維護(hù)成本。
基于這些目標(biāo)野舶,經(jīng)常有人說:“架構(gòu)是系統(tǒng)非功能性需求的解決辦法的集合”易迹。
架構(gòu)的不同風(fēng)格
典型的企業(yè)級(jí)應(yīng)用系統(tǒng)或者互聯(lián)網(wǎng)應(yīng)用系統(tǒng)一般都是通過 Web 提供一組業(yè)務(wù)服務(wù)能力。這類系統(tǒng)包括提供給用戶操作的平道、運(yùn)行于瀏覽器中睹欲、具有 UI的業(yè)務(wù)邏輯展示和輸入部分,運(yùn)行于服務(wù)器端一屋、用后端編程語言構(gòu)建的業(yè)務(wù)邏輯處理部分窘疮,以及用于存儲(chǔ)業(yè)務(wù)數(shù)據(jù)的關(guān)系數(shù)據(jù)庫或其他類型的存儲(chǔ)軟件。
根據(jù)軟件系統(tǒng)在運(yùn)行期的表現(xiàn)風(fēng)格和部署結(jié)構(gòu)冀墨,我們可以粗略地將其劃分為兩大類闸衫。
(1)整個(gè)系統(tǒng)的所有功能單元,整體部署到同一個(gè)進(jìn)程(所有代碼可以打包成1個(gè)或多個(gè)文件)诽嘉,我們可以稱之為“單體架構(gòu)”(Monolithic Architecture)蔚出;
(2)整個(gè)系統(tǒng)的功能單元分散到不同的進(jìn)程,然后由多個(gè)進(jìn)程共同提供不同的業(yè)務(wù)能力虫腋,我們稱之為“分布式架構(gòu)”(Distributed Architecture)骄酗。
再結(jié)合軟件系統(tǒng)在整個(gè)生命周期的特點(diǎn),我們可以進(jìn)一步區(qū)分不同的架構(gòu)風(fēng)格岔乔。
對(duì)于單體架構(gòu)酥筝,我們根據(jù)設(shè)計(jì)期和開發(fā)實(shí)現(xiàn)期的不同模式和劃分結(jié)構(gòu),可以分為:
簡(jiǎn)單單體模式:代碼層面沒有拆分雏门,所有的業(yè)務(wù)邏輯都在一個(gè)項(xiàng)目(Project)里打包成一個(gè)二進(jìn)制的編譯后文件嘿歌,通過這個(gè)文件進(jìn)行部署掸掏,并提供業(yè)務(wù)能力;
MVC 模式:系統(tǒng)內(nèi)每個(gè)模塊的功能組件按照不同的職責(zé)劃分為模型(Model)宙帝、視圖(View)丧凤、控制器(Controller)等角色,并以此來組織研發(fā)實(shí)現(xiàn)工作步脓;
前后端分離模式:將前后端代碼耦合的設(shè)計(jì)改為前端邏輯和后端邏輯獨(dú)立編寫實(shí)現(xiàn)的處理模式愿待;
組件模式:系統(tǒng)的每一個(gè)模塊拆分為一個(gè)子項(xiàng)目(SubProject),每個(gè)模塊獨(dú)立編譯打包成一個(gè)組件靴患,然后所有需要的組件一起再部署到同一個(gè)容器里仍侥;
類庫模式:A 系統(tǒng)需要復(fù)用 B 系統(tǒng)的某些功能,這時(shí)可以直接把 B 系統(tǒng)的某些組件作為依賴庫鸳君,打包到 A 系統(tǒng)來使用农渊。
對(duì)于分布式架構(gòu),我們根據(jù)設(shè)計(jì)期的架構(gòu)思想和運(yùn)行期的不同結(jié)構(gòu)或颊,可以分為:
面向服務(wù)架構(gòu)(Service Oriented Architecture):以業(yè)務(wù)服務(wù)的角度和服務(wù)總線的方式(一般是 WebService 與 ESB砸紊,Enterprise Service Bus)考慮系統(tǒng)架構(gòu)和企業(yè) IT 治理;
分布式服務(wù)架構(gòu)(Distributed Service Architecture):基于去中心化的分布式服務(wù)框架與技術(shù)囱挑,考慮系統(tǒng)架構(gòu)和服務(wù)治理醉顽;
微服務(wù)架構(gòu)(Micro-Services Architecture):微服務(wù)架構(gòu)可以看做是面向服務(wù)架構(gòu)和分布式服務(wù)架構(gòu)的拓展,使用更細(xì)粒度的服務(wù)(所以叫微服務(wù))和一組設(shè)計(jì)準(zhǔn)則來考慮大規(guī)模的復(fù)雜系統(tǒng)架構(gòu)設(shè)計(jì)平挑。
也有人把如上的各個(gè)架構(gòu)風(fēng)格總結(jié)為四個(gè)大的架構(gòu)發(fā)展階段:
(1)單體架構(gòu)階段
(2)垂直架構(gòu)階段
(3)SOA 架構(gòu)階段
(4)微服務(wù)架構(gòu)階段
這種分類跟前述的方式并沒有多大區(qū)別游添。我們接下來詳細(xì)介紹其中的一些重要架構(gòu)風(fēng)格。
單體架構(gòu):簡(jiǎn)單單體模式
簡(jiǎn)單單體模式是最簡(jiǎn)單的架構(gòu)風(fēng)格弹惦,所有的代碼全都在一個(gè)項(xiàng)目中否淤。這樣研發(fā)團(tuán)隊(duì)的任何一個(gè)人都可以隨時(shí)修改任意的一段代碼,或者增加一些新的代碼棠隐。開發(fā)人員也可以只在自己的電腦上就可以隨時(shí)開發(fā)石抡、調(diào)試、測(cè)試整個(gè)系統(tǒng)的功能助泽。也不需要額外的一些依賴條件和準(zhǔn)備步驟啰扛,我們就可以直接編譯打包整個(gè)系統(tǒng)代碼,創(chuàng)建一個(gè)可以發(fā)布的二進(jìn)制版本嗡贺。這種方式對(duì)于一個(gè)新團(tuán)隊(duì)的創(chuàng)立初期隐解,需要迅速開始從0到1,抓住時(shí)機(jī)實(shí)現(xiàn)產(chǎn)品最短時(shí)間推向市場(chǎng)诫睬,可以省去各種額外的設(shè)計(jì)煞茫,直接上手干活,爭(zhēng)取了時(shí)間,因而是非常有意義的续徽。
但是這種方式對(duì)于一個(gè)系統(tǒng)的長(zhǎng)期穩(wěn)定發(fā)展確實(shí)有很多壞處的蚓曼。
首先,簡(jiǎn)單單體模式的系統(tǒng)存在代碼嚴(yán)重耦合的問題钦扭。所有的代碼都在一起纫版,就算是按照 package 來切分了不同的模塊,各不同模塊的代碼還是可以直接相互引用客情,這就導(dǎo)致了系統(tǒng)內(nèi)的對(duì)象間依賴關(guān)系混亂其弊,修改一處代碼,可能會(huì)影響一大片的功能無法正常使用膀斋。
第二梭伐,簡(jiǎn)單單體模式的系統(tǒng)變更對(duì)部署影響大,并且這個(gè)問題是所有的單體架構(gòu)系統(tǒng)都存在的問題概页。系統(tǒng)作為一個(gè)單體部署籽御,每次發(fā)布的部署單元就是一個(gè)新版本的整個(gè)系統(tǒng),系統(tǒng)內(nèi)的任何業(yè)務(wù)邏輯調(diào)整都會(huì)導(dǎo)致整個(gè)系統(tǒng)的重新打包惰匙,部署、停機(jī)铃将、再重啟项鬼,進(jìn)而導(dǎo)致了系統(tǒng)的停機(jī)發(fā)布時(shí)間較長(zhǎng)。每次發(fā)布上線都是生產(chǎn)系統(tǒng)的重大變更劲阎,這種部署模式大大提升了系統(tǒng)風(fēng)險(xiǎn)绘盟,降低了系統(tǒng)的可用性。
第三悯仙,簡(jiǎn)單單體模式的系統(tǒng)影響開發(fā)效率龄毡。如果一個(gè)使用 Java 的簡(jiǎn)單單體項(xiàng)目代碼超過100萬行,那么在一臺(tái)筆記本電腦上修改了代碼后執(zhí)行自動(dòng)編譯锡垄,可能需要等待十分鐘以上沦零,并且內(nèi)存可能不夠編譯過程使用,這是非常難以忍受的货岭。
第四路操,簡(jiǎn)單單體模式打包后的部署結(jié)構(gòu)可能過于龐大,導(dǎo)致業(yè)務(wù)系統(tǒng)啟動(dòng)很慢千贯,進(jìn)而也會(huì)影響系統(tǒng)的可用性屯仗。這一條也是所有單體架構(gòu)的系統(tǒng)都有的問題。
第五搔谴,擴(kuò)展性受限魁袜,也是所有單體架構(gòu)的一個(gè)問題。如果任何一個(gè)業(yè)務(wù)存在性能問題,那么都需要考慮多部署幾個(gè)完整的實(shí)例的集群峰弹,或者再加上負(fù)載均衡設(shè)備店量,才能保證整個(gè)系統(tǒng)的性能可以支撐用戶的使用。
所以垮卓,簡(jiǎn)單單體模式比較適用于規(guī)模較小的系統(tǒng)垫桂,特別是需要快速推出原型實(shí)現(xiàn),以質(zhì)量換速度的場(chǎng)景粟按。
單體架構(gòu):MVC 模式
MVC 也是一個(gè)非常常見的3層(3-Tier)結(jié)構(gòu)架構(gòu)模式诬滩,它把每個(gè)模塊劃分為模型層(Model Layer)、視圖層(View Layer)灭将、控制器層(Controller Layer)等部分疼鸟。
模型層:代表業(yè)務(wù)數(shù)據(jù)實(shí)體部分;
視圖層:代表前端的展示部分庙曙;
控制器層:代表請(qǐng)求分發(fā)空镜,處理調(diào)度部分。
更一般地捌朴,我們可以添加數(shù)據(jù)操作層(Data Access Layer)等吴攒,形成一個(gè) N 層(N-Tier)結(jié)構(gòu)模型。
整個(gè)系統(tǒng)由多個(gè)模塊組成砂蔽,每個(gè)模塊又由這種不同的部分組成栽惶。這樣一來裸扶,我們就把整個(gè)系統(tǒng)拆解成了很多粒度較小的零件烫沙。這種方式之所以流行開來漫试,主要是因?yàn)椋?/p>
簡(jiǎn)單,直觀诡右,可以非常有效的上手安岂,作為 Web 系統(tǒng)設(shè)計(jì)的一般方法,這一點(diǎn)是 MVC 模式被普及的基礎(chǔ)條件帆吻;
經(jīng)過上面過程的橫割豎切域那,我們已經(jīng)把系統(tǒng)拆解為一個(gè)個(gè)的小單元,非常有利于分配開發(fā)工作桅锄,投入大量的工程師進(jìn)行大規(guī)模的工程化開發(fā)琉雳,這一點(diǎn)非常重要,在軟件行業(yè)高速發(fā)展的今天友瘤,適合工程化的方式才是最具有生產(chǎn)力的辦法翠肘;
不同的模塊和分層結(jié)構(gòu),本身就可以作為一個(gè)開發(fā)層面的子項(xiàng)目拆分結(jié)構(gòu)辫秧,這樣我們就可以把系統(tǒng)拆分成多個(gè)不同的子項(xiàng)目束倍;
基于 MVC 模式,又陸續(xù)發(fā)展了(ORM ,Object Relational Mapping) 等簡(jiǎn)化數(shù)據(jù)操作層的技術(shù)與框架绪妹,以及相應(yīng)的代碼生成工具等甥桂,極大的提供了軟件開發(fā)效率。
當(dāng)然邮旷,MVC 模式也存在定義不夠明確黄选,對(duì)于簡(jiǎn)單的業(yè)務(wù)場(chǎng)景拆解過細(xì)導(dǎo)致復(fù)雜度增加等問題,需要在實(shí)踐中不斷摸索和總結(jié)應(yīng)用經(jīng)驗(yàn)婶肩。基于單體架構(gòu)下的 MVC 模式依然解決不了單體架構(gòu)本身存在的問題办陷,特別是對(duì)于可用性和擴(kuò)展性的影響。
單體架構(gòu):前后端分離模式
傳統(tǒng)的 Web 系統(tǒng)都是 (B/S律歼,Browser/Server) 結(jié)構(gòu)的民镜,一般的 JSP 或頁面標(biāo)簽 Tag 技術(shù)、后端 FreeMaker 或 Velocity 等模板技術(shù)導(dǎo)致 HTML/CSS/JavaScript等前端技術(shù)與后端的處理邏輯和數(shù)據(jù)耦合到一起险毁,這種方式明顯不符合現(xiàn)代工程化的專業(yè)領(lǐng)域細(xì)分原則制圈。特別是隨著富網(wǎng)絡(luò)應(yīng)用程序(Rich Internet Application,RIA)概念的興起畔况,Ajax 和 JQuery 框架鲸鹦,前端 UI組件技術(shù)的大行其道,程序員們?cè)跒g覽器端寫了很多邏輯處理和界面處理的 JavaScript代碼跷跪。后來越來越多的業(yè)務(wù)邏輯需要在瀏覽器端實(shí)現(xiàn)亥鬓,前端技術(shù)逐漸發(fā)展到了一個(gè)百花齊放的階段,特別是近年來基于 NodeJS前端技術(shù)棧的成功應(yīng)用域庇,最終使前端技術(shù)成為了一個(gè)與后端技術(shù)領(lǐng)域并駕齊驅(qū)的領(lǐng)域。其實(shí)早在2006年覆积,ExtJS 作為當(dāng)時(shí)的前端解決方案集大成者听皿,已經(jīng)實(shí)現(xiàn)了前端代碼邏輯和界面全部都由 JavaScript完成,后端只提供基于 URL 的 JSON 數(shù)據(jù)接口宽档。這樣 Web 系統(tǒng)就由原來的 BS 系統(tǒng)尉姨,變成了提供(UI,User Interface)和交互的前端 B系統(tǒng)吗冤,提供數(shù)據(jù)接口的后端 S系統(tǒng)又厉,從而達(dá)到了前后端分離的目標(biāo)。自從椎瘟,越來越多的系統(tǒng)采用前后端分離的模式覆致,并且進(jìn)一步影響了研發(fā)團(tuán)隊(duì)的組成:前端團(tuán)隊(duì)負(fù)責(zé)前端系統(tǒng)開發(fā),后端團(tuán)隊(duì)負(fù)責(zé)后端系統(tǒng)開發(fā)肺蔚,兩個(gè)團(tuán)隊(duì)一起制定前后端系統(tǒng)的數(shù)據(jù)接口煌妈。只要數(shù)據(jù)接口保持穩(wěn)定不變,那么前后端系統(tǒng)可以各自獨(dú)立發(fā)展和維護(hù)。這一條準(zhǔn)則不僅僅是單體架構(gòu)獨(dú)有的璧诵,所有的 Web系統(tǒng)都可以按照這種方式進(jìn)行設(shè)計(jì)汰蜘。前后端分離模式一直影響到現(xiàn)在的系統(tǒng)架構(gòu)方法,成為了當(dāng)下的一種最佳實(shí)踐之宿。目前最主流的三種前端開發(fā)框架(React族操、AngularJS、Vue)比被,都遵循著這種設(shè)計(jì)理念色难。
分布式架構(gòu):面向服務(wù)架構(gòu)(SOA)
服務(wù)與SOA
面向服務(wù)架構(gòu)(SOA,Service Oriented Architecture)是一種建設(shè)企業(yè) IT 生態(tài)系統(tǒng)的架構(gòu)指導(dǎo)思想姐赡。SOA 的關(guān)注點(diǎn)是服務(wù)莱预。服務(wù)最基本的業(yè)務(wù)功能單元,由平臺(tái)中立性的接口契約來定義项滑。通過將業(yè)務(wù)系統(tǒng)服務(wù)化依沮,可以將不同模塊解耦,各種異構(gòu)系統(tǒng)間可以輕松實(shí)現(xiàn)服務(wù)調(diào)用枪狂、消息交換和資源共享危喉。
(1)從宏觀的視角來看,不同于以往的孤立業(yè)務(wù)系統(tǒng)州疾,SOA 強(qiáng)調(diào)整個(gè)企業(yè) IT 生態(tài)環(huán)境是一個(gè)大的整體辜限。整個(gè) IT生態(tài)中的所有業(yè)務(wù)服務(wù)構(gòu)成了企業(yè)的核心 IT資源。各系統(tǒng)的業(yè)務(wù)拆解為不同粒度和層次的模塊和服務(wù)严蓖,服務(wù)可以組裝到更大的粒度薄嫡,不同來源的服務(wù)可以編排到同一個(gè)處理流程,實(shí)現(xiàn)非常復(fù)雜的集成場(chǎng)景和更加豐富的業(yè)務(wù)功能颗胡。
(2)從研發(fā)的視角來看毫深,系統(tǒng)的復(fù)用可以從以前代碼級(jí)的粒度,擴(kuò)展到業(yè)務(wù)服務(wù)的粒度毒姨;能夠快速應(yīng)對(duì)業(yè)務(wù)需求和集成需求的變更哑蔫。
(3)從管理的角度來看,SOA 從更高的層次對(duì)整個(gè)企業(yè) IT 生態(tài)進(jìn)行統(tǒng)一的設(shè)計(jì)與管理弧呐,對(duì)消息處理與服務(wù)調(diào)用進(jìn)行監(jiān)控闸迷,優(yōu)化資源配置,降低系統(tǒng)復(fù)雜度和綜合成本俘枫,為業(yè)務(wù)流程梳理和優(yōu)化提供技術(shù)支撐腥沽。
SOA 落地方式
SOA的落地方式與水平,跟企業(yè) IT 特點(diǎn)崩哩、服務(wù)能力和發(fā)展階段直接相關(guān)巡球。目前常見的落地方式主要有分布式服務(wù)化和集中式管理兩種言沐。
(1)分布式服務(wù)化
互聯(lián)網(wǎng)類型的企業(yè),業(yè)務(wù)與技術(shù)發(fā)展快酣栈,數(shù)據(jù)基數(shù)與增量都大险胰,并發(fā)訪問量高,系統(tǒng)間依賴關(guān)系復(fù)雜矿筝、調(diào)用頻繁起便,分布式服務(wù)化與服務(wù)治理迫在眉睫。通過統(tǒng)一的服務(wù)化技術(shù)手段窖维,進(jìn)一步實(shí)現(xiàn)服務(wù)的注冊(cè)與尋址榆综、服務(wù)調(diào)用關(guān)系查找、服務(wù)調(diào)用與消息處理監(jiān)控铸史、服務(wù)質(zhì)量與服務(wù)降級(jí)等等”谴現(xiàn)有的一些分布式服務(wù)化技術(shù)有Dubbo(基于 Java)、Finagle(基于 Scala)和 ICE(跨平臺(tái))等琳轿。
(2)集中式管理
傳統(tǒng)企業(yè)的 IT 內(nèi)部遺留系統(tǒng)包袱較重判沟,資源整合很大一部分是需要打通新舊技術(shù)體系的任督二脈,所以更偏重于以 ESB作為基礎(chǔ)支撐技術(shù)崭篡,以整合集成為核心挪哄,將各個(gè)新舊系統(tǒng)的業(yè)務(wù)能力逐漸的在 ESB 容器上聚合和集成起來。比較流行的商業(yè) ESB 有 IBM 的WMB 和 Oracle 的 OSB琉闪,開源 ESB 有 Mule迹炼、ServiceMix/WSO2 ESB、JBoss ESB 和OpenESB颠毙。一方面斯入,集中式管理的SOA,其優(yōu)勢(shì)在于管理和集成企業(yè)內(nèi)部各處散落的業(yè)務(wù)服務(wù)能力蛀蜜,同時(shí)一個(gè)明顯的不足在于其中心化的架構(gòu)方法咱扣,并不能解決各個(gè)系統(tǒng)自己內(nèi)部的問題。另一方面涵防,隨著自動(dòng)化測(cè)試技術(shù)、輕量級(jí)容器技術(shù)等相關(guān)技術(shù)的發(fā)展沪铭,分布式服務(wù)技術(shù)越來越像微服務(wù)架構(gòu)方向發(fā)展壮池。
分布式架構(gòu):微服務(wù)架構(gòu)(MSA,Micro Service Architecture)
James Lewis 和 Martin Fowler 給微服務(wù)架構(gòu)的定義如下:微服務(wù)架構(gòu)風(fēng)格杀怠,以實(shí)現(xiàn)一組微服務(wù)的方式來開發(fā)一個(gè)獨(dú)立的應(yīng)用系統(tǒng)的方法椰憋。其中每個(gè)小微服務(wù)都運(yùn)行在自己的進(jìn)程中,一般采用 HTTP 資源API這樣輕量的機(jī)制相互通信赔退。這些微服務(wù)圍繞業(yè)務(wù)功能進(jìn)行構(gòu)建橙依,通過全自動(dòng)化的部署方式來進(jìn)行獨(dú)立部署证舟。這些微服務(wù)可以使用不同的語言來編寫,也可以使用不同的數(shù)據(jù)存儲(chǔ)技術(shù)窗骑,并且基于最低限度的集中管理女责。同時(shí) Martin Fowler 總結(jié)有如下 9 個(gè)特性:
組件以服務(wù)的形式提供
圍繞業(yè)務(wù)功能進(jìn)行組織
產(chǎn)品而不是項(xiàng)目
強(qiáng)化終端與弱化管道
“去中心化”地治理技術(shù)署
“去中心化”地管理數(shù)據(jù)
“基礎(chǔ)設(shè)施”自動(dòng)化
“容錯(cuò)”設(shè)計(jì)
“演進(jìn)式”設(shè)計(jì)
微服務(wù)架構(gòu)可以看作是一種 SOA 的發(fā)展實(shí)現(xiàn),其將 SOA 中原本可能聚合在同一個(gè)系統(tǒng)內(nèi)的多個(gè)服務(wù)組件拆分到各自獨(dú)立的系統(tǒng)進(jìn)程创译。
微服務(wù)架構(gòu)的優(yōu)勢(shì)在于:更加徹底的組件化抵知,系統(tǒng)內(nèi)部各個(gè)組件之間解耦的比較干脆,單個(gè)系統(tǒng)的規(guī)模小很多软族;
可以組建每個(gè)服務(wù)獨(dú)立的維護(hù)團(tuán)隊(duì)刷喜,利于各自團(tuán)隊(duì)獨(dú)立的開發(fā)和維護(hù);
每個(gè)微服務(wù)獨(dú)立部署立砸,只要服務(wù)間的接口穩(wěn)定掖疮,各系統(tǒng)可以相互之間互不干擾的獨(dú)立發(fā)展;
微服務(wù)架構(gòu)使得每個(gè)服務(wù)本身可以獨(dú)立的擴(kuò)展颗祝,性能出現(xiàn)瓶頸浊闪,優(yōu)化或增加這個(gè)服務(wù)的配置即可。
微服務(wù)架構(gòu)的劣勢(shì)也很明顯吐葵,拆分的過細(xì)則要求自動(dòng)化測(cè)試能力必須跟得上规揪。一個(gè)全流程的測(cè)試跨8~10個(gè)系統(tǒng)是所有測(cè)試人員的惡魔。
問題的排查温峭,數(shù)據(jù)的一致性保障猛铅,系統(tǒng)的監(jiān)控等等,都會(huì)因?yàn)椴鸱值奶?xì)凤藏,復(fù)雜度大幅度增加奸忽。如果代碼或設(shè)計(jì)上有一個(gè)修改涉及到多個(gè)不同的微服務(wù),那么在團(tuán)隊(duì)之間協(xié)調(diào)配合成本也會(huì)增加揖庄。對(duì)舊系統(tǒng)的微服務(wù)架構(gòu)和組件化改造也是一個(gè)比較大的問題栗菜。
在組件化上所做的任何工作的成功度,取決于軟件與組件的匹配程度蹄梢。但是合理的組件邊界應(yīng)該如何確定疙筹,這是非常困難的,演進(jìn)式的處理方式是我們覺得比較合理和靠譜的禁炒。因此而咆,Martin Fowler也建議,不要一上來就以微服務(wù)架構(gòu)作為系統(tǒng)設(shè)計(jì)的起點(diǎn)幕袱。相反地暴备,要用一個(gè)單塊系統(tǒng)作為起點(diǎn),并保持其模塊化们豌。當(dāng)這個(gè)單塊系統(tǒng)出現(xiàn)了問題后涯捻,再將其分解為微服務(wù)浅妆。