系统一多,为什么这么难查

单体时代排查问题很简单:一个进程,一份日志,一条堆栈基本就能说清发生了什么。等系统拆成十几个服务、调用链跨了三四跳,同样的报错可能来自上游、中间件、数据库,甚至一次超时重试。

可观测性要解决的就是这件事:系统内部的状态,能不能从外部推出来。它的三根支柱各管一段——日志记录细节、指标反映趋势、链路追踪还原一次请求的完整路径。

监控回答「系统挂了没有」,可观测性回答「为什么挂、卡在哪一步」。
三根支柱各看什么
  • 日志某一次事件的具体细节。
  • 指标一段时间里的数字变化。
  • 追踪一次请求跨服务的完整路径。
可观测性示意:蓝色渐变背景左侧发光服务节点方块,向右延伸出三条平行发光数据流横带,上方细长日志条带、中间圆环仪表盘、下方链路追踪树状连线,节点间有流动光点,扁平科技插画
一条请求穿过多个服务时,日志、指标、追踪各留下一条线索。

日志:结构化的基础

日志是排查的第一现场。可观测性对日志的第一个要求是结构化:别把关键信息拼在字符串里,而是用键值对输出,机器才好在海量日志里检索和聚合。

# 不要这样打日志
log.info("用户 " + userId + " 下单失败,原因是 " + reason)
# 要这样打日志:字段是字段,值归值
log.info({"event":"order_failed","user_id":12345,"reason":"stock_insufficient","cost_ms":312})

结构化之后,还要带上请求标识、时间、服务名、环境等公共字段,让同一次请求的日志能被捞出来排成一行。

指标:用数字看趋势

日志太多没法逐条看,指标负责把系统状态压缩成数字:每秒请求量、错误率、延迟分位、队列长度。看到错误率爬坡,再去查日志,方向就有了。

方法关注对象典型指标
RED服务请求请求速率、错误率、延迟
USE基础设施资源使用率、饱和度、错误

RED 看用户体验,USE 看资源是否顶到天花板,两套一起用,基本能覆盖服务层和基础设施层。

链路追踪:一次请求走全链路

指标说「下单接口变慢了」,可它慢在网关、订单服务、库存服务还是数据库?链路追踪给每次请求一个全局标识,沿途每个服务都记录自己这段的耗时,最后拼出完整路径。

# 一个 trace 由多个 span 组成
trace_id = "a1b2c3"
span_a = {service:"api_gateway",  span:"POST /order",  cost_ms:320}
span_b = {service:"order_svc",    span:"create_order", cost_ms:180}
span_c = {service:"inventory_svc",span:"check_stock",  cost_ms:95, error:"timeout_retry"}
# 从 span_b 的 180 毫秒里,能看到大部分时间花在了调库存上

实现的关键是上下文传递:调用下游时把追踪标识塞进请求头,下游再透传给更下游,一整条链才能对上。