軟件架構:5種你應該知道的模式

Singleton(單例模式)、倉儲模式(repository)、工廠模式(factory)、建造者模式(builder)、裝飾模式(decorator)……大概每一個上課聽講的程序員都不會陌生——軟件的設計模式爲咱們提供了針對現有的、重複出現的問題以可靠的解決方案。git

在軟件架構方面一樣存在相似的機制,通用的、可重用的解決方案在給定上下文中的軟件體系結構中常常出現的問題。不一樣的軟件架構模式各有千秋,如下是目前較爲主流的5種軟件架構模式。程序員

分層模式(Layered Pattern)

分層模式大概是最知名的軟件架構模式之一,有大量的開發者使用,但並不知道它的名字。分層模式將代碼拆分爲「層」,每一個層都有必定的責任,併爲更高「層」服務。github

分層模式並無規定層的數量,但一般會有如下結構:數據庫

  • 表現層 / UI層
  • 應用層
  • 業務/域(domain)層
  • 持久/數據訪問層
  • 數據庫層

分層模式的想法是用戶經過執行某些動做(例如點擊按鈕)在表現層啓動一段代碼。隨後,表現層調用應用層、進入業務層,最後持久層將全部內容存儲在數據庫中。簡單來講,分層模式中的高層調用並依賴低層。設計模式

根據應用複雜程度,咱們會看到不少相應的變體。例如某些應用會省略應用層,而某些應用會添加緩存層,甚至會出現兩層合一的狀況。緩存

層責任

如上所述,每層有每層的責任。表現層包含應用的圖形設計和處理交互的代碼。理論上來說,咱們不該該在這一層添加任何與user interface無關的邏輯。服務器

業務層是放置特定業務問題模型和邏輯的地方。微信

應用層位於業務層和和表現層之間。一方面爲表現層提供業務層抽象,另外一方面爲應用層提供放置某些不適合放置於業務層或表現層的某些協調邏輯。架構

持久層包含訪問數據庫層的代碼,而數據庫層是底層數據庫技術,例如SQL Server、MongoDB。持久層是用於操做數據庫的代碼集:SQL語句、鏈接詳情等。框架

優點

  • 大多數開發者都很熟悉
  • 一種用於編寫組織良好而且可測試應用的簡單方法

劣勢

  • 分層模式每每會致使應用的「一體化」並使之變得難以拆分
  • 開發者每每會發現本身編寫了大量的代碼來傳遞不一樣的層,而沒有在這些層裏添加任何值。若是咱們作的只是編寫一個簡單的CRUD應用,分層模式可能有點過度了。

適用於

  • 標準的、不只僅用於完成CRUD操做的業務線(line-of-business)應用

微內核模式(Microkernel)

當應用程序有一組核心職責和一組可互換的部件時,微內核模式(或插件模式)很是有用。微內核將提供應用程序的入口點和通常流程,而不須要真正瞭解不一樣的插件在作什麼。

例如任務調度,微內核能夠包含全部的調度和觸發邏輯,而插件負責特定的任務。只要插件遵循特定的API,微內核就能夠出發它們,而不須要了解實現的細節。

另外一個例子是工做流。工做流的實現包含諸如不一樣步驟的順序、評估步驟的結果、決定下一步的內容等概念,步驟的的具體實現對於工做流的核心代碼並不重要。

優點

  • 靈活性 & 可擴展性
  • 某些實現容許咱們在應用運行時添加插件
  • 微內核和插件能夠由不一樣團隊開發

劣勢

  • 難以肯定哪些東西屬於微內核
  • 預約義的API可能不適合將來的插件

適用於

  • 從不一樣來源獲取數據、轉換數據並寫入不一樣地方的應用
  • 工做流應用
  • 任務和做業調度應用

命令職責查詢分離模式(CQRS)

CQRS是Command and Query Responsibility Segregation的縮寫。這種模式的核心概念是應用具備徹底分離的讀取操做和寫入操做,這也意味着用於寫操做(命令)的模型和讀取(查詢)不一樣。此外,數據將存儲在不一樣的位置。在關係數據庫中,意味着將存在用於命令模型的表和用於讀取模型的表。一些實現甚至將不一樣的模型存儲在徹底不一樣的數據庫中,例如用於命令模型的SQL Server和用於讀取模型的MongoDB。

CQRS模式一般和事件溯源(Event Sourcing)結合,下一小節會講到。

CQRS如何工做?當用戶執行操做,應用會向命令服務器發送命令。命令服務從命令數據庫中檢索所需的任何數據,進行必要的操做並將其存儲回數據庫中,而後它通知讀取服務,以便更新讀取模型。以下所示:

當應用須要向用戶顯示數據時,它能夠經過調用讀取服務來檢索讀取模型,以下所示:

優點

  • 命令模型專一於業務邏輯和驗證,讀取模型根據特定情境進行定製
  • 能夠避免複雜的查詢,讓讀取更高效

劣勢

  • 保持命令和讀取模型同步可能會讓事情變得很複雜

適用於

  • 須要大量讀取的應用
  • 有複雜域的應用

事件溯源模式(Event Sourcing)

這種模式不會將模型的當前狀態存儲在數據庫中,而是將時間存儲其中。所以,例如customer name發生變化時,該值不會存儲在「name「列中,咱們會存儲一個」NameChanged「事件。

當咱們須要檢索模型時,咱們將檢索其存儲的全部事件並在新對象上從新應用,即rehydrating an object。

用EXCEL記帳來理解event sourcing會容易一些。當咱們添加支出時,咱們不需更改總值,而是增長一「行」,出現錯誤,也增長一「行」,最終利用EXCEL的公式自動計算出總數,而這裏計算總數能夠看做是讀取模型。

您能夠看到咱們在添加Invoice 201805時發生了錯誤。咱們添加了兩條新行,而不是更改行,首先是一行取消錯誤的行,而後是新的正確行。這就是event sourcing的工做方式。你永遠不會刪除事件,由於它們無能否認地發生在過去。爲了糾正狀況,咱們添加了新事件。

另外,請注意咱們是如何獲取總值的,它是上面單元格中全部值的總和。在Excel中,它會自動更新,所以咱們能夠說它與其餘單元格同步。這就是一個讀取模型。

Event sourcing一般會與CQRS同時使用,由於rehydrating an object可能會對性能產生影響,尤爲是當實例中存在大量事件時。快速讀取模型能夠顯着改善應用的響應時間。

優點

  • 提供「開箱即用」的audit log,每一個事件即特定時間點上的特定操做

劣勢

  • event sourcing有必定的限制要求,咱們不能直接經過數據庫中的簡單編輯來修復錯誤數據
  • 改變事件的結構比較複雜

適用於

  • 須要發佈事件到外部系統的應用
  • CQRS應用
  • 有複雜域的應用
  • 須要數據修改audit log的應用

微服務模式(Microservices)

編寫一組微服務實際上就是編寫能夠協同的多個應用。每一個微服務都有本身獨特的責任,團隊能夠獨立於其餘微服務開發它們。他們之間惟一的依賴是通訊。當微服務相互通訊時,咱們必須確保它們之間發送的消息保持backwards-compatible(向後兼容)。這須要一些協調,特別是當不一樣的團隊負責不一樣的微服務時。

以下圖所示——

在上圖中,應用調用一箇中央API,將調用轉發給正確的微服務。在此示例中,有爲用戶配置文件、庫存、訂單和付款提供單獨的服務。咱們能夠想象這是一個用戶訂購應用。單獨的微服務也能夠相互調用。例如,支付服務能夠在支付成功時通知訂單服務。而後,訂單服務能夠調用庫存服務來調整庫存。

沒有明確規定微服務有多大。在前面的示例中,用戶配置文件服務可能負責用戶的用戶名和密碼等數據,也可能負責家庭地址、頭像圖像、收藏夾等,也能夠選擇將全部這些責任分紅更小的微服務。

優點

  • 咱們能夠單獨編寫、維護、部署微服務
  • 微服務架構容易擴展
  • 重寫變得很容易,由於微服務之間鬆耦合

劣勢

  • 實際上沒有合適的工具平臺,反而在最初編寫結構良好的一體化應用,再拆分爲微服務的辦法實際上更容易。使用微服務,會產生許多額外的問題:通訊、協調,向後兼容、日誌記錄等。沒有編寫結構良好的總體結構的必要技能的團隊可能很難編寫一組良好的微服務。
  • 傳統微服務架構可能會有多個失敗點,查找問題可能會比較複雜

適用於

  • 某些組件被密集使用並須要擴展的應用
  • 爲其餘應用提供功能的應用
  • 一體化架構下很複雜的應用
  • 可以明肯定義bounded contexts的應用

總結

各類軟件架構模式不少時候會結合起來使用,他們之間並無咱們想象得那麼水火難容。換句話說,沒有萬能的軟件架構模式,如何選擇取決於咱們對於解決方案利弊的權衡。

關於Rainbond

當下,已經有很大一部分公司完成了單體架構向微服務架構的遷移改造,並在疲於應對大量微服務間通訊問題時,開始考慮採用Service Mesh微服務架構做爲服務與服務直接通訊的透明化管理框架,以插件式的方式實現各類業務所需的高級管理功能。

而開源PaaS Rainbond提供了開箱即用的Service Mesh微服務架構,部署在Rainbond上的應用原生便是Service Mesh微服務架構應用。

相關文章
相關標籤/搜索