Arch Day 13: 微服务治理(高级)
微服务治理不是"拆出微服务"——那只是开始。治理是确保几十甚至几百个独立部署的服务能协调运行、可被观测、出错时优雅降级、并在不断演进中保持API兼容性的系统工程。拆分微服务需要1个月,治理好微服务需要1年。
日期: 2026-04-12 (Day 13) 阶段: 第一阶段 - 架构基础 标签: #微服务治理 #Service-Mesh #OpenTelemetry #Saga #熔断降级 #API版本
核心概念
一句话定义
微服务治理不是"拆出微服务"——那只是开始。治理是确保几十甚至几百个独立部署的服务能协调运行、可被观测、出错时优雅降级、并在不断演进中保持API兼容性的系统工程。拆分微服务需要1个月,治理好微服务需要1年。
为什么资深架构师仍需关注
做了10年软件、经历过微服务从"时髦"变成"标配"的人,最深刻的体会是:微服务的80%复杂度不在业务逻辑中,而在服务间的通信、一致性、可观测性和运维中。资深架构师需要:
- 选择合适的治理粒度:不是每个公司都需要Istio,不是每个系统都需要Saga
- 设计弹性模式:熔断、限流、降级不是"加个注解"那么简单,需要针对业务场景设计
- 分布式追踪策略:从"日志够用"到"能在5分钟内定位跨10个服务的故障链"
- API演进而非API革命:在不停机的情况下升级API,让新旧消费者共存
常见误区与反模式
| 误区 | 真相 | 后果 |
|---|---|---|
| "Service Mesh解决一切" | Service Mesh增加15-20%的延迟和大量运维成本 | 小团队被Mesh运维拖垮 |
| "所有通信都应该异步" | 异步增加了调试难度和最终一致性复杂度 | 无法追踪请求链路 |
| "Saga就是把事务拆开" | Saga需要设计补偿逻辑、幂等性、超时处理 | 数据不一致又无法排查 |
| "熔断器加上就好了" | 熔断阈值需要根据业务调优(不是默认值) | 误熔断导致正常请求被拒绝 |
| "API版本就是在URL加/v2" | URL版本化会导致路由爆炸和消费者迁移痛苦 | 永远有人在用/v1 |
| "分布式追踪=打印日志" | 追踪需要结构化的Trace/Span/Context传播 | 日志海洋中找不到关联 |
知识点详解
知识点1: 服务网格(Service Mesh)的架构价值和成本
什么是Service Mesh:
没有Service Mesh:
[Service A] ──HTTP/gRPC──→ [Service B]
(服务自己处理: 重试/超时/熔断/TLS/认证/追踪)
有了Service Mesh:
[Service A] → [Sidecar Proxy A] ──→ [Sidecar Proxy B] → [Service B]
│ │
└────[Control Plane]─────┘
(基础设施关注点被Sidecar代理)
核心价值: 将"服务间通信的复杂度"从应用代码中剥离出来
Istio vs Linkerd 深度对比:
| 维度 | Istio | Linkerd |
|---|---|---|
| 数据面 | Envoy Proxy (C++, 功能全) | linkerd2-proxy (Rust, 极轻量) |
| 控制面复杂度 | 高(Istiod集成了多个组件) | 低(设计简洁) |
| 资源消耗 | 每个Pod +50-100MB内存 | 每个Pod +10-20MB内存 |
| 延迟增加 | +2-5ms (P99) | +1-2ms (P99) |
| 功能丰富度 | 最全(流量管理/安全/可观测) | 核心功能(够用但不花哨) |
| 学习曲线 | 陡峭(需要Kubernetes深度知识) | 平缓(10分钟上手) |
| 适合团队 | 大团队(有专门的平台工程) | 中小团队(需要Mesh但不想太复杂) |
| 多集群支持 | 原生支持 | 需要额外配置 |
何时需要Service Mesh:
| 场景 | 需要Mesh? | 理由 |
|---|---|---|
| 服务<10个 | 否 | 在应用代码中处理足够了 |
| 服务10-50个 | 可选 | Linkerd级别的轻量Mesh |
| 服务50+个 | 是 | 不可能在每个服务中重复治理代码 |
| 需要mTLS认证 | 是 | Mesh自动管理证书比手动简单100倍 |
| 需要灰度发布 | 是 | 流量镜像/金丝雀/蓝绿部署 |
| 对延迟极敏感(<10ms) | 否 | Sidecar增加的延迟可能不可接受 |
知识点2: 分布式追踪(OpenTelemetry)
为什么微服务需要分布式追踪:
用户报告"页面加载慢"。在微服务架构中:
请求路径: Gateway → User Service → Order Service → Payment Service → Bank API
哪个服务慢?
- 看单个服务的日志?每个都说自己处理了5ms
- 但总耗时2秒
- 原因: 网络延迟 + 排队等待 + 某个服务的数据库查询慢
- 没有分布式追踪,根本无法定位
OpenTelemetry核心概念:
Trace (追踪): 一个请求从进入系统到响应的完整链路
│
├── Span (跨度): 链路中的一个操作(如一次HTTP调用、一次数据库查询)
│ ├── SpanId: 唯一标识
│ ├── ParentSpanId: 父Span(形成树结构)
│ ├── Attributes: 附加信息(HTTP method, DB query, etc.)
│ ├── Events: Span内的时间点事件
│ └── Status: OK / ERROR
│
└── Context Propagation (上下文传播):
TraceId在服务间传递(通过HTTP Header / gRPC Metadata)
示例:
Trace: abc123
├── Span: Gateway (0-2000ms)
│ ├── Span: UserService.getUser (10-50ms)
│ ├── Span: OrderService.createOrder (60-1800ms) ← 找到瓶颈!
│ │ ├── Span: DB.query (60-1600ms) ← 数据库查询慢!
│ │ └── Span: PaymentService.charge (1610-1790ms)
│ └── Span: NotificationService.send (1810-1850ms)
OpenTelemetry实践要点:
// 自动检测(Auto-instrumentation) - 最小侵入性
// 大部分框架(Express/NestJS/Spring)都有自动探针
// 手动检测(Manual instrumentation) - 精细控制
import { trace, SpanKind, SpanStatusCode } from '@opentelemetry/api';
const tracer = trace.getTracer('payment-service');
async function processPayment(orderId: string, amount: Money) {
const span = tracer.startSpan('processPayment', {
kind: SpanKind.INTERNAL,
attributes: {
'order.id': orderId,
'payment.amount': amount.toDisplayString(),
'payment.currency': amount.currency.code,
}
});
try {
// 业务逻辑
const result = await chargeCard(orderId, amount);
span.setAttributes({
'payment.status': result.status,
'payment.transaction_id': result.transactionId,
});
span.setStatus({ code: SpanStatusCode.OK });
return result;
} catch (error) {
span.setStatus({
code: SpanStatusCode.ERROR,
message: error.message,
});
span.recordException(error);
throw error;
} finally {
span.end();
}
}
追踪数据的存储和查询:
| 工具 | 特点 | 适合场景 |
|---|---|---|
| Jaeger | 开源、Uber开发、K8s友好 | 中小规模微服务 |
| Zipkin | 开源、轻量、Java生态 | Spring Cloud生态 |
| Grafana Tempo | 开源、与Grafana集成好 | 已用Grafana的团队 |
| Datadog APM | SaaS、功能全 | 有预算的团队 |
| AWS X-Ray | AWS原生 | AWS生态 |
知识点3: 熔断/限流/降级策略
三者的区别和关系:
限流(Rate Limiting): 控制流入的请求数量
├── 目的: 保护服务不被流量打垮
├── 位置: 通常在网关或服务入口
└── 策略: 固定窗口/滑动窗口/令牌桶/漏桶
熔断(Circuit Breaker): 当下游服务故障时快速失败
├── 目的: 防止故障级联(服务A调服务B,B挂了→A也被拖垮)
├── 位置: 在调用方(而非被调用方)
└── 状态: Closed(正常) → Open(熔断) → Half-Open(试探)
降级(Degradation/Fallback): 当服务不可用时提供替代方案
├── 目的: 保证核心功能可用
├── 位置: 在调用方
└── 策略: 返回缓存/返回默认值/返回简化功能
熔断器详细设计(Resilience4j模式):
状态转换:
[Closed] ──失败率超阈值──→ [Open]
↑ │
│ 等待超时时间
│ │
│ ▼
└──试探请求成功──── [Half-Open]
│
试探请求失败
│
▼
[Open]
关键参数:
├── failureRateThreshold: 失败率阈值(如50%)
├── slowCallRateThreshold: 慢调用率阈值(如100%)
├── slowCallDurationThreshold: 多慢算慢(如3秒)
├── minimumNumberOfCalls: 最少调用数才统计(如10)
├── slidingWindowSize: 统计窗口大小(如100次调用)
├── waitDurationInOpenState: 熔断持续时间(如60秒)
└── permittedNumberOfCallsInHalfOpenState: 试探请求数(如3)
// 实际应用示例
class PaymentGatewayClient {
private circuitBreaker: CircuitBreaker;
constructor() {
this.circuitBreaker = CircuitBreaker.create({
name: 'payment-gateway',
failureRateThreshold: 50, // 50%失败率触发熔断
slowCallDurationThreshold: 3000, // 3秒算慢调用
waitDurationInOpenState: 30000, // 熔断30秒
slidingWindowSize: 20, // 统计最近20次调用
});
}
async charge(request: ChargeRequest): Promise<ChargeResult> {
return this.circuitBreaker.execute(
// 正常路径
async () => {
return await this.httpClient.post('/charge', request);
},
// 降级路径(熔断时执行)
async () => {
// 方案A: 排入异步队列稍后重试
await this.retryQueue.enqueue(request);
return ChargeResult.pending("Payment queued for retry");
// 方案B: 切换到备用支付通道
// return await this.backupGateway.charge(request);
// 方案C: 返回缓存的预授权结果
// return await this.cache.get(`preauth:${request.orderId}`);
}
);
}
}
降级策略设计框架:
| 服务 | 降级策略 | 用户感知 |
|---|---|---|
| 推荐服务 | 返回热门商品(缓存) | 低("推荐不准但有东西看") |
| 搜索服务 | 返回缓存结果/简化搜索 | 中("搜索结果不是最新的") |
| 支付服务 | 排队/切换备用通道 | 高(需要明确通知用户) |
| 认证服务 | 不能降级 | - (核心安全功能) |
| 日志服务 | 丢弃日志/写本地 | 无(用户不感知) |
知识点4: Saga——编排(Orchestration) vs 协调(Choreography)
为什么需要Saga:
微服务中没有分布式事务(2PC的性能和可用性都不行)。
Saga是替代方案: 将一个跨服务事务拆成多个本地事务,
每个本地事务有对应的补偿操作。如果某步失败,执行之前所有步骤的补偿。
例: 下单流程
T1: 创建订单 (补偿: 取消订单)
T2: 扣减库存 (补偿: 恢复库存)
T3: 扣款 (补偿: 退款)
T4: 发送确认 (无需补偿)
如果T3(扣款)失败:
执行 C2(恢复库存) → C1(取消订单)
编排式Saga (Orchestration):
有一个中心协调器(Orchestrator)控制整个流程:
[Saga Orchestrator]
│
├── Step 1: 命令 → Order Service → 创建订单
│ ← 响应: 订单已创建
│
├── Step 2: 命令 → Inventory Service → 扣减库存
│ ← 响应: 库存已扣减
│
├── Step 3: 命令 → Payment Service → 扣款
│ ← 响应: 扣款失败!
│
├── 补偿 Step 2: 命令 → Inventory Service → 恢复库存
│ ← 响应: 库存已恢复
│
└── 补偿 Step 1: 命令 → Order Service → 取消订单
← 响应: 订单已取消
协调式Saga (Choreography):
没有中心协调器,每个服务监听事件并自行决定下一步:
Order Service:
发出 [OrderCreated] 事件
Inventory Service:
监听 [OrderCreated] → 扣减库存 → 发出 [InventoryReserved]
Payment Service:
监听 [InventoryReserved] → 扣款 → 发出 [PaymentCompleted]
或 → 发出 [PaymentFailed]
Inventory Service:
监听 [PaymentFailed] → 恢复库存 → 发出 [InventoryReleased]
Order Service:
监听 [InventoryReleased] → 取消订单
深度对比:
| 维度 | 编排(Orchestration) | 协调(Choreography) |
|---|---|---|
| 流程可见性 | 高(在Orchestrator中看到完整流程) | 低(分散在各服务中) |
| 耦合度 | Orchestrator与所有服务耦合 | 服务之间通过事件松耦合 |
| 复杂度位置 | 集中在Orchestrator | 分散在各服务 |
| 调试难度 | 中(跟踪Orchestrator状态) | 高(跟踪事件链) |
| 单点故障 | Orchestrator是单点 | 无单点 |
| 适合步骤数 | 5-10步 | 3-5步 |
| 适合变更频率 | 流程经常变 → Orchestration | 流程稳定 → Choreography |
| 补偿逻辑 | 在Orchestrator中统一管理 | 分散在各服务 |
我的经验法则:
步骤少(≤4步) + 流程稳定 → Choreography
步骤多(>4步) + 流程复杂/常变 → Orchestration
金融场景(要求精确补偿) → Orchestration (可追踪性更重要)
知识点5: API版本演进策略
三种主流方案:
方案1: URL Path版本化
GET /api/v1/users/123
GET /api/v2/users/123
优点: 简单直观,路由清晰
缺点: URL变了=新资源,缓存策略复杂,消费者必须改代码
方案2: Header版本化
GET /api/users/123
Accept: application/vnd.company.v2+json
优点: URL稳定,版本信息在元数据中
缺点: 不直观,测试不方便(浏览器难以指定Header)
方案3: Consumer-Driven Contracts (消费者驱动契约)
不用显式版本号,通过契约测试保证兼容性
优点: 最灵活,向后兼容自动验证
缺点: 需要契约测试框架(Pact等)和团队纪律
API演进的最佳实践:
规则1: 永远不要Breaking Change
├── 只增加字段,不删除/重命名
├── 新增endpoint而非修改旧的
├── 使用可选字段(nullable)而非必填
└── 枚举值只增加不减少
规则2: 如果必须Breaking Change
├── 同时运行新旧版本(至少3个月)
├── 在旧版本加deprecation header
├── 提供迁移指南
├── 监控旧版本的调用量,降到0再下线
└── 在changelog中明确标注breaking change
规则3: 内部服务 vs 外部API
├── 内部服务: 可以更激进,契约测试+同步升级
├── 外部API: 必须保守,永远不删旧版本(或至少12个月过渡)
对比分析
微服务通信模式对比
| 模式 | 延迟 | 耦合 | 可靠性 | 适用场景 |
|---|---|---|---|---|
| 同步REST | 低 | 高(时间耦合) | 中 | 读操作、简单查询 |
| 同步gRPC | 更低 | 高 | 中 | 内部服务间高频调用 |
| 异步消息队列 | 高(但解耦) | 低 | 高(有持久化) | 写操作、事件通知 |
| 异步事件流(Kafka) | 中 | 低 | 高 | 数据流、日志、审计 |
| GraphQL Federation | 中 | 中 | 中 | BFF层、多服务数据聚合 |
Saga实现技术对比
| 技术 | 类型 | 复杂度 | 适合 |
|---|---|---|---|
| Temporal | Orchestration | 中 | 通用工作流 |
| AWS Step Functions | Orchestration | 低 | AWS生态 |
| Camunda | Orchestration | 中-高 | BPMN流程 |
| Kafka + 状态机 | Choreography | 高 | 高吞吐事件驱动 |
| 自研Orchestrator | Orchestration | 最高 | 特殊需求 |
架构设计实操
实操: "支付平台"微服务方案设计
业务背景: 设计一个支持多渠道(网页/APP/API)、多支付方式(银行卡/钱包/加密货币)的支付平台。
服务拆分:
1. Gateway Service (API网关)
└── 认证、路由、限流、日志
2. Payment Order Service (支付订单)
└── 创建/查询支付订单、状态管理
3. Payment Processing Service (支付处理)
└── 路由到具体支付通道、执行扣款
4. Channel Adapter Service (通道适配)
└── 对接各银行/钱包/加密支付网关
5. Account Service (账户)
└── 内部账户余额、钱包余额
6. Risk Service (风控)
└── 交易风控评估
7. Notification Service (通知)
└── 支付结果通知(短信/Push/Webhook)
8. Reconciliation Service (对账)
└── 与外部通道对账
服务通信矩阵:
| 调用方 | 被调用方 | 通信方式 | 原因 |
|---|---|---|---|
| Gateway | Payment Order | 同步REST | 用户等待响应 |
| Payment Order | Risk | 同步gRPC | 风控结果决定是否继续 |
| Payment Order | Payment Processing | 异步消息 | 处理可能耗时 |
| Payment Processing | Channel Adapter | 同步HTTP | 需要实时结果 |
| Payment Processing | Account | 同步gRPC | 扣款需要同步确认 |
| Payment Processing | Notification | 异步消息 | 通知不影响主流程 |
| Reconciliation | 所有 | 异步批处理 | 定时对账 |
Saga设计(支付流程):
使用编排式Saga(步骤>4步,且需要精确补偿):
PaymentSagaOrchestrator:
Step 1: 创建支付订单
→ Payment Order Service: createOrder()
← OrderCreated(orderId)
补偿: cancelOrder(orderId)
Step 2: 风控评估
→ Risk Service: assess(orderId, amount, user)
← RiskAssessed(riskLevel)
补偿: 无(读操作不需要补偿)
如果riskLevel=HIGH → 直接拒绝,补偿Step 1
Step 3: 冻结余额(如果是钱包支付)
→ Account Service: freezeBalance(accountId, amount)
← BalanceFrozen(freezeId)
补偿: unfreezeBalance(freezeId)
Step 4: 执行扣款
→ Payment Processing: charge(channelId, amount)
← ChargeResult(transactionId)
补偿: refund(transactionId)
Step 5: 确认入账
→ Account Service: confirmDebit(freezeId)
← DebitConfirmed
Step 6: 发送通知
→ Notification Service: notify(orderId, result)
补偿: 无(通知不需要补偿)
API版本演进计划:
## 支付API版本策略
### 当前: v1 (稳定)
POST /api/v1/payments
{
"amount": 100.00, // 注意: v1用float,这是设计缺陷
"currency": "USD",
"method": "card",
"card_token": "tok_xxx"
}
### 计划: v2 (金额精度修复)
POST /api/v2/payments
{
"amount": { // 改为对象,支持精确金额
"value": "100.00", // 字符串避免精度丢失
"currency": "USD"
},
"method": "card",
"card_token": "tok_xxx",
"idempotency_key": "idem_xxx" // v2新增幂等键
}
### 迁移计划
1. v2上线后v1继续运行12个月
2. v1响应头加 Deprecation: true, Sunset: 2027-04-12
3. 发布迁移指南
4. 监控v1调用量,每月通知仍在使用v1的消费者
5. v1调用量降到0后下线
ADR
# ADR-004: 支付平台Saga模式选择
## 状态: 已接受
## 上下文
支付流程涉及6个步骤和5个服务,需要保证数据一致性和可追踪性。
## 考虑的方案
1. Choreography (事件驱动)
2. Orchestration (中心协调器)
3. 2PC (分布式事务)
## 决策
选择Orchestration,使用Temporal作为Saga引擎。
## 理由
- 支付流程步骤多(6步)且可能变化(如增加合规检查步骤)
- 金融场景需要精确的补偿追踪和审计日志
- Choreography在5+个服务时调试极其困难
- 2PC性能差且不适合微服务
- Temporal提供了可靠的工作流引擎,支持重试、超时、补偿
## 后果
- 引入Temporal基础设施(需要运维)
- Orchestrator成为核心组件(需要高可用保障)
- 所有Saga流程在Temporal中可视化(利于审计)
AI增强实践
AI在微服务治理中的应用
1. 分布式追踪分析
Prompt: "以下是一个请求的分布式追踪数据(Jaeger格式):
[粘贴trace数据]
请分析:
1. 哪个服务/操作是性能瓶颈?
2. 是否有不必要的串行调用可以并行化?
3. 是否有重复调用(同一个服务被调了多次)?
4. 建议的优化方向?"
2. 熔断参数调优
Prompt: "我的支付服务调用银行API,统计数据如下:
- 平均响应时间: 500ms
- P99响应时间: 2000ms
- 错误率: 2% (正常时)
- 错误率: 40% (故障时)
- 请求量: 100 QPS
请帮我设计熔断器参数:
- failureRateThreshold
- slowCallDurationThreshold
- slidingWindowSize
- waitDurationInOpenState
并解释每个参数的选择理由。"
3. Saga补偿逻辑审查
Prompt: "以下是我的支付Saga流程和补偿逻辑:
[描述步骤和补偿]
请审查:
1. 是否所有步骤都有对应的补偿?
2. 补偿执行顺序是否正确(应该反序)?
3. 补偿操作是否幂等?
4. 超时场景是否处理了?
5. 是否有遗漏的边界情况?"
AI vs 人工边界:
| 任务 | AI能力 | 人工不可替代 |
|---|---|---|
| 追踪数据分析 | 优秀 | - |
| 熔断参数推荐 | 良好(需要实际验证) | 生产环境的真实负载特征 |
| Saga设计审查 | 优秀 | 业务异常场景的完整性 |
| Service Mesh选型 | 良好 | 团队运维能力评估 |
| API设计审查 | 优秀 | - |
与Web3/DeFi的关联
| 传统微服务概念 | Web3对应 | 关键差异 |
|---|---|---|
| 服务网格 | 区块链网络(P2P Mesh) | 链网络本身就是去中心化的Mesh |
| 分布式追踪 | 区块浏览器(Etherscan) | 链上交易天然可追踪 |
| 熔断器 | DeFi协议的暂停机制(Pausable) | 合约可以有紧急暂停功能 |
| Saga补偿 | 链上回滚(revert) + 闪电贷 | 同一区块内原子执行,无需补偿 |
| API版本 | 合约升级(Proxy Pattern) | 链上API(合约接口)升级更复杂 |
| 限流 | Gas机制 | Gas天然限流(出块容量有限) |
| 降级 | L2/侧链 | 主链拥堵时用L2作为"降级"路径 |
深度洞察:DeFi的"Saga"问题
传统Saga:
Step 1: 扣款 → Step 2: 转账 → Step 3: 通知
如果Step 2失败 → 补偿Step 1(退款)
DeFi优势: 原子性
在一个交易中: approve → swap → transfer
如果任何一步失败 → 整个交易revert(自动补偿)
但DeFi也有"Saga"问题:
跨链操作(Bridge):
Step 1: 在链A锁定资产
Step 2: 在链B铸造资产
如果Step 2失败 → 需要在链A解锁(类似Saga补偿)
这就是跨链桥被黑客攻击的核心风险之一
今日思考
-
你经历过最难排查的分布式系统故障是什么? 如果当时有完善的分布式追踪,排查时间能缩短多少?你的团队现在的可观测性水平如何——是"有日志就行"还是"有完整的Trace链路"?
-
Saga的补偿逻辑真的能保证数据一致吗? 如果补偿操作本身也失败了怎么办?在金融系统中,"补偿失败"是一个必须处理的场景。你会怎么设计"补偿的补偿"?
-
DeFi的原子性 vs 传统微服务的最终一致性,谁更好? 链上交易的原子性消除了Saga的需要,但也限制了跨链操作。传统微服务的最终一致性更灵活但更复杂。有没有可能将链上的原子性思想应用到传统微服务中?
面试题准备
Q1: Saga编排和协调各适合什么场景?
30秒版本: 编排(Orchestration)适合步骤多、流程复杂、需要精确追踪的场景,如金融支付;协调(Choreography)适合步骤少、流程稳定、追求松耦合的场景,如订单通知。核心区别是复杂度集中在一处(编排)还是分散在各服务(协调)。
2分钟版本:
编排式Saga有一个中心协调器控制整个流程。优点是流程可视化、补偿逻辑集中管理、容易添加新步骤;缺点是协调器成为单点和瓶颈。适合金融支付这类需要精确审计追踪的场景。
协调式Saga没有中心,每个服务监听事件并自行决定下一步。优点是高度解耦、无单点;缺点是流程分散在各服务中难以追踪,补偿逻辑也分散。适合通知、日志等步骤少且不需要精确补偿的场景。
我的实际经验是:大多数金融场景选编排。原因是金融场景的补偿逻辑非常复杂(退款不只是"反向转账",还涉及手续费、汇率差、记账调整等),这些逻辑放在一个地方管理比分散在各服务中更安全也更容易审计。
追问准备:
追问: "如何做微服务间的数据一致性?" 回答: 首先接受一个前提——微服务中不追求强一致性(那是单体的优势)。在此基础上,用三种手段保证最终一致性:一是Saga模式处理跨服务事务;二是事件溯源保证事件不丢失;三是对账机制作为最后防线——定期比对各服务的数据,发现不一致时告警和修复。在金融场景中,对账是必不可少的兜底。
Q2: 如何设计微服务的熔断降级策略?
30秒版本: 先分级——哪些服务是核心(不能降级)、哪些是增强(可降级)。核心服务出问题用熔断防止级联,增强服务出问题用降级提供替代方案。熔断参数需要根据实际SLA调优,不是用默认值。降级方案要在平时就准备好,不是出问题了才想。
2分钟版本:
设计分四步。
第一步,服务分级。P0服务(如认证、支付核心)不能降级,必须保证高可用(多副本/多区)。P1服务(如风控、账户查询)可以短暂降级(返回缓存/默认值)。P2服务(如推荐、通知)可以长期降级(不影响核心功能)。
第二步,熔断配置。根据上游服务的SLA设置:正常错误率2%→熔断阈值设30%(给10倍余量);正常P99延迟500ms→慢调用阈值设2000ms(给4倍余量)。窗口大小根据QPS设置——QPS=100时窗口设20(200ms数据),确保统计有效性。
第三步,降级方案预制。每个非P0服务都要有"Plan B":缓存兜底(推荐服务降级返回热门列表)、默认值(风控降级返回中风险)、功能裁剪(搜索降级只支持精确匹配)。这些方案要在开发时就实现,不是事故时临时写。
第四步,演练。定期做混沌工程——随机关闭某个服务,验证熔断和降级是否按预期工作。Netflix的Chaos Monkey就是这个思路。
学习资源
- 《Building Microservices, 2nd Edition》 - Sam Newman - 微服务治理的综合指南
- 《Release It!, 2nd Edition》 - Michael Nygard - 稳定性模式(熔断/超时/隔板)的经典
- OpenTelemetry官方文档 - https://opentelemetry.io/docs/
- Temporal官方文档 - https://docs.temporal.io/ (Saga/工作流引擎)
- Resilience4j文档 - https://resilience4j.readme.io/
- Netflix技术博客 - 微服务治理的先驱实践
明日预告
Day 14: 架构风格混合实战 —— 真实系统从不只用一种风格。明天我们将学习如何在一个系统中混合多种架构风格,使用架构决策矩阵方法,研究Cell-Based Architecture(蚂蚁/微众银行的实践),并完成Week 2的总结。实操:设计一个"全渠道零售系统"的混合架构,包含ADR和个人架构判断力清单。