HTTP/1.1の「パイプライン」はなぜ死んだのか?―現場が直面するHOLブロッキングの正体
現場でネットワークのパケットキャプチャを眺めていると、時折「HTTP/1.1の通信効率」についての議論に出くわします。特に、若手エンジニアから「リクエストを並列に投げれば速くなるのでは?」という質問を受けることは少なくありません。
彼らが思い描くのは、HTTP/1.1で導入された「パイプライン化(Pipelining)」という機能です。しかし、結論から言えば、この機能は現代のWeb開発の現場ではほぼ「禁じ手」であり、ブラウザ実装からも姿を消しました。
今回は、このパイプライン化がなぜ期待されたのか、そしてなぜ「ヘッド・オブ・ライン・ブロッキング(HOLブロッキング)」という致命的な壁にぶつかったのか。現場の視点から紐解いていきましょう。
—
1. HTTP/1.1パイプラインの夢と現実
HTTP/1.0までの時代、通信は「リクエスト→レスポンス→次のリクエスト」という、いわば「一問一答」形式でした。これでは毎回RTT(ラウンドトリップタイム)が発生し、Webページの読み込みは遅いままです。
そこでHTTP/1.1では、「レスポンスを待たずに、次のリクエストをTCPのコネクションにどんどん詰め込む」というパイプライン処理が仕様(RFC 7230)として定義されました。
パイプラインの通信フロー(理想)
1. Client -> Server: GET /a.html
2. Client -> Server: GET /style.css
3. Client -> Server: GET /script.js
4. Server -> Client: (a.htmlのレスポンス)
5. Server -> Client: (style.cssのレスポンス)
6. Server -> Client: (script.jsのレスポンス)
一見すると非常に効率的に見えますよね。しかし、これが実務で悲劇を生むことになります。
—
2. 最大の敵「ヘッド・オブ・ライン・ブロッキング(HOLB)」
パイプライン処理の最大の弱点は、「HTTPはレスポンスの順序を厳守しなければならない」という仕様にあります。
サーバー側がリクエストA、B、Cを順番に受け取った場合、たとえBの処理が1ミリ秒で終わり、Aの処理に10秒かかったとしても、サーバーは「Aのレスポンスを返し終えるまで、Bのレスポンスを返してはならない」というルールがあります。
もしAの処理で重いDBクエリが走っていれば、BとCはサーバー側で完全に「待機状態」になります。これがヘッド・オブ・ライン・ブロッキング(HOLブロッキング)です。
現場で見る「詰まり」の正体
TCPのパケットレベルで見ると、パケットロスが発生した際にTCPの再送制御が働き、コネクション全体が停止します。HTTPレベルのパイプラインは、この「列の先頭が詰まったら後ろも全て止まる」という性質をさらに助長してしまったのです。
—
3. 実践:curlでパイプラインを「体感」する
現代のブラウザはパイプラインをサポートしていませんが、`curl` を使うと、強制的にパイプラインのような挙動を確認できます。以下のコマンドで、サーバーの挙動を追ってみてください。
–http1.1を指定し、複数のリクエストをパイプライン的に投げるシミュレーション
注意: 多くのモダンサーバーはパイプラインを無視して単一のリクエストとして処理します
curl -v –http1.1 \
-H “Host: example.com” \
-d “GET /api/data1 HTTP/1.1\r\nHost: example.com\r\n\r\nGET /api/data2 HTTP/1.1\r\nHost: example.com\r\n\r\n” \
http://localhost:8080/
もし自前でAPIサーバーを構築しているなら、Nginxの設定でパイプラインの挙動を確認することも可能です。
nginx.conf
パイプラインを明示的に制御するディレクティブはないが、
接続のタイムアウト設定がパイプラインの維持に影響する
keepalive_timeout 65; # この値が短いとパイプライン中の後続リクエストが切断される
—
4. なぜHTTP/2以降に移行すべきなのか
現場のエンジニアとして断言しますが、HTTP/1.1のパイプラインをチューニングして高速化を図る努力は、現代では「無駄な工数」です。
- HTTP/2の「ストリーム多重化」: HTTP/2では、一つのTCPコネクションを細分化(ストリーム)し、レスポンスの順序に依存せず並行してデータを送受信します。HOLブロッキングは、HTTPレベルでは完全に解消されました。
- HTTP/3 (QUIC): さらにHTTP/3では、TCPそのものを捨ててUDPベースのQUICを採用することで、パケットロスによるHOLブロッキングすらも過去のものにしました。
—
まとめ:トラブルシューティングの教訓
もし皆さんのインフラで、「特定のAPIは速いのに、同時にリクエストすると遅くなる」「レスポンスが妙にまとまって返ってくる」という事象に遭遇したら、それはHTTP/1.1のコネクション再利用がボトルネックになっているサインかもしれません。
1. まずはプロトコルを確認: `curl -I` で `HTTP/1.1` が使われていないかチェックする。
2. コネクションの張りすぎを疑う: HTTP/1.1の場合、ブラウザはドメインごとに同時接続数を制限(通常6本)します。これがパイプライン化を無理やり使うよりも、現実的な高速化手段となっていました。
3. 結論: 根本解決は HTTP/2 または HTTP/3 への移行です。
技術の歴史は、失敗の歴史でもあります。パイプラインがなぜ廃れたのかを知ることは、現代のWebインフラがいかにして「効率」と「順序」の両立という難題を解いてきたかを理解する近道です。皆さんのシステムが、最新のプロトコルで快適に動くことを願っています。
コメント