1. 概要

Spring Bootは、実行中のアプリケーションとそのコンポーネントのステータスと正常性を検査するためのいくつかの異なる方法を提供します。 これらのアプローチの中で、HealthContributorHealthIndicatorAPIは注目に値する2つです。

このチュートリアルでは、これらのAPIに精通し、それらがどのように機能するかを学び、カスタム情報をそれらに提供する方法を確認します。

2. 依存関係

健康情報の寄稿者はSpringBootアクチュエーターモジュールの一部であるため、適切なMaven依存関係が必要です。

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

3. ビルトインHealthIndicator s

箱から出して、 SpringBootは特定のアプリケーションアスペクトの健全性を報告するために多くのHealthIndicatorsを登録します。

DiskSpaceHealthIndicatorPingHealthIndicatorなど、これらのインジケーターの一部はほとんどの場合登録されています。 前者はディスクの現在の状態を報告し、後者はアプリケーションのpingエンドポイントとして機能します。

一方、SpringBootはいくつかのインジケーターを条件付きで登録します。 つまり、いくつかの依存関係がクラスパスにあるか、他の条件が満たされている場合、SpringBootは他のいくつかのHealthIndicatorも登録する可能性があります。 たとえば、リレーショナルデータベースを使用している場合、Spring BootはDataSourceHealthIndicatorを登録します。 同様に、データストアとしてCassandraを使用した場合は、CassandraHealthIndicatorが登録されます。

Spring Bootアプリケーションのヘルスステータスを検査するために、/ actuator/healthエンドポイントを呼び出すことができます。 このエンドポイントは、登録されているすべてのHealthIndicatorの集計結果を報告します。

また、1つの特定のインジケーターからのヘルスレポートを表示するには、/ actuator / health/{name}エンドポイントを呼び出すことができます。 たとえば、 / actuator / health / diskSpace エンドポイントを呼び出すと、DiskSpaceHealthIndicatorからステータスレポートが返されます。

{
  "status": "UP",
  "details": {
    "total": 499963170816,
    "free": 134414831616,
    "threshold": 10485760,
    "exists": true
  }
}

4. カスタムHealthIndicator s

組み込みのものに加えて、カスタム HealthIndicator を登録して、コンポーネントまたはサブシステムの状態を報告できます。 そのためには、HealthIndicatorインターフェースの実装をSpringBeanとして登録するだけです。

たとえば、次の実装はランダムに障害を報告します。

@Component
public class RandomHealthIndicator implements HealthIndicator {

    @Override
    public Health health() {
        double chance = ThreadLocalRandom.current().nextDouble();
        Health.Builder status = Health.up();
        if (chance > 0.9) {
            status = Health.down();
        }
        return status.build();
    }
}

この指標からのヘルスレポートによると、アプリケーションは90% ofの時間しか稼働していないはずです。 ここでは、 Health ビルダーを使用して、ヘルス情報を報告しています。

ただし、リアクティブアプリケーションでは、タイプReactiveHealthIndicatorのBeanを登録する必要があります。 反応性健康() メソッドは単核症単純な代わりに健康 。 それ以外の詳細は、両方のWebアプリケーションタイプで同じです。

4.1. インジケーター名

この特定のインジケーターのレポートを表示するには、/アクチュエータ/ヘルス/ランダムエンドポイントを呼び出すことができます。 たとえば、API応答は次のようになります。

{"status": "UP"}

/ actuator / health / randomURLのrandomは、このインジケーターの識別子です。 特定のHealthIndicatorの識別子実装は、HealthIndicatorを除いたBean名と同じです。 サフィックス。  Beanの名前は randomHealthIdenticator ランダムプレフィックスが識別子になります。

このアルゴリズムでは、Bean名をrandなどに変更すると次のようになります。

@Component("rand")
public class RandomHealthIndicator implements HealthIndicator {
    // omitted
}

その場合、インジケーター識別子はランダムではなくランドになります。

4.2. インジケーターを無効にする

特定のインジケーターを無効にするには、「management.health」を設定します。 .enabled」構成プロパティをfalseに設定 。 たとえば、application.propertiesに次を追加すると次のようになります。

management.health.random.enabled=false

次に、SpringBootはRandomHealthIndicatorを無効にします。 この構成プロパティをアクティブにするには、インジケーターに@ConditionalOnEnabledHealthIndicatorアノテーションを追加する必要があります。

@Component
@ConditionalOnEnabledHealthIndicator("random")
public class RandomHealthIndicator implements HealthIndicator { 
    // omitted
}

ここで、 /アクチュエータ/ヘルス/ランダムを呼び出すと、SpringBootは404NotFoundHTTP応答を返します。

@SpringBootTest
@AutoConfigureMockMvc
@TestPropertySource(properties = "management.health.random.enabled=false")
class DisabledRandomHealthIndicatorIntegrationTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    void givenADisabledIndicator_whenSendingRequest_thenReturns404() throws Exception {
        mockMvc.perform(get("/actuator/health/random"))
          .andExpect(status().isNotFound());
    }
}

組み込みインジケーターまたはカスタムインジケーターを無効にすることは、互いに類似していることに注意してください。 したがって、組み込みのインジケーターにも同じ構成を適用できます。

4.3. 追加の詳細

ステータスの報告に加えて、 withDetail(key、value)を使用して追加のキー値の詳細を添付できます。

public Health health() {
    double chance = ThreadLocalRandom.current().nextDouble();
    Health.Builder status = Health.up();
    if (chance > 0.9) {
        status = Health.down();
    }

    return status
      .withDetail("chance", chance)
      .withDetail("strategy", "thread-local")
      .build();
}

ここでは、ステータスレポートに2つの情報を追加しています。 また、通過することで同じことを達成することができます地図 withDetails(マップ) 方法:

Map<String, Object> details = new HashMap<>();
details.put("chance", chance);
details.put("strategy", "thread-local");
        
return status.withDetails(details).build();

ここで、 /アクチュエータ/ヘルス/ランダムと呼ぶと、次のように表示される場合があります。

{
  "status": "DOWN",
  "details": {
    "chance": 0.9883560157173152,
    "strategy": "thread-local"
  }
}

自動テストでこの動作を確認することもできます。

mockMvc.perform(get("/actuator/health/random"))
  .andExpect(jsonPath("$.status").exists())
  .andExpect(jsonPath("$.details.strategy").value("thread-local"))
  .andExpect(jsonPath("$.details.chance").exists());

データベースやディスクなどのシステムコンポーネントとの通信中に例外が発生することがあります。 withException(ex)メソッドを使用して、このような例外を報告できます。

if (chance > 0.9) {
    status.withException(new RuntimeException("Bad luck"));
}

前に見たdown(ex)メソッドに例外を渡すこともできます。

if (chance > 0.9) {
    status = Health.down(new RuntimeException("Bad Luck"));
}

これで、ヘルスレポートにスタックトレースが含まれます。

{
  "status": "DOWN",
  "details": {
    "error": "java.lang.RuntimeException: Bad Luck",
    "chance": 0.9603739107139401,
    "strategy": "thread-local"
  }
}

4.4. 詳細露出

management.endpoint.health.show-details configurationプロパティは、各ヘルスエンドポイントが公開できる詳細のレベルを制御します。 

たとえば、このプロパティを常にに設定すると、の場合、上記の例のように、SpringBootは常にヘルスレポートのdetailsフィールドを返します。

一方、このプロパティをneverに設定すると、SpringBootは常に出力から詳細を省略します。 when_authorized 値もあり、許可されたユーザーに対してのみ追加のdetailsを公開します。 ユーザーは、次の場合にのみ許可されます。

  • 彼女は認証されています
  • そして、彼女はmanagement.endpoint.health.roles構成プロパティで指定された役割を持っています

4.5. 健康状態

デフォルトでは、SpringBootは4つの異なる値をヘルスステータスとして定義します。

  • UP —コンポーネントまたはサブシステムは期待どおりに機能しています
  • DOWN —コンポーネントが機能していません
  • OUT_OF_SERVICE —コンポーネントは一時的にサービスを停止しています
  • UNKNOWN —コンポーネントの状態が不明です

これらの状態は、Java列挙ではなく、 public staticfinalインスタンスとして宣言されます。 したがって、独自のカスタムヘルス状態を定義することができます。 これを行うには、 status(name)メソッドを使用できます。

Health.Builder warning = Health.status("WARNING");

ヘルスステータスは、ヘルスエンドポイントのHTTPステータスコードに影響します。 デフォルトでは、SpringBootはDOWN 、および OUT_OF_SERVICE 状態をマップして、503ステータスコードをスローします。 一方、 UP およびその他のマップされていないステータスは、200OKステータスコードに変換されます。

このマッピングをカスタマイズするには、 management.endpoint.health.status.http-mappingを設定できます。 構成プロパティを目的のHTTPステータスコード番号に変更します。

management.endpoint.health.status.http-mapping.down=500
management.endpoint.health.status.http-mapping.out_of_service=503
management.endpoint.health.status.http-mapping.warning=500

これで、SpringBootはDOWN ステータスを500に、 OUT_OF_SERVICE を503に、WARNINGを500HTTPステータスコードにマップします。

mockMvc.perform(get("/actuator/health/warning"))
  .andExpect(jsonPath("$.status").value("WARNING"))
  .andExpect(status().isInternalServerError());

同様に、タイプHttpCodeStatusMapperのBeanを登録して、HTTPステータスコードマッピングをカスタマイズできます。

@Component
public class CustomStatusCodeMapper implements HttpCodeStatusMapper {

    @Override
    public int getStatusCode(Status status) {
        if (status == Status.DOWN) {
            return 500;
        }
        
        if (status == Status.OUT_OF_SERVICE) {
            return 503;
        }
        
        if (status == Status.UNKNOWN) {
            return 500;
        }

        return 200;
    }
}

getStatusCode(status)メソッドは、ヘルスステータスを入力として受け取り、HTTPステータスコードを出力として返します。 また、カスタムステータスインスタンスをマップすることもできます。

if (status.getCode().equals("WARNING")) {
    return 500;
}

デフォルトでは、SpringBootはこのインターフェースの単純な実装をデフォルトのマッピングで登録します。 SimpleHttpCodeStatusMapperは、前に見たように、構成ファイルからマッピングを読み取ることもできます。

5. 健康情報と指標

重要なアプリケーションには通常、いくつかの異なるコンポーネントが含まれています。 たとえば、Cassandraをデータベースとして使用し、Apache Kafkaをpub-subプラットフォームとして使用し、Hazelcastをメモリ内データグリッドとして使用するSpringBootアプリケーションについて考えてみます。

HealthIndicatorsを使用して、アプリケーションがこれらのコンポーネントと通信できるかどうかを確認する必要があります。 通信リンクに障害が発生したり、コンポーネント自体がダウンしたり遅い場合は、注意が必要な異常なコンポーネントがあります。 つまり、これらのインジケーターは、さまざまなコンポーネントまたはサブシステムの正常性を報告するために使用する必要があります。

それどころか、値の測定、イベントのカウント、または期間の測定にHealthIndicatorを使用することは避けてください。 そのため、メトリックがあります。 簡単に言うと、メトリックは、CPU使用率、負荷平均、ヒープサイズ、HTTP応答分布などを報告するための優れたツールです。

6. 結論

このチュートリアルでは、アクチュエータのヘルスエンドポイントにより多くのヘルス情報を提供する方法を説明しました。 さらに、 Health Status 、HTTPステータスマッピングのステータスなど、ヘルスAPIのさまざまなコンポーネントについて詳しく説明しました。

最後に、健康情報と指標の違いについて簡単に話し合い、それぞれをいつ使用するかを学びました。

いつものように、すべての例はGitHubから入手できます。