This repository has been archived on 2026-05-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
all-in-kingsoft/hhs/MS/02-服务治理/08-流量治理.md
T
2026-05-17 22:00:24 +08:00

285 lines
9.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
tags: [microservice, canary-release, blue-green, traffic-routing, istio, load-balancing]
create time: 2026-05-05 10:30
---
# 流量治理
## 概述
灰度发布(也叫金丝雀发布)是降低变更风险的核心手段。它让你将新版本逐步推向一小部分用户,观察指标正常后再全量。
> [!question] 如何安全地上线?
> 你修复了一个紧急 Bug,但这次改动涉及核心支付链路。直接全量发布一旦出问题损失巨大。有没有办法先小范围验证,确认没问题再放量?
答案就是**按规则拆分流量**——将请求按照不同维度分配到新旧版本,用真实用户的流量来检验新代码,而不是靠测试环境的人为模拟。
```mermaid
flowchart LR
A["🟢 v1 (稳定版)<br/>95% 流量"] --> B["🔵 v2 (测试版)<br/>5% 流量"]
B --> C{"监控指标?"}
C -- "✅ 一切正常" --> D["逐步放量<br/>10% → 25% → 50%"]
C -- "❌ 错误率飙升" --> E["自动回滚到 v1 🔄"]
D --> F{"全部放量至 100%"}
F --> G["🟢 v2 成为新稳定版"]
```
## 一、灰度策略全景
### 常见灰度策略对比
| 策略 | 描述 | 优点 | 缺点 | 适用场景 |
|------|------|------|------|---------|
| **按百分比** | 随机分配 N% 流量到新版本 | 简单粗暴,覆盖面广 | 可能只命中特定用户 | 通用场景 |
| **按用户 ID** | 指定用户/内部账号走新版 | 可精准控制测试范围 | 样本不够代表性 | 内部验收阶段 |
| **按 Header** | `x-canary: true` 路由到新版本 | 灵活性最高 | 需要客户端配合 | QA / AB 测试 |
| **按地域** | 某个城市/机房的新版本 | 地域性问题的理想试验场 | 地域偏差大 | 全球化部署 |
| **按设备类型** | iOS 新用户先用新版 | 覆盖目标人群 | 样本有限 | 移动端发版 |
> [!tip] 实战建议:多策略组合
> 生产环境中通常不会只用单一规则。推荐的做法是分层判断:
>
> ```
> 第1层:内部员工 IP → 100% 进灰度(快速发现 bug)
> 第2层:header x-canary=true → 100% 进灰度(QA 验证)
> 第3层:新注册用户 → 50% 进灰度(扩大样本)
> 第4层:其余用户 → 默认 v1
> ```
### 按权重分流的 Go 实现
在应用层面(如 go-zero 或自研网关),流量分配往往通过中间件实现:
```go
// CanaryMiddleware: header 携带 canary=true 的请求直通灰度版本
func (m *CanaryMiddleware) Next(ctx context.Context, req any, reply any, rpc func(context.Context, any, any) error) error {
if m.r.isGray(ctx) { // 从 header/context 提取灰度标记
return m.grayHandler(ctx, req, reply) // 路由到灰度服务实例
}
return m.next(ctx, req, reply) // 走正常路径
}
```
### 客户端负载均衡中的灰度
客户端侧的灰度通常通过自定义负载算法实现,以加权轮询为例:
```go
// WeightedRoundRobin: 权重感知轮询
type WeightedRoundRobin struct {
servers []*Server // 包含 weight 字段
totalWeight int
}
func (w *WeightedRoundRobin) Next() (*Server, error) {
// 每次选取当前权重最高的可用服务器
// v1 权重 95, v2 权重 5 → 平均每 20 次请求 1 次命中 v2
}
```
## 二、蓝绿 vs 灰度
> [!summary] 两种发布策略对比
>
> | 维度 | 蓝绿部署 | 灰度发布 (金丝雀) |
> |------|---------|-----------------|
> | **切换方式** | 一次性全切 | 逐步放量 |
> | **资源消耗** | 双倍(新旧并行) | 初期少量副本 |
> | **回滚速度** | 秒级(切回 LB 即可) | 同样秒级 |
> | **风险等级** | 中高(全量暴露问题) | 低(渐进式) |
> | **适合场景** | 大型变更、重大版本 | 日常迭代、高风险链路 |
### 蓝绿部署流程
```mermaid
stateDiagram-v2
[*] --> Blue: 初始状态
Blue --> DeployGreen: 部署 v2 到 Green 环境
DeployGreen --> TestGreen: 验证 Green
TestGreen --> Switch: 切换入口流量
Switch --> Green: 全部流量到 Green/v2
Green --> CleanupBlue: 删除 Blue/v1
CleanupBlue --> [*]
```
### 金丝雀发布流程
```mermaid
graph TB
S1["v1 运行中<br/>100% 流量"]
S2["部署 v2<br/>5% 流量"]
S3["监控 15min"]
S4{"P99 延迟 < SLA?"}
S4 -- 否 --> Rollback["回滚 v2 🔄"]
S4 -- 是 --> S5["放量 25%"]
S5 --> S6["监控 30min"]
S6 --> S7{"错误率 < 0.1%?"}
S7 -- 否 --> Rollback
S7 -- 是 --> S8["放量 50%"]
S8 --> S9["监控 1h"]
S9 --> S10{"全项达标?"}
S10 -- 是 --> S11["100% 全量 ✅"]
S10 -- 否 --> Rollback
style Rollback fill:#ffebee
style S11 fill:#e8f5e9
```
> [!warning] 关键决策点
> 每个放量节点都是一个"继续 or 回滚"的决策门控。不要跳过任何一步,哪怕之前几轮都顺利通过。历史教训表明:**很多事故发生在最后一跳**。
## 三、高级路由规则
### Istio VirtualService
Istio 作为 Service Mesh 方案,流量治理能力强大但侵入性也更高。适合已有 K8s + Istio 基础设施的团队。
```yaml
# 灰度规则:header 携带 canary=true 的用户走 v2
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: order-route
spec:
hosts: ["order-service"]
http:
# 灰度规则
- match:
- headers:
x-canary:
exact: "true"
route:
- destination:
host: order-service
subset: v2
weight: 100
# 默认:全部走 v1
- route:
- destination:
host: order-service
subset: v1
weight: 100
```
### 权重路由示例
```yaml
# 按比例分流
http:
- route:
- destination:
host: order-service
subset: v1
weight: 90
- destination:
host: order-service
subset: v2
weight: 10
```
### 网关层 vs Sidecar 层
流量治理可以在两个不同的层级实现,选择取决于团队的基础设施成熟度:
```mermaid
flowchart TD
subgraph "网关层(中心化)"
GW["API Gateway<br/>集中管理路由规则"]
GW --> V1[[v1 实例集群]]
GW --> V2[[v2 实例集群]]
end
subgraph "Sidecar 层(分布式)"
GW2["API Gateway<br/>只做转发"]
GW2 --> ProxyV1["Envoy Sidecar<br/>本地执行路由规则"]
GW2 --> ProxyV2["Envoy Sidecar<br/>本地执行路由规则"]
ProxyV1 --> ContainerV1[[v1 容器]]
ProxyV2 --> ContainerV2[[v2 容器]]
end
```
| 维度 | 网关层治理 | Sidecar 层治理 |
|------|-----------|---------------|
| **复杂度** | 配置统一,易维护 | 需理解 Mesh 概念 |
| **性能** | 单点瓶颈风险 | 就近处理,开销更低 |
| **灵活性** | 依赖网关插件能力 | Istio 支持更丰富的规则 |
| **学习曲线** | 低 | 高 |
| **适用团队** | 中小型、快速起步 | 大规模微服务集群 |
> [!note] 选型建议
> - **初创期**:直接在网关或应用层做路由分发即可,不必引入 Service Mesh
> - **成长期**:当服务数量超过 30+、跨团队协作复杂时,考虑用 Istio 统一管理
> - **混合模式**:网关层做简单的按路径/权重分发,Sidecar 层做精细的 header/metadata 路由
## 四、流量治理的其他维度
除了发布策略,流量治理还包括:
| 能力 | 说明 | 关联文档 |
|------|------|---------|
| **熔断降级** | 下游不可用时自动降级 | [[02-服务治理/06-容错模式]] |
| **限流** | 保护上游不因过量请求被打垮 | [[02-服务治理/06-容错模式]] |
| **重试** | 对瞬态故障自动恢复 | [[02-服务治理/06-容错模式]] |
| **黑白名单** | IP 级别访问控制 | — |
| **A/B Testing** | 基于用户分组的长期实验 | — |
## 五、灰度发布的量化决策依据
> [!tip] 必须有可量化的观测指标作为决策依据
>
> 不要凭感觉放量,让数据说话:
>
> | 指标 | 阈值参考 | 告警级别 |
> |------|---------|---------|
> | **错误率** | < 0.1% (v1 baseline 对比) | > 1% 立即回滚 |
> | **P99 延迟** | ≤ v1 × 1.1 | > v1 × 1.3 暂停放量 |
> | **CPU/Memory** | 在 limits 的 70% 以内 | > 85% 扩容 |
> | **下游依赖成功率** | > 99.5% | < 95% 熔断 |
### 灰度监控面板设计要点
一个完整的灰度面板应该能一眼看出新旧版本的差异:
```mermaid
flowchart LR
subgraph RealTime["实时对比视图"]
R1["📊 P99 延迟趋势<br/>v1 vs v2 双线对比"]
R2["🔴 错误率柱状图<br/>区分 HTTP 状态码分类"]
R3["⚡ QPS 流量分布<br/>按版本分堆叠面积图"]
end
subgraph HealthCheck["健康检查"]
H1["✅ 版本 v1 正常运行<br/>副本数: 10/10"]
H2["⚠️ 版本 v2 异常<br/>副本数: 2/5 · 失败: 3"]
end
RealTime --> Decision["🎯 是否继续放量?"]
HealthCheck --> Decision
Decision -- "指标超标" --> Rollback["触发自动回滚"]
Decision -- "指标正常" --> Expand["推进下一放量阶段"]
style Rollback fill:#ffebee,color:#000
style Expand fill:#e8f5e9,color:#000
```
## 六、实践 checklist
> [!example] 灰度上线前必查清单
>
> - [ ] 旧版本保持至少一个副本不销毁(随时回滚)
> - [ ] 灰度期间禁止其他无关变更上线
> - [ ] 已配置好 v1 vs v2 的双线对比面板
> - [ ] 定义了明确的放量阶段和触发条件(何时扩、何时停)
> - [ ] 准备了回滚脚本 / 一键回滚操作
> - [ ] 通知了相关干系人(运维、产品、客服)
> - [ ] 选择了影响面最小的时间段开始灰度
## 关联笔记
- [[02-服务治理/01-API网关]] — API Gateway 的路由和权重分发
- [[02-服务治理/06-容错模式]] — 熔断、限流等配套治理手段
- [[04-可观测性/01-Metrics监控]] — 灰度期间的监控面板设计
- [[05-部署运维/04-SRE实践]] — 基于 SLO 的发布决策