Open2
HTTP/1.1, /2, /3
はじめに
こちらの書籍を参考にします。技術書典にて購入。
HTTP/1.1 から /2【通信の多重化・ストリーム・フレーム】
図のように「通信の多重化により、効率的」なのが1.1から2の違い
HTTP/2のベースは、Googleが提唱したSPDY(スピーディ)というプロトコル
ストリーム
具体的には
- HTTP/1.1:「リクエスト①→リクエスト①受付→①送信→①受信→リクエスト②・・・」
- HTTP/2:「リクエスト①②③→リクエスト①②③受付→①②③送信→①②③受信」
- 1つのコネクションの中に、擬似的に複数のコネクションを作成
これにより
- リクエストを待つ時間が削減された
- ダウンロード量が増え、速度が上がり、ダウンロード時間が削減された
- 総じて「サーバーもクライアントも余力があった1.1」「最大限性能を引き出せる2」と言える
フレーム
ざっくり言えば、データを送受信する際の最小単位
HTTP/1.1からの変化は「ヘッダなどの情報のフォーマット」
HTTP/1.1では「テキスト形式」だったが、HTTP/2では「固定長のバイナリ形式」になった
テキスト形式のデータ構造は柔軟性と拡張性、さらに人間が読めてデバッグが容易というメリットはある。しかしHTTPが生まれた直後ならともかく、プロトコルに求められる役割が確定した現在となっては、手間がかかる方法だ。効率性を重視してバイナリー形式を採用するのは妥当だろう。
- HTTP/1.1における「1つずつしか処理されないため、待たされてしまう問題」を「Head of Line Blocking」と呼ぶ
-
HTTP/2において「HTTPのHead of Line Blocking」は解消された
- ただし、「TCPレベルのパケットによるHead of Line Blocking」は依然として残っている
- TCPは送達を「保証」する ーパケットがロスした場合再送する間に、他のパケットを待たせるHead of Line Blockingが発生する
- HTTP/3では、Head of Line Blockingが発生するTCPではなくQUICを用いている(後述)
プライオリティ
通信の多重化をより柔軟・効率的に行う。
- 横のリソース配分を行う「Stream Weight」
- 縦の依存関係決定を行う「Stream Dependency」
がある。
Stream Weight
1 ~ 256 の値を設定し、ストリーム毎の通信リソースの配分を決定します。
例えば以下の場合、4:2:1のサイズ比で通信リソースを受け取ることになります。
- ID: 1 - SW: 128
- ID: 2 - SW: 64
- ID: 3 - SW: 32
このStream Weightにより、割り込みの優先事項にも柔軟に対応できます。
Client -> Server
ID: 1 - SW: 128
ID: 2 - SW: 128
...
ID: 10 - SW: 128
---
Server -> Client
ID: 1 - DATA 6.4KB
ID: 2 - DATA 6.4KB
...
ID: 10 - DATA 6.4KB
↓
割り込みでID: 11が発生!
最優先で処理を完了したい。
Client -> Server
ID: 1 - SW: 1
ID: 2 - SW: 1
...
ID: 10 - SW: 1
ID: 11 - SW: 256
---
Server -> Client
DATA 0.24KB
DATA 0.24KB
...
DATA 0.24KB
DATA 61.8KB
Stream Dependency
ストリームの親・兄弟関係を設定できます。
A -> B
A -> B / C -> D
A -> B -> C / D / E -> F / G
- 親 -> 子
-
/
で区切られた関係(B / C
など)は、兄弟
親グループ全ての通信が終わった後、子グループの通信が始まります。
兄弟間では、Stream Weightに基づいた割り振りが行われます。