🎉

AWSのSQSってどの構成で作ればよいの?

2021/03/28に公開

はじめに

皆さん、Queueシステム使っていますでしょうか?
最近はクラウドでもメッセージキューのサーバーレスサービスが充実しており、自前でタスクテーブルを作って...
みたいなことをしなくても簡単にキューの仕組みを使うことができるようになりました。

  • Amazon SQS
  • Google Cloud Pub/Sub
  • Google Cloud Tasks
  • Azure Queue Storage
  • etc...

多くのサーバーレスのキューサービスがありますが、今回AWSのSQSを使う機会があり、構成を考える上で各項目について、割としっかり学ぶ機会があったのでその内容を共有しようと思います。

AWS SQSの作り方

作成方法

キューを新しく作るには大きく分けて以下の3つのやり方があると思います、

  • SDK等を利用してAPIで作成
  • AWSCLIを用いて作成
  • コンソールを用いて作成

今回はコンソールを用いた作成手順をご紹介します。

※ AWSのアカウントはすでに作成している前提でご紹介しています

コンソールを用いた作成

  1. コンソールキューを作成 を押しましょう
  2. あとは、実際に作りたい構成を選ぶだけ!!!

これだけで、立派なキューシステムの構築が完了してしまいます。
なんと便利な世の中なんでしょうか!!!

作るだけは、簡単ですが 「実際にどんな構成にすればいいんだ?」 という方がほとんどだと思いますので続いては各構成についての説明をしていければと思います。
また、説明の仕方に関しては、公式ドキュメントの説明が詳しい説明としては一番わかり易いので、かなり噛み砕いた説明となっていることを予めご了承ください

AWS SQSの各種構成について

現時点のコンソールの各項目に沿って、どんな値をセットすればよいかを解説していこうと思います。

詳細

タイプ

AWSのSQSには 標準FIFO の2種類のキューシステムが用意されており、それぞれ次のような特徴の違いがあります。

標準キュー

確実にメッセージを突っ込んだ順には処理がされないこともあるが、その分高速処理向け

どんな処理に向いているか?
  • 処理の順序が関係ない重めのアップロード処理
  • メールの大量送信処理
  • 最悪処理が2回実行されちゃってもそんなに問題ないよねみたいな処理

一方通行である必要が必ずしもない

FIFOキュー

メッセージの送信も配信も、確実に順序が保証されるキュー
メッセージを送信した順番で配信処理が実行されることが保証されているので、処理が詰まっているときは単純に時間がかかるようになってくるの標準キューとの違いです

どんな処理に向いているか?
  • ユーザーの保持ポイントの残高変更処理
  • 入力情報をもとに、決済処理を完了させる処理
  • 確実に1回の実行を担保しないと行けない処理

一方通行である必要が必ずしもある

名前

名前はよしなに付けましょう!
しかし FIFO の場合 .fifo で終わる必要があるみたいです。

設定

キューの設定を指定していきます。

可視性タイムアウト

キューシステムはタスクが完了したときにメッセージを削除します。
しかし、何かしらの原因でタスクの処理が失敗した際に、そのメッセージをキューに戻す必要があります。
大体のキューシステムだと取り出したメッセージを戻す仕組みがあるんですが、AWSSQSの場合は非同期のサーバーレスであるため明示的に戻すことができなくなっています。
そこで、AWS SQSでは一定時間メッセージが削除されなかった場合は、もとに戻すという機能が備わっており、その時間が可視性タイムアウトになります。
これが 0秒から12時間の間でセットすることができます。

何をもとに時間を決めればよいの?

可視性タイムアウトの設定時間を決めるにあたって、そのタスクの実行にかかる最長時間をセットしてあげると良いと思います。
例えば実行に10秒かかるタスクがあったとして、メッセージの取得から10秒たっても削除処理が走らない場合はタスクの実行の失敗とみなし再びキューに戻すという形になります。
通信の状況等でタスクの時間に差がある場合は「これ以上動きがなかったら失敗とみなす」という時間を決めて、バッファをもたせて設定してあげると良いと思います。

メッセージ保持期間

キューに追加されたメッセージが音沙汰がない場合、どのくらいで自動削除するのかを決める項目です。
例えば、タスクを実行するサーバーが何かしらの不具合で停止した場合等タスクが消化されていかない期間があります。
タスクの消化に失敗した場合にどのような挙動になるべきなのかを基準に決めるのが良いと思います。

何をもとに決めるとよいか?

基本的に4日位で設定をして、デットキュレーターは長めに設定するが良いと思います。

配信遅延

メッセージを追加してから、そのメッセージを取得できるまでに遅延時間を設けたい場合この値を設定します。

メッセージを追加してから設定した時間を経過したら、メッセージを取得できるようになるので数分後に処理してほしいみたいなときに値をセットすると良いと思います。

どのようなときに使うか
  • とある処理に10分かかり、その処理の結果をもとに15分後にユーザーに通知をする
  • 数分後にメールを配信したい

最大メッセージサイズ

やり取りできる最大メッセージサイズです。
これは正直256KB以下にするメリットが良く分かりませんでした。

メッセージ受信待機時間

これは、メッセージを取得しにいくときにどんくらい待つかです。
時間を長くすればするほど待ち時間が長くなります。

どんくらいに設定すればよいの?

キューシステムからメッセージを取得して、タスクを処理させるworkerがどのようなものになっているのかにもよりますが、キューを取得してタスクを実行させるworkerが 「取得できるメッセージを待てるだけ待つか」 or 「メッセージが取得できないときは次のworkerにパスさせるか」 によって決まると思います。

例えば、 メッセージをポーリングする処理が1時間に1回のバッチでメッセージを処理する場合はそれを逃すと次の処理が1時間後になってしまうので、待てるだけ待ってその処理で実行できたほうが良いみたいな感じで設定できると良いと思います。
逆に、メッセージをポーリングする処理がすでに永続的にポーリングするような仕組みになっている場合はこの時間は少なくても良いのかなと思います。

以下FIFOのみの設定項目

コンテンツに基づく重複排除

FIFOキューは重複メッセージが許容されていないので、重複メッセージは排除してあげる必要があります。
その排除するキーを重複削除IDみたいな形でセットするのですが、それをコンテンツをもとに自動で作成するかの設定項目です。

どっちが良いの?

メッセージをセットする際にそのメッセージ固有のものがある場合はコンテンツではなく自身で設定するのが良いと思います。
重複の判定を キュー側で行いたいのか or アプリケーション側で行いたい のかで決まってくると思います。
基本的にメッセージはjson文字列でユニークの値を持っていることが多いと思うので、コンテンツに基づいて作成で問題ないと思います。

しかし、重複削除の重複判定期間が5分に設定されているのでメッセージのコンテンツ内容については次のような考慮が必要です。
例えば {id:1, type:'success'} みたいなjsonデータを用いて通知機能を実装する場合は5分以内に同じ成功通知を同じユーザーに出したい場合重複判定されてしまうので2回目の処理は実行されなくなってしまいます。

高スループット FIFO を有効にする

高スループットFIFOを有効にするかどうかです
この記事を書いている段階ではプレビュー版なので使ってませんが、簡単に言うとFIFOでも高スループットを使えるけど、負荷がかかる分値段が高くなるでみたいなものです。

重複排除スコープ

重複判定して、重複メッセージを削除する場合の重複対象をキュー単位にするかメッセージグループ単位にするかの同じキューでもタスクのカテゴリーによってはそのカテゴリーが異なる場合は重複しても問題ないと判断できるものに関してはグループ単位でセットしてあげると良いと思います。
例えばメール配信にキューを利用している場合「メルマガ配信」「リマインドメール」は同じメール配信だが別のタスクとして区別することができるのでこの場合はそれぞれにグループIDをセットしておき、それをもとに重複判定を行うようにするというものです。

FIFO スループット制限

上の高スループット FIFO を有効にするをONにしたときにその対象をキューあたりにするかキューのグループ単位にするか。
同じキューでもタスクのカテゴリーによっても、負荷が変わってくると思うので、それに応じて分けるというのが良いと思います。

アクセスポリシー


アクセスポリシーです。
独自でDBとかに作るキューシステムの場合、独自のVPCネットワークに属することになると思いますが、AWS SQSの場合はサーバーレスサービスのためそうはいきません。
ある意味、作成したキュー自体はパブリックなAWSの環境にいるだけの状態になっているので、適切なアクセスポリシーを設定して適切な人がメッセージの削除とメッセージの追加ができるようにすべきです。

これの設定方法は、各プロジェクトのポリシー方針によると思いますが。

  • メッセージをセットするアプリケーション
  • メッセージを受信してそれを処理するタスクworker
  • キューの管理者

この3つを同じポリシーで管理せずに、別々に管理して適切に権限を付与するのが良いと思います。

IAMの管理で、SQS全体の権限を付与することもできますが、キューテーブルごとにアカウントを分ける必要がある場合はキューテーブルごとにIAMやロールを作成しこの画面でセットしてあげたほうが良いと思います。

暗号化


これは、保存するデータを暗号化するかどうかです。
メッセージを取得する際は、勝手に復号化されるので復号化するための鍵があるとかそういったことではないみたいです。

AWS SQSではよくあるキューテーブルみたいに実際のデータを閲覧する機能みたいなのは知る感じないので、直接中身を見てということはないんですが、そのメッセージが流出しただけで問題があるもの(個人情報等)は暗号化しておくのが良いと思います。

デットレターキュー


デットレターキューとは何かしらの原因で配信に失敗した場合にそのメッセージを別のキューテーブルに移動するものになります。

キューの選択

ここで、バックアップ先のキュールを設定してください。先にキューを作成しておく必要があります。

最大受信数

何かしらの原因で配信に失敗したらとありますが、 可視性タイムアウト のところでも設定したようにメッセージの処理に失敗したら、もとに戻す機能がAWS SQSにはあります。
この最大受信数はその戻すという処理を何回許容するかという設定値になります。

失敗した原因が必ずしも、失敗ではなく何らかの原因で、一回やれば成功するかもしれないという処理もあるので、その「3回までは再トライしてみる」という値をセットしてください。

タグ

タグは任意でセットできるので、よしなにセットしましょう。
キューのジャンルと言うで絞り込みたいとかで使えそうなのでそのキーをセットしてあげると良さそうだなと思いました。

さいごに

こんな形で、今回はAWS SQSのキューの作成の仕方を説明させていただきました。
実際に文章に書いてみると、分かりづらい点もあると思いますが、公式の説明だけだとパットしないところが多々あったので、次に新規でSQSを作る人の参考になれば幸いです。

この値段で、これだけ整ったキューシステムを使えるのはかなり魅力的なので、有効に使いたいですね。

今回は作成のところにフォーカスを当てた内容となっていますが、使う際のベストプラクティスも作っていけたら良いなと思っています。

Discussion