NGINX Plus R15には、HTTP/2 サーバー プッシュのサポートも含まれています。
2018 年 2 月 20 日にリリースされたNGINX 1.13.9に、HTTP/2 サーバー プッシュのサポートが含まれることをお知らせします。 NGINX Plus ユーザーの場合、HTTP/2 サーバー プッシュ サポートは、2018 年 4 月に予定されているNGINX Plus R15リリースに含まれる予定です。
HTTP/2 仕様で定義されているサーバー プッシュを使用すると、サーバーは、クライアントがすぐにリソースを要求する可能性があることを予測して、事前にリソースをリモート クライアントにプッシュできます。 そうすることで、ページ読み込み操作における RTT (ラウンドトリップ時間、つまりリクエストと応答に必要な時間) の数を 1 RTT 以上削減でき、ユーザーへの応答が速くなります。
サーバー プッシュを使用すると、Web ページのレンダリングに必要なスタイル シート、画像、その他のリソースをクライアントに提供できます。 必要なリソースのみをプッシュするように注意する必要があります。クライアントがすでにキャッシュしている可能性のあるリソースはプッシュしないでください。
このブログ投稿では、次のことについて説明します。
nghttp を
使用)リンク
ヘッダーを使用してコンテンツを自動的にプッシュするページの読み込みと同時にリソースをプッシュするには、次のようにhttp2_push
ディレクティブを使用します。
server { # サーバーで HTTP/2 が有効になっていることを確認します listen 443 ssl http2 ; ssl_certificate ssl/certificate.pem; ssl_certificate_key ssl/key.pem; root /var/www/html; # クライアントが demo.html を要求するたびに、 # /style.css、/image1.jpg、/image2.jpg もプッシュします location = /demo.html { http2_push /style.css; http2_push /image1.jpg; http2_push /image2.jpg; } }
次の 2 つの方法のいずれかを使用して、サーバー プッシュが有効になっているかどうかを簡単に確認できます。
nghttp
などのコマンドラインHTTP/2クライアントここでは、Google Chrome を例に、Web ブラウザの開発者ツールを使用してサーバー プッシュが有効になっているかどうかを確認する方法を説明します。 図では、Chrome の開発者ツールの[ネットワーク]タブの[イニシエーター]列に、 /demo.htmlのリクエストの一部としていくつかのリソースがクライアントにプッシュされたことが示されています。
nghttp
) による検証Web ブラウザ ツールに加えて、 nghttp2.orgプロジェクトのnghttp
コマンドライン クライアントを使用して、サーバー プッシュが有効になっていることを確認できます。 nghttp
コマンドライン クライアントはGitHubからダウンロードできます。また、適切なオペレーティング システム パッケージがある場合はそれをインストールすることもできます。 Ubuntu の場合は、 nghttp2-client
パッケージを使用します。
出力では、アスタリスク (*) はサーバーによってプッシュされたリソースを示します。
$ nghttp -ans https://example.com/demo.html id responseEnd requestStart process code size request path 13 +84.25ms +136us 84.11ms 200 492 /demo.html 2 +84.33ms * +84.09ms 246us 200 266 /style.css 4 +261.94ms * +84.12ms 177.83ms 200 40K /image2.jpg 6 +685.95ms * +84.12ms 601.82ms 200 173K /image1.jpg
多くの場合、NGINX 構成ファイルにプッシュしたいリソースをリストすることは不便であり、不可能ですらあります。 このため、NGINX は、 Link
プリロード ヘッダーをインターセプトし、これらのヘッダーで識別されるリソースをプッシュするという規則もサポートしています。 プリロードを有効にするには、設定にhttp2_push_preload
ディレクティブを含めます。
server { # サーバーで HTTP/2 が有効になっていることを確認します listen 443 ssl http2 ; ssl_certificate ssl/certificate.pem; ssl_certificate_key ssl/key.pem; root /var/www/html; # Link ヘッダーを傍受し、要求されたプッシュを開始します location = /myapp { proxy_pass http://upstream; http2_push_preload on; } }
たとえば、NGINX がプロキシ (HTTP、FastCGI、またはその他のトラフィック タイプ用) として動作している場合、アップストリーム サーバーは次のようなLink
ヘッダーを応答に追加できます。
リンク: </style.css>; as=style; rel=preload
NGINX はこのヘッダーをインターセプトし、 /style.cssのサーバー プッシュを開始します。 リンク
ヘッダー内のパスは絶対パスである必要があります。./style.cssのような相対パスはサポートされていません。 パスにはオプションでクエリ文字列を含めることができます。
複数のオブジェクトをプッシュするには、複数のLink
ヘッダーを指定するか、さらに良い方法として、すべてのオブジェクトをコンマ区切りのリストに含めることができます。
リンク: </style.css>; as=style; rel=preload, </favicon.ico>; as=image; rel=preload
NGINX がプリロードされたリソースをプッシュしないようにするには、ヘッダーにnopush
パラメータを追加します。
# リソースはプッシュされませんLink: </nginx.png>; as=image; rel=preload; nopush
http2_push_preload
が有効になっている場合は、NGINX 構成で応答ヘッダーを設定することで、プリロード サーバー プッシュを開始することもできます。
add_header リンク "</style.css>; as=style; rel=preload";
HTTP/2 仕様では、リソースをプッシュするかどうかを決定するという課題には対処していません。 明らかに、クライアントがリソースを必要とする可能性が高く、すでにキャッシュされている可能性が低いことがわかっている場合は、リソースのみをクライアントにプッシュするのが最善です。
考えられるアプローチの 1 つは、クライアントがサイトに初めてアクセスしたときにのみリソースをプッシュすることです。 たとえば、セッション クッキーの存在をテストし、条件付きでLink
ヘッダーを設定することで、セッション クッキーが存在しない場合にのみリソースがプリロードされるようにすることができます。
クライアントが適切に動作し、後続のリクエストに Cookie を含めると仮定すると、次の構成では、NGINX はブラウザ セッションごとに 1 回だけリソースをクライアントにプッシュします。
server {
listen 443 ssl http2 default_server;
ssl_certificate ssl/certificate.pem;
ssl_certificate_key ssl/key.pem;
root /var/www/html;
http2_push_preload on;
location = /demo.html {
add_header Set-Cookie "session=1";
add_header Link $resources;
}
}
map $http_cookie $resources {
"~*session=1" "";
default "</style.css>; as=style; rel=preload, </image1.jpg>; as=image; rel=preload, </image2.jpg>; as=image; rel=preload";
}
サーバー プッシュの効果を測定するために、別のスタイルシート/style.cssを参照する簡単なテスト ページ/demo.html を作成しました。 スタイルシートはさらに 2 つの画像を参照します。 3 つの異なる構成を使用してページの読み込み時間をテストしました。
GET
(最適化なし) – ブラウザは必要なリソースを発見するとそれをロードします。リンク
ヘッダー)は、ブラウザに依存関係をロードするように指示するための最初の応答に含まれていました。HTTP、HTTPS、または HTTP/2 を使用して、各構成のテストを複数回実行しました。 最初の 2 つの構成は 3 つのプロトコルすべてに適用され、サーバー プッシュは HTTP/2 にのみ適用されます。
動作は Chrome 開発者ツールを使用して測定されました。 各構成の最も一般的な動作が評価され、平均化され、その時間がリンクの RTT ( ping を
使用して測定) と相関付けられ、各方法の機械的な効果を示しました。
GET
操作は約 1 RTT で完了します。GET
リクエストの 0.5 RTT)。keepalive_timeout
およびhttp2_idle_timeout を
使用して、キープアライブ接続をすばやく閉じました。このテストは、プリロードヒントとサーバープッシュの仕組みを強調するために意図的に単純化されました。 サーバー プッシュは、単純な状況ではプリロード ヒントよりも 1 RTT の改善をもたらし、最適化されていないシーケンシャルGET
リクエストや依存リソースの検出と比べても大きな改善をもたらします。
より現実的なユースケースには、複数の依存リソース、複数のソース、すでにキャッシュされているリソースやすぐに必要ではないリソースをプッシュすることで帯域幅が無駄になる可能性など、さらに多くの変数があります。 ブラウザの不一致もパフォーマンスに影響します。 この簡単なテストによって、走行距離は確実に変わります。
たとえば、Chrome チームは、サーバー プッシュを展開するタイミングに関する詳細な推奨事項を公開しており、より複雑なサイトで測定を行って、最適化なし、プリロード ヒント、HTTP/2 経由のサーバー プッシュの効果を比較しています。 彼らの「HTTP/2 プッシュに関する経験則」レポートは、本番環境で HTTP/2 サーバー プッシュを導入することを検討している人にとって一読の価値があります。
実用的な結論としては、事前に必要なリソースを特定できる場合、上流サーバーにプリロードヒントを送信させることに実際のメリットがあるということです。 これらのリソースをプッシュすることによる追加の利点は小さいながらも測定可能ですが、帯域幅の無駄や必要なリソースの遅延につながる可能性があります。 サーバープッシュ構成は慎重にテストおよび監視する必要があります。
以下の情報は、Jake Archibald の非常に詳細なブログ投稿「HTTP/2 の推進は思ったより困難です」の調査に一部基づいています。
HTTP/2 サーバー プッシュは通常、クライアントがリソースを要求したときに、依存するリソースを事前に送信するのに使用されます。 たとえば、クライアントが Web ページを要求すると、サーバーは依存するスタイルシート、フォント、および画像をクライアントにプッシュすることがあります。
クライアントが HTTP/2 接続を行うと、サーバーは接続を介して 1 つ以上のサーバー プッシュ応答を開始することを選択できます。 これらのプッシュは、クライアントが明示的に要求していないリソースを送信します。
クライアントは、プッシュを拒否するか( RST_STREAM
フレームを送信して)、または受け入れることができます。 クライアントは、プッシュされたコンテンツを、HTTP/2 接続に関連付けられたローカルの「プッシュ キャッシュ」に保存します。
その後、クライアントが確立された HTTP/2 接続を使用してリソースを要求すると、接続のプッシュ キャッシュで要求に対する完了した応答または転送中の応答がチェックされます。 リソースに対して新しい HTTP/2 リクエストを行うよりも、キャッシュされたリソースを優先して使用します。
プッシュされたリソースは、(a) 使用されるか、(b) HTTP/2 接続が閉じられるまで、接続ごとのプッシュ キャッシュに残ります。
これにはいくつかの意味があります:
問題のより詳細なリストについては、Jake Archibald のブログ投稿「HTTP/2 のプッシュは思ったより難しい」で確認できます。
HTTP/2 サーバー プッシュは興味深い機能です。 HTTP/2 サーバーのプッシュ構成を徹底的にテストし、より予測可能なキャッシュ対応の動作が得られる場合には、プリロードヒントにフォールバックできるように準備しておいてください。
「このブログ投稿には、入手できなくなった製品やサポートされなくなった製品が参照されている場合があります。 利用可能な F5 NGINX 製品およびソリューションに関する最新情報については、 NGINX 製品ファミリーをご覧ください。 NGINX は現在 F5 の一部です。 以前の NGINX.com リンクはすべて、F5.com の同様の NGINX コンテンツにリダイレクトされます。"