LoginSignup
3
2

More than 5 years have passed since last update.

nghttp2を使用する #2

Last updated at Posted at 2015-03-28

HTTP2のライブラリ「nghttp2」を紹介するエントリです。

nghttp2のインストールは#1をご覧ください。

ベンチマークツールを使用する

h2loadコマンドでベンチマークを実施できます。
次の例は、100リクエスト、10コネクション、各コネクション最大で5つのDATAストリームを使用する設定でベンチマークを計測してます。-tでスレッド数も指定できます。

h2load -n100 -c10 -m5 https://nghttp2.test:8080/doc/manual/html

starting benchmark...
spawning thread #0: 10 concurrent clients, 100 total requests
Protocol: TLSv1.2
Cipher: ECDHE-RSA-AES128-GCM-SHA256
progress: 10% done
progress: 20% done
progress: 30% done
progress: 40% done
progress: 50% done
progress: 60% done
progress: 70% done
progress: 80% done
progress: 90% done
progress: 100% done

finished in 34.98ms, 2858 req/s, 150.75KB/s
requests: 100 total, 100 started, 100 done, 100 succeeded, 0 failed, 0 errored
status codes: 0 2xx, 100 3xx, 0 4xx, 0 5xx
traffic: 5400 bytes total, 4260 bytes headers, 0 bytes data
                     min         max         mean         sd        +/- sd
time for request:      173us     12.23ms      3.20ms      3.84ms    75.00%

注意
この計測はインターネットに公開されているサーバーに対して行わないでください。

HPACK tools

ヘッダー圧縮をテストするツールです。
これもGitHubのREADMEに使い方が紹介されていて、その通りに使うだけです。

HTTP2ではリクエストヘッダーのセマンティクスは次のようなものです。

:method: GET
:scheme: https
:path: /
user-agent: nghttp2

これがハフマンコーディングで圧縮されるか、プレーンテキストで送信されます。

nghttp2の圧縮ツールは、JSONかHTTP2セマンティクスのヘッダーのキーバリューを入力して、その値を検証してくれます。

下記のcasesキーで始まるJSONファイルを用意します。

{
  "cases":
  [
    {
      "headers": [
        { ":method": "GET" },
        { ":path": "/" }
      ]
    },
    {
      "headers": [
        { ":method": "POST" },
        { ":path": "/" }
      ]
    }
  ]
}

標準入力から読み込ませてテストする。

deflatehd < testjson

結果が標準出力に表示されます。

{
  "cases":
  [
{
  "seq": 0,
  "input_length": 16,
  "output_length": 5,
  "percentage_of_original_size": 31.25,
  "wire": "3fe11f8284",
  "headers": [
    {
      ":method": "GET"
    },
    {
      ":path": "/"
    }
  ],
  "header_table_size": 4096
}
,
{
  "seq": 1,
  "input_length": 17,
  "output_length": 2,
  "percentage_of_original_size": 11.76470588235294,
  "wire": "8384",
  "headers": [
    {
      ":method": "POST"
    },
    {
      ":path": "/"
    }
  ]
}
  ]
}
Overall: input=33 output=7 ratio=0.21

最初のシーケンスは「:methodGET:path/」で16バイトで、圧縮後は5バイトになり、圧縮率は31.25%で、HTTP2おけるに圧縮後のバイト列は「3fe11f8284」になるという結果。

HTTP2には一度送信したヘッダー値を覚えておいて、次回からは番号だけで指定できる仕組みがあります。これを動的テーブルといいます。

-dオプションを指定すると、動的テーブルを使用したバージョンで動作し、動的テーブルの状態が続けて出力されます。

たとえば次のようなものがseqの後に出力される。

"header_table": {
        "entries": [
          {
            "index": 1,
            "name": "user-agent",
            "value": "nghttp2",
            "referenced": true,
            "size": 49
          },
          {
            "index": 2,
            "name": ":scheme",
            "value": "https",
            "referenced": true,
            "size": 44
          },

次に圧縮データの解凍を行います。

解凍はinflatehdでできます。
圧縮後のヘッダーデータを用意します。

{
  "cases":
  [
    { "wire": "8285" },
    { "wire": "8583" }
  ]
}

最初のデータ「8285」は「x82x85」を表現していて2バイトです。
これは「:method GET」と「:path /index.html」を圧縮した結果です。

なぜこれだけの長さを2バイトに圧縮できるのか?

HTTP2では、あらかじめ静的テーブルが定義されていて、よく使用するヘッダーフィルド名、および値とのペアが番号だけで指定できるようになっています。

HTTP2の静的テーブル

この表だと「:method GET」が2で「:path /index.html」が5として定義されています。
2 :method GET
5 :path /index.html

静的テーブルや動的テーブルで番号指定でヘッダーフィールドを表現する場合は、MSB(上位4ビット)の最上位に1を立てて、下位7ビットでインデクスを表現します。

  0   1   2   3   4   5   6   7
+---+---+---+---+---+---+---+---+
| 1 |        Index (7+)         |
+---+---------------------------+

10000002  :method GET
10000005  :path /index.html

↓

0x82 10000002
0x85 10000005

↓

8285

上記の仕組みでかなり高い圧縮率を実現できる場合があります。

次にこの圧縮データを解凍してみます。

inflatehd < jsondata2
{
  "cases":
  [
{
  "seq": 0,
  "wire": "8285",
  "headers": [
    {
      ":method": "GET"
    },
    {
      ":path": "/index.html"
    }
  ]
}
,
{
  "seq": 1,
  "wire": "8583",
  "headers": [
    {
      ":path": "/index.html"
    },
    {
      ":method": "POST"
    }
  ]
}
  ]
}

正しく解凍できました。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2