1、Spring Boot Actuator实现应用监控
前面的例子中,我们学习的都是 Prometheus 自身的内容,即监控的都是机器或者系统层面的指标。那么如果我
们需要对 Java 应用做监控,例如:监控 JVM 的信息,监控 Spring Bean 的信息。那我们应该怎么实现呢?
从这篇文章开始,我们就开始学习如何去监控 Java 应用的状态信息,并且最终实现自定义业务监控指标的监控。
1.1 Spring 监控机制
在学习如何监控 Java 应用之前,我们需要先了解下 SpringBoot 的监控机制。在 Spring 2.x 之前,SpringBoot 使
用 Actuator 模块进行监控,而在 Spring 2.x 之后,SpringBoot 使用了 Micrometer 进行监控。
Spring Boot Actuator 模块提供了生产级别的功能,比如健康检查,审计,指标收集,HTTP 跟踪等,帮助我们监
控和管理 Spring Boot 应用。这个模块是一个采集应用内部信息暴露给外部的模块,上述的功能都可以通过 HTTP
和 JMX 访问。
在 Spring 2.x 之后,Actuator 使用 Micrometer 与这些外部应用程序监视系统集成。这样一来,只需很少的配置
即可轻松集成外部的监控系统。
那什么是 Micrometer 呢?
Micrometer 为 Java 平台上的性能数据收集提供了一个通用的 API,应用程序只需要使用 Micrometer 的通用 API
来收集性能指标即可。Micrometer 会负责完成与不同监控系统的适配工作。这就使得切换监控系统变得很容易。
简单地说,actuator 是真正去采集数据的模块,而 Micrometer 更像是一个适配器,将 actuator 采集到的数据适
合给各种监控工具。
1.2 Spring Actuator 快速入门
接下来我们快速创建一个简单的项目,来让你明白 Spring Boot Actuator 能做什么。
我们到 Spring Initializr 创建一个名为 spring-web-actuator-demo 的项目,配置maven依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.6.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>spring-web-actuator-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-web-actuator-demo</name>
    <description>Spring Actuator 快速入门</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
            <version>2.4.5</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.4.5</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
 
启动文件:
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringWebActuatorDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringWebActuatorDemoApplication.class, args);
    }
}
 
打开项目后,直接运行 SpringWebActuatorDemoApplication.java 文件,正常情况下会使用 8080 端口作为服
务端口。
访问 localhost:8080/actuator/health 查看应用的健康状态,正常情况下会返回 UP 信息。

除了提供最基本的健康检查外,actuator 还提供了许多其他的端点(Endpoints)信息。通过这些端点信息,我们
可以掌握 99% 的应用状态信息。
1.3 端点暴露配置
不同于 Actuator 1.x,Actuator 2.x 的大多数端点默认被禁掉。所以在查看对应端点之前,我们需要做好配置,否
则我们是无法访问对应端点的。
我们可以通过以下配置,来配置通过 JMX 和 HTTP 暴露的端点。
| 属性 | 默认值 | 
|---|---|
| management.endpoints.jmx.exposure.exclude | |
| management.endpoints.jmx.exposure.include | * | 
| management.endpoints.web.exposure.exclude | |
| management.endpoints.web.exposure.include | info, health | 
我们可以选择打开所有的监控点,例如:
# 配置
management.endpoints.web.exposure.include=*
 
也可以选择打开部分端点,例如下面的配置打开 beans 和 trace 两个端点。
management.endpoints.web.exposure.exclude=beans,trace
 
Actuator 默认所有的监控点路径都在 /actuator/*,当然如果有需要这个路径也支持定制。例如下面的配置将前
缀改成了 monitor,那么访问路径就变成了 /monitor/*。
management.endpoints.web.base-path=/monitor
 
这里我们在 application.properties 中加入如下配置,默认打开所有端点。
management.endpoints.web.exposure.include=*
 
接着我们访问地址:localhost:8080/actuator/metrics,可以看到所有的指标地址。

如果我们要查看 process.uptime 指标,那么我们只需要访问
localhost:8080/actuator/metrics/process.uptime,就可以看到具体的信息。

1.4 常用端点介绍
Spring Boot Actuator 提供了 Endpoints(端点)给外部来与应用程序进行访问和交互。
例如 /health 端点提供了关于应用健康情况的一些基础信息,/metrics 端点提供了一些有用的应用程序指标
(JVM 内存使用、系统 CPU 使用等)。
一般来说,端点可以分为几类:
-  
应用配置类:获取应用程序中加载的应用配置、环境变量、自动化配置报告等与 Spring Boot 应用密切相关的
配置类信息。
 -  
度量指标类:获取应用程序运行过程中用于监控的度量指标,比如:内存信息、线程池信息、HTTP 请求统计
等。
 -  
操作控制类:提供了对应用的关闭等操作类功能。详细的原生端点介绍,请以官网为准,这里就不赘述徒增篇
幅。
 
1.4.1 health 端点
/health 端点会聚合你程序的健康指标,来检查程序的健康情况。端点公开的应用健康信息取决于参数
management.endpoint.health.show-details,该属性值可选项为:
| 属性值 | 描述 | 
|---|---|
| never | 不展示详细信息,up 或者 down 的状态,默认配置 | 
| when-authorized | 详细信息将会展示给通过认证的用户。授权的角色可以通过 management.endpoint.health.roles 配置 | 
| always | 对所有用户暴露详细信息 | 
接着在 application.properties 中增加如下参数,允许对所有用户暴露详细信息:
# 配置
management.endpoint.health.show-details=always
 
配置成 always 之后,启动应用,访问 localhost:8080/actuator/health 查看应用的健康状态,正常情况下
会返回 UP 信息。

在这里我们看到除了 status 状态之外,并没有其他信息。
这是因为我们应用中并没有其他依赖。当你的项目有依赖对应组件的时候,这些健康指示器就会被自动装配,继而
采集对应的信息。
现在我们在 pom.xml 文件中增加 redis 依赖:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
 
先启动redis,最终我们再次访问地址:localhost:8080/actuator/health。从图中我们可以看到 redis 的信息
了。
 
我们也可以通过配置禁用某个组件的健康监测,例如下面的配置禁用了 mongodb 的组件健康监测。
management.health.mongo.enabled: false
 
或者我们可以禁用所有自动配置的健康指示器:
management.health.defaults.enabled: false
 
例如在application.properties文件中配置:
# 配置
management.health.redis.enabled=false
 

常见的指示器有下面这些:
| 名称 | 描述 | 
|---|---|
| CassandraHealthIndicator | 检查Cassandra数据库是否已启动。 | 
| CouchbaseHealthIndicator | 检查Couchbase群集是否启动。 | 
| DiskSpaceHealthIndicator | 检查磁盘空间是否不足。 | 
| DataSourceHealthIndicator | 检查是否可以获取到DataSource的连接。 | 
| ElasticsearchHealthIndicator | 检查Elasticsearch群集是否启动。 | 
| InfluxDbHealthIndicator | 检查InfluxDB服务器是否启动。 | 
| JmsHealthIndicator | 检查JMS代理是否启动。 | 
| MailHealthIndicator | 检查邮件服务器是否启动。 | 
| MongoHealthIndicator | 检查Mongo数据库是否已启动。 | 
| Neo4jHealthIndicator | 检查Neo4j服务器是否启动。 | 
| RabbitHealthIndicator | 检查Rabbit服务器是否启动。 | 
| RedisHealthIndicator | 检查Redis服务器是否启动。 | 
| SolrHealthIndicator | 检查Solr服务器是否启动。 | 
除了使用自动引入的健康指示器之外,我们也可以自定义一个 Health Indicator,只需要实现 HealthIndicator 接
口或者继承 AbstractHealthIndicator 类。
例如下面我们创建了一个 CustomHealthIndicator 类,继承了 AbstractHealthIndicator 类,并返回了一些健康信
息。
package com.example;
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.stereotype.Component;
/**
 * @author zhangshixing
 * @date 2022年03月16日 12:30
 */
@Component
public class CustomHealthIndicator extends AbstractHealthIndicator {
    @Override
    protected void doHealthCheck(Health.Builder builder) throws Exception {
        // 使用 builder 来创建健康状态信息
        // 如果你throw 了一个 exception,那么status 就会被置为DOWN,异常信息会被记录下来
        builder.up()
                .withDetail("app", "向你报告:项目很健康哦!")
                .withDetail("error", "向你报告:项目有点问题哦!");
    }
}
 
我们重启应用并访问地址:localhost:8080/actuator/health,我们可以看到自定义的健康信息。

1.4.2 metrics 端点
/metrics 端点用来返回当前应用的各类重要度量指标,比如:内存信息、线程信息、垃圾回收信息、tomcat、
数据库连接池等。当我们访问:localhost:8080/actuator/metrics 时,会返回 SpringBoot Actuator 的所有
可查看端点信息。

我们可以进一步使用如下格式的 URL 访问到对应的信息:
http://localhost:8080/actuator/metrics/{MetricName}
 
例如我想访问 system.cpu.count 这个指标,那么我访问这个链接即可:
localhost:8080/actuator/metrics/system.cpu.count,返回值为:

1.4.3 loggers 端点
/loggers 端点暴露了我们程序内部配置的所有 logger 的信息,我们访问这个链接就可以看到:
localhost:8080/actuator/loggers。

我们也可以通过下述方式访问某一个 logger
http://localhost:8080/actuator/loggers/{name}
 
例如我想访问 Root Logger,就可以访问这个链接:localhost:8080/actuator/loggers/ROOT,返回信息
如下:
 
1.4.4 info 端点
/info 端点可以用来查看配置文件 application.properties 中 info 节点下的配置信息,默认情况下
application.properties 中并没有 info 节点配置,所以当我们访问 localhost:8080/actuator/info 时
会访问空 JSON 串。
接下来我们在 application.properties 中增加了如下配置:
# 配置
info.app.name=actuator-test-demo
info.app.encoding=UTF-8
info.app.java.source=1.8
info.app.java.target=1.8
 
再次访问localhost:8080/actuator/info 会返回 info 节点的信息:

同时我们还可以这么配置 info 端点,而不是硬编码这些值,我们就可以按照如下所示的配置:
# 配置
info.app.encoding=@project.build.sourceEncoding@
info.app.java.source=@java.version@
info.app.java.target=@java.version@
 

要注意,info 端点只会返回 info 节点下的信息,而不会返回其他节点下的信息。例如我在配置文件中添加如下配
置:
student.name=ronald
 
这时候通过 info 端点是访问不到该配置信息的。
1.4.5 beans 端点
/beans 端点会返回 Spring 容器中所有 bean 的别名、类型、是否单例、依赖等信息。
当我们访问 localhost:8080/actuator/beans 时,会返回如下信息:

1.4.6 heapdump 端点
访问 http://localhost:8080/actuator/heapdump 会自动生成一个 JVM 的堆文件 heapdump。

我们可以使用 JDK 自带的 JVM 监控工具 VisualVM 打开此文件查看内存快照。
1.4.7 threaddump 端点
访问 localhost:8080/actuator/threaddump 会返回应用的线程信息,包括线程名、线程 ID、线程的状态、
是否等待锁资源、线程堆栈等信息。

1.4.8 shutdown 端点
这个端点属于操作控制类端点,可以优雅关闭 Spring Boot 应用。要使用这个功能首先需要在配置文件中开启:
# 配置
management.endpoint.shutdown.enabled=true
 
由于 shutdown 接口默认只支持 POST 请求,我们启动 Demo 项目,向
http://localhost:8080/actuator/shutdown 发起 POST 请求。

远程操作相对来说比较危险,所以一般在线上都不会开启这个端点。
1.5 总结
通过这篇文章,我们了解到 Spring 是利用 Spring Boot Actuator 进行监控指标收集的。与此同时,我们用一个极
简单的例子讲解了如何进行应用监控。最后我们讲解了 Spring Boot Actuator 的端点暴露配置以及常见的端点信
息。


















