一文掌握Actuator,Spring Boot应用监控你想知道的都在这里

一文掌握Actuator,Spring Boot应用监控你想知道的都在这里

大家好,我是七哥。

咱们继续《Spring江湖路》第 8 回,持续更新中.....

0. 本文内容

之前一直有小伙伴让我出一篇 SpringBoot 四大核心特性之一 Actuator 的详细教程,那今天就安排上了。

你们可能都知道 Actuator是用来做监控的,但是具体能做什么,可能仍然是一知半解。这里给大家简单的介绍下。

Spring Boot Actuator 模块提供了生产级别的功能,比如健康检查,审计,指标收集,HTTP 跟踪等,帮助我们监控和管理 Spring Boot 应用。这个模块是一个采集应用内部信息暴露给外部的模块,上述的功能都可以通过 HTTP 和 JMX 访问。

那通过本文的学习,你可以掌握到 Spring BootActuator 到底提供了哪些生产级别的监控端点,同时也能掌握 Actuator 的各种使用方法。内容很详细,不管你是新手还是有多年经验的老鸟,都建议收藏下,总会用到的。

本文是基于SpringBoot2.5.2版本,适用于SpringBoot2.x版本,SpringBoot2 以下版本的可能有些端点名称发生了变更。

1. 开启 Actuator 的 Web 端点

对于SpringBoot开发的应用程序,想要启用 Actuator 的监控端点,只需要在项目中引入 Actuator 起步依赖即可。

gradle 构建说明文件中加入下面的配置:

implementation 'org.springframework.boot:spring-boot-starter-actuator'

如果是 maven 项目,引入如下依赖:

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifaceId>spring-boot-starter-actuator</artifaceId>
</dependency>

端点暴露配置

不同于 Actuator 1.x,Actuator 2.x 的大多数端点默认被禁掉。加入依赖后,我们如果直接去访问Actuator相关端点是行不通的,还需要在应用的属性配置文件 application.properties 中加入如下配置:

开放所有端点:

management.endpoints.web.exposure.include=* //打开所有的监控点

开放部分端点,例如下面的配置打开 beans 和 trace 两个端点

management.endpoints.web.exposure.exclude=beans,trace

Actuator 默认所有的监控点路径都在 /actuator/*,当然如果有需要这个路径也支持定制。例如下面的配置将前缀改成了 monitor,那么访问路径就变成了 /monitor/*

management.endpoints.web.base-path=/minitor

再补充下:/health 端点会聚合你程序的健康指标,用来检查程序的健康情况。端点公开的应用健康信息取决于参数 management.endpoint.health.show-details,该属性值可选项为:

  • never:不展示详细信息,up 或者 down 的状态,默认配置;
  • when-authorized:详细信息将会展示给通过认证的用户。授权的角色可以通过management.endpoint.health.roles 配置;
  • always:对所有用户暴露详细信息;

那我们用来学习的,就直接全部放开给所有用户了,生产环境可不敢这样搞哦~

management.endpoint.health.show-details=always

上面的依赖和配置项处理好了,应用程序启动运行时自动配置就会生效,将 Actuator 开启。接下来我们就开始整活了,将所有端点分为三大类:配置端点、度量端点和其它端点。

2. 查看配置明细的端点

1. 获取应用程序中 Spring 上下文的 Bean 装配情况

http://localhost:8080/actuator/beans // get请求

本地启动应用后,访问上面的地址,然后你就会得到下方的代码:

结果也是一目了然,我在图里做了标注,你就说是不是很贴心吧,

2. 详解自动配置

通过 /beans 端点产生的报告,我们知道了Spring上下文这个原本像黑盒一样的容器中都有哪些Bean。那接下来这个端点,就是用来告诉你这个 Bean 为什么会存在。

http://localhost:8080/actuator/conditions // get请求

本地启动应用后,访问上面的地址,然后你就会得到下方的代码:

这块你要知道,Spring Boot 的核心特性之一就是自动配置,它是基于Spring的条件化配置的,你也可以理解为就是那些 @Conditional注解配置类在作怪,根据条件是否成立决定是否帮你配置相关的Bean。

那相反,在 negativeMatches 里,就是表示所有条件不成立的自动配置类。

3. 查看配置属性

  • /env
http://localhost:8000/actuator/env  // get请求

这个 /env 端点就是用来获取我们应用中到底可以获取哪些环境属性值的,无论我们应用中是否用到,都会展示出来,包括了 环境变量、JVM 属性、命令行参数、application.propertiesapplication.xml 文件提供的属性。

那如果你想获取某一个属性的值,也非常的容易,直接在 /env后面加上属性名即可。比如我们想获取 server.port 属性值,则可以发送 /env/server.port 请求,获得结果是 8000。

  • /configprops
http://localhost:8000/actuator/configprops // get请求

我们在声明一些配置属性的时候,都会定义一个公共的 Java Bean ,然后通过 @ConfigurationProperties 注解将属性值绑定到 Java 对象上。 那具体的属性注入情况我们可以通过 /configprops 端点来查看报告。

上面的代码片段,说明 Spring Boot 源码中的 JpaProperties 添加了 @ConfigurationProperties 注解,属性前缀为 spring.jpa。那我们可以看下 JpaProperties 源码:

/configprops 这个端点我觉得用处还是比较大的,它除了展示应用程序的配置属性是如何设置的,同时也是一个非常好用的参考指南。

比如我们想配置嵌入式 Tomcat 服务器的最大线程数,但是不知道怎么改?

那这个时候我们只需要查看一下配置属性报告,就会发现 ServerProperties 这个配置类,它会获取前缀为 server 的属性值,里面有一个条 server.tomcat.threads.max 属性,默认值是200。 我们就可以通过设置这个 server.tomcat.threads.max 属性来修改 Tomcat 的最大线程数。这个操作是不是很香呢?

4. 接口路径和Controller的映射关系

如果你想知道你的应用程序都提供了哪些可以供前端访问的接口路径的话,这个时候就可以直接使用 /mappings 端点查看。

http://localhost:8000/actuator/mappings // get请求

访问这个端点后,我们会得到一个列表,可以很方便的了解应用程序在运行时接口的具体处理情况。下面我截取部分代码片段:

3. 查询应用度量指标

上面介绍完了配置相关的端点,接下来搞一组对于开发实践中很有用的端点,主要用来获取应用程序运行过程中用于监控的度量指标,比如:内存信息、线程池信息、HTTP 请求统计等。

1. 查询应用程序的各种运行指标

http://localhost:8000/actuator/metrics // get请求

/metrics 端点用来返回当前应用的各类重要度量指标,比如:内存信息、线程信息、垃圾回收信息、tomcat、数据库连接池等。当我们访问时,会返回 SpringBoot Actuator 的所有可查看端点信息,我将端点代表的含义也都帮大家备注了。

/ 20210916233722
// http://localhost:8000/actuator/metrics
{
  "names": [
    // hikaricp  Spring Boot2.x 选择的默认数据库连接池
    "hikaricp.connections", // 数据库连接池总连接数
    "hikaricp.connections.acquire", //单位时间内获取连接时间统计
    "hikaricp.connections.active", // 活跃连接数
    "hikaricp.connections.creation", // 创建连接时间
    "hikaricp.connections.idle", // 空闲连接
    "hikaricp.connections.max", // 最大连接数
    "hikaricp.connections.min", // 最小连接数
    "hikaricp.connections.pending", // 等待连接数
    "hikaricp.connections.timeout", // 获取连接超时总数
    "hikaricp.connections.usage", // 连接使用时间统计
    "http.server.requests", // 访问应用的总请求数
    "jdbc.connections.active", // 数据源分配的当前活跃连接数
    "jdbc.connections.idle", // 已和数据源建立的空闲连接数
    "jdbc.connections.max", // 同一时间最大可以建立的数据库连接数
    "jdbc.connections.min", // 数据库连接池中最小空闲连接数
    "jvm.buffer.count", // Java虚拟机缓冲区的个数估计
    "jvm.buffer.memory.used", // Java虚拟机用于这个缓冲池的内存的估计
    "jvm.buffer.total.capacity", // Java虚拟机中缓冲区总容量估计
    "jvm.classes.loaded", // 当前装入Java虚拟机中的类的数量
    "jvm.classes.unloaded", // 自虚拟机启动卸载的类总数
    "jvm.gc.live.data.size", // gc后老年代的大小
    "jvm.gc.max.data.size", // 老年代的最大内存
    "jvm.gc.memory.allocated", // 年轻代在一次gc后到下一次gc前过程中增长的内存大小
    "jvm.gc.memory.promoted", // 老年代有效gc次数
    "jvm.gc.pause", // gc暂停所花费的时间
    "jvm.memory.committed", // 提交给Java虚拟机使用的内存量(以字节为单位)
    "jvm.memory.max", // 可以用于jvm内存管理的最大内存数量(以字节为单位)
    "jvm.memory.used", // jvm已使用的内存数量
    "jvm.threads.daemon", // 当前活动守护进程线程的数量
    "jvm.threads.live", // 当前活动线程的数量,包括守护线程和非守护线程
    "jvm.threads.peak", // 自Java虚拟机启动后的最大活跃线程数
    "jvm.threads.states", // 当前处于BLOCKED状态的线程数
    "logback.events", // 记录到日志中的事件的数量
    "process.cpu.usage", // Java虚拟机进程的“最近cpu使用量”
    "process.files.max", // 最大文件描述符数量
    "process.files.open", // 当前打开的文件描述符数量
    "process.start.time", // 进程启动时间
    "process.uptime", // Java虚拟机的正常运行时间
    "spring.data.repository.invocations", // Spring中DAO访问数据库统计信息
    "system.cpu.count", // Java虚拟机可用的cpu数量
    "system.cpu.usage", // 整个系统的“最近的cpu使用量”
    "system.load.average.1m", // 一段时间内的CPU负载
    "tomcat.sessions.active.current", // tomcat服务器当前活跃会话数
    "tomcat.sessions.active.max", // tomcat最大会话数
    "tomcat.sessions.alive.max", // tomcat会话最大存活时间
    "tomcat.sessions.created", // tomcat会话已创建数量
    "tomcat.sessions.expired", // tomcat会话已创建数量
    "tomcat.sessions.rejected" // tomcat会话拒绝数量
  ]
}

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

2. 追踪Web请求

http://localhost:8080/actuator/httptrace // get请求

httptrace 端点可以提供所有 web 请求的详细信息,包括请求方法、路径、时间戳以及请求头等信息。

我在使用 Spring Boot 2.x 的时候发现这个端点默认是不能访问的会报404,需要自己实现添加一个配置类实现显示最近100个请求的信息,它是在内存中维护了一个跟踪库,当然我们也可以自定义这个跟踪库将信息持久化。

在应用中添加如下配置就可以显示这个 httptrance 端点了:

@Configuration
@ConditionalOnWebApplication
@ConditionalOnProperty(prefix = "management.trace.http", name = "enabled", matchIfMissing = true)
@EnableConfigurationProperties(HttpTraceProperties.class)
@AutoConfigureBefore(HttpTraceAutoConfiguration.class)
class TraceConfig {
    private List<HttpTrace> list = new CopyOnWriteArrayList<HttpTrace>();

    @Bean
    @ConditionalOnMissingBean(HttpTraceRepository.class)
    public HttpTraceRepository traceRepository() {
        return new HttpTraceRepository() {
            @Override
            public List<HttpTrace> findAll() {
                return list;
            }

            @Override
            public void add(HttpTrace trace) {
                if (list.size() > 99){
                    list.remove(0);
                }
                list.add(trace);
            }
        };
    }
}

3. 监控应用的健康状况

http://localhost:8080/actuator/health // get请求

如果你想知道自己的应用程序是否在运行,可以直接访问这个 /health 端点。

上面显示了数据库 h2、应用程序、磁盘空间的健康状态。

4. 关闭应用程序

接下来给大家介绍一个牛逼的杀手级端点,直接通过web端点关闭掉应用程序,这个端点适合如果有应用程序部署在云上,假设某个实例有问题了,我们需要关闭实例并且重启,这个命令就比较实用了。

/shutdown 端点需要发送 POST 请求,我们直接使用 curl 命令来操作。

curl --request POST http://localhost:8080/actuator/shutdown

那因为这个端点的杀伤力实在太大,所以默认是关闭的,我们需要手动打开,只需要在配置文件 application.properties 中加入一行配置即可。

management.endpoint.shutdown.enabled=true

执行后你会看到如下应用关闭提示信息:

5. 获取应用信息

http://localhost:8080/actuator/info // get请求

这个 /info 端点可以展示各种我们希望发布的应用信息,默认返回的是 {} ,一个空的字符串。我们可以通过在应用的配置文件 application.properties 中添加 info 前缀的属性,这样就可以在 /info 端点显示了。 比如我们希望提供应用作者的邮箱:

info.contactEmail=isevenluo@163.com

再次访问 /info 端点,就可以得到如下响应了:

6. 总结

通过这篇文章,我们了解到 Spring Boot2.x 提供的 Actuator 做监控指标收集的所有相关端点,同时我们讲解了 Spring Boot Actuator 的端点暴露配置以及常见的端点信息如何使用。

看到这里我们已经掌握了 Actuator 这些端点监控的指标如何读和使用,但是假如上生产环境部署,是不会直接放开这么多端点信息的,因为太不安全,所以往往需要和 Spring Security 做整合进行安全校验,还可能需要和 Grafana 整合将这些信息统一展示到面板上,但是这些都是后面我们要聊的内容,敬请期待!

那最后求个赞还是必须要的吧! 觉得不错,欢迎给 @程序员七哥 点个赞和分享,七哥感激不尽 ~

发布于 2021-10-08 08:09