EDB Postgres Distributed Proxy#

EDB Postgres分散プロキシは、クライアントアプリケーションとPostgres間の抽象化レイヤーとして機能するデーモンです。 PGDコンセンサスメカニズムとインターフェイスして、現在の書き込みリーダーノードのIDを取得し、トラフィックをそのノードにリダイレクトします。

PGDクラスターには、常に少なくとも1つのグローバルグループと1つのデータグループがあります。 PGDは、 enable_proxy_routing およびenable_raft オプションがtrueに設定されている各データグループの書き込みリーダーを選択します。プロキシをグローバルグループまたはデータグループにアタッチできます。各グループに複数のプロキシをアタッチできます。

PGDプロキシは、TCPレイヤー4プロキシです。

その仕組み#

PGDプロキシは、起動時に、ローカル構成ファイルで指定されたエンドポイントのいずれかに接続します。それは取得します

  • 全ノードのDB接続情報

  • リッスンアドレス、リッスンポートなどのプロキシオプション

  • 現在の書き込みリーダーなどのルーティングの詳細

構成ファイルで指定されたエンドポイントは、起動時にのみ使用されます。その後、実際のエンドポイントはPGDカタログのbdr.node_routing_config_summary のroute_dsn フィールドから取得されます。

PGDは、書き込みリーダー選択を管理します。 PGDプロキシはPGDと対話して、Postgres通知/リッスンチャネルで書き込みリーダー変更イベント通知を取得し、クライアントトラフィックを現在の書き込みリーダーにルーティングします。 PGDプロキシは、書き込みリーダーの変更または書き込みリーダーが使用できないときに、既存のすべてのクライアント接続を切断します。書き込みリーダー選挙はRaftによってサポートされるアクティビティであり、Raftリーダーの可用性の対象となります。書き込みリーダーが使用できない場合、 PGDプロキシは新しいクライアント接続を閉じます。

PGDプロキシは、 フェールオーバー と スイッチオーバー の2つの操作モードに分類できる書き込みリーダー変更イベントに応答します。

Postgresまたはオペレーティングシステムがクラッシュした場合に、現在の書き込みリーダーノードから新しいノードへの書き込みリーダーシップの自動転送は、フェールオーバーと呼ばれます。 PGDは、現在の書き込みリーダーがダウンするか、応答しなくなると、新しい書き込みリーダーを選択します。新しい書き込みリーダーがPGDによって選択されると、 PGDプロキシは古い書き込みリーダーへの既存のクライアント接続を閉じ、新しいクライアント接続を新しく選択された書き込みリーダーにリダイレクトします。

現在の書き込みリーダーから新しいターゲットリーダーへのユーザー制御の手動転送は、スイッチオーバーと呼ばれます。スイッチオーバーは、

PGD CLI switchover コマンドを介してトリガーされます。コマンドはPGDに送信され、指定されたターゲットノードを新しい書き込みリーダーとして選択しようとします。フェールオーバーと同様に、

PGDプロキシは既存のクライアント接続を閉じ、新しいクライアント接続を新しく選択された書き込みリーダーにリダイレクトします。これは、サーバーのメンテナンス中に、たとえば、サーバーの更新やOSパッチの更新などのメンテナンスのために現在の書き込みリーダーノードを停止する必要がある場合に役立ちます。

コンセンサス猶予期間#

PGDプロキシは、Raftリーダーの損失時にルーティング動作を構成するために使用できるconsensus_grace_period プロキシオプションを提供します。 PGDプロキシは、この期間にわたって現在の書き込みリーダー利用可能な場合にルーティングし続けます。この期間中に新しいRaftリーダーが選出されない場合、プロキシはルーティングを停止します。 0s に設定されている場合、PGDプロキシはルーティングをすぐに停止します。

このオプションの主な目的は、Raftリーダーが失われたときにユーザーが書き込み動作を構成できるようにすることです。 Raftリーダーがクラスターに存在しない場合、プロキシから見られる現在の書き込みリーダーが正しいものであるとは、必ずしも保証されません。場合によっては、次の例のネットワークパーティションのように、2つの書き込みリーダーが、同じグループに接続された2つの異なるプロキシによって認識され、書き込み競合の可能性が増加する可能性があります。これが目的の動作でない場合は、前述のconsensus_grace_period を0に設定できます。この設定は、Raftリーダーが失われたことを検出すると、ルーティングを停止し、既存のオープン接続をすぐに閉じるようにプロキシを構成します。

ネットワークパーティションの例#

各データノードにプロキシがある3つのデータノードグループを検討します。この場合、現在の書き込みリーダーがネットワーク分割または分離されると、マジョリティパーティションに存在するデータノードが新しい書き込みリーダーを選択します。 consensus_grace_period がゼロ以外の値10s に設定されている場合、以前の書き込みリーダーに存在するプロキシは、この期間書き込みをルーティングし続けます。

この場合、猶予期間が長すぎると、2つの書き込みリーダーで書き込みが発生し続けます。この条件により、書き込み競合が発生する可能性が増加します。

そうは言っても、ほとんどの場合、現在のRaftリーダーを失うと、ノードクォーラムの半分以上がまだ残っている場合、新しいRaftリーダーは数秒以内にBDRによって選択されます。したがって、Raftリーダーがダウンしているが、書き込みリーダーがまだアップしている場合、consensus_grace_period をゼロ以外の正の値に保つことにより、ルーティングを許可するようにプロキシを構成できます。プロキシは、ルーティングを停止する前に、この期間にRaftリーダーが選出されるのを待ちます。これは、可用性がより重要な場合に役立つ場合があります。

マルチホスト接続文字列#

PostgreSQL Cクライアントライブラリlibpqを使用すると、単純なフェイルオーバーのために単一の接続文字列で複数のホスト名を指定できます。これは、他の一部のプログラミング言語のクライアントライブラリドライバーでもサポートされています。ダウンまたはアクセス不能なPGDプロキシインスタンス全体のフェイルオーバーに適しています。

ただし、 PGDプロキシインスタンスにアクセスできるが、書き込みリーダーにアクセスできない場合、または特定のインスタンスの書き込みリーダーが存在しない場合、つまり、特定のPGDグループに書き込みリーダーがないため、接続単に失敗するだけです。マルチホスト接続文字列内の他のホストは試行されません。この動作は、 HAProxyやpgbouncerなどの他のプロキシを使用したPostgreSQLクライアントライブラリの動作と一貫しています。

PGDプロキシの管理#

PGD CLIは、 create-proxy 、delete-proxy 、set-proxy-options 、show-proxies など、PGDクラスターでプロキシを管理するためのいくつかのコマンドを提供します。詳細については、

PGD CLIを使用する を参照してください。

PGDプロキシの構成と管理のPGD側の詳細については、

接続管理 を参照してください。

プロキシのヘルスチェック#

PGDプロキシは、次のHTTPヘルスチェックAPIエンドポイントを提供します。 APIエンドポイントはGET 要求に応答します。使用する前にそれらを有効にして構成する必要があります。

競合ログ構成のリスト を参照してください。

GET /health/is-ready
GET /health/is-live

準備状況#

有効なGET 要求を受信すると、プロキシは現在の書き込みリーダーに接続を正常にルーティングできるかどうかを確認します。チェックが正常に返された場合、APIはtrue とHTTPステータスコード200 (OK) を含む本文で応答します。それ以外の場合、false を含む本文をHTTPステータスコード500 (Internal Server Error) とともに返します。

ライブネス#

Livenessチェックは、HTTPステータスコード200 (OK) を含むtrue またはErrorのいずれかを返します。 PGDプロキシサービスが開始に失敗するか終了すると、要求をリッスンするHTTPサーバーが停止するため、 false は返されません。

プロキシログの場所#

syslog#

  • Debianベース - /var/log/syslog

  • Red Hatベース - /var/log/messages

journalctl コマンドを使用して、プロキシのトラブルシューティングのためのログをフィルタリングおよび表示します。以下は、クイックリファレンスのためのいくつかのサンプルコマンドです。

journalctl -u pgd-proxy -n100 -f
journalctl -u pgd-proxy --since today
journalctl -u pgd-proxy --since "10 min ago"
journalctl -u pgd-proxy --since "2022-10-20 16:21:50" --until "2022-10-20 16:21:55"