続 カッコの付け方

AWSを始めとしたクラウドコンピューティング全般と、唯一神emacsにおける()の付け方についてだらだら書きます

Google Cloud Pub/Subと類似サービスの比較(SNS, SQS)

もう1ヶ月以上経過してしまいましたが、まだ情報が少ないみないなので、aws識者として競合との比較も含めて書きます。私は使わないと頭に入らない人間なので、ちょっと触ります。

概要

What is Google Cloud Pub/Sub? - Cloud Pub/Sub — Google Cloud Platform

の絵で大体想像がつくと思いますが、文字通り Pub/Subを実現するものです。
最初にPub/Subを見た時、AWS SNSをイメージしましたが、どうやら違うようです(一部重複の部分もある)。
じゃあSQSかとも思いまいたが、どうやらこれとも違うようです(使い方によっては一部重複する)。
Pub/Sub自体の機能については、結構言及されているので、

togetter.com

これも参考にしながら、まずはAWSとの比較から書きます。

競合比較

SNSとの違い

SNSは原則Push型です。Pub/Subは Push or Pull ですので、一部機能は重複しています。この辺りをまとめると
- SNSはPub/Subだが、Pushしか出来ない
- SNSはPush先が豊富 Mail, HTTP(s), SQS(AWS内のサービス連携), モバイルプッシュ など、かなりアプリケーションに突っ込んだところまで実装している。
- Pub/Sub が対応している Pushは HTTPSのみ(2015/04/29)

SQSとの違い

SQS自体にPub/Subの機能はありません。SQSと競合するサービスは、Google Task Queue です。両方古くからあるサービスなので、最初 Pub/Subと聞いての競合はSNSだと思いました。
- SQSはそもそもPub/Subではない
- SNSとSQSは連携できるので、組み合わせればPub/Sub & Pull型は一応できる(管理が大変そう)
- Cloud Pub/Sub の Pullは SQSそのものだが、単純にキューを使いたいならTask Queueで十分

総合的にみて

現状 Cloud Pub/Sub は Pull主体です。Pushは HTTPSに限定されているので、Push型のsubscriberはそんなに増やせない。よって、Pull型のSNS(Queue付きのSNS) = Cloud Pub/Sub というイメージ。互いに似て非なるものです。

Cloud Pub/Sub (subscriber視点)

こちらをご一読。

Subscriber Guide - Cloud Pub/Sub — Google Cloud Platform

  • Pullならポーリング当たり前だけどリアルタイム性はさがるよ
  • Pullなら通信費かさむよ
  • Pushなら HTTPSのエンドポイント用意して!
  • PushのエンドポイントはGAE(App Engine)ほぼ一択、DNS通さないとダメみたい

GAEか、勉強するぞ!いつか。

実践

サンプル動かす

GAEのサンプルは書かれている方がおりますので、GCEというかローカルPCで動かします。よってsubscriberはpullです。

github.com

Googleといえばpythonなので、python一択
READMEに従い、venvに必要なpipをぶち込みます。
オプション無しで叩くと、使い方が出ます。

$ python pubsub_sample.py
Available arguments are:
  PROJ list_topics
  PROJ create_topic TOPIC
  PROJ delete_topic TOPIC
  PROJ list_subscriptions
  PROJ list_subscriptions_in_topic TOPIC
  PROJ create_subscription SUBSCRIPTION LINKED_TOPIC [PUSH_ENDPOINT]
  PROJ delete_subscription SUBSCRIPTION
  PROJ connect_irc TOPIC SERVER CHANNEL
  PROJ publish_message TOPIC MESSAGE
  PROJ pull_messages SUBSCRIPTION

コマンドは叩いてもらうとわかるとして、気になる実装connect_ircをみてみます。ircの特定チャネルの情報を流すらしいですが、実装は単純に

    while True:
        readbuffer = readbuffer + irc.recv(1024)
        temp = readbuffer.split('\n')
        readbuffer = temp.pop()
        for line in temp:
            line = line.rstrip()
            parts = line.split()
            if parts[0] == "PING":
                irc.send("PONG {}\r\n".format(parts[1]))
            else:
                i = line.find(priv_mark)
                if i == -1:
                    continue
                line = line[i + len(priv_mark):]
                m = p.match(line)
                if m:
                    line = "Title: {}, Diff: {}".format(m.group(1), m.group(2))
                body = {
                    'messages': [{'data': base64.b64encode(str(line))}]
                }
                client.projects().topics().publish(
                    topic=topic, body=body).execute(num_retries=NUM_RETRIES)

ircのチャネルをポーリングしてpubしているだけです。サンプルとしてはひと通り動かせばよく分かり、どう実装するかも余計な部分がほとんど無いので、コードを読めばすぐわかる感じです。

まとめ

  1. pull主体
  2. pushやるならGAE
  3. Cloud Loggingとの連携、pushでスマートにやるならGAE一択
  4. 単純なキューなら、Task Queue使ったほうがいい(多分)