クライアント側コネクションプール
ActiveRecordを通してデータベースにアクセスするRubyプロセスは、同時実行数に基づいてプロセスのコネクションプールサイズを自動的に計算します。
Ruby on Railsはデータベース接続を管理するため、少なくともスレッド数と同じ数の接続を持つことが重要です。database.yml
には「プール」設定がありますが、アプリケーションのスレッド数と連動してメンテナーを維持する必要があるため、あまり実用的ではありません。このため、設定されたアプリケーションスレッド数に基づいて、データベース接続プールで許可される接続数をオーバーライドします。
Gitlab::Runtime.max_threads
は、プロセスが設定したユーザー向けアプリケーションスレッドの数です。また、データベース接続を使用する補助スレッドもあります。アプリケーションが時間と共に進化する際に、補助スレッドの数を正確にカウントし続けるのは簡単ではないので、ユーザー向けスレッドの数に固定ヘッドルームを追加するだけです。接続は遅延的にインスタンス化されるため、この数が大きすぎても問題ありません。
コネクションプールの問題のトラブルシューティング
コネクションプールの使用状況は、コネクションプール飽和度ダッシュボードで環境ごとに確認できます。
コネクションプールが小さすぎる場合、アプリケーションからActiveRecord::ConnectionTimeoutError
。ほぼすべての接続が使用されたときに警告を出すので、タイムアウトが発生する前にこれを知るべきです。このような場合は、DB_POOL_HEADROOM
環境変数をハードコードされた値(10)よりも大きな値に設定することで対処できます。
この時点で、何が予想以上のコネクションを使用しているかを調査する必要があります。そのためには、gitlab_ruby_threads_running_threads
メトリクスを使用します。例えば、このグラフはデータベースに接続するすべての実行中のスレッドをその名前で表しています。puma worker
またはsidekiq_worker_thread
と表示されているスレッドは、Gitlab::Runtime.max_threads
を定義するスレッドです。他のスレッドが 10 個以上実行されている場合は、デフォルトのヘッドルームを上げることを検討できます。
接続のライフサイクル
Web リクエストの場合、データベースへのクエリが最初に実行されると、プールから接続が取得されます。リクエストが完了すると、接続はプールに戻されます。
バックグラウンドジョブでは、動作は非常に似ています。スレッドは最初のクエリのために接続を取得し、ジョブ終了後にそれを返します。
これはRails内部で管理されます。