CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
可观测性入门/课时/遥测与 OpenTelemetry
RawBlame
课时目录12 节

可观测性入门

  1. 01可观测性三支柱
  2. 02指标与 SLI
  3. 03结构化日志
  4. 04分布式链路追踪
  5. 05插桩与埋点
  6. 06监控与告警
  7. 07遥测与 OpenTelemetry
  8. 08Spring 可观测性
  9. 09SLO 与错误预算
  10. 10仪表盘设计
  11. 11故障排查流程
  12. 12综合练习

遥测与 OpenTelemetry

telemetry、OTel SDK 概览。

35 分钟

遥测与 OpenTelemetry

这一课你将能做到

  1. 用自己的话解释 Telemetry,并对照 OTel 的 Traces / Metrics / Logs 三大 signal,说清每种信号解决什么问题
  2. 画出 SDK → Collector → Exporter/后端 的数据流,说明各层职责和判题系统怎么接入
  3. 解释「一套插桩、多种后端」如何降低迁移成本,并给出 Micrometer/旧 APM 与 OTel 的共存策略

为什么要学

过去 Zipkin、Jaeger、各云厂商 APM、Micrometer 各有 API,换后端常等于换埋点——团队被绑死在某个厂商,迁移成本极高。OpenTelemetry(OTel) 是 CNCF 下的开放标准:统一 API/SDK 与传播语义(W3C trace context),后端可换(Prometheus、Jaeger、Tempo、Loki、厂商 APM 等)。

判题链路横跨 Java backend、Python 判题 worker、Nginx 网关、Kafka 消息队列,多语言和多组件的遥测数据如果各自为政,排障时就是「每扇门配一把钥匙」。面试里「OTel 架构是怎样的」「和 Prometheus/Micrometer 是什么关系」是高频题,本课建立概念地图;Spring 落地见 obs-spring,插桩见 obs-instrumentation。

先建立图像

组件职责(人话)判题系统中的角色
OTel API/SDK应用内产生 span / metric / log 信号backend 和 worker 代码里的埋点
Instrumentation自动或手动把框架调用变成信号Java agent 自动采集 MVC/JDBC/Kafka;Python agent 自动采集 HTTP 请求
OTel Collector接收、批处理、采样、路由、格式转换集群内统一收集,再分发给各后端
Exporter写出到具体后端OTLP → Jaeger;Prometheus remote write;日志文件 → Loki
判题系统的 OTel 数据流:

浏览器 ──trace context──► Nginx(带 W3C header)
                              │
                              ▼
                  ┌───────────────────────┐
                  │  OTel Java Agent       │
                  │  - Spring MVC Span     │
                  │  - JDBC Span           │
                  │  - Kafka Producer Span │
                  │  - Micrometer bridge   │
                  └───────────┬───────────┘
                              │ OTLP (gRPC/HTTP)
                              ▼
                    ┌─────────────────┐
                    │ OTel Collector  │
                    │  receivers:     │
                    │   otlp, jaeger  │
                    │  processors:    │
                    │   batch, tail   │
                    │  exporters:     │
                    │   otlp/jaeger   │ → 链路后端
                    │   prometheus    │ → 指标后端
                    │   otlp/logs     │ → 日志后端
                    └─────────────────┘
                              │
          ┌───────────────────┼───────────────────┐
          │                   │                   │
          ▼                   ▼                   ▼
   ┌────────────┐    ┌────────────┐    ┌────────────┐
   │  Jaeger    │    │ Prometheus │    │  Loki      │
   │  (traces)  │    │ (metrics)  │    │ (logs)     │
   └────────────┘    └────────────┘    └────────────┘

并行现实(常见过渡方案):
  Micrometer → /actuator/prometheus → Prometheus scrape
  与 OTel traces 并存,逐步收敛为统一 OTLP 出口

跟着做

步骤 1:画判题系统的 OTel 数据流

在纸上画出三条路径:

A. 指标路径:Micrometer → /actuator/prometheus → Prometheus(scrape)
B. 链路路径:OTel Java Agent → OTLP → Collector → Jaeger
C. 日志路径:logback JSON → filebeat → Loki(含 traceId 字段)

应得到的核心结论:过渡期双栈是合理的——不必第一天全部切到 OTLP,先让链路统一标准,指标和日志逐步收敛。

步骤 2:理解 Collector 的价值——tail sampling

对比两种采样策略:

Head sampling(应用内):
  - 优点:实现简单,不占用网络带宽
  - 缺点:应用进程承担策略,每个实例独立采样,无法按「整链是否错误」决定保留

Tail sampling(Collector 层):
  - 优点:整链完成后判断——「有错误」或「总耗时 > 3s」的全链路保留,其他丢弃
  - 缺点:需要 Collector 缓存整链数据,内存开销增加

判题场景建议:开发环境 head sampling 10% 即可;生产环境用 Collector tail sampling,保留错误链路和慢链路(如判题总耗时 > 10s),正常链路采样 1%。

步骤 3:看一段 Collector 导出配置(可运行概念)

# otel-collector-config.yaml —— 接收 OTLP,同时导出到 Jaeger 和 Prometheus
receivers:
  otlp:
    protocols:
      http:
        endpoint: 0.0.0.0:4318
      grpc:
        endpoint: 0.0.0.0:4317

processors:
  batch:
    timeout: 1s
    send_batch_size: 1024
  tail_sampling:
    policies:
      - name: errors
        type: status_code
        status_code: {status_codes: [ERROR]}
      - name: slow
        type: latency
        latency: {threshold_ms: 10000}

exporters:
  otlp/jaeger:
    endpoint: jaeger-collector:4317
    tls:
      insecure: true
  prometheusremotewrite:
    endpoint: http://prometheus:9090/api/v1/write
    # 生产需加 tls 和 auth

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [tail_sampling, batch]
      exporters: [otlp/jaeger]
    metrics:
      receivers: [otlp]
      processors: [batch]
      exporters: [prometheusremotewrite]

应得到:管道按 signal 类型分开;同一接收可扇出到多个后端;tail sampling 策略集中管理。

步骤 4:验证 W3C trace context 跨边界传播

判题链路涉及多个进程,trace context 靠 W3C 标准头 traceparent 传播。检查清单:

1. Nginx → backend:检查 Nginx 是否透传 traceparent header
   # nginx.conf
   proxy_pass_request_headers on;
   # 或使用 opentelemetry-nginx-module

2. backend → Kafka:OTel Kafka producer 自动在消息头里塞 trace context
   消费端需确认:consumer 是否从 header 恢复 context

3. backend → 外部 HTTP:RestTemplate/WebClient 自动传播(OTel agent 支持)
   手写 HTTP client 时需手动加 header:traceparent=..."

应得到:链路断在哪,就查哪个环节的 header 有没有透传。

步骤 5:制定迁移一句话策略

「新服务(如新语言 worker)强制 OTel agent/SDK 统一接入;
  现有 Java backend dual-write 三个月(Micrometer + OTel traces 并存);
  Collector 统一扇出到 Prometheus/Jaeger/Loki;
  验证数据一致性后,再逐步下线旧 agent。」

reliability-essentials 强调:可移植观测契约避免绑死单一厂商。

讲清楚要点

  1. 遥测含三类信号,OTel 不是「只做 Tracing 的库」——Traces、Metrics、Logs 统一在同一项目下演进,共享 context 和语义约定。
  2. 应用不应绑死后端,所以 SDK 产出 + Collector 路由是推荐分层——换后端只需改 Collector exporter,不动应用代码。
  3. 传播格式已有 W3C trace context 标准,优先用标准头——减少网关和多语言间的摩擦,避免各团队「发明自己的头」。
  4. Micrometer 在 Spring 生态很强,所以指标路径常与 OTel 链路并存——用 bridge 或双写过渡,不要搞宗教战争。
  5. Collector 能处理批处理、采样、扇出,所以重逻辑上移可降低每个服务重复造轮子——采样策略、数据 enrich(如加 k8s 元数据)、格式转换都在 Collector 做。
  6. 语义约定让仪表盘可复用,自定义属性要克制且文档化——HTTP span 名用 http.method + http.route,属性用 http.status_code 而不是 code 或 status。
  7. K8s 常部署 Collector 为 Deployment 或 DaemonSet,所以遥测方案含集群运维面——见 kubernetes-essentials。

你可能会懵的地方

  • OTel 和 Jaeger 是什么关系? OTel 是「怎么产生和传输信号」的标准;Jaeger 是一种「追踪后端」,接收并存储追踪数据。OTel SDK/Collector 可以把 trace 发到 Jaeger,也可以发到 Tempo、Zipkin、云厂商 APM。

  • 没有 Collector 能用吗? 能。SDK 可以直接 export 到后端(如 OTEL_EXPORTER_OTLP_ENDPOINT 指向 Jaeger)。规模上升后 Collector 的优势才显现:统一采样策略、尾部采样、多后端扇出、数据 enrich。

  • Logs 在 OTel 里成熟吗? 相对 traces 和 metrics,logs 集成仍在快速演进。实践上常先「日志系统(Loki/ELK)+ traceId 关联」先行,再逐步接入 OTel logs pipeline。成熟顺序:traces > metrics > logs。

  • 这和 prometheus-essentials 冲突吗? 不冲突。Prometheus 仍是指标后端与告警主力;OTel 解决「如何统一产生和运输信号」。OTel Collector 可以导出 Prometheus remote write,也可以让 Micrometer 继续走 /actuator/prometheus scrape,两条路并存。

  • Python worker 和 Java backend 的 trace 能连起来吗? 能,只要都遵循 W3C trace context。Kafka 消息头里的 traceparent 会被各语言的 OTel SDK 识别,span 会挂到同一 traceId 下。前提是:消费端也要集成 OTel SDK(Python agent 或手动恢复 context)。

错法对照

错法问题正解
每个后端换一次应用埋点 API迁移成本极高,各服务口径不一致OTel API + Collector 扇出
应用内写死厂商 agent 配置散落各处改配置要改几十处配置集中到 Collector,应用只发 OTLP
拒绝 Micrometer,强行一天切完 OTLP业务风险高、排障断档分信号、分阶段收敛,双写验证
自定义属性名完全随心各服务「方言」不通,仪表盘无法复用遵循 semantic conventions
以为上了 OTel 就不用告警设计信号标准 ≠ 告警产品自动变好告警设计仍是人工工程(见 obs-monitoring)

卡点急救

  1. OTel agent 启动后没有 trace 数据:先确认 OTEL_EXPORTER_OTLP_ENDPOINT 指向 Collector 地址且网络可达;再检查 agent 版本与 JDK/Spring Boot 版本的兼容矩阵;最后看 Collector 日志是否有接收错误或 exporter 失败。
  2. 跨服务 trace 断成多截:逐层检查 traceparent header 是否透传。Nginx 层用 curl -v 看 response 有没有带 traceparent;Kafka 层检查消息头里有没有 traceparent 字段;消费端日志打印 Span.current().getSpanContext().getTraceId() 确认是否恢复成功。
  3. Collector 内存持续增长:多半是 tail sampling 缓存未设上限,或 batch processor 的队列堆积。调整方向:减小 tail sampling 的等待窗口;限制 batch size;检查 exporter 后端是否阻塞(网络慢或后端不可用会导致内存堆积)。

面试常问

  • OTel 的架构是怎样的?SDK、Collector、Exporter 各干什么? 背这个版本:SDK 在应用进程内,负责产生 spans/metrics/logs,管理 context 传播。Collector 是独立进程,负责接收(receivers)、处理(processors,如 batch、采样、enrich)、导出(exporters)到各种后端。Exporter 是 SDK 或 Collector 里写出到具体后端的模块,如 OTLP exporter、Prometheus remote write exporter。分层好处:应用只关心「产生标准信号」,后端切换只在 Collector 层改配置。

  • 为什么「一套插桩、多种后端」能降低迁移成本? 没有 OTel 时,换后端(如从 Jaeger 切到云厂商 APM)等于重写所有服务的埋点代码——API 不同、传播格式不同、标签语义不同。OTel 把埋点层统一为标准 API,后端通过 Collector exporter 配置切换,应用代码不动。这符合「可移植观测契约」原则,避免被单一厂商锁定。

  • Micrometer 指标和 OTel 链路怎么共存? 两种合理方案:A. 过渡期双栈——Micrometer 继续走 /actuator/prometheus scrape 到 Prometheus,OTel agent 负责 traces 发到 Collector → Jaeger,互不干扰。B. 收敛方案——Micrometer 通过 OTel bridge 把指标转成 OTLP,统一走 Collector 扇出到 Prometheus。选哪种取决于团队节奏,不要硬切。

自测三问

  1. SDK、Collector、Exporter 各干什么?数据流是怎样的?
  2. 为什么「一套插桩、多种后端」能降低迁移成本?用判题系统举例说明。
  3. 说明一种 Micrometer 指标与 OTel 链路并存的合理架构,并指出过渡期风险。

小结一句话

OTel 统一「怎么采怎么传」,后端各自「怎么存怎么查」——用 Collector 与语义约定保住可移植性。

延伸

  • OpenTelemetry 文档首页
  • OTel Collector 配置参考
  • W3C Trace Context 标准
  • OTel Semantic Conventions
  • 下一课《Spring 可观测性》:在 Spring Boot 上把 Micrometer 和 OTel 落地。
加载本节练习…
← 上一课监控与告警下一课 →Spring 可观测性