Micrometer Atlas
Atlas 是一个内存中的维度时间序列数据库,具有内置的绘图功能、自定义的基于堆栈的查询语言以及高级数学运算。Atlas 起源于 Netflix,目前仍然是其运营指标解决方案。
1. 安装 micrometer-registry-atlas
建议使用 Micrometer(或您的框架,如果有的话)提供的 BOM,您可以在此处查看如何配置它 here。以下示例假设您正在使用 BOM。
1.1. Gradle
在 配置 好 BOM 之后,添加以下依赖项:
implementation 'io.micrometer:micrometer-registry-atlas'
由于版本由 BOM 定义,因此此依赖项不需要指定版本。
1.2. Maven
在 配置 完 BOM 后,添加以下依赖:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-atlas</artifactId>
</dependency>
由于该依赖项的版本由 BOM 定义,因此不需要指定版本。
2. 配置
AtlasConfig atlasConfig = new AtlasConfig() {
@Override
public Duration step() {
return Duration.ofSeconds(10);
}
@Override
public String get(String k) {
return null; // accept the rest of the defaults
}
};
MeterRegistry registry = new AtlasMeterRegistry(atlasConfig, Clock.SYSTEM);
Micrometer 使用 Netflix 的 Spectator 作为底层工具库,用于记录发送到 Atlas 的指标。AtlasConfig
是一个带有默认方法的接口。如果在 get(String k)
的实现中,你将其绑定到一个属性源而不是返回 null
,则可以覆盖默认配置。例如,Micrometer 的 Spring Boot 支持将前缀为 management.metrics.export.atlas
的属性直接绑定到 AtlasConfig
:
management.metrics.export.atlas:
# The location of your Atlas server
uri: http://localhost:7101/api/v1/publish
# You will probably want to conditionally disable Atlas publishing in local development.
enabled: true
# The interval at which metrics are sent to Atlas. The default is 1 minute.
step: 1m
3. 图表绘制
本节将快速介绍如何在 Atlas 中呈现源自 Micrometer 的指标的有用表示。有关 Atlas 中可能性的更完整参考,请参阅 Atlas wiki。
3.1. 计数器
Atlas 以 PNG 图像的形式提供图表(以及其他输出格式)。
我们使用以下查询来可视化来自 Atlas 的计数器。请注意,该值是经过步长间隔速率归一化的,而不是单调递增的。Atlas 始终期望从 Micrometer 获取的计数器数据是速率聚合的。
图 1. 正偏差随机游走上的计数器。
GET /api/v1/graph?
q=
name,counter,:eq,
2,:lw
&tz=US/Central
&s=e-15m // <1>
&w=400 // <2>
&l=0 // <3>
Host: localhost:7101
我们希望在 x 轴上可视化的时间范围。
e
表示结束时间或“现在”。此图的时间轴从 15 分钟前到现在。Atlas 会自动从数据中选择最精细的步长间隔,以便在生成的图像上至少渲染 1px 宽。返回的 PNG 图像的总宽度应为 400px。
将 y 轴的下限设置为 0,以便随机游走中的波动看起来不那么剧烈。
3.2. 定时器
直接从 Timer
读取时返回的是一个 double
类型,但底层值在 Spectator 中是以纳秒精度的 long
类型存储的。在 Timer
接口中转换为 double
时丢失的精度不会影响像 Atlas 这样的系统,因为它已配置为从 Micrometer 隐藏的底层 Spectator Timer
中读取测量值。
Spectator Atlas 的 Timer
生成了四个时间序列,每个序列都有一个不同的 statistic
标签:
-
count
: 每秒调用次数。 -
totalTime
: 每秒总时间。 -
totalOfSquares
: 每秒总时间的平方(用于标准差计算)。 -
max
: 记录的最大值。
因此,您可以通过以下查询实现吞吐量(请求/秒)的线性增长:
name,timer,:eq,statistic,count,:eq,:and
请注意,statistic
只是一个可以像其他维度一样进行下钻和选择的维度。
此外,totalTime/count
表示平均延迟,可以使用简写 :dist-avg
查询来选择,该查询会选中 totalTime
和 count
时间序列并为我们执行除法运算:
name,timer,:eq,:dist-avg
在前面的示例中,你可以看到这两条线绘制在同一个双轴图表上。
图 2. 模拟服务上的计时器。
3.3. 长任务计时器
假设我们有一个任务,预期在 70 秒内完成,但实际上花费了两分钟。长任务计时器的一个关键优势是,在我们超过阈值后的第一个报告间隔内,我们能够收到警报。而使用常规计时器,我们只能在任务完成后的第一个报告间隔内收到警报。如果我们有一个 10 秒的发布间隔,常规计时器警报将比长任务计时器警报晚近一分钟到达。
图 3. 模拟的背靠背长任务。
GET /api/v1/graph?
q=
name,longTaskTimer,:eq,statistic,duration,:eq,:and, // <1>
:dup,
70,:gt,:vspan,f00,:color,40,:alpha,alerted,:legend, // <2>
70,f00,:color,alert+threshold,:legend // <3>
&tz=US/Central
&s=e-15m
&w=400
&l=0
&title=Peaks+of+Long+Tasks
&ylabel=time
Host: localhost:7101
表示连续发生的长任务的表示。
当长任务超过我们设定的 70 秒阈值时出现的垂直跨度。为了不让图表显得过于拥挤,我们还降低了垂直跨度的透明度。
将 70 秒的阈值绘制为一条单独的线。