Amazon Web Services ブログ

Amazon SNS FIFO のご紹介 – 先入れ先出しでの Pub/Sub メッセージング



分散ソフトウェアアーキテクチャを設計する場合、サービスの情報交換方法を定義することが重要になります。たとえば、非同期通信では、コンポーネントを疎結合化してスケーリングを簡素化することで、変更の影響が軽減され、新機能のリリースが簡単になります。

サービス間の非同期通信で最も一般的な形式は、メッセージキューpub/sub メッセージングの 2 つです。

  • メッセージキューでは、コンシューマーによる処理および削除まで、メッセージはキューに格納されます。AWS では、Amazon Simple Queue Service (SQS) が、管理コストなしで完全マネージド型メッセージキューイングのサービスを提供しています。
  • pub/sub メッセージングでは、トピックに発行されたメッセージは、トピックのすべてのサブスクライバーに配信されます。AWS の Amazon Simple Notification Service (SNS) は完全マネージド型の pub/sub メッセージングサービスで、多くのサブスクライバーへメッセージを配信できます。各サブスクライバーは、気になるメッセージだけを受信するようにフィルターポリシーを設定することも可能です。

複数のアプリケーションにメッセージをファンアウトする場合はトピックを使用し、1 つのアプリケーションにメッセージを送信する場合はキューを使用します。トピックとキューを一緒に使用することで、マイクロサービス分散システムサーバーレスアプリケーションを疎結合化できます。

SQS では FIFO(先入れ先出し)キューを用いてメッセージの送受信順序を保持し、メッセージが何度も処理されないようにできます。

SNS FIFO トピックスのご紹介
本日より SNS FIFO トピックを導入することで、pub/sub メッセージングにも同様の機能を追加し、複数のサブスクライバーに厳密なメッセージの順序付けと重複を排除したメッセージ配信を提供できるようになりました。

FIFO トピックは、FIFO キューと同様に順序付けと重複排除を管理します。

順序付けメッセージグループを設定するには、メッセージを FIFO トピックに発行する際にメッセージグループ ID を指定します。各メッセージグループ ID に、すべてのメッセージを到着順に送信および配信します。たとえば、同じ顧客に関連するメッセージを順番に配信するには、顧客のアカウント番号をメッセージグループ ID として使用することで、これらのメッセージをトピックに発行できます。FIFO トピックとキューを持つメッセージグループの数に、制限はありません。メッセージグループ ID を事前に宣言する必要はありません。どの値でも機能します。メッセージを論理的に区別しない場合は、すべてに同じメッセージグループ ID を使用するだけで、順序付けられたメッセージのグループを 1 つ持つことができます。メッセージグループ ID は、サブスクライブされた FIFO キューに渡されます

重複排除: 分散システム(SNS など)とクライアントアプリケーションが重複メッセージを生成することがあります。トピックから重複したメッセージ配信を回避するには、2 つの方法があります。トピックでコンテンツベースの重複排除を有効にするか、または発行するメッセージに重複排除 ID を追加するかのいずれかです。コンテンツベースのメッセージ重複排除では、SNS は SHA-256 ハッシュを使って、メッセージの本文を利用してメッセージ重複排除 ID を生成します。特定の重複排除 ID を持つメッセージが正常に発行されると、同じ重複排除 ID を持つメッセージは受け入れるが配信されない 5 分の間隔ができます。FIFO キューを FIFO トピックにサブスクライブすると、重複する ID がキューに渡され、SQS がそれを使って重複するメッセージの受信を回避します

FIFO トピックとキューを一緒に使用することで、操作やイベントの順序が重要な場合や、重複を許容できない場合において、アプリケーションの実装を簡素化できます。たとえば、財務業務や在庫の更新を処理したり、クライアントデバイスから受信するコマンドを非同期的に適用したりする場合です。 FIFO キューでは、FIFO トピックでのメッセージフィルタリング機能を使って、トピックに発行されたすべてのメッセージではなく、メッセージのサブセットのみを選択的に受信できます。

SNS FIFO トピックの使用方法
FIFO トピックが役立つ一般的なシナリオは、順番に処理する必要がある更新を受け取る場合です。たとえば、FIFO トピックを使って、顧客がアカウントプロファイルを編集するアプリケーションから更新を受け取ることができます。次に、SQS FIFO キューを FIFO トピックにサブスクライブし、このキューを Lambda 関数のトリガーとして使用します。このキューで、同期を保つ必要がある顧客管理システムが利用する Amazon DynamoDB テーブルにアカウントの更新を適用します。

FIFO トピックの導入による疎結合化で、既存のアプリケーションへの影響を最小限に抑えながら、新しい機能を簡単に追加できるようになります。たとえば、優良顧客にプロモーションを追加するには、Amazon Aurora が管理するリレーショナルデータベースに情報を格納する新たな Loyalty アプリケーションを追加します。Loyalty のデータベースに保存されている顧客情報を他のアプリケーションと同期させるには、新しい FIFO キューを同じ FIFO トピックにサブスクライブし、顧客の更新を生成したのと同じ順序でそれらを受け取る新しい Lambda 関数を追加して、Loyalty のデータベースに適用します。このように、新しい Loyalty アプリケーションを統合するために、他のアプリケーションのコードや設定を変更する必要はありません。

まず、SQS コンソールに 2 つの FIFO キューを作成し、すべてのオプションをデフォルトのままにしておきます。

  • customer.fifo キューは、顧客管理システムで更新を処理します。
  • loyalty.fifo キューは、Loyalty アプリケーションの顧客更新を収集して保存するのに役立ちます。

SNS コンソールで、updates.fifo トピックを作成します。タイプに FIFO を選択し、[コンテンツベースのメッセージの重複排除] を有効にします。

次に、customer.fifo キューと loyalty.fifo キューをトピックにサブスクライブします。

メッセージを受信できるようにするには、両方のキューのアクセスポリシーにステートメントを追加して、updates.fifo トピックにメッセージをキューに送信するアクセス許可を付与します。たとえば、customer.fifo キューの場合、ステートメントは次のようになります。

{
  "Effect": "Allow",
  "Principal": {
    "Service": "sns.amazonaws.com"
  },
  "Action": "SQS:SendMessage",
  "Resource": "arn:aws:sqs:us-east-2:123412341234:customer.fifo",
  "Condition": {
    "ArnLike": {
      "aws:SourceArn": "arn:aws:sns:us-east-2:123412341234:updates.fifo"
    }
  }
}

次に、SNS コンソールを使って 4 つのメッセージを順に発行します。すべてのメッセージに対して、同じメッセージグループ ID を使用します。このように、これらのメッセージはすべて同じメッセージグループに属します。唯一異なる部分は、順に使用するメッセージ本文です。

  • Update One
  • Update Two
  • Update Three
  • Update One

SQS コンソールで、FIFO キューには次の 3 つのメッセージしか配信されていないことがわかります。

なぜでしょうか? FIFOトピックを作成した際に、コンテンツベースの重複排除を有効にしました。この 4 つのメッセージは、5 分間の重複排除ウィンドウ内に送信されました。最後のメッセージは、最初のメッセージの複製として認識され、サブスクライブされたキューに配信されていません。

キュー内の実際のメッセージを見てみましょう。AWS コマンドラインインターフェイス (CLI) を使って SQS からメッセージを受信し、jq コマンドライン JSON プロセッサを利用して出力をフォーマットし、本文メッセージのみを取得します。

customer.fifo キュー内のメッセージは次のとおりです。

$ aws sqs receive-message --queue-url https://sqs.us-east-2.amazonaws.com/123412341234/customer.fifo --max-number-of-messages 10 | jq '.Messages[].Body | fromjson | .Message'

"Update One"
"Update Two"
"Update Three"

これらは loyalty.fifo キューにあるメッセージです。

$ aws sqs receive-message --queue-url https://sqs.us-east-2.amazonaws.com/123412341234/loyalty.fifo --max-number-of-messages 10 | jq '.Messages[].Body | fromjson | .Message'

"Update One"
"Update Two"
"Update Three"

予想通り、一意のコンテンツを持つ 3 つのメッセージは、送信されたのと同じ順序で両方のキューに配信されています。

今すぐご利用いただけます
すべての商用リージョンで SNS FIFO トピックをご利用いただけます。 FIFO トピックまたは FIFO キューごとに、最大 300 トランザクション/秒 (TPS) を処理できます。 SNS では、ご利用の分だけお支払いいただきます。詳細については、料金ページでご確認ください。

詳細については、こちらのドキュメントをご参照ください

Danilo