【入門編】HTTP/2のストリーム状態遷移図の理解 – HTTPプロトコル・通信規格実践ガイド

こんにちは!インフラの世界へようこそ。世界最高峰のネットワークアーキテクトとして、日頃から国内外の数々の通信インフラやプロトコルの挙動を見つめてきた私ですが、今回はWebの裏側を支える超重要プレイヤー「HTTP/2」、その中でも少し通好みな「ストリームの状態遷移」についてお話しします。

「ストリーム?状態遷移?」なんだか呪文のように聞こえるかもしれませんが、安心してください。難しい専門用語やパケットの細かい仕組みは一旦置いておいて、身近な「郵便配達」に例えながら、一歩ずつ優しく紐解いていきましょう!

—

そもそもHTTP/2の「ストリーム」ってなに?

HTTP/1.1の時代、ブラウザはサーバーに対して「この画像ちょうだい!」「次はCSSちょうだい!」と、1つずつ順番にお願いしていました。まるで、1人しかいない窓口に、みんなが1列に並んで順番を待っているような状態です。これでは前の人がモタモタしていると、後ろの人はずっと待たされてしまいますよね。

そこで登場したのがHTTP/2です。HTTP/2では、1本の太い回線(TCPコネクション)の中に、「仮想的な小部屋」をいくつも同時に作れるようになりました。この小部屋の1つひとつを「ストリーム」と呼びます。

このストリーム、ただの小部屋ではありません。それぞれが「今、どんなやり取りをしている最中なのか」という「気分(状態)」を持っています。これが今回のお題である「ストリームの状態遷移」です。

—

郵便配達でイメージする「ストリームの一生」

ストリームの気持ち(状態)は、生まれてから消滅するまでにいくつかのステージを通ります。全部で5つの状態があるのですが、身近な「郵便配達」に例えると驚くほどすんなり理解できます。

1. `idle`(アイドル:まだ何もしていない状態)

  • 例:郵便局の窓口に、まだ何の用紙も出していないまっさらな状態。

2. `reserved`(リザーブド:予約されている状態)

  • 例:大きな荷物を送るために、窓口の係員さんが「この番号の棚をキープしておきますね」と確保してくれた状態。

3. `open`(オープン:絶賛やり取り中の状態)

  • 例:手紙や荷物を「どうぞ!」「ありがとう!」と実際にキャッチボールしている真っ最中。

4. `half-closed`(ハーフクローズ:片方だけおしまい状態)

  • 例:「こちらからの荷物は全部送りました(送信完了)!あとはそっちからの返事を待つだけです」という状態。

5. `closed`(クローズ:お片付け完了!)

  • 例:荷物が無事に届き、やり取りがすべて終わって小部屋の鍵を閉めた状態。

それでは、この5つの状態が、実際のネットワーク上でどのような「合図(フレーム)」を受け取ることでバトンタッチしていくのか、詳しく見ていきましょう!

—

状態遷移のドラマを覗いてみよう

ストリームたちは、サーバーとブラウザの間で飛び交う「フレーム(手紙の切れ端のようなもの)」をきっかけに、次々と状態を変えていきます。

1. すべての始まり:`idle`(アイドル)

すべてのストリームは、この「何もない状態(idle)」から始まります。まだこの番号の小部屋は使われていません。

2. 会話のスタート:`open`(オープン)

ブラウザがサーバーに「このページのデザインデータをください!」とお願いする手紙(`HEADERS`フレーム)を送った瞬間、ストリームのスイッチが入ります!

  • 状態:`idle` ➔ `open`
  • この瞬間から、お互いにデータ(`DATA`フレーム)を自由に行き来させることができるようになります。HTTP/2のマルチプレクシング(同時並行通信)の真骨頂が発揮されるのは、まさにこの `open` 状態のときです。

3. 先回りして予約する:`reserved`(リザーブド)

少し珍しいケースとして、サーバー側から「ねえ、この後こういうデータも送るから、今のうちに心の準備(場所の確保)をしておいてね!」と先回りして伝えることがあります(これを「サーバープッシュ」と言います)。

  • 状態:`idle` ➔ `reserved`
  • サーバーが先に部屋を予約した状態です。ここからさらに通信が始まると、次のステップに進みます。

4. 片方だけおしまい:`half-closed`(ハーフクローズ)

Webの通信では、たいてい「クライアント(ブラウザ)がお願いをして、サーバーがそれに答える」という流れになります。
ブラウザが「お願いの品は全部伝えたよ!」と送信を終えると、ストリームは片側だけ閉じた状態になります。

  • 状態:`open` ➔ `half-closed (remote/local)`
  • 「こっちからの用事は済んだけど、サーバーからの返事(お返事のデータ)がまだ返ってくるのを待っているよ」という、片想いのような切なくも大事な状態です。

5. すべて完結:`closed`(クローズ)

サーバーから最後の返事データが届き、ブラウザもそれを受け取ると、このストリームの役目は完全に終了です。

  • 状態:`open` または `half-closed` ➔ `closed`
  • お疲れ様でした!使っていた小部屋は綺麗に片付けられ、別の通信のために再利用されます。

—

現場で役立つ!デバッグと検証の視点

インフラエンジニアやWebアプリケーション開発者として現場に立っていると、「あれ、なんだかページの読み込みが途中で止まるぞ…?」という場面に遭遇します。そんなとき、ブラウザの検証ツール(Developer Tools)の「ネットワークタブ」や、パケットキャプチャツール(Wiresharkなど)を覗くことになります。

ここで、HTTP/2の通信をプログラムや設定でどう扱うか、簡単なイメージを見ておきましょう。例えば、Node.jsなどの環境でHTTP/2サーバーを扱う際、ストリームのイベントをフックするコードは次のように書かれます。

// Node.jsのhttp2モジュールを使ったシンプルなサーバーのイメージ
const http2 = require(‘http2’);
const fs = require(‘fs’);

// サーバーの作成
const server = http2.createServer({
key: fs.readFileSync(‘localhost-privkey.pem’),
cert: fs.readFileSync(‘localhost-cert.pem’)
});

server.on(‘stream’, (stream, headers) => {
// 【open状態の始まり】
console.log(`新しいストリームがオープンしました。ID: ${stream.id}`);

// クライアントからのリクエストヘッダーを確認
console.log(‘:path:’, headers[‘:path’]);

// レスポンスのヘッダーを送信
stream.respond({
‘content-type’: ‘text/html; charset=utf-8’,
‘:status’: 200
});

// データを書き込んで送信
stream.write(‘

こんにちは、HTTP/2の世界へ!

‘);

// 【half-closed / closedへ】
// ここで送信を終了し、ストリームの役目を終えます
stream.end();

stream.on(‘close’, () => {
console.log(`ストリームが完全にクローズ(closed)されました。ID: ${stream.id}`);
});
});

server.listen(8443, () => {
console.log(‘HTTP/2サーバーが https://localhost:8443 で稼働中…’);
});

現場のトラブルシューティングでは、「どのストリームIDが `closed` にならずに `open` のままスタック(膠着)しているか」を見つけることが、コネクションリークやレスポンス遅延の原因特定への近道となります。

—

まとめ:ストリームは「会話のキャッチボール」の記録帳

今回はHTTP/2のストリーム状態遷移(`idle`, `reserved`, `open`, `half-closed`, `closed`)について、郵便配達や小部屋の例えを交えて解説しました。

一見すると難解なプロトコルの仕様書も、「今、ブラウザとサーバーの間でどんなキャッチボールが行われているんだっけ?」という視点(コンテキスト)を持つだけで、途端に生き生きとしたドラマのように見えてきますよね。

インフラやネットワークの学びは、こうした「目に見えないデータの旅」を頭の中でイキイキと想像できるようになると、一気に楽しく、そして得意になります。
日々の開発やインフラ運用の現場で、ぜひ今回のストリームの物語を思い出してみてくださいね!

コメント

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