- 云原生
- API网关
- 微服务
- 服务网格
【免费下载链接】easegress
A Cloud Native traffic orchestration system. (CNCF Project)
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):
| 参数 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| serviceName | string | 顶层服务名(必填) | - |
| attributes | map[string]string | 附加到每个 Span 的属性(推荐) | - |
| tags | map[string]string | 已废弃,用 attributes 替代 | - |
| sampleRate | float64 | 采样率 [0, 1] | 1 |
| spanLimits | spanlimits.Spec | Span 各类数量/长度上限 | 见下 |
| batchLimits | batchlimits.Spec | 批量导出行为调优 | 见下 |
| exporter | exporter.Spec | Zipkin/Jaeger/OTLP 导出器 | - |
| zipkin | zipkin.DeprecatedSpec | 旧版 Zipkin 配置(已废弃,见后文) | - |
| headerFormat | string | 上下文传播格式:trace-context或b3 | trace-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 在流量进入时附带时间戳请求头,配置步骤如下:
- 在 Cloudflare Dashboard 中进入你的站点;
- 进入
Rules -> Transform Rules -> Modify Request Header,创建一条规则; - 添加两个动态请求头:
"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 生命周期与链路传播
从代码层面看,一次带追踪的请求会经历以下完整生命周期:
- 创建:
muxInstance.serveHTTP调用mi.tracer.NewSpanForHTTP(...),若请求来自 Cloudflare 则进入 Cloudflare 分支(pkg/object/httpserver/mux.go); - 注入:Span 被写入请求上下文
context.New(span),Pipeline 与各 Filter 通过ctx.Span().NewChild(name)创建子 Span(如 HTTP Proxy 的ServerPoolSpec.spanName可自定义 Span 名称,未设置时默认使用 Proxy 名,见 pkg/filters/proxies/httpproxy/pool.go); - 传播:转发到后端服务时通过
span.InjectHTTP(r)将 Span 上下文写入出站请求头(W3Ctrace-context或b3,取决于headerFormat),实现跨服务串联(pkg/tracing/tracing.go); - 结束:请求处理完成后调用
span.End(),若存在 Cloudflare Span 会一并结束,随后由BatchSpanProcessor按batchLimits的配置异步批量导出到所有 Exporter(pkg/object/httpserver/mux.go); - 关闭: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)
相关推荐
res-downloader:视频号、抖音、m3u8 资源下载零门槛完整指南
res downloader:视频号、抖音、m3u8 资源下载零门槛完整指南 res downloader 是一款免费的跨平台网络资源下载器,通过本地代理自动嗅
桌面应用网络音视频Kamal分布式追踪:OpenTelemetry集成实战
Kamal分布式追踪:OpenTelemetry集成实战 引言:为什么Kamal需要分布式追踪? 在现代微服务架构中,一个用户请求往往需要经过多个服务协同处理。
云原生DevOps运维JPEXS Free Flash Decompiler与虚拟现实开发:SWF内容VR化工作流完整指南
JPEXS Free Flash Decompiler与虚拟现实开发:SWF内容VR化工作流完整指南 JPEXS Free Flash Decompiler是一
开发工具逆向工程桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考