天穹-Hera可观测性系列2:Hera-tracing之OpenTelemetry详解

先打个广告,天穹已开源:https://github.com/XiaoMi/mone,欢迎对云原生技术/研发效能感兴趣的小伙伴加入(Fork、Star)我们。

OpenTelemetry简介

什么是OpenTelemetry?“OpenTelemetry,也简称为OTel,是一个供应商中立的开源可观测性框架,用于检测、生成、收集和导出遥测数据,如链路追踪、 指标、 日志。作为行业标准,它本身就受到许多供应商的支持。”从官方的介绍中,我们可以看出如下几个关键点:

  • OpenTelemetry是一个可观测性框架。可观测性三剑客为链路追踪、指标监控和日志,OpenTelemetry作为可观测性框架,是用于检测、生成、收集、导出这三个维度的数据。

  • OpenTelemetry的目标,或者说它与生俱来的使命,是要成为可观测性框架的标准。作为标准,就需要与供应商无关,而他产生的数据,又需要支持这些供应商。这里说的供应商,指用于解析、存储、展示OpenTelemetry所产生的数据的第三方软件或框架。比如链路追踪中的ZipKin、Jaeger,指标监控中的Prometheus等。并且OpenTelemetry需要具有很好的可扩展性,支持自定义的数据导出方式。这些它都已经做到了。

那么OpenTelemetry是如何检测、生成、收集、导出这三个维度的数据呢?这里我援引官网的一个示例图。

  1. 在微服务的应用代码中,可以使用OTel提供的自动检测仪器(auto instrumentation),通过运行时生成、修改我们自己写的应用代码、或是其他中间件、框架代码中的bytecode,生成数据;或者是使用OTel提供的API、SDK,在代码中手动添加一些类似于切面的代码来生成数据。目前OTel也提供与云原生紧密结合的工具,如通过Kubernetes Operator自动加入OTel的javaagent,从而实现自动生成数据。

  1. 生成的数据,可以通过OTLP(OpenTelemetry Protocol)发送到一个名为OTel Collector的“收集器”中。OTel Collector提供了数据解析、数据格式转换、数据打标与数据过滤等功能,可以将OTel产生的数据,与后端供应商的数据格式对齐。

  1. 我们可以使用经由OTel Collector收集的数据,通过内置的格式转换,导出到第三方存储,像Prometheus的时序数据库、ES、HBase的列存储数据库。我们也可以导出到第三方服务,甚至可以直接打印到日志文件中。

从官方的介绍中,我们可以看出OpenTelemetry是一系列组件、API、SDK的集合,我们在生产使用中可以根据自身需要,进行插拔式的使用,非常便利。如果能了解这些组件,可以为很多使用场景提供解决方案。同样的,我们的学习成本也会变高,尤其是在不了解Go语言的情况下,有一些组件会让我们望而却步。

OpenTelemetry使用

探针

我们习惯性地把OTel提供的自动检测仪器(auto instrumentation)叫做探针。顾名思义,探针可以检测需要去拦截哪些类的哪些方法,去做一定的增强,从而产生一定的可观测性数据。OpenTelemetry提供了多种语言的探针,这里我们以Java语言来做示范。因为Java语言可以通过-javaagent参数,在启动过程中利用探针去检测应用程序代码中的哪些类、方法需要被拦截,通过字节码增强技术(OTel中使用的是ByteBuddy字节码组件)来添加、修改字节码,从而产生可观测性数据。但是这种方式有语言的局限性,比如Go语言可能没有这么自动化的方式。

  1. 我们可以从OpenTelemetry的Git上找到opentelemetry-java-instrumentation项目,这个项目就是探针的源文件。

  1. 将opentelemetry-java-instrumentation clone到本地,进行本地编译,在opentelemetry-java-instrumentation根目录下执行./gradlew assemble进行构建编译。编译成功后,会在opentelemetry-java-instrumentation/javaagent/build/libs目录下生成pentelemetry-javaagent-0.1.0-SNAPSHOT-all.jar,这个jar文件就是最终的探针。

  1. 将生成的opentelemetry-javaagent-0.1.0-SNAPSHOT-all.jar上传到服务器的应用目录下,在应用启动时,添加JVM参数:-javaagent:${应用目录}/opentelemetry-javaagent-0.1.0-SNAPSHOT-all.jar,启动成功后,探针就开始发挥作用了。

由于opentelemetry-java-instrumentation是使用Gradle进行项目与依赖管理,在首次编译的过程中可能并不会一帆风顺,这里最好参考我们Hera的opentelemetry-java-instrumentation编译过程,会让一个不了解Gradle的人顺利地、快速地进行编译。

另外,opentelemetry-java-instrumentation只是一个探针的源码文件,他所依赖的API、SDK,是在opentelemetry-java工程中,如果我们想进行更深一步的自定义开发,比如说自定义链路追踪(Trace)导出的方法、自定义指标(Metrics)的导出方式、自定义跨度(span)中的内容等等,都需要修改opentelemetry-java工程。这点也可以参考Hera中的opentelemetry-java,可以看到如何进行编译、上传,供opentelemetry-java-instrumentation引用。

使用API、SDK手动检测仪器(Manual Instrumentation)

这里需要引入OpenTelemetry的相关依赖,比如opentelemetry-api,opentelemetry-sdk等,再使用其中的方法进行数据的定义、生成。这种方式的好处是可以在代码任意位置生成跨度(span)、指标(metrics)等数据,但是缺点也会很明显:

  1. 让我们的代码看起来非常的臃肿;

  1. 增加了开发人员的代码工作量;

  1. 增加了应用本身的依赖,尤其是在Java中,依赖过多会导致严重的冲突;

  1. 对于没有丰富工作经验的开发者来说,错误的使用还会使程序产生意想不到的错误,甚至使整个应用因为内存泄漏导致不可用。

所以在生产过程中,Hera并没有对用户开放手动检测仪器,而是提供了方法级别的注解,通过探针来对拥有该注解的方法进行统一处理。当然,对于想要在代码中任意位置生成可观测性数据的用户来说,还是需要类似手动检测仪器的这种方式。

OTel Collector

对于小型应用来说,将可观测性数据由探针直接发送到后端存储是一个非常便利的过程,在很多时候我们可能都用不到OTel Collector。但是有这种工具之后,我们可以在数据无法传送到后端的时候,提供了一种选择。具体的使用方式可以参考官网的文档:https://opentelemetry.io/docs/collector/

Kubernetes Operator

目前不管是大型企业,还是小型公司,K8s都是一个比较通用的选择,所以OpenTelemetry也提供了Kubernetes Operator来实现自动检测、收集可观测性数据。有兴趣的话可以参考官网文档:https://opentelemetry.io/docs/k8s-operator/

OpenTelemetry的内容在不断丰富,如对于Ebpf的支持,Hera目前用到的最多的就是它的探针自动检测仪器,由于它的可扩展性,我们才能在它的基础上丰富了很多功能。更多地Hera中使用、扩展的功能,可以在后续的对于opentelemetry-java-instrumentation源码解读系列文章中进行介绍。

探针对比

在Hera的起步阶段,探针的选型尤为重要,他关系到后续的一系列技术选型的确定、适配工作。Hera的定位是云时代的应用可观测平台,要求对于监控、链路、日志三剑客之间的关联要非常紧密,我们需要在链路中去加入一些属性,去完成关联、跳转的工作;需要与我们Mone现有的应用、权限相结合,这就对于技术的可扩展性有着非常高的要求。下图是OpenTelemetry、SkyWalking、Jaeger-agent的对比图。

当时的OpenTelemetry我们主要是用它来产生Tracing数据,后端由Tracing数据转换为请求类型的监控指标(Request Scope Metrics),OpenTelemetry在Hera中的应用这一部分内容我会在后续的文章中进行讲解。基于可扩展性和标准化,我们选择了OpenTelemetry,也确实在它的基础上添改了很多,在Hera的整体架构中,它也发挥着非常重要的作用。

猜你喜欢

转载自blog.csdn.net/shanwenbang/article/details/129533083