☰
opentelemetry最佳实践
2026/11/5 1:57:18 网站建设 项目流程

一、本地全链路实战:docker-compose

一套"应用 → Collector → Jaeger"的最小生产形态,十分钟搭好。

docker-compose.yaml:

services:jaeger:image:jaegertracing/all-in-one:latestports:["16686:16686"]# UI;OTLP 端口只给 collector 内网用networks:[otel]otelcol:image:otel/opentelemetry-collector-contrib:latestcommand:["--config=/etc/otelcol/config.yaml"]volumes:-./otelcol.yaml:/etc/otelcol/config.yaml:roports:["4317:4317","4318:4318","13133:13133"]depends_on:[jaeger]networks:[otel]networks:{otel:{}}

otelcol.yaml:

receivers:otlp:protocols:grpc:{endpoint:0.0.0.0:4317}http:{endpoint:0.0.0.0:4318}processors:memory_limiter:{check_interval:1s,limit_mib:512,spike_limit_mib:128}batch:{timeout:5s,send_batch_size:1024}exporters:otlp/jaeger:endpoint:jaeger:4317tls:{insecure:true}debug:{verbosity:basic}extensions:health_check:{endpoint:0.0.0.0:13133}service:extensions:[health_check]pipelines:traces:receivers:[otlp]processors:[memory_limiter,batch]exporters:[otlp/jaeger,debug]

启动与验证:

dockercompose up-dcurlhttp://localhost:13133# Collector 健康# 跑 03 章的应用(SDK 端点指 http://localhost:4317)# 打开 http://localhost:16686 查链路

改造练习(强烈建议动手):

  1. 加spanmetricsconnector + Prometheus exporter,把 RED 指标抓出来;
  2. 把 batch 参数调小,观察 debug 输出频率变化;
  3. 故意配错 jaeger 地址,观察 exporter 重试日志与队列指标——体会"数据在哪丢的"。

二、采样策略决策

按场景对号入座:

场景方案理由
开发/测试AlwaysOn全量好排查
低流量内部服务AlwaysOn 或高比例 ratio数据量可承受,全量价值大
常规生产SDK:ParentBased(TraceIDRatioBased(0.05~0.5))简单稳定,链路完整性由 ParentBased 保证
错误必须全留SDK 全采 + Collectortail_sampling见下
高价值交易链路对特定 route 强制采样(SDK 端按属性自定义采样器)交易全留,其余降比

processors:tail_sampling:decision_wait:10s# 等链路走完再做决策的窗口num_traces:100000# 内存中缓存的链路数policies:[{name:errors,type:status_code,status_code:{status_codes:[ERROR]}},{name:slow,type:latency,latency:{threshold_ms:1000}},{name:baseline,type:probabilistic,probabilistic:{sampling_percentage:1}},]

注意:尾部采样要求链路完整经过同一 Collector 集群(Gateway 层),且decision_wait期间内存缓存全量链路——容量规划要做足。另一个坑:SDK 端已做了头采,尾采只能在"已采集"的 10% 里再选,错误链路早在 SDK 就被丢了。所以"错误全留"必须 SDK 全采或调高头采比例,成本核算要清楚。

三、SDK 端开销控制清单

埋点是侵入业务进程的,以下清单控制住"税负":

  1. 采样前置:ParentBased(TraceIDRatioBased(p)),Drop 的 Span 零分配(04 章原理);
  2. SpanLimits:限制属性数/长度,防止恶意或超大属性撑爆内存;
  3. 只用 Batcher,不要用 Syncer(同步导出阻塞业务);
  4. 批量参数按吞吐调:高 QPS 服务把OTEL_BSP_MAX_QUEUE_SIZE调到 10000+,并监控队列水位;
  5. 属性低基数:attributes 只放有限取值集合;user_id、URL 全文放日志;
  6. 优雅退出:监听 SIGTERM →tp.Shutdown(ctx),K8s 环境给 preStop/terminationGracePeriodSeconds 留时间;
  7. 按需选信号:不是每个服务都要三信号全开,内部工具先 trace 即可;
  8. eBPF 方案兜底:存量服务不想改代码?看 08 章 Go 自动插桩(odigos / go-instrumentation)。

四、Collector 高可用与扩容

  1. 无状态化:Agent 层天然无状态;Gateway 队列数据在内存,挂了会丢——重要链路可配file_storage扩展把队列落盘;
  2. 水平扩容:OTLP/HTTP 经 LB 直接轮询;OTLP/gRPC 需要 LB 支持 HTTP/2 长连接分摊(istio/nginx h2 或头部 LB),否则流量倾斜;
  3. 限流保护:exporter 侧配sending_queue+ retry;后端故障时队列顶住,恢复后追平;
  4. 分级部署:Agent(每节点,轻)→ Gateway(集中,重)双层;Gateway 按命名空间/业务域拆多套,爆炸半径小;
  5. 自监控告警(必做):
    • otelcol_exporter_queue_size接近上限;
    • otelcol_exporter_send_failed_spans持续增长;
    • otelcol_receiver_refused_spans(内存限流触发);
    • Collector 副本数/重启次数。

五、安全:TLS、认证、多租户

  1. 传输加密:应用 → Collector、Collector → 后端全程 TLS(本地开发才允许 insecure);
  2. 认证:
    • 应用 → Collector:bearer token 或 mTLS(用 Collector 的bearertokenauth扩展 + receivers 的auth配置);
    • Collector → 后端:后端凭据只配在 Gateway,Agent 层零凭据;
  3. 脱敏:attributes/transformprocessor 删改敏感字段(http.authorization、手机号正则替换),在数据出门前完成;
  4. 多租户路由:
# 请求带 tenant 头 → 路由到对应租户的 exporterprocessors:routing:from_attribute:tenantdefault_exporters:[otlp/pool]table:-value:acmeexporters:[otlp/acme]exporters:otlp/acme:{endpoint:acme-backend:4317,tls:{insecure:false}}

  1. 网络面:K8s 里用 NetworkPolicy 限制 4317/4318 只接受业务 Pod 与 Collector 互访。

六、后端选型速查

信号后端特点
TracesJaeger最经典,UI 成熟,本地开发首选;大规模存储依赖 ES/Cassandra
TracesTempo(Grafana)对象存储廉价,Grafana 深度集成
TracesSigNoz / Uptrace自带 OTLP + ClickHouse,APM 一体化开源
MetricsPrometheus / Mimir / VictoriaMetrics事实标准 / 大规模 / 高性能
LogsLoki对象存储便宜,标签索引模型
LogsElasticsearch / ClickHouse全文检索强
全家桶Grafana Stack(LGTM) + Grafana一站式,OTel 原生支持好

选型原则:先用 Jaeger + Prometheus + Loki 跑通,量级/预算变化再迁移——OTel 的意义正是"埋点不变,后端随便换"。

七、常见坑 Top 10

#现象原因 → 解法
1Jaeger 偶尔丢链路没调Shutdown,批量队列残留 → defer shutdown + 优雅退出
2跨服务链路断ctx 没传 / propagator 没注入提取 → 检查 otelhttp/otelgrpc 是否两端都包
3采样后错误链路也没了头采把错误 trace 丢了 → ParentBased+ratio 改为尾采,或错误请求强制采样
4后端被 Span 洪峰打挂没配 batch / exporter 没队列 → batch + sending_queue + 限流
5Collector OOMKilled无 memory_limiter 或 limit 太高 → 必配 memory_limiter + GOMEMLIMIT
6日志和 trace 对不上打日志没传 ctx →logger.InfoContext(ctx,...)或 otelslog 桥接
7高基数指标打爆存储属性放了 user_id/URL 全文 → 低基数化,明细落日志
8gRPC 过 LB 流量不均HTTP/2 长连接粘住 → LB 支持 h2 轮换,或换 OTLP/HTTP
9K8s 元数据缺失k8sattributes 无 RBAC → 给 Collector SA 加 get/list/watch pods 权限
10时序图上父子时间错乱跨机时钟偏移 → 保证 SERVER/CLIENT 时间戳语义,部署 NTP/chrony

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询