如何度量微服務系統的複雜性

當談到使用DDD劃分微服務的好處的時候,經常會說DDD能夠讓相關的業務邏輯更加內聚,並且降低服務之間的耦合性,從而最終實現達到降解系統的複雜性。但是在這裏,不論是高內聚,低耦合,甚至我們經常說的系統複雜性,我們有沒有一個客觀的可以量化的指標來衡量這些概念。由於無法量化,所以就沒法度量,這樣當團隊在討論一個系統是否複雜,有多複雜這些問題的時候,就很容易陷入各種主觀直覺的爭論中。

爲了能夠讓團隊不再陷入這種無意義的爭論中,我嘗試查找看看有沒有大牛深度的分析過這問題,最好還能是在計算機和互聯網出現以後的分析和思考。非常幸運的是我找到了這本書《複雜》,這是一本研究複雜系統的通識著作,作者在書中嘗試回答這些複雜系統着迷而令人費解的問題:

  • 螞蟻在組成羣體時爲何會表現出如此的精密性和具有目的性?
  • 數以億計的神經元是如何產生出像意識這樣極度複雜的事物?
  • 是什麼在引導免疫系統、互聯網、全球經濟和人類基因組等自組織結構?

這篇文章基於這本書的思想框架,嘗試能夠給出一個度量微服務系統的方法。

複雜的定義

先看看在自然界中有哪些複雜系統:一個上百萬只螞蟻組成的蟻羣,由神經元組成的人類大腦,生物體內的免疫系統,當今世界的經濟體系,還有我們現在已經離不開的互聯網。

這些系統在細節上不一樣,但是如果從抽象層面來看由很多共性:

  1. 這些系統都是由個體組成,並不存在中央控制。大量的個體的行爲產生出複雜,不斷變化且難以預測的行爲模式。
  2. 這些系統都會利用來自內部或外部的信息或信號,同時也產生信息或信號。
  3. 這些系統都通過學習和進化過程進行適應,改變自身的行爲以增加生存的機會。

對於一個微服務系統來說,上面三個特性同樣適用。一個微服務系統由很多個微服務組成,這些微服務的行爲產生出複雜的行爲模式。整個微服務系統會通過API利用內部或外部的信號,同時在系統內部也是通過服務之間的接口進行信息傳遞。一個微服務系統並不是靜態的,而是會不斷適應業務變化,改變系統的API或者系統內部的組織方式來增加生存的機會。

以上三點是一個微服務的複雜特性,那麼如何從量的角度來衡量微服務的複雜程度呢?兩個微服務系統都很複雜,那麼如何說一個比另一個更復雜呢?這是一個很重要也很困難的問題,現在在科學界對於複雜系統的度量也沒有形成一個共識,不過我想從複雜系統的前兩個特性出發,畢竟一個微服務系統的個體數量和服務之間的信號傳遞是能夠記錄和量化的,嘗試找到一個能夠度量微服務系統複雜度的方法。

度量複雜性

在《複雜》這本書中,作者列舉了在科學界度量複雜性的9種方法:

  • 用大小度量複雜性,這是一種簡單的度量方法,通常來說數量越多就越複雜
  • 用熵度量複雜性,就是使用香農熵的概念,混亂程度越高則熵越高
  • 用算法信息度量複雜性,這種方法把事物的複雜性定義爲能夠產生對事物完整描述的最短計算機程序的長度。
  • 用邏輯深度度量複雜性,邏輯深度要求構造事物的信息必須要有邏輯,不能是簡單無意義的隨機值。
  • 用熱力學深度度量複雜性,熱力學深度首先是確定產生出這個事物最科學合理的確定事件序列,然後測量構建過程需要的能量和信息總量。
  • 用計算能力度量複雜性,用一個事物的計算複雜度來度量這個事物的複雜度
  • 用統計複雜性度量,度量用來預測系統將來的統計行爲所需的系統過去行爲的最小信息量。
  • 用分形維度度量複雜性,動力系統理論的概念度量事物複雜性的方法
  • 用層次性度量複雜性,複雜系統最重要的共性就是層次性和不可分解性,所以可以使用層次來度量複雜性

度量微服務系統複雜性

根據上面給出的9種度量複雜性的方法,以此爲基礎設計了三種度量方法用來度量微服務的複雜性:API服務比例,頻率加權服務節點數,API鏈路平均相似度。下面將詳細介紹一下這三個指標。

指標1: API服務比例

對於微服務系統來說,所有的服務接口都是以API的方式呈現,因此在大小數量上很容易統計處整個軟件系統有多少個API。同樣,由於提供這些API的個體是微服務,所以也很好統計出軟件系統中微服務的數量。

API服務比例 = 所有服務提供的API數量/所有微服務數量

基於這個公式,如果一個系統一共有100個API,但是這個系統是一個大單體,那麼這時API服務比例就是100,很明顯當這個度量值過大時對於整個系統來說並不是一個好事情。再考慮另外一種場景,一個系統一共有100個API,但是這個系統由100個微服務構成,這時API服務比例就是1,在這種場景下,當業務需要修改一個API的時候可能會涉及到多個微服務,所以當這個度量值過小時也不是一個好事情。

那麼這個度量值究竟在一個什麼範圍內會比較好呢,通常來說根據DDD來設計微服務時,一個微服務會包含2-5個聚合,一個聚合會有1-3個實體,如果假設每個實體都需要有API進行創建,修改,刪除,和查詢,那麼就意味着一個微服務的API數量應該是從8到60之間,這就是API服務比例的一個健康範圍,高於這個範圍時說明服務太少,某些服務承擔的API太多,需要考慮進一步進行服務拆分,低於這個範圍時,說明服務拆分過細,過多,需要考慮進行服務合併。

考慮到這個數據在分佈上應該呈現一定的正態特性,所以在實際中可以把這個範圍稍微放的更緊一點。

指標2: 頻率加權服務節點數

前面一個指標是從簡單的數量上來度量微服務複雜性的,很明顯這種度量稍顯簡單,因爲每個API的業務價值是不相同的,頻率加權服務節點數就是以API的調用頻率作爲權重,來衡量整個系統在提供API服務時需要多少個服務節點來支持。

假設一個系統對外一共暴露了4個API(外部主要指前端和外部系統),在過去一個月4個API的訪問量分別如下:API1 10次,API2 30次,API3 55次,API4 5次。並且根據服務鏈路跟蹤分析我們知道,API1的鏈路上有5個微服務,API2的鏈路上有3個微服務,API3的鏈路上有6個微服務,API4的鏈路上有7個微服務。

那麼這時候頻率加權服務節點數這個指標的計算過程就是:
10% * 5 + 30% * 3 + 55% * 6 + 5% * 7 = 5.05

通常來說,一個系統的絕大部份有業務價值的API在鏈路上都不應該有太多的服務節點,所以如果一個系統的這個指標大於3時,說明很多業務價值較高的API的鏈路有些複雜了。在實際場景中,如果某個API的鏈路很複雜需要10多個服務節點,比如說報表的API,但是如果這個API的調用頻率非常低,可能一個月都不到5%,那麼基於這個API的業務價值來考慮,整個系統是可以忍受這個高複雜低價值的API的。

這個指標的計算需要在生產環境上使用鏈路跟蹤工具進行統計,比如pinpoint或者Zipkin來完成。這個指標的最終計算結果是整個系統按照頻率加權的節點數,用來從整體上衡量一個系統的複雜程度。但是在計算這個指標的過程中,也可以輕鬆的幫我們找到調用頻率高,鏈路複雜的API進行進一步的分析。

指標3: API鏈路平均相似度

在分析API鏈路時,有時候會遇到這樣的場景:

  • API1的調用鏈路是 服務A接口1-服務B接口1-服務C接口1-服務D接口3-服務E接口2
  • API2的調用鏈路是 服務A接口2-服務B接口1-服務C接口1-服務F接口1-服務G接口1
  • API3的調用鏈路是 服務H接口1-服務L接口1-服務C接口1-服務D接口3-服務E接口2

從上面三個API鏈路中很明顯三個API存在一定的相似度,當系統中大部分的API鏈路相似度都比較高的時候,那麼就說明系統裏面的微服務個體可能存在着進一步優化的空間。所以需要能夠對這些鏈路的相似度進行計算和度量。由於每個API鏈路都可以看做是一個序列,所以鏈路相似度的計算就是這個鏈路序列的相似度計算。

對於序列相似度,有很多中算法可以用來實現這個計算,個人推薦採用Levenshtein距離來計算序列相似度,Levenshtein距離的含義是求將a變成b(或將b變成a),所需要做的最少次數的變換。
舉個例子,字符串”kitten”與”sitting”的萊文斯坦距離是3, 應爲將一個字符串變爲另一個字符串,最小需要做三次變換:

  • kitten → sitten (字符k變爲s)
  • sitten → sittin (字符e變成i)
  • sittin → sitting (在末尾插入字符g)

而基於這個距離,兩個字符串的相似度就是 1-(Levenshtein距離/最長字符串長度)= 1 -(3/7)= 0.5714

這個算法詳細原理有點複雜,如果對此有興趣可以參看 https://en.wikipedia.org/wiki/Levenshtein_distance

使用相似度算法,我們就可以得出來每個API鏈路和其他鏈路之間的相似度,有了這個計算結果以後,對我們來說有兩個價值:

  1. 根據相似度進行排序,然後重點分析相似度較高的鏈路,看看是不是兩個API提供了相同價值的服務,或者說這兩個鏈路上的服務應該進行合併
  2. 可以根據這些鏈路相似度計算整個系統的相似度平均值,整個系統的相似度平均值較高時(比如高過0.7,但是要注意不通算法計算出來的相似度結果意義並不相同)這時候就說明系統存在優化空間,通過優化可以降低整個系統的複雜度。

系統複雜度度量框架

以上三個指標有些是可以通過靜態分析統計出來的,有些是需要上線運行以後才能統計得出的。因爲在考慮微服務系統的時候,我們主要考慮是構成整個系統的微服務個體,以及這些個體提供的API能力,所以在度量複雜度的時候也主要是從兩個概念開始入手。但是如果我們換個視角,想看看一個微服務內部的複雜度,只要把上面兩個概念轉變成聚合和聚合提供的方法,那麼這套框架依然可以應用到微服務內部。

因此對於所有符合三個基本特徵的複雜系統來說,我們都可以從這個系統的個體數量,這個系統內部的信息傳遞方式來度量系統複雜度。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章