【入門編】HTTP/2のヘッダー圧縮(HPACK)における動的テーブル – HTTPプロトコル・通信規格実践ガイド

こんにちは!技術メディア「Network Insights」主筆ライターの私です。

日頃からWebサイトを閲覧していて、「なんで最近のサイトはこんなにサクサク動くんだろう?」と感じたことはありませんか?その裏側を支える技術の一つが「HTTP/2」です。

HTTP/2の大きな目玉といえば、1本の通信回線で同時にいくつものデータをやり取りする「マルチプレクシング」ですが、実はもう一つ、通信を劇的に速くする隠れた主役がいます。それが今回フォーカスする「HPACK(エイチパック)」によるヘッダー圧縮です。

「ヘッダー圧縮って何だか難しそう……」「アルゴリズムとか英語がいっぱいで挫折しそう……」そんな風に思っていませんか?
大丈夫です!今回は、パケットの細かいビット数を数えるような退屈なお勉強はお休みにして、私たちの身近にある「郵便配達」の世界に例えながら、一歩ずつ優しく紐解いていきましょう。

—

そもそもHTTPの「ヘッダー」ってなに?(現実世界の例え)

Webブラウザがサーバーに「このページを見せて!」とお願いするときや、サーバーが「はい、どうぞ!」と返すとき、データ本体(HTMLや画像)のほかに、必ず「お供の手紙(メタデータ)」がついてきます。これがHTTPヘッダーです。

例えば、あなたがネットショッピングで買い物をする時を想像してください。
荷物のダンボール箱(=データ本体)には、必ず送り状(=ヘッダー)が貼ってありますよね。

  • 「宛先:東京都〇〇区……(:authority)」
  • 「ブラウザの種類:Chromeだよ(user-agent)」
  • 「受け入れられる言語:日本語(accept-language)」
  • 「Cookie:私のログイン情報(cookie)」

これらはWeb通信を行う上で絶対に欠かせない大切な情報ですが、実は大きな問題がありました。それは、「毎回、同じような長文の送り状を何枚も貼り付けて送っている」ということです。

「昨日も一昨日も同じ住所に同じような荷物を送っているのに、毎回宛先を全書きしているなんて、紙もインクももったいないよね?」
そう、昔のHTTP(HTTP/1.1)は、この「毎回同じヘッダーを丸ごと送信する無駄」を抱えていたのです。

—

HPACKの切り札!「動的テーブル」という名の記憶のノート

そこで登場したのが、HTTP/2のヘッダー圧縮技術である「HPACK」です。
HPACKには、あらかじめ決まったよくあるヘッダーをまとめた「静的テーブル」のほかに、「動的テーブル(Dynamic Table)」という特別な仕組みが用意されています。

この「動的テーブル」を、私たちの身近な例えで考えてみましょう。

郵便配達員さんと「常連さんノート」の物語

ここに、あなたと近所の郵便局員のAさんがいるとします。
あなたは毎日、同じ宛先(サーバー)に向けて、同じような長文の差出人情報が書かれた手紙を大量に送っています。

最初は、郵便局員のAさんも毎回その長い住所を一つひとつ確認していました。しかし、Aさんはこう思います。
「待てよ、この宛先への手紙はいつも同じ内容だな。わざわざ毎回全文を書かせるより、『番号』を振っておけばラクなんじゃないか?」

そこでAさんは、あなたとの専用の「ノート(=動的テーブル)」を用意しました。

1. 初回: あなたが長文のヘッダー(例: `user-agent: Mozilla/5.0…`)を送ります。
2. 学習: 郵便局員(サーバー)はそれを受け取ると、自分のノートに「これからは、この長文を 【番号:62】 と呼ぶことにしよう!」と書き留め、あなたにも同じメモを共有します。
3. 2回目以降: 次に同じヘッダーを送る時、あなたは長文を書く必要はありません。ただ一言、「62番で!」とだけ書いて送るのです。

これこそが、動流テーブルの正体です。
通信の途中でやり取りしたヘッダーの組み合わせを「お互いの記憶のノートに一時保存(学習)」し、次からは短い番号(インデックス)だけでやり取りする。これにより、通信データ量を劇的に削ることができるのです。

—

動的テーブルのルール:容量制限と「古い記憶の忘れ方」

「なるほど、じゃあ会話のたびにノートにどんどん記憶していけば、無限に小さくなって最強じゃないか!」
そう思われた方、素晴らしい着眼点です。しかし、ここに一つ大きな制約があります。それが「テーブルサイズ制限」です。

人間の脳や、スマートフォンのメモリと同じように、サーバーやブラウザが持てるノートの大きさには限界があります。
もし無限に記憶し続けたら、サーバーのメモリがパンクしてしまいますよね。

そのため、動的テーブルには以下のような厳格なルール(アルゴリズム)が決められています。

  • 上限のサイズが決まっている: 通常、デフォルトでは4096バイト(4KB)などの上限が設定されています。
  • 新しい記憶が、古い記憶を追い出す(FIFO方式に近い動き): ノートがいっぱいになった状態で、新しく覚えるべきヘッダーが登場すると、一番最初に覚えた(最も古い)記憶がノートから消去(ドロップ)されます。

郵便局員のノートが満杯になったら、「一番古い常連さんの情報はもう最近使ってないから消して、新しい常連さんのメモを書くスペースを空けよう」とするのと同じですね。

—

実務の現場でどう見える? デバッグでの確認方法

インフラエンジニアやWebエンジニアとして働いていると、この動的テーブルの動きをブラウザの「開発者ツール(DevTools)」やパケットキャプチャツール(Wiresharkなど)で覗き見する機会があります。

例えば、Google Chromeの開発者ツールを開き、「Network」タブの「Protocol」列を見てみてください。「h2」と表示されていれば、まさにHTTP/2で通信が行われています。

また、Node.jsやNginxなどのサーバー設定や、アプリケーションのデバッグ時には、このヘッダー圧縮サイズを意識することがあります。参考までに、Node.jsのHTTP/2モジュールでサーバーを構築する際の簡単なサンプルコードを見てみましょう。

const http2 = require(‘http2’);
const fs = require(‘fs’);

// テスト用の自己署名証明書と秘密鍵を読み込み(HTTP/2は実質的に暗号化通信が必須です)
const server = http2.createSecureServer({
key: fs.readFileSync(‘localhost-privkey.pem’),
cert: fs.readFileSync(‘localhost-cert.pem’)
});

server.on(‘error’, (err) => console.error(err));

server.on(‘stream’, (stream, headers) => {
// 客户端から送られてきたヘッダー情報をコンソールに出力する
console.log(‘— 受信したヘッダー(HPACKで展開済み) —‘);
console.log(headers);

// レスポンスのヘッダーを設定
// HTTP/2では、 ‘:status’ のようにコロンから始まる疑似ヘッダーが使われます
stream.respond({
‘content-type’: ‘text/html; charset=utf-8’,
‘:status’: 200
});

// レスポンスボディを返す
stream.end(‘

こんにちは!HPACKと動動的テーブルの世界へようこそ!

‘);
});

// 4430番ポートでサーバーを起動
server.listen(4430, () => {
console.log(‘HTTP/2 サーバーが https://localhost:4430 で起動しました’);
});

このコードを実行し、ブラウザからアクセスすると、最初の数回はテーブルの学習が行われ、それ以降の連続したリクエストではヘッダーのバイト数が驚くほど小さくなっていることが、ネットワークタブの「Size」項目などで確認できます。

—

まとめ:ネットワークの裏側にある「思いやり」

今回は、HTTP/2のヘッダー圧縮(HPACK)における「動的テーブル」について、郵便配達の例えを交えながら解説しました。

  • ヘッダー圧縮(HPACK)は、毎回同じような長文のメタデータを送る無駄を省く技術。
  • 動的テーブルは、通信中に登場したヘッダーの組み合わせをお互いの「記憶のノート」に保存し、次回からは番号だけでやり取りする仕組み。
  • サイズ制限があり、メモリを圧迫しないよう古い記憶から自動的に消去されていく。

普段私たちが意識することなく、数千キロ離れたサーバーから一瞬でWebページを受け取れるのは、こうしたエンジニアたちの「少しでも無駄を減らして、通信を速くしよう」という細やかな工夫(思いやり)の積み重ねのおかげなんですね。

「難しいプロトコル仕様も、身近な例えに置き換えれば怖くない!」
そう感じてもらえたら、主筆ライターとしてこれ以上の喜びはありません。それではまた、次回の技術解説でお会いしましょう!

コメント

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