Chris Richardson微服務翻譯:重構單體服務爲微服務

Chris Richardson 微服務系列翻譯全7篇連接:html

原文連接:Refactoring a Monolith into Microservicesnginx


微服務重構的概述

將單體應用轉化爲微服務是應用現代化的一種形式,數十年來開發者們一直致力於此。所以,將應用重構爲微服務時,咱們能夠借鑑其中的一些經驗。算法

首先不要大規模地重寫代碼,不要集中全部力量從頭構建一個新的微服務應用,這中方式聽起來很吸引人,可是會有極大的風險,有可能以失敗了結。正如 Martin Fowler 所言:數據庫

the only thing a Big Bang rewrite guarantees is a Big Bang!後端

相反,咱們應該漸進式的重構單體應用。逐步構建由微服務組成的新應用,與單體應用一塊兒運行;隨着時間的推移,單體應用實現的功能會不斷收縮,直至徹底消失或者轉變爲另外一個微服務。這一方法雖然充滿挑戰,但風險遠小於大規模重寫代碼。架構

Martin Fowler 將這一策略稱爲「殺手應用」。這一名稱源自熱帶雨林中的殺手藤。殺手藤附生於大樹的周圍,企圖獲得樹冠處的陽光,最後樹木死後,留下樹狀的藤蔓。應用現代化也遵循這一方式。咱們將圍繞着遺留應用構建由一些列微服務組成的新應用,直至遺留應用消失。框架

接下來了解不一樣的實現策略。前後端分離

策略一:中止挖坑

若是發現本身掉入坑裏,應該立刻中止挖坑。一旦單體應用變的難以管理,你應該中止讓單體應用繼續變的龐大,實現新功能時,不該該往單體應用中添加新的代碼。相反的,而是把新代碼放到獨立的微服務中。下圖展現了此方法的系統架構:dom

除了新服務和遺留的單體應用,這個系統還包括其餘兩個組件:第一個是請求路由,用來處理 HTTP 請求,與以前文章中所說的 API 網關相似。路由將與新功能相對應的請求發送到新服務上去,將遺留請求發送到已有的單體應用上去。異步

另外一組件是膠水代碼,用來集成微服務與單體應用。微服務不多獨立存在,一般須要訪問單體應用擁有的數據。膠水代碼存在於單體應用或微服務中,或者二者兼有,用來負責數據的集成。微服務使用膠水代碼來對單體應用的數據進行讀寫。

微服務能夠經過如下三種方式來訪問單體應用的數據:

  • 調用單體應用提供的 API
  • 直接訪問單體應用的數據庫
  • 維護一份數據副本,與單體應用的數據庫保持同步

膠水代碼也被稱爲 anti-corruption layer。由於膠水代碼能防止擁有全新領域模型的服務被遺留單體應用的領域模型所污染。膠水代碼在兩種不一樣的模型間進行轉換。anti-corruption layer 這一術語來自 Eric Evans 撰寫的 Domain Driven Design 中。要想遠離單體應用的泥淖,開發 anti-corruption layer 是必不可少的。

以輕量級微服務的方式實現新功能有許多優勢:它可以防止單體應用變的不可管理。微服務可以獨立開發、部署和擴展。你能夠經過建立新的服務來體會到微服務架構的好處。

然而,這一方法並無解決單體應用的問題。要想解決這些問題,須要拆分單體應用。讓咱們看一下拆分的策略。

策略二:先後端分離

縮小單體應用的策略之一是將展現層從業務邏輯層和數據訪問層中拆分出來。典型的企業應用包括一下三種組件:

  • 展現層:處理 HTTP 請求並實現基於 REST API 或 HTML 的 Web UI。在一個-
    用戶界面複雜的應用中,展現層一般包含了大量的代碼
  • 業務邏輯層:應用的核心,實現了業務邏輯
  • 數據訪問層:訪問數據庫和消息代理等基礎架構組件

一般展現層對於業務邏輯層與數據訪問層來說,彼此有着清晰的劃分。業務層由若干個 API 組成,內部封裝了業務邏輯。這些 API 是將單體應用拆分爲兩個更小應用的分界線。一個應用包含表示層,另外一個應用包含業務邏輯層和數據訪問層。拆分後,展現邏輯的應用向業務邏輯的應用發起遠程調用。下圖展現了重構先後的構架:

以這種方式拆分單體應用有兩大好處:1)它使得兩個應用能夠獨立的開發、部署和擴展。尤爲是,它使得展現層的開發者可以快速迭代用戶界面,輕鬆的進行 AB 測試。2)暴露了可被其餘服務調用的 API
這種策略也只是部分解決方案,頗有可能兩個應用會變成難以管理的單體應用。這時須要使用第三種策略來消除剩餘的單體應用。

策略三:提取微服務

重構的第三個策略是將單體中現有的模塊變成獨立的微服務,每次提取模塊爲微服務時,單體就會縮小,一旦轉化了足夠多的模塊,單體應用將再也不是問題,要麼消息,要麼變成另外一個微服務。

爲須要轉化爲微服務的模塊設置優先級

大型、複雜的單體應用由數十甚至數百個模塊組成,全部模塊都是可提取的。弄清楚哪一個模塊須要首先被提取每每是挑戰性的問題。一個好的方式是先選擇易於提取的模塊,這將給開發者熟悉微服務以及積累提取經驗。以後能夠提取哪些能夠帶來最大收益的模塊。

將模塊轉變爲微服務一般須要必定時間,通常會根據得到收益的大小來給模塊排序。一般轉換常常變化的模塊帶來的收益也最大。一旦把一個模塊轉換爲微服務,就能夠獨立開發、部署它了,從而加快了開發速度。

提取那些對資源有獨特需求的模塊也會帶來不少好處。例如,把須要內存數據庫的模塊轉化爲微服務,就能部署在大內存的主機上。一樣的,將實現計算密集型算法的模塊提取出來也是值得的,該微服務能夠部署在擁有多個 CPU 的主機上。這種方式使得應用更容易擴展。

當決定哪些模塊須要提取時,找出現有粗粒度的邊界(即分界線)也大有裨益。這會使模塊轉化爲微服務更加簡單、省力。例如:一個只經過異步消息與其餘部分通訊的模塊,轉化爲微服務是更簡單的。

如何提取模塊

提取模塊的第一步是肯定模塊和單體應用的接口粒度。單體應用和微服務須要訪問彼此的數據,更像是雙向 API,模塊和應用其它部分之間存在着互相依賴,所以實現這些 API 通常充滿挑戰。重構時使用領域模型來實現業務邏輯變的尤其困難,通常須要大的代碼改動才能打破這些依賴。

一旦實現粗粒度的接口,就能夠將模塊轉化爲獨立的微服務。要作到這一點,必須可以讓單體應用和微服務經過 API 通訊。 下圖展現了重構前、重構中和重構後的不一樣架構:

模塊 Z 是要被提取的模塊,它使用到模塊 Y ,同時它的組件被模塊 X 使用。重構的第一步就是定義一組粗粒度 API,第一個接口是模塊 X 調用模塊 Z 的 接口。第二個接口是模塊 Z 調用模塊 Y的接口。

重構的第二步是把模塊轉變爲獨立的微服務。對內和對外接口經過 IPC 機制實現,開發人員可能只須要將模塊 Z 與微服務支撐框架(Microservice Chassis framework)組合起來構建微服務。

一旦將模塊提取完畢,你就擁有了一個新的微服務,它可以獨立於單體應用和其它微服務進行開發、部署和擴展。若是想重寫微服務的代碼,集成微服務和單體應用的 API 會成爲這兩個領域模型之間的 anti-corruption layer。每提取一個模塊,就向着微服務的方向又邁進了一步。隨着時間推移,單體應用將會逐漸消失,你也會擁有更多的微服務。

總結

將單體應用遷移到微服務的過程是應用現代化的一種形式。並不須要從頭重寫代碼,而是漸進式地將應用重構爲一組微服務。其中有三種策略:使用微服務實現新功能;將展現層從業務邏輯層、數據訪問層中拆分;將單體應用內的模塊轉化爲微服務。隨着時間的推移,微服務的數量將會增長,從而提高團隊的敏捷和效率。

相關文章
相關標籤/搜索