クラウド メッセージング/キュー比較解説まとめ (Amazon SQS・Amazon SNS・Azure Queue Storage・Azure Service Bus・Google Cloud Pub/Sub・Google Task Queue)

前へ << クラウド DNS サービス比較解説まとめ (Amazon Route53・Azure DNS・Google Cloud DNS) クラウド データウェアハウス比較解説まとめ (Amazon Redshift・Azure SQL Data Warehouse・Google BigQuery) >> 次へ

目次

メッセージング/キュー

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 Task Queue

使い所

メッセージング・キューサービスは、使っていない人にとっては必要性がわかりづらい概念だと思います。

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

典型的な使い所としては、

  • 処理Aと処理B つながりを疎結合にしたい場合
    • 処理B が別サーバで行われるため、疎結合にならざるをえない場合
    • 仕様変更やトラブル時のリカバリ等で、処理B だけ開始したい場合
    • 処理B が異常終了した場合のリトライを自動的に行わせるため
    • 処理B があるサーバが障害やメンテでダウンしていても、復旧次第処理を行わせるため
  • 処理B を非同期にしたい場合
    • 処理B の時間がかかるため、終了を待てない場合 (処理A が Web アプリ、処理B が実行に10分かかるバッチなど)
    • 処理B を並列実行してスケールするようにしたい場合
    • 処理B はスケールしてほしいが、多重度が増えすぎないようコントロールしたい場合
などが考えられます。 さらに具体的な事例は下記です。
  • 画像をアップロードすると、画像種類別 (gif, png, Web など) × サイズ別のサムネイル画像を生成する。
  • 注文受付後、PDF ファイルを生成する
  • ある処理後に、お知らせとしてメールや PUSH 通知を送信する
  • ランキング情報や統計情報の更新
  • サービス退会後の、会員情報・購入情報・履歴のマスキングや削除

分類

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

  • 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 しないとずっとメッセージは残りますし、 1分間に一度 PULL した場合は、最大 1分間の遅延が発生します。

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

    GCP でのメッセージングと言えば基本これ。 Pub/Sub モデル。PULL・PUSH 可能。

  • Google Task Queue

    GAE 内のサービス。 Google Cloud Pub/Sub リリース当初は、Task Queue はなくなる予定だったそうだが、 Pub/Sub では吸収しきれない要望がたくさんあったため、存続決定とのこと。

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

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

GCP であれば、AppEngine のみでの利用で外部接続をしないなら Google Task Queue、 それ以外は Cloud Pub/Sub を使うべきでしょう。

比較表

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

- Amazon SQS+SNS Amazon MQ Azure Queue Storage Azure Service Bus Google Cloud Pub/Sub Google Task Queue
モデル PTP (SQS), Pub/Sub (SNS) PTP, Pub/Sub 両方 PTP Pub/Sub Pub/Sub PTP?
PULL ○ (SQS のみ)
PUSH ◯ (SNS のみ) ? ×
PEEK × ○? × ?
順序保証 標準キューは×、FIFOキューは○ × × ?
重複受信排除 標準キューは×。FIFOキューは◯ × × ?
デッドレター・有害メッセージ × ?
遅延送信 (キュー単位) 最大15分 ×
遅延送信 (メッセージ単位) 最大15分 ◯?
優先度指定 × × ? × ?
管理画面からキュー内容の確認 ×
管理画面からのメッセージ送信
滞留数カウント ? ? ? ×? ?
滞留数によるオートスケール ○ (SQS + CloudWatch) ? ? ? × ?
一括送信 10メッセージまで × ○ (上限不明) ○ (上限10MB?)
一括受信 10メッセージまで 32メッセージまで ○ (上限不明) ○ (上限10MB?)
受信時のセレクタ設定 × ○? ? ? × ?
Pub→Subsの条件設定 ◯ (SNS) ? (概念なし) ? × ?
メッセージ最大保持期間 14日間 7日間 29,247年? (TimeSpan .Max) 7日間
最大メッセージサイズ 256KB 64KB 256KB (プレミアムなら1MB) 10MB
リージョン依存 あり あり あり あり なし あり
実行時間制限 10分
送信手段 AWS CLI, SDK SDK, REST SDK, REST gcloud, SDK, REST, gRPC GAE
受信手段 AWS CLI, SDK, Lambda, EC2等 SDK, REST, Azure Functions, WebJob, WorkerRole SDK, REST, Azure Functions, WebJob, WorkerRole gcloud, SDK, REST, gRPC GAE、外部(pullのみ)
メッセージ永続化 ×? ◯? ×? ×? ×? ×?

モデル・PULL・PUSH について

- Amazon SQS+SNS Amazon MQ Azure Queue Storage Azure Service Bus Google Cloud Pub/Sub Google Task Queue
モデル PTP (SQS), Pub/Sub (SNS) PTP, Pub/Sub 両方 PTP Pub/Sub Pub/Sub PTP?
PULL ○ (SQS のみ)
PUSH ◯ (SNS のみ) ? ×
- Amazon SQS+SNS Amazon MQ Azure Queue Storage Azure Service Bus Google Cloud Pub/Sub Google Task Queue
PEEK × ○? × ?

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

前へ << クラウド DNS サービス比較解説まとめ (Amazon Route53・Azure DNS・Google Cloud DNS) クラウド データウェアハウス比較解説まとめ (Amazon Redshift・Azure SQL Data Warehouse・Google BigQuery) >> 次へ

ご意見・ご指摘は Twitter: @68user までお願いします。