このブログ投稿は、9 月にサンフランシスコで開催された nginx.conf 2015 での Valentin V. Bartenev のプレゼンテーションを基に作成されています。
目次
0:20 | プロトコルの概要 |
1:40 | HTTP/2の主な機能 |
3:08 | HTTP/2 内部 – バイナリ |
4:26 | HTTP/2 内部 – 多重化 |
7:09 | HTTP/2 の主な機能 – ヘッダー圧縮 |
8:40 | HTTP/2 の主な機能 – 優先順位付け |
10:06 | HTTP/2の歴史 |
10:16 | テストページ |
10:52 | テスト環境 |
11:02 | DOM ロード |
11:48 | 最初の絵画 |
12:45 | 構成 |
14:20 | 質疑応答 |
数日前、NGINX の HTTP/2 モジュールをリリースしました。 この講演では、新しいモジュールの概要を簡単に説明します。
まず最初に、新しいプロトコルに関するいくつかの誤解を解きたいと思います。
多くの人は、HTTP/2 を HTTP/1 の優れた後継版だと考えています。 私はこの意見に賛同しません。その理由は次のとおりです。 HTTP/2 は実際には HTTP/1 の単なる別のトランスポート層ですが、結果として、アプリケーションを変更することなく HTTP/2 を使用できるため、悪くはありません。同じヘッダーで動作します。 NGINX で HTTP/2 をオンにするだけで、NGINX がすべてのプロトコル関連の処理を丁寧に処理してくれます。
しかし、HTTP/2 は魔法ではありません。 確かに利点と欠点はあります。 適切に動作するユースケースもあれば、適切に動作しないシナリオもあります。
HTTP/2 は SPDY をベースにしており、非常によく似たプロトコルであるため、SPDY の新しいバージョンと考えることができます。 SPDY は、Web コンテンツの配信を高速化するために数年前に Google によって開発されたプロトコルです。
NGINX はすでに 2 年間 SPDY をサポートしているため、SPDY モジュールを使用することで HTTP/2 の利点を確認できます。 HTTP/2 は SPDY 3.1 の改良版に過ぎないと言う人もいるでしょう。
SPDY についてよく知らない方のために、いくつかの重要なポイントを説明します。 これらの重要な点は HTTP/2 にも当てはまります。なぜなら、これらは細部に若干の違いはあるものの、基本的には同じプロトコルだからです。
最初の重要なポイントは、プロトコル自体がバイナリであるということです。 私はバイナリ プロトコルが好きです。バイナリ プロトコルはコーディングが簡単で、優れたバイナリ プロトコルにはパフォーマンス上の利点があります。 しかし、私はこのアプローチの欠点も理解しています。
以下は HTTP/2 リクエストです。 見た目はかなりクールで、ご覧のとおりデバッグも非常に簡単です。 いいえ、冗談です。 デバッグが難しいです。 そして、それがバイナリ プロトコルの欠点の 1 つです。
リクエストをデコードするにはツールを使用する必要があるかもしれません。あるいは、ツールが壊れている可能性があり、またはツールがビット内に隠されたすべての詳細を表示しない可能性があるため、バイナリを手動でデバッグする必要がある場合もあります。
幸いなことに、ほとんどの場合、NGINX に HTTP/2 を投入するだけで、そのバイナリの性質を気にする必要がありません。 そして幸いなことに、リクエストのほとんどは機械によって処理されます。 機械は人間よりもバイナリ プロトコルの読み取りがはるかに得意です。
HTTP/2 の次の重要なポイントは多重化です。 HTTP/2 では、複数の接続を介して応答と要求を個別のデータ ストリームとして送受信するのではなく、1 つのバイト ストリームまたは 1 つのデータ ストリームを介してそれらを多重化します。 異なるリクエストと異なる応答のデータをスライスし、各スライスには独自の識別子とサイズ フィールドがあり、エンドポイントがどのデータがどのリクエストに属しているかを判断できるようにします。
ここでの欠点は、各データ チャンクには独自の識別子と独自のフィールドがあるため、実際のデータに加えて転送されるメタデータがいくつかあることです。 したがって、いくらかのオーバーヘッドが発生します。 その結果、たとえば映画を視聴しているときのように、データのストリームが 1 つしかない場合、HTTP/2 は追加のオーバーヘッドしか発生しないため、適切なプロトコルではありません。
多重化の利点は何ですか? 多重化の主な利点は、単一の接続のみを使用することで、新しいリクエストを作成する必要があるときに HTTP/1.x でハンドシェイクに費やす時間をすべて節約できることです。
このような遅延は、TLS を扱う場合には特に大きな問題となります。 そのため、現在、ほとんどのクライアントは TLS 経由の HTTP/2 のみをサポートしています。 私の知る限り、プレーン TCP 上で HTTP/2 をサポートする予定はありません。それほどメリットがないためです。 これは、TCP ハンドシェイクは TLS ハンドシェイクほどコストがかからないため、複数の接続を回避してもあまり節約にならないためです。
HTTP/2 に関する次の重要なポイントは、ヘッダー圧縮です。 非常に大きな Cookie がある場合、これによりリクエストまたは応答ごとに数百バイトを節約できますが、一般に、ほとんどの場合、ヘッダー圧縮によるメリットはあまり得られません。 なぜなら、個別のリクエストについて考えたとしても、最終的にはネットワーク上のパケット層を処理することになり、100 バイトを送信するか 100.5 バイトを送信するかは、最終的には 1 つのパケットになるため、あまり問題にはならないからです。
HTTP/2 ヘッダー圧縮の欠点は、ステートフルであることです [編集者– 圧縮/解凍情報を保存するために使用されるテーブルについて]。 その結果、サーバーとクライアントは接続ごとに何らかの状態を保持する必要があり、HTTP/1 接続の状態を保持する場合よりもはるかに多くのメモリを消費します。 そのため、結果として、各 HTTP/2 接続はより多くのメモリを使用することになります。
HTTP/2 に関する最後の重要なポイントは、優先順位付けの仕組みです。 これにより、多重化によって発生した問題が解決されます。 接続が 1 つしかない場合はパイプも 1 つしかないため、次にこのパイプにどの応答を入れるかを慎重に決定する必要があります。
HTTP/2 では優先順位付けはオプションですが、優先順位付けを行わないとパフォーマンス上のメリットはあまり得られません。 NGINX の HTTP/2 モジュールは優先順位付けを完全にサポートしており、重みに基づく優先順位と依存関係に基づく優先順位をサポートしています。 これまでのところ、現時点では HTTP/2 の実装が最も高速であることがわかります。 これらが HTTP/2 に関する重要なポイントです。
以下は、HTTP/2 の歴史を説明する簡単なスライドです。 かなりわかりやすいです。 HTTP/2 が実際にどのように機能するかを見ていきましょう。
さまざまなネットワーク条件下で HTTP/2 がどのように動作するかを理解するために、一般的な Web ページでいくつかのベンチマークを実行しました。 これは Github で見つけた HTTP/2 ページです。 リソースがいくつあるか、また各リソースの大きさがわかります。 典型的なサイトをかなり代表していると思います。
テストを再現したい場合に備えて、ここに私のテスト環境を示します。
そして、私が得た結果がこれです。 X 軸でさまざまなネットワーク遅延をラウンドトリップ時間 (RTT) としてミリ秒単位でシミュレートし、Y 軸でダウンロード時間を同じくミリ秒単位で測定していることがわかります。 これは、ページのすべてのリソースが完全に読み込まれたときのページの読み込み時間を測定するテストです。
グラフからは、低レイテンシの場合、HTTP、HTTPS、HTTP/2 の間に大きな違いがないという明らかな傾向がわかります。 レイテンシが高い場合は、プレーン HTTP/1.x が最も高速な選択肢であることがわかります。 2番目はHTTP/2で、最も遅いのはHTTPSです。
「初めてのお絵描き」の時間はどうですか? 多くの場合、これはユーザーが実際に画面上で何かを見るときなので、ユーザーの観点からは最も重要な指標となります。 多くの場合、ページが完全に読み込まれるまでにかかる時間はそれほど重要ではありませんが、ユーザーが何かを見るまでにどれくらいの時間がかかるかは非常に重要です。
ここでも同じ傾向が見られますが、このテストで興味深いのは、レイテンシが 30 ミリ秒から 250 ミリ秒の範囲の中間にある場合、その差は非常に小さいものの、HTTP/2 が通常の HTTP よりも少し高速であることです。
以上がベンチマークです。次は、HTTP/2 と NGINX の設定方法について説明します。
実はとても簡単です。 必要なのは、 listen
ディレクティブにhttp2
パラメータを追加することだけです。 ここでおそらく最も複雑なステップは、OpenSSL の最新バージョンを入手することです。HTTP/2 には ALPN [ Application‑Layer Protocol Negotiation ] 拡張が必要であり、ALPN 拡張は OpenSSL 1.0.2 でのみサポートされているためです。
また、HTTP/2 用の NPN [ Next Protocol Negotiation ] も実装しました。これは現時点ではほとんどのクライアントで動作しますが、2016 年初頭に SPDY が廃止されるため、NPN のサポートは削除される予定です。 つまり、現在多くの Linux ディストリビューションに含まれている OpenSSL バージョンで HTTP/2 を使用できますが、近い将来に動作しなくなることに留意する必要があります。
以上が、HTTP/2 用の NGINX の構成に関するすべてです。これで私のプレゼンテーションは終了です。 ありがとう。
[ HTTP/2 モジュールのリファレンスドキュメント]
質問: アップストリーム側でも HTTP/2 をサポートしますか、それともクライアント側でのみ HTTP/2 をサポートしますか?
答え: 現時点では、クライアント側では HTTP/2 のみをサポートしています。 proxy_pass
を使用して HTTP/2 を構成することはできません。[編集者 – この投稿の元のバージョンでは、この文は誤って「 proxy_pass
を使用して HTTP/2 を構成することができます。」と転記されていました。 この件で混乱を招いたことをお詫び申し上げます。
しかし、バックエンド側での HTTP/2 の意味は何でしょうか? ベンチマークからわかるように、アップストリーム接続などの低遅延ネットワークでは、HTTP/2 の利点はあまりありません。
また、NGINX にはkeepaliveモジュールがあり、keepalive キャッシュを設定できます。 HTTP/2 の主なパフォーマンス上の利点は追加のハンドシェイクが不要になることですが、キープアライブ キャッシュを使用して既にこれを実行している場合は、アップストリーム側で HTTP/2 は必要ありません。
あなたの環境で NGINX Plus を使用して HTTP/2 を試してみませんか? 今すぐ30 日間の無料トライアルを開始するか、使用事例についてご相談ください。
「このブログ投稿には、入手できなくなった製品やサポートされなくなった製品が参照されている場合があります。 利用可能な F5 NGINX 製品およびソリューションに関する最新情報については、 NGINX 製品ファミリーをご覧ください。 NGINX は現在 F5 の一部です。 以前の NGINX.com リンクはすべて、F5.com の同様の NGINX コンテンツにリダイレクトされます。"