【Chris Richardson 微服務(wù)系列】使用微服務(wù)重構(gòu)單體應(yīng)用

編者的話 |本文來自 Nginx 官方博客,是「Chris Richardson 微服務(wù)」系列的最后一篇。第一篇介紹了微服務(wù)架構(gòu)模塊,并且討論了使用微服務(wù)的優(yōu)缺點(diǎn)。隨后的文章討論了微服務(wù)的不同方面,包括使用 API 網(wǎng)關(guān)、進(jìn)程間通訊、服務(wù)發(fā)現(xiàn)、事件驅(qū)動的數(shù)據(jù)管理,以及部署微服務(wù)。本篇將討論從單體應(yīng)用遷移到微服務(wù)的策略。

作者介紹:Chris Richardson,是世界著名的軟件大師,經(jīng)典技術(shù)著作《POJOS IN ACTION》一書的作者,也是 cloudfoundry.com 最初的創(chuàng)始人,Chris Richardson 與 Martin Fowler、Sam Newman、Adrian Cockcroft 等并稱為世界十大軟件架構(gòu)師。

Chris Richardson 微服務(wù)系列全 7 篇:

1. 微服務(wù)架構(gòu)概念解析
2. 構(gòu)建微服務(wù)架構(gòu):使用 API Gateway
3. 深入微服務(wù)架構(gòu)的進(jìn)程間通信
4. 服務(wù)發(fā)現(xiàn)的可行方案以及實(shí)踐案例
5. 微服務(wù)的事件驅(qū)動數(shù)據(jù)管理
6. 選擇微服務(wù)部署策略
7. 將單體應(yīng)用改造為微服務(wù)(本篇文章)

使用微服務(wù)重構(gòu)概述

將單體應(yīng)用轉(zhuǎn)變?yōu)槲⒎?wù)的過程也是將應(yīng)用現(xiàn)代化的過程,數(shù)十年來開發(fā)者們一直致力于此。因此,當(dāng)把應(yīng)用重構(gòu)為微服務(wù)的時(shí)候,我們可以借鑒其中的理念。

首先不要大規(guī)模地重寫代碼。大規(guī)模重寫代碼意味著你需要集中全部開發(fā)力量、從頭構(gòu)建全新的基于微服務(wù)的應(yīng)用;聽起來吸引人,但是充滿風(fēng)險(xiǎn),有可能以失敗告終。正如 Martin Fowler 所言,“大規(guī)模重寫唯一能夠保證的只有大規(guī)模!”

相反,應(yīng)當(dāng)采取逐步重構(gòu)單體應(yīng)用的策略。逐步構(gòu)建一個(gè)由微服務(wù)構(gòu)成的應(yīng)用,與單體應(yīng)用并行運(yùn)行;隨著時(shí)間推移,原先由單體應(yīng)用實(shí)現(xiàn)的功能不斷收縮,最后或者完全消失,或者轉(zhuǎn)變?yōu)槲⒎?wù)。這一方法雖然充滿挑戰(zhàn),但風(fēng)險(xiǎn)遠(yuǎn)小于大規(guī)模重寫代碼。

Martin Fowler 將這一應(yīng)用現(xiàn)代化的策略稱為“殺手應(yīng)用”。這一名稱源自熱帶雨林中的殺手藤。殺手藤附生于樹,直達(dá)樹冠上方;樹死后,留下樹狀的藤蔓。應(yīng)用的現(xiàn)代化也是遵循這一模式。微服務(wù)構(gòu)成的新應(yīng)用圍繞著遺留應(yīng)用,后者最終完全不復(fù)存在。

接下來了解不同的實(shí)現(xiàn)策略。

策略一:停止挖坑

挖坑第一法則指出,如果發(fā)現(xiàn)自己掉坑里,馬上停止。這一忠告也適用于難以管理的單體應(yīng)用。換句話說,應(yīng)該停止讓單體應(yīng)用繼續(xù)變大,也就是在實(shí)現(xiàn)新功能的時(shí)候,不應(yīng)該再增加代碼。相反,這一策略的理念在于,把這部分新代碼開發(fā)稱為獨(dú)立的微服務(wù)。下圖展示了采用此方法的系統(tǒng)架構(gòu)。

除了新服務(wù)和遺留應(yīng)用,這個(gè)系統(tǒng)還包括另外兩個(gè)組件。其一是請求路由,處理傳入(HTTP)請求,與之前文章中描述的 API 網(wǎng)關(guān)類似。路由將與新功能對應(yīng)的請求發(fā)送到新服務(wù),將遺留請求發(fā)送到已有的單體應(yīng)用。

另一組件是膠水代碼(glue code),負(fù)責(zé)集成微服務(wù)與單體應(yīng)用。微服務(wù)很少孤立存在,通常需要訪問單體應(yīng)用擁有的數(shù)據(jù)。膠水代碼存在于單體應(yīng)用或微服務(wù)中,或者兩者兼有,負(fù)責(zé)數(shù)據(jù)集成。微服務(wù)使用膠水代碼來讀取和寫入單體應(yīng)用擁有的數(shù)據(jù)。

微服務(wù)可以通過以下三種方式訪問單體應(yīng)用的數(shù)據(jù):

  • 調(diào)用由單體應(yīng)用提供的遠(yuǎn)程 API
  • 直接訪問單體應(yīng)用的數(shù)據(jù)
  • 維護(hù)一份數(shù)據(jù)拷貝,與單體應(yīng)用的數(shù)據(jù)庫保持同步

膠水代碼也被稱作防崩潰層(anti-corruption layer)。對于擁有自己全新領(lǐng)域模型的微服務(wù),膠水代碼能夠阻止其受到遺留單體應(yīng)用的領(lǐng)域模型的污染,并且為這兩種模型提供轉(zhuǎn)換。防崩潰層這一術(shù)語最早出現(xiàn)于 Eric Evans 撰寫的必讀書 Domain Driven Design 中,并被提煉成為白皮書。開發(fā)防崩潰層是項(xiàng)不平凡的工作,要想遠(yuǎn)離單體應(yīng)用的泥淖,創(chuàng)建防崩潰層必不可少。

以輕量級微服務(wù)的方式實(shí)現(xiàn)新功能有諸多優(yōu)點(diǎn)。它能夠防止單體應(yīng)用變得不可管理。微服務(wù)能夠獨(dú)立于單體服務(wù)進(jìn)行開發(fā)、部署和擴(kuò)展。采用微服務(wù)能讓開發(fā)者切身感受其好處。

然而,這一方法并沒有解決單體應(yīng)用的問題。要想解決這些問題,需要分解單體應(yīng)用。

策略二:拆分前端和后端

縮小單體應(yīng)用的策略之一是將表示層(presentation layer)與業(yè)務(wù)邏輯和數(shù)據(jù)訪問層分離。典型的企業(yè)應(yīng)用包括至少三類組件:

  • 表示層:處理 HTTP 請求并實(shí)現(xiàn) (REST)API 或基于 HTML 的 Web UI。對于包含復(fù)雜用戶接口的應(yīng)用,表示層往往是代碼的實(shí)體部分。
  • 業(yè)務(wù)邏輯層:應(yīng)用的核心,實(shí)現(xiàn)業(yè)務(wù)邏輯
  • 數(shù)據(jù)訪問層:訪問諸如數(shù)據(jù)庫和消息代理這樣的基礎(chǔ)架構(gòu)組件

在表示邏輯與業(yè)務(wù)和數(shù)據(jù)訪問邏輯之間,有著清晰的間隔。業(yè)務(wù)層的粗粒度的 API 由若干方面組成,內(nèi)部封裝業(yè)務(wù)邏輯組件。這個(gè) API 是一道天然分界線,將單體應(yīng)用分割成兩個(gè)較小的應(yīng)用。一個(gè)應(yīng)用包含表示層,另一個(gè)應(yīng)用包含業(yè)務(wù)和數(shù)據(jù)訪問邏輯。拆分后,表示邏輯應(yīng)用對業(yè)務(wù)邏輯應(yīng)用遠(yuǎn)程調(diào)用。下圖展示了重構(gòu)前后的構(gòu)架。

以這種方式切割單體應(yīng)用有兩大好處。首先,它使得這兩個(gè)應(yīng)用的開發(fā)、部署和擴(kuò)展用各自獨(dú)立。尤其是,它使得表示層的開發(fā)人員能夠快速迭代用戶接口,輕松進(jìn)行 A|B 測試。其次,它暴露了遠(yuǎn)程 API,能夠被微服務(wù)調(diào)用。

這種策略也只是部分解決方案,很有可能其中一個(gè)應(yīng)用或兩個(gè)應(yīng)用變成難以管理的單體應(yīng)用。這時(shí)需要使用第三種策略來消除剩余的單體應(yīng)用。

策略三:提取微服務(wù)

第三種重構(gòu)策略是將單體應(yīng)用內(nèi)現(xiàn)有的模塊轉(zhuǎn)變?yōu)楠?dú)立的微服務(wù)。每當(dāng)提取模塊并將其轉(zhuǎn)化為服務(wù),單體應(yīng)用就會收縮。一旦轉(zhuǎn)化了足夠的模塊,單體應(yīng)用也不再是問題,它或者徹底消失,或者小到成為另一個(gè)微服務(wù)。

為需要轉(zhuǎn)化為微服務(wù)的模塊設(shè)置優(yōu)先級

大型、復(fù)雜的單體應(yīng)用由數(shù)十甚至數(shù)百個(gè)模塊組成,每個(gè)都是提取的對象。要弄清楚哪些模塊首先被轉(zhuǎn)化,往往具有挑戰(zhàn)性。從易于提取的模塊開始是個(gè)好方法,它能讓開發(fā)者熟悉微服務(wù)和提取過程。然后就應(yīng)該轉(zhuǎn)化能從中獲益最多的模塊。

鑒于把模塊轉(zhuǎn)變?yōu)槲⒎?wù)非常耗時(shí),一般會根據(jù)獲益程度來給模塊排序。從頻繁更改的模塊開始會讓用戶收獲不菲。一旦把模塊轉(zhuǎn)化為微服務(wù),也就能獨(dú)立開發(fā)和部署,從而加速開發(fā)進(jìn)度。

將資源需求大不相同的模塊優(yōu)先轉(zhuǎn)化,也頗有好處。例如,把內(nèi)存數(shù)據(jù)庫模塊轉(zhuǎn)化為微服務(wù),能夠被部署在大內(nèi)存主機(jī)上。同樣,將實(shí)現(xiàn)計(jì)算算法的模塊提取出來也是非常值得,這一微服務(wù)能夠部署在擁有大量 CPU 的主機(jī)上。通過將對資源有著特殊需求的模塊轉(zhuǎn)變?yōu)槲⒎?wù),應(yīng)用能夠易于擴(kuò)展。

找出哪些模塊需要優(yōu)先提取后,找出現(xiàn)有粗粒度的邊界(即分界線)也大有裨益。這些邊界讓模塊轉(zhuǎn)變?yōu)槲⒎?wù)更加簡單、省力。例如,通過異步消息與應(yīng)用的其它部分通信的模塊能夠相對省力、簡便地轉(zhuǎn)化為微服務(wù)。

如何提取模塊

模塊提取的第一步是定義模塊和單體應(yīng)用間的粒度接口。由于單體應(yīng)用和微服務(wù)互相需要對方擁有的數(shù)據(jù),因此更像是雙向 API。由于模塊和應(yīng)用其它部分之間存在著互相依賴和細(xì)粒度的交互模型,因此實(shí)現(xiàn)這樣的 API 充滿挑戰(zhàn)。對于重構(gòu)微服務(wù),通過領(lǐng)域模型實(shí)現(xiàn)的業(yè)務(wù)邏輯尤為挑戰(zhàn),開發(fā)人員需要大刀闊斧地修改代碼來打破這些依賴。

粗粒度接口一旦完成,模塊也就變成了獨(dú)立的微服務(wù)。要做到這一點(diǎn),開發(fā)人員必須編寫代碼,能夠讓單體應(yīng)用和微服務(wù)通過 API 通信,API 使用進(jìn)程間通信(IPC)機(jī)制。 下圖展示了重構(gòu)前、重構(gòu)中和重構(gòu)后的不同架構(gòu)。

在圖片中,模塊 Z 將要被重構(gòu),它用到了模塊 Y 的組件,同時(shí)它的組件被模塊 X 使用。重構(gòu)的第一步就是定義一對粗粒度 API。第一個(gè)接口是模塊 X 使用的對內(nèi)接口,用來喚醒模塊 Z。第二個(gè)接口是模塊 Z 使用的對外接口,喚醒模塊 Y。

重構(gòu)的第二步則是把模塊轉(zhuǎn)變?yōu)楠?dú)立的微服務(wù)。對內(nèi)和對外接口通過 IPC 機(jī)制的代碼實(shí)現(xiàn),開發(fā)人員可能只需要將模塊 Z 與微服務(wù)支撐框架(Microservice Chassis framework)組合起來構(gòu)建微服務(wù)。微服務(wù)支撐框架處理與割接相關(guān)的問題,比如服務(wù)發(fā)現(xiàn)。

一旦將模塊提取完畢,相當(dāng)于得到一個(gè)微服務(wù),能夠獨(dú)立于單體應(yīng)用和其它微服務(wù)進(jìn)行開發(fā)、部署和擴(kuò)展。如果要從頭重寫微服務(wù)代碼,集成微服務(wù)和單體應(yīng)用的 API 代碼會成為這兩個(gè)領(lǐng)域模型之間的防崩潰層。每重構(gòu)一個(gè)組件,就向著微服務(wù)的方向又邁進(jìn)了一步。隨著時(shí)間推移,單體應(yīng)用逐漸消失,微服務(wù)則越來越多。

總結(jié)

將現(xiàn)有單體應(yīng)用遷移到微服務(wù)架構(gòu)是應(yīng)用的現(xiàn)代化。實(shí)現(xiàn)這一結(jié)果并不需要從頭重寫代碼,相反,只需要漸進(jìn)式地將應(yīng)用重構(gòu)為一組微服務(wù)。其中有三種策略可以采納:使用微服務(wù)實(shí)現(xiàn)新功能、將表示組件與業(yè)務(wù)和數(shù)據(jù)訪問組件拆分、以及將現(xiàn)有應(yīng)用內(nèi)的模塊轉(zhuǎn)變?yōu)槲⒎?wù)。隨著時(shí)間推移,大量微服務(wù)形成,團(tuán)隊(duì)的敏捷和效率也會提升。

文章轉(zhuǎn)載自:http://blog.daocloud.io/microservices-7/

查看英文原文

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容