編者按: 如果你的工作圍繞一個(gè)大型的,復雜的單體應用,可能你每天開(kāi)發(fā)和部署應用的工作都是進(jìn)展緩慢而痛苦的。微服務(wù)看起來(lái)像是一個(gè)遙不可及的天堂,幸運的是,有方法可以幫助你逃離單體架構的地獄。本文將會(huì )介紹如何逐步地將單體應用改造為一系列的微服務(wù)。
作者簡(jiǎn)介: Chris Richardson是Cloudfoundry.com的創(chuàng )始人,現在為提供開(kāi)發(fā)和部署應用的咨詢(xún)服務(wù)。
本文是微服務(wù)系列文章的第七篇,這個(gè)系列的文章都很精彩,第一篇介紹了微服務(wù)架構的模式,討論了微服務(wù)架構的優(yōu)勢和缺點(diǎn),接下來(lái)的文章討論了微服務(wù)架構的不同方面:API Gateway,進(jìn)程間的通信,服務(wù)發(fā)現,事件驅動(dòng)的數據管理和部署微服務(wù)。你還對哪篇 文章感興趣,小編可以翻譯:
將單體應用改造為微服務(wù)實(shí)際上是應用現代化的過(guò)程,這是開(kāi)發(fā)者們在過(guò)去十年來(lái)一直在做的事情,所以已經(jīng)有一些可以復用的經(jīng)驗。
全部重寫(xiě)是絕對不能用的策略,除非你要集中精力從頭構建一個(gè)基于微服務(wù)的應用。雖然聽(tīng)起來(lái)很有吸引力,但是風(fēng)險很大,很有可能會(huì )失敗。就像MartinFowler所說(shuō)的: 『The only thing a Big Bang rewrite guarantees is a Big Bang!』
你應該循序漸進(jìn)地重構你的單體應用。你可以逐步地構建一個(gè)部分微服務(wù)化的應用,然后和你的單體應用集成起來(lái)。單體應用的實(shí)現的功能會(huì )逐漸變少,最終消失或變成一個(gè)新的微服務(wù)組件。
Law of Holes告訴我們,如果你正在一個(gè)洞里,就不要繼續再挖了。當你的單體應用已經(jīng)變得無(wú)法管理的時(shí)候,就不要再繼續擴大它的規模了。 比如你想添加新功能,不要在單體應用中添加代碼,而要將新的代碼放在另一個(gè)單獨的微服務(wù)中。 下圖展示了使用這種方法后的系統架構:
除了新服務(wù)和舊的單體應用,還有兩個(gè)組件。一個(gè)是 請求路由 (request router),用來(lái)處理過(guò)來(lái)的(比如HTTP)請求,類(lèi)似于A(yíng)PI網(wǎng)關(guān)。這個(gè)路由發(fā)送與新功能相應的請求到新的服務(wù)上,將舊服務(wù)相關(guān)的請求路由到單體應用上。
另一個(gè)組件是 膠水代碼 (glue code),用來(lái)將服務(wù)與單體應用集成起來(lái)。一個(gè)服務(wù)很少是隔離存在的,需要訪(fǎng)問(wèn)單體應用的數據。膠水代碼就負責這些數據集成。微服務(wù)組件可以通過(guò)它來(lái)讀寫(xiě)單體應用中的數據。
一個(gè)服務(wù)可以通過(guò)三種方式訪(fǎng)問(wèn)單體應用中的數據:
通過(guò)調用單體應用提供的遠程API
直接訪(fǎng)問(wèn)單體的數據庫
保存一份數據的副本,和單體數據庫保持同步
膠水代碼有時(shí)被稱(chēng)為 防腐層(anti-corruption layer) ,可以防止擁有自己原始領(lǐng)域模型的服務(wù),被來(lái)自單體領(lǐng)域模型的概念所影響。
膠水代碼可以在兩個(gè)不同的模型間充當翻譯官,防腐層這個(gè)詞最初出現在Eric Evans寫(xiě)的《Domain DrivenDesign》一書(shū)中。開(kāi)發(fā)一個(gè)防腐層不是一個(gè)小工程,但如果你想從單體地獄中走出來(lái),這是很重要的。
用輕量級的服務(wù)實(shí)現一個(gè)新功能,有很多好處。首先,可以防止單體應用變得更難以管理;其次,這個(gè)應用可以被獨立地開(kāi)發(fā),部署和擴展。
然而,這個(gè)方法并不能解決在舊有的單體部分遇到的問(wèn)題,你還需要破壞原有的單體部分。
縮減單體應用的一個(gè)策略是將表現層從業(yè)務(wù)邏輯和數據訪(fǎng)問(wèn)層中分離出來(lái),一個(gè)典型的企業(yè)應用至少包括三種組件:
表現層: 這層組件用來(lái)處理HTTP請求,實(shí)現(REST)API或者基于HTML的Web UI。在一個(gè)有著(zhù)復雜的用戶(hù)接口的應用中,表現層通常有大量的代碼;
業(yè)務(wù)邏輯層: 應用的核心代碼,用來(lái)實(shí)現業(yè)務(wù)規則;
數據訪(fǎng)問(wèn)層: 訪(fǎng)問(wèn)數據庫或信息中介的組件。
在表現邏輯與業(yè)務(wù)和數據訪(fǎng)問(wèn)邏輯之間通常有著(zhù)明顯的區分。業(yè)務(wù)層有一個(gè)粗粒度的API,包含一個(gè)或多個(gè)外立面組成,外立面封裝了業(yè)務(wù)邏輯組件。這個(gè)API是自然的『縫合』,所以可以將單體分割為更小的應用,一個(gè)應用包含了表現層,另一個(gè)應用包含了業(yè)務(wù)和數據訪(fǎng)問(wèn)層。分隔后,表現邏輯層應用可以遠程調用業(yè)務(wù)邏輯層應用,下圖展示了改造前后的架構:
這樣分隔單體應用有兩個(gè)主要好處。 首先你可以獨立地開(kāi)發(fā),部署和擴展兩個(gè)應用, 比如對于表現層開(kāi)發(fā)者來(lái)說(shuō),他們可以實(shí)現用戶(hù)界面的快速迭代,A/B測試也很容易實(shí)現; 其次,這樣做會(huì )向外開(kāi)放一個(gè)微服務(wù)也可以調用的遠程API。
但是這個(gè)策略只是部分解決方案,很有可能會(huì )變成兩個(gè)混亂的單體應用。需要用下面第三個(gè)策略去減少單體部分的比重。
策略3:提取服務(wù)
第三個(gè)策略的目的是將單體中的模塊,轉變?yōu)閱为毜奈⒎?wù)。每次提取一個(gè)模塊,就改造為微服務(wù),單體部分就縮減了。一旦你轉化了足夠的模塊,最后不管單體部分是完全消失了,還是變小成了另一個(gè)微服務(wù),都不是問(wèn)題了。
一個(gè)大型的復雜的單體應用,通常包含數十甚至上百個(gè)模塊,都可以被提取出來(lái),選擇先提取哪個(gè)是個(gè)問(wèn)題??梢詮娜菀妆惶崛〉拈_(kāi)始,積累微服務(wù)的經(jīng)驗,然后提取那些能給你帶來(lái)最大好處的模塊。
通常提取那些頻繁變化的模塊很有用 ,一旦你將這個(gè)模塊提取出來(lái),就可以獨立開(kāi)發(fā)和部署它了,可以加速開(kāi)發(fā)。
另外一個(gè)就是提取那些資源需求和其它部分有很大不同的模塊。 比如將一個(gè)有內存數據庫的模塊轉變?yōu)榉?wù),就可以把它部署在內存很大的主機上;同樣的,提取那些實(shí)現復雜算法的模塊,就可以把它部署在CPU多的主機上??傊@樣做有助于你擴展應用。
當決定了提取哪個(gè)模塊后,需要看下現有的粗粒度邊界,可以幫助你將模塊轉化為服務(wù)。比如一個(gè)只會(huì )通過(guò)異步信息和其它應用交互的模塊,就很容易能被改造為微服務(wù)。
第一步是在模塊和單體之間定義一個(gè)粗粒度的接口。 由于單體和微服務(wù)的數據互相都有需求,所以它 很像一個(gè)雙向的API。但是在這個(gè)模塊和應用的剩余部分之間,有著(zhù)混亂的依賴(lài)關(guān)系和細粒度的交互模式,所以實(shí)現這個(gè)API還是很有挑戰的。通過(guò)域模型實(shí)現的業(yè)務(wù)邏輯,改造起來(lái)尤其困難,因為各個(gè)域模型間的關(guān)系復雜。通常需要進(jìn)行大量的代碼修改,去打破這些依賴(lài)。
一旦你實(shí)現了細粒度的接口,就可以將模塊改造為一個(gè)獨立的服務(wù)。要寫(xiě)代碼實(shí)現單體和微服務(wù)間的通信,通過(guò)使用了IPC機制的API。下圖展現了一個(gè)架構在改造前,改造中和改造后的樣子:
改造的第一步是定義一對粗粒度的API,第一個(gè)接口是模塊X調用模塊Z的入站接口,第二個(gè)是模塊Z調用模塊Y的出站接口;
第二步是將這個(gè)模塊改造為獨立的服務(wù)。入站接口和出站接口都通過(guò)IPC機制的代碼實(shí)現??赡苣阈枰ㄟ^(guò)結合模塊Z到微服務(wù)底盤(pán)框架(用來(lái)處理橫切關(guān)注點(diǎn),比如服務(wù)發(fā)現)上,來(lái)構建這個(gè)服務(wù)。
一旦你提取了這個(gè)模塊,就可以獨立地開(kāi)發(fā),部署和擴展它了。你甚至可以從頭重寫(xiě)這個(gè)服務(wù),將這個(gè)服務(wù)和單體結合起來(lái)的API代碼就成了防腐層,相當于兩個(gè)域模型之間的翻譯官。每次提取一個(gè)服務(wù),都是向著(zhù)微服務(wù)又進(jìn)了一步,單體的比重會(huì )逐步縮減。
將單體架構改造為微服務(wù)的過(guò)程是一種應用現代化的形式,不應該從頭重寫(xiě)來(lái)實(shí)現。而是應該循序漸進(jìn)地改造你的應用成為一系列微服務(wù)。有三種策略可以應用: 用微服務(wù)實(shí)現新的功能;將表現層組件從業(yè)務(wù)和數據訪(fǎng)問(wèn)組件中分離出來(lái);改造單體中的模塊為微服務(wù)。 隨著(zhù)時(shí)間的推移,你的微服務(wù)比重會(huì )增大,你的開(kāi)發(fā)團隊的靈活性和速度也會(huì )提高。
靈雀云 ∣ 釋放云的無(wú)限潛能
長(cháng)按,識別二維碼,加關(guān)注
聯(lián)系客服