ちょっと話題の記事

【AWS】SQSキューの前には難しいこと考えずにSNSトピックを挟むと良いよ、という話

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

よく訓練されたアップル信者、都元です。SQSはみなさん使われていますでしょうか。複数のコンポーネント間の疎結合を保ち、バッチ処理等の冗長性・拡張性を確保するために必要不可欠なサービスです。

SQSの活用イメージにつきましては、AWSでジョブWorkerを構成するベストプラクティスのSQSの巻Beanstalk worker tierの巻をご覧いただくと良いと思います。

さて。SQSを使うぞ、ということになった場合。メッセージを投げる側(=プロデューサ)と、メッセージを受け取る側(=コンシューマ)が必要です。どこかから持ってくる(実装済みの既成品を探してくる)か、もしくは自分自身で実装するわけです。

もちろん、プロデューサはSQSのインターフェイス(API)を理解し(依存し)ていなければなりません。要するに、キューにメッセージを投入する方法を知っており、それを使ってメッセージを投げるような実装になっていなければなりません。同じように、コンシューマもSQSのインターフェイス(API)を理解し(依存し)ていなければなりません。要するに、キューにからメッセージを取得する方法に沿って処理を実装しなければなりません *1

で。構成として「プロデューサ → SQS queue → コンシューマ」というのがシンプルで直球の実装であることには同意します。ですが本稿タイトルで主張しているのは「プロデューサ → SNS topic → SQS queue → コンシューマ」という形が良いよ、ということです。

えー、なんでそんなことを…。

ですよね。とりあえずこうすることによるデメリットを考えてみましょう。

  • SNS topicの構築(SQSとの連携設定等)の手間が増える
  • コンポーネントが増え、複雑性が増すため、トラブルの原因が増える
  • SNSの課金が余計に掛かる

まぁ、こういったデメリットは確かにあります。他にもあるかもしれません。思いついた方がいましたら教えて下さい。SQSのみを利用する構成からこの構成に移行する場合、プロデューサ側の改修が必要となるでしょう。ただ、依存が増えるわけではなく、SQSへの依存がSNSへの依存に変わるだけです。メッセージの送り方がSNS topicへのメッセージ投入方法に変わるだけです。

個人的な感覚に過ぎませんが、大して重大なデメリットは無いと思っています。手間に関しては私は慣れてますし(ぇ)、トラブルの経験もないですし、SNSの課金はむしろ安すぎてビックリですし。

一方、この構成のメリット

を考えてみましょう。

より抽象的

SNSにメッセージを送るプロデューサは、プロデューサのコードを改修することなく、送り先をSQS queue以外に変更できます。例えば「メッセージをメールとしてどこかに配信する」「Webサーバに対してHTTP POSTを投げる」等への変更が可能です。

一方、SQSにメッセージを投げるプロデューサは、改修を避けることができません。意地でも改修を避けるのであれば、queueからメッセージを受け取ってメールを送信するコンシューマを追加実装するハメになります。

というわけで、SQSに直接メッセージを投げるより、ひとまずSNSにメッセージを投げる実装のほうが抽象的で、高い拡張性を持つことが分かります。

ドレーニングポイント

プロデューサとコンシューマが両者とも(ある程度)健全に動いている時、queueを通過するメッセージを観察するのは困難です。プロデューサにより投入されたメッセージは、瞬時にコンシューマに受信され、メッセージはinvisibleとなります。この瞬間を突いてメッセージを見ることは困難を極めることでしょう。

invisibleの状態のメッセージは、外部から観察することができませんが、SNSをはさんで置くことにより、SQSにメッセージを送りつつ、同時に自分のメールアドレスにメッセージを送らせる等の方法により、キューに入ったメッセージを観察することができます。

拡張ポイント

初期に設計をした時点では、メッセージはキューに入れば万事OKだったかもしれません。仮に「キューに入れつつ、かつ、HTTPサーバにPOSTもしてほしい」とか「複数のキューに同じメッセージを入れたい」となった場合。これもSQSに直接メッセージを投入する場合、プロデューサの改修を避けることができません。

ご想像の通り、SNSをはさんで置けば、SNSのsubscriptionを追加するだけで対応が完了します。

まとめ

というわけで、主にプロデューサ側の安定性を高める効果があるため、SQSを使う場合は手前にSNSを置いておくと良いと思っています。まぁ一部YAGNIに反する考え方ではありますが、それを理解した上で、お勧めです。

脚注

  1. Beanstalk worker tier内で動いているaws-sqsdを利用する前提であれば、コンシューマ側はHTTP POSTを受け取れれば良いので、SQSに依存する必要はありませんが。が、これは単にアダプタ(ラッパー)を噛ましただけですね。