微服務架構設計


微服務架構設計

Photo by Tatiana Latino on Unsplash

注意:本文內容是我的見解,而非我的僱主或其他實體的見解。

什麼是微服務?

從最簡單的定義來看,微服務架構是將邏輯域劃分為獨立服務的同時開發軟件的行為。 在過去的六年中,我聽說微服務方法學以驚人的速度增長。 每個人都在談論微服務!

還有另一個轉變,那就是從雲計算到微服務。〜Steve Singh(Concur)

大多數尚未使用微服務的工程師都生活在整體代碼庫中。 生活在一個單一的世界中並不都是一件壞事,並且可以使用許多已建立的架構模式來構建應用程序。 歸根結底,您必須選擇最適合您的應用的應用,而不是流行的應用。 如果將微服務作為體系結構模式,則邏輯和數據流在服務之間的分解和分佈方式之間存在一些根本差異。 讓我們快速看一下下面的兩個示例。

微服務架構設計

Microservices vs Monoliths

通過分解整體並分離層,您可以交換/更新單個層,而無需部署整個代碼庫! 不過,這僅僅是開始。

現在,您可以創建物理抽象層以分解代碼和邏輯。 創建這些域可以使工程師輕鬆找到並修復功能。 這也允許獨立部署域。 這些抽象也可以通過諸如nuget / npm / etc之類的Package References共享代碼。

微服務引入的另一個概念是隔離的數據存儲。 微服務中的數據存儲有兩種思路:隔離數據庫或共享數據庫。 如果它是共享數據庫,則建議按架構拆分域。 雖然,如果它是一個隔離的數據庫,您可以決定是否要為不同的域使用不同類型的數據存儲。 您的客戶域可能使用Sql Server數據庫,而您的訂單歷史記錄域可能使用MongoDB。 同樣,使用正確的工具完成正確的工作!

網關:您不得通過

可以控制基礎結構暴露的一種方法是網關。 可以將它視為控制服務的數據/邏輯流的一種方法,或者將一個或多個域包裝在一起的一種方法。 我使用網關將外部OAuth身份驗證轉換為我的內部基礎結構可以理解的標準共享密鑰,以使其輕巧。 對於那些熟悉領域驅動設計的人,我最好的建議是將每個微服務視為有界上下文,並將每個網關都視為域。

微服務架構設計

實施網關有很多好處:

  • 使用網關來分解身份驗證類型或訪問方法。
  • 使用網關來拆分域。
  • 使用網關按用戶類型,區域或租戶指示流量。
  • 使用網關將外部流量與管理流量分開。

混合代碼? 嗯?

微服務架構的一個很酷的方面是,您的整個基礎架構不必全部都是相同的結構甚至是相同的語言! 將應用程序的邏輯域分解為微服務可以使您能夠使用正確的工具來完成正確的工作。 如果您的代碼庫是.net,但您確實希望在Elixir中編寫基礎結構的線程密集型部分,沒問題! 這也有其自身的問題,但我確實鼓勵混合水平的團隊組成。 不同的平臺和語言都有各自的優缺點。 如果做得對,這可以帶來很多好處:

  • 跨團隊的交叉授粉模式
  • 向您的工程師介紹新技術
  • 允許感興趣的工程師突破常規並使用其他語言進行實驗


讓我們分解一個例子

繫好安全帶,這可能需要一點時間。 讓我們更深入一點,設計一個理論架構。 在不深入研究雜草的情況下,讓我們定義一個跨越幾個重要邊界的非常簡單的商務應用程序。

問題:我們想構建一個公共API來跟蹤客戶,允許下訂單並保留訂單的歷史記錄。 我們希望允許該API支持現代的前端,移動應用程序和第三方集成。 我們還知道,用戶在高峰時段瀏覽產品的頻率要比下訂單的頻率高100倍。 用戶創建訂單時,我們要向他們發送電子郵件。

微服務架構設計

An example microservice architecture to support a commerce application.

解決方案:上面的解決方案乍看之下似乎很複雜,但對我來說幾乎沒有。 我的第一步是定義我的域,在本例中是產品,訂單,歷史記錄和客戶。 我不希望我的服務集成必須單獨處理每個服務,否則可能會導致業務邏輯出現一些其他嚴重問題。

但是為什麼要有兩個網關? 這是兩倍。 我想避免網關做太多事情,但是它也允許集成有選擇地實現功能。 這也使我可以在購物周圍部署更新,而不必部署與客戶相關的更新。 我們要避免網關變得單一。

每個服務都應該是自包含的,並且不應跨越域壁壘。 這也包括數據存儲。 如果需要合併兩個服務之間的邏輯,請在網關中將調用綁定在一起。 "不要越過溪流!"

微服務架構設計

要提到的一件事是電子郵件集成。 這是參數的一個示例:服務或包引用。 我個人認為,應該將諸如SendGrid之類的電子郵件集成包裝在基礎結構服務中,以便您可以標準化處理電子郵件的方式。 電子郵件集成的很多因素使簡單的軟件包參考變得複雜。 讓我們舉幾個……

  • 批量發送電子郵件?
  • 交貨時間表?
  • 緩存的電子郵件模板?
  • 客戶品牌?
  • 電子郵件記錄?

如果有這些,則可能需要考慮將其包裝在服務中,並將元數據存儲在該服務的數據庫中。

好了,最後一項…數據位於一堆不同的數據庫中,那麼報告呢? 我有一個建議給你; 每個獨立的數據庫都應具有自己的ETL過程,該過程可以對數據進行非規範化並將其存儲在數據湖中。 我還建議任何BI工具都應直接從數據湖查詢。 有很多方法可以給貓咪貼皮,但是我喜歡看到人們提出的創新解決方案。


優點缺點

選擇微服務有很多優點和缺點,您必須確定最適合您的解決方案。

現在您有100個問題:在過去採用微服務時,我看到的一個結果是,開發人員試圖使一切都成為微服務。 我認為,出於抽象的考慮,它離抽象有點太近了。 對於某些人來說這可能是個滑坡,除非您有成熟的團隊,否則這可能成為不利條件。

除非您的系統過於複雜而無法作為一個整體進行管理,否則不要考慮使用微服務。 大多數軟件系統應構建為單體應用程序。 請務必注意該整體中的良好模塊化,但不要嘗試將其分為單獨的服務。-Martin Fowler

獨立部署:一個巨大的(有點明顯)優勢是單個服務的部署可以打破大型"爆炸式"部署。 一旦功能完成並針對生態系統的其餘部分進行了集成測試,您就可以部署它,而不必部署整個堆棧。

隔離域:我想向人們介紹的一個概念是安全域概念。 在設計微服務的拓撲時,應考慮這一點。 控制訪問權限和服務的生存方式,是使服務在需要的地方保持簡單,但在其他地方保持健壯和安全的一種很好的方法。 以這種方式控制訪問,也不再需要向"授權"工程師抽象超敏感服務。

微服務架構設計

Secure Domains using Infrastructure as Security

通過基礎架構實現安全性:將應用程序劃分為微服務的一個真正令人敬畏的結果是,能夠將敏感或管理服務抽象到防火牆後,並且僅將對它的訪問權限列入白名單。 這意味著,例如,電子郵件微服務不可公開訪問,但是您的公共服務可以使用它。 這大大減少了應用程序的公共空間。

共享基礎結構:沿著這種模式,您應該假設,您在域堆棧中越走越遠,服務就可以變得越"共享"。 並非總是如此,但絕對是多數。 電子郵件服務就是一個很好的例子。 與允許每個服務與SendGrid通信(例如)相反,我將構建一個微服務來承擔該責任。 所有需要電子郵件功能的服務都需要與該服務進行對話,以便我可以控制誰可以訪問。 它還為我提供了一個處理品牌或模板的位置!

數據庫是獨佔還是共享?

進入微服務時,您首先要做出的決定之一是選擇每個服務使用一個數據庫還是跨服務使用共享數據庫。 就個人而言,我更喜歡每個服務使用一個數據庫來解耦數據並創建更容易的部署管道。 如果選擇這種方式,則需要確定如何跨數據庫整合外鍵或查找數據。 如果您需要將這些數據放在一起進行分析或報告,通常可以將其ETL放入數據倉庫並整理數據。

示例:如果您有一個用於客戶的微服務和一個用於訂單歷史記錄的微服務,則需要將CustomerId與訂單歷史記錄一起存儲。 當ETL運行此歷史記錄記錄時,您將預取客戶記錄並將數據展平以存儲在數據池中的表中。

微服務適合我嗎?

微服務並非適合所有人。 邁出下一步還意味著要做好準備……成功和失敗。 這是為工作選擇合適的工具。 有時,這意味著您不必選擇"熱門"技術。 新技術並沒有錯,但保持公正很重要。

如果您無法構建整體,那麼為什麼您認為微服務才是答案?-西蒙·布朗

微服務架構設計

採用微服務與成熟度和剛性有關。 您必須準備好在部署和數據管道流程中引入一些麻煩,因為使用微服務,您可以獨立部署較小的代碼單元,並且必須確保一旦部署,它不會破壞現有的任何內容。

您必須準備好完全採用語義版本控制和包管理。 引入微服務時,我經常聽到工程師對軟件包管理和"轉換版本"的抱怨。 是的,這可能很麻煩,但部署時會有些許痛苦,但會引起一些注意。

好的,微服務適合我,現在呢?

有很多策略可以將整體拆分為微服務,我將在另一篇文章中深入介紹。 但是在此之前,讓我們介紹一些高層次的興趣點。 有四個要點要解決,我將按照採用的順序進行介紹。

1 突破基礎架構服務:將基礎級別的功能區域分解為整個集群可以使用的服務,這是打破整體的重要的第一步。

電子郵件微服務就是一個很好的例子。 您可以輕鬆引用Sendgrid nuget包並開始發送電子郵件。 但是,如果您想對每封電子郵件應用邏輯(例如將其包裝在模板中),該怎麼辦? 您應該站起來一個微服務,該微服務採用通用的數據合同來發送電子郵件,將其封裝在服務內的模板邏輯,並使其完成發送電子郵件的工作。 這也使您能夠更改電子郵件提供商/機制並僅部署微服務。

2 將可重複使用的項目移至"包引用"中:與上面的相同,但不需要擴展名或基於租戶的自定義。

一個示例是與RabbitMQ實例對話的持久隊列連接器。 將此功能包裝在服務中沒有任何意義。 僅創建一個nuget包並允許服務引用它並調用隊列就可以了。

3 識別域服務:識別域可能是進入微服務領域最具挑戰性的部分。 開發人員經常為可能(表面上)存在於兩個邏輯域之間的業務邏輯塊而苦惱。 永遠不要重複這種邏輯,如果不能決定,我建議您堅持一個經常問自己的問題:該記錄的根數據類型是什麼,或者最經常請求哪個域。

參考上面的購物車示例,例如" GetRecentOrders"之類的調用。 這些數據的根源是歷史記錄,但由客戶提供。 我要做的就是將此呼叫放入"歷史記錄"服務中,並需要一個CustomerId來獲取數據。

4 識別網關服務:在定義服務拓撲之前,最後一項真正的任務是識別網關。 這可能很困難,因為它是對域進行分組並確定前端(或第三方消費者)如何導航服務的好地方。 但是,您不需要太多的網關。

這樣的一個例子是在邏輯上將您的管理服務分組在" Admin Gateway"後面,並實施更嚴格的身份驗證要求和角色管理。 您甚至可以使用網關將允許使用此網關的IP地址或應用程序列入白名單。

微服務架構設計

由於每種解決方案都不相同,因此很難給出將整體分解為微服務的藍圖。 但我希望您現在有一個制定自己的策略的基礎。

結論

您是選擇使用微服務,無服務器功能還是堅持使用單體服務; 最終,您必須選擇最適合您的平臺和團隊的內容。 您必須考慮到公司採用的技術標準或語言,或者公司希望採用的技術指導。我堅信微服務應該成為構建現代Web服務的標準。

有許多方法可以沿著微服務道路走,許多人對此事有很強的見解。 不要害怕慢慢地遍歷一個模式,看看什麼有效,什麼無效。 如果它開始不適合您的目標,請進行調整。 不用遺憾,這是我們學習和改進現有模式的方法!

隨著我對無服務器功能的瞭解越來越多,肯定有一個地方可以填補微服務的空白。 但是,在某些情況下,也可以完全取代它,例如處理來自第三方服務(例如Twilio)的Web掛鉤。 即用即棄模式是學習無服務器並防止微服務執行過多操作的絕對完美方法。 但這是我們應該在另一篇文章中探討的內容。


(本文翻譯自Chris Fryer的文章《Microservice Architecture & Design》,參考:https://medium.com/@cfryerdev/microservice-architecture-design-2ac7eaae532)


分享到:


相關文章: