利用SpringBoot Actuator 来构造/health /info 等监控接口

当我们用K8S 部署微服务时, 很多时候需要调用 service的/health 等状态接口, 已确定container的运行状态是否健康。

而Spring boot Actuator 就是用来快速构造这些状态接口的工具

引入依赖

xml 复制代码
        <!-- actuator -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

启用/health 和 /info 接口

yaml 复制代码
management:
  endpoints:
    web:
      exposure:
        include: "info, health, loggers, env"
      base-path: /actuator

所有的接口介绍可以参考:

https://www.baeldung.com/spring-boot-actuators

bash 复制代码
/auditevents lists security audit-related events such as user login/logout. Also, we can filter by principal or type among other fields.
/beans returns all available beans in our BeanFactory. Unlike /auditevents, it doesn't support filtering.
/conditions, formerly known as /autoconfig, builds a report of conditions around autoconfiguration.
/configprops allows us to fetch all @ConfigurationProperties beans.
/env returns the current environment properties. Additionally, we can retrieve single properties.
/flyway provides details about our Flyway database migrations.
/health summarizes the health status of our application.
/heapdump builds and returns a heap dump from the JVM used by our application.
/info returns general information. It might be custom data, build information or details about the latest commit.
/liquibase behaves like /flyway but for Liquibase.
/logfile returns ordinary application logs.
/loggers enables us to query and modify the logging level of our application.
/metrics details metrics of our application. This might include generic metrics as well as custom ones.
/prometheus returns metrics like the previous one, but formatted to work with a Prometheus server.
/scheduledtasks provides details about every scheduled task within our application.
/sessions lists HTTP sessions, given we are using Spring Session.
/shutdown performs a graceful shutdown of the application.
/threaddump dumps the thread information of the underlying JVM.

配置/health 接口的具体输出信息

默认/health 只会输出 status up or down, 如下

bash 复制代码
[gateman@manjaro-x13 ~]$ curl 127.0.0.1:8080/actuator/health
{"status":"UP"}

当我们在application.yml 加上下面配置后。

yml 复制代码
management:
  endpoint:
    health:
      show-details: always

会令到 /health 接口输出额外的components 信息:

json 复制代码
{
    "status": "UP",
    "components": {
        "diskSpace": {
            "status": "UP",
            "details": {
                "total": 1038214316032,
                "free": 840063606784,
                "threshold": 10485760,
                "exists": true
            }
        },
        "ping": {
            "status": "UP"
        }
    }
}

这时, 我们可以额外 地从/health 接口知道ping 和 磁盘使用的信息。

其实 只要ping 和 diskSpace的状态任何1个status 为down, 这个/health的总status 就是down

但是通常来讲, 只考虑这两个子状态是不足够的。

增加BigQuery conneciton 状态

举个例子, 假如某个service 里面连接bigQuery, 我们需要在/health 接口加1个component , 去detect BQ 的connection 是否健康。 如果这个BQ connection 为Down, 则/health status 为down

增加1个类 for checking the BQ connection
java 复制代码
@Component
@Slf4j
public class BigQueryHealthCheck {

    @Autowired
    private BigQuery bigQuery;

    public boolean isBigQueryHealthy() {
        CompletableFuture<Boolean> future = CompletableFuture.supplyAsync(() -> {
            try {
                bigQuery.listDatasets();
                return true;
            } catch (Exception e) {
                log.error("Error in BigQueryHealthCheck...", e);
                return false;
            }
        });

        try {
            // set time out to 5 seconds,  to wait for the return of future object.
            return future.get(5, TimeUnit.SECONDS);
        } catch (InterruptedException | ExecutionException | TimeoutException e) {
            log.error("Timeout or error while checking BigQuery connection", e);
            return false;
        }
    }
}

这里使用了CompletableFuture 类来设置1个5秒 timeout, 只要5秒内连不上BQ, 则认为BQ connection down

再增加1个类 for 增加1个BQ connection component to /health 接口
java 复制代码
@Component
public class BQHealthIndicator extends AbstractHealthIndicator {

    @Autowired
    private BigQueryHealthCheck bigQueryHealthCheck;

    @Override
    protected void doHealthCheck(Health.Builder builder) throws Exception {
        if (bigQueryHealthCheck.isBigQueryHealthy()) {
            //int i=1/0;
            builder.up();
        } else {
            builder.down();
        }
    }
}

注意这个类必须是1个bean, 而且类名的suffix 是 HealthIndicator

这样, 当我们再次测试/health 接口时, 就包括BQ connection的监测了!

json 复制代码
{
    "status": "UP",
    "components": {
        "BQ": {
            "status": "UP"
        },
        "diskSpace": {
            "status": "UP",
            "details": {
                "total": 1038214316032,
                "free": 839953145856,
                "threshold": 10485760,
                "exists": true
            }
        },
        "ping": {
            "status": "UP"
        }
    }
}

配置/info 接口的具体输出信息

默认下 /info 接口是什么信息都没有输出的,只有1个空的对象{}

如果我们想把service name, version 等信息写进info 接口, 也不复杂。

把pom.xml 的version 写入application.yml

在spring boot 中, 获取pom.xml 里面的具体字段值没有那么简单。

相对地, 从application.yml 获取configuration item的值是很容易的。

幸运地, 有1个方法可以把pom.xml 的内容写入application.yml

yml 复制代码
pom:
  version: @project.version@

在application yml里加入上面两行即可

添加1个类for /info的信息输出
java 复制代码
@Component
public class AppVersionInfo implements InfoContributor {

    @Autowired
    private Environment environment;

    @Value("${pom.version}") // https://stackoverflow.com/questions/3697449/retrieve-version-from-maven-pom-xml-in-code
    private String appVersion;

    @Override
    public void contribute(Info.Builder builder) {
        builder.withDetail("app", "Sales API")
                .withDetail("version", appVersion)
                .withDetail("description", "This is a simple Spring Boot application to demonstrate the use of BigQuery in GCP.");
    }
}

效果:

json 复制代码
{
    "app": "Sales API",
    "version": "1.0-SNAPSHOT",
    "description": "This is a simple Spring Boot application to demonstrate the use of BigQuery in GCP."
}

就是甘简单

相关推荐
我会冲击波11 分钟前
告别flag与status:如何为你的布尔值(boolean)变量优雅命名?
java·后端
工藤学编程16 分钟前
分库分表之实战-sharding-JDBC水平分库+分表后:查询与删除操作实战
数据库·spring boot·后端·sql·mysql
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ18 分钟前
如何将一个本地的jar包安装到 Maven 仓库中
java·maven·jar
N维世界26 分钟前
Mybatis-XML映射文件
xml·java·mybatis
码出极致28 分钟前
Redisson 分布式锁自动续期机制解析
后端
小塵29 分钟前
【DeepSeek 聊天】五分钟部署本地 DeepSeek
人工智能·后端·deepseek
土拨鼠的旅程31 分钟前
Go map 源码详解【2】—— map 插入
后端
泊浮目35 分钟前
生产级Rust代码品鉴(一)RisingWave一条SQL到运行的流程
大数据·后端·rust
弹简特1 小时前
【Java SE】Arrays工具类
java·开发语言
Touper.1 小时前
JavaSE -- Lambda表达式
java·开发语言