📖

re:Invent 2024: AWSのEDA実装 - ECSとFargateによるイベント駆動型アーキテクチャ

2024/01/01に公開

はじめに

海外の様々な講演を日本語記事に書き起こすことで、隠れた良質な情報をもっと身近なものに。そんなコンセプトで進める本企画で今回取り上げるプレゼンテーションはこちら!

📖 AWS re:Invent 2024 - Building event-driven architectures using Amazon ECS with AWS Fargate (SVS339)

この動画では、Event-Driven Architecture(EDA)の基礎から実践的な実装パターンまでを包括的に解説しています。EDAの本質である「何かが起こってそれに反応する」という基本概念から、Amazon EventBridge、AWS Step Functions、Amazon SQSなどを活用した具体的な統合パターンまでを詳しく説明します。特にAWS Fargateを使用したAmazon ECSによるEDAの実装に焦点を当て、スタンドアロンタスク、長時間実行サービス、プッシュベース/プルベースパターンなど、様々なアプローチを紹介。また、EventBridgeとStep Functionsの新機能であるプライベートAPI統合についても言及し、オンプレミス環境とAWSをつなぐモダンなアプリケーション構築の可能性を示しています。
https://www.youtube.com/watch?v=-oXkuy_21BI
※ 動画から自動生成した記事になります。誤字脱字や誤った内容が記載される可能性がありますので、正確な情報は動画本編をご覧ください。
※ 画像をクリックすると、動画中の該当シーンに遷移します。

re:Invent 2024関連の書き起こし記事については、こちらのSpreadsheet に情報をまとめています。合わせてご確認ください!

本編

イベント駆動型アーキテクチャの基礎:自己紹介とアジェンダ

みなさん、お元気ですか? 皆さんの元気な様子が伝わってきます。re:inventの火曜日ですね。彼女の声は私の声にかき消されてしまうので、彼女の番になったら私は話すのを止めます。皆さんにお会いできて嬉しいです。私はEric Johnsonです。AWSのPrincipal Developer Advocateを務めています。そして、こちらの方をご紹介できることを光栄に思います。皆さんに自己紹介をお願いできますか。

皆さん、こんにちは。Uma Ramadossと申します。ServerlessのSpecialist Solutions Architectを務めています。唯一無二のEric Johnsonと一緒にステージに立てることをとても嬉しく思います。また、皆様の前でプレゼンテーションができることを光栄に思います。本日は皆様が私たちのセッションを選んでくださり、ありがとうございます。今日は、AWS Fargateを使用したAmazon ECSによるEvent-Driven Architectureの構築についてお話しします。

さて、私の講演を聞いたことがある方はどれくらいいらっしゃいますか? 念のために申し上げますが、ジョークは同じものを使います。今なら退席してもいいですよ。でも、まだ私の講演を聞いたことがない方が多いようなので、ルールの説明をさせていただきます。私が話すときのルールです - 難しくありませんが、皆さんの理解の助けになります。まず、これは私が好きな数字なら何でも良いということです。私には5人の子供がいると言うかもしれませんし、バーで一人なのに10人分のテーブルを予約したいと言うかもしれません。次に、これはアポストロフィではなく引用符です。なぜなら、これはこれよりも見た目が良いからです。これをするとウサギのマネをしていると思う人がいますが、そうではありません。文脈によってはウサギかもしれませんが。最後に、これは親指です。これをすると殴られるかもしれませんから。

Thumbnail 190

私は人差し指に関するジョークをよくします。私はこういう話し方に慣れています。ただし、真面目な話をさせていただきますと - もしこれが不快だったり、不comfortable感を感じられる方がいらっしゃいましたら、それも私は理解します。どちらでも構いませんので、楽しい時間を過ごしましょう。 それでは、アジェンダを見ていきましょう。Event-Driven Architectureとは何か、Event-Driven Architectureにおける統合パターン、AWS Fargateとは何か、AWS FargateのEDAパターン、そして最後にまとめを行います。

イベントとは何か?EDAの本質と利点

Thumbnail 220

Thumbnail 240

Event-Driven Architectureについて話す時、まずEventとは何かを理解する必要があります。なぜなら、それはEvent-Driven Architectureという言葉の主役だからです。皆さんはEventと聞くと、re:inventや今夜のパーティーのような出来事を思い浮かべるかもしれません。 しかし、ここでいうEventとはJSONオブジェクトのことです - つまり、何かが発生したことを示すものです。Eventとは、システムの状態が変化したことを示す信号です。Eventは過去に発生したものであり、変更することはできません。「それは起こらなかった」と言って過去に戻ることはできません。時にはログを取るなど、別のEventで修正する必要がありますが、Event自体は変更できないのです。

最後に、イベントはプロデューサーとコンシューマーの間の契約です。考えてみてください。ここにいる方で、APIを使ったことがある人はいますか?APIは私たちの開発生活の標準的な部分です。家族やパートナーに話しても興味を示さないかもしれませんが、私たちはAPIについて話します。APIリクエストを送信する際、そこには契約があります - 特定のフォーマットが期待されているわけです。Event-driven architectureでも同じことが言えます。

プロデューサーとコンシューマーの間のこの契約は、おそらく今回のトークの中で最も技術的な部分なので、メモを取りたい方はどうぞ。これからEvent-driven architectureについて説明しますが、多くの人は最初は理解しづらいかもしれません。必要であれば、もう一度説明します。

Thumbnail 350

こんな感じです:何かが起こって、それに反応する。「いやいや、Eric、ここで話すために報酬をもらってるんだから、もっと真面目な話をしてよ」と思われるかもしれません。確かにこれは単純化しすぎていますが、これがEvent-driven architectureの本質なんです - ポーリングで確認したり、誰かが全員に通知したりする必要がなく、何かが起こったらそれに反応するというものです。

Thumbnail 380

Thumbnail 400

EDAではない世界で、プロデューサーがコンシューマーに何かが起こったことを伝える必要がある場合を見てみましょう。プロデューサーは「これが起こりました」とConsumer A、Consumer B、Consumer Cに伝えます。プロデューサーはコンシューマーの存在を認識している必要があります。そこには密結合が存在するんです。EDAでは、これが異なる形になります。代わりに、プロデューサーはイベントを発行します。このイベントは私がデザインしました - とても誇りに思っています。四角形にしようかと思いましたが、私は円形にすることを提案しました。プロデューサーとコンシューマーの間にある太い緑の線に注目してください。これは「あなたのことを知る必要がない」ということを示しています。私の仕事はこのイベントを発行することだけで、あなたがそれを受け取るかどうかは私の問題ではありません。Event-driven architectureがもたらすこの自由さが大好きです。これによってアプリケーション同士を疎結合にできるんです。

API Destinationを活用したイベント通知の送信

Thumbnail 450

Thumbnail 470

これから、結合から疎結合への移行方法について、いくつかのIntegration patternを見ていきます。ここで質問です:開発者の方は手を挙げてください。ほとんどの方が開発者ですね。では、現在ECSを使用している方は手を挙げてください。かなりの数の方がいますね。これらのパターンを見ると、これは私たちがよく目にするパターンです。これは標準的なAPIパターン、同期的なリクエスト・レスポンスモデルです。リクエストを送信し、レスポンスを待ちます。レスポンスが失敗すると、リクエストも失敗します。そのため、ここにも密結合が存在するんです。

Thumbnail 490

Thumbnail 520

このアプローチの利点として、低レイテンシー、シンプルさ、そしてFail Fast(早期失敗)の機能が挙げられます。このFail Fastという考え方について少し掘り下げてみましょう。Fail Fastの利点は、開発環境で何か問題が発生した場合、その場ですぐに把握できるということです。これは非常に便利な特徴であり、同期型の大きな利点となっています。ただし、欠点もあります。スロットリングの問題が発生する可能性があります。ProducerはすべてのConsumerと通信する必要があり、1つでも失敗すると全体が失敗してしまうため、問題が生じやすくなります。また、複雑さも増します。これらのConsumerとの通信に関するロジックすべてをProducer内に実装する必要があり、さらにレジリエンシーの問題も発生します。

Thumbnail 540

Thumbnail 550

ここで、同期型から非同期型通信への移行について説明しましょう。その方法として、間にBrokerと呼ばれるものを導入します。これには様々な呼び方がありますが、Brokerの役割は、リクエストを受け取った際に単に確認応答を返すだけです。実際の処理やビジネスロジック、プロセスは実行せず、単に「受け取りました」と応答し、その後PushまたはPullのプロセスを通じてデータをConsumerに届けます。Consumerはデータの出所を知る必要はなく、気にする必要もありません。単にデータを受け取って処理するだけです。これがEvent-Driven Architectureです。

Thumbnail 590

これを実現する方法はいくつかあります。最初に説明するのはEvent Routerです。またあの円が出てきましたね。Event Routerは1つのイベントを一度に処理し、複数のエンドポイントやプロトコルに対してルーティングを行います。通常、フィルタリングはRouter層で実施されます。

Thumbnail 630

AWSでこれらのRouterを構築する際は、設定可能なリトライ機能とDLQ(Dead Letter Queue)機能を実装します。最初に検討するパターンは、特に注目に値するEvent Busです。これによってロケーションカップリングが減少し、送信側の効率が大幅に向上します。特に興味深い点は、ルーティングロジックがProducerやConsumer層ではなく、ルール層で処理されることです。これはEvent Bus内にルーティングのルールが含まれていることからも分かります。

Thumbnail 650

Thumbnail 670

Thumbnail 690

このサービスには、Amazon EventBridgeを使用します。AWSアカウントをお持ちの方は、すでにアクセス権をお持ちです。というのも、使用の有無に関わらず、すべてのアカウントにデフォルトのBusが用意されているからです。EventBridgeの仕組みを見ていきましょう。まず、様々なソースがあります。AWSサービスやカスタムアプリケーション、その他多くのものがソースとして機能します。これらのソースは、先ほど説明したデフォルトのBusを含む、いずれかのBusにデータを送信します。EventBridgeやCloudWatchがそのデフォルトのBusにデータを送信する可能性があります。また、カスタムEvent BusやPartner Busを作成することもできます。

Amazon SQSを用いたメッセージ処理とスケーリング

Thumbnail 710

Thumbnail 730

EventBridgeの真価は、Ruleにあります。 Ruleは不可欠なものです - 5人の子どもの父親として、それは間違いなく言えます。Ruleを使うと、マッチした際にデータをTargetに送信するように指定できます。 例を使って説明しましょう。このピザの注文イベントを見てください。名前に「パイナップルは載せない」と明記されているので、これは正しいイベントだということがわかります。これは今日お話しする中で最も重要なポイントかもしれません。なぜなら、ピザにパイナップルを載せるべきではないからです。このイベントは、本物の正統なピザに関するものなのです。

Thumbnail 760

Thumbnail 780

Ruleがどのようなものか見てみましょう。 Ruleはシンプルです - Sourceがcom.flixからのものであることを指定しています。これが配列になっているのは、マッチング条件を追加できるからです。また、regionはオーストラリアかニュージーランドのいずれかである必要があります。 ご覧の通り、com.flixがSourceで、regionも一致しているため、これはマッチと見なされます。この例は少し遊び心のあるものですが、シンプルでありながら非常に強力だということを覚えておいてください。

Thumbnail 800

Thumbnail 820

これらのRuleはTargetに接続され、 AWS Lambda、Amazon ECS(これについては今日詳しく説明します)、API、その他多くの送信先を含むことができます。これでイベントルーティングにおけるEvent Busの部分は説明し終わりました。次は、Topicを使用したイベントルーターについて見ていきましょう。 Topicでは、Topic levelでのフィルタリングを行いながら、複数のConsumerに対してブロードキャストベースで送信するという考え方です。フィルタリングされない限り、すべてのConsumerが同じTopicを受信します。

Thumbnail 840

Topicは複数のプロトコルをサポートしており、 これが特に強力な特徴です。後ほど説明するTopicは、様々な通信方法をサポートしています。メール、SMS、Lambda、外部APIエンドポイントに送信できます。これは情報を配信する上で非常に強力なツールとなります。基本的にTopicを指定し、そのTopicのSubscriberがデータを受信する仕組みです。

Thumbnail 870

このサービスには Amazon SNSを使用しており、 ドキュメントから重要な機能をいくつか紹介したいと思います。Standard Topicは1秒あたりほぼ無制限のメッセージをサポートしており、そのデータ処理能力の高さを示しています。最大1,250万のSubscriptionを持つことができ、FIFO(First-In-First-Out)機能も提供しており、強力なメッセージングサービスとなっています。

Thumbnail 910

Thumbnail 920

Amazon SNSの次に見ていくのは、一度に1つのイベントを処理するのではなく、複数のイベントを扱うEvent Storeと呼ばれるパターンです。 ここでは、イベントの配列やバッチを扱います。データはメッセージとして入力され、それをConsumerが消費します。 上のConsumerはメッセージ65と4を受け取り、下のConsumerは32と1を受け取っているのがわかります。すべてのConsumerがすべてのメッセージを受け取るわけではなく、各メッセージを処理するのは1つのConsumerだけです。これは、多くのConsumerで大量のデータを処理する必要があるものの、重複を避けたい場合に特に役立ちます。重複との戦いは、1つのConsumerだけがこれらのメッセージを処理するIdempotentなシステムを構築することで実現します。DLQをサポートしており、Amazon SNSで説明したように、FIFOを使用して順序を強制することもできます。

Thumbnail 990

Thumbnail 1000

複数のConsumerが同じイベントを必要とする場合は、複数のQueueを用意してFan-outする必要があります。Topicを使ってQueueにFan-outし、Consumer向けに複数のQueueを使用することができます。 このために使用するのが、ほぼ無限にスケールする完全マネージド型のメッセージキューサービス、Amazon SQSです。DLQをサポートする使いやすいシンプルなAPIを備えています。 もう1つ使用するのがAmazon MQで、これはActiveMQとRabbitMQをサポートしています。ActiveMQやRabbitMQを使用している場合は、AWSのマネージドサービスとして利用できます。運用面は私たちが担当しますので、お客様は収益を生み出すことに集中できます。

AWS FargateとAmazon ECSによるイベント駆動型アーキテクチャの実現

Thumbnail 1030

Thumbnail 1060

次のパターンはEvent Store Streamです。 これが異なるのは、すべてのサービスが入力データを受け取る点です。すべてのConsumerがすべてのイベントを受け取り、フィルタリングはConsumer側で行う必要があります。実際のBrokerではフィルタリングできず、Consumerがデータを受け取って処理するかどうかを判断する必要があります。順序は様々なパラメータに基づいて強制されます。 このパターンには、毎秒ギガビット単位のストリーミングを提供するAmazon Kinesis Data Streamsがあります。これは非常に高速にスケールするシステムで、大量のデータを処理でき、他のAWSサービスとの統合機能も備えています。

Thumbnail 1070

Thumbnail 1140

また、完全マネージド型のApache KafkaであるAmazon MSKもあります。さまざまなパターンについて多くの情報をお伝えしましたが、ここでAWS Fargateについて説明したいと思います。この部分はUmaに引き継ぎたいと思います。 これまで説明したすべてのサービスは、分散コンポーネントやMicroservicesを接続する統合において重要です。Containerを使用してMicroservicesの構築、パッケージング、デプロイを行うことができますが、AWS Fargateは基盤となるインスタンスを気にすることなくContainerを実行する最適な方法を提供します。

Thumbnail 1150

Thumbnail 1180

Thumbnail 1200

AWS Fargateは、基盤となるインスタンスを管理することなく、Containerを主要なコンピュートユニットとして使用できるServerlessコンピュートエンジンです。必要なのは、コードを構築してパッケージ化し、CPU、メモリ、ネットワーク設定などの要件を指定するだけです。AWSがContainerの分離実行、パッチ適用、コンプライアンスを確保します。1秒単位の課金粒度で利用できます。 アプリケーションをスケジュールしたり、イベントで実行したりする一回限りのアプリケーションとして実行したい場合があります。そのような場合は、スタンドアロンタスクとして実行します。 スタンドアロンタスクとして実行する場合は、CPUとメモリの要件を指定し、Run Task APIを使用できます。タスクをプロビジョニングしてコードを実行し、その後終了します。必要なときだけ実行するため、一回限りのタスクを実行するのに非常にコスト効率の良いアプローチです。

Thumbnail 1210

Thumbnail 1220

WebサイトのホスティングやバックエンドAPIの運用、ストリームからのメッセージ処理など、 アプリケーションを24時間365日稼働させたい場合があります。そのような場合、サービスとして実行するのが最適な方法です。サービスとして実行することで、アプリケーションを常時稼働させることができます。

Thumbnail 1240

Thumbnail 1260

サービスとして実行する場合、トラフィック需要に対応するためにアプリケーションの複数のコピーを実行したいと考えます。以前と同様に、CPUとメモリの要件を指定し、コードをコンテナとしてパッケージ化し、実行したいコピーの数を指定します。Amazon ECSは常にその希望する数のコピーを維持するよう管理します。ここでのタスクは自己修復機能も備えており、タスクが停止した場合、ECSは新しいタスクを立ち上げて置き換えます。

Thumbnail 1280

Thumbnail 1290

Thumbnail 1320

ご覧の通り、AWS Fargateはビジネス価値に集中できるようにしてくれます。Fargateがイベント駆動型アーキテクチャに適している理由は、アーキテクチャを実行する際に、特定の固有の特質が観察されるからです。例えば、スケーラブルで堅牢かつ信頼性が高く、Microservicesアーキテクチャを採用し、目的に特化したサービスを実行する可能性があります。イベント駆動型アプリケーションを実行するためのコンピュートを選択する際は、これらの特性を簡単に構築できるものである必要があります。AWS Fargateは、スケーラブルなアプリケーションを構築することができ、使用できる複数の異なるスケーリング手法を提供します。スケーリングの側面については、このセッションの後半で詳しく見ていきます。

Thumbnail 1340

Thumbnail 1360

Thumbnail 1370

Microservicesはイベント駆動型アーキテクチャの基盤です。AWS Fargateでは、vCPU 0.25個とメモリ512MBという小規模な構成から始めることができ、単一目的のMicroservicesを構築し、コンテナとしてパッケージ化して頻繁にデプロイすることができます。これがイベント駆動型アーキテクチャを構築するための enabler となります。FargateはAmazon EventBridgeやAWS Step Functionsといったイベントベースのサービスとネイティブに統合され、イベント駆動型アプリケーションを簡単に構築することができます。最後に、ストリームやキューからメッセージを処理する際には、Spotコンピュートを活用することができます。メッセージは永続的に保存されるため、Spotコンピュートを使用している場合でも、疎結合なアーキテクチャを構築し、メッセージを確実に処理することができます。

AWS Step Functionsを活用したワークフロー管理

Thumbnail 1420

Thumbnail 1430

ここまでで、統合パターンとFargateがイベント駆動型アーキテクチャに適している理由について見てきました。これから、スタンドアロンタスク、長時間実行サービス、プッシュベースパターン、プルベースパターンについてのパターンを見ていきます。従来のAWS Fargate上のAmazon ECSについて考えると、それはこのように機能します。タスクがあり、サービスがあり、AWS Fargateがあり、すべてがAmazon ECS上で常時実行されています。つまり、必要かどうかに関係なく稼働しているということです。時にはアイドル状態になることもありますが、開発者はアイドル状態を気にしません。ただし、費用を支払う側は気にします - アイドル状態は望ましくないのです。

Thumbnail 1460

Thumbnail 1470

Thumbnail 1480

常時稼働するサービスが必要な場合は、これで問題ありません。でも、常に必要というわけではない場合はどうでしょうか?イベント駆動型アーキテクチャのように、イベントが発生したときだけ必要な場合はどうでしょう?そこで、サービスを取り除いて、Amazon ECSとAWS Fargateを使用するものの、FargateやECS上でサービスを実行する代わりに、Amazon EventBridgeやAWS Step Functionsから実行するようにしてみたらどうでしょうか。私が昨年これを知ったとき、とても素晴らしいアイデアだと思いました。EventBridgeやStep Functionsによってタスクを定義・構築し、それを実行させることができます。そして先ほど説明したように、タスクは処理を実行して終了します。では、スタンドアロンタスクのパターンとその仕組みを見ていきましょう。ここでいくつかクールなアニメーションをお見せしますので、しっかりご覧ください。

Thumbnail 1510

Thumbnail 1520

Thumbnail 1550

ここで何が起きているのか説明させてください。動画が入力され、これは実は昨年構築したプロジェクトに基づいています。Serverlessで動画処理を行うことができるんです。動画がバケットにドロップされると、Amazon EventBridgeにイベントが発生し、それがAWS Fargateに送られます。1つのジョブを実行して終了し、また他のジョブを継続的に実行、起動、終了することができます。

Thumbnail 1580

これがEvent-driven architectureです。まだ一般的な用語ではないかもしれませんが、私は「Events Containers」と呼んでいます。つまり、イベントに基づいて実行されるContainerですね。これは大きなオブジェクトを処理する方法の1つです。イベントベースで処理できますし、スケジュールされた処理にも適用できます。例えば、夜間に実行する必要があるサービスがあるとします。毎晩9時にこのプロセスを実行してほしい、と指定できます。Schedulerを使ってEventBridgeにイベントを送信し、それによってFargateタスクを実行します。実行が終わると消えます。AWS Lambdaのような他のエフェメラルサービスよりも、より多くの計算能力や時間を確保できる素晴らしい方法です。

Thumbnail 1610

ただし、いくつかの考慮点があります。Lambdaが適していない場合にAWS Fargateを使用してください。私たちはLambdaを非常に特定の目的のために構築しました。それは、大規模に起動し、仕事を行い、消えていくエフェメラルな計算のためです。Containerは、より長時間実行されるタスクを同じく大規模に処理するために作られました。このAPIに過度な負荷をかけるべきではありません。1000個起動して1000個終了、また1000個起動して1000個終了、というような使い方は避けるべきです。それはLambda関数の仕事です。そのような使い方をする場合は、Umaが話すように、単にサービスとしてContainerを実行すべきです。

Thumbnail 1720

タスクの失敗は個別に管理する必要があります。何か失敗した場合は、DLQを通じて確実に処理する必要があります。タスクのバースト的な実行はスケーリングの問題を引き起こす可能性があります。これは先ほど話したように、そのような使用方法を想定して設計されていないためです。急激な増減を伴うバーストは、Lambdaで対応するように設計されています。したがって、これらのどちらを使用すべきかをよく理解しておく必要があります。

Thumbnail 1730

ここからは、より技術的な内容に入っていきます。24時間365日稼働するアプリケーションのパターンについてお話しします。まずは、EventBridgeを使用してパブリックAPIやプライベートAPIにイベントを送信するプッシュベースのパターンから始めましょう。 APIは、Microservicesを構築する上での基盤となります。非同期APIは、リクエストを受け取ってすぐにレスポンスを返し、その後でタスクを実行します。例えば、顧客からの苦情があった際にタスクを作成したり、注文作成イベントの通知を配送サービスに送信したりする場合などです。

Thumbnail 1770

Thumbnail 1790

Thumbnail 1800

公開されている非同期APIや、呼び出したいパブリックAPIがある場合は、API Destinationを活用できます。 API Destinationは、EventBridgeの機能で、ZendeskやStripe、あるいはお客様独自のパブリックAPIなど、どのようなパブリックAPIにもイベント通知を送信することができます。FargateタスクインスタンスやCompute上で実行している任意のプロデューサーからイベントを送信できます。イベントを送信する際には、ルールやフィルターを適用できます。 例えば、チャンネル名が「no pineapple on pizza」で、ユーザーがアジアにいる場合のみといった条件を設定できます。 イベントがフィルター条件に一致すると、APIエンドポイントにイベントが送信されます。

Thumbnail 1810

API Destinationは、複数の設定と様々な認証オプションをサポートしています。 APIがAPIキーやBasic認証を必要とする場合、API Destinationの接続で簡単に設定できます。EventBridgeは、AWS Secrets Managerで認証情報を安全に管理し、さらにSecrets Manager APIへのアクセスが無料で付いてきます。

Thumbnail 1860

Thumbnail 1880

API Destinationの特に気に入っている点は、APIを呼び出す際にバックプレッシャーを適用できることです。システムに多すぎるイベントが押し寄せないよう、APIがリクエストを受け付けられるレートに注意を払う必要があります。 API Destinationではレート制御を設定でき、設定したレートでEventBridgeが最善を尽くして送信を行います。指定したレートでのみAPIを呼び出すことができます。障害は自然に発生するものですから、失敗した場合は最大24時間までリトライを行います。 それでも失敗が続く場合は、Dead Letter Queueを設定することができます。

Thumbnail 1890

Thumbnail 1930

Thumbnail 1940

これは日曜日からお話ししていた新機能です。今週から、EventBridgeからVPC内のAPI、つまりロードバランサーの背後にあってVPC内部からのみアクセス可能なAPIに通知を送信できるようになりました。これは、Event-Driven Architectureを構築する上で非常に重要な進展です。なぜなら、AWSとオンプレミスのEvent-Driven Applicationの間で、ドメインやアカウント、システムを横断する連携が可能になったからです。Private API Destinationの開発者体験は、パブリックAPIと同様にシンプルで一貫性のあるものに保たれています。 先ほど説明したレート制御、リトライ、Dead Letter Queue、そして様々な認証方式など、すべての機能が プライベートAPIでも利用可能です。

Thumbnail 1970

Thumbnail 1990

APIのコンシューマーとして、パブリックエンドポイントではなく、プライベートエンドポイントに接続することになります。APIのプロバイダーが、コンシューマーがどのようにアクセスするかを決定し、すべてのアクセス権を提供します。コンシューマーは同じアカウント内でも、アカウントをまたいでも構いません。 これは、VPC Resource Accessという新しいプリミティブを使用して実現されます。ここまでは、EventBridgeからイベントを送信することで、疎結合のアーキテクチャをどのように構築できるかを見てきました。次は、Amazon SQSからメッセージを処理するプル型のパターンについて見ていきましょう。 時間の都合上、今回はSQSを使用しますが、これらの機能は他のタイプのキューでもよく似ています。

Step Functions ActivityとプライベートAPI統合:疎結合アーキテクチャの構築

Thumbnail 2040

SQSを2つのサービス間で使用する場合、プロデューサーからコンシューマーへのメッセージの流れを実際にコントロールすることになります。先ほど、EventBridgeがAPIにメッセージを送信する前にレート制御を適用する話をしましたが、ここでは、レート制御はコンシューマー(AWS Fargetインスタンス)によって決定されます。タスクインスタンスが消費のペースをコントロールするのです。SQSからのメッセージ処理は簡単です - 数行のコードを書き、パッケージ化して、タスクインスタンスとしてデプロイするだけです。より多くのメッセージを処理したい場合は、タスクインスタンスを追加します。 コーヒーショップを例に考えてみましょう:1人のバリスタですべての客に対応している場合、バリスタを増やせばサービスが速くなります。同様に、タスクインスタンスを追加すると、より多くのメッセージを処理できるようになります。

Thumbnail 2060

Thumbnail 2080

メッセージを処理した後は、それらを削除します。 常に一定のメッセージが入ってくる場合、リソースを調整する必要はありません。常に2人のバリスタと4人の客がいる状況なら、バリスタを増やす必要はありません。しかし実際には、そのようなケースはまれで、朝は午後よりも客が多くなるものです。 実際のアプリケーションでは、予測不可能なパターンが見られます。この予測不可能性に対処しないと、問題が発生する可能性があります。再びコーヒーショップの例を使うと、来店客が少ない場合はリソースの無駄遣いになり、逆に客が多すぎる場合は2人のバリスタでは対応しきれず、待ち時間が増加して客が離れてしまう可能性があります。キューからメッセージを処理する場合も、この状況はとてもよく似ています。

Thumbnail 2130

この問題を解決するには、入ってくるメッセージの流れに合わせて処理能力を調整する必要があります。事前定義されたメトリクスやカスタムメトリクスを使用して、タスクインスタンスを動的にスケーリングすることができます。

Thumbnail 2140

まずは事前定義されたメトリクスから始めましょう。Amazon SQSはApproximateNumberOfMessagesVisibleというメトリクスを提供しています。 このメトリクスは、処理待ちのキュー内のメッセージ数を示します。このメトリクスを使用して、数行のコードでスケーリングポリシーを構築できます。このポリシーは、キューがアクティブな時にタスク数をスケールアウトし、アクティブでない時にスケールバックします。キュー内の待機メッセージ数に応じてタスクインスタンス数を同期させることは、とても簡単なのです。

Thumbnail 2180

Thumbnail 2190

しかし、ここで問題があります。ApproximateNumberOfMessagesVisibleだけを見ているのです。 メッセージの処理にかかる時間や許容可能な遅延については考慮していません。 先ほどのコーヒーショップの例に戻りますと、注文によって処理時間が異なります。お客様の待ち時間を考慮せずに、単に列に並んでいる人数だけを見ていると、実際の待ち時間が長くなってしまう可能性があります。

Thumbnail 2220

この問題を解決するには、カスタムメトリクスを使用します。このカスタムメトリクスは、タスクあたりのバックログで、次の2つのメトリクスを組み合わせたものです: Amazon SQSのApproximateNumberOfMessagesVisibleと実行中のタスク数です。これらのメトリクスを組み合わせるため、このメトリクスを計算または導出するにはCloudWatchメトリクス数式が必要です。そして、スケールアップやスケールダウンの基準となるターゲット、つまり許容可能な遅延を設定する必要があります。メトリクスとターゲットが揃えば、リソースのスケールアップとスケールダウンを行うためのTarget Trackingポリシーを作成できます。

Thumbnail 2270

この実装方法については素晴らしいガイドがありますが、そのリンクは最後までお待ちいただく必要があります。また、Amazon ECSにはTask Scale-in Protectionという機能があります。これを有効にすると、 スケールダウン時にタスクインスタンスが処理の途中で終了されることを防ぐことができます。ここまでで、APIやSQSを使用した疎結合アーキテクチャの構築について見てきました。結合は必ずしも悪いものではありません - 一般的に、アプリケーションの上位レベルでは疎結合を、下位レベルでは密結合を目指すべきです。

Thumbnail 2320

これから、各サービスとAmazon ECSがどのように連携できるかについて詳しく見ていきましょう。最初に見るのはAWS Step Functionsです。先ほど、イベントの振り付けとその実行について話しましたが、実行のタイミングをどのように制御すればよいのでしょうか? Step Functionsはこの課題に対する非常に優れたソリューションです。従量課金制で、フルマネージドなワークフローサービスです。昨日の朝に、この高度なパターンについての講演を行いましたが、YouTubeでご覧いただけます。

Thumbnail 2350

次のサービスは Amazon Managed Workflows for Apache Airflow(MWAA)です。社内での呼び名はMWAAです。本当はこれを言うべきではなかったかもしれませんが、この場だけの話にしておきましょう。これは基本的に、オープンソース版のApache Airflowと同じものです。今回は主にStep Functionsについて話をしていきますので、そちらに焦点を当てていきましょう。

Thumbnail 2380

Step Functionsを使ってAmazon ECSと連携する際には、いくつかのパターンを活用できます。 一つ目は非同期呼び出しを行う「Asyncパターン」と呼ばれるもので、いわゆるファイアー・アンド・フォーゲット型です。何かの処理を実行する必要があるものの、その結果を待つ必要がない場合に使用します。Step Functionsからrun taskオペレーションを呼び出してデータを送信するだけで、処理が実行されます。ただし、Amazon ECSやその他のコンピューティングリソースを使用する場合、次のステップに進む前にタスクの完了を待つ必要があることが多いです。そこで登場するのが、Syncパターンです。

Thumbnail 2430

Syncパターンでは、同じように Amazon ECSにデータを送信しますが、システムが自動的にプロセスを管理してくれます。ECSタスクの状態を監視し、タスクが完了するまで待機します。この管理作業を自分で行う必要はなく、システムが自動的に処理してくれます。タスクが完了すると、成功または失敗のステータスを受け取り、それに応じて次のステップに進むことができます。

Thumbnail 2480

これはファイアー・アンド・フォーゲット型ではなく、完了を待つタイプのアプローチです。しかし、実際の計算結果が必要な場合は、別のパターンを考える必要があります。単なる完了ステータスではなく、実際の処理結果が必要な場合によく使われるのが、トークンを使用してタスクの完了を通知する「Callbackパターン」です。 このパターンでは、トークンと共にタスクをAmazon ECSに送信し、Step Functionsは一時停止して待機します。ECSタスクが処理を実行し、コードの最後のステップでそのタスクトークンを使ってStep Functionsにコールバックする必要があります。Step Functionsサービスは、どのワークフローが実行中で何をする必要があるのかを把握しています。成功または失敗、どちらかの呼び出しを行うことができます。

Thumbnail 2530

Thumbnail 2550

Thumbnail 2580

RunTask APIを使用する場合、トラフィックが少なく安定している場合は問題ありません。 しかし、Amazon S3のようにイベントが突発的に発生するような状況では、Step Functionsがそのスケールに対応できない可能性があります。イベントごとにRunTask APIを呼び出すため、APIの制限にすぐに達してしまう可能性があります。これは、トラフィックが多い場合や予測不可能なトラフィックパターンには最適なアプローチとは言えません。キューを使用して対処することもできますが、別の解決策として「Step Functions Activity」があります。

Thumbnail 2630

資料を作成している際、このトピックが出てきて、Activityパターンについて説明するかどうか質問されました。私は、これは非常に過小評価されており、あまり知られていないサービスだと考えています。Activityは Step Functionsのリソースの一つで、ワークフローとコンシューマーの間で疎結合なアーキテクチャを構築することができます。Step FunctionsでActivityを作成すると、メッセージの送受信が可能になります。

Thumbnail 2650

Thumbnail 2690

このユースケースでは、RunTask APIを各イベントごとに呼び出す代わりに、そのイベントをActivityに送信し、メッセージが処理されるまでタスクはPass状態に移行します。イベントがActivityに送られると、そこに保存されます。Activityのもう一方の端で魅力的な処理が行われ、ECSタスクインスタンスがAmazon SQSからメッセージを処理するのと同様に、Activityからメッセージを処理します。タスクインスタンスがメッセージを受信すると、どのWorkflowのどの状態がこのメッセージを生成したかを示すタスクトークンを含むこのようなメッセージを受け取ります。そしてコンシューマーがメッセージを処理します。

Thumbnail 2720

処理が完了したら、レスポンスを返す必要があります。キューからメッセージを処理する場合は、メッセージを削除しますが、同様に、トークンと追加のメッセージがある場合はそれらと共にWorkflowにレスポンスを返し、Workflowは次のステップに進みます。Workflowはトークンを理解し、レスポンスメッセージを取得して、それに基づいて判断を行います。これは本質的に、コールバックトークンを使用したキューの仕組みと言えます。

ここで質問に答えましょう:1つのStep FunctionだけがActivityを使用できるのでしょうか?いいえ、Activityは共有リソースです。複数のActivityを作成することもできますが、同じActivityを1つまたは複数のWorkflow、あるいは1つのWorkflowの複数の実行から使用することができます。一方で、メッセージを処理する側では、タスクインスタンスを増やせば、キューからの処理と同様に、メッセージをより速く処理することができます。

Thumbnail 2850

ご覧の通り、このパターンはAmazon SQSとStep Functionsのコールバック統合を使用して実装することができます。では、なぜActivityを使用するのでしょうか?それはActivityがStep Functionsの一部であり、Amazon SQSのような別個のサービスではないからです。SQSの方がより強力で、より多くの制御と柔軟性を備えています。Activityのメッセージは最大1年間保存できます。そのため、スケールアップが全くできないオンプレミスなど、スケーリングの制限があるコンシューマーを使用していて、メッセージをActivityにより長期間保存したい場合は、保持期間が14日間のSQSよりもActivityを選択することになるでしょう。

Thumbnail 2860

Thumbnail 2880

AWSのコンテナ化環境でメッセージを処理する方法を見てきましたが、Activityからオンプレミス環境でメッセージを処理することもできます。コンシューマーがWorkflowからのメッセージの到着レートとは異なるペースでスケールできるため、疎結合なアーキテクチャを構築することができます。メッセージが保存されるため、コスト削減につながるSpotコンピュートも活用できます。

Thumbnail 2890

本日最後のパターンは新しいローンチについてです。EventBridgeと同様に、Step FunctionsでもプライベートAPIを呼び出すことができます。これは、ロードバランサーの背後にある、VPCやオンプレミス環境からのみ見えるアプリケーションのAPIのことです。パブリックAPIをStep Functionsで使用した経験がある方なら、追加のコンピュートリソースが不要なことをご存知でしょう。設定を提供するだけでAPIを呼び出すことができ、Step FunctionsはAPIの完了を待ってから次のステップに進みます。

Thumbnail 2940

パブリックAPIはEventBridge Connectionを使用してAPIを呼び出します。Connectionは複数の異なる認証をサポートしています。プライベートAPIも同様にEventBridge Connectionを使用します。このConnectionがあれば、Step FunctionsとEventBridgeの間で共有することができます。プライベートエンドポイントに対する1つのConnectionで済むのです。これはマイクロサービスのオーケストレーションを構築する上で重要な意味を持ちます。これまで私たちは主にStep FunctionsとLambdaを使用してマイクロサービスのオーケストレーションを構築してきましたが、今後はコンテナ環境やオンプレミス環境内のAPIを使用してマイクロサービスのオーケストレーションを構築できるようになります。オンプレミス環境とAWSをつなぐ、よりモダンなアプリケーションを構築することが可能になります。

ここで、まとめの時間です。私たちは疎結合アーキテクチャの構築について見てきました。オーケストレーションパターンを使用して、より低レベルのアプリケーションを構築する方法も確認しました。また、プライベートAPI統合のような同期パターンについても見てきました。そこで、Ericからイベント駆動アーキテクチャに関する最後の考察を聞いて、締めくくりとしましょう。

EDAの学習と実践:まとめと今後のステップ

Thumbnail 3010

木曜日に講演予定のDr. Werner Vogelsの言葉で、私は特にこの引用が気に入っています。彼には有名な言葉がいくつかありますが、その一つが「進化しないシステムは死ぬ」というものです。私たちの業界の現実は、進化が必要だということです。イベント駆動アーキテクチャを構築する際、これは私たちが発明したものではありません - 私が考案したと言いたいところですが、そうではありません。何年も前からある概念ですが、最近特に注目を集めています。これは、AWSや他のプロバイダーが、分散マイクロサービスアーキテクチャを構築できる多くのサービスを提供しているからです。そのため、多くの人々がEDAに飛びつき、その仕組みを理解しようとしています。

Thumbnail 3050

EDAの旅をどこから始めるべきかについてお話ししたいと思います。実は、すべては理解することから始まります。「とにかく作り始めよう」という人が多くいます - 開発者の皆さん、私にはわかっています。「できなくなってから読もう、今はコードを書こう」と考えているでしょう。私も同じです。うまくいくまでひたすらコードを書く人は何人いますか?会場に一人いますね - 指さしませんが、その方は指をさされるのが好きではないので。実は彼はCDKの作者で、私は彼が会話しながらコードを書いているのを見たことがあります。「やあEric、調子はどう?」という具合に。そして、それが動くんです!私は彼が憎らしいです。でも私たちは、動かない、動かない、動かないとコードを書き続けて、最後に動いたときには、なぜ動いているのかわからなくなっているんです。

EDAについて理解を深めることを強くお勧めします。これから紹介するリソースを活用して学んでください。EDAとその背後にある考え方について学んでください。EDAコミュニティでよく知られているDavid Boyneという方がこの件について多くの知見を持っています。もちろん、キーボードに触れるなとは言いませんが、まずは計画を立てて学ぶことが大切です。理解することが全てです。理解が深まれば深まるほど、より良いものが作れるようになり、一方通行の道を作ってしまうことを避けることができます。ですので、本当にこれをお勧めします。

Thumbnail 3140

Thumbnail 3150

約束したリソースがこちらです - s12d.com/svs339でご確認ください。少しの間表示しておきます。指で数えてみましょう。これで終わりです。靴を脱げば4まで数えられます。他のセッションもチェックしてみてください。全て水曜日です - 火曜日のものは1つ見逃したかもしれませんが、大丈夫です。録画されていますので。これらのセッションをチェックすることをお勧めします。同じトピックについて話し合い、サービスについての学習を続けてください。s12d.comのService learningをぜひ訪れてみてください。

Thumbnail 3190

以上で終わりにしたいと思います。Umaさん、一つお伝えしたいことがあります - ちょっと待ってください。お話しする機会を与えていただき、ありがとうございます。とても楽しかったです。ありがとうございました。まだそれがクールかどうかわかりませんが。どうぞ。ありがとうございます。お話の途中ですみません。本当にありがとうございました。


※ こちらの記事は Amazon Bedrock を利用することで全て自動で作成しています。
※ 生成AI記事によるインターネット汚染の懸念を踏まえ、本記事ではセッション動画を情報量をほぼ変化させずに文字と画像に変換することで、できるだけオリジナルコンテンツそのものの価値を維持しつつ、多言語でのAccessibilityやGooglabilityを高められればと考えています。

Discussion