CLOVER🍀

That was when it all began.

Spring Boot Actuatorでデータストア(JDBC、Redis)を含んだヘルスチェックを行う

これは、なにをしたくて書いたもの?

Spring Boot Actuatorのヘルスチェックを行う時に、一緒にデータストアなどのヘルスチェックも行ってくれるようなので、
ちょっと見てみました。

Spring Boot Actuator/Health Information

そもそも、Spring Boot Actuatorは?というところからですが。

Spring Boot Actuatorは、本番環境でアプリケーションを動作させる際にモニタリング、管理するのに便利な機能を含んだものです。
HTTPエンドポイントまたはJMXを使用して、アプリケーションを管理したりモニタリングしたりできます。監査、ヘルスチェック、
メトリクスの収集などを含んでいます。

Spring Boot includes a number of additional features to help you monitor and manage your application when you push it to production. You can choose to manage and monitor your application by using HTTP endpoints or with JMX. Auditing, health, and metrics gathering can also be automatically applied to your application.

Production-ready Features

Spring Boot Actuatorには、複数のエンドポイントと呼ばれるものがあります。その一覧は、以下に記載してあります。

Production-ready Features / Endpoints

ヘルスチェックの場合は、healthエンドポイントが該当します。以降はヘルスチェック(healthエンドポイント)に絞ってドキュメントを
見ていきます。

Spring Boot Actuatorのヘルスチェックに関するドキュメントは、こちら。

Production-ready Features / Endpoints / Health Information

ヘルスチェックに使われる情報は、HealthContributorRegistryから収集されたものになると書かれています。

Health information is collected from the content of a HealthContributorRegistry (by default, all HealthContributor instances defined in your ApplicationContext).

デフォルトでは、ApplicationContextで定義されているすべてのHealthContributorインスタンスが含まれています。

HealthContributorはインターフェースであり、HealthIndicatorまたはCompositeHealthContributorのどちらかになります。
HealthIndicatorは、Statusを含むヘルス情報を提供するインターフェースです。CompositeHealthContributorは、複数のHealthContributorsの
組み合わせになります。

A HealthContributor can be either a HealthIndicator or a CompositeHealthContributor. A HealthIndicator provides actual health information, including a Status. A CompositeHealthContributor provides a composite of other HealthContributors.

デフォルトでは、ステータスの順に各HealthIndicatorのステータスを並び替えることにより、最終的なシステムのヘルス情報は
StatusAggregatorによって導出されます。

By default, the final system health is derived by a StatusAggregator, which sorts the statuses from each HealthIndicator based on an ordered list of statuses.

ソートされた結果、最初のステータスが全体のヘルスチェックの結果となります。

The first status in the sorted list is used as the overall health status.

Statusというのは、こちらですね。

Status (Spring Boot 2.6.7 API)

UP、DOWN、OUT_OF_SERVICE、UNKNOWNの4つのステータスがあります。

デフォルトのソート順は、DOWN → OUT_OF_SERVICE → UP → UNKNOWNのようです。

https://github.com/spring-projects/spring-boot/blob/v2.6.7/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/SimpleStatusAggregator.java#L44-L49

つまり、どれかひとつでもDOWNを返すHealthIndicatorがあれば、全体のヘルスチェックの結果としてはDOWNとなるわけですね。

ちなみに、StatusAggregatorが知っているステータスを返すHealthIndicatorがひとつもない場合、全体のステータスとしてはUNKNOWNに
なるようです。

If no HealthIndicator returns a status that is known to the StatusAggregator, an UNKNOWN status is used.

また、Spring BootはいくつかのHealthIndicatorを自動構成します。以下にリストアップされています。

Production-ready Features / Endpoints / Health Information / Auto-configured HealthIndicators

現時点で、以下が対象となるようです。()内はキー名です。

  • Apache Cassandra(cassandra)
  • Couchbase(couchbase)
  • DataSource(db)
  • ディスク(diskspace)
  • Elasticsearch(elasticsearch)
  • Hazelcast(hazelcast)
  • InfluxDB(influxdb)
  • JMSブローカー(jms)
  • LDAPサーバー(ldap)
  • メールサーバー(mail)
  • MongoDB(mongo)
  • Neo4j(neo4j)
  • 常にUPを返すHealthIndicator(ping)
  • RabbitMQ(rabbit)
  • Redis(redis)
  • Apache Solr(solr)

各HealthIndicatorは、management.health.[キー名].enabledプロパティをfalseに指定すると無効にすることができます。
デフォルトで自動構成されるHealthIndicatorをすべて無効にする場合は、management.health.defaults.enabledプロパティを
使えばよいみたいです。

ちなみに、デフォルトで有効になっていないLivenessStateHealthIndicator(livenessstate)、ReadinessStateHealthIndicator(readinessstate)
という2つのHealthIndicatorもあるようです。こちらは、Kubernetes向けみたいですね。

今回は扱いませんが、Spring Boot Actuatorで用意されているHealthIndicatorで足りない場合は、自分でHealthIndicatorを作成することに
なるんでしょうね。

Production-ready Features / Endpoints / Health Information / Writing Custom HealthIndicators

ヘルスチェック内で使用されるHealthIndicatorの情報は、詳細情報となるのでデフォルトでは表示されません。これを表示するように
するにはmanagement.endpoint.health.show-detailsプロパティまたはmanagement.endpoint.health.show-componentsプロパティを
使用します。

The information exposed by the health endpoint depends on the management.endpoint.health.show-details and management.endpoint.health.show-components properties, which can be configured with one of the following values:

Production-ready Features / Endpoints / Health Information

説明はこれくらいにして、今回はDataSource(JDBCですね)とRedisを含むように構成して、ヘルスチェックを行ってみましょう。

環境

今回の環境は、こちら。

$ java --version
openjdk 17.0.3 2022-04-19
OpenJDK Runtime Environment (build 17.0.3+7-Ubuntu-0ubuntu0.20.04.1)
OpenJDK 64-Bit Server VM (build 17.0.3+7-Ubuntu-0ubuntu0.20.04.1, mixed mode, sharing)


$ mvn --version
Apache Maven 3.8.5 (3599d3414f046de2324203b78ddcf9b5e4388aa0)
Maven home: $HOME/.sdkman/candidates/maven/current
Java version: 17.0.3, vendor: Private Build, runtime: /usr/lib/jvm/java-17-openjdk-amd64
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "5.4.0-110-generic", arch: "amd64", family: "unix"

データベースには、MySQLを使うことにします。バージョンは以下で、172.17.0.2で動作しているものとします。

$ mysql --version
mysql  Ver 8.0.29 for Linux on x86_64 (MySQL Community Server - GPL)

Redisのバージョンはこちら。Redisは172.17.0.3で動作しているものとします。

$ bin/redis-server --version
Redis server v=7.0.0 sha=00000000:0 malloc=jemalloc-5.2.1 bits=64 build=45b2bca311da7733

アプリケーションを作成する

まずは、Spring Bootプロジェクトを作成します。依存関係にweb、actuator、jdbc、mysql、data-redisを加えています。

$ curl -s https://start.spring.io/starter.tgz \
  -d bootVersion=2.6.7 \
  -d javaVersion=17 \
  -d name=actuator-healthcheck-with-datastore \
  -d groupId=org.littlewings \
  -d artifactId=actuator-healthcheck-with-datastore \
  -d version=0.0.1-SNAPSHOT \
  -d packageName=org.littlewings.spring.actuator \
  -d dependencies=web,actuator,jdbc,mysql,data-redis \
  -d baseDir=actuator-healthcheck-with-datastore | tar zxvf -

プロジェクト内に移動。

$ cd actuator-healthcheck-with-datastore

Mavenの依存関係やプラグイン設定など。

        <properties>
                <java.version>17</java.version>
        </properties>
        <dependencies>
                <dependency>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-actuator</artifactId>
                </dependency>
                <dependency>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-data-redis</artifactId>
                </dependency>
                <dependency>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-jdbc</artifactId>
                </dependency>
                <dependency>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-web</artifactId>
                </dependency>

                <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <scope>runtime</scope>
                </dependency>
                <dependency>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-test</artifactId>
                        <scope>test</scope>
                </dependency>
        </dependencies>

        <build>
                <plugins>
                        <plugin>
                                <groupId>org.springframework.boot</groupId>
                                <artifactId>spring-boot-maven-plugin</artifactId>
                        </plugin>
                </plugins>
        </build>

自動生成されたソースコードは、削除しておきます。

$ rm src/main/java/org/littlewings/spring/actuator/ActuatorHealthcheckWithDatastoreApplication.java src/test/java/org/littlewings/spring/actuator/ActuatorHealthcheckWithDatastoreApplicationTests.java

動作確認のために、用意したデータストアにアクセスするControllerを作成。

src/main/java/org/littlewings/spring/actuator/DataStoreController.java

package org.littlewings.spring.actuator;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("datastore")
public class DataStoreController {
    NamedParameterJdbcTemplate jdbcTemplate;
    StringRedisTemplate redisTemplate;

    public DataStoreController(NamedParameterJdbcTemplate jdbcTemplate, StringRedisTemplate redisTemplate) {
        this.jdbcTemplate = jdbcTemplate;
        this.redisTemplate = redisTemplate;
    }

    @GetMapping("jdbc")
    public String jdbc() {
        return jdbcTemplate
                .queryForObject("select now()", Collections.emptyMap(), LocalDateTime.class)
                .format(DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss"));
    }

    @GetMapping("redis")
    public String redis() {
        return redisTemplate
                .getRequiredConnectionFactory()
                .getConnection()
                .serverCommands()
                .info()
                .getProperty("redis_version");
    }
}

MySQLにselect now()を投げるメソッドと、Redisのバージョンを取得するメソッドを作成しています。

mainクラス。

src/main/java/org/littlewings/spring/actuator/App.java

package org.littlewings.spring.actuator;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {
    public static void main(String... args) {
        SpringApplication.run(App.class, args);
    }
}

設定は、まずは最低限にしておきます。

src/main/resources/application.properties

spring.datasource.url=jdbc:mysql://172.17.0.2:3306/practice?characterEncoding=utf-8
spring.datasource.username=kazuhira
spring.datasource.password=password

spring.redis.url=redis://redispass@172.17.0.3:6379
spring.redis.connect-timeout=3s
spring.redis.timeout=3s

Redisだけタイムアウトを入れているのは、ちょっと理由があります。

動作確認しておきましょう。

パッケージングして、アプリケーションを起動。

$ mvn package
$ java -jar target/actuator-healthcheck-with-datastore-0.0.1-SNAPSHOT.jar

確認。

# MySQL
$ curl localhost:8080/datastore/jdbc
2022-05-14 13:30:15


# Redis
$ curl localhost:8080/datastore/redis
7.0.0

OKですね。

Spring Boot Actuatorのヘルスチェックを確認してみる

では、Spring Boot Actuatorのヘルスチェックの確認に移りましょう。

デフォルトでは/actuator/healthがSpring Boot Actuatorのヘルスチェックのパスとして公開されるので、こちらにアクセスしてみます。

$ curl -i localhost:8080/actuator/health
HTTP/1.1 200
Content-Type: application/vnd.spring-boot.actuator.v3+json
Transfer-Encoding: chunked
Date: Sat, 14 May 2022 13:37:33 GMT

{"status":"UP"}


$ curl -s localhost:8080/actuator/health | jq
{
  "status": "UP"
}

HTTPステータスコードは200で、ステータスはUPと返ってきました。

ここで、Redisを停止してアクセスしてみます。

$ curl -i localhost:8080/actuator/health
HTTP/1.1 503
Content-Type: application/vnd.spring-boot.actuator.v3+json
Transfer-Encoding: chunked
Date: Sat, 14 May 2022 13:38:16 GMT
Connection: close

{"status":"DOWN"}


$ curl -s localhost:8080/actuator/health | jq
{
  "status": "DOWN"
}

HTTPステータスコードが503となり、ステータスはDOWNとなりました。

Redisにアクセスできなくなったので、ヘルスチェック全体としてはDOWNとなったようです。

アプリケーション側では、こんなログが出力されています。

2022-05-14 22:38:08.806  INFO 26433 --- [xecutorLoop-1-4] i.l.core.protocol.ConnectionWatchdog     : Reconnecting, last destination was /172.17.0.3:6379
2022-05-14 22:38:08.807  WARN 26433 --- [ioEventLoop-4-1] i.l.core.protocol.ConnectionWatchdog     : Cannot reconnect to [172.17.0.3/<unresolved>:6379]: 接続を拒否されました: /172.17.0.3:6379
2022-05-14 22:38:14.606  INFO 26433 --- [xecutorLoop-1-1] i.l.core.protocol.ConnectionWatchdog     : Reconnecting, last destination was 172.17.0.3/<unresolved>:6379
2022-05-14 22:38:14.607  WARN 26433 --- [ioEventLoop-4-3] i.l.core.protocol.ConnectionWatchdog     : Cannot reconnect to [172.17.0.3/<unresolved>:6379]: 接続を拒否されました: /172.17.0.3:6379

ところで、Spring Data Redisの設定でタイムアウトを設定していたのは、なにも指定しないとレスポンスが返ってくるまでにとても
時間がかかるからですね…。

ただ、これだとレスポンスからはなにが起こっているのかわかりません。src/main/resources/application.propertiesに以下を追加して
みましょう。

management.endpoint.health.show-details=always

パッケージングして、再度起動。

$ mvn package
$ java -jar target/actuator-healthcheck-with-datastore-0.0.1-SNAPSHOT.jar

Redisも起動しておきます。

確認すると、こんな結果になりました。

$ curl -i localhost:8080/actuator/health
HTTP/1.1 200
Content-Type: application/vnd.spring-boot.actuator.v3+json
Transfer-Encoding: chunked
Date: Sat, 14 May 2022 13:47:55 GMT

{"status":"UP","components":{"db":{"status":"UP","details":{"database":"MySQL","validationQuery":"isValid()"}},"diskSpace":{"status":"UP","details":{"total":100000000000,"free":10000000000,"threshold":10485760,"exists":true}},"ping":{"status":"UP"},"redis":{"status":"UP","details":{"version":"7.0.0"}}}}

ちょっとわかりづらいので、jqで見てみましょう。

$ curl -s localhost:8080/actuator/health | jq
{
  "status": "UP",
  "components": {
    "db": {
      "status": "UP",
      "details": {
        "database": "MySQL",
        "validationQuery": "isValid()"
      }
    },
    "diskSpace": {
      "status": "UP",
      "details": {
        "total": 100000000000,
        "free": 10000000000,
        "threshold": 10485760,
        "exists": true
      }
    },
    "ping": {
      "status": "UP"
    },
    "redis": {
      "status": "UP",
      "details": {
        "version": "7.0.0"
      }
    }
  }
}

db、diskSpace、ping、redisの4つで構成されていることがわかります。pingは、常にUPを返すHealthIndicatorでした。

ディスクの情報は今回はやめておきましょう。無効にします。

management.health.diskspace.enabled=false

再度パッケージングして起動。

$ mvn package
$ java -jar target/actuator-healthcheck-with-datastore-0.0.1-SNAPSHOT.jar

確認。ディスクの情報がなくなりました。

$ curl -s localhost:8080/actuator/health | jq
{
  "status": "UP",
  "components": {
    "db": {
      "status": "UP",
      "details": {
        "database": "MySQL",
        "validationQuery": "isValid()"
      }
    },
    "ping": {
      "status": "UP"
    },
    "redis": {
      "status": "UP",
      "details": {
        "version": "7.0.0"
      }
    }
  }
}

ここで、Redisを停止してアクセスしてみます。

$ curl -i localhost:8080/actuator/health
HTTP/1.1 503
Content-Type: application/vnd.spring-boot.actuator.v3+json
Transfer-Encoding: chunked
Date: Sat, 14 May 2022 13:52:30 GMT
Connection: close

{"status":"DOWN","components":{"db":{"status":"UP","details":{"database":"MySQL","validationQuery":"isValid()"}},"ping":{"status":"UP"},"redis":{"status":"DOWN","details":{"error":"org.springframework.dao.QueryTimeoutException: Redis command timed out; nested exception is io.lettuce.core.RedisCommandTimeoutException: Command timed out after 3 second(s)"}}}}



$ curl -s localhost:8080/actuator/health | jq
{
  "status": "DOWN",
  "components": {
    "db": {
      "status": "UP",
      "details": {
        "database": "MySQL",
        "validationQuery": "isValid()"
      }
    },
    "ping": {
      "status": "UP"
    },
    "redis": {
      "status": "DOWN",
      "details": {
        "error": "org.springframework.dao.QueryTimeoutException: Redis command timed out; nested exception is io.lettuce.core.RedisCommandTimeoutException: Command timed out after 3 second(s)"
      }
    }
  }
}

各構成要素のうち、RedisだけがDOWNになっていることがわかります。errorには失敗した時の例外メッセージが入っていますね。

Statusのソート順は、この結果からはわからなさそうです。

ここで、さらにRedisもヘルスチェックの対象から外してみましょう。

management.health.redis.enabled=false

パッケージングして起動。Redisは停止したままです。

$ mvn package
$ java -jar target/actuator-healthcheck-with-datastore-0.0.1-SNAPSHOT.jar

すると、ヘルスチェックが正常に終了するようになります。

$ curl -i localhost:8080/actuator/health
HTTP/1.1 200
Content-Type: application/vnd.spring-boot.actuator.v3+json
Transfer-Encoding: chunked
Date: Sat, 14 May 2022 13:55:13 GMT

{"status":"UP","components":{"db":{"status":"UP","details":{"database":"MySQL","validationQuery":"isValid()"}},"ping":{"status":"UP"}}}


$ curl -s localhost:8080/actuator/health | jq
{
  "status": "UP",
  "components": {
    "db": {
      "status": "UP",
      "details": {
        "database": "MySQL",
        "validationQuery": "isValid()"
      }
    },
    "ping": {
      "status": "UP"
    }
  }
}

当然ですが、Redisにアクセスする機能を使用すると失敗します。

$ curl localhost:8080/datastore/redis
{"timestamp":"2022-05-14T13:56:27.308+00:00","status":500,"error":"Internal Server Error","path":"/datastore/redis"}

Redisのヘルスチェックは、再度有効にしておきましょう。

#management.health.redis.enabled=false

ちなみに、MySQLだけを停止した場合はこうなりました。

$ curl -i localhost:8080/actuator/health
HTTP/1.1 503
Content-Type: application/vnd.spring-boot.actuator.v3+json
Transfer-Encoding: chunked
Date: Sat, 14 May 2022 15:38:57 GMT
Connection: close

{"status":"DOWN","components":{"db":{"status":"DOWN","details":{"error":"org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure\n\nThe last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server."}},"ping":{"status":"UP"},"redis":{"status":"UP","details":{"version":"7.0.0"}}}}


$ curl -s localhost:8080/actuator/health | jq
{
  "status": "DOWN",
  "components": {
    "db": {
      "status": "DOWN",
      "details": {
        "error": "org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure\n\nThe last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server."
      }
    },
    "ping": {
      "status": "UP"
    },
    "redis": {
      "status": "UP",
      "details": {
        "version": "7.0.0"
      }
    }
  }
}

DataSource、Redisで行うヘルスチェックの内容を確認してみる

ところで、DataSourceとRedisのHealthIndicatorはなにを確認しているんでしょうね?

ちょっと見てみましょう。

まずは、ヘルスチェックのレスポンスの内容をもう1度見てみます。

{
  "status": "UP",
  "components": {
    "db": {
      "status": "UP",
      "details": {
        "database": "MySQL",
        "validationQuery": "isValid()"
      }
    },
    "ping": {
      "status": "UP"
    },
    "redis": {
      "status": "UP",
      "details": {
        "version": "7.0.0"
      }
    }
  }
}

dbの場合はvalidationQuery、redisの場合はversionがちょっと不思議な感じがしますね。

dbに割り当てられているDataSourceHealthIndicatorの場合は、バリデーション用のクエリーが設定されていればそちらを使い、
そうでなければJDBCドライバーのConnection#isValidメソッドを使うようです。

Connection#isValid(int timeout))

https://github.com/spring-projects/spring-boot/blob/v2.6.7/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/jdbc/DataSourceHealthIndicator.java#L107-L118

https://github.com/spring-projects/spring-boot/blob/v2.6.7/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/jdbc/DataSourceHealthIndicator.java#L134

つまり、この状態のvalidQueryというのはConnection#isValidでヘルスチェックを行っていることを示しています。

    "db": {
      "status": "UP",
      "details": {
        "database": "MySQL",
        "validationQuery": "isValid()"
      }
    },

https://github.com/spring-projects/spring-boot/blob/v2.6.7/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/jdbc/DataSourceHealthIndicator.java#L115

redisに割り当てられているRedisHealthIndicatorの場合は、Redisがクラスター構成かどうかで変わるようです。今回はスタンドアロンですね。

https://github.com/spring-projects/spring-boot/blob/v2.6.7/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/redis/RedisHealthIndicator.java#L58-L64

スタンドアロンのRedisインスタンスの場合は、Redisのinfoコマンドのredis_versionプロパティを返すようになっています。

https://github.com/spring-projects/spring-boot/blob/v2.6.7/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/redis/RedisHealth.java#L37

それがこちらですね。

    "redis": {
      "status": "UP",
      "details": {
        "version": "7.0.0"
      }
    }

ちなみに、Controllerでも同じことをやっていました。

    @GetMapping("redis")
    public String redis() {
        return redisTemplate
                .getRequiredConnectionFactory()
                .getConnection()
                .serverCommands()
                .info()
                .getProperty("redis_version");
    }

redis-cliで確認すると、こんな感じになります。

$ bin/redis-cli -a redispass info server | grep redis_version
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
redis_version:7.0.0

最後に、DataSourceHealthIndicatorで使うvalidationQueryを設定してみましょう。

Spring BootはコネクションプールにHikariCPを使うようになっているため、spring.datasource.hikari.connection-test-queryを指定します。

spring.datasource.hikari.connection-test-query=select now()

ちなみに、HikariCPのconnectionTestQueryですが、JDBC version 4以降を使っている場合は使わないことを強く推奨されています。

If your driver supports JDBC4 we strongly recommend not setting this property.

HikariCP / Configuration

Connection#isValidをサポートしていないレガシーな環境向けのものです。

This is for "legacy" drivers that do not support the JDBC4 Connection.isValid() API.

つまり、ふだん使う時はspring.datasource.hikari.connection-test-queryを設定しないようにしておきましょう。

パッケージングして起動。

$ mvn package
$ java -jar target/actuator-healthcheck-with-datastore-0.0.1-SNAPSHOT.jar

確認。

$ curl -i localhost:8080/actuator/health
HTTP/1.1 200
Content-Type: application/vnd.spring-boot.actuator.v3+json
Transfer-Encoding: chunked
Date: Sat, 14 May 2022 15:47:13 GMT

{"status":"UP","components":{"db":{"status":"UP","details":{"database":"MySQL","validationQuery":"select now()","result":"2022-05-14T15:47:13"}},"ping":{"status":"UP"},"redis":{"status":"UP","details":{"version":"7.0.0"}}}}


$ curl -s localhost:8080/actuator/health | jq
{
  "status": "UP",
  "components": {
    "db": {
      "status": "UP",
      "details": {
        "database": "MySQL",
        "validationQuery": "select now()",
        "result": "2022-05-14T15:47:31"
      }
    },
    "ping": {
      "status": "UP"
    },
    "redis": {
      "status": "UP",
      "details": {
        "version": "7.0.0"
      }
    }
  }
}

validationQueryの内容が変わり、クエリーの結果まで入るようになりました。

    "db": {
      "status": "UP",
      "details": {
        "database": "MySQL",
        "validationQuery": "select now()",
        "result": "2022-05-14T15:47:31"
      }
    },

これで、確認OKとしましょう。

まとめ

Spring Boot Actuatorで、データストアまで含んだヘルスチェックを行ってみました。

なんとなくこういう機能があり、ちょっと興味があったのでこの機会に試しておいてよかったです。

最後に、application.propertiesのコメントアウトしている内容も含めて、全体を貼っておきます。
※ management.health.defaults.enabledは、デフォルトで有効なAuto ConfigurationされるHealthIndicatorをすべて無効にするプロパティです

src/main/resources/application.properties

spring.datasource.url=jdbc:mysql://172.17.0.2:3306/practice?characterEncoding=utf-8
spring.datasource.username=kazuhira
spring.datasource.password=password
#spring.datasource.hikari.connection-test-query=select now()

spring.redis.url=redis://redispass@172.17.0.3:6379
spring.redis.connect-timeout=3s
spring.redis.timeout=3s

management.endpoint.health.show-details=always

management.health.diskspace.enabled=false
#management.health.db.enabled=false
#management.health.ping.enabled=false
#management.health.redis.enabled=false

#management.health.defaults.enabled=false