5 ヘルス・チェックAPIの使用

Coherence 14.1.1.2206では、アプリケーション・コードからローカルCoherenceメンバーのヘルスを判別できるようにするヘルス・チェックAPIと、外部アプリケーションでクラスタとそのメンバーのヘルスを問い合せできるようにするための対応するHTTPエンドポイントおよび管理エンドポイントが導入されています。
ヘルスAPIでは、アプリケーションで独自のヘルス・チェックを登録することもできます。登録されたヘルス・チェックはメンバーおよびクラスタのヘルス・ステータスに含められます。

ノート:

ヘルス・チェックを有効にするには、ブートストラップAPIを使用してCoherenceクラスタ・メンバーを起動する必要があります。「ブートストラップAPIの使用」を参照してください。

この章の内容は次のとおりです。

ヘルス・チェックAPIについて

アプリケーション・コードからヘルス・チェックAPIを使用して、Coherenceが正常かどうかを判断できます。また、HTTPエンドポイントから使用して、KubernetesやDockerなどのコンテナ化された環境でのヘルス・チェックに役立てることもできます。

Coherenceのすべてのヘルス・チェックは、単純なインタフェースを実装します。
public interface HealthCheck
    {
    /**
     * Returns the unique name of this health check.
     *
     * @return the unique name of this health check
     */
    String getName();

    /**
     * Return {@code true} if this {@link HealthCheck} should
     * be included when working out this Coherence member's
     * health status.
     *
     * @return {@code true} if this {@link HealthCheck} should
     *         be included in the member's health status
     */
    default boolean isMemberHealthCheck()
        {
        return true;
        }

    /**
     * Returns {@link true} if the resource represented by
     * this {@link HealthCheck} is ready, otherwise returns
     * {@code false}.
     * <p>
     * The concept of what "ready" means may vary for different
     * types of resources.
     *
     * @return {@link true} if the resource represented by this
     *         {@link HealthCheck} is ready, otherwise {@code false}
     */
    boolean isReady();

    /**
     * Returns {@link true} if the resource represented by
     * this {@link HealthCheck} is alive, otherwise returns
     * {@code false}.
     * <p>
     * The concept of what "alive" means may vary for different
     * types of resources.
     *
     * @return {@link true} if the resource represented by this
     *         {@link HealthCheck} is alive, otherwise returns
     *         {@code false}
     */
    boolean isLive();

    /**
     * Returns {@link true} if the resource represented by
     * this {@link HealthCheck} is started, otherwise returns
     * {@code false}.
     * <p>
     * The concept of what "started" means may vary for different
     * types of resources.
     *
     * @return {@link true} if the resource represented by this
     *         {@link HealthCheck} is started, otherwise returns
     *         {@code false}
     */
    boolean isStarted();

    /**
     * Returns {@link true} if the resource represented by this
     * {@link HealthCheck} is in a safe state to allow a rolling
     * upgrade to proceed, otherwise returns {@code false}.
     * <p>
     * The concept of what "safe" means may vary for different
     * types of resources.
     *
     * @return {@link true} if the resource represented by this
     *         {@link HealthCheck} is in a safe state to allow
     *         a rolling upgrade to proceed, otherwise returns
     *         {@code false}
     */
    boolean isSafe();
    }

メソッドは、Coherenceが実行される他のシステム(たとえば、Kubernetesなど、同様の開始済ヘルス・チェック、稼働中ヘルス・チェックおよび準備状況ヘルス・チェックを使用するシステム)と統合するために選択されたものです。安全チェックはCoherenceに固有であり、次のクラスタ・メンバーのローリング前にクラスタが安全であると判断することが重要である、ローリング・アップグレードなどのユースケースを制御するために使用されます。

ヘルス・チェックAPIはCoherence管理APIの一部であり、 com.tangosol.net.management.Registryクラスからアクセスできます。Registryは通常、現在のCoherence Clusterインスタンスから取得されます。たとえば、com.tangosol.net.Coherence.main()を実行するか、ブートストラップAPIを使用してCoherenceを起動した場合は、次に示すように管理Registryを取得できます:
Cluster  cluster  = Coherence.getInstance().getCluster();
Registry registry = cluster.getManagement();

ヘルス・チェックAPIでは、クラスタ全体のAPIではないため、ローカルCoherenceメンバーの登録済ヘルス・チェックのみを表示できます。クラスタ全体のヘルス・チェックには、Coherence管理API、JMX、またはREST経由の管理を介して、対応するヘルスMBeanを使用します。

この項には次のトピックが含まれます:

すべてのヘルス・チェックの取得

すべての登録済ヘルス・チェックのコレクションを取得するには、RegistryインスタンスでgetHealthChecks()メソッドをコールできます。このメソッドは、登録済HealthCheckインスタンスの不変コレクションを返します。

たとえば、次のコードは、準備ができていないHealthCheckインスタンスの名前のSetを取得します:
Coherence coherence = Coherence.getInstance();
Registry registry = coherence.getManagement();
Collection<HealthCheck> healthChecks = registry.getHealthChecks();
Set<String> names = healthChecks.stream()
        .filter(hc -> !hc.isReady())
        .map(HealthCheck::getName)
        .collect(Collectors.toSet());

名前によるヘルス・チェックの取得

特定のヘルス・チェックを名前で取得するには、RegistryインスタンスでgetHealthCheck(String name)メソッドをコールします。このメソッドは、リクエストされたHealthCheckを含むOptionalを返します(リクエストされた名前に登録されているものがある場合)。リクエスト名にHealthCheckが登録されていない場合は空のOptionalを返します。

たとえば、次のコードは「Foo」という名前のHealthCheckを取得します:
Coherence coherence = Coherence.getInstance();
Registry registry = coherence.getManagement();
Optional<HealthCheck> healthChecks = registry.getHealthCheck("Foo");

すべてのヘルス・チェックが準備完了していることの確認

RegistryインスタンスでallHealthChecksReady()メソッドを使用すると、ローカルに登録されているすべてのヘルス・チェックが準備完了しているかどうかを判断できます。準備完了チェックには、isMemberHealthCheck()メソッドからtrueを返すヘルス・チェックのみが含まれます。
Coherence coherence = Coherence.getInstance();
Registry registry = coherence.getManagement();
boolean ready = registry.allHealthChecksReady();

すべてのヘルス・チェックが開始されていることの確認

RegistryインスタンスでallHealthChecksStarted()メソッドを使用すると、ローカルに登録されているすべてのヘルス・チェックが開始されているかどうかを判断できます。開始済チェックには、isMemberHealthCheck()メソッドからtrueを返すヘルス・チェックのみが含まれます。

Coherence coherence = Coherence.getInstance();
Registry registry = coherence.getManagement();
boolean started = registry.allHealthChecksStarted();

すべてのヘルス・チェックが稼働していることの確認

RegistryインスタンスでallHealthChecksLive()メソッドを使用すると、ローカルに登録されたすべてのヘルス・チェックが稼働中かどうかを判断できます。稼働チェックには、isMemberHealthCheck()メソッドからtrueを返すヘルス・チェックのみが含まれます。
Coherence coherence = Coherence.getInstance();
Registry registry = coherence.getManagement();
boolean live = registry.allHealthChecksLive();

すべてのヘルス・チェックが安全であることの確認

RegistryインスタンスでallHealthChecksSafe()メソッドを使用すると、ローカルに登録されたすべてのヘルス・チェックが安全かどうかを判断できます。安全チェックには、isMemberHealthCheck()メソッドからtrueを返すヘルス・チェックのみが含まれます。
Coherence coherence = Coherence.getInstance();
Registry registry = coherence.getManagement();
boolean safe = registry.allHealthChecksSafe();

組込みヘルス・チェックの使用

Coherenceには、すぐに使用できるヘルス・チェックが数多くあります。
  • 各Coherenceサービスには、対応するヘルス・チェックがあります。
  • com.tangosol.net.Coherenceのインスタンスは、対応するヘルス・チェックを提供します。
  • Coherence gRPC統合を使用している場合、gRPCプロキシ・サーバーにはヘルス・チェックがあります。

この項には次のトピックが含まれます:

サービス・ヘルス・チェックの使用

Coherenceサービスのヘルス・チェックには、次の機能があります:
  • 開始済: サービス・ヘルス・チェックのisStarted()メソッドは、対応するサービスが実行されている場合はtrueを返します。
  • 稼働中: サービス・ヘルス・チェックのisLive()メソッドは、対応するサービスが実行されている場合はtrueを返します。
  • 準備完了: サービスの場合、isReady()メソッドは、サービスが安全になるまではfalseを返し、その後は準備完了状態がtrueのままになります。これは具体的には、Kubernetesなど、ReadyでなければポッドがServiceから削除されるようなユース・ケースに対応しています。ただし、この動作は通常はCoherenceに必要ありません。
  • 安全: パーティション化されたキャッシュ・サービスを除くすべてのサービスの場合、isSafe()メソッドは常にtrueを返します。

PartitionedCacheサービスのisSafeチェックの使用

Coherence PartitionedCacheサービスは、Coherenceのほとんどのサービスよりも複雑であるため、そのヘルス・チェックで行われる処理も多くなります。PartitionedCacheサービスのisSafe()チェックでは、サービスが安定していて安全であることを確認するための多数のチェックが実行されます。安全チェックの主なユースケースは、ローリング・アップグレードを実行する場合、またはクラスタを安全にスケール・ダウンする場合です。

  • 記憶域が有効になっていないメンバーに対するPartitionedCacheサービスのisSafe()ヘルス・チェックは、サービスが実行されているかぎりはtrueを返します。
  • PartitionedCacheサービスのisSafe()ヘルス・チェックは、サービスでこのメンバーが記憶域が有効になった唯一のメンバーであるが、すべてのパーティションを所有しているわけではない場合に、falseを返します。これは、クラスタの他のすべてのメンバーが停止された直後、パーティションのリカバリおよび再割当てロジックがまだ進行中である場合に発生する可能性があります。したがって、このメンバーは、すべてのパーティションを所有していることをまだ認識していません。
  • バックアップ数が0より大きい値に構成されており、サービスのStatusHA状態がendangeredになっている場合、PartitionedCacheサービスのisSafe()ヘルス・チェックはfalseを返します。キャッシュ構成ファイルで個々のサービスに対するこの動作を変更して、それぞれが危険にさらされることを許可できます。バックアップ数が0のサービスは、安全チェックで危険にさらされることが許可されています。
  • パーティション再分散が進行中の場合、PartitionedCacheサービスのisSafe()ヘルス・チェックはfalseを返します。
  • 永続記憶域からのリカバリが進行中の場合、PartitionedCacheサービスのisSafe()ヘルス・チェックはfalseを返します。

メンバー・ヘルスからのサービスの除外

Coherenceサービスをメンバーの全体的なヘルス・チェックから除外することが望ましい場合もあります。これを行うには、キャッシュ構成ファイルでサービスの<health>要素に<member-health-check>要素を設定します。

たとえば、次のproxy-schemeでは<member-health-check>要素の値がfalseに設定されています。Proxyサービスのヘルス・チェックにはヘルスAPIを介してまだアクセスできますが、RegistryクラスのallHealthChecksReady()メソッドなど、メンバー・ヘルス全体のチェックからはProxyサービスが除外されます。

<proxy-scheme>
  <service-name>Proxy</service-name>
  <autostart>true</autostart>
  <health>
    <member-health-check>false</member-health-check>
  </health>
</proxy-scheme>

危険にさらされたサービスの許可

意図的に危険にさらすことができる分散キャッシュ・サービスをアプリケーションで構成する場合もあります。ただし、この状態がメンバーの全体的なヘルスに反映されないようにします。これを行うには、キャッシュ構成ファイルで分散スキームの<health>要素に<allow-endangered>要素を設定します。

たとえば、次のdistributed-schemeでは<allow-endangered>要素の値がtrueに設定されています。PartitionedCacheのヘルス・チェックでは、サービスのStatusHA値が'ENDANGERED'であっても、サービスが準備完了または安全であることが報告されます。

<distributed-scheme>
  <scheme-name>distributed-scheme</scheme-name>
  <service-name>PartitionedCacheOne</service-name>
  <backing-map-scheme>
    <local-scheme/>
  </backing-map-scheme>
  <autostart>true</autostart>
  <health>
    <allow-endangered>true</allow-endangered>
  </health>
</distributed-scheme>

HTTPヘルス・チェックの有効化

ヘルス・チェックHTTPエンドポイントは、ブートストラップAPIを使用してCoherenceを実行するか、com.tangosol.net.Coherenceをメイン・クラスとして使用してCoherenceを起動すると有効になります。それ以外の方法でCoherenceを起動した場合、ヘルス・チェックAPIは使用できますが、HTTPエンドポイントは実行されません。デフォルトでは、HTTPサーバーはエフェメラル・ポートにバインドされますが、これはcoherence.health.HTTP.portシステム・プロパティまたはCOHERENCE_HEALTH_HTTP_PORT環境変数を設定することで変更できます。
たとえば、次のコマンドを実行すると、Coherenceはhttp://localhost:6676のヘルス・エンドポイントを使用して起動されます:
java -cp coherence.jar -Dcoherence.health.http.port=6676 \
    com.tangosol.net.Coherence
または、Javaモジュールを使用して起動されます:
java -p coherence.jar \
    -Dcoherence.health.http.port=6676 \
    --module com.oracle.coherence
その後は、curlユーティリティを使用して、エンドポイントの1つ(/readyなど)をポーリングできます:
curl -i -X GET http://localhost:6676/ready
前述のコマンドは、次のような出力を返します:
HTTP/1.1 200 OK
Date: Tue, 19 Apr 2022 17:59:05 GMT
Content-type: application/json
Vary: Accept-Encoding
Content-length: 0
X-content-type-options: nosniff

Coherenceヘルス・チェックが失敗した場合、レスポンス・コードは503 (サービス使用不可を表す)になります。

ヘルスHTTPエンドポイント

ヘルス・チェックHTTPサーバーには、多数のエンドポイントがあります。

ノート:

いずれのエンドポイントも、ペイロードを受け入れたり、レスポンス本文を返すことはありません。レスポンスは、ステータス・コード200または503のみです。つまり、SSL/TLSを使用するようにヘルス・エンドポイントを構成できますが、暗号化の必要性はほとんどなく、Kubernetesやその他のコンテナ環境などの外部ツールで使用するほうが簡単です。

表5-1 ヘルス・チェックHTTPサーバー・エンドポイント

エンドポイント 説明

/started

リクエストの送信先のメンバーのすべてのヘルス・チェックが開始されている場合、このエンドポイントはレスポンスとしてステータス・コード200を返します。開始されていないヘルス・チェックが1つ以上ある場合、エンドポイントは503のレスポンスを返します。

/live

リクエストの送信先のメンバーのすべてのヘルス・チェックが稼働している場合、このエンドポイントはレスポンスとしてステータス・コード200を返します。稼働していないヘルス・チェックが1つ以上ある場合、エンドポイントは503のレスポンスを返します。

/ready

リクエストの送信先のメンバーのすべてのヘルス・チェックが準備完了している場合、このエンドポイントはレスポンスとしてステータス・コード200を返します。準備完了していないヘルス・チェックが1つ以上ある場合、エンドポイントは503のレスポンスを返します。

/safe

リクエストの送信先のメンバーのすべてのヘルス・チェックが安全である場合、このエンドポイントはステータス・コード200のレスポンスを返します。安全でないヘルス・チェックが1つ以上ある場合、エンドポイントは503のレスポンスを返します。

アプリケーション・ヘルス・チェックの使用

ヘルス・チェックAPIを使用すると、アプリケーション開発者はカスタム・ヘルス・チェックを追加できます。これは、Coherenceメンバーの全体的なヘルスを判別するために使用する必要があるサービスをアプリケーションが提供する場合に役立ちます。たとえば、アプリケーションにWebサーバーが含まれる場合、そのWebサーバーが起動するまでアプリケーションは準備完了とはみなされません。

カスタム・ヘルス・チェックを登録するには、com.tangosol.util.HealthCheckの実装を記述するだけです。

カスタム・ヘルス・チェックのgetName()メソッドは、このヘルス・チェックを表す一意の名前を返す必要があります。ヘルス・チェックはMBeanとして公開されるため、JMX MBeanオブジェクト名で有効な名前である必要があります。

次に、ヘルス・チェック実装で、関連するアプリケーション・ロジックを使用して、各メソッドに対して返す結果を決定する必要があります。一部のメソッドは該当しない可能性もあるため、その場合はtrueのみを返す必要があります。

様々なヘルス・チェック・メソッドの結果がアプリケーション・コードの外側でどのように使用されるかを理解することが重要です。たとえば、アプリケーションが、アプリケーションの状態をモニターする外部システムによってデプロイおよび管理されている場合です。たとえば、Kubernetesにデプロイされたアプリケーションが稼働中でないことが何度も報告される場合に、アプリケーションを中断します。準備完了であることが報告されないアプリケーションを、リクエストのルーティングなどから除外します。安全でないアプリケーションは、Coherenceクラスタのローリング・アップグレードまたは安全なスケーリングをブロックします。

メンバー・ヘルスからのカスタム・ヘルス・チェックの除外

アプリケーション開発者が、アプリケーション・サービスのカスタム・ヘルス・チェックを追加するが、これらのチェックを全体的なCoherenceメンバー・ヘルスに反映させないようにする必要があることもあります。HealthCheckインタフェースには、この目的のための isMemberHealthCheck()メソッドがあります。isMemberHealthCheck()のデフォルト実装では常にtrueが返されるため、デフォルトではすべてのヘルス・チェックがメンバーのヘルスに含められます。メンバーのヘルスからヘルス・チェックを除外するには、falseを返すようにisMemberHealthCheck()メソッドをオーバーライドします。

コンテナ化されたヘルス・チェックの使用

Coherenceアプリケーションをコンテナ内で(DockerやKubernetesなどで)実行する場合は、ヘルス・チェックと準備状況チェックを使用できると便利です。ヘルスHTTPエンドポイントを有効にしてCoherenceを実行すると、コンテナのヘルスの構成が簡単になります。

コンテナ内でヘルス・チェック・エンドポイントを使用している場合は、イメージのヘルス・チェックを構成できるようにHTTPポートを修正する必要があります。デフォルトの動作ではエフェメラル・ポートにバインドされるため、システムはヘルス・チェックAPIがバインドされているポートを認識しません。HTTPポートを設定するには、coherence.health.HTTP.portシステム・プロパティまたはCOHERENCE_HEALTH_HTTP_PORT環境変数を使用します。イメージを作成するときは、通常、環境変数を使用するほうが簡単です。これについては、この項で例を挙げて説明します。

この項には次のトピックが含まれます:

Dockerヘルス・チェックの使用

DockerfileのHEALTHCHECK構成を使用して、ヘルス・チェックで構成されたCoherence Dockerイメージを構築できます。

次のDockerfileの例では、ENV COHERENCE_HEALTH_HTTP_PORT=6676設定を使用してヘルス・チェック・ポートを6676に設定しています。次に、DockerfileHEALTHCHECKで構成しています。このコマンドはHTTP://127.0.0.1:6676/readyのHTTPエンドポイントに対してcurlを実行します。レスポンスが200でない場合、このコマンドは失敗します。
FROM openjdk:11-jre

ADD coherence.jar /coherence/lib/coherence.jar

ENTRYPOINT [ "java" ]
CMD [ "-cp", "/coherence/lib/*", "com.tangosol.net.Coherence" ]

ENV COHERENCE_HEALTH_HTTP_PORT=6676

HEALTHCHECK CMD curl --fail http://127.0.0.1:6676/ready || exit 1

前述のチェックでは、ベース・イメージにcurlがインストールされていることを前提としています。常にそうであるとはかぎりません。たとえば、非常にスリムなLinuxベース・イメージや歪みのないイメージには、curlなどの追加ツールがないものもあります。この場合、すべてのイメージにあるものはJavaです。したがって、Coherence jarに組み込まれているJavaヘルス・チェック・クライアント・クラスcom.tangosol.util.HealthCheckClientを使用するようにヘルス・チェックを構成できます。このクラスは、チェックするHTTPエンドポイントのURLである単一パラメータを使用して実行できます。

次のDockerfileの例では、LinuxカーネルおよびJava 11のみがインストールされている歪みのないベース・イメージを使用しています。ヘルス・チェック・ポートは、ENV COHERENCE_HEALTH_HTTP_PORT=6676設定を使用して6676に設定されています。次に、DockerfileHEALTHCHECKで構成しています。このコマンドはjava -cp /coherence/lib/coherence.jar com.tangosol.util.HealthCheckClient http://127.0.0.1:6676/readyを実行します。レスポンスが200でない場合、このコマンドは失敗します。
FROM gcr.io/distroless/java11

ADD coherence.jar /coherence/lib/coherence.jar

ENTRYPOINT [ "java" ]
CMD [ "-cp", "/coherence/lib/*", "com.tangosol.net.Coherence" ]

ENV COHERENCE_HEALTH_HTTP_PORT=6676

HEALTHCHECK CMD java -cp /coherence/lib/coherence.jar com.tangosol.util.HealthCheckClient http://127.0.0.1:6676/ready

Kubernetesの準備状況プローブおよび有効性プローブの使用

Kubernetesには、様々な構成可能な準備状況プローブおよび有効性プローブがあります。Kubernetesの準備状況と有効性はイメージとは無関係なので、イメージそのものはヘルス・チェックを必要としません(「Dockerヘルス・チェックの使用」を参照)。Kubernetesの準備状況および有効性の構成の詳細は、Kubernetesのドキュメントを参照してください。

次の例は、Coherenceのイメージおよびヘルス・チェックを使用した単純なPodです。COHERENCE_HEALTH_HTTP_PORT環境変数は、ヘルス・チェックHTTPポートを6676に修正するために使用されます。次に、readinessProbeを、リクエスト・パス/readyを使用してポート6676でHTTP GETリクエストを使用するように構成しています。リクエストのホストはデフォルトでポッドIPアドレスになるため、事実上http://<pod-ip>:6676/readyと同じです。
apiVersion: v1
kind: Pod
metadata:
  name: coherence
spec:
  containers:
  - name: coherence
    image: ghcr.io/oracle/coherence-ce:22.06
    env:
      - name: COHERENCE_HEALTH_HTTP_PORT
        value: "6676"
      - name: COHERENCE_WKA
        value: coherence_wka.svc.cluster.local
    readinessProbe:
      httpGet:
        path: "/ready"
        port: 6676
      initialDelaySeconds: 30
      periodSeconds: 30