iT邦幫忙

2024 iThome 鐵人賽

DAY 22
1
Software Development

微服務奇兵:30天Quarkus特訓營系列 第 22

開發概念建置-單體服務到微服務架構

  • 分享至 

  • xImage
  •  

老實說,前面討論的內容對於實際撰寫Quarkus代碼的關聯性並不強。不過,我個人認為,學習一個框架時,官方文件和示例代碼通常已經足夠完整,因此再編寫一些簡單的操作Lab,可能不會比官方文件更好。另一方面,前面提到的後端基礎知識,對於剛進入後端開發領域的工程師來說,其實非常重要。從我多年的工作經驗來看,能夠順暢闡述這些概念的工程師並不多,因為大多數開發工作都是站在巨人肩膀上,使用現有工具和框架完成任務。然而,如果想成為更資深的工程師,深入理解這些設計原理是不可或缺的。這將在設計系統時提供很大的幫助。

接下來,我們將專注於微服務架構這個話題。微服務在大型系統中是一個至關重要的設計模式,但要真正理解為何選擇這種架構,並非易事。我曾在知乎上看到過一個案例,講述了一個從單體架構逐步演進到微服務架構的過程,這對於剛開始設計單體應用的初學者來說,是一個很好理解為什麼要採用微服務的方式。

拍謝..閱讀之前,圖片我時間來不及修改,Ap Tier需改成 Web Tier,而Service Tier需改成Ap Tier。Web Tier一般定為有頁面的服務,而Ap Tier則是純服務。

從單體應用到微服務 - 一個線上學習平台的開發演進

在探討微服務架構之前,我們首先需要理解什麼不是微服務。通常與微服務相對的是單體應用(Monolithic Application),開發上會將所有功能都封裝在一個獨立單元的應用程式中。從單體應用到微服務並非一蹴可幾,而是一個漸進式的演進過程。接下來將以一個線上學習平台為例,詳細說明這個過程。

初始階段:單體應用

幾年前,工程師阿鵬和產品經理葉庭宇共同創立了一個線上學習平台新創公司。阿鵬負責後端開發,葉庭宇負責產品規劃和其他業務。當時線上教育市場還不飽和,只要基本功能實現就能獲得不錯的市場反應。因此他們的初始需求相對簡單:

  • 學習網站:
    • 會員系統(註冊、登入、權限管理)
    • 課程瀏覽和購買功能
    • 學習進度追蹤
  • 管理後台:
    • 會員管理
    • 課程管理
    • 學習數據管理

考慮到需求簡單,阿鵬選擇了使用 Spring Boot 框架快速開發了一個 Java Web 應用。資料庫使用 MySQL,前端則採用 Vue.js 框架。為了安全考量,管理後台被設計為一個獨立的應用。

https://ithelp.ithome.com.tw/upload/images/20240923/20115895NTeDxQtk36.png

阿鵬使用 Docker 容器化應用程式,並部署到 AWS EC2 實例上。網站很快上線,獲得了不錯的口碑。

業務擴張階段

隨著用戶數量快速增長,競爭對手也紛紛湧現。為了保持競爭力,阿鵬和葉庭宇決定擴充平台功能:

  • 實作行銷活動系統,支援各種優惠方案。
  • 開發行動應用程式(iOS 和 Android)。
  • 新增社群功能,如討論區和學習小組。
  • 加入即時串流直播課程功能。
  • 實作資料分析和個人化推薦系統。

為了應對這些新需求,阿鵬邀請了同學SI Yang加入團隊。SI Yang負責數據分析和行動端開發,阿鵬則專注於核心功能和效能優化。

由於開發時程緊迫,團隊沒有充分考慮架構設計,而是採取了一些權宜之計:

  • 在管理後台中增加了論壇管理、直播管理、數據分析功能與營銷活動管理。
  • 開發了獨立的行動應用程式,包含用戶功能、課程瀏覽、學習進度和離線學習功能。
  • 建立了獨立的直播系統,包含直播功能、互動問答和錄影回放。
  • 擴展了網站功能,增加了討論功能。

經過一段時間的密集開發,新功能陸續上線。此時的架構變成了這樣:

https://ithelp.ithome.com.tw/upload/images/20240923/20115895H9lZpJ51SK.png

image.png

雖然開發完了,但這個階段可能會面臨一些問題如下:

  1. 程式碼重複:網站和行動應用可能存在重複的業務邏輯。
  2. 資料一致性:不同應用間需要確保資料同步。
  3. 系統複雜度增加:隨著功能的增加,系統變得更加複雜,可能增加維護難度。
  4. 效能考量:所有應用共用同一個資料庫,在高負載時可能會成為效能瓶頸。
  5. 擴展性:雖然功能被分為不同模塊,但仍然共享資源,可能限制了獨立擴展的能力。

然而,現有的架構也展現了一些優點:

  1. 功能模組化:直播系統、行動應用等被設計為獨立模組,有利於功能開發和管理。
  2. 清晰的職責劃分:管理後台集中了各種管理功能,有助於統一管理。

微服務化改造

認識到現有架構的問題後,阿鵬和SI Yang決定進行微服務化改造。他們首先梳理了業務邏輯,將系統拆分為以下幾個核心服務:

  • 會員服務:負責用戶註冊、認證和授權。
  • 課程服務:管理課程信息和購買邏輯。
  • 學習進度服務:追踪和記錄用戶的學習狀態。
  • 社群服務:處理討論區和學習小組相關功能。
  • 資料分析服務:進行用戶行為分析和個人化推薦。

https://ithelp.ithome.com.tw/upload/images/20240923/2011589544VXYLdzCE.png

這個階段雖然將服務進行了拆分,但仍然使用共享的資料庫,因此仍存在一些問題:

  • 資料庫仍是單點故障風險。
  • 服務間邊界不清晰,容易出現跨服務的資料訪問。
  • 難以針對不同服務採用最適合的資料存儲方案。

為了解決這些問題,團隊決定進一步優化架構:

  • 資料庫拆分:每個服務使用獨立的資料庫,並根據需求選擇適合的資料庫類型。
  • 引入訊息佇列:使用 RabbitMQ 實現服務間的非同步通信,提高系統彈性。
  • 實現 API 網關:使用 Spring Cloud Gateway 統一管理外部請求。

最終的微服務架構如下:

https://ithelp.ithome.com.tw/upload/images/20240923/20115895kPXK9cEym9.png

在此架構中:

  1. 會員服務和課程服務使用 MySQL 資料庫。
  2. 學習進度服務選用 MongoDB,以便更靈活地存儲非結構化的學習數據。
  3. 社群服務使用 Redis 進行快取,提高讀取效能。
  4. 資料分析服務採用 Elasticsearch 作為資料倉儲,支援複雜的全文搜索和統計分析。

上述為一個簡單從業務面複雜度提高的微服物演進的示意,可以看到幾個重點

  1. 服務隔離:每個服務可以獨立開發、測試和部署。
  2. 技術異構:不同服務可以使用最適合的技術去實現。
  3. 擴展性提升:可以根據服務需求對特定服務進行水平擴展。
  4. 故障隔離:單一服務的問題不會影響整個系統。
  5. 團隊協作改善:明確的服務邊界有助於團隊分工和責任劃分。

但微服物運為複雜度高,需要更多的基礎建設管理,而網路延遲與資料一致性也是很大的問題! 最後是微服物需要更強大的監控工具與Trace Log,因為一個動作可能牽扯多個服務,沒有完整的Trace監控,很難發現問題出現在哪一個服務環節。

單體應用(Monolithic Application)與微服務架構 (Microservices Architecture)

單體應用(Monolithic Application)

單體應用是指將整個系統的所有功能集中在一個應用程式內,這是很多系統在初期發展時的常見做法。舉例來說,像是上述線上學習平台的會員註冊、課程購買、資料庫管理等等,這些功能全都被整合在同一個應用程式裡面。架構具有以下幾個特點:

  • 單一部署:所有的功能都放在同一個應用程式裡,當系統有任何更新時,必須重新部署整個應用程式。無論你是新增一個小功能,還是修改一個小錯誤,整個應用都需要重新啟動。
  • 資料庫共享:整個應用使用同一個資料庫。這樣的好處是,程式間可以輕鬆地分享資料,不用特別考慮數據同步的問題,但也容易成為效能瓶頸。
  • 開發簡單:單體應用對於初期開發來說比較直接,因為所有東西都集中在一個地方,所以不需要考慮太多系統間的溝通問題。這對小型團隊或新創公司來說,是非常快速且方便的選擇。
  • 測試和監控較簡單:單體應用的整體架構比較單一,因此在測試和監控方面也比較容易。不用擔心太多系統之間的通訊錯誤,測試工具可以針對整個應用進行一站式的檢查。

但是,當系統變得複雜,或是使用者數量暴增時,單體應用就會遇到一些問題:

  • 難以擴充:當用戶大量增加時,單體應用的唯一選擇是透過垂直擴充(增加伺服器資源),但這種方法有其物理和成本上的限制,難以長期支撐大規模成長。
  • 故障影響範圍大:因為所有功能都放在同一個應用程式中,所以如果某一個功能出現問題,有可能會導致整個應用當機,影響所有使用者。
  • 團隊開發的挑戰:隨著應用變得越來越大,維護變得困難。不同開發人員在同一個代碼庫上工作,容易造成代碼衝突和進度延誤。

微服務架構 (Microservices Architecture)

微服務的核心概念是將應用程式拆分為多個小而獨立的服務,每個服務都專注於某一特定的功能,比如會員系統、訂單系統、課程系統等。這樣每個服務都可以獨立開發、部署和管理。微服務架構有以下幾個特點:

  • 獨立部署:每個服務都是獨立的,當某個功能需要更新或修復時,你只需要重新部署該服務,不會影響其他功能的運作。這讓開發和上線變得更靈活。
  • 技術靈活:在微服務架構中,每個服務可以根據自己的需求使用不同的技術棧或資料庫。舉例來說,會員系統可以使用 MySQL 資料庫,而分析系統可能更適合使用 MongoDB。這讓技術選擇更加靈活,不會被單一技術限制住。
  • 高擴充性:微服務可以根據需求進行水平擴充。也就是說,如果某個服務(例如課程購買系統)需要更多資源,你可以只擴充該服務,而不需要擴充整個應用。
  • 故障隔離:由於服務之間是獨立的,所以當某個服務出現問題時,不會影響到其他服務。比如,討論區系統當掉了,課程購買和會員登入還是可以正常使用。

不過微服務架構也帶來不少挑戰:

  • 服務間的通訊:微服務需要通過網路進行彼此之間的溝通,這與單體應用內部的直接調用不同,會導致額外的延遲,並增加系統間的錯誤處理複雜度。
  • 資料一致性問題:每個微服務擁有自己的資料庫,當不同服務需要共享資料時,必須考慮如何保持資料的一致性。這在一些高要求的系統中,會變得很複雜。
  • 運維和監控:微服務的運維和監控比單體應用來得複雜。因為有多個服務同時運行,你需要更多工具來監控每個服務的健康狀況,並追蹤系統中的各種日誌和錯誤。

以下是簡易的表格整理

特性 單體應用 微服務架構
部署 一次部署整個應用 每個服務可獨立部署
擴展方式 垂直擴充 水平擴充,針對特定服務擴充
故障影響範圍 全系統可能受影響 故障只影響單一服務
開發複雜度 初期開發較簡單 需要額外處理服務間的溝通
資料管理 共用單一資料庫 每個服務有自己的資料庫
運維與監控 簡單集中 需要多重監控工具和追蹤系統

單體架構進化到微服務架構,是隨著系統規模和複雜度增加的一個自然演進。微服務架構適合那些希望能夠靈活擴展和管理,並且有較強技術能力支援的團隊或公司。

選擇考量

個人經驗上,建議不要為了微服物而去拆業務邏輯,其實單體也是有它的好處在,如果系統不是過於複雜且流量乘載也不是很巨量,其實單體反而是能快速滿足業務需求的選擇。具體參考依據考量如下

系統規模與功能模組數量

如果你的系統功能相對簡單,或是處於起步階段,單體架構會比較適合。單體架構容易開發、部署,並且可以快速交付,特別是當系統的功能比較有限時。當系統規模變大,功能模組越來越多時,維護單體架構的代價會變得更高,這時候再考慮微服務。

評估標準

  • 小規模且業務邏輯單一 → 適合單體應用
  • 功能模組多且業務邏輯複雜 → 考慮微服務

系統的擴展性需求

微服務架構適合用在需要高擴展性的系統中。舉例來說,如果系統某些部分(如登入系統或訂單處理系統)會因為使用量增加而需要更高的負載處理能力,微服務架構允許單獨擴展這些熱門服務,而不需要擴展整個應用。相比之下,單體應用的擴展方式較為局限,通常是透過垂直擴展(增加伺服器資源)來提高效能,但這樣很快會遇到物理限制。

評估標準

  • 低負載,服務不需要大規模擴展 → 單體應用
  • 高負載或流量突增,且需要動態擴展 → 微服務

部署頻率與靈活性

如果你應用需要頻繁地更新功能修復錯誤或進行版本迭代,微服務架構能夠提高部署靈活性,因為可以只更新需要改動的那部分服務,不需要重新部署整個應用。

評估標準

  • 變更不頻繁,部署週期長 → 單體應用
  • 頻繁更新,需要快速發布 → 微服務

系統容錯與隔離需求

微服務架構能夠實現更好的錯誤隔離。如果系統中的某個服務發生故障,不會影響到其他不相依業務羅及的服務正常運行。而在單體應用中,因為所有的功能都集中在一起,如果一個模組出現問題,直接噴Try Cache,可能會導致整個系統無法使用。

評估標準

  • 服務容錯要求不高,允許系統局部錯誤影響全系統 → 單體應用
  • 服務容錯要求高,要求服務隔離以防故障蔓延 → 微服務

最後稍微提一下,有些語言會有相關的微服物框架可以直接使用, .NET Core最有名的叫Dapr (Distributed Application Runtime),有興趣可以去玩玩。


上一篇
開發概念建置:CIDR表示格式(重要)
下一篇
開發觀念建置-關於身分識別授權流程
系列文
微服務奇兵:30天Quarkus特訓營30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言