速率聚合
Micrometer 能够识别特定的监控系统是否期望在指标发布之前进行客户端速率聚合,或者作为服务器查询的一部分进行临时聚合。它会根据监控系统期望的样式来累积指标。
并非所有的测量结果都以速率形式报告或最佳展示。例如,仪表值和活动任务计数长任务计时器就不是速率。
服务端
监控系统在执行服务器端速率计算时,期望在每个发布间隔报告绝对值。例如,自应用程序开始以来计数器所有增量的绝对计数将在每个发布间隔发送。
假设我们有一个略微正向偏移的随机游走,它选择每 10 毫秒递增一次计数器。如果我们在 Prometheus 这样的系统中查看原始计数器值,我们会看到一个阶梯状的单调递增函数(阶梯的宽度是 Prometheus 轮询或抓取数据的间隔)。
在某些时间窗口内,不进行速率聚合的计数器表示很少有用,因为这种表示既是计数器递增速度的函数,也是服务寿命的函数。在前面的例子中,计数器在服务重启时会回落到零。一旦新实例(例如在生产部署中)投入服务,速率聚合的图表将很快恢复到大约 55 的值。
如果你已经实现了零停机部署(例如,通过红黑部署),你应该能够轻松地在速率聚合图上设置最小警报阈值,而不会因为服务重启导致计数器值下降。
对于大多数生产用途,无论是告警、自动化金丝雀分析还是其他用例,都应以速率聚合数据为基础进行自动化。
客户端
其他两类监控系统要么是:
-
期望速率聚合数据。考虑到关键见解,对于大多数生产目的,我们应该基于速率而非绝对值做出决策。这样的系统受益于需要较少的数学计算来满足查询。
-
几乎没有或没有数学操作,可以通过查询进行速率聚合数据。对于这些系统,发布预聚合数据是构建有意义表示的唯一方式。
Micrometer 通过一个步进值有效地维护速率数据,该步进值会累积当前发布间隔内的数据。当轮询步进值时(例如在发布时),如果步进值检测到当前间隔已过,它会将当前数据移动到“先前”状态。这个先前状态将一直报告,直到下一次当前数据覆盖它为止。下图展示了当前状态和先前状态的交互,以及轮询的过程:
poll
函数返回的值始终是 每秒速率 * 间隔。如果前面图像中显示的步长值表示计数器的值,我们可以说计数器在第一个间隔内看到了“每秒 0.3 次增量”,这个值可以在第二个间隔内的任何时间报告给后端。
Micrometer 计时器至少会分别记录计数和总时间作为单独的测量值。假设我们配置了每 10 秒发布一次数据,并且我们观察到有 20 个请求,每个请求耗时 100 毫秒。那么,在第一个时间间隔内:
-
count
= 10 秒 * (20 请求 / 10 秒) = 20 请求 -
totalTime
= 10 秒 * (20 * 100 毫秒 / 10 秒) = 2 秒
count
统计量本身是有意义的:它是吞吐量的度量。totalTime
表示间隔内所有请求的总延迟。此外,还需要考虑:
totalTime / count
= 2 秒 / 20 请求 = 0.1 秒 / 请求 = 100 毫秒 / 请求
这是一个衡量平均延迟的有用指标。当同样的概念应用于来自分布摘要的 totalAmount
和 count
时,该指标被称为分布平均值。平均延迟只是以时间(计时器)衡量的分布摘要的分布平均值。一些监控系统(如 Atlas)提供了从这些统计数据中计算分布平均值的功能,而 Micrometer 将 totalTime
和 count
作为单独的统计数据提供。其他系统(如 Datadog)没有内置这种操作,Micrometer 在客户端计算分布平均值并发送该值。
发布间隔的速率足以推断任何大于或等于发布间隔的时间窗口内的速率。在我们的示例中,如果某个服务在给定的一分钟内,每 10 秒的间隔内持续接收 20 个请求,每个请求耗时 100 毫秒,我们可以说:
-
Micrometer 每 10 秒报告一次
count
为“20 个请求”。监控系统将这六个 10 秒间隔的数值相加,得出每分钟有 120 个请求的结论。请注意,这是监控系统在进行求和,而不是 Micrometer。 -
Micrometer 每 10 秒报告一次
totalTime
为“2 秒”。监控系统可以将一分钟内的所有总时间统计数据相加,得到一分钟内的总时间为“12 秒”。然后,平均延迟如我们所预期的那样:12 秒 / 120 个请求 = 100 毫秒/请求。