微服務從設計到部署(七)重構單體為微服務


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 所示。

圖 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 所示。

圖 7-2、重構現有的應用程序

以這種方式拆分單體有兩個主要優點。它使您能夠獨立於彼此開發、部署和擴展這兩個應用。特別是,它允許表現層開發人員在用戶界面上快速迭代,並且可以輕松執行 A/B 測試。這種方法的另一個優點是它暴露了可以被您開發的微服務調用的遠程 API。

然而,這一策略只是一個局部解決方案。兩個應用程序中的一個或兩個很可能是一個無法管理的單體。您需要使用第三種策略來消除剩余的整體或單體。

7.4、策略三:提取服務

第三個重構策略是將龐大的現有模塊轉變為獨立的微服務。每次提取一個模塊並將其轉換成服務時,單體就會縮小。一旦您轉換了足夠的模塊,單體將不再是一個問題。或者它完全消失,或者變得足夠小,它就可以被當做一個服務看待。

7.4.1、優先將哪些模塊轉換為微服務

一個龐大而復雜的單體應用由幾十個或幾百個模塊組成,所有模塊都是提取的候選項。弄清楚要先轉換哪些模塊往往存在一定的挑戰。一個好的方法是從容易提取的幾個模塊開始。您將得到微服務的相關經驗,特別是在提取過程方面。之后,您應該提取那些能給您最大利益的模塊。

將模塊轉換為服務通常是耗時的。您想按照您將獲得的利益對模塊進行排列。提取頻繁更改的模塊通常是有益的。一旦將模塊轉換為服務,您就可以獨立於單體開發和部署,這將加快開發工作。

提取這些資源需求與單體的其他模塊有顯著不同的模塊也是有益的。例如,將有一個有內存數據庫的模塊轉換為服務是很有用的,這樣可以部署在具有大量內存的主機上,無論是裸機服務器、虛擬機還是雲實例。同樣,提取實現了計算昂貴算法的模塊也是值得的,因為該服務可以部署在具有大量 CPU 的主機上。通過將具有特定資源需求的模塊轉換為服務,您可以使應用程序更加容易、廉價地擴展。

當找到要提取的模塊時,尋找現有的粗粒度邊界(又稱為接縫)是有用的。它們使模塊轉成服務變得更容易和更連廉價。有關這種邊界的一個例子是一個僅通過異步消息與應用程序的其他部分進行通信的模塊。將該模塊轉變為微服務相對比較廉價和簡單。

7.4.2、如何提取模塊

提取模塊的第一步是在模塊和單體之間定義一個粗粒度的接口。因為單體需要服務擁有的數據,它很可能是一個雙向 API,反之亦然。由於模塊和應用程序的其余之間存在着復雜的依賴關系和細粒度的交互模式,因此實現這樣的 API 通常存在挑戰。由於領域模型類之間的眾多關聯,使用領域模型模式來實現的業務邏輯尤其具有挑戰性。您通常需要進行重大的代碼更改才能打破這些依賴。圖 7-3 展示了重構。

圖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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM