不可不知的軟體架構模式

程式設計師修煉之旅發表於2020-10-15

什麼是系統架構(Architecture)

設計不僅僅指的是外觀和感覺,它還包括運作方式。—— 史蒂夫·賈伯斯

系統架構(System Architecture),軟體架構(Soft Architecture)是 IT 領域常見的名詞,架構設計是軟體系統構建過程中極其關鍵的一部分。

系統架構為什麼重要?常見的架構模式都有哪些?跟著 【碼哥位元組】瞭解不同的架構設計所運用的不同設計哲學。

一起來看下常見的架構模式:Client-Server、Peer to Peer、MVC、Layered、Distribute-Cluster、Micro-Service、Even-Source、Hexagonal 逐個擊破。

不可不知的軟體架構模式

Architecture,原意建築學,其實軟體架構的概念就是源於建築學。建築學是建築物設計和建造相關的藝術和技術的綜合。建築學是一門橫跨工程技術和人文藝術的學科。它研究的是建築物可資使用的空間、可供欣賞的形象,以及圍繞空間、形象如何產生確立、調整美化等的一系列問題。並且其所研究的物件不僅是建築物本身,更主要的是研究人們對建築物的要求及其如何得以滿足,研究建築物實體從無到有的產生過程中相應的策劃、設計、實施等。

建築學研究建築的規劃、設計和實施。軟體架構研究軟體的規劃、設計和實施。

在架構設計中,根據業務、技術、組織、靈活性、可擴充套件性以及可維護性等因素,將應用系統劃分成不同的部分,使這些部分之間相互分工、相互協作,從而完成特定的需求。架構貫穿系統實現的整個過程,是軟體系統實現的主要參考,是軟體系統實現的藍圖。軟體系統的規劃、設計和實施依架構的設計而組織實施。

系統架構為什麼重要

我們知道摩爾定律——計算機硬體的能力大致每兩年提高一倍的速度發展。然而軟體開發的流程卻沒有這樣的提速過程,開發成本也沒有下降,系統架構的設計方法論和設計模式不斷變化,而這個重要的流程依舊沒有一個完全可靠和一勞永逸的解決方案。為什麼?軟體開發過程有什麼特別的難題?有下面幾點:

  1. 複雜性(Complexity)

    軟體可以說是人類創造的最複雜的系統型別。軟體的各個模組之間有各種顯性或隱性的依賴關係,隨著系統的成長和模組的增多,這些關係的數量往往以幾何級數的速度增長。而理解運用這些複雜性的人並沒有太多的變化。

  2. 不可見性(Invisibility)

    軟體工程師能直接看見原始碼,但是原始碼不是軟體本身。並且靜態的原始碼和執行的系統也不一樣,軟體執行環境的複雜性也增加了軟體系統的不可預測性。軟體系統不能以簡單的方式描述出來,設計文件,描述說明,流程圖,架構圖這些也不過是讓複雜的軟體系統以更易於理解和易於交流的方式展示,卻依舊不能完全描述系統的全貌。

  3. 易變性(Changeability)

    修改軟體看似很容易,修改軟體比修改硬體容易多了,修改軟體系統也比修改一座巍立建築物容易的多。所以人們自然地期待軟體系統能夠適應未來的變化。但變化卻是複雜的,環境也是複雜的,這些複雜的情況往往讓一個易於修改的事情卻變成一件越來越困難的事情。

  4. 服從性(Conformity)

    軟體系統不能獨立存在,它總是執行在硬體上面,也總是要服從系統中其他組成部分的要求,也要服從使用者的要求、行業的要求。

軟體系統的以上特性使得系統架構的設計顯得尤其重要。系統架構設計通過以下方式來解決上面的軟體難題:

  • 抽象

    抽象是系統架構設計的重要一步。抽象是將複雜的概念簡單化。在最高層次上,將軟體系統抽象為物件過程兩個高層次概念。物件可以是系統、元件、介面、類、方法等等不同層次的概念,過程是系統執行的方式和流程。抽象使具象的事物概念化,從而確定邊界,易於理解,易於交流。

  • 分解

    分解與組合相互作用。分解就是將高層次的抽象概念分解成低層次的抽象概念,就是將實體分成小的部件或組成部分,在應對複雜度的諸多方式中,”分而治之“是一項基本策略,它把大問題持續分解成小問題,直到每一個小問題都能夠解決為止。

  • 語言

    語言的邊界就是世界的邊界。領域語言、設計語言確定系統的whathowwhy。語言使系統顯見於文件,設計圖等等易於理解的層次,也使得系統的易變性被規範在可預見和可控制的範圍之中。

幾種架構模式

Client-Server

不可不知的軟體架構模式cs

有了網際網路就有了 client-server 模式。client-server 模式以請求-響應方式工作,客戶端傳送請求資訊,服務端接受請求,作出相應處理,然後發回響應資訊。所有我們訪問的網際網路網站都是這種架構。在桌面程式流行的時代,網際網路還沒有當前這麼發達的時代。Client-Server 還只代表 Desktop Client-Server 模式,使用瀏覽器的方式稱之為 B-S 模式,即 Browser-Server 模式。如今 Browser、Desktop Application、Mobile Application、Mobile Web 等統稱為 Client。

因此我們當前訪問的大部分網站,如新聞諮詢網站、部落格網站等等都屬於這種模式。

Peer to Peer

不可不知的軟體架構模式p2p

端對端服務模式(Peer to Peer,簡稱 P2P),亦稱為“點對點模式”,是指通過網際網路將個人與個人連線起來,繞開中心平臺而直接提供服務、完成交易的模式。P2P 的早期含意是計算機通訊領域中的“對等網路協議”,它打破了傳統的 Client/Server(C/S)模式,使得成千上萬臺彼此連線的計算機都處於對等地位,網路的參與者直接共享他們所擁有的一部分硬體資源(包括處理能力、儲存能力、網路連線能力、印表機等),這些共享資源通過網際網路,能被其它對等節點(Peer)直接訪問而無需經過統一的中間體。在該網路中的參與者既是資源(服務或內容)提供者(Server),又是資源獲取者(Client)。

P2P 模式流行於檔案分享與下載、計算與儲存、即時通訊和協同共享等領域。

MVC

不可不知的軟體架構模式mvc

Model-View-Controller,MVC 架構是物件導向程式設計的一大進步。服務將邏輯劃分為三個不同的組建:Model——模型,即資料,通常儲存在資料庫中,在記憶體中進行邏輯操作。View——使用者可見的組建,用於使用者互動和資料展示,如 Web GUI。Controller——邏輯操作,連線 Model 和 View 的元件,操作 Model 邏輯和 View 互動展示邏輯。

MVC 模式在客戶端和 H5 前端都比較流行。也一直是 Web 後端流行的架構模式,在 Java Web 領域催生的 Struts、Spring MVC 等 Web 後臺框架,讓曾經複雜的 Web 開發變成一種異常簡單的開發。

隨著前後端漸漸分離,之前的後臺 MVC 已經將 View 完全交於前端,前後端通過相關協議通訊,完成 View 資料的傳輸。

Layered

分層架構是運用最為廣泛的架構模式,幾乎每個軟體系統都需要通過層(Layer)來隔離不同的關注點(Concern Point),以此應對不同需求的變化,使得這種變化可以獨立進行。

單一職責原則,是系統設計開發重要的原則。分層架構就時時遵循單一職責原則。不同的層次相互隔離,承擔不同的職責。

說起分層架構,最讓人熟知的就是經典的三層架構。經典三層架構自頂向下由使用者介面層(User Interface Layer)、業務邏輯層(Business Logic Layer)與資料訪問層(Data Access Layer)組成。三層架構是簡單 Client-Server 架構的升級。

不可不知的軟體架構模式three-layer

三層架構的經典和流行,以及大量 Web 後臺框架對三層架構的靠近,使得 Web 後臺開發簡單到一個剛剛入門的開發人員就可以進行 web 開發。也正因為此,使得大部分 web 開發人員的思維受限於此,從而成為人人調侃的 CRUD-Boy。隨著 MIS 系統時代的漸遠,三層架構也開始在一些領域無法成為“銀彈“。

除去經典的三層架構。在領域驅動設計中,Eric Evans 設計了一種經典的四層架構,其在使用者介面層與業務邏輯層之間引入了新的一層,即應用層(Application Layer)。其餘幾層也相應的有所調整。

不可不知的軟體架構模式ddd

Distribute-Cluster

之上所提的架構都是在單體架構之下。單體架構和多服務架構是從服務的部署模式、執行模式來考慮。

單體架構有如下優勢:

  • 易於開發:藉助於開發框架,單體應用的開發及其簡單,開發人員也很少需要考慮系統、部署、網路等層次的問題。
  • 易於測試:單體應用部署在一個程式中,環境簡單。只要服務啟動就可以測試所有的功能。
  • 易於部署:往往只需要將應用打包成一個簡單的包就可。
  • 易於水平擴充套件:只需要將程式包部署多個服務即可。

單體應用的劣勢:

  • 維護成本增加:隨著需求的增多,單體系統將越來越臃腫,維護的複雜性也將越來越大。
  • 持續互動週期長:一方面維護困難,另一方面單體應用在並行開發,並行測試上將十分困難,單體應用十分不適合快速迭代的敏捷開發。
  • 擴充套件性差:由於臃腫的系統,將導致系統擴充套件性變難。系統的升級也需要十分謹慎。
  • 對新人不友好。

分散式系統拆分:

不可不知的軟體架構模式service-scale

隨著網際網路的快速發展,一方面網際網路應用訪問量級大增,資料量大增。另一方面,應用的迭代速度也不斷變快。單體應用的模式已經不適合網際網路的快速發展。這樣,後臺分散式叢集架構越來越流行。

Micro-Service

微服務並沒有一個嚴格的定義。以下是 Martin Fowler 描述的微服務:

微服務架構是一種架構模式,它提倡將單一應用程式劃分成一組小的服務,服務之間相互協調、相互配合,為使用者提供最終價值。每個服務執行在其獨立的程式中,服務與服務間採用輕量級的通訊機制互相溝通(通常基於 HTTP 的 RESTful API)。每個服務都圍繞著具體業務進行構建,並且能夠被獨立地部署到生產環境。

微服務通常具有以下特性:

  • 單一職責:業務獨立,團隊自主。職責單一的服務應該具有核心的領域,高內聚、低耦合,與其他系統和領域確定明確的邊界。
  • 輕量級通訊:通訊應該簡單,輕量。與語言無關,與平臺無關。
  • 獨立性:獨立開發,獨立測試和獨立部署。

一切選擇都是權衡的過程。微服務解決了單體應用的許多問題,自然也會帶來相應的問題。分散式和叢集的環境是複雜的,基於此的微服務架構也將具有相應的複雜度。

隨著微服務的流行,微服務的很多問題也被越來越多的框架和服務解決掉了。我們以 Spring Cloud 技術棧為例:

  • SpringBoot:單體服務,快速建立專案,快速整合各種框架,易於測試,易於部署。
  • Feign:微服務獨立部署,通過相關協議通訊。Feign 就是一個簡單的申明式通訊框架,基於 HTTP restful。
  • Eureka:獨立服務越來越多,服務例項也越來越多。服務治理便是必須的,Eureka 提供高可用的服務註冊和服務發現功能。
  • Ribbon:Feign 只負責通訊,Ribbon 提供客戶端負載均衡,是系統優化的部分。
  • Hystrix:微服務將帶來服務間複雜的依賴關係,分散式和叢集的複雜度也將帶來許多難以預料的問題。為防止複雜網路和複雜系統某一點的問題導致整個系統的雪崩狀態,便有了 Hystrix,Hystrix 是 Spring Cloud 體系中優秀的斷路器,可以在系統發生問題時進行服務降級,防止整體系統崩潰。
  • Zuul:統一閘道器,統一閘道器是以 Facade 模式,對外提供友好的介面,微服務化之後,服務將越來越多,越來越複雜,為了降低外部系統呼叫的複雜度,統一閘道器就是常用解決方案。
  • Config:服務劃分越多,配置將越多,Spring cloud config 提供統一的配置管理。
  • Sleuth:服務監控和治理。監控是複雜系統必需的基礎設施。系統感知、問題發現、效能定位都需要監控的加持。

不可不知的軟體架構模式micro-service

Even-Source

事件溯源是最新流行一種應用程式體系結構模式。事件源將應用程式進行的狀態更改建模為事件的不可變序列或“日誌”。事件源不是在現場修改應用程式的狀態,而是將觸發狀態更改的事件儲存在不可變的日誌中,並將狀態更改建模為對日誌中事件的響應。

不可不知的軟體架構模式event-source

CQRS 模式通常基事件溯源模式。在傳統的體系結構中,使用同一資料模型查詢和更新資料庫。這十分簡單,非常適用於基本的 CRUD 操作。但是,在更復雜的應用程式中,此方法會變得難以操作。例如,在讀取方面,應用程式可能執行大量不同的查詢,返回具有不同形狀的資料傳輸物件 (DTO)。物件對映可能會變得複雜。在寫入方面,模型可能實施複雜驗證和業務邏輯。結果,模型執行太多操作,過度複雜。

CQRS(命令查詢的責任分離 Command Query Responsibility Segregation )將讀取和寫入操作分成不同的模型,使用 命令 更新資料,並使用 查詢 來讀取資料。

Hexagonal

不可不知的軟體架構模式hexagonal

?六邊形架構又稱“埠和介面卡模式”,是 Alistair Cockburn 提出的一種具有對稱性特徵的架構風格。在這種架構中,系統通過介面卡的方式與外部互動,將應用服務與領域服務封裝在系統內部。

六邊形架構由以下三個元件組成:

  • Ports:又可以分為輸入端和輸出端,是系統與其他系統互動的介面。
  • Adapters:與其他系統的適配層,一方面防止核心系統和領域被外部影響,即防腐;另一方面方便 api 使用。
  • Domain:應用和模型是程式的核心。

六邊形架構的核心理念是:應用通過"埠"跟外部進行互動。在傳統的分層架構中很容易跨越層間的邊界,把業務邏輯滲透到其它層中去。六邊形架構重要的就是“邊界”和“領域”。六邊形架構的初衷是為了解決技術與業務系統的解耦合問題,以及技術與技術間的解耦合問題,這一架構從設計模式中來,從業務的實體服務出發,將面向介面的設計具體化的埠協議和介面卡實現,服務自身實現獨立性和完備性。

參考:

《系統架構——複雜系統的產品設計與開發》丹尼爾·塞爾瓦
《構建之法——現代工程》鄒欣
《微服務架構與實現》王磊
《領域驅動設計——軟體核心複雜性應對之道》Eric Evans
《實現領域驅動設計》Vaughn Vernon
《Spring Cloud 微服務實戰》翟永超
《工程學——無盡的前沿》歐陽瑩之
《人月神話》Frederick P. Brooks, Jr.

 

關注 「程式設計師修煉之旅」後臺回覆加群,可新增個人微信進入專屬技術群。

不可不知的軟體架構模式

 

相關文章