その手の平は尻もつかめるさ

ギジュツ的な事をメーンで書く予定です

HikariCP で leakDetectionThreshold を設定して connection leak を検出する

HikariCP のような connection pool を利用する上で犯しがちなミスとして,connection leak (pool から connection を borrow しっぱなしで pool に返却しないこと) があると思います.connection leak を放っておくと pool 内の connection が枯渇してにっちもさっちもいかなくなるため再優先で修正しなければなりません.


connection leak を修正するには,まず connection leak の発生を検出する必要があります.
以前紹介したような,JMX を使って connection の状態をモニタリングする方法 もありますが,この方法では leak が発生した瞬間を検出することが出来ませんし,どこで発生したかもわかりませんからデバッグが難しくなります.
そこでどうするかというと,HikariCP を使っている場合は leakDetectionThreshold を設定すればグッとデバッグが便利になります.

setLeakDetectionThreshold() を用いてしきい値を設定すると,「connection が borrow されてから pool に返却されるまでの時間」がそのしきい値を超えた場合に,HikariCP は error log としてスタックトレースを出力します *1.これによっていつ,どこで connection leak が発生したのかを検出することが可能になります.

コード的にはこんな感じ.

final HikariDataSource dataSource = new HikariDataSource();
...
dataSource.setLeakDetectionThreshold(5000);

こうしておくと,borrow された connection がsetLeakDetectionThreshold() で設定した 5000ms (5sec) を超えても pool に返却されない時にスタックトレースが出力されるようになります.便利! これで connection leak も直したい放題ですね.

ちなみに実環境では,

final HikariDataSource dataSource = new HikariDataSource();
...
if (env.isDevelopment()) {
    dataSource.setLeakDetectionThreshold(5000);
}

という風にしていて,開発環境下でのみ検出を有効にしています.Java で素朴にスタックトレースを取るのは割とコストが高いというのと,leak を潰すのは開発中にあらかた出来るだろう,加えて JMX で connection の状態をモニタリングしているので実際の運用ではそれで十分だろうという判断からです.


connection leak というのは connection pool を利用する上で起こしやすいバグですし,かつデバッグが難しい部類のバグだと感じています.
採用する connection pool を選定する上で, そうした leak の検出やデバッグを容易にする機能が含まれているかどうかは割と重要な要因だと思います.HikariCP にはそういった connection leak のデバッグを助けるオプションが存在するので便利で良いですね.

*1:This property controls the amount of time that a connection can be out of the pool before a message is logged indicating a possible connection leak. A value of 0 means leak detection is disabled. Lowest acceptable value for enabling leak detection is 2000 (2 secs). Default: 0 https://github.com/brettwooldridge/HikariCP