微服务可观测性三支柱整合
可观测性 = 从外部输出推断内部状态的能力。三大支柱:指标(Metrics)、链路(Tracing)、日志(Logging)。单看任何一个都不够,整合起来才能快速定位问题。本文讲清三支柱的关系与一体化落地。
三支柱是什么
三大信号
| 支柱 | 回答的问题 | 例子 |
|---|---|---|
| Metrics(指标) | 系统现在怎么样? | QPS、错误率、响应时间、CPU |
| Tracing(链路) | 一次请求经历了什么? | traceId、各服务耗时 |
| Logging(日志) | 具体发生了什么细节? | 异常堆栈、业务上下文 |
三者关系
Metrics:全局视角(宏观)—— 发现"有问题"
│ 下钻
Tracing:单请求视角(中观)—— 定位"哪一段"
│ 下钻
Logging:单点细节(微观)—— 查明"为什么"发现:指标告警(QPS 突降)
定位:链路追踪(某服务超时)
排查:日志检索(具体异常堆栈)Metrics:指标采集
指标类型
| 类型 | 说明 | 例子 |
|---|---|---|
| Counter(计数器) | 只增不减 | 请求总数、错误总数 |
| Gauge(仪表盘) | 可增可减 | 当前连接数、内存使用 |
| Histogram(直方图) | 分布统计 | 响应时间分布、请求大小 |
| Summary(摘要) | 分位数 | p50、p95、p99 |
Micrometer:指标门面
Spring Boot 通过 Micrometer 统一指标 API:
应用代码 → Micrometer → 注册表 → 各种监控系统(Prometheus 等)java
// 引入 micrometer-registry-prometheus 后:
// 应用暴露 /actuator/prometheus 端点 → Prometheus 抓取内置指标
Spring Boot Actuator 自动暴露的指标:
jvm.*(内存、GC、线程)
http.server.requests(HTTP 请求)
tomcat.*(线程池、连接)
process.*(CPU、内存)
hikaricp.*(连接池)
......自定义指标埋点
java
// 计数器
@RestController
public class OrderController {
private final Counter orderCounter;
public OrderController(MeterRegistry registry) {
this.orderCounter = Counter.builder("order.created.total")
.description("创建订单总数")
.tag("env", "prod")
.register(registry);
}
@PostMapping("/order")
public Order createOrder(@RequestBody OrderRequest req) {
orderCounter.increment(); // 计数
return orderService.create(req);
}
}java
// 直方图(响应时间分布)
@Service
public class OrderService {
private final Timer orderTimer;
public OrderService(MeterRegistry registry) {
this.orderTimer = Timer.builder("order.create.time")
.publishPercentiles(0.5, 0.95, 0.99) // p50/p95/p99
.register(registry);
}
public Order create(OrderRequest req) {
return orderTimer.record(() -> doCreate(req)); // 计时
}
}Prometheus 抓取
yaml
spring:
application:
name: order-service
prometheus:
metrics:
export:
enabled: true
management:
endpoints:
web:
exposure:
include: prometheus,health,metricsPrometheus 配置抓取:
scrape_configs:
- job_name: 'order-service'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['order-service:8080']Tracing:链路追踪接入
统一链路
日志、指标、追踪都要有 traceId 才能关联
Spring Cloud 中:
micrometer-tracing + OTel 导出器(Zipkin/SkyWalking/Otlp)yaml
spring:
application:
name: order-service
tracing:
sampling:
probability: 1.0 # 采样率
zipkin:
base-url: http://zipkin:9411
management:
tracing:
enabled: true自定义 Span 埋点
java
@Service
public class OrderService {
@Autowired
private Tracer tracer; // micrometer-tracing Tracer
public Order create(OrderRequest req) {
Span span = tracer.nextSpan().name("order.create")
.start();
try (Tracer.SpanInScope ws = tracer.withSpan(span)) {
span.tag("order.id", req.getOrderId()); // 附加标签
return doCreate(req);
} finally {
span.end();
}
}
}Logging:日志关联 traceId
自动注入
接入 micrometer-tracing 后,日志自动带 traceId/spanId:
日志输出自动包含 [traceId=abc123, spanId=def456]标准格式:
2026-08-03 10:00:01.234 INFO [order-service,abc123,def456] 查询订单: 1001
└traceId─┘ └spanId─┘日志检索
按 traceId 检索同一请求的所有日志(跨服务):
查日志平台:traceId=abc123
→ 网关、订单、库存、支付各服务日志全部命中结构化日志
json
{
"timestamp": "2026-08-03T10:00:01.234Z",
"level": "ERROR",
"service": "order-service",
"traceId": "abc123",
"spanId": "def456",
"message": "扣减库存失败",
"orderId": 1001
}一体化方案:Prometheus + Grafana
整体架构
应用(Micrometer 指标)
│ /actuator/prometheus 抓取
▼
Prometheus(时序数据库 + 采集)
│ PromQL 查询
▼
Grafana(可视化大盘 + 告警)
│
├─ 指标大盘(Dashboard)
├─ 告警规则(Alerting)
└─ 关联入口(跳转到日志/追踪)Grafana 大盘设计
核心 Dashboard 面板:
1. 总览面板:服务健康状态、请求量、错误率
2. 性能面板:QPS、P99、响应时间热力图
3. 资源面板:CPU、内存、GC、线程池
4. 业务面板:订单量、成功率(自定义指标)常用 PromQL:
请求量:sum(rate(http_server_requests_seconds_count[1m]))
P99: histogram_quantile(0.99, sum(rate(http_server_requests_seconds_bucket[5m])) by (le))
错误率:sum(rate(http_server_requests_seconds_count{status=~"5.."}[1m])) /
sum(rate(http_server_requests_seconds_count[1m]))关联三大信号
Grafana → Loki(日志)
Grafana → Tempo / Zipkin(追踪)
Prometheus → 告警 → 通知
统一标签:service / traceId 作为关联键告警体系
告警流程
Prometheus 告警规则
│ 触发
▼
Alertmanager
│ 分组/抑制/静默
▼
通知渠道(邮件/钉钉/企业微信/Slack)
│
▼
值班响应 → 大盘下钻 → 链路/日志定位告警规则示例
yaml
groups:
- name: service-alerts
rules:
# 服务错误率超过 5%
- alert: HighErrorRate
expr: |
sum(rate(http_server_requests_seconds_count{status=~"5.."}[5m]))
/ sum(rate(http_server_requests_seconds_count[5m])) > 0.05
for: 2m
labels:
severity: critical
annotations:
summary: "{{ $labels.service }} 错误率过高"
# P99 超过 1s
- alert: HighLatency
expr: |
histogram_quantile(0.99,
sum(rate(http_server_requests_seconds_bucket[5m])) by (le, service)) > 1
for: 3m
labels:
severity: warning告警设计原则
1. 可操作性:每条告警明确影响与处理步骤
2. 分级:critical(立即响应)/ warning(工作时间处理)
3. 抑制重复:相同告警聚合、去重
4. 避免风暴:告警疲劳 → 提高阈值或静默
5. 黄金指标优先:错误率、延迟、吞吐、饱和度三支柱联动排查流程
实战场景
场景:订单服务 P99 突增,用户反馈下单慢
排查流程:
1. Grafana 大盘:确认 P99 升高(Metrics)
2. 下钻服务维度:哪个服务/端点慢(Metrics)
3. 打开链路追踪:慢请求的 trace(Tracing)
→ 发现"扣库存"调用耗时 2s
4. 打开该 traceId 的日志(Logging)
→ 发现 Redis 连接池等待日志
5. 结论:Redis 连接池耗尽 → 扩容/调参关联键设计
统一关联字段:
service:服务名(所有信号都带)
traceId:一次请求(日志、追踪关联)
时间窗口:指标 + 日志按时间对齐落地检查清单
1. 指标:Micrometer + Prometheus + Grafana 大盘 ✅
2. 追踪:micrometer-tracing + Zipkin/SkyWalking ✅
3. 日志:结构化 + traceId 注入 + Loki/ELK ✅
4. 告警:黄金指标 + 分级 + 通知渠道 ✅
5. 联动:大盘 → 链路 → 日志可下钻 ✅
6. 自定义埋点:核心业务指标(订单量、成功率)✅常见问题
- 指标太多存储爆炸? 只保留核心指标,降采样,控制保留期。
- traceId 没进日志? 检查 micrometer-tracing 依赖与日志 pattern 配置。
- 告警风暴? 分组抑制 + 告警分级 + 阈值调优。
- 三支柱数据对不上? 统一时间同步(NTP)与关联字段(service/traceId)。