OpenTelemetry 入门:架构、组件与 SDK 安装
讲链路追踪,绕不开 OpenTelemetry。你现在出去面试,聊可观测性,十个有八个会问你用过 OTel 没有。它已经是事实上的标准了。这章我们就把它的底裤扒开,看看里面到底长什么样。
为什么需要 OpenTelemetry?
我之前在一个老项目里,接了三种不同的 APM 探针。Jaeger 的、Zipkin 的,还有一个自研的。每次要查个全链路,得在三个系统里反复横跳,数据格式还不一样,对接得想死。说白了,接口协议都不统一,更别提什么生态了。
OpenTelemetry 做了什么事呢?它统一了数据采集的协议。不管你是 Jaeger、Zipkin 还是 Prometheus,都通过 OTel 这把“瑞士军刀”来采集。数据格式统一了,后面的存储和展示选择就自由了。
OpenTelemetry 的整体架构
我们先看张图,脑袋里有个整体印象。
这图里其实就三块核心:SDK、Collector 和 后端系统。我们逐个说。
SDK:嵌入应用的探针
SDK 是你需要打到代码里的库。它负责拦截你程序的 HTTP 调用、数据库查询、消息队列等等,生成一个个 Span,再把 Span 串成 Trace。嗯,这里要注意:SDK 只负责“生成”和“发射”,它不负责永久存储。
SDK 内部的核心组件是 Exporter。它决定了数据发往哪里去。我们做个对比:
| 组件 | 职责 | 我的建议/经验 |
|---|---|---|
| SDK 核心 | 自动/手动埋点,生成 Span | 优先用自动埋点,省力。但核心链路建议手动增加业务标签 |
| Processor(SDK 侧) | 本地的批处理、过滤、采样 | 我常用尾巴采样(Tail Sampling),只保留慢请求的 Trace |
| Exporter(SDK 侧) | 将数据发送到 Collector 或后端 | 推荐用 gRPC 协议,吞吐量比 HTTP 高。我之前踩过 HTTP 的坑,数据量一大就超时 |
Collector:数据中转与加工站
Collector 是 OTel 生态里我最喜欢的部分。它像一个中心化的数据管道。你想想看,如果每个微服务都直接把数据发到 Jaeger,改配置要改几十个服务,多痛苦。有了 Collector,你只需要改 Collector 的配置就行了。
Collector 组件也分三个:
- Receiver:负责接收来自 SDK 或者其他系统(比如 Prometheus)的数据。支持 OTLP、Jaeger、Zipkin 等协议。
- Processor:数据处理工厂。可以过滤掉健康检查的垃圾 Span、可以采样(比如每秒只保留前 100 条 Trace)、可以给数据加业务标签。
- Exporter:将处理完的数据送往目标。可以同时写往多个后端,比如一份写 Jaeger 存储,一份写日志平台归档。
Processor 的常见用途
结合实际项目,我推荐你关注这几个 Processor:
- Batch Processor:必配。将多个 Span 打包成一批发送,减少网络开销。我在高并发的服务上试过,不配 Batch,Collector 的 CPU 直接飙到 80%,配上后降到 20% 以下。
- Tail Sampling Processor:强推。全量采集太费钱,这个可以让你只保留那些“慢的”或者“出错的”请求。比如 P99 以上的请求保留,其他丢弃,成本降低十倍。
- Attributes Processor:给 Span 加常见属性。比如从请求 Header 里提取用户的租户 ID 加到 Span 上,后面查问题直接按租户筛选。
SDK 安装:以 Java 为例
纸上谈兵没意思,我们直接上手。底层逻辑都一样,换个语言就是换个包名。
// 1. 引入依赖(Maven)
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-api</artifactId>
<version>1.31.0</version>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk</artifactId>
<version>1.31.0</version>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-otlp</artifactId>
<version>1.31.0</version>
</dependency>
// 2. 初始化 SDK(往往在应用启动时执行)
OpenTelemetrySdk sdk = OpenTelemetrySdk.builder()
.setTracerProvider(
SdkTracerProvider.builder()
.addSpanProcessor(BatchSpanProcessor.builder(
OtlpGrpcSpanExporter.builder()
.setEndpoint("http://otel-collector:4317") // 指向 Collector
.build()
).build())
.build()
)
.build();
// 3. 全局设置,方便各处调用
OpenTelemetry.setGlobalOpenTelemetry(sdk);
你看,核心就几步:
1. 引入包
2. 创建 Exporter,指向 Collector
3. 配置 Processor(这里是 Batch 模式)
4. 全局注册,完事。
避坑清单(实战总结)
最后给你列个清单,都是我曾经在线上环境摔过的跟头:
- 版本一致性:API、SDK、Exporter、Collector 的版本号尽量保持一致。大版本不匹配,可能会序列化失败。
- 采样率先低后高:刚上线时,别开 100% 采样。量大的服务,全量采样能把后端写挂。我习惯先开 5% 看看效果,稳定了再调整。
- Collector 的高可用:别单点部署 Collector,至少两台。万一挂了一台,SDK 会重连到另一台。我们在 Kubernetes 上通常用 StatefulSet 部署,配 Headless Service 做负载均衡。
- 小心敏感数据:Span 的 Attributes 里别塞用户密码、身份证号等隐私字段。如果必须加,记得在 Processor 里用 Filter 或 Mask 处理掉。