從單體遷移到微服務的十二種方法

banq發表於2022-07-15

你的團隊決定是時候擺脫那個舊的、笨重的單體了,它執行得很好,但是單體已經變得如此之大,以至於你花費更多的精力來維護它而不是新增功能。這裡有 12 個技巧,可幫助您儘可能順利地過渡到微服務

#1 確保你知道你在做什麼
重寫從來都不是一件容易的事,但是從單體應用到微服務,你改變的不僅僅是編碼方式;你正在改變公司的運營模式。你不僅需要學習一個新的、更復雜的技術棧,管理層還需要調整工作文化,將人員重組為更小的跨職能團隊
如何最好地重組團隊和公司是值得單獨發帖的主題。在本文中,我想重點介紹遷移的技術方面。
首先,在開始之前儘可能多地研究採用微服務所涉及的權衡是很重要的。您希望絕對確定微服務(而不是其他替代解決方案,例如模組化單體)是適合您的解決方案。
首先學習有關微服務架構的所有知識,並檢視一些示例專案以瞭解其工作原理。這裡有些例子

#2 制定計劃
拆除單體應用需要大量準備工作,因為舊系統必須在過渡期間保持執行。
遷移步驟可以透過工單進行跟蹤,並像任何其他任務一樣在每個 sprint 中進行。這不僅有助於獲得動力(實際上有朝一日實現遷移),而且讓業務所有者瞭解團隊如何計劃實施如此大的變化。
在計劃期間,您必須:

  • 解開單體內部的依賴關係。
  • 確定所需的微服務。
  • 為微服務設計資料模型。
  • 開發一種在單體和微服務資料庫之間遷移和同步資料的方法。
  • 設計 API 並計劃向後相容。
  • 捕獲單體應用的基線效能。
  • 為新系統的可用性和效能設定目標。

除非您從一個相當簡單的單體架構遷移,否則您將需要高階技術,例如領域驅動設計 (DDD)。

#3 把所有東西都放在一個 monorepo 中
當你分解單體時,大量程式碼將從單體中移出並轉移到新的微服務中。monorepo幫助您跟蹤這些型別的更改。此外,將所有東西放在一個地方可以幫助您更快地從故障中恢復。
您的單體應用很可能已經包含在一個儲存庫中。因此,只需為微服務建立新資料夾即可。

從單體遷移到微服務的十二種方法

#4 使用共享 CI 管道
在開發過程中,您不僅會不斷推出新的微服務,還會重新部署單體應用。這個過程越快、越輕鬆,你的進步就越快。設定持續整合和交付(CI/CD) 以自動測試和部署程式碼。
如果您使用 monorepo 進行開發,則必須牢記以下幾點:


配置測試報告以快速發現和排除故障。

#5 確保你有足夠的測試
當我們確定程式碼沒有迴歸時,重構會更加令人滿意和有效。自動化測試讓您有信心持續釋出單體更新。
一個很好的起點是測試金字塔。您將需要大量的單元測試、一些整合測試和一些驗收測試

從單體遷移到微服務的十二種方法

旨在像在持續整合管道中一樣經常在本地開發機器上執行測試。

#6 安裝 API 閘道器或 HTTP 反向代理
隨著微服務的部署,您必須隔離傳入流量。遷移的功能由新服務提供,而尚未準備好的功能由單體提供。
有幾種路由請求的方法,具體取決於它們的性質:

  • API 閘道器允許您根據經過身份驗證的使用者、cookie、功能標誌或 URI 模式等條件轉發 API 呼叫。
  • HTTP 反向代理的作用相同,但針對的是 HTTP 請求。在大多數情況下,單體實現了 UI,因此大多數流量都會流向那裡,至少一開始是這樣。

從單體遷移到微服務的十二種方法
使用 API 閘道器和 HTTP 反向代理將請求路由到適當的端點。您可以在非常細粒度的級別上在單體和微服務之間切換。
遷移完成後,閘道器和代理將保留——它們是任何微服務應用程式的標準元件,因為它們提供轉發和負載平衡。如果服務出現故障,它們還可以充當斷路器。

#7 考慮一體成型的模式
好的,這僅適用於您計劃將容器或 Kubernetes 用於微服務的情況。在這種情況下,容器化可以幫助您實現基礎架構的同質化。一體式整體模式包括在 Docker 等容器內執行整體。
如果您以前從未使用過容器,那麼這是熟悉該技術的好機會。這樣一來,您就離了解 Kubernetes 更近了一步。要學習的東西很多,所以要為陡峭的學習曲線做好計劃:

  • 瞭解 Docker 和容器。
  • 在容器中執行你的單體應用。
  • 在容器中開發和執行您的微服務。
  • 完成遷移並掌握容器後,瞭解 Kubernetes。
  • 隨著工作的進展,您可以擴充套件微服務並逐漸將流量轉移到它們。

從單體遷移到微服務的十二種方法
容器化單體應用是標準化部署的一種方式,也是學習 Kubernetes 的絕佳第一步。

#8 熱身於變化
習慣微服務需要時間,所以最好從小處著手,為新正規化做好準備。留出足夠的時間讓每個人都進入正確的心態、提高技能並從錯誤中吸取教訓,而不會受到最後期限的壓力。
在這些初步的初步步驟中,您將學到很多關於分散式計算的知識。您必須處理雲 SLA,為您自己的服務設定 SLA,實施監控和警報,定義跨團隊通訊的渠道,並決定部署策略。
選擇一些容易開始的東西,比如與單體架構的其餘部分幾乎沒有重疊的邊緣服務。例如,您可以先構建身份驗證微服務並路由登入請求。

從單體遷移到微服務的十二種方法
選擇一些容易開始的東西,比如簡單的邊緣服務。

#9 使用功能標誌

功能標誌是一種無需重新部署即可更改系統功能的軟體技術。您可以使用功能標誌在遷移時開啟和關閉部分單體應用、試驗替代配置或執行 A/B 測試。
啟用功能標誌的遷移的典型工作流程是:

  • 確定要遷移到微服務的單體功能的一部分。
  • 用功能標誌包裝功能。重新部署單體。
  • 構建和部署微服務。
  • 測試微服務。
  • 一旦滿意,透過關閉該功能來禁用單體應用上的該功能。
  • 重複直到遷移完成。

因為功能標誌允許我們將非活動程式碼部署到生產環境並隨時切換它,所以我們可以將功能釋出與實際部署分離。這為開發人員提供了極大的靈活性和控制力。

#10 模組化單體
如果你的單體應用是一堆程式碼,那麼一旦遷移完成,你很可能會得到一堆分散式程式碼。就像在全面翻新之前收拾房子一樣,模組化整體結構是必要的準備步驟。
模組化單體是一種軟體開發模式,由獨立且可互換的垂直堆疊模組組成。與模組化單體相反的是經典的 N 層或分層單體。

從單體遷移到微服務的十二種方法
分層的單體很難解開——程式碼往往有太多的依賴關係(有時是迴圈的),使得更改難以實現。
模組化單體是微服務的下一個最佳選擇,也是邁向微服務的墊腳石。規則是模組只能透過公共 API 進行通訊,預設情況下一切都是私有的。因此,程式碼的交織更少,關係易於識別,依賴關係清晰。

從單體遷移到微服務的十二種方法
有兩種模式可以幫助你重構單體:Strangler Fig 和 Anticorruption Layer。

Strangler Fig
Strangler Fig模式中,我們將整體重構從邊緣到中心。我們在邊緣咀嚼,逐步重寫孤立的功能,直到整體重做。
模組之間的呼叫透過“扼殺外觀”進行路由,該外觀模擬和解釋遺留程式碼的輸入和輸出。一點一點地,模組被建立並慢慢取代舊的單體。​

從單體遷移到微服務的十二種方法
單體是一次模組化的。最終,舊的巨石消失了,取而代之的是新的。

反腐敗層模式
您會發現,在某些情況下,當您重構整體時,一個模組中的更改會傳播到其他模組。為了解決這個問題,您可以在快速變化的模組之間建立一個轉換層。此防腐敗層可防止一個模組中的更改影響其餘模組。

從單體遷移到微服務的十二種方法
反腐敗層透過轉換模組和單體之間的呼叫來防止更改傳播。​

#11 解耦資料
超級強大的微服務使您能夠隨時部署任何微服務,而與其他微服務幾乎沒有協調。這就是為什麼必須不惜一切代價避免資料耦合的原因,因為它會在服務之間產生依賴關係。每個微服務都必須有一個私有且獨立的資料庫。
意識到您必須將單體應用的共享資料庫非規範化為(通常是冗餘的)較小的資料庫,這可能會令人震驚。但資料區域性性最終將讓微服務自主工作。

從單體遷移到微服務的十二種方法
上圖是將資料解耦到獨立的資料庫中。
解耦後,您必須安裝機制以在轉換過程中保持新舊資料同步。例如,您可以設定資料映象服務或更改程式碼,以便將事務寫入兩組資料庫。

從單體遷移到微服務的十二種方法
在開發過程中使用資料複製來保持表同步。

#12 新增可觀察性
新系統必須比舊系統更快、效能更高、可擴充套件性更強。否則,為什麼要用微服務呢?
您需要一個基線來比較舊的和新的。在開始遷移之前,請確保您有良好的指標和日誌可用。安裝一些集中式日誌記錄和監控服務可能是一個好主意,因為它是任何微服務應用程式可觀察性的關鍵元件。

從單體遷移到微服務的十二種方法


結論
微服務之旅絕非易事。但我希望透過這些提示,您可以節省一些時間和挫敗感。
請記住以小增量進行迭代,利用 CI/CD 來保證單體應用程式正在接受迴歸測試,並將所有內容儲存在一個儲存庫中,以便在出現問題時隨時回退。


banq​注:該文以小增量小心翼翼謹慎的方式重構原來系統,但是沒有充分認識到單體與微服務是兩種完全不同風格的架構,是南轅北轍的戰略方向性區別,​為什麼?因為微服務比單體​切分更小,如何小?是依據DDD有界上下文去切分的,而上下文需要從戰略大背景大景觀圖下考慮的,所以,是團隊認知上對業務理解巨大升遷,變革,這種忽然開朗的結果往往是方向上南北大區別,而摸著石頭過河的小增量重構只適合方向未定或方向大概沒有偏向情況下​。這種重構是聽上去很有道理,但是完全不實用,從單體到微服務的遷移,不只是技術上的變化,還有業務知識的進步,更可能是團隊徹底改變​。​新團隊能忍受在舊思維舊單體下委曲求全嗎?

相關文章