天天看點

微服務粒度難題:找到合适的微服務大小

作者:不秃頭程式員
微服務粒度難題:找到合适的微服務大小

序言

在微服務架構風格中,微服務通常設計遵循SRP(單一職責原則),作為一個獨立部署的軟體單元,專注于做一件事,并且做到極緻。作為開發人員,我們常常傾向于在沒有考慮為什麼的情況下盡可能地将服務做得小。這種關于什麼是和不是什麼是單一職責的主觀性是我們開發人員在服務粒度方面容易犯錯誤的地方。為了克服開發團隊在微服務尺寸上面臨的這種困境,了解粒度驅動因素至關重要。

粒度

在微服務中,我們有兩個概念——子產品化,涉及将系統分解成獨立部分,另一個是粒度,處理這些獨立部分的大小。

确定正确的粒度水準——服務的大小——是微服務架構中我們開發人員苦苦掙紮的衆多難點之一。粒度不是由服務中的類的數量或代碼行數來定義的,而是由服務的職責來定義的——是以,找到服務粒度的正确之道存在困惑。

服務的粒度分為兩種對立的力量——粒度解耦器和粒度整合器。

粒度解耦器

什麼時候我應該考慮将一個服務拆分成更小的部分?

粒度整合器

微服務粒度難題:找到合适的微服務大小
什麼時候我應該考慮将服務重新組合在一起?

粒度解耦器

由于我們生活在微服務和納米服務的時代,大多數開發團隊往往會錯誤地随意拆分服務,而忽略随之而來的後果。為了找到合适的大小,應對不同參數進行權衡分析,并在微服務的上下文和邊界上做出明智的決策。

粒度解耦驅動因素提供了何時将服務拆分成更小部分的指導和依據。讓我們看看這些驅動因素如何影響微服務的尺寸,以一個例子為例。

示例:考慮一個典型的通知服務,它執行三項操作:通過短信、電子郵件或郵寄信件通知客戶。

微服務粒度難題:找到合适的微服務大小

讓我們在解耦驅動因素上分析這個場景,并找到合适的尺寸。我們從:

服務範圍和功能

服務是否在做太多不相關的事情? 範圍和功能主要取決于兩個屬性——第一個是内聚性,指的是特定服務操作之間的互相關系的程度和方式。第二個是元件的總體大小,通常以職責數量、服務的入口點數量或兩者的綜合來衡量。 場景:觀察通知服務,有人可能會說将這個服務拆分成三個單獨的單一職責服務。但這是正确的做法嗎?答案是否定的!因為這個服務具有相對較強的内聚性,即所有這些功能都與一件事有關,即通知,并且具有一個單一的目的。是以,不需要拆分這個服務,它應該是一個服務執行三項操作。 接下來是:

代碼波動性

微服務粒度難題:找到合适的微服務大小
微服務粒度難題:找到合适的微服務大小
更改是否僅限于服務的一部分? 代碼波動性是源代碼更改的頻率。我們必須衡量服務中代碼更改的頻率,以合了解釋為什麼要拆分服務。 場景:假設我們有以下服務功能的名額:

現在,如果我們依據更改的名額來看,郵寄信件通知部分的頻繁更改也需要測試短信和電子郵件部分,進而作為單一服務,這增加了測試範圍和部署風險。那麼我們如何解決這個問題呢?

如果我們将這個服務拆分成兩個單獨的服務,電子通知和郵寄信件通知,那麼頻繁的更改現在被隔離在自己的服務中,進而減少了測試範圍并降低了部署風險。

可擴充性和吞吐量

微服務粒度難題:找到合适的微服務大小
微服務粒度難題:找到合适的微服務大小
服務的部分是否需要不同的擴充能力? 不同服務功能的可擴充性需求可以客觀地測量,以量化服務是否應拆分。 場景:再次考慮通知服務示例,測量單個服務的可擴充性需求如下:

在這種情況下,作為一個單一服務,電子郵件和郵寄信件功能必須不必要地擴充以滿足短信通知的需求,進而影響成本和彈性(如MTTS,即平均啟動時間)。這完全合理地解釋了将通知服務拆分成獨立的服務——短信、電子郵件和信件,因為這樣可以讓每個服務獨立擴充以滿足它們不同的吞吐量需求。

容錯性

是否存在導緻服務關鍵功能失敗的錯誤? 應用程式在特定領域内繼續運作的能力,即使發生了緻命崩潰(如OOM)。 場景:考慮我們的通知服務場景,假設電子郵件功能繼續出現OOM錯誤并緻命崩潰,整個整合服務将會癱瘓,包括短信和郵寄信件處理。 将這個單一的整合通知服務拆分成三個獨立的服務,為客戶通知領域提供了一定的容錯性。是以,電子郵件功能中的緻命錯誤不會影響短信或郵寄信件。 進一步說明:現在,這裡可能會出現一個問題,因為電子郵件功能頻繁崩潰,為什麼不将短信和郵寄信件功能合并?這是一個有效的問題。如果我們記得,當我們讨論代碼波動性場景時,我們将郵寄信件與電子郵件和短信分開,并将它們合并成一個——電子通知。如果我們在那裡能這樣做,我們也可以在這裡這樣做。那麼,為什麼不呢? 因為電子郵件和短信是相關的,它們都是電子通知方式。但在這裡,短信和郵寄通知沒有任何共同之處可以将它們合并。換句話說,這裡沒有内聚性。
注意:記住,如果一個服務難以命名,因為它在做多個不相關的事情,那麼考慮拆分服務。第二,每當拆分服務時,無論驅動因素是什麼,總是檢查是否可以與“剩餘”功能形成強烈的内聚性。 是以,在這裡将通知服務拆分成三個獨立的服務是有意義的。 最後一個驅動因素是:

可擴充性

服務是否總是在擴充以添加新功能? 随着服務擴充,添加額外功能的能力。 場景:假設我們有新的功能要添加到通知服務——比如移動推送通知、桌面通知、社交媒體通知等。這些新功能當然可以添加到一個單一的整合通知服務中。然而,每次添加新通知時,整個通知服務都需要進行測試,并且所有通知功能都需要不必要地部署到生産環境中。
微服務粒度難題:找到合适的微服務大小
注意:僅當事先知道計劃和希望作為域的一部分的額外整合功能時,才應用此場景。

推薦實踐

  1. 如果一個服務難以命名,因為它在做多個不相關的事情,那麼考慮拆分服務。
  2. 每當拆分服務時,無論驅動因素是什麼,總是檢查是否可以與“剩餘”功能形成強烈的内聚性。
  3. 根據業務能力而不是技術能力拆分服務。
  4. 在設計微服務時使用單一職責原則(SRP),但要牢記強内聚性的全景。
  5. 使用解耦驅動因素分析拆分服務的權衡。
微服務粒度難題:找到合适的微服務大小

繼續閱讀