Spring Boot アプリケーションを Managed Service for Prometheus に接続することで、アプリケーションの健全性とパフォーマンスを継続的にモニタリングできます。本トピックでは、この統合を迅速に設定する方法について説明します。
背景情報
従来の SSM ベースの MVC アプリケーションでは、多数の構成が必要であり、わずかな誤りが障害を引き起こす可能性がありました。Spring Boot は自動構成機能によりこの課題を解決します。必要な JAR パッケージが存在する場合、Spring Boot は自動的にアプリケーションを構成します。また、カスタム構成で自動構成クラスを置き換えることで、エンタープライズグレードのアプリケーションを迅速に構築できます。
Spring Boot アプリケーション向けの包括的なモニタリングシステムは、通常、以下の主要コンポーネントで構成されます。
モニタリングデータの収集
モニタリングデータを収集する一般的な方法には、プッシュモデルとプルモデルがあります。Prometheus モニタリングエコシステムは、プルベースのシステムの代表例です。Managed Service for Prometheus も典型的なプルベースのシステムです。アプリケーションおよびインフラストラクチャは、OpenMetrics 準拠のインターフェイスを通じてモニタリングデータを公開し、Managed Service for Prometheus が定期的にこのデータをスクレイプして長期保存します。
OpenMetrics はクラウドネイティブで高度にスケーラブルなメトリックプロトコルであり、大規模なクラウドネイティブメトリックのレポートに関する標準を定義しています。テキスト形式と Protocol Buffers の両方をサポートしますが、テキストベースの形式がより一般的であり、Managed Service for Prometheus がデータスクレイプに使用するデフォルトプロトコルでもあります。以下の例は、OpenMetrics に基づくメトリックの表現形式を示しています。
# TYPE acme_http_router_request_seconds summary
# UNIT acme_http_router_request_seconds seconds
# HELP acme_http_router_request_seconds Latency though all of ACME's HTTP request router.
acme_http_router_request_seconds_sum{path="/api/v1",method="GET"} 9036.32
acme_http_router_request_seconds_count{path="/api/v1",method="GET"} 807283.0
acme_http_router_request_seconds_created{path="/api/v1",method="GET"} 1605281325.0
acme_http_router_request_seconds_sum{path="/api/v2",method="POST"} 479.3
acme_http_router_request_seconds_count{path="/api/v2",method="POST"} 34.0
acme_http_router_request_seconds_created{path="/api/v2",method="POST"} 1605281325.0
# TYPE go_goroutines gauge
# HELP go_goroutines Number of goroutines that currently exist.
go_goroutines 69
# TYPE process_cpu_seconds counter
# UNIT process_cpu_seconds seconds
# HELP process_cpu_seconds Total user and system CPU time spent in seconds.
process_cpu_seconds_total 4.20072246e+06
# EOF
メトリックのデータモデルは、メトリック名と「ラベル」と呼ばれるキーと値のペアのセットによって定義されます。同じメトリック名とラベルを持つデータポイントは、同一の時系列に属します。たとえば、acme_http_router_request_seconds_sum{path="/api/v1",method="GET"} は、メトリック名が acme_http_router_request_seconds_sum で、ラベル method の値が GET であるデータサンプルを表します。各サンプルには Float64 値とミリ秒精度の UNIX タイムスタンプが含まれます。時間の経過とともに、これらの収集されたサンプルがグラフ上の動的なラインを形成します。
クラウドネイティブエコシステム内のほとんどのインフラストラクチャコンポーネントは、OpenMetrics テキスト形式でメトリックを公開できます。ネイティブでこれをサポートしないコンポーネントについては、Prometheus コミュニティが豊富な Prometheus Exporter を提供しています。これらのコンポーネント(または Exporter)は、Managed Service for Prometheus からの定期的なスクレイプリクエストに応答し、その運用状態を Managed Service for Prometheus に記録して後続の分析に備えます。また、Managed Service for Prometheus のマルチ言語 SDK を使用してコードにイベントトラッキングを追加し、独自のビジネスメトリックを Prometheus エコシステムに統合することもできます。
データの可視化と分析
アプリケーションおよびインフラストラクチャのメトリックを収集した後は、多次元データをクエリ・分析・比較してシステムの状態を把握できます。Grafana は、オープンソースのデータビジュアライゼーションツールとして業界をリードしており、幅広いチャートタイプとテンプレートを提供します。Managed Service for Prometheus は、モニタリングデータのクエリ、分析、可視化のためのフルマネージド Grafana サービスを提供します。
タイムリーなアラート機能とインシデント管理
サービスが障害の危険にさらされている場合、モニタリングシステムは管理者に速やかに通知し、問題を解決または事前に防止できるようにする必要があります。これにより、ビジネスへの影響を最小限に抑えることができます。管理者はさまざまなメトリックと既存データを分析することで、根本原因を特定・解決できます。
統合プロセスの概要
Spring Boot アプリケーション向けに、コミュニティは Spring Boot Actuator フレームワークを提供しており、Java 開発者がコードのイベントトラッキング、メトリック収集、出力を簡素化できます。Spring Boot 2.0 以降、Actuator は Micrometer 上で再構築され、より強力かつ柔軟なモニタリング機能を提供しています。Micrometer はメトリックのファサードであり、ロギングにおける SLF4J に類似しています。Micrometer を使用することで、アプリケーションは AppOptics、Datadog、Elastic、InfluxDB、および Managed Service for Prometheus など、さまざまなモニタリングシステムに接続できます。
Java アプリケーションからのメトリックをマッピングする際、Micrometer は以下のセマンティクスを使用して、自身のメトリクスタイプを Managed Service for Prometheus で使用されるタイプにマッピングします。
|
Micrometer メトリクスタイプ |
Managed Service for Prometheus メトリクスタイプ |
典型的なユースケース |
|
Counter |
Counter |
単調増加する値。たとえば、ページビュー (PV)、ユニークビジター (UV)、API 呼び出し回数のカウントなど。 |
|
Gauge |
Gauge |
時間とともに変動する変数。たとえば、リソース使用率、システム負荷、リクエストキュー長など。 |
|
Timer |
Histogram |
データの統計的分布。通常は遅延時間に関するもの。たとえば、API 呼び出しの P50、P90、P99 遅延時間の計算など。 |
|
DistributionSummary |
Summary |
データの統計的分布。Histogram と同様の目的で使用される。 |
-
Micrometer の Counter メトリクスタイプは、Managed Service for Prometheus の Counter タイプにマッピングされ、API 呼び出し回数、キャッシュヒット数、総訪問者数など、単調増加する変数を記述するために使用されます。Timer は論理的に Counter を含みます。API の応答時間を Timer で収集すると、呼び出し回数も同時に収集されるため、同一の API に対して Timer と Counter の両方を指定する必要はありません。
-
Micrometer の Gauge メトリクスタイプは、Managed Service for Prometheus の Gauge タイプにマッピングされ、CPU 使用率やスレッドプールキュー内のタスク数など、範囲内で継続的に変動する変数を記述するために使用されます。
-
Micrometer の Timer メトリクスタイプは、Managed Service for Prometheus の Histogram タイプにマッピングされ、API のレスポンスタイム (RT) 分布など、時間関連データを記述するために使用されます。
-
Micrometer の DistributionSummary メトリクスタイプは、Managed Service for Prometheus の Summary タイプにマッピングされます。Histogram と同様に統計的分布に使用されますが、分布はクライアント側で計算された後に Managed Service for Prometheus に送信されて保存されるため、複数のマシン間で集計できません。この制限により、データ分布のグローバルなビューを提供できないため、利用が制限されます。
統合ワークフロー
Kubernetes クラスターにデプロイされた Spring Boot アプリケーションを Managed Service for Prometheus に接続する場合は、「コードのイベントトラッキング」→「アプリケーションデプロイメント」→「サービス検出」の順に処理を進める必要があります。
まず、コードに必要な Spring Boot Actuator Maven 依存関係を追加し、モニタリング対象のメトリックを登録するか、コントローラーのメソッドにアノテーションを追加します。
次に、イベントトラッキング済みのアプリケーションを Kubernetes にデプロイし、メトリック収集エンドポイントを Managed Service for Prometheus に登録します。このプロセスは サービス検出 と呼ばれます。Managed Service for Prometheus は、ServiceMonitor カスタムリソース定義 (CRD) を使用してサービス検出を実現します。
最後に、Managed Service for Prometheus がターゲットアプリケーションのメトリックエンドポイントを正常に検出した後、Grafana でデータソースを構成し、ダッシュボードを作成できます。また、重要なメトリックに基づいてアラートを設定することも可能です。
モニタリング目標
Kubernetes クラスター内の Spring Boot アプリケーションを Managed Service for Prometheus に接続することで、以下のことが可能になります。
-
システムのエントリーポイントのモニタリング:顧客トラフィックを処理するフロントエンドサービス上で、外部向け API の主要 RED メトリック(Rate、Errors、Duration)を追跡します。
-
重要なシステムパスのモニタリング:バックエンドサービスのクリティカルパス上のキーオブジェクト(スレッドプールのキュー状態や、インプロセス Guava Cache のヒット率など)を観測します。
-
ビジネスに関連するカスタムメトリックのモニタリング:特定の API のユニークビジター数など、ビジネス固有のメトリックをモニタリングします。
-
JVM パフォーマンスのモニタリング:JVM のガベージコレクション (GC) およびメモリ使用量を追跡します。
-
モニタリングの集中化:上記すべてのメトリックを集約し、統一ダッシュボードに表示するとともに、重要な指標に対してアラートを設定します。
手順 1:Spring Boot Actuator の構成
本トピックでは、Spring Boot および Spring Cloud Alibaba を使用して構築されたクラウドネイティブマイクロサービスアプリケーションを例に、Kubernetes クラスター内の Spring Boot マイクロサービスアプリケーションを Managed Service for Prometheus に接続する方法を説明します。
-
pom.xmlファイルに Spring Boot Actuator の依存関係を追加します。<!-- spring-boot-actuator dependency --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- prometheus dependency --> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> </dependency> -
application.propertiesファイルに、モニタリングデータを公開するポートの構成を追加します。本例ではポート 8091 を使用します。# Add the following configuration to application.properties to expose metrics spring.application.name=frontend management.server.port=8091 management.endpoints.web.exposure.include=* management.metrics.tags.application=${spring.application.name}構成が完了すると、アプリケーションのポート 8091 にアクセスできるようになります。このポートの
/actuator/prometheusパスで、OpenMetrics 形式のモニタリングデータが利用可能になります。
手順 2:コードのイベントトラッキング
API の RED メトリックを収集するには、対応するメソッドに @Timed アノテーションを追加します。以下の例では、インデックスページ API に @Timed を追加しています。
@Timed(value = "main_page_request_duration", description = "Time taken to return main page", histogram = true)
@ApiOperation(value = "Home page", tags = {"Home page operations"})
@GetMapping("/")
public String index(Model model) {
model.addAttribute("products", productDAO.getProductList());
model.addAttribute("FRONTEND_APP_NAME", Application.APP_NAME);
model.addAttribute("FRONTEND_SERVICE_TAG", Application.SERVICE_TAG);
model.addAttribute("FRONTEND_IP", registration.getHost());
model.addAttribute("PRODUCT_APP_NAME", PRODUCT_APP_NAME);
model.addAttribute("PRODUCT_SERVICE_TAG", PRODUCT_SERVICE_TAG);
model.addAttribute("PRODUCT_IP", PRODUCT_IP);
model.addAttribute("new_version", StringUtils.isBlank(env));
return "index.html";
}
ここで、value は /actuator/prometheus に公開されるメトリックの名前であり、histogram=true は API リクエストの持続時間についてヒストグラムメトリックを公開し、P90 や P99 などのリクエスト時間分布を計算できるようにします。
アプリケーションで Guava Cache などのインプロセスキャッシュライブラリを使用しており、そのランタイム状態を追跡したい場合は、Micrometer のデコレーターメソッドを使用してキーオブジェクトをラップできます。
Guava キャッシュの変更
-
MeterRegistryを注入します。Spring Boot は自動的にPrometheusMeterRegistry実装を注入します。 -
ユーティリティ API(以下のコードでは
GuavaCacheMetrics.monitor)を使用してローカルキャッシュをラップします。 -
.recordStats()メソッドを呼び出して、キャッシュ統計の記録を有効にします。 -
キャッシュオブジェクトに名前を付けて、対応するメトリックを生成します。
@Resource
private static MeterRegistry meterRegistry;
private static final LoadingCache<String, String> REFRESH_CACHE = GuavaCacheMetrics.monitor(
meterRegistry,
CacheBuilder.newBuilder()
.recordStats()
.build(new CacheLoader<String, String>() {
@Override
public String load(String key) {
// Implement the specific load operation here.
return "";
}
}),
"refresh-cache");
スレッドプールの変更
-
MeterRegistryを注入します。ここに注入される具体的な実装はPrometheusMeterRegistryです。 -
ユーティリティ API を使用してスレッドプールをラップします。
-
スレッドプールに名前を付けて、対応するメトリックを生成します。
@Resource
private static MeterRegistry meterRegistry;
private static final ScheduledExecutorService REFRESH_EXECUTOR = ExecutorServiceMetrics.monitor(
meterRegistry,
Executors.newScheduledThreadPool(1,
new ThreadFactory() {
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("dubbo.outlier.refresh-" + thread.getId());
return thread;
}
}),
"refresh-executor"
);
ビジネス固有のカスタムメトリックをモニタリングするには、Bean に MeterRegistry を注入し、要件に応じて Counter、Gauge、または Timer を構築します。その後、それを MeterRegistry に登録してメトリックを公開します。以下の例を参照してください。
@Service
public class DemoService {
Counter visitCounter;
public DemoService(MeterRegistry registry) {
visitCounter = Counter.builder("visit_counter")
.description("Number of visits to the site")
.register(registry);
}
public String visit() {
visitCounter.increment();
return "Hello World!";
}
}
これで必要なコード変更は完了です。次に、アプリケーションイメージを再ビルドし、Managed Service for Prometheus がインストールされている Kubernetes クラスターにデプロイします。その後、Managed Service for Prometheus コンソールで ServiceMonitor を構成してサービス検出を有効にしてください。詳細については、「Container Observability」および「インスタンス管理」をご参照ください。
ServiceMonitor の構成後、Targets リストに新しく登録されたアプリケーションが表示されます。
Targets ページで、default/frontend-service-monitor/0 (1/1 up) が表示され、State が UP となっている場合、メトリックエンドポイント(パス:/actuator/prometheus)が正常に動作しており、ServiceMonitor 構成がアクティブであることを示します。
手順 3:ダッシュボードの構成
Managed Service for Prometheus は、アプリケーションのモニタリングデータを収集・保存しています。ダッシュボードとアラートを構成してデータを表示できます。以下のオープンソース Grafana コミュニティのダッシュボードテンプレートを使用して、独自のモニタリングダッシュボードを構築できます。
これらのテンプレートと Managed Service for Prometheus のビルトイン Grafana サービスを使用することで、開発と運用保守に必要な主要メトリックを単一ページに統合したダッシュボードを作成できます。たとえば、これらのテンプレートから構築されたダッシュボードには、概要、コンポーネントランタイム、メモリ使用量、ヒープおよび非ヒープメモリ、世代別 GC 状態などが含まれます。
