无论您是 DevOps、SRE 还是只是数据驱动的个人,您都可能沉迷于仪表板和指标。我们查看我们的指标以了解我们的系统在基础架构、应用程序或业务级别上的运行情况。我们相信我们的指标可以向我们展示我们系统的状态以及它在哪里出现问题。但是我们的指标能告诉我们到底发生了什么吗?您会惊讶于事实并非如此。
在这篇文章中,我将研究指标背后的数学和机制、一些常见的误解、如何才能拥有准确的指标,以及是否存在这样的事情。
指标本质上是原始事件的汇总。在此汇总过程中,事件被转换为数字数据点。一个简单的例子是系统中发生的错误,用一个简单的指标来计算错误。指标还可以涉及多个变量,例如响应时间高于 1 秒的请求计数。当随着时间的推移进行测量时,这些数据点形成一个时间序列。
指标可以有多种类型,例如计数器、仪表和直方图。正如我们在上面的示例中看到的,计数器用于事件的累积计数。仪表通常代表最新的测量值。然后还有更精细的类型,例如直方图,它可以通过计算可配置的“桶”或“箱”中的事件来对指标值的分布进行采样。例如,您可能想了解给定时间点内集群中 pod 分段的内存使用百分比。
在理想情况下,我们会摄取并存储所有原始事件,然后计算查询时间的指标。这将使我们能够以我们需要的任何方式对事件进行切片和切块,并提出我们想要的任何临时问题。
然而,在现实世界中,由于数据量很大,将所有原始事件保存很长时间可能会非常昂贵。为了克服这个问题,事件经常被汇总到收集管道中的指标中,同时丢弃原始事件或仅短期保留它们。这通常是您的指标收集器代理中的简单配置问题。
除了降低成本之外,收集时的聚合还可以提高实时分析的性能,以更高的频率传输更高的指标和摄取率,并避免在查询时间进行繁重的聚合和计算。
这个汇总过程涉及一些数学。我们可能想要计算响应时间的平均值或中值,或者可能是百分位数,或者是时间窗口内的聚合。我们可能还想将多个事件汇总到一个复合指标中。例如,我可能想要计算集群中特定服务的所有 pod 的第 95 个百分位数(通常称为 P95)。
即使您不喜欢数学,也无法通过度量来避免它。您需要了解不同的聚合函数,以及您希望提出的问题与回答问题所需的指标和聚合之间的关系。让我们以 Average 函数为例,因为许多人倾向于从那里开始。根据定义,平均数会使事情变得平滑,并且不太适合清除异常行为和异常值。例如,在调查延迟问题时,查看平均指标值将毫无用处,最好还是查看百分位数。
在某种程度上,您可以将这些指标视为有损压缩,在此期间我们会丢失原始事件的数据和上下文。如果我们不保留原始事件,那么我们需要预先确定什么对我们很重要。例如,如果我只计算数据的平均值,我将无法在以后对预聚合数据询问 P95(第 95 个百分位数)。
您需要确定要回答的问题、对您重要的问题,并相应地设计指标和聚合。一个常见的错误是人们避免了这个设计阶段,而只是使用他们选择的指标收集器开箱即用的预设指标和默认值。虽然您可能认为这些默认值代表了一些行业标准,但这些默认值通常是相当陈旧的,并且在大多数情况下不会与您的特定需求保持一致。
就像在物理学中一样,当我们以离散的间隔(通常称为采样间隔)测量(看似)连续的属性时,就会出现测量问题,它决定了采样率。这会产生扭曲的表示,其中指标可能实际上不反映最初测量的属性。例如,如果我们每 60 秒测量一次 CPU 利用率,那么这些采样点之间发生的任何 CPU 异常值对我们来说都是不可见的。
此外,为了绘制一条连续的线,可视化工具通常会对连续的数据点进行平均,这会产生一种误导性的平滑线外观。在某些情况下,可能会出现相反的情况,您可能会在指标中获得不真实的伪影,例如指标中并不存在的峰值。由于进行计算的原因,在存储后端运行聚合时可能会发生这种情况。
采样周期还会影响系统变化在指标中可见的速度。大多数算法需要五个数据点来检测趋势。如果采样间隔为 60 秒,则简单的数学计算确定需要五分钟(即 60 秒 X 5 个数据点)我们才能发现错误。你能等 5 分钟才知道你的系统崩溃了吗?使用更短的采样间隔(即更高的采样率)将缩短这个周期并使我们能够更快地检测和做出反应。当然,更高的采样率会导致 CPU 和存储开销,因此我们需要找到能够满足我们需求的配置。
一种常见的做法是在分层方法中以不同的分辨率保存指标,以降低成本。例如,您可能希望在第一天每 10 秒保存一次指标,然后在下周每 5 分钟保存一次,可能在接下来的一个月或更长时间里每 1 小时保存一次。这种做法假设我们需要近乎实时的最细粒度,如果系统出现问题,我们可能需要它,而更长时间的调查需要更大规模的趋势。
不同的粒度可以通过缩小度量来实现,即从较高粒度的度量中计算出较小粒度的度量。虽然这听起来非常合理,但数学可能会干扰这里,因为某些聚合函数与某些计算不兼容,因此以后无法聚合。例如,百分位数是不可加的,不能相加。所以,按照上面的例子,如果你有一个以 10 秒分辨率采样的 P99 百分位数,你不能将它们滚动到 5 分钟分辨率。重要的是要认识到聚合函数的兼容性,并且在使用百分位数等不兼容函数时,做出关于我们需要哪些分辨率的设计决策,并预先计算这些时间序列。
变化的分辨率不仅限于时间因素。另一个例子是保存每个 pod 的数据,然后希望“分组”节点或集群。同样的约束适用于此,这意味着如果我们希望对每个节点、每个区域、每个命名空间或整个集群的基于百分位的指标进行切片和切块感兴趣,我们需要相应地进行预聚合。
另一种方法是通过使用直方图放弃测量的准确性以获得计算的兼容性。您可以获取几个服务器的直方图并将它们相加,或者多个时间窗口的直方图并将它们相加,然后进行缩小。问题是在这种情况下,百分位数将是估计值而不是准确值。同样重要的是要注意,直方图在存储和吞吐量方面更耗时,因为每个样本不仅仅是一个数字,而是几个样本(每个桶一个)。
指标是监控我们的应用程序的一种强大方式。但它们不一定代表实际系统的状态。它需要了解指标的数学和性质,以及精心设计,以确保我们的指标确实有助于回答我们需要的问题。除了指标之外,还可以访问原始数据总是好的,因为这最终是真相的来源。
想了解更多?查看 OpenObservability Talks 剧集:所有指标都是错误的,有些指标在Spotify 、 Apple 播客或其他播客应用程序上很有用。
这篇文章最初是在这里。