これは、C でのハイパーテキスト転送プロトコル バージョン 2 の実装です。
HTTP/2 のフレーミング層は、再利用可能な C ライブラリとして実装されています。その上に、HTTP/2 クライアント、サーバー、プロキシを実装しました。また、HTTP/2 の負荷テストおよびベンチマーク ツールも開発しました。
HPACK エンコーダーとデコーダーはパブリック API として利用できます。
nghttp2 は元々、RFC 7540 HTTP/2 および RFC 7541 HPACK - Header Compression for HTTP/2 に基づいて開発されました。現在、RFC 9113 を実装するためにコードを更新しています。
nghttp2 コードベースは、spdylay (https://github.com/tatsuhiro-t/spdylay) プロジェクトからフォークされました。
nghttp2 実装を試すには、次のエンドポイントが利用できます。
https://nghttp2.org/ (TLS + ALPN および HTTP/3)
このエンドポイントは、ALPN 経由でh2
、 h2-16
、 h2-14
、およびhttp/1.1
をサポートし、HTTP/2 接続には TLSv1.2 が必要です。
HTTP/3にも対応しています。
http://nghttp2.org/ (HTTP アップグレードおよび HTTP/2 ダイレクト)
h2c
とhttp/1.1
。
libnghttp2 ライブラリを構築するには、次のパッケージが必要です。
ドキュメントを構築するには、以下をインストールする必要があります。
libnghttp2 (C ライブラリ) のみが必要な場合は、上記のパッケージだけで十分です。 --enable-lib-only
使用して、libnghttp2 のみがビルドされるようにします。これにより、バンドルされたアプリケーションのビルドに関連する潜在的なビルド エラーが回避されます。
src
ディレクトリでアプリケーション プログラム ( nghttp
、 nghttpd
、 nghttpx
、およびh2load
) をビルドして実行するには、次のパッケージが必要です。
nghttp
で-a
オプション (ダウンロードされたリソースからリンクされたアセットを取得) を有効にするには、次のパッケージが必要です。
nghttpx で systemd サポートを有効にするには、次のパッケージが必要です。
HPACK ツールには次のパッケージが必要です。
サンプルディレクトリの下にソースをビルドするには、libevent が必要です。
長時間実行されるサーバー プログラム ( nghttpd
およびnghttpx
) でのヒープの断片化を軽減するには、jemalloc の使用をお勧めします。
ジェマロック
注記
Alpine Linux は現在、musl の制限により malloc 置換をサポートしていません。詳細については、第 762 号を参照してください。
BoringSSL または aws-lc ビルドの場合、アプリケーションで RFC 8879 TLS 証明書圧縮を有効にするには、次のライブラリが必要です。
nghttpx の mruby サポートを有効にするには、mruby が必要です。 C++ ABI を明示的に有効にして mruby をビルドする必要があり、おそらく他の mrgems が必要です。mruby は third-party/mruby ディレクトリの下の git サブモジュールによって管理されます。現在、nghttpx の mruby サポートはデフォルトで無効になっています。 mruby サポートを有効にするには、 --with-mruby
構成オプションを使用します。この記事の執筆時点では、Debian/Ubuntu の libmruby-dev および mruby パッケージは C++ ABI を有効にしていないため、nghttp2 では使用できないことに注意してください。 mruby をビルドするには、次のパッケージが必要です。
nghttpx は、OpenSSL の権限分離エンジンである Neverbleed をサポートしています。つまり、Heartbleed のような重大なバグが悪用された場合に秘密鍵が漏洩するリスクを最小限に抑えます。ネバーブリードはデフォルトでは無効になっています。これを有効にするには、 --with-neverbleed
構成オプションを使用します。
h2load および nghttpx の実験的な HTTP/3 サポートを有効にするには、次のライブラリが必要です。
--enable-http3
構成オプションを使用して、h2load および nghttpx の HTTP/3 機能を有効にします。
受信 QUIC UDP データグラムを nghttpx の正しいソケットに送信するオプションの eBPF プログラムを構築するには、次のライブラリが必要です。
--with-libbpf
設定オプションを使用して eBPF プログラムを構築します。 libbpf をビルドするには libelf-dev が必要です。
Ubuntu 20.04 の場合、ソース コードから libbpf をビルドできます。 nghttpx では、設定のリロードと実行可能ファイルのホットスワップに eBPF プログラムが必要です。
libnghttp2 C ソース コードをコンパイルするには、C99 コンパイラが必要です。 gcc 4.8 が適切であることが知られています。 C++ソースコードをコンパイルするには、C++20準拠のコンパイラが必要です。少なくとも g++ >= 12 および Clang++ >= 15 が動作することがわかっています。
注記
nghttpx で mruby サポートを有効にするには、 --with-mruby
構成オプションを使用します。
注記
Mac OS X ユーザーは、クラッシュを防ぐために、nghttpd、nghttpx、および h2load のマルチスレッドを無効にする--disable-threads
設定オプションが必要になる場合があります。 Mac OS X プラットフォームでマルチスレッドを機能させるためのパッチを歓迎します。
注記
関連するアプリケーション (nghttp、nghttpd、nghttpx、および h2load) をコンパイルするには、 --enable-app
appconfigure オプションを使用し、上記で指定された要件が満たされていることを確認する必要があります。通常、これらのアプリケーションを構築するために必要な依存関係をチェックするスクリプトを構成し、 --enable-app
自動的に有効にするため、明示的に使用する必要はありません。ただし、アプリケーションが構築されていないことが判明した場合は、 --enable-app
使用すると、依存関係の欠落などの原因が見つかる可能性があります。
注記
サードパーティのライブラリを検出するには、pkg-config が使用されます (ただし、一部のライブラリ (libev など) では pkg-config を使用しません)。デフォルトでは、pkg-config は標準の場所 (/usr/lib/pkgconfig など) で*.pc
ファイルを検索します。カスタムの場所にある*.pc
ファイルを使用する必要がある場合は、次のようにPKG_CONFIG_PATH
環境変数へのパスを指定し、それを構成スクリプトに渡します。
$ ./configure PKG_CONFIG_PATH=/path/to/pkgconfig
pkg-config 管理ライブラリの場合、 *_CFLAG
および*_LIBS
環境変数が定義されます ( OPENSSL_CFLAGS
、 OPENSSL_LIBS
など)。これらの変数に空でない文字列を指定すると、pkg-config が完全にオーバーライドされます。つまり、これらが指定されている場合、pkg-config は検出に使用されず、ユーザーはこれらの変数に正しい値を指定する責任があります。これらの変数の完全なリストを表示するには、 ./configure -h
を実行します。
Ubuntu 22.04 LTS を使用している場合は、次のコマンドを実行して必要なパッケージをインストールします。
sudo apt-get install g++ Clang make binutils autoconf automake
autotools-dev libtool pkg-config
zlib1g-dev libssl-dev libxml2-dev libev-dev
libevent-dev libjansson-dev
libc-ares-dev libjemalloc-dev libsystemd-dev
Ruby-dev bison libelf-dev
nghttp2 プロジェクトは、nghttp2 ソース コードと生成されたビルド ファイルを含む tar アーカイブを定期的にリリースします。これらはリリースページからダウンロードできます。
git から nghttp2 をビルドするには、autotools 開発パッケージが必要です。 tar アーカイブからのビルドにはそれらが必要ないため、はるかに簡単です。通常のビルド手順は次のとおりです。
$ tar xf nghttp2-XYZtar.bz2
$ cd nghttp2-XYZ
$ ./configure
$メイク
git からのビルドは簡単ですが、少なくとも autoconf 2.68 が使用されていることを確認してください。
$ git サブモジュール更新 --init
$ autoreconf -i
$オートメイク
$ autoconf
$ ./configure
$メイク
ネイティブ Windows nghttp2 DLL を構築する最も簡単な方法は、cmake を使用することです。 Visual C++ Build Tools の無料バージョンは正常に動作します。
cmake
を実行します。cmake --build
実行してライブラリをビルドします。上記の手順では、nghttp2 ライブラリのみが生成される可能性が高いことに注意してください。バンドルされたアプリケーションはコンパイルされません。
Mingw 環境では、ライブラリlibnghttp2-X.dll
とlibnghttp2.a
のみをコンパイルできます。
アプリケーション ( h2load
、 nghttp
、 nghttpx
、 nghttpd
) をコンパイルする場合は、Cygwin 環境を使用する必要があります。
Cygwin 環境でアプリケーションをコンパイルするには、最初に libev をコンパイルしてインストールする必要があります。
次に、マクロ__STRICT_ANSI__
の定義を解除する必要があります。そうしないと、関数fdopen
、 fileno
、およびstrptime
使用できなくなります。
サンプルコマンドは次のようになります。
$export CFLAGS="-U__STRICT_ANSI__ -I$libev_PREFIX/include -L$libev_PREFIX/lib"
$ エクスポート CXXFLAGS=$CFLAGS
$ ./configure
$メイク
examples/
下でアプリケーションをコンパイルする場合は、libevent のインストールと競合するため、libev のインストールからevent.h
削除するか名前を変更する必要があります。
make install
を使用して nghttp2 ツール スイートをインストールした後、同様のエラーが発生する可能性があります。
nghttpx: 共有ライブラリのロード中にエラーが発生しました: libnghttp2.so.14: 共有オブジェクト ファイルを開けません: そのようなファイルまたはディレクトリはありません
これは、ツールがlibnghttp2.so
共有ライブラリを見つけることができないことを意味します。
共有ライブラリキャッシュを更新するには、 sudo ldconfig
実行します。
注記
ドキュメントはまだ不完全です。
ドキュメントを構築するには、次を実行します。
$ HTMLを作る
ドキュメントはdoc/manual/html/
の下に生成されます。
生成されたドキュメントはmake install
ではインストールされません。
オンライン ドキュメントは https://nghttp2.org/documentation/ から入手できます。
HTTP/3 機能を有効にして h2load および nghttpx をビルドするには、 --enable-http3
を指定してconfigure スクリプトを実行します。
nghttpx が構成をリロードし、古いワーカー プロセスを正常に終了しながら実行可能ファイルを交換するには、eBPF が必要です。 --enable-http3 --with-libbpf
を指定して構成スクリプトを実行し、eBPF プログラムをビルドします。リロード中に既存の接続を維持するには、QUIC キーイング マテリアルを--frontend-quic-secret-file
で設定する必要があります。
HTTP/3 対応の h2load および nghttpx を構築する詳細な手順は次のとおりです。
aws-lc をビルドします。
$ git clone -- Depth 1 -b v1.39.0 https://github.com/aws/aws-lc
$ cd aws-lc
$ cmake -B build -DDISABLE_GO=ON --install-prefix=$PWD/opt
$ make -j$(nproc) -C build
$ cmake --install ビルド
$ cd ..
nghttp3 をビルドします。
$ git clone -- Depth 1 -b v1.6.0 https://github.com/ngtcp2/nghttp3
$ cd nghttp3
$ git submodule update --init --length 1
$ autoreconf -i
$ ./configure --prefix=$PWD/build --enable-lib-only
$ make -j$(nproc)
$メイクインストール
$ cd ..
ngtcp2 をビルドします。
$ git clone -- Depth 1 -b v1.9.1 https://github.com/ngtcp2/ngtcp2
$ cd ngtcp2
$ git submodule update --init --length 1
$ autoreconf -i
$ ./configure --prefix=$PWD/build --enable-lib-only --with-boringssl
BORINGSSL_CFLAGS="-I$PWD/../aws-lc/opt/include"
BORINGSSL_LIBS="-L$PWD/../aws-lc/opt/lib -lssl -lcrypto"
$ make -j$(nproc)
$メイクインストール
$ cd ..
Linux ディストリビューションに libbpf-dev >= 0.7.0 がない場合は、ソースからビルドします。
$ git clone -- Depth 1 -b v1.4.6 https://github.com/libbpf/libbpf
$ cd libbpf
$ PREFIX=$PWD/build make -C src install
$ cd ..
nghttp2 をビルドします。
$ git clone https://github.com/nghttp2/nghttp2
$ cd nghttp2
$ git サブモジュール更新 --init
$ autoreconf -i
$ ./configure --with-mruby --enable-http3 --with-libbpf
CC=clang-15 CXX=clang++-15
PKG_CONFIG_PATH="$PWD/../aws-lc/opt/lib/pkgconfig:$PWD/../nghttp3/build/lib/pkgconfig:$PWD/../ngtcp2/build/lib/pkgconfig:$PWD/ ../libbpf/build/lib64/pkgconfig"
LDFLAGS="$LDFLAGS -Wl,-rpath,$PWD/../aws-lc/opt/lib -Wl,-rpath,$PWD/../libbpf/build/lib64"
$ make -j$(nproc)
eBPF プログラムreuseport_kern.o
は、bpf ディレクトリの下にあるはずです。 --quic-bpf-program-file=bpf/reuseport_kern.o
オプションを nghttpx に渡してロードします。 nghttpx - HTTP/2 プロキシ - HOW-TO の HTTP/3 セクションも参照してください。
単体テストは、 make check
実行するだけで実行できます。
nghttpx プロキシ サーバーの統合テストがあります。テストは Go プログラミング言語で記述され、そのテスト フレームワークを使用します。次のライブラリに依存しています。
Go モジュールはこれらの依存関係を自動的にダウンロードします。
テストを実行するには、 integration-tests
ディレクトリで次のコマンドを実行します。
$それを作ります
テスト内では、ポート 3009 を使用してテスト対象サーバーを実行します。
nghttp2 v1.0.0 では、下位互換性のない変更がいくつか導入されました。このセクションでは、これらの変更点と v1.0.0 への移行方法について説明します。
h2
とh2c
になりました以前にh2-14
およびh2c-14
を発表しました。 v1.0.0 は最終プロトコル バージョンを実装し、ALPN ID をh2
およびh2c
に変更しました。この変更を反映するために、マクロNGHTTP2_PROTO_VERSION_ID
、 NGHTTP2_PROTO_VERSION_ID_LEN
、 NGHTTP2_CLEARTEXT_PROTO_VERSION_ID
、およびNGHTTP2_CLEARTEXT_PROTO_VERSION_ID_LEN
が更新されました。
基本的に、既存のアプリケーションは何もする必要はなく、この変更には再コンパイルするだけで十分です。
「クライアント接続プリフェイス」は、クライアント接続プリフェイスの最初の 24 バイトを意味するために使用します。クライアント接続のプリフェイスは 24 バイトのクライアント マジック バイト文字列とそれに続く SETTINGS フレームで構成されているため、これは技術的には正しくありません。明確にするために、この 24 バイトのバイト文字列と更新された API を「クライアント マジック」と呼びます。
NGHTTP2_CLIENT_CONNECTION_PREFACE
NGHTTP2_CLIENT_MAGIC
に置き換えられました。NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN
NGHTTP2_CLIENT_MAGIC_LEN
に置き換えられました。NGHTTP2_BAD_PREFACE
NGHTTP2_BAD_CLIENT_MAGIC
に名前変更されましたすでに非推奨となっているNGHTTP2_CLIENT_CONNECTION_HEADER
およびNGHTTP2_CLIENT_CONNECTION_HEADER_LEN
は削除されました。
アプリケーションがこれらのマクロを使用している場合は、古いマクロを新しいマクロに置き換えるだけです。 v1.0.0 以降、クライアント マジックはライブラリによって送信されるため (次のサブセクションを参照)、クライアント アプリケーションはこれらのマクロの使用を削除するだけで済みます。
以前の nghttp2 ライブラリはクライアント マジック (クライアント接続の先頭の最初の 24 バイトのバイト文字列) を送信せず、クライアント アプリケーションはそれを独自に送信する必要がありました。 v1.0.0 以降、クライアント マジックはnghttp2_session_send()
またはnghttp2_session_mem_send2()
の最初の呼び出しを介してライブラリによって送信されます。
クライアント マジックを送信するクライアント アプリケーションは、関連するコードを削除する必要があります。
Alt-Svc の仕様はまだ最終決定されていません。 API を安定させるために、Alt-Svc 関連の API をすべて nghttp2 から削除することにしました。
NGHTTP2_EXT_ALTSVC
が削除されました。nghttp2_ext_altsvc
削除されました。v0.7 シリーズでは Alt-Svc の機能がすでに削除されており、基本的には機能しません。これらのマクロと構造体を使用しているアプリケーションでは、これらの行を削除してください。
以前は、 nghttp2_on_invalid_frame_recv_cb_called
、 nghttp2_error_code
で定義されたerror_code
パラメータとして受け取りました。ただし、デバッグできるほど詳細ではありません。したがって、代わりにより詳細なnghttp2_error
値を使用することにしました。
このコールバックを使用するアプリケーションは、コールバック署名を更新する必要があります。 error_code
HTTP/2 エラー コードとして扱う場合は、 nghttp2_error
として扱われるようにコードを更新します。
以前の nghttp2 はクライアント マジック (24 バイトのバイト文字列) を処理しませんでした。これに対処するには、 nghttp2_option_set_recv_client_preface()
使用する必要がありました。 v1.0.0 以降、nghttp2 はデフォルトでクライアント マジックを処理し、 nghttp2_option_set_recv_client_preface()
が削除されました。
一部のアプリケーションではこの動作を無効にする必要があるため、これを実現するためにnghttp2_option_set_no_recv_client_magic()
を追加しました。
nghttp2_option_set_recv_client_preface()
をゼロ以外の値で使用しているアプリケーションは、それを削除してください。
nghttp2_option_set_recv_client_preface()
をゼロ値で使用するアプリケーション、またはそれを使用しないアプリケーションは、ゼロ以外の値でnghttp2_option_set_no_recv_client_magic()
を使用する必要があります。
src
ディレクトリには、HTTP/2 クライアント、サーバー、およびプロキシ プログラムが含まれています。
nghttp
HTTP/2 クライアントです。事前の知識、HTTP アップグレード、ALPN TLS 拡張機能があれば、HTTP/2 サーバーに接続できます。
フレーミング情報の詳細出力モードがあります。 nghttp
クライアントからの出力例を次に示します。
$ nghttp -nv https://nghttp2.org
[ 0.190] 接続されました
ネゴシエートされたプロトコル: h2
[ 0.212] recv SETTINGS フレーム
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.212] SETTINGS フレームを送信
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.212] SETTINGS フレームを送信
;確認応答
(niv=0)
[ 0.212] PRIORITY フレームを送信
(dep_stream_id=0、weight=201、exclusive=0)
[ 0.212] PRIORITY フレームを送信
(dep_stream_id=0、weight=101、exclusive=0)
[ 0.212] PRIORITY フレームを送信
(dep_stream_id=0、weight=1、exclusive=0)
[ 0.212] PRIORITY フレームを送信
(dep_stream_id=7、weight=1、exclusive=0)
[ 0.212] PRIORITY フレームを送信
(dep_stream_id=3、weight=1、exclusive=0)
[ 0.212] HEADERS フレームを送信
; END_STREAM | END_HEADERS |優先度
(padlen=0、dep_stream_id=11、weight=16、exclusive=0)
;新しいストリームを開く
:メソッド: GET
:パス: /
:スキーム: https
:権限: nghttp2.org
受け入れる: */*
accept-encoding: gzip、deflate
ユーザーエージェント: nghttp2/1.0.1-DEV
[ 0.221] recv SETTINGS フレーム
;確認応答
(niv=0)
[ 0.221] 受信 (stream_id=13) :メソッド: GET
[ 0.221] recv (stream_id=13) :scheme: https
[ 0.221] recv (stream_id=13) :path: /stylesheets/screen.css
[ 0.221] recv (stream_id=13) :authority: nghttp2.org
[ 0.221] recv (stream_id=13) accept-encoding: gzip、deflate
[ 0.222] recv (stream_id=13) ユーザーエージェント: nghttp2/1.0.1-DEV
[ 0.222] recv PUSH_PROMISE フレーム
; END_HEADERS
(padlen=0、promise_stream_id=2)
[ 0.222] 受信 (ストリーム ID=13) :ステータス: 200
[ 0.222] recv (stream_id=13) 日付: 2015 年 5 月 21 日木 16:38:14 GMT
[ 0.222] recv (stream_id=13) コンテンツタイプ: text/html
[ 0.222] recv (stream_id=13) 最終更新日: Fri, 15 May 2015 15:38:06 GMT
[ 0.222] recv (stream_id=13) etag: W/"555612de-19f6"
[ 0.222] 受信 (stream_id=13) リンク: ; rel=プリロード; as=スタイルシート
[ 0.222] recv (stream_id=13) コンテンツエンコーディング: gzip
[ 0.222] 受信 (stream_id=13) サーバー: nghttpx nghttp2/1.0.1-DEV
[ 0.222] recv (stream_id=13) via: 1.1 nghttpx
[ 0.222] recv (stream_id=13) 厳密なトランスポート セキュリティ: max-age=31536000
[ 0.222] recv HEADERS フレーム
; END_HEADERS
(パドレン=0)
;最初の応答ヘッダー
[ 0.222] recv DATA フレーム
; END_STREAM
[ 0.222] 受信 (ストリーム ID=2) :ステータス: 200
[ 0.222] recv (stream_id=2) 日付: 2015 年 5 月 21 日木 16:38:14 GMT
[ 0.222] recv (stream_id=2) コンテンツタイプ: text/css
[ 0.222] recv (stream_id=2) 最終更新日: Fri, 15 May 2015 15:38:06 GMT
[ 0.222] recv (stream_id=2) etag: W/"555612de-9845"
[ 0.222] recv (stream_id=2) コンテンツエンコーディング: gzip
[ 0.222] recv (stream_id=2) サーバー: nghttpx nghttp2/1.0.1-DEV
[ 0.222] recv (stream_id=2) via: 1.1 nghttpx
[ 0.222] recv (stream_id=2) 厳密なトランスポート セキュリティ: max-age=31536000
[ 0.222] recv HEADERS フレーム
; END_HEADERS
(パドレン=0)
;最初のプッシュ応答ヘッダー
[ 0.228] recv DATA フレーム
; END_STREAM
[ 0.228] GOAWAY フレームを送信
(last_stream_id=2、error_code=NO_ERROR(0x00)、opaque_data(0)=[])
HTTP アップグレードは次のように実行されます。
$ nghttp -nvu http://nghttp2.org
[ 0.011] 接続されました
[ 0.011] HTTP アップグレード リクエスト
GET/HTTP/1.1
ホスト: nghttp2.org
接続: アップグレード、HTTP2 設定
アップグレード: h2c
HTTP2 設定: AAMAAABkAAQAAP__
受け入れる: */*
ユーザーエージェント: nghttp2/1.0.1-DEV
[ 0.018] HTTP アップグレード応答
HTTP/1.1 101 スイッチングプロトコル
接続: アップグレード
アップグレード: h2c
[ 0.018] HTTP アップグレード成功
[ 0.018] recv SETTINGS フレーム
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.018] SETTINGS フレームを送信
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[ 0.018] SETTINGS フレームを送信
;確認応答
(niv=0)
[ 0.018] PRIORITY フレームを送信
(dep_stream_id=0、weight=201、exclusive=0)
[ 0.018] PRIORITY フレームを送信
(dep_stream_id=0、weight=101、exclusive=0)
[ 0.018] PRIORITY フレームを送信
(dep_stream_id=0、weight=1、exclusive=0)
[ 0.018] PRIORITY フレームを送信
(dep_stream_id=7、weight=1、exclusive=0)
[ 0.018] PRIORITY フレームを送信
(dep_stream_id=3、weight=1、exclusive=0)
[ 0.018] PRIORITY フレームを送信
(dep_stream_id=11、weight=16、exclusive=0)
[ 0.019] recv (stream_id=1) :メソッド: GET
[ 0.019] recv (stream_id=1) :scheme: http
[ 0.019] recv (stream_id=1) :path: /stylesheets/screen.css
[ 0.019] recv (stream_id=1) ホスト: nghttp2.org
[ 0.019] recv (stream_id=1) ユーザーエージェント: nghttp2/1.0.1-DEV
[ 0.019] recv PUSH_PROMISE フレーム
; END_HEADERS
(padlen=0、promise_stream_id=2)
[ 0.019] 受信 (ストリーム ID=1) :ステータス: 200
[ 0.019] recv (stream_id=1) 日付: 2015 年 5 月 21 日木 16:39:16 GMT
[ 0.019] recv (stream_id=1) コンテンツタイプ: text/html
[ 0.019] recv (stream_id=1) コンテンツ長: 6646
[ 0.019] recv (stream_id=1) 最終更新日: Fri, 15 May 2015 15:38:06 GMT
[ 0.019] recv (stream_id=1) etag: "555612de-19f6"
[ 0.019] recv (stream_id=1) リンク: ; rel=プリロード; as=スタイルシート
[ 0.019] recv (stream_id=1) 受け入れ範囲: バイト
[ 0.019] 受信 (stream_id=1) サーバー: nghttpx nghttp2/1.0.1-DEV
[ 0.019] recv (stream_id=1) via: 1.1 nghttpx
[ 0.019] recv HEADERS フレーム
; END_HEADERS
(パドレン=0)
;最初の応答ヘッダー
[ 0.019] recv DATA フレーム
; END_STREAM
[ 0.019] 受信 (ストリーム ID=2) :ステータス: 200
[ 0.019] recv (stream_id=2) 日付: 2015 年 5 月 21 日木 16:39:16 GMT
[ 0.019] recv (stream_id=2) コンテンツタイプ: text/css
[ 0.019] recv (stream_id=2) コンテンツ長: 38981
[ 0.019] recv (stream_id=2) 最終更新日: Fri, 15 May 2015 15:38:06 GMT
[ 0.019] recv (stream_id=2) etag: "555612de-9845"
[ 0.019] recv (stream_id=2) 受け入れ範囲: バイト
[ 0.019] recv (stream_id=2) サーバー: nghttpx nghttp2/1.0.1-DEV
[ 0.019] recv (stream_id=2) via: 1.1 nghttpx
[ 0.019] recv HEADERS フレーム
; END_HEADERS
(パドレン=0)
;最初のプッシュ応答ヘッダー
[ 0.026] recv DATA フレーム
[ 0.027] recv DATA フレーム
[ 0.027] WINDOW_UPDATE フレームを送信
(ウィンドウサイズ増分=33343)
[ 0.032] WINDOW_UPDATE フレームを送信
(ウィンドウサイズ増分=33707)
[ 0.032] recv DATA フレーム
; END_STREAM
[ 0.032] recv SETTINGS フレーム
;確認応答
(niv=0)
[ 0.032] GOAWAY フレームを送信
(last_stream_id=2、error_code=NO_ERROR(0x00)、opaque_data(0)=[])
-s
オプションを使用すると、 nghttp
リクエストのタイミング情報を完了時間順に並べて出力します。
$ nghttp -nas https://nghttp2.org/
***** 統計 *****
リクエストのタイミング:
responseEnd: 応答の最後のバイトが受信された時刻
connectEnd を基準にして
requestStart: リクエストの最初のバイトが送信される直前の時間
connectEnd を基準とした相対値。 「*」が表示されている場合、これは
サーバーによってプッシュされます。
プロセス: 応答終了 - 要求開始
コード: HTTPステータスコード
size: 応答本文として受信したバイト数 (省略時)
インフレーション。
URI: リクエストURI
http://www.w3.org/TR/resource-timing/#processing-model を参照してください。
「完全」で並べ替え
id 応答終了リクエスト開始処理コードサイズリクエストパス
13 +37.19ms +280us 36.91ms 200 2K /
2 +72.65ms * +36.38ms 36.26ms 200 8K /stylesheets/screen.css
17 +77.43ms +38.67ms 38.75ms 200 3K /javascripts/octopress.js
15 +78.12ms +38.66ms 39.46ms 200 3K /javascripts/modernizr-2.0.js
-r
オプションを使用すると、 nghttp
より詳細なタイミング データを指定されたファイルに HAR 形式で書き込みます。
nghttpd
マルチスレッドの静的 Web サーバーです。
デフォルトでは、SSL/TLS 接続が使用されます。無効にするには--no-tls
オプションを使用します。
nghttpd
ALPN 経由の HTTP/2 接続または直接 HTTP/2 接続のみを受け入れます。 HTTP アップグレードはサポートされていません。
-p
オプションを使用すると、ユーザーはサーバー プッシュを構成できます。
nghttp
と同様に、フレーミング情報の詳細出力モードがあります。 nghttpd
からの出力例を次に示します。
$ nghttpd --no-tls -v 8080
IPv4: リッスン 0.0.0.0:8080
IPv6: リッスン :::8080
[id=1] [1.521] SETTINGS フレームを送信
(niv=1)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[id=1] [1.521] 受信設定フレーム
(niv=2)
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[id=1] [1.521] 受信設定フレーム
;確認応答
(niv=0)
[id=1] [1.521] recv PRIORITY フレーム
(dep_stream_id=0、weight=201、exclusive=0)
[id=1] [1.521] recv PRIORITY フレーム
(dep_stream_id=0、weight=101、exclusive=0)
[id=1] [1.521] recv PRIORITY フレーム
(dep_stream_id=0、weight=1、exclusive=0)
[id=1] [1.521] recv PRIORITY フレーム
(dep_stream_id=7、weight=1、exclusive=0)
[id=1] [1.521] 受信優先フレーム
(dep_stream_id=3、weight=1、exclusive=0)
[id=1] [1.521] 受信 (stream_id=13) :メソッド: GET
[id=1][1.521]recv (stream_id=13) :path: /
[id=1] [1.521] 受信 (stream_id=13) :scheme: http
[id=1][1.521]recv (stream_id=13) :authority: localhost:8080
[id=1] [1.521] 受信 (stream_id=13) 受け入れ: */*
[id=1] [1.521] recv (stream_id=13) accept-encoding: gzip、deflate
[id=1][1.521]recv (stream_id=13) ユーザーエージェント: nghttp2/1.0.0-DEV
[id=1] [1.521] recv HEADERS フレーム
; END_STREAM | END_HEADERS |優先度
(padlen=0、dep_stream_id=11、weight=16、exclusive=0)
;新しいストリームを開く
[id=1] [1.521] SETTINGS フレームを送信
;確認応答
(niv=0)
[id=1] [1.521] HEADERS フレームを送信
; END_HEADERS
(パドレン=0)
;最初の応答ヘッダー
:ステータス: 200
サーバー: nghttpd nghttp2/1.0.0-DEV
コンテンツの長さ: 10
キャッシュ制御: max-age=3600
日付: 2015 年 5 月 15 日金曜日 14:49:04 GMT
最終更新日: 火曜日, 30 9月 2014 12:40:52 GMT
[id=1] [1.522] DATA フレームを送信
; END_STREAM
[id=1] [ 1.522] stream_id=13 終了しました
[id=1] [1.522] 受信 GOAWAY フレーム
(last_stream_id=0、error_code=NO_ERROR(0x00)、opaque_data(0)=[])
[id=1] [ 1.522] 閉店しました
nghttpx
、HTTP/3、HTTP/2、および HTTP/1.1 用のマルチスレッド リバース プロキシであり、http://nghttp2.org を強化し、HTTP/2 サーバー プッシュをサポートします。
nghttpx
コマンドライン インターフェイスを作り直した結果、1.8.0 以前と互換性のないものがいくつかあります。これは、機能を拡張し、将来のリリースでのさらなる機能強化を確保するために必要です。以前のリリースから移行する方法については、「nghttpx v1.8.0 以前からの移行」をお読みください。
nghttpx
、セッション ID、セッション チケット (自動キー ローテーション付き)、OCSP ステープリング、動的レコード サイズ設定、ALPN、Forward Secrecy、HTTP/2 などの重要なパフォーマンス指向の機能を TLS に実装します。 nghttpx
memcached を介して複数のnghttpx
インスタンス間でセッション キャッシュとチケット キーを共有する機能も提供します。
nghttpx
2 つの動作モードがあります。
モードオプション | フロントエンド | バックエンド | 注記 |
---|---|---|---|
デフォルトモード | HTTP/3、HTTP/2、HTTP/1.1 | HTTP/1.1、HTTP/2 | リバースプロキシ |
--http2-proxy | HTTP/3、HTTP/2、HTTP/1.1 | HTTP/1.1、HTTP/2 | フォワードプロキシ |
現時点で興味深いのはデフォルト モードです。リバース プロキシのように機能し、HTTP/3、HTTP/2、および HTTP/1.1 をリッスンし、既存の Web サーバーの SSL/TLS ターミネーターとして展開できます。
すべてのモードで、フロントエンド接続はデフォルトで SSL/TLS によって暗号化されます。暗号化を無効にするには、 --frontend
オプションでno-tls
キーワードを使用します。暗号化が無効になっている場合、受信 HTTP/1.1 接続は、HTTP アップグレードを通じて HTTP/2 にアップグレードできます。もう一方のハードでは、バックエンド接続はデフォルトでは暗号化されません。バックエンド接続を暗号化するには、 --backend
オプションでtls
キーワードを使用します。
nghttpx
設定ファイルをサポートしています。 --conf
オプションとサンプル構成ファイルnghttpx.conf.sample
を参照してください。
デフォルト モードでは、 nghttpx
バックエンド サーバーへのリバース プロキシとして機能します。
クライアント <-- (HTTP/3、HTTP/2、HTTP/1.1) --> nghttpx <-- (HTTP/1.1、HTTP/2) --> Web サーバー
[リバースプロキシ]
--http2-proxy
オプションを使用すると、フォワード プロキシとして機能し、いわゆるセキュア HTTP/2 プロキシとなります。
クライアント <-- (HTTP/3、HTTP/2、HTTP/1.1) --> nghttpx <-- (HTTP/1.1) --> プロキシ
[安全なプロキシ] (例: Squid、ATS)
上記の例のClient
、 nghttpx
安全なプロキシとして使用するように構成する必要があります。
この記事の執筆時点では、Chrome と Firefox は両方ともセキュア HTTP/2 プロキシをサポートしています。安全なプロキシを使用するように Chrome を構成する 1 つの方法は、次のような proxy.pac スクリプトを作成することです。
function FindProxyForURL ( url , host ) {
return "HTTPS SERVERADDR:PORT" ;
}
SERVERADDR
とPORT
nghttpx が実行されているマシンのホスト名/アドレスとポートです。 Chrome では安全なプロキシの有効な証明書が必要であることに注意してください。
次に、次の引数を指定して Chrome を実行します。
$ google-chrome --proxy-pac-url=file:///path/to/proxy.pac --use-npn
バックエンド HTTP/2 接続は、HTTP プロキシを通じてトンネリングできます。プロキシは--backend-http-proxy-uri
を使用して指定します。次の図は、nghttpx が HTTP プロキシを介して外部 HTTP/2 プロキシと通信する方法を示しています。
クライアント <-- (HTTP/3、HTTP/2、HTTP/1.1) --> nghttpx <-- (HTTP/2) --
--===================---> HTTP/2 プロキシ
(HTTP プロキシ トンネル) (例: nghttpx -s)
h2load
プログラムは、HTTP/3、HTTP/2、および HTTP/1.1 のベンチマーク ツールです。 h2load
の UI は、 weighttp
(https://github.com/lighttpd/weighttp) から大きく影響を受けています。一般的な使用方法は次のとおりです。
$ h2load -n100000 -c100 -m100 https://localhost:8443/
ベンチマークを開始しています...
スレッド #0 の生成: 同時クライアント数 100、合計リクエスト数 100000
プロトコル: TLSv1.2
暗号: ECDHE-RSA-AES128-GCM-SHA256
サーバー一時キー: ECDH P-256 256 ビット
進捗状況: 10% 完了
進捗状況: 20% 完了
進捗状況: 30% 完了
進捗状況: 40% 完了
進捗状況: 50% 完了
進捗状況: 60% 完了
進捗状況: 70% 完了
進捗状況: 80% 完了
進捗状況: 90% 完了
進捗状況: 100% 完了
771.26ミリ秒で終了、129658リクエスト/秒、4.71MB/秒
リクエスト: 合計 100000、開始 100000、完了 100000、成功 100000、失敗 0、エラー 0
ステータスコード: 100000 2xx、0 3xx、0 4xx、0 5xx
トラフィック: 合計 3812300 バイト、ヘッダー 1009900 バイト、データ 1000000 バイト
最小値 最大値 平均値 sd +/- sd
リクエスト時間: 25.12ms 124.55ms 51.07ms 15.36ms 84.87%
接続時間: 208.94ms 254.67ms 241.38ms 7.95ms 63.00%
最初のバイトまでの時間: 209.11ms 254.80ms 241.51ms 7.94ms 63.00%
上記の例では、100 の同時クライアント (つまり 100 の HTTP/2 セッション) とクライアントあたり最大 100 のストリームを使用して、合計 100,000 のリクエストを発行しました。 -t
オプションを使用すると、 h2load
複数のネイティブ スレッドを使用して、クライアント側の単一コアの飽和を回避します。
警告
公開されているサーバーに対してこのツールを使用しないでください。これは DOS 攻撃とみなされます。プライベートサーバーに対してのみ使用してください。
実験的な HTTP/3 が有効になっている場合、h2load は HTTP/3 サーバーにリクエストを送信できます。これを行うには、次のように--alpn-list
オプションにh3
指定します。
$ h2load --alpn-list h3 https://127.0.0.1:4433
nghttp2 v1.58 以前の場合は、 --alpn-list
代わりに--npn-list
使用します。
src
ディレクトリには HPACK ツールが含まれています。 deflatehd
プログラムは、コマンド ライン ヘッダー圧縮ツールです。 inflatehd
プログラムは、コマンド ライン ヘッダー解凍ツールです。どちらのツールも入力を標準入力から読み取り、出力を標準出力に書き込みます。エラーは標準エラー出力に書き込まれます。これらは入力および出力として JSON を受け取ります。 https://github.com/http2jp/hpack-test-caseで説明されている同じJSONデータ形式を(ほとんど)使用します。
deflatehd
プログラムは、STDINからJSONデータまたはHTTP/1スタイルのヘッダーフィールドを読み取り、JSONの圧縮ヘッダーブロックを出力します。
JSON入力の場合、ルートJSONオブジェクトにはcases
キーを含める必要があります。その値には、入力ヘッダーセットのシーケンスを含める必要があります。それらは同じ圧縮コンテキストを共有し、表示される順序で処理されます。シーケンス内の各アイテムはJSONオブジェクトであり、 headers
キーを含める必要があります。その値は、JSONオブジェクトの配列で、正確に1つの名前/値ペアが含まれます。
例:
{
"cases" :
[
{
"headers" : [
{ ":method" : " GET " },
{ ":path" : " / " }
]
},
{
"headers" : [
{ ":method" : " POST " },
{ ":path" : " / " }
]
}
]
}
-t
オプションを使用すると、プログラムはより馴染みのあるHTTP/1スタイルヘッダーフィールドブロックを受け入れることができます。各ヘッダーセットは、空の行で区切られています。
例:
:方法:get
:スキーム:https
:パス: /
:方法:投稿
ユーザーエージェント:nghttp2
出力はJSONオブジェクトにあります。 cases
キーを含める必要があり、その値は少なくとも次のキーを備えたJSONオブジェクトの配列です。
output_length
/ input_length
* 100例:
{
"cases" :
[
{
"seq" : 0 ,
"input_length" : 66 ,
"output_length" : 20 ,
"percentage_of_original_size" : 30.303030303030305 ,
"wire" : " 01881f3468e5891afcbf83868a3d856659c62e3f " ,
"headers" : [
{
":authority" : " example.org "
},
{
":method" : " GET "
},
{
":path" : " / "
},
{
":scheme" : " https "
},
{
"user-agent" : " nghttp2 "
}
],
"header_table_size" : 4096
}
,
{
"seq" : 1 ,
"input_length" : 74 ,
"output_length" : 10 ,
"percentage_of_original_size" : 13.513513513513514 ,
"wire" : " 88448504252dd5918485 " ,
"headers" : [
{
":authority" : " example.org "
},
{
":method" : " POST "
},
{
":path" : " /account "
},
{
":scheme" : " https "
},
{
"user-agent" : " nghttp2 "
}
],
"header_table_size" : 4096
}
]
}
出力は、 inflatehd
およびdeflatehd
の入力として使用できます。
-d
オプションを使用すると、追加のヘッダーセットが処理された後、追加のheader_table
キーが追加され、その関連する値には動的ヘッダーテーブルの状態が含まれます。値には、少なくとも次のキーが含まれます。
referenced
true
である場合、それは参照セットにあります。 size
オーバーヘッド(32バイト)が含まれます。 index
ヘッダーテーブルのインデックスに対応します。 name
はヘッダーフィールド名で、 value
はヘッダーフィールド値です。max_deflate_size
内で占有されているスペースエントリの合計。max_size
よりも小さくなる場合があります。この場合、エンコーダは最初のmax_deflate_size
バッファーまでのみ使用します。ヘッダーテーブルのサイズはまだmax_size
であるため、エンコーダーはmax_deflate_size
外側ではmax_size
内のエントリを追跡し、参照されなくなったことを確認する必要があります。例:
{
"cases" :
[
{
"seq" : 0 ,
"input_length" : 66 ,
"output_length" : 20 ,
"percentage_of_original_size" : 30.303030303030305 ,
"wire" : " 01881f3468e5891afcbf83868a3d856659c62e3f " ,
"headers" : [
{
":authority" : " example.org "
},
{
":method" : " GET "
},
{
":path" : " / "
},
{
":scheme" : " https "
},
{
"user-agent" : " nghttp2 "
}
],
"header_table_size" : 4096 ,
"header_table" : {
"entries" : [
{
"index" : 1 ,
"name" : " user-agent " ,
"value" : " nghttp2 " ,
"referenced" : true ,
"size" : 49
},
{
"index" : 2 ,
"name" : " :scheme " ,
"value" : " https " ,
"referenced" : true ,
"size" : 44
},
{
"index" : 3 ,
"name" : " :path " ,
"value" : " / " ,
"referenced" : true ,
"size" : 38
},
{
"index" : 4 ,
"name" : " :method " ,
"value" : " GET " ,
"referenced" : true ,
"size" : 42
},
{
"index" : 5 ,
"name" : " :authority " ,
"value" : " example.org " ,
"referenced" : true ,
"size" : 53
}
],
"size" : 226 ,
"max_size" : 4096 ,
"deflate_size" : 226 ,
"max_deflate_size" : 4096
}
}
,
{
"seq" : 1 ,
"input_length" : 74 ,
"output_length" : 10 ,
"percentage_of_original_size" : 13.513513513513514 ,
"wire" : " 88448504252dd5918485 " ,
"headers" : [
{
":authority" : " example.org "
},
{
":method" : " POST "
},
{
":path" : " /account "
},
{
":scheme" : " https "
},
{
"user-agent" : " nghttp2 "
}
],
"header_table_size" : 4096 ,
"header_table" : {
"entries" : [
{
"index" : 1 ,
"name" : " :method " ,
"value" : " POST " ,
"referenced" : true ,
"size" : 43
},
{
"index" : 2 ,
"name" : " user-agent " ,
"value" : " nghttp2 " ,
"referenced" : true ,
"size" : 49
},
{
"index" : 3 ,
"name" : " :scheme " ,
"value" : " https " ,
"referenced" : true ,
"size" : 44
},
{
"index" : 4 ,
"name" : " :path " ,
"value" : " / " ,
"referenced" : false ,
"size" : 38
},
{
"index" : 5 ,
"name" : " :method " ,
"value" : " GET " ,
"referenced" : false ,
"size" : 42
},
{
"index" : 6 ,
"name" : " :authority " ,
"value" : " example.org " ,
"referenced" : true ,
"size" : 53
}