跳轉到

Introduction to Microservice

單體地獄

成功的應用有一個趨勢,隨著時間推移而變得越來越臃腫。你的開發團隊在每個衝刺階段都要實現更多的用戶需求,這意味著需要添加許多行代碼。幾年之後,小而簡單的應用將逐漸成長成一個龐大的單體。

一旦應用成為一個龐大、複雜的單體,你的開發組織可能會陷入了一個痛苦的境地,敏捷開發和交付的任何一次嘗試都將原地徘徊。一個主要問題是應用實在非常複雜,它對於任何一個開發人員來說都顯得過於龐大。而最終,正確修復 bug 和實現新功能變得非常困難而耗時。

另一個大問題是,複雜的單體應用本身就是持續部署的障礙。如今,SaaS 應用發展到了可以每天多次將變更推送到生產環境。這對於複雜的單體來說非常困難,因為你需要重新部署整個應用才能更新其中任何一部分。

當不同模塊存在資源需求衝突時,單體應用可能會難以擴展。例如,一個模塊可能會執行 CPU 密集型圖像處理邏輯,理想情況下是部署在 Amazon EC2 Compute Optimized 實例中。另一個模塊可能是一個內存數據庫,最適合部署到 EC2 Memory-optimized 實例。然而,由於這些模塊被部署在一起,你必須在硬件選擇上做出妥協。

最後同樣重要的是,單體應用使得採用新框架和語言變得非常困難。例如,假設你有 200 萬行代碼使用了 XYZ 框架編寫。如果使用較新的 ABC 框架來重寫整個應用,這將非常昂貴(時間和成本方面),即使框架非常好。因此,這對於新技術採用是一個非常大的障礙。

總結:你有一個成功的關鍵業務應用,它已經發展成一個只有少數開發人員能夠理解的巨大單體。它使用了過時、非生產性技術,這使得招聘優秀開發人員變得非常困難。應用變得難以擴展、不可靠。因此敏捷開發和持續交付是不可能的。

微服務的優點

  • 解決了複雜問題。它把可能會變得龐大的單體應用分解成一套服務。雖然功能數量不變,但應用已經被分解成可管理的塊或者服務。每個服務都有一個明確的邊界定義方式,如遠程過程調用(RPC)驅動或消息驅動 API。微服務架構模式強制一定程度的模塊化,實際上,使用單體代碼來實現是極其困難的。因此,使用微服務架構模式,個體服務能被更快地開發,並且易於理解和維護。

  • 這種架構使得每個服務都可以由一個團隊獨立專注開發。開發者可以自由選擇任何符合服務 API 契約的技術。當然,更多的組織是希望通過技術選型限制來避免完全混亂的狀態。然而,這種自由意味著開發人員不再有可能在這種自由的新項目開始時使用過時的技術。當編寫一個新服務時,他們可以選擇當前的技術。此外,由於服務較小,使用當前技術重寫舊服務將變得更加可行。

  • 微服務架構模式可以實現每個微服務獨立部署。開發人員根本不需要去協調部署本地變更到服務。這些變更一經測試即可立即部署。比如,UI 團隊可以執行 A/B 測試,并快速迭代 UI 變更。微服務架構模式使得持續部署成為可能。

  • 微服務架構模式使得每個服務能夠獨立擴展。你可以僅部署滿足每個服務的容量和可用性約束的實例數目。此外,你可以使用與服務資源要求最匹配的硬件。例如,你可以在 EC2 Compute Optimized 實例上部署一個 CPU 密集型圖像處理服務,並且在 EC2 Memory-optimized 實例上部署一個內存數據庫服務。

微服務的缺點

微服務是一個分佈式系統,其使得整體變得複雜。開發者需要選擇和實現基於消息或者 RPC 的進程間通信機制。此外,由於目標請求可能很慢或者不可用,他們必須要編寫代碼來處理局部故障。雖然這些並不是很複雜、高深,但模塊間通過語言級方法/過程調用相互調用,這比單體應用要復雜得多。

另一個挑戰是分區數據庫架構。更新多個業務實體的業務事務是相當普遍的。這些事務在單體應用中的實現顯得微不足道,因為單體只存在一個單獨的數據庫。在基於微服務的應用中,你需要更新不同服務所用的數據庫。通常不會選擇分佈式事務,不僅僅是因為 CAP 定理。他們根本不支持如今高度可擴展的 NoSQL 數據庫和消息代理。你最後不得不使用基於最終一致性的方法,這對於開發人員來說更具挑戰性。

此外,此架構必須實現跨越多服務變更。例如,假設你正在實現一個修改服務 A、服務 B 和 服務 C 的需求,其中 A 依賴於 B,且 B 依賴於 C。在單體應用中,你可以簡單地修改相應的模塊、整合變更並一次性部署它們。相反,在微服務中你需要仔細規劃和協調變更到每個服務。例如,你需要更新服務 C,然後更新服務 B,最後更新服務 A。

每個服務都有多個運行時實例。還有更多的移動部件需要配置、部署、擴展和監控。此外,你還需要實現服務發現機制,使得服務能夠發現需要與之通信的任何其他服務的位置(主機和端口)。而傳統的基於票據(ticket-based)和手動的操作方式無法擴展到如此複雜的程度。因此,要成功部署微服務應用,需要求開發人員能高度控制部署方式和高度自動化。

  • 一種自動化方式是使用現成的平台即服務(PaaS),如 Cloud Foundry。 PaaS 為開發人員提供了簡單的方式來部署和管理他們的微服務。它讓開發人員避開了諸如採購和配置 IT 資源等煩惱。同時,配置 PaaS 的系統人員和網絡專業人員可以確保達到最佳實踐以落實公司策略。

  • 自動化微服務部署的另一個方式是開發自己的 PaaS。一個普遍的起點是使用集群方案,如 Kubernetes,與 Docker 等容器技術相結合。

微服務架構的進入門檻

微服務因為它先天就是分散式系統,因此有些必須要跨過的門檻,請先評估團隊具備這樣的能力之後,才有資格繼續往下評估下去,看看是否適合用微服務?

1. (分散式) 系統架構

分散式就代表複雜度高。包括問題排除 (你以前只要除錯一個 app, 現在你得同時對多個 app 進行除錯),還有 log 追蹤查詢等等。遠端的呼叫 可靠度跟效能也不如本地端的呼叫,正確率也會大大的降低 (本地端呼叫過程中幾乎不會出問題)

2. 開發流程

由於你要開發的系統變多了 (雖然每個系統都變小變簡單了),開發的管理,開發後的部署,服務跟服務之間的套件,API 介面的版本及相容性要求, 自動化測試、CI / CD 等等 DevOps 探討的課題,在這邊都是必要的。沒做到這些,你在微服務的發展過程一定會很痛苦,只要碰到幾次問題,你 浪費在追查問題的過程中浪費的時間,就足以抵銷掉微服務帶來的好處。若不顧好 API 的相容性問題,若你異動單一服務,相關的服務都得一併更新升級的話,那這樣你還算享受到微服務的好處嗎? 回想一下: 微服務 可以個別升級系統中的個別服務,不會影響到整體系統的運作。這是必須建立在 API 隨時維持新舊版的相容性為前提。

3. 營運流程

開發之後就是維運。微服務化,就是用很多規模較小的系統,用大量的 instance 來取代單一的 app, 因此你需要部署的 app 數量會暴增。 此時若沒有改善 app 的部署方式,同時改善執行環境的基礎建設,結果也是一樣,慘不忍睹。

Reference