NGINXのHTTP/2モジュール

NGINX | 2016年1月19日

このブログ記事は、9月にサンフランシスコで開催されたnginx.conf 2015で、Valentin V. Bartenevが行ったプレゼンテーションを基に編集したものです。

目次

数日前、NGINXのHTTP/2モジュールをリリースしました。この講演では、この新しいモジュールの概要を簡単にご紹介します。

0:20 プロトコルの概要

HTTP/2はHTTP/1.xに代わるものでも、万能な解決策でもありません。長所と短所を持つHTTP/1の別のトランスポート層であり、基本的にはSPDYと同じです

まず、この新しいプロトコルにまつわる誤解をいくつか解いておきます。

多くの人は、HTTP/2をHTTP/1の新しく優れた後継プロトコルだと考えています。しかし、私はそうは考えていません。その理由を説明します。実際のところ、HTTP/2はHTTP/1の別のトランスポート層にすぎません。とはいえ、これは悪いことではありません。同じヘッダーを使用できるため、アプリケーションを変更せずにHTTP/2を利用できるからです。NGINXでHTTP/2を有効にするだけで、プロトコルに関する処理はすべてNGINXが適切に行います。

しかし、HTTP/2は万能ではありません。長所もあれば短所もあります。適切に機能するユースケースがある一方で、うまく機能しないシナリオもあります。

1:40 HTTP/2の主な機能

HTTP/2の主な特徴は、バイナリ形式、多重化、HPACKヘッダー圧縮、複雑な優先順位付けです

HTTP/2はSPDYをベースとしており、非常によく似たプロトコルであるため、SPDYの新しいバージョンと考えることができます。SPDYは、Webコンテンツの配信を高速化するためにGoogleが数年前に開発したプロトコルです。

NGINXはすでに2年前からSPDYをサポートしているため、SPDYモジュールを使用してHTTP/2の利点を確認できます。HTTP/2はSPDY 3.1を洗練させたものにすぎないという見方もあります。

SPDYをご存じない方のために、いくつかの要点を説明します。細部には多少の違いがあるものの、基本的には同じプロトコルであるため、これらの要点はHTTP/2にも当てはまります。

最初の重要なポイントは、プロトコル自体がバイナリ形式であることです。バイナリプロトコルはコーディングしやすく、適切に設計されたものにはパフォーマンス上の利点もあるため、私は好んでいます。ただし、このアプローチに欠点があることも理解しています。

3:08 HTTP/2の内部 – バイナリ

HTTP/2リクエストのペイロードがバイナリ形式であるのに対し、HTTP/1.1リクエストは人が読めるテキスト形式であることを示すスライド

こちらはHTTP/2リクエストです。なかなか格好よく、見てのとおりデバッグもとても簡単です。……というのは冗談で、実際にはデバッグが困難です。これはバイナリプロトコルの欠点の1つです。

リクエストのデコードにツールが必要になる場合があります。あるいは……ツールが正常に動作しなかったり、ビットに隠された詳細がすべて表示されなかったりするため、バイナリを手動でデバッグしなければならないこともあります。

幸い、ほとんどの場合はNGINXでHTTP/2を有効にするだけで、そのバイナリ形式を意識する必要はありません。また幸いなことに、ほとんどのリクエストはマシンによって処理されます。バイナリプロトコルの読み取りは、人間よりもマシンのほうがはるかに得意です。

4:26 HTTP/2の内部 – 多重化

HTTP/2は、単一の接続上でリクエストとレスポンスを多重化します

HTTP/2の次の重要なポイントは、多重化です。複数の接続を介してレスポンスとリクエストを個別のデータストリームとして送受信するのではなく、HTTP/2では、これらを1つのバイトストリーム、つまり1つのデータストリーム上で多重化します。異なるリクエストやレスポンスのデータを分割し、各データ片に固有の識別子とサイズフィールドを付与することで、エンドポイントは各データがどのリクエストに属するかを判別できます。

ここでの欠点は、データの各チャンクに固有の識別情報とフィールドがあるため、実際のデータに加えてメタデータも転送されることです。そのため、一定のオーバーヘッドが発生します。したがって、動画を視聴する場合など、データストリームが1つしかない場合、追加のオーバーヘッドが生じるだけなので、HTTP/2は適したプロトコルではありません。

多重化にはどのようなメリットがあるのでしょうか。最大のメリットは、単一の接続のみを使用することで、新しいリクエストを作成する際にHTTP/1.xでは必要となるハンドシェイクの時間をすべて省けることです。

このような遅延は、TLSを使用する場合に特に大きな問題となります。そのため、現在ではほとんどのクライアントがTLS経由でのみHTTP/2をサポートしています。私の知る限り、暗号化されていないTCP経由でHTTP/2をサポートする計画はありません。そうしても大きなメリットがないためです。TCPハンドシェイクはTLSハンドシェイクほど負荷が高くないため、複数の接続を避けても、ここではそれほど時間を短縮できません。

7:09 HTTP/2の主な機能 – ヘッダー圧縮

HTTP/2では、ヘッダー圧縮専用に設計されたHPACKアルゴリズムを使用します

HTTP/2の次の重要なポイントは、ヘッダー圧縮です。Cookieが非常に大きい場合は、リクエストまたはレスポンスごとに数百バイトを削減できますが、一般的には、ヘッダー圧縮のメリットを得られるケースはそれほど多くありません。個々のリクエスト単位で考えても、最終的にはネットワークのパケット層で処理されるためです。100バイトを送信しても150バイトを送信しても、結局は1つのパケットに収まるので、大きな違いはありません。

HTTP/2のヘッダー圧縮には、状態を保持する必要があるという欠点があります[編集者注 – 圧縮/展開情報を格納するテーブルについて]。そのため、サーバーとクライアントは接続ごとに何らかの状態を保持する必要があり、HTTP/1接続の状態を保持する場合よりもはるかに多くのメモリを消費します。したがって、HTTP/2接続はそれぞれ、より多くのメモリを使用します。

8:40 HTTP/2の主な機能 – 優先順位付け

HTTP/2の優先順位付けメカニズムにより、チャネルが1つしかない場合に最も重要なデータを先に送信する必要があるという問題を解決できます

HTTP/2に関する最後の重要なポイントは、優先順位付けの仕組みです。これは、多重化によって生じる問題を解決します。接続が1つしかない場合、データの経路も1つしかないため、次にどのレスポンスをこの経路に送るかを慎重に判断する必要があります。

HTTP/2では優先順位付けは任意ですが、使用しなければパフォーマンス上のメリットはあまり得られません。NGINXのHTTP/2モジュールは優先順位付けを完全にサポートしており、重みと依存関係に基づく優先順位付けに対応しています。これまでに確認した限りでは、現時点で最速のHTTP/2実装です。以上がHTTP/2の要点です。

10:06 HTTP/2の歴史

NGINXリリースにおけるSPDYおよびHTTP/2のサポートの歴史を示すスライド

これは、HTTP/2の歴史を簡単にまとめたスライドです。内容は比較的シンプルです。続いて、HTTP/2が実際にどのように動作するのかを見ていきましょう。

10:16 テストページ

一般的なリソースタイプを組み合わせた、NGINX HTTP/2モジュールのパフォーマンステスト用Webページ

さまざまなネットワーク条件下でHTTP/2がどのように動作するかを把握するため、一般的なWebページを使ってベンチマークを実施しました。これはGithubで見つけたHTTP/2ページです。リソースの数と各リソースのサイズを確認できます。一般的なサイトをかなりよく表していると思います。

10:52 テスト環境

NGINX HTTP/2モジュールのテストに使用したハードウェア、ソフトウェア、NGINX構成を説明するスライド

テストを再現する場合に備えて、私のテスト環境をご紹介します。

11:02 DOM読み込み

レイテンシーが異なるネットワークにおけるHTTP/1、HTTP/2、HTTPSのダウンロード時間を比較した棒グラフ

こちらが得られた結果です。X軸では、さまざまなネットワーク遅延をミリ秒単位のラウンドトリップ時間(RTT)としてシミュレーションし、Y軸ではダウンロード時間を同じくミリ秒単位で測定しています。このテストでは、ページ上のすべてのリソースが完全に読み込まれるまでの時間をページ読み込み時間として測定しています。

グラフから、レイテンシが低い場合、HTTP、HTTPS、HTTP/2の間に大きな差はないという明確な傾向が見て取れます。レイテンシが高い場合は、暗号化されていないHTTP/1.xが最も高速で、次いでHTTP/2、HTTPSが最も低速です。

11:48 初回描画

レイテンシーが異なるネットワーク上で、HTTP/1、HTTP/2、HTTPSを使用してWebページの最初の要素を配信するまでの時間を比較した棒グラフ

「ファーストペイント」までの時間はどうでしょうか。これは、ユーザーが実際に画面上で何かを目にするまでの時間であるため、多くの場合、ユーザーの視点では最も重要な指標です。ページ全体の読み込みにかかる時間よりも、ユーザーが何かを目にするまでの時間のほうがはるかに重要な場合が多くあります。

ここでも同じ傾向が見られますが、今回のテストで興味深いのは、30 ms~250 msという中程度のレイテンシーでは、差はごくわずかなものの、HTTP/2が通常のHTTPよりも若干高速である点です。

12:45の構成

HTTP/2モジュールを含むNGINXバイナリをビルドするための要件とコマンド引数、および設定でHTTP/2を有効にするためのディレクティブを説明するスライド

以上がベンチマーク結果です。続いて、HTTP/2とNGINXの設定方法について説明します。

実際のところ、設定は非常に簡単です。必要なのは、http2パラメーターをlistenディレクティブに追加することだけです。おそらく最も複雑なのは、最新バージョンのOpenSSLを入手する手順です。HTTP/2にはALPN[Application‑Layer Protocol Negotiation]拡張が必要であり、この拡張をサポートしているのはOpenSSL 1.0.2のみだからです。

HTTP/2向けにNPN[Next Protocol Negotiation]も実装しています。現時点ではほとんどのクライアントで動作しますが、2016年初頭にSPDYが非推奨となるため、各クライアントはNPNのサポートを終了する予定です。つまり、現時点では多くのLinuxディストリビューションに含まれるバージョンのOpenSSLでHTTP/2を使用できますが、近い将来、動作しなくなる点に注意が必要です。

以上で、HTTP/2向けのNGINXの設定についての説明と、私のプレゼンテーションを終わります。ありがとうございました。

[リファレンスドキュメント:HTTP/2 モジュール]

Q&A

Q: HTTP/2はクライアント側だけでなく、アップストリーム側でもサポートする予定ですか?

A: 現時点では、HTTP/2はクライアント側でのみサポートしています。proxy_passではHTTP/2を設定できません。[編集者注 – この記事の初版では、この文が誤って「 proxy_passでHTTP/2を設定できます」と記載されていました。これにより混乱を招いた可能性があることをお詫びいたします。]

では、バックエンド側でHTTP/2を使用することに、どのような意味があるのでしょうか。ベンチマークからもわかるように、アップストリーム接続のような低レイテンシのネットワークでは、HTTP/2を使用しても大きなメリットはありません。

また、NGINXにはkeepaliveモジュールがあり、keepaliveキャッシュを設定できます。HTTP/2の主なパフォーマンス上の利点は、追加のハンドシェイクを不要にできることです。ただし、keepaliveキャッシュですでにそれを実現している場合、アップストリーム側でHTTP/2を使用する必要はありません。

HTTP/2に関するその他のリソース

お使いの環境でNGINX PlusによるHTTP/2を試してみませんか?今すぐ30日間の無料トライアルを開始するか、ユースケースについてお問い合わせください。


共有
タグ: F5 NGINX, 2016, Tech

関連するブログ記事

チュートリアル:NGINXを使用してアプリケーション向けにOpenTelemetryを構成する
NGINX | 2024/01/18

チュートリアル:NGINXを使用してアプリケーション向けにOpenTelemetryを構成する

OpenTelemetryを使用してNGINXサーバーの状態と健全性をより明確に把握することで、問題のトラブルシューティングを行い、Webアプリケーションのパフォーマンスを向上できます。

AkitaのNGINX Plus認定モジュールでAPIエンドポイントの問題を特定・修正
NGINX | 2023/05/31

AkitaのNGINX Plus認定モジュールでAPIエンドポイントの問題を特定・修正

Akita SoftwareのAPIオブザーバビリティ向け新しいNGINX Plus Certified Moduleを活用して、APIエンドポイントの問題をより迅速に特定し、修正できます。

JavaプロジェクトをスキャフォールディングしてKubernetesネイティブアプリを構築する方法
NGINX | 2023/02/09

JavaプロジェクトをスキャフォールディングしてKubernetesネイティブアプリを構築する方法

Red HatのシニアプリンシパルデベロッパーアドボケイトであるDaniel Oh氏が、Javaプロジェクトをゼロから構築するためのひな形を作成し、Kubernetesネイティブアプリケーションとしてビルドする方法を解説します。

F5 NGINXaaS for Azureのご紹介:Microsoft Azureでネイティブに利用できるSaaS型ロードバランシング
NGINX | 2022/05/24

F5 NGINXaaS for Azureのご紹介:Microsoft Azureでネイティブに利用できるSaaS型ロードバランシング

NGINXaaS for Azureは、NGINX PlusをAzureネイティブのSaaSとして利用できるサービスです。NGINXの設定を容易にリフト&シフトできるため、クラウド導入とモダンアプリの展開を加速できます。

SELinuxでNGINXおよびNGINX Plusを使用する
NGINX | 2018/08/17

SELinuxでNGINXおよびNGINX Plusを使用する

Red Hat Enterprise Linux(RHEL)および関連ディストリビューションでSecurity-Enhanced Linux(SELinux)を有効にすると、デフォルト設定によりNGINXとNGINX Plusの一部の操作が制限されます。この記事では、すべての機能を利用できるようにSELinuxの設定を変更する方法について説明します。

NGINX PlusによるAWS Auto Scalingグループの負荷分散
NGINX | 2017/03/06

NGINX PlusによるAWS Auto Scalingグループの負荷分散

新しいnginx-asg-sync統合ソフトウェアにより、NGINX PlusはAWS Auto Scalingグループの負荷を直接分散できるため、クラウドでの負荷分散がさらに柔軟になります