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レプリカ構成の記事 が参考になります。