Chuyển đến nội dung chính

第 4 課:微服務設計原則 — SRP、DDD 與有界上下文

什麼是微服務、單一職責原則、領域驅動設計、定義服務邊界的有界脈絡、鬆散耦合和高內聚、何時應該和不應該使用微服務。

🏗️ 建築 — 第 4 課 第 4 課:微服務設計原則 — SRP、DDD 與限界上下文

雲端原生微服務架構

第 2 部分:微服務設計與通訊模式

亞洲開發網

第 4 課:微服務設計原則 — SRP、DDD 與有界上下文

簡介

微服務不僅僅是「拆分整體」。如果分割方式錯誤,您將擁有一個「分散式整體」—同時具有兩種架構的所有缺點。本文介紹了正確劃分微服務的設計原則。


1.什麼是微服務?

微服務是一種架構風格,其中應用程式由許多小型獨立服務組成:

Monolith                          Microservices
┌──────────────────────┐         ┌──────────┐ ┌──────────┐
│     Một ứng dụng     │         │  Order   │ │ Payment  │
│   ┌──────┐ ┌──────┐  │         │  Service │ │ Service  │
│   │Order │ │Payment│  │   →    └──────────┘ └──────────┘
│   ├──────┤ ├──────┤  │         ┌──────────┐ ┌──────────┐
│   │Invent│ │Notif  │  │         │Inventory │ │  Notif   │
│   └──────┘ └──────┘  │         │  Service │ │ Service  │
│    Shared Database    │         └──────────┘ └──────────┘
└──────────────────────┘          Mỗi service có DB riêng

特點

  • 在單獨的進程中運行:每個服務都是一個獨立的進程/容器
  • 網路通訊:HTTP/REST、gRPC、訊息佇列
  • 獨立部署:部署服務A,不影響服務B
  • 私人資料庫:每個服務資料庫模式
  • 小團隊:2 個披薩團隊(5-8 人)擁有 1-3 項服務

2.單一職責原則(SRP)

每個服務只負責一項操作並且有一個改變的理由。

✅ Đúng — Mỗi service một nghiệp vụ rõ ràng:
├── OrderService         → Quản lý vòng đời đơn hàng
├── PaymentService       → Xử lý thanh toán
├── InventoryService     → Quản lý tồn kho
├── NotificationService  → Gửi email/SMS/push
└── UserService          → Quản lý tài khoản

❌ Sai — Service "thùng rác":
├── OrderPaymentService      → 2 nghiệp vụ gộp
├── CommonService            → Mọi thứ chung
└── UtilityService           → Không rõ trách nhiệm

違反 SRP 的跡象

  • 服務有 太多不相關的 API 端點
  • 更改功能 A 需要重新測試功能 B
  • 許多團隊修復相同的服務
  • 服務名稱包含“and”或“util”或“common”

3.領域驅動設計(DDD)

3.1 為什麼需要DDD?

DDD 幫助回答了最重要的問題:「每個服務的邊界在哪裡?」

DDD不是依照技術(前端服務、後端服務、資料庫服務)來劃分,而是依照業務領域來劃分。

3.2 策略設計

無所不在的語言

在開發人員和領域專家之間建立通用語言:

Domain Expert (Business):        Developer (Tech):
"Đơn hàng"                   →   Order
"Thanh toán"                  →   Payment
"Giao hàng"                  →   Shipment
"Hoàn tiền"                  →   Refund
"Kho hàng"                   →   Inventory

Đảm bảo: Code, API, database, documentation đều dùng cùng thuật ngữ

有界上下文

有界上下文定義了模型具有意義的**範圍:

┌──────────────────────────────────────────────────────┐
│                   E-Commerce System                   │
│                                                       │
│  ┌─────────────┐  ┌─────────────┐  ┌──────────────┐ │
│  │   Order      │  │  Catalog    │  │  Customer    │ │
│  │   Context    │  │  Context    │  │  Context     │ │
│  │              │  │             │  │              │ │
│  │  "Product"   │  │  "Product"  │  │  "Customer"  │ │
│  │  = OrderItem │  │  = SKU with │  │  = Account   │ │
│  │  (id, qty,   │  │  specs,     │  │  with prefs, │ │
│  │   price)     │  │  images,    │  │  addresses   │ │
│  │              │  │  pricing    │  │              │ │
│  └─────────────┘  └─────────────┘  └──────────────┘ │
│                                                       │
│  Cùng từ "Product" nhưng ý nghĩa KHÁC NHAU           │
│  trong mỗi Bounded Context                           │
└──────────────────────────────────────────────────────┘

重要規則:每個限界上下文 → 一個(或多個)微服務。

3.3 上下文映射-上下文之間的關係

┌─────────────┐    Published    ┌──────────────┐
│   Order     │────Language────▶│   Payment    │
│   Context   │                 │   Context    │
└──────┬──────┘                 └──────────────┘
       │
       │ Customer/Supplier
       ▼
┌─────────────┐    Conformist   ┌──────────────┐
│  Shipping   │◀───────────────│  3rd Party   │
│  Context    │                 │  Logistics   │
└─────────────┘                 └──────────────┘
關係描述
共享核心2 個上下文共享子集程式碼/模型
客戶/供應商上游提供API,下游消費
墨守成規下游完全遵循上游模式
反腐敗層外部模型與內部模型之間的翻譯層
發布語言透過標準格式(JSON 模式、Protobuf)進行通訊

3.4 戰術設計-建構模組

Bounded Context
│
├── Entity        → Có identity, lifecycle (Order, User)
├── Value Object  → Không có identity, immutable (Money, Address)
├── Aggregate     → Cluster of entities, consistency boundary
│   └── Aggregate Root → Entry point (Order là root, OrderItem là child)
├── Domain Event  → Sự kiện nghiệp vụ (OrderCreated, PaymentReceived)
├── Repository    → Persistence abstraction
└── Domain Service → Logic không thuộc entity nào (PricingCalculator)

聚合 — 一致性單位

Order Aggregate:
┌───────────────────────────────┐
│  Order (Aggregate Root)       │
│  ├── id: "O-001"             │
│  ├── status: "confirmed"     │
│  ├── total: $500             │
│  │                           │
│  ├── OrderItem               │
│  │   ├── product: "iPhone"   │
│  │   ├── qty: 1              │
│  │   └── price: $400         │
│  │                           │
│  ├── OrderItem               │
│  │   ├── product: "Case"     │
│  │   ├── qty: 1              │
│  │   └── price: $100         │
│  │                           │
│  └── ShippingAddress         │
│      └── "123 ABC Street"   │
└───────────────────────────────┘

Quy tắc:
- Chỉ truy cập thông qua Aggregate Root (Order)
- Một transaction = một aggregate
- Cross-aggregate = eventual consistency

4. 鬆散耦合和高內聚

4.1 鬆散耦合

服務 A 的變更不需要服務 B 的變更。

✅ Loose Coupling:
Order Service ──event──▶ Kafka ──▶ Payment Service
(Thay đổi internal logic của Order → Payment không bị ảnh hưởng)

❌ Tight Coupling:
Order Service ──direct DB query──▶ Payment Database
(Thay đổi schema Payment DB → Order Service bị broken)

4.2 高內聚力

相關功能在一個服務中分組在一起。

✅ High Cohesion:
Payment Service:
├── ProcessPayment()
├── RefundPayment()
├── ValidateCard()
└── GetPaymentHistory()
→ Tất cả đều liên quan đến "thanh toán"

❌ Low Cohesion:
MiscService:
├── ProcessPayment()
├── SendEmail()
├── GenerateReport()
└── ResizeImage()
→ Không liên quan gì đến nhau

5. 什麼時候應該/不應該使用微服務?

5.1 應該在下列情況下使用

  • ✅ 大規模系統,許多團隊並行開發
  • ✅ 需要獨立擴展系統的每個部分
  • ✅ 需要多語言(多種語言/框架)
  • ✅ 快速的發布週期,持續部署
  • ✅ 複雜的領域,具有清晰的邊界
  • ✅ 組織擁有 DevOps 成熟度(CI/CD、監控、容器編排)

5.2 不應在下列情況下使用

  • ❌團隊小(< 5人)
  • ❌ 簡單應用程序,不太複雜的域
  • ❌ 不清楚域邊界
  • ❌ 沒有 CI/CD 基礎架構和容器編排
  • ❌時間有限發展
  • ❌ 團隊沒有操作分散式系統的經驗

5.3 Monolith First

Martin Fowler 建議 「單體優先」:

Phase 1: Monolith
├── Hiểu rõ domain
├── Phát triển nhanh
└── Xác định boundary tự nhiên

Phase 2: Modular Monolith
├── Tách module rõ ràng trong monolith
├── Mỗi module có boundary riêng
└── Giao tiếp qua internal API

Phase 3: Microservices (khi cần)
├── Tách module thành service
├── Thêm API Gateway
└── Event-driven communication

6. 應避免反模式

Distributed Monolith

❌ Chia thành nhiều service nhưng:
- Deploy phải đồng thời tất cả
- Shared database
- Synchronous chain calls dài
- Tightly coupled API contracts

→ Có đầy đủ nhược điểm của cả Monolith VÀ Microservices
→ Không có ưu điểm của cái nào cả

奈米服務(太小)

❌ Chia quá nhỏ:
├── CreateOrderService
├── UpdateOrderService
├── DeleteOrderService
├── GetOrderService
└── ListOrderService

→ Quá nhiều service, overhead network, khó quản lý
→ Nên gom thành: OrderService

7. 總結

原理重點
建議零售價每項服務都有業務、有改變的理由
國內長途根據Bounded Context,而不是根據技術來劃分服務
骨材一致性單元,可透過聚合根
鬆散耦合更改服務 A 不會影響服務 B
高凝聚力相關功能被分組為一項服務
整體第一開始單體,在理解領域時逐漸分離

下一篇文章:同步通訊 - REST API 和 gRPC,微服務之間同步通訊的兩種最受歡迎的協定。