[アップデート] Amazon SNS で新しく使えるようになったアーカイブ&リプレイ機能を検証してみた

[アップデート] Amazon SNS で新しく使えるようになったアーカイブ&リプレイ機能を検証してみた

Clock Icon2023.11.01

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

いわさです。

先日 Amazon SNS がアップデートされ、メッセージのアーカイブとリプレイという新しい機能が使えるようになりました。

上記アップデートアナウンスでは、障害シナリオからの回復などがユースケースとして挙げられているのですが、おそらくこちらを流し読みしただけだと何が出来てどういう使い方が出来るのかイメージしにくいのではないでしょうか。

実際に SNS トピックを作成し、アーカイブの設定とリプレイの動作をさせてみるとイメージがつきやすいです。
今回はこちらの検証の様子などを紹介したいと思います。

FIFO トピックのオプションで「アーカイブポリシー」が設定が出来る

まず、今回のアップデートでは SNS トピックに「アーカイブポリシー」を設定出来るようになりました。
実際の動作は後ほど確認しますが、このアーカイブポリシーを設定することでメッセージをアーカイブ領域に保存することが出来ます。
メッセージのアーカイブ保存を有効化することで、特定期間のメッセージを何度でも再送することが出来ます。

アーカイブポリシーは次のように作成時に設定することが出来ます。

デフォルトでは上記のように無効化されていて、有効化の際にはメッセージを保持する期間を日数で指定します。
指定可能な日数は最短で 1 日、最長で 365 日となります。
後述しますが、アーカイブ機能は追加料金が発生します。このメッセージの保存期間によって料金が変動します。

トピックのアーカイブポリシータブから設定中のポリシーを確認することが出来ます。
また、既存トピックの編集画面からアーカイブポリシーの変更や有効化・無効化を切り替えを行うことも出来ます。
一点注意点としては、アーカイブポリシーを無効化すると、アーカイブ領域に保存されていたメッセージが削除されますのでご注意ください。

なお、本日時点で本機能は FIFO トピックでのみ使用することが出来ます。
スタンダードトピックの場合は次のように設定エリアが表示されません。

アーカイブ設定されている場合、サブスクリプションに対して「リプレイ」が出来る

トピックに対して何日メッセージを保存しておくかというアーカイブポリシーを設定することが出来ました。
実際にこの保存されたメッセージを使う際には「リプレイ」(再生)という操作が必要になります。

このリプレイ操作は対象トピックをサブスクライブしているサブスクリプションに対して操作します。
つまり、あるトピックに対して複数のサブスクリプションが関連づいている場合、どのサブスクリプションに対してリプレイ、つまりアーカイブされたメッセージを再送するかを選択して使うことになります。

実際にリプレイ操作の流れを確認してみましょう。
前提としてアーカイブポリシーを設定したトピックは FIFO トピックになりますので、SQS キューがサブスクライバーとして選択出来ます。
その SQS キューをトリガーに Lambda 関数でメッセージを受信し、CloudWatch Logs あたりでメッセージの送信状況を確認してみようと思います。

Lambda の関数コードは SQS メッセージを処理するためのブループリントが用意されていますのでそちらをそのまま使っています。

console.log('Loading function');

export const handler = async (event) => {
    //console.log('Received event:', JSON.stringify(event, null, 2));
    for (const { messageId, body } of event.Records) {
        console.log('SQS message %s: %j', messageId, body);
    }
    return `Successfully processed ${event.Records.length} messages.`;
};

なお、SNS コンソールでサブスクリプションを作成する際に「サブスクリプション作成後にメッセージをリプレイ」という設定値が新しく追加されています。

まず、メッセージのリプレイはワンショットの操作であり、アーカイブポリシーと違って恒久的な設定ではありません。
このサブスクリプション作成時のリプレイは、サブスクリプション作成直後にリプレイを開始しますよ。という設定です。
メッセージのリプレイはいつでも実施することが出来るので、ここで特に設定せずに作成後にリプレイ操作を行うでも問題ありません。

ここでは設定せずにサブスクリプションを作成して、トピックにメッセージを発行してみましょう。

Lambda のログを確認してみると、SNS で発行したメッセージが出力されています。
SNS トピックへ発行したメッセージが、SQS キューを経由して Lambda 関数まで伝わっていることが確認出来ます。

自動でアーカイブ保存されているのでリプレイ期間を指定して実行

通常どおりメッセージを送信したわけですが、対象トピックはアーカイブポリシーが設定されているので先程のメッセージは既に保存されています。
続いてリプレイを試してみましょう。

サブスクリプションの属性値に「リプレイステータス」というものが追加されています。
また、右上には「リプレイ」メニューが追加されており、リプレイの開始と停止を操作することが出来ます。
トピックごとではなくて、サブスクリプションごとにリプレイ操作を行える点がポイントです。

リプレイ操作時には期間を指定します。
開始日と時刻は必須で、アーカイブ開始時刻よりも過去日を指定することは出来ません。

アーカイブ時間よりも過去時刻を指定しました。リプレイ期間エラーの場合次のような表示となります。

リプレイが開始されるとアーカイブされているメッセージのうち対象期間のものが再送されます。
Lambda のログを確認してみます。

先程と同じメッセージ ID のメッセージが Lambda 関数で最初処理されていることが確認出来ますね。
二重実行にならないように気をつける必要がありますが、同一の情報で送信されるので、処理に失敗していたものを手動でリトライしたり、一時的にサブスクリプションより先がメンテナンス状態だった場合にも処理をさせることができます。

なおリプレイの回数に限りはありません。
アーカイブが残っている限りは何度でもリプレイすることが出来ました。

リプレイの料金については発生しませんが、通常のサブスクリプションの実行料金(ここでは SQS や Lambda)の料金が発生します。

別のサブスクリプションに切り替えてリプレイしてみる

ユースケースとして DR が挙げられていますが、例えば A リージョンで構成していたシステムで障害が発生し、B リージョンに切り替えるようなシチュエーションを想定した検証を試してみたいと思います。

下記構成図ではリージョンまで記載していませんが、SNS の統合先を SQS1 から SQS2 に切り替えてみます。
その間の SNS のメッセージが処理されませんが、再統合したのちにリプレイ機能で SQS2 に送信する形です。
上記構成図は割愛していますが、SQS の先には先程と同様に Lambda 関数が存在しています。

トピックに新しいサブスクリプションを関連付けします。 その際に、先程は無視していた「サブスクリプション作成後にメッセージをリプレイ」オプションを使ってみましょう。

サブスクリプション作成後、リプレイステータスが実行中となっており、少し待つと完了となりました。

ログを確認してみると、アーカイブされていて対象期間のメッセージが新しいサブスクリプションで処理し直されていることがわかります。

利用料金

アーカイブ機能は追加料金が発生します。

本日時点の東京リージョンでは次のような 2 段階の料金構成となっています。

  • Archive processing is $0.13 per GB of stored payload data.
  • In-place storage of payload data is $0.025 per GB-Month

まず、メッセージがアーカイブされるタイミングで処理データ量に応じた料金が発生します。
加えてアーカイブ期間に応じてアーカイブ用ストレージの利用料金が発生します。

さいごに

本日は Amazon SNS のアーカイブ&リプレイ機能を検証してみました。

SNS メッセージの自動バックアップ&リストアという感じでしょうか。
通常の異常検知や自動処理については引き続きデッドレターキューを使う形とし、問題が発生したときの復旧に備えてアーカイブ機能を有効化しておくような使い方でしょうかね。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.