Amazon SNS のモバイルプッシュじゃない一面!? …モバイルサービス #とは #アドカレ2015

よく訓練されたアップル信者、都元です。いきなり正直申し上げますと、都元はあまりモバイルに強みを持っておらず、どうしたもんかと考えておりました。

モバイルサービス #とは

現時点でAWSにおいて「Mobile Services」に分類されているのは下記の5つ。

  • Mobile Hub
  • Cognito
  • Device Farm
  • Mobile Analytics
  • SNS

この一番最後に挙がっている Amazon Simple Notification Service (SNS) は皆さんご存知でしょうか。実はこのSNS、以前はモバイルサービスではなく、アプリケーションサービスに分類されるものでした。まぁ1年半前に遡ると、SNS以外のモバイルサービスはまだありませんでしたから。

さて、本アドベントカレンダーをお読みの皆様におかれましては、SNSと言えば各社(下記)のプラットフォームにプッシュ通知を送るサービス、という認識かと思います。なんたってモバイルサービスですから。

  • Kindle Fire向け - Amazon Device Messaging(ADM)
  • iOSデバイス向け - Apple Push Notification Service(APNS)
  • ANdroidデバイス向け - Google Cloud Messaging for Android(GCM)
  • Windows Phoneデバイス向け - Microsoft Push Notification Service for Windows Phone(MPNS)
  • Windows8アプリ向け - Windows Push Notification Services(WNS)
  • ? - Baidu Cloud Push

様々なプラットフォームにおいてプッシュ通知を抽象化し、プラットフォームの種類によらず同じ操作で通知を送信できるサービスです。

いや、待て。

そうなんだけど違うんだ。SNSってのはプッシュ通知にも使えるけど、そのためのサービスではない。確かにフィーチャーされている機能は「モバイルプッシュ」なのですが、もう一つ「pub-subメッセージング」という顔があります。pub-subについては後で詳しく説明します。

SNSのサービストップページには、下記のような特徴が記述されています。ここでも先に出てくるのはモバイルプッシュ。

  • モバイルアプリケーションとユーザー通知サービス
  • クラウドベースのエンタープライズ pub-sub メッセージング

タブを切り替えるとやっと、もう一つのpub-subの説明が現れます。これはもうマーケティングの陰謀としか思えません。私の認識ではSNSは「モバイルプッシュにも使える、pub-subモデルの実装」なんですが、どう見ても「pub-subできるモバイルプッシュ通知サービス!」にしか見えません。

というわけで今日は、SNSに見るシステム間メッセージング『Pub-Sub』というモデルについて学んでいきましょう! モバイルについてはここまでです! お出口はあちらです!(自棄)

システム間メッセージング

コンピュータの世界で「メッセージング」と言うと、オブジェクト指向におけるオブジェクト間のメッセージパッシング、プロセス間の通信、サーバ間の通信など、様々な粒度の話がでてきます。何れのケースでも、メッセージングを行う理由というのはsender(送信者)がreceiver(受信者)に対して何らかのアクションを期待して司令を出すためです。

SNSはsenderからのメッセージを受け取り、それをreceiverに渡す、senderとreceiverの仲立ちをする立ち位置に居ます。そして、SNSが対象とするのは主にサーバ間の通信であるため、ここは話を単純にするため、サーバ(EC2インスタンス等)間の通信で考えていこうと思います。

同期/非同期

メッセージングには「同期メッセージング」と「非同期メッセージング」があります。

サーバ間でメッセージングをする場合、まず最初に思い浮かぶのがHTTP通信でしょう。Web API(receiver)とそれを利用するClient(sender)がこれにあたります。

HTTPは一般的に同期メッセージングと言われ、senderはメッセージを送った後、receiverから結果が来るのを待ちます。結果が返ってくるまでの間、senderは処理をストップして待機を続けます。(もちろん、タイムアウトはありますが。)

一方、非同期メッセージングというのは、sender側はメッセージを投げっぱなしにし、receiverの処理の完遂を期待はするものの、結果を要求しません。(本当に結果を要求しないパターンと、ひとまずこの場では結果を要求せずに、後から任意のタイミングであらためて同期メッセージングを行って結果を受け取るパターンがあります。)

同期メッセージングは非同期に比べてシンプルな処理になりますが、待ちが発生するため処理効率が悪く、スケーラビリティにも難が出ます。一方、非同期メッセージングは処理が複雑になってしまいますが、sender側とreceiver側で並行して処理を継続でき、スケーラビリティ的に有利に働きます。

SNSが対象にするメッセージングは非同期メッセージングです。senderはSNSにメッセージを渡した後、receiverからの結果を待ちません。というか、SNSが仲介をした結果、receiverからの折り返しを受け取れない構造となっているので、そもそも待つことができません。

senderとreceiverの依存関係

さて、ここでもう一つ別の切り口でメッセージングを見ていきましょう。この2つのサーバは、どちらか一方が他方に依存しています。下記のどちらの可能性も考えられます。

  • senderはreceiverについての知識を持ち、receiverはsenderの知識を持たないパターン(senderがreceiverに依存)
  • receiverはsenderについての知識を持ち、senderはreceiverの知識を持たないパターン(receiverがsenderに依存)

例えば先ほどのHTTP(ClientとWebAPI)の例では、senderがreceiverに依存している例です。Web APIは、リクエスト元がどのようなシステムだかは知らず、とにかくsenderがリクエストを送ってくるから、それに対してレスポンスをします。一方Clientは、相手が特定の機能を持ったサーバだということを知っており、どようにリクエストを送るべきで、どのようなレスポンスが返ってくるのかを知っていて、それに従ってメッセージングを行います。

一方でSNSというのはreceiverがsenderに依存しているモデルです。つまり、senderは「メッセージによって誰かが何かの処理をすることを期待しつつも、具体的に誰がどんな処理をするかは知らない」のです。かたやreceiverはsenderのことを良く知っており、相手がどんなシステムで、どんな時にメッセージを送ってくるのか、そしてどんなメッセージを送ってくるのか、を熟知しています。

不思議な関係に感じるでしょうか。

pub-subモデル 〜 新聞社と購読者

さて、SNSというのはサービス紹介ページにもある通り「pub-subメッセージング」を仲介するサービスです。

pub-subとは、略さずに言えば Publish-Subscribe(出版-購読)です。現実世界の新聞購読の仕組みと似ているため、このように呼ばれています。

新聞の世界には配達先リストがあるはずで、そのリストは配達所が持っています。まず新聞を読みたい人は配達先リストに対して、購読の手続きをします。新聞社が新聞を発行した時に、購読者の元に新聞が届くわけです。

この配達者リストのことを、pub-subモデルにおいては「トピック(topic)」と呼びます。そしてtopicを持っているのがSNSです。

メッセージを受信したいサーバ(subscriber)はトピックに対して、subscribeをします。メッセージを送信したいサーバ(publisher)がメッセージを発行(publish)した時、subscriberにメッセージが届くのです。

そしてご想像の通り、1つのトピックには複数のsubscriberが紐付いていて、publisherとsubscriberは1対多の関係となり、同報通信が可能になります。また、ここは新聞の例とちょっと違いますが、1つのトピックに対して複数のsubscriberが居ても構いません。通常の新聞発行者に加えて、号外の発行者が別にいる、と考えて…。ちょっと苦しいですかねw しかしまぁ、そう考えれば多対多と見ることもできるかもしれません。

さて、現実世界に新聞が何種類もあるのと同じようにトピックも複数構成することができます。subscriberは数あるトピックのうち、必要なトピック複数にsubscribeしても構いません。

新聞社は購読者が新聞を読み終わってリアクションをするのを待ちません。ただし、後から任意のタイミングでアンケート等によって感想(結果)を集めたりすることもありますよね。つまり非同期メッセージングです。

また、新聞社はどんな読者がいるのかを知りません。対する購読者は新聞社の特徴を把握していて、だいたいどんな論調の記事を書いてくるのか。。。まぁ分かってたり分かってなかったりしますかねw ここは分かっているものとしてください。つまり、新聞社は購読者に依存しないメッセージングです。

繰り返しになりますが、pub-subにおいて、publisherは何も知りません。もしかしたらsubscriberが一人もいないかもしれませんが、情報を発信することを使命と心得て、決まった形式でメッセージをトピックに投げ続けます。

pub-subは、非同期senderがreceiverに依存しないメッセージングモデルだということが分かると思います。

pub-subのユースケース

さてこのpub-subモデルのメッセージングですが、何に使えるんだろう? って思いますか? いや、意外と便利なんですよ。私が今まで使ったり考えたりしたユースケースを下記にご紹介します。

1. システム(pub)から運用担当者(sub)への状況報告

システムは時に、運用担当者に何らかの連絡をしたいことがあります。ネガティブな例になってしまいますが、システムに何らかの障害が発生した際には、運用担当者に状況を報告したいはずです。

そんな時のために、状況報告用のトピックを作っておき、運用担当者(サーバではなく人ですが)はそのトピックを購読しておきます。システムは障害が発生した際に、(メッセージを誰かが受け取ってくれることを祈りつつ)トピックに情報を投げます。

2. Auto Scaling配下の1つのEC2(pub)が、全EC2群(sub)に対して、インスタンス内に持つキャッシュをパージさせたい

2つ目にしてだいぶアレな例が出てきてしまいましたが。。。Auto Scalingで展開したWebサーバ群があり、ELBの配下にもいるとします。そしてEC2インスタンス内に個別独立で、何らかのデータのキャッシュを保持する仕組みがあったとします。

ELBを経由して、1つのインスタンスがキャッシュの破棄が必要な処理を行ったとします。その時、全EC2インスタンス上で保持するキャッシュを全てパージしたいわけです。

この場合、トピックを用意しておいてEC2が起動時にsubscribeするようにしておき、破棄をトリガしたいインスタンスがメッセージを発信するようにします。破棄要求のメッセージを受けたEC2インスタンスは、キャッシュを破棄します。

…すみません。アタマで考えただけで、実際にはやってませんw 「キャッシュ」という、例としてスジの良くないものでしたが、Auto Scaling配下の全サーバに同じ処理を要求したい、というケースで何か使える機会が来るんじゃないかとぼんやり考えています。

まとめ

図やコードが一枚もない中、そして抽象的な説明ばかりが並ぶ中、よくぞここまでたどりついた。僕もう疲れたよ…何だかとっても眠いんだ…zzz