QuarkusでHealth Checkのエンドポイントを作成する
はじめに
KubernetesにはLiveness ProbeをReadiness Probeといった概念があり、アプリケーションにそれぞれを確認するためのエンドポイントを作成する場合があります。
Spring Boot(2.3以上)などではそのエンドポイントが用意されていますが、Quarkusにもそれぞれのエンドポイントを作るやりたか(正確にはMicroprofileの実装であるsmallryeのQuarkus拡張)があったので試してみようかと思います。
基本的に以下のドキュメントにしたがってやる形で試してみようと思います。
やってみる
環境
実行環境は以下の通り
$ java --version openjdk 11.0.8 2020-07-14 OpenJDK Runtime Environment 18.9 (build 11.0.8+10) OpenJDK 64-Bit Server VM 18.9 (build 11.0.8+10, mixed mode) $ mvn --version Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f) Maven home: /snap/intellij-idea-ultimate/253/plugins/maven/lib/maven3 Java version: 11.0.8, vendor: N/A, runtime: /home/yuya-hirooka/.sdkman/candidates/java/11.0.8-open Default locale: ja_JP, platform encoding: UTF-8 OS name: "linux", version: "5.4.0-48-generic", arch: "amd64", family: "unix"
プロジェクトはQuarkus - Start coding with code.quarkus.ioで作成します。 設定は以下の通り
デフォルトのエンドポイントを確認する
実は特になにもせずともデフォルトでRedinessとLivenessのエンドポイントは用意されています。
/health/live
: アプリケーション本体が立ち上がっているかどうか/health/ready
: DBの接続チェックなどを含めたアプリケーションがアクセスを受け入れる準備できているかどうか/health
: RedinessとLiveness両方の情報を返す
アプリケーションを起動し以下のエンドポイントにアクセスしてみます。
$ curl -i http://localhost:8080/health HTTP/1.1 200 OK content-type: application/json; charset=UTF-8 content-length: 46 { "status": "UP", "checks": [ ] } $ curl -i http://localhost:8080/health/ready HTTP/1.1 200 OK content-type: application/json; charset=UTF-8 content-length: 46 { "status": "UP", "checks": [ ] } $ curl -i http://localhost:8080/health/live HTTP/1.1 200 OK content-type: application/json; charset=UTF-8 content-length: 46 { "status": "UP", "checks": [ ] }
ここで、UP
がアプリケーションがアクティブな状態を示し、DOWN
がアプリケーションがインアクティブであることを示します。
見ての通りこの状態だとアプリケーションはなにもチェックせず、自分自身が起動していることのみ確認することができます。
任意のチェックを行い結果を返す必要がある場合は、少し手をくわえてやる必要があります。
Health Cheackを作成する
例えば、Readinessのチェックではデータベースとの接続がうまく行っているか否かの確認を行いたい場合があります。そのような場合にはReadinessのHealth Checkを実装してやる必要があります。
まずは単にHealth Checkを実装します。
import org.eclipse.microprofile.health.HealthCheck; import org.eclipse.microprofile.health.HealthCheckResponse; import org.eclipse.microprofile.health.Readiness; import javax.enterprise.context.ApplicationScoped; @Readiness @ApplicationScoped public class ReadinessCheck implements HealthCheck { @Override public HealthCheckResponse call() { return HealthCheckResponse.up("test"); } }
Healthチェックを行なう際はorg.eclipse.microprofile.health.HealthCheck
を実装したCDIのBeanとして作成します。この際、クラスに@Rediness
をつけると/health/ready
に対するHealth Cheackを実装でき、@Liveness
をつけると/health/live
に対する実装を行えます。このブログでは@Rediness
での実装しか行いませんが、基本的には全く同じことが@Liveness
でも行えるはずです。
UPの状態の結果を返す場合はHealthCheckResponse.up("任意の文字列")
を利用します。
この状態で、cURLを叩くと以下のようなレスポンスを返します。
$ curl -i http://localhost:8080/health/ready HTTP/1.1 200 OK content-type: application/json; charset=UTF-8 content-length: 121 { "status": "UP", "checks": [ { "name": "test", "status": "UP" } ] }
実装をデータベースへの接続を確認するように修正します。
ここでは仮想的にDBの接続が失敗するような場合における実装をしてみます。
@Readiness @ApplicationScoped public class ReadinessCheck implements HealthCheck { @Override public HealthCheckResponse call() { try { checkDB(); return HealthCheckResponse.up("test"); } catch (Exception e) { e.printStackTrace(); return HealthCheckResponse.down("db connection"); } } private void checkDB(){ throw new RuntimeException("db connection falied"); } }
ここでは、checkDB()
というDBの接続を確認することを想定したメソッドを作成し、失敗を模擬的に表した、RuntimeException
を投げています。
もう一度、cURLを叩くと以下のようなレスポンスが返ってきます。
$ curl -i http://localhost:8080/health/ready HTTP/1.1 503 Service Unavailable content-type: application/json; charset=UTF-8 content-length: 134 { "status": "DOWN", "checks": [ { "name": "db connection", "status": "DOWN" } ] }
任意の情報を付加する
Health Checkに任意の情報を更かしたい場合はHealthCheckResponseBuilderを使います。
@Readiness @ApplicationScoped public class ReadinessCheck implements HealthCheck { @Override public HealthCheckResponse call() { try { checkDB(); return HealthCheckResponse.named("db connection") .up() .build(); } catch (Exception e) { e.printStackTrace(); return HealthCheckResponse .named("db connection") .withData("foo", "bar") .down().build(); } } private void checkDB(){ throw new RuntimeException("db connection falied"); } }
ここで、HealthCheckResponse.named("db connection")
はHealthCheckResponseBuilder
を返し、そのwithData("key", "value")
メソッドを使って任意のデータを返します。
cURLを叩くと以下のようなレスポンスが返ってきます。
$ curl -i http://localhost:8080/health/ready HTTP/1.1 503 Service Unavailable content-type: application/json; charset=UTF-8 content-length: 200 { "status": "DOWN", "checks": [ { "name": "db connection", "status": "DOWN", "data": { "foo": "bar" } } ] }
複数の条件を確認するようなチェックを行なう
例えば、DB接続の他に依存APIも立ち上がっていることが必要な場合、複数の状態を確認してHealth Checkの結果としてUP
を返す必要があります。
この場合、単にHealth Checkクラスを増やしてやるだけでOKです。
新たなHealth CheckクラスであるReadinessAPICheck.java
を作成します。
@Readiness @ApplicationScoped public class ReadinessAPICheck implements HealthCheck { @Override public HealthCheckResponse call() { try { chekAPI(); return HealthCheckResponse.up("dependent api"); } catch (Exception e) { e.printStackTrace(); return HealthCheckResponse.down("dependent api"); } } private void chekAPI(){ } }
cURLを叩くと以下のような結果が返ってきます。
$ curl -i http://localhost:8080/health/ready HTTP/1.1 503 Service Unavailable content-type: application/json; charset=UTF-8 content-length: 209 { "status": "DOWN", "checks": [ { "name": "api", "status": "UP" }, { "name": "db connection", "status": "DOWN" } ] }
最終的なチェック結果は各チェックのAND条件で決まります。
この場合、DB接続のほうがDOWN
となっているので最終的な結果もDOWN
となります。
Health UI
QuarkusのHealth Checkでは簡易的なUIもデフォルトで用意してくれています。http://${APP_URL}//health-ui/
にアクセスすることで、そのUIをみることができます。
ヘッダーの歯車ボタンを押すと設定を行なうことができます。
Pollの項目ではチェック結果更新のためのポーリングの時間を決められた間隔で設定することができます。
Configuration Property
application.propterties
には以下のような設定ポイントが用意されています。
プロパティ名 | 説明 | デフォルト値 |
---|---|---|
quarkus.health.extensions.enabled | Health Checkを有効にするか否かのフラグ | true (Boolean) |
quarkus.smallrye-health.root-path | Health Checkのルートパス | /health (String) |
quarkus.smallrye-health.liveness-path | Helth CheckのLivenessのパス | /live (String) |
quarkus.smallrye-health.readiness-path | Helth CheckのReadinessのパス | /ready (String) |
quarkus.smallrye-health.ui.root-path | Health UIへアクセするためのパス | /health-ui |
quarkus.smallrye-health.ui.always-include | Health UIをビルド常にビルドに含めるかどうかの設定。デフォルトではtestモードとdevモードのときだけHealth UIをビルドに含める | false (Boolean) |
quarkus.smallrye-health.ui.enable | Health UIを有効にするか否かのフラグ | ture (Boolean) |