Skip to content

OpenTelemetry:云原生可观测性的统一标准

"可观测性不是监控,而是让系统自己告诉你它发生了什么。"

一、问题引入:为什么需要可观测性?

1.1 监控的演进

监控的三个阶段:

第一阶段:监控(Monitoring)
- 关注:系统是否健康?
- 手段:CPU、内存、磁盘、网络
- 问题:只知道"病了",不知道"哪里病了"

第二阶段:可观测性(Observability)
- 关注:系统为什么这样?
- 手段:Trace、Metric、Log三支柱
- 优势:能诊断"病因"

第三阶段:智能运维(AIOps)
- 关注:系统未来会怎样?
- 手段:机器学习 + 可观测性数据
- 目标:预测和预防

1.2 可观测性三支柱

可观测性三支柱:

1. Metrics(指标)
   - 是什么:随时间变化的数值
   - 示例:CPU使用率、请求QPS、错误率
   - 特点:低基数、聚合、高效
   - 问题:丢失细节

2. Logs(日志)
   - 是什么:离散的事件记录
   - 示例:错误日志、访问日志、审计日志
   - 特点:高基数、详细、结构化
   - 问题:难以关联

3. Traces(追踪)
   - 是什么:请求的完整路径
   - 示例:用户请求 → API网关 → 服务A → 服务B → 数据库
   - 特点:端到端、可视化、关联
   - 问题:开销大

三支柱的关系:
Metrics → 发现问题
Traces  → 定位问题
Logs    → 诊断问题

1.3 OpenTelemetry的诞生

OpenTelemetry的历史:

2019年:OpenTracing + OpenCensus 合并
  - OpenTracing:API标准化
  - OpenCensus:Google的监控库
  - 合并目标:统一可观测性标准

2021年:CNCF Graduated项目
  - 成为可观测性事实标准
  - 厂商中立:不绑定任何后端

2026年:全面普及
  - 主流语言SDK支持
  - 自动埋点成熟
  - 企业生产环境标配

二、OpenTelemetry架构设计

2.1 核心组件

OpenTelemetry架构:

┌─────────────────────────────────────────────────┐
│              应用程序层                          │
│  ┌─────────────────────────────────────────┐    │
│  │         OpenTelemetry SDK               │    │
│  │  ┌──────────┐ ┌──────────┐ ┌────────┐  │    │
│  │  │ Tracing  │ │ Metrics  │ │ Logs   │  │    │
│  │  │ API/SDK  │ │ API/SDK  │ │ API/SDK│  │    │
│  │  └─────┬────┘ └─────┬────┘ └───┬────┘  │    │
│  └─────────┼───────────┼──────────┼────────┘    │
└────────────┼───────────┼──────────┼─────────────┘
             │           │          │
┌────────────▼───────────▼──────────▼─────────────┐
│            OpenTelemetry Collector              │
│  ┌─────────────┐  ┌─────────────┐              │
│  │  Receivers  │  │  Processors │              │
│  │ (接收数据)   │  │ (处理数据)   │              │
│  └──────┬──────┘  └──────┬──────┘              │
│         │                 │                     │
│  ┌──────▼──────┐  ┌──────▼──────┐              │
│  │  Exporters  │  │  Extensions │              │
│  │ (导出数据)   │  │ (扩展功能)   │              │
│  └─────────────┘  └─────────────┘              │
└───────────────────┬─────────────────────────────┘

┌───────────────────▼─────────────────────────────┐
│              后端存储层                          │
│  ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐  │
│  │Jaeger  │ │Prometheus│ │ELK   │ │Tempo  │  │
│  │(Trace) │ │(Metric) │ │(Log)  │ │(Trace)│  │
│  └────────┘ └────────┘ └────────┘ └────────┘  │
└─────────────────────────────────────────────────┘

2.2 OTLP协议

OTLP(OpenTelemetry Protocol):

协议特点:
- 基于gRPC/HTTP
- Protobuf序列化
- 高效、可扩展
- 厂商中立

数据结构:

// Trace数据
message TracesData {
  repeated ResourceSpans resource_spans = 1;
}

message ResourceSpans {
  Resource resource = 1;           // 资源信息(服务名、主机等)
  repeated ScopeSpans scope_spans = 2; // SDK信息
}

message ScopeSpans {
  InstrumentationScope scope = 1;  // SDK名称、版本
  repeated Span spans = 2;         // Span列表
}

message Span {
  bytes trace_id = 1;              // 追踪ID
  bytes span_id = 2;               // Span ID
  bytes parent_span_id = 3;        // 父Span ID
  string name = 4;                 // Span名称
  int64 start_time_unix_nano = 5;  // 开始时间
  int64 end_time_unix_nano = 6;    // 结束时间
  repeated AttributeKeyValue attributes = 7; // 属性
  repeated Link links = 8;         // 链接
  Status status = 9;               // 状态
}

// Metric数据
message MetricsData {
  repeated ResourceMetrics resource_metrics = 1;
}

message ResourceMetrics {
  Resource resource = 1;
  repeated ScopeMetrics scope_metrics = 2;
}

message ScopeMetrics {
  InstrumentationScope scope = 1;
  repeated Metric metrics = 2;
}

message Metric {
  string name = 1;
  string description = 2;
  oneof data {
    Gauge gauge = 4;
    Sum sum = 5;
    Histogram histogram = 7;
  }
}

三、核心概念详解

3.1 Trace与Span

Trace与Span的关系:

一次请求的完整Trace:

Trace ID: 4bf92f3577b34da6a3ce929d0e0e4736

┌─ Span: API Gateway (root) ──────────────────────┐
│ Trace ID: 4bf92f35...                          │
│ Span ID: 00f067aa0ba902b9                      │
│ Duration: 125ms                                │
│ Attributes: http.method=GET, http.path=/api/users│
│                                                 │
│  ┌─ Span: Auth Service ─────────────────────┐   │
│  │ Parent: 00f067aa0ba902b9                 │   │
│  │ Span ID: 5c4b5e3a1d7f8e2b                │   │
│  │ Duration: 15ms                           │   │
│  │ Attributes: auth.type=jwt                │   │
│  └───────────────────────────────────────────┘   │
│                                                 │
│  ┌─ Span: User Service ─────────────────────┐   │
│  │ Parent: 00f067aa0ba902b9                 │   │
│  │ Span ID: 7a3c9e1f5d8b2e4a                │   │
│  │ Duration: 95ms                           │   │
│  │ Attributes: db.statement=SELECT...       │   │
│  │                                          │   │
│  │  ┌─ Span: DB Query ───────────────────┐  │   │
│  │  │ Parent: 7a3c9e1f5d8b2e4a           │  │   │
│  │  │ Span ID: 2e8f5a1c9d3b7e4f          │  │   │
│  │  │ Duration: 45ms                     │  │   │
│  │  │ Attributes: db.type=mysql          │  │   │
│  │  └─────────────────────────────────────┘  │   │
│  └───────────────────────────────────────────┘   │
└───────────────────────────────────────────────────┘

关键概念:
- Trace:一次请求的完整路径
- Span:Trace中的一个操作单元
- Parent Span:父子关系构建树形结构
- Attributes:键值对,存储上下文信息

3.2 Context Propagation

上下文传播(Context Propagation):

跨服务传递Trace上下文:

服务A ──HTTP请求──→ 服务B

请求Header:
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b9-01

格式:
- 00: 版本
- 4bf92f3577b34da6a3ce929d0e0e4736: Trace ID
- 00f067aa0ba902b9: Span ID
- 01: Trace Flags(采样标记)

W3C Trace Context标准:
- 厂商中立
- 语言无关
- 跨进程传播

3.3 资源与属性

资源(Resource)与属性(Attributes):

资源:标识产生遥测数据的实体
  - 服务名
  - 主机名
  - 容器ID
  - 部署环境

属性:键值对,提供上下文信息
  - HTTP方法、路径、状态码
  - 数据库类型、语句
  - 用户ID、会话ID
  - 自定义业务属性

示例:
Resource:
  service.name: order-service
  service.version: 1.2.3
  host.name: prod-server-01
  deployment.environment: production

Span Attributes:
  http.method: POST
  http.url: /api/orders
  http.status_code: 201
  db.type: mysql
  db.statement: INSERT INTO orders...
  user.id: usr_12345

四、生产环境实践

4.1 自动埋点

自动埋点(Auto-instrumentation):

Java自动埋点:
java -javaagent:/path/opentelemetry-javaagent.jar \
     -Dotel.service.name=order-service \
     -Dotel.exporter.otlp.endpoint=http://collector:4317 \
     -jar order-service.jar

Python自动埋点:
pip install opentelemetry-instrumentation
opentelemetry-instrument \
  --traces-exporter otlp \
  --metrics-exporter otlp \
  --service-name order-service \
  python app.py

Node.js自动埋点:
npm install @opentelemetry/sdk-node
node --require ./tracing.js app.js

支持的框架:
- HTTP/HTTPS
- Express, Fastify, Koa
- gRPC
- JDBC, MySQL, PostgreSQL
- Redis, MongoDB
- Kafka, RabbitMQ
- AWS SDK, GCP SDK

4.2 Collector配置

yaml
# OpenTelemetry Collector配置

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318
  
  prometheus:
    config:
      scrape_configs:
        - job_name: 'kubernetes-pods'
          kubernetes_sd_configs:
            - role: pod

processors:
  batch:
    timeout: 5s
    send_batch_size: 1000
  
  attributes:
    actions:
      - key: environment
        value: production
        action: upsert
  
  memory_limiter:
    check_interval: 1s
    limit_mib: 1000
    spike_limit_mib: 200

exporters:
  otlp/jaeger:
    endpoint: jaeger:14250
    tls:
      insecure: true
  
  prometheus:
    endpoint: 0.0.0.0:8889
    namespace: promapp
  
  loki:
    endpoint: http://loki:3100/loki/api/v1/push

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch, attributes]
      exporters: [otlp/jaeger]
    
    metrics:
      receivers: [otlp, prometheus]
      processors: [batch]
      exporters: [prometheus]
    
    logs:
      receivers: [otlp]
      processors: [batch]
      exporters: [loki]

4.3 采样策略

采样策略(Sampling):

1. 固定比例采样
   - 采样10%的请求
   - 简单有效
   - 问题:可能丢失异常请求

2. 头部采样
   - 在请求开始时决定
   - 跨服务一致
   - 减少传输开销

3. 尾部采样
   - 在请求结束后决定
   - 基于属性决策
   - 保留异常请求

4. 自适应采样
   - 根据流量动态调整
   - 高流量时降低采样率
   - 低流量时提高采样率

5. 基于属性采样
   - 错误请求100%采样
   - 慢请求100%采样
   - 正常请求10%采样

配置示例:
otel.traces.sampler=parentbased_traceidratio
otel.traces.sampler.arg=0.1  # 10%采样率

五、最佳实践

5.1 命名规范

遥测数据命名规范:

Span命名:
✅ http.get /api/users/{id}
✅ db.query SELECT users
✅ cache.get user:123
❌ http.get /api/users/123  (高基数)

Metric命名:
✅ http_server_duration_seconds
✅ http_server_requests_total
✅ db_client_operations_total
❌ my_custom_metric_123

属性命名:
✅ http.method, http.status_code
✅ db.type, db.statement
✅ user.id, session.id
❌ custom_field_1, random_key

5.2 性能优化

性能优化建议:

1. 采样策略
   - 生产环境10-20%采样
   - 错误/慢请求100%采样
   - 避免100%采样(开销大)

2. 批量导出
   - 批量发送数据
   - 减少网络开销
   - 配置合理的batch size

3. 异步处理
   - 异步导出遥测数据
   - 不影响主业务逻辑
   - 使用内存队列

4. 属性精简
   - 只记录必要的属性
   - 避免高基数属性
   - 定期审查属性使用

5. 资源限制
   - 配置内存限制
   - 避免OOM
   - 监控Collector健康

六、总结

6.1 OpenTelemetry的价值

OpenTelemetry带来的价值:

1. 标准化
   - 统一的可观测性API
   - 厂商中立
   - 避免供应商锁定

2. 自动化
   - 自动埋点成熟
   - 减少手动工作
   - 快速接入

3. 可移植
   - 随时切换后端
   - 多后端同时导出
   - 灵活部署

4. 生态完善
   - 主流语言支持
   - 框架集成丰富
   - 社区活跃

6.2 开始使用OpenTelemetry

快速开始步骤:

第1步:选择SDK
  - Java: opentelemetry-java
  - Python: opentelemetry-python
  - Node.js: opentelemetry-js
  - Go: opentelemetry-go

第2步:部署Collector
  - Docker: otel/opentelemetry-collector
  - Kubernetes: Helm Chart
  - 配置receivers/processors/exporters

第3步:配置后端
  - Trace: Jaeger/Tempo
  - Metric: Prometheus
  - Log: Loki/ELK

第4步:应用埋点
  - 自动埋点优先
  - 手动埋点补充
  - 定义业务属性

第5步:监控和调优
  - 监控Collector健康
  - 调整采样策略
  - 优化性能开销

记住:可观测性不是一蹴而就的,需要持续迭代和优化。

作者:和风科技 | 发布日期:2026-04-27