Spring Boot Actuator监控使用
2021-02-06 16:47:58 阿炯

在实际的软件开发中需要对应用程序的监控和管理,SpringBoot的Actuator模块实现了应用的监控与管理。常见是使用JMX对Java应用程序包括JVM进行监控,使用JMX需要把一些监控信息以MBean的形式暴露给JMX Server,而Spring Boot已经内置了一个监控功能,它叫Actuator。使用Actuator非常简单,只需添加如下依后正常启动应用程序,Actuator会把它能收集到的所有信息都暴露给JMX。Actuator还可以通过URL/actuator/挂载一些监控点,许多网关作为反向代理需要一个URL来探测后端集群应用是否存活,这个URL就可以提供给网关使用。


Actuator简介

生产系统中,往往需要对系统实际运行的情况例如cpu、disk-net_io、db、业务功能等指标进行监控运维。在SpringBoot项目中Actuator模块提供了众多HTTP接口端点Endpoint,来提供应用程序运行时的内部状态信息。

Actuator模块提供了一个监控和管理生产环境的模块,可以使用http、jmx、ssh、telnet等来管理和监控应用。包括应用的审计Auditing、健康health状态信息、数据采集metrics gathering统计等监控运维的功能。同时,提供了可以扩展 Actuator端点Endpoint自定义监控指标。这些指标都是以JSON接口数据的方式呈现。actuator有助于对应用程序进行监视和管理,通过 restful api 请求来监管、审计、收集应用的运行情况,针对微服务而言它是必不可少的一个环节。


Actuator的使用

使用Spring Boot Actuator需要加入如下依赖:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

actuator并没有默认集成在自动配置中,而在作为独立的项目来呈现的。当引入了上面的依赖,默认会引入actuator相关的两个项目:
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-actuator</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-actuator-autoconfigure</artifactId>
</dependency>

其中spring-boot-actuator为功能实现,spring-boot-actuator-autoconfigure为自动配置。例如输入http://localhost:8080/actuator/health,我们可以查看应用程序当前状态:
{
  "status": "UP"
}

需要注意:因SpringBoot Actuator会暴露服务的详细信息,为了保障安全性,建议添加安全控制的相关依赖spring-boot-starter-security,这样在访问应用监控端点时,都需要输入验证信息。所需依赖如下:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

关于security的使用我们在此不进行展开,可在application文件中配置相应的访问密码:
spring:
  security:
    user:
      name: admin
      password: admin_pWd

在下面的内容中为了方便,我们暂时不引入security。

经过以上步骤的操作,启动SpringBoot项目,actuator便自动集成配置了,可通过:http://localhost:8080/actuator 访问,结果如下:
{
    "_links": {
        "self": {
            "href": "http://localhost:8080/actuator",
            "templated": false
        },
        "health": {
            "href": "http://localhost:8080/actuator/health",
            "templated": false
        },
        "health-component": {
            "href": "http://localhost:8080/actuator/health/{component}",
            "templated": true
        },
        "health-component-instance": {
            "href": "http://localhost:8080/actuator/health/{component}/{instance}",
            "templated": true
        },
        "info": {
            "href": "http://localhost:8080/actuator/info",
            "templated": false
        }
    }
}

默认支持的链接有:
/actuator
/actuator/health
/health/{component}/{instance}
/health/{component}
/actuator/info

可以在application配置文件中配置开启更多的监控信息:
management:
  endpoints:
    web:
      exposure:
        include: '*'
#      base-path: /monitor
  endpoint:
    health:
      show-details: always
    shutdown:
      enabled: true

management.endpoints.web.exposure.include='*',代表开启全部监控,也可仅配置需要开启的监控,如: management.endpoints.web.exposure.include=beans,trace。
management.endpoint.health.show-details=always,health endpoint开启显示全部细节。默认情况下/actuator/health是公开的,但不显示细节。
management.endpoints.web.base-path=/monitor,启用指定的url地址访问根路径,默认路径为/actuator/*,开启则访问路径变为/monitor/*。
management.endpoint.shutdown.enabled=true,启用接口关闭SpringBoot。

监控信息如果需要跨越调用,可通过CORS配置来支持,默认处于禁用状态。设置management.endpoints.web.cors.allowed-origins属性后开启。

比如允许来自https://www.freeoa.net 主机的GET和POST调用:
management:
  endpoints:
    web:
      cors:
        allowed-origins: https://www.reeoa.net
        allowed-methods: GET,POST

REST接口

Spring Boot Actuator提供了非常丰富的监控接口,可以通过这些接口了解应用程序运行时的内部状况。Actuator也支持用户自定义添加端点,可以根据实际应用,定义一些比较关心的指标,在运行期进行监控。
HTTP方法路径描述
GET/auditevents显示当前应用程序的审计事件信息
GET/beans显示一个应用中所有Spring Beans的完整列表
GET/conditions显示配置类和自动配置类(configuration and auto-configuration classes)的状态及它们被应用或未被应用的原因。
GET/configprops显示一个所有@ConfigurationProperties的集合列表
GET/env显示来自Spring的ConfigurableEnvironment的属性。
GET/flyway显示数据库迁移路径,如果有的话。
GET/health显示应用的健康信息当使用一个未认证连接访问时显示一个简单的’status’,使用认证连接访问则显示全部信息详情
GET/info显示任意的应用信息
GET/liquibase展示任何Liquibase数据库迁移路径,如果有的话
GET/metrics展示当前应用的metrics信息
GET/mappings显示一个所有@RequestMapping路径的集合列表
GET/scheduledtasks显示应用程序中的计划任务
GET/sessions允许从Spring会话支持的会话存储中检索和删除(retrieval and deletion)用户会话。使用Spring Session对反应性Web应用程序的支持时不可用。
POST/shutdown允许应用以优雅的方式关闭默认情况下不启用
GET/threaddump执行一个线程dump

如果使用web应用(Spring MVC, Spring WebFlux, 或者 Jersey),还可以使用以下接口:

HTTP方法路径描述
GET/heapdump返回一个GZip压缩的hprof堆dump文件
GET/jolokia通过HTTP暴露JMX beans当Jolokia在类路径上时,WebFlux不可用
GET/logfile返回日志文件内容如果设置了logging.file或logging.path属性的话,支持使用HTTP Range头接收日志文件内容的部分信息
GET/prometheus以可以被Prometheus服务器抓取的格式显示metrics信息



接口详解

health主要用来检查应用的运行状态,这是使用频次最高的监控点。通常使用此接口显示应用实例的运行状态,以及应用不“健康”的原因,比如数据库连接、磁盘空间不够等。默认情况下health的状态是开放的,访问:http://localhost:8080/actuator/health 即可看到应用的状态。
{
 "status" : "UP"
}

设置状态码顺序:setStatusOrder(Status.DOWN,Status.OUT_OF_SERVICE, Status.UP, Status.UNKNOWN)。过滤掉不能识别的状态码。如果无任何状态码,整个SpringBoot应用的状态是UNKNOWN,将所有收集到的状态码排序。返回有序状态码序列中的第一个状态码,作为整个SpringBoot应用的状态。

Health通过合并几个健康指数检查应用的健康情况,SpringBoot Actuator会自动配置以下内容:
名称描述
CassandraHealthIndicator检查Cassandra数据库是否已启动。
CouchbaseHealthIndicator检查Couchbase群集是否已启动。
DiskSpaceHealthIndicator检查磁盘空间不足。
DataSourceHealthIndicator检查是否可以建立连接DataSource。
ElasticsearchHealthIndicator检查Elasticsearch集群是否已启动。
InfluxDbHealthIndicator检查InfluxDB服务器是否已启动。
JmsHealthIndicator检查JMS代理是否启动。
MailHealthIndicator检查邮件服务器是否已启动。
MongoHealthIndicator检查Mongo数据库是否已启动。
Neo4jHealthIndicator检查Neo4j服务器是否已启动。
RabbitHealthIndicator检查Rabbit服务器是否已启动。
RedisHealthIndicator检查Redis服务器是否启动。
SolrHealthIndicator检查Solr服务器是否已启动。


可以通过设置 management.health.defaults.enabled属性来全部禁用。


Endpoints

actuator 的核心部分,它用来监视应用程序及交互,spring-boot-actuator中已经内置了非常多的 Endpointshealth、info、beans、httptrace、shutdown等等,同时也允许我们自己扩展自己的端点。Spring Boot 2.0 中的端点和之前的版本有较大不同,使用时需注意。另外端点的监控机制也有很大不同,启用了不代表可以直接访问,还需要将其暴露出来,传统的management.security管理已被标记为不推荐。
iddescSensitive
auditevents显示当前应用程序的审计事件信息Yes
beans显示应用Spring Beans的完整列表Yes
caches显示可用缓存信息Yes
conditions显示自动装配类的状态及及应用信息Yes
configprops显示所有 @ConfigurationProperties 列表Yes
env显示 ConfigurableEnvironment 中的属性Yes
flyway显示 Flyway 数据库迁移信息Yes
health显示应用的健康信息未认证只显示status,认证显示全部信息详情No
info显示任意的应用信息在资源文件写info.xxx即可No
liquibase展示Liquibase 数据库迁移Yes
metrics展示当前应用的 metrics 信息Yes
mappings显示所有 @RequestMapping 路径集列表Yes
scheduledtasks显示应用程序中的计划任务Yes
sessions允许从Spring会话支持的会话存储中检索和删除用户会话。Yes
shutdown允许应用以优雅的方式关闭默认情况下不启用Yes
threaddump执行一个线程dumpYes
httptrace显示HTTP跟踪信息默认显示最后100个HTTP请求 - 响应交换Yes


Spring Boot默认的健康端点就很有可能不能满足,先看看默认装配 HealthIndicators。下列是依赖spring-boot-xxx-starter后相关HealthIndicator的实现通过management.health.defaults.enabled 属性可以禁用它们,但想要获取一些额外的信息时,自定义的作用就体现出来了。
名称描述
CassandraHealthIndicator检查 Cassandra 数据库是否启动。
DiskSpaceHealthIndicator检查磁盘空间不足。
DataSourceHealthIndicator检查是否可以获得连接 DataSource
ElasticsearchHealthIndicator检查 Elasticsearch 集群是否启动。
InfluxDbHealthIndicator检查 InfluxDB 服务器是否启动。
JmsHealthIndicator检查 JMS 代理是否启动。
MailHealthIndicator检查邮件服务器是否启动。
MongoHealthIndicator检查 Mongo 数据库是否启动。
Neo4jHealthIndicator检查 Neo4j 服务器是否启动。
RabbitHealthIndicator检查 Rabbit 服务器是否启动。
RedisHealthIndicator检查 Redis 服务器是否启动。
SolrHealthIndicator检查 Solr 服务器是否已启动。


内置Endpoints

原生端点

原生端点分为三大类:
应用配置类:获取应用程序中加载的应用配置、环境变量、自动化配置报告等与Spring Boot应用密切相关的配置类信息。
度量指标类:获取应用程序运行过程中用于监控的度量指标,比如:内存信息、线程池信息、HTTP请求统计等。
操作控制类:提供了对应用的关闭等操作类功能。



应用配置类

/conditions:该端点用来获取应用的自动化配置报告,其中包括所有自动化配置的候选项。同时还列出了每个候选项自动化配置的各个先决条件是否满足。该端点可以帮助我们方便的找到一些自动化配置为什么没有生效的具体原因。该报告内容将自动化配置内容分为两部分:positiveMatches中返回的是条件匹配成功的自动化配置和negativeMatches中返回的是条件匹配不成功的自动化配置。

/info:就是在配置文件中配置的以info开头的信息,如配置为:
info:
  app:
    name: spring-boot-actuator
    version: 1.0.0

返回结果:
{
  "app":{
    "name":"spring-boot-actuator",
    "version":"1.0.0"
  }
}

info中配置的参数也可以通过符号*@*包围的属性值来自pom.xml文件中的元素节点。

/beans:该端点用来获取应用上下文中创建的所有Bean。

接口展现了bean的别名、类型、是否单例、类的地址、依赖等信息。

/configprops:该端点用来获取应用中配置的属性信息报告。

/mappings:该端点用来返回所有SpringMVC的控制器映射关系报告。

/env:该端点与/configprops不同,它用来获取应用所有可用的环境属性报告。包括:环境变量、JVM属性、应用的配置配置、命令行中的参数。

度量指标类

应用配置类提供的指标为静态报告,而度量指标类端点提供的报告内容则是动态变化的,提供了应用程序在运行过程中的一些快照信息,比如:内存使用情况、HTTP请求统计、外部资源指标等。这些端点对于构建微服务架构中的监控系统非常有帮助。

/metrics:该端点用来返回当前应用的各类重要度量指标,比如:内存信息、线程信息、垃圾回收信息等。


从上面的示例中有这些重要的度量值:
系统信息:包括处理器数量processors、运行时间uptime和instance.uptime、系统平均负载systemload.average。
mem.*:内存概要信息,包括分配给应用的总内存数量以及当前空闲的内存数量。这些信息来自java.lang.Runtime。
heap.*:堆内存使用情况。这些信息来自java.lang.management.MemoryMXBean接口中getHeapMemoryUsage方法获取的java.lang.management.MemoryUsage。
nonheap.*:非堆内存使用情况。这些信息来自java.lang.management.MemoryMXBean接口中getNonHeapMemoryUsage方法获取的java.lang.management.MemoryUsage。
threads.*:线程使用情况,包括线程数、守护线程数daemon、线程峰值peak等,这些数据均来自java.lang.management.ThreadMXBean。
classes.*:应用加载和卸载的类统计。这些数据均来自java.lang.management.ClassLoadingMXBean。
gc.*:垃圾收集器的详细信息,包括垃圾回收次数gc.ps_scavenge.count、垃圾回收消耗时间gc.ps_scavenge.time、标记-清除算法的次数gc.ps_marksweep.count、标记-清除算法的消耗时间gc.ps_marksweep.time。这些数据均来自java.lang.management.GarbageCollectorMXBean。
httpsessions.*:Tomcat容器的会话使用情况。包括最大会话数httpsessions.max和活跃会话数httpsessions.active。该度量指标信息仅在引入了嵌入式Tomcat作为应用容器的时候才会提供。
gauge.*:HTTP请求的性能指标之一,它主要用来反映一个绝对数值。比如上面示例中的gauge.response.hello: 5,它表示上一次hello请求的延迟时间为5毫秒。
counter.*:HTTP请求的性能指标之一,它主要作为计数器来使用,记录了增加量和减少量。如上示例中counter.status.200.hello: 11,它代表了hello请求返回200状态的次数为11。

/threaddump:会生成当前线程活动的快照,方便我们在日常定位问题的时候查看线程的情况。主要展示了线程名、线程ID、线程的状态、是否等待锁资源等信息。

/trace:该端点用来返回基本的HTTP跟踪信息。默认情况下,跟踪信息的存储采用。

操作控制类

/shutdown:配置文件中配置开启此功能:
management.endpoint.shutdown.enabled=true

使用 curl 模拟 post 请求此接口:
curl -X POST "http://localhost:8080/actuator/shutdown"

显示结果为:
{
 "message": "Shutting down, bye..."
}


许多网关作为反向代理需要一个URL来探测后端集群应用是否存活,这个URL就可以提供给网关使用。Actuator默认把所有访问点暴露给JMX,但处于安全原因,只有health和info会暴露给Web。Actuator提供的所有访问点均在官方文档列出,要暴露更多的访问点给Web,需要在application.yml中加上配置:
management:
  endpoints:
    web:
      exposure:
        include: info, health, beans, env, metrics

要特别注意暴露的URL的安全性,比如/actuator/env可以获取当前机器的所有环境变量,不可暴露给公网。

保护HTTP端点

应该注意保护HTTP端点的方式与使用其他任何敏感网址的方式相同。如果存在Spring Security,则默认使用Spring Security的内容协商策略(content-negotiation strategy)保护端点。例如,如果希望为HTTP端点配置自定义安全性,比方说只允许具有特定角色的用户访问它们,Spring Boot提供了一些方便的RequestMatcher对象,可以与Spring Security结合使用。

跨域支持

跨源资源共享Cross-origin resource sharing,CORS是W3C规范,允许以灵活的方式指定授权哪种跨域请求。如果使用Spring MVC或Spring WebFlux,则可以配置Actuator的Web端点来支持这些场景。

默认情况下,CORS支持处于禁用状态,只有在设置了management.endpoints.web.cors.allowed-origins属性后才能启用。以下配置允许来自freeoa.net域的GET和POST调用:
management.endpoints.web.cors.allowed-origins=http://freeoa.net
management.endpoints.web.cors.allowed-methods=GET,POST

通过HTTP进行监控和管理

如果正在开发Web应用程序,Spring Boot Actuator会自动配置所有已启用的端点以通过HTTP进行公开。默认约定是使用以/actuator作为前缀的端点的ID作为URL路径。例如,health被暴露为/actuator/health。Actuator本身支持Spring MVC,Spring WebFlux和Jersey。

1)自定义管理端点路径

有时候,自定义管理端点的前缀非常有用。例如应用程序可能已经将/actuator用于其他目的。可以使用management.endpoints.web.base-path属性更改管理端点的前缀,如以下示例中所示:
management.endpoints.web.base-path=/manage

前面的application.properties示例将端点从/actuator/{id}更改为/manage/{id}例如/manage/info。

除非管理端口已配置为使用不同的HTTP端口公开端点,否则management.endpoints.web.base-path与server.servlet.context-path相关。如果配置了management.server.port,则management.endpoints.web.base-path将与management.server.servlet.context-path相关。

2)自定义管理服务器端口

通过使用默认的HTTP端口公开管理端点是基于云的部署的明智选择。但如果您的应用程序在您自己的数据中心内运行,则可能希望使用不同的HTTP端口来公开端点。可以设置management.server.port属性来更改HTTP端口,如以下示例所示:
management.server.port=8081

3)配置管理专用SSL

配置为使用自定义端口时,管理服务器也可以使用各种management.server.ssl.*属性配置自己的SSL。通过这样做,管理服务器可通过HTTP使用,而主应用程序使用HTTPS,如以下属性设置所示:
server.port=8443
server.ssl.enabled=true
server.ssl.key-store=classpath:store.jks
server.ssl.key-password=secret
management.server.port=8080
management.server.ssl.enabled=false

或者,主服务器和管理服务器都可以使用SSL,但使用不同的密钥存储区,如下所示:
server.port=8443
server.ssl.enabled=true
server.ssl.key-store=classpath:main.jks
server.ssl.key-password=secret
management.server.port=8080
management.server.ssl.enabled=true
management.server.ssl.key-store=classpath:management.jks
management.server.ssl.key-password=secret

4)自定义管理服务器地址

可以通过设置management.server.address属性来自定义管理端点可用的地址。如果只想在内部网络或面向操作系统的网络上收听,或只收听本地主机的连接,那么这样做会很有用。只有当端口与主服务器端口不同时,才可以监听其他地址。以下示例application.properties不允许远程管理连接:
management.server.port=8081
management.server.address=127.0.0.1

5)禁用HTTP端点

如果不想通过HTTP公开端点,则可以将管理端口设置为-1,如以下示例所示:
management.server.port=-1

下面是内置健康状态类型对应的HTTP状态码列表:
StatusMapping
DOWNSERVICE_UNAVAILABLE (503)|服务不可用 (503)
OUT_OF_SERVICESERVICE_UNAVAILABLE (503)|服务不可用 (503)
UPNo mapping by default, so http status is 200|默认情况下没有映射,所以http状态是200
UNKNOWNNo mapping by default, so http status is 200|默认情况下没有映射,所以http状态是200