spring-boot整合Micrometer+Prometheus

news2024/11/18 12:41:54

环境:
micrometer 1.8.2
prometheus 0.14.1
spring-boot-actuator 2.6.6

使用案例

<!-- Springboot启动actuator,默认会引入依赖:micrometer-core -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
  <version>2.6.6</version>
</dependency>
<!-- micrometer桥接prometheus包,默认会引入相关依赖:io.prometheus:simpleclient -->
<dependency>
  <groupId>io.micrometer</groupId>
  <artifactId>micrometer-registry-prometheus</artifactId>
  <version>1.8.2</version>
</dependency>

Timer

打点记录任务的每次执行时间。兜底默认的时间窗口是1分钟。如果想要修改可以配置:io.micrometer.core.instrument.distribution.DistributionStatisticConfig.Builder#expiry

Metrics.timer("my_name", "my_tag_1", "my_tag_2").record(() -> {
    doMyJob();
});

LongTaskTimer

与Timer类似,记录任务执行时间,官方注释中也说了LongTask是一个主观判断,比如:1分钟以上的任务
一个比较大区别在于多了一个接口方法:io.micrometer.core.instrument.LongTaskTimer#activeTasks
获取当前正在执行中的任务数量

Metrics.more().longTaskTimer("my_name", "my_tag").record(doMyJob());

Gague

在服务器拉取指标时,或者客户端上报指标时,调用提供的对象与方法获取当前指标。即:记录的是当前状态

RingBuffer<MatchingOutput> rb = disruptor.getRingBuffer();
Metrics.gauge("ringbuffer_remaining", Tags.of("my_tag_1", "my_tag_2"), rb, RingBuffer::remainingCapacity);

Counter

计数器打点

Metrics.counter("my_request", "my_tag_1", "my_tag_2").increment();

DistributionSummary

跟踪事件的样本分布。 一个例子是访问 http 服务器的请求的响应大小。

DistributionSummary ds =  DistributionSummary.builder("my.data.size")
    .tag("type", "my_type_1")
    .publishPercentileHistogram()
    .register(Metrics.globalRegistry);
ds.record(myValue);

配置actuator

配置指标拉取端口,以及需要曝光的web接口

management:
  server:
    port: 9999
  endpoints:
    web:
      exposure:
        include: '*'
  metrics:
    tags:
      application: myAppName

Springboot整合启动流程

拉取指标:http://localhost:9999/actuator/prometheus

servlet配置

接口自动配置有很多入口,例如下面两个

  1. 普通web服务:org.springframework.boot.actuate.autoconfigure.endpoint.web.servlet.WebMvcEndpointManagementContextConfiguration#webEndpointServletHandlerMapping
  2. 云服务商:org.springframework.boot.actuate.autoconfigure.cloudfoundry.servlet.CloudFoundryActuatorAutoConfiguration#cloudFoundryWebEndpointServletHandlerMapping

servlet逻辑

org.springframework.boot.actuate.metrics.export.prometheus.PrometheusScrapeEndpoint

@ReadOperation(producesFrom = TextOutputFormat.class)
public WebEndpointResponse<String> scrape(TextOutputFormat format, @Nullable Set<String> includedNames) {
    try {
        Writer writer = new StringWriter(this.nextMetricsScrapeSize);
        Enumeration<MetricFamilySamples> samples = (includedNames != null)
        ? this.collectorRegistry.filteredMetricFamilySamples(includedNames)
        : this.collectorRegistry.metricFamilySamples();
        format.write(writer, samples);

        String scrapePage = writer.toString();
        this.nextMetricsScrapeSize = scrapePage.length() + METRICS_SCRAPE_CHARS_EXTRA;

        return new WebEndpointResponse<>(scrapePage, format);
    }
    catch (IOException ex) {
        // This actually never happens since StringWriter doesn't throw an IOException
        throw new IllegalStateException("Writing metrics failed", ex);
    }
}

没有配置过滤器,获取枚举对象
io.prometheus.client.CollectorRegistry#metricFamilySamples -》 io.prometheus.client.CollectorRegistry.MetricFamilySamplesEnumeration#MetricFamilySamplesEnumeration()

io.prometheus.client.CollectorRegistry.MetricFamilySamplesEnumeration

  1. sampleNameFilter
  2. collectorIter:对应io.prometheus.client.CollectorRegistry#namesToCollectors属性的value集合
  3. 构造器中查询一次next:findNextElement

findNextElement

遍历collectorIter迭代器一次,并收集一次指标

  1. io.prometheus.client.Collector#collect(io.prometheus.client.Predicate<java.lang.String>)
  2. io.micrometer.prometheus.MicrometerCollector#collect
  3. 遍历io.micrometer.prometheus.MicrometerCollector#children集合中所有io.micrometer.prometheus.MicrometerCollector.Child对象
    1. 例如Gauge类型中的lambda匿名实现:io.micrometer.prometheus.PrometheusMeterRegistry#newGauge
  4. 将遍历的child中所有样本,按照conventionName(例如:ringbuffer_remaining)分组,每个组对应一个样本家庭:io.prometheus.client.Collector.MetricFamilySamples
  5. 返回List,将其迭代器赋给next属性:io.prometheus.client.CollectorRegistry.MetricFamilySamplesEnumeration#next
  6. 遍历samples:io.prometheus.client.Collector.MetricFamilySamples#samples
  7. 将sample(io.prometheus.client.Collector.MetricFamilySamples.Sample)数据写入response响应结果:org.springframework.boot.actuate.metrics.export.prometheus.TextOutputFormat#CONTENT_TYPE_004#write

接口输出案例

公共配置的tag,所有的指标都会带有该tag:application=myAppName
指标名称:ringbuffer_remaining
指标tag:type=my_tag_1
指标类型:gauge

# HELP ringbuffer_remaining  
# TYPE ringbuffer_remaining gauge
ringbuffer_remaining{application="myAppName",type="my_tag_1",} 1024.0

采样取数逻辑

Gauge

结合前面Gague使用案例的代码
io.micrometer.core.instrument.internal.DefaultGauge

  1. ref:对应ringbuffer实例的弱引用
  2. value:对应RingBuffer::remainingCapacity方法

取样逻辑即直接调用实例响应方法返回的结果作为打点value

public class DefaultGauge<T> extends AbstractMeter implements Gauge {
    ...
    private final WeakReference<T> ref;
    private final ToDoubleFunction<T> value;
    ...
    @Override
    public double value() {
        T obj = ref.get();
        if (obj != null) {
            try {
                return value.applyAsDouble(obj);
            }
            catch (Throwable ex) {
                logger.log("Failed to apply the value function for the gauge '" + getId().getName() + "'.", ex);
            }
        }
        return Double.NaN;
    }
    ...
}

Timer

io.micrometer.prometheus.PrometheusTimer

  1. count:LongAdder,递增计数器
  2. totalTime:LongAdder,任务耗时累加结果
  3. max:io.micrometer.core.instrument.distribution.TimeWindowMax,简化版的ringbuffer,用于记录时间窗口中的最大值
  4. histogramFlavor:直方图风味(类型),当前版本只有两种:Prometheus/VictoriaMetrics
  5. histogram
    1. Prometheus类型:io.micrometer.core.instrument.distribution.TimeWindowFixedBoundaryHistogram#TimeWindowFixedBoundaryHistogram
    2. VictoriaMetrics类型:io.micrometer.core.instrument.distribution.FixedBoundaryVictoriaMetricsHistogram#FixedBoundaryVictoriaMetricsHistogram

取样逻辑即监控的方法实际调用时就会触发打点记录。取样逻辑只是在接口拉取数据时调用实例实现的接口方法拍一个样本快照

  1. io.micrometer.core.instrument.distribution.HistogramSupport#takeSnapshot()
  2. io.micrometer.prometheus.PrometheusTimer#takeSnapshot
  3. io.micrometer.core.instrument.AbstractTimer#takeSnapshot
  4. 如果histogram != null则追加histogramCounts数据
--io.micrometer.core.instrument.AbstractTimer#takeSnapshot
    @Override
    public HistogramSnapshot takeSnapshot() {
        return histogram.takeSnapshot(count(), totalTime(TimeUnit.NANOSECONDS), max(TimeUnit.NANOSECONDS));
    }
--io.micrometer.prometheus.PrometheusTimer#takeSnapshot
    @Override
    public HistogramSnapshot takeSnapshot() {
        HistogramSnapshot snapshot = super.takeSnapshot();

        if (histogram == null) {
            return snapshot;
        }

        return new HistogramSnapshot(snapshot.count(),
                snapshot.total(),
                snapshot.max(),
                snapshot.percentileValues(),
                histogramCounts(),
                snapshot::outputSummary);
    }

时间窗口

io.micrometer.core.instrument.distribution.TimeWindowMax

  1. rotatingUpdater:AtomicIntegerFieldUpdater,rotating标志符原子更新方法
  2. clock:Clock,系统时钟,返回当前系统时间戳
  3. durationBetweenRotatesMills:long,滚动步进大小
  4. ringBuffer:AtomicLong[],队列
  5. currentBucket:int,队列当前游标
  6. lastRotateTimestampMills:上一次rotate的时间戳
  7. rotating:int,标志符,0 - not rotating, 1 - rotating

每次写入record,或者查询poll,都会提前校验下是否需要翻转,调用rotate方法
io.micrometer.core.instrument.distribution.TimeWindowMax#rotate

  1. wallTime=系统当前时间
  2. timeSinceLastRotateMillis = wallTime - lastRotateTimestampMillis,即:当前时间距离上次翻转的时间间隔
  3. 如果低于步进,直接返回不需要翻转:timeSinceLastRotateMillis < durationBetweenRotatesMillis
  4. 否则更新标志符,表示当前正在翻转,需要阻塞等待下
  5. 如果timeSinceLastRotateMillis已经超出整个队列的长度了:timeSinceLastRotateMillis >= durationBetweenRotatesMillis * ringBuffer.length
    1. 那么直接重置队列返回即可
    2. 遍历ringBuffer所有位置设置为0
    3. currentBucket更新为0
    4. 更新上次翻转时间:lastRotateTimestampMillis = wallTime - timeSinceLastRotateMillis % durationBetweenRotatesMillis
  6. 否则,将当前时间与上次翻转时间之间已经超时的bucket重置为0
int iterations = 0;
do {
    ringBuffer[currentBucket].set(0);
    if (++currentBucket >= ringBuffer.length) {
        currentBucket = 0;
    }
    timeSinceLastRotateMillis -= durationBetweenRotatesMillis;
    lastRotateTimestampMillis += durationBetweenRotatesMillis;
} while (timeSinceLastRotateMillis >= durationBetweenRotatesMillis && ++iterations < ringBuffer.length);

例如:当前时间为4,上次翻转时间为2,队列大小为3,durationBetweenRotatesMillis=1,currentBucket=1,那么timeSinceLastRotateMillis=4-2=2
循环第1轮

  1. 更新ringBuffer[1]=0
  2. 更新currentBucket=2
  3. 更新timeSinceLastRotateMillis=2-1
  4. 更新lastRotateTimestampMillis=2+1
  5. 更新iterations=1

循环第2轮

  1. 更新ringBuffer[2]=0
  2. 更新currentBucket=3
    1. currentBucket>=队列长度
    2. 重置currentBucket=0
  3. 更新timeSinceLastRotateMillis=1-1
  4. 更新lastRotateTimestampMillis=3+1
  5. 更新iterations=2,此时timeSinceLastRotateMillis=0,小于durationBetweenRotatesMillis,结束循环

一次旋转图例

当发现上次旋转时间(lastRotateTimestampMillis)已经落后当前时间(wallTime)4个单位后,lastRotateTimestampMillis向右移动4个时间单位,currentBucket也向右移动4个单位。但是因为currentBucket是数组的index,当越界的时候就移动到0继续(一个环)。例如下图:
currentBucket向右移动4个单位,队列长度为3,当前index=0,那么移动后index=2(转了一圈)
image.png

总结

Micrometer可以整合Prometheus也可以整合influxDB等时序数据库,主要作用就是桥接,类似于Slf4j与log4j,logback的关系。提供一个通用的打点能力,并将打点数据对接到相应的时序数据库,用户只需要关心何时打点即可。例如:

  1. 桥接包中的io.micrometer.prometheus.PrometheusMeterRegistry,将打点数据桥接至io.prometheus.client.CollectorRegistry
  2. 桥接包中的io.micrometer.influx.InfluxMeterRegistry,将打点数据按照influx协议桥接push至influxDB。
    1. 默认push频率为1分钟一次,可以按需配置:io.micrometer.core.instrument.push.PushRegistryConfig#step
    2. 线程池默认为单线程:java.util.concurrent.Executors#newSingleThreadScheduledExecutor(java.util.concurrent.ThreadFactory)
    3. 线程池线程命名规则针对influxDB实现:influx-metrics-publisher

actuator就像是启动器,会将对接具体时序数据库所需要的配置自动化,例如指标矩阵相关的:Prometheus曝光web接口的相关配置,influx相关配置,micrometer metrics等等相关配置

  1. org.springframework.boot.actuate.autoconfigure.metrics.JvmMetricsAutoConfiguration
  2. org.springframework.boot.actuate.autoconfigure.metrics.KafkaMetricsAutoConfiguration
  3. org.springframework.boot.actuate.autoconfigure.metrics.Log4J2MetricsAutoConfiguration
  4. org.springframework.boot.actuate.autoconfigure.metrics.LogbackMetricsAutoConfiguration
  5. org.springframework.boot.actuate.autoconfigure.metrics.SystemMetricsAutoConfiguration

最终可以通过Grafana等报表工具对接打点数据源展示图表。常见的架构有:Micrometer-》Prometheus-〉Grafana
注意:前端页面渲染存在瓶颈,例如一个指标的tag如果太多会导致报表非常的卡顿,一般5k个tag就会有感知,1W+会明显影响使用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1683822.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ctfhub中的SSRF相关例题(中)

目录 上传文件 gopher协议的工作原理&#xff1a; gopher协议的使用方法&#xff1a; 相关例题: FastCGI协议 FastCGI协议知识点 相关例题&#xff1a; Redis协议 知识点&#xff1a; 相关例题 第一种方法 第二种方法 上传文件 gopher协议的工作原理&#xff1a; …

《ESP8266通信指南》番外-(附完整代码)ESP8266获取DHT11接入(基于Lua)

前言 此篇为番外篇,是 ESP8266 入门的其他功能教程,包括但不限于 DHT11 驱动TCP 通信Thingsboard 平台的接入阿里云物联网云平台接入华为云平台接入 1. 小节目标 使用 Lua 驱动 DHT11 传感器,获取温湿度的值 2. 进入主题 NodeMCU 基于 LUA 相关资料 官方文档&#xff1a;…

商品指数创年内新高,粘性通胀成为美联储噩梦

文章概述 虽然美国4月CPI增幅放缓让美联储今年降息的可能性大增&#xff0c;但与此同时&#xff0c;大宗商品价格却达到了一年来的最高水平&#xff0c;粘性通胀可能成为美联储的噩梦。数据显示&#xff0c;跟踪24种能源、金属和农业合约彭博大宗商品现货指数今年以来已经上涨…

Mysql超详细安装配置教程(保姆级图文)

MySQL是一种流行的开源关系型数据库管理系统&#xff0c;它广泛用于网站和服务的数据存储和管理。MySQL以其高性能、可靠性和易用性而闻名&#xff0c;是许多Web应用程序的首选数据库解决方案之一。 一、下载安装包 &#xff08;1&#xff09;从网盘下载安装文件 点击此处直…

RK3588 Android13 TvSetting 中增加字体样式切换功能

前言 电视产品,客户需求又升级了,有了切换字体大小还不行,还得增加动态切换字体样式功能, 同样需要在设备偏好设置子菜单里的显示和声音二级菜单里增加字体样式菜单功能,开整。 效果图 framework 部分修改文件清单 frameworks/base/data/fonts/fonts.mk frameworks/bas…

附代码:策略常用-正余弦优化算法

正余弦优化算法作为群智能优化算法的一种, 正弦余弦算法 (sine cosine algorithm, SCA) 是 2016 年由 Mirjalili 提出的一种新型仿自然优化算法, 通过创建多个随机候选解, 利用正余弦函数的数学性质来平衡算法在搜系过程中的全局探索和局部开发能力。该算法具有结构简单、参数少…

MobaXterm:Network error: Connection refused

问题描述 使用MobaXterm连接服务器或者虚拟机里面的操作系统显示“Network error: Connection refused” 因为服务器或者虚拟机里面的操作系统没安装 ssh 解决方法 安装ssh sudo apt-get update sudo apt-get upgrade sudo apt-get install ssh重启 ssh service ssh resta…

Docker 镜像是什么?

Docker 镜像是什么&#xff1f; Docker 镜像&#xff08;Docker Image&#xff09;是用于创建 Docker 容器的只读模板。它包含了运行应用程序所需的所有内容&#xff0c;包括代码、运行时环境、库、环境变量以及配置文件。Docker 镜像是构建和分发应用程序的基础。 在深入阅读…

[数据集][目标检测]弹簧上料检测数据集VOC+YOLO格式142张2类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;142 标注数量(xml文件个数)&#xff1a;142 标注数量(txt文件个数)&#xff1a;142 标注类别…

如何保护好源代码

在信息技术飞速发展的今天&#xff0c;源代码作为软件开发的核心要素&#xff0c;其安全性与保密性至关重要。一旦源代码泄露或被恶意篡改&#xff0c;将可能导致企业面临重大损失&#xff0c;甚至威胁到整个行业的安全。因此&#xff0c;如何保护源代码已成为软件企业和个人开…

15.1使用curl命令,命令行模拟登陆discuz

使用curl命令,命令行模拟登陆discuz web保存session&#xff0c;鼠标点一点&#xff0c;发起http请求&#xff0c;html 注意不能使用登录带验证码的网站测试 1.curl命令模拟访问discuz论坛 在192.168.111.16服务器的web站点新建一个目录&#xff0c;获取cookie信息与html文件…

IP学习——ospf1

OSPF:开放式最短路径优先协议 无类别IGP协议&#xff1a;链路状态型。基于 LSA收敛&#xff0c;故更新量较大&#xff0c;为在中大型网络正常工作&#xff0c;需要进行结构化的部署---区域划分、ip地址规划 支持等开销负载均衡 组播更新 ---224.0.0.5 224.0.0.6 …

一剪梅-答赠云安客刘自果

当众网友看了笔者“边吸氧边动鼠标”的短视频之后&#xff0c;纷纷发来微信问候。其中我的远房亲戚&#xff0c;那个正在潜心写作数十万字的长篇纪实文学《川江向东流》的66岁贤弟刘自果&#xff08;号云安客&#xff0c;亦称自果居士&#xff09;&#xff0c;发来微信鼓励我&a…

mysql 多表关联查询性能优化-同一sql不同的执行计划

一、问题背景 相同的sql&#xff0c;不同的日期&#xff0c;执行的时间差异很大&#xff0c;执行计划不一样。执行快时&#xff0c;30ms左右。执行慢时&#xff0c;15s左右。 二、分析结论 1、经过分析&#xff0c;发现不同日期下&#xff0c;sql的执行计划不同&#xff0c;驱…

《Effective Objective-C 2.0》读书笔记——熟悉Objective-C

目录 第一章&#xff1a;熟悉Objective-C第1条&#xff1a;了解Objective-C语言的起源第2条&#xff1a;在类的头文件中尽量少引入其他头文件第3条&#xff1a;多用字面量语法&#xff0c;少用与之等价的方法第4条&#xff1a;多用类型常量&#xff0c;少用#define预处理指令第…

网络世界的盗梦空间:用Crawley框架破解数据维度

嗨&#xff0c;我是阿佑&#xff0c;你是否设想过自己能够像电影中的盗梦者一样&#xff0c;潜入网站深层&#xff0c;巧妙抓取那些隐藏在数字幻境中的数据宝藏&#xff1f;今天阿佑将带你体验前所未有的数据探险&#xff0c;让你在Python的海洋中乘风破浪&#xff0c;成为数据…

【漏洞复现】用友U8 CRM uploadfile 文件上传致RCE漏洞

0x01 产品简介 用友U8 Cloud是用友推出的新一代云ERP&#xff0c;主要聚焦成长型、创新型企业&#xff0c;提供企业级云ERP整体解决方案。 0x02 漏洞概述 用友 U8 CRM客户关系管理系统 uploadfle.php 文件存在任意文件上传漏洞&#xff0c;未经身份验证的攻击者通过漏洞上传…

open drain 与 push pull

Open drain: open drain 输出&#xff1a;输出端相当于三极管的集电极&#xff0c;要得到高电平需要上拉电阻才行。 栅极输入为0时&#xff0c;NMOS 的漏极和源极导通&#xff0c;输出为0。即Uce 0 V。 栅极输入为1时&#xff0c;NMOS不导通&#xff0c;漏极高祖&#xff0…

防静电液的这些用处你知道多少

防静电液又叫抗静电剂&#xff0c;是工业上常用来消除静电的化学用品&#xff0c;一般是液体状态&#xff0c;它的用途很广泛。 防静电液适用于对静电有控制要求的电器、仪器桌面、台面、塑料制品、包装品、存储盒、托盘、毛毯、织物等任何物品表面。 应用举例如消除各种塑胶材…

eNSP学习——OSPF单区域配置

目录 相关命令 实验背景 实验目的 实验步骤 实验拓扑 实验编址 实验步骤 1、基础配置 2、部署单区域OSPF网络 3、检查OSPF单区域的配置结果 OSPF——开放式最短路径优先 基于链路状态的协议&#xff0c;具有收敛快、路由无环、扩展性好等优点&#xff1b; 相关命令 […