如何把復雜單體應用快速遷移到微服務
從我接手過的一個項目說起。先上一個無關緊要的圖提提神:
隨著項目快速迭代,項目代碼變得臃腫,數據表已經接近一百張了。其中部分模塊代碼消耗cpu和內存大,十幾個開發人員在同一個工程里面同時開發著十來個特性,系統如下問題凸顯:
1. 特性耦合,發版困難
往往一個特性的改動,會牽涉到若干模塊,多個特性代碼改動重疊,給測試以及合板,發版帶來了極大的考慮,降低了發版的效率。
2. 非彈性部署,擴展能力差
有些模塊需要消耗大量cpu和內存,有些模塊需要支持高并發,有些模塊需要很少的服務器資源,由于都在單一的系統中,各個模塊之間公用同一套服務器資源,分配不均衡,不能針對具體業務進行合理配置擴展。
3. 系統業務復雜,接手項目困難
在單一的系統中,涵蓋了眾多的業務,一個新入職的同事,花三個月可能都未必能熟悉所有的模塊,模塊間的各種耦合更是讓人傷神;不敢輕易調整代碼,修改一個問題極易引發另外一個問題。
4. 技術升級困難
由于在同一個項目中,技術架構單一,引入一個新技術對所有模塊均會有所影響,調整難度極大,增加技術升級風險,整體技術成保守狀態,難以升級以適應快速發展的互聯網技術。
為此,服務化拆分提上了日程,喵~
服務化拆分流程
在摸透系統里面所有的業務和數據庫的前提下,我們才可以進行服務化的拆分。由于該系統在線上運營時間較久,在參與系統遷移的同事繼續迭代了若干需求和線上問題跟進之后,對整個系統的業務都了解的前提下展開服務化拆遷工作。
先梳理各個模塊的數據模型,然后確定每個模塊的職責,從而可以梳理清晰各個服務的邊界。
1. 解耦老系統外部關聯
實際的業務場景和系統交互異常復雜,在這里我簡化成以下模型進行說明:
根據確定下來的服務的職責和邊界,創建新服務程序和數據庫,在新服務中約定B、C接口,把老系統中對外依賴A全部轉接到新系統,新系統通過編寫的路由器,把請求路由到老系統。
之所以把外部系統關聯解耦放在第一位,是因為外部系統對接需要協調對應的項目組配合整改,周期不可控,需要先把這部分不可控的先完成上線,方便后續系統內部模塊快速拆解上線。
2. 解耦老系統模塊間關聯
把老系統模塊間直接調用A,提升到rpc或者http調用B,對外暴露接口,打斷原有模塊間業務層或者數據層的直接調用;
原有系統數據庫sql關聯查詢需要按照模塊進行拆解,避免跨模塊表關聯操作;
3. 程序遷移到新系統
按照模塊,把相關程序遷移到新系統。
在做解耦老系統模塊間關聯和程序遷移的時候,需要對老系統業務有深刻的掌握,清晰數據庫所有表和字段的作用,以便能快速遷移。
4. 老系統數據全量遷移
把老系統中的所有數據,通過腳本直接遷移到對應新的數據庫中。至此,所有業務數據的寫入和讀取都是基于新服務的數據庫了,從把老系統遷移到了新系統。
關于服務化拆遷的灰度上線
根據系統的業務,制定對應的灰度上線策略。由于我們系統整個業務是圍繞著產品來開展業務的。所以可以在灰度發布(金絲雀部署①)的時候,發布灰度測試產品,將白名單用戶流量打到新版本的服務器分組上面進行驗證。待驗證沒有問題之后,再逐步開放給全量用戶。
在驗證期間,舊版本如果需要繼續流入業務數據,所產生的新的和改動的業務數據需要再次增量遷移到新數據庫中。這樣會增加增量數據遷移的工作量,容易出錯。我們在升級的過程中停止了老版本系統業務數據入庫:
其中灰度測試用戶產生的數據只存在于新數據庫中。
如何給快速迭代的系統進行拆分
一般互聯網企業版本迭代速度都比較快,所以系統遷移的速度一定要迅速。如果周期太長,一個大的需求下來,系統改的面目全非系統遷移的相關工作就得重頭再來了。
為了能盡快推進系統拆分,總結以上流程,我們要考慮如下五個步驟:
- 需要外部項目組配合的事情先處理完:創建新服務,進行依賴遷移(遷移外部系統接口依賴,遷移外部消息依賴);
- 接口系統內模塊間依賴,定義好服務的職責和邊界;
- 快速遷移模塊到新服務,同時進行數據遷移,進入灰度測試環境;
- 灰度測試驗證完畢,遷移增量數據到新數據庫,全量用戶遷移至新系統;
- 線上穩定后,下線老系統,回收相關運維資源。
遷移之后要繼續完善的事情
- 跟上服務化技術配套:服務拆分之后,系統的運維需要輔助額外的代價,維護和測試難度幾何級別增加,我們必須要對應的配套技術:自動化測試,持續集成,自動化部署,配置中心,任務中心,日志監控等;
- 分布式一致性事務問題:為了解決此類問題,我們可以通過業務補償、可靠事件模型,TCC模式進行開發。
系統遷移工作中帶來后續工作的啟發
- 即使是沒有做服務化拆分,系統間各個模塊也要職責邊界定義清晰,梳理清晰業務模型,保證模塊間的低耦合,以及模塊的高內聚;
- 盡量避免過多的數據表關聯查詢,把數據庫當成存儲數據的介質,業務邏輯轉移到程序中實現,這也為后續分庫分表,服務化拆分做好了準備;
- 提前準備服務化配套技術,重視底層平臺大家。強大的底層平臺支撐,幫助我們填平前人已經踩過的坑:灰度發布,服務升級回退,服務注冊發現,熔斷降級,自動化部署等;
- 服務化之后,新技術盡量從邊緣業務進行嘗試,積累相關的遷移,服務化,運維問題,構建了一套相對完善的方案,行程一整套技術規范之后,再推廣至核心業務中,方便了新技術的布道;
作者:彭展旋,來自金蝶隨手記的后端開發工程師,目前做項目管理相關工作,逐漸轉型架構,在服務化、分布式事務、p2p金融系統設計、互聯網資訊系統等領域有相關經驗。
【本文來自51CTO專欄作者張開濤的微信公眾號(開濤的博客),公眾號id: kaitao-1234567】