SESとSNSとSQS
目的
私以外にもこの3つについて明確に使い分けできる自信がない人がきっといるはず!ということで整理します。
概要
できることや用途をChatGPTに聞いてみました。
①SES
任意のメールアドレスへの大量メール送信
HTMLメールや添付ファイル付きメールの送信
ドメイン認証(SPF/DKIM)による信頼性の高いメール運用
メール受信(S3保存、Lambda連携による自動処理)
バウンス・コンプレイント(送信失敗・迷惑メール報告)の管理
APIやSMTP経由でアプリやサービスからメール送信
要するにメール送受信サービスです。
大量のクライアントに一斉にメールを送ったり、クライアントに予約完了メールを送ったりとかがよくあるユースケースですかね?
※ちなみに、SESには送信制限があり、サンドボックス環境かプロダクション環境かによって送信レートや送信クォータが変わってきます。(初期はサンドボックスで、プロダクションになるためにはAWSへ申請が必要)
環境 | 送信レート | 送信クォータ |
---|---|---|
サンドボックス | 1通/秒 | 200通/日 |
プロダクション | 最大50通/秒 | 最大50,000通/日 |
※アカウントやリージョンによって異なる。
②SNS
メッセージ(通知)を複数の宛先に同時配信(パブリッシュ/サブスクライブ方式)
メール、SMS、HTTP/HTTPSエンドポイント、Lambda、SQSなどに通知を送信
システムやアプリのイベント通知のハブとして利用
サブスクライバーごとに通知方法を選択可能
フォールバックや再送などの通知管理
SNSは通知サービスのようです。
システムやアプリのイベント通知のハブとして利用しているのをよく見かけます。
③SQS
メッセージをキューに保存し、順番に処理できる
システム間の非同期通信やジョブ管理ができる
複数のワーカーで分散処理が可能
メッセージの重複排除や可視性タイムアウトなどの制御
メッセージの遅延配信や再送管理
こちらはキューイングサービスです。
高トラフィックや大量リクエストが発生する処理を安定して処理するために使うといったイメージがあります。
本題
ざっくり、概要を見てみたところでこんな感想を抱きました。
「名前が似てるし、微妙に用途被ってそうだし、分かりづらくね??」
ということで、色々なユースケースを元に理解を深めたいと思います。
SESとSNSの使い分け
SNSはメール受信ができないものの、どちらもメールの送信が可能です。
メール送信において、状況によってどちらを使うべきか考えられるように整理したいと思います。
前提として、SESは対外向け、本格的なメール送信、SNSは内部向け、通知用途がキーワードな気がしています。
例えば、予約完了、購入完了メールなどユーザー宛に送るメールはすべてSESを使うべきです。
SNSでメールを送る場合は事前にSNSトピックにサブスクライブする必要があります。
更に、サブスクライブを完了させるには、SNSにサブスクリプション登録したあとに、そのメールアドレス所有者がメール認証をする手間が発生します。10万人サービス利用者がいたら、10万人登録処理する必要があるし、例えば一つのSNSトピックに10万人分のメールアドレスをサブスクライバーできたとしても、誰かが何かが購入すると購入完了メールが10万人に送られることになります。
SNSトピックをユーザーごとで作成して、ユーザー全員がメール認証をしてくれれば、メール送信することに関しては、SESと同等の機能を実装することができます。
これだけでも、非現実的ですが、SNSにはなく、SESのみにある機能として、HTMLメールや添付ファイルの送信、差出人や返信先の細かい指定が可能です。
SNSのメールはAWSが管理するno-reply@などのドメインで送られます。
ユーザーからすると、迷惑メールと間違われやすいし、内容もこちらで作れるものの、SESと比べて制約が多いので簡素なものにならざるを得ません。
まとめると、運用効率やユーザーの手間を考えるとSNSで不特定多数のユーザーにメールを送るのは現実的ではなく、メールの内容もユーザーエクスペリエンスを考えると良くない、ということです。
逆に社内向けのシステム通知に使う場合は、基本的にSNSを使うべきです。
というのも、社内通知において、メール通知だけで良いことはほぼないと思います。
裏で待機しているLambdaを起動して障害の一次対応をさせたり、メール通知だと通知に気づかないこともあるので、slackに障害通知を連携したりなどなど、メール以外に複数の宛先に通知を配信する必要があると思います。
メールを送ることが目的なのであれば、SES、通知を出すことが目的なのであればSNSという感じですかね。(概要の話とあまり変わってないような気がする・・。)
ちなみに、社内向けでも通知目的ではなく、単純になにかをトリガーにメールを送りたい場合は、SESのほうが料金も安いです。
SNSとSQSの使い分け
SES,SNS,SQSは組み合わせて使われることが結構多いです。
特に、SESのconfigルールの通知先として、SNSにするのかSQSにするのかといった問題があると思います。
-SESのconfigルールとは
受信メールの自動処理(保存・通知・連携)を柔軟に設定できる仕組み。
SESはメール受信時の自動連携先としては、S3、SNS、SQS、Lambdaがありますが、今回はSNSとSQSに絞って整理します。
-SNSを連携先にするパターン
①複数の通知先に同時配信したい場合
②リアルタイム性やイベント駆動型アーキテクチャにしたい場合
-SQSを連携先にするパターン
①非同期処理や分散処理をしたい場合
②通知先が一つだけのとき
③高負荷時でも安定して処理したい場合
後続処理の特性を元に決めることになるなと思いました。
通知先が一つか複数か、処理が重いのか、リアルタイム性を重視するのかを考えれば、最適な構成を選べそうです。
ややこしいことに、SES→SNS→アプリケーションのパターンと、SES→SNS→SQS→アプリケーションのパターンもあります。
この使い分けに関しては、SESの通知先が複数あり、その中で重い処理があるケースや高負荷時でも安定して処理できる必要がある処理が含まれている場合に、そのアプリの前段にSQSを置くことになります。
後続がLambdaの場合
SESとSNS両方で連携できるAWSサービスはLambdaとSQSです。
SQSのパターンは既に述べているのでLambdaパターンについて考えたいと思います。
-SES→Lambdaのパターン
受信メールを即座にLambdaで処理したい場合
シンプルでリアルタイム性が高い(SNS挟んでもほぼリアルタイムだがより早い)
受信メールの内容によって処理を分岐させたい場合
-SES→SNS→Lambda
受信メール通知を複数の通知先に配信する必要がある場合
拡張性・柔軟性が必要な場合
※SESは一つの受信ルールで複数サービスと連携させることが可能です。なので、今後連携予定のサービスが増える予定がない(拡張性が不要)の場合は、SNSはいらないということになります。(殆どの場合、リアルタイム性が重視されないケースでは、念の為間に挟むことになると思いますが、、)
基本的には通知先が複数なのか、厳密なリアルタイム性が求められているのかを確認するのが良さそうです。
また、SESはメール解析機能があるので、メールの内容によって後続処理を変えさせることができるようですが、SNSにはメールが届いたという情報しか流せないというのも盲点でした。
まとめ
振り返ると、冒頭に書いていたSES=メール送受信サービス、SNS=通知サービス、SQS=キューイングサービスでしかなかったですが、私の中ではより深いレベルで整理できました。
①メール送信機能を実装するに当たってのサービス選定基準
送信先はクライアントでメールの内容自体が重要→SES。
送信先が社内向けor後続処理のトリガーとして使いたい場合→SNS。
②SES連携先としてSNSとSQSの選定基準
後続処理が重いor非同期処理が必要or安定稼働が必要→SQS。
複数サービスと連携させたい→SNS(各連携先の処理でSQSがSNS、アプリ間に必要かどうかは都度検討)
③SESの後続がLambdaの場合のサービス選定基準
リアルタイム性が重要orメール内容によって処理を分岐させたい→SNSを挟まず、直接Lambda連携
複数の連携先が存在→SNS
※明示的に記述していませんが、SES→LambdaやSES→SNS→Lambdaのパターンには、Lambdaの前にSQSが来ることもあります。ここは②の基準を応用すれば大丈夫かと思います。
ちなみに、SES→SQS→Lambdaの場合は、当然ですがリアルタイム性が落ちます。必要なリアルタイム性と処理の重さを見て検討する形だと思います。
基本的に、通知先が複数あるなら、SNSを挟むことになります。また、各々の処理で重いものや非同期処理にするべきものがあればSQSを挟みます。
SNSを挟んでしまうと、メール内容による分岐ができなくなってしまうことに注意が必要です。
PS
①SESの通知先が複数あるものの、受信内容で処理を分岐させたい。
SES→SNS→Lambda→(SQS,SNS,各アプリケーション)
②リアルタイム性を重視したいが、耐障害性も担保したい。
SES→Lambdaに連携させつつ、SES受信メールをS3にも保存。S3に保存したメールとLambdaの処理済みメールIDを定期的に突き合わせするような監視が必要。
※Lambda自体の失敗はCloudWatchAlarmやDLQで拾えるが、高負荷時はSES→Lambdaの連携が失敗する可能性もあり、そこのエラーはCWAやDLQでは拾えない。(そもそもそんなに高負荷になりえるならLambdaではなく、ECS使ったほうが良さそう)
Discussion