こんにちは!ネットワークの世界へようこそ。インフラやプロトコルの世界を覗いていると、時々「おっ、これって現実世界のアレに似ているな!」と膝を打つような面白い仕組みに出会います。
私たちが普段何気なく使っているWebブラウザ。URLを入力してエンターキーを押すと、パッと画面が表示されますよね。この裏側では、ブラウザとサーバーがものすごい勢いで会話をしているのですが、今日はその中でもちょっと特別で、そしてちょっぴり切ない(?)ドラマを秘めた技術、「HTTP/2サーバープッシュ(Server Push)」の仕組みについてお話ししていきます。
小難しいパケットの構造や英語の専門用語は、できるだけ置いていきましょう。郵便配達のストーリーに例えながら、一歩ずつ優しく紐解いていきますね!
—
1. 昔ながらのWebと、HTTP/2の「マルチプレクシング」
本題に入る前に、私たちが今使っているHTTP/2がどんな風に進化してきたのかを少しだけおさらいしておきましょう。
昔の「HTTP/1.1」という時代は、Webページを表示するのにこんな苦労がありました。
1. まずHTMLファイルを取りに行く。
2. HTMLを読んで、「あ、中にCSS(デザインのファイル)と画像があるぞ」と気づく。
3. 改めてCSSを取りに行く。
4. 画像を取りに行く……。
これをレストランに例えるなら、注文を1つずつしか受け付けない頑固なウェイターさんのようなものです。「ハンバーガーをください」「かしこまりました」……(厨房から戻ってくるのを待つ)……「次はポテトをください」「かしこまりました」……。これではお腹が空いてしまいますよね。
そこで登場したのがHTTP/2です。HTTP/2の最大の発明は「マルチプレクシング(多重化)」という技術でした。
これは、1本の太いパイプライン(TCPコネクション)の中に、いくつもの「専用レーン(ストリーム)」を作り、複数のリクエストとレスポンスを同時に往復させることができる仕組みです。ウェイターさんが一度に何人ものお客さんの注文をお盆に載せて、一気に運んでくるようなイメージですね。
—
2. 先回りして届ける!「サーバープッシュ」の魔法
マルチプレクシングのおかげでWebの表示は劇的に速くなりました。しかし、当時の天才エンジニアたちはこう考えました。
「クライアント(ブラウザ)から『これちょうだい』って言われる前に、こっちから『これ絶対いるでしょ!』って先に渡しちゃえば、もっと速くなるんじゃないか?」
これが、HTTP/2サーバープッシュのコンセプトです。
郵便配達の例えで考えてみよう
想像してみてください。あなたがネットショッピングで新しい洋服を注文しました。
通常の通信(HTTP/2の通常リクエスト)はこうです。
1. あなた:「この服の注文書を送ります」(リクエスト)
2. 配達員:「届きました。服を発送しますね」(レスポンス)
3. あなた:「服が届いた! あ、そういえばこの服に合うコーディネート用の帽子も欲しかったんだ。帽子の注文書を送ります」(リクエスト)
4. 配達員:「かしこまりました。帽子を発送しますね」(レスポンス)
時間がかかりますよね。そこでサーバープッシュの登場です。
1. あなた:「この服の注文書を送ります」(リクエスト)
2. 配達員:「届きました! 服と一緒に、『きっとこの帽子も欲しくなるはずだから、頼まれてないけど先に送っとくね!』という手紙と帽子も一緒にお届けします!」(プッシュ!)
素晴らしいおせっかい、いえ、素晴らしい先回りサービスです! この「頼まれていないけど、先に送るよ」という約束を伝えるために使われるのが、今回主役の`PUSH_PROMISE(プッシュ・プロミス)`フレームなのです。
—
3. PUSH_PROMISEフレームの正体
サーバーが「先回りをし始めるよ!」とブラウザにこっそり伝えるメッセージ、それが`PUSH_PROMISE`です。
パケットの細かいバイナリデータを覚える必要はありませんが、このフレームの中には大切な情報が入っています。
- 「これからこのURLのリソースを勝手に送るから、キャッシュ(一時保存場所)の準備をしておいてね!」という予告
- その予告に割り振られた「ストリームID(専用レーン番号)」
サーバーは、ブラウザが「ちょうだい」と言うよりも先に、この`PUSH_PROMISE`を送り、その直後に実際のデータ(CSSや画像など)を流し込みます。ブラウザ側は、「おっ、サーバーが先に送ってくれるって言ってたやつだ! キャッシュに保管しておこう」と、通信の無駄を省くことができるわけです。
実際のNginx設定例(イメージ)
実務でサーバープッシュを有効にする際、NginxなどのWebサーバーでは次のような設定を行っていました(※現在は非推奨ですが、仕組みの理解としてご覧ください)。
server {
listen 443 ssl http2; # HTTP/2を有効にする
server_name example.com;
location = /index.html {
# index.htmlが要求されたら、スタイルシートを先回りしてプッシュする
http2_push /css/style.css;
# 内部的な処理の記述…
}
}
このように設定しておくと、ユーザーが `/index.html` を見に来た瞬間、サーバーは自動的に `/css/style.css` をプッシュしてくれていました。理屈上は、非常にスマートで美しい技術ですよね。
—
4. なぜサーバープッシュは「非推奨」になってしまったのか?
さて、ここからが少し切ない現実のお話です。こんなに素晴らしい技術に見えたサーバープッシュですが、実は現在の主要なWebブラウザ(Google Chromeなど)や仕様策定の現場では、「実質的に使わない方向(非推奨・Deprecated)」へと舵が切られています。
「えっ、せっかく仕組みを覚えたのに、なんでなの!?」と思いますよね。
その理由は、現実世界の複雑さにありました。主な理由は以下の2つです。
① ブラウザのキャッシュを無視してしまう(無駄な通信)
考えてみてください。あなたがそのWebサイトを初めて訪れたならサーバープッシュは有効ですが、2回目以降の訪問で、すでにブラウザがそのCSSを自分の手元(キャッシュ)に持っていたらどうなるでしょうか?
サーバーはそれを知るよしもなく、「はい、これ持ってきたよ!」と強制的にCSSを送りつけてきます。結果として、「すでに持っているデータを、わざわざ帯域(通信量)を消費して二重に送りつける」という、ありがた迷惑な事態が発生してしまいました。これはモバイル回線などでは致命的な無駄になります。
② サーバー側の実装が難しく、コントロールしづらい
「どのファイルを一緒にプッシュすべきか」の判断をサーバー側で行うのは意外と面倒です。Webサイトが複雑化するにつれ、かえってページの読み込みスピードが遅くなってしまうケースが多発しました。
こうした背景から、現在ではブラウザ側でサーバープッシュのサポートが次々と終了、あるいは縮小されています。「良かれと思ってやったのに、すれ違ってしまった」という、技術の難しさを象徴するエピソードですね。
—
5. まとめとこれからの私たち
今回は、HTTP/2サーバープッシュの仕組みと、`PUSH_PROMISE`フレームの役割、そして現在のトレンドについてお話しました。
- サーバープッシュとは、クライアントに頼まれる前にリソースを先回りして送信する仕組み。
- その予告をするのが`PUSH_PROMISE`フレーム。
- 理論は美しかったものの、キャッシュとの相性問題などから、現在のモダンWebでは非推奨となり、別の高速化手法(「103 Early Hints」など)へバトンタッチされつつある。
一見すると「使われなくなった技術」ですが、ネットワークプロトコルが「いかにクライアントとサーバーの無駄なやり取りを減らし、高速化するか」を試行錯誤してきた歴史を知る上で、サーバープッシュの仕組みは非常に価値のある学びです。
インフラやプロトコルの世界は、こうした「理想と現実のトレードオフ」の連続でできています。だからこそ、エンジニアリングは面白いんですよね!
それでは、また次回のネットワーク解説でお会いしましょう。一歩ずつ、確実に知識を深めていきましょうね!
コメント