# Lesson 25: 淺談 單體架構、微服務架構與單/多租戶架構

過去我們討論了 要把程式寫在哪、程式要怎麼拆的題目，接下來我們來看看「如何服務不同客戶」，這些架構反映了軟體開發在擴充性與複雜度之間的權衡。

# 軟體架構深度解析：從系統拆分到商業規模化

在軟體工程的演進中，架構的選擇往往是在「開發效率」、「系統擴充性」與「營運成本」之間尋求平衡。我們可以從兩個核心維度來觀察這些架構：系統如何運行（單體 vs. 分散式） 以及 如何服務客戶（單租戶 vs. 多租戶）。

## 規模與擴展維度：程式該如何運行？

### 單體架構 (Monolithic Architecture)

整個系統（API、業務邏輯、資料存取）打包成一個應用程式部署。

一個典型的Laravel 專案就是單體架構。

*   代表實例： 標準的 Laravel 或 Rails 專案。
    
*   特性： 同步的 Function Call、共用單一資料庫、單一部署流程。
    
*   優點： 初期開發速度極快、測試與部署簡單、維運壓力小。
    
*   缺點： 「牽一髮而動全身」，任一模組崩潰會導致全站失效；且難以針對特定功能進行水平擴展（Scaling）。
    
    ![](https://cdn.hashnode.com/uploads/covers/693a6e8cf7ff0b7590781231/0dbf1e7a-05fc-4562-a708-a66cabde1438.png align="center")
    

### 分散式架構 (Distributed Architecture)

系統跨越多個節點運行，透過網路協作完成任務。**微服務即是分散式架構的一種具體實現。**

*   關鍵挑戰： 必須面對 CAP 定理 的物理限制（一致性、可用性、分區容忍性）。
    
*   優點： 高可用性（HA）與強大的水平擴展能力，具備容錯機制。
    
*   缺點： 網路延遲、數據一致性（Eventual Consistency）問題，以及複雜的 Race Condition 處理。
    

### 微服務架構 (Microservices Architecture)

將系統拆分為「多個獨立服務」，每個服務負責單一業務能力（bounded context）。

*   特性： 每個服務獨立部署、擁有專屬 DB、透過 HTTP/gRPC/MQ 通訊。
    
*   核心痛點： 運維複雜度（Observability）與分散式交易處理（如 Saga Pattern）。
    
*   決策關鍵： 依據 DDD（領域驅動設計） 的「界限上下文」來拆分，避免淪為分散式單體。
    
*   一致性模型改變：單體架構可以容易地實現強一致性，微服務在「跨服務」場景下通常需要採用最終一致性。
    

**常見設計 Pattern**

*   API Gateway
    
*   Circuit Breaker
    
*   Saga Pattern
    
*   Event-driven Architecture
    

![](https://cdn.hashnode.com/uploads/covers/693a6e8cf7ff0b7590781231/342e22e5-6b9e-4b8a-af2f-6c672650657a.png align="center")

## 服務與商業維度：如何服務不同客戶？

當進入 SaaS（軟體即服務）領域時，核心決策點在於如何處理多個客戶（Tenant）的數據與資源。

### 獨立部署（單租戶模型）

每個客戶擁有獨立的運行環境與資料邊界。

*   適用： 高資安需求的標案或極大企業客戶。
    
*   問題： 維護 100 個客戶需要更新 100 次，難以規模化。
    

### 多租戶架構（Multi-Tenant Architecture）

一套系統服務「多個客戶（Tenant）」，但資料彼此隔離。多租戶架構主要是在「SaaS 情境下的資料隔離策略」。

*   資源利用度高且多客戶管理容易(集中部署與統一版本管理)
    
*   權限與資料隔離設計需要更謹慎且複雜
    
*   在多租戶架構中，當租戶數量成長時，會面臨資料遷移與資源重新分配（例如：將大型租戶遷移至獨立資料庫）的挑戰。
    

**三種實作模式**

1.  Shared DB, Shared Schema
    
    *   用 `tenant_id` 區分
        
    *   成本最低，但隔離性最差，任何 query 若未正確套用 tenant 條件（例如：global scope），將導致資料越權存取
        
2.  Shared DB, Separate Schema
    
    *   每個 tenant 一個 schema，隔離性提升 且可以 可 partial backup
        
    *   schema 管理複雜、migration 要處理多 schema
        
3.  Separate Database(DB Per Tenant)
    
    *   每個 tenant 一個 DB
        
    *   隔離最好，成本最高
        

![](https://cdn.hashnode.com/uploads/covers/693a6e8cf7ff0b7590781231/cec65896-13a9-4db5-bd93-fcd6c00e4b6e.png align="center")

# 實務運用

## 單體與微服務的邊界

當單體要轉微服務時，最難的不是技術，而是「怎麼拆」。

*   關鍵概念： DDD（領域驅動設計）中的 界限上下文。
    
*   實務建議： 如果邊界劃分錯誤（例如：訂單服務與庫存服務耦合太深），會變成最糟糕的情況——「分散式單體」。這具備了微服務的所有缺點（網路延遲、部署複雜），卻沒有任何優點（開發依然互相牽制）。
    

## 分散式架構的幽靈：CAP 定理

在討論分散式與微服務時，CAP 定理是繞不開的物理限制。

*   一致性 (Consistency)
    
*   可用性 (Availability)
    
*   分區容忍性 (Partition Tolerance) 在分散式系統中，我們被迫在 C 與 A 之間做選擇。例如：
    
*   金融交易： 寧可系統暫時無法服務 (A)，也要保證金額絕對正確 (C)。
    
*   社群貼文： 寧可讓不同使用者看到稍微不同的按讚數 (C)，也要保證系統隨時能讀取 (A)。
    

## 多租戶架構的隱形陷阱：Noisy Neighbor

在 SaaS 開發中，多租戶最怕 吵鬧鄰居 效應。

*   問題： 當 A 租戶突然有暴增流量，若使用「共享資料庫 (Shared Schema)」，B 租戶的服務品質也會下降。
    
*   解決方案： 這時需要引入 Rate Limiting（限流） 或 Resource Quota。如果你的客戶是像「台積電」這種等級的大企業，通常會要求 Separate Database，不只是為了效能，更多是為了資安合規。
    

# 結論

選擇架構時不應盲目追求「微服務」，因為架構的引入是有代價的。很多成功的產品都是從單體開始，隨後演進為分散式，最後為了團隊協作才拆分為微服務。而多租戶則是打算將這套系統賣給多個客戶時，必須考慮的數據隔離策略。
