PubSubHubbub をハッキングする

オープンソース・ツールを使用して Web 上にパブリッシュ/サブスクライブを実現する方法を学ぶ

PubSubHubbub はパブリッシュ/サブスクライブ・フレームワークに従ってニュース・フィードの更新通知に接続するためのオープンな Web プロトコルです。PubSubHubbub はサーバー間でやり取りされる一連の HTTP として定義され、Atom 拡張機能や RSS 拡張機能に統合されます。名前は奇妙ですが、PubSubHubbub は情報が大量に更新されるアプリケーションを設計する際に非常に簡単に使用することができます。PubSubHubbub 標準について、また PubSubHubbub のオープンソース実装とサポート・ソフトウェアについて学びましょう。

Uche Ogbuji, Partner, Zepheira, LLC

Photo of Uche OgbujiUche Ogbuji は Zephira のパートナーであり、高度な Web カタログやその他のリッチなコンテキスト・データベースの作成を監督しています。彼は長年、XML、セマンティック Web や Web サービス、Akara などのオープンソース・プロジェクトといった高度な Web 技術を初期段階から扱ってきました (Akara は Web データ・アプリケーションのためのオープンソース・プラットフォームです)。彼はナイジェリア生まれのコンピューター・エンジニア兼ライターであり、米国コロラド州ボルダー近郊に住み、そこで働いています。彼についての詳細は彼のブログ、Copia をご覧ください。



2012年 5月 10日

どのような文化であれ、長い道のりの旅行をしていると、ほぼ必ず起こることがあります。後部座席に座った子供が何度も何度も、「まだ着かないの?・・・まだ着かないの?・・・まだ着かないの?」と尋ね続け、やがて苛立った親が運転席から「もう聞かないで。着いたら教えるから!」とビシッと言い返すのです。このような光景を見るのはいつでも楽しいものですが、この我慢できずにいる子供と同じような動きをするものが Web 上に非常に多く存在するという状況は、あまり楽しいものではありません。

皆さんは何らかのフィード・リーダーを使用することで、ニュース・サイト、ブログ、または IBM developerWorks のような定期公開資料など、お気に入りのパブリッシャーの新しいコンテンツを追跡しているかもしれません。そうであれば、そのリーダーは通常、15 分程度の間隔でサイトをポーリングしてフィード URL を要求し、新しいコンテンツがあるかどうかを確認します。フィード・リーダーとサイトが HTTP (特に Cache-Control ヘッダー) をフルに活用するなら、フィードに変更がない場合にはネットワーク上の情報交換は最小限になります。しかし、たとえ最小限のリソースしか使用しなくても、それは時間と共に蓄積されていきます。皆さん以外にも同じサイトに関心を持つ人が大勢いることを考えればなおのことです。

こうした不必要なトラフィックは深刻な問題です。そこで数年前、Google の何人かの技術者が、従来のパブリッシュ/サブスクライブ・パターンの新たな生まれ変わりを開発することにしました。パブリッシュ/サブスクライブは車の運転席の親に似ています。つまり子供に対して、「どこに近づいたら教えて欲しいのか言いなさい。そうすれば、近くに来たら教えてあげるから。」とあらかじめ言うことで、子供が何度も何度も「まだ着かないの?」と聞かなくても済むようにしています。この場合、皆さんは関心のあるフィードをサブスクライブし、そのフィードのパブリッシャーは皆さんに内容の変更を知らせてくれるため、ポーリングは必要ありません。

パブリッシュ/サブスクライブはかなり以前からあり、特にクローズド・システムでは昔から使用されていますが、Web はオープンであるため、有効かつセキュアに実装するのは少し厄介です。かつて RSSCloud (「参考文献」を参照) などが試みられたこともありますが、Web のための新世代のパブリッシュ/サブスクライブが必要な時が来ていたのです。その結果生まれたプロトコルには、PubSubHubbub という奇妙な名前が付けられました。PubSubHubbub は「PuSH」と省略される場合がよくあります。PuSH は、最初は Google の数人の頭脳から生み出されたものであったかもしれませんが、最初からオープンに開発された仕様であり、Google 以外の多くのコントリビューターが参加してきました。さらに良いことに、PuSH 仕様の開発はオープンソースのリファレンス実装と並行して進められました。他にも実装はありますが、仕様の開発者達がオープンソースのリファレンス・プロジェクトにコミットし、コミュニティー発足を支援できたことが良いことであることは間違いありません。

この記事では PuSH について紹介するとともに、PuSH のオープンソース・リファレンス実装の基本的な使い方について説明します。

PubSubHubbub の概要

PuSH は、ディスカバー、サブスクライブ、パブリッシュ、という 3 つのフェーズに分けて考えると理解しやすくなります。このように分けると PuSH の最も核心的な部分を把握することができますが、すべてを把握できるわけではありません (例えば PuSH には十分に検討されたアンサブスクライブ・メカニズムがあり、このフェーズは他のフェーズとは独立しています)。

ディスカバー

ディスカバー・フェーズは、まずサブスクライバーが 1 つのトピックに関心を持つと開始されます。PuSH のトピックは基本的に URL であり、一般的にはフィード URL と考えることができます。IBM developerWorks の各ゾーンには、それぞれの RSS フィードがあり、それらの各 RSS フィードは PuSH トピックになることができます。この場合、メインの URL は、PuSH 非対応のクライアントがポーリングに使用するフィード URL と同じ URL にすぎません。

PuSH で改善された重要な点の 1 つは、実際のサブスクライバーと、PuSH によるサブスクリプションを管理するシステムとが異なっても構わないことです。さらには、実際のサブスクライバーが別のサーバー上にあっても構いません。この方式のおかげで、ユーザーはプロトコルの一部を専用のライブラリーや、Web サービスにすら渡すことができます。PuSH に関するほとんどの説明では、サブスクライバーが 1 つのエンティティーとして表現されていますが、実際には PuSH プロトコルでは 2 つの別々のエンティティーを定義しているものと私は考えています。つまり 1 つは私がサブスクライバー・エージェントと呼ぶエンティティーであり、もう 1 つは単なるサブスクライバーです。場合によると、この両方が同時に実装されるかもしれませんが、必ずしもそうする必要はありません。図 1 はディスカバー・プロセスを図で表現したものです。

図 1. PuSH のディスカバー・プロセス
この図は、サブスクライバー・エージェントとパブリッシャーとの間で HTTP GET、Atom によって行われるディスカバーのフローを示しています。

サブスクライバー・エージェントはサブスクライバーに代わってフィードを要求し、フィード内に 1 つまたは複数ある、PuSH ハブへの特別なリンクを探します。下記はそうしたリンクの一例です。

<link rel="hub" href="http://pubsubhubbub.appspot.com"/>

この場合のフィードは、「私は http://pubsubhubbub.appspot.com にある PuSH ハブにパブリッシュします。」と表現しています。ちなみに、このサイトは Google が用意した PuSH のリファレンス・ハブであり、Google App Engine 上で実行されています。皆さんはお好みに応じて任意のハブを使用することができ、Google のオープンソース実装を使用して皆さん自身で実行するハブを使用することもできます。

そうした PuSH ハブのリンクがない場合には、サブスクライバー・エージェントはそれ以上何もせず、サブスクライバーはポーリングまたは他の何らかのメカニズムに頼らざるを得ません。PuSH ハブのリンクがある場合には、サブスクライバーは次のフェーズでそのハブと通信し、サブスクライブ・フェーズを開始します。

サブスクライブ

図 2 はサブスクライブ・プロセスを図で示したものです。このプロセスでは、サブスクライバー・エージェントは HTTP POST をハブに送信します。送信される情報の中には、コールバックに関する情報 (ハブが新しいコンテンツを通知する宛先となる URL) と、サブスクライバーが関心を持っているトピックが含まれています。またセキュリティー・メカニズムも含まれており、マルウェアがサブスクライバー・エージェントを装って不要なフィードをサブスクライブさせる、といった悪意のある操作をすることはできません。

図 2. PuSH のサブスクライブ・プロセス
この図は、サブスクライバー・エージェント、ハブ、サブスクライバーの間で HTTP POST、HTTP GET、Confirmation (確認) によって行われるサブスクライブのフローを示しています。

サブスクライブが開始されると、ハブは自らのサブスクライバー・エージェント・リストにコールバック URL を追加し、パブリッシャーがコンテンツに何らかの変更を加えると、そのコールバック URL に通知が送られるようにします。

パブリッシュ

図 3 はパブリッシュ・プロセスを図で示したものです。トピックが更新されると、パブリッシャーはそのパブリッシャーの各ハブに対し、更新されたコンテンツの URL を含む HTTP POST を送信します。PuSH の仕様では、これを「New Content Notification (新規コンテンツ通知)」と呼んでいます。次に各ハブは、そのトピックの新規コンテンツを要求する GET リクエストを送信します。このプロセスは「Content Fetch (コンテンツ取得)」と呼ばれます。最後にハブは更新されたコンテンツを HTTP POST によって各サブスクライバーに送信します。このプロセスは「Content Distribution (コンテンツ配信)」と呼ばれます。

図 3. PuSH のパブリッシュ・プロセス
この図は、パブリッシャー、ハブ、サブスクライバーの間で HTTP POST、HTTP GET、HTTP POST によって行われるパブリッシュのフローを示しています。

PuSH の強力さ

ここまで説明したプロセスはどれも複雑な動作のように思えるかもしれませんが、PuSH は少し複雑な代わりに大幅な非集中化が図られ、それによって高いスケーラビリティーと柔軟性を実現しています。図 4 は、PuSH ネットワークの中で、複数のハブ、パブリッシャー、サブスクライバー、サブスクライバー・エージェントが、いかに柔軟にやりとりできるかを示しています。

図 4. 複数のサブスクライバー、サブスクライバー・エージェント、ハブ、パブリッシャーの間のやり取り
この図は、サブスクライバー、サブスクライバー・エージェント、ハブ、パブリッシャーの間のやり取りを示しています。

PuSH のためのコード

これで PuSH プロトコルの基本を理解できたので、Google による PuSH リファレンス実装の使い方を説明しましょう。この実装はオープンソース (Apache ライセンス) です。ここでは特に、サブスクライバーの実装に焦点を絞ります。この実装を利用すると、サブスクライバーとして動作するシステムを構築することができます。

このプロジェクトの Subversion リポジトリー (「参考文献」を参照) からコードをチェックアウトし、簡単に内容を調べてみます。subscriber ディレクトリーは完全な App Engine アプリケーションです。このディレクトリーには、私がサブスクライバー・エージェントとして説明した部分は含まれておらず、その部分は皆さんが自分で用意する必要があります。subscriber_client ディレクトリーには、出発点として使用できる PHP コードが多少含まれています。

ファイアウォールを通過できるようにルーターを構成するという余分な作業を望む場合を除き、サブスクライバーをファイアウォールの背後に配置することはできません。Google App Engine SDK (「参考文献」を参照) を使用して皆さんの App Engine アカウントにサブスクライバーをデプロイすることも、SDK を使用してコードのテスト版をお好みの任意の Linux ホスト上にホストすることもできます。IBM はアプリケーションを IBM ミドルウェアにポーティングするための App Engine サポート・ツールを提供していますが (「参考文献」を参照)、これらのツールは Java の実装を必要とし、一方 PubSubHubbub のリファレンス実装は Python で作成されています。ここでは SDK を使用して Linux ホスト上でアプリケーションをホストする場合について説明します。この場合には Google が提供するデータ・ストレージ・バックエンドのスケーラビリティーを完全に活用することはできませんが、単純なサブスクライバーの場合には、いずれにしてもそうしたスケーラビリティーは必要ないはずです。リスト 1 に、このプロセスを示します。

リスト 1. PubSubHubbub をセットアップする
#Set up the App engine SDK
mkdir -p $HOME/.local/gae
cd $HOME/.local/gae
#Use wget or curl -O
wget http://googleappengine.googlecode.com/files/google_appengine_1.6.2.zip
unzip google_appengine_1.6.2.zip 

#Set up the PubSubHubbub app
svn checkout http://pubsubhubbub.googlecode.com/svn/trunk/ pubsubhubbub-read-only
google_appengine/dev_appserver.py  --address=$ADDR pubsubhubbub-read-only/subscriber/

この最後の行はポート 8080 でサーバーを起動します。ADDR は、必ずホスト環境のサーバーのホスト名または IP アドレスに設定します。バージョン 2.5 よりも新しいバージョンの Python を実行すると警告が表示されるかもしれませんが、この場合は気にする必要はありません。

先ほど、皆さんが自らサブスクライバー・エージェントを提供する必要があることに触れました。単純な HTTP の便利な点として、1 つの cURL コマンドによってサブスクライバー・エージェントを動作させることができ、サーバーがフィードをサブスクライブできるようになります。リスト 2 のコマンドを見てください。

リスト 2. cURL を使用してサブスクライブする
curl -v http://pubsubhubbub.appspot.com/subscribe \
-d hub.callback=http://$ADDR:8080/subscriber\&\
hub.topic=http://stackoverflow.com/feeds/tag/python\&\
hub.verify=sync\&hub.mode=subscribe\&hub.verify_token=\&hub.secret=

リスト 2 の cURL コマンドは Google のハブと通信し、Stack Overflow の Web フィードのトピックをサブスクライブしてくれます。Stack Overflow は開発者達が質問をしたり、問題を議論したりするコミュニティー・サイトです。たまたま私は Stack Overflow が Google のハブを使用していることを知っているので、ディスカバー・フェーズで頭を悩ますこともなく、Python に関するトピックのフィードを単純に選択しました (このトピックに関しては、かなり活発な議論が行われています)。すべてが順調であれば、上記の cURL によって HTTP 204 というレスポンスが得られるはずです。また、ハブとサブスクライバーとが通信すると、実行中のサブスクライバーのコンソールにデバッグ情報も表示されるはずです。

これで、Stack Overflow の Python フィードが更新されるのを少し待つと、サブスクライバーでコンテンツが更新されたことがわかるはずです。この場合も cURL を使用することで、ハブから取得した更新の単純な構造を表示することができるはずです (例えば curl http://addr:8080/items など)。

この addr を、皆さんのサブスクライバー・サーバー、つまり ADDR 環境変数と同じ値で置き換えます。

私の場合、1 時間ほどすると、ある 1 つの項目がサブスクライバーにプッシュされたことがわかりました。この項目はリスト 3 のような構造でした。

リスト 3. プッシュされた項目
[{"content": "...",
"source": "http://stackoverflow.com/questions/9155264/xyz-question", 
"title": "XYZ Question",
"time": "2012-01-25 05:11:22.849931"}]

省略記号の場所には、このエントリーの HTML 表現が入っています。この構造を Python で扱うのは非常に簡単で、JSON に変換することもできます。まさにこのようにして、パブリッシュ/サブスクライブを実行することができるのです。


まとめ

PubSubHubbub を最初に見た時は理解しにくいプロトコルに思えるかもしれませんが、要領をつかんで強力さを理解するまでに時間はかかりません。また PubSubHubbub が Web 上でアイデアやコードを交換するオープンソース開発者にとっていかに有効なものか、すぐに理解できるはずです。Google が作成したオープンソースのリファレンス実装は、商業組織などの他のユーザーによって既に分岐され、別の PuSH 実装のベースになっています。今や、多くの言語やプラットフォームのためのハブやサブスクライバーの実装があり、自らコードを実行したくない場合には Web サービスを利用することもできます。いつの間にか、皆さんもパブリッシュ/サブスクライブのハッキングが楽しくなり、成果を得られることもあるかもしれません。

参考文献

学ぶために

製品や技術を入手するために

  • PubSubHubbub プロジェクトのホームページで PubSubHubbub について学び、またリファレンス・コードを入手してください。
  • Web テストとスクリプト統合のための究極的なツール、cURL を入手してください。
  • IBM ソフトウェアの試用版にアクセスし (ダウンロードまたは DVD で入手することができます)、特に開発者のために用意されたソフトウェアを利用して皆さんの次のオープンソース開発プロジェクトを革新してください。

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Open source, Linux
ArticleID=812261
ArticleTitle=PubSubHubbub をハッキングする
publish-date=05102012