HTML5Experts.jp

「WebSocket, WebRTC, Socket API, … 最新Webプロトコルの傾向と対策」HTML5 Conference 2013 セッションレポート

2013年11月30日(土)に開催された「HTML5 Conference 2013」の、エヌ・ティ・ティ・コミュニケーションズ株式会社・小松健作さんによるセッション「WebSocket, WebRTC, Socket API,…最新Webプロトコルの傾向と対策」の内容をご紹介します。

最新のWebプロトコルが続々と誕生

1990年から10年間ほどは、HTTPというたった一つのプロトコルが、Web通信用のプロトコルとして使われていました。その後、HTML5という言葉が出てきてから、WebSocketやSPDY、HTTP/2.0、WebRTC、Raw Socket API、SCTP over UDP、QUICといった、新しいプロトコルが続々と誕生してきました。この4年間ほどで、これらの多くのプロトコルが誕生してきた背景・理由をこれから説明します。

HTTPの仕組みと問題

約20年間に渡り、Webを支え続けているHTTPの仕組みをまずは説明します。HTTPは非常に単純なプロトコルで、ブラウザ・サーバ間でリクエスト・レスポンスがやり取りされる仕組みとなっています。例えば、ブラウザから「index.htmlがほしい」とサーバへリクエストを送信すると、サーバからそのHTMLファイルがレスポンスとして送信されます。その後、ブラウザから「CSSがほしい」とサーバへリクエストを送信すると、またサーバからレスポンスが返ってくるという流れになります。

ここで問題となるのが、ブラウザがサーバへリクエストを送信してレスポンスが返ってくるまでの間、ブラウザが次のリクエストを送信できないということです。この待ち時間をRound Trip Timeと言いますが、例えばこれが100ミリ秒だとすると、全て合計するとこの時間だけで1~2秒かかる場合があります。この状況を改善するために、TCPの接続を複数張り、同時に複数のリクエストを送信するという方法があり、これが今のHTTPのメジャーな使用方法となっています。この方法で改善はするのですが、例えばChromeですとブラウザから同一のサーバに対しては、同時に6つまでしかリクエストを送信できないという制限があり、どうしても待ち時間が発生してしまいます。

このような制限がある中でWebサービスのレスポンス性を高めるために、やり取りされる複数のリソースを一つにまとめて、リクエスト・レスポンスの回数を減らすという方法があります。具体的な方法の一つとして、複数の画像ファイルを一つのファイルにまとめるCSS Spritesという手法があります。ただし、Twitterのアイコンなど、リクエストによって動的に表示させる画像を変更しなければならない状況では、このような手法を使うことはできません。このような課題があり、そもそも開発者側でこのようなパッキング・テクニックを使わなくても済むように、複数のリソースをまとめるための一般的な方法が求められるようになりました。

複数のリソースを一つにまとめるSPDY

複数のリソースを一つにまとめて通信するプロトコルとして、SPDYがあります。SPDYでは、一つのTCP接続の中で、複数のリクエストを送信することができ、これによって高速化が図られています。

ただし、常にSPDYを使用すればよいというわけではありません。ネットワークの遅延がない状況ですと、SPDYの方がHTTPSよりも常に速いのですが、ネットワークの遅延が100ミリ秒ある状況ですと、HTTPSの方がSPDYよりも速くなります。そして、通信するリソースサイズが大きくなればなるほど、その通信速度の差は大きくなります。

TCPにはLong Fat Pipeという問題があります。TCPでデータをダウンロードする際は、データが複数の小さいパケットに分割されてサーバからブラウザへ送られます。ブラウザは、ある程度パケットをダウンロードすると、サーバへACK(Acknowledgement:受信応答)を送信し、サーバはブラウザからのACKを受信することで、次のデータをブラウザへ送信します。ここで、サーバが、ブラウザからのACKを受信するまで次のデータを送信することができないという問題があります。そのため、レイテンシが増えるにつれて、ブラウザからのACKの待ち時間が増えることになります。これがLong Fat Pipeと呼ばれる問題です。すごく太い、例えば1GBくらいの回線があったとしても、100ミリ秒などの遅延があると、1GBという速度は到底でません。このLong Fat Pipeは、個々のTCPの接続で発生するため、1つのTCP接続でデータをやり取りするSPDYの方が、複数のTCP接続に分散してデータをやり取りするHTTPSよりもLong Fat Pipeの影響を受けやすくなります。よって、ネットワークのレイテンシが大きい状況では、通信するリソースサイズが増えるに従ってLong Fat Pipeの影響が大きくなり、SPDYの方がHTTPSよりも通信速度が遅くなります。このように、常にSPDYの方が速いというわけではありません。

さらに、Head of Line Blockingという問題についても、SPDYの方がより大きな影響を受けます。Head of Line Blockingとは、TCP通信内でサーバから送られるデータが欠損する(パケット・ロスが起こる)と、そのデータが再送されるまでは、その後続のデータがブラウザへ送信されないという問題です。HTTPSの場合、TCPを複数張っているため、一つのTCPでHead of Line Blockingが発生しても、他のTCPでは通常通り通信が行われるため、この影響をあまり受けませんが、SPDYの場合、一つのTCPのみを使用しているため、Head of Line Blockingの影響を大きく受けることになります

Webの進化によりTCPの制限に直面

以上のようなSPDYを使用することによる問題は、SPDY自体に原因があるわけではありません。その下のレイヤであるTCPに、Long Fat PipeやHead of Line Blockingといった制限があることに原因があります。Webの進化によって、TCPの制限が顕著になってきたのです。このように、TCPの制限がWebサービスに影響を及ぼすことがわかってきたため、「TCP以外のプロトコルを使った方が良いのではないか」という議論が国際標準化の場でなされるようになってきました。Googleは、TCPの代替としてQUICという、Head of Line Blockingが起こりにくい新たなプロトコルを提案しています。また、WebRTCの方ですと、SCTP over UDPという、Head of Line Blockingが起きないプロトコルが提案されています。ただし、インターネットのあらゆる機器に影響があるため、TCPを代替するこれらのプロトコルの普及には、時間がかかると考えられます。

ユーザの体感速度を上げる

TCPの制限により、SPDYが速いとは一概に言えない状況の中で、Web開発者は、「速度とは何か」を今一度考える必要があります。結局は、全てのコンテンツをブラウザへダウンロードするということはそれほど重要なことではなく、ユーザへ、最低限見せなければならない情報を素早く見せる、つまり、ユーザの体感速度をあげることが重要になります。体感速度を上げる方法として、ファーストビューのレンダリングを高速化させ、ファーストビューに関係ない画像やスクリプトを後でダウンロードするという方法があります。これを実現する技術として、HTMLのResource Prioritiesというものがあります。これを使うことで、タグの中に、あるアトリビュートを指定するだけで、そのリソースを後から読み込むことができます。具体的には、後から読み込むようにしたいリソースについては、タグに属性「lazyload」を指定することで、そのリソースを後から読み込むことができます。

<img class='Backgrounds' id='BackgroundLevel1' src='Background1.png' />
<img class='Backgrounds' id='BackgroundLevel2' src='Background2.png' lazyload />

P2P通信を実現するWebRTC

WebRTCの特徴はP2Pにあります。WebSocketを使ってブラウザ間でメッセージのやり取りを行う場合、必ずサーバを経由して通信しなければなりません。WebRTCを使う場合は、サーバを介せず、ブラウザ間で直接データをやり取りすることができます。

P2P通信を実現させるためには、通信対象の端末のIPアドレスとUDPのポート番号を知る必要があります。しかし、通常は端末がNATの内側にあるため、インターネット上でやり取りをする際に必要となる、NATの外側のIPアドレスとポート番号を知ることができません。

NATの外側のIPアドレスとポート番号を知るために、WebRTCではICEという仕組みを使用するのですが、その中でSTUNサーバというものがあります。端末は、STUNサーバへUDPのパケットを送信すると、NATの外側にあるIPアドレスとポート番号を知ることができます。そのようして得られた自分のIPアドレスとポート番号を、通信したい端末とお互いに交換しあうことで、P2P通信を行うことができます。ただし、STUNサーバは、フルコーンNATのように、宛先のIPアドレスを気にしないNATでないと使用できないため、シンメトリックNATではSTUNサーバを使用することができません。ちなみに、大体の家庭のNATはフルコーンNATで、企業で使用されるNATはほとんどがシンメトリックNATです。

WebRTCでは、STUNサーバが使えない場合は、TURNサーバを使うようになっています。TURNサーバを使う場合は、WebSocketを利用してブラウザ間でデータをやり取りする場合と同様に、このTURNサーバを介してデータのやり取りが行われるようになります。同一セグメント内であれば、STUN, TURNサーバを使うことなくP2P通信を行うことができます。ただし、セキュリティの観点から同一LAN内のP2P通信が禁止されていることがあり、同一LAN内であってもP2P通信を行うためにTURNサーバが必要になる場合があります。IPv6で通信が行われるようになると、NATが不要になるため、P2P通信のためにSTUN, TURNサーバが不要になると思われているのですが、NATの代わりとなるファイアーウォールが恐らく設置されることになると思いますので、ファイアーウォールを超えてP2P通信を実現させるために、STUNのようなサーバが必要になると考えられます。