クラウド メッセージング/キュー比較解説まとめ

  • このエントリーをはてなブックマークに追加

最終更新

本ページでは、Amazon・Microsoft・Google の提供するメッセージング・キューサービスの機能・料金等について比較します。具体的には下記サービスを対象とします。

  • Amazon Simple Queue Service (SQS)
  • Amazon Simple Notification Service (SNS)
  • Amazon MQ
  • Azure Queue Storage
  • Azure Service Bus
  • Google Cloud Pub/Sub
  • Google Cloud Tasks (GAE Task Queue)

※Amazon Kinesis・Azure Event Hub・Azure Event Grid を含めていないですが、そのうち追加したいと思っています。

目次

メッセージング・キューサービスの使い所

メッセージング・キューサービスは、使っていない人にとっては必要性がわかりづらい概念だと思います。まずはどこで使うのか、何がうれしいのかを説明します。

端的に言うと「あるプログラムがキューにメッセージを送信し、それを別のプログラムで受信することができるもの」です。 プログラム視点で言うと、「処理Aの後に処理Bを実行する」という場合に、間にメッセージング・キューサービスを挟むわけです。

典型的な使い所としては、処理A の後に処理B が動くという前提で、「処理A と処理B のつながりを疎結合にしたい場合」に使用します。

具体的には下記のようなケースです。

  • 処理A と 処理B が別サーバで行われるため、疎結合にならざるをえない場合
  • 仕様変更やトラブル時のリカバリ等で、処理B だけを実行したいことがある場合
  • 処理B が異常終了した場合のリトライを自動的に行わせるため
  • 処理B があるサーバが障害やメンテでダウンしていても、復旧次第処理を行わせるため
  • 処理B の時間がかかるため、終了を待てない場合 (処理A が Web アプリ、処理B が実行に10分かかるバッチなど)
  • 処理B を並列実行してスケールするようにしたい場合
  • 処理B はスケールしてほしいが、多重度が増えすぎないようコントロールしたい場合
  • 処理A の個数が多すぎるために、処理B でまとめて処理したいの場合

さらに具体的な事例は下記です。

  • 画像をアップロードすると、画像種類別 (gif, png, WebP など) × サイズ別のサムネイル画像を生成する。
  • 注文受付後、PDF ファイルを生成する
  • ある処理後に、お知らせとしてメールや PUSH 通知を送信する
  • ランキング情報や統計情報の更新など、長時間かかる情報更新
  • サービス退会後の、会員情報・購入情報・履歴のマスキングや削除
  • SNS で「いいね」を押すと、投稿者に通知する。

分類

キュー・メッセージングについて、下記の分類があります。

  • PTP (Peer To Peer) モデル または キューモデルPTP モデルは、1本のキューがあり、送信側と受信側が 1対1 の形になっているものです。
  • Pub/Sub (パブ・サブ) モデルPub/Sub モデルは、Publish/Subscribe のことで、 送信側と受信側のレイヤがわかれており、1対1 もできますし、1対多 にすることもできます。 「出版-購読型モデル」と言うこともあるようです。

さらに別の切り口として、PULL・PUSH があります。

  • PULL受信側が、新しいメッセージを取りに来るタイプ。 例えば1秒に1回とか、1分に1回などの頻度でメッセージを取りに来るので、その分のタイムラグが発生します。
  • PUSH新しいメッセージがあると (比較的) すぐに受信側に送りつけるタイプです。

例えば Amazon SQS は、PTP モデルであり、PULL のみです。 Google Pub/Sub は、Pub/Sub モデルであり、PULL と PUSH 両方が可能です。

疑似コマンドで説明 – PTP モデル編

わかりにくいと思いますので、メッセージ・キューに関する作業を擬似コマンドで示します (create-queue というコマンドは実際は存在しません)。

まずは PTP モデルから。キュー myqueue を作成します。

% create-queue myqueue 

キューに対し、メッセージを送信します。下記例では JSON フォーマットで送信していますが、 お互いの合意があれば CSV でもなんでも OK です。

% send-message myqueue '{"hoge":"fuga", "num":1}' 

get-message コマンドでキューからメッセージを取得します。さきほど送信したメッセージが取得できました。

% get-message myqueye
ID: 12345 {"hoge":"fuga", "num":1} 

言ってみればこれだけです。Amazon SQS や Azure Queue Storage はこんな感じです。 さらに続けます。

再度メッセージを取得すると以下のようにメッセージがないと言われます。 さきほどキューから取得したからですね。

% get-message myqueye
No message 

しかしながら数分待ってもう一度メッセージ取得をすると、さきほど取得したメッセージを再度取得してしまいます。

% get-message myqueye
ID: 12345 {"hoge":"fuga", "num":1} 

これはどういうことかというと、一度受信したメッセージは削除しないとキューに残り続けるのです。 取得したメッセージは一旦見えなくなり、数分待つと再度見えるようになります。 下記のようにメッセージを削除してしまうと、二度と見えなくなります。

% delete-message myqueye --id=12345
ID: 12345 was deleted. 

わざわざ削除しなければいけないなんてめんどくさいと思うかもしれませんが、 これがあることで、「後続処理が途中でエラーとなった場合でも一定時間後に再実行される」 とすることができるのです。

疑似コマンドで説明 – Pub/Sub モデル編

次は Pub/Sub モデルについて疑似コマンドで説明します。 下記は、「トピック」として mytopic を作成し、mytopic に届いたメッセージを取得するための 「サブスクリプション」として mysubscription を作成します。

% create-topic mytopic
% create-subscription mysubscription --from-mytopic 

send-message コマンドで、トピックに対してメッセージを送信します。

% send-message mytopic '{"hoge":"fuga", "num":1}' 

get-message コマンドでサブスクリプションからメッセージを取得します。

% get-message mysubscription
ID: 12345 {"hoge":"fuga", "num":1} 

できることは、PTP モデルと同じです。メッセージを送って受信するだけです。

では、せっかくの Pub/Sub モデルなので、1対多のメッセージ送信をやってみましょう。 注文をしたときにメッセージを投げる「トピック」と、 そのトピックからメッセージを受信できる「サブスクリプション」を 2つ作成します。 1つのトピックから、2つのサブスクリプションに同じデータが流れるようにします。

% create-topic order-topic
% create-subscription order-shipment-subscription \
     --from-topic=order-topic
% create-subscription order-email-subscription \
     --from-topic=order-topic 

トピックに対し、メッセージを送信します。 注文処理なので「この customer が、この item を、何個買った」という情報です。

% send-message order-topic '{"customerId":88888, "itemId": 99999, "itemNum": 3}' 

メール送信バッチは、注文受付メールを即時に送信します。

% get-message order-email-subscription
ID: 22222, {"customerId":88888, "itemId": 99999, "itemNum": 3} 

一方、出荷処理バッチは 1日数回動き、order-shipment からメッセージを取得し、 出荷処理を行います。

% get-message order-shipment-subscription
ID: 22222, {"customerId":88888, "itemId": 99999, "itemNum": 3} 

このように、1対多の関係を作っておくと、 メール送信と出荷処理に一切の関係性がなくなり、疎結合が実現できるということです。 Amazon SNS や Google Pub/Sub は、このように「トピック」「サブスクリプション」という二段構えになっており、 一対多関係を実現できます。

上記の説明は、いずれも「get-message コマンドを叩くとはじめてメッセージ取りに行く」ものなので、 PULL 型です。PULL しないとずっとメッセージは残ります。

PUSH 型の例も示しておきます。メッセージを投げると (ほぼ) 即時で実行されるというものです。 疑似コマンドで書くと下記のような感じです。

% create-subscription order-email-subscription \
   --from-topic=order-topic \
   --to-url='https://foo.bar/api/email' 

上記により、order-topic にメッセージが届くと (ほぼ) 即時で登録した URL を叩きます。この URL が 200 OK を返さない場合は失敗とみなし、 一定時間待ってリトライします。URL 以外にも、別のトピックに投げたり、 AWS Lambda や Azure Functions のようなサーバレスの関数型サービスを呼び出したりもできます。

各サービス紹介

概念を抑えたところで、各クラウドサービスにおけるキュー・メッセージングサービス概要を説明します。

  • Amazon Simple Queue Service (SQS) … PTP モデル。PULL のみ (PUSH なし)。 2004年サービスイン。Simple というだけあって、1対1のキュータイプのみで、1対多はできない。2016年に順序性を維持する FIFO キューが追加された。
  • Amazon Simple Notification Service (SNS) … Pub/Sub モデル。PUSH のみ (PULL なし)。 本来は SMS・プッシュ通知・http/https・メール・Lambda 等への汎用通知サービスであるが、 SNS から SQS につなげることができる。さらに、SNS 自体は Pub/Sub モデルなので 1対多の設定ができるので、SNS → SQS とすることで、1対多の Pub/Sub が実現できる。
  • Amazon MQ … 2017年11月サービスイン。 Apache ActiveMQ というオープンソースのメッセージングサーバを、 AWS によりフルマネージドサービスとして提供しているもの。 多分、とっても高機能。現在オンプレミスで ActiveMQ を使っている場合、Amazon MQ を移行対象として検討してみるとよいでしょう。
  • Azure Queue Storage … Azure Storage 上のキューサービス。 PTP モデル。PULL のみ (PUSH なし)。
  • Azure Service Bus … Azure 上のより高機能と思われるメッセージングサービス。 Pub/Sub モデル。PULL・PUSH 可能。
  • Google Cloud Pub/Sub … bGCP でのメッセージングと言えば基本これ。 Pub/Sub モデル。PULL・PUSH 可能。
  • Google Cloud Tasks … GAE 内のサービスである「Task Queue」を、GAE 以外でも利用できるようにしたもの。 Google Cloud Pub/Sub リリース当初は、Task Queue をなくして Pub/Sub に一本化する予定だったそうだが、 Pub/Sub では吸収しきれない要望がたくさんあったため、存続決定とのこと。

結局どれを使えばよいのかについて、AWS であれば、「オンプレで Active MQ を使っている」なら Amazon MQ を、それ以外であれば Amazon SQS+SNS を選択すればよいでしょう。

Azure であれば、Azure Queue Storage よりも高機能な Service Bus がよいと思います。

GCP であれば、大量データでない場合はまずは Cloud Tasks (Task Queue) を検討し、不十分な場合は Cloud Pub/Sub を使うべきでしょう。

メッセージング・キュー比較表

機能比較表をまとめてみました。 詳細は後述。

この場所には ↓ にある表が自動的にしゅっとまとめられるはずですが、この文章が見えているということは Javascript がうまく動いていないということなので、その場合は教えてもらえるとありがたいです。

比較表はここまでです。以下詳細説明をします。

モデル・PULL・PUSH・PEEK について

「モデル」について

Amazon SQS+SNSAmazon MQAzure Queue StorageAzure Service BusGoogle Cloud Pub/SubGoogle Cloud Tasks
モデルPTP (SQS), Pub/Sub (SNS)PTP, Pub/Sub 両方PTPPub/SubPub/SubPTP

「PULL・PUSH」について

Amazon SQS+SNSAmazon MQAzure Queue StorageAzure Service BusGoogle Cloud Pub/SubGoogle Cloud Tasks
PULL○ (SQS のみ)
PUSH◯ (SNS のみ)?××

「PEEK」について

Amazon SQS+SNSAmazon MQAzure Queue StorageAzure Service BusGoogle Cloud Pub/SubGoogle Cloud Tasks
PEEK×○?××

運用時、PULL はしないまでも中身をチラと見てみたいことがあります。そのような場合に PEEK できるサービスもあります (peek はちらっと見る、そっと覗くという意味の英単語)。

「基本機能」詳細説明

「順序保証」について

Amazon SQS+SNSAmazon MQAzure Queue StorageAzure Service BusGoogle Cloud Pub/SubGoogle Cloud Tasks
順序保証 標準キューは×、FIFOキューは○ ×××

順序保証とは、「先に送信された古いメッセージを先にください」ということです。ある意味当然とも思える機能ではありますが、これを実現するのはなかなか難しい。クラウドサービスにおいては可用性・性能確保のために複数のインスタンスがあるため、一般的には順序を維持するためには性能が犠牲となります。

Amazon SQS の FIFOキュー・Amazon MQ・Azure Service Bus が順序保証をサポートしています。その他は順序保証がありません。順序保証がないとは、「たまに順序がおかしくなって新しいものから先に受信してしまうがおおむね古いものから順に取得する」ではなく「ランダムな順序で受信してしまう」と考えておいたほうがよいでしょう。

「重複受信排除」について

Amazon SQS+SNSAmazon MQAzure Queue StorageAzure Service BusGoogle Cloud Pub/Sub Google Cloud Tasks
重複受信排除
標準キューは×。FIFOキューは◯ (最大5分間)
○ (最大N個分) × ○ (30秒~7日間)××

一般的には、メッセージは重複する可能性があります。よってメッセージ受信側は冪等性をもたせることで同じメッセージを複数回受信してしまっても処理が破綻しないようにすべきです。

しかしながら、自動で重複メッセージを排除してほしいときもある。それができるのは Amazon SQS (FIFO キュー)、

「デッドレター・有害メッセージ」について

Amazon SQS+SNSAmazon MQAzure Queue StorageAzure Service BusGoogle Cloud Pub/Sub Google Cloud Tasks
デッドレター・有害メッセージ ×

メッセージを受信して後続処理を行うとき、後続処理がエラーとなったらどうするか。再実行されるのですが、5回や10回再実行しても失敗し続けた場合、いさぎよくあきらめてほしい場合があります。

そのようなとき、処理できなかったメッセージをデッドレターや有害メッセージと呼びます。

「遅延送信」について

Amazon SQS+SNSAmazon MQAzure Queue StorageAzure Service BusGoogle Cloud Pub/SubGoogle Cloud Tasks
遅延送信 (メッセージ単位) 最大15分 ◯ ?
Amazon SQS+SNSAmazon MQAzure Queue StorageAzure Service BusGoogle Cloud Pub/Sub Google Cloud Tasks
遅延送信 (キュー単位) 最大15分 ×

「優先度指定」について

Amazon SQS+SNSAmazon MQAzure Queue StorageAzure Service BusGoogle Cloud Pub/SubGoogle Cloud Tasks
優先度指定 ××?×?

「一括送信」について

Amazon SQS+SNSAmazon MQAzure Queue StorageAzure Service BusGoogle Cloud Pub/SubGoogle Cloud Tasks
一括送信 10メッセージまで ×○ (上限100メッセージまで) ○ (上限10MB?) ?

1つのメッセージを10回送信するより、10個のメッセージをまとめて一度に送信する方が効率的でスループットも上がります。

「一括受信」について

Amazon SQS+SNSAmazon MQAzure Queue StorageAzure Service BusGoogle Cloud Pub/SubGoogle Cloud Tasks
一括受信 10メッセージまで 32メッセージまで ○ (上限不明) ○ (上限10MB?)

「受信時のセレクタ設定 」について

Amazon SQS+SNSAmazon MQAzure Queue StorageAzure Service BusGoogle Cloud Pub/SubGoogle Cloud Tasks
受信時のセレクタ設定 ×○???×?

「Pub→Subの条件設定」について

Amazon SQS+SNSAmazon MQAzure Queue StorageAzure Service BusGoogle Cloud Pub/SubGoogle Cloud Tasks
Pub→Subの条件設定 ◯ (SNS) ?(概念なし) ?×(概念なし)

「メッセージ更新」について

Amazon SQS+SNSAmazon MQAzure Queue StorageAzure Service BusGoogle Cloud Pub/SubGoogle Cloud Tasks
メッセージ更新×××?

一度発行したメッセージ内容を更新したい場合があります。メッセージを受信した側が、処理A→処理B→処理Cと複数の処理を行うとします。そしてそれぞれの処理が30分かかるとします。

受信したアプリがクラッシュした場合、再度次回処理でメッセージを受信すればよいのですが、もし処理Bまで完了していて処理Cでクラッシュした場合、次回処理は処理Cから再開したいでしょう。その場合、メッセージを更新し「処理Bまでは完了」ということを記録しておけば、次回処理からは処理Cから再開が可能です (受信側プログラムはメッセージ内容を確認して、どこまで処理が完了しているかを調べる必要があります)。

また、失敗回数を記録して、内容に応じて処理を中断することも可能です。

ただしメッセージの更新は、メッセージング・キューの単純性を損ない、複雑になり、リカバリミスも起きやすくなります。複数のメッセージに分割する方法 (例えば、メッセージ→処理A→メッセージ→処理B→メッセージ→処理C)、アプリ側で別途 DB に進捗情報を保存する方法も検討してみてください。

「メッセージ一括削除」について

Amazon SQS+SNSAmazon MQAzure Queue StorageAzure Service BusGoogle Cloud Pub/SubGoogle Cloud Tasks
メッセージ一括削除○ (SQS)×○ (purge)

「送信・受信手段」詳細説明

「送信手段」について

Amazon SQS+SNSAmazon MQAzure Queue StorageAzure Service BusGoogle Cloud Pub/SubGoogle Cloud Tasks
送信手段 awsコマンド, API, SDK azコマンド, API, SDK azコマンド, API, SDK gcloudコマンド, SDK, APIgcloudコマンド, SDK, API

「受信手段 」 について

Amazon SQS+SNSAmazon MQAzure Queue StorageAzure Service BusGoogle Cloud Pub/SubGoogle Cloud Tasks
受信手段 awsコマンド, API, SDK, Lambda, EC2等 azコマンド, API, SDK, Azure Functions, WebJob, WorkerRole azコマンド, API, SDK, Azure Functions, WebJob, WorkerRole gcloudコマンド, SDK, API 現時点では GAE のみ

「管理画面からの操作」詳細説明

「管理画面からキュー内容の確認」について

Amazon SQS+SNSAmazon MQAzure Queue StorageAzure Service BusGoogle Cloud Pub/SubGoogle Cloud Tasks
管理画面からキュー内容の確認

「管理画面からのメッセージ送信 」 について

「 滞留数カウント」について

Amazon SQS+SNSAmazon MQAzure Queue StorageAzure Service BusGoogle Cloud Pub/SubGoogle Cloud Tasks
滞留数カウント ??? ×? ?

「滞留数によるオートスケール」について

Amazon SQS+SNSAmazon MQAzure Queue StorageAzure Service BusGoogle Cloud Pub/SubGoogle Cloud Tasks
滞留数によるオートスケール ○ (SQS + CloudWatch) ??? × ?

「制限・上限」詳細説明

「メッセージ最大保持期間・メッセージ永続化」について

Amazon SQS+SNSAmazon MQAzure Queue StorageAzure Service BusGoogle Cloud Pub/Sub Google Cloud Tasks
メッセージ最大保持期間 14日間 デフォルトは永続化 7日間 29,247年?(TimeSpan .Max) 7日間 31日

送信したメッセージは受信され、その後削除されるのが通常の流れです。しかし、誰も受信しない、あるいは受信しても削除されない場合、メッセージングサービスにデータはたまり続けます。

「最大メッセージサイズ」について

Amazon SQS+SNSAmazon MQAzure Queue StorageAzure Service BusGoogle Cloud Pub/Sub Google Cloud Tasks
最大メッセージサイズ 256KB 64KB 256KB (プレミアムなら1MB) 10MBなし?

「リージョン依存」について

Amazon SQS+SNSAmazon MQAzure Queue StorageAzure Service BusGoogle Cloud Pub/Sub Google Cloud Tasks
リージョン依存 ありありありあり なし (グローバル)あり (たぶん)

リージョン依存がない、つまりグローバルなサービスは Google Cloud Pub/Sub のみです。つまり Cloud Pub/Sub は、リージョンをどこにしようと悩まなくてすむということです。

それ以外のサービスはリージョン依存ですので、メッセージ送信側と受信側のリージョンを考え、どこにキューを配置するかをよく考える必要があります。

「実行時間制限」について

Amazon SQS+SNSAmazon MQAzure Queue StorageAzure Service BusGoogle Cloud Pub/Sub Google Cloud Tasks
実行時間制限 10分

「キュー等の自動削除」について

Amazon SQS+SNSAmazon MQAzure Queue StorageAzure Service BusGoogle Cloud Pub/Sub Google Cloud Tasks
キュー等の自動削除サブスク31日 (削除させないことも可能)何かあったような

Google Cloud Pub/Sub には、「31日間一度も使用していない (PULL されていない、PUSHが成功していない) サブスクリプション」は自動的に削除されるという仕様があります。

メモ

Cloud PubSub のサブスクを使わないと 31日で消えてしまう件。有効期限ポリシー設定(beta)で、消えないようにできるかもしれない件。

  • このエントリーをはてなブックマークに追加

SNSでもご購読できます。

Leave a Reply

*

CAPTCHA