Upgrade to Pro — share decks privately, control downloads, hide ads and more …

HTTP2 最速実装v2

HTTP2 最速実装v2

http2 クライアントを最小限の手間で実装するための情報を解説。
2014/05/24 http2 ハッカソン#2

Yoshihiro Iwanaga

May 24, 2014
Tweet

More Decks by Yoshihiro Iwanaga

Other Decks in Technology

Transcript

  1. HTTP/1.1 の問題 ブラウザから 張れる接続数の上限: 5 client server 1 リクエストで  TCP

    コネクションを 1 つ消費。 6 個⽬目のリクエストは 送信を待たないといけない。 リクエストを 6個  送りたい ※  Keep-‐‑‒Alive  は  3-‐‑‒way  handshake  を省省略略できるだけ。結局待つことになる。
  2. 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
  3. 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
  4. 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  を⼊入れることになっている。
  5. 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
  6. 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  を番号で指定。
  7. 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のみ)
  8. 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  を表現
  9. 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
  10. stream ID の管理理ルール Client Server 1 2 3 5 4

    6 ・client  →  server  は奇数 ・server  →  client  は偶数 ・0  は全体の制御で利利⽤用
  11. 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  によって構造が違う。                   後ほど説明。
  12. Client Server req1 req3 req2 res1 res2 res1 続き res3

    必要な情報は出揃った。いざ実装!
  13. 順番 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
  14. 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 メソッドは存在しない」と処理理して終了了。 送信するデータ
  15. 順番 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
  16. 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 無しで送信
  17. 順番 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
  18. 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 に記載されている。
  19. 最短  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
  20. 順番 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
  21. 6〜~7.  レスポンス受信 まずは Data Frame の payload を⾒見見て感動しましょう  J この後紹介するサーバ実装は、Indexed

    で Huffman Encoding 7.  DATA  Frame  受信 6.  HEADERS  Frame  受信 この payload に HTML が⼊入ってます。 ここをきちんと実装するにはすごく時間がかかります。 これは後回しにして、先に DATA Frame を⾒見見てみましょう。
  22. テストサーバ  Docker file •  nghttp2 – Direct 接続⽤用 (ALPN 無し) • 

    https://gist.github.com/tsahara/ 7332972d057370d2e686 – ALPN 有り •  https://gist.github.com/tsahara/ e6831656d7e2ff99ce7e 提供:tsahara さん
  23. インデックス 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 今回の実装では利利⽤用しません。