404 Not Found

404 Not Found


nginx

Spring Boot Actuator

ActuatorはSpring Bootのダッシュボードです。ヘルスステータス, メトリクス, 設定情報を提供し, 運用チームに「俯瞰的な視点」を与えてくれます。

1. 学ぶ内容


2. 運用エンジニアのリアルストーリー

(1) ペインポイント:本番環境がブラックボックス

BobはOrderFlow本番環境の運用保守を担当していますが, アプリケーションは彼にとって完全なブラックボックスです。データベース接続は正常か?メモリはどれくらい使用されているか?どのAPIの応答が遅いのか?問題が発生するたびに, Aliceにログ追加やアプリケーション再起動を依頼してトラブルシューティングを行う必要があり, 平均MTTR (平均復旧時間)は1時間を超えています。CharlieはMTTRを10分以内に短縮するよう要求しています。

(2) Actuatorによる解決策

Actuatorはすぐに使え, 幅広い運用エンドポイントを提供しています:

YAML
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus
BASH
curl http://localhost:8080/actuator/health
# {"status":"UP","components":{"db":{"status":"UP"},"diskSpace":{"status":"UP"}}}

(3) 成果

BobがActuatorを使い始めた後, /healthでデータベース接続を監視し, /metricsでAPI応答時間を追跡し, カスタムHealthIndicatorで外部決済ゲートウェイをチェックするようになり, MTTRは1時間から5分に短縮されました。


3. Actuatorエンドポイント概要

(1) 組み込みエンドポイント一覧

エンドポイント 説明 デフォルト公開
/actuator/health アプリのヘルスステータス ✅ はい
/actuator/info アプリ情報 ✅ はい
/actuator/metrics 指標一覧 ❌ いいえ
/actuator/metrics/{name} 特定のメトリクス値 ❌ いいえ
/actuator/env 環境設定 ❌ いいえ
/actuator/beans Bean一覧 ❌ いいえ
/actuator/loggers ログレベル ❌ いいえ
/actuator/threaddump スレッドダンプ ❌ いいえ
/actuator/heapdump ヒープダンプ ❌ いいえ
/actuator/prometheus Prometheus形式のメトリクス ❌ いいえ

(1) ▶ サンプル:Actuator依存関係の有効化

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

出力:

TEXT
// 実行成功

(2) ▶ サンプル:エンドポイント公開の設定

YAML
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,env,loggers
      base-path: /actuator
  endpoint:
    health:
      show-details: when-authorized
    metrics:
      enabled: true
  info:
    env:
      enabled: true

出力:

TEXT
設定が反映されました。
公開ポリシー 設定値 説明
ヘルスと情報のみ include: health,info 最も安全, デフォルト
必要に応じて公開 include: health,info,metrics 推奨
すべて表示 include: "*" 開発環境のみ
特定を除外 exclude: env,beans 全体から除外

4. ヘルスエンドポイントの詳細解説

(1) ヘルスステータス集約ルール

100%
graph TD
    A["Health Status<br/>Aggregator"] --> B["DiskSpace<br/>UP"]
    A --> C["DataSource<br/>UP"]
    A --> D["PaymentGateway<br/>DOWN"]
    A --> E["Redis<br/>UP"]
    D --> F["Overall: DOWN<br/>Any DOWN → DOWN"]
ステータス 意味 集約ルール
UP 正常
DOWN 異常 1つでもDOWN → 全体DOWN
DEGRADED 低下 非重要コンポーネントの低下
OUT_OF_SERVICE サービス利用不可 1つでも → 全体OUT_OF_SERVICE
UNKNOWN 不明 デフォルト

(1) ▶ サンプル:カスタムHealthIndicator

JAVA
@Component
public class PaymentGatewayHealthIndicator implements HealthIndicator {

    private final RestTemplate restTemplate;

    public PaymentGatewayHealthIndicator(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @Override
    public Health health() {
        try {
            ResponseEntity<String> response = restTemplate.getForEntity(
                "https://api.payment-gateway.com/ping", String.class);
            if (response.getStatusCode().is2xxSuccessful()) {
                return Health.up()
                    .withDetail("gateway", "reachable")
                    .withDetail("responseTime", response.getHeaders().getDate())
                    .build();
            }
            return Health.down()
                .withDetail("gateway", "unhealthy")
                .withDetail("statusCode", response.getStatusCode())
                .build();
        } catch (Exception e) {
            return Health.down()
                .withDetail("gateway", "unreachable")
                .withDetail("error", e.getMessage())
                .build();
        }
    }
}

出力:

TEXT
// 実行成功
💻 出力:

JSON
{
  "status": "DOWN",
  "components": {
    "diskSpace": {"status": "UP", "details": {"total": 536870912000, "free": 268435456000}},
    "db": {"status": "UP", "details": {"database": "MySQL", "validationQuery": "SELECT 1"}},
    "paymentGateway": {"status": "DOWN", "details": {"gateway": "unreachable", "error": "Connection refused"}}
  }
}

5. メトリクスエンドポイントの詳細解説

(1) ▶ サンプル:HTTPリクエストメトリクスの確認

BASH
# 利用可能なすべてのメトリクスを一覧表示
curl http://localhost:8080/actuator/metrics

# 特定のメトリクスを取得:HTTPサーバーリクエスト
curl http://localhost:8080/actuator/metrics/http.server.requests

# フィルタリングしたメトリクスを取得
curl "http://localhost:8080/actuator/metrics/http.server.requests?tag=uri:/api/v1/orders&tag=status:200"

出力:

TEXT
{"status":"ok","data":{}}
一般的なメトリクス 説明
http.server.requests HTTPリクエスト所要時間の分布
jvm.memory.used JVMメモリ使用量
jvm.threads.live アクティブスレッド数
process.cpu.usage プロセスCPU使用率
disk.total / disk.free ディスク容量
hikaricp.connections.active データベース接続プール

(2) ▶ サンプル:カスタムビジネスメトリクス

JAVA
@Service
public class OrderMetrics {

    private final Counter orderCreatedCounter;
    private final Timer orderCreationTimer;
    private final AtomicLong pendingOrders;

    public OrderMetrics(MeterRegistry registry) {
        this.orderCreatedCounter = Counter.builder("orderflow.orders.created")
            .description("Total orders created")
            .tag("service", "orderflow")
            .register(registry);

        this.orderCreationTimer = Timer.builder("orderflow.orders.creation.time")
            .description("Order creation time")
            .register(registry);

        this.pendingOrders = registry.gauge("orderflow.orders.pending",
            new AtomicLong(0));
    }

    public void recordOrderCreated() {
        orderCreatedCounter.increment();
        pendingOrders.incrementAndGet();
    }

    public void recordOrderCompleted() {
        pendingOrders.decrementAndGet();
    }

    public Timer getCreationTimer() {
        return orderCreationTimer;
    }
}

出力:

TEXT
// 実行成功

6. カスタムエンドポイント

(1) ▶ サンプル:カスタムOrderStatsエンドポイント

JAVA
@Endpoint(id = "orderstats")
@Component
public class OrderStatsEndpoint {

    private final OrderRepository orderRepository;

    public OrderStatsEndpoint(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
    }

    @ReadOperation
    public Map<String, Object> orderStats() {
        long total = orderRepository.count();
        long pending = orderRepository.countByStatus("PENDING");
        long completed = orderRepository.countByStatus("COMPLETED");
        long cancelled = orderRepository.countByStatus("CANCELLED");
        return Map.of(
            "totalOrders", total,
            "pendingOrders", pending,
            "completedOrders", completed,
            "cancelledOrders", cancelled,
            "completionRate", total > 0
                ? String.format("%.2f%%", (double) completed / total * 100)
                : "N/A"
        );
    }

    @ReadOperation
    public Map<String, Object> orderStatsByStatus(
            @Selector String status) {
        long count = orderRepository.countByStatus(status.toUpperCase());
        return Map.of("status", status, "count", count);
    }
}

出力:

TEXT
// 実行成功
YAML
management:
  endpoint:
    orderstats:
      enabled: true
  endpoints:
    web:
      exposure:
        include: health,info,orderstats
💻 出力:

BASH
curl http://localhost:8080/actuator/orderstats
# {"totalOrders":1523,"pendingOrders":45,"completedOrders":1420,"cancelledOrders":58,"completionRate":"93.30%"}

curl http://localhost:8080/actuator/orderstats/PENDING
# {"status":"PENDING","count":45}

7. セキュリティ強化

(1) エンドポイントセキュリティポリシー

レベル ポリシー 説明
ネットワーク層 専用管理ポート management.server.port=8081
ネットワーク層 内部IPにバインド management.server.address=127.0.0.1
アプリケーション層 Spring Security制御 .requestMatchers("/actuator/**").hasRole("ADMIN")
エンドポイント層 機密エンドポイントの無効化 management.endpoint.env.enabled=false

(1) ▶ サンプル:本番レベルのセキュリティ設定

YAML
# application-prod.yml
management:
  server:
    port: 8081                    # 管理ポートの分離
    address: 127.0.0.1            # localhostのみにバインド
  endpoints:
    web:
      exposure:
        include: health,prometheus,orderstats
      base-path: /actuator
  endpoint:
    health:
      show-details: when-authorized
    env:
      enabled: false
    beans:
      enabled: false
    heapdump:
      enabled: false

出力:

TEXT
監視設定が読み込まれました
Prometheusターゲット:3件アクティブ
Grafanaダッシュボード:準備完了
環境 公開ポリシー 管理ポート
開発 include: "*" ポート8080
テスト include: health,info,metrics,env 同じポート8080
本番 include: health,prometheus 専用ポート8081 + 内部ネットワーク

8. 総合例:OrderFlow Actuatorの完全設定

YAML
# application.yml
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus,orderstats
  endpoint:
    health:
      show-details: when-authorized
    orderstats:
      enabled: true
  metrics:
    tags:
      application: ${spring.application.name}
  info:
    env:
      enabled: true

info:
  app:
    name: OrderFlow Service
    version: @project.version@
    description: Eコマース注文管理マイクロサービス
JAVA
// PaymentGatewayHealthIndicator.java
@Component
public class PaymentGatewayHealthIndicator implements HealthIndicator {
    private final RestTemplate restTemplate;
    public PaymentGatewayHealthIndicator(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }
    @Override
    public Health health() {
        try {
            ResponseEntity<String> resp = restTemplate
                .getForEntity("https://api.payment.com/ping", String.class);
            return resp.getStatusCode().is2xxSuccessful()
                ? Health.up().withDetail("gateway", "reachable").build()
                : Health.down().withDetail("statusCode", resp.getStatusCode()).build();
        } catch (Exception e) {
            return Health.down().withDetail("error", e.getMessage()).build();
        }
    }
}

// OrderStatsEndpoint.java
@Endpoint(id = "orderstats")
@Component
public class OrderStatsEndpoint {
    private final OrderRepository orderRepository;
    public OrderStatsEndpoint(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
    }
    @ReadOperation
    public Map<String, Object> stats() {
        return Map.of(
            "total", orderRepository.count(),
            "pending", orderRepository.countByStatus("PENDING"),
            "completed", orderRepository.countByStatus("COMPLETED")
        );
    }
}

❓ よくある質問

Q Actuatorエンドポイントはパフォーマンスに影響しますか?
A 読み取り操作 (health, metrics)のオーバーヘッドは最小です。Heapdumpとthreaddump操作はアプリケーションを一時停止させるため, 本番環境ではデフォルトで無効になっています。Prometheusエンドポイントの推奨ポーリング間隔は15〜30秒です。
Q ヘルスチェックエンドポイントは誰が使うべきですか?
A /healthはロードバランサーとK8sプローブ向けであり, 機密情報は公開しません。詳細付きの/healthは運用チーム向けで, ADMIN権限が必要です。本番環境ではshow-details: when-authorizedを使用してください。
Q ヘルスステータスの集約ルールをカスタマイズするにはどうすればよいですか?
A HealthAggregatorを実装するか, StatusAggregator Beanを使用します。デフォルトルールは:Any DOWN → Overall DOWNです。statusOrderで優先度をカスタマイズできます。
Q /actuator/envはパスワードを公開しますか?
A 設定値を表示しますが, Spring Boot 3.xではデフォルトでpassword, secret, key, tokenを含むキー値をマスクし (••••••と表示), 元の値は表示しません。それでも本番環境ではこのエンドポイントを無効にすることをお勧めします。
Q 管理ポートとアプリケーションポートを分離するメリットは何ですか?
A 1)管理ポートは内部ネットワークのみにバインドされ, 外部インターネットに公開されない;2)アプリケーショントラフィックと管理トラフィックが分離され, 互いに干渉しない;3)管理ポートに異なるセキュリティポリシーを設定できる。
Q ActuatorメトリクスをPrometheusと統合するにはどうすればよいですか?
A micrometer-registry-prometheus依存関係を追加し, prometheusエンドポイントを公開し, Prometheus設定に収集ターゲットを追加します。詳しくは後のレッスン (L23)で解説します。

📖 まとめ


📝 練習問題

  1. 基本問題 (難易度 ⭐):OrderFlowにActuatorを追加し, health, info, metricsエンドポイントを公開するように設定し, /actuator/healthが「UP」ステータスを返すことを確認してください。

  2. 応用問題 (難易度 ⭐⭐):カスタムPaymentGatewayHealthIndicatorOrderStatsEndpointを実装し, 本番環境用に専用管理ポートを設定してください。

  3. チャレンジ (難易度 ⭐⭐⭐):micrometer-registry-prometheus依存関係を追加し, /actuator/prometheusエンドポイントを公開し, カスタムビジネスメトリクス (注文作成数, 注文作成時間)を作成し, メトリクスの命名規則とタグ設計を検討してください。

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%