Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
HTTP2 最速実装v2
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Yoshihiro Iwanaga
May 24, 2014
Technology
130
0
Share
HTTP2 最速実装v2
http2 クライアントを最小限の手間で実装するための情報を解説。
2014/05/24 http2 ハッカソン#2
Yoshihiro Iwanaga
May 24, 2014
More Decks by Yoshihiro Iwanaga
See All by Yoshihiro Iwanaga
JavaScript と Arduino でオリジナルデバイスを作ろう
yoshi
0
86
Anomaly Detection by Mean and Standard Deviation
yoshi
0
180
WebComponents LT at AQ
yoshi
0
66
MHTML LT at AQ
yoshi
2
56
HOTATE (Developers Summit 2012)
yoshi
0
36
Anomaly detection using correlations of load
yoshi
0
58
Other Decks in Technology
See All in Technology
実践ハーネスエンジニアリング:TAKTで実現するAIエージェント制御 / Practical Harness Engineering: AI Agent Control Enabled by TAKT
nrslib
9
4k
Introduction to Sansan for Engineers / エンジニア向け会社紹介
sansan33
PRO
6
74k
Introduction to Sansan, inc / Sansan Global Development Center, Inc.
sansan33
PRO
0
3k
幾億の壁を超えて/Beyond Countless Walls(JP)
ikuodanaka
0
140
CloudSec JP #005 後締め ~ソフトウェアサプライチェーン攻撃から開発者のシークレットを守る~
lhazy
0
220
サイボウズ 開発本部採用ピッチ / Cybozu Engineer Recruit
cybozuinsideout
PRO
10
78k
AI時代のガードレールとしてのAPIガバナンス
nagix
0
210
レビューしきれない?それは「全て人力でのレビュー」だからではないでしょうか
amixedcolor
0
280
AIエージェントを構築して感じた、AI時代のCDKとの向き合い方
smt7174
1
260
AIが書いたコードを信じられない問題 〜レビュー負荷を下げるために変えたこと〜 / The AI Code Trust Gap: Reducing the Review Burden
bitkey
PRO
1
430
AWS認定資格は本当に意味があるのか?
nrinetcom
PRO
1
260
KGDC_13_Amazon Q Developerで挑む! 13事例から見えたAX組織変革の最前線_公開情報
kikugawa
0
110
Featured
See All Featured
svc-hook: hooking system calls on ARM64 by binary rewriting
retrage
2
210
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
Bootstrapping a Software Product
garrettdimon
PRO
307
120k
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2.2k
Embracing the Ebb and Flow
colly
88
5k
So, you think you're a good person
axbom
PRO
2
2k
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.1k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
2.8k
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
64
53k
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
2
3.8k
Exploring anti-patterns in Rails
aemeredith
3
320
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
1
170
Transcript
HTTP/2 最速実装 v2 @y_iwanaga_
ゴール HTTP/2 クライアント を 最⼩小限の時間 で実装できる状態になる )551༷Λཧղ ࣮ʹศརͳπʔϧɾใݯΛѲ
HTTP/2 仕様 1. 全体像を掴む HTTP/1.0, 1.1 どこがダメなの? 設計思想、⽬目的を知ると理理解が早くなる。 それをもとに HTTP/2
はどんな仕様になったの? 接続確⽴立立からレスポンス受信まで 2. 実装解説
30分で HTTP/2 の全要素を解説するのは無理理。 今⽇日は最⼩小限の要素に厳選。
HTTP/1.1 の問題 ブラウザから 張れる接続数の上限: 5 client server 1 リクエストで TCP
コネクションを 1 つ消費。 6 個⽬目のリクエストは 送信を待たないといけない。 リクエストを 6個 送りたい ※ Keep-‐‑‒Alive は 3-‐‑‒way handshake を省省略略できるだけ。結局待つことになる。
HTTP/2 では 1つのTCPコネクションで 複数のリクエストを送信 Client Server request response server push
HTTP/1.1 もう1つの問題 パフォーマンスを改善していくと、 通信の遅延がボトルネックになる ネットワーク品質は⼿手が出せない場合が多い。 けど、送受信するデータサイズを⼩小さくすれば改善できる。 ⼀一般論論
HTTP/2 では ・情報をより⼩小さいデータサイズで表現 ・出来るだけ CPU とメモリの消費でカバー 設計⽅方針
以上を実現するために
TCP コネクション 1 つで 複数のリクエストを扱うためには 各リクエストの境界を判別する必要がある HTTP/2 では Frame で分割
Client Server req1 req2 res1 res2 res1 続き TCP ペイロードの中に複数のデータを連結させる
Frame の定義 0 1 2 3 0 1 2 3
4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | R | Length (14) | Type (8) | Flags (8) | +-+-+-----------+---------------+-------------------------------+ |R| Stream Identifier (31) | +-+-------------------------------------------------------------+ | Frame Payload (0...) ... +---------------------------------------------------------------+ http2-spec の 4.1. Frame Format
Frame の全体像 0 1 2 3 0 1 2 3
4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | R | Length (14) | Type (8) | Flags (8) | +-+-+-----------+---------------+-------------------------------+ |R| Stream Identifier (31) | +-+-------------------------------------------------------------+ | Frame Payload (0...) ... +---------------------------------------------------------------+ その後に Frame Payload が続く 最初の 64bit に Frame Header
Frame の仕様 0 1 2 3 0 1 2 3
4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | R | Length (14) | Type (8) | Flags (8) | +-+-+-----------+---------------+-------------------------------+ |R| Stream Identifier (31) | +-+-------------------------------------------------------------+ | Frame Payload (0...) ... +---------------------------------------------------------------+ R: Reserved. 今は 0 を⼊入れることになっている。
Frame の仕様 0 1 2 3 0 1 2 3
4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | R | Length (14) | Type (8) | Flags (8) | +-+-+-----------+---------------+-------------------------------+ |R| Stream Identifier (31) | +-+-------------------------------------------------------------+ | Frame Payload (0...) ... +---------------------------------------------------------------+ Length: Frame Payload のサイズ ※ Frame Header のサイズを⾜足しちゃダメ J
Frame の仕様 0 1 2 3 0 1 2 3
4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | R | Length (14) | Type (8) | Flags (8) | +-+-+-----------+---------------+-------------------------------+ |R| Stream Identifier (31) | +-+-------------------------------------------------------------+ | Frame Payload (0...) ... +---------------------------------------------------------------+ Type: Frame Type を番号で指定。
Frame の種類 Type ID タイプ名 意味 0x0 DATA HTTP/1 の
Body に相当 0x1 HEADERS HTTP/1 の Header に相当 0x2 PRIORITY ストリームの優先度度 0x3 RST_STREAM ストリームの異異常終了了 0x4 SETTINGS ストリームの設定 0x5 PUSH_PROMISE サーバプッシュ 0x6 PING 死活監視、遅延測定 0x7 GOAWAY コネクション終了了 0x8 WINDOW_UPDATE フロー制御設定 0x9 CONTINUATION HEADERS, PUSH_̲PROMISE の続き 0xa ALTSVC プロトコル切切り替え 0xb BLOCKED フロー制御デバッグ情報 (draft-‐‑‒12のみ)
Frame の仕様 0 1 2 3 0 1 2 3
4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | R | Length (14) | Type (8) | Flags (8) | +-+-+-----------+---------------+-------------------------------+ |R| Stream Identifier (31) | +-+-------------------------------------------------------------+ | Frame Payload (0...) ... +---------------------------------------------------------------+ Flags: 各 bit で複数オプションの On/Off を表現
Frame の仕様 0 1 2 3 0 1 2 3
4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | R | Length (14) | Type (8) | Flags (8) | +-+-+-----------+---------------+-------------------------------+ |R| Stream Identifier (31) | +-+-------------------------------------------------------------+ | Frame Payload (0...) ... +---------------------------------------------------------------+ Stream ID: 各リクエスト、レスポンスを識識別するための ID
Stream ID の意義 データがフラグメントした場合、 どの Frame の続きなのか判断したい。 そのために Stream ID
を利利⽤用 Client Server res2 res1 続き res1 の⼀一部
stream ID の管理理ルール Client Server 1 2 3 5 4
6 ・client → server は奇数 ・server → client は偶数 ・0 は全体の制御で利利⽤用
Frame の仕様 0 1 2 3 0 1 2 3
4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | R | Length (14) | Type (8) | Flags (8) | +-+-+-----------+---------------+-------------------------------+ |R| Stream Identifier (31) | +-+-------------------------------------------------------------+ | Frame Payload (0...) ... +---------------------------------------------------------------+ Frame Payload: Frame Type によって構造が違う。 後ほど説明。
Client Server req1 req3 req2 res1 res2 res1 続き res3
必要な情報は出揃った。いざ実装!
順番 Server Client 0. プロトコルネゴシエーション 1. Magic Octet 2. SETTINGS
Frame 3. SETTINGS Frame ACK 4. SETTINGS Frame ACK 5. HEADERS Frame で GET / 6. HEADERS Frame 7. DATA Frame HTTP/2 接続確⽴立立 HTML
1. Magic Octet 0x505249202a20485454502f322e300d0a0d0a534d0d0a0d0a PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n HTTP/2 をサポートしているか最終チェック HTTP/2
をサポートしないサーバに ALPN しないで直接 HTTP/2リクエストした時に問題を出さないように。 HTTP/1.1 では「PRI メソッドは存在しない」と処理理して終了了。 送信するデータ
順番 Server Client 0. プロトコルネゴシエーション 1. Magic Octet 2. SETTINGS
Frame 3. SETTINGS Frame ACK 4. SETTINGS Frame ACK 5. HEADERS Frame で GET / 6. HEADERS Frame 7. DATA Frame HTTP/2 接続確⽴立立 HTML
2〜~4. SETTINGS Frame 0 1 2 3 0 1 2
3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Identifier (8)| +---------------+-----------------------------------------------+ | Value (32) | +---------------------------------------------------------------+ 下記を 0 個以上。 ※ 受信側は、Payload Length で個数が分かる。 payload の定義 Step 2: Server へ Stream ID = 0, payload 無しで送信 Step 3: Server から Stream ID =0, flags = 0x1 (ACK), payload を受信 Step 4: Client から Stream ID = 0, flags = 0x1 (ACK), payload 無しで送信
順番 Server Client 0. プロトコルネゴシエーション 1. Magic Octet 2. SETTINGS
Frame 3. SETTINGS Frame ACK 4. SETTINGS Frame ACK 5. HEADERS Frame で GET / 6. HEADERS Frame 7. DATA Frame HTTP/2 接続確⽴立立 HTML
5. HEADERS Frame 最後の難関 0 1 2 3 0 1
2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Pad High? (8) | Pad Low? (8) | +-+-------------+---------------+-------------------------------+ |E| Stream Dependency? (31) | +-+-------------+-----------------------------------------------+ | Weight? (8) | +-+-------------+-----------------------------------------------+ | Header Block Fragment (*) ... +---------------------------------------------------------------+ | Padding (*) ... +---------------------------------------------------------------+ flags = END_̲HEADERS | END_̲STREAM stream ID = 1 Header Block Fragment: Payload はここだけになる。 ※ 仕様は HPACK-07 に記載されている。
最短 HPACK http://example.com/ を GET する場合 0 1 2 3
4 5 6 7 +---+---+---+---+---+---+---+---+ | 0 | 0 | 0 | 1 | 0 | +---+---+-----------------------+ | 0 | Name Length (7+) | +---+---------------------------+ | Name String (Length octets) | +---+---------------------------+ | 0 | Value Length (7+) | +---+---------------------------+ | Value String (Length octets) | +-------------------------------+ Name Value :scheme http :authority example.com :path / :method GET Header Block の定義 (Literal Header Field never Indexed & ASCII Encoding パターン) サーバに送信する情報 最後に、4つの Header Block を連結すれば、最短 HPACK 完了了! :scheme は 7 ⽂文字 :scheme は ASCII で 0x3a736368656d65 http は 4 ⽂文字 http は ASCII で 0x68747470
順番 Server Client 0. プロトコルネゴシエーション 1. Magic Octet 2. SETTINGS
Frame 3. SETTINGS Frame ACK 4. SETTINGS Frame ACK 5. HEADERS Frame で GET / 6. HEADERS Frame 7. DATA Frame HTTP/2 接続確⽴立立 HTML
6〜~7. レスポンス受信 まずは Data Frame の payload を⾒見見て感動しましょう J この後紹介するサーバ実装は、Indexed
で Huffman Encoding 7. DATA Frame 受信 6. HEADERS Frame 受信 この payload に HTML が⼊入ってます。 ここをきちんと実装するにはすごく時間がかかります。 これは後回しにして、先に DATA Frame を⾒見見てみましょう。
実装を効率率率よく進めるために • 仕様ドキュメント – HTTP/2-‐‑‒12 • http://tools.ietf.org/html/draft-‐‑‒ietf-‐‑‒httpbis-‐‑‒ http2-‐‑‒12 – HPACK-‐‑‒07 • http://tools.ietf.org/html/draft-‐‑‒ietf-‐‑‒httpbis-‐‑‒
header-‐‑‒compression-‐‑‒07 • Public Test Server – nghttp2 (h12c, upgrade/direct) • http://nghttp2.org/
テストサーバ Docker file • nghttp2 – Direct 接続⽤用 (ALPN 無し) •
https://gist.github.com/tsahara/ 7332972d057370d2e686 – ALPN 有り • https://gist.github.com/tsahara/ e6831656d7e2ff99ce7e 提供:tsahara さん
backup slides
エンコーディング • Huffman – 出現頻度度の⾼高い⽂文字を少ない bit で表現 – でも、今回の実装では使わない • ASCII – ⾮非圧縮。簡単。
– 今回の実装ではこちらを使う
インデックス index Header Name Header Value 1 :authority 2 :method
GET 3 :method POST 4 :path / 5 :path /index.html 6 :scheme http 7 :scheme https 8 :status 200 9 :status 204 (以下略略) よく使うヘッダ名と値を 番号で指定 http://tools.ietf.org/html/ draft-ietf-httpbis-header-compression-07#appendix-B 今回の実装では利利⽤用しません。
リファレンスセット • ヘッダの差分のみを送信するためのテー ブル – 何度度も同じデータを送信しないで済む。 – そのために、サーバとクライアントで学習 テーブルを同期する必要がある。 – 今回の実装では利利⽤用しません