Spring Boot 使用 Micrometer 集成 Prometheus 监控 Java 应用性能
转载自:https://cloud.tencent.com/developer/article/1508319
文章目录1、Micrometer 介绍2、环境、软件准备3、Spring Boot 工程集成 Micrometer4、配置 Prometheus 监控应用指标5、配置 Grafana Dashboard 展示监控项6、自定义监控指标并展示到 Grafana6.1、监控某几个 API 请求次数6.2、监控所有 API 请求次数6.3、监控实时在线人数
1、Micrometer 介绍
Micrometer 为 Java 平台上的性能数据收集提供了一个通用的 API,它提供了多种度量指标类型(Timers、Guauges、Counters等),同时支持接入不同的监控系统,例如 Influxdb、Graphite、Prometheus 等。我们可以通过 Micrometer 收集 Java 性能数据,配合 Prometheus 监控系统实时获取数据,并最终在 Grafana 上展示出来,从而很容易实现应用的监控。
Micrometer 中有两个最核心的概念,分别是计量器(Meter)和计量器注册表(MeterRegistry)。计量器用来收集不同类型的性能指标信息,Micrometer 提供了如下几种不同类型的计量器:
- 计数器(Counter): 表示收集的数据是按照某个趋势(增加/减少)一直变化的,也是最常用的一种计量器,例如接口请求总数、请求错误总数、队列数量变化等。
- 计量仪(Gauge): 表示搜集的瞬时的数据,可以任意变化的,例如常用的 CPU Load、Mem 使用量、Network 使用量、实时在线人数统计等,
- 计时器(Timer): 用来记录事件的持续时间,这个用的比较少。
- 分布概要(Distribution summary): 用来记录事件的分布情况,表示一段时间范围内对数据进行采样,可以用于统计网络请求平均延迟、请求延迟占比等。
2、环境、软件准备
本次演示环境,我是在本机 MAC OS 上操作,以下是安装的软件及版本:
- Docker: 18.06.3-ce
- Oracle VirtualBox: 6.0.8 r130520 (Qt5.6.3)
- Linux: 7.6.1810
- Prometheus: v2.11.1
- Grafana: v6.3.4
注意:这里为了快速方便启动 Prometheus、Grafana 服务,我使用 Docker 方式启动,所以本机需要安装好 Docker 环境,这里忽略 Docker 的安装过程,着重介绍一下 Spring Boot 项目如何使用 Micrometer 来监控 Java 应用性能,并集成到 Prometheus 最终使用 Grafana Dashboard 展示出来。
3、Spring Boot 工程集成 Micrometer
我们一般说 Spring Boot 集成 Micrometer 值得时 Spring 2.x 版本,因为在该版本 spring-boot-actuator 使用了 Micrometer 来实现监控,而在 Spring Boot 1.5x 中可以通过micrometer-spring-legacy 来使用 micrometer,显然在 2.x 版本有更高的集成度,使用起来也非常方便了。那么创建一个 Spring Boot 2.1.4.RELEASE 版本的工程 springboot2-promethues,首先添加依赖如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>1.1.4</version>
</dependency>
这里引入了 io.micrometer 的 micrometer-registry-prometheus 依赖以及 spring-boot-starter-actuator 依赖,因为该包对 Prometheus 进行了封装,可以很方便的集成到 Spring Boot 工程中。
其次在 application.properties 中配置如下:
server.port=8088
spring.application.name=springboot2-prometheus
management.endpoints.web.exposure.include=*
management.metrics.tags.application=${spring.application.name}
这里 management.endpoints.web.exposure.include=* 配置为开启 Actuator 服务,因为Spring Boot Actuator 会自动配置一个 URL 为 /actuator/Prometheus 的 HTTP 服务来供 Prometheus 抓取数据,不过默认该服务是关闭的,该配置将打开所有的 Actuator 服务。management.metrics.tags.application 配置会将该工程应用名称添加到计量器注册表的 tag 中去,方便后边 Prometheus 根据应用名称来区分不同的服务。
然后在工程启动主类中添加 Bean 如下来监控 JVM 性能指标信息:
@SpringBootApplication
public class Springboot2PrometheusApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot2PrometheusApplication.class, args);
}
@Bean
MeterRegistryCustomizer<MeterRegistry> configurer(@Value("${spring.application.name}") String applicationName){
return registry -> registry.config().commonTags("application", applicationName);
}
}
最后,启动服务,浏览器访问 http://127.0.0.1:8088/actuator/prometheus 就可以看到应用的 一系列不同类型 metrics 信息,例如 http_server_requests_seconds summary、jvm_memory_used_bytes gauge、jvm_gc_memory_promoted_bytes_total counter 等等。

4、配置 Prometheus 监控应用指标
Prometheus 的安装配置可参考之前文章 Prometheus 监控报警系统 AlertManager 之邮件告警,写的很详细,这里就不在详细说明了,修改 prometheus.yml 配置,在上篇文章配置示例基础上,添加上边启动的服务地址来执行监控。
$ vim prommetheus.yml
......
- job_name: 'application'
scrape_interval: 5s
metrics_path: '/actuator/prometheus'
file_sd_configs:
- files: ['/usr/local/prometheus/groups/applicationgroups/*.json']
这里依然采用 file_sd_configs 方式动态服务发现,新建 <local_dir>/groups/applicationgroups/application.json 文件如下:
$ vim groups/applicationgroups/application.json
[
{
"targets": [
"192.168.1.124:8088"
],
"labels": {
"instance": "springboot2-prometheus",
"service": "springboot2-prometheus-service"
}
}
]
这里 192.168.1.124:8088 就是上边本地启动的服务地址,也就是 Prometheus 要监控的服务地址,同时添加一些与应用相关的标签,方便后期执行 PromSQL 查询语句区分。最后重启 Prometheus 服务,查看 Prometheus UI 界面确认 Target 是否添加成功。

在 Graph 页面执行一个简单的查询,也是获取 springboot2-prometheus 服务的 JVM 性能指标值的。
5、配置 Grafana Dashboard 展示监控项
Prometheus 现在已经可以正常监控到应用 JVM 信息了,那么我们可以配置 Grafana Dashboard 来优雅直观的展示出来这些监控值了。首先创建 Grafana 服务,这里为了方便,依旧采用 Docker 的方式启动,启动命令如下:
$ docker run -d -p 3000:3000 --name=grafana grafana/grafana
启动完毕后,浏览器访问 http://192.168.1.121:3000 即可,首次登录使用 admin:admin 默认账户密码登录并修改密码。登录完毕,需要添加数据源,这里我们要添加的就是上边 Prometheus 数据源,配置如下图:

配置完毕,接下来需要导入对应的监控 JVM 的 Dashboard 模板,模板编号为 4701。

导入完毕后,就可以看到 JVM (Micrometer) 各种类型指标监控图形化以后的页面。
6、自定义监控指标并展示到 Grafana
上边是 spring-boot-actuator 集成了 Micrometer 来提供的默认监控项,覆盖 JVM 各个层间的监控,配合 Grafana Dashboard 模板基本可以满足我们日常对 Java 应用的监控。当然,它也支持自定义监控指标,实现各个方面的监控,例如统计访问某一个 API 接口的请求数,统计实时在线人数、统计实时接口响应时间等功能,而这些都可以通过使用上边的四种计量器来实现。接下来,来演示下如何自定义监控指标并展示到 Grafana 上。
6.1、监控某几个 API 请求次数
我们继续在 springboot2-promethues 工程上添加 IndexController.java,来实现分别统计访问 index 及 core 接口请求次数,代码如下:
@RestController
@RequestMapping("/v1")
public class IndexController {
@Autowired
MeterRegistry registry;
private Counter counter_core;
private Counter counter_index;
@PostConstruct
private void init(){
counter_core = registry.counter("app_requests_method_count", "method", "IndexController.core");
counter_index = registry.counter("app_requests_method_count", "method", "IndexController.index");
}
@RequestMapping(value = "/index")
public Object index(){
try{
counter_index.increment();
} catch (Exception e) {
return e;
}
return counter_index.count() + " index of springboot2-prometheus.";
}
@RequestMapping(value = "/core")
public Object coreUrl(){
try{
counter_core.increment();
} catch (Exception e) {
return e;
}
return counter_core.count() + " coreUrl Monitor by Prometheus.";
}
}
说明一下,这里是一个简单的 RestController 接口,使用了 Counter 计量器来统计访问 /v1/index 及 /v1/core 接口访问量。因为访问数会持续的增加,所以这里使用 Counter 比较合适。启动服务,我们来分别访问一下这两个接口,为了更好的配合下边演示,可以多访问几次。


服务可以正常访问,并且访问了 6 次 /v1/index,访问了 10 次 /v1/core。接下来,我们可以到 Prometheus UI 界面上使用 PromSQL 查询自定义的监控信息了。分别添加 Graph 并执行如下查询语句,查询结果如下:


可以看到正确统计出来这两个接口请求的访问数,这里解释一下查询语句:app_requests_method_count_total{application="springboot2-prometheus", instance="springboot2-prometheus", method="IndexController.core"} 这里的
app_requests_method_count_total为上边代码中设置的 Counter 名称。application为初始化 registry 时设置的通用标签,标注应用名称,这样做好处就是可以根据应用名称区分不同的应用。instance为<local_dir>/groups/applicationgroups/application.json中配置的 instance 实例名称,用来区分应用实例。method为上边代码中设置的 Counter 标签名称,可以用来区分不同的方法,这样就不用为每一个方法设置一个 Counter 了。
接下来,我们在 Grafana Dashboard 上添加一个新的 Panel 并添加 Query 查询,最后图形化展示出来。首先添加一个 Panel 并命名为 自定义监控指标,然后点击 Add Query 增加一个新的 Query 查询,查询语句为上边的 PromSQL 语句,不过这里为了更好的扩展性,我们可以将 application 及 instance 两个参数赋值为变量,而这些变量可以直接从 Prometheus 上传递过来,最终的查询语句为 app_requests_method_count_total{application="$application", instance="$instance", method="IndexController.core"},最后修改 Title 为 实时访问量 /v1/core,保存一下,返回首页就可以看到刚添加的 Dashboard 了,是不是很直观。

6.2、监控所有 API 请求次数
上边针对某个或某几个接口请求次数做了监控,如果我们想针对整个应用监控所有接口请求总次数,这个该如何实现呢?监控请求次数可以继续使用 Counter 计数器,整个应用所有请求,我们自然而然的想到了 Spring AOP,通过切面注入可以做到统计所有请求记录,添加依赖如下:
...
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.4</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.12</version>
</dependency>
添加 AspectAop.java 代码到 Springboot2PrometheusApplication.java 同级目录, 代码如下:
@Component
@Aspect
public class AspectAop {
@Autowired
MeterRegistry registry;
private Counter counter_total;
ThreadLocal<Long> startTime = new ThreadLocal<>();
@Pointcut("execution(public * com.promethues.demo.controller.*.*(..))")
private void pointCut(){}
@PostConstruct
public void init(){
counter_total = registry.counter("app_requests_count", "v1", "core");
}
@Before("pointCut()")
public void doBefore(JoinPoint joinPoint)throws Throwable {
startTime.set(System.currentTimeMillis());
counter_total.increment();
}
@AfterReturning(returning = "returnVal", pointcut = "pointCut()")
public void doAftereReturning(Object returnVal){
System.out.println("请求执行时间:" + (System.currentTimeMillis() - startTime.get()));
}
}
这里 Spring AOP 操作代码就不在说了,我们创建了一个名称为 app_requests_count 的 Counter,所有请求过来都会执行 counter_total.increment(); 操作,从而实现统计所有请求总数。重启服务,访问多次不同的接口,然后在 Prometheus UI 界面执行 PromSQL 查询,查询语句为 app_requests_count_total{application="springboot2-prometheus", instance="springboot2-prometheus", v1="core"} 查询结果如下:

可以看到,能够正确统计出来所有的请求数量,现在,我们可以在 Grafana 上之前的面板上增加一个新的 Query 并图形化显示出来了,Query 语句为: app_requests_count_total{application="$application", instance="$instance",v1="core"}, 添加完成后,展示效果如下:

6.3、监控实时在线人数
接下来,来演示下如何监控瞬时数据变化,例如实时交易总金额,实时网络请求响应时间,实时在线人数等,这里我们简单模拟一下实时在线人数监控,这里采用 Gauge 计量仪来做为指标统计类型,在 IndexController.java 中添加相关代码如下:
@RestController
@RequestMapping("/v1")
public class IndexController {
@Autowired
MeterRegistry registry;
private Counter counter_core;
private Counter counter_index;
private AtomicInteger app_online_count;
@PostConstruct
private void init(){
counter_core = registry.counter("app_requests_method_count", "method", "IndexController.core");
counter_index = registry.counter("app_requests_method_count", "method", "IndexController.index");
app_online_count = registry.gauge("app_online_count", new AtomicInteger(0));
}
@RequestMapping(value = "/index")
public Object index(){
try{
counter_index.increment();
} catch (Exception e) {
return e;
}
return counter_index.count() + " index of springboot2-prometheus.";
}
@RequestMapping(value = "/core")
public Object coreUrl(){
try{
counter_core.increment();
} catch (Exception e) {
return e;
}
return counter_core.count() + " coreUrl Monitor by Prometheus.";
}
@RequestMapping(value = "/online")
public Object onlineCount(){
int people = 0;
try {
people = new Random().nextInt(2000);
app_online_count.set(people);
} catch (Exception e){
return e;
}
return "current online people: " + people;
}
}
重启服务,访问一下 /v1/online 接口,得到一个 2000 以内的随机数作为实时在线人数,浏览器访问一下,得到结果如下:

我们在 Prometheus UI 界面执行一下 PromeSQL 查询语句 app_online_count{application="springboot2-prometheus", instance="springboot2-prometheus"},同样能够对应获取到实时数据。

继续在 Grafana 上之前的面板上增加一个新的 Query 并图形化显示出来,Query 语句为: app_online_count{application="$application", instance="$instance"}, 添加完成后,展示效果如下:

注意:这里我采用了 Grafana 中 Gauge 图形来展示的,可以根据实际要求来展示对应的数据。
参考资料
Spring Boot 使用 Micrometer 集成 Prometheus 监控 Java 应用性能的更多相关文章
- Spring Boot 如何快速集成 Redis 哨兵?
上一篇:Spring Boot 如何快速集成 Redis? 前面的分享栈长介绍了如何使用 Spring Boot 快速集成 Redis,上一篇是单机版,也有粉丝留言说有没有 Redis Sentine ...
- Java Spring Boot VS .NetCore (十) Java Interceptor vs .NetCore Interceptor
Java Spring Boot VS .NetCore (一)来一个简单的 Hello World Java Spring Boot VS .NetCore (二)实现一个过滤器Filter Jav ...
- Spring Boot HikariCP 一 ——集成多数据源
其实这里介绍的东西主要是参考的另外一篇文章,数据库读写分离的. 参考文章就把链接贴出来,里面有那位的代码,简单明了https://gitee.com/comven/dynamic-datasource ...
- Spring Boot系列——如何集成Log4j2
上篇<Spring Boot系列--日志配置>介绍了Spring Boot如何进行日志配置,日志系统用的是Spring Boot默认的LogBack. 事实上,除了使用默认的LogBack ...
- 【ELK】4.spring boot 2.X集成ES spring-data-ES 进行CRUD操作 完整版+kibana管理ES的index操作
spring boot 2.X集成ES 进行CRUD操作 完整版 内容包括: ============================================================ ...
- 15、Spring Boot 2.x 集成 Swagger UI
1.15.Spring Boot 2.x 集成 Swagger UI 完整源码: Spring-Boot-Demos 1.15.1 pom文件添加swagger包 <swagger2.versi ...
- 7、Spring Boot 2.x 集成 Redis
1.7 Spring Boot 2.x 集成 Redis 简介 继续上篇的MyBatis操作,详细介绍在Spring Boot中使用RedisCacheManager作为缓存管理器,集成业务于一体. ...
- 6、Spring Boot 2.x 集成 MyBatis
1.6 Spring Boot 2.x 集成 MyBatis 简介 详细介绍如何在Spring Boot中整合MyBatis,并通过注解方式实现映射. 完整源码: 1.6.1 创建 spring-bo ...
- spring boot rest 接口集成 spring security(2) - JWT配置
Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...
随机推荐
- 2022-7-13 java_1 第七组 刘昀航
@ 目录 前言 一.一些基本的指令 二.java 1.java的三个版本 2.java特点 3.运行一个java程序 三.java的数据类型 1.java基本数据类型 2.强制转换的原理 3.八种基本 ...
- DQL分组查询和DQL分页查询
分组查询: 1.语法:group by 分组字段: 2.注意: 分组之后查询的字符按:分组字段.聚合函数 where 和having 的区别 where再分组前进行限定,如果不满足条件则不参与分组.h ...
- 【Azure 应用服务】本地创建Azure Function Kafka Trigger 函数和Kafka output的HTTP Trigger函数实验
问题描述 在上一篇博文(https://www.cnblogs.com/lulight/p/16525902.html)中,我们成功的以VM作为Kafka服务器运行,并且验证了从其他机器中远程访问.在 ...
- javascript引用"bug"带来的"继承"
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- SQL 字符串去除空格函数汇总
SQL 中使用ltrim()去除左边空格 ,rtrim()去除右边空格 ,没有同时去除左右空格的函数,要去除所有空格可以用replace(字符串,' ',''),将字符串里的空格替换为空 . 例:去除 ...
- 开源风吹动开源心 ~ 8月16日,你若来,我们(Apache)在等你!
点击上方蓝字关注ALC Beijing 抢! 太好看了吧! 买它,就是它,买它! 要抢! ALC是Apache Local Community的缩写,是全世界范围的 Apache 开源爱好者本地群组. ...
- "蔚来杯"2022牛客暑期多校训练营9 G Magic Spells【马拉车+哈希】
四川今天又上热搜了,继南部疫情的未雨绸缪后,龙槽沟是真的倾盆大雨了.我没有兴趣虚伪矫情地对罹难的游人表达同情,因为人与人互不相通徒增谈资:我也没有兴趣居高临下地对擅闯的愚人表达不屑,因为你我皆为乌合之 ...
- HandInDevil 的头发 (分 块)
题面 H a n d I n D e v i l \rm HandInDevil HandInDevil 的头发很油,因此随时有跳蚤跳上 H a n d I n D e v i l \rm HandI ...
- 【MIDO】乐理基础 与 python - 从零开始到编写柱式和弦与分解和弦
本篇文章从律学开始,从十二平均律出发,介绍一些基础必要的乐理知识,然后编写python文件,输出和弦音频文件. 乐理知识部分: 一.律学简述(temperament) 1.概论 律学,又称&q ...
- APICloud如何对接大牛直播SDK
随着apicloud的普及,越来越多的用户苦于apicloud下没有一款真正靠谱低延迟的rtmp/rtsp直播播放器苦恼. 鉴于此,大牛直播SDK携手apicloud资深版主,推出apicloud对接 ...