アプリケーションとワークロードに関する考慮事項
マルチテナントおよびマルチユーザー環境
スケーラビリティと接続管理の改善に関して、RDS Proxy を使用する利点は接続プーリングを実行できること、そしてそれ以上に接続多重化を実行できることに大きく依存しています。接続プーリングは、接続の開閉に関連するオーバーヘッドを削減します。接続多重化により、プロキシはトランザクション後にバックエンドデータベース接続を再利用できます。詳細については、「RDS Proxy の概念と用語」を参照してください。
接続を多重化できない場合、プロキシは接続の固定と呼ばれる動作に戻ります。固定は、クライアントがセッション全体で同じ基盤となるプロキシ接続を使用することを強制される状況です。プロキシ接続はその 1 つのクライアント用に予約されているため、他のクライアントで再利用することはできません。つまり、固定により、クライアントとプロキシの接続とプロキシとデータベースの接続の間に排他的な 1 対1 の関連付けが作成されます。固定を回避することは、主にスケーラビリティと効率の理由から RDS Proxy が使用されるすべてのシナリオで重要です。固定の最新の動作については、「RDS Proxy の固定の回避」を参照してください。
一般的なルールとして、接続の状態が同じであれば、接続を多重化できます。セッション固有のカスタム状態情報が含まれている場合、接続を多重化することはできません。セッション状態を定義する要素の 1 つは、接続に関連付けられたデータベースユーザー名です。プロキシに「user_A」として接続する場合、プロキシはバックエンドデータベース接続も「user_A」として開く必要があります。プロキシは、「user_A」としてログインする他のクライアントに対して、このバックエンド接続をプールして再利用できる可能性がありますが、別のユーザー名を使用するクライアントには再利用できません。
この動作により、一意のデータベースアカウントが多数あるマルチユーザー環境において、プーリングと多重化の効率が大幅に低下する可能性があります。これは、データベースレベルまたはスキーマレベルのマルチテナンシーを使用するアーキテクチャで特に当てはまります。データベースに 1,000 個のスキーマ (テナントごとに 1 つ) が含まれており、各テナントが異なるユーザー名でデータベースに接続すると、接続プールはユーザー固有のマイクロプールに断片化され、全体的な効率が低下します。
さらに、データベースエンジンに固有の側面は、プーリング効率とプロキシの接続を多重化する機能にさらに影響を与える可能性があります。
-
Amazon RDS と Aurora PostgreSQL では、テナントごとに 1 つのデータベースを使用してマルチテナンシーを実装することがよくあります。ただし、PostgreSQL では、接続はデータベース固有です。あるデータベースに対して開かれた接続は、他のデータベースのデータにアクセスできません。したがって、データベースレベルのマルチテナンシーにより、プロキシレベルでのプーリングと多重化の効率が低下します。この考慮事項は、ワークロードがスキーマレベルのマルチテナンシーを使用し、クライアントセッションがカスタムの
search_pathを使用する場合にも適用されます。ただし、すべてのセッションがデフォルトの検索パスを使用し、完全修飾名 (schema_name.table_name) を使用してテーブルを参照する場合は、それらのセッションを多重化できます。 -
Amazon RDS と Aurora MySQL では、「データベース」と「スキーマ」という用語は同義語です。マルチテナンシーは、多くの場合、テナントごとに 1 つのスキーマを使用して実装されます。MySQL では、テナントごとに 1 つのデータベースを使用することと同じです。接続は MySQL サーバー全体に対して開かれ、スキーマには関連付けられません。アプリケーションがスキーマレベルのマルチテナンシーを使用する場合、同じデータベースユーザー名を使用するクライアントは、それらの接続が異なるスキーマのデータにアクセスする必要がある場合でも、接続の多重化が可能です。多重化は、テナントごとに異なるデータベースアカウントを使用する代わりに、テナントの分離がアプリケーションレベルで行われる場合に最も効果的です。
マルチスキーマ環境では、多重化の効率はテーブル名をどのように参照するかによって異なります。
-
セッション変数 (PostgreSQL では
SET search_path ...、MySQL ではUSE schema;) を使用して現在のスキーマを選択し、クエリで非修飾テーブル名 (SELECT ... FROM table_nameなど) を使用するクライアントの場合、接続多重化は、同じスキーマまたは同じ検索パスを使用するクライアント間でのみ機能します。 -
セッション状態を変更して現在のスキーマを定義するのではなく、SQL ステートメントで完全修飾テーブル名 (
SELECT ... FROM schema_name.table_nameなど) を使用するクライアントの場合、多重化は同様に制約されません。
複数のアプリケーションまたはソフトウェアスタックに対応するデータベース
前のセクションで説明したように、特定の接続状態の特性によって固定が発生することはありませんが、異なるクライアント間での接続の再利用におけるプロキシの機能は低下します。MySQL ターゲットで使用すると、RDS Proxy は、文字セット、タイムゾーン、照合設定など、セッション状態を設定する多数のステートメントとセッション変数を追跡します。クライアントが追跡されたステートメントまたは変数を使用してセッション設定を構成する場合、プロキシ接続は、それらの設定に同じ値を持つ他のクライアントに対してのみ再利用できます。
その結果、特定のアプリケーションやドライバーの動作により、プロキシ内の接続を再利用できなくなる可能性があります。例えば、プロキシがそれらのアプリケーション間の接続を再利用および多重化できると仮定すれば、異なるアプリケーションが同じユーザー名を使用してデータベースに接続することを許可できるかもしれません。ただし、あるアプリケーションがタイムゾーン A (SET time_zone = ?) との接続をブートストラップし、別のアプリケーションがタイムゾーン B を使用する場合、接続はアプリケーション内で再利用できますが、アプリケーション間では再利用できません。これにより、接続プールが断片化され、プールと多重化の有効性に悪影響を及ぼします。
詳細については、「RDS Proxy が RDS for MariaDB および RDS for MySQL データベースに対して追跡する内容」を参照してください。セッション状態の追跡は現在、MySQL 以外のデータベースターゲットではサポートされていません。
接続の固定を回避するためのセッション状態管理に関する設定ガイドラインとベストプラクティスについては、「設定のガイドライン」を参照してください。
RDS Proxy でのアプリケーションレベルのプーリングと高度なドライバーの使用
RDS Proxy は、アプリケーション自体が接続プーリングを使用していない状況において、スケーラビリティと接続効率の向上に役立ちます。同時に、多くのドライバーとフレームワークにはプーリング機能が含まれています。また、ドライバーレベルでプロキシの一部の機能を実装する高度なラッパーまたはドライバーを使用している場合もあります。
アプリケーションレベルのプーリングやその他の接続処理の改善策を使用しても、RDS Proxy の使用と本質的に競合することはなく、その利点が損なわれることもありません。例えば、アプリケーションコンテナで接続プーリングを使用している場合でも、コンテナの数が非常に多いため、プロキシを使用しないとデータベース接続の制限に達してしまう可能性があります。アプリケーションレベルのプールやその他の接続関連の機能と RDS Proxy を併用する場合は、高度な接続処理機能がアプリケーションレベルに存在する理由を確認して理解してください。それらの機能のうち、保持する価値がある機能 (または無害な機能) と、プロキシの動作と重複または干渉する可能性がある機能を判断します。例えば、次のようになります。
-
ドライバーやフレームワークに組み込まれたプーリング機能は、RDS Proxy 機能と重複しているように見える場合でも、有用な場合があります。アプリケーションレベルのプールがプロキシが提供する利点に加えてローカル接続の効率を向上させる場合は、それを維持できます。
-
フェイルオーバー処理に関連する機能は、RDS Proxy ロジックに干渉したり、利点をもたらさずにスタック全体の複雑さを増大させたりする可能性があります。例えば、アプリケーションが DNS 関連のフェイルオーバーの遅延を回避するために Aurora クラスターのトポロジを積極的に追跡している場合、RDS Proxy で追跡する必要はありません。このトポロジ追跡ロジックを保持すると、アプリケーションスレッドがプロキシをバイパスし、個々のデータベースインスタンスに直接接続するなど、望ましくない動作が発生する可能性があります。このシナリオでは、アプリケーションレベルの追跡ロジックを無効にし、RDS Proxy にクラスタートポロジを抽象化させることができます。
-
接続プーリングライブラリは、理論的には有益と思われる状態管理機能を使用することがありますが、それらがプロキシの動作を妨げる場合があります。その一例として、PostgreSQL ライブラリが、借用間の接続状態をリセットするために
DISCARD ALLクエリを呼び出すことが挙げられます。接続のリセットはプーリングと多重化に役立ちますが、Amazon RDS Proxy の内部セッション状態管理を妨げる可能性があります。DISCARDを使用する場合、プロキシはクライアント接続をリリース時に固定するため、多重化の効率が低下します。
保持するアプリケーションレベルの接続処理コンポーネントについては、それらの設定が Amazon RDS Proxy で使用される接続処理ロジックに干渉しないことを確認してください。例えば、次のようになります。
-
スタックのすべてのレイヤーでプールのサイズ設定を合わせます。アプリケーションレベルのプールのサイズが大きすぎる (またはプロキシプールのサイズが小さすぎる) 場合、アプリケーションはプロキシが処理するように設定されていない接続を開こうとする可能性があります。これらの接続では、最良の場合でも遅延が発生し、最悪の場合は拒否エラーが発生する可能性があります。
-
タイムアウト設定を調整してチャーンを減らし、接続動作に関する混乱を回避します。アプリケーションプールが接続を 300 秒間維持しているにも関わらず、プロキシが 60 秒後に接続を閉じるように設定されている場合、アプリケーションは予想される動作ではなく、早期の接続切断を経験することになります。
これらのアーキテクチャ上の決定や設定の選択には、テストと実験が必要になる場合があります。複数のレイヤーからなるプールと接続管理が存在する環境では、アプリケーションの動作を正確に予測できるとは限りません。
一般的な設定ガイドラインについては、「設定のガイドライン」を参照してください。