編者的話 |html
做者介紹:Chris Richardson,是世界著名的軟件大師,經典技術著做《POJOS IN ACTION》一書的做者,也是 cloudfoundry.com 最初的創始人,Chris Richardson 與 Martin Fowler、Sam Newman、Adrian Cockcroft 等並稱爲世界十大軟件架構師。前端
Chris Richardson 微服務系列全 7 篇:nginx
1. 微服務架構概念解析算法
2. 構建微服務架構:使用 API Gateway數據庫
3. 深刻微服務架構的進程間通訊(本篇文章)後端
4. 服務發現的可行方案以及實踐案例架構
5. 微服務的事件驅動數據管理框架
6. 選擇微服務部署策略異步
7. 將單體應用改造爲微服務(本篇文章)微服務
使用微服務重構概述
將單體應用轉變爲微服務的過程也是將應用現代化的過程,數十年來開發者們一直致力於此。所以,當把應用重構爲微服務的時候,咱們能夠借鑑其中的理念。
首先不要大規模地重寫代碼。大規模重寫代碼意味着你須要集中所有開發力量、從頭構建全新的基於微服務的應用;聽起來吸引人,可是充滿風險,有可能以失敗了結。正如 Martin Fowler 所言,「大規模重寫惟一可以保證的只有大規模!」
相反,應當採起逐步重構單體應用的策略。逐步構建一個由微服務構成的應用,與單體應用並行運行;隨着時間推移,原先由單體應用實現的功能不斷收縮,最後或者徹底消失,或者轉變爲微服務。這一方法雖然充滿挑戰,但風險遠小於大規模重寫代碼。
Martin Fowler 將這一應用現代化的策略稱爲「殺手應用」。這一名稱源自熱帶雨林中的殺手藤。殺手藤附生於樹,直達樹冠上方;樹死後,留下樹狀的藤蔓。應用的現代化也是遵循這一模式。微服務構成的新應用圍繞着遺留應用,後者最終徹底不復存在。
接下來了解不一樣的實現策略。
策略一:中止挖坑
挖坑第一法則指出,若是發現本身掉坑裏,立刻中止。這一忠告也適用於難以管理的單體應用。換句話說,應該中止讓單體應用繼續變大,也就是在實現新功能的時候,不該該再增長代碼。相反,這一策略的理念在於,把這部分新代碼開發稱爲獨立的微服務。下圖展現了採用此方法的系統架構。
除了新服務和遺留應用,這個系統還包括另外兩個組件。其一是請求路由,處理傳入(HTTP)請求,與以前文章中描述的 API 網關相似。路由將與新功能對應的請求發送到新服務,將遺留請求發送到已有的單體應用。
另外一組件是膠水代碼(glue code),負責集成微服務與單體應用。微服務不多孤立存在,一般須要訪問單體應用擁有的數據。膠水代碼存在於單體應用或微服務中,或者二者兼有,負責數據集成。微服務使用膠水代碼來讀取和寫入單體應用擁有的數據。
微服務能夠經過如下三種方式訪問單體應用的數據:
- 調用由單體應用提供的遠程 API
- 直接訪問單體應用的數據
- 維護一份數據拷貝,與單體應用的數據庫保持同步
膠水代碼也被稱做防崩潰層(anti-corruption layer)。對於擁有本身全新領域模型的微服務,膠水代碼可以阻止其受到遺留單體應用的領域模型的污染,而且爲這兩種模型提供轉換。防崩潰層這一術語最先出現於 Eric Evans 撰寫的必讀書 Domain Driven Design 中,並被提煉成爲白皮書。開發防崩潰層是項不平凡的工做,要想遠離單體應用的泥淖,建立防崩潰層必不可少。
以輕量級微服務的方式實現新功能有諸多優勢。它可以防止單體應用變得不可管理。微服務可以獨立於單體服務進行開發、部署和擴展。採用微服務能讓開發者切身感覺其好處。
然而,這一方法並無解決單體應用的問題。要想解決這些問題,須要分解單體應用。
策略二:拆分前端和後端
縮小單體應用的策略之一是將表示層(presentation layer)與業務邏輯和數據訪問層分離。典型的企業應用包括至少三類組件:
- 表示層:處理 HTTP 請求並實現 (REST)API 或基於 HTML 的 Web UI。對於包含複雜用戶接口的應用,表示層每每是代碼的實體部分。
- 業務邏輯層:應用的核心,實現業務邏輯
- 數據訪問層:訪問諸如數據庫和消息代理這樣的基礎架構組件
在表示邏輯與業務和數據訪問邏輯之間,有着清晰的間隔。業務層的粗粒度的 API 由若干方面組成,內部封裝業務邏輯組件。這個 API 是一道自然分界線,將單體應用分割成兩個較小的應用。一個應用包含表示層,另外一個應用包含業務和數據訪問邏輯。拆分後,表示邏輯應用對業務邏輯應用遠程調用。下圖展現了重構先後的構架。
以這種方式切割單體應用有兩大好處。首先,它使得這兩個應用的開發、部署和擴展用各自獨立。尤爲是,它使得表示層的開發人員可以快速迭代用戶接口,輕鬆進行 A|B 測試。其次,它暴露了遠程 API,可以被微服務調用。
這種策略也只是部分解決方案,頗有可能其中一個應用或兩個應用變成難以管理的單體應用。這時須要使用第三種策略來消除剩餘的單體應用。
策略三:提取微服務
第三種重構策略是將單體應用內現有的模塊轉變爲獨立的微服務。每當提取模塊並將其轉化爲服務,單體應用就會收縮。一旦轉化了足夠的模塊,單體應用也再也不是問題,它或者完全消失,或者小到成爲另外一個微服務。
爲須要轉化爲微服務的模塊設置優先級
大型、複雜的單體應用由數十甚至數百個模塊組成,每一個都是提取的對象。要弄清楚哪些模塊首先被轉化,每每具備挑戰性。從易於提取的模塊開始是個好方法,它能讓開發者熟悉微服務和提取過程。而後就應該轉化能從中獲益最多的模塊。
鑑於把模塊轉變爲微服務很是耗時,通常會根據獲益程度來給模塊排序。從頻繁更改的模塊開始會讓用戶收穫不菲。一旦把模塊轉化爲微服務,也就能獨立開發和部署,從而加速開發進度。
將資源需求大不相同的模塊優先轉化,也很有好處。例如,把內存數據庫模塊轉化爲微服務,可以被部署在大內存主機上。一樣,將實現計算算法的模塊提取出來也是很是值得,這一微服務可以部署在擁有大量 CPU 的主機上。經過將對資源有着特殊需求的模塊轉變爲微服務,應用可以易於擴展。
找出哪些模塊須要優先提取後,找出現有粗粒度的邊界(即分界線)也大有裨益。這些邊界讓模塊轉變爲微服務更加簡單、省力。例如,經過異步消息與應用的其它部分通訊的模塊可以相對省力、簡便地轉化爲微服務。
如何提取模塊
模塊提取的第一步是定義模塊和單體應用間的粒度接口。因爲單體應用和微服務互相須要對方擁有的數據,所以更像是雙向 API。因爲模塊和應用其它部分之間存在着互相依賴和細粒度的交互模型,所以實現這樣的 API 充滿挑戰。對於重構微服務,經過領域模型實現的業務邏輯尤其挑戰,開發人員須要大刀闊斧地修改代碼來打破這些依賴。
粗粒度接口一旦完成,模塊也就變成了獨立的微服務。要作到這一點,開發人員必須編寫代碼,可以讓單體應用和微服務經過 API 通訊,API 使用進程間通訊(IPC)機制。 下圖展現了重構前、重構中和重構後的不一樣架構。
在圖片中,模塊 Z 將要被重構,它用到了模塊 Y 的組件,同時它的組件被模塊 X 使用。重構的第一步就是定義一對粗粒度 API。第一個接口是模塊 X 使用的對內接口,用來喚醒模塊 Z。第二個接口是模塊 Z 使用的對外接口,喚醒模塊 Y。
重構的第二步則是把模塊轉變爲獨立的微服務。對內和對外接口經過 IPC 機制的代碼實現,開發人員可能只須要將模塊 Z 與微服務支撐框架(Microservice Chassis framework)組合起來構建微服務。微服務支撐框架處理與割接相關的問題,好比服務發現。
一旦將模塊提取完畢,至關於獲得一個微服務,可以獨立於單體應用和其它微服務進行開發、部署和擴展。若是要從頭重寫微服務代碼,集成微服務和單體應用的 API 代碼會成爲這兩個領域模型之間的防崩潰層。每重構一個組件,就向着微服務的方向又邁進了一步。隨着時間推移,單體應用逐漸消失,微服務則愈來愈多。
總結
將現有單體應用遷移到微服務架構是應用的現代化。實現這一結果並不須要從頭重寫代碼,相反,只須要漸進式地將應用重構爲一組微服務。其中有三種策略能夠採納:使用微服務實現新功能、將表示組件與業務和數據訪問組件拆分、以及將現有應用內的模塊轉變爲微服務。隨着時間推移,大量微服務造成,團隊的敏捷和效率也會提高。
文章轉載自:http://blog.daocloud.io/microservices-7/
同轉:http://www.gaoxuan1989.com/category/微服務/