XMPPの神話 (XMPP Myths和訳)

この文章はDave Cridlandさんが書いたXMPP Mythsという文章の日本語訳です。 ドラフトの状態で公開されたために様々な場所で議論を巻き起こした話題の文章です。

正式バージョンが公開されてから翻訳に着手しようとも考えましたが、未だ議論が収束する気配が見えないので現状のまま翻訳版を公開することにしました。 そのため原文の更新に翻訳版が追いついていない可能性がありますがご了承ください。

誤訳などありましたら@xmpp_jpまでご連絡ください。

神話と伝説

私がこの文章を書いているこの場所では窓の外からちょうどマーリンの丘が見えます。 伝説によるとマーリンの丘の下にはマーリンが眠っておりイングランドに危機が訪れる時を待っているとされています。 しかし、マーリンの丘はイングランドではないのでこれは疑わしい神話です。 それでも私はなんとなくこの神話を信じることができるので、私は神話の専門家に向いているのかもしれません。

XMPPにも幾つかの興味深い神話があるようです。 そしてマーリンの丘に関連する神話と同様にこれらの多くは創作されたものです。 ここでは私のお気に入りのものを紹介します。

神話その1: XMPPはXMLを使っているので遅い

仮説: XMLはJSONやその他の類似したシンタックスに比べてとにかく遅い、だからXMPPはパフォーマンスの面で劣っている。

事実: XMLはJSONと同じ速さである。従ってXMPPはXMLが原因で遅くなったりなどしない。

とりわけJSONは全てにおいてXMLより優れたものであると言われることがあります。

実際の所JSONはより小さいサイズになるという利点がありますが、これは唯一の利点です。 省サイズはモバイル環境で重要な利点になると思うかもしれませんが、これについては神話その3で述べます。

典型的なパーサーを利用する場合、XMLとJSONはほとんど変わりありません。 ただ高性能なJSONパーサーの数に比べて高性能なXMLパーサーの数が少ないという事に関しては注目に値するでしょう。

パフォーマンスの点を無視したとしても、XMLは幾つかの点で勝っています。詳しくはこちら:

http://balisage.net/Proceedings/vol10/html/Lee01/BalisageVol10-Lee01.html

神話その2: 基本構成の機能が少ないので、XMPPは使いにくい

仮説: XMPPのコア仕様は小さすぎて実用的ではありません、私にとって必須の機能を後から付け加える必要があります。

事実: XMPPは拡張するように設計されています、そして多くの拡張仕様が用意されています。

「それはバグではなく仕様です」と断言出来ます。 XMPPのコア仕様(RFC 6120)は古典的なインスタント・メッセージング機能を含んでいません。それらはRFC 6121で定義されています。 XMPPはそろそろ15歳になるプロトコルですが、機能を追加する度にコア仕様を再設計していては既存のサーバーの互換性を崩してしまうでしょう。

その代わりにXMPPはクリーンなコア仕様と膨大な数の拡張仕様を持っています。 このコア仕様にはコネクションプロパティを拡張する方法についても定義されています。 実際に、コミュニティは早い段階でエンド・ツー・エンドの拡張システムを設計しました。

ほとんどのクライアントとサーバーはワイドレンジ拡張仕様に対応していますが、全ての拡張仕様をサポートしていないクライアントでサーバーに接続し、動作させることも可能です。

XMPP Researchというサイトでは学術論文で議論されている最も人気の拡張仕様について考察しています: XEPs used in XMPP research

神話その3: モバイル回線の通信が非効率です

仮説: XMPPスタンザは冗長なのでモバイル環境に不向きです

事実: XMPPはSATCOMなどの人工衛星通信や短波通信での実績があります。

XMLはその他のシリアライズ形式と比べて冗長であると言われているため、低速な回線で問題があると思うかもしれません。 しかし、実際にはXMPPにおけるXMLの使い方は極めて簡潔です。 SOAPに見られるような使い方はしていません。 さらにXMPPはとんでもなく遅い回線で利用されています(現在も使われています)

SATCOMの回線速度は約9600bpsです。 これはGSMデータ呼び出しと同じ速さです。と言っても使ったことが無いから分からないかもしれませんが… レイテンシは大体30秒です。 一方、短波通信(HF)は半二重で相当低い通信速度です。 大体 9bps程度の速度しか出ませんし、電波の方向を切り替えるのに2分ほどかかってしまうという厳しい世界です。

そのような環境でもXMPPは動作します。 これに関してIsode社は素晴らしいホワイトペーパーを公開しています: M-Link Support for XMPP over Constrained Networks、 また、SATCOMで利用されているXMPPサーバーの殆どはOpenfireなどのオープンソースソフトウェアです。

モバイル環境で最も注目すべきコストはストリームの開始処理です。 なぜなら、それは逐次的なラウンドトリップ通信だからです。 しかし、XEP-0198という仕様でこれを改善できます。

すでに述べたようにXMPPはNAKプロトコルです。 成功時には応答しないので通信は発生せず、エラーの場合のみ応答を返します。 その他の低速通信向けに設計されたプロトコルを調べてみると、同じような特徴の設計方針である事に気がつくでしょう。

HTTP上でJSONを利用する他のプロトコルと比較してみましょう。 HTTP/1.1はトランザクション毎にオーバーヘッドが発生する驚くほど冗長なプロトコルです。 そして全てのHTTP APIコマンドは応答を確認する必要があります。 HTTP/2.0でこれは改善されるでしょうが、オーバーヘッドは完全に無くなりません。

XMPPはモバイル環境で長年利用されてきましたが、Push (XEP-0357)は比較的新しい仕様です。 どうしてかと言うとApple以外のプラットホームで必要とされなかったからです。 例えばAndroidのクライアントではこの仕様無しでうまく動作します。 そしてコミュニティではモバイルに集中した作業を数年間行ってきました。XEP-0286を読んでください。

神話その4: XMPPは拡張仕様を使わなければ信頼性が低い

仮説: XMPPスタンザは喪失する可能性がある。したがってシステムには信頼性がない。

事実: XMPPは一般的に信頼性の高いストリーム通信を利用するので、拡張仕様を使わなくても十分信頼性は高い。

これは計算機科学で「二人の将軍問題」と呼ばれる古典的な問題です。 私はあなたがWikipediaのこのページを読み終わるまで待ちましょう。

読み終わりましたか?

通常1人の人間が利用するTCPバインディングでは、TCPは異常処理を最小化するための多くの機能をXMPPに与えてくれます。 TCPを経由してスタンザを受信した場合、同じストリーム内のそれ以前のスタンザは確実に到達していることが保証されています。 これにより、2人の将軍問題はいくらか簡単になります。 これは重要なことであり、後ほどまた出てきます。 WebSocketも同様にTCPストリームを利用します。

これはXMPPのHTTPバインディングであるBOSHを見てみるとわかりやすいです。 これは通信方法には信頼性が無いので、コミュニティは再送タイマーやバッファリングなどを追加して同様の信頼性を保証する必要がありました。 実際のところ、HTTPポーリングをベースとしたシステムでは基本的な信頼性を得るために何らかの対応が必要ですので、信頼性が欠けていることは別の視点で見ると驚くことではありません。

これが事実であれば、なぜ拡張仕様が必要になったのか?という疑問が生まれます。 実際に異なる拡張仕様が2つありますが、両方ともAckが関わっています。

まず、神話その3で述べた様にXMPPは規定ではNAKプロトコルです。 これは帯域利用量の面で優れていますが、メッセージが正しく到達したか、クライアントがクラッシュしていないか、コネクションが切れていないかどうかを確認したい場合に、少し困ってしまうでしょう。 XEP-0184はこの欠点を補います。 クライアントに対してAckを送信し、メッセージを受信できていれば応答を返します。

しかし、応答が返ってこない場合、メッセージが喪失したのか、Ackが喪失したのかを知るすべはありませんし、この様な状況で行うべき決まった方法はありません。 再送すべきでしょうか? オフラインメッセージに格納されているだけかもしれません。 どうしたらよいのでしょうか?

ここでXEP-0198 ストリームマネジメントが役立ちます。 これはモバイル環境でのTCPセッションの信頼性がとても低いためにコミュニティで開発されました。 今では多くのサーバーがこの仕様をサポートしており、多くのモバイル向け(特にAndroid)のXMPPクライアントで利用されています。

XEP-0198は複数のセッションを渡るTCPの信頼性とアプリケーションを拡張します。 リクエストを送信したら同一の接続を経由してAckを送信します。(TCPの通信シーケンスの様にAckは必須です) クライアントとサーバーは送信スタンザをバッファしているので、もしAckがなければ、喪失したスタンザを再送したり、クライアントが再接続した際にXMPPセッションを再開することが出来ます。

これにより、最後に送った数メッセージとセッションの再開が出来なかった場合のみに注目すれば良いので2人の将軍問題は緩和されます。

ということは、XMPPの全ての拡張仕様を使ったとしても信頼性は低いということでしょうか? 仮説(XMPPスタンザは喪失することがある)は正しいという事でしょうか? 確かに、そういうことも起こるでしょう。 2人の将軍問題は本質的に解決不可能です。 どこかの誰かは100%に信頼できる通信システムを持っていて、永久機関を持っているというかもしれませんが私はそのような愚か者ではありません。

確かに言えるのは、XMPPは実用的なプロトコルとして十分信頼性があるということです。

神話その5 : XMPPはWEBに適さない

仮説: XMPPはカッコ<>を使うのでWebに適さない。

事実: XMPPは数多くのWebサイトに導入されており、初期の頃からピュアなJavascriptライブラリが存在した。

オーケー、私はWeb業界の人間ではないと認めましょう。 なぜXMPPはHTTPの様にJSONを利用せずカッコ<>を利用するのか分かりませんしこれらはWebで利用すべきではないでしょう。 このカッコは本当に紛らわしいです。 XMLはWeb関連技術にもかかわらず、かつて程人気はありません。 BOSHの様なバインディングはHTTP上にXMPPを流すために長年利用されてきましたが、Strophe.jsの様なライブラリはブラウザ内で完全なXMPPスタックを驚くほどうまく処理します。 なぜならブラウザーはXMLを処理するためのネイティブサポートを持っているからです。(神話その1参照)

しかし私は多くの聡明な人々がWebベースのAPIはJSONフォーマットであるべきだと感じていることを認めます。 良いニュースは、これを実現するための少なくとも2つのXMPPライブラリが存在することです。

Stanza.io は純粋にクライアント側で動作し、XMPPの標準的なバインディングであるHTTPロングポーリング(BOSH)とWebSocketsを利用し、幅広いJSON APIを提供します。

また、XMPP-FTWはサーバー側でXMLベースのTCPセッションからJSON APIに変換するプロキシーを利用することで、伝統的なブラウザが通信手段を切り替えられることを示しました。

それと、これらは現在同じJSONの変換コードを利用していますので切り替えは快適です。

WebRTCではXMPPのJingleシグナリング技術を利用してスタックを超えて通話することができます。また、オリジナルのStrophe.jsライブラリも同様です。 JingleはWebRTCの機能設計にに大きな影響を与えたので驚くことではありません。 また、WebRTCが押し上げてくれたおかげで、XMPPのデスクトップクライアントは現にこれに追いつき、よりWeb向きになったと言えます。