

# DynamoDB のルーティング戦略
<a name="bp-global-table-design.prescriptive-guidance.request-routing"></a>

グローバルテーブルのデプロイで最も複雑な部分は、おそらくリクエストルーティングの管理です。リクエストは、まずエンドユーザーから、何らかの方法で経路が選定されたリージョンに送る必要があります。リクエストは、そのリージョンでサービスのスタックに遭遇します。これには、AWS Lambda 関数、コンテナ、または Amazon Elastic Compute Cloud (Amazon EC2) ノードでバッキングされたロードバランサーを構成要素とするコンピューティングレイヤーや、場合によっては他のサービス (別のデータベースなど) が含まれます。このコンピューティングレイヤーは DynamoDB と通信します。この通信は、そのリージョンのローカルエンドポイントを使用して行う必要があります。グローバルテーブルのデータは、参加している他のすべてのリージョンにレプリケートされ、各リージョンには DynamoDB テーブルを中心に同様のサービスのスタックがあります。

 グローバルテーブルは、さまざまなリージョンの各スタックに同じデータのローカルコピーを提供します。1 つのリージョンの 1 つのスタックを対象とした設計を行い、ローカルの DynamoDB テーブルに問題が発生した場合は、セカンダリリージョンの DynamoDB エンドポイントにリモート呼び出しを行うということも考えられます。しかし、これは、ベストプラクティスではありません。あるリージョンで DynamoDB が原因で問題が生じた場合 (または、スタック内の他の要素や、DynamoDB に依存する別のサービスが原因である可能性が高い場合) の最善策として、エンドユーザーを別のリージョンにルーティングして処理を行い、その別のリージョンのコンピューティングレイヤーを使用して、ローカル DynamoDB エンドポイントと通信すると良いでしょう。このアプローチを取ると、問題のあるリージョンを完全に迂回してルーティングを行えます。レジリエンスを確保するには、複数リージョン間でのレプリケーション、かつ、コンピューティングおよびデータレイヤーのレプリケーションが必要です。

 エンドユーザーのリクエストをリージョンにルーティングして処理するための代替手法は数多くあります。最適な選択は、書き込みモードとフェイルオーバーに関する考慮事項によって異なります。このセクションでは、クライアント主導、コンピューティングレイヤー、Route 53、Global Accelerator の 4 つのオプションについて説明します。

## クライアント主導のリクエストルーティング
<a name="bp-global-table-design.prescriptive-guidance.request-routing.client-driven"></a>

次の図に示すように、クライアント主導のリクエストルーティングでは、エンドユーザークライアント (アプリケーション、JavaScript を使用したウェブページ、別のクライアントなど) が有効なアプリケーションエンドポイント (リテラル DynamoDB エンドポイントではなく Amazon API Gateway エンドポイントなど) を追跡します。さらに、独自の埋め込みロジックを使用して、通信対象のリージョンを選択します。この選択は、ランダムな選択、観測された最低のレイテンシー、観測された最大の帯域幅測定値、ローカルで実行されたヘルスチェックなどに基づいて行われると考えられます。

![\[クライアントが選択したターゲットへの書き込みの仕組みを示す図。\]](http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/images/gt-routing-is-clients-choice2_v2.png)


クライアント主導で行うリクエストルーティングの利点の 1 つは、パフォーマンスの低下が検出された際にリージョンを切り替えるなどして、実際のパブリックインターネットトラフィック状況に適応できることです。クライアントは、すべての潜在的なエンドポイントを認識している必要がありますが、新しいリージョンエンドポイントの立ち上げは頻繁に起こることではありません。

*任意のリージョンへの書き込み*モードでは、クライアントが優先エンドポイントを一方的に選択できます。1 つのリージョンへのアクセスが損なわれた場合、クライアントは別のエンドポイントにルーティングできます。

*1 つのリージョンへの書き込み*モードでは、クライアントは現在アクティブなリージョンに書き込みをルーティングするメカニズムが必要になります。これは、どのリージョンが現在書き込みを受け入れているかを経験的にテストする (書き込み拒否を確認して別のリージョンにフォールバックする) という基本的なものから、グローバルコーディネーターを呼び出して現在のアプリケーションの状態をクエリするという複雑なものまであります。後者の場合は、このようなニーズに対応してグローバル状態を維持するために、Amazon Application Recovery Controller (ARC) ルーティング制御に基づいて構築し、5 リージョンのクォーラム駆動型システムを提供するようなメカニズムとなります。クライアントは、読み取りを任意のリージョンに送って結果整合性を確保するのか、アクティブなリージョンにルーティングして強力な整合性を確保するのかを決定できます。詳細については、「[Route 53 の仕組み](https://docs.aws.amazon.com/r53recovery/latest/dg/introduction-how-it-works.html)」を参照してください。

 *自分のリージョンへの書き込み*モードでは、クライアントは使用するデータセットのホームリージョンを決定する必要があります。例えば、クライアントがユーザーアカウントと一致し、ユーザーアカウントごとに 1 つのリージョンをホームとする場合、クライアントはグローバルログインシステムに対して適切なエンドポイントをリクエストできます。

 例えば、ユーザーがウェブ経由で財務を管理できるよう支援する金融サービス会社では、*自分のリージョンへの書き込み*モードでグローバルテーブルを使用できます。各ユーザーは中央サービスにログインする必要があります。このサービスは、認証情報と共に、認証情報が機能するリージョンのエンドポイントを返します。認証情報の有効期間は短期です。有効期間後に、ウェブページは新しいログインを自動ネゴシエートし、ユーザーのアクティビティを新しいリージョンにリダイレクトする機会を提供します。

## コンピューティングレイヤーのリクエストルーティング
<a name="bp-global-table-design.prescriptive-guidance.request-routing.compute"></a>

次の図に示すコンピューティングレイヤーのリクエストルーティングでは、コンピューティングレイヤーで実行するコードによって、リクエストをローカルで処理するか、別のリージョンで実行中の自身のコピーに渡すかを決定します。*1 つのリージョンへの書き込み*モードを使用する場合、コンピューティングレイヤーでは、アクティブリージョンでないことが検出すると、ローカルでの読み取りオペレーションを許可すると同時に、すべての書き込みオペレーションを別のリージョンに転送することがあります。このコンピューティングレイヤーコードは、データトポロジとルーティングルールを認識する必要があります。また、どのリージョンをどのデータに対してアクティブにするかを指定する最新の設定に基づいて、これらのデータトポロジとルーティングルールを確実に適用する必要があります。リージョン内の外側のソフトウェアスタックは、読み取りリクエストと書き込みリクエストがマイクロサービスによってどのようにルーティングされるかを認識する必要はありません。堅牢な設計では、受信側リージョンが書き込みオペレーションの現在のプライマリであるかどうかを検証します。プライマリでない場合は、グローバル状態を修正する必要があることを示すエラーが生成されます。プライマリリージョンが変更中の場合、受信側リージョンが書き込みオペレーションをしばらくバッファリングすることもあります。いずれの場合も、リージョン内のコンピューティングスタックはローカルの DynamoDB エンドポイントにのみ書き込みますが、コンピューティングスタック間で相互に通信する可能性があります。

![\[コンピューティングレイヤーのリクエストルーティングを示す図。\]](http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/images/gt-compute-layer-routing2.png)


Vanguard グループでは、[re:Invent 2022](https://www.youtube.com/watch?v=ilgpzlE7Hds&t=1882s) での説明のように、グローバルオーケストレーションとステータスツール (GOaST) というシステムと、グローバルマルチリージョンライブラリ (GMRlib) というライブラリをこのルーティングプロセスに使用しています。フォローザサンの単一プライマリモデルを採用しています。GOaST では、前のセクションで説明した ARC ルーティングコントロールと同様に、グローバル状態が維持されます。このシステムでは、グローバルテーブルを使用して、どのリージョンがプライマリで、プライマリ状態の次回の切り替えがいつ予定されているかを追跡しています。すべての読み取りおよび書き込みオペレーションは、GOaST と連携する GMRlib を経由してルーティングされます。GMRlib を使用すると、ローカルでの読み取りオペレーションを低レイテンシーで実行できます。書き込みオペレーションでは、GMRlib によって、ローカルリージョンが現在のプライマリリージョンかどうかを確認します。プライマリリージョンである場合、書き込みオペレーションは直接完了します。プライマリでない場合は、GMRlib によって、書き込みタスクがプライマリリージョンの GMRlib に転送されます。受信側のライブラリは、自身もプライマリリージョンであると認識したことを確認します。そうでない場合は、エラーを生成します。これにより、グローバル状態の伝播が遅延します。このアプローチでは、リモート DynamoDB エンドポイントに直接書き込まないため、検証上の利点があります。

## Route 53 のリクエストルーティング
<a name="bp-global-table-design.prescriptive-guidance.request-routing.r53"></a>

Amazon Application Recovery Controller (ARC) は、ドメインネームサービス (DNS) テクノロジーです。Route 53 の場合、クライアントは既知の DNS ドメイン名を検索してエンドポイントをリクエストし、Route 53 は最も適切と思われるリージョンエンドポイントに対応する IP アドレスを返します。これについては、以下の図で示されています。Route 53 には、ルーティングポリシーの長いリストがあり、これを使用して適切なリージョンを決定します。フェイルオーバールーティングも実行し、これによって、ヘルスチェックに失敗したリージョンからトラフィックを迂回させます。

![\[コンピューティングレイヤーのリクエストルーティングの図。\]](http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/images/gt-rt-53-anycast2_v2.png)


*任意のリージョンへの書き込み*モードを使用するか、バックエンドでコンピューティングレイヤーのリクエストルーティングと組み合わせることで、ネットワークに最も近いリージョン、地理的に最も近いリージョンなど、複雑な内部ルールに基づいてリージョンを返すフルアクセスを Route 53 に許可できます。

*1 つのリージョンへの書き込み*モードでは、現在アクティブなリージョンを返すように Route 53 を設定できます (Route 53 ARC を使用)。読み取りオペレーションなどを行うためにパッシブリージョンに接続するクライアントは、別の DNS 名を検索できます。

**注記**  
クライアントは、ドメイン名の有効期間 (TTL) 設定で指定された期間にわたって、Route 53 からの応答に含まれている IP アドレスをキャッシュします。TTL を長くすると、すべてのクライアントが新しいエンドポイントを認識するまでの目標復旧時間 (RTO) が長くなります。フェイルオーバーを使用する場合は通常 60 秒です。必ずしもすべてのソフトウェアが DNS TTL の有効期限に完全に準拠しているとは限らないため、オペレーティングシステム、仮想マシン、アプリケーションなど、複数のレベルの DNS キャッシュが存在する可能性があります。

*自分のリージョンへの書き込み*モードでは、コンピューティングレイヤーのリクエストルーティングを一緒に使用する場合を除いて、Route 53 を避けるのが最善です。

## Global Accelerator のリクエストルーティング
<a name="bp-global-table-design.prescriptive-guidance.request-routing.gax"></a>

次の図に示すように、[AWS Global Accelerator](https://aws.amazon.com/global-accelerator/) を使用する場合、クライアントは Route 53 で既知のドメイン名を検索します。ただし、クライアントはリージョンのエンドポイントに対応する IP アドレスを取得する代わりに、最も近い AWS エッジロケーションにルーティングするエニーキャスト静的 IP アドレスを受け取ります。このエッジロケーションを起点に、すべてのトラフィックはプライベート AWS ネットワークでルーティングされます。ルーティング先は、Global Accelerator 内で維持されるルーティングルールで選択された、リージョンの一部のエンドポイント (ロードバランサーや API ゲートウェイなど) です。Global Accelerator のリクエストルーティングは、Route 53 ルールに基づくルーティングと比較して、パブリックインターネットのトラフィック量を削減するため、レイテンシーが短縮されます。さらに、Global Accelerator はルーティングルールを変更するために DNS TTL の有効期限に依存しないため、ルーティングをより迅速に調整できます。

![\[Global Accelerator を使用したクライアント書き込みの仕組みを示す図。\]](http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/images/gt-routing-gax-excerpt2_v2.png)


 *任意のリージョンへの書き込み*モード、またはバックエンドのコンピューティングレイヤーのリクエストルーティングと組み合わせることで、Global Accelerator はシームレスに動作します。クライアントは最も近いエッジロケーションに接続するため、どのリージョンがリクエストを受け取るか気にする必要はありません。

 *1 つのリージョンに書き込む*場合、Global Accelerator のルーティングルールにより、現在アクティブなリージョンにリクエストを送信する必要があります。ヘルスチェックを使用すると、グローバルシステムによってアクティブなリージョンとは見なされていないリージョンの障害を人為的に報告できます。DNS と同様に、読み取りリクエストがどのリージョンからでも可能な場合は、代替の DNS ドメイン名を使用して読み取りリクエストをルーティングできます。

 *自分のリージョンへの書き込み*モードでは、コンピューティングレイヤーのリクエストルーティングを一緒に使用する場合を除いて、Global Accelerator を避けるのが最善です。