微服務的優點在於:它能讓你的系統具有可擴展性、可維護性和速度。
現實情況是:對於大多數系統而言,微服務會增加延遲、複雜性和故障點,而不會帶來任何實質的好處。
讓我們來看看實際數字。
根本問題在於:微服務透過網路進行通訊。而網路速度很慢。
進程內函數呼叫(單體式):
Function call: 0.001ms (1 microsecond)
同一資料中心內的HTTP呼叫(微服務):
HTTP request: 1-5ms (1,000-5,000 microseconds)
那速度慢了1000倍到5000倍。
場景:電子商務結帳流程
所需操作:
驗證使用者會話
檢查產品庫存
計算運費
處理付款
建立訂單記錄
發送確認郵件
單體架構:
Total time: 6 function calls × 0.001ms = 0.006ms
Database queries: 3 × 2ms = 6ms
External API (payment): 150ms
Total: ~156ms
微服務架構:
Service calls:
- User service: 2ms
- Inventory service: 3ms
- Shipping service: 2ms
- Payment service: 2ms + 150ms (external API)
- Order service: 3ms
- Notification service: 2ms
Each call includes:
- Serialization/deserialization: 0.5ms
- Network latency: 1-2ms
- Service processing: 1-2ms
Total service overhead: 6 services × 3ms = 18ms
Database queries: 6 services × 1 query × 2ms = 12ms
External API: 150ms
Total: ~180ms
結果:對於這種簡單的流程,微服務的速度慢了 15% 。
在資料庫中,我們都知道 N+1 查詢。微服務包含 N+1 個服務。
要求:
顯示用戶個人資料
顯示最近 10 個訂單
根據訂單歷史記錄顯示建議內容
單體架構(最佳化版):
-- Single query with JOIN
SELECT
users.*,
orders.*,
recommendations.*
FROM users
LEFT JOIN orders ON orders.user_id = users.id
LEFT JOIN recommendations ON recommendations.user_id = users.id
WHERE users.id = $1
LIMIT 10;
執行時間:約5毫秒
微服務(現實版):
// 1. Get user
const user = await userService.getUser(userId); // 3ms
// 2. Get orders (requires user_id from step 1)
const orders = await orderService.getOrders(userId); // 3ms
// 3. Get recommendations (requires orders from step 2)
const orderIds = orders.map(o => o.id);
const recommendations = await recommendationService
.getByOrders(orderIds); // 3ms
// Total: 9ms (sequential)
// Can't parallelize due to data dependencies
執行時間:約9毫秒(慢80%)
這假設:
網路狀況良好
無服務故障
沒有重試邏輯
沒有斷路器
讓我們透過受控實驗來測量實際開銷。
系統:簡單的 CRUD 應用程式
4 個實體:使用者、產品、訂單、支付
每秒 10,000 個請求負載
AWS EC2 t3.medium 實例
┌─────────────────┐
│ Application │
│ (Node.js) │
│ │
│ ┌───────────┐ │
│ │ Database │ │
│ │ (Postgres)│ │
│ └───────────┘ │
└─────────────────┘
配置:
單一 Node.js 進程
連接池(20 個連接)
Redis 快取(同一實例)
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ User │ │ Product │ │ Order │ │ Payment │
│ Service │ │ Service │ │ Service │ │ Service │
└────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │ │
└─────────────┴─────────────┴─────────────┘
│
┌──────┴──────┐
│ Postgres │
│ (shared) │
└─────────────┘
配置:
4 個 Node.js 服務
服務網格(Istio)
同一個Postgres資料庫
Redis 快取(共享)
| 指標 | 單體架構 | 微服務 | 差異 |
|--------|----------|---------------|------------|
| p50 延遲| 12毫秒 | 18毫秒 | +50% |
| p95 延遲| 25毫秒 | 45毫秒 | +80% |
| p99 延遲| 50毫秒 | 120毫秒 | +140% |
|吞吐量| 10,000 請求/秒 | 8,500 請求/秒 | -15% |
| CPU 使用率| 45% | 65% | +44% |
|記憶體使用情況| 512MB | 2GB | +300% |
|網路輸入/輸出| 50MB/秒| 180MB/秒| +260% |
主要發現:
尾部延遲受影響最大(p99:+140%)
資源使用量急劇增加
儘管具有“可擴展性”,但吞吐量卻下降了。
讓我們來分析一下微服務呼叫中時間都花在了哪裡。
總耗時:約3毫秒
DNS resolution: 0.1ms (cached)
TCP handshake: 0.5ms (within datacenter)
TLS handshake: 1.0ms (if using HTTPS)
HTTP headers: 0.2ms
Request serialization: 0.3ms (JSON)
Network transmission: 0.5ms
Service processing: 0.5ms
Response serialization: 0.3ms
Network transmission: 0.5ms
Response parsing: 0.2ms
────────────────────────────
Total: ~3.0ms
在一塊巨石中:
Function call: 0.001ms
────────────────────────
Total: 0.001ms
同樣的操作,開銷是原來的 3000 倍。
微服務會放大故障率。
假設:
每項服務的正常運作時間都達到 99.9%(三個九——相當不錯!)
請求需要 5 項服務
巨石:
Availability: 99.9%
Downtime: 43 minutes/month
微服務(5 個服務串連而成):
Availability: 0.999^5 = 0.995 = 99.5%
Downtime: 3.6 hours/month
這意味著停機時間增加了5倍。
User Request
↓
API Gateway (99.9%)
↓
Auth Service (99.9%)
↓
Product Service (99.9%)
↓
Inventory Service (99.9%)
↓
Price Service (99.9%)
↓
Response
Combined availability: 99.5%
加入:
斷路器(增加延遲)
重試(失敗後進行 3 次網路呼叫)
備用方案(部分降級)
結果:複雜、緩慢,故障率仍然較高。
微服務並不能解決資料庫瓶頸問題──反而會讓問題更加嚴重。
巨石:
Application → Connection Pool (20) → Database
微服務:
User Service → Pool (20) ───┐
Product Service → Pool (20) ├→ Database (max 100 connections)
Order Service → Pool (20) ──┤
Payment Service → Pool (20) ┘
Total connections: 80 (near database limit)
問題:
連線耗盡速度更快
鎖爭用增加(並發事務增加)
查詢快取效率較低(不同服務的存取模式不同)
測試: 1000 個並髮用戶
| 架構 | 連線數 | 鎖定等待時間 | 查詢時間 |
|--------------|--------------------|----------------|------------|
| 單體 | 20-30 | 5毫秒 | 10毫秒 |
| 微服務 | 60-80 | 25毫秒 | 18毫秒 |
微服務使用 3 倍的連線數,並且存在 5 倍的鎖定爭用。
每次網路呼叫都需要序列化/反序列化。
測試:序列化典型的 API 回應(包含巢狀資料的使用者物件)
const user = {
id: 123,
name: "John Doe",
email: "[email protected]",
profile: { /* 50 fields */ },
orders: [ /* 10 orders */ ]
};
基準測試(Node.js):
| 操作 | 時間 |
|-----------|------|
| 記憶體物件存取 | 0.001毫秒 |
| JSON.stringify() | 0.15毫秒 |
| JSON.parse() | 0.20毫秒 |
| 網路傳輸 | 0.50毫秒 |
每次通話總耗時| 0.85毫秒|
在一個包含 6 個服務的微服務鏈中:
Total serialization overhead: 6 × 0.85ms = 5.1ms
光是將資料轉換為 JSON 格式/從 JSON 格式轉換資料就花了 5 毫秒。
我並不是說「永遠不要使用微服務」。
在以下情況使用微服務:
例如:視訊串流平台
Video Upload Service: CPU-intensive (encoding)
→ Needs: 8 CPU cores, 4GB RAM
→ Scale: 5 instances
Metadata Service: Memory-intensive (search)
→ Needs: 2 CPU cores, 16GB RAM
→ Scale: 3 instances
Video Playback Service: I/O-intensive (CDN)
→ Needs: 1 CPU core, 2GB RAM
→ Scale: 20 instances
每項服務所需的資源各不相同。單體架構會造成資源浪費。
例如:一家擁有 100 多名工程師的公司
Team A: User Management (15 engineers)
Team B: Payment Processing (10 engineers)
Team C: Inventory (12 engineers)
Team D: Recommendations (8 engineers)
巨石:
100 位工程師修改同一份程式碼庫
每日合併衝突
部署協調噩夢
微服務:
團隊獨立部署
明確的所有權邊界
更快的迭代
門檻: 50名以上工程師共同開發相同產品。
例如:機器學習密集型應用
Web API: Node.js (familiar to web team)
ML Model Serving: Python (scikit-learn, TensorFlow)
Real-time Analytics: Go (performance)
Data Processing: Rust (memory safety)
單體架構:難以混合使用多種語言。
微服務:每個服務都使用最適合其工作的工具。
範例:醫療保健應用程式
PHI (Protected Health Information):
→ Strict audit logs
→ Encrypted at rest
→ Access controls
→ Isolated database
Non-PHI (Billing, Marketing):
→ Normal security
→ Shared database
分離式服務簡化了合規範圍。
兼具單體架構和微服務架構的優點。
┌─────────────────────────────────────┐
│ Application (Monolith) │
│ │
│ ┌─────────┐ ┌─────────┐ │
│ │ User │ │ Product │ │
│ │ Module │ │ Module │ │
│ └────┬────┘ └────┬────┘ │
│ │ │ │
│ ┌────┴────────────┴────┐ │
│ │ Shared Database │ │
│ └─────────────────────┘ │
└─────────────────────────────────────┘
關鍵原則:
模組之間透過介面(而非HTTP)進行通訊。
清晰的邊界(例如微服務)
共享資料庫(交易優勢)
單次部署(無網路開銷)
| 指標 | 微服務 | 模組化單體架構 | 改進 |
|--------|---------------|------------------|-------------|
| 延遲 (p50) | 18毫秒 | 12毫秒 |速度提升33% |
| 延遲 (p99) | 120毫秒 | 50毫秒 |速度提升58% |
| 吞吐量 | 8,500 請求/秒 | 10,000 請求/秒 |提高 18% |
| 記憶體 | 2GB | 512MB |減少 75% |
| 複雜度 | 高 | 中 | 低 |
好處:
✅ 快速(無需網路通話)
✅ 模組化(邊界清晰)
✅ 交易型(ACID 保證)
✅ 可除錯(單堆疊追蹤)
✅ 可測試(無需模擬服務)
權衡取捨:
⚠️ 單次部署(模組無法獨立擴充)
⚠️ 單一語言(通常)
⚠️共享資料庫(需要模式協調)
不要一夕之間將單體架構重寫為微服務架構。
標準:
獨立擴展需求
不同的技術要求
團隊邊界
合規隔離
例子:
Keep in monolith:
- User management
- Product catalog
- Order processing
Extract to services:
- Video encoding (CPU-intensive)
- Email sending (I/O-intensive)
- ML recommendations (Python-specific)
首先選擇風險最低的服務:
Before:
┌─────────────────┐
│ Monolith │
│ - Users │
│ - Products │
│ - Email │ ← Extract this
└─────────────────┘
After:
┌─────────────────┐ ┌─────────────┐
│ Monolith │────→│ Email │
│ - Users │ │ Service │
│ - Products │ └─────────────┘
└─────────────────┘
措施:
延遲影響
錯誤率變化
營運複雜性
如果收益小於成本:到此為止。
每月提取 1 項服務:
監控效能
衡量營運成本
驗證收益
停止條件:
複雜性大於其益處
團隊無法管理更多服務
性能下降
場景:每秒 10,000 個請求的應用程式
Application:
- 3x t3.large instances (4 CPU, 8GB) @ $0.0832/hr
= $180/month
Database:
- 1x db.r5.xlarge (4 vCPU, 32GB) @ $0.29/hr
= $210/month
Load Balancer:
- 1x ALB @ $20/month
= $20/month
Total: $410/month
Services (4 services × 3 instances):
- 12x t3.medium instances (2 CPU, 4GB) @ $0.0416/hr
= $360/month
Service Mesh:
- 12x sidecar proxies (overhead)
= +30% CPU = $108/month
Database:
- 1x db.r5.2xlarge (8 vCPU, 64GB) @ $0.58/hr
(needs more capacity for connection overhead)
= $420/month
Load Balancers:
- 1x ALB (external) @ $20/month
- 1x NLB (internal) @ $25/month
= $45/month
Service Discovery:
- Consul cluster (3 nodes) @ $30/month
= $30/month
Monitoring (per-service):
- Datadog/New Relic @ $100/month
= $100/month
Total: $1,063/month
對於相同的工作負載,微服務的成本高出 2.6 倍。
Error: Payment failed
at processPayment (payment.js:42)
at createOrder (order.js:18)
at handleCheckout (checkout.js:5)
at Router.post (/api/checkout)
除錯時間: 5 分鐘(請查看堆疊追蹤)
Error: Payment failed
Service: order-service
Trace ID: abc123
Span: checkout
↓ HTTP call (2ms)
Service: payment-service
Trace ID: abc123
Span: process_payment
↓ HTTP call (150ms)
Service: stripe-gateway
Trace ID: abc123
Error: Card declined
Total trace spans: 15
Services involved: 4
Debug time: 30 minutes (correlate logs across services)
所需其他工具:
分散式追蹤(Jaeger、Zipkin)
日誌聚合(ELK、Loki)
服務網格可觀測性(Istio、Linkerd)
成本:可觀測性堆疊每月 200-500 美元
是否應該使用微服務?
Do you have 50+ engineers?
├─ No → Monolith
└─ Yes
├─ Do services need independent scaling?
│ ├─ No → Modular Monolith
│ └─ Yes
│ ├─ Can you afford 2-3x infrastructure cost?
│ │ ├─ No → Monolith
│ │ └─ Yes
│ │ ├─ Can you afford performance degradation?
│ │ │ ├─ No → Monolith
│ │ │ └─ Yes → Microservices ✅
90% 的應用場景:單體架構或模組化單體架構
微服務並不能解決技術問題。
它們解決組織問題:
✅ 團隊自主性
✅ 獨立部署
✅ 所有權清晰
✅ 技術多樣性
如果沒有這些組織問題,你就不需要微服務。
微服務的優勢:
可擴展性
彈性
表現
微服務提供以下功能:
延遲增加(+50-150%)
更多故障(停機時間增加 5 倍)
更複雜(營運成本增加 10 倍)
但也:
團隊獨立性
更快的迭代速度(適用於大型團隊)
技術靈活性
權衡取捨是真實存在的,請慎重選擇。
圖書:
《建構微服務》,作者:Sam Newman
《從單體架構到微服務架構》,作者 Sam Newman(是的,是同一作者,正反雙方都是他寫的)
單體架構工具:
模組邊界:NX、Turborepo
測試:是的,劇作家
部署方式:Docker,單容器
微服務工具:
服務網格:Istio、Linkerd
描圖:Jaeger、Zipkin、Honeycomb
服務發現:Consul、Eureka
基準測試:
微服務新增:
延遲增加 50-150%(網路開銷)
資源使用率增加 300%(多實例)
運作複雜度增加 500%(分散式系統)
基礎設施成本的 2-3 倍
在以下情況使用微服務:
50多位工程師參與同一產品研發
獨立擴展要求
需要技術多樣性
合規隔離要求
否則:使用模組化單體架構。
你使用微服務架構和單體架構的經驗如何?在評論區分享你的效能資料吧! 👇
PS - 如果你想了解“模組化單體架構”或“微服務遷移的慘痛經歷”,請告訴我!
原文出處:https://dev.to/polliog/microservices-are-killing-your-performance-and-heres-the-math-21op