こんにちは!インフラエンジニアの皆さん、そして日夜Webの裏側の仕組みにワクワクしている皆さん、いつもお疲れ様です。技術メディア「Net-Dive」主筆の私です。
Webブラウザを開いてページが表示されるまで、ほんのコンマ数秒。普段私たちは意識すらしませんが、その瞬間、ネットワークの世界では数々のパケットが猛烈なスピードで駆け巡っています。前世代の「HTTP/1.1」から大きく進化し、今やWebの高速化を裏で支える主役となった「HTTP/2」。その大きな特徴の一つが、1本の通信路(コネクション)の上で同時にいくつものデータをやり取りする「マルチプレクシング(多重化)」ですよね。
今回は、そのHTTP/2の裏側でいぶし銀の活躍を見せる、ちょっとマニアックだけど実は超重要な主役「CONTINUATIONフレーム」にスポットを当ててみたいと思います。
「なんだか難しそうな名前だな……」と思いましたか? 大丈夫です! 一歩ずつ、身近な例えを交えながら優しく紐解いていきましょう!
—
1. そもそもHTTP/2の「ヘッダー」ってどうやって運ばれているの?
HTTP/2の世界では、やり取りするすべてのデータが「フレーム」という小さな小包に分解されて流れていきます。Webサイトの画像も、テキストも、すべてはこのフレームの集まりです。
そして、Webページをリクエストするときには、「このページが欲しいです!」という情報(リクエストヘッダー)や、サーバーからの「はい、どうぞ!」という返事(レスポンスヘッダー)が必ずくっついてきますよね。
HTTP/2では、このヘッダー情報を運ぶために「HEADERS(ヘッダーズ)フレーム」という専用の小包を用意しています。基本的には、「ヘッダーはこのHEADERSフレームという1つの箱に入れて送る!」というルールになっています。
例え話:郵便配達の「封筒の大きさ制限」
ここで、現実世界に置き換えて考えてみましょう。
あなたは大量の手紙を出すために、郵便局にやってきました。窓口の係員さんからこう言われます。
> 「お客さま、当社のルールでは、1つの封筒に入れられる手紙の量はここまでと決まっております。このサイズを超える場合は、封筒を分けて出してくださいね」
HTTP/2の「HEADERSフレーム」もこれと全く同じです。
HTTP/2の通信を行うサーバーやクライアントの間では、「1つのフレーム(小包)に詰め込めるデータの最大サイズ(SETTINGS_MAX_FRAME_SIZE)」があらかじめ決められています。
もし、あなたが送りたいCookieや認証情報、様々なカスタムヘッダーがモリモリに詰め込まれていて、HEADERSフレームの最大サイズをオーバーしてしまったら……どうなるでしょうか?
「入りきりません!」とパニックになってしまいますよね。
—
2. そこで登場するのが「CONTINUATIONフレーム」!
入りきらないほどの巨大なヘッダーブロックを前にしたとき、HTTP/2は諦める……なんてことはしません。ここでスマートに登場するのが、今回の主役である「CONTINUATION(コンティネーション=継続)フレーム」です。
CONTINUATIONフレームの役割は、文字通り「さっきのHEADERSフレームに入りきらなかった分のヘッダーを、続きからお届けします!」という継ぎ足しの小包です。
郵便配達で例えると……
1. 1通目の封筒(HEADERSフレーム):
「入りきらないから、まずはここまでのメインのヘッダーを送るね! 続きがあるからまだ封はしないでおくよ(フラグ:END_HEADERSがオフ)」
2. 2通目の封筒(CONTINUATIONフレーム):
「こっちはさっきの続きのヘッダーだよ! まだ入りきらないから次の封筒もあるよ(CONTINUATION)」
3. 最後の封筒(CONTINUATIONフレーム):
「これでヘッダーは全部おしまい! これでパケットの組み立てを始めてね(フラグ:END_HEADERSがオン)」
このように、1つの大きなヘッダー情報を、複数のフレームに分割してリレー形式で安全に送り届ける仕組みが、CONTINUATIONフレームの正体なのです。
—
3. 実装上の注意点と、現場でハマる「意外な落とし穴」
ここまで聞くと、「なるほど、システムが勝手に分割してうまくやってくれるんだね」と思われるかもしれません。確かに基本的にはプロトコルスタックやWebサーバー(NginxやApacheなど)がよしなにやってくれますが、インフラエンジニアやバックエンド開発者が知っておくべき重要な実務上の注意点がいくつかあります。
注意点1:HEADERSとCONTINUATIONは「引き離してはいけない」厳粛な関係
ネットワークのルールとして、「HEADERSフレームが来たら、その直後に必ずCONTINUATIONフレーム(または終わりの合図)が来なければならない」という鉄の掟があります。
もし、途中に全く関係のない別のデータのフレーム(例えば、別のストリームのDATAフレームなど)が割り込んでしまった場合、受信側のサーバーやブラウザは「えっ、ヘッダーの途中に別のデータが混ざってきた! プロトコル違反だ!」と判断し、コネクションを強制切断(RST_STREAMやGOAWAY)してしまいます。
注意点2:HTTP/2のヘッダー圧縮(HPACK)との関係
HTTP/2には、ヘッダーを小さく圧縮して送る「HPACK(エッチパック)」という巧妙な仕組みがあります。
ヘッダーは順番に解凍されていくため、もしCONTINUATIONフレームが途中でロスしたり、順序が狂ったりすると、解凍のコンテキスト(文脈)がズレてしまい、通信全体がエラーになってしまいます。
設定値(パラメーター)のチューニング例
NginxなどのWebサーバーや、Go/Node.jsなどのHTTP/2実装では、このフレームサイズを制御するための設定が存在します。
例えば、Nginxの設定(※概念的なイメージ)では以下のようなパラメータが関わってきます。
http {
# HTTP/2で一度に受け付けるバッファサイズの調整
# ヘッダーが大きすぎて標準のバッファに入りきらないと、CONTINUATIONが多発するかエラーになります
http2_max_field_size 4k;
http2_max_header_size 16k;
# サーバー側の最大フレームサイズ設定(パケットの最大値)
# 通常はデフォルト値(16384バイト / 16KB)で運用されますが、
# 巨大な認証トークンなどをやり取りする環境では、このあたりのサイジングがトラブルシューティングの鍵になります。
}
もし、巨大なJWT(JSON Web Token)や社内の複雑な認証Cookieをリクエストヘッダーに載せた途端、なぜか「431 Request Header Fields Too Large」や、理由のよく分からないHTTP/2コネクションエラーが発生する場合、このフレームサイズとCONTINUATIONの処理が絡んでいることが少なくありません。
—
4. まとめ:小さなフレームに宿る、プロトコル設計の美しさ
今回は、HTTP/2の縁の下の力持ちである「CONTINUATIONフレーム」について解説しました。
- HEADERSフレームだけでは入りきらない巨大なヘッダーを分割して送るための「続きの小包」であること。
- 途中で他のデータが割り込んではいけないという、厳格な順番のルールがあること。
- 実務では、Cookieや認証トークンの肥大化に伴うヘッダーサイズ制限のトラブルシューティングで意識することがあること。
普段私たちが何気なくブラウザでWebサイトを見ている裏側では、こうした細かなフレームが何重にも行儀よく連携し、データを確実に届け合っています。
ネットワークの仕組みを知ることは、トラブルシューティングの引き出しを増やすだけでなく、私たちが書くアプリケーションの設計(例えば「無駄に大きなCookieを作らない」など)を見直す素晴らしいきっかけにもなります。
「一歩ずつ理解していけば、ネットワークの世界は怖くない!」
それでは、次回の技術解説記事でもお会いしましょう。インフラライフを一緒に楽しんでいきましょうね!
コメント