本文來自開源云中文社區(qū)。
當涉及到將單體應用程序重構為微服務時,大多數工程團隊不知道從哪里開始。此外,最近的一項調查顯示,79%的現(xiàn)代化項目失敗,平均花費150萬美元和16個月的時間。
在盲目進行現(xiàn)代化項目之前,必須了解技術債務積累、創(chuàng)新和所有權成本、復雜性和風險等因素。
事件風暴練習、領域驅動設計(DDD)、Strangler Fig Pattern和其他都是要遵循的有用概念,但作為架構師或開發(fā)人員,如何將單體應用程序重構為微服務?
完成這項工作的最佳實踐有很多種,在這篇文章中,我們將探討一些具體的行動,以智能地將單體分解為微服務。
這些操作包括識別服務域、將兩個服務合并為一個服務、將服務更精確地重命名以及刪除作為微服務提取候選的服務或類。最好的部分是:我們將使用人工智能(AI)和自動化來實現(xiàn)目標,而不是試圖手動完成這些工作。
最佳實踐1:自動識別服務和域
調查表明,使用白板上的便簽手動分析一個單體的時間太長,成本太高,很少成功。團隊中的哪一位架構師或開發(fā)人員有時間和能力手工審閱數百萬行代碼和數萬個類?大型單體應用程序需要一種自動化、數據驅動的方法來識別潛在的服務邊界。
讓我們選擇一個現(xiàn)成的、真實的應用程序作為平臺,在其中探索這些最佳實踐。作為Java開發(fā)人員的教程示例,Oracle提供了一個醫(yī)療記錄(MedRec)應用程序——也稱為Avitek醫(yī)療記錄應用程序,它是一個使用WebLogic和Java EE的傳統(tǒng)單體。
使用vFunction,我們將啟動一個“學習”階段,使用基于調用樹和系統(tǒng)流的動態(tài)分析、靜態(tài)分析和機器學習來識別理想的服務域。
圖1:此服務圖顯示了為提取而標識的單個服務
在圖1中,我們看到一個服務圖,其中服務顯示為不同大小和顏色的球體,以及連接它們的線(邊)。每個球體表示vFunction自動識別為與特定域相關的服務。這些服務的名稱和詳細信息顯示在屏幕右側。
球體的大小表示服務中包含的類的數量。顏色表示每個服務中的類“排他性”級別,指的是僅存在于該服務中的類別的百分比,而不是跨多個服務共享的類別。
紅色代表低排他性,藍色代表中排他性和綠色代表高排他性。較高的類排他性表明服務之間的邊界更好,相互依賴性更少,代碼重復更少。綜上所述,這些特征表明,將高度獨占的服務重構為微服務將不那么復雜。
圖2和圖3:實線和虛線表示服務之間的不同關系
這里的實線表示跨服務共享的公共資源(圖2)。常見資源包括bean、同步對象、只讀DB事務和表、讀寫DB事務和表、WebSocket、文件和嵌入式文件等。虛線表示服務之間的方法調用(圖3)。
中間的黑色球體表示仍處于單體中的類,其中包含不特定于任何特定域的類和資源,因此未被選為提取的候選對象。
通過使用自動化和人工智能來分析和公開以前包含在單體黑匣子中的新服務邊界,你現(xiàn)在可以開始在建議的參考架構中操作服務,該架構為基于數據驅動分析做出更好的決策掃清了道路。
最佳實踐2:整合功能并避免重復
當一切都在單體中時,能見度有限。如果能夠公開建議的服務邊界,你可以開始做出決策并測試設計概念,例如,識別多個服務中的重疊功能。
什么時候將具有類似功能的不同服務整合到單個微服務中才有意義?最基本的例子是,作為一名架構師,你可能會看到將兩個看起來重疊的服務組合在一起的機會,我們可以根據類名和類排他性級別來識別這些服務。
圖4:兩個類似的服務已被確定要合并
在服務圖(圖4)中,我們看到了兩個類似的聊天服務,它們用白色圓圈勾勒出來:PatientChatWebSocket和PhysicanChatWebSocket。我們可以看到,Physican聊天服務(紅色)具有0%的動態(tài)排他性,而Patient聊天服務(藍色)具有略高的排他性(33%)。
這兩個服務都沒有使用任何共享資源,這表明我們可以將這些資源合并到一個服務中,而不會因為我們的操作而糾纏任何東西。
圖5:確認合并服務的決定可以通過按下按鈕立即回滾
通過合并兩個類似的服務,你可以合并重復的功能,并在新合并的服務中增加類的排他性(圖5)。由于我們在本例中使用vFunction平臺,邏輯綁定這些服務所需的一切都得到了處理——類、入口點和資源都得到了智能更新。
圖6:新合并的單個服務現(xiàn)在表示兩個以前的聊天服務
合并服務就像將一個服務拖放到另一個服務上一樣簡單,在vFunction平臺重新計算對該操作的分析后,我們看到球體現(xiàn)在是綠色的,動態(tài)排他性為75%(圖6)。這表明新合并的服務在類級別上互連較少,并使我們有機會以較低的復雜性提取此服務。
最佳實踐3:為服務創(chuàng)建準確和有意義的名稱
我們都知道給事物命名很難。在處理單體服務時,我們實際上只能使用類名來了解發(fā)生了什么。僅憑這些信息,很難準確識別哪些類和功能可能屬于特定的域。
在示例中,vFunction從圖7中屏幕右側的類名中自動導出服務域名。作為架構師,你需要能夠根據偏好和需求重命名服務。
圖7:將合并的服務更精確地重命名
現(xiàn)在讓我們回到上一節(jié)中合并的兩個聊天服務。雖然以前我們有一個用于患者和醫(yī)生聊天的服務,但現(xiàn)在我們有了一個代表這兩個配置文件的單一服務,因此PatientChatWebSocket的名稱不再準確,可能會導致將來使用此服務的其他開發(fā)人員產生誤解。我們可以選擇一個更好的名稱,例如ChatService(圖7)。
圖8:將自動識別的服務重命名為更有意義的服務
在圖8中,我們可以看到另一個名為JaxRSRecordFacadeBroker(+2)的服務。這里的(+2)部分表示我們有屬于多個類的入口點。你可能會發(fā)現(xiàn)此名稱具有不必要的描述性,因此可以簡單地將其更改為RecordBroker。
通過以更準確和更有意義的方式重命名服務,可以確保工程團隊能夠以直接的方式快速識別和處理未來的微服務。
最佳實踐4:確定不應作為單獨微服務的功能
什么品質表明,以前包含在一個整體中的功能應該成為一個微服務?并不是所有的東西都應該成為一個微服務,所以什么時候你想刪除一個作為分離和提取候選的服務?
你可能會決定某些服務實際上不屬于單獨的域,例如,一個只過濾消息的過濾器類。因為這不是任何特定服務所獨有的,所以你可以決定將來將其移動到公共庫或其他服務。
當刪除作為未來提取為微服務的候選功能時,您決定不將此類視為接收流量的單獨入口點。讓我們看看AuthenticationAdministrationController服務(圖9),它是一個簡單的控制器類。
圖9:刪除一個非常簡單的非特定服務
在圖9中,我們可以看到所選類的紅色排他性很低,而且它是一個非常小的服務,只包含一個動態(tài)類、一個靜態(tài)類,沒有資源。你可以決定它本身不應該是一個單獨的服務,并通過將其拖放到中間的黑色球體上來刪除它(圖10)。
通過將這個類重新定位到單體,我們已經確定這個特定的功能不滿足成為單個微服務的要求。
在本文中,我們展示了架構師和開發(fā)人員可以遵循的一些最佳實踐,以便將單體應用程序重構為有界的上下文和精確的域,用于未來的微服務提取。
通過使用vFunction平臺,使用人工智能和數據驅動分析,許多繁重的起始和手動工作已經自動化。這確保了架構師和開發(fā)團隊可以將時間集中在基于智能建議的參考架構上,而不是在沒有適當的“全局”上下文的情況下花費數千小時手動分析小塊代碼。
原文鏈接:
https://thenewstack.io/monoliths-to-microservices-4-modernization-best-practices-2/