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