分布式追踪的简介

106 阅读9分钟

目前和正在进行的对分布式追踪的反应是不同的,也是有分歧的。仍然有一种强烈的感觉,即分布式追踪是一项巨大的投资,对于大型组织来说,其回报可能有限。随着我们的进步,这种观念将逐渐消失。对于调试涉及几个以上服务的问题的工程师来说,分布式跟踪不可避免地成为一个宝贵的工具。

那么,为什么我们要关心分布式跟踪?公司已经将他们的软件架构从单体进化到了微服务。这种演变导致了大规模的分布式系统的诞生。

在处理分布式系统的时候,我们通常会面临两个操作上的挑战。

网络

在单体应用中管理网络是一项相当简单的任务。客户端和服务器之间的路径是有限的。这使得连接性、性能和安全性可以在单一或有限的流量中得到管理。当处理分布式系统时,网络的复杂性增加了许多倍。它允许我们将交易路由到正确的地方,动态地扩大和缩小,并控制对不同服务的访问和授权。在分布式系统的世界里,客户端和应用程序之间的路径变得更加曲折和难以推理。这个挑战就是为什么像EnvoyIstioConsul这样的工具作为管理分布式基础设施连接的工具越来越受到欢迎。

单一的可观察性

可观察性是指了解事务如何在网络和基础设施中流动。在一个单体应用中,比如说Java应用,对事务的状态和性能进行推理是可行的。客户端通过负载均衡器向网络或应用服务器发出网络请求,通常会创建一些数据库事务,并对记录进行查询或更新,然后生成一个响应返回给客户端。

Monolith 单片机

虽然在整个过程中存在跳转,但事务通常采取从客户端到服务器的线性路径。

Monolith trace 单片机追踪

  1. 客户端发起a1 请求。
  2. a1 请求进入网络。
  3. a1 请求在负载均衡器处终止。
  4. a2 请求来自负载均衡器。
  5. a2 请求在应用服务器上终止。
  6. a3 请求来自于应用服务器。
  7. ..
  8. a3 响应在客户端终止。

很有可能对每一个环节进行检测,并通过单片机直观地看到事务的状态和它的性能。

更重要的是,即使通过这些跳转,我们也可以通过应用程序的生命周期将请求和响应事务映射到一个标识符。我们可以从该事务的生命周期中看到它发生了什么,它的表现如何,识别瓶颈等。

分布式系统的可观察性

分布式系统由代表一个复杂实体的几个微服务组成。一个事务经过多个服务,可以触发多个DB事务、其他事务或在服务间来回移动。

Distributed system 分布式系统

在这里,事务的路径是非常不同的。我们曾假设我们的系统位于一个单一的虚拟实体中。相反,一个分布式系统大多存在于多个虚拟位置,由边缘的服务和分布在各区域的服务组成。

Distributed trace 分布式跟踪

  1. 客户端发起a0 请求。
  2. a0 向服务b发送一个消息。
  3. c0 执行一个本地事件。
  4. a1 接收来自服务b的消息。
  5. c1 执行一个本地事件。
  6. a2 执行一个本地事件。
  7. b1 向服务c发送一个消息。
  8. c3 向服务b发送消息。
  9. b3 向服务a发送一个消息。
  10. 等等。

这种缺乏明确的线性路径的情况使得跟踪事务变得很有挑战性和乏味。由于没有单一的服务,通常很难将客户的请求映射到交易中。依靠传统和常规的工具来进行性能监控和瓶颈,可能无法清楚地了解到底在哪里发生了什么。

那么,分布式跟踪是如何帮助我们的呢?

追踪在我们的应用程序中跟踪行动或事件,记录它们的时间并收集有关行动或事件性质的其他信息。为了有效地使用分布式跟踪,我们需要对我们的代码进行检测,以便为我们想要监控的动作产生跟踪,例如,一个HTTP请求。追踪包裹着请求,并记录请求和响应周期的开始和结束时间。

span是跟踪的主要组成部分。一个跨度代表分布式系统中的一个单独的工作单位。跨度通常有一个开始和结束时间。

一个跟踪包含一个以上的跨度。在我们上面的例子中,我们的a2b3 、等请求是一个跟踪中的跨度。这些跨度通过一个跟踪ID连接在一起。这使得我们有可能建立一个请求在系统中传播的完整生命周期的视图。

跨段也可以有用户定义的标签形式的注释,允许我们为跨段添加元数据,以帮助理解跟踪的来源和产生的背景。

最后,跨度还可以以 key:value 对的形式携带日志,这对应用程序的信息输出很有用,可以设置一些背景或记录一些特定的事件。

OpenTracing 文档描述了一个典型跨度的例子,说明了这个概念。

open tracing 开放式跟踪

这些跟踪数据,连同其跨度和跨度上下文,然后被提供给后端,在那里被索引和存储。然后,它可用于查询或在可视化工具(如Grafana)中显示。

分布式跟踪是如何融入基础设施和监控阶层的?

分布式追踪器是监测分布式系统的工具和框架。这方面的情况相对复杂。有几家公司已经开发并发布了解决这些问题的工具,尽管现阶段它们在很大程度上仍处于萌芽状态。让我们来看看前两个主要的追踪框架。

OpenCensus和OpenTracing都是工具和框架。它们都试图为分布式追踪产生一个 "标准",尽管不是一个正式的标准。

OpenCensus

OpenCensus是一套API、语言支持和规范,基于一个叫做Census的谷歌工具,用于从应用程序中收集指标和跟踪,并将它们输出到各种后端。OpenCensus提供了一个通用的上下文传播格式,并提供了一个一致的方式来检测多语言的应用程序。

开放追踪

OpenCensus的另一个选择是OpenTracing。OpenTracing提供了一个类似的框架、API和跟踪库。它从Zipkin中脱颖而出,为追踪提供了一个与厂商无关的、跨平台的解决方案。与OpenCensus不同的是,它没有对指标的任何支持。这里提到的很多工具,如ZipkinJaegerAppdash,都采用了OpenTracing的规范。它也得到了Datadog等商业组织的支持,并被云原生计算基金会所接受。

让我们来看看几个更倾向于监控的工具。

Zipkin

Zipkin是由Twitter开发的,用Java编写,是开源的。它支持Cassandra和Elasticsearch作为存储跟踪数据的后端。它实现了HTTPKafka作为通信协议,但也有其他协议选项,如Apache ActiveMQgRPCRabbitMQ

Zipkin有一个客户端-服务器架构。它把客户端称为 "报告者",这些是为我们的应用程序提供工具的组件。报告者将数据发送到收集器,收集器对跟踪进行索引和存储,并将它们传入存储。

zipkin zipkin

不过Zipkin与经典的客户端-服务器应用程序略有不同。为了防止跟踪阻塞,Zipkin只传送一个跟踪ID,以表明跟踪正在发生。报告者收集的实际数据会被异步发送到收集器,就像许多监控系统在带外发送指标一样。Zipkin还配备了一个查询接口/API和一个Web UI,我们可以用它来查询和探索跟踪。

Jaeger

Jaeger是在Uber工作的产物。它也是由CNCF孵化的。它用Go编写,和Zipkin一样使用Thrift进行通信,支持Cassandra和ElasticSearch作为后端,并且与OpenTracing项目完全兼容。

Jaeger的工作方式与Zipkin类似,但依赖于对跟踪数据的采样,以避免被埋没在信息中。它使用概率抽样算法,对约0.1%的仪器化请求进行抽样,即千分之一。如果需要,你可以调整这个采集,以获得更多或更少的数据。

和Zipkin一样,Jaeger也有客户端来检测我们的代码。但Jaeger有一个运行在每个主机上的本地代理,接收来自客户端的数据,并将其分批转发到收集器上。一个查询API和Web UI提供了跟踪数据的接口。

Appdash

和Jaeger一样,Appdash也是开源的,基于Go,但由Sourcegraph的团队创建。它也支持OpenTracing这种格式。它还没有像其他玩家那样成熟,需要更多的摆弄才能开始使用,并且缺乏一些文档。

Appdash的架构让人联想到Jaeger,客户端对你的代码进行检测,本地代理收集跟踪数据,中央服务器对跟踪数据进行索引和存储。

这篇文章的目的是让你对分布式跟踪有一个基本的了解,以及为什么在处理多个微服务时它是必要的。我鼓励你探索上述工具,列出你应用程序中的主要工作流程,并对其进行检测。这将很快成为了解你的应用程序如何表现和执行的端到端工作流程的一个非常强大的窗口。