今回は改めてHTTP/3とはどのようなもので、QUICとは何か、HTTP/2時代からの改善点と我々はHTTP/3の波に乗るべきなのかチェックしていきたいと思います。時がたち次世代Web通信プロトコル「HTTP/3」の標準化プロセスが完了し、2022年6月に「RFC 9114」となりました。既に基盤となる「QUICプロトコル」の標準化プロセスも完了し、RFC9000としてRFCとなりました。もうHTTP/3は無視出来ないところまできています。
HTTP/3の誕生と歴史
HTTP/3とは、HTTP/1.1 HTTP/2に続く新しいバージョンの約束事です。HTTP/1.1からHTTP/2は様々な点で劇的な進化を遂げましたが、HTTP/3はHTTP/2の根本的な課題をTCP・TLSの融合という形で解決し問題点を補うよう進化してきました。
HTTPの歴史
1991年:HTTP/0.9(HTTPの始まりGETメソッドしかなかった。)
1996年:HTTP/1.0(GET以外のメソッドが増えヘッダーやボディ、ステータスコードが誕生!セッションが生まれました。)
1997年:HTTP/1.1(通信効率化、Keep-Aliveの誕生。暗号化やバーチャルホスト、chunk送信などが爆誕)
2015年:HTTP/2(元祖SPDYプロトコルを元にストリームが誕生)
202X年:HTTP/3(いまここ)
HTTPのバージョンは1.0からという認識を持たれているかたもいるとおもいます。実は、HTTP/1.0はその前にドキュメント化されたGETしか存在しない決まり事の最初のアップデートでした。HTTP/0.9という名称はこの先のバージョンと区別をつけるために後からバージョン番号が決まりました。
そう考えると、HTTP/2誕生当初は劇的な変化だ!といわれてきましたが、HTTP/1.0も今では当たり前のレスポンスコードやヘッダーという新しい概念が生まれたので相当な変化だったことが分かります。そしてHTTP/1.1は通信の効率化や暗号化、データの送信方法などHTTP/1.0の進化版として生まれました。HTTP/2は平文であったデータの一部をバイナリ化してストリームという概念でデータの効率化、通信の多重化、Server Pushや優先度、圧縮といった新しい概念が加わり、約20年ぶりのUPDATEということもあって劇的な変化だ!といわれました。
そして、今度はHTTP/3です。HTTP/3は通信的に劇的な変化だ!とはおもっているのですがどちらかというとHTTP/1.0からHTTP/1.1に近いイメージで進化しています。
HTTP/3の主なメリット
圧縮技術やシーケンスの変更など他にも多数ありますが、その中でもユーザー目線で特徴的な事柄は以下の通りです。
- 最初の接続時・再接続時の通信削減
- TLS1.3 暗号化が必須
- パケットロス時の効率化
- ほとんどのデータが暗号化される
- UDPベースのQUICが使われている(ポートは443という決まりはない)
シンプルにいうとセキュアで通信が最適化されており、Web表示速度が速くなる可能性があるということです。
HTTP/2の時と同様に、環境によっては必ずしも早くなるとは言い切れませんが、Googleによるとそれなりの改善がされている結果がでており、既にYOUTUBEやGoogle検索など様々なサービスで採用されている実績があります。今後はHTTP/3の割合がHTTP/2よりも増えてくることは確実でしょう。
そこで、まずは広く普及しているHTTP/2ではなにが課題だったのか振り返ってみます。
TCPとHTTP/2の欠点
HTTP/2はHTTP1.1の問題を克服するため実に様々な改良がされました。そして、ブラウザが対応を発表するに従い、ほとんどのWebサーバー、レンタルサーバー事業者が続々とHTTP/2対応になりました。しかし、全て解決したとはいえなかったのです。
ヘッドオブライン(HoL)ブロッキング問題
ヘッドオブラインブロッキングとは、たとえば10個の画像があり、3つめの画像が大容量だったりレスポンスが返却されるまでに時間がかかると、4つめの画像ダウンロードに進まないといった現象のことをいいます。
昔、Web表示速度を早くするハック的な要素でブラウザが複数通信を張って他のリクエストに引っ張られないよう複数ドメインをつかって画像などにリンクしていたのをご存じでしょうか。これらは接続自体が複数発生するため、サーバー負荷や輻輳により回線の使用効率が低下するためよろしくはありませんでした。
HTTP/1.1ではKeep-aliveという機能をつかって、1度に多くのリクエストを送ることが出来るようになりましたが、Keep-aliveは送信した順番でレスポンスを返す必要があるため、やはり途中のレスポンスが遅いと後のレスポンスを返すことができないという問題が残っていました。
HTTP/2では従来までプレーンテキストであったHTTP1.1を大幅に変更しバイナリフォーマットとしたことによって、1つの通信内に仮想的なストリームを作成し多重化することで、HoLブロッキングを解消してきました。HTTP/2はストリームという単位でIDを付与することで通信を並列としていたため、先ほどのように大きな画像や遅いダウンロードがあっても影響はそのストリームの範囲内に収まります。
しかし、HTTP/2の完璧そうなストリームの多重化もTCPを利用していることにより完璧ではありませんでした。TCP接続はその仕組み上途中でパケットが破棄された場合、再度ネゴシエーションをして回復を図ります。この回復している最中の時間はHTTP/2であっても手出しができない領域となります。
よって、HTTP/2では遅延や再送がない通信環境においてHTTP1.1で課題となっていたリクエストの並列化はできても、TCPで再送処理が発生してしまうと結局の所引きずられHoLブロッキングと同じ現象がおこってしまう問題が残っていました。
上に立つモノが最大の権力ではないのがネットワークの世界
弊社と同様にネットワークの世界も上にたつものが最大の権力を持っているわけではありません。例えば1層であるネットワークケーブルが切断するとその上の方々はどうすることもできないのと同じように、TCP→HTTP(S)という順番がある以上、ネットワークの世界では低レイヤーのほうがむしろ権力を握っているといえます。このためHTTPレイヤー以下で待ちが発生してしまうと結局一番上にいるHTTP・HTTPSはどうすることもできないのです。
再接続が頻発する問題
これもHTTP/2の欠点というよりかは、HTTP/2が利用しているTCP通信に起因する問題です。TCPコネクションは3 Way handshakeを行いクライアントのIPアドレス+ポート番号、サーバー側のIPアドレス+ポート番号とプロトコルの合計5つの内容で管理していました。
そのため、例えば5Gから無線接続に切り替えや場所を移動して基地局が変わり先ほどのいずれかの情報が変更になってしまうと通信の再接続をやり直す必要があります。
優先度制御の複雑性
HTTP/2ではどのコンテンツを先にダウンロードするか?という優先度制御が実装されました。従来までは、HTMLに記載順にリクエストが発生するため、CSSは上のほうに、ファーストビューに関係無いJSは下の方に記載みたいな表示高速化コーディングがありました。HTTP/2では優先度という扱いが追加されたため、ブラウザとサーバーが自動でCSSは先に画像は後にと最適化してくれそうなのでコーダーが頑張らなくてもいいのでは??!と思われていました。
しかし、このツリー構造の優先度はブラウザーによって何を優先するのかというルールが異なっていたり、サーバー側も同様の実装をしなければ実質意図した通りの優先順位とならないことが多いという課題がありました。
サーバーPUSHの問題
HTTP/2で注目されたもう1つの機能がサーバーPUSHです。通常は、ブラウザであるクライアント側からこれちょうだい!とサーバーにリクエストして初めてサーバーは対象のコンテンツを送ることができました。
サーバーPUSHは、名前の通りクライアントからちょうだいといわれなくても、サーバー側からコンテンツをクライアントに投げつけることができます。たとえば、HTMLコンテンツをDBから取得するのに時間がかかるようなサイトの場合、HTMLがダウンロードされないことには、次のリソースである画像やCSS・JSはダウンロードされません。
この待ち時間の間にサーバーから他のリソースをクライアントに送ることにより、HTMLをGETした時点で既にCSSや画像はダウンロード済という感じになるわけです。すごいですよね。
ただし、そんなサーバーPUSHもサーバー側はクライアントの状態を知る術がないという課題があります。たとえば、サーバーから送信するコンテンツは既にブラウザがキャッシュしていたりダウンロード完了しているならばPUSH不要かもしれません。サーバーから問答無用でコンテンツを送りつけてしまうとお互いリソースの無駄になる可能性があります。
またHTMLが生成完了した後、コンテンツ送信からHTML送信への切り替えに時間がかかることから、平均的にサーバーPUSHは無効のほうがユーザー体験が上がるという結果になりました。このことからChromeではサーバーPUSHをサポートしないことになってしまいました。
QUICの仕組みと特徴
TCP通信を利用しているHTTP/2も改良が加えられているが、課題も残されていることがわかりました。これらの課題をまるっと克服するために2012年の頃最初の(g)QUIC(Quick UDP Internet Connections)という仕組みがGoogleによって開発されました。
QUICの歴史
QUICは最近突然でてきた仕組みではありません。QUICの最初の発表は2013年、近年まで様々な変化・議論がされておりQUICバージョン1.0となりました。当初はGoogleのQUICなのでGQUICと言われておりQUICは(Quick UDP Internet Connections)の略語とされてきましたが、2022年現在ではQUICという略称ではなく名称になっています。近年ではFacebookやほとんどのGoogleサービスで利用されていますがここまでくるのには長い道のりだったということがわかります。
In 2012, Google started working on QUIC
In 2013, Chrome started small-scale experiments with the original versions of QUIC (those versions are now known as Google QUIC)
In 2014, Chrome started a wide-scale deployment of Google QUIC
In 2015, Google brought QUIC to the IETF
In 2017, the IETF started creating versions of QUIC that diverged from Google QUIC (those new versions were then called IETF QUIC)
In 2020, Chrome started wide-scale experiments with IETF QUIC
In 2021, the IETF officially published QUIC as RFC 9000. Chrome added support for RFC 9000 in Chrome 90 and default-enabled it for all users in Chrome 93
※https://www.chromium.org/quic/?_fsi=Mu7I9hyJより
HTTP/3=QUICではない
QUICはトランスポート層という通信の階層で使われる仕組みのことで、その上にHTTPが位置しています。QUICはよくHTTP/3と一緒に解説されていますが、HTTP/3=QUICではなくHTTP/3はQUICというプロトコルをつかっているセマンティクスです。
GoogleのQUICでは独自暗号化が実装されておりましたが、これらを標準的なTLSに変更したものがIETF版のHTTP over QUICです。よってHTTP/3=IETF版のHTTP over QUIC といえるでしょう。
QUIC発表当初はGoogle版QUIC+HTTP/2という独自の暗号化を付与した仕組みがあったとおり、HTTP/3に限ったお話ではなくHTTP以外の用途でも活用が検討されています。
そうだ、TCP捨てよう。
インターネットの世界(トランスポート層)では主に2種類のプロトコルがある。信頼性重視のTCP(Transmission Control Protocol)通信と自由なUDP(User Datagram Protocol)通信だ。
TCPはコネクション型通信のため、通信する際様々なやりとりを行い通信の順番や信頼性を担保する。信頼性を担保するため通信のオーバーヘッドも大きい。よって、スピードよりも信頼性が必要なWeb閲覧やメール送受信などはTCPが使われている。
いっぽうで、UDPはデータ転送の際データ抜けが発生する可能性がありTCP通信のように信頼性を担保する仕組みがないため、データをどんどん送ることができ、オーバーヘッドが少ないことが特徴です。データの順番が多少保証されなくても動くようなDNSやNTP、DHCPといったサービスで利用される。近年ではVPN・オンラインMeetingの動画や音声部分なんかも利用されてきています。
このようにTCPとUDPはどちらが良いというわけではなく、通信する目的とサービスによって使い分けてきました。
前述の通りまず通信においては、TCPがそもそも問題ありということが明らかです。しかし、普及していない新しい仕組みを1からつくると、これらを普及させるには、OSが対応すること、世界のネットワーク機器やそれに付随するシステムもUPDATEが必要なことから何年かかるかわかりません。現にQUICも発表から数年かかってようやく普及の目処がたってきました。そこでQUICでは既に普及している自由なUDPをベースに開発されました。
初回接続の大幅削減
TCP通信は最初に信頼性を確保するため、3 way handshakeという約束事があります。これは名前の通り3回通信を行います。
さらにTCP+TLS(暗号化)通信の場合、この3 way handshakeに加えTLSで2回通信が発生し、最低5回もネゴシエーションが発生します。HTTPSでWebを閲覧する最初のステップでブラウザは様々なやりとりをして通信が問題ないと判断してから、HTMLコンテンツをGETするわけです。このネゴシエーションの最初の段階で何らかの問題で通信が切れてしまうと最初からまたやり直しとなるのがTCPのお決まりごと。
しかしQUICはUDPを採用しTLSを統合していることから、5回の通信をなんと1回まで削減します。単純に5倍通信が削減されたことになります。これらがHTTP/3は通信を最適化していると言われている理由の1つです。
下の図では従来のTCP左 TCP+TLS中央 QUIC右 となっており初回接続がいかにQUICで削減されているかわかるとおもいます。
0-RTT (Zero RTT)とは?
今ではHTTPS通信が当たり前となっておりますが、HTTPSを行う為にTLSを利用しています。暗号化の歴史としては以下の通りで現在最新版はTLS1.3になりQUICはこのTLS1.3を採用しています。現在ではセキュリティの都合上TLS1.2以上のみ対応としているWebサーバーやCDNが多く存在するため実質TLS1.2以下は利用されなくなりました。
- 1995年 SSL 3.0 (NetScape社)
- 1999年 TLS 1.0 (RFC 2246)
- 2006年 TLS 1.1 (RFC 4346)
- 2008年 TLS 1.2 (RFC 5246)
- 2018年 TLS 1.3 (RFC 8446)
TLS1.2では、初回接続時:2回・再接続時:1回通信が必要です。いっぽうで、最新版のTLS1.3ではFinishedメッセージのタイミングを変更し2回発生していた通信を1回に削減することができました。
TCP+TLSではそれぞれhandshakeが必要でした。しかしQUICではTLS1.3 EaryDataという仕組みを包括しつつトランスポート層とセキュリティを統合し一度接続が確立している場合再接続時はゼロラウンドトリップ(Zero RTT)つまり、通信しないためRTTがゼロということを実現しています。※RTTとはラウンドトリップタイムといい、往復遅延時間のことを指します。
再接続というのはたとえばスマートフォンを移動しながらつかったり、電波が悪いような環境で利用すればごくごく一般的に起こることです。よって、再接続時通信をしない0-RTTは強力な仕組みといえます。
強力なACKと再送制御でムダのないデータ再送
QUICはパケット番号を確認し一定の順番ではない(番号がぬけている)場合、パケットロスしたと判断し確認応答の送信を行います。この確認応答ACKには従来のACKよりも多くの情報をいれることができるようになったため、ここに再送が必要なデータはこれですと記載することができるようになりました。
この仕組みにより、パケット自体を再処理するのではなく、ロスしたパケットに含まれている再送に必要なデータ部分を新しいパケットとして再送することが出来るようになりました。
HTTP/2のTCP時代、TCPが切断されると上位のHTTPに影響がありました。そのため、QUICはTCPと同じような信頼性機能を追加しつつ、最初からストリームの多重化を前提として作られています。よって、パケットロス時も並行して他のパケットを処理できるようになり本当の意味でHoLブロックを回避しています。
通信の継続性(Connectin Migration)
QUICはConnection Migrationという機能により、2つの可変長ID(RFC9000)を使用してIPアドレスやポート番号が変更されても同じ通信を継続できる仕組みが実装されています。これにより電車に乗ってる最中にスマートフォンでブラウジングするような環境では根本的に再接続の削減が期待できます。
- クライアントがPATH_CHALLENGEフレームを送る
- 受け取ったサーバーはPATH_RESPONSEフレームを返す
- 新しい経路を作成する
- 古い経路を削除する
トランスポート層の制御コードを含めた暗号化
TCPの場合は暗号化は下の階層のTLSに任せていましたが、QUICではQUICパケットにTLSメッセージをいれてクライアントと鍵を共有し暗号化を行うため内部的に利用するところが大きな違いです。これは、再送・切断等のメッセージ制御コードも含めて暗号化できることを意味するためHTTP/2のTLS時代と比べるとよりセキュアになったといえるでしょう。
HTTP/2はTLSと別であることから、厳密にはHTTPでもHTTP/2は動く仕様でした。実際はブラウザがHTTP/2を利用するためにはTLSが必須としていたため、実運用上HTTPでHTTP/2が利用されることはありませんでした。しかし、QUICはTLSを内部的に利用するためHTTP/2の時のようにHTTPでOK!というわけにはいかず暗号化が必須になりました。
HTTP/3の特徴
HTTP/3はQUICを使う事により、初回接続時と再接続時・パケットロス時の大幅な効率化ができていることがわかったとおもいます。次は、QUIC以外の特徴もみていきましょう。
HTTP/3の優先度制御
HTTP/2では複雑な優先度制御が故に普及が難しい状況でした。HTTP/3ではこれらをどうするか議論されてきましたが、最終的にHTTP/3の仕様から分離することがきまりました。
RFC 9218: Extensible Prioritization Scheme for HTTPでは以下の様に定義されています。
- Priorityヘッダーを利用する
- 優先度をUrgency Incrementalで表記する
- 優先度を更新する拡張フレーム(HTTP/2 とHTTP/3)
優先度通知の仕組み
クライアントは優先度をpriorityヘッダーでサーバーに伝えます。サーバー側もpriorityヘッダーでクライアントの優先度を伝えられます。そして、優先度にはレベルと種類があり、urgencyは0から7まで値が小さいほど優先度が高くなります。さらに、バックグラウンドで徐々に処理するIncrementalフラグもあります。
以下の例ではHTMLとCSSは最高優先度とし、画像は徐々に表示させるといった優先度を定義しています。
- HTML: GET / priority: u=1
- CSS: GET /style.css priority: u=1
- 画像: GET /redbox.jpg priority: u=4,i=?1
加えて、優先度は通信の途中でも任意にUPDATEすることができるようになりました。これにより、非アクティブになったタブのリソースは優先度を下げるなんてこともできるのではないでしょうか。
従来まではツリー構造で複雑化していた優先度の仕組みを無理矢理HTTP/3に実装するのではなく、簡略化してあえて分離したことにより、優先度制御はHTTPのバージョンに関係なく利用できるような方向へ進んでいます。
HTTP/3のサーバープッシュ
HTTP2/時代にもサーバープッシュがありましたが前述の通りリソースが無駄になる問題がありました。HTTP/3でもサーバープッシュはありますが若干仕組みがことなっています。HTTP/3では、PUSH_PROMISEフレーム内にPUSH IDとEncoded Field Section(リクエストヘッダー)があり、これらを受け取ったサーバーはヘッダー上にあるauthorityまたはpathといった情報をみてどのリソースをPUSHするべきか判断します。
ここまではなんとなくHTTP/2と同じように見えますが、HTTP/3のサーバープッシュはサーバーから送られてきた情報を元にクライアント側でサーバープッシュされてくるリソースを受け取るか、それともキャンセルするか判断できるところにあります。
従来まではキャッシュがあっても問答無用でサーバーからデータがPUSHされてくる少し強引な手段でしたが、通知する仕組みを実装したことにより、クライアント側でいりませんとキャンセルすることもできるためリソースの無駄にならないプッシュ方式に進化しました。
103 Early Hints
少し余談ですが、サーバープッシュに変わってよりクライアントが早くコンテンツを取得する方法としてプリロードが利用されることがあります。突然ですが200や404、503と同じように103というレスポンスコードがあるのはご存じでしょうか。
RFC8297の103 Early Hintsは、サーバー側で103レスポンスを行い同時にHTTPヘッダーでクライアントに情報を渡すだけ実施します。サーバープッシュのように勝手にBODYを送りつけないのです。
クライアントは103が返却されると、キャッシュがある場合はキャッシュをつかい無ければコンテンツをプリロードするといった動作が可能となります。
ちょうど2022年5月26日「Google Chrome 103」がベータ版に103 Early Hintsのサポートが有効となるアナウンスがされました。バージョン103でレスポンスコード103をサポートするなんて偶然とは思えませんが偶然のようです。
HTTP/3の開始通知方法
HTTP/2の時、サーバー側でHTTP/2に対応させ対応したブラウザでアクセスすると自動的にHTTP/2になりました。もしHTTP/2にならなかった場合は、いずれかが適切に対応していないという判断ができました。しかし、HTTP/3はUDPを利用していることもあり、クライアント・サーバー双方がHTTP/3に対応しただけでは機能しません。
ブラウザ側(クライアント)は初回接続時、サーバーがHTTP/3に対応しているかどうかHTTP/3以外の通信で確認し対応している場合はHTTP/3の通信を開始します。
HTTP/2 では TLS ハンドシェイクを ALPN 拡張 を使って直接ネゴシエーションしていたのですが、HTTP/3はQUIC上で動くため私はHTTP/3で動いています!とクライアントに適切なAlt-svcヘッダーを付与して通知してあげる必要があります。この通知をもってブラウザは初めて相手がHTTP/3対応なんだなと分かることになります。つまり厳密には最初からHTTP/3でブラウザはやりとりするのではなく、初回以降の通信からHTTP/3となります。
Alt-Svcヘッダー例:Alt-Svc: h3="443"; ma=3600
UDPではTCPのようにHTTPSは443のように決められていないため、通知する情報にはUDPのポート番号も必要です。こちらの例では、UDP443で通信しこの情報の有効期限は3600秒ですという意味になります。
なお、Alt-SvcヘッダーはHTTP/3のために定義されたわけではなく、既にRFC7838で定義されているものをHTTP/3は活用しています。
HTTP/3の対応状況
HTTP/3について2022年6月現在の対応状況を見てみましょう。HTTP/2の時と同様に、ブラウザもサーバーも双方に対応していなければ素晴らしいHTTP/3も利用することができません。
クライアント・サーバー側
みんな大好きCan I Useでみるとこのような状況でした。IEはいいとして、Safariがまだ未対応ということのようです。FirefoxやChromeはかなり前から対応済みなのはさすがといったところでしょう。
サーバー側は今後めまぐるしく変わる可能性があるため、詳細はIETF QUIC Interop Matrixを見て頂ければと思います。
主要箇所としては執筆時点でApacheは未対応・Nginxはプレビュー版で開発が進められています。なお、QUICバージョンの相互通信正誤表についてはこちらが便利です。
HTTP/3対応CDN
国内ベンダーもそうですが、グローバルでみてもまだまだ少ないのが現状です。
- レッドボックスのエッジキャッシュCDN(一応先頭に記載!)
- Cloudflare
- Fastly
- Akamai
HTTP/3対応Webサイトの確認方法
やはり皆さんHTTP/3に対応したら、本当にHTTP/3化しているか見たいものです。いやみますよね?ここでは、簡単に確認する方法をいくつかご紹介します。
Chromeデベロッパーツール
ChromeのLatest版でデベロッパーツールを開きプロトコルのセクションがH3またはHTTP3となっているかどうかチェックしてみて下さい。前述の通り初回リクエストではHTTP/3以外で通信するため、必ず2回アクセスして下さい。もちろん弊社メディア及び公式ページはHTTP/3 Quic V1に対応しています。
HTTP/3 Check
0-RTTに対応しているかやQUICの細かいバージョンを確認したい場合はLitespeedが提供しているサイトが便利です。さらにAdvancedというセクションではIPを直指定できるため、公開前の開発サイトをチェックするのに便利です。
QUICのログを確認する方法
QUICはQLOGという形式のログがありこれらを可視化できるqvisというツールがあります。
ログさえあればオンラインでも確認することができます。シーケンスやら色々みられるのでとても楽しいのは我々だけではないはずです。
HTTP/3まとめ
HTTP/3はUDPベースのQUICプロトコルを使うことによりHTTP/2+TCP時代の根本的な課題であった通信・再接続・再転送・サーバーPUSHなど様々な観点が改善されています。HTTP/3は今後正式版となりHTTP/2のように加速度的に普及していくことは間違いないため、我々はこの波にのらない理由はないというのが結論です。
今後、私たちがHTTP/3に対応するためには少なくともサーバー側のアップデートを行い、適切なHTTPヘッダーを付与し、UDPポートを許可する必要がでてきます。IDSや下位レイヤーで動作するセキュリティがある場合は、攻撃と検知されないかどうかも確認が必要です。よって、WebサーバーはそのままでCDNをつかってラップしてしまうという近年の流行にのるのも選択肢の1つです。
レッドボックスが提供する定額CDNエッジキャッシュは、ご提供から7年が経過する中様々な技術をいち早く取り入れてきました。HTTP/2については国内CDNベンダー初で早い時期の提供をして参りましたがHTTP/3も同様にプレビュー版を国産CDNベンダーとしていち早く提供しています。近日、ご契約ユーザー様全員対象として、HTTP/3有効化のボタンが管理画面に追加されますのでご期待下さい。