SpringBoot 3 进阶教程之一整合 Prometheus 与 Grafana

大纲

前言

本文主要介绍 SpringBoot 3 如何整合 Actuator、Prometheus 与 Grafana,实现微服务应用的监控。

官方文档

概念介绍

可观测性

可观测性 (Observability) 一般是指对线上应用进行观测、监控、预警等,包括的详细内容如下:

  • 健康状况:组件状态、存活状态等,属于 Health 范畴
  • 运行指标:CPU、内存、垃圾回收、吞吐量、响应成功率等,属于 Metrics 范畴
  • 链路追踪
  • ……

Actuator 整合

提示

本章节完整的案例代码可以直接从 GitHub 下载对应章节 spring-boot3-17

引入依赖

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

添加配置

1
2
3
4
5
# 暴露所有端点信息
management.endpoints.enabled-by-default=true

# 以Web方式暴露
management.endpoints.web.exposure.include=*

访问端点

SpringBoot 应用正常启动后,通过以下路径可以获取常用的端点信息。

  • http://127.0.0.1:8080/actuator:展示出所有可以用的监控端点
  • http://127.0.0.1:8080/actuator/beans
  • http://127.0.0.1:8080/actuator/configprops
  • http://127.0.0.1:8080/actuator/metrics
  • http://127.0.0.1:8080/actuator/metrics/jvm.gc.pause
  • http://127.0.0.1:8080/actuator/endpointName/detailPath

端点进阶使用

常用端点

提示

下述的所有端点信息,都可以使用 http://ip:port/actuator/xxx 的路径进行访问,如 http://ip:port/actuator/health

ID 描述
auditevents 暴露当前应用程序的审核事件信息。需要一个 AuditEventRepository 组件。
beans 显示应用程序中所有 Spring Bean 的完整列表。
caches 暴露可用的缓存。
conditions 显示自动配置的所有条件信息,包括匹配或不匹配的原因。
configprops 显示所有 @ConfigurationProperties 的配置信息。
env 暴露 Spring 的属性 ConfigurableEnvironment
flyway 显示已应用的所有 Flyway 数据库迁移。需要一个或多个 Flyway 组件。
health 显示应用程序运行状况信息。
httptrace 显示 HTTP 跟踪信息(默认情况下,最近 100 个 HTTP 请求 / 响应)。需要一个 HttpTraceRepository 组件。
info 显示应用程序信息。
integrationgraph 显示 Spring integrationgraph。需要依赖 spring-integration-core
loggers 显示和修改应用程序中日志的配置。
liquibase 显示已应用的所有 Liquibase 数据库迁移。需要一个或多个 Liquibase 组件。
metrics 显示当前应用程序的 “指标” 信息。
mappings 显示所有 @RequestMapping 路径列表。
scheduledtasks 显示应用程序中的计划任务。
sessions 允许从 Spring Session 支持的会话存储中检索和删除用户会话。需要使用 Spring Session 的基于 Servlet 的 Web 应用程序。
shutdown 使应用程序正常关闭。默认禁用。
startup 显示由 ApplicationStartup 收集的启动步骤数据。需要使用 SpringApplication 配置 BufferingApplicationStartup
threaddump 执行线程转储。
heapdump 返回 hprof 堆转储文件。
jolokia 通过 HTTP 暴露 JMX Bean(需要引入 Jolokia,不适用于 WebFlux)。需要引入依赖 jolokia-core
logfile 返回日志文件的内容(如果已设置 logging.file.namelogging.file.path 属性)。支持使用 HTTP Range 标头来检索部分日志文件的内容。
prometheus 以 Prometheus 服务器可以抓取的格式公开指标。需要依赖 micrometer-registry-prometheus
threaddump 显示 JVM 的所有线程信息
heapdump 将 JVM 的堆内存导出为文件
metrics 显示应用程序的度量指标信息,例如 CPU 使用率、内存使用率、请求次数等,如 /actuator/metrics/system.cpu.usage

定制端点

定制端点分为两种:

  • HealthEndpoint (健康监控): 返回存活、死亡
  • MetricsEndpoint (指标监控): 返回次数、成功率 …

提示

本章节完整的案例代码可以直接从 GitHub 下载对应章节 spring-boot3-17

定制 HealthEndpoint

提示

这里的案例,主要用于演示如何通过定制 HealthEndpoint 来监控自定义组件的运行状况。

  • 添加配置,显示详细的健康信息
1
2
3
4
5
6
7
8
9
# 暴露所有端点信息
management.endpoints.enabled-by-default=true

# 以Web方式暴露
management.endpoints.web.exposure.include=*

# 总是显示详细健康信息,包括显示每个模块的状态信息
management.endpoint.health.enabled=true
management.endpoint.health.show-details=always
  • 自定义被监控的组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Component
public class MyBizComponent {

/**
* 检查自定义组件的健康状态
*
* @return
*/
public boolean check() {
// 业务代码判断当前组件是否存活
return true;
}

}
  • 第一种定制方式:实现 HealthIndicator 接口,建议这里实现类的类名以 HealthIndicator 结尾。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Component
public class MyBizHealthIndicator implements HealthIndicator {

@Autowired
private MyBizComponent bizComponent;

@Override
public Health health() {
// 检查自定义组件是否存活
boolean check = bizComponent.check();
if (check) {
// 存活
return Health.up()
.withDetail("msg", "Servcie online")
.withDetail("code", "200")
.build();
} else {
// 下线
return Health.down()
.withException(new RuntimeException())
.withDetail("msg", "Servcie offline")
.withDetail("code", "500")
.build();
}
}

}
  • 第二种定制方式:继承 MyHealthIndicator 类,建议这里继承类的类名以 HealthIndicator 结尾。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Component
public class MyBizHealthIndicator extends AbstractHealthIndicator {

@Autowired
private MyBizComponent bizComponent;

@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
Map<String, Object> details = new HashMap<>();
// 检查自定义组件是否存活
boolean check = bizComponent.check();
if (check) {
// 存活
builder.status(Status.UP);
details.put("msg", "Servcie online");
details.put("code", 200);
} else {
// 下线
builder.status(Status.DOWN);
details.put("msg", "Servcie offline");
details.put("code", 500);
}
builder.withDetails(details);
}

}
  • 最后浏览器访问 http://127.0.0.1:8080/actuator/health 后,显示的健康监控信息如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
"status": "UP",
"components": {
"diskSpace": {
"status": "UP",
"details": {
"total": 26897127,
"free": 18168525,
"threshold": 104857,
"exists": true
}
},
"myBiz": {
"status": "UP",
"details": {
"msg": "Servcie online",
"code": "200"
}
},
"ping": {
"status": "UP"
}
}
}

定制 MetricsEndpoint

提示

这里的案例,主要用于演示如何通过定制 MetricsEndpoint 来统计业务方法执行的次数。

  • 添加配置
1
2
3
4
5
# 暴露所有端点信息
management.endpoints.enabled-by-default=true

# 以Web方式暴露
management.endpoints.web.exposure.include=*
  • 控制器类
1
2
3
4
5
6
7
8
9
10
11
12
@RestController
public class MyBizController {

@Autowired
private MyBizService myBizService;

@GetMapping("/process")
public void process() {
myBizService.process();
}

}
  • 服务类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Service
public class MyBizService {

private final Counter counter;

/**
* 自动注入 MeterRegistry,用于保存和统计所有自定义指标
*/
public MyBizService(MeterRegistry meterRegistry) {
// 获取一个名称是 myBizCounter 的计数器
counter = meterRegistry.counter("myBizCounter");
}

/**
* 处理业务逻辑
*/
public void process() {
// 统计业务方法被调用的次数
counter.increment();
}

}
  • 最后手动多次调用接口,浏览器访问 http://127.0.0.1:8080/actuator/metrics/myBizCounter 后,显示的指标监控信息如下:
1
2
3
4
5
6
7
8
9
10
11
12
{
"name": "myBizCounter",
"measurements": [
{
"statistic": "COUNT",
"value": 4.0
}
],
"availableTags": [

]
}

Prometheus 整合

这里主要介绍 SpringBoot Actuator 如何整合 Prometheus,并基于 Grafana 实现微服务应用的监控,整体工作流程如下图所示:

代码下载

提示

本章节完整的案例代码可以直接从 GitHub 下载对应章节 spring-boot3-17

安装步骤

推荐使用 Docker 快速安装 Prometheus 和 Grafana,详细的安装步骤如下。

创建配置文件

  • 创建 prometheus.yml 配置文件,用于配置 Prometheus 的监控任务
1
2
3
4
5
6
7
8
global:
scrape_interval: 15s
evaluation_interval: 15s

scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
  • 创建 docker-compose.yml 配置文件,用于 Docker Compose 管理容器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
version: '3.9'

services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
restart: always
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
networks:
- backend

grafana:
image: grafana/grafana:latest
container_name: grafana
restart: always
depends_on:
- prometheus
ports:
- "3000:3000"
networks:
- backend

networks:
backend:
name: backend

启动 Docker 容器

1
2
3
4
5
# 创建并启动容器
docker compose up -d

# 查看容器的运行状态
docker compose ps -a

测试 Docker 容器

浏览器访问以下应用的控制台管理界面,若能正常访问,则说明对应的 Docker 容器正常运行(请自行更改容器的 IP 地址

应用访问地址
Grafanahttp://192.168.1.130:3000
Prometheushttp://192.168.1.130:9090

Grafana 默认登录账号

Grafana 默认的用户名称是 admin,用户密码是 admin。值得一提的是,首次登录 Grafana 会提示更改用户名和密码。

整合步骤

SpringBoot Actuator 整合 Prometheus 的步骤如下。

引入依赖

1
2
3
4
5
6
7
8
9
10
11
12
<!-- Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<!-- Prometheus -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>1.10.6</version>
</dependency>

添加配置

1
2
3
4
5
# 暴露所有端点信息
management.endpoints.enabled-by-default=true

# 以Web方式暴露
management.endpoints.web.exposure.include=*

验证配置

启动 SpringBoot 应用,浏览器访问 http://127.0.0.1:8080/actuator/prometheus,若可以返回 Prometheus 格式的所有指标信息(如下),则说明 SpringBoot Actuator 整合 Prometheus 成功。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# HELP jvm_memory_usage_after_gc_percent The percentage of long-lived heap pool used after the last GC event, in the range [0..1]
# TYPE jvm_memory_usage_after_gc_percent gauge
jvm_memory_usage_after_gc_percent{area="heap",pool="long-lived",} 0.0
# HELP executor_completed_tasks_total The approximate total number of tasks that have completed execution
# TYPE executor_completed_tasks_total counter
executor_completed_tasks_total{name="applicationTaskExecutor",} 0.0
# HELP http_server_requests_active_seconds_max
# TYPE http_server_requests_active_seconds_max gauge
http_server_requests_active_seconds_max{exception="none",method="GET",outcome="SUCCESS",status="200",uri="UNKNOWN",} 0.0038188
# HELP http_server_requests_active_seconds
# TYPE http_server_requests_active_seconds summary
http_server_requests_active_seconds_active_count{exception="none",method="GET",outcome="SUCCESS",status="200",uri="UNKNOWN",} 1.0
http_server_requests_active_seconds_duration_sum{exception="none",method="GET",outcome="SUCCESS",status="200",uri="UNKNOWN",} 0.00379906
......

Prometheus 拉取数据

更改配置文件

更改上述的 prometheus.yml 配置文件,添加 SpringBoot 应用的监控信息,完整的配置示例如下(请自行更改 SpringBoot 应用的 IP 地址):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
global:
scrape_interval: 15s
evaluation_interval: 15s

scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']

- job_name: 'spring-boot-actuator-demo'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['192.168.2.130:8080']
labels:
nodename: 'actuator-demo'

重启 Docker 容器

重启 Prometheus 的 Docker 容器,使配置文件的更改生效。

1
docker retart prometheus

验证配置文件生效

浏览器打开 Prometheus 的控制台管理界面,如 http://192.168.1.130:9090

菜单栏点击 Status -> Targets,查看各个监控任务的运行状态。

Grafana 添加监控面板

配置数据源

浏览器打开 Grafana 的控制台管理界面,如 http://192.168.1.130:3000,默认的登录账号和密码都是 admin

左侧菜单栏点击 Connections -> Data sources -> Add data source -> 选择 Prometheus -> 填写 Prometheus 的服务器地址(可以使用 Docker 容器的名称替代服务器的 IP) -> 点击 Save & test 按钮。

添加监控面板

在 Grafana 官方的 DashBoard 市场 搜索一款合适的 SpringBoot 监控面板,记录下 DashBoard 的 ID 或者下载对应的 JSON 文件。

左侧菜单栏点击 Dashboards -> New -> Import -> 填写 DashBoard 的 ID -> 点击 Load 按钮。

数据源选择上面已经配置好的 Prometheus,点击 Import 按钮。

上述配置全部完成后,就可以在 Grafana 的 DashBoard 看到完整的 SpringBoot 应用监控信息,监控数据来自 Prometheus + Actuator。