ここ最近ハマっているのは、マヌルネコを動画で愛でることです。日本では那須どうぶつ王国や神戸どうぶつ王国など一部の動物園で見ることができるようで、先に挙げた動物園はアソビュー!で入場券の購入が可能です。ご興味ある方は、是非。
今回はコネクションプールの設定を見直す機会があったので、それについて書こうと思います。
背景
本記事を書くに至った背景ですが、今年の夏にDBへの負荷が高まったことで各種パラメータを見直す機会がありました。
弊社ではプロダクトを支える技術としてAWSを採用しており、DBはAmazon Aurora(以下、Aurora)を使っています。アプリケーションにはJavaのフレームワークであるSpring bootを採用しております。
今回はコネクションプールのライブラリの中でも、HikariCPに限ってお話をします。HikariCPの詳しい説明については、ライブラリのReademeに委ねますのでそちらをご参照ください。
課題
- アプリケーションが定期的かつ自動的にコネクションプール内のコネクションを再取得できていない
Auroraクラスターのスケールアップ時に、アプリケーションが動的にコネクションプール内のコネクションを再取得できていないことで、スケールアウトに追従できずにアプリケーションのスケールアップと同時にアプリケーションの再起動が必要になっていました。
2. フェイルオーバー時のダウンタイムが長い
フェイルオーバー時に発生する事象として、readerインスタンス(以後、reader)とwriterインスタンス(以後、writer)が入れ替わり、もともとwriterに投げるべきだったSQLをreaderに投げてしまい、SQLが失敗及びそれに付随するデータの整合が取れなくなってしまいます。
そのため、それぞれのロール(writerとreader)を判断できる仕組みが必要です。この設定により、フェイルオーバー時に素早くロールの切り替えができるようになりダウンタイムを短くすることができます。
内容
1.「アプリケーションが定期的かつ自動的ににコネクションプール内のコネクションを再取得できる状態」にするために、コネクションプールで保持しているコネクションの生存期間を設定する
2. DBの役割が変わったときに、素早くその役割の変更が検知できる状態にするために、validation queryの有効化と間隔調整
上記をHikariCPの設定に落とし込むと以下のようになります。
maxLifetimeについて
connectionの生存期間(Tomcat poolingでいうMaxAge)で、デフォルトは30分で最低許容設定値は30秒。値が0の場合は設定がないことになります。
keepalivetime について
hikariCPで、connectionTestQueryを投げる間隔のパラメータです。このパラメータの条件として、30000ms(30秒)以上、maxLifeTimeより小さい値の設定が推奨されています。この設定した値の時間に到達した際の挙動は以下の通りとなっており、pingというのはJDBC4がサポートされているドライバの場合はisValid()メソッドを呼び出し、そうでなければconnectionTestQueryで設定されているQueryを投げる挙動になっています。
When the time arrives for a “keepalive” against a given connection, that connection will be removed from the pool, “pinged”, and then returned to the pool. The ‘ping’ is one of either: invocation of the JDBC4 isValid() method, or execution of the connectionTestQuery.
ただしHikariCPのソースを確認したところ、keepaliveTime(validation queryの間隔)は、設定値をもとに乱数を作成させているため、設定値通りではないようです。(実際に挙動を確認しましたが、設定値よりも短い間隔でvalidationQueryが投げられてました。)
ConnectionTestQueryについて
validation queryとして投げてほしいQueryを設定します。公式の案内にもありますが、使用しているドライバがJDBC4をサポートしている場合の使用は非推奨です。しかし、今回はそれぞれのロール(writerとreader)を判断できる仕組みが必要なので、設定をしています。
MySQL,PostgreSQLでそれぞれロール判断する仕組みが違いますので、ConnectionTestQueryで投げるQueryは違っています。今回は詳細には触れませんが、PostgreSQLの設定については探すのに苦労をしたので、情報の共有に留めます。以下のリンクの「ホスト文字列を取得するためのその他のオプション」をご参照ください。
結果測定
以下の方法でConnectionのライフサイクルとvalidation queryが流れているうことを確認しました。
・Cloudwatch logsから監査ログを見て、validation queryが流れていること
・DBクライアントツールから該当DBに接続し、コネクションが設定値の時間を超えたら切り替わっていること
まとめ
アプリケーションとDBのコネクションのパラメータを見直すことで、障害時間の短縮や作業時間短縮ができました。今後は他のパラメータも見直してみようと思いました。
また、本記事では対応の一部を紹介しましたが、他にもドメインレベルでできることやアプリケーションのTTLの見直すこともできるかと思います。
さいごに
アソビュー!では一緒に働くメンバーを募集しています。
興味がありましたら、まずはざっくばらんにお話しだけでも聞きに来て頂けたら嬉しいです。ご応募をお待ちしております。