资讯详情

云原生观测性 - OpenTelemetry

对于很多企业来说,应用的稳定性,以及出现问题时,如何快速定位到真正的原因,不断设计和完善的能力。主要体现在如何监控系统,如何快速从日志中发现错误,如何快速知道呼叫链是否有问题,以及应用程序运行中是否有问题,应用程序依赖的数据库和中间件是否有问题。这也是观测性的大三元素,监控,日志,链路,大家经常听到。随着云原生技术的发展,社区也在重新思考这些问题,不断提出新的标准。接下来,我们将介绍它 OpenTelemetry 这个技术。

主要总结察方案主要总结:

:filebeats->elasticsearch->kibana;filebeats->kafka->logstash->elasticsearch->kibana; fluentd->elasticsearch->kibana;fluentd->kafka->fluentd->elasticsearch->kibana 。

:统一使用 prometheus,prometheus-operator,thanos,grafana。

:主要方案有开源 skywalking,jaeger,zipkin,还有商业计划,比如 dynatrace 等。

方法论之一如何连接日志、监控、链路

答案是,不是很统一(商业计划不确定)。不同领域的重点不同。例如,我们可以使用关键业务模型 ID,Name 等三个技术方便的入口串起。将业务注入日志 ID;将业务注入监控数据 ID;在 trace 以标准化的方式注入业务 ID。这样,当某个业务对象在系统中出现问题时,就可以根据业务 ID,以相对统一的方式获取三个观测领域的相关数据。

用了 OpenTelemetry,我还需要重新规划业务 ID?事实上,你不能使用它。在三个观测领域中,有一个需要承担领导作用。谁越接近应用程序,谁就应该承担责任。 Trace。在 OpenTelemetry 三种观测能力的核心点是 trace id 和 span id。了解过Trace,应该知道 trace id 代表业务处理全局的上下文 ID,所以 OpenTelemetry 方案是 metrics 里,在 log 里增加了 trace id 和span id 字段。这样只需要根据告警,以及告警信息里嵌入的 trace id 和 span id (来源于嵌入报警规则 metrics 的名为 trace id 的 lable,以及对应的 value),你可以在出现问题的那一刻快速获得所有准确的观测数据。

方法论之二如何在最短的时间内定位问题?

在调查问题时,如何确定问题发生的事件?即使有报警辅助,业务和观察系统各自的处理部分也需要时间,具体时间如何确定?正常情况是知道问题是什么时候出现的。即便如此,如果你想快速定位这个问题,你仍然需要在准确的时间内整合三个观测数据。此时,你所能做的就是取一个相对较小的时间范围,如根据报警的大约十分钟或大约半小时。肉眼识别最后需要的日志仍然需要时间。这个时间也与参与调查问题的人的经验有关。这种情况是一个相对标准化和完美的游戏玩法。对于一些没有计划这些解决方案的团队来说,在很短的时间内更难发现问题。最后,首先保存日志,首先重新启动服务或重新启动机器,然后解决问题。这不是我们预期的解决方案。

同时通过 trace id 和 span id 串起三大能力。每个部分都需要时间。例如,监控是时间数据库,模式带有时间字段;例如,日志和日志框架有时间字段;例如,链路和链路也有时间字段。因为在收集三者时,每个模块的执行时间都有顺序,但可以保证这个时间范围必须在这个请求过程中,以便将时间范围缩短到一个非常短的时间范围,以实现准确的定位问题。

方法论之三如何定位相关资源的故障

因为分析需要知道真正的问题,不仅仅是应用本身。由于链路工具包中有内置应用所依赖的基础设施的访问链路分析,因此链路分析最为接近。在应用所依赖的基础设施的位置定位,下一个前提是所依赖的基础设施本身具有监控和报警的能力。查找基础设施监控数据进行显示和分析。但基础设施监控数据可能更多,如何快速发现问题,这需要在基础设施监控和报警能力的建设中,规划最常见问题的监控能力,该能力的建设在相关分析中更重要、更困难,数据的准确性取决于经验建设,减少不必要的监控数据和报警设置,防止有用的报警和监控数据被掩盖。

方法论之四如何构建与业务相关的观测能力?

与观测相关的工具只提供一些工具。要建立业务观测能力,需要根据需要观测的具体业务来关联观测数据。

最接近业务的是业务日志,这也是成本最低的方式。业务逻辑程序需要考虑业务虑业务的可操作性和维护性,因此需要在需要观察的业务逻辑日志中添加业务相关字段,包括当前操作的具体业务,以便根据固定的关键业务名称快速定位到相关的错误日志,并配合日志报警,以便第一次通过报警知道问题,以及再根据 logs 里带有的 trace 具体业务的链路信息快速定位。

建设与业务相关的监控能力,以程序化的方式为重要业务提供监控能力,如业务 A 访问频率和错误数,以便在出现问题时通过报警第一次知道,然后根据 metrics 里带有的 trace 具体业务的链路信息快速定位。

对需要支持观测能力的重要业务,定义和管理业务名称,向日志查询映射业务名称,向日志查询映射业务名称 metrics 指标查询语句或快速查看相应指标的入口。

OpenTelemetry 以解决观测为初衷的项目,包括链路、监控和日志。主要问题是观测领域模型、观测数据收集和观测数据输出的统一。这些统一主要体现在这些统一上 API 规范,SDK 实现规范、接口规范等。OpenTelemetry 不负责存储观测数据,需要存储这些观测数据 backend。OpenTelemetry 定义数据输出的规范,由主要制造商完成数据的持久性。

OpenTelemetry 它还提供了大量的语言开发 SDK,开发者需要使用他们熟悉的语言 SDK 完成应用程序的观察能力。目前,不同开发语言的支持程度不同。

主要组成:

:该组件与语言无关,主要定义规范,如API 的规范,SDK 开发规范,数据规范。使用不同的开发来源于具体的开发 SDK 按标准开发,保证标准化。

:这个组件与语言无关,主要定义 OpenTelemetry 的 OTLP 协议定义,OTLP 协议是 OpenTelemetry 数据传输的重要组成部分。如 SDK 到Collector,Collector 到 Collector,Collector 到 Backend数据传输遵循这些过程 OTLP 协议。

:是根据 SDK 支持不同语言的标准开发 SDK,如 java,golang,c 等语言的 SDK。在构建观察性时,客户可以直接使用社区提供的已开发的产品 SDK 来构建观测能力。社区也在此基础上提供了一些工具,这些工具已经集成了常见软件的对接。

:负责收集观测数据,处理观测数据,导出观测数据。

架构介绍:

:一般的应用程序,同时使用了 OpenTelemetry 的 Library (实现了 API 的 SDK)。

:也称为SDK,在客户端程序中收集观测数据,包括 metrics,traces,logs,处理观测数据,然后根据观测数据进行观测数据 exporter 通过不同的方式 OTLP 方式发送到 Collector 或直接发送 Backend 中。

:负责根据 OpenTelemetry 协议收集数据的组件,并将观测数据导出到外部系统。这里的协议是指 OTLP(OpenTelemetryProtocol)。如果不同的供应商想让观测数据持续到自己的产品中,他们需要遵循 OpenTelemetry 的标准 exporter 该协议接收数据并存储数据。同时,社区已经提供了普通开源软件的输出能力,如 Prometheus,Jaeger,Kafka,zipkin 等。图中看到的颜色不同 Collector,Agent Collector 是单机的部署方式,每台机器或容器使用一台,避免大规模使用 Application 直接连接 Service Collector;Servce Collector 是可以多副本部署的,可以根据负载进行扩容。

: 负责持久化观测数据,Collector 本身不会去负责持久化观测数据,需要外部系统提供,在 Collector 的 exporter 部分,需要将 OTLP 的数据格式转换成 Backend 能识别的数据格式。目前社区的已经集成的厂商非常多,除了上述的开源的,常见的厂商包括 AWS,阿里,Azure,Datadog,Dynatrace,Google,Splunk,VMWare 等都实现了 Collector 的 exporter 能力。

由于 Trace 是 OpenTelemetry 中,比较成熟的部分,下面以 opentelemetry-go 这个 SDK,来分析一下 Trace 部分的基本工作原理。对 Trace 本身的数据结构和知识点不在本篇文章中详解。

1.  开始一个 span。

2. 当客户的 App 要想记录一次 trace,需要在 code 里 call 这个 Start 方法,这个方法最后会返回一个 span 出来,后续 span 可以调用 span 的 End 接收这次的 trace。

3. 开始真正的初始化 span,保存 span 的 TraceID,SpanID,以及 span 的attributes,events,links,以及处理 span 限制的 spanLimits,以及 span 的 startTime,span的parent span,span 的 n ame 等一个 span 需要的相关属性。

4. 初始化处理 span 的所有类型的 processors,根据定义的 processor 去处理 span,目前只支持 simple 和 batch 两种,simple 是不推荐生产,因为是同步的 call,而且是一条一条的生产上推荐使用 batch,性能好。

5. 根据配置的所有 span 的 processors,使用每一个 processor 的 OnStart 的去处理 span,这里的 OnStart 其实是空实现。不管是 simple 类型的,还是 batch 类型的,目前都是一个是个空的方法,这个方法的定义的作用就是在开始处理 span 的时候,做一些处理。最后返回一个初始化后的 span 给到客户 (注意,要想让这个 span 真正的进入到整个 trace 里,还要调用 span 对象的 End 方)。

6. 由 tracer 返回开始的 span。

7. 当 call span 的 End 方法时候就会对 span 做一下快照,这里的快照只是将可读写的 span,复制到只读的 ReadOnlySpan 对象,通过 processor 的 OnEnd 方法放到 processor 的 queue 中,可见放到 queue 中等待发送出去的 span 都是只读的 sp.sp.OnEnd(s.snapshot()))。

8. 从 queue 获取 span 放到 batch 中,当 batch 的数量满了,或者到达了固定时间,都会将已经处于 end 状态的 span 通过 exporter 发送出去。

9. 从 queue 获取 span 放到 batch 中,当 batch 的数量满了,或者到达了固定时间,都会将已经处于 end 状态的 span 通过 processor 的 exportSpans 方法发送出去。

10. exportSpans 方法处理,只会去拿 processor 的 batch 字段的数据去处理,每次 exportSpans 时都是一次处理一个 batch 的数据。

11. 使用一个 batch 里的数据,进行转换成 collector 能接受的 trace 数据。

12. 使用 exporter 的 client,upload trace 数据到 collector。

13. 循环所有的 trace 数据,封装成 tracepb.Span, 由 Spans 方法再封装成 tracepb.ResourceSpans。

14. 定义一个 traces 发送的请求。

15. 进行发送 traces。

16. 在发送 traces 的时候,在 send 中 call singleSend 去发送数据,会有失败重试。

17. 使用 http 或者 grpc 的client,发送 tracepb.ResourceSpans 数据到 collector。

18. 将 batch 的数据处理完之后,清空一下 batch 字段,用于继续从 queue里面拿 span,用于下一个发送时机要去处理的 span 数据。

以 golang 的 SDK 的案例代码

Metrics 是业务系统监控所必须的工具。从使用者的角度,更加关心有哪些监控数据采集类型和场景。以下介绍 OpenTelemetry 中规范的几种类型以及每种类型的一些特性,来帮助理解。(Metrics 在 OpenTelemetry 中的实现部分是三大块中最复杂,篇幅有限,原理部分不在当前这篇文章中详细介绍)

6.1. Instrument 类型总结

 :递增的计数器。

:可增可减的计数器。

:统计一组数据,如直方图。

:异步方式的递增计数器。

:异步方式的可增可减计数器。

:异步的方式观测最新数据的计量器。

6.2. 聚合器类型总结

:类型匹配到 Counter,UpDownCounter,CounterObserver,UpDownCounterObserver。这类聚合器用于对数据做加法。

:类型匹配到 GaugeObserver。这类聚合器用于根据数据的时间,计算出最新时间点的数据。

:类型匹配到 Histogram。这类聚合器用于计算一组 Points 中 sum,count,buckets。

:类型匹配到 Histogram。这类聚合器用于计算 sum,count,min,max。

:类型匹配到 Histogram。这类聚合器虽然处理的也是一组 Points,但是不做任何计算,只是保存这些 Points。

:有三个聚合器都对应到了 Histogram Instrument,根据期望的分布统计选择对应的策略。NewWithHistogramDistribution 对应选择 Histogram 聚合器作为 Histogram Instrument 的聚合器 (默认推荐);NewWithExactDistribution 对应选择 Exact 聚合器作为 Histogram Instrument 的聚合器;NewWithInexpensiveDistribution 对应选择MinMaxSumCount 聚合器作为 Histogram Instrument 的聚合器; 

6.3. 同步/异步的区别

:类型匹配到 Counter,UpDownCounter,Histogram。由应用程序每次主动指定 Instrument 的监控数据,随着每次程序的执行而执行。如一次请求处理,在请求处理中设置请求次数。

:类型匹配到 CounterObserver,UpDownCounterObserver,GaugeObserver。由 SDK 每次的收集周期执行一次异步类型 Instrument 设置的回掉函数,在回掉函数中设置监控数据。如每次收集间隔是,统计一下程序的运行时间。

6.4. Adding 和 Grouping 的区别 

:类型匹配到 Counter,UpDownCounter,CounterObserver,UpDownCounterObserver。每次收集周期,Instrument 对应的聚合器关注于对同一个 Instrument 做加法。

:类型匹配到 Histogram,GaugeObserver。关注于一组数据的处理。如 GaugeObserver 对应的聚合器会保存 Points,Points 中保存着同一个 Instrument 在不同时间点采集的数据 (Point);Histogram 会计算一组Points 中的 sum,count,min,max,buckets,Points。

6.5. 对应的Prometheus类型 

 :Counter

:Gauge

:Histogram

:Counter

:Gauge

:Gauge

6.6 代码案例

以下介绍了 OpenTelemetry 中,Log 的数据格式规范。

Log4j2 支持 Trace,引用 OpenTelemetry 提供的 jar 包,以及修改配置文件。

Logback 支持 Trace,引用 OpenTelemetry 提供的 jar 包,以及修改配置文件。

Golang logrus 支持 Trace,在 code 里手动注入 trace 的相关信息。

OpenTelemetry 自己的 log sdk,在 code 里手动注入 trace 的相关信息。

这里先引入一个概念,Exemplars。Exemplars 的作用是连接 metrics 和 trace 的关键,也就是在 metrics 的数据里注入 trace id 和 span id。这种方式目前已经实现的开源软件有 Prometheus,OpenMetrics。OpenTelemetry 引用 OpenMetrics 的设计,也使用一样的概念完成在 OpenTelemetry 中注入 trace id 和 span id 到 metrics,区别是 OpenMetrics只实现 Histogram Instrument 类型的 Exemplars,OpenTelemetry 将会实现所有 Instrument 类型的 Exemplars 能力。

opentelemetry-java 最新版本是 1.7.0,已经支持了默认支持了 Exemplars,但还是 alpha 版本。OTEL_METRICS_EXEMPLAR_FILTER 这个环境变量默认值是 WITH_SAMPLED_TRACE 作,会自动将需要 sampled (trace中需要被采样的span) 的 trace id 以及 span id 和 metrics 关联起来。

: 

request_duration{path="/test",le="0.004"} 4.0 #{trace_id="043cd631811e373e4188e",span_id="cd122d2ca5b0"} 0.0033 1618261159.027

opentelemetry-go 目前版本暂时还没有实现这部分功能。

在使用工具的时候,都希望这个工具简单而且强大。

OpenTelemetry 的 java sdk 中,应用可以无需修改 code,只需要引用对应的 jar 包就可以完成对很多常见观测能力的集成。目前支持的集成已经比较广泛,包含常见的软件集成。主要包含,akka,camel,dubbo,httpclient,cassandra,couchbase,elasticsearch,finatra,geode,grails,grizzly,grpc,guava,get,hibernate,hystrix,jaxrs,jaxws,jdbc,jedis,jetty,jms,jsf,jsp,kafka,kubernetes,log4j,logback,mongo,netty,quartz,rabbitmq,reactor,redisson,rmi,rocketmq,scala,servlet,spark,spymemcached,struts,spring,tomcat,vertx等。使用了 OpenTelemetry 的 java 的 SDK,就可以自带这些软件的调用分析能力。

OpenTelemetry 的 golang sdk 中开始支持 http,grpc,beego,mongo,sarama (kakfa),host (程序所在主机的内存,网络,CPU使用),runtime (程序本身的资源使用,如 heap memory 的使用,gc 的情况),gocql,mux,gin,go-kit,go-restful,gomemcache 等,使用了 OpenTelemetry 的 go 的 sdk,就可以自带这些软件的调用分析能力。

collector 的 contrib,是各大厂商参与社区的主要方向之一, 其中对 receiver,processor,exporter 都进行了大量的扩展。

各种语言的 SDK 的 auto instrumentation,主要分布在各种语言 SDK 的 contrib 仓库中。使用了这些工具之后,可以具备更多自动化的能力,而不需要自己再基于 SDK 的基础能力去开发这些能力。举例,可以自动获取当前进程的运行状态等等。所以此类的能力也是社区参与度比较高的部分。

java 的 SDK 的版本是比较高的,因为目前企业还是 java 的系统偏多,其它版本低一点,但是 trace 部分也都发布了 1.0 以上的版本。

trace 的成熟度最高,基本可以商用。metrics 还在 alpha 阶段,最近还在变动 Instrument Kind,举例 ValueRecorder 改成了 Histogram。log 也是在 alpha 阶段,比 metrics 稍微落后一点,java 的 SDK 已经有 alpha 版本,但是 golang 的 SDK 中还没有任何 log 相关的实现。

OpenTelemetry 的出现,将会改变目前现有的观测能力的方案方向。重新定义云原生观测性能力。从目前的社区状态看,还有一些部分还不是很成熟,还需要一些时间。随着社区的发展,会有越来越多的 vendor 去适配,会有更多的观测能力方案和存储观测数据的方案集成到 OpenTelemetry 中。

最后,云原生交流群,欢迎加入参与交流互动:

标签: 防水型接线箱连接器jsf

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

 锐单商城 - 一站式电子元器件采购平台  

 深圳锐单电子有限公司