DNSラウンドロビンで負荷分散しているDB(Aurora等)にコネクションプールを使って接続すると設定次第で負荷分散ができないっていう話と解決法
環境
RDSのクラスタ構成(Aurora@MySQL5.7使用。全部、db.t2.small)
アプリ構成
* Spring-boot:2.1.0
* HikariCP:3.2.0
※JVMがDNSキャッシュしないようにしておくこと
実験内容
hikariCPのmaxLifetimeを変えながら、コネクションプール使用環境下で継続的にDBアクセスがある場合に負荷分散が行われるかどうかを確認する。
- コネクションプール数は最大10とする。
- abコマンドを 4リクエスト、4同時接続でバックグラウンドで実行する。
- ↑のabコマンドをwhileでループさせて、3秒に1回実行する、というのをしばらくの間継続して実行し続ける。
- リクエスト1回で、DBへselectを実行し、数秒(少なくともリクエストが滞留する程度には遅い)でselectの結果が返ってくるようにしてある。
※リクエスト毎に読み込みエンドポイントに対して、↓の状態のテーブルに、
SELECT * FROM hoge a, hoge b, hoge c, hoge d, hoge e, hoge f, hoge g, hoge h where a.pk != #{id} order by a.pk desc limit 1
を投げるようになっている。
※#{id} の部分にはランダムで数値が入るようにして、結果がキャッシュされないようにする
どこのIPアドレスに接続しているかはnetstatで常時監視
while :; do netstat -ano | grep ":3306 "; sleep 1; clear; done
実験結果
動画とれれば面白いのですがそういうの無いので、結果のテキストだけ。。
maxlifetimeを30"分"にして実行する(hikariCPのデフォルト値)
最初に接続したIPアドレスから接続先が変わりません。
※レプリカ3台にしていますが、最初に接続したのが2台だった場合、残りの1台には30分間に接続しません。
maxlifetimeを30"秒"にして実行する(hikariCPの最小値)
30秒毎に接続しているIPアドレスが変化しているのが確認できます。
※Spring-bootのログからもmaxlifetimeに引っかかり再接続しにいくログが見れます
※30秒間は同じところに繋ぎに行くのが良いのかどうかはまた別の話。。
結論
DNSラウンドロビンで負荷分散をしているシステムに対して、コネクションプールを張り続けると負荷分散ができない。
※厳密にいうとできていない訳ではないけど、、
ので、短いスパンでDB接続を一旦張りなおす設定をいれましょう。
※maxlifetimeでなくても、規定秒idleで切断する(idleTimeout)とか。idleしないと切れないけど。。
参考
- MySQLへコネクションプール有り無しでの速度差検証 ※接続コストが。。っていう人向け(多分、MySQL系限定)
- Aurora、クラスタ構成でホスト名にアクセスした時、ping 打つ毎にIPアドレスが変わるのを確認する
Author And Source
この問題について(DNSラウンドロビンで負荷分散しているDB(Aurora等)にコネクションプールを使って接続すると設定次第で負荷分散ができないっていう話と解決法), 我々は、より多くの情報をここで見つけました https://qiita.com/k_hoso/items/73443cc38ab0ae75ac2c著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .