HTTPの「パイプライン化」って何?郵便配達で学ぶ、Web通信の効率化と限界
こんにちは!ネットワークの世界へようこそ。今日は、Web通信の歴史の中で少しだけ「意欲的すぎて、結果的にちょっと苦労した」技術、「HTTPパイプライン(HTTP Pipelining)」についてお話しします。
「パイプライン」という言葉、なんとなく「配管」をイメージしますよね。実はWebの世界でも、データの流れをスムーズにするための「工夫」として使われていたんです。
一歩ずつ、身近な例えで紐解いていきましょう!
—
1. 昔のWebは「一問一答」の行列だった
HTTP/1.1が登場する前、あるいは登場初期の通信は、とても律儀なルールで動いていました。
- あなた(ブラウザ): 「りんごを1個ください!」
- サーバー: 「はい、りんごです。」(ここで初めて完了)
- あなた: 「じゃあ、次はみかんを1個ください!」
- サーバー: 「はい、みかんですね。」
これが「リクエスト・レスポンスの逐次処理」です。いちいち「届きましたか?」「はい、届きました」を確認してから次の注文をする。これでは、Webページに画像やCSS、JavaScriptがたくさんある場合、待ち時間が長すぎてストレスが溜まってしまいますよね。
—
2. 「パイプライン化」は、注文をどんどん投げるテクニック!
そこで登場したのが「パイプライン化」です。これは、「相手の返事を待たずに、注文書をどんどんポストに投げ込む」という仕組みです。
例えば、郵便配達員さんに手紙を出すときを想像してください。
- 普通の通信: 手紙を1通出し、配達員さんが返事を持って帰ってくるまで、次の手紙を書かずに待機する。
- パイプライン化: 「りんごの注文」「みかんの注文」「ぶどうの注文」をまとめてポストにガサッと入れる。
これなら、サーバー側は「注文が3つ届いたな」と認識して、準備ができ次第、順番に返事を返せます。一見、すごく効率的ですよね!
HTTP/1.1での概念図
[ブラウザ] —- リクエストA —-> [サーバー]
[ブラウザ] —- リクエストB —-> [サーバー]
[ブラウザ] —- リクエストC —-> [サーバー]
(返事を待たずにどんどん投げる!)
—
3. なぜ「パイプライン化」は普及しなかったのか?
「待ち時間が減るなら最高じゃないか!」と思いますよね。しかし、ここにはネットワークエンジニア泣かせの「致命的な制約」がありました。
呪縛:FIFO(先入れ先出し)のルール
HTTP/1.1のパイプラインには、「リクエストした順番通りに返事を出さなければならない」という絶対的なルールがありました。
例えば、あなたがこんな注文をしたとします。
1. 重い巨大な動画データ(処理に10秒かかる)
2. 小さなテキストファイル(処理に0.1秒かかる)
サーバーは「順番通りに返さなきゃ!」と律儀に守るため、小さなテキストファイルが準備万端でも、前の動画データの処理が終わるまで、そのテキストファイルを送ることができません。
これを専門用語で「ヘッド・オブ・ライン・ブロッキング(先頭の詰まり)」と呼びます。行列の先頭の人がモタモタしているせいで、後ろの全員が足止めを食らう状態ですね。
—
4. 現場で直面する「実装の難しさ」
実はこのパイプライン、サーバーやブラウザを開発するエンジニアからすると「非常に実装が難しい」技術でした。
もし途中で通信が切れたら?どのリクエストまで処理が成功したのか分からなくなり、中途半端な状態で再送しなければなりません。この複雑さゆえに、多くのブラウザやサーバーは「パイプラインを使わない」という選択をしました。
確認のための疑似コード(イメージ)
もし現代のブラウザがパイプラインを強引に実装しようとしたら、こんな感じのロジックが必要になります。
// 注意:これは概念的な擬似コードです
const queue = [‘image.jpg’, ‘style.css’, ‘script.js’];
// 順番を絶対に守らないといけないため、サーバーからの返信を待ち続ける必要がある
async function sendRequests() {
for (const item of queue) {
// 1つ前のレスポンスが完了するまで次の送信を待つか、
// 送信だけして、受信の順番を厳密に管理する高度なロジックが必要
const response = await fetch(item);
console.log(`${item} が届きました!`);
}
}
—
5. そして現代へ:HTTP/2 が全てを解決した
結局、HTTP/1.1のパイプラインは「理想は高いが、現実にはリスクが多すぎる」ということで、あまり活用されないまま、次の世代のHTTP/2へとバトンタッチされました。
HTTP/2では、リクエストを「ストリーム」という単位で分割することで、「前の処理が終わるのを待たずに、次のデータを並行して受け取る」という、真の意味での高速化を実現しました。
まとめ:今回の学び
1. HTTP/1.1のパイプラインは、返事を待たずに注文を投げる「効率化」の試みだった。
2. しかし、「順番通りに返さなければならない」というルールのせいで、前の処理が詰まると全体が止まる「ヘッド・オブ・ライン・ブロッキング」という弱点があった。
3. この教訓があったからこそ、現代のHTTP/2やHTTP/3では、もっと賢く並行処理ができるようになった。
ネットワークの世界は、こうした「失敗や制約」を一つずつ克服しながら進化しています。「なぜ今の技術が便利なのか?」を考えるとき、昔のエンジニアが苦労したこうした歴史を振り返ると、より一層理解が深まりますよ。
もし次にWebサイトを見ていて「表示が速いな」と感じたら、裏側で繰り広げられているこの進化の歴史を思い出してみてくださいね!
コメント