Microservices Fundamentals(微服務基礎)
是什麼?
Microservices Architecture 是一種將應用程式拆分為多個小型、獨立部署的服務的架構風格。每個服務擁有自己的資料庫、獨立的部署週期,透過 API 或 Message Queue 溝通。
ℹ️不是新概念
微服務的本質是 SOA(Service-Oriented Architecture) 的進化版,加上了 DevOps 文化、容器化技術、和 CI/CD 的支撐。沒有這些基礎設施,微服務的維運成本會高到不值得。
核心觀念
Monolith vs Microservices
| 面向 | Monolith | Microservices | |------|----------|---------------| | 部署 | 整個應用一起部署 | 每個服務獨立部署 | | 擴展 | 整體水平擴展 | 按服務需求個別擴展 | | 技術棧 | 統一 | 每個服務可以不同 | | 資料庫 | 共用一個 | 每個服務自己的資料庫 | | 團隊 | 按技術分工(前端/後端/DBA) | 按業務功能分工(訂單團隊/支付團隊) | | 複雜度 | 程式碼內部複雜 | 網路通訊與分散式系統複雜 | | 一致性 | 容易(ACID Transaction) | 困難(需要 Saga 等模式) |
什麼時候該用微服務?
- 團隊人數超過 15-20 人,開始互相干擾
- 不同模組的變更頻率和擴展需求差異大
- 組織已具備 DevOps、CI/CD、容器化的成熟度
- 業務領域可以清楚劃分 Bounded Context
什麼時候不該用?
- 新創早期(業務邊界不清楚)
- 團隊小於 5 人
- 沒有自動化部署和監控基礎設施
- 追求快速驗證 MVP
常見誤區
⚠️微服務不是銀彈
- 「微服務比較先進,所以一定比 Monolith 好」(Monolith 不是壞架構,很多成功產品用 Monolith)
- 「先建微服務,再找業務邊界」(應該先建 Monolith,再根據真實需求拆分)
- 「每個 API endpoint 就是一個微服務」(微服務按業務能力劃分,不是按 API)
- 「微服務可以解決程式碼品質問題」(爛的程式碼搬到微服務只會變成分散式的爛程式碼)
執行流程
從 Monolith 開始
先用單體架構快速驗證業務,釐清領域邊界
識別 Bounded Context
找出業務邊界,決定哪些模組適合拆分
建立基礎設施
CI/CD、容器化、Service Mesh、監控告警
漸進拆分
用 Strangler Fig 模式逐步將模組抽出為獨立服務
持續演進
根據實際需求持續調整服務邊界和粒度
流程解讀:微服務的採用是一個漸進的過程,而非一步到位。Martin Fowler 提出的「Monolith First」策略建議先用單體架構釐清業務邊界,等到團隊規模和系統複雜度真正需要時再拆分。基礎設施的準備是關鍵前提 — 沒有自動化部署和監控,維運微服務的成本會遠超收益。
程式碼範例
C# 版本
// Monolith: 所有邏輯在同一個專案
public class OrderService
{
private readonly OrderDbContext _db;
private readonly PaymentService _payment;
private readonly InventoryService _inventory;
private readonly NotificationService _notification;
public async Task<Order> PlaceOrder(OrderRequest request)
{
// 所有操作在同一個 transaction
using var tx = await _db.Database.BeginTransactionAsync();
var order = await CreateOrder(request);
await _payment.Charge(order); // 直接呼叫
await _inventory.Reserve(order); // 直接呼叫
await _notification.Send(order); // 直接呼叫
await tx.CommitAsync();
return order;
}
}
// Microservices: 每個服務獨立,透過 HTTP/Message Queue 溝通
public class OrderService // 訂單服務
{
private readonly HttpClient _paymentClient;
private readonly IMessageBus _bus;
public async Task<Order> PlaceOrder(OrderRequest request)
{
var order = await CreateOrder(request);
// 透過 HTTP 呼叫支付服務
await _paymentClient.PostAsJsonAsync("/api/payments", new
{
OrderId = order.Id,
Amount = order.Total
});
// 透過 Message Queue 通知庫存和通知服務
await _bus.PublishAsync(new OrderPlacedEvent(order.Id));
return order;
}
}TypeScript 版本
// Monolith: Express app 包含所有 routes
const app = express();
app.use("/api/orders", orderRoutes);
app.use("/api/payments", paymentRoutes);
app.use("/api/inventory", inventoryRoutes);
// 全部跑在同一個 process
// Microservices: 每個服務是獨立的 Express app
// order-service/index.ts
const orderApp = express();
orderApp.post("/api/orders", async (req, res) => {
const order = await createOrder(req.body);
// 發送事件通知其他服務
await messageBus.publish("order.placed", {
orderId: order.id,
items: order.items,
});
res.json(order);
});
orderApp.listen(3001);
// payment-service/index.ts(獨立 process)
const paymentApp = express();
messageBus.subscribe("order.placed", async (event) => {
await processPayment(event.orderId);
});
paymentApp.listen(3002);Python 版本
# Monolith: Django 或 Flask 的所有模組在一起
# 優點:簡單、一個 DB transaction 搞定
class OrderView:
def post(self, request):
with transaction.atomic():
order = Order.objects.create(**request.data)
Payment.objects.charge(order)
Inventory.objects.reserve(order)
Notification.objects.send(order)
return Response(order)
# Microservices: 每個服務獨立部署
# order_service/main.py
from fastapi import FastAPI
import httpx
import aio_pika
app = FastAPI()
@app.post("/api/orders")
async def place_order(request: OrderRequest):
order = await create_order(request)
# HTTP 呼叫支付服務
async with httpx.AsyncClient() as client:
await client.post(
"http://payment-service/api/payments",
json={"order_id": order.id, "amount": order.total}
)
# 發布事件
await publish_event("order.placed", {"order_id": order.id})
return order結構圖
圖中 Client 透過 API Gateway 統一入口存取各個微服務。Order Service 和 Payment Service 各自擁有獨立的資料庫(Database per Service 模式)。服務之間透過 Message Queue 進行非同步溝通,降低耦合度。API Gateway 負責路由、認證、限流等橫切關注點。
面試常見問題
Q: 什麼時候該從 Monolith 轉向 Microservices?
A: 當出現以下訊號時考慮拆分:部署頻率受限(一個小改動要部署整個系統)、團隊之間頻繁衝突(改 A 模組影響 B 模組)、不同模組的擴展需求差異大(訂單服務需要 10 個 instance,報表服務只需要 1 個)。前提是已具備 CI/CD、容器化、監控等基礎設施。
Q: Microservices 最大的挑戰是什麼?
A: 分散式系統的固有複雜性:網路不可靠(需要重試和熔斷)、資料一致性(沒有 ACID transaction,需要 Saga)、服務發現和負載均衡、分散式追蹤和除錯、部署和配置管理的複雜度。這些都需要額外的基礎設施和團隊能力。
Q: Database per Service 模式的利弊?
A: 好處是服務之間完全解耦,可以各自選擇最適合的資料庫類型(SQL/NoSQL),獨立擴展和優化。壞處是跨服務查詢變得困難(需要 API Composition 或 CQRS),資料一致性需要額外處理(Saga Pattern),資料冗餘是常態。
理解測驗
🤔 以下哪個不是微服務架構的特徵?
🤔 Martin Fowler 建議的微服務採用策略是什麼?
🤔 以下哪個團隊最適合採用微服務架構?
重點整理
💡一句話記住
Microservices = 獨立部署 + 獨立資料庫 + API 溝通。 口訣:「Monolith 先行,痛點再拆,基建先備」
| 概念 | 說明 | |------|------| | Monolith | 所有功能在一個部署單位,簡單但耦合 | | Microservices | 按業務拆分的獨立服務,靈活但複雜 | | Database per Service | 每個服務擁有自己的資料庫 | | API Gateway | 微服務的統一入口 | | 核心取捨 | 用分散式複雜度換取獨立部署和擴展的靈活性 |