次世代Webカンファレンス「HTTP2」レポート #nextwebconf

2015.10.19

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、虎塚です。

10月18日(日)、次世代 Web カンファレンスに行ってきました。イベントの趣旨は「「次世代 Web カンファレンス」を開催します - Block Rockin’ Codes」で公開されています。

午後2つめのセッション「http2」に参加したので、取ったメモを共有します。

HTTP2

2015年はHTTP2が登場

——Jxck_さん:HTTP2のRFCが今年出ましたけど、現状をふりかえってもらえますか。

jovi0608さん:2015年5月にRFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)RFC 7541 - HPACK: Header Compression for HTTP/2でHTTP2の仕様化が完了した。2014年11月時点でほぼ固まった状態のまま無事に仕様確定した。クライアントは主要ブラウザはほぼ対応しており、Webサーバの実装もnginx、Apacheモジュールなどすでに用意されている。goには言語に標準で入る予定。

——Jxck_さん:HTTP2対応サーバ実装の進捗を教えてください。

tatsuhiro_tさん:mod_http2は、nghttp2を使って実装されている。libcurlもnghttp2を使っている(参考: HTTP/2 with curl)ので、クライアントもサーバも手中におさめたといえる。(※tatsuhiro_tさんがnghttp2を開発されました)

kazuhoさん:H2Oはバージョン1.5でクライアントをみてサーバpushしたり、最適化したりした。ただ、HTTP2の機能を利用してHTTP1より速いWebを作れたかというと、まだまだこれからだと思う。

HTTP2でWebは速くなるか

——Jxck_さん:Jxckさん:HTTP2で速くなるとは本当でしょうか。どこが速くなるんでしょうか。どう考えていますか。

kazuhoさん:遅くなるケースもある。HTTP1だと同時接続は6本だったが、HTTP2になって100本張れるようになった。昔はWebブラウザからの接続で最初にhtmlを取得し、それからJavaScriptやCSS、最後に画像をとってきていた。いまはリクエストを送ると、ブラウザがリンクのURLを解析して、html、CSS、JavaScript、画像をすべていっしょくたにして返そうとする。これはSafariやIEで顕著。従来はJavaScriptとCSSがきた時点でレンダリングしていたが、それができないので、結果としてユーザがWebページを最初に見るまでの時間が遅くなる。

——Jxck_さん:multi plexing(多重化)がよくはたらく場合とそうでない場合ですね。

tatsuhiro_tさん:HTTP1と2をくらべて、ページロード時間は2で下がったが、最初の表示は1のほうが速いのはなぜかとよくいわれる。これは1つの接続で多重化されているためコンテンションを起こしているため。HTTP2には、一斉にロードするのでなくクライアントが優先度をつけるためのプライオリティという仕組みが入っている。検証不能なので仕様ではoptionalだが、実用上は必須と思う。サーバ側でプライオリティを解釈する実装があるのはH2Oやnghttp2くらい。サーバ側だけでなく、クライアント側もどのリソースを先に欲しいか伝えてほしいが、いまはFireFoxしかできない。

jovi0608さん:SPDYの時代、試験サーバに2000くらいのサンプルを置き、APIで同じページを同じクライアントでリフレッシュするベンチマークをとっていた。SPDYを使って速くなることも遅くなることもある。平均値でいうと1.1倍くらいだった。速度が下がる理由は、6本の接続なら1本落ちても6分の1だが、SPDYでは1本落ちると破壊的に全体がダメになるからではないか。速くするには1本のTCPにきっちりのせて多重化すること。プライオリティはHTTP2の最終仕様の1個か2個前に入った。HTTP2で知見を貯めて、その次の仕様でリファインされるのがあるべき姿かもしれない。

HTTP2をどのように使うべきか

——Jxck_さん:単純にHTTP2にすれば速いわけではないと。ではどう考えてどう使うべきですか? 体感的にどの程度答えが出ていますか?

kazuhoさん:ブラウザが優先度をつけられないなら、サーバ側でみてあげるスタンス。MIME TypeをみてCSSやJavaScriptを先に送り込む機能をH2Oではデフォルトでonにしている。Webサイトを作っている人のほうが、どのリソースのプライオリティが高いかブラウザよりも分かってる場合が多いし。

tatsuhiro_tさん;Chromeはプライオリティの実装がissueに上がっているので、やがて実装されるだろう。そうしないとFireFoxにまける。IEは、仕様策定の時点からむずかしいから実装しないという意見が多かった。IEには今後に期待。クライアント側の実装がそろうまではH2Oのようなやり方をするのはよいと思う。

kazuhoさん:Safariではネットワークスタックにはプライオリティを指定する仕組みがあるが、ブラウザ側で対応していない。比較的早く対応するかも。

jovi0608さん:HTTPのhead-of-line blockingが起きていること、6本の接続が埋まっていることを測定できている状況なら、HTTP2に移行するのは有効だろう。リクエストサイズが大きかったり、非同期でレスポンスが来るのを読まなかったりするようなものがページに散らばっているようであれば、やってみるといいかも。abベンチマークとってみるとよい。

——Jxck_さん:話題をプライオリティに戻します。ブラウザが対応しなければダメという話ですが、htmlの中でプライオリティタグを載せるような手もありますか?

kazuhoさん:スクリプトタグの中で「javascript?priority=high」のように書けるようにするのもありかなと思う。asyncでロードするリソースも、同期でロードするリソースもあり、MIME Typeを見るだけでは足りないのでクエリパラメータで補う。

——Jxck_さん:Resource Hintsも使えるかも。プライオリティ以外に使えるものはありますか?

jovi0608さん:プライオリティが万能だとは思っていない。SPDYのころは1〜6本の並列構造だったが(HTTP/2は優先度付きのツリー構造に対して) SPDYのころは、0~3の並列構造だったが、大規模になればなるほど優先順位付けして送れない場合も増える。手元に送るべきリソースがあって、うまくコントロールできるシチュエーションばかりではない。たとえば、CDNだったり、アプリケーションサーバやDBでリソースがまだ生成されていないこともある。プライオリティが最適化するのは、手元にリソースが揃っている場合。以前ブログにも書いたが、ソケットバッファに先に埋め込まれてしまうと、プライオリティを高くしても書かれた後ならどうしようもない(※ SPDYとLinuxの間でGoogleマップがハマった落とし穴 - ぼちぼち日記 でしょうか? 追記: Yes. TCP_NOTSENT_LOWATの話です、と本記事にコメントいただきました)。kernelチューニングがダイナミックにできるならいいが、TCP上でできることには限界がある。

tatsuhiro_tさん:それはそのとおり。プライオリティの高いリソースを送れなかったら低いものを送れ、でないと帯域がむだになる、と仕様にも書かれている。ソケットバッファの話は、Cでプログラミングしても、kernelでどれくらい溜まっているかわからなくて、writeをcallしてもう書けないといわれるまで書くしかないので困っている。

kazuhoさん:Linuxだとすぐ送れるサイズの2倍くらいバッファをもっているのでUDPにしようとか、いますぐ送れるデータ量をとれるシステムコールが追加されるべきとかいう話がある。

——Jxck_さん:RTT (Round Trip Time)の話がありましたが、そうそう減らせるものではないので、そもそもしないようにしようということで、サーバpushが出てきました。

tatsuhiro_tさん:HTTP2が1より優れているところに遅延の影響を受けにくいことがある。以前は6並列しかできなかったのが100並列できて、待ち時間が少ない。サーバpushが最初に導入されたのはSPDY時代。おそらく考えたのはGoogleさんだが、GoogleよりJettyの人たちが使いはじめた印象がある。HTTP2ではその延長で、サーバpushはクライアントキャッシュをアップデートするものと位置づけられた。クライアントが欲しいものはキャッシュに入るという考え方だ。HTTP1では接続コストが高いので、小さい画像をinliningしていた。キャッシュも効かないので、少しでも変更があると全部とらなければいけなかった。それをなくすためにサーバpushが入った。

kazuhoさん:飛行機内のように、サーバpushで速くなるケースもある。ただ、ふつうにWebサイトをみるときは500msecとか1000msecとか待つわけで、そこから1RTTを削ることは大きなインパクトではない。

jovi0608さん:サーバpushは仕様から削ろうという話もあった。クライアント側のキャッシュ状態がサーバ側の期待と一致しているかを調べる方法がないため、キャッシュの扱いが難しいから。ただ、bidirectionalは絶対必要だというのと、(RFCの) チャーターにサーバーpushを入れると書いてしまったのでなくせない、という背景があった。レイヤー7を見てキャッシュコントロールできるようになることを期待。そうすると今後広く使われるかも。

——Jxck_さん:HTTP2の特徴としてserver initiateというのがあります。

kazuhoさん:H2Oの最新バージョンでは、クライアントサイドでキャッシュ状態をcookieに入れ、サーバサイドでみて、必要に応じてデータをpushで送る。それによってさらに1RTT削る。

tatsuhiro_tさん:素晴らしい仕組みだと思う。pushしてキャッシュがあったらもったいないという話があるが、pushはもともとinliningの代替。HTTPbisのメーリングリストに、pushで帯域が埋まるよねという話を送ると、キャンセルもできるんだから前よりは悪くないと返ってくる。それくらいの感覚がベースラインだが、kazuhoさんはそれをもっとうまく使おうとしている。

kazuhoさん:効果の出るサイトと出ないサイトがある。TCPのパケットの届き方は一様ではない。数パケット先にpush対象のデータがきていたりすると差は出ない。

速さ以外にHTTP2を導入する理由

——Jxck_さん:HTTP2を入れれば速くなる場合もあるが、かならずしもそうではない、とわかってきたわけですね。ところでHTTP2は速さだけを目的としたものなのか。速さ以外にわれわれがHTTP2を採用する理由はあるでしょうか。

jovi0608さん:bidirectionになったので、サーバーイニシエイトのstreamが一旦つながったら、サーバとクライアントがイーブンな関係になる。

——Jxck_さん:それで何が変わるでしょうか。

jovi0608さん:クライアントサイドとサーバサイドの役割を変える。現在のセマンティックスを変えるので直近ではないが、世界を広げたといえる。

tatsuhiro_tさん:HTTP2はフレーム単位でやりとりする。これをベースに次の仕様に向けてリビジョンしやすくなった。HTTP1ではヘッダに追加するしか拡張方法がなかったが、HTTP2なら独自フレームタイプを定義できる。拡張ノブが増えた。いまのところhttpsしか使えないのも、セキュアに使うという意味ではいいと思う。

kazuhoさん:基本的に速くなると思っている。たとえいま問題があるとしても、解決されれば高速化される。その余地が生まれたのが大事。それ以外では、HTTP2にすることでサーバとクライアントの負荷が下がる。HTTP2では1本のTCPで複数くるので、1つのパケットにまとめて送れる。TCP接続ごとの負荷は上がってくるので、リクエストをまとめることができるのはメリットだ。

jovi0608さん:GoogleもSSL化の負荷よりも、リクエストを束ねてコネクションを減らしたメリットが大きいといっている。インフラの負荷をおさえる上でスケールメリットがあるのだろう。Twitterもそう。

ハイパージャイアント以外でもHTTP2を導入する価値はあるか

——Jxck_さん:ハイパージャイアントといわれるGoogleやTwittterくらい大きなデータセンターを持っていたり、ハードウェアエンコードを使うとかであれば、全体の負荷下がるでしょう。HTTP2はハイパージャイアントのものなのでしょうか。GoogleやTwitterの何千分の1の規模だとして、導入を検討する価値があるでしょうか。

tatsuhiro_tさん:小さなサイトでHTTP2を採用しないと明日生きられないかというとそんなことはないと思う。kazuhoさんがおっしゃったとおり、RTTの影響を受けにくいとか、パケット数が少なくなるとかの利点が、ほとんどフリーで手に入る。nginxも対応したしH2Oもある。最新のWebサーバをプロダクションに入れられるかどうかという意味では、あとはサーバ証明書の問題くらい。

jovi0608さん:HTTP2は、そもそもハイパージャイアントたちから話を聞いて仕様を決めてきた。使うかどうかは自由。速くするための制約条件の整理がこれからおこなわれるはず。新しい要件やスキームが出てくるかもしれない。

kazuhoさん:サーバ台数を減らせるのはハイパージャイアントにしかメリットがないというのは、そのとおり。ただ、GoogleやMicrosoftが5年前に発表したとおり、pingが少しでも遅くなると売上が1%落ちるというデータがある。もし1%の売り上げを大事にするなら、HTTP2を入れることでプラスの影響があるだろう。

——Jxck_さん:ハイパージャイアントでない自分たちも(高速化される)1秒がどうでもいいかというと、そうではないと。

tatsuhiro_tさん:HTTP2にするとシャーディングや結合が不要になるというが、HTTP2に最適化してWebサイトを作ればいいかというとそうでもない。1と2が混在しているので、動的に切り替える仕組みが必要という課題がある。

kazuhoさん:いつHTTP2オンリーのサイトを作っていいかというと、モバイルならiOS 10が出るタイミングだろう。サポートOSがiOS 9とiOS 10になり、HTTP2がデフォルトになる。

HTTP2に足りていないもの、HTTP2のこれから

——Jxck_さん:HTTP2に足りていないものはなんでしょうか。また、HTTP2のこれからは?

jovi0608さん:最近はHTTPbisを追いかけていないが、HTTP3の話はまだ出てきていない。話題の比重がTLS1.3に移っている。仕様の後半のappendixにcipherのブラックリストが100以上載っているのをみてもわかるとおり、まずはTLS1.3を作って、HTTP3なりQUIC (Quick UDP Internet Connections) なりを作っていこうというフェーズにある。HTTP2にTLS1.3が間に合わなかった問題(参考: いわゆる9.2.2問題: HTTP/2 9.2.2問題 - 株式会社レピダム )もあった。SSL3.0でも使えるべきだという議論もあった。使う際にいろいろベストプラクティスを取り入れないと、SSL LabでA+をもらえない状態なので、TLS1.3待ちの状態だ。

tatsuhiro_tさん:HTTP3がいつかはちょっとわからない。HTTP2を皆が使って問題点を出し、議論しなければ、まだ先になるだろう。プロトコルについては拡張しようという話もある。プロトコロル自体は双方向に投げられる仕様になっている。従来のクライアント/サーバ間通信に合わせるためにつけていた制限を取っ払うためのドラフトも出ている。

kazuhoさん:HTTP3でWebブラウザのさらなる高速化の話はある。電車の中でなかなかWebページが落ちてこないのは、パケットロスが起きてるため。QUICのように対応できるプロトコルが求められており、改善の余地がある。HTTP2に足りないものは、Request Responseモデルなので双方向でやりとりする形になっていない点。GRPCはHTTP2上のプロトコルなので、サーバとクライアントが同時に送れる。しかし、そのままではHTTP2にマッピングできないため、HTTP2のstreamを複数本張って対応している。だからGRPCはHTTP1では動かなかったり、特定のバインディングとがっつり組み合わさっていたりする。それらをベンダーが対応する時代ではないと思うので、HTTP2上でいろいろやる流れになりそう。

tatsuhiro_tさん:WebSocketはHTTP2で使えない。標準化の際に一時期活発に議論されたが、某ワーキンググループでいろいろあり合意が得られなくて、HTTP2が先にいってしまった。今後それがどうなるのか興味がある。

——Jxck_さん:1本でブロッキングしてしまう問題や、代替としてQUICをという話は、すでにITEFで話が上がっています。で、QUICについて説明をお願いします。

jovi0608さん:QUICは、Googleが独自に開発しているプロトコルで、UDP上でTCPとUDPのいくつかのコントロール機能を実装している。TCPのhead-of-line blocking、パケットロスすると再送まで全体が待たなければならなくなるのを解消したいという動機がある。また、TCPのハンドシェイクは通常3回のやりとりが必要で、resumptionでも1回多くしないといけないが、QUICでは再接続が1RTT0-RTTで済む。フローコントロールも、今はTCPのフロー制御の上にHTTPのフロー制御を重ねていていて無駄が多くので、1つのレイヤーで管理することで改善したい。やろうとしていることはレイヤーのリストラクチャリング。

——Jxck_さん:TCPがやっていることをUDP上でやって無駄を省くという話ですね。

kazuhoさん:HTTP2がそもそもSCCP(※)を無視してアプリケーションレイヤーで対処する方法をとったので、QUICはそれをさらに一歩すすめてパケットの再送も自分たちでしようというのは納得する。ハイパージャイアントにとって売上が上がる面もあるだろう。しかし標準化には時間がかかる。だからUDPで実装してしまおうというのは合理的。(※? 聞こえなかった&理解できなかった。どなたか補足をお願いします)

——Jxck_さん:TCPのハンドシェイクをなくすために標準化していくのは時間がかかるので、自前でUDPの上に実装するのはありうる、と。

tatsuhiro_tさん:QUICになるとstreamごとに色々できる。パケットロスの影響が個々のstreamに対する影響に変わる点も興味がある。また、IETFは伝統的にビッグエンディアンだが、QUICはリトルエンディアン。どうなるのだろうと思っている。サーバはほとんどリトルエンディアンなので、無駄な処理が1つ減るが。

——Jxck_さん:UDPの上にTCPがやってくれていたことを実装しなければいけなくなることについて、どうですか。

jovi0608さん:すごく大変。ちまちま作ってると終わらない。1万1000行でMSの人がプロトタイプを作ったらしいが、個人で作れる限界が見えてきている。TLS1.3ベースに変える流れがきているので、ライブラリを再利用できるとうれしい。

tatsuhiro_tさん:可能性はなくはないが、様々な分野のものが突っ込まれた。暗号化、HTTP2のようなもの、輻輳制御アルゴリズム、UDP、セッション管理など。

kazuhoさん:いつやるかの問題で。標準化が進んだらやったほうがいいと思っている。QUICでモバイルの環境はよくなると思っているので。デスクトップでは正直なくてよいと思っている。H2Oはファーストリリースまで1ヶ月だったが、QUICの実装には数倍かかりそう。暗号化はTLS1.3と共通化できそうではあるが、誰かがが書いてくれるのを待っていられるのか、という話もある。それに、QUICはゲーム制作者に期待されてる。TCPはパケットロスすると数秒後に応答が返るが、UDPは届いたら即/届かないとどうしようもない。そういう点でUDPで動くものとして期待されている。

Webはどこに向かっているのか?

——Jxck_さん:コンテンツを取得するだけでなく、もっと広がっています。telnetでGET /...していたのが、TCPですらなくなってきました。どこに向かっているんでしょうか? そして、いまだにHTTP1を使っていて、TLS化も完璧に終わっていない人たちからみて、HTTP2はついていかなければいけないムーブメントなのでしょうか。Webを取り巻くプロトコルの変遷はどうなっていくでしょうか。

jovi0608さん:90年代に広く普及したインターネットの技術的負債を返すフェーズかなと思っている。セマンティクス以外の部分についてはHTTP2が変えた。TLSも1.3ではメジャーバージョンアップに近いくらい手が入っている。負債を削り、新しいプロトコルを作るのと同じくらいの仕組みのアップデートがある。ブラウザやOSのアップデートも環境が整いつつある。技術的負債を返し終えたら、また新しい世界がくる。過渡期なのではないか。

——Jxck_さん:負債を返すことには歴史的必要性がありそうですが、もし使われなければ、新たな負債となりえないでしょうか。

jovi0608さん:われわれにとってはそこにプロトコルがあるからやってます感だけがモチベーション。一般の人にはそこまで必要ないので、細分化がすすむと思う。プライオリティ制御などもうまく扱うフレームワークがないと、作ったけど使われないプロトコルになるかもしれない。

——Jxck_さん:負債を返すのはどれくらいのスパンでしょうか。

jovi0608さん:HTTP1はずっとサポートし続ける形になると思う。1.1と(その時の最新版の)3だけ、5だけ、とか。

tatsuhiro_tさん:HTTP2はSPDYをベースにしているから2009年のテクノロジだ。プロトコルを実装する分量は増えたが、ユーザやアプリケーションサイドの複雑さはそれほどではない。プライオリティ制御は端っこに影響が出るものではない。バイナリプロトコルも皆使ってきたはず。telnetでなくcurlやWiresharkを使ってデバッグしていけばよい。手の届かない世界ではないと思う。

——Jxck_さん:Wiresharkでデバッグするとして、UDPで、かつ暗号化されててもやっていけるでしょうか? エコシステムはついていけるでしょうか。

tatsuhiro_tさん:初期実装はインセンティブがあるので皆競ってやってくれるはず。QUICはパケットヘッダを見るような実装をもう入れている人もいるし。

kazuhoさん:HTTP1はこの先もなくならないと思う。それで何が悪いか。FTPもHTTP1.0もいまだに使っているはず。そこにHTTP2やQUIC が追加されていくだけ。意味論ではかわらず、下のほうのプロトコルが変わるだけだ。

一同:Jxckさんはどう考えているんですか?

——Jxck_さん:

  1. 早く進化していて意味があると思うが、実装する側はともかく、使う側がついていけるかが怖いところだと思う。HTTP1.1はなくならないのだから、そこに居続けるのは罪ではないが、エコシステムの中心が移った時に取り残されることになる。それを容認できるくらい、留まっていられるだろうか。
  2. Webを勉強するコストが上がっている。Wiresharkで覗いて「GET」と書いてあればGETしているとわかった世界から、パケットを複号するところから入らなければならない世界へ。
  3. セマンティクスは変わらず過去の互換として残すというのは、今は英断だが次の負債になるのではないか。セマンティクスは進化しなくてもよいのか。今と違うWebの形になった時には、もう今の延長ではないのでは、という気がしている。本当についていけるのかとしつこく聞いているのは、そのままの形ではいられないと感じているからだ。

jovi0608さん:ホワイトボックスになっただけだと思う。学ばなければいけないことが増えた。

——Jxck_さん:学習コストについては各位がんばれでいいのか (笑)

tatsuhiro_tさん:先ほどのセキュリティのセッションであったように、新しいセキュリティヘッダが標準化されていくが、知っている人しか使っていいないというのと同じ話ではないか。おそらくすでにHTMLを教える時にタグだけ教えてもダメな時代で、attributeやWebサーバの設定まで必要だろう。HTTPのプロトコルはだいぶ背後に隠れているところなので、そんなに大きな影響が出るかどうか。セマンティクスは、HTTP2ではHTTP1との互換性をファーストプライオリティでキープしたが、2から3へいく時には変わるかもしれない。今は緩衝材としての期間かもしれない。

kazuhoさん:HTTP-NGの時は多少セマンティクスをいじりたいという話があり、それもあって上手くいかなかった。だから段階的に変えるために互換性を重視している。とはいえWebのセマンティクスはここ20年変わっていないので、今更変わるのか疑問。学習コストについては、通信プロトコルは変化が遅くて、JavaScriptのライブラリが登場するような勢いで毎年新しいプロトコルが出てくるわけではないので、気にしなくていいよ!

おわりに

HTTP2が利用者にもたらす恩恵はなにか、利用者はHTTP2にどういうスタンスをとるべきか、といった点を追求しようというJxckさんの想いから(というのは想像ですが)議論がドライブされ、HTTP2実装について素人でも、非常に興味を持って聴きいったセッションでした。

HTTP2に移行もしていない段階でその次というのは自分には想像もつかないですが、サーバの実装をされている登壇者の皆さんは、過去と現在の延長として、すでに手の届くものとして議論されていました。興味深い未来のお話を聞かせていただき、ありがとうございました。

それでは、また。

ほかのセッションのレポートは、こちらです。