HTTPの進化
HTTPは、Webの基盤となるプロトコルです。1991年のHTTP/0.9から始まり、現在はHTTP/3まで進化しています。
flowchart LR
H09["HTTP/0.9<br/>(1991)"] --> H10["HTTP/1.0<br/>(1996)"]
H10 --> H11["HTTP/1.1<br/>(1997)"]
H11 --> H2["HTTP/2<br/>(2015)"]
H2 --> H3["HTTP/3<br/>(2022)"]
HTTP/1.1の課題
Head-of-Line Blocking
1つのTCP接続では、リクエストを順番に処理する必要があります。
sequenceDiagram
participant C as クライアント
participant S as サーバー
Note over C,S: HTTP/1.1 - 順次処理
C->>S: リクエスト1
S-->>C: レスポンス1
C->>S: リクエスト2
S-->>C: レスポンス2
C->>S: リクエスト3
S-->>C: レスポンス3
Note over C,S: 先のリクエストがブロックすると<br/>後続も待たされる
複数接続の必要性
並列性を確保するため、ブラウザは1ドメインあたり6-8本のTCP接続を使用します。
flowchart TB
subgraph Domain["ドメイン: example.com"]
TCP1["TCP接続1: script.js"]
TCP2["TCP接続2: style.css"]
TCP3["TCP接続3: image1.jpg"]
TCP4["TCP接続4: image2.jpg"]
TCP5["TCP接続5: image3.jpg"]
TCP6["TCP接続6: image4.jpg"]
end
Note["接続のオーバーヘッド、リソースの無駄"]
HTTP/2の特徴
多重化(Multiplexing)
1つのTCP接続で複数のリクエスト/レスポンスを並列処理できます。
flowchart TB
subgraph TCP["HTTP/2: 単一TCP接続"]
subgraph Requests["リクエスト(並列)"]
R1["Req 1"]
R2["Req 2"]
R3["Req 3"]
R4["Req 4"]
end
subgraph Responses["レスポンス(並列)"]
S1["Res 1"]
S2["Res 2"]
S3["Res 3"]
S4["Res 4"]
end
R1 --> S1
R2 --> S2
R3 --> S3
R4 --> S4
end
Note["並列処理、順序に依存しない"]
バイナリプロトコル
HTTP/1.1のテキストベースからバイナリフレームに変更。
flowchart TB
subgraph HTTP11["HTTP/1.1(テキスト)"]
Text["GET /index.html HTTP/1.1\r\n<br/>Host: example.com\r\n"]
end
subgraph HTTP2["HTTP/2(バイナリフレーム)"]
Header["Length | Type | Flags"]
StreamID["Stream ID"]
Payload["Payload"]
Header --> StreamID --> Payload
end
ヘッダー圧縮(HPACK)
ヘッダーを効率的に圧縮し、重複するヘッダーを省略します。
flowchart LR
subgraph First["1回目のリクエスト"]
F1[":method: GET"]
F2[":path: /index.html"]
F3[":authority: example.com"]
F4["user-agent: Mozilla/5.0..."]
F5["accept: text/html"]
end
subgraph Second["2回目のリクエスト"]
S1[":path: /style.css"]
S2["(他は前回と同じなので省略)"]
end
First --> Second
Note["ヘッダーサイズが大幅に削減"]
サーバープッシュ
クライアントがリクエストする前に、サーバーからリソースを送信できます。
sequenceDiagram
participant C as クライアント
participant S as サーバー
C->>S: index.html リクエスト
S-->>C: index.html レスポンス
S-->>C: style.css プッシュ(リクエストなしで送信)
S-->>C: script.js プッシュ
Note over C,S: RTTを削減
注意: サーバープッシュは実際にはあまり使われておらず、Chrome 106以降では無効化されています。
優先度制御
ストリームに優先度を設定し、重要なリソースを先に処理できます。
flowchart TB
subgraph Priority["優先度制御"]
S1["ストリーム1 (HTML): 優先度 高"]
S2["ストリーム2 (CSS): 優先度 高"]
S3["ストリーム3 (画像): 優先度 低"]
end
S1 & S2 --> Load["HTML/CSSを先にロード"]
S3 -.-> Load
HTTP/2の課題
TCPレベルのHead-of-Line Blockingは解決できていません。
flowchart TB
subgraph TCP["HTTP/2 over TCP"]
P1["パケット1 ✓"]
P2["パケット2 ✓"]
P3["パケット3 ✗ (パケットロス)"]
P4["パケット4 ✓ → TCP層で待機"]
P5["パケット5 ✓ → TCP層で待機"]
end
P3 --> Block["1つのパケットロスで<br/>全ストリームがブロック"]
style P3 fill:#f99,stroke:#f00
style P4 fill:#ff9,stroke:#f90
style P5 fill:#ff9,stroke:#f90
HTTP/3とQUIC
HTTP/3は、TCPの代わりにQUICプロトコル(UDP上に構築)を使用します。
QUICの特徴
flowchart TB
subgraph Traditional["従来"]
T_App["アプリケーション層: HTTP/2"]
T_Trans["トランスポート層: TCP + TLS"]
T_Net["ネットワーク層: IP"]
T_App --> T_Trans --> T_Net
end
subgraph HTTP3["HTTP/3"]
H_App["アプリケーション層: HTTP/3"]
H_Trans["トランスポート層: QUIC<br/>(UDP + TLS 1.3 統合)"]
H_Net["ネットワーク層: IP"]
H_App --> H_Trans --> H_Net
end
ストリーム独立性
各ストリームが独立しており、1つのパケットロスが他のストリームに影響しません。
flowchart TB
subgraph QUIC["HTTP/3 over QUIC"]
S1["ストリーム1: パケット1 ✓ → 処理続行"]
S2["ストリーム2: パケット2 ✗ (ロス)<br/>→ このストリームのみ再送待ち"]
S3["ストリーム3: パケット3 ✓ → 処理続行"]
end
Note["ストリーム間で独立"]
style S2 fill:#ff9,stroke:#f90
0-RTT接続
以前接続したサーバーへの再接続が高速化されます。
sequenceDiagram
participant C as クライアント
participant S as サーバー
Note over C,S: 従来のTCP + TLS
C->>S: 1. TCP SYN
S->>C: 2. TCP SYN-ACK
C->>S: 3. TCP ACK + TLS ClientHello
S->>C: 4. TLS ServerHello
S->>C: 5. TLS Finished
C->>S: 6. データ送信開始
Note over C,S: QUIC 0-RTT
C->>S: 1. QUIC Initial(前回のセッション情報 + データ)
Note over C,S: 最初のパケットからデータ送信可能
接続のマイグレーション
IPアドレスが変わっても接続を維持できます。
flowchart LR
subgraph Traditional["従来"]
T1["WiFi"] --> T2["モバイル回線"]
T2 --> T3["IPアドレス変更"]
T3 --> T4["接続切断"]
T4 --> T5["再接続"]
end
subgraph QUIC["QUIC"]
Q1["WiFi"] --> Q2["モバイル回線"]
Q2 --> Q3["接続ID維持"]
Q3 --> Q4["シームレスに継続"]
end
style T4 fill:#f99,stroke:#f00
style Q4 fill:#9f9,stroke:#0f0
パフォーマンス比較
| 観点 | HTTP/1.1 | HTTP/2 | HTTP/3 |
|---|---|---|---|
| 接続数 | 複数必要 | 1接続 | 1接続 |
| HoLブロック | あり | 部分的解決 | 解決 |
| 接続確立 | 遅い | 遅い | 高速 |
| パケットロス耐性 | 低い | 低い | 高い |
| モバイル対応 | 弱い | 普通 | 強い |
対応状況の確認
// ブラウザでの確認
if (window.performance) {
const entries = performance.getEntriesByType('navigation');
console.log(entries[0].nextHopProtocol);
// → "h2" (HTTP/2) または "h3" (HTTP/3)
}
# curlでの確認
curl -I --http2 https://example.com
curl -I --http3 https://example.com
サーバー設定例
Nginx(HTTP/2)
server {
listen 443 ssl http2;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
}
Cloudflare(HTTP/3)
Cloudflareを使用している場合、ダッシュボードからHTTP/3を有効化できます。
まとめ
HTTP/2は多重化とヘッダー圧縮により、HTTP/1.1の課題を大幅に改善しました。HTTP/3はQUICプロトコルにより、さらにパケットロス耐性とモバイル対応を強化しています。現代のWebサイトでは、HTTP/2以上の対応が推奨されます。
← 一覧に戻る