透視不同的架構(gòu)思維,賞析架構(gòu)之美
什么是系統(tǒng)架構(gòu)(Architecture)
設(shè)計(jì)不僅僅指的是外觀和感覺(jué),它還包括運(yùn)作方式。—— 史蒂夫·喬布斯
系統(tǒng)架構(gòu)(System Architecture),軟件架構(gòu)(Soft Architecture)是 IT 領(lǐng)域常見(jiàn)的名詞,架構(gòu)設(shè)計(jì)是軟件系統(tǒng)構(gòu)建過(guò)程中極其關(guān)鍵的一部分。
系統(tǒng)架構(gòu)為什么重要?常見(jiàn)的架構(gòu)模式都有哪些?跟著 【碼哥字節(jié)】了解不同的架構(gòu)設(shè)計(jì)所運(yùn)用的不同設(shè)計(jì)哲學(xué)。
一起來(lái)看下常見(jiàn)的架構(gòu)模式:Client-Server、Peer to Peer、MVC、Layered、Distribute-Cluster、Micro-Service、Even-Source、Hexagonal 逐個(gè)擊破。
Architecture,原意建筑學(xué),其實(shí)軟件架構(gòu)的概念就是源于建筑學(xué)。建筑學(xué)是建筑物設(shè)計(jì)和建造相關(guān)的藝術(shù)和技術(shù)的綜合。建筑學(xué)是一門橫跨工程技術(shù)和人文藝術(shù)的學(xué)科。它研究的是建筑物可資使用的空間、可供欣賞的形象,以及圍繞空間、形象如何產(chǎn)生確立、調(diào)整美化等的一系列問(wèn)題。并且其所研究的對(duì)象不僅是建筑物本身,更主要的是研究人們對(duì)建筑物的要求及其如何得以滿足,研究建筑物實(shí)體從無(wú)到有的產(chǎn)生過(guò)程中相應(yīng)的策劃、設(shè)計(jì)、實(shí)施等。
建筑學(xué)研究建筑的規(guī)劃、設(shè)計(jì)和實(shí)施。軟件架構(gòu)研究軟件的規(guī)劃、設(shè)計(jì)和實(shí)施。
在架構(gòu)設(shè)計(jì)中,根據(jù)業(yè)務(wù)、技術(shù)、組織、靈活性、可擴(kuò)展性以及可維護(hù)性等因素,將應(yīng)用系統(tǒng)劃分成不同的部分,使這些部分之間相互分工、相互協(xié)作,從而完成特定的需求。架構(gòu)貫穿系統(tǒng)實(shí)現(xiàn)的整個(gè)過(guò)程,是軟件系統(tǒng)實(shí)現(xiàn)的主要參考,是軟件系統(tǒng)實(shí)現(xiàn)的藍(lán)圖。軟件系統(tǒng)的規(guī)劃、設(shè)計(jì)和實(shí)施依架構(gòu)的設(shè)計(jì)而組織實(shí)施。
系統(tǒng)架構(gòu)為什么重要
我們知道摩爾定律——計(jì)算機(jī)硬件的能力大致每?jī)赡晏岣咭槐兜乃俣劝l(fā)展。然而軟件開(kāi)發(fā)的流程卻沒(méi)有這樣的提速過(guò)程,開(kāi)發(fā)成本也沒(méi)有下降,系統(tǒng)架構(gòu)的設(shè)計(jì)方法論和設(shè)計(jì)模式不斷變化,而這個(gè)重要的流程依舊沒(méi)有一個(gè)完全可靠和一勞永逸的解決方案。為什么?軟件開(kāi)發(fā)過(guò)程有什么特別的難題?有下面幾點(diǎn):
- 復(fù)雜性(Complexity)
軟件可以說(shuō)是人類創(chuàng)造的最復(fù)雜的系統(tǒng)類型。軟件的各個(gè)模塊之間有各種顯性或隱性的依賴關(guān)系,隨著系統(tǒng)的成長(zhǎng)和模塊的增多,這些關(guān)系的數(shù)量往往以幾何級(jí)數(shù)的速度增長(zhǎng)。而理解運(yùn)用這些復(fù)雜性的人并沒(méi)有太多的變化。
2. 不可見(jiàn)性(Invisibility)
軟件工程師能直接看見(jiàn)源代碼,但是源代碼不是軟件本身。并且靜態(tài)的源代碼和運(yùn)行的系統(tǒng)也不一樣,軟件運(yùn)行環(huán)境的復(fù)雜性也增加了軟件系統(tǒng)的不可預(yù)測(cè)性。軟件系統(tǒng)不能以簡(jiǎn)單的方式描述出來(lái),設(shè)計(jì)文檔,描述說(shuō)明,流程圖,架構(gòu)圖這些也不過(guò)是讓復(fù)雜的軟件系統(tǒng)以更易于理解和易于交流的方式展示,卻依舊不能完全描述系統(tǒng)的全貌。
3. 易變性(Changeability)
修改軟件看似很容易,修改軟件比修改硬件容易多了,修改軟件系統(tǒng)也比修改一座巍立建筑物容易的多。所以人們自然地期待軟件系統(tǒng)能夠適應(yīng)未來(lái)的變化。但變化卻是復(fù)雜的,環(huán)境也是復(fù)雜的,這些復(fù)雜的情況往往讓一個(gè)易于修改的事情卻變成一件越來(lái)越困難的事情。
4. 服從性(Conformity)
軟件系統(tǒng)不能獨(dú)立存在,它總是運(yùn)行在硬件上面,也總是要服從系統(tǒng)中其他組成部分的要求,也要服從用戶的要求、行業(yè)的要求。
軟件系統(tǒng)的以上特性使得系統(tǒng)架構(gòu)的設(shè)計(jì)顯得尤其重要。系統(tǒng)架構(gòu)設(shè)計(jì)通過(guò)以下方式來(lái)解決上面的軟件難題:
- 抽象
抽象是系統(tǒng)架構(gòu)設(shè)計(jì)的重要一步。抽象是將復(fù)雜的概念簡(jiǎn)單化。在最高層次上,將軟件系統(tǒng)抽象為對(duì)象和過(guò)程兩個(gè)高層次概念。對(duì)象可以是系統(tǒng)、組件、接口、類、方法等等不同層次的概念,過(guò)程是系統(tǒng)運(yùn)行的方式和流程。抽象使具象的事物概念化,從而確定邊界,易于理解,易于交流。
- 分解
分解與組合相互作用。分解就是將高層次的抽象概念分解成低層次的抽象概念,就是將實(shí)體分成小的部件或組成部分,在應(yīng)對(duì)復(fù)雜度的諸多方式中,”分而治之“是一項(xiàng)基本策略,它把大問(wèn)題持續(xù)分解成小問(wèn)題,直到每一個(gè)小問(wèn)題都能夠解決為止。
- 語(yǔ)言
語(yǔ)言的邊界就是世界的邊界。領(lǐng)域語(yǔ)言、設(shè)計(jì)語(yǔ)言確定系統(tǒng)的what、how和why。語(yǔ)言使系統(tǒng)顯見(jiàn)于文檔,設(shè)計(jì)圖等等易于理解的層次,也使得系統(tǒng)的易變性被規(guī)范在可預(yù)見(jiàn)和可控制的范圍之中。
幾種架構(gòu)模式
Client-Server
有了互聯(lián)網(wǎng)就有了 client-server 模式。client-server 模式以請(qǐng)求-響應(yīng)方式工作,客戶端發(fā)送請(qǐng)求信息,服務(wù)端接受請(qǐng)求,作出相應(yīng)處理,然后發(fā)回響應(yīng)信息。所有我們?cè)L問(wèn)的互聯(lián)網(wǎng)網(wǎng)站都是這種架構(gòu)。在桌面程序流行的時(shí)代,互聯(lián)網(wǎng)還沒(méi)有當(dāng)前這么發(fā)達(dá)的時(shí)代。Client-Server 還只代表 Desktop Client-Server 模式,使用瀏覽器的方式稱之為 B-S 模式,即 Browser-Server 模式。如今 Browser、Desktop Application、Mobile Application、Mobile Web 等統(tǒng)稱為 Client。
因此我們當(dāng)前訪問(wèn)的大部分網(wǎng)站,如新聞咨詢網(wǎng)站、博客網(wǎng)站等等都屬于這種模式。
Peer to Peer
端對(duì)端服務(wù)模式(Peer to Peer,簡(jiǎn)稱 P2P),亦稱為“點(diǎn)對(duì)點(diǎn)模式”,是指通過(guò)互聯(lián)網(wǎng)將個(gè)人與個(gè)人連接起來(lái),繞開(kāi)中心平臺(tái)而直接提供服務(wù)、完成交易的模式。P2P 的早期含意是計(jì)算機(jī)通信領(lǐng)域中的“對(duì)等網(wǎng)絡(luò)協(xié)議”,它打破了傳統(tǒng)的 Client/Server(C/S)模式,使得成千上萬(wàn)臺(tái)彼此連接的計(jì)算機(jī)都處于對(duì)等地位,網(wǎng)絡(luò)的參與者直接共享他們所擁有的一部分硬件資源(包括處理能力、存儲(chǔ)能力、網(wǎng)絡(luò)連接能力、打印機(jī)等),這些共享資源通過(guò)互聯(lián)網(wǎng),能被其它對(duì)等節(jié)點(diǎn)(Peer)直接訪問(wèn)而無(wú)需經(jīng)過(guò)統(tǒng)一的中間體。在該網(wǎng)絡(luò)中的參與者既是資源(服務(wù)或內(nèi)容)提供者(Server),又是資源獲取者(Client)。
P2P 模式流行于文件分享與下載、計(jì)算與存儲(chǔ)、即時(shí)通信和協(xié)同共享等領(lǐng)域。
MVC
Model-View-Controller,MVC 架構(gòu)是面向?qū)ο缶幊痰囊淮筮M(jìn)步。服務(wù)將邏輯劃分為三個(gè)不同的組建:Model——模型,即數(shù)據(jù),通常存儲(chǔ)在數(shù)據(jù)庫(kù)中,在內(nèi)存中進(jìn)行邏輯操作。View——用戶可見(jiàn)的組建,用于用戶交互和數(shù)據(jù)展示,如 Web GUI。Controller——邏輯操作,連接 Model 和 View 的組件,操作 Model 邏輯和 View 交互展示邏輯。
MVC 模式在客戶端和 H5 前端都比較流行。也一直是 Web 后端流行的架構(gòu)模式,在 Java Web 領(lǐng)域催生的 Struts、Spring MVC 等 Web 后臺(tái)框架,讓曾經(jīng)復(fù)雜的 Web 開(kāi)發(fā)變成一種異常簡(jiǎn)單的開(kāi)發(fā)。
隨著前后端漸漸分離,之前的后臺(tái) MVC 已經(jīng)將 View 完全交于前端,前后端通過(guò)相關(guān)協(xié)議通信,完成 View 數(shù)據(jù)的傳輸。
Layered
分層架構(gòu)是運(yùn)用最為廣泛的架構(gòu)模式,幾乎每個(gè)軟件系統(tǒng)都需要通過(guò)層(Layer)來(lái)隔離不同的關(guān)注點(diǎn)(Concern Point),以此應(yīng)對(duì)不同需求的變化,使得這種變化可以獨(dú)立進(jìn)行。
單一職責(zé)原則,是系統(tǒng)設(shè)計(jì)開(kāi)發(fā)重要的原則。分層架構(gòu)就時(shí)時(shí)遵循單一職責(zé)原則。不同的層次相互隔離,承擔(dān)不同的職責(zé)。
說(shuō)起分層架構(gòu),最讓人熟知的就是經(jīng)典的三層架構(gòu)。經(jīng)典三層架構(gòu)自頂向下由用戶界面層(User Interface Layer)、業(yè)務(wù)邏輯層(Business Logic Layer)與數(shù)據(jù)訪問(wèn)層(Data Access Layer)組成。三層架構(gòu)是簡(jiǎn)單 Client-Server 架構(gòu)的升級(jí)。
三層架構(gòu)的經(jīng)典和流行,以及大量 Web 后臺(tái)框架對(duì)三層架構(gòu)的靠近,使得 Web 后臺(tái)開(kāi)發(fā)簡(jiǎn)單到一個(gè)剛剛?cè)腴T的開(kāi)發(fā)人員就可以進(jìn)行 web 開(kāi)發(fā)。也正因?yàn)榇耍沟么蟛糠?web 開(kāi)發(fā)人員的思維受限于此,從而成為人人調(diào)侃的 CRUD-Boy。隨著 MIS 系統(tǒng)時(shí)代的漸遠(yuǎn),三層架構(gòu)也開(kāi)始在一些領(lǐng)域無(wú)法成為“銀彈“。
除去經(jīng)典的三層架構(gòu)。在領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)中,Eric Evans 設(shè)計(jì)了一種經(jīng)典的四層架構(gòu),其在用戶界面層與業(yè)務(wù)邏輯層之間引入了新的一層,即應(yīng)用層(Application Layer)。其余幾層也相應(yīng)的有所調(diào)整。
Distribute-Cluster
之上所提的架構(gòu)都是在單體架構(gòu)之下。單體架構(gòu)和多服務(wù)架構(gòu)是從服務(wù)的部署模式、運(yùn)行模式來(lái)考慮。
單體架構(gòu)有如下優(yōu)勢(shì):
- 易于開(kāi)發(fā):借助于開(kāi)發(fā)框架,單體應(yīng)用的開(kāi)發(fā)及其簡(jiǎn)單,開(kāi)發(fā)人員也很少需要考慮系統(tǒng)、部署、網(wǎng)絡(luò)等層次的問(wèn)題。
- 易于測(cè)試:?jiǎn)误w應(yīng)用部署在一個(gè)進(jìn)程中,環(huán)境簡(jiǎn)單。只要服務(wù)啟動(dòng)就可以測(cè)試所有的功能。
- 易于部署:往往只需要將應(yīng)用打包成一個(gè)簡(jiǎn)單的包就可。
- 易于水平擴(kuò)展:只需要將程序包部署多個(gè)服務(wù)即可。
單體應(yīng)用的劣勢(shì):
- 維護(hù)成本增加:隨著需求的增多,單體系統(tǒng)將越來(lái)越臃腫,維護(hù)的復(fù)雜性也將越來(lái)越大。
- 持續(xù)交互周期長(zhǎng):一方面維護(hù)困難,另一方面單體應(yīng)用在并行開(kāi)發(fā),并行測(cè)試上將十分困難,單體應(yīng)用十分不適合快速迭代的敏捷開(kāi)發(fā)。
- 擴(kuò)展性差:由于臃腫的系統(tǒng),將導(dǎo)致系統(tǒng)擴(kuò)展性變難。系統(tǒng)的升級(jí)也需要十分謹(jǐn)慎。
- 對(duì)新人不友好。
分布式系統(tǒng)拆分:
隨著互聯(lián)網(wǎng)的快速發(fā)展,一方面互聯(lián)網(wǎng)應(yīng)用訪問(wèn)量級(jí)大增,數(shù)據(jù)量大增。另一方面,應(yīng)用的迭代速度也不斷變快。單體應(yīng)用的模式已經(jīng)不適合互聯(lián)網(wǎng)的快速發(fā)展。這樣,后臺(tái)分布式集群架構(gòu)越來(lái)越流行。
Micro-Service
微服務(wù)并沒(méi)有一個(gè)嚴(yán)格的定義。以下是 Martin Fowler 描述的微服務(wù):
微服務(wù)架構(gòu)是一種架構(gòu)模式,它提倡將單一應(yīng)用程序劃分成一組小的服務(wù),服務(wù)之間相互協(xié)調(diào)、相互配合,為用戶提供最終價(jià)值。每個(gè)服務(wù)運(yùn)行在其獨(dú)立的進(jìn)程中,服務(wù)與服務(wù)間采用輕量級(jí)的通信機(jī)制互相溝通(通常基于 HTTP 的 RESTful API)。每個(gè)服務(wù)都圍繞著具體業(yè)務(wù)進(jìn)行構(gòu)建,并且能夠被獨(dú)立地部署到生產(chǎn)環(huán)境。
微服務(wù)通常具有以下特性:
- 單一職責(zé):業(yè)務(wù)獨(dú)立,團(tuán)隊(duì)自主。職責(zé)單一的服務(wù)應(yīng)該具有核心的領(lǐng)域,高內(nèi)聚、低耦合,與其他系統(tǒng)和領(lǐng)域確定明確的邊界。
- 輕量級(jí)通信:通信應(yīng)該簡(jiǎn)單,輕量。與語(yǔ)言無(wú)關(guān),與平臺(tái)無(wú)關(guān)。
- 獨(dú)立性:獨(dú)立開(kāi)發(fā),獨(dú)立測(cè)試和獨(dú)立部署。
一切選擇都是權(quán)衡的過(guò)程。微服務(wù)解決了單體應(yīng)用的許多問(wèn)題,自然也會(huì)帶來(lái)相應(yīng)的問(wèn)題。分布式和集群的環(huán)境是復(fù)雜的,基于此的微服務(wù)架構(gòu)也將具有相應(yīng)的復(fù)雜度。
隨著微服務(wù)的流行,微服務(wù)的很多問(wèn)題也被越來(lái)越多的框架和服務(wù)解決掉了。我們以 Spring Cloud 技術(shù)棧為例:
- SpringBoot:?jiǎn)误w服務(wù),快速創(chuàng)建項(xiàng)目,快速集成各種框架,易于測(cè)試,易于部署。
- Feign:微服務(wù)獨(dú)立部署,通過(guò)相關(guān)協(xié)議通信。Feign 就是一個(gè)簡(jiǎn)單的申明式通信框架,基于 HTTP restful。
- Eureka:獨(dú)立服務(wù)越來(lái)越多,服務(wù)實(shí)例也越來(lái)越多。服務(wù)治理便是必須的,Eureka 提供高可用的服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)功能。
- Ribbon:Feign 只負(fù)責(zé)通信,Ribbon 提供客戶端負(fù)載均衡,是系統(tǒng)優(yōu)化的部分。
- Hystrix:微服務(wù)將帶來(lái)服務(wù)間復(fù)雜的依賴關(guān)系,分布式和集群的復(fù)雜度也將帶來(lái)許多難以預(yù)料的問(wèn)題。為防止復(fù)雜網(wǎng)絡(luò)和復(fù)雜系統(tǒng)某一點(diǎn)的問(wèn)題導(dǎo)致整個(gè)系統(tǒng)的雪崩狀態(tài),便有了 Hystrix,Hystrix 是 Spring Cloud 體系中優(yōu)秀的斷路器,可以在系統(tǒng)發(fā)生問(wèn)題時(shí)進(jìn)行服務(wù)降級(jí),防止整體系統(tǒng)崩潰。
- Zuul:統(tǒng)一網(wǎng)關(guān),統(tǒng)一網(wǎng)關(guān)是以 Facade 模式,對(duì)外提供友好的接口,微服務(wù)化之后,服務(wù)將越來(lái)越多,越來(lái)越復(fù)雜,為了降低外部系統(tǒng)調(diào)用的復(fù)雜度,統(tǒng)一網(wǎng)關(guān)就是常用解決方案。
- Config:服務(wù)劃分越多,配置將越多,Spring cloud config 提供統(tǒng)一的配置管理。
- Sleuth:服務(wù)監(jiān)控和治理。監(jiān)控是復(fù)雜系統(tǒng)必需的基礎(chǔ)設(shè)施。系統(tǒng)感知、問(wèn)題發(fā)現(xiàn)、性能定位都需要監(jiān)控的加持。
Even-Source
事件溯源是最新流行一種應(yīng)用程序體系結(jié)構(gòu)模式。事件源將應(yīng)用程序進(jìn)行的狀態(tài)更改建模為事件的不可變序列或“日志”。事件源不是在現(xiàn)場(chǎng)修改應(yīng)用程序的狀態(tài),而是將觸發(fā)狀態(tài)更改的事件存儲(chǔ)在不可變的日志中,并將狀態(tài)更改建模為對(duì)日志中事件的響應(yīng)。
CQRS 模式通?;录菰茨J健T趥鹘y(tǒng)的體系結(jié)構(gòu)中,使用同一數(shù)據(jù)模型查詢和更新數(shù)據(jù)庫(kù)。 這十分簡(jiǎn)單,非常適用于基本的 CRUD 操作。 但是,在更復(fù)雜的應(yīng)用程序中,此方法會(huì)變得難以操作。 例如,在讀取方面,應(yīng)用程序可能執(zhí)行大量不同的查詢,返回具有不同形狀的數(shù)據(jù)傳輸對(duì)象 (DTO)。 對(duì)象映射可能會(huì)變得復(fù)雜。 在寫(xiě)入方面,模型可能實(shí)施復(fù)雜驗(yàn)證和業(yè)務(wù)邏輯。 結(jié)果,模型執(zhí)行太多操作,過(guò)度復(fù)雜。
CQRS(命令查詢的責(zé)任分離 Command Query Responsibility Segregation )將讀取和寫(xiě)入操作分成不同的模型,使用 命令 更新數(shù)據(jù),并使用 查詢 來(lái)讀取數(shù)據(jù)。
Hexagonal
六邊形架構(gòu)又稱“端口和適配器模式”,是 Alistair Cockburn 提出的一種具有對(duì)稱性特征的架構(gòu)風(fēng)格。在這種架構(gòu)中,系統(tǒng)通過(guò)適配器的方式與外部交互,將應(yīng)用服務(wù)與領(lǐng)域服務(wù)封裝在系統(tǒng)內(nèi)部。
六邊形架構(gòu)由以下三個(gè)組件組成:
- Ports:又可以分為輸入端和輸出端,是系統(tǒng)與其他系統(tǒng)交互的接口。
- Adapters:與其他系統(tǒng)的適配層,一方面防止核心系統(tǒng)和領(lǐng)域被外部影響,即防腐;另一方面方便 api 使用。
- Domain:應(yīng)用和模型是程序的核心。
六邊形架構(gòu)的核心理念是:應(yīng)用通過(guò)"端口"跟外部進(jìn)行交互。在傳統(tǒng)的分層架構(gòu)中很容易跨越層間的邊界,把業(yè)務(wù)邏輯滲透到其它層中去。六邊形架構(gòu)重要的就是“邊界”和“領(lǐng)域”。六邊形架構(gòu)的初衷是為了解決技術(shù)與業(yè)務(wù)系統(tǒng)的解耦合問(wèn)題,以及技術(shù)與技術(shù)間的解耦合問(wèn)題,這一架構(gòu)從設(shè)計(jì)模式中來(lái),從業(yè)務(wù)的實(shí)體服務(wù)出發(fā),將面向接口的設(shè)計(jì)具體化的端口協(xié)議和適配器實(shí)現(xiàn),服務(wù)自身實(shí)現(xiàn)獨(dú)立性和完備性。