【入門編】PUSH_PROMISEフレームによるサーバープッシュの予約 – HTTPプロトコル・通信規格実践ガイド

こんにちは!技術メディアの主筆ライターです。日々、ネットワークの海を駆け巡るパケットの息吹を感じながら、Webの裏側を覗き見るのが大好きな私ですが、今日は皆さんと一緒に「HTTP/2のちょっとユニークな仕掛け」について深掘りしていきたいと思います。

Webブラウザを開いてページを表示するとき、裏側ではブラウザとサーバーの間で無数のデータ(リクエストとレスポンス)が飛び交っていますよね。その通信を劇的に速く、スマートにしてくれたのが「HTTP/2」です。

HTTP/2の目玉機能といえば、1本の通信路(コネクション)で同時にいくつものデータをやり取りできる「マルチプレクシング(多重化)」ですが、実はもう一つ、「サーバー側から先回りしてデータを送りつける」という非常に面白い機能が隠されています。それが今回スポットを当てる「サーバープッシュ」であり、その予約チケットである「PUSH_PROMISE(プッシュプロミス)フレーム」です。

小難しいパケットの構造や英語の仕様書は、一旦置いておきましょう。まずは私たちの身近な世界に置き換えて、この仕組みを優しく紐解いていきたいと思います。一歩ずつ理解していきましょう!

—

1. サーバープッシュって、どんな仕組み?(身近な例え話)

想像してみてください。あなたは今、近所の美味しいカフェに来て、お気に入りの「ブレンドコーヒー」をカウンターで注文しました。

店員さんはあなたの注文を聞いてコーヒーを淹れ始めますが、心の中でこう思います。
「このお客さん、いつもブレンドコーヒーと一緒に、あの人気の焼き立てクロワッサンも注文するんだよな。コーヒーを出し終わった後に、また『クロワッサンも』って言われるより、先にコーヒーと一緒にトレーに乗せて出しちゃったほうが、お客さんも待たなくていいし効率的だよね!」

そして店員さんは、あなたが頼んでいないにもかかわらず、コーヒーとクロワッサンを同時にあなたのテーブルへと運んできました。

これが「サーバープッシュ」の概念です。
Webの世界に置き換えると、こういうことになります。

  • クライアント(ブラウザ): 「このHTMLファイル(コーヒー)をください!」とサーバーにお願いする。
  • サーバー: 「HTMLファイルですね、どうぞ! あ、そうそう、このHTMLを表示するなら絶対にあのCSSファイル(クロワッサン)も後から読みに来るはずだから、頼まれてないけど先回りして一緒に送っちゃえ!」

ブラウザが「CSSをください」とお願いする手間(往復の通信時間)を丸ごとカットできるため、ページが表示されるスピードが圧倒的に速くなるというわけですね。

—

2. 予約のチケット「PUSH_PROMISEフレーム」の正体

さて、ここで一つの疑問が湧いてきます。
「頼んでもいないのに、サーバーが勝手にファイルを送りつけてきたら、ブラウザ側でパニックになりませんか?」

おっしゃる通りです。もしサーバーが前触れもなく突然ファイルを送りつけてきたら、ブラウザは「えっ、これ何のデータ!? どこに保存すればいいの?」と混乱してしまいます。

そこで登場するのが、今回の主役である「PUSH_PROMISE(プッシュプロミス)フレーム」です。

PUSH_PROMISEは、データ本体を送りつける前に、サーバーがブラウザへこっそり渡す「事前予約チケット(予告状)」のようなものです。

この予告状には、こんなことが書かれています。

  • 「今から、あなたに頼まれていないファイル(例:`/css/style.css`)を勝手に送る予定だからね!」
  • 「そのファイルの専用ストリーム(通信レーン)として、『ストリームID:2番』を空けておくから準備しておいてね!」

つまり、PUSH_PROMISEはデータそのものではなく、「これから送りつけるプッシュデータの告知と、お部屋の予約」の役割を持っているのです。

—

3. ここが重要!ストリームIDの厳格なルール

HTTP/2では、1本の通信路の中にいくつもの仮想的なレーン(これを「ストリーム」と呼びます)を作り、それぞれに番号(ストリームID)振って並行してデータを流します。

ここで、ネットワークエンジニアや開発者が絶対に押さえておかなければならない「ストリームIDのルール」があります。

クライアントが使うID、サーバーが使うID

HTTP/2の世界では、喧嘩にならないようにIDの割り振りがきれいに分かれています。

1. 奇数(1, 3, 5, 7…): クライアント(ブラウザ)が開始するストリーム。
2. 偶数(2, 4, 6, 8…): サーバーが開始するストリーム。

PUSH_PROMISEにおけるIDの動き

サーバープッシュを行う際、このストリームIDがどのように割り当てられるのか、流れを追ってみましょう。

1. ステップ1:クライアントのリクエスト
ブラウザが、メインのHTML(例: `/index.html`)をサーバーに要求します。

  • ここで使われるストリームIDは奇数(例: `1`)です。

2. ステップ2:サーバーのPUSH_PROMISE送信
サーバーは、ストリームID `1` の通信を使って、「これから `style.css` をプッシュするよ!」という予約(PUSH_PROMISE)を送信します。
この時、サーバーはプッシュ用のデータ専用に、次に自分が使える偶数のストリームID(例: `2`)を勝手に割り当てて予告します。
3. ステップ3:プッシュデータの送信
サーバーは、予告したストリームID `2` を使って、実際に `style.css` の中身(DATAフレーム)をクライアントに送り届けます。

このように、「サーバー側から能動的に仕掛ける通信は、必ず偶数のストリームIDを使う」というルールがあるおかげで、クライアントとサーバーが同時にデータをやり取りしても、お互いのデータが混ざり合うことなく綺麗に整理整頓されるのです。

—

4. 実際のネットワーク通信をイメージしてみよう

実務でパケットキャプチャツール(Wiresharkなど)や、ブラウザの開発者ツール、あるいはHTTP/2を扱うアプリケーションのログを覗くと、このやり取りが手に取るようにわかります。

以下は、HTTP/2の通信を擬似的なプログラムコードや設定値のイメージとして表現したものです。デバッグ時などの参考にしてみてください。

— ステップ1: ブラウザからの通常リクエスト —
クライアントは「奇数(1)」のストリームIDを使ってHTMLを要求します。
[Stream 1] HEADERS
:method = GET
:path = /index.html
:authority = example.com

— ステップ2: サーバーからのPUSH_PROMISE(予約) —
サーバーは既存のストリーム(1)を使い、「偶数(2)」のストリームでCSSをプッシュすると予告します。
[Stream 1] PUSH_PROMISE
promised_stream_id = 2 <-- これから使うプッシュ用の予約ID(偶数!) :method = GET :path = /css/style.com :authority = example.com --- ステップ3: サーバーからのプッシュデータ本体送信 --- 先ほど予約した「偶数(2)」のストリームを使って、サーバーが勝手にデータを送り始めます。 [Stream 2] HEADERS :status = 200 OK content-type = text/css [Stream 2] DATA body = "body { background-color: #f0f0f0; }" [END_STREAM] <-- 送信完了 このように、コードやログの裏側でも「奇数と偶数のルール」がしっかりと守られて調和を保っていることが分かりますよね。 ---

5. まとめ:サーバープッシュの現在地とこれから

今回は、HTTP/2の「PUSH_PROMISEフレームによるサーバープッシュの予約」について、身近な例えを交えながらお話ししてきました。

  • サーバープッシュとは: ブラウザに頼まれる前に、先回りでデータを送りつける効率化の仕組み。
  • PUSH_PROMISEとは: データ本体を送る前の「予告状」兼「プッシュ用ストリームの予約チケット」。
  • ストリームIDのルール: クライアント起因は「奇数」、サーバー起因(プッシュなど)は「偶数」。

ちなみに、この非常に便利そうなサーバープッシュですが、現代のWeb開発の現場(特にHTTP/2からさらに進化したHTTP/3の時代)においては、「ブラウザのキャッシュ機能とうまく連携できない」「本当に必要なファイルかサーバー側で判断しきれない」といった理由から、実際にはあまり使われなくなってきたり、ブラウザ側で無効化される動きがあったりと、少し複雑な歴史を持っています。

とはいえ、「1本の通信路の中で、クライアントとサーバーが主導権を握り合いながら、IDを使って綺麗に交通整理をしている」というHTTP/2の根幹の思想を理解する上で、サーバープッシュとPUSH_PROMISEの仕組みは最高の教材です。

ネットワークの裏側で繰り広げられるパケットたちのこんなドラマを知っていると、日頃何気なく見ているWebサイトの表示速度も、なんだか愛おしく感じられるのではないでしょうか?

それでは、また次回の技術解説でお会いしましょう! インフラとプロトコルの世界を、一緒に楽しんでいきましょうね。

コメント

タイトルとURLをコピーしました