MEGAZONEブログ
AWSで分散デザインパターンを実現する
Speaker : AWS Korea Solutions Architect イム・ヨンウク / AWS Korea Solutions Architect チョ・ヒョンス
Pulisher : ジェユン
引用:Pete loucks. Core Modeling Practices Purist
はじめに
まず、クライアントにサービスを説明する際に、建築物に例えて次のように話しているようです。
・人々は新しい建築に魅力を感じるが、時間が経つにつれて、クライアントのニーズや時代の流れに合わせて、建築物のリモデリングがよく行われる。
・サービスの観点から見ると、クライアントに対して最初に最低限の機能を構築することを推奨する。提供したサービスが本当に満足しているかどうかがわからないため。
・そのため、最初はMonolithic architectureを提供する。
最初はシンプルにし、必要に応じて複雑性を増やす
多くの人がMonolithic architectureに否定的な印象を持っていますが、実際には非常に有効に活用できます。一番の理由は、様々なリソースを短時間で構築できるからです。しかし、先ほどの建築物の例でお伝えしたリモデリングのように、サービスにも機能追加などのメンテナンスが必要です。そのため、私たちは「適応型システム設計」を考えます。
適応型システム設計
・継続的に発展するシステムアーキテクチャとデザイン
・機能変更を最小限のコストで達成
・ビジネスと技術変化に迅速に適応
ビジネス成長による適応方式
例えば、サービス開始時は問題が少ないが、ユーザー数が100名から1,000,000名に増加するとボトルネックが発生する可能性があります。大規模なトラフィックによるトランザクション遅延の悪化を避けるため、Scale UpやScale Outが必要になります。しかし、投資対効果を考慮すると、これらの方法が最適とは限らないため、代替案を検討する必要があります。今回説明する分散デザインパターンが有効な代替案の一つとして提案されます。
では、一つのシナリオを例に見てみましょう。
Unicornリテールサービス
Unicornリテールという架空のサービスがあります。UIは次のようになります。
・Userの利用残額(チャージ式)
・Unicornモデル名
・Unicornモデル金額
サービスは建築物のように進化していきます。「ロイヤルティポイント制度」の機能を追加します。
ビジネス戦略による技術決定
「ロイヤルティポイント制度」は、Unicorn製品を購入するユーザーに限りポイントを提供し、再購入を促すビジネス戦略です。新機能導入にあたり、次のような悩みが生じます。
・「モノリシック構成に適応する」OR「分散デザインに変更する」
実際には、正解はありませんが、仮定として「ロイヤルティポイント制度をリリースした後、1週間後にブラックフライデーが始まる」という状況があるとします。この場合は、「分散デザイン」を選択します。その理由は、各サービスを柔軟にテストでき、障害が発生しても既存のUnicornリテールサービスに影響が与えられないためです。
新しい機能を追加することは単純な作業のように思えますが、実際にはシステムをより複雑にします。この複雑さを管理する方法について考えてみましょう。
Domain-Driven Design
複雑性を管理するために、業界ではさまざまな設計手法が用いられますが、今回はドメイン駆動設計(DDD)について説明します。DDDには2つの重要な概念があります。
・Ubiquitous Language: 異なるチームが共通の用語を使用し、より明確に表現することで、スムーズなコミュニケーションを図る。
・Bounded Context: システム内のバウンダリーを定義する。
Bounded Context設計
「ロイヤルティポイント制度」機能を追加する際に、Unicornリテールサービスを以下のようにBounded Contextで分けることができます。
・リテールContext(既存):会員認証、在庫、購買、Payment、アカウント、補償
・ロイヤルティポイントContext(新機能):アカウント、積金、ポイント、日付、種類
Bounded Context仕様
「ロイヤルティポイント制度」の機能を追加した時のシナリオを確認してみましょう。
・UserがUnicornを選択し、購入する
・Back-endでは、リテールContextが動く
・購入完了後、ロイヤルティポイントContextが動く
2と3を繋ぐには、イベントを利用します。最小限の従属性で異なるContextを繋ぐことができるためです。
サービスに反映されたBounded Context
このイベントでは、Unicornを購入またはキャンセルした際に、イベントをトリガーしてロイヤリティサービスのロジックが動作する仕組みになっています。
非機能要件の定義
非機能要件にも注意が必要です。例えばUnicornリテールサービスでは、以下のようになります。
品質属性 | 非機能要件の定義 |
単純性 | 異なるドメイン(リテール、ロイヤリティポイント)間のロジックを単純化 |
拡張性 | トラフィックが急増しても高いQPS/TPSを維持 |
利用性 | 高いQPS/TPS状況でも、常に一貫したUXを提供 |
性能 | リアルタイムに近いロイヤリティポイントの発行と利用 |
チェックアウトのプロセス
ECサイトでは、「チェックアウト」処理も重要です。例えば、Unicornを購入し、支払いからロイヤリティポイントまで発行されることを示します。
・在庫予約:在庫予約後、決済を行う。
・利用残額減少:チャージした金額から減らす。
・ポイント発行:ロイヤリティポイントを発行する。
しかし、このプロセスでは障害が発生する可能性もあります。例えば、在庫の予約ができない、利用残高やポイントが反映されないケースが考えられます。マイクロサービスアーキテクチャ(MSA)を扱う際に、障害が発生した場合にロールバックが可能になるようにする手法です。MSAでは、データベースが物理的に分離されており、単一のトランザクションでのコミットとロールバックが不可能です。そのため、ビジネスロジックにおいて、コミットやロールバックなどのトランザクションに対する責任を持つように設計する必要があります。
このようなMSAを上手く処理するためには、Sagaパターンを検討する必要があります。
Sagaパータンについて
Sagaパータンには、次の2つの方式があります。
- Orchestration
- Orchestrationエンジン
- 段階的なワークフロー管理
- ローカルトランザクションと補償
- Choreography
- 中央集権的(Orchestration)なものは無し
- 各ローカルトランザクションによって発行
- 分散型ビジネスロジック
架空のUnicornリテールサービスには、AWS Step Functionsを利用し、Saga Orchestration方式で具現します。
Unicornリテールドメインのアーキテクチャ
Sagaオーケストレーションでは、在庫を予約し、確認できたらユーザーの利用残高から支払いを行い、ロイヤリティポイントを発行する流れになります。各イベントで障害が発生した場合は、前のステップにロールバックすることになります。この構成をAWSアーキテクチャで実現すると、次のような流れになります。
1.UserがUnicornを注文して、API Gatewayが在庫予約のマイクロサービスを呼び出すと、注文の処理が始まる。
2.在庫マイクロサービスが商品の確認を行う。
3.在庫がある場合、インベントリから商品を引き当て、決済マイクロサービスへ進む。
4.決済が完了すると、Amazon EventBridgeがロイヤリティポイント発行のイベントが起動する。
5.このスタップで障害が発生した場合、ロールバックを行い、前の状態に戻る。
また、AWS Step Functions Workflow Studioの機能を利用し、Sagaオーケストレーションを実現することが可能です。
全体的なアーキテクチャ
こちらは、ロイヤリティポイント発行機能を追加した際の全体の構成図になります。EventBridgeを基盤にして、左側のボックスはリテールドメインです。Unicornの購入に関するトランザクションを行うと、EventBridgeがイベントを発行し、ロイヤリティドメイン側でロイヤリティポイントを発行します。このロイヤリティドメインでは、Event SourcingとCQRSパターンを実現するために、Lambda、DynamoDB、API Gatewayを使用します。
セッションを終えて
このAWSセッションでは、複雑なビジネスプロセスを効率的に管理するためのドメイン駆動設計(DDD)とSagaパターンが紹介されました。DDDはチーム間のコミュニケーションを円滑にし、Sagaパターンは障害時のロールバックを可能にすることで、システムの回復力を高めます。これらの手法をAWSアーキテクチャに適用することで、堅牢なECサイトのチェックアウト処理が実現されます。