This commit is contained in:
2026-05-24 11:42:38 +08:00
commit 30d312ac35
521 changed files with 146481 additions and 0 deletions
+160
View File
@@ -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{"这个值是<br/>只增不减的吗?"}
Q -- "是" --> C["Counter<br/>请求数、错误数、订单量"]
Q -- "否" --> G["Gauge<br/>在线用户数、队列长度、内存使用量"]
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-可观测性/04-告警管理]] — Metrics 是告警的基础数据来源
- [[04-可观测性/03-链路追踪]] — Tracing 与 Metrics 互补,定位具体故障
- [[05-部署运维/04-SRE实践]] — SLO 基于 Metrics 数据
+149
View File
@@ -0,0 +1,149 @@
---
tags: [microservice, logging, elk, loki, structured-logging]
create time: 2026-05-05
---
# 日志系统
## 概述
Logging 回答的问题是:**具体发生了什么?**——通过原始事件记录提供上下文。
在微服务架构中,所有服务的日志必须集中收集。散落在各台机器上的日志无法支撑有效的故障排查。
```mermaid
flowchart LR
APP[应用容器] -->|stdout/stderr| COLLECTOR[采集器<br/>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["采集器<br/>Filebeat / FluentBit"]
Collector --> Backend["存储后端<br/>Elasticsearch / Loki"]
Backend --> UI["查询面板<br/>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<br/>低成本、轻量"]
Q -- "是,复杂的全文搜索" --> ELK["✅ ELK<br/>功能强大"]
LOKI --> Check{"日日志量 > 1TB?"}
Check -- 是 --> ConsiderES["考虑混合架构<br/>高频用 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-可观测性/01-Metrics监控]] — Metrics + Logging = 完整的问题定位能力
- [[04-可观测性/03-链路追踪]] — trace_id 是日志与追踪的桥梁
- [[04-可观测性/04-告警管理]] — 日志可以触发基于模式的告警
+166
View File
@@ -0,0 +1,166 @@
---
tags: [microservice, tracing, opentelemetry, context-propagation]
create time: 2026-05-05
---
# 链路追踪
## 概述
Tracing 回答的问题是:**请求在哪一步慢了 / 失败了?**——通过完整的调用链定位瓶颈和故障。
一次请求在多个服务中的完整调用路径:
```mermaid
flowchart LR
RID["Request<br/>trace_id: abc-123"]
subgraph SPANS["调用链 (Trace)"]
direction TB
S1["Span #1<br/>API Gateway<br/>5ms"]
S2["Span #2<br/>Order Service<br/>70ms"]
S3["Span #3<br/>Payment RPC<br/>160ms"]
S4["Span #4<br/>Inventory RPC<br/>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-可观测性/01-Metrics监控]] — Tracing 与 Metrics 互补
- [[04-可观测性/02-日志系统]] — trace_id 串联日志和追踪
- [[04-可观测性/04-告警管理]] — 基于 Trace 数据的异常检测告警
+186
View File
@@ -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["冻结发布 ❄️<br/>专注稳定性修复"]
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["激进策略:<br/>保持常规告警阈值<br/>加快迭代节奏"]
BudgetLeft -- "10~50%" --> Moderate["保守策略:<br/>降低告警阈值<br/>收紧发布频率"]
BudgetLeft -- "< 10%" --> Emergency["紧急策略:<br/>所有非紧急告警暂停<br/>全员关注稳定性"]
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-可观测性/01-Metrics监控]] — Metrics 是告警的数据来源
- [[05-部署运维/04-SRE实践]] — SLO/Error Budget 的详细方法论
- [[02-服务治理/06-容错模式]] — 熔断器状态可以作为告警信号
+78
View File
@@ -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-可观测性/01-Metrics监控]] | 怎么量化系统的健康度?RED/USE 方法怎么用? |
| 2 | [[04-可观测性/02-日志系统]] | 日志怎么集中收集?结构化日志的最佳实践是什么? |
| 3 | [[04-可观测性/03-链路追踪]] | trace_id 如何贯穿跨服务调用链?OpenTelemetry 怎么用? |
| 4 | [[04-可观测性/04-告警管理]] | 如何设计告警避免疲劳?SLO/Error Budget 怎么做? |
### 为什么需要独立的"可观测性"体系?
```mermaid
flowchart LR
subgraph MONO["单体系统"]
S[Service] --> DB[(DB)]
LOG["同一份日志<br/>一目了然"]
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["问题:日志分散、链路断裂<br/>传统监控无法回答'这个请求经历了什么'"]
MICRO --> NOTE
```
> [!keypoint] 可观测性与监控的本质区别
>
> **监控系统**告诉你"出事了"(已知未知),**可观测性系统**让你去探究"为什么会出事"(未知未知)。
### 三大支柱
| 支柱 | 回答的问题 | 典型工具 |
|------|-----------|---------|
| **Metrics** | 系统现在健康吗?— 趋势、告警 | Prometheus + Grafana |
| **Logging** | 具体发生了什么?— 历史回溯 | ELK / Loki |
| **Tracing** | 请求在哪一步慢了/失败了?— 链路追踪 | Jaeger / Zipkin |
### 关联笔记
- [[02-服务治理]] — 熔断器可以触发告警,与监控系统联动
- [[05-部署运维/02-Kubernetes]] — K8s Liveness/Readiness Probe 是可观测性的基础
- [[hzh/MS/README.md]] — 完整微服务知识索引