使用 OpenTelemetry 零代码修改接收 SkyWalking 追踪数据

SDN in China

2022年8月15日

产品资讯

经过半年的努力,我们向OpenTelemetry社区贡献了完整的SkyWalking Receiver。从现在开始,使用SkyWalking探针的所有用户能够在不修改任何代码的情况下,丝滑的使用OpenTelemetry兼容的所有可观测性后端平台。

什么是分布式追踪

2010年,Google的一篇Dapper论文[1]开启了分布式追踪的序章。CNCF的 OpenTracing作为分布式追踪的标准协议,定义了一套厂商无关、语言无关的规范,也有Jaeger 、Zipkin等项目的实现和支持。

随后Google和微软提出了 OpenCensus项目,在定义分布式追踪协议的基础上,也规范了应用性能指标,并实现了一套标准的API ,为可观测性能力统一奠定了基础。经过对已有的标准协议不停的打磨和演变,CNCF提出了OpenTelemetry,它结合了OpenTracing与OpenCensus两个项目,成为了一个厂商无关、平台无关的支撑可观测性三大支柱的标准协议和开源实现。

另一方面,基于Dapper论文的思想,国内也有SkyWalking开源项目实现了分布式追踪,由于探针的无侵入性,SkyWalking获得了大量的用户,并且有越来越多的贡献者推动着它的高速迭代。

以Dapper的定义作为基准,一个标准的分布式Trace示例如下图所示。一个 Trace是由Span构成的有向无环图(DAG),Span是一个最小粒度的调用,既可以指代一个程序块执行,也可以指代一次HTTP等应用协议的远程调用。

协议对比

目前在做分布式追踪的开源项目很多,接下来挑选几个社区活跃度高,且生产环境使用多的项目对比一下传输协议的差异,大致如下:

代码解读

为了能兼容不同的分布式追踪实现,OpenTelemetry提供了组件植入的方式让不同的厂商能够经由OpenTelemetry标准化数据处理后输出到不同的后端。Jaeger与Zipkin在社区中实现了JaegerReceiver、ZipkinReceiver。我们也为社区贡献了SkyWalkingReceiver,并进行了持续的打磨,现在已经具备了在生产环境中使用的条件,而且无需修改任何一行业务代码。

OpenTelemetry与SkyWalking有一些共同点:都是使用Trace来定义一次追踪,并使用Span来标记追踪里的最小粒度。但是在一些细节和实现上还是会有差别:

明确了这些差异后,就可以开始实现将SkyWalking Trace[2]转换为 OpenTelemetry Trace[3]。主要工作包括:

  • 如何构造OpenTelemetry的TraceId和SpanId
  • 如何构造OpenTelemetry的ParentSpanId
  • 如何在OpenTelemetry Span中保留SkyWalking的原始TraceId、SegmentId、SpanId

代码实现见GitHub[4][5] :opentelemetry-collector-contrib/skywalkingproto_to_traces.go at main · open-telemetry/opentelemetry-collector-contrib · GitHub

首先我们来看如何构造OpenTelemetry的TraceId和SpanId。SkyWalking和 OpenTelemetry都是通过TraceId串联起各个分布式服务调用,并通过SpanId 来标记每一个Span ,但是实现规格有较大差异:

具体来讲,SkyWalking TraceId和SegmentId所有可能的格式如下[6]:

其中,在OpenTelemetry协议里,Span在所有Trace中都是唯一的,而在 SkyWalking中,Span仅在每个Segment里是唯一的,这说明要通过 SegmentId与SpanId 结合才能在SkyWalking中对Span做唯一标识,并转换为OpenTelemetry的SpanId。

代码实现见GitHub[7] :「链接」

接下来,我们来看如何构造OpenTelemetry的ParentSpanId。在一个 Segment内部,SkyWalking的ParentSpanId字段可直接用于构造 OpenTelemetry的ParentSpanId字段。但当一个Trace跨多个Segment时,SkyWalking是通过Reference中的ParentTraceSegmentId和ParentSpanId 表示的关联信息,于是此时需要通过Reference中的信息构建 OpenTelemetry的ParentSpanId。

代码实现见GitHub:opentelemetry-collector-contrib/skywalkingproto_to_traces.go at main · open-telemetry/opentelemetry-collector-contrib · GitHub

最后,我们来看如何在OpenTelemetry Span中保留SkyWalking的原始 TraceId、SegmentId、SpanId。我们携带这些原始信息是为了能将分布式追踪后端展现的OpenTelemetry TraceId、SpanId与应用程序日志中的 SkyWalking TraceId、SegmentId、SpanId进行关联,打通追踪和日志。我们选择将SkyWalking中原有的TraceId、SegmentId、ParentSegmentId携带到OpenTelemetry Attributes中。

代码实现见GitHub[8]:opentelemetry-collector-contrib/skywalkingproto_to_traces.go at main · open-telemetry/opentelemetry-collector-contrib · GitHub

经过上述一系列转换后,我们将SkyWalking Segment Object完整的转换为了OpenTelmetry Trace,总结如下:

部署 Demo

下面我们以一个Demo来展示使用OpenTelemetry收集、展示SkyWalking追踪数据的完整过程。

首先,在部署OpenTelemetry Agent之后,开启如下配置,即可在 OpenTelemetry中拥有兼容SkyWalking协议的能力:


# otel-agent config
receivers:
  # add the following config
  skywalking:
    protocols:
      grpc:
        endpoint: 0.0.0.0:11800 # 接收 SkyWalking Agent 上报的 Trace 数据
      http:
        endpoint: 0.0.0.0:12800 # 接收从前端/ nginx 等 HTTP 协议上报的 Trace 数据
service:
  pipelines:
    traces:
      # add receiver `skywalking`
      receivers: [skywalking]

# otel-agent service yaml
spec:
  ports:
    - name: sw-http
      port: 12800
      protocol: TCP
      targetPort: 12800
    - name: sw-grpc
      port: 11800
      protocol: TCP
      targetPort: 11800

接下来需要将业务应用对接的SkyWalking OAP Service(如:oap:11800)修改为OpenTelemetry Agent Service(如:otel-agent:11800),就可以开始使用OpenTelemetry接收SkyWalking探针的追踪数据了。

我们以SkyWalking-showcase Demo为例展示整个效果。它使用 SkyWalking Agent做追踪,通过OpenTelemetry标准化处理后使用Jaeger来呈现最终效果:

通过SkyWalking Showcase的架构图,可知SkyWalking的数据经过 OpenTelemetry标准化后,依然完整。在这个Trace里,请求从 app/homepage发起,之后在app同时发起两个请求/rcmd/与/songs/top ,分发到recommandation/songs两个服务中,并最终到达数据库进行查询,从而完成整个请求链路。

另外,我们也可从Jaeger页面中查看到原始SkyWalking Id信息,便于与应用日志关联:

作者简介

谭建

DaoCloud可观测性技术专家

GitHub:@JaredTan95

DaoCloud 道客是云原生领域的创新领导者,成立于 2014 年底,拥有自主知识产权的核心技术,致力于打造开放的云操作系统为企业数字化转型赋能。产品能力覆盖云原生应用的开发、交付、运维全生命周期,并提供公有云、私有云和混合云等多种交付方式。

林嘉炜

云杉网络DeepFlow工程师

GitHub:@taloric

云杉网络成立于 2011 年,公司秉承“技术创造价值”的使命,为运营商和大型企业提供领先的云网络和云监控解决方案,满足云时代 IT 系统不断增长的自动化和可观测性需求。DeepFlow是一个开源的高度自动化的可观测性平台。

引用

  • [1] Dapper 论文 https://bigbully.github.io/Dapper-translation/
  • [2] SkyWalking 协议 https://skywalking.apache.org/docs/main/latest/en/protocols/trace-data-protocol-v3/
  • [3] OpenTelemetry 协议 https://opentelemetry.io/docs/reference/specification/overview/
  • [4] https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/8107
  • [5] https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/8549
  • [6] SkyWalking JavaAgent https://github.com/apache/skywalking-java
  • [7] https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/11562
  • [8] https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/12651

加入DeepFlow开源社区

体验高度自动化的可观测性新时代

官网链接

https://deepflow.yunshan.net

GitHub地址

https://github.com/deepflowys/deepflow

访问DeepFlow Demo

https://deepflow.yunshan.net/docs/zh/install/overview/

Related Posts

什么是云原生可观测性追踪技术?

云杉 世纪

2023年2月3日

产品资讯

在云原生领域,云原生可观测性指从外部输出推断和衡量系统内部状态,描述系统中所发生情况的理解程度。常见的云原生可观测性的三大基础是监控指标(Metrics)、追踪(Tracing)和日志(Logging)

Read More

网络流量分发的方式有哪些?

云杉 世纪

2023年1月13日

产品资讯

DeepFlow?混合云全网流量采集与网络流量分发方案,为企业混合云建立统一高效的网络流量采集及处理平台,面对异构资源池实现统一的流量采集抽象层,支持IPv4、IPv6协议环境,并且能对流量实现过滤、去重、压缩、截短等处理功能,能为网络运营中心、安全运营中心、大数据分析平台等多方流量消费端提供数据供给。

Read More