HTTP/2マルチプレクシング:なぜ「1本の道」で世界が変わったのか
Webのエンジニアリングにおいて、HTTP/2は単なる「速いプロトコル」ではありません。これは、TCPという、かつてWebの進化を縛り付けていた「古い鎖」を、ソフトウェアの力でいかに巧妙に回避するかという、エンジニアの執念が生んだ傑作です。
今日は、HTTP/2の真骨頂であるマルチプレクシング(多重化)について、現場の視点から深掘りしてみましょう。
—
1. HTTP/1.1の悲劇:Head-of-Line Blocking(HOLB)
HTTP/1.1の時代、ブラウザは「1つのドメインに対して最大6つ」といったTCP接続制限を設けていました。しかし、1つのTCPコネクションで複数のリクエストを送ろうとすると、前のリクエストのレスポンスが返ってくるまで、次のリクエストは待たなければなりませんでした。これが「Head-of-Line Blocking(先頭行のブロッキング)」です。
重い画像が1枚あるせいで、後ろに並んでいる軽量なCSSやJavaScriptの読み込みが止まる。この「渋滞」を解消するために、私たちはドメインシャーディング(`img1.example.com`, `img2.example.com`…)というダーティなハックでごまかしてきましたが、それも限界でした。
—
2. マルチプレクシングの正体:ストリームという「論理的な仮想回線」
HTTP/2は、この問題を「1本のTCPコネクションの中に、無数の論理的な通り道(ストリーム)を作る」ことで解決しました。
- ストリーム (Stream): 1つのTCP接続内に共存する、独立した双方向のメッセージフロー。
- フレーム (Frame): HTTP/2における通信の最小単位。ヘッダーやデータはすべてこのフレームに分解され、ストリームIDを付与されて、インターリーブ(交互配置)して送られます。
イメージしてください。HTTP/1.1が「1車線の狭い道路を1台ずつ交互に通る」のに対し、HTTP/2は「1本の道路を、色分けされたパケットの断片が高速で追い越し合いながら駆け抜ける」状態です。これにより、あるストリームで大きなデータが詰まっていても、他のストリームは影響を受けずに並行して処理が進みます。
—
3. 実践:マルチプレクシングを体感する
現場でHTTP/2の挙動を追うには、Chromeのデベロッパーツール(Networkタブ)が最適ですが、CLIでその挙動を確認するのもエンジニアの嗜みです。
curlでHTTP/2の通信を確認する
`–http2` フラグを付けてリクエストを投げると、マルチプレクシングの恩恵を確認できます。
-v: 詳細表示, –http2: HTTP/2を強制
curl -I https://www.google.com –http2 -v
出力の中で注目すべきポイント:
“Using HTTP2, server supports multiplexing” といったログや、
ストリームIDの割当状況が確認できます。
Python (httpx) での並列リクエスト検証
HTTP/2の恩恵は、接続のオーバーヘッドが減る点にあります。`httpx` ライブラリを使えば、簡単に検証可能です。
import httpx
import asyncio
HTTP/2対応のClientを生成
async def fetch_resources():
async with httpx.AsyncClient(http2=True) as client:
urls = [“https://example.com/api/v1/data1”, “https://example.com/api/v1/data2″]
# 同時にリクエストを投げる
tasks = [client.get(url) for url in urls]
responses = await asyncio.gather(tasks)
for res in responses:
print(f”Status: {res.status_code}, HTTP Version: {res.http_version}”)
実行結果: どちらもHTTP/2で、同じコネクションを共有して処理されることが確認できます
asyncio.run(fetch_resources())
—
4. インフラ運用のTips:ここだけは押さえておけ
HTTP/2を導入する際、運用担当者が必ずハマるのが「サーバーの設定」です。特にNginx等のWebサーバーでは、以下の設定が鍵を握ります。
Nginx設定例:
server {
listen 443 ssl http2; # http2を明示的に有効化
server_name example.com;
# ストリームの最大数制御
http2_max_concurrent_streams 128;
# ヘッダー圧縮(HPACK)のサイズ制限
http2_header_table_size 4k;
# … ssl設定など
}
現場で役立つ教訓:
1. TCPのHOLBは残る: HTTP/2は「アプリケーション層のHOLB」を解決しましたが、TCPパケットレベルでパケットロスが発生すれば、依然としてTCP再送待ちによる遅延は発生します(これがQUIC/HTTP/3が生まれた理由です)。
2. サーバーのストリーム上限に注意: 同時接続数が多すぎると、サーバー側でストリームのキューが溢れ、パフォーマンスが急落します。負荷試験では、`http2_max_concurrent_streams` を適切にチューニングしてください。
—
まとめ:次に進むために
HTTP/2のマルチプレクシングは、Webインフラを劇的に効率化させました。しかし、技術は常に進化しています。もしあなたが今、不安定なモバイルネットワークでパフォーマンスを極限まで追求しているなら、次は HTTP/3 (QUIC) の世界へ踏み出すべきです。
HTTP/2は「TCPという器」をいかに使うかという知恵の結晶です。今日学んだ「ストリーム」という概念を意識するだけで、API設計やトラブルシューティングの解像度は一段と高まるはずです。
何かネットワークの挙動で不可解なことがあれば、まずはパケットをキャプチャし、ストリームIDの流れを追うこと。それが、真のネットワークエンジニアへの第一歩です。
コメント