HTTP/2とHTTP/3はいずれも、1つの接続上で複数のリクエストとレスポンスを並行して扱う「多重化」に対応しています。しかし、HTTP/2はTCP上で動作するのに対し、HTTP/3はUDPを基盤とするQUIC上で動作します。このトランスポート層の違いは、特にパケットロスが発生した際の通信性能に大きな違いを生みます。
重要なのは、HTTP/2にもストリーム単位の多重化はあるものの、その下にあるTCPでは1本の順序付きバイトストリームとして処理されるという点です。HTTP/3ではQUIC自体が複数の独立したストリームを扱えるため、あるストリームのデータが失われても、原則として無関係な別ストリームの処理を継続できます。
HTTP/2の多重化とTCPの関係
HTTP/1.1では、通信の並列性を確保するために複数のTCP接続を利用する方法が一般的でした。HTTP/2では1つの接続の中に複数の「ストリーム」を作り、それぞれのHTTPリクエストやレスポンスを並行して送受信できます。
たとえばWebページを表示するときにHTML、CSS、JavaScript、画像A、画像Bを取得するとします。HTTP/2なら、これらを複数のHTTP/2ストリームとして1本のTCP接続上で並行してやり取りできます。そのため、HTTPレベルではあるレスポンスが完了するまで別のレスポンスを待つ必要がありません。
ところが、その下で使われているTCPは受信データを順序どおりの連続したバイト列として上位層へ渡す仕組みです。この性質が、パケットロス時にはHTTP/2の弱点になることがあります。
HTTP/2でパケットロスが起きると何が問題なのか
TCPでは送信したデータの一部が失われると、その欠損した部分が再送されて受信されるまで、後続データをアプリケーションへ順序どおり渡せない状況が発生します。これがトランスポート層におけるHead-of-Line Blocking(HOLブロッキング)です。
ここで重要なのは、HTTP/2のストリーム自体は論理的に独立していても、すべてが同じTCP接続を共有していることです。あるHTTP/2ストリームに関係するTCPデータが失われた場合でも、TCPから見ればHTTP/2のどのストリームのデータなのかは関係ありません。欠損したバイト列を復元する必要があります。
例えばストリームAがHTML、ストリームBがCSS、ストリームCが画像を運んでいるとします。ストリームCに関係するデータを含んだTCPセグメントが失われたとしても、その後に届いたAやBに関係するデータまでTCPの順序制御によって上位層への受け渡しを待つことがあります。つまり、HTTP/2でアプリケーション層の多重化を実現しても、TCPレベルのHOLブロッキングは残るわけです。
HTTP/3ではQUICのストリームが独立している
HTTP/3ではTCPではなくQUICが利用されます。QUICはUDP上に構築されたトランスポートプロトコルで、信頼性のある通信、輻輳制御、暗号化、複数ストリームなどの機能を備えています。
HTTP/2との大きな違いの一つが、QUICではストリームごとに順序制御を行えることです。QUICパケットが失われ、その中にストリームAのデータが含まれていた場合、ストリームAは不足データの回復を待つ必要があります。しかし、必要なデータがそろっているストリームBやストリームCまで同じ理由で待たされる必要はありません。
言い換えると、HTTP/2では「HTTPのストリームは別々でも、その下のTCPという一本の順序付きバイト列を共有する」のに対し、HTTP/3では「QUICの段階から独立したストリームとして扱える」という違いがあります。
パケットロス時のHTTP/2とHTTP/3を具体例で比較
3つのHTTPレスポンスを同時に受信している状況を考えると違いが分かりやすくなります。ストリームAでHTML、ストリームBでCSS、ストリームCで画像を取得しているとします。
| 比較項目 | HTTP/2 | HTTP/3 |
|---|---|---|
| 下位プロトコル | TCP | QUIC(UDP上) |
| HTTPの多重化 | 対応 | 対応 |
| トランスポートのデータモデル | 単一の順序付きバイトストリーム | 複数の独立したストリーム |
| 一部のデータが失われた場合 | TCPの順序制御により無関係なHTTP/2ストリームにも待ちが波及し得る | 原則として影響をデータが失われたQUICストリームに限定できる |
| トランスポート層のHOLブロッキング | 発生する | ストリーム間では回避 |
たとえば画像を運ぶストリームCのデータの一部が失われた場合、HTTP/2では同一TCP接続上の後続データがTCPの再送・順序回復を待つ可能性があります。一方、HTTP/3ではCの不足データを待っている間にも、AやBについて必要なデータが到着していれば処理を進められます。
この差はパケットロスが比較的起こりやすいモバイル回線やWi-Fiなどで特に意味を持ちます。ただし、HTTP/3だからパケットロスそのものがなくなるわけではありません。失われたデータについてはQUICでも回復処理が必要です。改善されるのは、1つのストリームの損失による待ち時間を、無関係なストリームへ波及させにくいことです。
QUICでもHOLブロッキングが完全になくなるわけではない
「HTTP/3ではHOLブロッキングがない」という説明は少し単純化されています。正確には、QUICによって異なるストリーム間でTCP由来のHOLブロッキングを回避できると考えるのが適切です。
同じQUICストリーム内ではデータの順序が重要です。そのストリームに必要なデータが失われれば、後続データが到着していても、そのストリームの処理では不足部分の回復を待つケースがあります。つまり「ストリーム内部の待ち」まで消滅するわけではありません。
また、ネットワーク全体でパケットロスが発生すれば輻輳制御などの影響も受けます。したがって、HTTP/3を「ロスが起きても速度が一切低下しないプロトコル」と理解するのは誤りです。
HTTP/3では接続確立の遅延も改善されている
HTTP/3とQUICの利点はHOLブロッキングだけではありません。従来のHTTPS通信ではTCP接続を確立したうえでTLSによる暗号化通信を確立する必要があります。一方、QUICではTLS 1.3の仕組みがプロトコルへ統合されており、接続確立に必要な往復回数を減らせるよう設計されています。
さらに、過去に通信したことがあるサーバーとの接続では条件を満たせば0-RTTを利用できる場合があります。ただし0-RTTにはリプレイ攻撃への考慮が必要で、すべてのHTTPリクエストを無条件に0-RTTで安全に送信できるという意味ではありません。
QUICにはConnection IDという仕組みもあり、端末のIPアドレスなどが変化した場合でも接続を維持しやすくなっています。例えばスマートフォンがWi-Fiからモバイル回線へ切り替わるような環境でメリットを得られる可能性があります。
HTTP/2とHTTP/3の違いを理解するポイント
HTTP/2とHTTP/3を比較するときは、「どちらも多重化できるのに、なぜHTTP/3が必要なのか」という視点で考えると理解しやすくなります。HTTP/2はHTTPレベルのHOLブロッキングを大幅に改善しましたが、TCPという単一の順序付きバイトストリームを利用する以上、TCPレベルのHOLブロッキングが残りました。
HTTP/3はこの問題をHTTPの機能だけで解決するのではなく、トランスポートをQUICへ変更しました。「HTTPのストリームを分ける」だけでなく「トランスポート層でもストリームを独立させる」ことが、パケットロス時の違いを生む中心的なポイントです。
HTTP/2・HTTP/3・QUICの仕様をさらに確認する場合は、IETFが公開しているHTTP/2のRFC 9113、HTTP/3のRFC 9114、QUICのRFC 9000が一次資料になります。[HTTP/2:RFC 9113] [HTTP/3:RFC 9114] [QUIC:RFC 9000]
まとめ
HTTP/2とHTTP/3はどちらも複数のHTTPストリームを多重化できますが、その土台となるトランスポートの構造が異なります。HTTP/2はTCPの単一の順序付きバイトストリームを共有するため、パケットロスによる再送待ちが無関係なHTTPストリームにも影響する可能性があります。
HTTP/3が利用するQUICでは複数のストリームが独立して管理されるため、あるストリームでデータ損失が起きても、原則として正常にデータを受信できている別ストリームは処理を継続できます。これにより、TCPで問題となっていたストリーム間のHOLブロッキングを回避できます。
ただし、パケットロス自体や同一ストリーム内での再送待ちがなくなるわけではありません。HTTP/3の本質的な改善点は、「損失をなくすこと」ではなく「あるデータの損失による待ちを無関係なストリームへ広げないこと」にあると理解すると、HTTP/2との違いを正確に捉えられます。


コメント