微服務設計指南

EAWorld發表於2018-11-15

微服務設計指南

本文為翻譯發表,轉載需要註明來自公眾號EAWorld。

作者:Thilina Ashen Gamage

譯者:白小白 

原題:Microservices Design Guide

原文:http://t.cn/EAvCCMb


全文5949字,閱讀約需要10分鐘

2018年,每個人都聽說過微服務。但你知道怎麼設計嗎?

微服務是當今軟體工程師的一個熱門話題。讓我們瞭解如何使用微服務架構風格構建真正模組化、業務敏捷的IT系統。

一、微服務概念

微服務體系結構由輕量級、鬆散耦合的服務集合組成。每個服務都實現了單個業務功能。理想情況下,這些服務應該是具有足夠的內聚性,可以獨立地開發、測試、釋出、部署、擴充套件、整合和維護

正式定義 

“微服務架構風格是一種將單個應用程式開發為一組小型服務的方法,每個小服務執行在自己的程式中,並且以輕量級機制(通常是HTTP REST API)通訊。這些服務是圍繞業務能力建立的,並且可以由完全自動化的部署機構獨立部署。這些服務的集中管理只有最低限度,可以用不同的程式語言編寫並使用不同的資料儲存技術。”

——  James Lewis and Martin Fowler

定義微服務的特性

  • 每個服務都是一個輕量級、獨立和鬆散耦合的業務單元。

  • 每個服務都有自己的程式碼庫,由一個小團隊管理和開發(主要是用於敏捷環境中)。

  • 每個服務負責一部分功能或者說業務能力,並且做得很好。

  • 每個服務都可以為其用例選擇最佳的技術棧(無需將整個應用程式繫結在一個框架中)。

  • 每個服務都有自己的DevOps計劃(測試、釋出、部署、擴充套件、整合和獨立維護)。

  • 每個服務都部署在一個獨立自給的環境中。

  • 服務通過使用定義良好的API(智慧端點)和簡單協議如基於HTTP 的REST協議(啞管道)相互通訊。

  • 每個服務負責持久化自己的資料和保持外部狀態(只有當多個服務使用相同的資料時,這種情況才在公共資料層中處理)。


小白

智慧端點和啞管道,其實我一直認為“啞”管道不如“笨”管道或者“呆”管道更易理解。防呆設計是一種預防使用者錯誤使用產品造成不良後果的設計理念,比如USB設計成一半有實體晶片,就是讓使用者可以不假思索的在插錯後直接掉轉方向再插。不讓使用者思考就是“呆”的含義。“啞”管道的“啞”其實就是體現在微服務的通訊過程儘量簡單,不要讓通訊機制有“思考能力”,不在其中加入過多的處理機制,反例是SOA時代的ESB產品,ESB產品通常會包含複雜的設施用於訊息路由,編排和轉換,以及業務規則應用。反過來,智慧端點的概念就容易理解了,也就是將與某服務相關的處理都限定在微服務的範疇之內,通訊過程中的微服務端點是“智慧”的,這也從一個方面體現了微服務“高內聚”的含義,有了高內聚,才能具備自治和獨立性,從而可以支援“鬆耦合”的機制。

微服務的好處

微服務可以用於擴充套件大型系統,也為持續整合和交付提供了巨大的能力。

微服務設計指南

Scale Cube:用於可伸縮性的三維模型

(圖片:Nginx部落格)

獨立縮放:《 The Art of Scalability》( http://t.cn/EAvlQ4o)這本優秀的書中所描述的Scale Cube概念,是微服務架構所支援的。在開發微服務以實現功能分解時,應用程式通過Y軸自動縮放。當服務呼叫量較高時,微服務可以通過克隆更多的CPU和記憶體,通過X軸進行擴充套件。為了在多臺機器上分發資料,可以分離大型資料庫(分庫分表)轉換成更小、更快、更容易管理的部件,從而實現Z軸的縮放。

獨立釋出和部署:使用微服務,Bug修復和特性發布更易於管理,風險更小。可以在不重新部署整個應用程式的情況下更新服務,並在出現問題時回滾或前滾更新。

獨立開發:每個服務都有自己的程式碼庫,由一個小的焦點小組開發、測試和部署。開發人員可以專注於一種服務,並且只關注相對較小的範圍。這將提高生產率、專案速度、持續創新能力和原始碼質量。

優雅降級:如果服務崩潰,其影響不會傳播到應用程式的其他部分,並導致系統發生災難性故障,從而體現某種程度的健壯性。

分散治理:開發人員可以自由選擇技術棧,制定最適合其服務的設計標準和實現決策。團隊不必因為過去的技術決定而受到懲罰。

業務關切

獨立的服務本身並不能形成一個系統。要使微服務體系結構真正成功,需要大量投資來處理跨系統的問題,例如:

  • 服務複製:一種讓服務易於擴充套件的基於後設資料的機制

  • 服務註冊和發現:啟用服務查詢並查詢服務端點的機制

  • 服務監測和日誌:收集來自不同微服務的日誌的機制,並提供一致的報告

  • 彈性:服務在故障期間自動採取糾正行動的機制

  • DevOps:處理持續整合和部署的機制(CI和CD)

  • API閘道器:為客戶端提供入口的機制


二、中介軟體與設計模式

API閘道器(所有客戶端的單一入口點)

微服務設計指南

API閘道器風格的微服務體系結構(圖片來自:Microsoft Azure Docs),是用於微服務的最常見的設計模式。API閘道器是一箇中間層,具有最小化的路由功能,只是充當一個“啞管道”,裡面沒有業務邏輯。一般來說,API閘道器允許客戶端基於REST/HTTP呼叫託管的API。其他型別的微服務整合模式有:點對點風格(直接從客戶端應用程式呼叫服務)和訊息代理風格(實現非同步訊息傳遞)。

API閘道器充當所有客戶端的單一入口點,API閘道器也作為一種邊緣服務來將微服務作為託管API公開給外部世界。這聽起來像是一個反向代理,但也有一些額外的責任,例如簡單的負載平衡,認證和授權,故障處理,稽核,協議轉換,和路由機制。開發團隊可以選擇以下方法之一來實現API閘道器。

  • 自己程式設計實現:具有更好的客戶化和管控能力。

  • 部署現有的API閘道器產品:節省初始開發時間,並使用高階內建功能(缺點在於:此類產品依賴於供應商,並不完全免費。配置和維護通常是冗長而耗時的)

解釋API閘道器行為的一些設計模式如下(請參閱微服務設計模式 http://t.cn/RKx8bhG).

閘道器聚合(http://t.cn/EAvT2jl):將針對多個內部微服務的多個客戶端請求(通常是HTTP請求)聚合到單個客戶端請求中,減少了使用者和服務之間的互動和網路延遲。

閘道器分流(http://t.cn/EAvTGmA):使單個微服務能夠將一些共享的服務功能分流到API閘道器級別。這些跨服務功能包括認證、授權、服務發現、容錯機制、QoS、負載平衡、日誌記錄、分析等。

閘道器路由(第7層路由,通常是HTTP請求 http://t.cn/EAvTMm4):使用單一入口端點將請求路由到內部微服務的端點,這樣服務呼叫者就不需要自行管理多個獨立的端點

請注意,API閘道器應該始終是一個高可用性和高效能的元件,因為它是整個系統的入口點。

事件匯流排(用於非同步事件驅動通訊的、釋出/訂閱、中介通道)

微服務設計指南

微服務之間基於事件驅動的非同步通訊實現最終一致性

(圖片來源:microsoft.com)

應用程式的不同部分在進行相互通訊時,無論訊息的順序(為處理非同步的訊息)或使用的語言(為了體現語言無關性),都可以使用事件匯流排來實現。大多數事件匯流排支援釋出/訂閱、分散式、點對點和請求響應訊息傳遞。一些事件匯流排(如Vert.x)允許客戶端使用相同的事件匯流排與相應的伺服器節點進行通訊,這是全堆疊團隊所喜愛的一個很酷的特性。

服務網格(用於服務間通訊的外掛(Sidecar)機制)

微服務設計指南

服務網格風格的服務間通訊

(圖片來源:微服務實踐http://t.cn/EAAJWRi)


微服務設計指南

如何在應用程式中使用服務網格

(圖片來源:http://t.cn/EAAizgn)

服務網格通過提供服務間通訊的輔助架構來實現外掛模式,包括彈性(容錯、負載平衡)、服務發現、路由、可觀察性、安全性、訪問控制、通訊協議支援等功能。

微服務設計指南

服務網格在網路堆疊中的位置

(圖片來源:http://t.cn/EAAizgn)

實際上,外掛例項部署在每個服務的旁邊(理想情況下是在同一個容器中)。他們可以通過服務本身的網路功能來進行通訊。服務網格的控制平面被單獨部署,以提供中心功能,如服務發現、訪問控制和可觀察性(監視、分散式日誌記錄)。最重要的是,服務網格風格的設計模式允許開發人員從微服務程式碼中分離網路通訊功能並使服務只關注於業務功能。(來自:Netflix Prana, 微服務網格)

儘管上面的圖片顯示了服務之間的直接連線,但是處理服務間通訊的好方法是使用一個簡單的事件匯流排作為中介,以保持最低階別的耦合。

聚合器(BFF模式)

微服務設計指南

在API閘道器級別上實現BFF模式和聚合器模式

(圖:microsoft.com)

如果應用程式需要裁剪每個API以適應客戶端應用程式型別(Web端、移動端以及其他不同平臺),則可以通過聚合器(Aggregator)執行不同的業務規則,也可以執行不同的配置以根據客戶端功能適配不同的構建。這可以在API閘道器級別實現,也可以在服務級別並行實現。這種模式對於提供特定的使用者體驗非常有用。但是,開發團隊應該足夠小心,將BFF保持在可管理的範圍內。

小白

“通過聚合器”,原文是“via a facade”,直譯是“通過一個外觀/門面”。門面模式(外觀模式),是一種Java的設計模式,為子系統中的一組介面提供了一個統一的訪問介面,引申自一個前店後廠的生意模式,前面是門面,後面會有進料、生產、包裝多個服務。用在這裡是指將相關的服務通過聚合器聚合在一起,這個聚合器就是門面。服務呼叫者與門面互動而不是與一組服務互動降低了耦合性,但同時違反了物件導向設計原則開閉原則,開閉原則要求模組在擴充套件時可以不改動內部的程式碼,但顯然當聚合器後端的某個服務發生變更時,需要在聚合器層面也發生變更,這也是文中說“開發團隊應該足夠小心”的原因,因為違反了開閉原則,就會降低可複用性。

三、最佳實踐

領域驅動設計:圍繞業務領域進行服務建模。


微服務設計指南

為了處理大型模型和團隊,可以應用領域驅動設計(DDD)。DDD通過將大型模型劃分為不同的有界上下文來明確他們之間的相互關係和子領域。這些有界上下文可以在應用設計級別轉換為單獨的微服務。(參見:領域驅動設計中的有界上下文 http://t.cn/EAAK4Xk

分散資料管理(避免共享資料庫):當多個服務使用一個共享資料架構時,會在資料層形成緊耦合。為了避免這種情況,每個服務都應該有自己的資料存取邏輯獨立資料儲存。開發團隊可以根據服務和資料性質的不同自由選擇最適合的資料永續性方法。

微服務設計指南

避免共享資料儲存和訪問機制

(圖片來源:http://t.cn/RcLB5Kv)

智慧端點和啞管道:每個服務都擁有一個定義良好的外部通訊API,並儘量避免洩露實現細節。通訊則始終使用簡單協議,如基於HTTP的REST協議。

非同步通訊:當跨服務使用非同步通訊時,其他服務不會阻塞資料流。

微服務設計指南

同步訊息和非同步訊息傳遞

(來源: http://t.cn/EAA9xRU)

避免服務耦合:服務應保持鬆耦合高內聚。產生耦合的主要原因包括共享資料庫模型和嚴格的通訊協議。

分散開發:避免在多個服務/專案之間共享程式碼庫、資料架構或開發團隊成員。讓開發者從源頭上關注創新和質量。

將領域知識排除在閘道器之外:讓閘道器處理路由和跨服務問題(如身份驗證、SSL終端等)。

基於令牌的認證:不要在每個微服務級別實現安全元件,因為這將需要元件與集中式/共享使用者儲存庫對話並檢索身份驗證資訊;而是考慮實現API閘道器級別的身份驗證,使用廣泛使用的API安全標準,如OAuth2和OpenID Connect。一旦從認證提供者獲得令牌之後,就可以用於與其他微服務進行通訊。

微服務設計指南

使用OAuth2和OpenID Connect的微服務安全性

(來源:Kasun’s Blog http://t.cn/EAACGvY)

事件驅動性質:既然人可以成為對事件作出反應的自主主體,系統也可以。(參見:為什麼微服務應該是事件驅動的:自主性與權威性 http://t.cn/EAACWOx)

最終一致性:由於微服務的高內聚特性,很難在整個系統內實現很強的一致性。因此開發團隊必須處理最終一致性。

容錯:由於系統由多個服務和中介軟體組成,因此在某些地方可能很容易發生故障。對於這些薄弱環節,有一些實現模式,如斷路器,防水艙,重試,超時,快速失敗,故障轉移快取,速率限制,負載釋放,可以將重大故障的風險降到最低。(參見:設計一種面向故障的微服務體系結構http://t.cn/RChKlg9)

產品工程化:把微服務工程化為一種產品,而不是作為一個專案,可以讓微服務更好的發揮作用。這意味著,不能僅僅考慮能用而且及時交付,而是要長期致力於卓越的工程化。

四、微服務實踐

何時使用微服務

微服務架構最適合的應用場景:

  • 具有高可伸縮性需求的應用

  • 對交付速度要求較高的專案

  • 具有豐富域或多個子域的業務用例

  • 小型、跨功能的開發團隊協作開發大型產品的敏捷環境(請參閱:微服務架構的真正成功故事 http://t.cn/EAANng7)

一些實現微服務的入門框架

Vert.x:輕量級,易於理解/實現/維護,多語言支援(支援多種語言),事件驅動,非阻塞,可以說,具備了以最少的硬體處理高併發需求時的最佳效能和可伸縮性,並且具備足夠的開放性(與傳統的限制性框架不同,Vert.x只提供有用的元件,開發人員可以自由地創新並仔細構建他們的應用程式)

Akka:令人滿意的效能,實現了Actor模型(一種併發模型),有利於響應式微服務和事件驅型微服務

Spring Boot/Spring Cloud:容易上手(採用熟悉正規化),基於良好的舊Spring框架,有點重的框架,許多整合可用,大規模的社群支援

Drop Wizard:有利於RESTful Web服務的快速開發,它搭載了一些不錯的Java工具和庫,如Google Guava、Jetty Server、Logback、Hibernate Validator、Joda Time、Jersey和Jackson。

部署選項

容器:有利於執行DevOps目標(快速開發,縮短上市時間,無縫縮放)

雲端計算架構:有利於構建可靠和可伸縮的基礎設施,為地理位置分散的使用者服務。

無伺服器架構:適合處理高度不穩定的流量。

維護自己的IT基礎設施:對那些擁有足夠能力和資源建設整個基礎設施的組織來說是件好事。

微服務的開發理念

自給系統:由獨立系統組裝軟體(按業務垂直切分系統)

微前端:將單體應用的Web UI劃分為獨立的特性,這些特性可以作為獨立的UI元件開發,並直接與微服務進行通訊。

需要搜尋和學習的關鍵詞

領域驅動設計(DDD)有界上下文(BC)| 聚合永續性(PP)命令和查詢責任隔離(CQRS)| 命令查詢分離(CQS)| 事件溯源(ES)CAP定理 |最終一致性 |十二要素應用 |SOLID原則 |

五、參考架構


微服務設計指南

用於線上購物應用程式的微服務體系結構

(圖片:microsoft.com)

此體系結構是由使用Microsoft技術的Microsoft開發人員提出的。在這裡,API Gateway是針對不同的Web和移動使用者而定製的。對於資料層,資料儲存技術是根據業務功能仔細選擇的(關聯式資料庫用於結構化資料,Redis用於臨時資料快取,MongoDB和Cosmos DB用於非結構化資料)。事件匯流排處理服務間通訊。撇開技術不說,這是基於微服務的應用最常見的整合模式

微服務設計指南

一種非阻塞應用程式的微服務體系結構,該應用程式使用來自各種事件源(例如交通資料、天氣指數、股票市場線索、社交媒體帖子、感測器輸出)的大量輸入資料流來向終端使用者顯示實時更新。這些輸入資料流最初由使用Kafka實現的事件日誌收集。它將資料儲存在磁碟上,因此可以用於批處理呼叫(分析、報告、資料科學、備份、審計)或用於實時呼叫(運營分析、CEP、管理儀表板、警報應用程式)。上圖中,使用Spark按指定的時間間隔,將持續的輸入資料流劃分為微批次,並輸入到WSO2 Siddhi CEP引擎中。後者標識事件並使用MongoDB儲存以非結構化形式儲存資料。微服務調取這些資料並顯示給終端使用者。仔細觀察這一設計, Vert.x事件匯流排能夠建立與前端UI元件的連線,該特性僅用於有效地更新UI中的相關部分。撇開技術不說,這是基於事件驅動的非阻塞微服務應用程式的一個很好的架構。

微服務設計指南

用於訂單管理應用程式的雲原生泛渠道微服務體系結構(圖片:ibm.com)這個設計的一個主要特點是,IBM架構師沒有使用API閘道器,而是為每個客戶端通道(移動應用程式、Web應用程式、IOT裝置、API使用者)提出了一個具有獨立後端的邊緣層。另一個特點是將微服務層劃分為業務邏輯層和基礎層兩個子層。基礎層(即核心服務層)使用各種雲原生服務(雲資料儲存、整合和索引Watson會話的Elastic搜尋引擎)處理持久化和整合任務。業務邏輯層整合了基礎層的資料,並提供了有意義的業務功能。這將是一個很好的架構,可以為地理上分散的大量使用者群提供服務,並通過各種平臺訪問應用程式。

關於作者:前 @MillenniumIT 平臺開發部工程實習生 - 熱衷於快速的網路開發 - PlatformEngineer.com

關於EAWorld:微服務,DevOps,資料治理,移動架構原創技術分享

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31562043/viewspace-2220182/,如需轉載,請註明出處,否則將追究法律責任。

相關文章