軟件技術發展這麼多年,我們經歷了單體,再到SOA,再到微服務的架構轉變,這些變化的實踐發起者都是用户規模龐大的大型企業,引來行業無數中小公司的效仿。可近些年出現了這樣一個現象。那些已經遷移到微服務的公司,逐漸在試着迴歸單體架構。這不僅是中小公司的選擇,像亞馬遜、字節跳動、阿里、騰訊甚至谷歌都在這樣做。

要想弄懂這種轉變的背後底層邏輯,我們必須清楚以下幾個點,微服務流行的契機是什麼?它帶來了哪些好處?又帶來了哪些弊端?為什麼開始迴歸“單體”?

 

一、微服務流行的契機

 

微服務在2010年代中後期開始盛行,並迅速成為互聯網架構的主流,主要得益於以下幾個關鍵契機:

  1. 單體架構的瓶頸: 隨着互聯網用户和業務的爆炸式增長,早期的單體應用變得無比龐大、複雜。
  • 技術棧僵化: 整個系統必須使用統一的技術棧,難以引入新的技術。
  • 開發效率低下: 代碼庫巨大,編譯、啓動時間漫長,一個小改動就需要部署整個應用,團隊間協作成本高。
  • 可擴展性差: 無法對特定功能進行擴展,只能“眉毛鬍子一把抓”地水平擴展整個應用,成本高昂。
  • 可靠性風險: 任何一個微小模塊的bug都可能導致整個系統崩潰。

容器化技術的成熟: Docker 的普及為微服務提供了理想的部署和隔離環境。它使得應用及其依賴可以被輕鬆打包、分發,並在任何地方以一致的方式運行。

DevOps文化的興起: 強調開發與運維的協同,提倡“誰開發,誰運維”。微服務架構與DevOps理念天然契合,小團隊可以獨立負責一個服務的全生命週期。

雲原生與編排工具的完善 :Kubernetes等容器編排平台的成熟,解決了微服務在部署、調度、服務發現、彈性伸縮等方面的巨大運維挑戰,使得管理成百上千個服務成為可能。

領域驅動設計(DDD)的推廣: DDD提出的“限界上下文”概念,為如何劃分服務邊界提供了理論指導,使得微服務的拆分更加合理。

大廠的示範效應: Netflix、Amazon、Twitter等公司通過成功實踐微服務架構,處理了海量流量,並將其經驗開源(如Netflix OSS),極大地推動了整個行業對微服務的採納。

 

二、微服務帶來的核心好處

 

微服務的流行絕非偶然,它確實解決了單體的核心痛點:

  • 技術異構性: 每個服務可以選擇最適合其業務需求的技術棧(如用Go處理高併發,用Python做數據分析)。
  • 獨立部署與持續交付: 服務可以獨立開發、測試和部署,大大提升了交付速度,實現了真正的敏捷開發。
  • 彈性與容錯: 故障被隔離在單個服務內,避免“一顆老鼠屎壞了一鍋湯”。可以通過熔斷、降級等機制保證系統整體可用性。
  • 可擴展性: 可以對資源密集型服務進行精準擴容,優化資源使用和成本。
  • 團隊自治: 小團隊圍繞特定的服務進行工作,權責清晰,溝通效率高,符合“兩個披薩團隊”的管理理念。

 

三、微服務帶來的顯著弊端

 

隨着實踐的深入,微服務的弊端也逐漸暴露,尤其是在業務複雜度、團隊規模和基礎設施不匹配的情況下,這些弊端會被急劇放大:

  • 分佈式系統複雜性: 這是最根本的弊端。開發者需要處理網絡延遲、異步消息、分佈式事務、最終一致性等單體中不存在的問題。
  • 運維開銷與成本: 需要一整套成熟的監控、日誌、鏈路追蹤、服務治理和自動化部署平台。維護這套基礎設施的團隊成本和資源成本非常高。並且應用的基本信息的維護,運行資源的維護都變得力不從心。
  • 測試與調試的噩夢: 服務間的依賴使得集成測試極其複雜。生產環境的問題排查如同破案,需要跨多個服務日誌去追溯根源。
  • 數據一致性挑戰: 跨服務的數據強一致性難以保證,最終一致性模型對業務邏輯和用户體驗設計提出了更高要求。
  • 網絡性能與可靠性: 大量的服務間調用(RPC/HTTP)會消耗CPU資源(如序列化/反序列化),並受網絡抖動和不可靠的影響,導致延遲增加。
  • 服務劃分的困難: 不合理的服務邊界(過細或耦合)會導致服務間產生循環依賴和“分佈式單體”,這比單體架構更糟糕。

 

四、為什麼大廠開始迴歸“單體”?

 

瞭解了上面這些以後,你能理解為什麼大廠開始要回歸“單體”了嗎?從 其根本原因在於: 當業務發展到一定規模後,微服務在“開發期”和“運維期”帶來的額外複雜度,開始超過它所帶來的收益。 其實這裏的單體,不是説真的把整個端到端業務都放到一個應用部署上去,而是找到正確的劃分粒度,做 模塊化單體 。

具體來説:

  1. 過度拆分導致研發效率反降:
  • 開發一個需求需要跨多個倉庫修改、協調、聯調,溝通成本遠超編碼成本。
  • 本地開發環境需要啓動幾十個服務做自測驗證,幾乎不可能。
  • 問題排查和生產恢復變得效率低下。

2. 性能與成本問題凸顯:

  • 一次用户請求可能穿越幾十個服務,累計的網絡延遲和JSON/ProtoBuf解析開銷變得不可忽視。
  • 每個微服務都需要獨立的CPU、內存預留和副本,導致資源使用率低下,整體成本高昂。

3. 治理複雜度成為不可承受之重:

  • 成百上千個服務使得應用基礎信息,服務網格、配置管理、API網關等治理組件本身就成為巨大的負擔。

4. “模塊化單體”找到了平衡點:

  • 我們追求的並非原始的“大泥球”單體,而是 模塊化單體 或 分佈式單體 。
  • 核心思想: 在 開發時 是微服務(代碼層面高內聚、低耦合,通過模塊(module)進行物理隔離),在 運行時 是單體(合併部署為一個進程)。
  • 這吸收了微服務 清晰邊界 的優點,同時避免了分佈式 運行時 的絕大多數弊端。

五、實踐案例

這裏我舉一個我實際做過的金融場景的案例,主要是一個針對貸款逾期客户做調解和催收的業務案例,促進逾期客户的還款。

名詞解釋:

催收 : 催收是指當借款人未按期還款時,金融機構或其委託的第三方催收機構,通過電話、短信、信函、上門等方式, 督促借款人履行還款義務 的行為 。

調解 : 調解是指在 中立第三方(如法院、仲裁委、金融調解中心) 主持下,債權人和債務人 平等協商 ,在自願基礎上達成還款協議,解決債務糾紛的一種方式。

1. 改造前的架構圖

2. 改造後的架構圖

3. 帶來的實際收益

突出架構態運行態合併,重要業務多運行態隔離,發佈時可先發佈一個集羣。

①架構簡潔性

  • 前端層面 ,我們在架構態上去除了很多前端服務,按業務運行單元的方式對前端模塊做合併部署(如催收業務單元,以催收前端為部署主體,合併呼叫中心前端部署到同一個ng,在ng下劃分不同靜態資源目錄,某個前端模塊發佈的時候,只是對對應目錄下的靜態資源做替換)。如果 對於高保障性的業務,可以劃分出多個業務運行單元,例如催收業務單元01,催收業務單元02,每個業務單元都部署了能完成閉環業務能力的應用集合 。(關於架構態和運行態的概念,可參考這篇文章: 一篇文章總結系統架構態與運行態劃分準則 )
  • 後端層面 ,我們把原來多個微小服務甚至系統合併,架構態和運行態上,我們不再需要維護這些微小服務和它們關聯的微小數據庫,只是在工程上,我們還是保持了各個模塊的獨立。這裏特別要提到,為什麼新架構下把催收和調解系統合併了,因為他們功能重複性很高,且催收的業務數據,調解也需要看到,同樣,調解的業務數據,催收也需要看到。這就決定了它們業務緊密性很高,數據模型高度重合。之前都是做了相互的數據變更同步,複雜度高。合併後,架構簡單,且同樣的,重要的業務,可劃分多個運行單元。 發佈時,可先發佈一個運行單元,穩定運行一段時間,再發布其他運行單元 。
  • 我們減少了大量的微小服務之間的接口調用,本身它們就是緊密關聯的,之前很多的微服務都需要修改同樣的表,都是通過接口去實現,這就説明他們的關聯是緊密的,是功能內聚的,所以應該合併。

② 系統穩定性與高性能

  • 減少了各個鏈路上接口超時的風險和網絡消耗,性能更好。
  • 微小服務合併後, 減少了微服務之間的大量調用後,系統訪問鏈路更簡單,減少大量不必要的數據同步和複雜的數據一致性技術保障手段,穩定性指數級提升。

③ 可維護性

  • 架構態和運行態都減少了大量應用和關聯數據庫,從CMDB基礎數據維護,基礎資源維護,監控,問題排查,生產恢復等都大大提升了可維護性。

④ 需求交付效率

  • 沒有了那些大量交互接口的開發,各個模塊直連數據庫操作即可,大大提升了開發的效率。
  • 少了這些多餘的交互,大大降低了對接溝通成本和構建部署時間成本。

⑤ 擴展靈活性

  • 微服務合併後,依然保留了功能模塊在工程上的獨立性,我們甚至可以 基於模塊級別去做人員代碼權限管控 ,代碼互不影響。
  • 我在負責這塊業務的架構時,系統不僅給內部自營業務使用,還會做 saas和私有化輸出,這就要求系統的基礎能力,擴展能力劃分邊界非常清晰,以便於針對不同租户,組合不同的基礎能力和個性化的擴展能力輸出 。例如某個租户,它只需要資產委派能力,策略管理能力,客户觸達能力以及呼叫中心的所有能力、自身的擴展能力,那這時候我們就會在CI階段,選中這些模塊去構建打包,生成鏡像。這樣能做到針對不同租户靈活組裝。具體的工程劃分範例見我的這篇文章: SAAS及私有化-系統工程範例

⑥ 成本有效控制

  • 微小服務合併後,運行資源可大量被回收,研發成本大大降低。
  • 越少的服務,意味着系統維護的研發人力投入可以更少,一樣可以起到降本增效的效果。

總結

歸根結底,造成企業逐漸迴歸“模塊化單體”的原因就是當初在微服務盛行的時候,服務劃分的太微小,導致一個微服務甚至不能完成一個比較完整的能力,最後需要花費更大的技術成本去保障數據一致性,研發各個環節開始失控。