🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付

微服務的優點在於:它能讓你的系統具有可擴展性、可維護性和速度。

現實情況是:對於大多數系統而言,微服務會增加延遲、複雜性和故障點,而不會帶來任何實質的好處。

讓我們來看看實際數字。


網路呼叫的效能成本

根本問題在於:微服務透過網路進行通訊。而網路速度很慢。

延遲比較

進程內函數呼叫(單體式):

Function call: 0.001ms (1 microsecond)

同一資料中心內的HTTP呼叫(微服務):

HTTP request: 1-5ms (1,000-5,000 microseconds)

那速度慢了1000倍到5000倍。

真實案例

場景:電子商務結帳流程

所需操作:

  1. 驗證使用者會話

  2. 檢查產品庫存

  3. 計算運費

  4. 處理付款

  5. 建立訂單記錄

  6. 發送確認郵件

單體架構:

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 查詢。微服務包含 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 實例

架構 1:單體架構

┌─────────────────┐
│   Application   │
│   (Node.js)     │
│                 │
│  ┌───────────┐  │
│  │ Database  │  │
│  │ (Postgres)│  │
│  └───────────┘  │
└─────────────────┘

配置:

  • 單一 Node.js 進程

  • 連接池(20 個連接)

  • Redis 快取(同一實例)

架構2:微服務

┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐
│  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% |

主要發現:

  1. 尾部延遲受影響最大(p99:+140%)

  2. 資源使用量急劇增加

  3. 儘管具有“可擴展性”,但吞吐量卻下降了。


網路開銷分解

讓我們來分析一下微服務呼叫中時間都花在了哪裡。

服務間呼叫的剖析

總耗時:約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)

問題:

  1. 連線耗盡速度更快

  2. 鎖爭用增加(並發事務增加)

  3. 查詢快取效率較低(不同服務的存取模式不同)

績效影響

測試: 1000 個並髮用戶

| 架構 | 連線數 | 鎖定等待時間 | 查詢時間 |

|--------------|--------------------|----------------|------------|

| 單體 | 20-30 | 5毫秒 | 10毫秒 |

| 微服務 | 60-80 | 25毫秒 | 18毫秒 |

微服務使用 3 倍的連線數,並且存在 5 倍的鎖定爭用。


序列化開銷

每次網路呼叫都需要序列化/反序列化。

JSON 序列化成本

測試:序列化典型的 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 毫秒。


微服務何時真正適用

我並不是說「永遠不要使用微服務」。

在以下情況使用微服務:

1. 獨立擴展要求

例如:視訊串流平台

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

每項服務所需的資源各不相同。單體架構會造成資源浪費。

2. 團隊邊界

例如:一家擁有 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名以上工程師共同開發相同產品。

3. 技術多樣性

例如:機器學習密集型應用

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)

單體架構:難以混合使用多種語言。

微服務:每個服務都使用最適合其工作的工具。

4. 合規要求

範例:醫療保健應用程式

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    │           │
│  └─────────────────────┘            │
└─────────────────────────────────────┘

關鍵原則:

  1. 模組之間透過介面(而非HTTP)進行通訊。

  2. 清晰的邊界(例如微服務)

  3. 共享資料庫(交易優勢)

  4. 單次部署(無網路開銷)

效能比較

| 指標 | 微服務 | 模組化單體架構 | 改進 |

|--------|---------------|------------------|-------------|

| 延遲 (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)

第二階段:提取一項服務(第 2-3 個月)

首先選擇風險最低的服務:

Before:
┌─────────────────┐
│   Monolith      │
│  - Users        │
│  - Products     │
│  - Email        │ ← Extract this
└─────────────────┘

After:
┌─────────────────┐     ┌─────────────┐
│   Monolith      │────→│   Email     │
│  - Users        │     │  Service    │
│  - Products     │     └─────────────┘
└─────────────────┘

措施:

  • 延遲影響

  • 錯誤率變化

  • 營運複雜性

如果收益小於成本:到此為止。

第三階段:逐步擷取(第 4-6 個月)

每月提取 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

基準測試:

  • k6 - 負載測試

  • 火砲- 性能測試


太長不看

微服務新增:

  • 延遲增加 50-150%(網路開銷)

  • 資源使用率增加 300%(多實例)

  • 運作複雜度增加 500%(分散式系統)

  • 基礎設施成本的 2-3 倍

在以下情況使用微服務:

  • 50多位工程師參與同一產品研發

  • 獨立擴展要求

  • 需要技術多樣性

  • 合規隔離要求

否則:使用模組化單體架構。


你使用微服務架構和單體架構的經驗如何?在評論區分享你的效能資料吧! 👇

PS - 如果你想了解“模組化單體架構”或“微服務遷移的慘痛經歷”,請告訴我!


原文出處:https://dev.to/polliog/microservices-are-killing-your-performance-and-heres-the-math-21op


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝8   💬7   ❤️2
212
🥈
我愛JS
💬1  
6
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付