4. 监控体系搭建:三大支柱
监控体系,说白了就是SLA保障的“眼睛”。没有它,故障排查就像蒙着眼睛走夜路。我个人习惯把监控拆成三个维度:指标、日志、链路追踪。业内管这叫“三大支柱”,我觉得挺贴切。
你想想看,一个系统出问题了,你总得知道“哪里出了问题”、“为什么出问题”、“影响范围有多大”吧?指标告诉你“哪里”,日志告诉你“为什么”,链路追踪告诉你“影响范围”。三者缺一不可。
4.1 指标监控(Metrics)—— 先知道“坏了”
指标监控是基础。它回答的是“系统健康吗?”这个核心问题。我见过不少团队,一上来就搞链路追踪,结果基础指标都没配全,出事了连CPU打满都不知道。
指标监控的核心是“黄金信号”。Google SRE 那本书里提过四个:延迟、流量、错误、饱和度。我个人习惯再加一个“资源水位”,一共五个维度。
| 维度 | 说明 | 常见指标 |
|---|---|---|
| 延迟 | 请求处理耗时 | P50/P95/P99 响应时间 |
| 流量 | 系统负载压力 | QPS、TPS、并发连接数 |
| 错误 | 请求失败率 | HTTP 5xx 率、超时率 |
| 饱和度 | 资源使用程度 | CPU/内存/磁盘使用率 |
| 资源水位 | 容量余量 | 连接池使用率、队列深度 |
举个例子,我曾经遇到一个数据同步任务,每天凌晨3点准时超时。查了半天,发现是凌晨有全量备份任务,把磁盘IO打满了。如果当时配了“磁盘IO饱和度”指标,一眼就能看出来。
4.2 日志监控(Logging)—— 搞清楚“为什么”
指标告诉你“坏了”,日志告诉你“为什么”。日志是故障排查的“黑匣子”。
日志监控有三大原则:结构化、集中化、可检索。我见过最坑的日志,就是那种纯文本、无格式、散落在各个服务器上的。出事了,你连 grep 都不知道从哪开始。
日志采集架构,我推荐用 Filebeat + Kafka + Logstash + Elasticsearch 这条链路。Filebeat 轻量,Kafka 做缓冲,Logstash 做解析,ES 做存储和检索。
# 一个标准的日志格式(JSON 结构化)
{
"timestamp": "2024-01-15T10:30:00.123Z",
"level": "ERROR",
"service": "data-sync-service",
"trace_id": "abc123def456",
"message": "数据写入HBase超时",
"stack_trace": "com.example.DataSyncException: ...",
"context": {
"table": "user_profile",
"row_key": "user_10001",
"retry_count": 3
}
}
你看,这种日志,在 Kibana 里一搜 trace_id,整个请求的上下文全出来了。排查效率能提升好几倍。
4.3 链路追踪(Tracing)—— 定位“在哪坏了”
微服务架构下,一个请求可能经过十几个服务。指标和日志只能告诉你“某个服务有问题”,但链路追踪能告诉你“具体是哪个调用环节出了问题”。
链路追踪的核心是“Trace”和“Span”。一个 Trace 代表一次完整的请求,一个 Span 代表请求中的一个步骤。每个 Span 都记录了开始时间、结束时间、父 Span ID。
- Trace ID: 全局唯一,标识一次完整请求
- Span ID: 标识请求中的单个操作
- Parent Span ID: 标识父子关系,形成调用树
- Duration: 每个操作的耗时
我常用的链路追踪工具是 Jaeger。它和 OpenTelemetry 协议兼容,部署简单。你只需要在代码里埋点,把 Trace 信息透传下去就行。
// 伪代码:在服务间透传 Trace 信息
// 服务A 调用 服务B 时,在 HTTP Header 中传递
headers.put("traceparent", "00-${traceId}-${spanId}-01");
// 服务B 收到请求后,从 Header 中提取 Trace 信息
String traceparent = request.getHeader("traceparent");
// 解析 traceparent,创建新的 Span
Span span = tracer.buildSpan("serviceB.process")
.asChildOf(extractContext(traceparent))
.start();
我记得有一次,数据产品报表生成特别慢。指标看 CPU 和内存都正常,日志也没报错。最后靠链路追踪发现,是某个下游的 Redis 缓存查询,因为缓存穿透,每次都要查数据库,耗时从 2ms 变成了 200ms。如果没有链路追踪,这种问题根本定位不到。
4.4 三大支柱的关系
指标、日志、链路追踪,不是互相替代的关系,而是互补的。我画了一张图,帮你理解它们之间的关系。
你看这张图,从左到右,从指标到日志再到链路追踪,是一个层层递进的关系。指标先报警,告诉你“出事了”;然后你去查日志,看看“为什么出事”;最后用链路追踪,定位“具体在哪出的事”。
4.5 实战:如何快速搭建
说了这么多理论,来点实际的。如果你从零开始搭建监控体系,我建议按这个步骤来:
- 第一步:确定核心指标 —— 先配好黄金信号,每个服务至少要有 QPS、错误率、P99 延迟、CPU/内存使用率。
- 第二步:统一日志格式 —— 所有服务输出 JSON 结构化日志,包含 trace_id、service、level、message 等字段。
- 第三步:部署链路追踪 —— 用 OpenTelemetry SDK 埋点,把 Trace 信息透传到所有下游服务。
- 第四步:建立关联 —— 在日志和指标中带上 trace_id,实现“指标 → 日志 → 链路”的一键跳转。
- 第五步:配置告警 —— 基于指标设置告警规则,告警信息中附带日志查询链接和链路追踪链接。
好了,三大支柱就讲到这里。记住一句话:指标是“眼睛”,日志是“耳朵”,链路追踪是“手”。三者配合,才能把故障排查这件事做好。