Block Rockin’ Codes

back with another one of those block rockin' codes

なぜ QUIC や SPDY が生まれたのか ?

Intro

Google が SPDY の開発を始めたのは 2009 年で、 2012 年に HTTP2.0 のドラフトとして採用されたあたりからちょっと話題になりました。
翌 2 月には新たなプロトコル QUIC の存在が Chromium のソースからリークしたのですが、しばらくは音沙汰なく。
6 月に入ってやっと Google から公式アナウンスとドキュメント類が出ました。


去年から今年にかけて立て続けに出てくる新しいプロトコルの話。
なぜ今 Web のプロトコルが見直されるのか?
何が問題で、なぜ Google はそれらを作り変えるのか?


SPDY や QUIC は Google の独自プロトコルだけど、それは本当にただの独自プロトコルで終わらせていいのか?
20% ルールで作ってみた Play プロジェクトでしかないのか?


こうした新しい動きには、かならず「それまで」と「今」を踏まえた議論が起こります。
つまりこれらを追うと、「今何が起こっているのか?」を知ることができて非常に得るものがあります。


プロトコルの解説は何度か書いたけど、そういう話をもう少し書いてもいいかと思い
自分がわかる範囲でちょっとつらつらと書いてみようかと思います。

Web を速くするということ

単純にWeb を高速化するといっても様々なレイヤがあります。
たとえば、ぱっと浮かぶ範囲でも以下のようなものがあります。

  • A, Web アプリ/システム/サービスの高速化
  • B, ブラウザ、サーバプロダクト、カーネルのネットワーク周りなどの高速化
  • C, ネットワーク機器などの高速化
  • D, ネットワーク帯域などのインフラの強化


A は、 Web アプリがあってそれが遅いから速くしようとした場合です。
ISUCON で行われているようなチューニングなんかが浮かぶでしょう、これは一般の開発者にとって一番手を出しやすいレイヤになります。自分のアプリなので、アップデートもしやすいです。


B は、 Chrome が速くなる Nginx が速くなるとかといったレイヤです。
OSS であれば、パッチを投げることで貢献はできますが、自分のプロダクトに手を加えるのと比べれば多少敷居は上がるかもしれません。アップデートは定期的なものになり、多少時間が必要なります。


C は、 アプリの開発者からは通常意識されないレイヤで、ネットワーク上の機器とかそういうレイヤになりますかね。 PC 自体の NIC とかも入るかもです。本格的にハードがからんでくるので、アップデートはより時間がかかるし、なかなか手を入れることも難しい部分になってきます。


D は、通常一般の開発者では手が出ないレイヤです。ネットワーク事業者などがインフラに投資をすることで、改善していきます。わかりやすいのは帯域の改善などです。サイクルは、、ものによるとしか言えないかもです。


さて、これらの改善は、独立して実施できます。つまり、それぞれが別々に努力をして改善でき、それらが組み合わさって全体を「速く」することができます。


なぜ、独立で実施できるか。これはネットワークの世界にレイヤの考え方があり、各レイヤに「約束事」としての標準プロトコル/フォーマットが存在するからです。担当するレイヤの中で、プロトコル/フォーマットに従って実装をしていれば、「相互接続性」が保たれ、プロダクトなどをアップデートしても「Web が壊れる」ことを防ぐことができます。これが、プロトコル/フォーマットを「標準仕様」として定義するメリットです。


独立で実施できるということは、大げさにとらえると、あるレイヤが改善すればボトルネックは他に移ります(アプリが十分に早ければ、ネットワークがネックになるなど)。そして、各々のレイヤで改善が進むと、最終的にボトルネックは、そのレイヤをつなぐプロトコル/フォーマットに移っていく場合があります。今回一番絡んでくるのは、「どんなに帯域とアプリが早くても、 HTTP がボトルネックになる」といったパターンです。


このレイヤ、標準プロトコル/フォーマット自体の改善は、先ほどのリストに加えて E としておきましょう。
標準仕様の改善などにあたるので、 IETF や W3C などに参加することで貢献はできます。一般の技術者には敷居が高いでしょう。またステークホルダが多いので、議論も多岐にわたり、決まっても普及に時間がかかる場合が多いです。

Make the Web Faster

Google は、 Make The Web Faster というプロジェクトを実施しており、そこでは Google というポジションだからこそできる Web の改善方法の開発や、仕様の提案を行っています。(以下、長いので単にプロジェクトと言ったらこれを指すとします。)


Page Speed というプロダクトは、先の A にあたります。 Apache のモジュールなどとして提供されていて、自分のアプリに取り込めば、「ハイパフォーマンス Web サイト」にあるような改善の補助をしてくれるものです。その内容を、ベストプラクティスとしてまとめたものも公開されています。


最近すっかりシェアを伸ばした Chrome が速くなるのは、 B にあたるでしょう。まあ、 Chrome の改善は Google が普通にやっていることで、 Make the Web Faster にリストされているのは、 Chrome の Analyze 機能の改善になっています。


Google が提供する DNS や CDN もプロジェクトに含まれています。 Google の強力なインフラをベースとしたもので、 C や D に含まれると言えそうです。


では E にはどういったものが含まれるのでしょうか?

Google が取り組む Protocol / Standards の改善

E の中身として Make the Web Faster には Protocol / Standards が分けてのせてあります。

Standards

Web はネットワークを介すので、送信するファイルのサイズは小さいほど有利です。そして、サイズが大きいファイルの代表が画像と動画でしょう。
WebP は、 PNG や JPEG といった Standard な形式よりも、効率の良い圧縮形式です。 Facebook なんかも使い始めていますが、まだ対応したオーサリングツールなどがなくてちょっと問題になったりしています。
標準的なフォーマットを変えるのはまた難しいものですが、これもプロジェクトの一つです。
(ちなみに、動画版の WebM もあります。あまり詳しくないのですが、これはコーデック問題とかそっちが主眼みたいで、プロジェクトにはリストされていません。)


画像や動画に限らず圧縮率が高いことは有利です。圧縮を有効にすると、こまごましたミニファイが誤差程度になるほどには効率が良くなる場合があります。で、この圧縮の定番である gzip を改善したのが Zopfli です。 プロジェクトには上がっていませんが、圧縮に多少時間がかかる代わりにサイズが 3-8% 小さくなる、展開時間は同じ、というもの。圧縮は Web だけの問題領域ではありませんが、モチベーションは同じかなと思っています。


他には、 HTML5 まわりで W3C に貢献すること自体、プロジェクトの一環としても位置付けられているみたいです。(まあ、これもプロジェクトを超えて、 Google 自体の大きなミッションでしょうが。)

Protocol

先ほどの D の改善で、例えばネットワーク帯域が増えたとき、動画や大きなファイルのやり取りの改善は期待できますが、小さいファイルの集合である Web ページの読み込みの改善は限界があります。


実際 Web ページについて言えば、帯域よりも RTT の改善の方が効果が大きいことが、 Google の調査からもわかっています。


RTT の改善は、要するに行って返ってくるまでの時間の短縮ですが、これは物理的な距離なども関係するので改善は難しいです。


Web ページの取得には、 DNS 名前解決、 TCP 接続(3-way-handshake)、 HTTP req/res などが必要になり、増えるほど RTT の総和は長くなるので、そもそも「RTT の数を減らす」というのが現実的なアプローチです。アプリ側でファイルを統合するなどの方法がそれにあたりますが、そもそもプロトコル自体を見なおせば、もっと減らせるかもしれません。


HTTP はそもそも、論文の共有などを目的に作られたシステムなので、設計もテキストドキュメントの共有に寄せた仕組みとなっていました。
これ自体は、重要な設計思想だったと思います。扱いやすいテキストプロトコル、スケールさせやすいステートレス性。シンプルなデザインだったからこそ、 Web はここまで普及したと言えるでしょう。


問題は、 Web 自体が十分すぎるほどに普及した今、アプリ/システム/ゲームなどのプラットフォームとして使われ、単一ドキュメントの閲覧に留まらない様々な用途に使われるようになった今現在において、そのデザインは本当に最適か?ということだと思います。


通常、標準プロトコルに手を入れるのは、接続性がなくなるために簡単にはできません。しかし、 Google は多くの Web サービスとともに、クライアントとなるブラウザも持っています。両方を備えかつユーザ規模も大きい Google は、Google のサービスに Chrome で接続するユーザにだけ、オレオレプロトコルで大規模な実証試験を行うことができたのです。

SPDY とはなんだったのか


Web の根幹を成すプロトコルに手を入れる取り組みが SPDY です。現在では Chrome と Google のほぼすべてのサービスが対応し、大規模に運用されています。


独自プロトコルとはいっても、あまり標準から外れたパケットを流すと、 intermediaries (proxy や FW など中間に入るもの) をうまく通れない可能性があります。SPDY がデフォルトを SSL にしているのはそうした意味もあります。暗号化しちゃえば中で何が流れても中間ではわからないですし、変にいじられることもありません。また 443 は 80 と並んでほぼ通るポートです。 npn というアップグレードの仕組みも Google の提案したもので対応が多いのもあるし、そもそも Google 並のサービスだとセキュリティ的に全部 SSL の方がいいという判断も絡んでいると思いますが。


SPDY にはいろいろなアイデアが盛り込まれていますが、ここではTCP 接続の扱いに着目しましょう。
HTTP/1.0 では、毎回接続し、毎回切っていました。ドキュメントを取得して表示する用途であれば、まあ自然といえば自然です。
しかし、ページを構成するコンテンツ(CSS, JS, Image)が増えると、毎回切って 3-way-handshake からやり直すのはやはり無駄です。そこで、 HTTP/1.1 では Keep-Alive で確立した TCP 接続を使いまわすようになりました。
使いまわすといっても、繋ぎっぱなしは負荷が増えるので、ページのコンテンツ全部を落としたら切断したいところです。しかし、ページ単位でのライフサイクルの管理は容易ではなく、 Apache などでは「時間」「アクセス回数」などのわかりやすい指標で設定されているのが現状のようです。


あと、せっかく使いまわせても、前のレスポンスが終わらないと次のリクエストを投げられないという仕様があり、 1 本のリクエストを使いまわすと逆に遅くなる場合がありました。これを解決するのが pipelining という仕様だったのですが、対応が難しく、しかも対応していないサイトは崩れることがあったため、ブラウザもオフのものが多かったのです(Opera は有効だったけど、無効にしているユーザが多いみたい)。
また、やったところでそんなに速くならないという話もあったり。


pipelining は10 年近くたっても普及しきらず、ブラウザベンダはたくさんの TCP 接続(6 本がメジャー)を同時に確立することで並行してコンテンツを取るように実装しました。仕様では、同一サイトには 2 本位にしようね、という推奨があるのですが、守っていると他のブラウザより「遅い」というレッテルを張られかねないので、ベンダとしてはしょうがない選択だったのでしょう。(よって 1 ドメインには 6 本までの制限ですが、別ドメインだともう 6 本確立できます。静的ファイルなどはサブドメインや別ドメインのCDN に置きましょうという最適化手法はここからきます。)


SPDY は、 1 本の接続を極力使い切る設計になっています。具体的には、コネクションの上に「ストリーム」という論理的な接続を作り、それは多重化されています。たとえば 3 つのコンテンツの取得は 3 つのストリームを確立して行い、取得が終わっても終わるのはストリームでコネクションはそのままですし、ストリームの順番も自由なのでたくさん接続を作る必要もありません(理想は)。 Keep-Alive + Pipelining + α なイメージです。


あと、一本の TCP 接続を使い続けることは、 TCP の性質上も有利です。
TCP は、輻輳制御のため、最初は小さいパケットを送り、送るたびにそのサイズを増やしていく Slow Start という仕組みがあります。接続を毎回やり直すと、パケットサイズも毎回リセットしてしまいます。使いまわせば、送れば送るほどコネクションが温まって、輻輳が起きるまではパケットサイズが増えて効率がよくなります。


さて TCP を使いまわすという点では SPDY はだいぶ効率が良くなったと思います。でも、それって「接続が確立した後」の話ですよね。ただユーザにとっては「一番最初」の表示もやっぱり重要です。
Google は SPDY 以外にも、 TCP の層にまで下りた改善提案もあります。
例えば、 TCP の 3-way-handshake を Cookie を使って 1 回省略する TCP Fast Open という仕様や、送信する最初のパケットサイズを大きくする Increasing Initial Congestion Window などがそれにあたります(これもプロジェクトに入っています)。
実際は SPDY のレイヤだけでなく、 TCP のレイヤにも手を入れたいのが本音ですね。

TCP とはなんだったのか


TCP にも手を入れたいと考えた時点で、やっぱり TCP も HTTP と同様に「現在のニーズに合わないデザインなのかも」という疑問を持つのが正しい考え方なのかもしれません。
じゃあ、 TCP のデザインってなんだったでしょう?


自分のように、ネットワークをインター博士 に学んだ人なら、 TCP は「正確・確実」であると教え込まれたでしょう。
その通りで、 TCP の 3-way-handshake も輻輳制御も、ネットワークを通じて確実にデータを届けるための仕組みです。これがあったから、今ほどネットワークが良くない時代でも、データは確実にクライアントに届きました。「正確・確実」を実現するためにチェックやリトライの仕組みを持っていたのです。


SPDY はそんな TCP の上に多重化の仕組みを設けました。つまり、どんなにストリームを多重化しても、パケットレベルで落ちれば再送が走るし、輻輳が起きればパケットサイズは下がってしまいます。(HTTPでたくさん接続を作っていた頃は、一個の接続の影響は他には出なかったのに。)


3-way-handshake もなんとかならないものでしょうか、 Fast Open で速くなるのは Cookie ができた後、つまり本当に初対面のサーバとは無理なんですよね。


しかも、 TCP レイヤの改善は影響が大きいし、いじれる余地も少ない、なにより OS レベルの対応などになるので、普及にも時間がかかります(先の二つはもうカーネルには入っていますが、 Windows には無いです)。


そもそも「TCP の上に多重化レイヤ」という発想自体は、ネットワークプログラミングの視点から見ると筋の良いものではないといえます。TCP自体の性質のために、いろいろ不自由が出てしまうし、劇的な改善も見込みにくい。

そして QUIC へ


そこで、 Google は TCP ではなく UDP の上に Web を構築するという方針にも取り組み始めました。それが QUIC です。


UDP は、ご存じのとおり信頼性を担保するレイヤがありません。とにかく送りつけて、後はしらんというような仕組みです。そのため、映像の配信のような「ちょっとくらい欠けてもいいからどんどん送る」という用途なんかに使われるという説明が多いでしょう。


さすがにそのままだと、安定した Web の提供はできません。そこで QUIC は、独自に信頼性を確保するレイヤを UDP の上に構築しています。
具体的には、 TCP のようにストリーム全体に影響がないような輻輳制御や、再送を減らすための誤り訂正の仕組みです。
また、先の理由と同じく全体を暗号化するレイヤも自分で持っています。
その上に、多重化のレイヤを構築して、 SPDY を提供することによって、 TCP がボトルネックになっていた部分を改善して、 Web を提供できるのです。
(実際に QUIC を 443 ポートを通して、 HTTPS 上で提供できるようにするための実装が、Chromium では始まっているようです。)


つまり、 QUIC は SPDY over QUIC over UDPという手法をとることで、 SPDY over TCP の限界を突破するために考えられたプロトコルです。


公式にでたドキュメントからも、 QUIC が SPDY をまねた言葉遊び先行の Play Project ではなく、本気で Make the Web Faster を考えた上にたどり着いたプロトコルだと考えるのも、無理はないのではないでしょうか?


ちなみに、この改善の効果は未知数です、Google も完全に実装が終わっているわけではないようなのですが、 Google のユーザの多いサービス群と、シェアの大きい Chrome を合わせてそのうちテストが始まるでしょう。
(今は、 SPDY-Indicator も QUIC に反応できるようになっているので、もし QUIC サービスに気が付いたら教えていただけると幸いです。)

「なぜ出てきたのか」からの学び


QUIC は、それこそまだ Google のオレオレプロトコルです。 Google 自身もこれを標準にするかどうかといったところまでまだ考えてはいないでしょう。実績も効果も未知数ですし、実際にやってみないと本当に価値があるかはわからないのが本音だと思います。


同じように、他にも色々な改善案が Google 社内では動いているのかもしれません。


Make the Web Faster は Google が本気で Web を考えて取り組んだ成果が詰まっています。今すぐ取り込めるプラクティスもあれば、一般の開発者じゃ手が出しにくい Standard や Protocol にも大きなリソースを割いています。
そして、使わなくてもこうしたプロジェクトを知ることで、 Web が持つ様々な面(良さ、欠点)が見えてきます。


それがどういうデザインで、効果がどうかという点ももちろん重要です。
すぐ使えるか、対応はどうか、みんなが使っているかというのももちろん重要です。
でも、もう一つの側面として、なんでそんなものが出てくるのか?という視点を持つと、またいろいろ見えてくるなぁと。


で、今回は SPDY/QUIC 周りを見て思ったことを、連休のノリでなんとなく書いてみたところ話が伸びて、また長くなってしまったなぁという、、