遥测技术
背景
当我们使软件系统成为分布式时,首先要做的事情之一就是观察和理解应用程序作为一个整体在做什么。
但是理解一个复杂的系统很困难,如果它是一个黑匣子。点燃这些黑匣子的唯一方法是使用高质量的遥测技术:分布式跟踪、度量、日志等等。
那么,我们如何才能从整个现代软件栈中获得精确、低开销的遥测数据呢?
一种方法是仔细地检测每一个微服务,一件一件,一层一层。这将是真正地工作,它也是完全不适合初学者 - 我们将花在测量上的时间和我们在软件本身上的时间一样多!
我们需要将遥测技术作为我们服务的一项内置功能。
三大支柱
Metrics:应用于服务拓扑,指标分析,监控报表,告警
Metrics 是一种聚合态的数据形式,日常中经常会接触到的 QPS、TP99、TP95 等等都属于Metrics 的范畴,它和统计学的关系最为密切,往往需要使用统计学的原理来做一些设计;
Tracing:应用于全链路跟踪数据,请求级别
Tracing 这个概念几乎是由 SOA 时代带来的复杂性补偿,服务化带来的长调用链,仅仅依靠日志是很难去定位问题的,因此它的表现形式比 Metrics 更复杂,好在业界涌现出来了多个协议以支撑 Tracing 维度的统一实现;
Logging:应用于服务拓扑,请求分析,链路回溯,告警源
Logging 是由请求或者事件触发,应用程序当中用以记录状态快照信息的一种形式,简单说就是日志,但这个日志不仅仅是打印出来这么简单,它的统一收集、存储以及解析都是一个有挑战的事情,比如结构化(Structured)与非结构化(Unstructed)的日志处理,往往需要一个高性能的解析器与缓冲器;
关系图
- Low volume 低存储量级
- High volume 高存储量级
协议标准
- OpenTracing 分布式跟踪 API,以 tracing 为主
- OpenCensus 谷歌开源分布式追踪,用于处理 metric 和 trace 的标准通信协议和一致的 API
- OpenTelemetry 云原生,合并 OpenTracing 与 OpenCensus
知名中间件
tracing 追踪
- zipkin 老牌,2012
- jaeger 新兴,云原生 lstio 2016
- skywalking 新兴 2015,国人佳作
metrics 指标
- statsd, graphite/Prometheus
logging 日志
- fluentd (k8s) / ELK(传统)
- Envoy access log
OpenTelemetry 项目
OpenTelemetry 合并了 OpenTracing 和 OpenCensus 项目,提供了一组 API 和库来标准化遥测数据的采集和传输。OpenTelemetry 提供了一个安全,厂商中立的工具,这样就可以按照需要将数据发往不同的后端。
OpenTelemetry项目由如下组件构成:
- 推动在所有项目中使用一致的规范
- 基于规范的,包含接口和实现的APIs
- 不同语言的SDK(APIs的实现),如 Java, Python, Go, Erlang 等
- Exporters:可以将数据发往一个选择的后端
- Collectors:厂商中立的实现,用于处理和导出遥测数据
术语
- Traces 记录经过分布式系统的请求活动,一个trace是spans的有向无环图
- Spans 一个trace中表示一个命名的,基于时间的操作。Spans嵌套形成trace树。每个trace包含一个根span,描述了端到端的延迟,其子操作也可能拥有一个或多个子spans。
- Metrics 在运行时捕获的关于服务的原始度量数据
- Context 一个span包含一个span context,它是一个全局唯一的标识,表示每个span所属的唯一的请求,以及跨服务边界转移trace信息所需的数据
- Context propagation 表示在不同的服务之间传递上下文信息,通常通过HTTP首部。 Context propagation 是 Opentelemetry 系统的关键功能之一除了tracing之外,还有一些有趣的用法,如,执行A/B测试,全链路测试标记
优势
通过将 OpenTracing 和 OpenCensus 合并为一个开放的标准,OpenTelemetry 提供了如下便利:
选择简单:不必在两个标准之间进行选择,OpenTelemetry 可以同时兼容 OpenTracing 和OpenCensus。
跨平台:OpenTelemetry 支持各种语言和后端。它代表了一种厂商中立的方式,可以在不改变现有工具的情况下捕获并将遥测数据传输到后端。
简化可观测性:正如 OpenTelemetry 所说的”高质量的观测下要求高质量的遥测”。希望看到更多的厂商转向 OpenTelemetry,因为它更方便,且仅需测试单一标准。
架构
OpenTelemetry 的默认实现中,其架构可以分为如下三部分
- OpenTelemetry API
- OpenTelemetry SDK
- Collector
架构图
API
- 语义规范 该规范包含了命名 spans,属性以及与 spans 相关的错误
- A Tracer API 生成spans,可以给 span 分配一个 traceId,也可以选择性地加上时间戳
- A Metrics API 提供了多种类型的 Metric instruments(桩功能),如 Counters 和 Observers。Counters 允许对度量进行计算,Observers 允许获取离散时间点上的测量值。
- A Context API 会在使用相同 “context” 的 spans 和 traces 中添加上下文信息如 W3C Trace Context, Zipkin B3 首部, 或 New Relic distributed tracing 首部
SDK
OpenTelemetry SDK 是 OpenTelemetry API 的实现
- Tracer pipeline
当配置 SDK 时,需要将一个或多个 SpanProcessors 与 Tracer pipeline 的实现进行关联。SpanProcessors 会查看 spans 的生命周期,然后在合适的时机将spans传送到一个 SpanExporter。SDK中内置了一个简单的 SpanProcessor,可以将完成的 spans 直接转发给 exporter。
Tracer pipeline 的最后是 SpanExporter。一个 exporter 的工作很简单:将 OpenTelemetry 的spans 转换为遥测后端要求的表达格式,然后转发给该后端即可。提供定制化的SpanExporter是遥测厂商参与 OpenTelemetry 生态系统的最简单方式。
- Meter pipeline
Meter pipeline 会创建和维护多种类型的 metric 工具,包括 Counters 和 Observers。每个工具的实例都需要以某种方式聚合
默认情况下,Counters 通过累加数值进行聚合,而 Observers 通过采集记录到的最后一个数值进行聚合。所有的工具默认都有一个聚合
不同语言的 Meter pipeline 的实现会有所不同,但所有场景下,metric 的聚合结果都会被传递到MetricExporter。与 spans 类似,供应商可以提供自己的 exporter,将由 metric aggregators生成的聚合数据转换为遥测后端所需的类型
OpenTelemetry 支持两种类型的 exporter:基于 exporters 的”push”,即 exporter 按照时间间隔将数据发送到后端;基于 exporters 的”pull”,即后端按照需要请求数据。New Relic 是一个基于push的后端,而 Prometheus 是一个基于 push 的后端。
- Shared Context Layer
位于 Tracer 和 Meter pipeline 之间,允许在一个执行的 span 的上下文中记录所有非observer的metric。可以使用 propagators 自定义Context,在系统内外传递 span 上下文。OpenTelemetry SDK 提供了一个基于 W3C Trace Context 规范的实现,但也可以根据需要来包含 Zipkin B3 propagation 等。
Collector
OpenTelemetry Collector 提供了一种厂商中立的实现,无缝地接收,处理和导出遥测数据。此外,它移除了为支持发送到多个开源或商业后端而使用的开源可观察性数据格式(如 Jaeger,Prometheus 等)的运行,操作和维护。
OpenTelemetry collector可以扩展或嵌入其他应用中。下面应用扩展了collector:
- opentelemetry-collector-contrib
- jaeger