面试知识库
进阶

可观测性三件套#

一句话答案#

可观测性三件套:Metrics(发现问题)→ Tracing(定位链路)→ Logging(确认根因),三者协同才能在微服务环境下快速排障。

核心要点

全景概览#

维度解决问题典型工具数据形态
Metrics”系统是不是有问题?“Prometheus + Grafana时序数值(Counter/Gauge/Histogram)
Logging”具体报了什么错?“ELK(Elasticsearch + Logstash + Kibana)结构化文本
Tracing”请求经过了哪些服务,哪里慢?“Jaeger / SkyWalking / Zipkin分布式调用链

1. Metrics —— 发现问题#

四种指标类型(Prometheus):

类型用途示例
Counter只增不减的累加值请求总数、错误总数
Gauge可增可减的瞬时值当前线程数、队列长度
Histogram分布统计(分桶)请求延迟分布(P50/P99)
Summary客户端计算分位数类似 Histogram,但在客户端算

核心监控指标(RED 方法):

  • Rate:请求速率(QPS)
  • Errors:错误率(5xx 比例)
  • Duration:延迟分布(P50/P99/P999)

告警规则示例:

# 5 分钟内错误率 > 5% 触发告警
- alert: HighErrorRate
  expr: rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) > 0.05
  for: 2m
yaml

2. Logging —— 确认根因#

结构化日志#

为什么用 JSON 而不是纯文本?

  • 纯文本:2026-05-25 10:30:00 ERROR OrderService - 创建订单失败: 库存不足
  • 结构化:
{
  "timestamp": "2026-05-25T10:30:00.123Z",
  "level": "ERROR",
  "service": "order-service",
  "traceId": "abc123def456",
  "spanId": "span789",
  "class": "OrderService",
  "method": "createOrder",
  "userId": 12345,
  "orderId": "ORD-20260525-001",
  "message": "创建订单失败",
  "reason": "库存不足",
  "skuId": "SKU-100"
}
json

结构化日志能被 ES 索引,支持按任意字段搜索和聚合。

TraceID 透传#

请求进入网关 → 生成 TraceID(如 UUID)
  → 放入 HTTP Header(X-Trace-Id)
  → 服务 A 取出放入 MDC(SLF4J)
  → 服务 A 调用服务 B 时透传 Header
  → 所有服务的日志都带同一个 TraceID
  → 在 ELK 中按 TraceID 搜索 → 一次请求的全链路日志
plaintext

Spring Boot 实现: Spring Cloud Sleuth / Micrometer Tracing 自动注入 TraceID。

日志级别规范#

级别用途示例
ERROR需要立即处理的错误数据库连接失败、支付失败
WARN异常但可自愈重试成功、降级生效
INFO关键业务节点订单创建成功、用户登录
DEBUG开发调试信息方法入参出参(生产关闭)

注意: 生产环境日志级别通常设 INFO,不要开 DEBUG——日志量会暴增。

ELK 架构#

应用日志 → Filebeat(采集) → Logstash(解析/过滤) → Elasticsearch(存储/索引) → Kibana(查询/可视化)
plaintext

3. Tracing —— 定位链路#

核心概念#

  • Trace:一次完整请求的调用链,由一个 TraceID 标识
  • Span:Trace 中的一个操作单元(如一次 RPC 调用、一次 DB 查询)
  • Parent-Child:Span 之间的父子关系构成调用树
Trace: abc123
├── Span 1: API Gateway (50ms)
│   ├── Span 2: Order Service (30ms)
│   │   ├── Span 3: MySQL Query (5ms)
│   │   └── Span 4: Redis Get (2ms)
│   └── Span 5: Inventory Service (15ms)
│       └── Span 6: MySQL Update (8ms)
plaintext

Jaeger vs SkyWalking#

维度JaegerSkyWalking
侵入性需要代码埋点(OpenTelemetry SDK)Java Agent 自动埋点,零代码侵入
语言支持多语言(Go/Java/Python)以 Java 为主,其他语言支持较弱
功能专注 TracingTracing + Metrics + Logging 一体化
适用多语言微服务Java 技术栈

三者协同排障流程#

1. Grafana 告警:订单服务 P99 延迟从 200ms 飙升到 2s

2. Jaeger/SkyWalking 查看慢 Trace:
   发现 Span "Redis Get" 从 2ms 变成 800ms

3. Kibana 搜索该 TraceID 的日志:
   发现 Redis 连接池满,等待获取连接

4. 根因:Redis 连接数配置过小 + 流量突增

5. 修复:调大连接池 + 加连接池监控指标
plaintext

日志敏感信息脱敏#

生产日志中不能出现

  • 用户密码、Token
  • 完整手机号、身份证号
  • 信用卡号

脱敏方式: 日志框架层做正则替换,或用 Logback 的自定义 Converter。

面试回答(2分钟版)

可观测性三件套是Metrics、Tracing和Logging,三者协同才能在微服务环境下快速定位问题。Metrics回答”系统是不是有问题”,用Prometheus+Grafana监控RED指标(请求速率、错误率、延迟分布),发现P99飙高了就知道有问题。Tracing回答”问题在哪个环节”,通过Jaeger或SkyWalking查看分布式调用链,一个Trace由多个Span组成,能精确看到哪个服务、哪个SQL慢了。Logging回答”具体错了什么”,在ELK中按TraceID搜索,拿到那一次请求经过所有服务的完整日志,确认根因。实际排障流程就是这三步闭环:Grafana告警触发→查Trace定位慢Span→搜日志确认根因→修复→补监控。关键实践:日志必须结构化JSON并透传TraceID,否则微服务环境下日志散落各处根本没法串联。

追问与易错

追问方向:

  • “Metrics 和 Tracing 有什么区别?”→ Metrics 是聚合数据(知道”慢了”),Tracing 是个体数据(知道”谁慢了”)
  • “日志量太大怎么办?”→ 采样(只记录 10% 的 Trace)+ 日志分级 + 冷热分离
  • “你项目中怎么做的监控?”→ 结合具体项目讲

易错点:

  • ❌ 只有 Metrics 没有 Tracing——知道系统慢但不知道慢在哪
  • ❌ 日志不带 TraceID——微服务环境下无法串联一次请求的完整日志
  • ❌ 所有日志都打 INFO——要么日志太少看不出问题,要么太多找不到重点