OpenTelemetry 体系介绍:规范、SDK、Collector 架构
大家好。这章咱们聊聊 OpenTelemetry 的体系结构。我早期做链路追踪的时候,各家方案各搞一套,数据格式不互通,SDK 也不一样,后来 OpenTelemetry 出来,总算有了一个统一的方向。说白了,这个体系就三大块:规范(Specification)、SDK(软件开发工具包)、Collector(收集器)。它们怎么配合?咱们往下看。
核心逻辑: 规范定标准,SDK 实现标准并嵌入应用,Collector 负责接收、处理、转发数据。三者缺一不可。
1. 规范(Specification)—— 一切的基础
没有规范,大家各写各的,就不可能互通。OpenTelemetry 规范定义了三件事:数据模型(Traces、Metrics、Logs 长什么样)、API(开发者怎么调用)、协议(SDK 和 Collector 之间怎么传数据)。
我当年参与过一个多语言微服务项目,Java 和 Go 用的是不同的 APM 厂商,traceId 的编码方式都不一样,联调时对不上。后来我们统一迁到 OpenTelemetry,靠的就是规范里明确的 trace_id 和 span_id 的字节长度和编码规则。嗯,这里要注意:规范本身是不写具体代码的,它是一份文档,目前托管在 github.com/open-telemetry/opentelemetry-specification。
小提示: 规范里的 语义约定(Semantic Conventions) 很重要,比如 HTTP 请求的 http.method、http.url 等 key 都是固定好的。如果你自己乱取名,后续分析工具可能没法识别。
2. SDK —— 开发者的直接战场
SDK 就是规范的具体实现,每种主流语言都有一份。你只需要在你的应用里引入对应的 SDK 包,然后调用 API 打点。我习惯把 SDK 的工作分为三块:
- TracerProvider: 创建 Tracer,Tracer 创建 Span,Span 就是一次操作的记录。
- MeterProvider: 创建 Meter,Meter 记录指标(Counter、Histogram 等)。
- Context Propagation: 把 trace 上下文在进程间(比如 HTTP 请求头)传下去,这是链路不丢的关键。
我曾经踩过一个坑:用 Python SDK 时,默认的 Sampler 是 AlwaysOn,结果业务量上来后 CPU 飙到 90%,后来改成 TraceIdRatioBased(0.1) 才压住。所以啊,生产环境一定要配置采样率。
// 一个最简单的 Java 示例
OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
.setTracerProvider(
SdkTracerProvider.builder()
.addSpanProcessor(BatchSpanProcessor.builder(OtlpGrpcSpanExporter.builder().build()).build())
.setSampler(Sampler.traceIdRatioBased(0.1))
.build()
)
.build();
Tracer tracer = openTelemetry.getTracer("my-service");
Span span = tracer.spanBuilder("doSomething").startSpan();
try {
// 你的业务逻辑
} finally {
span.end();
}
警告: SDK 版本一定要与 Collector 的 OTLP 版本匹配。我见过有人用 v0.7.0 的 SDK 对接 v1.0.0 的 Collector,结果 protobuf payload 解析失败,数据全部丢弃。
3. Collector —— 数据管道的核心枢纽
Collector 是一个独立的代理服务,不侵入业务代码。它接收来自 SDK 或各种 Exporter 的数据,经过管道(Pipeline)处理,再导出到后端。我个人认为这是整个体系中最灵活的部分,因为它允许你在不修改应用的前提下,做数据过滤、采样、重试、甚至转换格式。
Collector 的架构其实很简单:管道由 Receivers、Processors、Exporters 三段组成。数据流是:Receiver 接收 → Processor 处理(可以有多个) → Exporter 发送。
| 组件 | 作用 | 常见实现 |
|---|---|---|
| Receiver | 接收数据,支持多种协议 | OTLP Receiver、Jaeger Receiver、Prometheus Receiver |
| Processor | 处理数据,如采样、过滤、批处理、属性修改 | Batch Processor、Memory Limiter、Attributes Processor |
| Exporter | 发送到后端存储或分析系统 | OTLP Exporter、Jaeger Exporter、Prometheus Exporter、Logging Exporter |
配置 Collector 用的是 YAML 文件。举个例子,一个最简的配置:
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
batch:
timeout: 1s
send_batch_size: 1024
exporters:
otlp:
endpoint: my-backend:4317
tls:
insecure: true
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlp]
metrics:
receivers: [otlp]
processors: [batch]
exporters: [otlp]
你想想看,这个配置里我们只启用了 OTLP 接收和导出,中间加了一个 Batch Processor 来合并数据。实际生产环境我还会加上 Memory Limiter 防止 OOM,以及 Filter Processor 丢弃健康检查的 trace。
部署建议: Collector 可以每个节点部署一个(DaemonSet 模式),也可以独立集群部署。小规模用 DaemonSet 简单;大规模推荐独立集群,利用 Processor 做全局采样和降级。
总结一下
OpenTelemetry 的三层体系设计得很巧妙:规范保证了跨语言、跨厂商的兼容性;SDK让开发者零成本接入;Collector提供了数据管道的灵活性。这三层各司其职,缺一不可。我今年在迁移一个遗留系统的监控时,就是用这个体系:先在业务代码里埋 SDK,再部署 Collector 做统一出口,最后迁移后端。整个过程几乎没有停服。