卡罗琳·罗德维希(Caroline Rodewig)和加勒特·麦格拉思(Garrett McGrath)是FlightAware飞行跟踪联队的成员。作为预测技术团队的负责人,卡罗琳致力于扩大我们预测应用的范围和质量。加勒特是航空平台机组人员的负责人,负责多机超级馈送的性能、可靠性和可观测性。
航空平台机组人员(有关机组人员和机翼的解释,请参阅此博客帖子)围绕Hyperfeed的性能和可靠性展开[1]。Hyperfeed是FlightAware的核心飞行跟踪引擎。它的输出为该公司最突出的服务提供了动力:网站上的航班页面、Firehose、FlightXML和航班警报。因此,如果Hyperfeed停止工作,FlightAware的大部分也会停止工作。考虑到超级馈送中断的影响,我们需要立即知道是否有问题-或可能出现问题-以便我们能够迅速而准确地采取行动来补救这种情况。为了保持Hyperfeed输出所需的准确性和及时性,我们在很大程度上依赖于监控[2]。为此,我们最近开始采用时间序列度量数据库Prometheus和功能强大的可视化平台Grafana。这些工具的引入标志着对Hyperfeed当前监控堆栈的重大升级和改进。希望通过分享我们的经验和通过的原因,我们可以帮助在类似情况下为其他人的决策提供信息。
在讨论普罗米修斯及其给我们的Hyperfeed监控带来的许多增强功能之前,我们先检查一下我们目前使用的是什么,以及它是如何随着时间的推移而演变的,这有助于提供一些背景信息。在目前的形式下,Hyperfeed是一个分布式系统,由分布在多台机器上的十几个组件和子系统组成,以实现性能和容错。它的子系统包括许多其他知名的服务:Postgres、ZooKeeper、Kafka和RabbitMQ。不过,情况并不总是这样的。当我在2016年开始研究Hyperfeed时,它并不是分布式的;它的所有组件都运行在一台机器上(严格来说并非如此,因为它还使用了运行在单独服务器上的Postgres数据库)。当然,当时的监测相对较不复杂:覆盖的表面积明显较小。我们结合了定制、内部工具和大剂量的Zabbix,能够有效地完成这项工作。
我们的自定义监控工具主要由一些脚本组成,这些脚本跟随在Hyperfeed的输出及其日志语句之后,查找问题,例如,输出已完全停止、输出已过期或发生了过多的回溯。这些工具是特定于Hyperfeed的,不能很好地推广到其他软件。另一方面,Zabbix一直是FlightAware的主要监控和警报框架。它在整个公司使用,并不特定于任何一款软件。当应用于Hyperfeed时,Zabbix监视运行应用程序的服务器的一些关键特征,例如CPU、内存、磁盘和网络使用率。此外,前面提到的自定义工具将它们的数据输入到Zabbix中,以便在出现问题时向工程师发出警报。最重要的是,Zabbix为我们提供了一个基本的Web界面,用于以图形格式查看它收集的数据。当Hyperfeed舒适地安装在一台服务器上时,这种监控服务得很好:Zabbix是提供所有监控服务的一站式商店。但随着对Hyperfeed的需求增加,其操作复杂性也随之增加。
最终,单机架构不足以处理Hyperfeed不断增加的输入量,这是由FlightAware获取新的数据源并扩展其现有数据源造成的。为了适应这种规模变化,有必要在多台机器上分发Hyperfeed。当这种情况发生时,我们继续使用(现在仍然在使用)自定义工具和Zabbix进行监控。不过,我们的定制工具和我们发送到Zabbix的数据也必须进行扩展。虽然在多台机器上分发超级馈送是必要的,并提高了系统的性能和可靠性,但它也带来了新的挑战和困难,特别是在监控方面[3]。
考虑到它们的起源,我们的定制工具在设计时并没有考虑到分布式设置。因此,它们缺乏跨多台机器轻松聚合数据的能力,并且随着Hyperfeed架构的发展,操作起来有些麻烦。此外,随着我们对Zabbix提出更多要求,Zabbix开始吱吱作响,露出一些粗糙的边缘。一个核心问题是,Zabbix在监控特定机器方面做得很好,但在系统或应用程序级别的监控方面做得不好,特别是在服务可以在故障发生时从一台机器移动到另一台机器的环境中,或者作为设计的有意部分。在分布式设置中,它还强制非TRI
过去6个月处理ADS-B职位所用时间的99%。
请注意,为了使捕获的数据量保持可管理性,触发每个事件的输入消息的内容被聚合在一起。例如,使用指标,可以在整个系统中测量离职率,但不能调查任何单一的离职率。正如Datadog简要总结的那样,度量提供了“大而宽泛的度量,可以帮助您快速回答有关系统内部运行状况和性能的最紧迫问题。”度量还可以捕获资源利用率(如CPU、内存或磁盘)以及元数据(如代码修订和配置值)。尽管有必要省略很多细节,但时间序列度量仍然是非常通用的,为整个系统的关键活动提供了实用的监控数据。
普罗米修斯的主要卖点之一是,它提供了一个强大的、概念上简单的数据模型,用于从感兴趣的系统中提取指标并跟踪其随时间的变化率。普罗米修斯跟踪的每个时间序列指标包括以下信息:
帮助文档:描述指标用途或指标来源的字符串。
度量类型:提供了四种类型,但其中两种类型提供了其他类型的原子构建块。基本类型是计数器和量规,计数器只能上升或复位,量规可以设置为任何值。
标签:将附加维度附加到指标的键-值对。标签提供了一种将更多细节附加到指标上的方式,而不是仅仅通过名称来传达。典型的例子是度量Web服务器响应时间的指标的URL路径。使用路径标签,不仅可以跟踪特定URL的响应时间,还可以聚合所有标签并查看任何路径的响应时间。标签为指标提供了额外的粒度,并在查询时提供了巨大的功能。
有了Prometheus数据模型,下一个主要卖点,正如上一节所暗示的,是它可以相对容易地直接从它监控的应用程序或系统公开白盒指标[6]。通常,这是通过使用所监视系统的语言的普罗米修斯客户端库来实现的。所有最流行的语言都已经有了一个库,但FlightAware是Tcl的重度用户,根据TIOBE指数,Tcl是一种较少使用的语言。TCL没有开放源码的普罗米修斯库可用,所以我不得不编写一个,以便充分利用普罗米修斯提供的功能[7]。值得庆幸的是,普罗米修斯项目有很好的文档,为库创建者提供了详细的指导,所以编写库的过程虽然不是微不足道的,但却相对简单和直截了当。有了客户端库,下一步就是在被监控的整个应用程序中使用它,然后将这些指标输入普罗米修斯。
要将客户端库中的数据放入Prometheus,需要一个进程通过HTTP公开其度量,并且Prometheus知道它可以请求度量的主机名和端口[8]。一旦数据到达普罗米修斯,它就可以使用Grafana可视化,使用由普罗米修斯项目维护的单独组件发出警报,并进行查询和探索。在计算和内存方面,使用普罗米修斯库检测应用程序是一个相对便宜的操作。由于指标会随时间聚合值,而不是构建一系列值来批量发送,因此给定的一组指标有恒定的内存成本;计算成本非常低,虽然不是免费的[9]。
除了直接使用客户端库插入代码之外,还有许多所谓的导出器可用于公开来自未考虑普罗米修斯度量的程序的度量,例如Postgres、Kafka或ZooKeeper。导出器充当翻译器,使用查询和探测直接观察应用程序,将这些观察的输出转换为普罗米修斯能够理解的格式,并通过HTTP公开结果指标,以响应来自普罗米修斯服务器的擦伤。有了出口商,许多最常见的开源服务器都可以很容易地使用普罗米修斯指标进行监控。如果特定服务不存在导出器,编写一个导出器是相当容易的,普罗米修斯的官方文档提供了一些这样做的指导。普罗米修斯不仅受益于可以使用客户端库的代码,而且整个项目还提供了一个非常活跃的产品生态系统,用于从我们的系统中获取白盒指标。
在讨论的这一点上,虽然已经概述了普罗米修斯的强大功能-它在概念上简单但功能强大,通过Grafana拥有强大的可视化支持,为动态、分布式系统构建,推广到FlightAware的其他分支,对白盒和黑盒监控有同样强大的支持,并在系统级观察和分析方面表现出色-但可能仍不清楚普罗米修斯比当前的Hyperfeed监控系统提供了什么好处。为了消除这类疑虑,我们现在来看两个具体的案例,在这两个案例中,普罗米修斯取代了我们目前的实践,并促进了我们对采用普罗米修斯来监控FlightAware基础设施的核心部分之一的普遍兴奋和热情。
第一个案例涉及一个内部图书馆,该图书馆目前尚未投入使用,但在Hyperfeed中用于白盒监控已有数年之久。这个内部库提供了一个事件计数器:它的API接受一些感兴趣的事件的名称,并在幕后递增一个整数。这些整数计数器存储在Hyperfeed用于共享状态的Postgres数据库中;数据库视图按天聚合计数器。虽然这个工具有很多值得称赞的地方--跟踪一段时间内的事件计数看似简单,但却是一种极其强大的技术--但它也遭遇了一系列导致其退役的问题:它最终对性能产生了负面影响;它的数据模型使聚合和速率计算变得困难;我们缺乏合适的可视化来探索它的数据。当我们淘汰该工具时,我们的意图是以一种更新、更改进的形式复兴它;普罗米修斯正是通过解决上述所有问题来做到这一点的(另外,它允许更多问题,并且不限于内部工具开发的用例)。
为了跟踪特定事件随时间的计数,普罗米修斯提供了计数器数据类型[10]。计数器只能增加或重置;计数器在任何给定时间的值并不有趣或重要,但值如何随时间变化才是真正重要的。虽然这看起来实现起来并不复杂,但普罗米修斯仁慈地为我们解决了与丢失数据或计数器重置相关的各种微妙之处。虽然我们的内部工具将计数器存储在Postgres中,并最终导致不可接受的性能问题,但普罗米修斯计数器只保留在内存中,供递增它们的进程使用,然后由普罗米修斯服务器收集和存储,这很好地解决了这个问题。此外,我们的内部工具没有很好地捕捉数据的维度,但普罗米修斯通过使用标签,在其设计中内置了这一功能。通过使用Grafana,这些计数器及其变化率可以轻松而有力地可视化,从而解决了我们内部工具的所有问题,并将其带回一种新的、大大改进的形式。
普罗米修斯和格拉凡纳对Hyperfeed的系统监控进行重大改进的第二种情况涉及测量和可视化Hyperfeed的输入速率。为了提供航班跟踪的全球画面,FlightAware综合了来自几十个不同来源的数据。因此,监视Hyperfeed的一个关键部分是监视其输入,测量其总速率,并将速率分解为数据源的子集。在普罗米修斯和格拉凡纳之前,这是通过扎比克斯完成的。虽然Zabbix可以毫无问题地收集有关Hyperfeed数据的数据,但考虑到数据提要的绝对数量,它在可视化方面遇到了巨大的困难;因此,它不容易支持数据探索。然而,普罗米修斯和格拉法纳却非常容易地很好地完成了这项任务。
首先,在Zabbix中,收集的度量是input.data feed name的形式。这使得查询总输入率或输入率的子集相当笨拙。另一方面,普罗米修斯的数据模型简明扼要
Thomas Sowell曾经断言“没有解决方案,只有权衡。”[12]Sowell写这句话的背景与系统监控相去甚远,但他的格言非常适用于软件和系统工程。以普罗米修斯为例,尽管人们对它的使用热情很高,也是当之无愧的,但重要的是不要过于乐观,没有认识到,就像所有其他技术一样,它也有缺点,不可能解决每一个监控问题。普罗米修斯的局限性的核心是它选择使用指标进行监控。尽管指标非常强大,对系统监视非常有用,但它必然会省略有关系统中事件的许多细节。对于调试或事后分析,这些细节通常正是所需的,这就是为什么日志记录是度量的重要补充。进一步推动这一点,所有基于指标的解决方案都必须。
.