Open4

HTTP1~3

KanoKano

以下の連載について自分なりにキャッチアップした内容の備忘録
https://gihyo.jp/admin/serial/01/http3/0001#sec3

HTTP/1.1

HTTPメッセージ構成

  • Keep-Aliveがデフォルト有効化されることで通信の高速化
  • TLS対応
    ※HTTP Keep-Alive:連続したリクエストに対して前回のTCPコネクションを流用する仕組み
    ※TCP Keep-Alive:通信開始後に相手からの通信が途絶えた際に相手が生きているか死活を確認する仕組み

HTTP/2.0

1.1では以下の課題があった

  • Head-of-Line-Blocking問題
    Keep-Aliveによって多くのリクエストを一度に送信できるようになったものの、レスポンスは必ずリクエスト順で返す必要があり、待ち時間が生じる
    2.0による改善点
  • メッセージの並列化
    ストリームという単位で1つのTCPコネクション上に複数の単位を構成し、それぞれの命令があたかも並列に動いているようにした。といいつつ、後述するがTCPではパケロス時や順番が入れ替わったときに再送が必須となるためストリームの遅延がほかのストリームへ伝搬する。
    ※あくまで動作自体は並列に送るのではなく、フレームという単位でメッセージを分割して直列にならして送る
KanoKano

QUIC

3.0の話に入る前にまずはQUICについて。
QUICはTCPやUDPと同じレイヤのトランスポート層のプロトコル。
従来HTTPの用いるTCPでは送信者がお明けっとを送信した順番通りに受信者がパケットを処理する必要がある。
パケロスが生じれば、再送が必要になり、パケットの順番が入れ替われば元の順番に整形する必要がある。その期間は待ち時間になりロスになる。
そこでHTTP/3では新しいプロトコルが求められ、QUICが開発された。

QUIC概要

  • UDPを用いる。※ただしUDPにはない信頼性を獲得している。
  • トランスポート層でのHead-of-Line-Blocking問題の回避
     パケロスが生じても受信している後続データが先にアプリケーションで伝搬される。
  • IPアドレスが変わっても通信可能
     電車などでネットワークが変わっても続けて通信が可能
  • 内部的にTLSを利用してトランスポート層の制御情報も暗号化

    サーバクライアントの両社がコネクションIDというものを保有し、IPアドレスではなく、コネクションIDを使って識別
    よってコネクション時にはコネクションIDの交換を行えばok

QUICパケット構造

  • パケット番号は送信者が採番し、パケットロスの判断に用いられる。
  • パケットには以下2つの種類がある

1.ロングヘッダパケット

コネクションを結ぶときに用いるパケット
信元コネクションIDと送信先コネクションIDの両方が格納される
以下の種類がある

  • Initial
  • 0-RTT
  • Handshake
  • Retry

2.ショートヘッダパケット

コネクション締結後にデータを送るときに用いるパケット
送信先コネクションIDだけ格納される
以下の種類がある

  • 1-RTT

フレーム

QUICパケットには1つ以上のフレーム(メッセージ)が格納される。
フレームには20個のタイプがある。
抜粋↓

ストリーム

QUICでは1つのQUICコネクション内に仮想的な通信監理単位であるストリームを複数保持する。
ストリームはストリーム単位で信頼性を保有するため、ストリーム内においてデータの順番は保障される。
また、ストリームの遅延はほかのストリームには伝搬しない

HTTP/2.0でやっていたことをレイヤ4でまとめて行っている。

また、ストリームには以下の2つがある。

  • 単方向ストリーム
  • 双方向ストリーム

QUICコネクション

1-RTTハンドシェイク

KanoKano

HTTP/3.0

ストリーム

HTTP/3.0ではQUICストリームを用いてメッセージをやり取りする。

単方向ストリーム

QUICの単方向ストリームを使う場合、HTTP/3.0では以下5つのタイプが存在する。

双方向ストリーム

HTTPメッセージの送受信に使うRequestストリームだけが定義されている。
常にクライアントからオープンし、リクエストとレスポンスを1つずつ送受信したらクローズされ、再利用はしない。

フレーム

HTTP/2.0同様にバイナリ形式のフレームというメッセージ形式を採用

フレームには以下7つのタイプが存在する。

通信シーケンス

### HTTP/3への対応確認

  • 対応確認を行ってから通信を開始する。
  • HTTP/3で用いるUDPPort番号は決まっていないのでポート番号を確認する必要もある。
  • 一度HTTP/1.1または2でリクエストを送信し、RFC 7838で定義されているAlt-Svcヘッダをクライアントに通知する。
    例(UDP50781ポートでHTTP/3を提供可能、maは情報の有効期限)
Alt-Svc: h3=":50781" ; ma=3600

### QUICコネクションの確率
指定されたポートに対してQUICコネクションのリクエストを行う

通信パラメータの設定

コネクション締結後、通信に関するパラメータを設定する。
まず、クライアントとサーバはそれぞれ1つづつ単方向ストリームのControlストリームをオープンし接続中ずっとつなぎ続ける。HTTP/3通信中はクローズ不可。

Controlストリームを用いてそれぞれSETTINGSフレームを送信し、パラメータを設定する。
※クライアントはSETTINGSフレームの送信が終わればサーバからのSETTINGSフレームの受信を待たずに次のステップに進める

HTTPメッセージの送受信

HTTP/3では、HTTPメッセージのフィールドはHEADERSフレームに格納される。
※複数のコンテンツが含まれる場合は1つ以上のDATAフレームに分けて格納される。

クライアントは双方向ストリームのRequestストリームを用いてHEADERSフレームとDATAフレームをリクエストとして送信し、サーバはレスポンスの入ったHEADERSフレームとDATAフレームを返却する。

HTTP/1.1と3のリクエスト比較

HTTP/1.1

GET /resource HTTP/1.1
Host: example.org
Accept: image/jpeg

HTTP/3

:method = GET
:scheme = https
:path = /resource
:authority = example.org
accept = image/jpeg

HTTP/1.1と3のレスポンス比較

HTTP/1.1

HTTP/1.1 200 OK
Age: 234274
Cache-Control: max-age=604800
Content-Type: text/html; charset=UTF-8

HTTP/3

:status = 200
Age = 234274
Cache-Control = max-age=604800
Content-Type = text/html; charset=UTF-8

通信の終了

ControlストリームでGOAWAYフレームを送信し、切断の準備を行う。
QUICでの即時クローズを行う(QUICのCONNECTION_CLOSEフレームを送信)

QPACK(ヘッダ圧縮)

HTTP/2ではHPACKを使ってヘッダ圧縮していたがHTTP/3ではQPACK

serverプッシュ

リクエストよりも先にサーバがレスポンスを送る仕組み。

KanoKano

WebTransport

双方向通信においてHTTP/3を用いる上位プロトコル

MASQUE

通信のトンネリングに用いる
HTTP/3で接続を確立して、QUICコネクション上で別の通信をトンネリングする手法