iT邦幫忙

2025 iThome 鐵人賽

DAY 29
0
Software Development

微服務導入:從觀念到落地的架構實戰地圖系列 第 29

微服務導入 – Day 29 重構 – 分割單體式系統 II

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20251006/20178262gUiddE3Yzz.png

我們持續地探討「分割單體式系統」,有時候我們要提取的功能可能沒有像前一篇討論的那麼單純地可以從單體式的入口獲取其溝通的介面。如果,我們要提取的服務位於整個單體式系統的「深處」(也就是可能有很多其他功能會呼叫到這個部分),這時候我們可能需要花費更多的工夫才能完成移轉作業。


抽象層

此時,可以參考一個解決的模式,先將要提取的功能建立一個「抽象層」,這個做法比前一個做法暴力了許多,因為我們去改動了比較深層的功能模組 (就技術上來說,這應該放到最後再來處理。但,有時候業務就是來不及,想要盡快處理這部分的功能)。

你可以想像這跟我們在重構時提取 interface 有異曲同工之妙,有了 interface 之後我們就可以透過物件導向程式設計中「多型」的方式來切換不同的實作 (一個是既有的單體式系統、一個是新的微服務系統)。下圖說明著這個實際的範例,當我們要調整的功能被多個 Client (C1 and C2) 所使用時,將其移轉到微服務將造成 C1 以及 C2 運作的異常。

https://ithelp.ithome.com.tw/upload/images/20250925/20178262SjbIUtiNay.png

參照介面下的多型實作

所以,處理的方式就是為上述的 function 抽取出 interface 並讓 C1 及 C2 透過 interface 呼叫到需要的 function,如下圖所示。

https://ithelp.ithome.com.tw/upload/images/20250925/2017826257QkQfD7ML.png

可選擇的抽換實作

藉由這樣的概念逐步地將此功能萃取出來形成新的微服務。具體設計的程序如下:

  1. 為要替換的功能建立抽象介面
    首先,需要先定義我們本次要處理的功能範疇,並且找到其功能介面將其予以抽象化 (例如:重構中的提取介面)。有時候,我們要提取的功能因為沒有適當的模組化,如此一來可能會需要找到多個功能的「接縫」並進行抽象化的動作。

  2. 更改現有功能的客戶端以使用新的抽象介面
    當我們將程式的抽象介面建立起來之後,我們就需要讓本來呼叫「實作」的 Client 改為透過「抽象介面」來呼叫實作。現在很多 IDE 的重構功能可以協助我們快速地完成此作業,並且減少修改時漏掉某部分應用程式忘記調整 (這時候記得善用工具,避免少改到一些東西)。

  3. 以抽象介面來建立新的服務
    此時,我們將需要提取的功能在其他專案實現,並提供對應的 Web API 以提供此業務功能。既有系統則透過「多型」的方式,將實作的物件改為「Proxy」(它透過 HTTP Client 呼叫新實作的 Web API),以便將服務分拆出去。

所以,這時候我們在原有的程式中產生異動,所以這個動作是有風險的,要小心注意不要引起修改的 side effect (雖然風險應該很小,但只要有機會犯錯,就會有人做錯)!

https://ithelp.ithome.com.tw/upload/images/20250925/201782627wViBLYziY.png

  1. 切換抽象的實作 (在原有的單體中,可以是一個 Proxy 透過 API 來呼叫遠端的服務)

完成了上述的實作並且通過測試之後,我們就可以為使用到該實作的 Client 切換到新實作的端點,基本上透過這個方式我們可以很快地在「新」、「舊」兩個實作之間快速地進行切換。

  1. 停用舊的實作

在驗證新的實作穩定無誤後,可以讓舊的功能「停用」。但,在這裡要思考一件事情,在原本的文獻中這裡是建議「刪除」舊的實作。

為什麼要刪除舊的實作?(我們不是要保持隨時可以切換回來?)我的主張是在這個功能未出現「異動」之前,停用可以是一個選項。如果,功能有修改了 (這時候當然是改微服務這邊),你不會希望要改兩次吧!

所以,當有發生功能的質變時,「刪除」可能就成為我們不得不的工作了!


錯誤的概念

到了這邊,我們可以探討另外一個問題。很多時候我問客戶,為什麼你們想要做微服務?他們會回我希望系統可以跑得更快,效能更好!

我的思路是這樣,首先你發現改成微服務之後效能好像變好了,這通常是「幻覺」。但是,你量測出來的數據就是真的變快了!

基本上,這樣的專案通常跟設備採購綁在一起 (因為要採用 Kubernetes,所以順便買點硬體也是合理的)。這時候會出現,舊系統在幾年前的機器上跑,新系統在剛買的機器跑的情境。然後,我們測試出來效能比較好!(這應該是新機器效能本來就比舊機器好好幾倍吧)! 當然也有測試完比舊的效能還差的悲劇。

另外一點,從目前講到的「遷移」,手法都是多了幾層然後本來的本地呼叫改成 Web API 去呼叫。所以,從物理上來看經過更多的節點,然後你覺得改微服務會變得比較快?我是不相信啦!

但,不是說微服務就不好,不然不會有那麼多人趨之若鶩地套用這個架構。所以,一開始我們有提到要套微服務之前「三思」!特別是要弄清楚自己的「目標」。微服務是達成目標的手段,而不是我們真正的「目標」。


結語

寫著寫著到了鐵人賽的倒數第二篇,Day 30 就不談技術談心得,後續還有一部分是關於資料庫分割的議題,我會在鐵人賽後陸續釋出!


上一篇
微服務導入 – Day 28 重構 – 分割單體式系統 I
下一篇
微服務導入 – Day 30 鐵人賽的最後一天
系列文
微服務導入:從觀念到落地的架構實戰地圖30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言