クライアント側の Postgres 接続プール
この記事の英語版に更新があります。ご覧の翻訳には含まれていない変更点があるかもしれません。
最終更新日 2022年12月13日(火)
Table of Contents
Heroku には、アプリケーションコードと共に PgBouncer を実行するための buildpack が用意されています。これは、他の buildpack と組み合わせて使用するように考慮されています。
この buildpack の主な使用法は、dyno 内の複数のワーカー間での PostgreSQL データベース接続のトランザクションプーリングを可能にすることです。たとえば、10 個の Unicorn ワーカーが 1 つのデータベース接続を共有することにより、Postgres サーバー上の接続制限やメモリ不足エラーを回避できるようになります。
この buildpack のソースコードは、Github で見つけることができます。
トランザクションプーリングを使用する必要がある場合
開かれたアイドル接続を保持する多数のワーカーが dyno ごとに存在し、Postgres が接続制限に近づいていることを心配している場合。
これは、stackoverflow からの多少は完全になった回答です。
トランザクションプーリングを使用するべきではない場合
名前付きプリペアドステートメント、アドバイザリロック、リッスン/通知、またはセッションレベルで動作するその他の機能を使用する必要がある場合。
トランザクションプーリングに関するすべての注意事項については、PGBouncer の機能マトリックスを参照してください。
設定
PgBouncer buildpack をアプリに追加します。
$ heroku buildpacks:add heroku/pgbouncer
Procfile
を編集し、bin/start-pgbouncer
を適切な行に追加します。次の例では、Web プロセスは PgBouncer を使用して Postgres に接続するように、またワーカープロセスは Postgres に直接接続するように設定します。
web: bin/start-pgbouncer your-web-app
worker: your-worker-app
変更をコミットしてプッシュします。これで、アプリは PgBouncer を使用して Postgres に接続するようになります。
$ git commit -av -m "web processes now use PgBouncer"
$ git push heroku
複数のデータベースへの接続
PGBOUNCER_URLS
を環境設定の一覧に設定することによって、PgBouncer を使用して複数のデータベースに接続できます。
$ heroku config:add PGBOUNCER_URLS="DATABASE_URL HEROKU_POSTGRESQL_ROSE_URL"
フォロワーレプリカデータベース
当社では、平等に関する当社の価値観に適合するよう、インクルーシブでない用語を可能な範囲で変更しました。当社製以外のシステムに関する記述では、インクルーシブでない用語をそのまま使用していますが、当社では開発者コミュニティに対し、よりインクルーシブな表現の採用を奨励しています。該当する用語については、技術的な正確さのために必要でなくなった時点での更新を予定しています。
Octopus Replication を使用して読み取りをレプリカに送信している場合は、SLAVE_DISABLED_FOLLOWERS
ブロックリストにリーダーの色 URL を確実に含めるようにしてください。そうしないと、Octopus はリーダーを読み取り専用レプリカとして使用しようとするため、接続数が 2 倍になる可能性があります。
言語/ライブラリ固有の設定
特定の Postgres ドライバーに対して ignore_startup_parameters を設定する
一部のドライバー (Go の pq ドライバーなど) では、Postgres に接続するために使用される URI に extra_float_digits
が含まれています。これらのドライバーでこの buildpack を使用するには、追加の環境設定を設定する必要があります。
$ heroku config:set PGBOUNCER_IGNORE_STARTUP_PARAMETERS=extra_float_digits
このコマンドにより、dyno の起動時に PgBouncer の設定ファイルに ignore_startup_parameters = extra_float_digits
が追加されます。
ORM での予期しないセッション設定
一部の ORM (v4.2.5 より前の ActiveRecord など) では、一貫性を確保するために、クエリ中にセッション変数を設定する場合があります。これは Postgres に直接接続するときに役立つこともありますが、トランザクションの接続プールで予期しない動作や診断が困難なエラーが発生する場合があります。接続プールに移行する前に、アプリケーションを徹底的にテストするようにしてください (ORM コードを監査して “必要以上の動作をする” セッション設定がないかどうかを調べるなど)。
これらの問題の例は、GoCardless のエンジニアリングブログにあります。
Go の pq ドライバーの SSL モード
PgBouncer buildpack で Go の pq ドライバーを使用すると、次のエラーが発生します。これは、dyno 上の PgBouncer がサーバーの証明書にアクセスできないために発生します。
pq: SSL is not enabled on the server
接続を成功させるには、次の環境変数を設定します。
$ heroku config:set PGSSLMODE=disable
接続は引き続き安全です。PgBouncer は、Postgres 自体に接続するためにネイティブな TLS を使用します。PGSSLMODE
を設定した場合のみ、アプリケーションから PgBouncer への TLS 接続が無効になります。
Rails でプリペアドステートメントを無効にする
Rails 4.1 では、データベースの URI に ?prepared_statements=false
を追加することによって、プリペアドステートメントを無効にすることができます。
Rails バージョン 4.0.0 ~ 4.0.3 ではプリペアドステートメントをまったく無効にできないことが報告されています。プリペアドステートメントの失敗をトラブルシューティングする前に、フレームワークが最新であることを確認してください。
Rails 3.2 ~ 4.0 では、イニシャライザで prepared_statements 設定の文字列をブール値として正しくキャストすることも必要です。このイニシャライザは、このコミット. In file config/initializers/database_から適応されます。ファイル config/initializers/database_connection.rb で、次を挿入します。
require "active_record/connection_adapters/postgresql_adapter"
class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
alias initialize_without_config_boolean_coercion initialize
def initialize(connection, logger, connection_parameters, config)
if config[:prepared_statements] == 'false'
config = config.merge(prepared_statements: false)
end
initialize_without_config_boolean_coercion(connection, logger, connection_parameters, config)
end
end
調整のための設定
一部の設定は、実行時にアプリ環境設定によって設定できます。実際にどの設定が適しているかを確認するには、PgBouncer の適切なドキュメントを参照してください。
Procfile
内の環境設定またはインライン環境変数のどちらかが設定のために機能します。
環境設定から行う場合:
$ heroku config:set PGBOUNCER_POOL_MODE=session
インライン環境変数から行う場合:
web: PGBOUNCER_POOL_MODE=session bin/start-pgbouncer
設定可能な設定
PGBOUNCER_POOL_MODE
デフォルトはトランザクションです。
PGBOUNCER_MAX_CLIENT_CONN
デフォルトは 100 です。
PGBOUNCER_DEFAULT_POOL_SIZE
デフォルトは 1 です。
PGBOUNCER_MIN_POOL_SIZE
デフォルトは 0 です。
PGBOUNCER_RESERVE_POOL_SIZE
デフォルトは 1 です。
PGBOUNCER_RESERVE_POOL_TIMEOUT
デフォルトは 5.0 秒です。
PGBOUNCER_SERVER_LIFETIME
デフォルトは 3600.0 秒です。
PGBOUNCER_SERVER_IDLE_TIMEOUT
デフォルトは 600.0 秒です。
PGBOUNCER_URLS
PgBouncer に接続するために上書きされるすべての環境設定が含まれています。たとえば、PgBouncer を使用して RDS 接続を送信するには、この変数を AMAZON_RDS_URL
に設定します。デフォルトは DATABASE_URL
です。
PGBOUNCER_CONNECTION_RETRY
デフォルトは no です。
PGBOUNCER_LOG_CONNECTIONS
デフォルトは 1 です。アプリが永続的なデータベース接続を使用していない場合、この設定はノイズとなる可能性があるため、0 に設定する必要があります。
PGBOUNCER_LOG_DISCONNECTIONS
デフォルトは 1 です。アプリが永続的なデータベース接続を使用していない場合、この設定はノイズとなる可能性があるため、0 に設定する必要があります。
PGBOUNCER_LOG_POOLER_ERRORS
デフォルトは 1 です。
PGBOUNCER_STATS_PERIOD
デフォルトは 60 です。
PGBOUNCER_SERVER_RESET_QUERY
デフォルトは、プールモードがトランザクションである場合は空、セッションである場合は “DISCARD ALL;” です。
PGBOUNCER_IGNORE_STARTUP_PARAMETERS
PgBouncer の起動時に無視するパラメータを追加します。一部の Postgres ライブラリ (Go の pq など) では、このパラメータを追加すると、この buildpack を使用できなくなります。デフォルトは空であり、最も一般的に無視されるパラメータは extra_float_digits
です。
複数のパラメータをカンマで区切ることができます。
例: PGBOUNCER_IGNORE_STARTUP_PARAMETERS="extra_float_digits, some_other_param"