鐘陳星,李杉杉,張 賀,章 程
1(南京大學 軟件學院,江蘇 南京 210023)
2(計算機軟件新技術國家重點實驗室(南京大學),江蘇 南京 210023)
3(安徽大學 計算機科學與技術學院,安徽 合肥 230601)
伴隨著互聯網技術的飛速發(fā)展和市場需求的急劇擴增,軟件應用是否可以靈活地調整業(yè)務與規(guī)模,持續(xù)交付部署,快速更新迭代成為企業(yè)在現代化商業(yè)競爭中取勝的決定性因素.然而,傳統的軟件開發(fā)采用單體架構(monolithic architecture)[1]方式,將應用程序的所有功能封裝在一個獨立的單元中,隨著軟件系統復雜度的劇增和開發(fā)團隊的擴大,逐漸暴露出其不夠靈活、開發(fā)效率低下以及妨礙持續(xù)交付與部署等缺點.
針對軟件敏捷性、靈活性和可擴展性需求的不斷增長,使得突破單體架構的限制成為亟待解決的問題,也使得微服務架構(microservices architecture)[2]應運而生.微服務架構將一個獨立的應用程序分成多個協同工作的小而自治的服務,每個微服務通常只完成某個特定的功能,并且運行在單獨的進程中.相較于單體架構,微服務在面對快速發(fā)展變化的業(yè)務需求時表現出更加敏捷(agility)、靈活(flexibility)及可擴展性(scalability)等優(yōu)點.具體來說,微服務擁有技術異構,不同的服務采用適合的技術;對數據進行“去中心化”控制,不同的服務無需共享一個中心數據庫;智能端點,服務管理相關業(yè)務邏輯并通過輕量級的消息交互與其他服務通信;圍繞業(yè)務功能組織服務,負責服務開發(fā)的團隊同時負責該服務相關業(yè)務需求的所有實現細節(jié)等特性[3].微服務的這些特點與DevOps 提倡的生產環(huán)境的彈性、可靠性、穩(wěn)定性以及高頻率部署是一致的,這使其在Netflix、Amazon 以及eBay 等世界領先的互聯網公司中率先流行起來.
然而,微服務的這些優(yōu)勢并不是一蹴而就的.微服務劃分是微服務領域的一項難題.其原因主要來自于以下4 個方面:第一,項目設計的初級階段可以為解決微服務劃分問題做決策提供支撐的信息過少;第二,微服務的劃分不僅與系統的領域知識相關,還需要綜合考慮開發(fā)團隊的組織結構、項目的可用資源以及系統的非功能性需求等多個因素;第三,微服務劃分問題本身就是一個極富挑戰(zhàn)性的多目標優(yōu)化問題.合理的微服務劃分要求設計者在多個相互排斥的性質之間權衡利弊[4].比如,微服務提倡小而自治的服務之間相互合作[2].小而自治的服務符合單一職責原則(簡稱SRP),簡化了開發(fā)過程,但同時由于更多的服務需要部署也增加了運維人員的壓力[5].從內聚與耦合的角度看,粒度越小的服務具有越高的內聚性,然而粒度越小的服務要實現同一個用例必然涉及更頻繁的服務間的通信交互,這使得服務間的耦合性提高,系統的復雜性更大;第四,微服務領域仍缺少針對服務設計本身的質量評估方法.發(fā)展成熟的面向對象領域有許多評估面向對象設計的有效方法.然而,這些方法通常聚焦于代碼實現層的概念(比如類),與面向服務的微服務架構的關注點不同.另外,在代碼實現后才評估微服務劃分的粒度所需要的系統重構代價實在太大.因此,將評估面向對象設計的方法直接應用于微服務架構中不具備合理性.在很大程度上,架構師對微服務劃分的合理性評估仍然依賴于他們對領域知識的理解和直覺[4].
針對上述問題,本文旨在利用限界上下文(bounded context)理論[6]對微服務架構的服務劃分粒度進行研究,為微服務劃分粒度的質量評估問題提供理論方法及工具支持,幫助實現傳統單體應用向微服務架構的遷移.本文的主要貢獻在于提出的微服務粒度評估模型及其工具可用于指導微服務架構中合理的服務劃分[7],輔助架構師做出微服務設計決策,一方面可以降低不合理的微服務設計所造成的軟件開發(fā)與部署難度;另一方面可以提高團隊開發(fā)效率和系統性能,提升軟件企業(yè)的競爭力.
本文第1 節(jié)介紹背景及相關工作.第2 節(jié)提出評估方法.第3 節(jié)給出4 種評估指標及指標合并過程.第4 節(jié)實現自動化工具原型,并利用案例研究驗證模型的有效性.第5 節(jié)總結論文,并提出下一步的工作.
合理的微服務劃分是微服務架構敏捷、靈活和可擴展性的先決條件,也是微服務領域所面臨的一項嚴峻挑戰(zhàn).過去的幾年里,一些研究人員致力于探究微服務劃分問題.Richardson[8]提出了用于指導微服務劃分的4 個策略,包括根據業(yè)務能力(business capability)進行劃分、基于領域驅動設計中子領域(subdomain)的概念進行劃分、利用動詞和用例圖進行劃分以及利用名詞和資源定義服務等.Richardson[8]提出的指導微服務劃分的4 個策略并沒有為微服務劃分問題提供系統化的指導方法,具體的微服務劃分過程仍然依賴于系統架構人員對領域業(yè)務需求的理解和主觀經驗判斷.Gysel 等人[9]開發(fā)了微服務劃分工具Service Cutter.他們根據軟件架構設計的經驗定義了16 種耦合度度量標準,用以衡量系統中的nanoentities(包括數據、操作和軟件制品)之間的耦合度,從而提取出以nanoentities 為節(jié)點的系統無向加權圖,在此基礎上實施聚類算法,實現微服務的劃分.Service Cutter存在兩個方面的問題,其一,系統架構人員需要學習16 種耦合度度量標準的定義,并且結合系統的領域業(yè)務需求規(guī)定耦合度度量標準的優(yōu)先級,這極大地依賴于系統架構人員的主觀經驗;其二,由Service Cutter 計算得到的候選微服務準確度較低,系統架構人員仍需結合自己的預期劃分決定是否采納Service Cutter 提供的劃分方案.Baresi 等人[10]以符合OpenAPI 規(guī)范的系統API 為輸入,使用DISCO 相似度評估算法計算API 操作之間的相似度,將相似度高的操作及其數據劃分到同一服務,從而實現微服務的劃分.該方法同樣存在兩個方面的問題,其一,該方法以系統API 中操作之間的相關性而不是領域業(yè)務邏輯層面的業(yè)務需求作為劃分依據,操作的具體實現對最終劃分結果的影響較大;其二,該方法以實現層面的API 為輸入,適用于單體應用到微服務應用的遷移,而不適用于全新的微服務應用的開發(fā).Chen 等人[11]將系統的領域業(yè)務邏輯繪制成數據流圖,將所有具有相同輸出數據的操作合并為一個操作,最終得到的每個操作及其數據都成為一個候選微服務.該方法僅考慮了處理相同數據的操作應屬于同一服務,而忽略了微服務劃分的其他重要原則,可能存在微服務粒度過大的缺陷.顯然,微服務劃分問題仍缺少系統可行的理論指導方法.
更重要的是,當前的研究對于“什么樣的微服務劃分是合理的”這一問題還缺乏標準而統一的認識.缺乏微服務劃分合理性的評估標準使得比較不同微服務劃分方案變得困難.Baresi 等人[10]與Chen 等人[11]在將其工作與Service Cutter 進行比較時,都僅討論了兩種方法在實現層面的復雜程度,而未提及微服務劃分結果之間的優(yōu)劣對比情況.在評估微服務劃分問題上,Newman[2]指出,微服務劃分的核心原則是高內聚與低耦合.高內聚將相關聯的業(yè)務邏輯包含在同一個服務中,便于代碼管理;低耦合降低了服務間的依賴與通信開銷,允許服務的獨立修改和部署.Newman[2]給出的評估微服務劃分的討論屬于定性分析,存在含糊不清的情況.Zdun 等人[12]基于微服務架構的實踐模式設計了幾種評估微服務劃分的標準,并定義了相關算法,定量地計算當前微服務劃分遵循該實踐模式的程度.設計的評估標準包括“所有組件是否都可獨立部署或者所有組件可獨立部署的程度”以及“當前微服務劃分方案是否避免了共享其他組件或者避免了以緊耦合的方式共享其他組件”.該微服務劃分的評估方法僅衡量了當前微服務劃分是否符合微服務架構的實踐模式,而未考慮系統的具體領域業(yè)務邏輯以及當前微服務劃分下系統的內聚性等其他方面的問題.
限界上下文是領域驅動設計(domain-driven design,簡稱DDD)[6]的核心概念.在應對高復雜度的軟件開發(fā)任務時,DDD 提倡將應用按照領域業(yè)務邏輯劃分為多個限界上下文,不同上下文使用獨立的模型,并且顯式地定義每個限界上下文的邊界和限界上下文之間的映射關系.限界上下文與微服務是天然契合的.其關注點分離的思想有助于系統架構人員從每個服務內部和服務之間兩個角度設計架構.從限界上下文視角討論微服務粒度能夠幫助我們分離出問題的核心點.
本文基于限界上下文理論提出了一種微服務劃分的評估模型,具有以下優(yōu)點:(1)以用例圖和實體關系圖為輸入,充分考慮了系統的領域業(yè)務邏輯;(2)設計了 4 種評估指標,定量地衡量微服務劃分在各項指標上的表現;(3)設計的4 種評估指標都結合了微服務劃分的核心原則,包括高內聚與低耦合;(4)進行了指標合并,提供綜合評分,用以比較不同微服務劃分方案;(5)實現了工具原型,可以自動化地評估微服務劃分;(6)提出的評估模型不涉及微服務應用的具體實現,既適用于單體應用向微服務應用的遷移,又適用于全新的微服務應用的開發(fā).
本節(jié)為解決微服務粒度界定問題提出一種基于限界上下文的量化評估方法,并給出具體的評估步驟.
以評估微服務劃分為目的,基于UML 2.0[13]對微服務設計初級階段的關鍵元素建模以便于闡述后文.建模結果如圖1 所示.
基于限界上下文劃分微服務將一個獨立的應用程序劃分為多個協同工作的小而自治的服務,每個服務對應一個特定的限界上下文,規(guī)定了一組領域業(yè)務邏輯和相應的領域實體.服務通過完成用例實現應用的領域業(yè)務邏輯,即軟件系統的功能需求.一個服務允許實現多個用例,一個用例允許由多個服務通過消息交互實現.屬性描述了實體的特征,是實體的組成元素,也是微服務劃分中不可再分的原子單元.一個用例涉及到的屬性可以分為輸入和輸出兩部分,分別由對應服務的讀操作和寫操作完成[8].實體與關聯關系之間的對應關系與傳統ER模型一致.
Fig.1 Modeling of key elements in microservices decomposition圖1 微服務設計中關鍵元素的建模
在評估微服務粒度的工作中,服務模型的表現形式包括軟件制品(Artifact,包括用例圖和實體關系圖等)和候選微服務.
(1)用例圖描述了軟件系統的功能需求.每個用例對應于軟件系統的一項業(yè)務邏輯,完成一個用例有時需要多個服務之間的協同合作.Richardson[8]指出,用例可以作為微服務劃分的依據.
(2)實體關系圖與自然語言相對應,描述了軟件系統中關鍵的領域實體及實體與實體之間的關系,可用于指導微服務的拆分.關聯關系緊密的領域實體傾向于劃分到同一個服務中.
(3)候選微服務描述了微服務劃分中服務與用例、實體之間的對應關系,規(guī)定了每個服務負責的領域業(yè)務邏輯和相關限界上下文.本文通過評估候選微服務在各量化指標上的表現來評估微服務劃分的合理性.
本文提出的微服務粒度的評估過程可以分為4 個步驟,如圖2 所示.
Fig.2 Evaluating the rationality of microservices decomposition圖2 評估微服務劃分合理性的過程
(1)輸入服務模型數據:包括用例圖、實體關系和候選微服務3 種表現形式.
(2)指標計算:以服務模型數據作為輸入,定量地計算候選微服務在所有評估指標上的值,衡量該微服務劃分在各項指標上的表現.
(3)指標合并:對指標計算的結果做歸一化處理與加權求和,得到該微服務劃分的綜合評分,用以比較不同的微服務劃分方案.
(4)評估模型是否可優(yōu)化:設計人員根據指標計算及合并過程得到的結果對微服務劃分進行分析,判斷能否重新調整劃分以獲得更優(yōu)的微服務粒度.
容易看出,微服務粒度的評估是一個向更優(yōu)劃分靠近的不斷迭代的過程.架構設計人員應選擇評估過程得到的最優(yōu)劃分方案作為最終的微服務劃分結果.
本節(jié)根據業(yè)界廣泛采用的微服務劃分原則[2,8]定義一系列評估指標,用于衡量微服務劃分,指出各項指標的有效性,并給出具體的指標計算公式.
服務內聚性是指服務內用例之間的功能相關性[14].服務的內聚性越高,設計模型的可理解性越強,系統也就越敏捷[14].
3.1.1 指標有效性分析
內聚性是軟件系統中的主要屬性,也是微服務設計質量評估的重要因素.服務的內聚性越低,一方面意味著該服務存在越多功能邏輯不相關的代碼,其他服務對該服務存在越多的依賴,該服務越難以獨立修改;另一方面意味著不同服務中存在越多功能邏輯相關的代碼,代碼的冗余度越大.與此同時,系統的技術可選性越小[2].另外,高內聚性的服務由于實現了功能邏輯緊密相關的用例,因而具有更清晰的限界上下文,可理解性更強.當系統的微服務劃分與開發(fā)團隊的組織結構一致時,具有高內聚性的微服務開發(fā)速度更快.并且,由于服務的內聚性減少了微服務內部組件間的消息交互,因此具有更高的系統效率[15].
正確定義服務邊界、分析系統語義是提高服務內聚性的前提[15].Newman[2]指出,高內聚是微服務領域的重要概念,是指將邏輯相關的代碼盡可能地放在相同服務中.通過領域驅動設計中的限界上下文劃分微服務邊界,每個服務聚焦于一個具體的業(yè)務邏輯,可以避免服務粒度過大,實現高內聚從而實現微服務優(yōu)勢的最大化.
3.1.2 計算方法
服務的內聚性可通過服務內部的實體間內聚性來度量.現有的許多研究[16-18]通過為ER 模型中的關聯關系信息定義優(yōu)先級來衡量實體間的內聚性,涉及到的關聯關系信息包括類型、基數(cardinality ratios)和參與約束(participation)等.文獻[18]使用距離的概念度量實體間的內聚性,并為不同優(yōu)先級別的實體間內聚性設置了不同的距離值,距離的值越大,實體間的內聚性越小.文獻[17]指出,強實體與弱實體(strong-weak)之間的內聚性最高,擁有第1 優(yōu)先級.擁有內聚性第2 優(yōu)先級的是具有特殊化/概化(generalization)關系的超類和子類.另外,聚合(aggregation)關聯關系由于具有部分與整體生存周期上的聯系,同樣屬于第2 優(yōu)先級隊列.具有限制(exclusive binary)關聯關系的實體間內聚性較低,擁有第3 優(yōu)先級[18].具體的實體間關聯關系類別與距離值的對應見表1.
Table 1 Correspondences between relationship of entities and distances in ER diagrams表1 ER 圖中實體間關聯關系類別與距離值的對應
對于ER 模型中的其他關聯關系類別,我們根據基數與參與約束信息定義不同的優(yōu)先級,以表現實體間不同程度的內聚性特征.針對關聯關系的基數,不同基數的關聯關系對應的實體內聚性特征如下:一對一>一對多>多對多.針對關聯關系的參與約束,不難理解,強制性(mandatory)參與的關聯關系比可選(optional)參與的關聯關系具有更強的內聚性,因此,不同參與約束的關聯關系對應的實體間內聚性特征如下:強制-強制(M-M)>強制-可選(M-O)>可選-可選(O-O).據此,Mohammad[14]列出了表2.
Table 2 Correspondences between cardinality and participation of relationship and distances in ER diagrams[14]表2 ER 圖中一般關聯關系的基數與參與約束信息對應的距離值[14]
在計算三元及其他n(n>2)元關聯關系時,我們將表2 數據乘以10n-2得到對應的距離值.表1 和表2 中距離值的數值選擇只反映了ER 模型中不同關聯關系對應的實體內聚性的強弱,與具體數值多少無關.比如,1 和10的差距使得具有M-M 參與約束的兩個實體比具有M-O 參與約束的兩個實體內聚性更強.最后,出于完整性考慮,規(guī)定兩個相同實體之間的距離值為1.
那么,任意實體E1和E2之間的距離值可以表示為ER 圖中兩個實體之間所有路徑上的邊的距離值之和的最小值,即最短路徑的長度,如式(1)所示.
其中,p表示ER 圖中實體E1和E2之間的路徑數,ep表示當前路徑的邊數,di表示邊的距離值.實體E1和E2的內聚性如式(2)所示.
由式(1)得到任意ER 圖對應的ER 模型中所有實體之間的距離值,文獻[14]稱其為距離表(distance table).接下來,利用ER 模型中實體之間的距離值來度量服務內聚性.根據第1 節(jié)提出的服務模型,一個服務允許實現多個用例.一個服務實現的用例越多,該服務的內聚性就越低[2].對于服務內的任意兩個用例1 和2,我們得到對一個實體集(BE1,BE2)以及所有的1 中實體與2 中實體之間的距離值(由距離表可得),從而構建二分圖G(V,E),二分圖中每條邊E(i)的距離值用Weight(E(i))表示.使用貪心算法選出連接用例1 和用例2 中所有實體的距離值最小的邊的集合R可用于度量兩個用例間的內聚性.具體算法如Algorithm 1 偽碼所示.
Algorithm 1.使用貪心算法選出符合條件的R.
輸入:BE1,BE2,距離表DistanceTable;
輸出:R:連接用例1 和用例2 中所有實體的距離值最小的邊的集合.
4:從G中選出具有最小距離值的邊e
5:ife不屬于邊集R且e不與R內其他邊構成環(huán)then
6:將e加入集合R
7:將e的端點加入集合S
8:end if
9:end while
根據得到的符合條件的邊集R,我們由式(3)計算用例之間的內聚性UCC(use case cohesion).不難理解,式(3)的計算結果是邊集R的內聚性平均值.
對應的服務K的內聚性SC(service cohesion)可以表示如下,其中,a表示第k個服務中的用例數.
同時,得到微服務系統設計的服務內聚性SDC(service design cohesion)如下,s表示系統中的所有服務數:
服務耦合性描述了一個服務依賴于其他服務的程度,或者說一個服務的改變對其他服務的影響程度[15].
3.2.1 指標有效性分析
微服務的特征之一是服務自治,允許服務獨立地修改和部署.這就要求減少服務之間的依賴,降低服務的耦合度.服務之間的低耦合可以帶來兩個好處.一方面,服務之間的通信交互越小,意味著系統具有更高的效率和更好的性能.另一方面,低耦合度意味著其他服務的修改對當前服務的影響較小,系統具有更好的靈活性,能夠快速適應需求的變化[2].低耦合是軟件工程中衡量系統設計的重要標準.
依據限界上下文定義微服務邊界,正確實現微服務劃分可以保證實現服務間的松耦合[19].Martin[20]的單一職責原則——“Gather together the things that change for the same reasons.Separate those things that change for different reasons.”——同樣可以降低微服務劃分的耦合度.具體來說,將同一個用例涉及到的屬性劃分到同一個服務,將具有緊密關聯關系的實體劃分到同一個服務,減少服務之間的通信數量,消除不必要的服務之間的關聯和依賴[9].
3.2.2 計算方法
服務間的耦合度體現了服務間的相互依賴程度.若服務A訪問服務B的實體以實現其業(yè)務用例,則稱服務A依賴于服務B,服務A與B之間存在耦合.在微服務應用中,服務之間通過輕量級消息機制實現交互.服務之間的消息交互越多,系統的通信開銷就越大,系統性能也就越差.因此,可以用服務間傳遞消息的大小,包括傳遞的屬性個數以及屬性的復雜度等,來度量服務間的耦合度[11].其中,屬性的復雜度由屬性本身的組成結構決定.類級別的屬性具有比基本數據類型屬性更高的復雜度,集合類型的屬性也具有比基本數據類型屬性更高的復雜度.為此,定義兩種不同的屬性復雜度級別:類與集合(ClassOrList)復雜度為10,原子(primitive)級別復雜度為1,所有屬性的默認復雜度為原子級別.另外,服務之間以不同的頻率傳遞消息體現的服務耦合程度是不同的.在項目設計階段,消息頻率表現為用例頻率(frequency of use).用例頻率屬于用例圖的內容,根據業(yè)務邏輯預估該用例在系統運行時單位時間內的調用次數獲得.比如,修改用戶密碼等涉及到基礎配置的用例調用次數較少,頻率較低.我們定義3 種不同的用例頻率:低、中、高(分別對應頻率值1、10、100),并設置默認用例頻率為中.為屬性和用例頻率設置默認值降低了設計人員使用該工具進行服務粒度評估的輸入工作量.基于以上分析,用式(6)度量系統設計的服務耦合性.
其中,
ul表示服務l實現的用例總數(ul≥0);
flt表示服務l中的用例t的頻率(flt≥0);
rlt表示服務l中的用例t包含的在服務間讀屬性的總數(rlt≥0);
wlt表示服務l中的用例t包含的在服務間寫屬性的總數(wlt≥0);
cltm表示服務l中的用例t包含的在服務間讀屬性m的復雜度(cltm≥0);
cltn表示服務l中的用例t包含的在服務間寫屬性n的復雜度(cltn≥0).
用例收斂性指代單個服務聚焦于處理特定領域業(yè)務功能的程度.
3.3.1 指標有效性分析
微服務劃分的原則之一是每個服務要足夠小.著名的面向對象設計原則——單一職責原則(SRP)——規(guī)定每個類/模塊都應該有單一的功能,并且該功能應由這個類/模塊完全封裝起來.SRP 對于面向服務的微服務設計同樣有效[8].服務實現的用例體現了該服務為軟件系統提供的業(yè)務功能.服務實現的用例越多,意味著微服務設計不符合SRP 的程度越大,系統可復用性和內聚性就越低.
另一方面,實現單個用例涉及的服務越多,需要的服務之間的通信開銷就越大,系統延遲也就越高.不僅如此,這還需要越多的開發(fā)團隊之間的合作,一定程度上提高了服務間耦合和開發(fā)團隊間的依賴,降低了服務及其開發(fā)團隊的自治性,應盡量避免.
3.3.2 計算方法
基于第3.3.1 節(jié)中的分析,微服務設計中,(1)每個服務實現的用例應盡可能地少;(2)實現單個用例涉及的服務應盡可能地少.為了評估(1),計算微服務設計中服務實現的用例平均數.為了評估(2),計算設計中實現每個用例涉及的服務平均數.微服務劃分的用例收斂性用公式(7)表示如下:
其中,
s表示當前微服務設計中的服務數;
Uk表示服務k中對應的用例數;
u表示當前微服務設計中的用例數;
Sl表示實現用例l涉及的服務數.
實體收斂性指代單個服務聚焦于處理特定領域實體的程度.
3.4.1 指標有效性分析
微服務傾向于讓每個服務管理自己的數據庫[19],包括對領域實體數據的增加、刪除、更改和查詢.為滿足單一職責原則,降低服務的數據庫管理負載,單個服務管理的實體數應盡可能地少.
另一方面,共同閉包原則(common closure principle,簡稱CCP)——“the packages should not have more than one reason to change.”——強調從變化的角度看待軟件架構設計,可用于提高微服務設計的可維護性.具體來說,訪問同一實體的用例趨向于劃分到同一服務.這樣,當某一領域實體發(fā)生需求變更時,需要做出修改的服務應盡可能地少,帶來的服務間耦合也應盡可能地小.
3.4.2 計算方法
基于第3.4.1 節(jié)中的分析,微服務設計中,(1)每個服務管理的實體數據應盡可能地少;(2)同一實體數據涉及的服務也應盡可能地少.為了評估(1),計算微服務設計中服務管理的實體平均數.為了評估(2),計算設計中實體涉及的服務平均數.微服務劃分的實體收斂性用公式(8)表示如下:
其中,
s表示當前微服務設計中的服務數;
Ek表示服務k中管理的實體數據數;
e表示當前微服務設計中的實體數;
Sl表示實體l涉及的服務數.
合理的微服務劃分要求設計者在多個相互排斥的性質之間權衡利弊[4].減少服務實現的用例數以降低微服務粒度,使微服務設計更符合單一職責原則.一方面,這不僅提高了服務內聚性,同時還降低了對應開發(fā)團隊的工作強度.另一方面,這也帶來了更多的服務間數據流,增加了服務間的耦合與依賴.在劃分微服務時,需要更多數據交互的用例及其數據應趨向于被劃分到同一個服務內.另外,當微服務劃分具有良好的實體收斂性時,服務需要接收更多的服務間消息才能完成同一用例,服務間的耦合度較高.而當微服務劃分具有較小的用例收斂性時,一方面要求服務包含較少的用例,另一方面要求用例涉及的輸入輸出屬性盡量包含在更少的服務中,這就與較小的實體收斂性目標,即要求每個服務包含的實體較少發(fā)生了沖突.根據上述分析,我們需要合并計算得到的所有指標以得到對微服務劃分的綜合評分.假設當前存在n個不同的微服務劃分,對每個劃分都能通過前文所述的公式得到4 個指標,從而得到指標矩陣M,M的每一列分別對應服務內聚性、服務耦合性、實體收斂性和用例收斂性:
由于每種指標表示的含義不同,其量綱和取值范圍也存在很大的差別,將不同指標直接累加可能造成某一維指標對結果影響過大.因此,為了更公平地合并不同的指標,我們需要對指標計算結果進行歸一化處理,使所有指標數據的歸一化結果在[0,1]之間.另外,為了使加權結果越大與微服務設計越合理的目標相統一,在歸一化過程中還應考慮到指標本身.根據前4 節(jié)的分析,更合理的微服務劃分具有更高的服務內聚性、更低的服務耦合性、用例收斂性以及實體收斂性.
(1)對于劃分目標為更高的指標i,對mij作如下歸一化處理:
(2)對于劃分目標為更低的指標i,對mij作如下歸一化處理:
其中,mimax和mimin分別是指標i在n個不同劃分結果下的最大值和最小值.
接下來,對歸一化處理后的指標進行加權以獲得綜合評分.顯然,不同的軟件系統對不同指標的優(yōu)先級要求不同.比如,對于具有更高性能要求的軟件系統,耦合性對系統設計非常關鍵,服務耦合性指標應具有更高的權重.相反地,更強調可復用性的軟件系統應增加服務內聚性和實體收斂性在評估微服務劃分工作中的權重.假設各指標的權重向量為W={w1,w2,w3,w4},那么候選微服務k的綜合評分為
為了驗證提出的微服務劃分的評估模型,我們實現了service candidates evaluating(SCE)工具原型,自動化地計算候選微服務于服務內聚性、服務耦合性、用例收斂性和實體收斂性4 個方面的指標,并給出綜合評分,以比較不同微服務劃分的優(yōu)劣.SCE 的實現基于Python 2.7.13 與Gui 編程技術PyQt5.圖3 描述了該SCE 的圖形化用戶接口,主要包括以下幾個方面:軟件制品與候選微服務的輸入,指標優(yōu)先級的輸入,當前候選微服務的評估結果輸出以及歷史評估結果的排行輸出.SCE 規(guī)定軟件制品與候選微服務的輸入應嚴格遵循特定格式的JSON 文件形式.
Fig.3 Interface of the SCE system prototype圖3 SCE 系統界面
本節(jié)將評估模型應用于領域驅動設計中的經典場景——貨物跟蹤系統(cargo tracking system,簡稱CTS)——以闡述評估模型的具體使用過程,并驗證模型的有效性.利用評估模型對CTS 案例下的幾種微服務劃分方案進行評估,若評估結果排序與微服務架構設計人員的預期相符,則認為評估模型有效.
4.2.1 業(yè)務場景
CTS 是Evans[6]用于闡述領域驅動設計的經典案例,(1)具有合適的問題復雜度;(2)具有完整且合理的架構分析;(3)具有公認合理的限界上下文劃分方案;(4)GitHub 上具有已實現的完整代碼:DDDSample.對DDDSample 進行逆向分析,不難得到CTS 的業(yè)務需求如下.
(1)將Cargo 從Location A 運送到Location B.每個Cargo 創(chuàng)建時都伴隨著一個TrackingId,Cargo 的具體說明用類RouteSpecification 來實現.一旦Cargo 被創(chuàng)建,一到多個Itinerary 將分配給該Cargo;
(2)系統通過計算現有的Voyage 給Cargo 分配合適的Itinerary,每個Voyage 都包含一系列的Carrier Movement;
(3)在Cargo 的路線確定以后,HandlingEvent 跟蹤Cargo 的每個Itinerary,完成貨物跟蹤;
(4)Cargo 的Delivery 實例描述了具體的運輸狀態(tài)、預計到達時間以及該Cargo 當前是否被跟蹤.
進一步分析后可得到CTS 的用例圖和實體關系圖.同時,得到CTS 的業(yè)務用例和領域實體如下.
(1)業(yè)務用例:View Tracking,View Cargo,Book Cargo,Change Cargo Destination,Route Cargo,Create Location,Create Voyage,Add Carrier Movement,Handle Cargo Event.
下文使用的縮寫形式為VT,VC,BC,CCD,RC,CL,ACM,HC.
(2)領域實體:Cargo,HandlingEvent,Delivery,Voyage,RouteSpecification,Location,Itinerary,CarrierMovement,Leg.
下文使用的縮寫形式為Car,HE,Del,Voy,RS,Loc,Iti,CM,Leg.
表3 給出CTS 系統中業(yè)務用例與領域實體之間的對應.
Table 3 Use cases of CTS表3 CTS 的業(yè)務用例及其領域實體
4.2.2 模型驗證
接下來,通過驗證CTS 案例下5 個候選微服務在評估模型中的表現來驗證提出的微服務劃分評估模型的有效性.5 個候選微服務的具體細節(jié)見表4.
Table 4 Microservices candidates of CTS application表4 CTS 應用程序中的候選微服務
候選微服務SC0 到候選微服務SC3 在設計時僅考慮評估模型的一項指標.在候選微服務SC0 中,每個服務僅負責一個用例的開發(fā)與實現,服務的內聚性最大.在候選微服務SC1 中,服務S10 將系統中所有業(yè)務用例與領域實體都組合在一起,實現任意用例都只需訪問本地領域實體,無服務間消息交互,具有最小的服務耦合性.候選微服務SC2 從用例收斂性的角度出發(fā),在保證服務實現的用例平均數較小的前提下,盡可能地將實現同一業(yè)務用例涉及到的領域實體劃分到相同服務.比如,實現業(yè)務用例ViewTracking 涉及到的領域實體有Cargo、HandlingEvent、Delivery、Voyage 和RouteSpecification,若將這5 個領域實體(CTS 共有9 個領域實體)都劃分到同一服務,則違背服務實現的用例平均數較小的原則.注意到,領域實體Cargo 和RouteSpecification 在業(yè)務用例ViewTracking、ViewCargo、BookCargo、ChangeCargoDestination 以及RouteCargo 中均有涉及,因此,將領域實體Cargo 和RouteSpecification 劃分到一個服務中.候選微服務SC3 中,在保證服務管理的實體平均數較小的前提下,盡可能地將處理相同領域實體的業(yè)務用例劃分到同一服務,劃分方式與SC2 同理.SC4 對領域實體的劃分與領域驅動設計對CTS 的劃分一致.在領域驅動設計中,Evans 根據限界上下文方法將CTS 劃分為4 個服務:(1)Voyage 服務負責所有航運的信息管理,包含領域實體Voyage 和CarrierMovement;(2)系統中的地點數據具有“多讀少寫”的業(yè)務特點,由Location 服務負責管理,包含領域實體Location;(3)Planning 服務負責管理系統中所有的貨物及其航段信息,包含領域實體Cargo,RouteSpecification,Itinerary 和Leg;(4)Tracking 服務用于跟蹤貨物的具體事件,包含領域實體HandlingEvent.SC4 實現了在4 個指標之間的權衡.
由于SC4 是公認合理的限界上下文劃分方案,而SC0 到SC3 都僅考慮了4 個評估指標中的一項,因此,預計在評估模型給出的評估結果中候選微服務4 即SC4 應具有最好的綜合評分.
在運行SCE 進行微服務劃分評估時,根據CTS 的項目需求指定4 個指標的優(yōu)先級參數為[0.25,0.25,0.25,0.25].運行SCE,對5 個候選微服務分別計算其指標,得到如下指標矩陣M(M的每一行對應SC0~SC4):
對指標計算結果進行歸一化處理得到矩陣M′如下.分析矩陣M′后發(fā)現,候選微服務SC0 具有最大的服務內聚性,SC1 具有最小的服務耦合性,SC2 具有較小的用例收斂性,SC3 具有最小的實體收斂性,與此前的服務設計的分析相一致.
之后,再按照優(yōu)先級參數對M′做加權求和后,得到5 個候選微服務的綜合指標為[0.663,0.254,0.733,0.806,0.831].候選微服務SC4 由于權衡了微服務劃分的多個方面,具有最好的綜合指標結果.綜合指標的計算結果與預想一致,一定程度上說明了評估模型的有效性.
4.2.3 與Service Cutter 對比
由于微服務領域缺少評估微服務劃分的系統化工作,我們選擇劃分微服務的工具原型Service Cutter,使用本評估模型對CTS 在Service Cutter 中的幾種劃分結果進行評估,將評估結果與Service Cutter 的人為評估結果進行比較.
Service Cutter 的微服務劃分過程包括 4 個步驟:系統定義(system definition)、系統說明(system specification)、服務劃分(service decomposition)和分析服務劃分結果(analyze service cuts).在利用CTS 進行微服務劃分的模型驗證時,Gysel 等人[9]同樣通過對DDDSample 的逆向分析得到相關用戶描述(user representation),并以此作為系統定義和系統說明步驟的輸入,得到的用戶描述包括用例圖、實體關系圖、nanoentities 的內容易變性和結構易變性特征等.Service Cutter 通過逆向分析得到的用例圖和實體關系圖與第4.2.1 節(jié)中的基本一致.除用例圖和實體關系圖外,Service Cutter 分析DDDSample 得到的部分用戶描述列舉見表5.Service Cutter 對Location 的內容易變性與結構易變性的定義與本文第4.2.2 節(jié)的討論相一致.在服務劃分步驟中,Gysel等人還根據CTS 的需求特性對16 種耦合度度量標準的優(yōu)先級進行了調整,以使微服務劃分結果更接近預期結果.
Table 5 Part of user representations of CTS application in Service Cutter表5 Service Cutter 得到的CTS 部分用戶描述
以用戶描述和調整后的耦合度度量標準的優(yōu)先級作為輸入,Service Cutter 在劃分CTS 系統時調整聚類算法得到了兩種劃分方案,具體細節(jié)見表6.
Table 6 Microservices candidates of CTS application in Service Cutter表6 Service Cutter 對CTS 應用程序劃分得到的候選微服務
Service Cutter 對劃分結果的討論認為,CUT0 將領域實體Location 劃分到兩個服務,并且依據劃分結果與預期結果的一致程度判定CUT0 為“壞”劃分,CUT1 為“可接受”的劃分.運行SCE 得到本評估模型對兩種劃分方案的評估結果見表7.
Table 7 Evaluation of two decompositions in Service Cutter by SCE表7 SCE 對Service Cutter 兩種劃分方案的評估結果
SCE 的運行結果顯示,微服務CUT0 具有更高的綜合評分,與Service Cutter 的人為評估結果不一致.盡管候選微服務CUT1 的服務耦合性更小,但是由于CUT1 中只有3 個服務,每個服務實現的業(yè)務用例和管理的領域實體更多,因此,用例收斂性和實體收斂性都更大.并且,對比候選微服務CUT0 和CUT1 的具體劃分,CUT0 將業(yè)務用例AddCarrierMovement 劃分出來,成為一個服務,使服務S00 更符合SRP 原則,提高了劃分的服務內聚性.從服務內聚性、服務耦合性、用例收斂性和實體收斂性4 個方面綜合考慮,CUT0 對應的微服務劃分更合理.與本模型相比,Service Cutter 對劃分結果的人為評估具有更強的主觀性.
微服務和DevOps 在縮短交付周期、提高團隊自治性等特性方面是相輔相成的.然而,合理的微服務粒度是微服務一切特性的前提,也是微服務領域的一項難題.本文從限界上下文視角提出一種微服務劃分粒度的評估模型.首先,針對微服務劃分問題給出完整的評估過程;然后,結合微服務劃分的核心原則包括高內聚、低耦合等設計4 項評估指標以量化評估過程;其次,引入指標合并得到微服務劃分的綜合評分以比較不同微服務劃分方案;再次,實現工具原型SCE 自動化地評估微服務劃分;最后,比較評估結果與架構師心理預期驗證模型的有效性.
目前,該方法仍存在如下待改進的問題:首先,評估模型僅考慮了微服務劃分的4 個優(yōu)化目標,評估結果不夠精確,評估過程考慮的因素不夠全面,后續(xù)工作將圍繞微服務架構本身及限界上下文討論更多的微服務劃分原則,并結合實際工程項目完善評估模型;其次,工具原型SCE 要求架構設計人員將軟件制品轉化為格式規(guī)范的JSON 文件作為輸入,后續(xù)工作考慮將SCE 集成到微服務工具鏈,使圖形化軟件制品直接轉化為SCE 輸入,減少架構設計人員的工作負擔.