非同期処理を使いこなそう !

- 第 3 回 AWS サービスを活用した非同期処理アーキテクチャ

2022-08-02
デベロッパーのためのクラウド活用方法

五十嵐 直人

こんにちは、プロフェッショナルサービス本部クラウドアプリケーションアーキテクトの五十嵐です。

「非同期処理を使いこなそう !」シリーズの第 3 回となる今回は、いよいよ物理アーキテクチャ、つまり AWS サービスを利用したアーキテクチャ構成を考えていきます。

これまでの連載記事では、EC サイトを例として 第 1 回 で同期処理と非同期処理の使い分けについてご説明し、第 2 回 で各処理のステップや論理構成についてご説明しました。これをベースとして、第 3 回は非同期処理を実現するための AWS サービスをご紹介し、それらを活用した非同期処理アーキテクチャについてご説明します。

みなさまは AWS を活用したアーキテクチャ (以下「アーキテクチャ」と記載) をご自身で描かれたことはありますでしょうか。もしあまりイメージがわいていなかったり、見たことはあるけどもご自身で描いたことがないという方がいらっしゃれば、本記事をお読み頂く前に builders.flash の記事「AWS のアーキテクチャ図を描きたい ! でもどうすれば良いの ?」をぜひご参照ください。アーキテクチャの具体的なイメージや必要な要素について把握いただけるかと思います。

さて、準備も整いました。ここからは非同期処理を実現するためのアーキテクチャ考えていきましょう !

この連載記事のその他の記事はこちら

選択
  • 選択
  • 第 1 回 非同期処理ってなんだろう ?
  • 第 2 回 非同期処理と同期処理の処理構造
  • 第 3 回 AWS サービスを活用した非同期処理アーキテクチャ
  • 第 4 回 非同期処理の設計上の検討ポイント

1. 非同期処理を実現する AWS サービス

まずはアーキテクチャの構成要素となる「AWS サービス」についてご紹介します。第 2 回 の連載記事では、非同期処理を実現するための手段として「キュー」と「トピック」をご説明しました。

これらを AWS で実現するためには、どのようなサービスがあるのでしょうか。

キューの処理構成
(クリックスト拡大します)

トピックの処理構成
(クリックスト拡大します)

まずはじめに、右の表で非同期の実現に利用できる AWS サービスの一覧をご紹介します。ここに示される「キュー」「ストリーム」「トピック」「イベントバス」およびそれに紐づく各 AWS サービスについて以降でご説明します。

キューでご紹介するサービスは、Amazon SQSAmazon MQ です。キューは、一時的にメッセージを格納する軽量バッファと接続エンドポイントを提供することで、メッセージの送信側と受信側の分離を可能とし、非同期化の実現に利用することができます。

Amazon SQS は、AWSが提供するフルマネージド型のメッセージキューイングサービスです。このサービスを利用することで、メッセージの送信側と受信側を分離するキューの機能を容易に実現することができます。

Amazon MQ は、オープンソースのメッセージブローカーである Apache ActiveMQ および RabbitMQ をサポートしたサービスです。Apache ActiveMQ または RabbitMQ を利用したいケースや、既にこれらのオープンソースを既存システムで利用している場合、Amazon MQ を利用することでサーバー管理の負荷を軽減しながらもこれらオープンソースと同等の機能を実現することができます。

ストリームでご紹介するサービスは、Amazon Kinesis Data StreamAmazon MSK です。ストリームは、データソースによって継続的に生成されるデータを扱うために、レコードの並べ替えや高速な読み書きをサポートするストレージレイヤーと、そのデータに対するコンピューティングを実行する処理レイヤーから構成されるものです。送信側からのデータを一時的に溜め込むことができるため、キュー同様に送信側と受信側の非同期化を実現することができます。

Amazon Kinesis Data Streams は、Amazon SQS 同様にフルマネージド型のストリーミングサービスであり、高いスケーラビリティ、データの耐久性、および耐障害性を実現するサービスです。センサデータやユーザイベントなどをリアルタイムで処理するユースケースに適しています。

Amazon MSK (Managed Streaming for Apache Kafka) は、オープンソースの Apache Kafka を利用したストリーミングデータ処理を可能にするフルマネージド型のサービスです。Apache Kafka を利用したいケースや、既にこのオープンソースを既存システムで利用している場合、Amazon MSK を利用することでサーバー管理の負荷を軽減しながらもこのオープンソースと同等の機能を実現することができます。

トピックでご紹介するサービスは、Amazon SNSAmazon MQ です。トピックは、通信チャネルとして機能する論理アクセスポイントを提供することで、送信側からのメッセージを複数の受信者に発行する pub/sub メッセージングを実現できるものです。

Amazon SNS は、AWS が提供するフルマネージド型のメッセージングサービスです。このサービスを利用することで、送信側のメッセージを受信側に届ける仕組みを容易に実現することができます。
Amazon MQ は先述のため割愛します。

最後にイベントバスでご紹介するサービスは、Amazon EventBridgeAmazon MQ です。イベントバスは、送信側からのイベントを受信するパイプラインです。イベントバスで受信されたイベントは、事前に定義されたルール条件に一致するかチェックされたのち、該当する受信者にルーティングされます。

Amazon EventBridge は、フルマネージド型のイベントバスサービスです。様々な AWS サービスから生成されたイベントをメッセージとして、メッセージを加工できたり、多様な AWS サービスや特定の SaaS に対してメッセージを送信することができます。
Amazon MQ は、先述のため割愛します。

本連載記事ではこれらの中から、EC サイトの事例に適したキュートピックを選定することとします。またこの中から利用する AWS サービスとしては、適用事例が豊富でシンプルに活用可能な Amazon SQS および Amazon SNS を選定してご紹介します。


1-1. キューを実現する Amazon SQS

ここからは、「キュー」に紐づく AWS サービスである Amazon SQS についてご紹介します。

Amazon SQS は、AWS が提供するフルマネージド型のメッセージキューイングサービスです。このサービスを利用することで、情報の送信側であるプロデューサー (= 図中のプロセス α) がメッセージを Amazon SQS に保存し、情報の受信側であるコンシューマー (= 図中のプロセス β) がそこからメッセージを取り出して処理をする機能を実現できます。Amazon SQS は、フルマネージド型のサービスであるため、利用者がキューを稼働させるためのサーバーを管理する必要はありません。また、高い耐久性・可用性・スケーラビリティといったキューに求められる要件を満たすよう設計されています。

キューの処理構成
(クリックスト拡大します)

第 1 回 の記事では、EC サイトにおける非同期処理活用の一例として、急激なリクエスト増加が発生した場合の応答性改善と処理能力改善について言及しました。これを実現するためには、キュー自体に急激なリクエスト増加を受けられるためのスケーラビリティと可用性が求められます。Amazon SQS の標準キューでは、高いスケーラビリティによりほぼ無制限のスループットを提供し、冗長化されたインフラストラクチャ構成により高い可用性を実現しているため、ご紹介した事例に適したサービスとなっています。

また、注文処理のようなユースケースでは、注文順序を保証するためにキューに格納されるメッセージの順序を保証したいケースがあります。Amazon SQS では、標準キューと FIFO キューの 2 種類が用意されており、FIFO キューを利用することで First In First Out による順序を保証することができます。

Amazon SQS に格納できる情報量は、1 メッセージあたり最大 256KB となります。仮に UTF-8 の半角英数字であれば 1 文字 1Byte であるため最大で約 25.6 万文字の情報量、日本語であれば大半が 1 文字 3 byte として最大で約 8.5 万文字の情報量をプロデューサーとコンシューマーの間で受け渡すことができます。大半のユースケースはこの情報量で事足りるかと思いますが、万が一 256KB を超えるメッセージを連携したい場合には、Amazon S3 と組み合わせた処理パターン もご検討ください。


さて、キューの処理構成を AWS サービスで表してみましょう。
ここでは説明を簡略化するため、プロデューサーとコンシューマーに利用する AWS サービスは AWS Lambda に統一した記載とします。

キューの処理構成
(クリックすると拡大します)

キューのアーキテクチャ例
(クリックすると拡大します)

通常、Amazon SQS に対してコンシューマーがメッセージを確認するためには、ポーリングの仕組みを独自に構築する必要があります。ただし、今回のアーキテクチャ例のように AWS Lambda をコンシューマーとして指定すると、Amazon SQS のメッセージを自動でポーリングするよう設定することができます。詳細は「AWS Lambda 関数 (コンソール) をトリガーするキューの設定」をご参照ください。また、コンシューマーがキューのメッセージを取得し処理が完了した後はキューのメッセージを削除する処理が必要となりますが、こちらも AWS Lambda を利用することで自動で削除してくれます。

以上により、キューを利用したアーキテクチャのパターンが完成しました。後ほどご説明する EC サイトのアーキテクチャでは、キューでこのパターンを利用してアーキテクチャを組み上げていきます。

(※) Amazon SQS についてより詳しく知りたい方は、公式ドキュメント のほか、builders.flashの記事「アプリケーション間連携を疎結合で実現。「Amazon SQS」をグラレコで解説」や、Black Beltの動画 / PDF もご参照ください。

1-2. トピックを実現する Amazon SNS

次にご紹介するのが、「トピック」に紐づく AWS サービスである Amazon SNS です。

Amazon SNS は、AWS が提供するフルマネージド型のメッセージングサービスです。このサービスを利用することで、メッセージの送信側であるパブリッシャー (= 図中のプロセス α) が Amazon SNS に対して送ったメッセージを、メッセージの受信側である複数のサブスクライバー (= 図中のプロセス β) に送信する機能を実現できます。こちらも Amazon SQS 同様にフルマネージド型のサービスであるため、トピックを稼働させるためのサーバー管理は不要となります。

トピックの処理構成
(クリックすると拡大します)

第 2 回 の記事では EC サイトにおける一例として、複数の処理を並列化することで処理時間の短縮を図り、他の処理との影響分離を実現するケースについて言及しました。Amazon SNS を用いることで、この並列化と影響分離を実現することが可能となります。

メッセージ順序の保証や格納できる情報量については、Amazon SQS と類似した仕様となっています。トピックは標準トピックと FIFO トピックの2種類が用意されており、格納できる情報量は 1 メッセージあたり最大 256KB となります。標準トピックの場合、1 秒間にほぼ上限のないメッセージ数をサポートできるため、高いスループットでパブリッシャーからのメッセージを受け取ることが可能です。


さて、トピックの処理構成を AWS サービスで表してみましょう。

下記に示すアーキテクチャでは、2 つのトピック (トピック A とトピック B) をもつ Amazon SNS を例として示しており、3 つのサブスクライバーのうち 2 つがこのトピック A をサブスクライブしています。この場合、パブリッシャーがトピック A にメッセージを発行した場合には、トピック A をサブスクライブしている 2 つのサブスクライバーにのみメッセージが発行されます。

なおここでは説明を簡略化するため、パブリッシャーとサブスクライバーに利用する AWS サービスは AWS Lambda に統一した記載とします。

トピックの処理構成
(クリックすると拡大します)

キューのアーキテクチャ例
(クリックすると拡大します)

これにより、トピックを利用したアーキテクチャのパターンも完成しました。後ほどご説明する EC サイトのアーキテクチャでは、トピックでこのパターンを利用してアーキテクチャを組み上げていきます。

(※) Amazon SNSについてより詳しく知りたい方は、公式ドキュメント のほか、Black Beltの動画 / PDF もご参照ください。


2. AWS サービスを活用した EC サイトのアーキテクチャ

ここからは 第 2 回 で示した論理構成のうち、同期処理と非同期処理、およびキューとトピックのすべてを網羅した EC サイトのケース「例 5 : キューイングをしつつ同時に並列処理もしたいケース」に対してアーキテクチャを考えていきます。

例 5 : キューイングをしつつ同時に並列処理もしたいケース
(クリックすると拡大します)

本連載記事の主題は非同期処理のため、キューとトピック以外で利用する AWS サービスはこちらの前提を置いたうえでアーキテクチャを考えていきます。また、セキュリティや運用監視などで利用する AWS サービスは省略した形での記載としています。

<本連載記事で利用する AWS サービスの前提>

ユースケース AWS サービス
エンドユーザーとの接続インタフェース Amazon API Gateway
EC サイトの業務ロジック AWS Lambda
データの永続化 Amazon DynamoDB
メール通知 Amazon SES

はじめに、「例 5 : キューイングをしつつ同時に並列処理もしたいケース」に紐づくアーキテクチャの全体像を以下に示します。この全体像を①〜⑥の各パートに細分化しながらアーキテクチャを読み解いていきましょう。

アーキテクチャ (全体像)
(クリックすると拡大します)

アーキテクチャ (全体像) の細分化
(クリックすると拡大します)

2-1. AWS サービスを活用した同期処理アーキテクチャ

まずは、同期処理の箇所についてアーキテクチャを考えてみましょう。

EC サイトの事例では、注文処理サービスから在庫管理サービスへの接続に同期処理を利用しました。この処理の流れを整理し、AWS サービスを活用したアーキテクチャとして表すと以下のようになります。

① 注文処理サービス (同期処理)

1. エンドユーザーの画面が Amazon API Gateway の API を呼び出す

2. AWS Lambda を呼び出し業務ロジックを実行する

3. AWS Lambda が在庫管理サービスを呼び出す → ②在庫管理サービス (同期処理)  に続く

4. 永続化したいデータを Amazon DynamoDB に保存する (保存処理はユースケースに合わせて適切なタイミングで実施することとし、3 と 4 の処理順序は便宜上の記載とする)

5. Amazon API Gateway が API レスポンスを返す


② 在庫管理サービス (同期処理)

3-1. 注文処理サービスからのリクエストを受け付けた Amazon API Gateway が AWS Lambdaを呼び出す

3-2. AWS Lambda が業務ロジックを実行する

3-3. 永続化したいデータを Amazon DynamoDB に保存する

3-4. AWS Lambda が注文処理サービスにレスポンスを返す

同期処理のアーキテクチャ
(クリックすると拡大します)

2-2. AWS サービスを活用した非同期処理アーキテクチャ

次に、本連載記事の主題である非同期処理について AWS サービスを活用したアーキテクチャを考えてみましょう。

EC サイトの事例では、注文処理サービスから配送処理サービス・メール通知処理サービス・請求処理サービス・ポイント計算処理サービスへの接続に非同期処理が利用されていました。この処理の流れを整理し、AWS サービスを活用して表すと以下のようになります。ここでは、トピックにメッセージを発行するまでの処理と、発行後の処理を分けて記載します。

③ 注文処理サービス (非同期処理)

1. エンドユーザーの画面が Amazon API Gateway の API を呼び出す

2. AWS Lambda を呼び出し業務ロジックを実行する

3. AWS Lambda が Amazon SNS の注文完了トピックにメッセージを配信する

4. 永続化したいデータを Amazon DynamoDB に保存する (保存処理はユースケースに合わせて適切なタイミングで実施することとし、3 と 4 の処理順序は便宜上の記載とする)

5. Amazon API Gateway が API レスポンスを返す

非同期処理のアーキテクチャ (注文処理サービス)
(クリックすると拡大します)

④ 配送処理サービス (非同期処理)

3-a-1. Amazon SNS の注文完了トピックをサブスクライブしている Amazon SQS の配送処理キューがメッセージを受信する

3-a-2. AWS Lambda が Amazon SQS からメッセージを取得し業務ロジックを実行する

3-a-3. AWS Lambda が外部システムへ情報を連携する (外部システムの API コール等を想定)

3-a-4. 永続化したいデータを Amazon DynamoDB に保存する (保存処理はユースケースに合わせて適切なタイミングで実施することとし、3-a-3 と 3-a-4 の処理順序は便宜上の記載とする)

非同期処理のアーキテクチャ (配送処理サービス)
(クリックすると拡大します)

⑤ メール通知処理サービスの流れ (非同期処理)

3-b-1. Amazon SNS の注文完了トピックをサブスクライブしている Amazon SQS のメール通知キューがメッセージを受信する

3-b-2. AWS Lambda が Amazon SQS からメッセージを取得し業務ロジックを実行する

3-b-3. AWS Lambda が Amazon SES を呼び出しメール通知を実施する

3-b-4. 永続化したいデータを Amazon DynamoDB に保存する (保存処理はユースケースに合わせて適切なタイミングで実施することとし、3-b-3 と 3-b-4 の処理順序は便宜上の記載とする)

非同期処理のアーキテクチャ (メール通知処理サービス)
(クリックすると拡大します)

⑥ 請求処理サービス / ポイント計算処理 (非同期処理)
※ 2 つのサービスは処理が類似のため同一アーキテクチャで記載する

3-c-1. Amazon SNS の注文完了トピックをサブスクライブしている Amazon SQS の請求処理キュー / ポイント計算キューがメッセージを受信する

3-c-2. AWS Lambda が Amazon SQS からメッセージを取得し業務ロジックを実行する

3-c-3. 永続化したいデータを Amazon DynamoDB に保存する

非同期処理のアーキテクチャ (請求処理サービス / ポイント計算処理サービス)
(クリックすると拡大します)

非同期で実施された処理結果は、エンドユーザーからするとすぐには不要でも、後から欲しいケースも多々あります。例えば請求処理サービスで出力された請求書や、ポイント計算処理サービスで計算されたポイントなどは、いずれもどこかのタイミングでエンドユーザーに見せられるようにしなければなりません。

これを実現するために、いくつかの方法が挙げられます。

例えば、画面から注文処理サービスの API Gateway に対して定期的にポーリングさせることで、最新の情報をプル型で取得させる方法があります。この場合、定期的なポーリングがバックエンドに対するリクエスト負荷を高める可能性もあります。もし高負荷が課題となる場合には、全ユーザー均一の定期的なポーリングではなく、ユーザーのアクションに応じて情報を取得させるように画面上へリロードボタンを用意したり、画面遷移させることで最新情報を取得させる方法もあります。

また、メール通知処理サービスにあるメール通知のように、プッシュ型でエンドユーザーに通知するといった方法があります。

もし、チャットのようにニアリアルタイム性が求められる場合には、双方向の通信プロトコルである WebSocket を利用することで実現することもできます。このように、非同期処理をアーキテクチャに組み込む際には、エンドユーザーへの結果の通知方法についてもご検討ください。

2-3. AWS サービスを活用したアーキテクチャのまとめ

本記事の冒頭でご説明した AWS サービスを利用することで、AWS サービスを活用した非同期処理アーキテクチャを実現することができました。

アーキテクチャに非同期を取り入れるメリットを改めて振り返ると、今回の EC サイトの事例では以下の点を挙げることができます。

  • エンドユーザーの待ち時間短縮
  • 注文処理サービスのスループット向上
  • 注文完了トピック以降にある後続処理のサービス数増減による影響を排除
  • 各サービスの処理特性に応じて個別にスケーリング可能

非同期処理を取り入れるメリット
(クリックすると拡大します)

第 1 回 で述べたとおり、同期処理と非同期処理は排他的な存在ではなく、組み合わせることで価値を享受することができます。今回ご説明したアーキテクチャもその一例を示しています。そしてこの一例は EC サイトに限ったものではなく、みなさまが担当されているであろう様々なユースケースにも適用することができます。

これまで第 1 回〜第 3 回でご説明した内容を深く理解するためにも、改めてみなさまが設計開発に取り組まれているユースケースに当てはめながら非同期処理 / 同期処理の検討、そしてアーキテクチャの設計に取り組んでみてください。

そして深く設計を進めていくと、ここまでの記事では書かれていなかった新たな非同期処理の課題に直面するかもしれません。非同期処理のエラーハンドリングはどのように実施すれば良いのか、キューにあるメッセージを複数のコンシューマーで重複処理してしまうことはないのか、この他にも検討すべき課題があるはずです。

最終回となる次回は、非同期処理を利用する際に考慮すべき設計ポイントについてご説明することで、これら課題に対する解決策を示します。第 1 回掲げた「アーキテクチャ設計で同期処理と非同期処理を使いこなす」という目標に向けて、最終回もぜひお付き合いください。


3. まとめ

第 3 回目となる今回は、最初に非同期処理の実現に利用できる AWS サービスを取り上げ、ECサイトの事例をもとに AWS サービスを活用した非同期処理 / 同期処理のアーキテクチャをご説明しました。

ここまでにご紹介したアーキテクチャを使いこなすためには、エラーが発生した場合のハンドリングや、重複処理への対応なども考慮しなければなりません。最終回となる第 4 回目では、非同期処理を設計する際の考慮ポイントをご説明することでこれら考慮事項に対する解決策を示したいと思います。

最終回も乞うご期待ください。それではまたお会いしましょう。

この連載記事のその他の記事はこちら

選択
  • 選択
  • 第 1 回 非同期処理ってなんだろう ?
  • 第 2 回 非同期処理と同期処理の処理構造
  • 第 3 回 AWS サービスを活用した非同期処理アーキテクチャ
  • 第 4 回 非同期処理の設計上の検討ポイント

builders.flash メールメンバーへ登録することで
AWS のベストプラクティスを毎月無料でお試しいただけます

筆者プロフィール

五十嵐 直人
アマゾン ウェブ サービス ジャパン合同会社
プロフェッショナルサービス本部 クラウドアプリケーションアーキテクト

クラウドアプリケーションアーキテクトとして、サーバーレスを中心としたアーキテクチャ設計やアプリケーション開発に取り組んでいます。技術を通してビジネス課題を解決すべく、日々活動しています。
最近は山とウイスキーが好きです。今年から雪山登山とテント泊をはじめました。

AWS のベストプラクティスを毎月無料でお試しいただけます

さらに最新記事・デベロッパー向けイベントを検索

AWS を無料でお試しいただけます

AWS 無料利用枠の詳細はこちら ≫
5 ステップでアカウント作成できます
無料サインアップ ≫
ご不明な点がおありですか?
日本担当チームへ相談する