HikariCPのチューニング記事 で maximumPoolSize などの値を決めた方は多いと思います。でもその値が本番トラフィックに十分かは、設定した瞬間には分かりませんよね。この記事では、HikariCPがMicrometerに公開するメトリクスをActuator/Prometheusで可視化し、エラーが出る前に枯渇の兆候を閾値とアラートで検知する方法を解説します。

ログだけでは枯渇の兆候に気づけない

Failed to validate connection のようなエラーログが出るのは、プールが実際に枯渇した後です。すでに影響が出てから気づくことになります。

しかも枯渇しかけている間は、待機スレッドが増えてレスポンスが遅くなるだけで、例外にならないことも多いです。エラーログだけに頼っていると、この予兆の段階を見逃してしまいます。

主要メトリクスとチューニング値の対応

HikariCPはMicrometerに10種類弱のメトリクスを公開しています。Prometheus形式の名前(ドットがアンダースコアに変わったもの)で、チューニング記事で決めた設定値との対応も見ておきましょう。

  • hikaricp_connections_active は現在使用中のコネクション数です
  • hikaricp_connections_idle は待機中の空きコネクション数で、minimumIdle の現在値に対応します。ゼロに近づき続けているなら枯渇寄りの状態です
  • hikaricp_connections_pending はコネクションを取得できず待っているスレッド数で、枯渇検知で最も重要な指標です
  • hikaricp_connections_max は maximumPoolSize の現在値そのもので、active との比率が使用率になります
  • hikaricp_connections_acquire_seconds はコネクション取得までの待ち時間です(Timer型のため複数系列に分解されます)
  • hikaricp_connections_timeout_total は connectionTimeout を超えて取得に失敗した回数です

設定値は「意図」、メトリクスは「実態」です。両方を見比べて初めて、チューニングが効いているかが分かります。

application.ymlでPrometheusエンドポイントを有効化する

まず依存を追加します。

implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("io.micrometer:micrometer-registry-prometheus")

続けてエンドポイントを公開します。management.metrics.enable.hikaricp はデフォルトtrueなので追加設定は不要です。

management:
  endpoints:
    web:
      exposure:
        include: health,metrics,prometheus

起動後に確認しましょう。

curl -s localhost:8080/actuator/prometheus | grep hikaricp_connections

pool="HikariPool-1" のラベルで出ていればOKです。これは pool-name 未設定時の自動採番名なので、明示設定している場合は以降のクエリの値を置き換えてください。

枯渇の兆候をPrometheusで可視化する

瞬間値だけで判断すると誤検知が増えるので、継続時間で見るのがポイントです。使用率はこのクエリで出せます。

hikaricp_connections_active{pool="HikariPool-1"}
  / hikaricp_connections_max{pool="HikariPool-1"}

80%以上で5分以上推移していたら危険域です。pendingの継続は min_over_time で判定します。

min_over_time(hikaricp_connections_pending{pool="HikariPool-1"}[5m]) > 0

pendingは本来ゼロであるべき指標なので、1分でも0より大きい状態が続いたら要注意です。Grafanaでは使用率のゲージとpendingの時系列を並べると傾向がひと目で分かります。導入自体は SpringBootのObservability構築記事 を参考にしてください。

Prometheusでのアラートルール設計

ここで定義するのはPrometheus側の「アラートルール」(rule_files)です。Alertmanagerの設定ファイル(alertmanager.yml)とは書式が違うので、そのまま貼るとパースエラーになります。

groups:
  - name: hikaricp
    rules:
      - alert: HikariPoolPendingThreads
        expr: hikaricp_connections_pending{pool="HikariPool-1"} > 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: 'HikariCPでコネクション待ちが発生しています'

使用率ベースも expr を書き換え severity: warning を追加すれば2段階運用になります。for 句は一瞬のスパイクで発火させないために必須です。

通知するのはAlertmanagerの役割です。severity でルーティング先を分けると、criticalだけ即時通知できます。

route:
  receiver: default-mail
  routes:
    - matchers: [severity = "critical"]
      receiver: slack-critical
receivers:
  - name: default-mail
    email_configs: [{to: '[email protected]'}]
  - name: slack-critical
    slack_configs: [{channel: '#alerts-critical'}]

criticalが出た時点では、プールサイズの見直しだけでなく、スロークエリやリークも疑ってください。

まとめ

チューニングしただけでは本番で十分かは分かりません。maximumPoolSize と hikaricp_connections_max のように設定値とメトリクスを対応づけ、pending の発生や使用率の高止まりをアラートにしておくことで、エラーになる前に対応できます。

チューニングが済んでいない場合は HikariCPのチューニング記事 を、Actuatorに不安があれば はじめてのSpring Boot Actuator入門 を先に読むのがおすすめです。すでにエラーが出ている場合は Failed to validate connectionの対処記事、DB側の max_connections が頭打ちの場合は Kubernetesレプリカ構成の記事 が参考になります。