点击一键订阅《云荐大咖》专栏,获取官方推荐优质内容,学技术不迷路!随着分布式应用越来越普遍,分布式应用需要依赖强大的可观测设施来提供监控保障,而强大的可观测设施又需要依赖高质量的遥测数据。虽然很多开源或者商业供应商都提供了遥测数据监控采集方案。但在没有统一标准的情况下,采集的遥测数据兼容性差,维护和监控客户端也给用户带来了沉重的负担。Opentelemetry可以为开发者提供一个统一的、独立于第三方的遥测数据采集方案来解决上述问题。起源Opentelemetry起源于两个开源社区OpenTracing和OpenCensus的合并。OpenTracing由BenSigelman于2016年发起,旨在解决开源Tracing实现监控客户端重复开发、数据模型不一致、Tracing后端兼容成本高等问题。OpenCensus源自谷歌内部实践,结合Tracing和Metrics监控客户端开源工具包。由于两大开源社区各自的影响力都不小,存在两个或多个Tracing标准本身就与社区形成的目的背道而驰。于是两个开源社区一拍即合,成立了OpenTelemetry。为什么一定要从用户的角度访问Tracing监控客户端,对业务代码有侵入性。一旦连接了一个提供商的监控客户端,就很难切换到另一个提供商的监控客户端。从Tracing服务器提供商的角度来看,服务器除了能够处理自己Tracing客户端的数据外,还需要兼容其他供应商Tracing客户端生成的数据,维护成本越来越高和更高。尤其是在分布式应用逐渐普及的情况下,正如文章开头所说,Opentelemetry的价值更加明显。Opentelemetry项目由Opentelemetry项目主要分为四个部分:跨语言规范;用于收集、转换和转发遥测数据的工具;各种语言的采集器、监控客户端;API&SDK,自动监控客户端和第三方库;仪器和贡献;跨语言规范规范包括范围广泛的主题。其中有遥测客户端内部实现所需的规范,以及遥测客户端与外界通信所需的协议规范。代码仓库:opentelemetry-遥测客户端内部实现所需的规范,如监控客户端基本架构、设计原则、遥测信号(Traces/Metrics/Logs)和辅助对象(Baggage/Context/Propagator)的概念和模型定义,实现遥测客户端需要实现的类和函数的设计。这部分内容本文不作详细介绍,可在相应对象文件夹下的specification/overview.md和datamodel.md/api.md/sdk.md中查阅。遥测客户端与外界通信需要实现的协议规范主要是指OpenTelemetryProtocol(简称OTLP)。OTLP是Opentelemetry的本地遥测信号协议。虽然Opentelemetry项目中的组件支持Zipkinv2或JaegerThrift协议格式的实现,但它们都是以第三方贡献库的形式提供的。只有OTLP得到Opentelemetry的官方支持。OTLP的数据模型定义是基于ProtoBuf的。如果需要实现一套可以收集OTLP遥测数据的后端服务,需要了解里面的内容。对应的可以参考代码仓库:代码仓库:opentelemetry-protocollection,conversion1.Collector,转发遥测数据的工具,在Tracing实践中有一个原理。遥测数据收集过程需要与业务逻辑处理正交。这意味着遥测数据采集和传输到遥测后端服务的过程不会占用业务逻辑的通道/线程,最大限度地减少监控客户端对原有业务逻辑的影响。Collector就是基于这个原则实践的产物。代码仓库:opentelemetry-collector在架构上,Collector有两种模式。一种是将Collector部署在与应用相同的宿主机中(如K8SDaemonSet),或者将其部署在与应用相同的Pod中(如K8S中的Sidecar)。应用程序收集的遥测数据通过环回网络直接传输到收集器。这种模式统称为Agent模式。另一种模式是将Collector作为一个独立的中间件,应用程序将采集到的遥测数据传递给这个中间件。这种模式称为网关模式。两种方式可以单独使用,也可以结合使用,只要数据导出的数据协议格式与数据录入的数据协议格式一致即可。在OpentelemetryArchitecture对Collector的内部设计中,一组数据流入、处理、流出的过程称为pipeline。管道由三个组件组成,它们是接收器/处理器/导出器。Receiver负责根据相应的协议格式监听和接收遥测数据,并将数据传送给一个或多个处理器Processor负责对遥测数据进行处理,如丢弃数据、添加信息、批量处理等,并通过数据到下一个处理器或传递给一个或多个出口商。出口商负责将数据发送到下一个接收端(通常是遥测后端)。导出器可以定义收集器管道以同时从多个不同的处理器获取遥测数据。从上面的设计可以看出,Collector除了提供让遥测数据采集与业务逻辑处理正交的能力外,还充当遥测数据连接遥测后端的适配器。Collector可以接收otlp、zipkin、jaeger等任意格式的数据,然后转发otlp、zipkin、jaeger等任意格式的数据。这完全取决于您需要输入或输出的格式是否有相应的接收器和导出器实现。otlp相关的实现在opentelemetry-collector存储库中。对于otlp以外的协议实现,可以参考下面的代码库。代码存储库:opentelemetry-collector-contrib每种语言的监控客户端API和SDKOpentelemetry为每种语言提供基本的监控客户端API和SDK包。这些包一般是基于opentelemetry-specification中的建议和定义,结合语言本身的特点,实现在客户端收集遥测数据的基本能力。比如服务和进程之间元数据的传递,添加Trace的监控和数据导出,Metrics指标的创建、使用和数据导出等。下面是各语言监控客户端API&SDK包对应的代码仓库表。根据Opentelemetry项目的计划,大部分组件将在2021年上半年完成Tracing支持。从目前时间点(2021年12月)来看,C++/.NET/Golang/Java/Javascript/Python/Ruby监控客户端对Tracing的支持已经进入Stable状态。Erlang/Rust/Swift监控客户端对Tracing的支持已经进入Beta测试阶段。Opentelemetry项目计划稍后支持Mertics。希望2021年下半年大部分组件能够完成Metrics支持。从目前情况来看,各语言客户端包对Metrics的支持还处于Alpha测试阶段。计划2022年开始支持Logs,如果Instrumentation&Contrib单纯使用监控客户端API&SDK包,很多操作需要修改应用代码。比如增加Tracing监控点,记录字段信息,对进程/服务之间传递的元数据进行装箱和拆箱等。这种方式有代码侵入性,不易解耦,运行成本高,提高了用户使用门槛.这时候可以利用公共组件的设计模式或者语言特性来降低用户的使用门槛。利用公共组件的设计模式,比如Golang中的Gin组件,实现了中间件责任链设计模式。我们可以参考github.com/gin-gonic/gin库,创建一个otelgin.Middleware,手动添加到Middleware链中,实现对Gin的快速监控。利用语言特性,例如Java利用JavaAgent的能力和bytebuddy字节码编织技术,在Java应用程序启动前找到对应的类和方法,修改字节码注入监控,实现对指定类的自动监控。理论上,快速监控依赖客户端API&SDK,自动监控依赖快速监控。但实际操作并没有按照理论进行。比如Java语言可以使用JavaAgent和bytebuddy技术实现对指定开源组件的自动监控,所以没有单独的快速监控(在OpenTracing中是分开的)。总结Opentelemetry的使命是收集高质量、大规模和便携的遥测数据,以启用有效的可观察性设施。它本身并不提供完整的可观测性解决方案,而是遥测数据采集的统一解决方案。而如果需要搭建一套完整的可观察性设施,还需要搭配相应的监控后端进行数据持久化和数据查询,比如Tracing后端zipkin/jaeger/tempo/、metrics后端prometheus、logs后端loki等。周东科往期精彩文章推荐:Tracing的前世今生(下)《云荐大咖》是腾讯云+社区的优质内容栏目。云推荐官特邀行业领袖,聚焦前沿技术落地与理论实践,持续为您解读云时代热点技术,探索行业发展新机遇。点击一键订阅,我们会定期为您推送优质内容。
