您正工作於大型複雜的單體應用程式上,這是相當不錯的機會。您開發和部署應用程式的日常經歷是緩慢而痛苦的。微服務似乎是一個遙不可及的天堂。幸運的是,有一些戰略可以用來逃離單體地獄。在本文中,我將描述如何將單體應用程式逐漸重構為一組微服務。 ...
https://github.com/oopsguy/microservices-from-design-to-deployment-chinese
譯者:http://oopsguy.com
本書是關於如何使用微服務構建應用程式,這是本書的第七章,也是最後一章。第一章介紹了微服務架構模式,討論了使用微服務的優點與缺點。隨後的章節討論了微服務架構的方方面面:使用 API 網關、進程間通信、服務發現、事件驅動數據管理和部署微服務。在本章中,我們將介紹單體應用遷移到微伺服器的策略。
我希望這本電子書能夠讓您對微服務架構、其優點和缺點以及何時使用它有很好的瞭解。微服務架構也許很適合您的組織。
然而,您正工作於大型複雜的單體應用程式上,這是相當不錯的機會。您開發和部署應用程式的日常經歷是緩慢而痛苦的。微服務似乎是一個遙不可及的天堂。幸運的是,有一些戰略可以用來逃離單體地獄。在本文中,我將描述如何將單體應用程式逐漸重構為一組微服務。
7.1、微服務重構概述
單體應用程式轉換為微服務的過程是應用程式現代化的一種形式。這是幾十年來開發人員一直在做的事情。因此,在將應用程式重構為微服務時,有一些想法是可以重用的。
一個不要使用的策略是“大爆炸”重寫。就是您將所有的開發工作都集中在從頭開始構建新的基於微伺服器的應用程式。雖然這聽起來很吸引人,但非常危險,有可能會失敗。據 AsMartin Fowler 講到:“大爆炸重寫的唯一保證就是大爆炸!”("the only thing a Big Bang rewrite guarantees is a Big Bang!")。
您應該逐步重構單體應用程式,而不是通過大爆炸重寫。您逐漸添加新功能,並以微服務的形式創建現有功能的擴展 —— 以互補的形式修改單體應用,並且一同運行微服務和修改的單體。隨著時間推移,單體應用程式實現的功能量會縮小,直到它完全消失或變成另一個微服務。這種策略類似於在 70公裡/小時的高速公路上駕駛一輛汽車,這很具有挑戰性,但比嘗試大爆炸改寫的風險要小得多。
Martin Fowler 將這種應用現代化策略稱為殺手應用(Strangler Application)。這個名字來自於熱帶雨林中發現的葡萄樹(也稱為絞殺榕)。一棵葡萄樹生長在一棵樹上,以獲取森林冠層之上的陽光。有時,樹死了,留下一個樹形的騰。應用現代化也遵循相同的模式。我們將構建一個新的應用程式,包括了圍繞遺留應用的微服務(它將會慢慢縮小或者最終消亡)。
讓我們來看看能做到這點的不同策略。
7.2、策略一:停止挖掘
洞穴定律說到,每當您身處在一個洞穴中,您應該停止挖掘。當您的單體應用變得難以管理時,這是一個很好的建議。換句話說,您應該停止擴張,避免使單體變得更大。這意味著當您要實現新功能時,您不應該向單體添加更多的代碼。相反,這一策略的主要思想是將新代碼放在獨立的微服務中。
應用此方法後,系統架構如圖 7-1 所示。
除了新服務和傳統的單體,還有另外兩個組件。第一個是請求路由,它處理傳入的(HTTP)請求,類似於第二章中描述的 API 網關。路由向新服務發送與新功能相對應的請求。它將遺留的請求路由到單體。
另一個組件是粘合代碼,它將服務與單體集成。一個服務很少孤立存在,通常需要訪問單體的數據。位於單體、服務或兩者中的膠合代碼負責數據集成。該服務使用粘合代碼來讀取和寫入單體數據。
服務可以使用三種策略來訪問單體數據:
- 調用由單體提供的遠程 API
- 直接訪問單體資料庫
- 維護自己的數據副本,與單體資料庫同步
粘合代碼有時被稱為防護層(anti-corruption layer)。這是因為粘合代碼阻止了服務被遺留的單體領域模型的概念所污染,這些服務具有自己的原始領域模型。粘合代碼在兩種不同的模型之間轉換。防護層一詞首先出現於埃里克·埃文斯(Eric Evans)的必讀圖書《領域驅動設計》(Domain Driven Design)中,併在白皮書中進行了改進。開發一個防護層並不是一件簡單的事。但是,如果您想要從單體地獄中走出來,這是必不可少的步驟。
使用輕量級服務來實現新功能有幾個好處。它防止單體變得更加難以管理。該服務可以獨立於單體開發、部署和擴展。可讓您創建的每個新服務體驗到微服務架構的優勢。
然而,這種方法沒有解決單體問題。要解決這些問題,您需要分解單體。讓我們來看看這樣做的策略。
7.3、策略二:前後端分離
縮小單體應用的一個策略是從業務邏輯層和數據訪問層拆分出表現層。一個典型的企業應用由至少三種不同類型的組件組成:
- 表現層(Presentation Layer,PL) - 處理 HTTP 請求並實現(REST)API 或基於 HTML 的 Web UI 組件。在具有複雜用戶界面的應用中,表現層通常存在大量代碼。
- 業務邏輯層(Business Logic Layer,BLL) - 作為應用程式核心,實現業務規則的組件。
- 數據訪問層(Data Access Layer,DAL) - 訪問基礎架構組件的組件,如資料庫和消息代理。
一方面的表現邏輯和另一方的業務和數據訪問邏輯之間通常有一個完全的隔離。業務層具有由一個或多個門面組成的粗粒度 API,其封裝了業務邏輯組件。這個 API 是一個天然的邊界,您可以沿著該邊界將單體拆分成兩個較小的應用程式。一個應用程式包含表現層。另一個應用程式包含業務和數據訪問邏輯。分割後,表現邏輯應用程式對業務邏輯應用程式進行遠程調用。
重構之前和之後的架構如圖 7-2 所示。
以這種方式拆分單體有兩個主要優點。它使您能夠獨立於彼此開發、部署和擴展這兩個應用。特別是,它允許表現層開發人員在用戶界面上快速迭代,並且可以輕鬆執行 A/B 測試。這種方法的另一個優點是它暴露了可以被您開發的微服務調用的遠程 API。
然而,這一策略只是一個局部解決方案。兩個應用程式中的一個或兩個很可能是一個無法管理的單體。您需要使用第三種策略來消除剩餘的整體或單體。
7.4、策略三:提取服務
第三個重構策略是將龐大的現有模塊轉變為獨立的微服務。每次提取一個模塊並將其轉換成服務時,單體就會縮小。一旦您轉換了足夠的模塊,單體將不再是一個問題。或者它完全消失,或者變得足夠小,它就可以被當做一個服務看待。
7.4.1、優先將哪些模塊轉換為微服務
一個龐大而複雜的單體應用由幾十個或幾百個模塊組成,所有模塊都是提取的候選項。弄清楚要先轉換哪些模塊往往存在一定的挑戰。一個好的方法是從容易提取的幾個模塊開始。您將得到微服務的相關經驗,特別是在提取過程方面。之後,您應該提取那些能給您最大利益的模塊。
將模塊轉換為服務通常是耗時的。您想按照您將獲得的利益對模塊進行排列。提取頻繁更改的模塊通常是有益的。一旦將模塊轉換為服務,您就可以獨立於單體開發和部署,這將加快開發工作。
提取這些資源需求與單體的其他模塊有顯著不同的模塊也是有益的。例如,將有一個有記憶體資料庫的模塊轉換為服務是很有用的,這樣可以部署在具有大量記憶體的主機上,無論是裸機伺服器、虛擬機還是雲實例。同樣,提取實現了計算昂貴演算法的模塊也是值得的,因為該服務可以部署在具有大量 CPU 的主機上。通過將具有特定資源需求的模塊轉換為服務,您可以使應用程式更加容易、廉價地擴展。
當找到要提取的模塊時,尋找現有的粗粒度邊界(又稱為接縫)是有用的。它們使模塊轉成服務變得更容易和更連廉價。有關這種邊界的一個例子是一個僅通過非同步消息與應用程式的其他部分進行通信的模塊。將該模塊轉變為微服務相對比較廉價和簡單。
7.4.2、如何提取模塊
提取模塊的第一步是在模塊和單體之間定義一個粗粒度的介面。因為單體需要服務擁有的數據,它很可能是一個雙向 API,反之亦然。由於模塊和應用程式的其餘之間存在著複雜的依賴關係和細粒度的交互模式,因此實現這樣的 API 通常存在挑戰。由於領域模型類之間的眾多關聯,使用領域模型模式來實現的業務邏輯尤其具有挑戰性。您通常需要進行重大的代碼更改才能打破這些依賴。圖 7-3 展示了重構。
一旦實現了粗粒度的介面,您就可以將模塊變成獨立的服務。要做到這點,您必須編寫代碼以使單體和服務通過使用進程間通信(IPC)機制的 API 進行通信。圖 7-3 顯示了重構前、重構中和重構後的架構。
在此例中,模塊 Z 是要提取的候選模塊。其組件由模塊 X 使用,並且它使用了模塊 Y。第一個重構步驟是定義一對粗粒度的 API。第一個介面是一個使用模塊 X 來調用模塊 Z 的入站介面。第二個介面是一個使用模塊 Z 調用模塊 Y 的出站介面。
第二個重構步驟是將模塊轉換為一個獨立服務。入站和出站介面使用 IPC 機制的代碼來實現。您將很可能需要通過將 Module Z 與 Microservice Chassis 框架相結合來構建服務,該框架負責處理諸如服務發現之類的橫切點。
一旦您提取了一個模塊,您就可以獨立於單體和任何其他服務開發、部署和擴展其他服務。您甚至可以從頭開始重寫服務;在這種情況下,整合服務與單體的 API 代碼成為在兩個領域模型之間轉換的防護層。每次提取服務時,您都會朝微服務方向邁近一步。隨著時間的推移,單體將縮小,您將擁有越來越多的微服務。
7.5、總結
將現有應用程式遷移到微服務的過程是應用程式現代化的一種形式。您不應該從頭開始重寫您的應用來遷移到微服務。相反,您應該將應用程式逐漸重構為一組微服務。可以使用這三種策略:將新功能實現為微服務;從業務組件和數據訪問組件中分離出表現組件;將單體中的現有模塊轉換為服務。隨著時間推移,微服務的數量將會增長,您的開發團隊的靈活性和速度也同樣會增加。
微服務實戰:用 NGINX 馴服單體
by Floyd Smith
如本章所述,將單體轉換為微服務可能是一個緩慢而具有挑戰性的過程,但這同樣具有許多好處。使用 NGINX,您可以在實際開始轉換過程之前獲得微伺服器的一些優勢。
您可以通過將 NGINX 放在您現有的單體應用之前,以節省遷移微服務所花費的大量時間。以下簡要說明與微服務有關的好處:
- 更好地支持微服務 — 如第五章最後欄目所述,NGINX 和 NGINX Plus 具有利於開發基於微服務的應用的功能。當您開始重新設計單體應用時,由於 NGINX 的功能,您的微服務將執行得更好、更易於管理。
- 跨環境的功能抽象 — 從您管理的伺服器到各種公共雲、私有雲和混合雲上將功能遷移到 NGINX 作為反向代理伺服器可以減少部署在新的環境中的設施數量變化。這補充擴展了微服務所固有的靈活性。
- NGINX 微服務參考架構可用性 — 當您遷移到 NGINX 時,您可以借鑒 NGINX 微服務參考架構(MRA,Microservices Reference Architecture),以便在遷移到微服務之後定義應用程式的最終結構,並根據需要使用的 MRA 部分應用於您創建的每個新的微服務。
總而言之,實現NGINX作為您的轉型的第一步,將壓倒您的單片應用程式,使其更容易獲得微服務的所有優勢,併為您提供用於進行轉換的模型。您可以瞭解有關 MRA 的更多信息,並獲得 NGINX Plus 的免費試用版。
此系列全部譯文(完結)
https://github.com/oopsguy/microservices-from-design-to-deployment-chinese