Rails(ActiveRecord)でデータベースへのコネクションプーリングをさせなくする
ActiveRecordを使ったRailsアプリは,デフォルトでデータベースへの接続をプールするようになっています.
ActiveRecordユーザとしては待ちわびたぜ!的な機能らしいのですが,設定等でこれをdisableすることが出来ず,LVS+keepalivedを介する場合にはロードバランシングが最初の接続時にしか為されずがなかなか厄介です.
対策として思いついたのは
- プールした接続を早い周期で捨てる
- LVS+keepalivedではなく,MySQL Proxyでバランシングする(Proxyへの接続はプール)
- そもそも接続をプールさせない
くらいでした.
どうするのがセオリーなのかと調べてみると
など4年近く前に議論されていて,"あー,高速道路あるなあ"と,コネクション確立のコストを調べる前に「プールさせない」という選択が出来てしまいました.本来は根っこから調べるべきだとは思いますが,今回はサービスレベルで何が変わるかというのを端的に調べることにしました.
ただ,ActiveRecordのコネクションプーリングについては,実装されることを喜んでいる人はネットで多く見つかるのですが,この機能を潰したいと思う人の声にはなかなか巡り会えませんでした.大きなRailsサイトはいっぱいあると云うのに...そもそもAR使うの?とかMySQLProxy噛まそうよってことなのでしょうか.
最初はdatabase.ymlとかで
pool: 0
とか
wait_timeout: 0
とかやったら出来るんじゃないかと楽をするつもりで試みましたが,エラーだらけになってしまいました.(ちなみにどちらもデフォルト値は5です)
読めよ.コード.
ARでコネクションプーリングを行っている箇所
ActiveRecord-2.3.5だと
activerecord-2.3.5/lib/active_record/connection_adapters/abstract/connection_pool.rb
の
- checkout
- checkin
といったメソッドですね.コメントアウトの説明にもcheckinでpoolにコネクションのオブジェクトconnを入れて,checkoutで取り出しているよと書いてありますね.
安易ではありますが,checkinのときにプールせずにコネクションを捨てて,checkoutで新しくコネクションを確立させればプーリングを機能させなくて済みそうです.
def checkout ActiveRecord::Base.send(spec.adapter_method, spec.config.dup) # same def new_connection end def checkin(conn) conn.disconnect! end
みたいな感じ.
ちょっと不安だなと思っていたらgithubでも巡り会いました.余計なメソッド潰したりもしていらっしゃいますね.
verify!(activerecord-2.3.5/lib/active_record/connection_adapters/abstract_adapter.rb)で,接続されているかを確認し,そうでなかったら再接続もさせています.