diff --git a/hzh/MS/02-服务治理.md b/hzh/MS/02-服务治理.md
deleted file mode 100644
index a4d8f35..0000000
--- a/hzh/MS/02-服务治理.md
+++ /dev/null
@@ -1,572 +0,0 @@
----
-tags: [microservice, service-governance, api-gateway, circuit-breaker, service-discovery, distributed-tracing, canary-deployment]
-create time: 2026-04-29 12:02
----
-
-# 服务治理
-
-## 概述
-
-服务治理是微服务架构的"操作系统"——它不直接实现业务逻辑,但决定了系统能否在复杂、高并发、多团队协作的环境中稳定运转。
-
-本文覆盖服务治理的 **七大核心能力**:
-
-```mermaid
-quadrantChart
- title 服务治理能力矩阵
- x-axis Low Impact --> High Impact
- y-axis Foundational --> Advanced
- "服务发现": [0.25, 0.2]
- "负载均衡": [0.45, 0.25]
- "API Gateway": [0.35, 0.4]
- "熔断降级": [0.55, 0.5]
- "限流": [0.65, 0.6]
- "链路追踪": [0.5, 0.75]
- "配置中心": [0.4, 0.7]
- "灰度发布": [0.75, 0.9]
-```
-
-> [!question] 开篇思考
-> 假设你有 10 个微服务,每个服务有 3 个实例,总共 30 个服务实例。手动维护它们的地址列表会带来哪些问题?你能想到几种解决方案?
-
-答案藏在下面每一个章节里——从服务发现到流量治理,每一层都在解决特定维度的复杂度。
-
-## 服务发现
-
-服务实例的动态变化(扩容、缩容、故障重启)让硬编码地址成为不可能。服务要回答的核心问题是:**我怎么找到你?**
-
-### 两种模式
-
-```mermaid
-graph TB
- subgraph Client["客户端发现模式"]
- A[Service A] -->|1.查询注册中心| R1[(Registry)]
- R1 -->|2.返回实例列表| A
- A -->|3.自选实例直连| B[Service B]
- end
-
- subgraph Server["服务端发现模式"]
- C[Service C] -->|请求| P[LoadBalancer Proxy]
- P -->|查询注册中心| R2[(Registry)]
- R2 -->|返回实例| P
- P -->|转发| D[Service D]
- end
-```
-
-**对比**:
-
-| 维度 | 客户端发现 | 服务端发现 |
-|------|-----------|-----------|
-| 典型实现 | Eureka、Consul、Nacos | Nginx、Envoy、K8s Service |
-| 耦合度 | 客户端嵌入注册逻辑 | 透明代理,客户端无感知 |
-| 性能 | 直连调用,延迟最低 | 多一跳代理开销 |
-| 运维复杂度 | 每门语言需独立 SDK | 统一部署代理,技术无关 |
-
-> [!tip] 推荐路径
-> Kubernetes 环境下直接用 **K8s Service + Ingress**;非容器环境优先考虑 **Nacos**(阿里开源,国内生态好)。
-> 如果团队已有 Consul 基础设施,无需迁移——它在中小规模集群中表现优秀。
-
-### 实战:Nacos 服务发现
-
-```go
-// Nacos 服务注册 & 拉取
-import (
- "github.com/nacos-group/nacos-sdk-go/v2/clients"
- "github.com/nacos-group/nacos-sdk-go/v2/common/constant"
-)
-
-// 创建注册客户端
-sc := constant.ServerConfig{
- IpAddr: "127.0.0.1",
- Port: 8848,
-}
-
-// 注册服务实例
-client, _ := clients.NewNamingClient(
- value_map.NewValueMap(map[string]any{"serverConfig": sc}),
-)
-
-client.RegisterInstance(naming_param.RegisterInstanceParam{
- Ip: "10.0.0.1",
- Port: 8080,
- ServiceName: "order-service",
- ClusterName: "DEFAULT",
-})
-
-// 拉取某服务的可用实例列表
-instances, _ := client.SelectInstances(naming_param.SelectInstanceParam{
- ServiceName: "order-service",
-})
-```
-
-> [!warning] 注意
-> Nacos 同时支持临时实例(故障自动摘除)和持久实例(基于 etcd)。生产环境中临时实例更常见——节点挂了会自动从列表中剔除。
-
-**关键问题**:服务下线时,如何确保正在处理的请求不会被打断?这引出了健康检查和优雅关闭的概念。
-
-## API Gateway
-
-API Gateway 是所有外部请求的统一入口,承担以下职责:
-
-```mermaid
-graph LR
- Client["客户端"] --> GW["API Gateway"]
- GW --> Auth["鉴权 & 限流"]
- GW --> Route["路由转发"]
- GW --> Transform["协议转换"]
- GW --> Log["日志 & 监控"]
- GW -.-> CB[(配置中心)]
-```
-
-常见实现:**Kong、APISIX、Spring Cloud Gateway、Nginx**。
-
-### 网关放什么?
-
-> [!summary] 网关职责清单
->
-> - ✅ 鉴权与认证
-> - ✅ 限流熔断
-> - ✅ HTTPS 终结
-> - ✅ 请求/响应转换
-> - ✅ 路由分发
-> - ❌ 业务逻辑 — 网关保持瘦,重逻辑应下沉到业务服务
-
-> [!question] 权衡题
-> 有人说:"鉴权放到网关统一做,避免每个服务重复写。"但如果某个内部服务不需要鉴权呢?或者不同团队要求不同的鉴权方式呢?你怎么设计才能兼顾统一性和灵活性?
-> 👉 [[02-服务治理/网关鉴权策略]] — 分层鉴权模型详解
-
-## 服务间通信
-
-### RPC vs RESTful API
-
-| 维度 | REST over HTTP/JSON | gRPC (HTTP/2) |
-|------|---------------------|---------------|
-| 性能 | 序列化开销大 | Protocol Buffers,二进制高效 |
-| 人类可读 | URL + JSON 直观 | 需要 Proto 定义辅助理解 |
-| 语言兼容性 | 广泛,任何能发 HTTP 的语言都能用 | 需要代码生成 |
-| 适用场景 | 对外 API、跨团队/跨组织调用 | 内部服务间高频强类型调用 |
-
-```go
-// Go 示例:gRPC Protobuf 定义
-// proto/order/v1/order.proto
-syntax = "proto3";
-package order.v1;
-
-service OrderService {
- rpc CreateOrder(CreateOrderRequest) returns (CreateOrderResponse);
- rpc GetOrder(GetOrderRequest) returns (Order);
-}
-
-message CreateOrderRequest {
- string user_id = 1;
- repeated Item items = 2;
- float total = 3;
-}
-
-message Item {
- string product_id = 1;
- int32 quantity = 2;
-}
-```
-
-### 典型请求链路
-
-一次下单操作会串联多个服务和两种通信模式:
-
-```mermaid
-sequenceDiagram
- participant C as Client
- participant GW as API Gateway
- participant O as Order Service
- participant I as Inventory Service
- participant P as Payment Service
- participant MQ as Message Queue
-
- C->>GW: POST /orders (HTTP/JSON)
- GW->>O: CreateOrder (gRPC)
-
- rect rgb(200, 220, 250)
- Note over O,P: 同步 RPC 链
- O->>I: CheckStock (gRPC)
- I-->>O: {ok: true, quantity: 1}
- O->>P: Charge (gRPC)
- P-->>O: {success: true}
- end
-
- O-->>GW: {orderId: "ORD-001"}
- GW-->>C: 200 OK
-
- rect rgb(255, 240, 220)
- Note over O,MQ: 异步事件解耦
- O->>MQ: Publish OrderCreated Event
- MQ->>N: Consume → SendSms
- Note right of N: 通知类场景,不阻塞主流程
- end
-```
-
-> [!keypoint] 关键洞察
->
-> - 同步链路(蓝色):**gRPC 直连**,延迟低,适合核心事务(查库存 → 扣款)
-> - 异步链路(橙色):**消息队列**,解耦非关键路径(发短信、发积分),即使失败也不影响下单主干
-> - API Gateway 负责统一鉴权和限流,下游服务之间通过 gRPC 高效通信
->
-> 这就是「同步 RPC 保性能,异步 MQ 保解耦」的组合拳。
-
-### 同步 vs 异步
-
-> [!question] 关键时刻的判断
-> 用户点击"提交订单"后,系统要做:① 创建订单记录 ② 扣减库存 ③ 扣款 ④ 发送短信通知。哪些步骤必须同步完成?哪些可以异步处理?为什么?
-
-**答案**:①~③需要立即得到结果或保证一致性,走同步流程;④纯粹的通知类场景完全异步,用消息队列解耦。即使扣款失败,短信也没必要发出。
-
-```go
-// 异步消息:Go + RabbitMQ 简易示例
-producer.Publish("orders", []byte(`{
- "orderId": "ORD-2026-001",
- "userId": "user-42",
- "amount": 199.00
-}`))
-
-// 消费者监听
-messages := consumer.Consume("order-notifications")
-for msg := range messages {
- sendSms(msg.OrderId) // 不阻塞主流程
-}
-```
-
-> [!tip] 选型建议
-> 事件驱动架构(Event-driven)适合「最终一致性」场景;强一致事务需求仍依赖 SAGA/TCC 等分布式事务方案。
-
-## 容错模式
-
-微服务最大的挑战是 **网络不可靠**。分布式系统的每个远程调用都可能超时、被拒绝、或部分成功。必须提前设计降级和恢复策略。
-
-### 重试机制
-
-> [!warning] 关键原则
-> 只对 **幂等操作** 重试!POST 创建操作直接重试会导致重复数据。GET、PUT(同参数)适合重试。
-
-```go
-// exponential backoff + jitter(防雪崩)
-func retryWithBackoff(ctx context.Context, maxRetries int, fn func() error) error {
- for attempt := uint(0); attempt <= uint(maxRetries); attempt++ {
- if err := fn(); err != nil {
- if attempt == uint(maxRetries) {
- return err
- }
- // jitter: 随机偏移,避免所有客户端同时重试造成二次冲击
- jitter := time.Duration(rand.Int63n(int64(time.Millisecond * 100)))
- wait := time.Duration(math.Pow(2, float64(attempt)))*time.Second + jitter
- select {
- case <-ctx.Done():
- return ctx.Err()
- case <-time.After(wait):
- }
- } else {
- return nil
- }
- }
- return nil
-}
-```
-
-### 熔断器 (Circuit Breaker)
-
-当下游服务频繁失败时,快速失败避免线程堆积雪崩:
-
-```mermaid
-flowchart TD
- CB{{🔘 CIRCUIT BREAKER}}
-
- subgraph CL ["CLOSED — 正常"]
- C["请求放行
⏱ 实时统计成功率
⚠️ 连续失败 → 熔断"]
- end
-
- subgraph OP ["OPEN — 熔断"]
- O["🚫 请求短路
💥 直接返回降级响应
🛡 不调下游,防雪崩"]
- end
-
- subgraph HO ["HALF-OPEN — 半开"]
- H["🔍 放行少量探测请求
✅ 成功 → 恢复全量流量
❌ 失败 → 重新熔断"]
- end
-
- CB --> CL
- CL -.->|失败 > N| OP
- OP -.->|等待超时| HO
- HO -->|探测成功| CL
- HO -->|探测失败| OP
-
- style CL fill:#e6f9e6,stroke:#4caf50,stroke-width:3px,color:#000
- style OP fill:#ffebee,stroke:#ef5350,stroke-width:3px,color:#000
- style HO fill:#fff8e1,stroke:#ffa726,stroke-width:3px,color:#000
-```
-
-```go
-// gobreaker 示例
-cb := state.NewCB(state.Settings{
- Name: "UserService",
- MaxElems: 10,
- WaitRetry: 5 * time.Second,
- ReadyToTrip: func(counts Counters) bool {
- return counts.Failures > 5
- },
-})
-
-result := cb.Execute(doRequest)
-if result.Err != nil {
- // 熔断打开,立即短路返回错误,不调用下游
-}
-```
-
-### 健康检查
-
-```mermaid
-sequenceDiagram
- participant LB as 负载均衡器
- participant S1 as 服务实例 A
- participant S2 as 服务实例 B
-
- LB->>S1: "GET /health -> 200 OK"
- LB->>S2: "GET /health -> 503 ERROR"
- Note over LB: "标记 S2 不健康,剔除出池"
- LB->>S2: "GET /health -> 200 OK"
- Note over LB: "逐步恢复,重新加入池"
-```
-
-- **存活探针 (Liveness)**:判断"进程是否还活着",挂了则重启
-- **就绪探针 (Readiness)**:判断"是否能接收流量",未就绪则剔除负载均衡池
-- ** readiness 比 liveness 更重要**——一个进程活着但数据库连接耗尽时,应该停止接收流量而不是重启
-
-> [!summary] 舱壁隔离 (Bulkhead)
->
-> 为不同下游服务分配独立的线程池/连接池:
->
-> ```go
-> // poolgroup 示例:为不同服务隔离连接池
-> orderPool := pool.New(10, 100) // 最多10个活跃,上限100
-> userPool := pool.New(5, 50)
-> // 订单服务占满连接不会影响用户服务的调用
-> ```
->
-> 超时 + 熔断 + 舱壁三者组合,构成了经典的稳定性防护三件套。
-
-## 负载均衡
-
-```mermaid
-flowchart LR
- subgraph "客户端负载均衡 (Client-Side)"
- A[Service A] --> RR[轮询]
- A --> LH[最少连接]
- A --> CH[一致性哈希]
- end
-
- subgraph "服务端负载均衡 (Server-Side)"
- B[Service B] --> VIP[[Virtual IP]]
- VIP --> B1[B-1]
- VIP --> B2[B-2]
- VIP --> B3[B-3]
- end
-```
-
-| 策略 | 说明 | 适用场景 |
-|------|------|---------|
-| Round Robin | 轮询分配 | 各实例负载相近,请求耗时均匀 |
-| Least Connections | 最少连接优先 | 长连接场景,请求处理时间差异大 |
-| Consistent Hash | 哈希路由,同一 key 始终到同实例 | 有状态缓存、会话绑定场景 |
-| Random | 随机选择 | 最简单但不一定最优 |
-
-> [!tip] K8s 中的实践
-> K8s Service 默认 Round Robin;如需更精细的控制,可配合 **Istio VirtualService** 实现基于权重/头部的流量分发。
-
-## 配置管理
-
-> [!question] 引出配置中心的必要性
-> 假设你的 50 个服务实例都要连同一个数据库。现在需要把数据库密码从 `password1` 改为 `password2`,你会怎么改?登录每台机器改配置文件?滚动重启所有 Pod?还是……有更好的办法?
-
-当服务实例数以百计时,手动管理配置是不可想象的。配置中心提供 **集中化、动态化、版本化** 的配置管理能力。
-
-### 核心价值
-
-```mermaid
-flowchart LR
- Dev["开发/运维"] --> CC[(配置中心)]
- CC -->|热更新推送| S1[Service A]
- CC -->|热更新推送| S2[Service B]
- CC -->|热更新推送| S3[Service C]
-
- CC -.->|版本管理| V1[v1.0 历史配置]
- CC -.->|版本管理| V2[v1.1 当前配置]
-```
-
-| 能力 | 说明 |
-|------|------|
-| 动态刷新 | 修改配置后立即生效,无需重启 |
-| 环境隔离 | dev / test / prod 配置分离 |
-| 版本管理与回滚 | 每次变更有迹可循,一键回滚 |
-| 权限控制 | 敏感配置(密钥、Token)按角色隔离 |
-
-### Nacos Config 示例
-
-```go
-// 动态监听配置变更
-configClient, _ := clients.NewConfigClient(value_map.NewValueMap(map[string]any{
- "serverConfig": sc,
-}))
-
-content, _ := configClient.GetConfig(config_param.GetConfigParam{
- DataId: "order-service.yaml",
- Group: "DEFAULT_GROUP",
-})
-
-// 监听配置变化
-configClient.ListenChange(config_param.ListenChangeParam{
- DataId: "order-service.yaml",
- Group: "DEFAULT_GROUP",
- Callback: func(content string) {
- fmt.Println("配置更新了:", content)
- // 重新加载配置...
- },
-})
-```
-
-> [!note] 主流对比
->
-> - **Nacos Config**:阿里开源,国内首选,兼顾客户端发现+配置管理
-> - **Apollo**:携程开源,配置审核流程完善,适合大型团队
-> - **Spring Cloud Config**:与 Spring 生态深度集成,但需额外 Git/DB 存储后端
-> - **K8s ConfigMap**:原生方案,适合纯 K8s 环境,不支持热更新需配合 Sidecar
-
-## 分布式链路追踪
-
-> [!question] 定位问题的困难
-> 用户反映下单慢,你的系统由订单、支付、库存、会员 4 个服务串联而成。没有工具的情况下,你要怎么知道是哪个服务拖慢了整体响应时间?
-
-单个服务的日志只能告诉你局部信息。分布式链路追踪将一次请求跨越多个服务的完整调用链串起来,形成全局视图。
-
-### 核心概念
-
-```mermaid
-flowchart TB
- Req["请求 trace_id=abc123"] --> Span1["订单服务 - 20ms"]
- Span1 --> Span2["库存服务 - 80ms"]
- Span1 --> Span3["会员服务 - 15ms"]
- Span2 --> Span4["数据库查询 - 60ms"]
-
- style Span2 fill:#ff9999
-```
-
-- **Trace**:一次完整请求的调用链
-- **Span**:链路中的一个执行片段(如一次 HTTP 调用、一次 SQL 查询)
-- **Context Propagation**:通过 Header 传递 trace_id/span_id,贯穿整条链路
-
-### 主流方案
-
-| 方案 | 协议 | 存储后端 | 特点 |
-|------|------|---------|------|
-| **OpenTelemetry** | OTLP | Prometheus/Jaeger/Zipkin | CNCF 标准,厂商中立,未来趋势 |
-| **Jaeger** | Jaeger native | Cassandra/Elasticsearch | Uber 开源,UI 友好 |
-| **SkyWalking** | SkyWalking | MySQL/Elasticsearch | 国产,零侵入 Agent,中文文档完善 |
-
-### OpenTelemetry Go 示例
-
-```go
-// 初始化 tracer provider
-provider := sdktrace.NewTracerProvider(
- sdktrace.WithBatcherExporter(exporter), // 异步上报,不阻塞
-)
-
-tracer := provider.Tracer("order-service")
-
-// 在 handler 中创建 span
-func handleOrder(w http.ResponseWriter, r *http.Request) {
- ctx, span := tracer.Start(r.Context(), "handleOrder")
- defer span.End()
-
- // 传播 context 到下游
- resp, err := callInventoryService(ctx) // SDK 自动注入 trace context
- if err != nil {
- span.RecordError(err)
- span.SetStatus(codes.Error, err.Error())
- return
- }
- w.Write(resp.Body)
-}
-```
-
-> [!tip] 渐进式落地建议
-> 不要试图一开始就采集全部 Span。先从 **核心链路**(下单、支付)入手,采集 rate 设为 100%;稳定后再逐步扩展,日常采样率可降至 5%~10% 以节省存储。
-
-## 灰度发布与流量治理
-
-> [!question] 如何安全地上线?
-> 你修复了一个紧急 Bug,但这次改动涉及核心支付链路。直接全量发布一旦出问题损失巨大。有没有办法先小范围验证,确认没问题再放量?
-
-灰度发布(也叫金丝雀发布)是降低变更风险的核心手段。它让你将新版本逐步推向一小部分用户,观察指标正常后再全量。
-
-### 灰度策略
-
-```mermaid
-flowchart LR
- subgraph "Canary Release"
- A["1% 流量"] --> B{"指标正常?"}
- B -- 是 --> C["10% 流量"]
- B -- 否 --> D["自动回滚"]
- C --> E{"指标正常?"}
- E -- 是 --> F["50% 流量"]
- E -- 否 --> D
- F --> G{"指标正常?"}
- G -- 是 --> H["100% 全量"]
- G -- 否 --> D
- end
-```
-
-### 灰度路由规则
-
-```yaml
-# Istio VirtualService 示例
-apiVersion: networking.istio.io/v1beta1
-kind: VirtualService
-metadata:
- name: order-route
-spec:
- hosts: ["order-service"]
- http:
- # 灰度规则:header 携带 canary=true 的用户走 v2
- - 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
-```
-
-### 蓝绿 vs 灰度
-
-> [!summary] 两种发布策略对比
->
-> | 维度 | 蓝绿部署 | 灰度发布 (金丝雀) |
-> |------|---------|-----------------|
-> | 切换方式 | 一次性全切 | 逐步放量 |
-> | 资源消耗 | 双倍(新旧并行) | 初期少量副本 |
-> | 回滚速度 | 秒级(切回即可) | 同样秒级 |
-> | 风险等级 | 中高 | 低 |
-> | 适合场景 | 大型变更、重大版本 | 日常迭代、高风险链路 |
-
-> [!tip] 实战经验
-> 无论哪种发布方式,**必须有可量化的观测指标作为决策依据**——错误率、P99 延迟、CPU/内存使用率。不要凭感觉放量,让数据说话。
-
-## 关联笔记
-
-- [[hzh/MS/01-基础概念]] — 微服务的整体架构认知
-- [[hzh/MS/05-部署运维]] — K8s Service 天然提供负载均衡和服务发现
-- [[hzh/MS/03-数据一致性]] — 微服务下的数据分片与一致性策略
-- [[hzh/MS/04-可观测性]] — 日志、指标、链路追踪的完整体系
diff --git a/hzh/MS/02-服务治理/API网关/README.md b/hzh/MS/02-服务治理/API网关/README.md
new file mode 100644
index 0000000..8735d63
--- /dev/null
+++ b/hzh/MS/02-服务治理/API网关/README.md
@@ -0,0 +1,153 @@
+---
+tags: [microservice, api-gateway, kong, apisix, spring-cloud-gateway]
+create time: 2026-05-05
+---
+
+# API 网关
+
+## 概述
+
+API Gateway 是所有外部请求的统一入口,承担以下职责:
+
+```mermaid
+graph LR
+ Client["客户端 App / Web"] --> GW["API Gateway"]
+ GW --> Auth["鉴权 & 限流"]
+ GW --> Route["路由转发"]
+ GW --> Transform["协议转换"]
+ GW --> Log["日志 & 监控"]
+ GW -.-> CB[(配置中心)]
+```
+
+常见实现:**Kong、APISIX、Spring Cloud Gateway、Nginx + Lua**。
+
+## 网关应该做什么?
+
+> [!summary] 网关职责清单
+
+| ✅ 适合放 | ❌ 不应该放 |
+|---------|-----------|
+| 鉴权与认证 | 业务逻辑(如订单创建) |
+| 限流熔断 | 复杂的数据聚合查询 |
+| HTTPS 终结 | 大量 CPU 密集型计算 |
+| 请求/响应转换 | 涉及数据库写操作 |
+| 路由分发 | 跨服务事务管理 |
+| 日志 & 监控 | 邮件/短信发送等异步任务 |
+
+> [!tip] 核心原则
+> **网关保持瘦**——它是 traffic cop(交通警察),不是 warehouse manager(仓库管理员)。重逻辑应下沉到业务服务。
+
+### 分层鉴权模型
+
+> [!question] 权衡题
+> 有人说:"鉴权放到网关统一做,避免每个服务重复写。"但如果某个内部服务不需要鉴权呢?或者不同团队要求不同的鉴权方式呢?
+
+**分层鉴权架构**:
+
+```mermaid
+graph TB
+ External["外部用户"] --> GW["API Gateway
JWT 校验 + OAuth2"]
+ GW --> S1[公开接口
无需额外鉴权]
+ GW --> S2[内部接口
Service Token]
+
+ S1 --> UserSvc[[User Service]]
+ S2 --> OrderSvc[[Order Service]]
+ S2 --> PaySvc[[Payment Service]]
+
+ OrderSvc -->|"mTLS + JWT"| DB[(DB)]
+ PaySvc -->|"mTLS + JWT"| DB
+```
+
+- **第一层(网关)**:校验外部用户的 JWT/OAuth Token,拦截非法请求
+- **第二层(服务间)**:通过 Service Token 或 mTLS 保证调用方身份可信
+- **第三层(数据层)**:RBAC / ABAC 细粒度权限控制
+
+## 路由策略
+
+### 基础路由规则
+
+```yaml
+# APISIX 路由示例
+routes:
+ - uri: /api/orders/*
+ upstream:
+ nodes:
+ "order-service:8080": 1
+ type: roundrobin
+
+ - uri: /api/payments/*
+ upstream:
+ nodes:
+ "payment-service:8080": 1
+ type: roundrobin
+```
+
+### 高级路由策略
+
+| 策略 | 场景 | 示例 |
+|------|------|------|
+| **路径匹配** | 按 URL 前缀路由 | `/api/v1/*` → v1 版本服务 |
+| **Header 匹配** | A/B 测试、灰度发布 | `x-canary: true` → 新版本 |
+| **权重路由** | 金丝雀发布 | 90% 流量 → v1, 10% → v2 |
+| **正则匹配** | 复杂 URL 模式 | `/api/user/(?P\d+)/*` |
+
+## 网关插件体系
+
+网关的核心价值在于 **可插拔的中间件链**,类似 Express/Koa 的 middleware 概念。
+
+```mermaid
+graph LR
+ Req["Request"] -->|Plugin 1| RateLimiter["限流"]
+ RateLimiter -->|Plugin 2| Auth["鉴权"]
+ Auth -->|Plugin 3| CBR["熔断"]
+ CBR -->|Plugin 4| Transform["协议转换"]
+ Transform -->|Plugin 5| Logger["日志"]
+ Logger --> Backend["Backend Service"]
+```
+
+### 常用插件列表
+
+| 插件 | 作用 | 推荐算法 |
+|------|------|---------|
+| **Rate Limiting** | 防刷限流 | 令牌桶 / 漏桶 |
+| **CORS** | 跨域处理 | 预检缓存 |
+| **IP 黑白名单** | 访问控制 | Redis Bloom Filter |
+| **Response Rewrite** | 修改响应体 | JSON Patch |
+| **Request Transformation** | Header/Body 改写 | Map-based |
+| **Prometheus Exporter** | 指标采集 | 自动埋点 |
+| **Fault Injection** | 混沌测试注入延迟/错误 | 按比例注入 |
+
+## 网关的高可用设计
+
+```mermaid
+graph TB
+ DNS["DNS / CLB"] --> GW1["Gateway Node 1"]
+ DNS --> GW2["Gateway Node 2"]
+
+ subgraph GW_Cluster["网关集群"]
+ GW1
+ GW2
+ end
+
+ GW1 --> B1["backend-pool-v1"]
+ GW2 --> B2["backend-pool-v1"]
+
+ B1 --> Svc1[[order-service]]
+ B1 --> Svc2[[user-service]]
+ B2 --> Svc1
+ B2 --> Svc2
+
+ GW1 -.-> Config["配置中心 (同步)"]
+ GW2 -.-> Config
+```
+
+**关键点**:
+- 网关无状态设计,可横向扩展
+- 配置通过注册中心实时同步,无需重启
+- 多节点前接负载均衡器(CLB/Nginx)
+
+## 关联笔记
+
+- [[02-服务治理/服务发现/README]] — 网关需要订阅服务实例列表
+- [[02-服务治理/流量治理/README]] — 高级路由和灰度发布的延伸
+- [[hzh/MS/API 设计原则]] — API Gateway 的设计与 REST/gRPC 选型
diff --git a/hzh/MS/02-服务治理/README.md b/hzh/MS/02-服务治理/README.md
new file mode 100644
index 0000000..ffe8e33
--- /dev/null
+++ b/hzh/MS/02-服务治理/README.md
@@ -0,0 +1,54 @@
+---
+tags: [microservice, service-governance]
+create time: 2026-04-29 12:02
+---
+
+# 服务治理
+
+## 概述
+
+服务治理是微服务架构的"操作系统"——它不直接实现业务逻辑,但决定了系统能否在复杂、高并发、多团队协作的环境中稳定运转。
+
+> [!question] 开篇思考
+> 假设你有 10 个微服务,每个服务有 3 个实例,总共 30 个服务实例。手动维护它们的地址列表会带来哪些问题?你能想到几种解决方案?
+
+答案藏在下面每一个章节里——从服务发现到流量治理,每一层都在解决特定维度的复杂度。
+
+## 知识体系
+
+```mermaid
+graph LR
+ A["服务发现"] --> B["API 网关"]
+ B --> C["服务间通信"]
+ C --> D["容错模式"]
+ D --> E["配置管理"]
+ E --> F["分布式追踪"]
+ F --> G["流量治理"]
+ G --> H["安全机制"]
+```
+
+| # | 主题 | 核心问题 |
+|---|------|----------|
+| 1 | [[02-服务治理/服务发现/README]] | 服务如何找到彼此?注册中心的工作原理是什么? |
+| 2 | [[02-服务治理/API网关/README]] | 统一入口承担哪些职责?网关应该瘦还是胖? |
+| 3 | [[02-服务治理/服务间通信/README]] | RPC vs RESTful?同步 vs 异步怎么选? |
+| 4 | [[02-服务治理/容错模式/README]] | 网络不可靠,故障怎么隔离和恢复? |
+| 5 | [[02-服务治理/配置管理/README]] | 上百个服务的配置如何统一管理? |
+| 6 | [[02-服务治理/分布式追踪/README]] | 请求穿越多个服务后,如何追踪链路? |
+| 7 | [[02-服务治理/流量治理/README]] | 灰度发布如何做?高级路由策略有哪些? |
+| 8 | [[02-服务治理/安全机制/README]] | 服务间调用如何认证和授权?mTLS 是什么? |
+
+### 学习建议
+
+> [!tip] 学习路径
+> 按编号顺序阅读。前三个主题是理解服务治理的基础,后面的容错、配置、追踪是在此之上的稳定性保障。
+
+> [!question] 带着问题读
+> 每篇文章都设计了启发式问题。先自己想一遍答案,再看文档,效果更好。
+
+### 关联笔记
+
+- [[01-基础概念]] — 微服务的整体架构认知
+- [[03-数据一致性]] — 服务调用链路上的数据一致性问题
+- [[04-可观测性]] — 日志、指标、链路追踪的完整体系
+- [[05-部署运维]] — K8s Service 天然提供负载均衡和服务发现
diff --git a/hzh/MS/02-服务治理/分布式追踪/README.md b/hzh/MS/02-服务治理/分布式追踪/README.md
new file mode 100644
index 0000000..97ae778
--- /dev/null
+++ b/hzh/MS/02-服务治理/分布式追踪/README.md
@@ -0,0 +1,209 @@
+---
+tags: [microservice, distributed-tracing, opentelemetry, jaeger, skywalking]
+create time: 2026-05-05
+---
+
+# 分布式链路追踪
+
+## 概述
+
+单个服务的日志只能告诉你局部信息。分布式链路追踪将一次请求跨越多个服务的完整调用链串起来,形成全局视图。
+
+> [!question] 定位问题的困难
+> 用户反映下单慢,你的系统由订单、支付、库存、会员 4 个服务串联而成。没有工具的情况下,你要怎么知道是哪个服务拖慢了整体响应时间?
+
+## 核心概念
+
+```mermaid
+flowchart TB
+ Req["请求 trace_id=abc123"] --> Span1["Span #1
API Gateway
5ms"]
+ Span1 --> Span2["Span #2
Order Service
70ms"]
+ Span1 --> Span3["Span #3
User Service
15ms"]
+ Span2 --> Span4["Span #4
Inventory DB Query
60ms"]
+
+ style Span2 fill:#ff9999
+ style Span4 fill:#ffcc99
+```
+
+| 概念 | 说明 |
+|------|------|
+| **Trace** | 一次完整请求的调用链,由一个唯一的 `trace_id` 标识 |
+| **Span** | 链路中的一个执行片段(如一次 HTTP 调用、一次 SQL 查询),有独立的 `span_id` |
+| **Parent-Child** | Span 之间通过 `parent_span_id` 建立父子关系,形成树状结构 |
+| **Context Propagation** | 通过 Header 传递 `trace_id`/`span_id`,贯穿整条链路 |
+| **Sampling** | 不是每条请求都采样,按比例或策略选择,降低存储开销 |
+
+### Trace/Span 数据结构
+
+```json
+{
+ "traceId": "abc123def456...",
+ "spans": [
+ {
+ "spanId": "span-001",
+ "parentId": null,
+ "operationName": "POST /orders",
+ "startTime": "2026-05-05T10:00:00.000Z",
+ "durationMs": 120,
+ "tags": {
+ "http.method": "POST",
+ "http.url": "/api/orders",
+ "http.status_code": 200
+ },
+ "logs": [
+ {
+ "timestamp": "2026-05-05T10:00:00.050Z",
+ "fields": [{"key": "event", "value": "order.created"}]
+ }
+ ]
+ },
+ {
+ "spanId": "span-002",
+ "parentId": "span-001",
+ "operationName": "GetUserById (gRPC)",
+ "startTime": "2026-05-05T10:00:00.010Z",
+ "durationMs": 15,
+ "tags": {
+ "rpc.system": "grpc",
+ "rpc.service": "UserService",
+ "rpc.method": "GetUser"
+ }
+ }
+ ]
+}
+```
+
+## 上下文传播 (Context Propagation)
+
+`trace_id` 如何从上游服务传递到下游?
+
+### HTTP 场景:W3C Trace Context 标准
+
+```json
+// HTTP Header 中实际传递的字段
+{
+ "traceparent": "00-abc123def456...-789ghi012jkl-01",
+ "tracestate": "congo=t61rcWkgMzE"
+}
+```
+
+格式:`version-trace_id-span_id-flags`
+
+```go
+// OpenTelemetry SDK 自动处理 context 注入和提取
+func Middleware(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ // 从入站请求提取 trace context
+ ctx := propagator.Extract(r.Context(), headerReader{r.Header})
+
+ // 创建新的 span
+ ctx, span := tracer.Start(ctx, "handleOrder")
+ defer span.End()
+
+ // 将 trace context 注入到出站请求
+ r = r.WithContext(ctx)
+ propagator.Inject(ctx, headerWriter{r.Header})
+
+ next.ServeHTTP(w, r)
+ })
+}
+```
+
+### MQ 场景:Message Header 透传
+
+```go
+// RocketMQ 生产者 - 自动注入 trace context
+msg := rocketmq.NewMessage("order-created", payload)
+msg.WithProperty("trace_id", currentTraceID) // 手动注入
+msg.WithProperty("span_id", currentSpanID)
+
+// RocketMQ 消费者 - 恢复 trace context
+traceID := msg.GetProperty("trace_id")
+span, _ := tracer.Start(ctx, "processOrderCreated",
+ trace.WithSpanKind(trace.SpanKindConsumer))
+```
+
+## 主流方案对比
+
+| 方案 | 协议 | 存储后端 | 侵入程度 | 特色能力 |
+|------|------|---------|---------|---------|
+| **OpenTelemetry** | OTLP | Prometheus/Jaeger/Zipkin | SDK + Auto-Instrumentation | CNCF 标准,厂商中立,未来趋势 |
+| **Jaeger** | Jaeger native | Cassandra/Elasticsearch | Agent / SDK | Uber 开源,UI 友好,支持业务 Tags |
+| **SkyWalking** | SkyWalking | MySQL/Elasticsearch/ES | 零侵入 Java Agent | 国产,中文文档完善,APM 一体 |
+
+> [!tip] 选型建议
+> 新项目优先选 **OpenTelemetry**——它是行业标准,未来会被所有工具支持。如果团队需要开箱即用的 APM,**SkyWalking** 的 Java Agent 零侵入方案是快速上手的最佳选择。
+
+## OpenTelemetry Go 实战
+
+```go
+// 初始化 TracerProvider
+provider := sdktrace.NewTracerProvider(
+ sdktrace.WithBatcherExporter(exporter), // 异步批量上报,不阻塞
+)
+defer provider.Shutdown(context.Background())
+
+tracer := provider.Tracer("order-service")
+
+func handleOrder(w http.ResponseWriter, r *http.Request) {
+ ctx, span := tracer.Start(r.Context(), "handleOrder")
+ defer span.End()
+
+ // 设置丰富的属性,方便查询和过滤
+ span.SetAttributes(
+ attribute.String("http.method", r.Method),
+ attribute.Int("http.status_code", http.StatusOK),
+ attribute.String("user.id", getUserID(r)),
+ )
+
+ // 调用下游服务(trace context 自动传播)
+ resp, err := callInventoryService(ctx)
+ if err != nil {
+ span.RecordError(err)
+ span.SetStatus(codes.Error, err.Error())
+ w.WriteHeader(http.StatusBadGateway)
+ return
+ }
+ w.Write(resp.Body)
+}
+```
+
+## 采样策略
+
+```mermaid
+flowchart LR
+ AllReq["全部请求"] --> Sampler{"采样决策"}
+ Sampler -->|"100%"| Core["核心链路全量采集"]
+ Sampler -->|"5~10%"| Normal["普通路径随机采样"]
+ Sampler -->|"0%"| Health["健康检查/内部心跳"]
+
+ Core --> Storage["Trace 存储"]
+ Normal --> Storage
+ Health --> Drop["丢弃"]
+```
+
+| 环境 | 采样率 | 理由 |
+|------|--------|------|
+| **开发 / 测试** | 100% | 方便调试,无存储压力 |
+| **生产 - 核心链路** | 100% | 下单、支付等关键路径必须全量 |
+| **生产 - 普通路径** | 5~10% | 平衡成本和覆盖率 |
+| **生产 - 错误链路** | 100% | 出错时的请求优先保留 |
+
+> [!note] 基于错误的智能采样
+>
+> 高级做法:**正常路径低采样,一旦检测到错误立即提升当前请求的采样率**。这样既省了存储,又能在出问题时有足够的数据回溯。
+
+## 渐进式落地路线
+
+> [!tip] 不要试图一开始就采集全部 Span
+>
+> 1. **第一步**:先接 Tracing,覆盖核心链路(下单、支付),rate=100%
+> 2. **第二步**:加入 Metrics 监控(Prometheus + Grafana)
+> 3. **第三步**:集中 Logging(Loki / ELK),与 trace_id 关联
+> 4. **第四步**:全量上 OpenTelemetry Collector,统一管理
+
+## 关联笔记
+
+- [[02-服务治理/API网关/README]] — API Gateway 可以在入口处注入 trace_id
+- [[04-可观测性/链路追踪/README]] — 更详细的链路追踪设计方法论
+- [[02-服务治理/配置管理/README]] — 配置中心的动态刷新可以联动调整采样率
diff --git a/hzh/MS/02-服务治理/安全机制/README.md b/hzh/MS/02-服务治理/安全机制/README.md
new file mode 100644
index 0000000..af8aa58
--- /dev/null
+++ b/hzh/MS/02-服务治理/安全机制/README.md
@@ -0,0 +1,181 @@
+---
+tags: [microservice, security, mTLS, JWT, OAuth2, zero-trust]
+create time: 2026-05-05
+---
+
+# 安全机制
+
+## 概述
+
+微服务架构下,服务间通信的安全保障比单体应用复杂得多。每个服务的 API 都是潜在的攻击面,需要多层防御。
+
+```mermaid
+graph TB
+ subgraph "防御层"
+ L1["L1: 网络隔离
VPC / 安全组"]
+ L2["L2: 传输加密
mTLS / TLS"]
+ L3["L3: 身份认证
JWT / Service Token"]
+ L4["L4: 授权控制
RBAC / ABAC"]
+ L5["L5: 审计追踪
操作日志"]
+ end
+
+ L1 -.-> L2 -.-> L3 -.-> L4 -.-> L5
+```
+
+> [!tip] Zero Trust 原则
+> **永不信任,始终验证**。每个服务调用都要经过认证和授权,无论请求来自内网还是外网。
+
+## 服务间认证
+
+### mTLS (双向 TLS)
+
+```mermaid
+sequenceDiagram
+ participant Client as 调用方 Service
+ participant CA as Certificate Authority
+ participant Svc as 被调方 Service
+
+ Client->>CA: 申请证书 (SPIFFE ID)
+ Svc->>CA: 申请证书 (SPIFFE ID)
+
+ Client->>Svc: TLS Handshake + ClientCert
+ Svc->>Svc: 验证书 + SPIFFE ID
+ Svc-->>Client: ✅ 认证成功
+
+ note over Client,Svc: 建立加密通道
+```
+
+**mTLS 的核心优势**:
+- 双方都持有对方可验证的证书,防止中间人攻击
+- 证书自动轮换(配合 Istio/Linkerd 等服务网格)
+- 零代码侵入——Sidecar 代理处理握手
+
+### JWT / Service Token
+
+适用于不具备 mTLS 基础设施的场景:
+
+```go
+// 生成 Service Token
+token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
+ "sub": "order-service", // 服务标识
+ "iss": "auth-server", // 签发者
+ "aud": "payment-service", // 目标服务
+ "exp": time.Now().Add(1*time.Hour).Unix(),
+ "iat": time.Now().Unix(),
+})
+tokenString, _ := token.SignedString(secretKey)
+```
+
+| 方案 | 安全性 | 复杂度 | 适用场景 |
+|------|--------|--------|---------|
+| **mTLS** | ⭐⭐⭐⭐⭐ | 中(需 PKI 基础设施) | 服务网格环境、K8s 内部通信 |
+| **JWT + Shared Secret** | ⭐⭐⭐⭐ | 低 | 中小规模,快速上手 |
+| **mTLS + JWT** | ⭐⭐⭐⭐⭐ | 中高 | 金融级安全要求 |
+
+> [!tip] 最佳实践
+> 在生产环境中,推荐 **mTLS + JWT 双层防护**:mTLS 保证通道安全,JWT 传递调用方的身份信息(谁在调用)。
+
+## API 鉴权模型
+
+### RBAC (基于角色的访问控制)
+
+```mermaid
+flowchart LR
+ User["用户"] -->|"拥有"| Role["角色"]
+ Role -->|"拥有"| Permission["权限"]
+ Permission -->|"访问"| Resource["资源"]
+
+ Admin["Admin"] --> ReadWrite
+ Editor["Editor"] --> ReadWrite
+ Viewer["Viewer"] --> ReadOnly
+
+ ReadWrite --> OrderCRUD
+ ReadOnly --> OrderRead
+
+ OrderCRUD --> CRUD["Create/Read/Update/Delete"]
+ OrderRead --> Read["Read Only"]
+```
+
+### ABAC (基于属性的访问控制)
+
+适合细粒度场景:
+
+```go
+func canAccess(user User, resource Resource, action string) bool {
+ // 属性比较规则
+ rules := []Rule{
+ {
+ Condition: user.Department == resource.Department, // 同部门
+ Action: "read",
+ },
+ {
+ Condition: user.Role == "admin" || user.ID == resource.OwnerID,
+ Action: "write",
+ },
+ }
+
+ for _, r := range rules {
+ if r.Condition && r.Action == action {
+ return true
+ }
+ }
+ return false
+}
+```
+
+## 输入校验与防攻击
+
+### SQL 注入防护
+
+```go
+// ❌ 危险:字符串拼接
+query := fmt.Sprintf("SELECT * FROM users WHERE name = '%s'", userInput)
+
+// ✅ 安全:参数化查询
+rows, err := db.Query("SELECT * FROM users WHERE name = ?", userInput)
+```
+
+### XSS 防护
+
+```go
+// Go HTML template 自动转义
+tpl.ExecuteTemplate(w, "page.html", data) // {{.Name}} 自动 HTML 转义
+
+// JSON API 天然免疫(Content-Type: application/json)
+```
+
+### 常见攻击防护清单
+
+| 威胁 | 防护手段 | 实现位置 |
+|------|---------|---------|
+| **SQL 注入** | 参数化查询 / ORM | 数据访问层 |
+| **XSS** | 输出转义 / CSP Header | Web 框架 / Gateway |
+| **CSRF** | SameSite Cookie / CSRF Token | 网关 / Session |
+| **DDoS** | 限流 + WAF | API Gateway |
+| **重放攻击** | Nonce + Timestamp | API 签名 |
+| **凭证泄露** | HTTPS + Secure Cookie | 传输层 |
+
+## API 签名(防重放攻击)
+
+对高安全要求的 API,客户端需要对请求签名:
+
+```
+Signature = HMAC-SHA256(Secret, HTTP_Method + URL + Timestamp + Body)
+```
+
+```
+GET /api/orders?userId=123×tamp=1714900000&nonce=abc123
+↓ 用 Secret 做 HMAC-SHA256 签名
+a1b2c3d4e5f6...
+```
+
+服务端验证步骤:
+1. 检查 `timestamp` 是否在允许窗口内(如 ±5 分钟)
+2. 检查 `nonce` 是否已使用(Redis SetNX,TTL 5min)
+3. 用同样的算法计算签名,比对是否一致
+
+## 关联笔记
+
+- [[02-服务治理/API网关/README]] — 网关层的统一鉴权和限流
+- [[02-服务治理/服务发现/README]] — 服务注册时也需要安全认证
+- [[hzh/MS/API 设计原则]] — API 设计中的安全考量
diff --git a/hzh/MS/02-服务治理/容错模式/README.md b/hzh/MS/02-服务治理/容错模式/README.md
new file mode 100644
index 0000000..3da78d0
--- /dev/null
+++ b/hzh/MS/02-服务治理/容错模式/README.md
@@ -0,0 +1,288 @@
+---
+tags: [microservice, circuit-breaker, retry, rate-limiting, bulkhead, health-check]
+create time: 2026-05-05
+---
+
+# 容错模式
+
+## 概述
+
+微服务最大的挑战是 **网络不可靠**。分布式系统的每个远程调用都可能超时、被拒绝、或部分成功。必须提前设计降级和恢复策略。
+
+```mermaid
+graph TB
+ A["🛡️ 超时控制"] --> B["⏱ 重试机制"]
+ B --> C["⚡ 熔断器"]
+ C --> D["🔀 限流"]
+ D --> E["🧱 舱壁隔离"]
+ E --> F["💤 降级策略"]
+```
+
+> [!warning] 核心认知
+> 不要假设任何网络调用会成功。每个远程调用的代码都应该考虑失败路径。
+
+## 1. 超时控制
+
+这是所有容错机制的**前提**——没有超时的系统迟早会被拖垮。
+
+```go
+// Go context 超时时序图
+ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
+defer cancel()
+
+resp, err := client.DoRequest(ctx, req)
+if err == context.DeadlineExceeded {
+ // 上游超时 → 走降级逻辑或快速返回错误
+}
+```
+
+| 层级 | 推荐超时值 | 说明 |
+|------|-----------|------|
+| HTTP 客户端 → 业务服务 | 3~5s | 留有余量给下游 |
+| gRPC → 内部服务 | 1~2s | 内网延迟低 |
+| DB 查询 | 500ms~1s | 长查询应在 SQL 层限制 |
+
+> [!tip] 超时传递原则
+> 如果整体 SLA 要求 P99 < 200ms,子调用的超时时间必须逐层递减。例如:网关 200ms → 订单服务 150ms → 库存服务 80ms。
+
+## 2. 重试机制
+
+> [!warning] 关键原则
+> 只对 **幂等操作** 重试!POST 创建操作直接重试会导致重复数据。GET、PUT(同参数)适合重试。
+
+### 指数退避 + Jitter
+
+```
+第 1 次重试:等待 1s + random(0~100ms)
+第 2 次重试:等待 2s + random(0~100ms)
+第 3 次重试:等待 4s + random(0~100ms)
+...
+```
+
+```go
+func retryWithBackoff(ctx context.Context, maxRetries int, fn func() error) error {
+ for attempt := uint(0); attempt <= uint(maxRetries); attempt++ {
+ if err := fn(); err != nil {
+ if attempt == uint(maxRetries) {
+ return err
+ }
+ // jitter: 随机偏移,避免所有客户端同时重试造成二次冲击
+ jitter := time.Duration(rand.Int63n(int64(time.Millisecond * 100)))
+ wait := time.Duration(math.Pow(2, float64(attempt)))*time.Second + jitter
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-time.After(wait):
+ }
+ } else {
+ return nil
+ }
+ }
+ return nil
+}
+```
+
+**Jitter 为什么重要?**
+- 如果没有随机偏移,当某个下游服务挂掉时,所有客户端会在同一时刻同时重试
+- 这会造成 **retry storm(重试风暴)**,对恢复中的服务施加二次冲击
+- 加上 jitter 后,请求均匀分散到时间窗口内
+
+### 可重试 vs 不可重试的错误类型
+
+| 可以重试 | 不应重试 |
+|---------|---------|
+| 连接超时 | 4xx Client Error(除 429) |
+| 连接重置 | 404 Not Found |
+| 502/503/504 Gateway Error | 业务错误(如余额不足) |
+| 并发冲突(乐观锁失败) | 403 Forbidden |
+
+## 3. 熔断器 (Circuit Breaker)
+
+当下游服务频繁失败时,快速失败避免线程堆积雪崩。
+
+```mermaid
+flowchart TD
+ CB{{🔘 CIRCUIT BREAKER}}
+
+ subgraph CL ["CLOSED — 正常"]
+ C["请求放行
⏱ 实时统计成功率
⚠️ 连续失败 → 熔断"]
+ end
+
+ subgraph OP ["OPEN — 熔断"]
+ O["🚫 请求短路
💥 直接返回降级响应
🛡 不调下游,防雪崩"]
+ end
+
+ subgraph HO ["HALF-OPEN — 探测"]
+ H["🔍 放行少量探测请求
✅ 成功 → 恢复全量流量
❌ 失败 → 重新熔断"]
+ end
+
+ CB --> CL
+ CL -.->|失败 > N| OP
+ OP -.->|等待超时| HO
+ HO -->|探测成功| CL
+ HO -->|探测失败| OP
+
+ style CL fill:#e6f9e6,stroke:#4caf50,stroke-width:3px,color:#000
+ style OP fill:#ffebee,stroke:#ef5350,stroke-width:3px,color:#000
+ style HO fill:#fff8e1,stroke:#ffa726,stroke-width:3px,color:#000
+```
+
+### 状态转换条件
+
+| 状态 | 触发条件 | 行为 | 退出条件 |
+|------|---------|------|---------|
+| **Closed** | 初始状态 / 从 Half-Open 恢复 | 正常放行请求 | 连续失败数 > threshold → 打开 |
+| **Open** | 失败率超过阈值 | 立即短路返回错误 | 等待 recoveryTimeout → 进入半开 |
+| **Half-Open** | 探测期 | 放少量请求测试 | 探测成功 → Closed;探测失败 → Open |
+
+### 实战示例
+
+```go
+// gobreaker 示例
+cb := state.NewCB(state.Settings{
+ Name: "UserService",
+ MaxElems: 10, // 窗口大小
+ WaitRetry: 5 * time.Second, // Open → Half-Open 等待时间
+ ReadyToTrip: func(counts state.Counters) bool {
+ return counts.Failures > 5 // 连续 5 次失败熔断
+ },
+})
+
+result := cb.Execute(doRequest)
+if result.Err != nil {
+ // 熔断打开,立即短路返回错误,不调用下游
+ return fallbackResponse()
+}
+```
+
+## 4. 限流 (Rate Limiting)
+
+保护下游服务不被过量请求压垮。
+
+### 常见算法
+
+```mermaid
+flowchart LR
+ subgraph "令牌桶"
+ T1["匀速添加令牌"]
+ T2["请求消耗令牌"]
+ T3["不够则拒绝"]
+ end
+
+ subgraph "滑动窗口"
+ S1["按时间片切分"]
+ S2["统计每片请求数"]
+ S3["超过阈值则拒绝"]
+ end
+```
+
+| 算法 | 特点 | 适用场景 |
+|------|------|---------|
+| **固定窗口** | 简单实现,存在边界突发问题 | 低频场景 |
+| **滑动窗口** | 精确控制,内存占用高 | 需要精细限流的场景 |
+| **令牌桶** | 允许一定突发,平均速率受限 | API 网关通用方案 |
+| **漏桶** | 强制匀速输出,不允突发 | 防止下游被打满 |
+
+### 限流层级
+
+```mermaid
+graph TB
+ Client["客户端"] --> GW["L1: 网关级限流
防刷 / DDOS"]
+ GW --> Biz["L2: 业务级限流
按用户/接口配额"]
+ Biz --> Downstream["L3: 下游服务限流
保护实例不被打满"]
+
+ style GW fill:#ffebee
+ style Biz fill:#fff3e0
+ style Downstream fill:#e8f5e9
+```
+
+## 5. 舱壁隔离 (Bulkhead)
+
+为不同下游服务分配独立的线程池/连接池,防止一个服务的故障蔓延到其他服务。
+
+```mermaid
+graph TB
+ Caller["调用方"]
+
+ subgraph Bulkhead["舱壁隔离"]
+ Pool1[订单池
maxActive=10]
+ Pool2[用户池
maxActive=5]
+ Pool3[支付池
maxActive=8]
+ end
+
+ Caller --> Pool1
+ Caller --> Pool2
+ Caller --> Pool3
+
+ Pool1 --> OrderSvc[[Order Service]]
+ Pool2 --> UserSvc[[User Service]]
+ Pool3 --> PaySvc[[Payment Service]]
+
+ note[订单服务爆满不会影响用户服务的调用]
+ Pool1 -.-> note
+```
+
+```go
+// poolgroup 示例:为不同服务隔离连接池
+orderPool := pool.New(10, 100) // 活跃10个,上限100个
+userPool := pool.New(5, 50)
+payPool := pool.New(8, 80)
+// 订单服务占满连接不会影响用户服务的调用
+```
+
+## 6. 降级策略
+
+当系统部分不可用时,通过降级保证核心功能可用。
+
+```mermaid
+flowchart TD
+ Req["用户请求"]
+
+ Req --> Normal{"正常链路是否可用?"}
+
+ Normal -- 是 --> Full["完整功能 ✅"]
+
+ Normal -- 否 --> Degrade{"降级级别?"}
+
+ Degrade -- "非核心模块" --> Skip["跳过该功能 ⚡"]
+ Degrade -- "核心模块不可用" --> Cache["返回缓存兜底 📦"]
+
+ Cache -- "无缓存" --> Default["返回默认值/提示页"]
+
+ Skip --> Partial["部分可用 ✅"]
+ Default --> Minimal["最低可用 ✅"]
+```
+
+### 常见降级场景
+
+| 场景 | 降级方案 | 影响 |
+|------|---------|------|
+| 推荐服务挂了 | 展示热门榜单 / 空 | 用户体验略降 |
+| 评论服务挂了 | 隐藏评论区 | 不影响购买流程 |
+| 搜索服务超时 | 返回最近浏览记录 | 降低用户感知 |
+| 库存服务不可用 | 显示"暂时无法确认库存" | 引导用户稍后再试 |
+
+## 7. 健康检查
+
+```mermaid
+sequenceDiagram
+ participant LB as 负载均衡器/K8s
+ participant S1 as 服务实例 A
+ participant S2 as 服务实例 B
+
+ LB->>S1: GET /healthz -> 200 OK
+ LB->>S2: GET /healthz -> 503 ERROR
+ Note over LB: 标记 S2 不健康,剔除出池
+ LB->>S2: GET /healthz -> 200 OK
+ Note over LB: 逐步恢复,重新加入池
+```
+
+- **存活探针 (Liveness)**:判断"进程是否还活着",挂了则重启
+- **就绪探针 (Readiness)**:判断"是否能接收流量",未就绪则剔除负载均衡池
+- **Readiness 比 Liveness 更重要**——一个进程活着但数据库连接耗尽时,应该停止接收流量而不是重启
+
+## 关联笔记
+
+- [[02-服务治理/API网关/README]] — 网关层的限流和熔断插件
+- [[02-服务治理/服务发现/README]] — 健康检查是服务发现的基础
+- [[04-可观测性/Metrics监控/README]] — 熔断器的指标暴露和告警联动
diff --git a/hzh/MS/02-服务治理/服务发现/README.md b/hzh/MS/02-服务治理/服务发现/README.md
new file mode 100644
index 0000000..dda7e13
--- /dev/null
+++ b/hzh/MS/02-服务治理/服务发现/README.md
@@ -0,0 +1,205 @@
+---
+tags: [microservice, service-discovery, consul, nacos, etcd, kubernetes]
+create time: 2026-05-05
+---
+
+# 服务发现
+
+## 概述
+
+服务实例的动态变化(扩容、缩容、故障重启)让硬编码地址成为不可能。服务要回答的核心问题是:**我怎么找到你?**
+
+> [!question] 引出问题
+> 假设你的订单服务有 3 个实例,运行在 `10.0.1.1:8080`、`10.0.1.2:8080`、`10.0.1.3:8080`。当其中一个实例扩容下线时,调用方如何得知最新的地址列表?手动改配置滚动重启?还是……有更好的办法?
+
+## 两种发现模式
+
+```mermaid
+graph TB
+ subgraph Client["客户端发现模式"]
+ A[Service A] -->|1.查询注册中心| R1[(Registry)]
+ R1 -->|2.返回实例列表| A
+ A -->|3.自选实例直连| B[Service B]
+ noteA[客户端内置负载均衡逻辑]
+ end
+
+ subgraph Server["服务端发现模式"]
+ C[Service C] -->|请求| P[LoadBalancer Proxy]
+ P -->|查询注册中心| R2[(Registry)]
+ R2 -->|返回实例| P
+ P -->|转发| D[Service D]
+ noteC[客户端无感知,透明代理]
+ end
+```
+
+**对比**:
+
+| 维度 | 客户端发现 | 服务端发现 |
+|------|-----------|-----------|
+| 典型实现 | Eureka、Consul、Nacos | Nginx、Envoy、K8s Service |
+| 耦合度 | 客户端嵌入注册逻辑 | 透明代理,客户端无感知 |
+| 性能 | 直连调用,延迟最低 | 多一跳代理开销 |
+| 运维复杂度 | 每门语言需独立 SDK | 统一部署代理,技术无关 |
+| 灵活性 | 客户端可自定义路由策略 | 受限于代理能力 |
+
+### 客户端发现的优劣势分析
+
+**优势**:
+- 直连调用,少了一跳网络开销
+- 客户端可以根据本地缓存做智能选择(如就近节点优先)
+- 框架成熟,Eureka/Consul 社区案例丰富
+
+**劣势**:
+- 每个服务实现中都需要集成 SDK,跨语言迁移成本高
+- 客户端需要处理实例列表的缓存与刷新逻辑
+- 新增服务时需要修改调用方的代码或配置
+
+### 服务端发现的优劣势分析
+
+**优势**:
+- 完全解耦——调用方只需知道 Proxy 地址
+- 统一治理入口,可以在代理层加限流、熔断等逻辑
+- 适合多语言团队,无需各自维护 SDK
+
+**劣势**:
+- 额外一跳增加延迟(通常 <1ms,高吞吐场景累积明显)
+- Proxy 本身成为单点瓶颈,必须做横向扩展
+- 调测复杂度上升——出了问题要看两层日志
+
+## 主流注册中心选型
+
+### Nacos(推荐国内团队首选)
+
+阿里开源,支持 AP(临时实例)+ CP(持久实例)双模型,同时提供配置管理功能。
+
+```go
+// Nacos 服务注册 & 拉取
+import (
+ "github.com/nacos-group/nacos-sdk-go/v2/clients"
+ "github.com/nacos-group/nacos-sdk-go/v2/common/constant"
+)
+
+// 创建注册客户端
+sc := constant.ServerConfig{
+ IpAddr: "127.0.0.1",
+ Port: 8848,
+}
+
+// 注册服务实例
+client, _ := clients.NewNamingClient(
+ value_map.NewValueMap(map[string]any{"serverConfig": sc}),
+)
+
+client.RegisterInstance(naming_param.RegisterInstanceParam{
+ Ip: "10.0.0.1",
+ Port: 8080,
+ ServiceName: "order-service",
+ ClusterName: "DEFAULT",
+})
+
+// 拉取某服务的可用实例列表
+instances, _ := client.SelectInstances(naming_param.SelectInstanceParam{
+ ServiceName: "order-service",
+})
+```
+
+### Consul
+
+HashiCorp 出品,基于 Raft 共识协议(CP),天然支持健康检查和 DNS 接口。
+
+**核心特点**:
+- 内建 KV 存储,可作为轻量配置中心
+- 支持 multi-datacenter 部署
+- DNS 接口:`order-service.service.consul` 可直接解析 IP
+
+### etcd + K8s Service
+
+纯容器环境下最自然的选择。etcd 存数据,K8s 提供完整的发现和负载均衡体系。
+
+```yaml
+# K8s Service — 服务端发现模式的代表
+apiVersion: v1
+kind: Service
+metadata:
+ name: order-service
+spec:
+ selector:
+ app: order
+ ports:
+ - port: 80
+ targetPort: 8080
+ type: ClusterIP
+```
+
+调用方只需 `http://order-service:80`,K8s 通过 iptables/IPVS 自动实现负载均衡。
+
+### Eureka
+
+Netflix 开源,AP 模型。**注意**:Eureka 2.x 已开源关闭,不建议新项目使用。已有系统在迁移到 Nacos 或 Consul 之前可以继续用。
+
+## 关键机制
+
+### 服务注册流程
+
+```mermaid
+sequenceDiagram
+ participant S as 服务实例
+ participant R as 注册中心
+ participant H as 健康检查器
+
+ S->>R: 1. Register(instance)
+ R-->>S: 2. ACK
+ Note over S,R: 实例写入内存 / etcd
+
+ loop 定时心跳
+ S->>R: 3. Heartbeat (每 5s)
+ R-->>S: 4. ACK
+ end
+
+ R->>H: 5. 超过心跳间隔未收到 → 标记不健康
+ H->>R: 6. 摘除实例
+```
+
+### 临时实例 vs 持久实例
+
+| 类型 | 宕机检测方式 | 数据存储 | 适用场景 |
+|------|-------------|---------|---------|
+| **临时实例 (ephemeral)** | 心跳超时自动摘除 | 内存 | Web 服务、应用实例 |
+| **持久实例 (persistent)** | 主动注销才摘除 | etcd | 数据库连接、外部依赖 |
+
+> [!warning] 常见陷阱
+> 把数据库当成临时实例注册 —— 数据库挂了不需要被 "检测到",它自己控制启停。应该用持久实例。
+
+### 优雅上下线
+
+服务下线时不能直接断网,否则正在处理的请求会失败。
+
+**上线流程**:
+1. 进程启动 → 加载配置、初始化连接池
+2. `/ready` 探针返回 200 → 注册中心注册 + K8s 加入负载均衡池
+3. 开始接收流量
+
+**下线流程**:
+1. 注册中心注销实例 → 停止接收新请求
+2. 等待正在处理的请求完成(最大等待 N 秒)
+3. 关闭连接池、保存状态
+4. 进程退出
+
+> [!tip] K8s Pod 优雅终止
+> ```yaml
+> spec:
+> terminationGracePeriodSeconds: 30 # 最多等 30 秒再 SIGKILL
+> ```
+> 配合 `preStop` Hook 可以提前摘除流量:
+> ```yaml
+> lifecycle:
+> preStop:
+> exec:
+> command: ["sh", "-c", "sleep 15"] # 给负载均衡摘流的时间
+> ```
+
+## 关联笔记
+
+- [[02-服务治理/API网关/README]] — API Gateway 是服务发现的用户之一
+- [[02-服务治理/容错模式/README]] — 健康检查是容错体系的基础
+- [[05-部署运维/Kubernetes/README]] — K8s Service 的服务发现原理
diff --git a/hzh/MS/02-服务治理/服务间通信/README.md b/hzh/MS/02-服务治理/服务间通信/README.md
new file mode 100644
index 0000000..687c3b9
--- /dev/null
+++ b/hzh/MS/02-服务治理/服务间通信/README.md
@@ -0,0 +1,201 @@
+---
+tags: [microservice, rpc, rest, grpc, message-queue, event-driven]
+create time: 2026-05-05
+---
+
+# 服务间通信
+
+## 概述
+
+微服务之间如何通信,是架构设计的核心决策之一。选错了通信方式,后面会带来一系列问题:耦合度太高、性能瓶颈、或者运维复杂度爆炸。
+
+## RPC vs RESTful API
+
+### 对比分析
+
+| 维度 | REST over HTTP/JSON | gRPC (HTTP/2) | GraphQL |
+|------|---------------------|---------------|---------|
+| **性能** | 序列化开销大 | Protocol Buffers,二进制高效 | 中等(JSON) |
+| **人类可读** | URL + JSON 直观 | 需要 Proto 定义辅助理解 | 查询语言自描述 |
+| **语言兼容性** | 广泛,任何能发 HTTP 的语言都能用 | 需要代码生成 | 需客户端 SDK |
+| **缓存** | 天然支持 HTTP 缓存 | 不支持(HTTP/2 多路复用替代) | 可设计缓存层 |
+| **版本管理** | URL 路径 (/v1/, /v2/) | Proto 文件向前兼容 | Schema 演进工具 |
+| **适用场景** | 对外 API、跨团队/跨组织调用 | 内部服务间高频强类型调用 | 前端聚合查询、移动端 |
+
+```mermaid
+graph TB
+ subgraph "何时选什么?"
+ D{"你的场景是?"}
+
+ D -->|"对外暴露 API"| REST["REST over HTTP"]
+ D -->|"内部服务高频调用"| GRPC["gRPC"]
+ D -->|"前端/移动端复杂查询"| GraphQL["GraphQL"]
+ D -->|"异步解耦通知"| MQ["消息队列"]
+ end
+```
+
+### 混合通信模式(推荐)
+
+实际工程中很少单一选型。**最佳实践是混合使用**:
+
+```mermaid
+sequenceDiagram
+ participant C as 客户端
+ participant GW as API Gateway
+ participant O as Order Service
+
+ note over C,O: 外部请求 — 用 REST/gRPC
+ C->>GW: POST /orders (HTTP/JSON)
+ GW->>O: CreateOrder (gRPC)
+
+ note over O,O: 内部处理 — 同步 + 异步组合
+ O->>O: 创建订单记录 (本地事务)
+ O-->>GW: {orderId: "ORD-001"}
+ GW-->>C: 200 OK
+
+ O->>O: Publish OrderCreated Event (MQ)
+ Note right of O: 通知类场景异步处理
+```
+
+## 同步通信
+
+### gRPC 协议详解
+
+gRPC 基于 Protocol Buffers(Proto3),利用 HTTP/2 的多路复用特性,非常适合高性能的内部服务间调用。
+
+```go
+// proto/order/v1/order.proto
+syntax = "proto3";
+package order.v1;
+
+service OrderService {
+ rpc CreateOrder(CreateOrderRequest) returns (CreateOrderResponse);
+ rpc GetOrder(GetOrderRequest) returns (Order);
+ rpc StreamOrders(StreamRequest) returns (stream Order); // 服务端流
+}
+
+message CreateOrderRequest {
+ string user_id = 1;
+ repeated Item items = 2;
+ float total = 3;
+}
+
+message Item {
+ string product_id = 1;
+ int32 quantity = 2;
+}
+
+enum OrderStatus {
+ UNKNOWN = 0;
+ PENDING = 1;
+ PAID = 2;
+ SHIPPED = 3;
+ CANCELLED = 4;
+}
+```
+
+**Proto3 注意事项**:
+- 字段编号(`= 1`, `= 2`)不能重编——破坏向后兼容
+- 新增字段标记为 `optional` 时 Proto3 才能区分"未设置"和"默认值"
+- `repeated` 字段空数组不会省略,需要特殊处理
+
+### RESTful API 设计规范
+
+```
+GET /api/v1/orders → 获取订单列表
+POST /api/v1/orders → 创建订单
+GET /api/v1/orders/{id} → 获取订单详情
+PUT /api/v1/orders/{id} → 更新订单(全量替换)
+PATCH /api/v1/orders/{id} → 部分更新
+DELETE /api/v1/orders/{id} → 删除订单
+```
+
+**核心原则**:
+- **资源名词化**:URL 用名词复数,不用动词
+- **无状态**:每个请求携带完整上下文(通过 Header 传 Token)
+- **统一接口**:用标准 HTTP Method + Status Code 表达语义
+
+## 异步通信
+
+### 事件驱动架构
+
+> [!question] 关键时刻的判断
+> 用户点击"提交订单"后,系统要做:① 创建订单记录 ② 扣减库存 ③ 扣款 ④ 发送短信通知。哪些步骤必须同步完成?哪些可以异步处理?为什么?
+
+**答案**:①~③需要立即得到结果或保证一致性,走同步流程;④纯粹的通知类场景完全异步,用消息队列解耦。即使扣款失败,短信也没必要发出。
+
+```mermaid
+graph LR
+ A["订单创建"] --> B{"是否需要同步响应?"}
+ B -->|"是"| Sync["同步 RPC 链"]
+ B -->|"否"| Async["异步 MQ 事件"]
+
+ Sync --> Stock["查库存 (RPC)"]
+ Stock --> Pay["支付 (RPC)"]
+
+ Async --> SMS["发短信 (Event)")
+ Async --> Points["加积分 (Event)"]
+ Async --> Email["发确认邮件 (Event)"]
+```
+
+### 消息队列选型
+
+| 方案 | 吞吐量 | 延迟 | 可靠性 | 特色能力 |
+|------|--------|------|--------|---------|
+| **RocketMQ** | 极高 (百万级) | 毫秒级 | 事务消息支持 | 阿里出品,国内首选 |
+| **Kafka** | 最高 (千万级) | 秒级 | 持久化 | 大数据生态集成 |
+| **RabbitMQ** | 中等 (十万级) | 亚毫秒 | 高 | 灵活的路由模型 |
+| **Pulsar** | 高 | 毫秒级 | 高 | 存储计算分离 |
+
+### 发布订阅 vs 点对点
+
+```mermaid
+graph TB
+ Publisher[生产者] --> Broker[(MQ Broker)]
+
+ Broker --> Sub1["消费者组 A
Topic: order-events"]
+ Broker --> Sub2["消费者组 B
Topic: order-events"]
+ Broker --> Sub3["消费者组 C
Topic: order-events"]
+
+ style Sub1 fill:#cfe2f3
+ style Sub2 fill:#d9e2f3
+ style Sub3 fill:#e2d9f3
+```
+
+- **发布订阅 (Pub/Sub)**:一个消息被多个消费组分别消费,每个组内只有一个实例收到
+- **点对点 (Queue)**:一条消息只被一个消费者处理
+
+## 同步与异步的组合拳
+
+```mermaid
+sequenceDiagram
+ participant Client
+ participant Gateway
+ participant Order
+ participant MQ
+ participant Notify
+ participant Analytics
+
+ Client->>Gateway: 下单请求
+ Gateway->>Order: 创建订单
+ Order->>Order: 写库 + 出消息(事务)
+ Order-->>Gateway: 返回 orderId
+ Gateway-->>Client: 202 Accepted ⚡
+
+ Note over MQ: 异步后续处理
+ MQ->>Notify: 发送通知
+ MQ->>Analytics: 数据统计
+
+ Note right of Client: 用户体验好:
主流程快速响应
非关键任务后台处理
+```
+
+> [!keypoint] 关键洞察
+> - 同步链路:**gRPC 直连**,延迟低,适合核心事务链
+> - 异步链路:**消息队列**,解耦非关键路径,即使失败也不影响主干
+> - 核心原则:**同步保性能,异步保解耦**
+
+## 关联笔记
+
+- [[02-服务治理/API网关/README]] — API Gateway 负责协议转换
+- [[03-数据一致性/分布式事务/README]] — 消息投递的一致性保障
+- [[05-部署运维/Kubernetes/README]] — Sidecar 代理透明拦截通信流量
diff --git a/hzh/MS/02-服务治理/流量治理/README.md b/hzh/MS/02-服务治理/流量治理/README.md
new file mode 100644
index 0000000..2ccc6e9
--- /dev/null
+++ b/hzh/MS/02-服务治理/流量治理/README.md
@@ -0,0 +1,164 @@
+---
+tags: [microservice, canary-release, blue-green, traffic-routing, istio]
+create time: 2026-05-05
+---
+
+# 流量治理
+
+## 概述
+
+灰度发布(也叫金丝雀发布)是降低变更风险的核心手段。它让你将新版本逐步推向一小部分用户,观察指标正常后再全量。
+
+> [!question] 如何安全地上线?
+> 你修复了一个紧急 Bug,但这次改动涉及核心支付链路。直接全量发布一旦出问题损失巨大。有没有办法先小范围验证,确认没问题再放量?
+
+## 灰度策略全景
+
+```mermaid
+flowchart LR
+ A["🟢 v1 (稳定版)
95% 流量"] --> B["🔵 v2 (测试版)
5% 流量"]
+ B --> C{"监控指标?"}
+
+ C -- "✅ 一切正常" --> D["逐步放量
10% → 25% → 50%"]
+ C -- "❌ 错误率飙升" --> E["自动回滚到 v1 🔄"]
+
+ D --> F{"全部放量至 100%"}
+ F --> G["🟢 v2 成为新稳定版"]
+```
+
+### 常见灰度策略对比
+
+| 策略 | 描述 | 优点 | 缺点 | 适用场景 |
+|------|------|------|------|---------|
+| **按百分比** | 随机分配 N% 流量到新版本 | 简单粗暴,覆盖面广 | 可能只命中特定用户 | 通用场景 |
+| **按用户 ID** | 指定用户/内部账号走新版 | 可精准控制测试范围 | 样本不够代表性 | 内部验收阶段 |
+| **按 Header** | `x-canary: true` 路由到新版本 | 灵活性最高 | 需要客户端配合 | QA / AB 测试 |
+| **按地域** | 某个城市/机房的新版本 | 地域性问题的理想试验场 | 地域偏差大 | 全球化部署 |
+| **按设备类型** | iOS 新用户先用新版 | 覆盖目标人群 | 样本有限 | 移动端发版 |
+
+## 蓝绿 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 运行中
100% 流量"]
+ S2["部署 v2
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
+```
+
+## 高级路由规则
+
+### Istio VirtualService
+
+```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
+```
+
+## 流量治理的其他维度
+
+除了发布策略,流量治理还包括:
+
+| 能力 | 说明 |
+|------|------|
+| **熔断降级** | 下游不可用时自动降级,参见 [[02-服务治理/容错模式/README]] |
+| **限流** | 保护上游不因过量请求被打垮,参见 [[02-服务治理/容错模式/README]] |
+| **重试** | 对瞬态故障自动恢复,参见 [[02-服务治理/容错模式/README]] |
+| **黑白名单** | 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% 熔断 |
+
+## 关联笔记
+
+- [[02-服务治理/API网关/README]] — API Gateway 的路由和权重分发
+- [[04-可观测性/Metrics监控/README]] — 灰度期间的监控面板设计
+- [[05-部署运维/SRE实践/README]] — 基于 SLO 的发布决策
diff --git a/hzh/MS/02-服务治理/配置管理/README.md b/hzh/MS/02-服务治理/配置管理/README.md
new file mode 100644
index 0000000..468e784
--- /dev/null
+++ b/hzh/MS/02-服务治理/配置管理/README.md
@@ -0,0 +1,173 @@
+---
+tags: [microservice, config-management, nacos, apollo, spring-cloud-config]
+create time: 2026-05-05
+---
+
+# 配置管理
+
+## 概述
+
+当服务实例数以百计时,手动管理配置是不可想象的。配置中心提供 **集中化、动态化、版本化** 的配置管理能力。
+
+> [!question] 引出配置中心的必要性
+> 假设你的 50 个服务实例都要连同一个数据库。现在需要把数据库密码从 `password1` 改为 `password2`,你会怎么改?登录每台机器改配置文件?滚动重启所有 Pod?还是……有更好的办法?
+
+## 核心价值
+
+```mermaid
+flowchart LR
+ Dev["开发/运维"] --> CC[(配置中心)]
+ CC -->|热更新推送| S1[Service A]
+ CC -->|热更新推送| S2[Service B]
+ CC -->|热更新推送| S3[Service C]
+
+ CC -.->|版本管理| V1[v1.0 历史配置]
+ CC -.->|版本管理| V2[v1.1 当前配置]
+```
+
+| 能力 | 说明 |
+|------|------|
+| **动态刷新** | 修改配置后立即生效,无需重启 |
+| **环境隔离** | dev / test / prod 配置分离 |
+| **版本管理与回滚** | 每次变更有迹可循,一键回滚 |
+| **权限控制** | 敏感配置(密钥、Token)按角色隔离 |
+| **配置审计** | 记录谁在什么时候改了什么 |
+
+## 配置分层模型
+
+```mermaid
+graph TB
+ subgraph "配置优先级(低 → 高)"
+ Base["Base 基线配置
各项目共享的默认值"]
+ App["应用级配置
每个服务的专属配置"]
+ Env["环境级配置
dev/test/prod 差异"]
+ Instance["实例级配置
单节点调优参数"]
+ end
+
+ style Base fill:#e3f2fd
+ style App fill:#fff3e0
+ style Env fill:#fce4ec
+ style Instance fill:#e8f5e9
+```
+
+**典型配置项分层**:
+
+| 层级 | 示例 | 修改频率 |
+|------|------|---------|
+| 基线配置 | Redis 集群地址、公共超时时间 | 极低 |
+| 应用配置 | 线程池大小、日志级别 | 低 |
+| 环境配置 | DB 连接串、Feature Flag | 中 |
+| 实例配置 | 单机限流阈值、调试开关 | 高 |
+
+## Nacos Config 示例
+
+```go
+// 动态监听配置变更
+configClient, _ := clients.NewConfigClient(value_map.NewValueMap(map[string]any{
+ "serverConfig": sc,
+}))
+
+content, _ := configClient.GetConfig(config_param.GetConfigParam{
+ DataId: "order-service.yaml",
+ Group: "DEFAULT_GROUP",
+})
+
+// 监听配置变化——Nacos 推送更新回调
+configClient.ListenChange(config_param.ListenChangeParam{
+ DataId: "order-service.yaml",
+ Group: "DEFAULT_GROUP",
+ Callback: func(content string) {
+ fmt.Println("配置更新了:", content)
+ // 重新加载配置...
+ ReloadConfig(content)
+ },
+})
+```
+
+### 配置文件的命名规范
+
+推荐格式:`{service-name}.{environment}.yaml`
+
+| 服务名 | 环境 | Data ID |
+|--------|------|---------|
+| order-service | dev | `order-service.dev.yaml` |
+| order-service | prod | `order-service.prod.yaml` |
+| user-service | prod | `user-service.prod.yaml` |
+
+## Apollo vs Nacos Config 对比
+
+| 维度 | Apollo (携程) | Nacos Config (阿里) | Spring Cloud Config |
+|------|--------------|---------------------|--------------------|
+| **界面体验** | Web UI 完善,操作直观 | 较好 | 需自建 |
+| **发布流程** | 支持审核、灰度、回滚 | 基础发布+回滚 | 依赖 Git 工作流 |
+| **配置粒度** | 应用/Cluster/Namespace 多维 | Service/Group | File-based |
+| **性能** | AP 模型,延迟 < 1s | AP 模型,延迟 < 1s | 读取 Git,延迟稍高 |
+| **生态集成** | 适合 Java/Spring 体系 | Java + Go + Python 等 | 仅 Spring 生态 |
+| **适用场景** | 大型企业,多团队协同 | 中小团队快速落地 | 纯 Spring 项目 |
+
+## K8s ConfigMap & Secret
+
+纯 K8s 环境内的原生方案:
+
+```yaml
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: order-service-config
+data:
+ application.yaml: |
+ server:
+ port: 8080
+ datasource:
+ url: jdbc:mysql://db-host:3306/orders
+ username: ${DB_USERNAME}
+ password: ${DB_PASSWORD}
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ name: order-service-secrets
+type: Opaque
+stringData:
+ DB_USERNAME: "app_user"
+ DB_PASSWORD: "s3cret_p@ss"
+```
+
+注入到容器:
+
+```yaml
+envFrom:
+ - configMapRef:
+ name: order-service-config
+ - secretRef:
+ name: order-service-secrets
+```
+
+> [!warning] K8s 原生方案的局限
+> - 修改 ConfigMap 后 Pod 不会自动重载配置(需配合 Sidecar 或手动触发 reload)
+> - 没有版本管理和灰度发布能力
+> - **建议**:简单项目用 K8s ConfigMap,复杂场景上 Apollo/Nacos
+
+## 敏感信息处理
+
+> [!danger] 安全红线
+> **永远不要**在代码仓库中硬编码密码、API Key、私钥等敏感信息。
+
+```mermaid
+flowchart LR
+ Dev["开发者本地"] -->|"K8s Secret / Vault"| Store["加密存储"]
+ Store -->|"运行时解密"| Runtime["运行时的环境变量"]
+ Runtime --> App["应用程序"]
+
+ Audit["审计系统"] -.->|"只读访问"| Store
+```
+
+**推荐方案**:
+- **K8s Secret** — 小型集群内使用(base64 编码,非加密,配合 EncryptionConfiguration 增强)
+- **HashiCorp Vault** — 企业级密钥管理,动态秘钥、自动轮换
+- **云厂商 KV 服务** — AWS Secrets Manager / 阿里云 KMS / 腾讯云 SecretManager
+
+## 关联笔记
+
+- [[02-服务治理/服务发现/README]] — Nacos 同时提供服务发现和配置管理
+- [[05-部署运维/Kubernetes/README]] — ConfigMap/Secret 是 K8s 的配置注入方式
diff --git a/hzh/MS/03-数据一致性.md b/hzh/MS/03-数据一致性.md
deleted file mode 100644
index b12426d..0000000
--- a/hzh/MS/03-数据一致性.md
+++ /dev/null
@@ -1,217 +0,0 @@
----
-tags: [microservice, distributed-system, database, data-consistency, saga-pattern, tcc, idempotency, outbox-pattern]
-create time: 2026-04-29 12:03
----
-
-# 数据一致性
-
-## 概述
-
-微服务的核心设计原则是 **"每个服务拥有独立数据库"**,这带来了分布式事务和数据一致性的经典难题。本文梳理主要解决方案及其取舍。
-
-## 为什么不能共享数据库
-
-```mermaid
-graph LR
- S1[订单服务 DB]
- S2[库存服务 DB]
-
- subgraph BAD["反模式:共享数据库"]
- S1 --- SHARED[(共享 DB)]
- S2 --- SHARED
- end
-```
-
-> [!failure] 反模式警告
-> 如果两个服务连接同一个数据库的同一张表,它们就不再是独立的微服务——你得到的是**分布式单体**。服务可以随意互相查询彼此的数据,失去了边界和自治性。
-
-## 分布式事务方案概览
-
-| 方案 | 一致性级别 | 性能 | 复杂度 | 适用场景 |
-|------|-----------|------|--------|---------|
-| 本地事务 + 事件通知 | 最终一致 | 高 | 低 | 绝大多数场景 |
-| Saga 模式 | 最终一致 | 中 | 中 | 长流程业务 |
-| TCC | 强最终一致 | 中 | 高 | 对一致性要求较高的场景 |
-| AT 模式 (Seata) | 伪强一致 | 中低 | 低 | 不想改业务代码时 |
-
-> [!info] 选择策略
-> 先默认用 **本地事务 + 异步事件**(最简单、最高效),只有在业务明确需要 Saga 或 TCC 时才升级。
-
-## 方案一:本地事务 + 消息队列
-
-这是**最常用**的方案,核心思想是将"数据变更 + 发消息"合并到一个本地事务中。
-
-```mermaid
-sequenceDiagram
- participant U as 用户
- participant O as 订单服务
- participant MQ as 消息队列
- participant I as 库存服务
-
- U->>O: 创建订单
- O->>O: BEGIN 事务
- O->>O: 插入订单记录
- O->>MQ: 发送订单创建消息
- O->>O: COMMIT 事务
- MQ-->>I: 投递消息
- I->>I: 扣减库存
- I-->>O: 返回结果(可选)
-```
-
-### 实战:电商订单创建流程
-
-以「用户下单」为例,这个流程涉及 **订单服务**(创建订单)和 **库存服务**(扣减库存),是典型的跨服务数据一致性问题:
-
-| 步骤 | 动作 | 一致性保障点 |
-|------|------|-------------|
-| 1 | 用户点击"提交订单" | 前端防重复提交(按钮置灰 / Token 机制) |
-| 2 | 订单服务写入订单表 + 发送 `order.created` 消息 | **事务边界**:两件事必须在同一个本地事务中完成 |
-| 3 | 消息队列投递给库存服务 | 保证消息至少一次投递(At-Least-Once) |
-| 4 | 库存服务扣减库存 | **幂等性**:防止消息重投导致库存被扣两次 |
-| 5 | 库存不足时回滚订单 | 通过 Sagas 补偿:已创建的订单标记为"取消" |
-
-> [!question] 思考
-> 如果步骤 2 的数据库写成功了,但 MQ 发消息失败了,会发生什么?用户看到下单成功但实际上库存没被锁定。这说明为什么必须用事务消息或本地消息表,而不是直接调 MQ API。
-
----
-
-### 如何保证"事务内既写库又发消息"?
-
-**方案 A:事务消息**(推荐)
-- RocketMQ /阿里云 MSE 原生支持事务消息
-- MQ 回查机制确保消息不丢
-
-**方案 B:本地消息表**
-- 在业务库里建一张 `outbox` 表
-- 业务事务同时写入业务数据和消息记录
-- 后台定时任务扫描未发送的消息推送出去
-
-```go
-// 本地消息表方案示意
-tx, _ := db.Begin()
-// 1. 业务操作
-tx.Exec("UPDATE accounts SET balance = balance - ? WHERE id = ?", amount, fromID)
-// 2. 记录待发送消息(带状态字段)
-tx.Exec("INSERT INTO outbox (topic, payload, status, created_at) VALUES (?, ?, 'pending', NOW())", "order.created", jsonPayload)
-tx.Commit()
-// 后台进程轮询 outbox 表中 status='pending' 的记录,发送到 MQ 后更新为 'sent'
-```
-
-#### Outbox 表建表示例
-
-```sql
-CREATE TABLE outbox (
- id BIGSERIAL PRIMARY KEY,
- topic VARCHAR(255) NOT NULL, -- 消息主题
- payload JSONB NOT NULL, -- 消息体
- status VARCHAR(20) NOT NULL DEFAULT 'pending', -- pending / sent / failed
- error_msg TEXT, -- 失败原因
- created_at TIMESTAMP NOT NULL DEFAULT NOW(),
- sent_at TIMESTAMP
-);
-
--- 加速定时扫描查询
-CREATE INDEX idx_outbox_pending ON outbox (status, created_at) WHERE status = 'pending';
-```
-
-### 消费幂等性
-
-消息可能重复投递(网络超时、MQ 重投),消费者必须做到**幂等**——处理一次和处理多次的结果完全相同。
-
-**三种常见策略:**
-
-| 策略 | 实现方式 | 适用场景 |
-|------|---------|---------|
-| 数据库唯一约束 | 用 `msg_id` 或业务主键做 `UNIQUE` | 最可靠,推荐首选 |
-| Redis 去重键 | SET 一个 TTL Key(如 `dedup:{msg_id}` 过期 24h) | 高吞吐场景,需考虑 Redis 可用性 |
-| 乐观锁版本控制 | UPDATE 时加 `WHERE version = old_version` | 适用于金额调整类操作 |
-
-```go
-// 推荐方案:利用 UNIQUE 约束做幂等保障
-_, err := db.Exec(`
- INSERT INTO order_events (msg_id, order_id, action, amount)
- VALUES ($1, $2, $3, $4)
- ON CONFLICT (msg_id) DO NOTHING -- 重复到达时静默忽略
-`, msgID, orderID, action, amount)
-if err != nil {
- // 其他错误才需要处理,UNIQUE 冲突直接忽略
- if !isUniqueViolation(err) {
- log.Error("process message failed", err)
- }
-}
-// 执行业务逻辑...
-```
-
-> [!tip] 设计要点
-> `ON CONFLICT DO NOTHING` 比先查后插更可靠——它消除了竞态窗口。即使用两个实例同时收到同一条消息,只会有一个成功写入。
-
-> [!question] 思考
-> 为什么要在生产者侧保证消息可靠投递,而不是靠消费者反复拉取重试?
-
-## 方案二:Saga 模式
-
-Saga 适用于**跨多个服务的长流程操作**,将大事务拆成一系列本地小事务,每个步骤都有对应的补偿操作。
-
-```mermaid
-graph LR
- S1[① 创建订单
→ 取消订单]
- S2[② 扣减库存
→ 恢复库存]
- S3[③ 支付扣款
→ 退款]
- S4[④ 发货
→ 无补偿]
-
- S1 --> S2 --> S3 --> S4
-```
-
-**编排式 vs 编舞式**:
-
-```mermaid
-graph TB
- subgraph ORCHESTRATION["编排式 — 中心协调器"]
- CO[Coordinator] --> S1[OrderSvc]
- CO --> S2[InventorySvc]
- CO --> S3[PaymentSvc]
- end
-
- subgraph CHOREOGRAPHY["编舞式 — 事件驱动"]
- E1[订单创建] --> S11[订单服务]
- S11 --> E2[库存不足事件]
- E2 --> S12[库存服务]
- S12 --> E3[扣减完成事件]
- E3 --> S13[支付服务]
- end
-```
-
-| | 编排式 | 编舞式 |
-|---|--------|--------|
-| 控制流 | 中心化 Coordinator | 各服务通过事件自发响应 |
-| 可观测性 | ✅ 集中管理 | ❌ 流程散布在各服务 |
-| 耦合度 | 依赖 Coordinator | 服务间仅感知事件 |
-
-## 方案三:TCC 与 AT 模式
-
-> [!abstract] 进阶了解
->
-> **TCC** (Try-Confirm-Cancel):每个事务步骤实现三个接口。适合对一致性要求严格且能承受开发成本的业务。
->
-> **AT 模式** (Seata):框架层自动处理两阶段提交,对业务透明。本质上是基于 undo_log 的增强型 XA,性能低于 Saga。
-
-## 总结选型指南
-
-> [!summary] 决策树
->
-> ```mermaid
-> graph TD
-> A["跨几个服务"] -->|"1-2"| B["本地事务 + 事件通知"]
-> A -->|"3+"| C["Saga 模式"]
-> B -->|"强"| D["加幂等,必要时上 TCC"]
-> B -->|"弱"| E["本地事务已够"]
-> C -->|"不能"| F["考虑 AT 模式"]
-> C -->|"能"| G["自行实现补偿"]
-> ```
->
-> **经验法则**:80% 的场景,本地事务 + MQ 就足够了。先别急着上复杂方案。
-
-## 关联笔记
-
-- [[01-基础概念]] — 微服务拆分与独立数据库原则
-- [[02-服务治理]] — 服务调用链路上的超时、重试、熔断
diff --git a/hzh/MS/03-数据一致性/ID生成/README.md b/hzh/MS/03-数据一致性/ID生成/README.md
new file mode 100644
index 0000000..076fa0c
--- /dev/null
+++ b/hzh/MS/03-数据一致性/ID生成/README.md
@@ -0,0 +1,157 @@
+---
+tags: [microservice, id-generation, snowflake, uuid, distributed-id]
+create time: 2026-05-05
+---
+
+# 分布式 ID 生成
+
+## 概述
+
+在微服务架构中,数据库被拆分成多个独立实例,不再共享自增主键。如何生成分布式环境下全局唯一的 ID,是一个经典问题。
+
+```mermaid
+graph LR
+ A["❌ 数据库 AUTO_INCREMENT"] -->|"分库后冲突"| Problem["不可用"]
+
+ B["✅ 分布式 ID"] --> Unique["全局唯一"]
+ B --> Ordered["趋势有序"]
+ B --> HighThroughput["高吞吐"]
+
+ style Problem fill:#ffebee
+ style Unique fill:#e8f5e9
+ style Ordered fill:#e8f5e9
+ style HighThroughput fill:#e8f5e9
+```
+
+> [!question] 为什么要自己生成?不用数据库自增?
+>
+> - **分库后**:每个库的自增 ID 从 1 开始,必然冲突
+> - **性能瓶颈**:DB 序列或号段模式在高并发下成为瓶颈
+> - **耦合度高**:ID 生成依赖特定数据库类型
+
+## 主流方案对比
+
+| 方案 | 唯一性保证 | 有序性 | 性能 (QPS) | 复杂度 | 适用场景 |
+|------|-----------|--------|-----------|--------|---------|
+| **UUID** | MD5/SHA 哈希保证 | ❌ 完全无序 | ⭐⭐⭐⭐⭐ | 极低 | 临时标识、缓存 Key |
+| **雪花算法 (Snowflake)** | WorkerId + 时间戳 | ✅ 趋势有序 | ⭐⭐⭐⭐⭐ | 中 | 通用方案,首选 |
+| **号段模式** | DB 批量发放 | ✅ 严格有序 | ⭐⭐⭐⭐ | 中 | 已有 DB 架构改造 |
+| **Leaf (美团)** | Snowflake + 号段 | ✅ 趋势/严格有序 | ⭐⭐⭐⭐⭐ | 中高 | 大规模生产环境 |
+| **NanoID** | Base62 + CSPRNG | ❌ 无序 | ⭐⭐⭐⭐⭐ | 低 | API Token、短链 |
+
+## 雪花算法 (Snowflake)
+
+Twitter 开源的经典算法,将 ID 分为三部分:
+
+```
+64 bit: 1 bit(符号位) + 41 bit(时间戳) + 10 bit(机器ID) + 12 bit(序列号)
+ │ │ │ │
+ │ │ │ └─ 每毫秒最多 4096 个 ID
+ │ │ └──────────────── 1024 台机器
+ │ └────────────────────────────── ~69 年跨度
+ └────────────────────────────────────────── 固定为 0
+```
+
+### 核心公式
+
+```go
+// 伪代码
+func generateID() int64 {
+ timestamp = currentMillis() // 当前毫秒时间戳(相对时间戳)
+ workerId = 1 // 机器编号 (0-1023)
+ sequence = incrementSequence() // 递增序号 (0-4095)
+
+ return (timestamp << 22) | // 时间戳占高位
+ (workerId << 12) | // 机器 ID 放中间
+ sequence // 序列号放在低位
+}
+```
+
+### Go 实现要点
+
+```go
+type Snowflake struct {
+ mu sync.Mutex
+ lastTime int64
+ sequence int64
+ workerId int64
+ workerBits uint8 = 10
+ stepBits uint8 = 12
+}
+
+func (sf *Snowflake) NextID() int64 {
+ sf.mu.Lock()
+ defer sf.mu.Unlock()
+
+ now := time.Now().UnixMilli()
+ if now < sf.lastTime {
+ panic("clock moved backwards") // 时钟回拨保护
+ }
+
+ if now == sf.lastTime {
+ sf.sequence++
+ } else {
+ sf.sequence = 0
+ }
+
+ sf.lastTime = now
+
+ return (now << 22) | (sf.workerId << 12) | sf.sequence
+}
+```
+
+### 注意事项
+
+| 问题 | 解决方案 |
+|------|---------|
+| **时钟回拨** | 等待到回拨前的时间点再继续;或分配备用 WorkerId |
+| **WorkerId 分配** | 启动时从注册中心获取,或使用 K8s Pod Name 映射 |
+| **单机 QPS 上限** | 单 WorkerId × 单机房约 409.6 万/秒,通常够用 |
+| **跨代际兼容性** | 新字段插入会改变位移量,设计时需预留比特位 |
+
+## UUID v7 (时间有序 UUID)
+
+如果你不想维护 Snowflake 的 WorkerId,可以考虑 **UUID v7**——它是 RFC 9562 定义的新版本,保持了时序性。
+
+```
+UUID v7: 48-bit timestamp + 12-bit rand_a + 4-bit version + 12-bit rand_b + 2-bit variant + 62-bit rand_c
+```
+
+| 维度 | UUID v4 | UUID v7 |
+|------|---------|---------|
+| **生成方式** | 纯随机 | 时间戳 + 随机数 |
+| **有序性** | ❌ 完全随机 | ✅ 趋势有序 |
+| **索引效率** | ❌ 随机插入导致页分裂 | ✅ 顺序插入友好 |
+| **存储大小** | 16 bytes | 16 bytes |
+| **实现复杂度** | 极低 | 低(标准库支持) |
+
+> [!tip] 如果你的数据库是 MySQL 5.7+,直接改用 `BINARY(16)` 存储 UUID v7,比 BIGINT AUTO_INCREMENT 更优。
+
+## 号段模式
+
+基于数据库分批领取 ID 区间:
+
+```mermaid
+sequenceDiagram
+ App->>DB: SELECT max_id FROM id_generator WHERE biz='order'
+ DB-->>App: max_id = 10000, step = 2000
+
+ Note over App: 内存中维护 [10000, 12000) 号段
+
+ loop 每次请求
+ App->>App: ID++ (本地原子操作)
+ end
+
+ App->>DB: UPDATE id_generator SET max_id = 12000 WHERE max_id = 10000
+ DB-->>App: ACK
+
+ Note over App: 下次取号段: [12000, 14000)
+```
+
+**优点**:兼容现有 MySQL 架构,无需引入外部组件。
+**缺点**:存在 ID 浪费(宕机未用完的号段),极端情况下可能产生空洞。
+
+## 关联笔记
+
+- [[03-数据一致性/数据库拆分/README]] — 分库分表场景下的 ID 生成
+- [[03-数据一致性/分布式事务/README]] — Outbox 消息 ID 也需要全局唯一
diff --git a/hzh/MS/03-数据一致性/README.md b/hzh/MS/03-数据一致性/README.md
new file mode 100644
index 0000000..e191e2c
--- /dev/null
+++ b/hzh/MS/03-数据一致性/README.md
@@ -0,0 +1,39 @@
+---
+tags: [microservice, data-consistency]
+create time: 2026-04-29 12:03
+---
+
+# 数据一致性
+
+## 概述
+
+微服务的核心设计原则是 **"每个服务拥有独立数据库"**,这带来了分布式事务和数据一致性的经典难题。本文梳理主要解决方案及其取舍。
+
+## 知识体系
+
+```mermaid
+graph LR
+ A["数据库拆分"] --> B["分布式事务"]
+ B --> C["ID 生成"]
+
+ style A fill:#e3f2fd
+ style B fill:#fff3e0
+ style C fill:#e8f5e9
+```
+
+| # | 主题 | 核心问题 |
+|---|------|----------|
+| 1 | [[03-数据一致性/数据库拆分/README]] | 每个服务独立 DB,表大了怎么拆分?跨库查询怎么做? |
+| 2 | [[03-数据一致性/分布式事务/README]] | 本地事务 + MQ、Saga、TCC,哪个方案最合适? |
+| 3 | [[03-数据一致性/ID生成/README]] | 没有自增主键了,全局唯一 ID 怎么生成? |
+
+### 学习建议
+
+> [!tip] 学习路径
+> 先理解"为什么不能共享数据库",再学分库分表的策略,最后深入分布式事务方案选型。ID 生成是最轻量的话题,可以随时了解。
+
+### 关联笔记
+
+- [[01-基础概念]] — 微服务拆分与独立数据库原则
+- [[02-服务治理]] — 服务调用链路上的超时、重试、熔断
+- [[hzh/MS/README.md]] — 完整微服务知识索引
diff --git a/hzh/MS/03-数据一致性/分布式事务/README.md b/hzh/MS/03-数据一致性/分布式事务/README.md
new file mode 100644
index 0000000..030c5cb
--- /dev/null
+++ b/hzh/MS/03-数据一致性/分布式事务/README.md
@@ -0,0 +1,249 @@
+---
+tags: [microservice, distributed-transactions, saga, tcc, outbox]
+create time: 2026-05-05
+---
+
+# 分布式事务
+
+## 概述
+
+每个服务拥有独立数据库,跨服务的"一次操作"实际上涉及**多个本地事务**。如何保证这些本地事务要么全部成功、要么全部回滚,就是分布式事务要解决的问题。
+
+```mermaid
+graph LR
+ A["用户下单"] --> B["订单服务
写库"]
+ B --> C["库存服务
扣减"]
+ C --> D["支付服务
扣款"]
+
+ style A fill:#e3f2fd
+ style B fill:#fff3e0
+ style C fill:#fff3e0
+ style D fill:#fff3e0
+```
+
+## 分布式事务方案全景
+
+| 方案 | 一致性级别 | 性能 | 复杂度 | 适用场景 |
+|------|-----------|------|--------|---------|
+| **本地事务 + MQ 事件** | 最终一致 | ⭐⭐⭐⭐⭐ | ⭐ | 绝大多数场景 |
+| **Saga 模式** | 最终一致 | ⭐⭐⭐ | ⭐⭐ | 长流程业务 |
+| **TCC** | 强最终一致 | ⭐⭐⭐ | ⭐⭐⭐⭐ | 对一致性要求较高的场景 |
+| **AT 模式 (Seata)** | 伪强一致 | ⭐⭐ | ⭐ | 不想改业务代码时 |
+
+> [!tip] 选择策略
+> **先默认用本地事务 + 异步事件(最简单、最高效)**,只有在业务明确需要 Saga 或 TCC 时才升级。80% 的场景,本地事务 + MQ 就足够了。
+
+## 方案一:本地事务 + 消息队列
+
+核心思想:**将"数据变更 + 发消息"合并到一个本地事务中。**
+
+### Outbox 模式(推荐)
+
+```mermaid
+sequenceDiagram
+ participant App as 应用服务
+ participant DB as 数据库
+ participant Outbox as Outbox 表
+ participant MQ as 消息队列
+ participant Sub as 订阅方
+
+ App->>DB: BEGIN 事务
+ App->>DB: 写业务数据
+ App->>Outbox: 写入待发送消息
+ App->>DB: COMMIT
+
+ loop 定时任务
+ MQ->>Outbox: 扫描 status='pending'
+ Outbox-->>MQ: 返回消息列表
+ MQ->>Sub: 投递消息
+ MQ->>Outbox: 更新为 'sent'
+ end
+
+ Note right of Sub: 至少一次投递 + 消费者幂等
+```
+
+#### Outbox 表建表示例
+
+```sql
+CREATE TABLE outbox (
+ id BIGSERIAL PRIMARY KEY,
+ topic VARCHAR(255) NOT NULL, -- 消息主题
+ payload JSONB NOT NULL, -- 消息体
+ status VARCHAR(20) NOT NULL DEFAULT 'pending', -- pending / sent / failed
+ error_msg TEXT, -- 失败原因
+ created_at TIMESTAMP NOT NULL DEFAULT NOW(),
+ sent_at TIMESTAMP
+);
+
+-- 加速定时扫描查询
+CREATE INDEX idx_outbox_pending ON outbox (status, created_at)
+WHERE status = 'pending';
+```
+
+```go
+// Go 示例:出事务内同时写业务数据和 outbox 记录
+tx, _ := db.Begin()
+tx.Exec("INSERT INTO orders (user_id, total) VALUES ($1, $2)", userID, total)
+tx.Exec(`INSERT INTO outbox (topic, payload, status)
+ VALUES ('order.created', $1, 'pending')`, jsonPayload)
+tx.Commit()
+
+// 后台 goroutine 轮询并推送
+func outboxWorker(ctx context.Context, ticker *time.Ticker) {
+ for {
+ select {
+ case <-ctx.Done():
+ return
+ case <-ticker.C:
+ sendPendingMessages(ctx)
+ }
+ }
+}
+```
+
+#### 事务消息(RocketMQ 原生支持)
+
+如果使用的是 RocketMQ,可以绕过 Outbox 模式直接用事务消息:
+
+```go
+// 发送事务消息
+txMsg := rocketmq.NewTransactionMessage("order-created", payload)
+localTx := &MyLocalTxChecker{}
+
+// half 消息发送 → 本地事务执行 → 提交/回查
+res, _ := producer.SendMessageInTransaction(txMsg, localTx)
+```
+
+RocketMQ 的事务消息流程:
+1. 生产者发送 "half 消息" 到 MQ(消费者不可见)
+2. 执行本地事务
+3. 根据结果 Commit(消费者可见)或 Rollback(丢弃)
+4. 如果步骤 2 超时,MQ 回查本地事务状态
+
+### 消费幂等性
+
+> [!warning] 关键保障
+> 消息可能重复投递(网络超时、MQ 重投),消费者必须做到**幂等**——处理一次和处理多次的结果完全相同。
+
+**三种常见策略:**
+
+| 策略 | 实现方式 | 适用场景 |
+|------|---------|---------|
+| **数据库唯一约束** | `msg_id` 做 `UNIQUE` | 最可靠,推荐首选 |
+| **Redis 去重键** | `SET dedup:{msg_id} 1 NX EX 86400` | 高吞吐场景 |
+| **乐观锁版本控制** | `UPDATE SET qty = qty - N WHERE version = V` | 金额调整类操作 |
+
+```go
+// 推荐方案:利用 UNIQUE 约束做幂等保障
+_, err := db.Exec(`
+ INSERT INTO order_events (msg_id, order_id, action, amount)
+ VALUES ($1, $2, $3, $4)
+ ON CONFLICT (msg_id) DO NOTHING
+`, msgID, orderID, action, amount)
+
+if !isUniqueViolation(err) {
+ log.Error("process message failed", err)
+ return
+}
+// 执行业务逻辑——到这里说明消息是新到达的
+```
+
+## 方案二:Saga 模式
+
+Saga 适用于**跨多个服务的长流程操作**,将大事务拆成一系列本地小事务,每个步骤都有对应的补偿操作。
+
+### 编排式 vs 编舞式
+
+```mermaid
+graph TB
+ subgraph ORCHESTRATION["编排式 — Coordinator 中心化"]
+ CO[Coordinator] --> S1[OrderSvc: Create]
+ CO --> S2[InventorySvc: Reserve]
+ CO --> S3[PaymentSvc: Charge]
+
+ S1 -.->|失败→Cancel| CO
+ S2 -.->|失败→Cancel| CO
+ S3 -.->|失败→Cancel| CO
+ end
+
+ subgraph CHOREOGRAPHY["编舞式 — 事件驱动"]
+ E1[OrderCreated] --> S11[OrderService]
+ S11 --> E2[StockReserved]
+ E2 --> S12[InventoryService]
+ S12 --> E3[PaymentCharged]
+ E3 --> S13[PaymentService]
+
+ S13 -.-> E4[PaidFailed] -.-> S11
+ end
+```
+
+| 维度 | 编排式 | 编舞式 |
+|------|--------|--------|
+| **控制流** | 中心化 Coordinator | 各服务通过事件自发响应 |
+| **可观测性** | ✅ 集中管理全流程 | ❌ 流程散布在各服务 |
+| **耦合度** | 依赖 Coordinator | 服务间仅感知事件 |
+| **适合规模** | 5~15 步的 Saga | 简单链路 (< 5 步) |
+
+### Saga 补偿设计原则
+
+每个正向操作必须有对应的**反向补偿**:
+
+| 正向操作 | 补偿操作 |
+|---------|---------|
+| 创建订单 | 取消订单 |
+| 预留库存 | 释放库存 |
+| 扣款 | 退款 |
+| 发送通知 | 撤销通知(一般不需要) |
+
+> [!warning] 补偿操作的幂等性
+> 补偿操作也必须幂等——CancelOrder 可能被触发多次。用订单状态的流转来保证(如只有 PENDING 才能转到 CANCELLED)。
+
+## 方案三:TCC (Try-Confirm-Cancel)
+
+TCC 在每个事务步骤中实现三个接口:
+
+```
+Try: 预留资源(冻结余额 / 锁定库存)
+Confirm: 确认使用资源(正式扣减 / 正式锁定)
+Cancel: 释放资源(解冻余额 / 解锁库存)
+```
+
+### TCC 时序图
+
+```mermaid
+sequenceDiagram
+ participant Orch as Coordinator
+ participant O as Order Service
+ participant I as Inventory Service
+ participant P as Payment Service
+
+ Orch->>O: Try(CreateOrder)
+ O-->>Orch: OK
+
+ Orch->>I: Try(ReserveStock)
+ I-->>Orch: OK
+
+ Orch->>P: Try(ChargeBalance)
+ P-->>Orch: OK
+
+ Orch->>O: Confirm
+ Orch->>I: Confirm
+ Orch->>P: Confirm
+
+ Note over Orch,P: 全部 Confirm → 事务完成
+```
+
+### TCC vs Saga 对比
+
+| 维度 | TCC | Saga |
+|------|-----|------|
+| 一致性强度 | 较强(资源被占用期间不允许其他事务使用) | 较弱(中间态数据可见) |
+| 开发成本 | 高(每个业务方法实现 Try/Confirm/Cancel) | 低(只需正向 + 反向操作) |
+| 性能 | 中(需要两阶段提交) | 中高(单阶段本地事务) |
+| 适用场景 | 资金、库存等高敏感业务 | 订单流程、审批流等业务链 |
+
+## 关联笔记
+
+- [[03-数据一致性/数据库拆分/README]] — 数据库拆分是分布式事务的前提
+- [[02-服务治理/容错模式/README]] — 熔断器和重试在分布式事务中的作用
+- [[02-服务治理/服务间通信/README]] — 消息投递的一致性保障
diff --git a/hzh/MS/03-数据一致性/数据库拆分/README.md b/hzh/MS/03-数据一致性/数据库拆分/README.md
new file mode 100644
index 0000000..a1609e7
--- /dev/null
+++ b/hzh/MS/03-数据一致性/数据库拆分/README.md
@@ -0,0 +1,198 @@
+---
+tags: [microservice, database, sharding, replication]
+create time: 2026-05-05
+---
+
+# 数据库拆分
+
+## 概述
+
+微服务的核心设计原则是 **"每个服务拥有独立数据库"**,这意味着每个服务的表结构、数据存储、甚至数据库类型都可以不同。但当单表数据量持续增长时,就面临拆分的需求。
+
+```mermaid
+graph LR
+ S1[订单服务 DB]
+ S2[库存服务 DB]
+
+ subgraph BAD["反模式:共享数据库"]
+ S1 --- SHARED[(共享 DB)]
+ S2 --- SHARED
+ end
+
+ style SHARED fill:#ffebee,stroke:#ef5350
+```
+
+> [!failure] 反模式警告
+> 如果两个服务连接同一个数据库的同一张表,它们就不再是独立的微服务——你得到的是**分布式单体**。服务可以随意互相查询彼此的数据,失去了边界和自治性。
+
+## 垂直拆分 vs 水平拆分
+
+### 垂直拆分(按业务域)
+
+按 **微服务边界** 拆库——这是微服务的标配。
+
+```mermaid
+graph TB
+ subgraph "DB-Order"
+ orders[orders]
+ order_items[order_items]
+ order_status[order_status]
+ end
+
+ subgraph "DB-User"
+ users[users]
+ user_profiles[user_profiles]
+ user_addresses[user_addresses]
+ end
+
+ subgraph "DB-Product"
+ products[products]
+ categories[categories]
+ product_images[product_images]
+ end
+```
+
+| 特点 | 说明 |
+|------|------|
+| 每个服务独占一个数据库 | 物理隔离,互不干扰 |
+| 可异构选型 | 订单用 MySQL,用户用 PostgreSQL,搜索用 Elasticsearch |
+| 天然解耦 | 服务间不能直接查对方库 |
+
+### 水平拆分(分库分表)
+
+当单个表的记录量达到千万级以上,需要进一步拆分。
+
+```mermaid
+graph TB
+ subgraph "分库策略"
+ DB1[(DB-01)]
+ DB2[(DB-02)]
+ DB3[(DB-03)]
+ end
+
+ subgraph "order_0001 表"
+ Row1[userId=1 → order_0001]
+ Row2[userId=4 → order_0001]
+ end
+
+ subgraph "order_0002 表"
+ Row3[userId=2 → order_0002]
+ Row4[userId=5 → order_0002]
+ end
+
+ userId_mod["ORDER BY user_id % 2"] --> DB1
+ userId_mod --> DB2
+```
+
+### 常见分片策略
+
+| 策略 | 哈希公式 | 优点 | 缺点 |
+|------|---------|------|------|
+| **Hash Mod** | `user_id % N` | 简单高效,路由确定 | 扩缩容困难,数据迁移成本高 |
+| **Range** | `user_id BETWEEN x AND y` | 范围查询友好 | 热点用户集中到单分片 |
+| **Time-based** | `year_month` | 按生命周期管理 | 新分片写入压力大 |
+| **Geo-based** | 按地域分片 | 本地化访问,延迟低 | 跨区域操作复杂 |
+
+### ShardingSphere / MyCat
+
+> [!tip] 推荐中间件
+>
+> **Apache ShardingSphere** 是国内使用最广泛的分库分表方案:
+> - 支持 JDBC / Proxy / Sidecar 三种部署模式
+> - 内置分片算法:Mod、Range、Hash、Tag
+> - 分布式主键生成器(Snowflake)原生集成
+> - 读写分离、强制路由、广播表等高级特性
+
+#### ShardingSphere 配置示例
+
+```yaml
+# sharding-jdbc 配置
+sharding jdbc:
+ data-sources:
+ ds0: { type: HikariCP, ... }
+ ds1: { type: HikariCP, ... }
+
+ sharding:
+ tables:
+ orders:
+ actual-data-nodes: ds$->{0..1}.orders$->{0..1}
+ table-strategy:
+ standard:
+ sharding-column: user_id
+ sharding-algorithm-name: user-id-mod
+ key-generate-strategy:
+ column: order_id
+ key-generator-name: snowflake
+
+ sharding-algorithms:
+ user-id-mod:
+ type: MOD
+ props:
+ sharding-count: 2
+```
+
+## 跨库查询方案
+
+> [!question] 经典难题
+> 订单服务需要展示用户的姓名和手机号来做收货地址。但用户信息在用户库,订单数据在订单库——怎么办?
+
+### 方案对比
+
+| 方案 | 描述 | 性能 | 复杂度 | 适用场景 |
+|------|------|------|--------|---------|
+| **冗余字段** | 订单表存用户名字段 | ⭐⭐⭐⭐⭐ | 低 | 只读字段,变更频率低 |
+| **接口组装** | 先查订单,再调用户服务补全 | ⭐⭐⭐ | 中 | 偶尔需要关联的场景 |
+| **CQRS / 宽表** | 异步同步一份宽表用于查询 | ⭐⭐⭐⭐ | 高 | 高频关联查询 |
+| **搜索引擎** | ES/Kibana 做关联查询 | ⭐⭐⭐⭐ | 中高 | 复杂搜索 + 聚合 |
+
+### 冗余字段实践
+
+```sql
+-- 订单表冗余关键字段
+CREATE TABLE orders (
+ id BIGINT PRIMARY KEY,
+ user_id BIGINT NOT NULL,
+ username VARCHAR(64), -- 冗余用户名(快照,不参与编辑)
+ phone VARCHAR(20), -- 冗余手机号(脱敏存储)
+ created_at TIMESTAMP DEFAULT NOW(),
+ INDEX idx_user (user_id)
+);
+```
+
+> [!note] 冗余数据的维护
+>
+> 用户改名字了怎么办?**不改订单表**。订单上的 username 是该时刻的"快照"——它反映的是下单时的状态,不是当前状态。这符合业务语义。
+>
+> 如果需要批量更新冗余字段(如用户头像),通过消息队列异步通知订单服务更新。
+
+## 数据库迁移工具
+
+```mermaid
+graph LR
+ Dev["开发环境"] -->|"flyway migrate"| Stage["Staging"]
+ Stage -->|"人工审批"| Prod["Production"]
+ Prod -->|"flyway validate"| Check["校验版本一致性"]
+```
+
+| 工具 | 语言 | 特点 |
+|------|------|------|
+| **Flyway** | Java | 基于文件命名,SQL 脚本方式,简单直观 |
+| **Liquibase** | Java | XML/YAML/JSON 格式,支持回滚生成 |
+| **golang-migrate** | Go | CLI 工具,轻量,适合 Go 项目 |
+
+### Flyway 迁移流程
+
+```
+db/migration/
+├── V1__create_users_table.sql
+├── V2__add_user_phone.sql
+├── V3__create_orders_table.sql
+└── V4__add_order_status_enum.sql
+```
+
+执行顺序:V1 → V2 → V3 → V4。Flyway 内部维护 `_schema_version` 表追踪已执行的迁移。
+
+## 关联笔记
+
+- [[03-数据一致性/分布式事务/README]] — 拆分后的数据一致性问题
+- [[01-基础概念]] — DDD 限界上下文与数据库拆分的对应关系
diff --git a/hzh/MS/04-可观测性.md b/hzh/MS/04-可观测性.md
deleted file mode 100644
index be41122..0000000
--- a/hzh/MS/04-可观测性.md
+++ /dev/null
@@ -1,446 +0,0 @@
----
-tags: [microservice, observability, monitoring, tracing]
-create time: 2026-04-29 12:04
----
-
-# 可观测性
-
-## 概述
-
-微服务架构下,一个请求可能穿越十几个甚至上百个服务。**排查问题就像在大海捞针**。可观测性通过三大支柱(Metrics、Logging、Tracing)让系统行为变得"可见"。
-
-> [!question] 核心思考
-> 单体应用出问题,SSH 到服务器上 `tail -f` 日志就能定位。但当你有 50 个服务、每个 3 个副本,日志散落在不同容器里——你还能用同样的方式排障吗?如果不能,什么体系能替代它?
-
-### 为什么需要独立的"可观测性"体系?
-
-```mermaid
-flowchart LR
- subgraph MONO["单体系统"]
- S[Service] --> DB[(DB)]
- LOG["同一份日志
一目了然"]
- S --> LOG
- end
-
- subgraph MICRO["微服务系统"]
- REQ("Request") --> GW["Gateway"]
- GW --> O1["Order Svc"]
- GW --> U1["User Svc"]
- O1 --> PAY["Payment Svc"]
- O1 --> INV["Inventory Svc"]
- PAY --> DB1[(DB)]
- INV --> DB2[(DB)]
-
- style O1 fill:#faa
- style U1 fill:#faa
- style PAY fill:#faa
- style INV fill:#faa
- end
-
- NOTE["问题:日志分散、链路断裂
传统监控无法回答'这个请求经历了什么'"]
- MICRO --> NOTE
-```
-
-可观测性与监控的本质区别:**监控系统告诉你"出事了"**(已知未知),**可观测性系统让你去探究"为什么会出事"**(未知未知)。
-
-### SLO 与 Error Budget
-
-可观测性的终极目标不是收集数据,而是**支撑决策**。SLO(Service Level Objective)将技术指标映射到用户体验。
-
-> [!summary] SLI / SLO / SLA 三层模型
->
-> | 层级 | 含义 | 示例 |
-> |------|------|------|
-> | **SLI** (Indicator) | 实际测量的指标 | P99 延迟 = 120ms |
-> | **SLO** (Objective) | 内部目标值 | P99 延迟 < 200ms(99.9% 的请求) |
-> | **SLA** (Agreement) | 对外的契约承诺 | 可用性 ≥ 99.95%,否则赔偿 |
-
-> [!tip] Error Budget(错误预算)
->
-> 如果 SLO 是 99.9%,那么每月允许的错误时间 = 30 × 24 × 60 × 0.1% ≈ **43 分钟**。
->
-> - **预算充足时**:可以大胆发布新功能、尝试激进方案
-> - **预算耗尽时**:冻结非功能性变更,专注稳定性修复
->
-> 这构成了"创新"和"稳定"之间的动态平衡机制。
-
-## 三大支柱
-
-| 支柱 | 回答的问题 | 典型工具 |
-|------|-----------|---------|
-| **Metrics** | 系统现在健康吗? — 趋势、告警 | Prometheus + Grafana |
-| **Logging** | 具体发生了什么? — 历史回溯 | ELK / Loki |
-| **Tracing** | 请求在哪一步慢了/失败了? — 链路追踪 | Jaeger / Zipkin |
-
-### Metrics:系统的脉搏
-
-Metrics 回答的问题是:**系统现在健康吗?**——通过聚合后的数值揭示趋势。
-
-> [!summary] RED 和 USE 方法
->
-> | 方法 | 适用于 | 指标 |
-> |------|--------|------|
-> | **RED** (Rate, Errors, Duration) | 有状态服务(API) | QPS、错误率、响应时间 P99 |
-> | **USE** (Utilization, Saturation, Errors) | 基础设施(CPU/内存/网络) | 使用率、饱和度、错误数 |
-
-核心指标类型:
-
-- **Counter(计数器)**:只增不减,如 `http_requests_total`。适合统计请求总量、错误总数
-- **Gauge(仪表盘)**:可增可减,如 `queue_depth`、在线用户数
-- **Histogram(直方图)**:样本分布,自动分桶统计,如请求延迟的 P50/P90/P99
-- **Summary(摘要)**:类似 Histogram,但客户端计算分位数(Go SDK 默认)
-
-```go
-// Go 示例:定义并注册 Prometheus 指标
-var (
- // Counter: HTTP 请求总数,按 method 和 status 标签分类
- httpRequestsTotal = prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Name: "http_requests_total",
- Help: "Total HTTP requests",
- },
- []string{"method", "status"},
- )
-
- // Histogram: API 响应延迟分布
- apiLatency = prometheus.NewHistogramVec(
- prometheus.HistogramOpts{
- Name: "api_latency_seconds",
- Help: "API latency distribution",
- Buckets: prometheus.DefBuckets, // [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10]
- },
- []string{"endpoint"},
- )
-)
-
-func init() {
- prometheus.MustRegister(httpRequestsTotal, apiLatency)
-}
-```
-
-> [!tip] 解读提示
-> Counter 用于统计"发生了多少",Histogram 用于理解"有多慢"。一个完整的告警面板通常同时展示两者:QPS 突降 + 延迟飙升 = 大概率出事了。
-
-在 Grafana 中的典型视图:
-
-```mermaid
-graph TB
- subgraph GRAFANA["Grafana Dashboard"]
- G1["QPS
[Counter]"] -->|关联分析| G2["P99 Latency
[Histogram]"]
- G3["错误率
[Counter %]"] -->|关联分析| G2
- G2 --> G4["告警规则
阈值触发"]
- end
-
- GRAFANA -.->|从 Prometheus 拉取| PROM[(Prometheus)]
-```
-
-### Logging:集中化日志
-
-Logging 回答的问题是:**具体发生了什么?**——通过原始事件记录提供上下文。
-
-- **所有服务的日志必须集中收集**,不能散落在各台机器上
-- 日志格式推荐 JSON,便于解析
-- 每条日志必须携带 `trace_id`,与 Tracing 串联
-
-```json
-{
- "timestamp": "2026-04-29T12:00:00Z",
- "level": "ERROR",
- "service": "order-service",
- "trace_id": "abc-123-def",
- "span_id": "span-456",
- "msg": "failed to connect payment service",
- "caller": "payment/client.go:42",
- "cost_ms": 30000
-}
-```
-
-#### 结构化日志的核心字段
-
-> [!note] 最小集合(必选)
->
-> - `timestamp` — ISO 8601 格式,统一时区 UTC
-> - `level` — TRACE / DEBUG / INFO / WARN / ERROR / FATAL
-> - `service` — 微服务名称
-> - `trace_id` — 链路追踪 ID,用于跨服务关联
-> - `msg` — 人类可读的消息描述
-
-> [!warning] 日志最佳实践
->
-> - **不要记录敏感信息**:密码、Token、身份证号等绝不能出现在日志中
-> - **INFO 级记录关键业务事件**:下单成功、支付回调——这些是排查业务问题的主线
-> - **WARN 级记录异常但不致命**:重试了一次、降级走了备用方案
-> - **ERROR 级必须有 trace_id 和错误堆栈**,否则毫无价值
-
-#### 日志采集管线
-
-```mermaid
-flowchart LR
- APP[应用容器] -->|stdout/stderr| LO[FLUENTD / Filebeat]
- LO -->|TCP/Lumberjack| LO2[(Logstash / Loki)]
- LO2 -->|解析 & 过滤| PIPE[Pipeline]
- PIPE -->|写入| ES[(Elasticsearch)]
- PIPE -->|跳转| GRAF[Grafana / Kibana]
-
- style PIPE fill:#ff9
-```
-
-**常见方案对比**:
-
-| 方案 | 存储 | 查询能力 | 适用场景 |
-|------|------|---------|---------|
-| ELK (Elasticsearch) | ES 集群 | 全文检索强大,灵活度高 | 日志量大、需要复杂分析的团队 |
-| Loki + Grafana | 对象存储 (S3) | 对标 LogQL,轻量高效 | 已经在用 Grafana 的团队 |
-| CloudWatch / SLS | 云厂商托管 | 开箱即用,成本较高 | 全云原生环境 |
-
-> [!tip] 日志采样策略
->
-> 生产环境中并非所有日志都要采集。**正常路径采 1%,异常路径全量**。这既能大幅降低存储成本,又能在出问题时有足够的调试数据可用。采样逻辑建议写在日志库中,而非业务代码里。
-
-### Tracing:分布式链路追踪
-
-Tracing 回答的问题是:**请求在哪一步慢了 / 失败了?**——通过完整的调用链路定位瓶颈和故障。
-
-一次请求在多个服务中的完整调用路径:
-
-```mermaid
-flowchart LR
- RID["Request
trace_id: abc-123"]
-
- subgraph SPANS["调用链 (Trace)"]
- direction TB
- S1["Span #1
API Gateway
5ms"]
- S2["Span #2
Order Service
70ms"]
- S3["Span #3
Payment RPC
160ms"]
- S4["Span #4
Inventory RPC
70ms"]
-
- S1 --> S2 --> S3
- S2 --> S4
- end
-
- RID --> S1
- style S3 fill:#ff9999
-
- note["Span #3 耗时最长 → Payment 是瓶颈"]
- S3 -.-> note
-```
-
-> [!tip] 关键实践
-> - 确保 `trace_id` 在整个调用链中传递(HTTP Header 或 MQ Message Header)
-> - 采样策略:**全量采集开发环境**,**生产环境按百分比采样**(避免存储爆炸)
-> - 重点关注的 Span 标签:HTTP method、status code、database query
-> - **Span 不要嵌套过深**,一个 HTTP 调用或 DB 查询对应一个 Span 即可
-
-#### Context Propagation(上下文传播)
-
-trace_id 如何从上游服务传递到下游?
-
-```go
-// 1. 入站:从 HTTP Header 提取 trace context
-func Middleware(next http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- // OpenTelemetry SDK 自动从 Header 恢复 span context
- ctx := propagator.Extract(r.Context(), headerReader{r.Header})
-
- // 2. 创建新的 span
- ctx, span := tracer.Start(ctx, "handleOrder")
- defer span.End()
-
- // 3. 将 trace context 注入到新请求的 Header 中
- r = r.WithContext(ctx)
- propagator.Inject(ctx, headerWriter{r.Header})
-
- next.ServeHTTP(w, r)
- })
-}
-```
-
-```json
-// HTTP Header 中实际传递的字段 (W3C Trace Context)
-{
- "traceparent": "00-abc123def456...-789ghi012jkl-01",
- "tracestate": "congo=t61rcWkgMzE"
-}
-```
-
-> [!note] W3C Trace Context 标准
->
-> `traceparent` 格式:`version-trace_id-span_id-flags`,如 `00-{32位trace_id}-{16位span_id}-{2位flags}`。
-> 这是 W3C 推荐的标准,被 OpenTelemetry、Jaeger、Zipkin 等主流方案统一支持。**无需再自定义 Header**。
-
-## 告警设计原则
-
-### 告警疲劳是常态
-
-> [!warning] 核心问题
->
-> 如果一个团队每天收到 200 条告警,其中 195 条是误报或无需处理,工程师会对剩下的 5 条真正重要的告警产生"脱敏"。这就是 **告警疲劳**。
-
-- **告警要能 actionable**:收到告警后知道该做什么,否则不要告
-- **区分级别**:P0(电话叫醒)vs P1(工单处理)vs P2(次日处理)
-- **基于 SLO 告警**:不是 CPU > 80% 就告警,而是用户感知到延迟增加时才告
-- **降噪**:同一个根因可能触发连锁告警,需要抑制机制
-
-### 告警层级设计
-
-```mermaid
-flowchart TD
- subgraph L1["L1: 页面上的用户受损"]
- A1["HTTP 5xx 错误率 > 1%"]
- A2["核心接口 P99 > 2s"]
- end
-
- subgraph L2["L2: 系统健康度下降"]
- B1["单个服务错误率 > 5%"]
- B2["下游依赖超时率升高"]
- end
-
- subgraph L3["L3: 资源预警"]
- C1["磁盘使用 > 70%"]
- C2["内存使用 > 80%"]
- end
-
- A1 -->|P0 - 电话 + IM| ONCALL[On-Call 值班]
- A2 -->|P0 - 电话 + IM| ONCALL
- B1 -->|P1 - IM 通知| OPS[运维群]
- B2 -->|P1 - IM 通知| OPS
- C1 -->|P2 - 日报汇总| TEAM[团队看板]
- C2 -->|P2 - 日报汇总| TEAM
-```
-
-> [!tip] 告警规则编写清单
->
-> 每条告警规则都应该能回答以下问题:
-> 1. **什么问题?** — 清晰描述故障现象
-> 2. **谁负责?** — 指定明确的责任人 / On-Call
-> 3. **怎么修复?** — 链接到 Runbook / 处置文档
-> 4. **多久升级?** — P1 无人响应则自动升级到上级
-
-## OpenTelemetry:统一的可观测性标准
-
-过去,Metrics、Logging、Tracing 各用各的工具链,数据割裂在完全不同的系统中。**OpenTelemetry (OTel)** 试图解决这个问题。
-
-> [!summary] OTel 的核心思想
->
-> 一套 SDK → 三种信号(Metrics、Logs、Traces)→ 任意后端(Jaeger、Prometheus、ELK...)
->
-> 这意味着:**你不需要在代码里为不同后端写多套采集逻辑**。换一个后端只需要改配置,不改代码。
-
-### OTel Architecture
-
-```mermaid
-flowchart LR
- subgraph APP["你的应用"]
- OTEL_SDK["OpenTelemetry SDK
auto-instrumentation Agent"]
- end
-
- OTEL_SDK -->|SDK 自动采集| COLLECTOR[(OpenTelemetry Collector)]
-
- COLLECTOR -->|OTLP| JAEGER[(Jaeger
Tracing)]
- COLLECTOR -->|OTLP| PROM[(Prometheus
Metrics)]
- COLLECTOR -->|OTLP| LOKI[(Loki
Logging)]
-
- style OTEL_SDK fill:#ff9
-```
-
-> [!note] 为什么需要 Collector?
->
-> Collector 是一个独立的服务进程,承担三个职责:
-> 1. **接收**:从应用的 SDK 接收数据
-> 2. **处理**:过滤、采样、富化(添加额外标签)
-> 3. **导出**:将数据转发到不同的后端存储
->
-> 这样你的应用只关心"发送数据",Collector 负责"怎么存、存到哪里"。两者解耦。
-
-### Go 中接入 OpenTelemetry
-
-```go
-// 1. 初始化 TracerProvider(Tracing)
-provider := sdktrace.NewTracerProvider(
- sdktrace.WithBatcherExporter(exporter), // 异步批量上报,不阻塞业务
-)
-defer provider.Shutdown(context.Background())
-
-tracer := provider.Tracer("order-service")
-
-// 2. 在 handler 中创建 span
-func handleOrder(w http.ResponseWriter, r *http.Request) {
- ctx, span := tracer.Start(r.Context(), "handleOrder")
- defer span.End()
-
- // 设置丰富的 Span 属性(供查询和过滤)
- span.SetAttributes(
- attribute.String("http.method", r.Method),
- attribute.Int("http.status_code", 200),
- attribute.String("user.id", userID),
- )
-
- // 调用下游服务(trace context 自动传播)
- resp, err := callPayment(ctx)
- if err != nil {
- span.RecordError(err)
- span.SetStatus(codes.Error, err.Error())
- return
- }
-}
-```
-
-> [!tip] 渐进式落地路线
->
-> 1. **第一步**:先接 Tracing(价值最大、投入最小),覆盖核心链路
-> 2. **第二步**:加 Metrics(Prometheus + Grafana),建立基础监控
-> 3. **第三步**:集中 Logging(Loki / ELK),与 trace_id 关联
-> 4. **第四步**:全量上 OTel Collector,统一管理三件套
->
-> 不要试图一步到位——Tracing 的 ROI 最高,先从这里开始。
-
-## Dashboard 与 On-Call 实践
-
-收集了这么多数据,下一步是怎么用。
-
-### Service Health Dashboard
-
-一个优秀的 Dashboard 应该让任何团队成员在 **30 秒内**了解服务的整体状态:
-
-```mermaid
-flowchart TB
- subgraph DASH["Service Health Dashboard"]
- ROW1["🔴 可用性 & 错误率 — 第一眼判断"]
- ROW2["🟡 性能指标 — P50/P90/P99 趋势"]
- ROW3["🔵 基础设施 — CPU/内存/连接数"]
- ROW4["⚫ 业务指标 — 订单量/支付成功率"]
- end
-
- ROW1 --> JUDGE{是否异常?}
- ROW2 --> JUDGE
- ROW3 --> JUDGE
- ROW4 --> JUDGE
-
- JUDGE --"否" --> NORMAL["一切正常 ✓"]
- JUDGE --"是" --> ALERT["触发告警 → On-Call"]
-```
-
-### Runbook:告警处置手册
-
-告警来了之后该怎么办?答案不应存在某个资深工程师的脑子里。
-
-> [!summary] Runbook 模板
->
-> | 字段 | 内容 |
-> |------|------|
-> | **标题** | `支付服务 P99 延迟 > 2s 持续 5 分钟` |
-> | **影响范围** | 下单接口超时,用户体验受损 |
-> | **检查步骤** | ① 看 Grafana 延迟面板确认峰值时间点 → ② 查同期部署记录 → ③ 检查下游 DB 慢查询 |
-> | **常见原因** | ① 新上线代码有性能 regression → ② DB 连接池耗尽 → ③ 下游超时风暴 |
-> | **快速恢复** | ① 回滚最近一次发布 → ② 扩容支付服务实例 → ③ 开启熔断降低下游压力 |
-> | **彻底解决** | 排查根本原因,补充回归测试,完善容量规划 |
-
-> [!question] 反模式自检
->
-> 如果你的 On-Call 流程是这样的:收到告警 → 群里问 "有人遇到过吗?" → 等半天有人回复 → SSH 到服务器上翻日志 → ……——这说明你们的可观测性体系还不够成熟。**好的 On-Call 体验 = 清晰的告警 + 完善的 Runbook + 一键处置工具**。
-
-## 关联笔记
-
-- [[02-服务治理]] — 熔断器可以触发告警,与监控系统联动;分布式链路追踪章节也有详细说明
-- [[05-部署运维]] — K8s Liveness/Readiness Probe 是可观测性的基础
-- [[01-基础概念]] — 微服务的整体架构认知
diff --git a/hzh/MS/04-可观测性/Metrics监控/README.md b/hzh/MS/04-可观测性/Metrics监控/README.md
new file mode 100644
index 0000000..54871b8
--- /dev/null
+++ b/hzh/MS/04-可观测性/Metrics监控/README.md
@@ -0,0 +1,160 @@
+---
+tags: [microservice, metrics, prometheus, grafana, sre]
+create time: 2026-05-05
+---
+
+# Metrics 监控
+
+## 概述
+
+Metrics 回答的问题是:**系统现在健康吗?**——通过聚合后的数值揭示趋势。
+
+```mermaid
+graph TB
+ App["应用服务"] -->|Push / Scrape| PROM[(Prometheus)]
+ PROM --> GRAF["Grafana Dashboard"]
+ PROM --> ALERT["Alertmanager"]
+
+ style PROM fill:#e3f2fd
+ style GRAF fill:#fff3e0
+ style ALERT fill:#fce4ec
+```
+
+## 指标类型
+
+| 类型 | 含义 | 特点 | 示例 |
+|------|------|------|------|
+| **Counter** | 只增不减的计数器 | 可 Reset(重启) | `http_requests_total` |
+| **Gauge** | 可升可降的仪表盘 | 反映当前状态 | `queue_depth`, `cpu_temp` |
+| **Histogram** | 样本分布,自动分桶 | 计算 P50/P90/P99 | `api_latency_seconds` |
+| **Summary** | 类似 Histogram,客户端算分位 | Go SDK 默认类型 | `grpc_duration_seconds` |
+
+### Counter vs Gauge 场景选择
+
+```mermaid
+flowchart LR
+ Q{"这个值是
只增不减的吗?"}
+
+ Q -- "是" --> C["Counter
请求数、错误数、订单量"]
+ Q -- "否" --> G["Gauge
在线用户数、队列长度、内存使用量"]
+
+ style C fill:#c8e6c9
+ style G fill:#bbdefb
+```
+
+## RED 方法 (针对有状态服务)
+
+适用于 API、微服务等有明确请求/响应的服务。
+
+| 指标 | 公式 | 说明 |
+|------|------|------|
+| **Rate** | `rate(http_requests_total[5m])` | 每秒请求量 (QPS) |
+| **Errors** | `rate(http_requests_total{status="5xx"}[5m])` | 每秒错误数 |
+| **Duration** | `histogram_quantile(0.99, rate(api_latency_bucket[5m]))` | P99 响应时间 |
+
+> [!tip] PromQL 关键函数
+>
+> - `rate()` — 计算 Counter 每秒增长率(必须用于 Counter)
+> - `irate()` — 即时速率,对突发更敏感
+> - `histogram_quantile(0.99, ...)` — 从直方图计算分位数
+> - `increase()` — 时间段内的增长总量
+> - `avg() / max() / min()` — 基础聚合函数
+
+## USE 方法 (针对基础设施)
+
+适用于 CPU、内存、网络、磁盘等底层资源监控。
+
+| 指标 | 说明 | Grafana PromQL 示例 |
+|------|------|---------------------|
+| **Utilization** | 使用率 | `1 - avg(rate(node_cpu_seconds_total{mode="idle"}[5m]))` |
+| **Saturation** | 饱和度 | `node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes` |
+| **Errors** | 错误数 | `rate(node_network_receive_errs_total[5m])` |
+
+## Go Prometheus 集成
+
+```go
+var (
+ httpRequestsTotal = prometheus.NewCounterVec(
+ prometheus.CounterOpts{
+ Name: "http_requests_total",
+ Help: "Total HTTP requests by method and status",
+ },
+ []string{"method", "status"},
+ )
+
+ apiLatency = prometheus.NewHistogramVec(
+ prometheus.HistogramOpts{
+ Name: "api_latency_seconds",
+ Help: "API latency distribution",
+ Buckets: prometheus.DefBuckets, // [0.005, 0.01, ..., 10]
+ },
+ []string{"endpoint"},
+ )
+)
+
+func init() {
+ prometheus.MustRegister(httpRequestsTotal, apiLatency)
+}
+
+// Middleware 中使用
+func MetricsMiddleware(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ start := time.Now()
+ next.ServeHTTP(w, r)
+
+ duration := time.Since(start).Seconds()
+ httpRequestsTotal.WithLabelValues(r.Method, fmt.Sprintf("%d", w.Status())).Inc()
+ apiLatency.WithLabelValues(r.URL.Path).Observe(duration)
+ })
+}
+```
+
+## Dashboard 设计原则
+
+一个优秀的 Dashboard 应该让任何团队成员在 **30 秒内**了解服务的整体状态:
+
+```mermaid
+flowchart TB
+ subgraph DASH["Service Health Dashboard"]
+ ROW1["🔴 可用性 & 错误率 — 第一眼判断"]
+ ROW2["🟡 性能指标 — P50/P90/P99 趋势"]
+ ROW3["🔵 基础设施 — CPU/内存/连接数"]
+ ROW4["⚫ 业务指标 — 订单量/支付成功率"]
+ end
+
+ ROW1 --> JUDGE{是否异常?}
+ ROW2 --> JUDGE
+ ROW3 --> JUDGE
+ ROW4 --> JUDGE
+
+ JUDGE --"否" --> NORMAL["一切正常 ✓"]
+ JUDGE --"是" --> ALERT["触发告警 → On-Call"]
+```
+
+### Dashboard 布局模板
+
+```
+┌─────────────────────────────────────────────────┐
+│ Row 1: 🔴 Service Availability │
+│ ├─ QPS (Rate) ┌─ Error Rate (%) │
+│ ├─ Active Connections └─ 5xx Count │
+├─────────────────────────────────────────────────┤
+│ Row 2: 🟡 Performance │
+│ ├─ P50 Latency ┌─ P90 Latency │
+│ ├─ P99 Latency └─ Slow Requests (>1s) │
+├─────────────────────────────────────────────────┤
+│ Row 3: 🔵 Infrastructure │
+│ ├─ CPU % ┌─ Memory Usage │
+│ ├─ GC Pause Time └─ Goroutine Count │
+├─────────────────────────────────────────────────┤
+│ Row 4: ⚫ Business Metrics │
+│ ├─ Orders/Minute ┌─ Payment Success Rate │
+│ └─ New Users/Day └─ Failed Transactions │
+└─────────────────────────────────────────────────┘
+```
+
+## 关联笔记
+
+- [[04-可观测性/告警管理/README]] — Metrics 是告警的基础数据来源
+- [[04-可观测性/链路追踪/README]] — Tracing 与 Metrics 互补,定位具体故障
+- [[05-部署运维/SRE实践/README]] — SLO 基于 Metrics 数据
diff --git a/hzh/MS/04-可观测性/README.md b/hzh/MS/04-可观测性/README.md
new file mode 100644
index 0000000..8c12aef
--- /dev/null
+++ b/hzh/MS/04-可观测性/README.md
@@ -0,0 +1,78 @@
+---
+tags: [microservice, observability]
+create time: 2026-04-29 12:04
+---
+
+# 可观测性
+
+## 概述
+
+微服务架构下,一个请求可能穿越十几个甚至上百个服务。**排查问题就像在大海捞针**。可观测性通过三大支柱(Metrics、Logging、Tracing)让系统行为变得"可见"。
+
+## 知识体系
+
+```mermaid
+graph LR
+ A["Metrics 监控"] --> C["日志系统"]
+ B["链路追踪"] --> C
+ C --> D["告警管理"]
+
+ style A fill:#e3f2fd
+ style B fill:#fff3e0
+ style C fill:#fce4ec
+ style D fill:#e8f5e9
+```
+
+| # | 主题 | 核心问题 |
+|---|------|----------|
+| 1 | [[04-可观测性/Metrics监控/README]] | 怎么量化系统的健康度?RED/USE 方法怎么用? |
+| 2 | [[04-可观测性/日志系统/README]] | 日志怎么集中收集?结构化日志的最佳实践是什么? |
+| 3 | [[04-可观测性/链路追踪/README]] | trace_id 如何贯穿跨服务调用链?OpenTelemetry 怎么用? |
+| 4 | [[04-可观测性/告警管理/README]] | 如何设计告警避免疲劳?SLO/Error Budget 怎么做? |
+
+### 为什么需要独立的"可观测性"体系?
+
+```mermaid
+flowchart LR
+ subgraph MONO["单体系统"]
+ S[Service] --> DB[(DB)]
+ LOG["同一份日志
一目了然"]
+ S --> LOG
+ end
+
+ subgraph MICRO["微服务系统"]
+ REQ("Request") --> GW["Gateway"]
+ GW --> O1["Order Svc"]
+ GW --> U1["User Svc"]
+ O1 --> PAY["Payment Svc"]
+ O1 --> INV["Inventory Svc"]
+ PAY --> DB1[(DB)]
+ INV --> DB2[(DB)]
+
+ style O1 fill:#faa
+ style U1 fill:#faa
+ style PAY fill:#faa
+ style INV fill:#faa
+ end
+
+ NOTE["问题:日志分散、链路断裂
传统监控无法回答'这个请求经历了什么'"]
+ MICRO --> NOTE
+```
+
+> [!keypoint] 可观测性与监控的本质区别
+>
+> **监控系统**告诉你"出事了"(已知未知),**可观测性系统**让你去探究"为什么会出事"(未知未知)。
+
+### 三大支柱
+
+| 支柱 | 回答的问题 | 典型工具 |
+|------|-----------|---------|
+| **Metrics** | 系统现在健康吗?— 趋势、告警 | Prometheus + Grafana |
+| **Logging** | 具体发生了什么?— 历史回溯 | ELK / Loki |
+| **Tracing** | 请求在哪一步慢了/失败了?— 链路追踪 | Jaeger / Zipkin |
+
+### 关联笔记
+
+- [[02-服务治理]] — 熔断器可以触发告警,与监控系统联动
+- [[05-部署运维/Kubernetes/README]] — K8s Liveness/Readiness Probe 是可观测性的基础
+- [[hzh/MS/README.md]] — 完整微服务知识索引
diff --git a/hzh/MS/04-可观测性/告警管理/README.md b/hzh/MS/04-可观测性/告警管理/README.md
new file mode 100644
index 0000000..56babf8
--- /dev/null
+++ b/hzh/MS/04-可观测性/告警管理/README.md
@@ -0,0 +1,186 @@
+---
+tags: [microservice, alerting, slo, error-budget, on-call]
+create time: 2026-05-05
+---
+
+# 告警管理
+
+## 概述
+
+收集了这么多 Metrics、Logs 和 Traces,下一步是**用数据驱动决策**。告警系统是在问题影响用户之前及时响应的最后一道防线。
+
+> [!warning] 核心挑战:告警疲劳
+>
+> 如果一个团队每天收到 200 条告警,其中 195 条是误报或无需处理,工程师会对剩下的 5 条真正重要的告警产生"脱敏"。这就是 **告警疲劳 (Alert Fatigue)**。
+
+## SLO / Error Budget 告警
+
+### SLI / SLO / SLA 三层模型
+
+| 层级 | 全称 | 含义 | 示例 |
+|------|------|------|------|
+| **SLI** | Service Level Indicator | 实际测量的指标 | P99 延迟 = 120ms |
+| **SLO** | Service Level Objective | 内部目标值 | P99 延迟 < 200ms(99.9%) |
+| **SLA** | Service Level Agreement | 对外契约承诺 | 可用性 ≥ 99.95%,否则赔偿 |
+
+```mermaid
+flowchart LR
+ Real["真实用户请求"] --> SLI{成功率达标?}
+ SLI -- 是 --> SLO_OK["✅ SLO 达成"]
+ SLI -- 否 --> BUDGET["消耗错误预算"]
+
+ BUDGET --> Left{"预算 > 0?"}
+ Left -- 是 --> Continue["继续发布新功能 🚀"]
+ Left -- 否 --> Freeze["冻结发布 ❄️
专注稳定性修复"]
+
+ style SLO_OK fill:#e8f5e9
+ style Freeze fill:#ffebee
+```
+
+### 错误预算计算
+
+```
+每月允许停机时间 = 月总分钟数 × (1 - SLO)
+
+SLO = 99.9% → 30×24×60×0.1% = 43.2 分钟
+SLO = 99.95% → 30×24×60×0.05% = 21.6 分钟
+SLO = 99.99% → 30×24×60×0.01% = 4.3 分钟
+SLO = 99% → 30×24×60×1% = 432 分钟 ≈ 7.2 小时(几乎无意义)
+```
+
+### 基于错误预算的告警策略
+
+```mermaid
+flowchart TD
+ BudgetLeft{"错误预算剩余"}
+
+ BudgetLeft -- "> 50%" --> Aggressive["激进策略:
保持常规告警阈值
加快迭代节奏"]
+ BudgetLeft -- "10~50%" --> Moderate["保守策略:
降低告警阈值
收紧发布频率"]
+ BudgetLeft -- "< 10%" --> Emergency["紧急策略:
所有非紧急告警暂停
全员关注稳定性"]
+
+ style Aggressive fill:#e8f5e9
+ style Moderate fill:#fff3e0
+ style Emergency fill:#ffebee
+```
+
+## 告警设计原则
+
+### 1. 告警必须 Actionable
+
+收到告警后知道该做什么,否则不要告。
+
+每条告警规则都应该能回答以下问题:
+
+| # | 问题 | 示例答案 |
+|---|------|---------|
+| 1 | **什么问题?** | `支付服务 P99 延迟 > 2s 持续 5 分钟` |
+| 2 | **谁负责?** | `支付组 On-Call: @zhangsan` |
+| 3 | **怎么修复?** | 链接到 Runbook `📖 Runbook: 支付超时排查指南` |
+| 4 | **多久升级?** | `P1 无人响应 → 5min 后升级至组长` |
+
+### 2. 分级设计
+
+```mermaid
+flowchart TD
+ subgraph L1["P0 — 立即响应(电话 + IM)"]
+ A1["HTTP 5xx 错误率 > 1% 持续 2min"]
+ A2["核心接口 P99 > 2s 持续 5min"]
+ A3["数据库连接池耗尽"]
+ end
+
+ subgraph L2["P1 — 当天处理(IM 通知)"]
+ B1["单个服务错误率 > 5%"]
+ B2["下游依赖超时率升高"]
+ B3["磁盘使用 > 75%"]
+ end
+
+ subgraph L3["P2 — 本周修复(日报汇总)"]
+ C1["CPU 使用率 > 80% 持续 1h"]
+ C2["内存使用 > 85% 持续 1h"]
+ C3["非核心服务 P99 异常"]
+ end
+
+ L1 --> ONCALL[On-Call 值班群]
+ L2 --> OPS[运维监控群]
+ L3 --> DAILY["每日健康报告"]
+
+ style L1 fill:#ffebee
+ style L2 fill:#fff3e0
+ style L3 fill:#e3f2fd
+```
+
+### 3. 降噪与抑制
+
+同一个根因可能触发连锁告警,需要抑制机制:
+
+```
+┌──────────┐ ┌──────────┐ ┌──────────┐
+│ DB 宕机 │───→│ 服务 A 报错│───→│ 关联告警 │
+└──────────┘ └──────────┘ │ 只发 Root Cause│
+ │ 其他静默 │
+ └──────────┘
+```
+
+| 技术 | 说明 |
+|------|------|
+| **告警分组** | 同一根因的多个告警合并为一条 |
+| **静默期** | Pod 重启后 5 分钟内不重复告警 |
+| **维护窗口** | 已知变更期间暂时抑制非关键告警 |
+| **继承抑制** | DB 挂了 → 自动抑制依赖 DB 的所有服务的告警 |
+
+## On-Call 最佳实践
+
+### Runbook:告警处置手册
+
+> [!summary] Runbook 模板
+>
+> | 字段 | 内容 |
+> |------|------|
+> | **标题** | `支付服务 P99 延迟 > 2s 持续 5 分钟` |
+> | **影响范围** | 下单接口超时,用户体验受损 |
+> | **检查步骤** | ① 看 Grafana 延迟面板确认峰值时间点 → ② 查同期部署记录 → ③ 检查下游 DB 慢查询 |
+> | **常见原因** | ① 新代码性能 regression → ② DB 连接池耗尽 → ③ 下游超时风暴 |
+> | **快速恢复** | ① 回滚最近一次发布 → ② 扩容实例 → ③ 开启熔断降负载 |
+> | **彻底解决** | 排查根本原因,补充回归测试,完善容量规划 |
+
+### Blameless Postmortem
+
+事故复盘不问"谁干的",问"流程哪里可以改进":
+
+```mermaid
+flowchart LR
+ Incident["事故发生"] --> Contain["控制影响面"]
+ Contain --> Investigate["调查根因"]
+ Investigate --> Action["制定改进行动"]
+ Action --> Share["分享经验教训"]
+
+ style Incident fill:#ffebee
+ style Contain fill:#fff3e0
+ style Investigate fill:#e3f2fd
+ style Action fill:#e8f5e9
+ style Share fill:#f3e5f5
+```
+
+> [!tip] 事后复盘三问
+>
+> 1. **什么导致了这次事故?** (技术根因)
+> 2. **为什么监控系统没有更早发现?** (检测延迟)
+> 3. **下次如何避免同类问题?** (流程改进)
+
+## 告警疲劳自检清单
+
+如果你的团队出现以下情况,说明告警体系需要重构:
+
+- [ ] On-Call 工程师下班前都要关闭/忽略一堆告警
+- [ ] 有人会在群里说 "这个告警不用管"
+- [ ] 同一个服务每天都触发相同的告警
+- [ ] 新同事不知道哪些告警是真的严重
+- [ ] PagerDuty/Oncall 通知已读率低于 50%
+
+如果以上超过 2 项 ✅ —— 你的告警需要认真治理了。
+
+## 关联笔记
+
+- [[04-可观测性/Metrics监控/README]] — Metrics 是告警的数据来源
+- [[05-部署运维/SRE实践/README]] — SLO/Error Budget 的详细方法论
+- [[02-服务治理/容错模式/README]] — 熔断器状态可以作为告警信号
diff --git a/hzh/MS/04-可观测性/日志系统/README.md b/hzh/MS/04-可观测性/日志系统/README.md
new file mode 100644
index 0000000..8eb443c
--- /dev/null
+++ b/hzh/MS/04-可观测性/日志系统/README.md
@@ -0,0 +1,149 @@
+---
+tags: [microservice, logging, elk, loki, structured-logging]
+create time: 2026-05-05
+---
+
+# 日志系统
+
+## 概述
+
+Logging 回答的问题是:**具体发生了什么?**——通过原始事件记录提供上下文。
+
+在微服务架构中,所有服务的日志必须集中收集。散落在各台机器上的日志无法支撑有效的故障排查。
+
+```mermaid
+flowchart LR
+ APP[应用容器] -->|stdout/stderr| COLLECTOR[采集器
FLUENTD / Filebeat]
+ COLLECTOR --> PARSE["解析 & 过滤"]
+ PARSE --> ES[(Elasticsearch)]
+ PARSE --> LOKI[(Loki)]
+ ES --> GRAF["Grafana / Kibana"]
+ LOKI --> GRAF
+
+ style COLLECTOR fill:#fff3e0
+ style PARSE fill:#e3f2fd
+```
+
+## 结构化日志
+
+**不要写纯文本日志**。推荐 JSON 格式,便于程序解析和查询:
+
+```json
+{
+ "timestamp": "2026-05-05T10:30:00Z",
+ "level": "ERROR",
+ "service": "order-service",
+ "trace_id": "abc-123-def",
+ "span_id": "span-456",
+ "msg": "failed to connect payment service",
+ "caller": "payment/client.go:42",
+ "cost_ms": 30000,
+ "user_id": "user-42"
+}
+```
+
+### 最小字段集合(必选)
+
+| 字段 | 格式 | 说明 |
+|------|------|------|
+| `timestamp` | ISO 8601 (`2026-05-05T10:30:00Z`) | UTC 时区,不可省略 |
+| `level` | TRACE / DEBUG / INFO / WARN / ERROR / FATAL | 大小写统一 |
+| `service` | 字符串 | 微服务名称 |
+| `trace_id` | 字符串 | 链路追踪 ID,与 Tracing 串联 |
+| `msg` | 字符串 | 人类可读的消息描述 |
+
+### 日志级别使用规范
+
+| 级别 | 使用场景 | 示例 |
+|------|---------|------|
+| **TRACE** | 调试级详细输出(仅开发环境) | 方法入参/出参、循环体内部状态 |
+| **DEBUG** | 诊断信息 | 缓存命中率、连接池状态 |
+| **INFO** | 关键业务事件 | 下单成功、支付回调、用户注册 |
+| **WARN** | 异常但不致命 | 重试了一次、走降级、配置热更新 |
+| **ERROR** | 影响单个请求的失败 | DB 超时、下游调用失败、空指针 |
+| **FATAL** | 进程无法继续运行 | 配置文件缺失、依赖服务完全不可用 |
+
+> [!warning] 最佳实践
+>
+> - **不要记录敏感信息**:密码、Token、身份证号等绝不能出现在日志中
+> - **INFO 级记录关键业务事件**——这些是排查业务问题的主线
+> - **WARN 级记录异常但不致命**——如重试、降级
+> - **ERROR 级必须有 trace_id 和错误堆栈**,否则毫无价值
+
+## 日志采集管线
+
+```mermaid
+flowchart LR
+ App["业务应用"] -->|stdout/stderr| K8sPod["Pod 容器日志"]
+ K8sPod --> Collector["采集器
Filebeat / FluentBit"]
+ Collector --> Backend["存储后端
Elasticsearch / Loki"]
+ Backend --> UI["查询面板
Grafana / Kibana"]
+
+ Collector -->|"过滤掉 health check"| Drop["丢弃无用日志"]
+
+ style Drop fill:#ffebee,stroke:#ef5350
+```
+
+### 采集器选型
+
+| 组件 | 语言 | 资源消耗 | 特点 |
+|------|------|---------|------|
+| **Filebeat** (ELK) | Go | 低 | 轻量,适合 K8s DaemonSet |
+| **Fluentd** | Ruby | 中 | 插件生态丰富,处理灵活 |
+| **FluentBit** | C | 极低 | 边缘场景首选,K8s 官方推荐 |
+
+## 日志方案对比
+
+| 方案 | 存储 | 查询能力 | 成本 | 适用场景 |
+|------|------|---------|------|---------|
+| **ELK** (Elasticsearch) | ES 集群 | 全文检索强大 | 高 | 日志量大、需要复杂分析 |
+| **Loki + Grafana** | 对象存储 (S3) | Label 索引 + LogQL | 低 | 已在用 Grafana 的团队 |
+| **云 SLS / CloudWatch** | 云托管 | 开箱即用 | 中~高 | 全云原生环境 |
+
+### Loki vs ELK 决策树
+
+```mermaid
+flowchart TD
+ Q{"需要全文检索吗?"}
+
+ Q -- "否,按时间/Service/TraceId 查询" --> LOKI["✅ Loki
低成本、轻量"]
+ Q -- "是,复杂的全文搜索" --> ELK["✅ ELK
功能强大"]
+
+ LOKI --> Check{"日日志量 > 1TB?"}
+ Check -- 是 --> ConsiderES["考虑混合架构
高频用 Loki,低频归档到 ES"]
+ Check -- 否 --> Done["直接用 Loki ✅"]
+
+ ELK --> Check2{"团队有经验?"}
+ Check2 -- 是 --> UseES["直接上 ES ✅"]
+ Check2 -- 否 --> Managed["用托管版 (阿里云 SLS)"]
+```
+
+## 采样策略
+
+生产环境中并非所有日志都要采集。**正常路径采 1%,异常路径全量**。
+
+```
+正常 HTTP 200 → 1% 采样率 → 每小时 ~360 条日志
+异常 HTTP 5xx → 100% 全量采集 → 可能数千条日志
+DB 慢查询 → 100% 全量采集 → 重点关注
+健康检查 → 不采集 → 零成本
+```
+
+> [!tip] 实现方式
+> 采样逻辑建议写在日志库的中间件层,而非业务代码里:
+> ```go
+> func SampleLogger(next logger.Logger, rate float64) logger.Logger {
+> return &sampledLogger{
+> next: next,
+> shouldSample: func() bool {
+> return rand.Float64() < rate
+> },
+> }
+> }
+> ```
+
+## 关联笔记
+
+- [[04-可观测性/Metrics监控/README]] — Metrics + Logging = 完整的问题定位能力
+- [[04-可观测性/链路追踪/README]] — trace_id 是日志与追踪的桥梁
+- [[04-可观测性/告警管理/README]] — 日志可以触发基于模式的告警
diff --git a/hzh/MS/04-可观测性/链路追踪/README.md b/hzh/MS/04-可观测性/链路追踪/README.md
new file mode 100644
index 0000000..5492fec
--- /dev/null
+++ b/hzh/MS/04-可观测性/链路追踪/README.md
@@ -0,0 +1,166 @@
+---
+tags: [microservice, tracing, opentelemetry, context-propagation]
+create time: 2026-05-05
+---
+
+# 链路追踪
+
+## 概述
+
+Tracing 回答的问题是:**请求在哪一步慢了 / 失败了?**——通过完整的调用链定位瓶颈和故障。
+
+一次请求在多个服务中的完整调用路径:
+
+```mermaid
+flowchart LR
+ RID["Request
trace_id: abc-123"]
+
+ subgraph SPANS["调用链 (Trace)"]
+ direction TB
+ S1["Span #1
API Gateway
5ms"]
+ S2["Span #2
Order Service
70ms"]
+ S3["Span #3
Payment RPC
160ms"]
+ S4["Span #4
Inventory RPC
70ms"]
+
+ S1 --> S2 --> S3
+ S2 --> S4
+ end
+
+ RID --> S1
+ style S3 fill:#ff9999
+
+ note["Span #3 耗时最长 → Payment 是瓶颈"]
+ S3 -.-> note
+```
+
+## Trace/Span 核心概念
+
+| 概念 | 说明 |
+|------|------|
+| **Trace** | 一次请求的完整调用链,全局唯一 `trace_id` |
+| **Span** | 调用链中的一个执行单元,有独立的 `span_id` |
+| **Parent-Child** | Span 树状结构,子 Span 继承父 Span 的 trace_id |
+| **Tags / Attributes** | 键值对标注(HTTP method、status code) |
+| **Logs** | Span 级别的时间戳事件(如 "DB query started") |
+| **Sampling** | 按比例采样,降低存储开销 |
+
+### OpenTelemetry W3C Trace Context 标准
+
+```json
+// HTTP Header
+{
+ "traceparent": "00-{trace_id}-{span_id}-01",
+ "tracestate": "vendor=value"
+}
+```
+
+格式解析:`version(2字节) - trace_id(32字节) - span_id(16字节) - flags(2字节)`
+
+```
+示例: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
+ │ └─── trace_id ───┘ └─ span_id ─┘ └flags─┘
+```
+
+## 上下文传播详解
+
+`trace_id` 必须从上游传递到下游。不同通信场景有不同的传播方式:
+
+### HTTP 传播
+
+```go
+func Middleware(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ // 1. 提取入站 trace context
+ ctx := propagator.Extract(r.Context(), headerReader{r.Header})
+
+ // 2. 创建新的 Span
+ ctx, span := tracer.Start(ctx, "handleRequest")
+ defer span.End()
+
+ // 3. 将 trace context 注入出站请求
+ r = r.WithContext(ctx)
+ propagator.Inject(ctx, headerWriter{r.Header})
+
+ next.ServeHTTP(w, r)
+ })
+}
+```
+
+### MQ 消息头传播
+
+```go
+// 生产者 - 手动注入 trace context
+msg.Properties.Set("trace_id", extractTraceID(ctx))
+msg.Properties.Set("span_id", extractSpanID(ctx))
+
+// 消费者 - 恢复 trace context
+traceID := msg.Properties.Get("trace_id")
+span, _ := tracer.Start(traceContext, "consumeMessage",
+ trace.WithAttributes(attribute.String("mq.message.id", traceID)))
+```
+
+## 采样策略
+
+```mermaid
+flowchart TD
+ AllReq["全部请求"] --> Sampler{"采样决策"}
+
+ Sampler -->|"100%"| Core["核心链路全量采集"]
+ Sampler -->|"5~10%"| Normal["普通路径随机采样"]
+ Sampler -->|"100%"| Error["错误链路优先保留"]
+ Sampler -->|"0%"| Health["健康检查/内部心跳"]
+
+ Core --> Storage["Trace 存储"]
+ Normal --> Storage
+ Error --> Storage
+ Health --> Drop["丢弃"]
+```
+
+| 环境 | 采样率 | 说明 |
+|------|--------|------|
+| 开发 / 测试 | 100% | 方便调试,无存储压力 |
+| 生产 - 核心链路 | 100% | 下单、支付等关键路径 |
+| 生产 - 普通路径 | 5~10% | 平衡成本和覆盖率 |
+| 生产 - 错误链路 | 100% | 出错时优先保留 |
+
+> [!tip] 基于错误的智能采样
+>
+> 高级做法:**正常路径低采样,一旦检测到 HTTP 5xx 或 DB 超时,立即提升当前请求的采样率**。这样既省了存储,又能在出问题时有足够的数据回溯。
+
+## 主流方案对比
+
+| 方案 | 存储后端 | 侵入程度 | 中文支持 | 推荐理由 |
+|------|---------|---------|---------|---------|
+| **OpenTelemetry** | 任意 Jaeger/Prometheus/Loki | SDK + Auto-instrumentation | 良好 | CNCF 行业标准,未来趋势 |
+| **Jaeger** | Cassandra / Elasticsearch | Agent / SDK | 社区支持 | Uber 开源,UI 优秀 |
+| **SkyWalking** | MySQL / ES | 零侵入 Agent | ⭐ 完善 | 国产首选,开箱即用 |
+
+## 渐进式落地路线
+
+> [!tip] 不要试图一步到位——先从 Tracing 开始,ROI 最高。
+>
+> 1. **第一步**:接入 Tracing(OpenTelemetry),覆盖核心链路(下单、支付),rate=100%
+> 2. **第二步**:加 Metrics(Prometheus + Grafana),建立基础监控面板
+> 3. **第三步**:集中 Logging(Loki / ELK),日志携带 trace_id 与 Tracing 关联
+> 4. **第四步**:全量上 OpenTelemetry Collector,统一管理三件套
+
+## 性能影响评估
+
+| 指标 | 预期影响 |
+|------|---------|
+| CPU 增加 | < 3%(异步批量上报) |
+| 内存增加 | ~10MB(Span buffer) |
+| 网络带宽 | 每条 Trace 约 2~5KB(取决于 Span 数量) |
+| 延迟增加 | < 0.1ms(SDK 内处理不阻塞业务) |
+
+> [!note] 关键实践
+> - 使用 **BatchProcessor** 异步上报,不阻塞业务线程
+> - Span 不要嵌套过深,一个 HTTP 调用或 DB 查询对应一个 Span
+> - 给 Span 设置丰富的 Attributes,方便查询和过滤
+> - 错误 Span 标记 `isError=true`,便于快速定位问题链路
+
+## 关联笔记
+
+- [[04-可观测性/Metrics监控/README]] — Tracing 与 Metrics 互补
+- [[04-可观测性/日志系统/README]] — trace_id 串联日志和追踪
+- [[04-可观测性/告警管理/README]] — 基于 Trace 数据的异常检测告警
diff --git a/hzh/MS/05-部署运维.md b/hzh/MS/05-部署运维.md
deleted file mode 100644
index 1ffdf4e..0000000
--- a/hzh/MS/05-部署运维.md
+++ /dev/null
@@ -1,397 +0,0 @@
----
-tags: [microservice, kubernetes, cicd, container, sre, observability]
-create time: 2026-04-29 12:05
----
-
-# 部署运维
-
-## 概述
-
-微服务架构下,服务数量从几个增长到几百个。**人工运维完全不可行**。本文涵盖容器化编排、K8s 资源管理、发布策略、弹性伸缩、CI/CD 流水线、日志告警和 SRE 核心概念。
-
-## 容器化与编排
-
-### Docker 容器 — 标准交付单元
-
-```dockerfile
-# Go 多阶段构建示例
-FROM golang:1.22 AS builder
-WORKDIR /app
-COPY . .
-RUN CGO_ENABLED=0 GOOS=linux go build -o server .
-
-FROM alpine:latest
-COPY --from=builder /app/server /server
-EXPOSE 8080
-CMD ["/server"]
-```
-
-> [!tip] 关键实践
-> - **多阶段构建**:镜像只包含运行时产物,体积极大缩小
-> - **非 root 用户运行**:安全最佳实践
-> - `.dockerignore`:排除不必要的文件(git、vendor、测试文件)
-
-### Kubernetes 核心概念
-
-```mermaid
-graph TB
- subgraph CLUSTER["K8s Cluster"]
- master["Master Node
API Server / Scheduler / ETCD"]
-
- subgraph NODES["Worker Nodes"]
- N1[Node A]
- N2[Node B]
- end
-
- master --> N1
- master --> N2
-
- subgraph PODS1["Deployment: order-service"]
- P1[Pod 1]
- P2[Pod 2]
- P3[Pod 3]
- end
-
- subgraph PODS2["Deployment: payment-service"]
- Q1[Pod 1]
- Q2[Pod 2]
- end
-
- N1 --> P1 & Q1
- N2 --> P2 & P3 & Q2
- end
-
- Svc["Service: order-service
Load Balancer → Pods"]
- Svc --> P1 & P2 & P3
-```
-
-| K8s 对象 | 作用 |
-|---------|------|
-| Pod | 最小部署单元,一个或多个容器 |
-| Deployment | 管理 Pod 的声明式更新和扩缩容 |
-| Service | 稳定的网络入口,实现负载均衡 |
-| Ingress | HTTP/HTTPS 路由规则(外部访问入口) |
-| ConfigMap / Secret | 配置注入,与代码分离 |
-| HPA (Horizontal Pod Autoscaler) | 根据 CPU/自定义指标自动扩缩 |
-
-### 资源管理与健康检查
-
-K8s 调度 Pod 的核心依据是 **资源请求 (Requests)**,而决定 pod 生死的是 **探针 (Probes)**。这两个概念配合使用才能保障服务稳定运行。
-
-```yaml
-# Deployment 核心片段:资源配置 + 探针
-spec:
- replicas: 3
- template:
- spec:
- containers:
- - name: order-service
- image: registry.example.com/order:v1.2.3
- resources:
- requests: # 调度依据:K8s 保证至少有这些资源
- cpu: "250m" # 0.25 核
- memory: "256Mi" # 256 MB
- limits: # 硬上限:超过则 OOMKill / CPU Throttle
- cpu: "500m"
- memory: "512Mi"
- livenessProbe: # 活体检测:死了就重启
- httpGet:
- path: /healthz
- port: 8080
- initialDelaySeconds: 15
- periodSeconds: 10
- readinessProbe: # 就绪检测:未就绪就不进负载均衡
- httpGet:
- path: /ready
- port: 8080
- initialDelaySeconds: 5
- periodSeconds: 5
- startupProbe: # 启动检测:慢启动服务友好
- httpGet:
- path: /healthz
- port: 8080
- failureThreshold: 30
- periodSeconds: 10
-```
-
-> [!tip] Probe 选择指南
->
-> | 探针类型 | 触发条件 | 后果 | 适用场景 |
-> |---------|---------|------|---------|
-> | **Liveness** | `/healthz` 返回非 2xx | K8s **重启容器** | 死锁、无法恢复的崩溃 |
-> | **Readiness** | `/ready` 返回非 2xx | **摘除 Service 流量** | 依赖 DB 连接池未就绪、热加载进行中 |
-> | **Startup** | 首次成功前一直失败 | **不重启,只等待** | 大模型初始化、JVM cold start 等慢启动场景 |
-
-> [!question] 思考
-> 如果一个服务的 `/healthz` 因为数据库连接超时而持续返回 503,K8s 会怎么做?
-
-**答案**:Liveness Probe 会认为容器挂了并反复重启它 — 这就是经典的 **CrashLoopBackOff**。正确做法是让 `/healthz` 做降级判断(DB 不可用时返回 200 + 标注降级),用 `/ready` 来摘除流量。Liveness 应该只对"进程已死"的情况敏感,对"性能下降"保持宽容。
-
----
-
-## 发布策略
-
-微服务需要独立发布,如何在不停服的情况下完成更新?
-
-### 蓝绿发布
-
-```mermaid
-stateDiagram-v2
- [*] --> Blue: 初始状态
- Blue --> DeployGreen: 部署新版本到 Green
- DeployGreen --> TestGreen: 灰度验证
- TestGreen --> Switch: 切换流量
- Switch --> Green: 全部流量到新版
- Green --> CleanupGreen: 删除旧版 Blue
-```
-
-- 优点:**回滚极速**(切回 Blue 即可),验证充分
-- 缺点:资源翻倍,需要两套环境
-
-### 金丝雀发布 (Canary)
-
-```mermaid
-graph LR
- A["95% traffic to stable"]
- B["5% traffic to canary"]
- C["Metrics normal?"]
- D["Gradually expand to 20% → 50% → 100%"]
- E["Metrics abnormal → Auto rollback"]
-
- A --> B
- B --> C
- C -- "yes" --> D
- C -- "no" --> E
-```
-
-- 优点:资源效率高,风险渐进暴露
-- 缺点:流程复杂,需要完善的监控配合
-
-### 两种策略选择
-
-> [!question] 思考
-> 你的团队应该用蓝绿还是金丝雀?
-
-**答案线索**:看你们的**监控成熟度和发布频率**。低频次(每周/每月)、监控完善时用金丝雀;高频次(每天多次)或想简化流程时用蓝绿。
-
-## 弹性伸缩
-
-```mermaid
-graph TD
- Metrics["CPU / Memory / Custom QPS"] --> Trigger{Threshold met?}
- Trigger -- "yes" --> ScaleUp["Scale up new Pod"]
- Trigger -- "no" --> Keep["Keep current replicas"]
- ScaleDown{"Load decreased?"} -- "yes" --> ScaleDownPod["Scale down Pod"]
- ScaleDown -- "no" --> Keep
-```
-
-**注意事项**:
-- **预热时间**:新 Pod 启动后不能立刻算入统计,否则可能反复扩缩
-- **优雅关闭**:HPA 缩容前,Pod 需要先摘除 Service 流量再退出
-- **预留容量**:不要将集群利用率拉到 100%,给突发流量留缓冲
-
-## CI/CD 流水线
-
-```mermaid
-graph LR
- CODE["代码提交"]
- TEST["单元测试 + 集成测试"]
- SCAN["安全扫描 + 代码质量"]
- BUILD["构建 Docker 镜像"]
- PUSH["推送镜像仓库"]
- DEPLOY["CI→Staging → 审批 → Production"]
-
- CODE --> TEST --> SCAN --> BUILD --> PUSH --> DEPLOY
-```
-
-> [!summary] CI/CD 设计原则
->
-> - **一次构建,多处部署**:镜像不随环境重新编译,只改 K8s ConfigMap/环境变量
-> - **语义化版本号**:镜像 tag 用 `v1.2.3`,tag 即版本溯源
-> - **自动化测试覆盖率要求**:合并 PR 前必须通过,否则不允许发布
-
-### Pipeline 实战:GitHub Actions
-
-```yaml
-# .github/workflows/deploy.yml
-name: Deploy order-service
-on:
- push:
- branches: [main]
- paths:
- - "services/order/**" # 仅该目录变更才触发
-
-jobs:
- build-and-push:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - name: Build & push image
- run: |
- docker build -t registry/order:${{ github.sha }} .
- docker tag registry/order:${{ github.sha }} \
- registry/order:v$(git describe --tags --abbrev=0)
- docker push registry/order:${{ github.sha }}
-
- deploy-staging:
- needs: build-and-push
- runs-on: ubuntu-latest
- environment: staging
- steps:
- - name: Apply K8s manifests
- run: |
- kubectl set image deployment/order-service \
- order=registry/order:${{ github.sha }}
- kubectl rollout status deployment/order-service --timeout=120s
-
- deploy-production:
- needs: deploy-staging
- runs-on: ubuntu-latest
- environment: production
- steps:
- - name: Canary release (10% → 50% → 100%)
- run: |
- kubectl patch canary order-service --type merge \
- -p '{"spec":{"weight":10}}'
- # ... 等待监控确认,逐步放大流量
-```
-
-> [!tip] Pipeline 设计要点
->
-> - **路径过滤**:只对相关服务的代码变更触发构建,避免全量重建
-> - **Commit SHA 作为镜像 tag**:保证精确回滚 — `git revert` 之后用同一 SHA 拉取旧镜像
-> - **分阶段部署**:Staging → Production 的审批关卡是最后的防线,不要跳过
-
-## 日志管理与告警
-
-微服务单实例崩溃不可怕 — 可怕的是 **不知道哪一台、为什么挂了**。日志和告警是运维的眼睛。
-
-### 日志架构选型
-
-```mermaid
-graph LR
- App["业务应用"] -->|stdout/stderr| K8sPod[Pod 容器日志]
- K8sPod --> Filebeat[采集器: Filebeat / FluentBit]
- Filebeat --> ES["Elasticsearch / Loki"]
- ES --> Grafana["Grafana 查询面板"]
-
- App -->|structured log| sidecar[Sidecar 辅助日志]
- sidecar --> Filebeat
-```
-
-**业界两种主流方案对比:**
-
-| 维度 | ELK (Elasticsearch) | EFK/Loki |
-|------|---------------------|----------|
-| 存储成本 | 高(全文索引) | 低(索引 label + 对象存储原文) |
-| 查询性能 | 毫秒级全文检索 | 按 label 过滤较快,复杂查询慢 |
-| 运维复杂度 | 高(ES 集群维护) | 低(Loki 无索引) |
-| 适用规模 | 百万条/天以上 | 万 ~ 百万条/天 |
-
-> [!important] 结构化日志
->
-> 无论选择哪家方案,**日志格式必须是结构化的**(JSON),否则后期处理全是手工活:
-> ```json
-> {
-> "timestamp": "2026-04-29T10:30:00Z",
-> "level": "error",
-> "service": "order-service",
-> "trace_id": "abc-123-def",
-> "msg": "payment gateway timeout",
-> "duration_ms": 5023
-> }
-> ```
-
-### 告警策略设计
-
-> [!question] 思考
-> 如果一个 Pod CPU 使用率从 20% 飙升到 90%,你应该立刻打电话叫值班工程师吗?
-
-不一定。**好的告警应该是" actionable"的** — 能让人立刻采取行动,而不是单纯告诉你"出事了"。
-
-```mermaid
-mindmap
- root((告警设计原则))
- 区分等级
- P0: 立即响应 (页面电话)
- P1: 当天处理 (IM 消息)
- P2: 本周修复 (工单)
- 抑制噪音
- 相关告警聚合: 一个根因一条告警
- 静默期: 重启后的自动恢复不打扰
- 附带上下文
- 告警信息包含: 什么服务 · 哪个指标 · 当前值 vs 阈值
-```
-
----
-
-## SRE 核心概念
-
-站点可靠性工程 (SRE) 把运维问题看作**软件工程问题**。它的核心理念是用 SLI/SLO/SLA 来量化服务质量,避免"我觉得系统很慢"这类模糊描述。
-
-### SLI / SLO / SLA
-
-| 术语 | 全称 | 定义 | 谁定义 |
-|------|------|------|--------|
-| **SLI** | Service Level Indicator | **实际度量**:用户请求的成功率是多少? | 观测系统自动产出 |
-| **SLO** | Service Level Objective | **内部目标**:我们承诺达到 99.9% 可用性 | SRE + 研发制定 |
-| **SLA** | Service Level Agreement | **对外合同**:达不到就赔钱 | 法务 + 商务制定 |
-
-> [!tip] 实用比例
->
-> - **99.9% (三个九)** = 每年约 8.76 小时停机 — 适合大多数后端服务
-> - **99.95%** = 每年约 4.38 小时 — 核心交易链路
-> - **99.99% (四个九)** = 每年约 52 分钟 — 金融级系统
-> - **99%** 意味着每月近 7 小时不可用 — **几乎等于没有可用性目标**
-
-### 错误预算 (Error Budget)
-
-这是 SRE 最核心的机制 — **允许犯错,但设上限**:
-
-```
-错误预算 = 1 - SLO
-
-SLO = 99.9% → 错误预算 = 0.1% → 每月允许 21 分钟停机
-SLO = 99.99% → 错误预算 = 0.01% → 每月仅 4 分钟停机
-```
-
-**基于错误预算的决策逻辑:**
-
-```mermaid
-flowchart TD
- Budget{"错误预算剩余 > 50%?"}
-
- Budget -- "是" --> Aggressive["可激进发布:
金丝雀 + 自动扩缩"]
- Budget -- "< 50%" --> Conservative["保守发布:
蓝绿 + 全量人工审查"]
- Budget -- "< 10%" --> Freeze["冻结发布:
优先修复稳定性
不允许新功能上线"]
-
- Aggressive --> Monitor["持续监控指标"]
- Conservative --> Monitor
-```
-
-> [!summary] SRE 心法
->
-> 1. **用户视角定义 SLO**:不是"API P99 < 200ms",而是"用户在 3G 网络下打开页面 < 2s"
-> 2. **错误预算用完 = 停止功能开发**:全力修 bug 加稳定性
-> 3. **Blameless Postmortem**:事故复盘不问"谁干的",问"流程哪里可以改进"
-
----
-
-## 运维 Checklist
-
-每次上线前快速过一遍这个清单,避免低级事故:
-
-| # | 检查项 | 说明 |
-|---|--------|------|
-| 1 | **探针已配置** | liveness/readiness/startup probe 都已设定 |
-| 2 | **资源 limits 已设** | 防止单个 Pod 拖垮整台机器 |
-| 3 | **日志为 JSON 格式** | 可被采集器解析 |
-| 4 | **追踪 ID 透传** | trace_id 在跨服务调用链中不丢失 |
-| 5 | **回滚预案明确** | 知道怎么回到上一版本,且演练过 |
-| 6 | **告警已配置** | 关键指标异常时有人收到通知 |
-| 7 | **数据迁移有回退脚本** | DB schema 变更要兼容新老版本共存 |
-
-## 关联笔记
-
-- [[02-服务治理]] — K8s Service 提供原生的服务发现和负载均衡
-- [[04-可观测性]] — K8s Liveness/Readiness Probe 是可观测性的基础
diff --git a/hzh/MS/05-部署运维/CI-CD与GitOps/README.md b/hzh/MS/05-部署运维/CI-CD与GitOps/README.md
new file mode 100644
index 0000000..9f10bd1
--- /dev/null
+++ b/hzh/MS/05-部署运维/CI-CD与GitOps/README.md
@@ -0,0 +1,176 @@
+---
+tags: [microservice, cicd, gitops, github-actions, argocd]
+create time: 2026-05-05
+---
+
+# CI/CD 与 GitOps
+
+## 概述
+
+微服务需要**独立部署**。上百个服务的手工发布是不可想象的——必须用自动化流水线保证每次变更都能安全、快速地推送到生产环境。
+
+```mermaid
+flowchart LR
+ CODE["代码提交"] --> TEST["测试 & 静态分析"]
+ TEST --> SCAN["安全扫描"]
+ SCAN --> BUILD["构建镜像"]
+ BUILD --> PUSH["推送仓库"]
+ PUSH --> STAGING["Staging 验证"]
+ STAGING -->|"人工审批"| PROD["Production 部署"]
+
+ style CODE fill:#e3f2fd
+ style TEST fill:#fff3e0
+ style SCAN fill:#fce4ec
+ style BUILD fill:#e8f5e9
+ style PUSH fill:#f3e5f5
+ style STAGING fill:#e0f7fa
+ style PROD fill:#c8e6c9
+```
+
+## CI/CD 设计原则
+
+| 原则 | 说明 |
+|------|------|
+| **一次构建,多处部署** | 镜像不随环境重新编译,只改 K8s ConfigMap/环境变量 |
+| **语义化版本** | 镜像 tag 用 `v1.2.3`,tag 即版本溯源 |
+| **路径过滤** | 只对相关服务的代码变更触发构建 |
+| **Commit SHA 作为镜像 tag** | 保证精确回滚 |
+| **分阶段部署** | Staging → Production 的审批关卡不可跳过 |
+
+## GitHub Actions Pipeline 实战
+
+```yaml
+# .github/workflows/deploy.yml
+name: Deploy order-service
+on:
+ push:
+ branches: [main]
+ paths:
+ - "services/order/**"
+
+env:
+ REGISTRY: registry.example.com
+ IMAGE: order-service
+
+jobs:
+ # ========== Stage 1: Build & Test ==========
+ build-and-test:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Run tests
+ run: make test
+
+ - name: Security scan
+ uses: aquasecurity/trivy-action@master
+ with:
+ scan-type: 'fs'
+ severity: 'CRITICAL,HIGH'
+
+ - name: Build Docker image
+ run: |
+ docker build -t ${{ env.REGISTRY }}/${{ env.IMAGE }}:${{ github.sha }} \
+ -t ${{ env.REGISTRY }}/${{ env.IMAGE }}:v${{ github.run_number }} \
+ -f services/order/Dockerfile \
+ services/order
+
+ - name: Push to registry
+ run: |
+ echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login -u ${{ secrets.REGISTRY_USER }} --password-stdin
+ docker push ${{ env.REGISTRY }}/${{ env.IMAGE }}:${{ github.sha }}
+ docker push ${{ env.REGISTRY }}/${{ env.IMAGE }}:v${{ github.run_number }}
+
+ # ========== Stage 2: Deploy to Staging ==========
+ deploy-staging:
+ needs: build-and-test
+ runs-on: ubuntu-latest
+ environment: staging
+ steps:
+ - name: Deploy to staging
+ run: |
+ kubectl set image deployment/order-service \
+ order=${{ env.REGISTRY }}/${{ env.IMAGE }}:${{ github.sha }} \
+ --namespace=staging
+ kubectl rollout status deployment/order-service \
+ --namespace=staging --timeout=120s
+
+ # ========== Stage 3: Deploy to Production ==========
+ deploy-production:
+ needs: deploy-staging
+ runs-on: ubuntu-latest
+ environment: production
+ steps:
+ - name: Canary release (10% → 50% → 100%)
+ run: |
+ kubectl patch canary order-service --type merge \
+ -p '{"spec":{"weight":10}}'
+
+ # ... 等待监控确认,逐步放大流量
+ echo "Monitor metrics before proceeding..."
+```
+
+## GitOps 工作流
+
+GitOps 的核心思想:**K8s 集群的状态 = Git 仓库中声明式配置的当前状态。**
+
+```mermaid
+flowchart LR
+ Dev["开发者 PR"] -->|"修改 K8s manifest"| Git[(Git Repo)]
+
+ subgraph Cluster["K8s Cluster"]
+ Argo["ArgoCD / Flux"] -->|同步| K8sState["Pod/Service/ConfigMap"]
+ end
+
+ Git -.->|Webhook| Argo
+
+ Argo -->|"检测到差异"| Diff{"状态一致?"}
+ Diff -- 否 --> Sync["自动同步到 K8s ✅"]
+ Diff -- 是 --> OK["已一致 ⏸️"]
+
+ style Git fill:#e3f2fd
+ style Argo fill:#fff3e0
+ style K8sState fill:#e8f5e9
+```
+
+### 与传统 CI/CD 的区别
+
+| 维度 | 传统 CI/CD | GitOps |
+|------|-----------|--------|
+| **部署驱动** | CI 服务器主动推送 | Git 仓库变动触发拉取 |
+| **状态源** | CI pipeline 的历史记录 | Git commit history |
+| **回滚方式** | 回到上一次的 pipeline | `git revert` + 自动同步 |
+| **漂移检测** | 通常无 | 持续比对,自动修复不一致 |
+| **代表工具** | Jenkins / GitLab CI / GitHub Actions | ArgoCD / Flux |
+
+### GitOps 的优势
+
+1. **审计完整** — 所有变更都在 Git 中可追溯
+2. **回滚简单** — `git revert` 就是回滚操作
+3. **自修复** — ArgoCD 持续监测并修复集群状态偏离
+4. **多人协作** — 通过 PR Review 流程管控配置变更
+
+## Helm — K8s 的包管理
+
+当每个服务都有几十行 YAML 时,Helm 能大幅简化部署:
+
+```bash
+# 创建 Chart 模板
+helm create order-service
+
+# 使用 values.yaml 参数化部署
+helm upgrade --install order-service ./charts/order-service \
+ --set image.tag=v1.2.3 \
+ --set replicas=3 \
+ --namespace=production
+```
+
+> [!tip] 为什么需要 Helm?
+>
+> 没有 Helm 时,每个服务都要手动维护 Deployment、Service、Ingress、ConfigMap 等几十个 YAML 文件。Helm 允许你把通用模板抽出来,只在 values.yaml 里改差异化配置。
+
+## 关联笔记
+
+- [[05-部署运维/容器化/README]] — Docker 镜像构建是 CI/CD 的第一步
+- [[05-部署运维/Kubernetes/README]] — K8s 是部署的目标平台
+- [[05-部署运维/SRE实践/README]] — 错误预算影响发布策略
diff --git a/hzh/MS/05-部署运维/Kubernetes/README.md b/hzh/MS/05-部署运维/Kubernetes/README.md
new file mode 100644
index 0000000..e45b5a0
--- /dev/null
+++ b/hzh/MS/05-部署运维/Kubernetes/README.md
@@ -0,0 +1,266 @@
+---
+tags: [microservice, kubernetes, k8s, container-orchestration]
+create time: 2026-05-05
+---
+
+# Kubernetes
+
+## 概述
+
+Kubernetes (K8s) 是微服务架构的事实标准编排引擎。它将容器化的服务组织成声明式的资源对象,自动处理部署、扩展、故障恢复。
+
+```mermaid
+graph TB
+ subgraph CLUSTER["K8s Cluster"]
+ Master["控制面
API Server / Scheduler / Controller Manager / etcd"]
+
+ subgraph NODES["工作节点"]
+ N1["Node A
kubelet + kube-proxy"]
+ N2["Node B
kubelet + kube-proxy"]
+ end
+
+ Master --> N1
+ Master --> N2
+
+ subgraph APPS["应用层"]
+ Order["Order Service Deployment"]
+ Pay["Payment Service Deployment"]
+ end
+
+ N1 --> Order
+ N2 --> Order
+ N1 --> Pay
+ N2 --> Pay
+ end
+
+ SVC["Service (ClusterIP)"] -->|Load Balance| Order
+ Ingress["Ingress (HTTP Routing)"] --> SVC
+
+ style Master fill:#e3f2fd
+ style N1 fill:#fff3e0
+ style N2 fill:#fff3e0
+```
+
+## 核心概念速查
+
+| K8s 对象 | 用途 | 类比 |
+|---------|------|------|
+| **Pod** | 最小部署单元,包含一个或多个容器 | 应用实例 |
+| **Deployment** | 管理 Pod 的副本数和滚动更新 | 应用的"模板" |
+| **Service** | 稳定的网络入口,负载均衡 | 内部 VIP |
+| **Ingress** | HTTP/HTTPS 路由规则 | 外部网关 |
+| **ConfigMap** | 配置注入(明文) | 环境变量/配置文件 |
+| **Secret** | 敏感配置注入(base64) | 密码/API Key |
+| **HPA** | 根据指标自动扩缩容 | 弹性伸缩 |
+| **StatefulSet** | 有状态应用的有序管理 | DB、ZK |
+| **Job/CronJob** | 一次性任务 / 定时任务 | 批处理 |
+
+## Deployment 详解
+
+### 完整示例
+
+```yaml
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: order-service
+ labels:
+ app: order
+ version: v1.2.3
+spec:
+ replicas: 3 # 期望副本数
+ strategy:
+ type: RollingUpdate
+ rollingUpdate:
+ maxSurge: 1 # 最多超额 1 个 Pod
+ maxUnavailable: 0 # 滚动更新期间不允许不可用
+
+ selector:
+ matchLabels:
+ app: order
+
+ template:
+ metadata:
+ labels:
+ app: order
+ version: v1.2.3
+ spec:
+ containers:
+ - name: order-service
+ image: registry.example.com/order:v1.2.3
+ ports:
+ - containerPort: 8080
+
+ # ========== 资源配置 ==========
+ resources:
+ requests: # 调度依据:保证至少有这些
+ cpu: "250m"
+ memory: "256Mi"
+ limits: # 硬上限:超过则 OOMKill/CPU Throttle
+ cpu: "500m"
+ memory: "512Mi"
+
+ # ========== 探针 ==========
+ livenessProbe:
+ httpGet:
+ path: /healthz
+ port: 8080
+ initialDelaySeconds: 15
+ periodSeconds: 10
+ failureThreshold: 3 # 连续失败 3 次才重启
+
+ readinessProbe:
+ httpGet:
+ path: /ready
+ port: 8080
+ initialDelaySeconds: 5
+ periodSeconds: 5
+ failureThreshold: 3
+
+ startupProbe:
+ httpGet:
+ path: /healthz
+ port: 8080
+ failureThreshold: 30 # 最长等待 300s (慢启动友好)
+
+ # ========== 环境变量 & 挂载 ==========
+ envFrom:
+ - configMapRef:
+ name: order-service-config
+ - secretRef:
+ name: order-service-secrets
+
+ lifecycle:
+ preStop:
+ exec:
+ command: ["sh", "-c", "sleep 15"] # 优雅退出,给 LB 摘流时间
+```
+
+### Probe 选择指南
+
+| 探针类型 | 触发条件 | 动作 | 适用场景 |
+|---------|---------|------|---------|
+| **Liveness** | `/healthz` 返回非 2xx | 重启容器 | 死锁、无法恢复的崩溃 |
+| **Readiness** | `/ready` 返回非 2xx | 摘除 Service 流量 | 依赖未就绪、热加载中 |
+| **Startup** | 首次成功前持续失败 | 不重启,只等待 | 大模型/JVM 冷启动 |
+
+> [!warning] 经典陷阱:CrashLoopBackOff
+>
+> 如果 Liveness Probe 因为 DB 连接超时而返回 503,K8s 会认为容器挂了并反复重启它——这就是 CrashLoopBackOff。正确做法是:让 `/healthz` 做降级判断(DB 不可用时返回 200),用 `/ready` 来摘除流量。
+
+## Service 与 Ingress
+
+### Service 类型
+
+| 类型 | 特点 | 使用场景 |
+|------|------|---------|
+| **ClusterIP** | 集群内 IP,外部不可访问 | 默认,内部服务间调用 |
+| **NodePort** | 在每个 Node 上开端口 | 调试、临时访问 |
+| **LoadBalancer** | 云厂商分配公网 IP | 对外暴露的服务 |
+| **ExternalName** | CNAME 到外部域名 | 对接外部系统 |
+
+```yaml
+# ClusterIP Service — 服务发现的载体
+apiVersion: v1
+kind: Service
+metadata:
+ name: order-service
+spec:
+ selector:
+ app: order
+ ports:
+ - port: 80
+ targetPort: 8080
+ protocol: TCP
+ type: ClusterIP
+```
+
+调用方只需 `http://order-service:80`,K8s 通过 iptables/IPVS 自动实现负载均衡。
+
+### Ingress — HTTP 路由
+
+```yaml
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: main-ingress
+ annotations:
+ nginx.ingress.kubernetes.io/rewrite-target: /
+spec:
+ rules:
+ - host: api.example.com
+ http:
+ paths:
+ - path: /orders
+ pathType: Prefix
+ backend:
+ service:
+ name: order-service
+ port:
+ number: 80
+ - path: /users
+ pathType: Prefix
+ backend:
+ service:
+ name: user-service
+ port:
+ number: 80
+```
+
+## HPA 弹性伸缩
+
+```yaml
+apiVersion: autoscaling/v2
+kind: HorizontalPodAutoscaler
+metadata:
+ name: order-service-hpa
+spec:
+ scaleTargetRef:
+ apiVersion: apps/v1
+ kind: Deployment
+ name: order-service
+ minReplicas: 3
+ maxReplicas: 20
+ metrics:
+ - type: Resource
+ resource:
+ name: cpu
+ target:
+ type: Utilization
+ averageUtilization: 70 # CPU > 70% 时扩容
+ - type: Resource
+ resource:
+ name: memory
+ target:
+ type: Utilization
+ averageUtilization: 80
+ behavior:
+ scaleUp:
+ stabilizationWindowSeconds: 60 # 扩容稳定期
+ policies:
+ - type: Pods
+ value: 2
+ periodSeconds: 60 # 每分钟最多扩 2 个
+ scaleDown:
+ stabilizationWindowSeconds: 300 # 缩容稳定期 5min(防抖动)
+```
+
+## K8s 运维 Checklist
+
+每次上线前过一遍这个清单:
+
+| # | 检查项 | 说明 |
+|---|--------|------|
+| 1 | **Probe 已配置** | liveness/readiness/startup 都设定了阈值 |
+| 2 | **Resources Limits** | 防止单个 Pod OOMKill 拖垮整台机器 |
+| 3 | **日志输出到 stdout/stderr** | 可被采集器解析为 JSON |
+| 4 | **trace_id 透传** | 跨服务调用链 trace_id 不丢失 |
+| 5 | **回滚预案** | `kubectl rollout undo deployment/order-service` 能用 |
+| 6 | **告警已配置** | 关键指标异常时有人收到通知 |
+| 7 | **镜像 Tag** | 不用 latest,用语义化版本或 commit SHA |
+
+## 关联笔记
+
+- [[02-服务治理/服务发现/README]] — K8s Service 是服务端发现模式的代表
+- [[02-服务治理/流量治理/README]] — Istio VirtualService 在 K8s 上的高级路由
+- [[05-部署运维/SRE实践/README]] — SLO/Error Budget 在 K8s 中的落地
diff --git a/hzh/MS/05-部署运维/README.md b/hzh/MS/05-部署运维/README.md
new file mode 100644
index 0000000..873aef6
--- /dev/null
+++ b/hzh/MS/05-部署运维/README.md
@@ -0,0 +1,42 @@
+---
+tags: [microservice, deployment, ops]
+create time: 2026-04-29 12:05
+---
+
+# 部署运维
+
+## 概述
+
+微服务架构下,服务数量从几个增长到几百个。**人工运维完全不可行**。本文涵盖容器化编排、K8s 资源管理、发布策略、弹性伸缩、CI/CD 流水线和 SRE 核心概念。
+
+## 知识体系
+
+```mermaid
+graph LR
+ A["容器化"] --> B["Kubernetes"]
+ B --> C["CI/CD 与 GitOps"]
+ C --> D["SRE 实践"]
+
+ style A fill:#e3f2fd
+ style B fill:#fff3e0
+ style C fill:#fce4ec
+ style D fill:#e8f5e9
+```
+
+| # | 主题 | 核心问题 |
+|---|------|----------|
+| 1 | [[05-部署运维/容器化/README]] | Docker 镜像怎么优化?最佳实践有哪些? |
+| 2 | [[05-部署运维/Kubernetes/README]] | K8s 核心概念和资源管理怎么做? |
+| 3 | [[05-部署运维/CI-CD与GitOps/README]] | 自动化流水线怎么设计?GitOps 流程怎么走? |
+| 4 | [[05-部署运维/SRE实践/README]] | SLI/SLO/Error Budget 如何落地? |
+
+### 学习建议
+
+> [!tip] 学习路径
+> 先掌握容器化(Docker),再学 K8s 核心概念,CI/CD 和 SRE 可以在实践中逐步深入。
+
+### 关联笔记
+
+- [[02-服务治理]] — K8s Service 提供原生的服务发现和负载均衡
+- [[04-可观测性]] — K8s Liveness/Readiness Probe 是可观测性的基础
+- [[hzh/MS/README.md]] — 完整微服务知识索引
diff --git a/hzh/MS/05-部署运维/SRE实践/README.md b/hzh/MS/05-部署运维/SRE实践/README.md
new file mode 100644
index 0000000..fdf64c8
--- /dev/null
+++ b/hzh/MS/05-部署运维/SRE实践/README.md
@@ -0,0 +1,160 @@
+---
+tags: [microservice, sre, slo, error-budget, postmortem]
+create time: 2026-05-05
+---
+
+# SRE 实践
+
+## 概述
+
+站点可靠性工程 (SRE) 把运维问题看作**软件工程问题**。它的核心理念是用 SLI/SLO/SLA 来量化服务质量,避免"我觉得系统很慢"这类模糊描述。
+
+```mermaid
+flowchart LR
+ User["用户体验"] --> SLI{"实际测量"}
+ SLI -->|"达标"| SLO_OK["✅ SLO 达成"]
+ SLI -->|"不达标"| Budget["消耗错误预算"]
+
+ Budget --> Left{"预算剩余?"}
+ Left -- "> 50%" --> Ship["快速迭代 🚀"]
+ Left -- "< 10%" --> Stabilize["稳定优先 ❄️"]
+
+ style User fill:#e3f2fd
+ style SLO_OK fill:#e8f5e9
+ style Ship fill:#fff3e0
+ style Stabilize fill:#ffebee
+```
+
+## SLI / SLO / SLA 详解
+
+### 三层模型
+
+| 术语 | 全称 | 定义 | 谁制定 | 变更频率 |
+|------|------|------|--------|---------|
+| **SLI** | Service Level Indicator | 实际度量:用户请求的成功率是多少? | 观测系统自动产出 | 持续更新 |
+| **SLO** | Service Level Objective | 内部目标:我们承诺达到 99.9% 可用性 | SRE + 研发 | 季度回顾 |
+| **SLA** | Service Level Agreement | 对外契约:达不到就赔钱 | 法务 + 商务 | 按合同约定 |
+
+### 实用性比例对照表
+
+| SLO | 每年停机时间 | 每月停机时间 | 适用级别 |
+|-----|-------------|-------------|---------|
+| **99%** | ~87.6 小时 | ~7.2 小时 | 内部工具(几乎无意义) |
+| **99.9% ("三个九")** | ~8.76 小时 | ~43 分钟 | 大多数后端服务 ✅ |
+| **99.95%** | ~4.38 小时 | ~21 分钟 | 核心交易链路 |
+| **99.99% ("四个九")** | ~52.6 分钟 | ~4.3 分钟 | 金融级 / 支付系统 |
+| **99.999%** | ~5.26 分钟 | ~26 秒 | 电信级,极难实现 |
+
+> [!warning] "三个九"是底线
+>
+> 如果团队宣称 SLO = 99%,这意味着每月可以容忍近 **7 小时的不可用**——这在生产环境中基本等于没有可用性目标。
+
+## Error Budget (错误预算) 深度解析
+
+### 计算方式
+
+```
+可用率 = (总时间 - 故障时间) / 总时间 × 100%
+错误预算 = 1 - SLO
+
+SLO = 99.9% → 错误预算 = 0.001
+ 每月可容忍故障 = 30 × 24 × 60 × 0.001 = 43.2 分钟
+ 每周可容忍故障 = 7 × 24 × 60 × 0.001 = 10.1 分钟
+
+SLO = 99.99% → 错误预算 = 0.0001
+ 每月可容忍故障 ≈ 4.3 分钟
+```
+
+### 基于错误预算的决策矩阵
+
+```mermaid
+flowchart TD
+ Ratio["错误预算使用率 = 已消耗 / 总预算"]
+
+ Ratio -- "< 50%" --> Green["🟢 绿灯阶段
预算充足: 可以大胆发布
新功能、尝试激进方案
常规发布节奏"]
+ Ratio -- "50~90%" --> Yellow["🟡 黄灯阶段
预算紧张: 收紧发布频率
增加人工审查
暂停非关键功能开发"]
+ Ratio -- "> 90%" --> Orange["🟠 橙灯阶段
严重不足: 冻结发布
专注稳定性修复
全员 On-Call"]
+ Ratio -- "> 100%" --> Red["🔴 红灯阶段
预算耗尽: 禁止所有
功能性变更
SLO 事故复盘"]
+
+ style Green fill:#c8e6c9
+ style Yellow fill:#fff9c4
+ style Orange fill:#ffe0b2
+ style Red fill:#ffcdd2
+```
+
+### 错误预算告警联动
+
+```yaml
+# Prometheus 告警规则示例
+groups:
+ - name: error-budget
+ rules:
+ - alert: ErrorBudgetBurnRateHigh
+ expr: |
+ sum(rate(http_requests_total{status=~"5.."}[1h])) /
+ sum(rate(http_requests_total[1h])) > 0.001
+ for: 1h
+ labels:
+ severity: warning
+ budget_phase: yellow
+ annotations:
+ summary: "错误预算消耗加速"
+ message: "当前错误率 {{ $value }}% > SLO 阈值 0.1%"
+
+ - alert: ErrorBudgetExhausted
+ expr: |
+ (sum(rate(http_requests_total{status=~"5.."}[24h])) /
+ sum(rate(http_requests_total[24h]))) >= 0.001
+ labels:
+ severity: critical
+ budget_phase: red
+ annotations:
+ summary: "错误预算已耗尽!"
+ message: "本月 SLO 已破线,冻结非紧急变更"
+```
+
+## SRE 心法
+
+1. **用户视角定义 SLO** — 不是"API P99 < 200ms",而是"用户在正常网络下加载页面 < 2s"
+2. **错误预算用完 = 停止功能开发** — 全力修 bug、加稳定性
+3. **Blameless Postmortem** — 不问"谁干的",问"流程哪里可以改进"
+4. **自动化一切重复劳动** — 手动操作一定会出错
+5. **接受一定程度的失败** — 在可控范围内快速迭代,比追求完美更重要
+
+## Blameless Postmortem 模板
+
+| 字段 | 填写内容 |
+|------|---------|
+| **事件名称** | `2026-05-05 支付服务超时事故` |
+| **影响范围** | 约 15% 的支付请求失败,持续 23 分钟 |
+| **发现时间** | 14:32 (On-Call 接到告警) |
+| **恢复时间** | 14:55 (回滚后确认恢复) |
+| **根本原因** | 某次变更后支付网关的连接池大小从 50 降到 10 |
+| **时间线** | 14:00 发布 v1.2.3 → 14:30 错误率开始升高 → 14:32 收到告警 → 14:35 开始排查 → 14:45 定位根因 → 14:50 回滚 → 14:55 完全恢复 |
+| **改进行动** | ① 连接池参数变动必须经过压测验证;② 监控中补充连接池活跃数指标 |
+| **跟进人** | @zhangsan (行动 ①)、@lisi (行动 ②) |
+
+## SRE Metrics 看板
+
+除了 SLO,SRE 还需要关注以下运营指标:
+
+| 指标 | 说明 | 目标 |
+|------|------|------|
+| **MTTR** | Mean Time To Recovery | 核心服务 < 30min |
+| **Change Failure Rate** | 变更导致故障的比例 | < 5% |
+| **Lead Time for Changes** | 代码提交到上线的时间 | < 2h |
+| **Deployment Frequency** | 日均部署次数 | > 5 (大规模团队) |
+
+> [!tip] DORA Metrics
+>
+> Google 提出的四大 DevOps 指标,广泛用于评估工程效能:
+> - **部署频率** — 交付速度
+> - **变更前置时间** — 从代码提交到生产部署需要多久
+> - **变更失败率** — 多少部署导致了故障或回滚
+> - **MTTR** — 恢复服务的平均时间
+
+## 关联笔记
+
+- [[04-可观测性/告警管理/README]] — SLO/Error Budget 与告警体系的联动
+- [[05-部署运维/Kubernetes/README]] — K8s HPA 弹性伸缩支撑 SLO 保障
+- [[05-部署运维/CI-CD与GitOps/README]] — GitOps 支持安全的持续交付
diff --git a/hzh/MS/05-部署运维/容器化/README.md b/hzh/MS/05-部署运维/容器化/README.md
new file mode 100644
index 0000000..f94053c
--- /dev/null
+++ b/hzh/MS/05-部署运维/容器化/README.md
@@ -0,0 +1,155 @@
+---
+tags: [microservice, docker, container, image-optimization]
+create time: 2026-05-05
+---
+
+# 容器化
+
+## 概述
+
+Docker 容器是微服务交付的标准单元。它解决了"在我机器上是好的"这个经典问题——**开发、测试、生产使用完全一致的运行时环境**。
+
+```mermaid
+graph TB
+ CODE["源代码"] --> BUILD["CI 构建镜像"]
+ BUILD --> REGISTRY["镜像仓库
Harbor / ECR / ACR"]
+ REGISTRY --> K8s["Kubernetes 部署"]
+
+ style BUILD fill:#e3f2fd
+ style REGISTRY fill:#fff3e0
+ style K8s fill:#e8f5e9
+```
+
+## Dockerfile 最佳实践
+
+### Go 多阶段构建(推荐)
+
+```dockerfile
+# ========== 阶段 1: 构建 ==========
+FROM golang:1.22-alpine AS builder
+
+RUN apk --no-cache add git ca-certificates
+
+WORKDIR /app
+COPY go.mod go.sum ./
+RUN go mod download
+
+COPY . .
+ARG LDFLAGS="-s -w -extldflags '-static'"
+RUN CGO_ENABLED=0 GOOS=linux go build -ldflags "$LDFLAGS" -o server .
+
+# ========== 阶段 2: 运行时 ==========
+FROM alpine:latest
+
+RUN apk --no-cache add ca-certificates tzdata && \
+ cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
+ echo "Asia/Shanghai" > /etc/timezone
+
+RUN addgroup -S appgroup && adduser -S appuser -G appgroup
+USER appuser
+
+WORKDIR /app
+COPY --from=builder /app/server .
+
+EXPOSE 8080
+
+HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
+ CMD wget -qO- http://localhost:8080/healthz || exit 1
+
+CMD ["./server"]
+```
+
+### 关键优化点
+
+| 优化项 | 方法 | 效果 |
+|--------|------|------|
+| **多阶段构建** | 编译和运行分离 | 镜像从 800MB → 15MB |
+| **alpine 基础镜像** | 替代 debian/ubuntu | 减小体积 |
+| **非 root 运行** | `USER appuser` | 安全合规 |
+| **静态链接** | `CGO_ENABLED=0` | 不依赖系统库 |
+| **layer cache** | `go.mod` 先 COPY | CI 加速构建 |
+| **健康检查** | HEALTHCHECK 指令 | K8s 原生支持 |
+
+### `.dockerignore`
+
+```
+.git
+.gitignore
+*.md
+vendor/
+tests/
+*.log
+.DS_Store
+.idea/
+.vscode/
+```
+
+> [!tip] 为什么 .dockerignore 很重要?
+>
+> 如果不排除 `.git` 目录,整个版本历史都会被打包进镜像(增加数百 MB)。如果排除不当,可能遗漏必要的配置文件。
+
+## 镜像安全
+
+```mermaid
+flowchart LR
+ Scan["镜像扫描 (Trivy/Snyk)"] --> Clean{"漏洞等级?"}
+
+ Clean -- "CRITICAL/HIGH" --> Block["❌ 阻止推送"]
+ Clean -- "MEDIUM" --> Review["⚠️ 人工审核"]
+ Clean -- "LOW/INFO" --> Allow["✅ 允许推送"]
+
+ style Block fill:#ffebee
+ style Review fill:#fff3e0
+ style Allow fill:#e8f5e9
+```
+
+### 安全检查清单
+
+- [ ] 不使用 `latest` tag(永远用具体版本号)
+- [ ] 不安装不必要的软件包(`apk del --purge .build-deps`)
+- [ ] 定期更新基础镜像(修复 CVE)
+- [ ] 使用非 root 用户运行
+- [ ] 镜像不包含密钥、密码、私钥
+- [ ] 使用最小基础镜像(scratch / distroless)
+
+### Distroless 镜像
+
+Google 推出的**无 shell、无包管理器**的极简运行时镜像:
+
+```dockerfile
+# 最极致的精简
+FROM gcr.io/distroless/static-debian12
+COPY --from=builder /app/server .
+USER nonroot
+CMD ["./server"]
+```
+
+> ⚠️ 注意:distroless 镜像没有 shell (`/bin/sh`),调试时需要额外工具(如 debug 镜像或 `kubectl exec` 到 sidecar)。
+
+## 镜像仓库管理
+
+```mermaid
+flowchart LR
+ Dev["开发者本地"] -->|"docker push"| DEV_REPO["dev 仓库
v1.2.3-dev"]
+
+ Staging["Staging 验证"] -->|"通过"`PROD_REPO["prod 仓库
v1.2.3"]
+
+ K8s["K8s Cluster"] -->|"pull"| PROD_REPO
+
+ PR["PR Merge"] --> Tag["打标签 v1.2.3"]
+ Tag --> ProdRepoMove["移动到 prod 仓库"]
+
+ style DEV_REPO fill:#fff3e0
+ style PROD_REPO fill:#e8f5e9
+```
+
+| 仓库方案 | 特点 | 适用场景 |
+|---------|------|---------|
+| **Harbor** | 自托管,RBAC + 扫描 | 国内企业首选 |
+| **ECR / ACR / GCR** | 云厂商托管 | 全云环境 |
+| **Docker Hub** | 公共免费 | 开源项目 |
+
+## 关联笔记
+
+- [[05-部署运维/Kubernetes/README]] — K8s 以 Pod 为部署单元,镜像来自 Docker
+- [[05-部署运维/CI-CD与GitOps/README]] — CI/CD 流水线中的镜像构建环节
diff --git a/hzh/MS/README.md b/hzh/MS/README.md
index 156f4b2..c4c3155 100644
--- a/hzh/MS/README.md
+++ b/hzh/MS/README.md
@@ -7,7 +7,7 @@ create time: 2026-04-29 12:00
## 概述
-本目录系统整理微服务架构的核心知识点。围绕 **5 个核心主题**,由浅入深地覆盖从概念理解到工程实践的关键路径。
+本目录系统整理微服务架构的核心知识点。围绕 **5 个核心主题**,由浅入深地覆盖从概念理解到工程实践的关键路径。每个主题下进一步拆分为多个专题文档。
## 知识体系
@@ -18,17 +18,63 @@ graph LR
B --> D["04 可观测性"]
C --> E["05 部署运维"]
D --> E
+
+ style A fill:#e3f2fd
+ style B fill:#fff3e0
+ style C fill:#fce4ec
+ style D fill:#e8f5e9
+ style E fill:#f3e5f5
```
-| # | 主题 | 核心问题 |
-|---|------|----------|
-| 1 | [[01-基础概念]] | 什么是微服务?单体 vs 微服务的权衡是什么? |
-| 2 | [[02-服务治理]] | 服务如何发现彼此?如何通信?失败怎么处理? |
-| 3 | [[03-数据一致性]] | 每个服务拥有独立数据库,跨服务数据一致性怎么保证? |
-| 4 | [[04-可观测性]] | 请求穿越多个服务后,如何追踪、监控和排查问题? |
-| 5 | [[05-部署运维]] | 上百个服务如何容器化编排、灰度发布、弹性伸缩? |
+## 核心主题
-### 学习建议
+### 1. [[01-基础概念]] — 什么是微服务?
+
+微服务的核心定义、DDD 限界上下文拆分原则、单体 vs 微服务的权衡。
+
+> [!tip] 理论基础篇
+> 这是整个系列的起点,建议在动手之前先通读。
+
+### 2. [[02-服务治理]] — 服务如何被发现和治理?
+
+| 子主题 | 核心内容 |
+|--------|---------|
+| [[02-服务治理/服务发现/README]] | Nacos / Consul / K8s Service,客户端 vs 服务端发现模式 |
+| [[02-服务治理/API网关/README]] | 统一入口的职责边界、路由策略、插件体系 |
+| [[02-服务治理/服务间通信/README]] | gRPC vs REST,同步 vs 异步组合拳 |
+| [[02-服务治理/容错模式/README]] | 超时 / 重试 / 熔断 / 限流 / 舱壁隔离 / 降级 |
+| [[02-服务治理/配置管理/README]] | Nacos Config / Apollo,动态刷新与版本管理 |
+| [[02-服务治理/分布式追踪/README]] | OpenTelemetry,trace/span 概念,采样策略 |
+| [[02-服务治理/流量治理/README]] | 灰度发布策略,蓝绿 vs 金丝雀,Istio VirtualService |
+| [[02-服务治理/安全机制/README]] | mTLS, JWT, RBAC/ABAC, 输入防护 |
+
+### 3. [[03-数据一致性]] — 跨服务数据一致性怎么保证?
+
+| 子主题 | 核心内容 |
+|--------|---------|
+| [[03-数据一致性/数据库拆分/README]] | 垂直拆分 / 水平分片,ShardingSphere,跨库查询方案 |
+| [[03-数据一致性/分布式事务/README]] | Outbox 模式,Saga,TCC,AT 模式,幂等设计 |
+| [[03-数据一致性/ID生成/README]] | Snowflake, UUID v7, 号段模式 |
+
+### 4. [[04-可观测性]] — 请求穿越多个服务后如何排查问题?
+
+| 子主题 | 核心内容 |
+|--------|---------|
+| [[04-可观测性/Metrics监控/README]] | Prometheus, RED/USE 方法, Counter/Gauge/Histogram |
+| [[04-可观测性/日志系统/README]] | JSON 结构化日志, ELK vs Loki, 采集管线, 采样策略 |
+| [[04-可观测性/链路追踪/README]] | OpenTelemetry, W3C Trace Context, 上下文传播, 采样 |
+| [[04-可观测性/告警管理/README]] | SLO/Error Budget 告警, 分级降噪, On-Call 最佳实践 |
+
+### 5. [[05-部署运维]] — 上百个服务如何容器化编排与发布?
+
+| 子主题 | 核心内容 |
+|--------|---------|
+| [[05-部署运维/容器化/README]] | Dockerfile 最佳实践, 镜像安全, distroless |
+| [[05-部署运维/Kubernetes/README]] | Pod/Deployment/Service/Ingress, Probe, HPA, 资源配置 |
+| [[05-部署运维/CI-CD与GitOps/README]] | GitHub Actions Pipeline, GitOps (ArgoCD), Helm |
+| [[05-部署运维/SRE实践/README]] | SLI/SLO/SLA, Error Budget, Blameless Postmortem, DORA Metrics |
+
+## 学习建议
> [!tip] 学习路径
> 按编号顺序阅读。第 1 篇是理论基础,后面 4 篇在实践中高度耦合,可以按需跳读。
@@ -36,6 +82,6 @@ graph LR
> [!question] 带着问题读
> 每篇文章都设计了启发式问题。先自己想一遍答案,再看文档,效果更好。
-### 关联笔记
+## 关联笔记
-- [[API 设计原则]] — API Gateway 的设计与 REST/gRPC 选型
+- [[hzh/MS/API 设计原则]] — API Gateway 的设计与 REST/gRPC 选型