一般的な使用シナリオ
アプリケーションのスケーラビリティ
サーバーレスおよびイベント駆動アプリケーションでの接続処理
AWS Lambda を基盤とする API やウェブサービスなどのサーバーレスおよびイベント駆動アプリケーションは、多くの場合、多数の短期間のクライアントリクエストをサポートする必要があります。この使用パターンにより、アプリケーション側で接続プーリングを実装できないため、データベース側で接続チャーンが発生する可能性があります。同時接続の数だけが原因でデータベースのパフォーマンスが低下する可能性があり、データベースが接続制限を超えるとクライアント側エラーが発生する可能性があります。
これらのシナリオでは、RDS Proxy には次の利点があります。
-
データベースからプロキシへの接続を確立するコストをオフロードし、接続プーリングと多重化によって、多数のクライアント接続をはるかに少数のバックエンドデータベース接続に変換します。これにより、特に接続の確立と維持のコストが比較的高い PostgreSQL などのデータベースエンジンでは、接続のオーバーヘッドとデータベースの競合を軽減するのに役立ちます。
-
接続の急増をより適切に処理できます。例えば、データベースが接続制限を超えると、即座にクライアントにエラーが返されます。RDS Proxy がプールから接続を借用する必要があるが、プールが既に満杯の場合、プロキシは接続が利用可能になるまで待機できます。この機能により、重大なエラーをクエリレイテンシーのわずかな増加に変えることで、クライアントエクスペリエンスを向上させることができます。
-
接続プールのサイズを設定できるため、RDS Proxy をスロットリングまたは負荷分散メカニズムとして使用することもできます。接続数が指定した制限を超えると、RDS Proxy は設定可能なタイムアウト内に接続が利用可能になるまで待機します。これは、データベースが複数のワークロードを処理し、特定のワークロードがデータベースに与える負荷の量を制限する場合に便利です。
コンテナベースの分散アプリケーションでの接続処理
コンテナベースの分散アプリケーションアーキテクチャには、数百または数千のコンテナがあり、それぞれでアプリケーションコードのコピーが実行される場合があります。個々のコンテナが接続プーリングに対応していたとしても、これらのプールはコンテナ固有であるため、非常に小さくなります。コンテナの数に各コンテナミニプールのサイズを掛けると、Amazon RDS または Aurora データベースの接続制限を超える可能性があります。
この状況では、RDS Proxy が接続プーリング (接続の再利用) と多重化 (1 つのバックエンド接続を使用して複数のクライアントに提供する) を実行する能力が最も価値を発揮します。各コンテナ内の接続プールを使用して、アプリケーションスレッドと RDS Proxy 間のチャーンを減らすことはできますが、プロキシはバックエンドデータベースへの接続の数を管理可能なレベルに減らすのに役立ちます。
リードレプリカの使用率を向上させる
読み取り量の多いデータベースでは、読み取り専用トラフィックをサポートするために複数のリードレプリカが必要になる場合があります。アプリケーションは独自のロジックを使用して、どのレプリカに接続するかを選択できます。より一般的には、Aurora クラスターリーダーエンドポイントなどの DNS ベースのラウンドロビンメカニズムを使用します。ただし、DNS ベースのアプローチでは、DNS キャッシュの結果としてレプリカ使用率が不均等になる可能性があります。例えば、クライアントが特定のレプリカに「ピン」接続したり、クラスターに追加された新しいレプリカを認識できなかったり、存在しなくなったレプリカに接続しようとしたりする可能性があります。
RDS Proxy 読み取り専用エンドポイントを使用する場合、プロキシは「未処理の接続が最も少ない」というロジックを使用して、使用可能なすべてのレプリカ間でクライアント接続をルーティングします。RDS Proxy は、CPU 使用率などのデータベースメトリクスに基づいてトラフィックの負荷分散を行うのではなく、データベースの接続制限に基づいて重み付けして、各レプリカのクライアント接続の数を均等化しようとします。例えば、max_connections の設定がそれぞれ 500、500、1000 の 3 つの Aurora レプリカが実行されている場合、プロキシは他の 2 つのレプリカと比較して、3 番目のレプリカに対して約 2 倍の接続数を送信しようとします。
RDS Proxy リーダーエンドポイントは、Aurora クラスターまたは 2 つの読み取り可能なスタンバイを持つ Amazon RDS マルチ AZ DB クラスターデプロイで使用できます。プロキシリーダーエンドポイントは、リードレプリカを使用する Amazon RDS DB インスタンスのデプロイではサポートされていません。
接続効率の向上
クライアントアプリケーションとデータベース間にプロキシを導入する場合、通常、接続処理の効率を高めることを目的とすると同時に、プロキシを介した追加のネットワークホップによるレイテンシーコストも考慮する必要があります。接続効率を向上させるために中間レイヤーを追加することは、一見すると直感に反しているように思えるかもしれません。なぜなら、データベースに対して直接開かれていた接続がプロキシに対して開かれるようになるためです。プロトコルハンドシェイクのステップはどちらの場合も同じであるため、接続ハンドシェイクにリソースを消費し続けている状況では、効率改善がどこから来ているのか分かりにくいかもしれません。
プロキシを使用しても、必ずしも接続確立コストが安くなるわけではありません。代わりに、ハンドシェイク処理の負担のほとんどをデータベースレイヤーからプロキシレイヤーに移動します。データベースリソースの料金を支払うのであれば、そのリソースを補助的なオーバーヘッドではなく、データベース作業に費やす必要があります。これは、暗号化された接続を使用する場合に特に重要になります。既存の接続を介して暗号化されたデータを送信するオーバーヘッドはそれほど大きくありませんが、暗号化された接続のセットアップのための初期オーバーヘッドは相当なものです。1 秒あたり数百または数千の接続を処理するような環境では、そうした余分な労力がすぐに蓄積される可能性があります。CPU 時間を (比較的高価な) データベースリソースに消費するのではなく、(比較的安価な) プロキシレイヤーにオフロードするほうが良いかもしれません。
追加のネットワークホップによって生じるレイテンシーについては、アプリケーションがどの程度「おしゃべり」であるか、およびデータベースとの「会話」ごとに実行されるステートメントの数によって異なります。RDS Proxy では、通常、1 桁ミリ秒程度のレイテンシーが増加しますが、必ずしもアプリケーションに目に見える影響を与えるとは限りません。例えば、次のようになります。
-
クエリ実行時間が数十または数百ミリ秒 (またはそれ以上) のワークロードでは、プロキシのオーバーヘッドは、合計クエリ時間のごく一部であるため、それに気付く可能性はほとんどありません。
-
1 桁ミリ秒または 1 ミリ秒未満のクエリを実行するアプリケーションでは、クエリのオーバーヘッド (クエリごとに 1 つの追加のネットワークホップ) がクエリ実行時間と比較してかなり大きいため、違いが顕著に現れる可能性があります。クライアントセッションで少数のクエリのみを実行する場合であれば、累積オーバーヘッドが小さいため、これは問題ではない可能性があります。
お客様の状況において、追加されるレイテンシーが顕著で望ましくない場合は、プロキシを使用することによるその他の利点 (プーリング、多重化、フェイルオーバー処理) と比較検討する必要があります。
高可用性
Amazon RDS および Aurora (Aurora DSQL を除く) で実行されているマルチ AZ データベースは、フェイルオーバーメカニズムを使用して、プライマリデータベースインスタンスに問題がある場合に可用性を復元します。フェイルオーバーは、プライマリインスタンスのコンピューティングのスケーリングなど、運用ワークフローの一部としても使用されます。フェイルオーバーでは、DNS の変更によってプライマリ (読み取り/書き込み可能) データベースエンドポイントを、以前のプライマリインスタンスから新たに昇格したインスタンスに移動します。この DNS の変更は、クライアントが遅延なくプライマリをフォローできるように、クライアントアプリケーションによって監視および認識される必要があります。
一部のアプリケーションは、オペレーティングシステムまたはアプリケーションレベルでの DNS キャッシュが原因で、DNS の変更をタイムリーに認識できない場合があります。アプリケーションレベルで DNS キャッシュの問題に対処するのがベストプラクティスですが、アプリケーションの複雑さや変更の導入コストが原因で、必ずしも実行可能とは限りません。
このシナリオでは、RDS Proxy は DNS 関連のフェイルオーバーの遅延を回避する効果的な方法です。RDS Proxy が提供する読み取り/書き込みエンドポイントとオプションの読み取り専用エンドポイントは、データベースインスタンスがロールを交換するときにエンドポイントの背後にある IP アドレスが変更されないという点で「安定」しています。RDS Proxy は、バックエンドデータベースのトポロジを継続的に追跡し、インスタンスロールの変更をクライアントから抽象化します。
DNS キャッシュの問題を処理する別の方法として、DNS に依存することなくデータベーストポロジを直接検出できる高度なドライバーを使用する方法などがあります。ただし、アプリケーションレベルでコード変更や新しいドライバーを導入する代わりに、データベースの前に単一のプロキシをデプロイする方が簡単な場合があります。
読み取り可用性
データベースフェイルオーバー中のクライアントエクスペリエンスの向上に加えて、RDS Proxy はリードレプリカの問題が発生した場合のアプリケーションの可用性にも役立ちます。これは、次の 2 つの方法で行われます。
-
リードレプリカが使用できなくなっても、クラスターに他のレプリカが使用可能な場合、プロキシは新しい接続を使用可能なレプリカにルーティングできます。クライアントは、DNS 伝播の遅延や DNS キャッシュについて心配する必要はありません。
-
多重化された既存のクライアント接続の場合、プロキシはその接続から利用可能な別のレプリカに後続のクエリを送信できます。このような状況では、クライアントはバックエンドのレプリカで問題が発生したことにさえ気付かない場合があります。この手法を使用する場合、RDS Proxy はレプリケーションの遅延に関して新しいレプリカが以前のレプリカより遅れないようにします。これにより、クライアントによって送信された後続のクエリは、古くなったと考えられるデータを参照することがなくなります。
1 つのターゲットに対して複数のプロキシを使用する
ベストプラクティスとして、Amazon RDS インスタンスや Aurora クラスターなどのデータベースターゲットごとに 1 つの RDS Proxy を使用します。これはほとんどのシナリオでうまく機能し、設定をシンプルに保ち、クライアントエクスペリエンスをより予測可能なものにします。これに対して、複数のプロキシを使用する場合は、予期しない動作を避けるために、すべてのプロキシ間で設定を慎重に調整する必要があります。例えば、すべてのプロキシプールの合計サイズが単一のデータベースターゲットの接続制限を超えないようにする必要があります。
特定の状況では、複数のプロキシを使用するというアイデアを試すこともできます。以下のセクションでは、最も一般的なシナリオについて説明し、単一プロキシとマルチプロキシアプローチの長所と短所について概説します。
プロキシの可用性
RDS Proxy のインフラストラクチャは可用性が高く、複数のアベイラビリティーゾーン (AZ) にデプロイできます。プロキシ容量は、継続的なヘルスモニタリングを備えた多数のノードに分散され、プロビジョニングされたインスタンスサイズまたはデータベースの Serverless v2 最大 ACU 設定に基づいて自動的に調整されます。プロキシの分散マルチ AZ 設計により、高可用性を実現するために Amazon RDS または Aurora クラスターの前に複数のプロキシを実行する必要はありません。
実際に、1 つのデータベースターゲットの前に複数のプロキシを使用すると、アプリケーションスタックはプロキシに組み込まれている堅牢なメカニズムに依存するのではなく、問題を検出して対応する責任を担うようになります。したがって、可用性を高めるために複数のプロキシを使用することは、解決できるよりも多くの問題を引き起こす可能性があるため、強く推奨されません。
複数のクライアントプールを処理する
各プロキシは、1 つの読み取り/書き込みエンドポイントと (オプションで) 追加の読み取り/書き込みエンドポイントまたは読み取り専用エンドポイントを提供します。単一のプロキシを使用して複数のクライアントグループまたは複数のワークロードを処理すると、それらのワークロードが干渉する可能性があります。例えば、あるワークロードが接続プールを独占してしまい、他のワークロードを処理するのに十分な空き接続が残らなくなる可能性があります。ワークロードを分離するために個別のプロキシを使用することは有力なソリューションとなり得ますが、その前に他のオプションを検討することができます。
-
データベース自体が、複数のプロキシを実行するよりも簡単な代替手段を提供する場合があります。例えば、特定のユーザーがプールを独占したことが原因で問題が発生した場合、データベースのアクセス許可システムを使用して、ユーザーが開くことができる同時接続の数を制限できます。
-
同様に、データベースレベルのクエリタイムアウトとアイドルタイムアウトは、孤立した接続やランナウェイクエリの問題に対処するのに役立ちます。
-
同時接続数ではなく、クエリまたはトランザクションの実行時間、またはクエリごとのリソース消費が原因で問題が発生した場合、プロキシはクエリまたはトランザクションの重みに制限を課さないため、追加のプロキシの使用は役に立ちません。ソースで問題に対処できない場合は、問題のあるクライアントを別のプロキシに移動する代わりに、データベースのイベントスケジューラを使用して、任意の条件に基づいてクライアントのアクティビティを検出して終了するコードを実行できます。
同じターゲットの前に複数のプロキシを使用する場合は、すべての接続プールの合計サイズがターゲットデータベースの容量を超えないようにしてください。例えば、すべてのプロキシの MaxConnectionsPercent の合計は 100 未満である必要があります。そうしないと、プロキシはデータベースが処理するように設定されているよりも多くの接続を開こうとする可能性があります。
各プロキシは個別に課金され、請求レートはワークロードアクティビティではなく、基盤となるデータベースリソースのサイズによって決まります。複数のプロキシを実行するコストと、代替ソリューションがある場合は、それを導入するコストを考慮してください。
読み取りプールと書き込みプールを個別に制御する
各プロキシは、1 つの読み取り/書き込みエンドポイントと (オプションで) 追加の読み取り/書き込みエンドポイントまたは読み取り専用エンドポイントを提供しますが、制限とタイムアウトはプロキシエンドポイントごとに個別に設定されるのではなく、プロキシターゲット全体に設定されます。
例えば、複数のリードレプリカとプロキシのリーダーエンドポイントを使用して大量の読み取り専用クエリを処理する Aurora クラスターがある場合でも、読み取り/書き込み接続の数を制限して単一ライターのリソース負荷を軽減したい場合があります。MaxConnectionsPercent 設定はプロキシターゲット (クラスター) 全体に対して定義されているため、読み取り専用エンドポイントの制限に影響を与えることなく、読み取り/書き込みエンドポイントに対する接続数を制限することはできません。
この課題にアプローチする方法は複数あります。
クラスターで追加のリードレプリカを起動し、プロキシの MaxConnectionsPercent 設定を比例的に減らすことができます。これにより、読み取り専用接続プールの合計サイズは維持されつつ、書き込みで許可される最大接続数が削減されます。ただし、これはクラスターのコストを増加させるだけでなく、レプリカの数が増えるほど効果が徐々に低下します。
インスタンスレベルのパラメータグループを使用して、ライターとは別に、リードレプリカのデータベース接続制限 (Aurora MySQL や PostgreSQL の max_connections など) を設定できます。ただし、非対称なパラメータ設定の使用は避ける必要があります。フェイルオーバー中にレプリカがライターロールに昇格される可能性があるため、初期のパラメータの差異が永続的なものにならないからです。フェイルオーバー中にどのレプリカが昇格対象として選択されるかに影響を与えるために、インスタンスレベルのフェイルオーバー優先度設定を変更し、それを緩やかなフェイルオーバー除外メカニズムとして使用することで、非対称な設定をより予測可能にすることができます。ただし、フェイルオーバーの優先順位はヒントとしてのみ機能し、フェイルオーバー動作の確実な保証にはなりません。したがって、非対称設定のマルチインスタンス設定は、継続的なモニタリングが必要であり、フェイルオーバーが意図しないインスタンスで発生した場合に予期しない動作が発生する可能性があるため、推奨されません。
このシナリオでは、複数のプロキシを使用することが、読み取りプールと書き込みプールを個別に管理する最もクリーンな方法でとなる可能性があります。単一のデータベースターゲットに 2 つのプロキシを作成し、アプリケーションが最初のプロキシのライターエンドポイントと 2 番目のプロキシの読み取り専用エンドポイントを使用するように設定できます。一方のプロキシは書き込みワークロードのみを処理し、もう一方のプロキシは読み取りワークロードのみを処理します。また、MaxConnectionsPercent (および他の設定) は、プロキシごとに個別に設定できます。このソリューションでは、2 つ目のプロキシを実行するために追加コストがかかりますが、前述の代替方法よりもシンプルで予測可能です。