Slide 1

Slide 1 text

HTTP/2 を なんとなく理解した気になれる話

Slide 2

Slide 2 text

目標と対象 • 目標 • HTTP/2 をなんとなく理解した気になれる • 間違いがあったらごめんなさい • 対象 • TCP/IP と HTTP/1.1 をなんとなく理解してる人

Slide 3

Slide 3 text

自己紹介 • ゔぇい • Twitter: @veigr • Web: https://www.cat-ears.net • ♥: C#, Kotlin, WPF, DDD, Clean Architecture … • 業務アプリケーション開発者 • 趣味で HTTP Proxy を作っている者 • とりあえず RFC 通り(多分)動くものを作って満足してしまった • HTTP/1.1, HTTP/2, WebSocket は完全に理解した(

Slide 4

Slide 4 text

HTTP/2 概要

Slide 5

Slide 5 text

HTTP/2 とは • 目的 • ネットワークリソースの効率的な利用とレイテンシ削減 • 方法 • 同一 TCP Connection 上での通信の多重化 • ヘッダーフィールドの圧縮 • HTTP の意味論的な(セマンティクス)部分の変更はない • ので、アプリケーションレベルでは意識する機会は少ない • 実はもう結構使われてる • 標準規格 • RFC 7540 HTTP/2 • RFC 7541 HPACK (ヘッダーフィールド圧縮方式)

Slide 6

Slide 6 text

HTTP/2 と HTTP/1.1 の差異 • HTTP/1.1 は 2020/02 現在 6 つの RFC から構成されている • RFC 7230 Message Syntax and Routing • 構文と通信方法的な感じ • RFC 7231 Semantics and Content • HTTP の意味論と内容的な感じ • RFC 7232 Conditional Requests • 条件付きリクエスト • RFC 7233 Range Requests • 範囲リクエスト • RFC 7234 Caching • キャッシュ • RFC 7235 Authentication • 認証 通信の仕方 HTTP の中身 ほぼオプション

Slide 7

Slide 7 text

HTTP/2 と HTTP/1.1 の差異 • HTTP/1.1 は 2020/02 現在 6 つの RFC から構成されている • RFC 7230 Message Syntax and Routing • 構文と通信方法的な感じ • RFC 7231 Semantics and Content • HTTP の意味論と内容的な感じ • RFC 7232 Conditional Requests • 条件付きリクエスト • RFC 7233 Range Requests • 範囲リクエスト • RFC 7234 Caching • キャッシュ • RFC 7235 Authentication • 認証 通信の仕方 HTTP の中身 ほぼオプション HTTP/2 で変わるのは ここだけ! RFC 7230 → 7540

Slide 8

Slide 8 text

Client Server HTTP/2 と HTTP/1.1 の差異 • メッセージの中身は変わらないが、通信方法だけ変わる Request Message Semantics Method : GET Path : / UA : Mozilla/5.0 (… … Response Message Semantics Status : 200 Date : 2020/01/01 00:00:00 Content-Type : text/html … 変わらない 変わる! Response Message Syntax HTTP/1.1 200 OK Date : 2020/01/01 00:00:00 Content-Type : text/html … Request Message Syntax GET / HTTP/1.1 User-Agent : Mozilla/5.0 (… …

Slide 9

Slide 9 text

HTTP/2 の仕様一覧 (主観) • 通信の開始 • プロトコルアップグレード方法 など • 通信の制御 • ストリームとその多重化 • フロー制御、優先度、依存関係 など • 通信の中身 • バイナリ通信のフォーマット • HTTP メッセージの表現形式の変更 • サーバープッシュ • CONNECT メソッドの変更 • ヘッダーフィールドの圧縮方法 (HPACK) など ここの一部だけ 話します

Slide 10

Slide 10 text

HTTP/2 通信の開始

Slide 11

Slide 11 text

HTTP/2 通信の開始 • https の場合 • TLS 拡張機能の ALPN (Application Layer Protocol Negotiation) • TLS ハンドシェイク(開始)時に内部プロトコルを交渉する機能 • ブラウザ実装は https しか対応してないケースが大半なので大体これ • SslStream でのサポートは Core 2.1, Standard 2.1 以降 • http の場合 • HTTP/1.1 で開始し、Upgrade ヘッダーによりプロトコルアップグレード • 事前同意の場合 • Alt-Svc ヘッダーなどで事前に HTTP/2 対応であることを知っておく • 平文でのみ利用可

Slide 12

Slide 12 text

HTTP/2 通信の開始 – https の場合 TLS ClientHello 使えるプロトコルリスト (ALPN) ・HTTP/1.1 ・HTTP/2 TLS ServerHello 選択したプロトコル (ALPN) ・HTTP/2 Client Server

Slide 13

Slide 13 text

HTTP/2 通信の開始 – http の場合 Client Server GET / HTTP/1.1 Host: Example.com Connection: upgrade Upgrade: h2c HTTP/1.1 101 Switching Protocols Connection: upgrade Upgrade: h2c

Slide 14

Slide 14 text

HTTP/2 通信の制御

Slide 15

Slide 15 text

TCP Connection Client Server TCP Connection HTTP/1.0 の Request / Response • 1 つの TCP Connection の中に 1 つの Request / Response • TCP Connection の消費が激しい HTTP Request 1 HTTP Response 1 HTTP Request 2 HTTP Response 2

Slide 16

Slide 16 text

Client Server TCP Connection HTTP/1.1 の Request / Response • 1 つの TCP Connection の中に複数の Request / Response • Request / Response の並列処理ができない HTTP Request 1 HTTP Response 1 HTTP Request 2 HTTP Response 2

Slide 17

Slide 17 text

Client Server TCP Connection HTTP/2 の Request / Response • 1 つの Request / Response を Stream という概念でラップ • 1 つの Request / Response の交換で 1 つの Stream を完全に消費 HTTP/2 Stream HTTP Request HTTP Response

Slide 18

Slide 18 text

Client Server TCP Connection HTTP/2 の Request / Response • 1 つの TCP Connection の中に複数の Stream • 複数の Stream (Request / Response) を並列処理 (多重化) できる HTTP/2 Stream HTTP/2 Stream HTTP/2 Stream

Slide 19

Slide 19 text

HTTP/2 の Stream とは • HTTP/2 の Stream は、Stream ID で HTTP アプリケーション内の Request / Response ペアを識別するレイヤー • TCP/IP 通信は上位レイヤーになるにつれて通信相手をより詳細に 識別する • これにより Request / Response の並列処理 (多重化) が可能に レイヤー 方法 識別対象 IP IP アドレス 端末 TCP TCP ポート 端末内のアプリケーション HTTP/2 Stream Stream ID アプリケーション内の Request / Response ペア

Slide 20

Slide 20 text

• HTTP/2 は Frame という単位でバイナリ通信を行う • Frame は Stream ID を持ち、所属 Stream を識別できる TCP Connection Client Server Stream は Frame によって構成される Stream 7 HEADERS Stream 5 HEADERS Stream 3 DATA Stream 1 DATA Stream 3 DATA Stream 1 Buffer Stream 1 HEADERS Stream 1 DATA Stream 1 Buffer Stream 1 HEADERS Stream 3 Buffer Stream 3 HEADERS Stream 3 Buffer Stream 3 HEADERS

Slide 21

Slide 21 text

• HTTP/2 は HTTP/1.1 と違い管理すべき状態がいくつも存在する • 各 Stream バッファ、依存関係、優先度、HPACK の動的テーブル、 Connection の設定 など TCP Connection Client Server HTTP/2 はステートフル Stream 7 HEADERS Stream 5 HEADERS Stream 3 DATA Stream 1 DATA Stream 3 DATA Stream 1 Buffer Stream 1 HEADERS Stream 1 DATA Stream 1 Buffer Stream 1 HEADERS Stream 3 Buffer Stream 3 HEADERS Stream 3 Buffer Stream 3 HEADERS ステート フル! ステート フル!

Slide 22

Slide 22 text

Client Server TCP Connection 補足: Stream ID • クライアントから開始された Stream ID は奇数、サーバーからは偶数 • Stream ID 0 の Stream は Connection 制御用 • 設定を変更したり、切断したり、Ping を投げたりする • ID を使い切ったら切断して再接続する HTTP/2 Stream ID 0 HTTP/2 Stream ID 1 HTTP/2 Stream ID 3

Slide 23

Slide 23 text

Frame と Message の変換

Slide 24

Slide 24 text

Frame と Message の変換 • HTTP/2 Message は HTTP/2 Frame に変換されて送受信される HTTP/2 Message (Request or Response) HTTP/2 Frame HTTP/2 Frame HTTP/2 Frame HTTP/2 Frame

Slide 25

Slide 25 text

Frame Format フィールド ビット数 説明 Length 24 フレームペイロードの長さ。24ビット符号なし整数。 Type 8 フレームのタイプ。 Flags 8 各タイプ固有のフラグ。 R 1 予約済みビット。 Stream Identifier 31 Stream ID。31ビット符号なし整数。 Frame Payload 0… 各タイプ固有のペイロード。 +-----------------------------------------------+ | Length (24) | +---------------+---------------+---------------+ | Type (8) | Flags (8) | +-+-+-----------+---------------+-------------------------------+ |R| Stream Identifier (31) | +=+=============================================================+ | Frame Payload (0...) ... +---------------------------------------------------------------+ 出典: RFC 7540 4.1 ヘッダー

Slide 26

Slide 26 text

Frame Types タイプ 概要 HEADERS HTTP メッセージヘッダーを転送する CONTINUATION ヘッダー内容の続きを転送する DATA HTTP メッセージボディーを転送する PUSH_PROMISE サーバープッシュ用ストリームの作成指示と共に、 予想リクエストヘッダーを転送する PRIORITY ストリーム優先度を変更する WINDOW_UPDATE フロー制御ウィンドウサイズを変更 SETTINGS 通信設定を共有する PING Ping RST_STREAM ストリームを切断する GOAWAY コネクションの終了や重大なエラー通知

Slide 27

Slide 27 text

HTTP/2 Message Frame → Message 変換 - Body が空の場合 HEADERS Frame -- Flags -- END_HEADERS=False END_STREAM=True Header Block Fragment CONTINUATION Frame -- Flags -- END_HEADERS=True Header Block Fragment HPACK Headers … Connection 両端でヘッダーフィールドキャッシュし 再送を抑制する感じの仕組み Body (空)

Slide 28

Slide 28 text

HTTP/2 Message Frame → Message 変換 - Body がある場合 DATA -- Flags -- END_STREAM=False Data DATA -- Flags -- END_STREAM=True Data Headers Body … … HEADERS -- Flags -- END_HEADERS=False END_STREAM=False Header Block Fragment CONTINUATION -- Flags -- END_HEADERS=True Header Block Fragment HPACK …

Slide 29

Slide 29 text

Message の HTTP/1.1 からの変更点 • メッセージの表現(Syntax)は変わっているが、 意味(Semantics)的にはほぼ一緒 • Request Line / Status Line にあったような内容 は擬似ヘッダーフィールド(:methodとか)に変更 • reason-phrase (OK とか Not Found とか)は廃止 • ヘッダーフィールド名は小文字に統一 • Host が廃止され :authority に • :scheme 擬似ヘッダーフィールドが追加され、 メッセージからプロトコルスキームが判別可能に HTTP/2 Message Syntax 例 -- Headers – :authority: www.cat-ears.net :method: POST :path: / :scheme: https accept-language: ja user-agent: Mozilla/5.0 (… … -- Body – …

Slide 30

Slide 30 text

サーバープッシュ

Slide 31

Slide 31 text

/index.html サーバープッシュの目的 • クライアントがリクエストしたページに紐付くリソース(js/css)を、 サーバーがページよりも先行して送信することで通信を効率化する • HTTP/2 ではサーバー側から Stream を開始できる Client Server GET /index.html /hoge.css /hoge.js /index.html hoge.css hoge.js

Slide 32

Slide 32 text

サーバープッシュの実現方法 Client Server PUSH_PROMISE Frame 予約 Request Headers -- :method: GET :path: /hoge.css … /hoge.css Request Headers (Push Promise) /hoge.css をキャッシュ /index.html Response /hoge.css Response GET /index.html /index.html 内で必要な /hoge.css をキャッシュで解決 /index.html には /hoge.css が必要

Slide 33

Slide 33 text

サーバープッシュの実現方法 Client Server PUSH_PROMISE Frame 予約 Request Headers -- :method: GET :path: /hoge.css … /hoge.css Request Headers (Push Promise) /hoge.css をキャッシュ /index.html Response /hoge.css Response GET /index.html /index.html 内で必要な /hoge.css をキャッシュで解決 /index.html には /hoge.css が必要 • 安全かつキャッシュ可能 でなければならない (GET or HEAD) • Body は持てない キャッシュ汚染防止の為 権限のないリソースは サーバープッシュ不可

Slide 34

Slide 34 text

おまけ: .NET での HTTP/2

Slide 35

Slide 35 text

HttpClient の HTTP/2 対応 • .NET Framework • HttpClientHandler では利用不可 • WinHttpHandler (要NuGet & fw4.6 & Win10 1607)を利用すれば利用可 • .NET Core • ~2.0 : Win10 1607~のみ利用可? • WinHttpHandler を使ってる (元々 Core 用に作られたものっぽい) • 2.1~2.2 : 利用不可 • SocketsHttpHandler に移行したため • ただし WinHttpHandler を利用するよう構成すれば Windows では利用可 • 3.0~ : 利用可 • SocketsHttpHandler の HTTP/2 対応?

Slide 36

Slide 36 text

HttpClient の HTTP/2 利用方法 (Core 3.x) var client = new HttpClient(); using var request = new HttpRequestMessage(HttpMethod.Get, "https://www.cat-ears.net/") { Version = new Version(2, 0) }; using var response = await client.SendAsync(request); Console.WriteLine(response.Version); var client = new HttpClient() { DefaultRequestVersion = new Version(2, 0) }; using var response = await client.GetAsync("https://www.cat-ears.net/"); Console.WriteLine(response.Version); OR

Slide 37

Slide 37 text

サーバーサイドでの HTTP/2 • クライアントと違って通信スタックは原則アプリ外 • ので Kestrel や HTTP.sys、IIS 等ホスティング環境などに依存 • サーバープッシュ API の追加は .NET Framework 4.6 以降 • ASP.NET Core には実装されてなさそう

Slide 38

Slide 38 text

まとめ • HTTP/2 は HTTP/1.1 から通信の仕方が変わっているだけで、 HTTP メッセージの意味的には変わっていない • 通信の効率化だけが目的 • HTTP/2 はステートフルなバイナリ通信 • 1 つの TCP Connection 上に Stream という通信レイヤーを用意 • Stream の中で Frame を用いてメッセージのやり取りと通信制御を行う