跳至主要内容

Spring Boot Actuator 2 示例

Welcome file

简介

Spring Boot Actuator为应用程序提供了各种开箱即用的运维特性,可以与应用方便的交互和监控。

使用环境:Java 11 和 Spring Boot 2.4.3.RELEASE

集成Spring Boot Actuator

在Spring Boot中集成Spring Boot Actuator与集成其他的框架类似,在pom.xml里引入相关的starter就可以:

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

由于大部分的使用场景还是web,所以这里也用Spring MVC做示例。

配置好pom.xml后,默认actuator仅暴露一些基本功能,实际使用中,根据需求暴露对应功能。为了简便测试,这里在application.yml中配置暴露全部功能:

management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      enabled: true
      show-details: always
      probes:
        enabled: true
    shutdown:
      enabled: true
  metrics:
    export:
      jmx:
        enabled: false
server:
  shutdown: graceful

之后启动程序,在控制台应该能看到以下输出:

2021-03-08 23:05:08.555  INFO 32637 --- [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 16 endpoint(s) beneath base path '/actuator'

常用内置功能

Actuator内置了许多功能接口,下面介绍一些个人常用的。

查看缓存

/actuator/caches

这个接口能查看被Spring管理的缓存,依赖具体实现

查看环境

/actuator/env

这个接口能看到目前生效的环境参数

查看程序运行指标

/actuator/metrics

访问之后能得到目前可以查询的指标:

{"names":["http.server.requests","jvm.buffer.count","jvm.buffer.memory.used","jvm.buffer.total.capacity","jvm.classes.loaded","jvm.classes.unloaded","jvm.gc.live.data.size","jvm.gc.max.data.size","jvm.gc.memory.allocated","jvm.gc.memory.promoted","jvm.gc.pause","jvm.memory.committed","jvm.memory.max","jvm.memory.used","jvm.threads.daemon","jvm.threads.live","jvm.threads.peak","jvm.threads.states","logback.events","process.cpu.usage","process.files.max","process.files.open","process.start.time","process.uptime","running.demo.timer","system.cpu.count","system.cpu.usage","system.load.average.1m","tomcat.sessions.active.current","tomcat.sessions.active.max","tomcat.sessions.alive.max","tomcat.sessions.created","tomcat.sessions.expired","tomcat.sessions.rejected"]}

直接在url后加上对应的指标key能查询具体结果,比如:

/actuator/metrics/system.cpu.count

可以查看到结果:

{"name":"system.cpu.count","description":"The number of processors available to the Java virtual machine","baseUnit":null,"measurements":[{"statistic":"VALUE","value":12.0}],"availableTags":[]}

查看Request Mapping

/actuator/mappings

查看定时任务

/actuator/scheduledtasks

查看Thread dump

/actuator/threaddump

扩展内置功能

扩展HealthIndicator

定时的健康检查能及时发现应用中的问题,actuator默认提供了一系列内置的应用健康指标:

/actuator/health

访问之后可以看到结果:

{"status":"UP","components":{"diskSpace":{"status":"UP","details":{"total":999995129856,"free":965321064448,"threshold":10485760,"exists":true}},"livenessState":{"status":"UP"},"ping":{"status":"UP"},"readinessState":{"status":"UP"}},"groups":["liveness","readiness"]}

默认提供的是较为通用的健康指标,我们可以根据应用的特点,提供自定义的健康检查指标。比如对各种外部依赖的检查,应用内部状态的检查等。

假如应用对接了一个外部系统,我们可以扩展HealthIndicator来提供新的健康指标。扩展需要实现HealthIndicator接口,覆盖health()方法,并返回Health对象:

@Component
public class DemoHealthIndicator implements HealthIndicator {

    private static final HttpClient httpClient = HttpClient.newBuilder()
            .version(HttpClient.Version.HTTP_1_1)
            .connectTimeout(Duration.ofSeconds(10))
            .build();

    @Override
    public Health health() {
        return checkFooServiceHealth();
    }

    public Health checkFooServiceHealth(){
        try {
            HttpRequest request = HttpRequest.newBuilder()
                    .GET()
                    .uri(URI.create("https://start.spring.io/"))
                    .build();

            HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
            if (response.statusCode() == 200) {
                return Health.up()
                        .withDetail("statusCode", response.statusCode()).build();
            }
            return Health.down()
                    .withDetail("statusCode", response.statusCode()).build();
        } catch (Exception e) {
            return Health.unknown()
                    .withDetail("exception", e.getMessage()).build();
        }
    }
}

这时再访问health接口,可以看到返回结果已经加上了自定义的健康指标:

{"status":"UP","components":{"demo":{"status":"UP","details":{"statusCode":200}},"diskSpace":{"status":"UP","details":{"total":999995129856,"free":965321064448,"threshold":10485760,"exists":true}},"livenessState":{"status":"UP"},"ping":{"status":"UP"},"readinessState":{"status":"UP"}},"groups":["liveness","readiness"]}

扩展InfoContributor

Info接口主要提供应用程序相关信息,一般会放在当前运行版本中不会改变的信息。比如访问Elasticsearch,就会展示一串json,表示当前Elasticsearch的版本,构建时间等信息。在实际应用中,我们可以使用该接口提供开发者信息,应用名称,版本,git版本等信息。

自定义Info信息与上面类似,实现InfoContributor接口,覆盖contribute方法:

@Component
public class DemoInfo implements InfoContributor {

    @Value("${spring.application.name}")
    private String application;

    @Override
    public void contribute(Info.Builder builder) {
        builder.withDetail("application", application)
                .withDetail("git-version", "2d5fg23")
                .withDetail("version", "1.0-SNAPSHOT")
                .withDetail("dev", "Nereus Yi");
    }

}

为了演示简便,git-version、version信息直接写在代码里,实际应用中,可以通过读取根据maven构建信息来实现。

这时再访问info接口,

/actuator/info

可以看到返回结果已经加上了自定义的信息:

{"application":"actuator-demo","git-version":"2d5fg23","version":"1.0-SNAPSHOT","dev":"Nereus Yi"}

总结

本文展示了actuator的常用功能示例和一些扩展,示例工程可以在Github上找到。

参考资料

[1]https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html

评论

此博客中的热门博文

国密SM2签名封装成PKCS7格式

在国内做金融行业,难免会有被强制使用国密算法的情况,而且一般还会指定必须使用硬件加密机之类的设备,所以我也稍微的研究了一下国密算法,使用软算法签名并封装 PKCS7 格式(文档中的一个交互)。 以下是基于 Bouncy Castle 的示例,密钥对的生成可以参考 Bouncy Castle 中 test 包下 SM2 相关代码 public static String sign ( ) throws Exception { //加载公钥 byte [ ] plainText = "hello, world" . getBytes ( ) ; FileInputStream input = new FileInputStream ( "F:\\certificate\\public.cer" ) ; CertificateFactory certificateFactory = new CertificateFactory ( ) ; X509Certificate certificate = ( X509Certificate ) certificateFactory . engineGenerateCertificate ( input ) ; input . close ( ) ; //加载私钥,private为换成实际的私钥 PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec ( "private" . getBytes ( ) ) ; //SM2算法实际上为ECC算法,并指定了一些参数值,所以这里的参数是EC KeyFactory factory = KeyFactory . getInstance ( "EC" , "BC" ) ; PrivateKey privateKey = factory . generatePrivate ( spec ) ; //以下为签名并封装成PKCS7格式 byte [ ] signedMessag

NextCloud数据目录迁移

最近服务器的环境坏了,所以迁移了NextCloud的数据目录。不过在迁移过程中有点小问题。 环境: Ubuntu 18.04 Docker 19.03.7 1.NextCloud页面不正常,Docker日志显示XX目录permission denied 参考了 这里 的做法,不过是把  /var/www/html/   整个目录的权限都修改为  chown -R www-data:www-data ,之后就不再报权限问题了。 2.数据库配置修改 因为NextCloud是在初始化时填的数据库连接信息,所以直接迁移数据目录的情况下,会导致应用连不到新的数据库环境。此时可以找到数据目录下的  config/config.php 文件,直接修改数据库连接配置。