從單體應用轉換到微服務架構並非一蹴可幾,需要仔細規劃和逐步實施。優先考量高頻使用、效能瓶頸和技術替代方案等因素,選擇合適的模組進行重構。過程中需定義清晰的微服務邊界,確保每個微服務專注於單一功能。技術選型方面,可以根據特定領域的需求選擇合適的程式語言和資料函式庫,實作多語言程式設計和多樣化持久化。程式碼重構時,應著重於重新封裝現有程式碼並暴露必要的 API,而非新增功能。資料遷移則需根據資料來源和目標資料函式庫制定相應的策略。版本控制和程式碼管理也至關重要,每個微服務都應視為獨立專案,並遵循既定的版本控制流程。在轉換過程中,可以採用混合方法,逐步將單體應用拆解成微服務,並根據微服務標準進行持續最佳化。Docker 容器技術的興起,為微服務架構的佈署和擴充套件提供了有效的解決方案。相較於虛擬機器,容器更加輕量級,資源利用率更高,且易於移動和分享。容器技術透過將應用程式及其依賴項封裝在一起,實作了環境一致性和佈署效率的提升。Docker 的輕量級設計、高效率隔離和資源利用率優勢,使其成為微服務佈署的理想選擇。隨著雲端原生技術的發展,容器技術將扮演越來越重要的角色,Kubernetes 等容器協調平台的應用也將更加普及。

從單體應用轉換為微服務

大多數新建立微服務應用程式的一些最佳實踐也適用於從現有單體應用轉換為微服務架構。然而在轉換過程中也有一些額外指引可遵循:

分步轉換策略

雖然聽起來轉換整個單體應用程式為完全根據微服務架構可能是正確的做法,但在某些情況下這可能是低效甚至代價昂貴。可能最終會導致從頭開始寫應用程式。

正確轉換策略需要分步進行(如圖4.4所示)。首先要問的是:從當前單體應用開始轉換?如果應用很老且取出程式碼片段非常耗時且困難(即高度內聚),那麼最好重新開始。如果部分程式碼能夠快速停用且技術架構不完全過時,則最好從重建元件為微服務開始並替換舊程式碼。

  graph TD
    A[單體應用] --> B[識別可分離模組]
    B --> C[重構模組為微服務]
    C --> D[逐步替換舊模組]
    D --> E[最終轉換為全面微服務]

此圖示說明

此圖示展示了從單體應用轉換為全面微服務架構的基本步驟:

  1. 識別可分離模組:首先要識別出哪些模組可以被獨立出來重構。
  2. 重構模組為微服務:將可分離模組重構為獨立執行且可擴充套件的微服務。
  3. 逐步替換舊模組:逐步替換原有單體應用中的舊模組。
  4. 最終轉換為全面微服務:完成所有模組替換後轉換為全面根據微服務架構應用。

透過這樣逐步分離與重構單體應用中的各個模組進行轉換為微領域專注於開發和維護完善及元件化單體應用所需流程進而簡化整體系統並提升其靈活性與可維護性同時符合當今開發趨勢技術標準及營運高效所需條件減少開發過程中所產生複雜問題與提升專案開發週期內各階段從設計測試佈署執行等方面整體效率增強應對現代複雜營運環境中的需求並結合企業自身實際情況及資源來制定精準合理轉換計劃與具體實施方案提升系統整體價值與競爭力達到目標效果

微服務遷移與實施

在微服務架構中,遷移及實施的過程需要仔細規劃,特別是決定哪些元件應該首先遷移或是否應該遷移。這裡我們可以參考「微服務標準」,這是一組用來選擇和優先處理應該遷移為微服務的功能的規則。這些標準會根據組織在當下的需求來判斷是否適合將現有的單體應用元件轉換為微服務。

微服務標準

在遷移過程中,以下是一些可以考慮的最佳實踐,這些可以作為微服務標準:

機能擴充套件(Scale)

首先要確定哪些功能是高頻使用的。高頻使用的服務或應用功能應該優先轉換為微服務。記住,每個微服務只執行一個明確定義的服務。按照這個原則來分割應用程式。

效能最佳化(Performance)

有些元件可能效能不佳,而其他替代方案則可以輕易取代它們。例如,可能有一個開源外掛可供使用,或者你可能想從頭開始構建一個服務。關鍵是要考慮到微服務的邊界。只要設計你的微服務只執行一個功能並且做得很好,這就是好的設計。決定邊界通常會比較困難,但隨著實踐經驗的增加,這會變得更容易。另一種看待微服務邊界的方式是:你應該能夠在幾週內重寫整個微服務(如果需要),而不是花幾個月的時間重寫。

技術替代方案或多語言程式設計(Polyglot Programming)

可以使用特定領域的程式語言來處理特定問題。這特別適用於那些過去曾經收到很多增強請求且未來也會繼續收到請求的元件。如果你認為某個元件的實作可以透過新語言或市場上新出現的能力來簡化,並且未來的維護和更新也會變得更容易,那麼現在就應該處理這些變更。此外,你可能會發現另一種語言提供了比現在使用的語言更簡單的平行抽象化方式。你可以利用這種新語言來編寫某些微服務,而其他的應用程式部分仍然可以使用不同的語言。同樣地,如果你希望某些微服務特別快速,可能會選擇用C語言編寫以獲得最大收益而不是使用其他高階語言。

儲存替代方案或多樣化持久化(Polyglot Persistence)

隨著大資料技術的興起,某些應用程式元件可能會透過使用NoSQL資料函式庫而不是關聯式資料函式庫來提供更大價值。如果應用程式中的任何這類別元件可以從這種替代方案中受益,那麼現在就應該考慮切換到NoSQL。

修改請求

在任何軟體生命週期中追蹤新增強請求或變更是很重要的一環。那些有更多變更請求的功能可能適合轉換為微服務,因為它們減少了構建和佈署時間。分離這些服務可減少構建時間,因為不必構建整個應用程式,只需要構建改變過的微服務,這樣也增加了其餘應用程式的可用時間。

佈署

總是有一些部份會增加佈署複雜度。在單體應用中,即使某個特定功能沒有被修改過,你仍然需要經歷完整的構建和佈署流程。如果存在這樣的情況,則有必要剝離出這些片段並將它們替換為微服務,以縮短其餘單體應用程式的整體佈署時間。

輔助服務

在大多數應用中,核心或主要服務依賴於一些輔助服務。如果這些輔助功能不可用,則會影響核心服務的可用性。例如,在本文第11章中討論到的一個幫助台應用中,“票證系統”依賴於“產品目錄”系統。“產品目錄”系統不可用時,“票證系統”就無法提交票證。“產品目錄”系統不可用時,“票證系統”就無法提交票證。”如果存在這樣情況,則輔助系統需要轉換為可高用性微服務來更好地支援核心服務。

  graph TD;
    A[核心/主要服務] --> B[輔助/輔助功能];
    B --> C[可高用性];
    C --> D[更好地支援核心/主要應用];

此圖示展示了核心/主要應用與輔助功能之間的關係及其轉換為高用性微服務以更好支援核心/主要應用

內容解密:
  • 擴充套件需求(Scale):必須確定哪些功能是高頻使用者才有必要進行轉換為微服務。
  • 效能最佳化(Performance):處理效能不佳元件並採取替代方案如開源外掛或從頭開始構建。
  • 多語言程式設計(Polyglot Programming):利用特定領域語言或新技術進行維護和更新。
  • 多樣化持久化(Polyglot Persistence):根據大資料技術切換NoSQL資料函式庫。
  • 修改請求:針對有高數量修改請求之功能進行轉換。
  • 佈署複雜度降低:將增加佈署複雜度之部分轉為微服務以提升整體效率。
  • 輔助系統:將影響核心/主要系統之輔助系統轉為高可針對以提升整體可用性

微服務的遷移與實施

在微服務架構的遷移過程中,根據應用程式的需求,可能需要將大部分服務轉換為微服務。這裡的目的是簡化轉換過程,讓你能夠優先排序並定義遷移到微服務架構的路線圖。

重構服務

一旦你確定了要轉換為微服務的功能,就該開始重構選定的服務,遵循之前章節中的最佳實踐。以下是需要注意的幾個方面:

微服務定義

對於每個功能,定義適當的微服務,這包括通訊機制(API)、技術定義等。考慮你現有功能使用的資料,或者為微服務建立和規劃相應的資料策略。如果原本功能依賴於重型資料函式庫如 Oracle,是否有必要轉換為 MySQL?確定如何管理資料關係。最後,將每個微服務執行為獨立的應用程式。

重構程式碼

如果不更改程式語言,可能會重用一些程式碼。考慮儲存/資料函式庫層——分享還是專用、記憶體還是外部。這裡的目標不是新增新功能,除非必要,而是重新封裝現有程式碼並暴露所需的 API。

版本控制

在開始編寫程式碼之前,決定原始碼控制和版本控制機制,並確保遵守這些標準。每個微服務應該是一個獨立的專案並作為獨立應用程式佈署。

資料遷移

如果決定建立新資料函式庫,也需要遷移舊資料。這通常透過編寫簡單的 SQL 指令碼來處理,取決於源和目的地。

單體程式碼

最初,保留單體應用中的現有程式碼以防需要回復。你可以更新其他程式碼以使用新微服務,或者更好地將應用流量分割(如果可能),以利用單體和微服務版本。這提供了測試和監控效能的機會。一旦確認無誤,可以將所有流量轉移到微服務並停用或移除舊程式碼。

混合方法

當開發全新應用時,開發者可以直接遵循微服務架構原則和藍圖來構建軟體應用程式。開發者有時會採用混合方法,部分應用為微服務,其餘部分根據某些標準遵循標準 SOA/MVC 概念。這意味著並非應用中的所有元件都符合微服務標準。

如前所述,「玄貓」認為微服務提供了很大靈活性,但這種靈活性也帶來了一些成本。混合方法是平衡靈活性和成本方面,理解隨著時間推移,元件可以從單體部分分離並根據需求轉換為微服務。關鍵是在轉型過程中保持兩種方法和微服務標準。


Docker 容器

這一章節涵蓋了另一個流行主題:Docker 容器。「玄貓」認為隨著公司擴充套件,「玄貓」經常面臨因軟體佈署和可擴充套件性問題而產生的挑戰。「玄貓」認為隨著使用者和功能的增加,「玄貓」經常看到軟體變得複雜,「玄貓」認為佈署和可擴充套件性問題開始成為噩夢。「玄貓」認為在第一章「微服務介紹」中討論過,「玄貓」認為微服務可以透過簡化架構來解決開發挑戰,「玄貓」認為但同時也將營運複雜性(包括佈署和可擴充套件性)推向下游。「玄貓」認為進一步複雜化挑戰的是,「玄貓」認為根據微服務架構,「玄貓」經常需要主機、佈署和管理數千個服務。「玄貓」認為這就是容器登上舞台解決大部分問題的時候。

Docker 是一個開源技術專案,「玄貓」認為它解決了佈署和可擴充套件性問題,「玄貓」認為它透過將應用與基礎設施依賴項隔離來解決問題。「玄貓」認為它使用容器來包含應用及其所有依賴項,「玄貓」認為包括目錄結構、後設資料、程式空間、埠集等。「玄貓」認為「玄貓」可以在所有機器和環境中以相同方式執行已封裝的應用程式。「玄貓」認為這就是 Docker 變得有趣且迅速崛起的原因。「玄貓」認為你可能會想到虛擬機器(VM)也是如此做到這點。「玄貓」認為瞭解它們之間區別,「玄貓」來看看它們如何不同。

graph TD
    A[Docker] --> B[包含應用及其依賴項]
    B --> C[目錄結構]
    B --> D[後設資料]
    B --> E[程式空間]
    B --> F[埠集]

    G[虛擬機器(VM)] --> H[包含作業系統]
    H --> I[完整作業系統核心]
    H --> J[與宿主機隔離]

此圖示說明 Docker 和 VM 的區別

  • Docker:包含應用及其所有依賴項,包括目錄結構、後設資料、程式空間、埠集等。
  • 虛擬機器(VM):包含完整作業系統核心與宿主機隔離。

「此圖示」說明 Docker 和 VM 的區別,「此圖示」顯示 Docker 包含應用及其所有依賴項,「此圖示」顯示 VM 包含完整作業系統核心與宿主機隔離。

容器化技術的興起與應用

虛擬機器的概念與發展

虛擬機器(Virtual Machines, VMs)是一種自成體系的系統,包含從作業系統(Guest OS)到應用程式環境及應用程式本身的所有元素。透過在主機作業系統之上安裝一層稱為「Hypervisor」的軟體,可以在單一物理機器上安裝多個虛擬機器。這種Hypervisor,也稱為Type 2 Hypervisor,會充當硬體的代理,使得Guest OS以為自己在獨立的硬體上執行。而Type 1 Hypervisor則直接執行在硬體之上,無需主機作業系統,被稱為裸機Hypervisor。

虛擬機器的概念迅速普及,並且創造了一個價值數十億美元的產業。這主要是因為虛擬化技術允許企業充分利用可用的硬體資源。在虛擬化技術出現之前,公司通常會為每個應用程式組態專用的伺服器。雖然在開發環境中分享這些資源並沒有問題,但在生產環境中,為了確保最佳實踐,所有伺服器資源都會專門分配給單一應用程式。這導致了資源浪費,因為應用程式並不總是能夠全面利用所有資源。隨著時間的推移,伺服器和機器變得越來越強大,虛擬化提供了一個巨大的機會,能夠更有效地利用伺服器資源,同時提供應用程式隔離,使得每個應用程式都能在獨立的虛擬機器上執行自己的作業系統。這種模式取得了巨大的成功,實際上也是雲端計算起源的基礎。

虛擬機器的優勢

虛擬機器提供了許多優勢:

  • 效率:虛擬機器看起來和運作起來就像一台獨立的電腦。關鍵優勢在於資源使用效率高且從安全形度來看具有隔離性。
  • 靈活性:資源可以根據需求分配。CPU、記憶體等都可以根據初始需求分配,並在需要時進行自動調整。這種概念也被稱為彈性。
  • 備份與還原:虛擬機器可以儲存為單一檔案,方便備份到其他來源。必要時可以輕鬆還原。
  • 作業系統自由度:不同的Guest OS可以在同一個Hypervisor上執行。因此,可以支援多種應用程式滿足其特定的作業系統需求。
  • 效能與移動性:將虛擬機器從一台主機移動到另一台主機非常簡單。大多數Hypervisor都支援這種自動功能。VMware等成功的虛擬化軟體提供了名為VMotion的功能,允許即時遷移正在執行的虛擬機器。

虛擬機器的挑戰

儘管虛擬機器有許多優勢,但也存在一些挑戰:

  • 分享困難:由於檔案過大,移動和分享虛擬機器透過廣域網路(WAN)需要很長時間。
  • 可攜性:當開發者將虛擬機器傳送給其他開發者時,隨著時間推移應用程式、資料函式庫和環境可能會發生變化。這意味著開發者必須再次傳送整個VM檔案,而無法進行差異檢查(diff)。
  • 效能開銷:應用程式與其Guest OS進行通訊,後者再透過Hypervisor與主機作業系統進行通訊以控制硬體以完成請求。這樣層層轉譯會導致顯著的效能開銷。
  • 資源利用效率:雖然虛擬化比在單一作業系統上的物理機器有更好的資源使用效率,但由於複製多個作業系統和Hypervisor仍然存在浪費。

容器技術的引入

容器技術提供了一種替代方案來解決這些問題。容器也提供了一個虛擬環境來封裝應用程式程式、中繼資料和檔案系統——所有應用程式執行所需的元素。然而不同於虛擬機器需要獨立的作業系統,容器只是UNIX程式的一種包裝方式,直接與核心溝通以請求和使用資源。

此圖示展示了容器技術架構

  graph TD
    A[容器 1] --> B[Application 1]
    C[容器 2] --> D[Application 2]
    E[核心] --> F[Host OS]
    A --> E
    C --> E

此圖示展示了容器技術架構

玄貓認為容器技術對於現代軟體開發和佈署至關重要。以下是對容器技術的一些深入分析:

容器技術如何解決問題?

容器技術解決了許多虛擬機器面臨的挑戰:

  • 輕量級設計:容器不需要獨立的作業系統,它們僅僅是UNIX程式的一種包裝方式。因此它們更加輕量且易於移動和分享。
  • 高效率隔離:容器利用Linux核心中的控制組(cgroups)和名稱空間(namespaces)來實作資源隔離功能。
  • 更高效率地利用資源:由於容器不需要額外作業系統及相關開銷,因此可以在相同硬體下執行更多容器。

內容解密:

  1. 輕量級設計

    • 容器與虛擬機器不同之處在於它們不需要獨立的作業系統(OS)。由於缺乏OS層面所帶來的負荷及複雜度管理問題(例如作業系統更新、安全修補),所以容易維護且快速佈署。
    • 內建於Linux核心中的control groups (cgroups) 和 namespaces 提供了對資源與程式名稱空間隔離而實作。
  2. 高效率隔離

    • cgroups 控制每個容器使用哪些計算、網路以及儲存等資源;namespaces 則是透過提供獨立名稱空間確保不同程式之間沒有互相影響。
  3. 高效利用硬體資源

    • 在同樣規格硬體下佈署容器比佈署VMs節省更多計算與儲存資源;因此提升整體運算效率。

未來趨勢

隨著雲端計算和微服務架構日益普及,容器技術將成為軟體開發和佈署中的不可或缺的一部分。未來可能會看到更多企業採用容器平台如Docker和Kubernetes來管理其應用程式佈署和維運工作流程。