可观测性行业正处在巨变中。
传统上,我们观察系统时使用的是一套筒仓式的、独立的工具,其中大部分包含结构不良(或完全非结构化)的数据。这些独立的工具也是垂直整合的。工具、协议和数据格式都属于一个特定的后端或服务,不能互换。这意味着更换或采用新的工具需要耗费时间来更换整个工具链,而不仅仅是更换后端。
这种孤立的技术格局通常被称为可观测性的 “三大支柱”:日志、度量和(几乎没有)追踪(见图 1-1)。
日志
记录构成事务的各个事件。
度量
记录构成一个事务的事件的集合。
追踪
测量操作的延迟和识别事务中的性能瓶颈,或者类似的东西。传统上,许多组织并不使用分布式追踪,许多开发人员也不熟悉它。
我们用这种方法工作了很久,以致于我们不常质疑它。但正如我们将看到的,“三大支柱” 并不是一种正确的结构化的可观测性方法。事实上,这个术语只是描述了某些技术碰巧被实现的方式,它掩盖了关于如何实际使用我们的工具的几个基本事实。
什么是事务和资源?
在我们深入探讨不同可观测性范式的利弊之前,重要的是要定义我们所观察的是什么。我们最感兴趣的分布式系统是基于互联网的服务。这些系统可以被分解成两个基本组成部分:事务和资源。
事务(transaction) 代表了分布式系统需要执行的所有动作,以便服务能够做一些有用的事情。加载一个网页,购买一个装满物品的购物车,订购一个共享汽车:这些都是事务的例子。重要的是要理解,事务不仅仅是数据库事务。对每个服务的每个请求都是事务的一部分。
例如,一个事务可能从一个浏览器客户端向一个网络代理发出 HTTP 请求开始。代理首先向认证系统发出请求以验证用户,然后将请求转发给前端应用服务器。应用服务器向各种数据库和后端系统发出若干请求。例如,一个消息系统:Kafka 或 AMQP,被用来排队等待异步处理的额外工作。所有这些工作都必须正确完成,以便向急切等待的用户提供结果。如果任何部分失败或耗时过长,其结果就是糟糕的体验,所以我们需要全面理解事务。
一路下来,所有这些事务都在消耗资源(resource)。网络服务只能处理这么多的并发请求,然后它们的性能就会下降并开始失效。这些服务可以扩大规模,但它们与可能调用锁的数据库互动,造成瓶颈。数据库读取记录的请求可能会阻碍更新该记录的请求,反之亦然。此外,所有这些资源都是要花钱的,在每个月的月底,你的基础设施供应商会给你发账单。你消耗的越多,你的账单就越长。
如何解决某个问题或提高服务质量?要么是开发人员修改事务,要么是运维人员修改可用资源。就这样了。这就是它的全部内容。当然,魔鬼就在细节中。
第四章将详细介绍可观测性工具表示事务和资源的理想方式。但是,让我们回到描述迄今为止我们一直在做的非理想的方式。
不是所有事情都是事务
请注意,除了跨事务之外,还有其他的计算模型。例如,桌面和移动应用程序通常是基于反应器(reactor) 模型,用户在很长一段时间内连续互动。照片编辑和视频游戏就是很好的例子,这些应用有很长的用户会话,很难描述为离散的事务。在这些情况下,基于事件的可观测性工具,如真实用户监控(RUM),可以增强分布式追踪,以更好地描述这些长期运行的用户会话。
也就是说,几乎所有基于互联网的服务都是建立在事务模式上的。由于这些是我们关注的服务,观察事务是我们在本书中描述的内容。附录 B 中对 RUM 进行了更详细的描述。
可观测性的三大支柱
考虑到事务和资源,让我们来看看三大支柱模式。将这种关注点的分离标记为 “三大支柱”,听起来是有意的,甚至是明智的。支柱听起来很严肃,就像古代雅典的帕特农神庙。但这种安排实际上是一个意外。计算机的可观测性由多个孤立的、垂直整合的工具链组成,其真正的原因只是一个平庸的故事。
这里有一个例子。假设有一个人想了解他们的程序正在执行的事务。所以他建立了一个日志工具:一个用于记录包含时间戳的消息的接口,一个用于将这些消息发送到某个地方的协议,以及一个用于存储和检索这些消息的数据系统。这足够简单。
另一个人想监测在任何特定时刻使用的所有资源;他想捕捉指标。那么,他不会为此使用日志系统,对吗?他想追踪一个数值是如何随时间变化的,并跨越一组有限的维度。很明显,一大堆非结构化的日志信息与这个问题没有什么关系。因此,一个新的、完全独立的系统被创造出来,解决了生成、传输和存储度量的具体问题。
另一个人想要识别性能瓶颈。同样,日志系统的非结构化性质使它变得无关紧要。识别性能瓶颈,比如一连串可以并行运行的操作,需要我们知道事务中每个操作的持续时间以及这些操作是如何联系在一起的。因此,我们建立了一个完全独立的追踪系统。由于新的追踪系统并不打算取代现有的日志系统,所以追踪系统被大量抽样,以限制在生产中运行第三个可观测系统的成本。
这种零敲碎打的可观测性方法是人类工程的一个完全自然和可理解的过程。然而,它有其局限性,不幸的是,这些局限性往往与我们在现实世界中使用(和管理)这些系统的方式相悖。
实际上我们如何观察系统?
让我们来看看运维人员在调查问题时所经历的实际的、不加修饰的过程。
调查包括两个步骤:注意到有事情发生,然后确定是什么原因导致了它的发生。
当我们执行这些任务时,我们使用可观测性工具。但是,重要的是,我们并不是孤立地使用每一个工具。我们把它们全部放在一起使用。而在整个过程中,这些工具的孤立性给操作者带来了巨大的认知负担。
通常情况下,当有人注意到一个重要的指标变得歪七扭八时,调查就开始了。在这种情况下,“毛刺” 是一个重要的术语,因为运维人员在这一点上所掌握的唯一信息是仪表盘上一条小线的形状,以及他们自己对该线的形状是否看起来 “正确” 的内部评估(图 1-2)。
在确定了线的形状开始看起来 “不对劲” 的那一点后,运维人员将眯起眼睛,试图找到仪表板上同时出现 “毛刺” 的其他线。然而,由于这些指标是完全相互独立的,运维人员必须在他们的大脑中进行比较,而不需要计算机的帮助。
不用说,盯着图表,希望找到一个有用的关联,需要时间和脑力,更不用说会导致眼睛疲劳。
就个人而言,我会用一把尺子或一张纸,只看什么东西排成一排。在 “现代” 仪表盘中,标尺现在是作为用户界面的一部分而绘制的线。但这只是一个粗略的解决方案。识别相关性的真正工作仍然必须发生在操作者的头脑中,同样没有计算机的帮助。
在对问题有了初步的、粗略的猜测后,运维人员通常开始调查他们认为可能与问题有关的事务(日志)和资源(机器、进程、配置文件)(图 1-3)。
在这里,计算机也没有真正的帮助。日志存储在一个完全独立的系统中,不能与任何指标仪表板自动关联。配置文件和其他服务的具体信息通常不在任何系统中,运维人员必须通过 SSH 或其他方式访问运行中的机器来查看它们。
因此,运维人员再次被留下寻找相关性的工作,这次是在指标和相关日志之间。识别这些日志可能很困难;通常必须查阅源代码才能了解可能存在的日志。
当找到一个(可能是,希望是)相关的日志,下一步通常是确定导致这个日志产生的事件链。这意味着要找到同一事务中的其他日志。
缺乏关联性给操作者带来了巨大的负担。非结构化和半结构化的日志系统没有自动索引和按事务过滤日志的机制。尽管这是迄今为止运维人员最常见的日志工作流程,但他们不得不执行一系列特别的查询和过滤,将可用的日志筛选成一个子集,希望能代表事务的近似情况。为了成功,他们必须依靠应用程序开发人员来添加各种请求 ID 和记录,以便日后找到并拼接起来。
在一个小系统中,这种重建事务的过程是乏味的,但却是可能的。但是一旦系统发展到包括许多横向扩展的服务,重建事务所需的时间就开始严重限制了调查的范围。图 1-4 显示了一个涉及许多服务的复杂事务。你将如何收集所有的日志?
分布式追踪是一个好的答案。它实际上拥有自动重建一个事务所需的所有 ID 和索引工具。不幸的是,追踪系统经常被看作是用于进行延迟分析的利基工具。因此,发送给它们的日志数据相对较少。而且,由于它们专注于延迟分析,追踪系统经常被大量采样,使得它们与这类调查无关。
不是三根柱子,而是一股绳子
不用说,这是一个无奈之举。上述工作流程确实代表了一种可怕的状态。但是,由于我们已经在这种技术体制下生活了这么久,我们往往没有认识到,与它可以做到的相比,它实际上是多么低效。
今天,为了了解系统是如何变化的,运维人员必须首先收集大量的数据。然后,他们必须根据仪表盘显示和日志扫描等视觉反馈,用他们的头脑来识别这些数据的相关性。这是一种紧张的脑力劳动。如果一个计算机程序能够自动扫描和关联这些数据,那么这些脑力劳动就是不必要的。如果运维人员能够专注于调查他们的系统是如何变化的,而不需要首先确定什么在变化,那么他们将节省大量宝贵的时间。
在编写一个能够准确执行这种变化分析的计算机程序之前,所有这些数据点都需要被连接起来。日志需要被连接在一起,以便识别事务。衡量标准需要与日志联系在一起,这样产生的统计数据就可以与它们所测量的事务联系起来。每个数据点都需要与底层系统资源 —— 软件、基础设施和配置细节相关联,以便所有事件都能与整个系统的拓扑结构相关联。
最终的结果是一个单一的、可遍历的图,包含了描述分布式系统状态所需的所有数据,这种类型的数据结构将给分析工具一个完整的系统视图。与其说是不相连的数据的 “三根支柱”,不如说是相互连接的数据的一股绳子。
OpenTelemetry 因此诞生。如图 1-5 所示,OpenTelemetry 是一个新的遥测系统,它以一种综合的方式生成追踪、日志和指标。所有这些连接的数据点以相同的协议一起传输,然后可以输入计算机程序,以确定整个数据集的相关性。
这种统一的数据是什么样子的?在下一章,我们将把这三个支柱放在一边,从头开始建立一个新的模型。