4.1 监控与日志 本节摘要:可观测性由三大支柱构成——指标负责"整体是否正常"的快速判断,日志负责"当时发生了什么"的细节还原,链路追踪负责"这次请求经过了哪里"的路径定位。本节讲三大支柱的分工与配合、黄金指标与告警分级的设计,并完整还原一次从凌晨告警到根因定位的真实排查,展示三者如何在十五分钟内协同收敛问题。 学习目标 说出三大可观测性支柱各自的形态、成本与适用问题 用四大黄金信号为服务建立基础监控 设计三档告警分级并守住"每条告警值得被看"的底线 演练"指标→追踪→日志"的标准排查路径 一、行车记录仪:为什么需要三种记录 发布之后的系统是个黑盒吗?取决于你装了什么记录仪。
本节摘要:可观测性由三大支柱构成——指标负责"整体是否正常"的快速判断,日志负责"当时发生了什么"的细节还原,链路追踪负责"这次请求经过了哪里"的路径定位。本节讲三大支柱的分工与配合、黄金指标与告警分级的设计,并完整还原一次从凌晨告警到根因定位的真实排查,展示三者如何在十五分钟内协同收敛问题。
发布之后的系统是个黑盒吗?取决于你装了什么记录仪。只装了"能否 ping 通"的存活检查,你只能知道它死没死,死了为什么、什么时候开始不正常、影响了多少用户,一概不知。而一个可观测的系统,应当能回答三类问题。
整体健康吗?——指标(Metrics)回答。指标是随时间采集的聚合数值:每秒请求数、错误率、延迟分位数、内存用量。它体积小、可长期存储、适合画曲线和触发告警,是"第一发现者"。
当时发生了什么?——日志(Logs)回答。日志是离散的事件记录:一次下单失败、一次重试、一次降级触发。它信息最丰富但体积最大,是"现场还原者"。
这次请求走了哪条路?——链路追踪(Traces)回答。在一个请求穿过网关、订单服务、库存服务、三个数据库调用的分布式系统里,追踪给每次请求发一张"行程单",记录每一站的耗时与状态,是"路径定位者"。
三者的配合不是并列,是有序的接力:指标发现异常(错误率在 02:14 开始爬升)→ 追踪缩小范围(该时段的慢请求都卡在库存服务的数据库调用)→ 日志还原现场(库存服务日志显示连接池耗尽等待)。这个接力就是分布式系统排查的标准路径。

新服务上线,监控从哪建?经验答案是四个黄金信号,它们覆盖了"用户感受到的几乎所有异常"。
延迟——请求处理耗时。关键细节:要分别统计成功与失败请求的延迟。失败请求常常"快速失败",混在一起统计会让延迟曲线在故障时反而下降,造成误判。流量——每秒请求数。异常的流量形态(陡增、陡降)本身即是信号:陡增可能是促销或攻击,陡降可能是上游故障。错误——失败请求比例,含显式错误(500)与隐式错误(返回 200 但内容错误)。饱和度——资源占用率,如连接池使用率、队列积压、CPU 与内存。饱和度是领先指标:错误率上升之前,饱和度往往已经爬高——它是"故障发生前的那点余量"。
采集端一行代码的接入示例:
# 服务暴露指标的标准做法(文本协议示例) # HELP order_request_seconds 订单接口耗时分布 # TYPE order_request_seconds histogram order_request_seconds_bucket{path="/api/orders",status="200",le="0.1"} 84213 order_request_seconds_bucket{path="/api/orders",status="200",le="1.0"} 91077 order_request_seconds_bucket{path="/api/orders",status="500",le="0.05"} 317 # 注: 分位数由监控系统从直方图聚合,避免跨实例求平均的统计陷阱
一个统计陷阱值得点破:平均延迟是谎言。若 1% 的请求耗时 10 秒、其余 100 毫秒,平均值只有 200 毫秒,看起来一切正常,而那 1% 的用户体验已是灾难。始终看分位数(p95、p99),而且分位数要在单实例统计后再聚合,不能对各实例的平均值再求平均。
监控的失败往往不是"没数据",而是"数据太多、告警太滥"。凌晨三点被十几条不痛不痒的告警轰炸的值班员,会发展出"告警免疫"——真正要命的那条到来时也在被忽略之列。治理靠三档分级。
P1 紧急(立即处理,电话唤醒):核心交易错误率超阈值持续五分钟、主数据库不可用、证书即将过期。判据是"用户利益正在受损且在扩大"。P2 重要(一小时内处理,即时消息通知):非核心服务异常、饱和度持续超 85%、金丝雀指标越界。P3 提示(工作时间处理,汇总日报):磁盘用量 70%、个别批处理延迟。判据是"风险在积累但尚未兑现"。
配套三条纪律:每条告警必须有明确的责任人(告警到"订单服务值班"而不是"运维群");必须有可执行的动作(收到后做什么是有写的,"可能有问题"类告警一律降级或删除);定期做告警复盘——统计每条告警的触发次数与"看后行动率",行动率低的裁掉。告警体系和测试套件一样需要持续瘦身。
# 告警规则示例:两级黄金信号守卫 groups: - name: order-service rules: - alert: 订单错误率超标 expr: | sum(rate(order_requests_total{status=~"5.."}[5m])) / sum(rate(order_requests_total[5m])) > 0.01 for: 5m # 持续 5 分钟才触发,滤掉毛刺 labels: {severity: P1} annotations: summary: "订单服务 5xx 比例超过 1%" runbook: "先查最近 1 小时变更;执行回滚预案" - alert: 订单连接池饱和 expr: db_pool_used / db_pool_max > 0.85 for: 15m labels: {severity: P2} annotations: summary: "连接池使用率持续超 85%" runbook: "检查慢查询与池参数;必要时扩容只读副本"
日志的现代化改造核心是一句话:从"写给人看的散文"变成"写给机器查的结构化记录"。
# 旧式散文日志: 人能读, 机器难检索 [2026-08-12 02:14:37] WARN 订单 88421 扣库存失败, 已重试 3 次 # 新式结构化日志: 字段可索引, 检索秒级 {"ts":"2026-08-12T02:14:37.412Z","level":"WARN","svc":"order", "trace_id":"a4f9c2e1","order_id":88421,"event":"stock_deduct_retry", "attempt":3,"err":"pool_timeout","latency_ms":4021}
结构化日志里的 trace_id 是关键一环——它把日志与链路追踪缝在一起:从异常指标点进一条慢请求的追踪,再一键跳到该请求在各服务产生的全部日志。三大支柱不是三套孤岛系统,靠这个 ID 互相打通。
日志的分级采集也是省钱之道:正常 INFO 日志采样存储,WARN 与 ERROR 全量保留,含敏感字段(手机号、令牌)的日志在采集端脱敏。日志的"量"很容易失控——一个中型服务一天可产生几百 GB,保留策略(错误 30 天、普通 7 天)要在搭建时就定好。
把本节内容串成一次真实演练。02:14,值班工程师手机响起(P1:订单错误率超标)。她不急着猜原因,按固定路径走。
第一步,看指标大盘确认影响面。错误率 6%,集中在订单创建接口;流量正常(不是攻击);数据库 CPU 正常但连接数曲线在 02:11 有一级跳升。第二步,查最近变更(手册第一条 runbook 动作)。部署系统显示 01:50 有一次版本发布(连接池参数变更),时间与异常起点接近——嫌疑最大,但先继续取证。第三步,拉一条失败请求的追踪。调用树显示订单服务的库存调用段耗时 3.8 秒并以超时告终。第四步,用 trace_id 查日志。库存服务日志出现成片的 pool_timeout,等待连接的队列积压。第五步,止血。根因证据已足够指向 01:50 的版本,执行标准回滚(第 3 章演练过的动作),02:21 错误率回落。第六步,收尾。故障时长 7 分钟;事后复盘发现参数变更虽过了评审,但测试环境的并发量不足以暴露池上限配置错误,改进项是"连接池类变更需在预发跑压力档位的回归"——回流为流水线关卡。
七分钟止血的背后,是三支柱的接力、一条 runbook、一次演练过的回滚,和一条"先止血再查因"的纪律。
💡 关键直觉:可观测性建设的成功标准不是图表有多漂亮,而是"从告警响起到根因确认"的时间在分钟级。每多一次需要"凭经验猜测"的环节,恢复时间就翻一倍。