news 2026/10/12 3:15:58

Easegress 分布式追踪实战:基于 OpenTelemetry 的 Span 采集、Exporter 配置与 Cloudflare 集成

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Easegress 分布式追踪实战:基于 OpenTelemetry 的 Span 采集、Exporter 配置与 Cloudflare 集成
  • 云原生
  • API网关
  • 微服务
  • 服务网格

【免费下载链接】easegress

A Cloud Native traffic orchestration system. (CNCF Project)

项目地址:https://gitcode.com/gh_mirrors/ea/easegress
点击查看免费下载

Easegress 的分布式追踪能力建立在 OpenTelemetry 标准之上,你可以在 HTTPServer 等 Traffic Gate 中通过一行tracing配置快速开启,让每个请求自动生成跨网关、Pipeline、Filter 的完整 Span 链路,并同时推送到 Zipkin、Jaeger 或 OTLP Collector。本文以 docs/03.Advanced-Cookbook/3.05.Distributed-Tracing.md 为主线,结合 pkg/tracing/tracing.go 的源码实现,完整讲解配置项、Span 层级结构、Exporter 对接、向后兼容策略与 Cloudflare 场景,读完即可在自己的网关上落地一套可观测的追踪方案。

追踪原理与 Span 层级

Easegress tracing 基于 OpenTelemetry 实现。在 Traffic Gate(例如HTTPServer)中通过定义tracing条目即可启用追踪。追踪会创建一个包含服务名(tracing.serviceName)和其他信息的 Span,此后:

  • 请求匹配到的 Pipeline 会启动一个子 Span(child span);
  • Pipeline 内部的 Filter 会根据各自的实现与配置再启动子 Span,例如ProxyFilter 就有专门的 Span 实现。

最终形成的是一条HTTPServer → Pipeline → Filter的层级链路,每一层都可以独立查看耗时与属性,便于定位瓶颈发生在网关入口、代理转发还是具体过滤器上。

从源码看,Span 的创建链路在 pkg/object/httpserver/mux.go 中启动:serveHTTP处理每个请求时调用mi.tracer.NewSpanForHTTP(...)创建顶层 Span,并通过context.New(span)将 Span 注入到请求上下文;Pipeline 与 Filter 则通过ctx.Span().NewChild(name)(见 pkg/context/context.go 与 pkg/filters/proxies/httpproxy/pool.go)向下延伸子 Span。

快速上手:在 HTTPServer 中启用追踪

最简单的配置如下:在HTTPServer的 spec 中加入tracing块,声明服务名、采样率与 Zipkin Exporter 地址。

kind: HTTPServer name: http-server-example port: 10080 tracing: serviceName: httpServerExample sampleRate: 1 exporter: zipkin: endpoint: http://localhost:9412/api/v2/spans rules: - paths: - pathPrefix: /pipeline backend: pipeline-example

其中各字段的含义:

  • serviceName(必填):顶层 Span 的服务名,会以service.name资源属性的形式附加到所有 Span 上(见 pkg/tracing/tracing.go 的newResource);
  • sampleRate:采样率,取值范围 [0, 1],默认 1(全量采样)。源码中采样器逻辑见newSampler:小于等于 0 时永不采样(NeverSample),大于等于 1 时全量采样(AlwaysSample),介于 0 与 1 之间时按 TraceID 比例采样(TraceIDRatioBased);
  • exporter.zipkin.endpoint:Zipkin 服务端接收 Span 的 URL(v2 spans API)。

配置完成后,所有经由此 HTTPServer 且命中pathPrefix: /pipeline规则的请求都会生成追踪数据。启动 Zipkin 后即可在界面上看到完整的调用链。

自定义属性(Custom Attributes)

自定义属性可以帮助进一步过滤与排查追踪 Span。在tracing下添加attributes条目,以 key-value 形式打上业务标签:

kind: HTTPServer name: http-server-example port: 10080 tracing: serviceName: httpServerExample attributes: # add "attributes" entry and tags as key-value pairs customAttributeKey: customAttributeValue sampleRate: 1 exporter: zipkin: endpoint: http://localhost:9412/api/v2/spans rules: - paths: - pathPrefix: /pipeline backend: pipeline-example

在实现层面,attributes会被写入 TracerProvider 的resource,从而附加到该 Tracer 产生的每一个 Span 上,非常适合标注环境(如env: staging)、业务线(如team: payment)等全局维度信息。

需要特别注意的是,tags是旧版写法(已废弃),tags与attributes不能同时配置,源码校验会直接报错并提示统一使用attributes管理(见 pkg/tracing/tracing.go 的Validate)。

Exporter 配置:同时对接 Zipkin、Jaeger 与 OTLP

得益于 OpenTelemetry 的标准化,Easegress 除了 Zipkin,还能将 Span 发送到 Jaeger、OTLP(OpenTelemetry Collector)等后端。完整的 Exporter 类型与参数可参考 tracing.Spec。

Easegress 支持同时配置多个 Exporter,Span 会被并行推送到所有已配置的后端,适合在灰度迁移后端或同时保留两套观测平台的场景。示例如下:

kind: HTTPServer name: http-server-example port: 10080 tracing: serviceName: httpServerExample sampleRate: 1 exporter: zipkin: endpoint: http://localhost:9412/api/v2/spans jaeger: mode: agent endpoint: localhost:6831 otlp: protocol: grpc endpoint: localhost:4317 insecure: true rules: - paths: - pathPrefix: /pipeline backend: pipeline-example

各 Exporter 的参数说明(对应 pkg/tracing/tracing.go 中的ExporterSpec):

  • zipkin:endpoint(必填,URL 格式)为 Zipkin 服务端地址;
  • jaeger:
    • mode(必填):agent或collector两种接入模式;
    • endpoint:agent 模式下必须是host:port(源码中通过net.SplitHostPort强校验,见 pkg/tracing/tracing.go),collector 模式下为完整 URL;
    • username/password:collector 模式下可选的认证信息;
  • otlp:
    • protocol(必填):http或grpc;
    • endpoint(必填):OTLP Collector 的地址;
    • insecure:是否允许非 TLS 连接,默认 false;
    • compression:负载压缩方式,可选gzip。

多个 Exporter 的实现逻辑在newExporters中:逐一构建 Jaeger、Zipkin、OTLP 的SpanExporter并追加到列表,随后每个 Exporter 对应一个BatchSpanProcessor(见 pkg/tracing/tracing.go)。

tracing.Spec 完整参数参考

除了上文已涉及的字段,tracing.Spec还包含 Span 限制与批量上报的调优参数,默认值均对齐 OpenTelemetry SDK 的官方默认(见 pkg/tracing/tracing.go 的UnmarshalJSON):

参数类型说明默认值
serviceNamestring顶层服务名(必填)-
attributesmap[string]string附加到每个 Span 的属性(推荐)-
tagsmap[string]string已废弃,用 attributes 替代-
sampleRatefloat64采样率 [0, 1]1
spanLimitsspanlimits.SpecSpan 各类数量/长度上限见下
batchLimitsbatchlimits.Spec批量导出行为调优见下
exporterexporter.SpecZipkin/Jaeger/OTLP 导出器-
zipkinzipkin.DeprecatedSpec旧版 Zipkin 配置(已废弃,见后文)-
headerFormatstring上下文传播格式:trace-context或b3trace-context

spanlimits.Spec(Span 上限):attributeValueLengthLimit(属性值最大长度,默认 -1 表示不限)、attributeCountLimit(Span 属性数量上限,默认 128)、eventCountLimit(事件数上限,默认 128)、linkCountLimit(链接数上限,默认 128)、attributePerEventCountLimit与attributePerLinkCountLimit(默认均 128)。设为零表示不记录,设为负数表示不限。

batchlimits.Spec(批量上报):maxQueueSize(缓冲队列大小,默认 2048,队列满时会丢弃 Span)、batchTimeout(组批超时,默认 5000 毫秒)、exportTimeout(导出超时,默认 30000 毫秒)、maxExportBatchSize(单批最大 Span 数,默认 512)。源码在newBatchSpanProcessors中将这些值透传给BatchSpanProcessor,适用于高 QPS 场景下控制内存占用与上报抖动。

headerFormat(链路传播格式):默认使用 W3Ctrace-context标准(traceparent/tracestate头);可切换为 Zipkin 生态常用的b3单头格式。特别地,源码newPropagator规定:若配置的是旧版zipkin字段(而非exporter),则自动使用b3格式以保持向后兼容。

向后兼容:旧版 Zipkin 配置的迁移

当前版本仍然支持旧版配置写法,但与新写法存在少量差异,需要调整。旧版配置示例如下:

kind: HTTPServer name: http-server-example port: 10080 tracing: serviceName: httpServerExample tags: # Deprecated: This option will be kept until the next major version incremented release. customTagKey: customTagValue zipkin: hostport: 0.0.0.0:10080 # This option will no longer be used serverURL: http://localhost:9412/api/v2/spans sampleRate: 1 sameSpan: true # This option will no longer be used id128Bit: false # # This option will no longer be used rules: - paths: - pathPrefix: /pipeline backend: pipeline-example

调整后的等效配置应为:

kind: HTTPServer name: http-server-example port: 10080 tracing: serviceName: httpServerExample tags: # Deprecated: This option will be kept until the next major version incremented release. customTagKey: customTagValue zipkin: serverURL: http://localhost:9412/api/v2/spans sampleRate: 1 rules: - paths: - pathPrefix: /pipeline backend: pipeline-example

迁移要点(对应ZipkinDeprecatedSpec的定义与注释,见 pkg/tracing/tracing.go):

  • hostport:不再使用,直接删除;
  • sameSpan、id128Bit:不再使用,直接删除;
  • disableReport:已废弃,不再生效;
  • serverURL、sampleRate:保留有效,其中sampleRate是必填项,取值范围 [0, 1];
  • tags:已废弃,声明将保留到下一个大版本发布后再移除,建议迁移到attributes(注意两者不能同时出现)。

同时注意校验规则:exporter与旧版zipkin字段不能同时为空,也不能同时存在(见 pkg/tracing/tracing.go);若配置了exporter,则旧版zipkin字段不再生效。若配置的是旧版zipkin,其sampleRate会被用作全局采样率(newSampler中的兼容逻辑)。

与 Cloudflare 集成

当请求来自 Cloudflare CDN 时,HTTPServer 的 Span 会自动携带cf.ray标签,其值即该请求的 Cloudflare RayID,可用于在追踪系统中按 RayID 精确检索某次经过 CDN 的请求。

更进一步,你还可以在 HttpServer Span 之上叠加一个独立的 Cloudflare Span,形成cloudflare → http-server → pipeline → filter的完整链路。实现原理见 pkg/tracing/cloudflare.go:网关检测到请求头中的cf-ray后,读取时间戳请求头并解析出毫秒级时间戳,以该时刻为起点创建名为cloudflare的 Span,再在其下创建 HttpServer 子 Span,从而把请求在 Cloudflare 侧消耗的时间也纳入观测范围。

要实现这一效果,需要让 Cloudflare 在流量进入时附带时间戳请求头,配置步骤如下:

  1. 在 Cloudflare Dashboard 中进入你的站点;
  2. 进入Rules -> Transform Rules -> Modify Request Header,创建一条规则;
  3. 添加两个动态请求头:
    • "x-ts-msec":值取"http.request.timestamp.msec"
    • "x-ts-sec":值取"http.request.timestamp.sec"

两个请求头分别携带毫秒与秒级时间戳,网关侧的newSpanForCloudflare会将二者拼接解析为毫秒时间戳(sec + msec组合解析,见 pkg/tracing/cloudflare.go)。注意:

  • 若请求带cf-ray但缺少任一时间戳请求头或解析失败,则退化为普通 Span,仅附加cf.ray标签,不影响正常追踪;
  • x-ts-sec/x-ts-msec仅影响 Cloudflare Span 的起始时间戳,不会改变网关实际处理时间。

源码级补充:Span 生命周期与链路传播

从代码层面看,一次带追踪的请求会经历以下完整生命周期:

  1. 创建:muxInstance.serveHTTP调用mi.tracer.NewSpanForHTTP(...),若请求来自 Cloudflare 则进入 Cloudflare 分支(pkg/object/httpserver/mux.go);
  2. 注入:Span 被写入请求上下文context.New(span),Pipeline 与各 Filter 通过ctx.Span().NewChild(name)创建子 Span(如 HTTP Proxy 的ServerPoolSpec.spanName可自定义 Span 名称,未设置时默认使用 Proxy 名,见 pkg/filters/proxies/httpproxy/pool.go);
  3. 传播:转发到后端服务时通过span.InjectHTTP(r)将 Span 上下文写入出站请求头(W3Ctrace-context或b3,取决于headerFormat),实现跨服务串联(pkg/tracing/tracing.go);
  4. 结束:请求处理完成后调用span.End(),若存在 Cloudflare Span 会一并结束,随后由BatchSpanProcessor按batchLimits的配置异步批量导出到所有 Exporter(pkg/object/httpserver/mux.go);
  5. 关闭:HTTPServer 配置热更新时,若tracing配置发生变化,旧 Tracer 会被关闭(tp.Shutdown),避免资源泄漏(pkg/object/httpserver/mux.go)。

单元测试 pkg/tracing/tracing_test.go 也验证了NewSpan、NewChildWithStart、InjectHTTP以及 Noop Tracer 的空实现路径,可作为理解 API 行为的参考。

小结

Easegress 的分布式追踪开箱即用、配置声明式、后端可替换:通过tracing.serviceName定义服务身份,attributes注入全局业务标签,sampleRate控制采样成本,exporter并行对接 Zipkin/Jaeger/OTLP,headerFormat决定跨服务传播协议;同时保留旧版 Zipkin 配置的兼容通道,并提供 Cloudflare 场景下的 RayID 标签与额外 CDN Span。若要进一步调整 Span 上限与批量上报行为,参考 tracing.Spec 中的spanLimits与batchLimits即可在生产环境精细调优。

  • 云原生
  • API网关
  • 微服务
  • 服务网格

【免费下载链接】easegress

A Cloud Native traffic orchestration system. (CNCF Project)

项目地址:https://gitcode.com/gh_mirrors/ea/easegress
点击查看免费下载
上一篇:实时数据传输:DeepLabCut与WebSocket实时监控系统
下一篇:Flax 高级 RNN 层设计全解:从 FLIP 2396 到 nn.RNN 与 Bidirectional 的源码级剖析

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/12 3:15:01

个人版AI订阅直连Devin:自主编程智能体接入与成本控制实战

1. 这件事到底意味着什么个人版 AI 编程助手订阅可以直接用在 Devin 上了。这个消息乍一看像是一条普通的产品更新,但如果你正在用 AI 辅助写代码,或者正在为团队挑选自动化编程工具,这件事的影响面其实比想象中大得多。先说清楚背景。Devin …

作者头像 李华
网站建设 2026/10/12 3:13:49

Autodesk插件源码防护指南:从反编译风险到分层加固方案

我做了几年 Autodesk 平台插件的开发,也见过不少同行在官方应用商店里卖插件赚得盆满钵满,但很少有人愿意聊这事:你辛辛苦苦写的代码,从打包上架那一刻起,就一直“裸奔”在用户的电脑上。Autodesk App Store 不像移动应…

作者头像 李华
网站建设 2026/10/12 3:13:33

读取硬盘MBR:从hexdump到Python解析器实战

简介:这份资源围绕硬盘MBR(主引导记录)的读取与解析展开,面向具备一定C基础、希望深入理解磁盘底层结构与系统级I/O编程的开发者。内容涵盖文件操作、低级I/O调用、512字节扇区读取、内存映射、MBR分区表结构解析以及安全备份与错…

作者头像 李华
网站建设 2026/10/12 3:11:51

光线追踪渲染器从零实现:核心代码、调参与避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/12 3:11:38

Linux 下用 nvm 安装 Node v23 与 npm 10,实现多版本隔离管理

1. 项目概述1.1 为什么需要 nvm,而不是直接改系统的 Node先说个我踩过的坑。早些年我在一台服务器上把 Node 从 v16 升到 v18,直接拿了官方 tar 包覆盖,结果系统里某老运维脚本里硬编码的 npm 路径全部炸掉,找问题花了整整半天。后…

作者头像 李华