Webアプリケーションのパフォーマンス向上は、これまで以上に重要になっています。オンラインで行われる経済活動の割合は拡大しており、現在では先進国経済の5%超がインターネット上で展開されています(以下の「インターネット統計に関するリソース」を参照)。常時接続が当たり前となった現代の高度にネットワーク化された社会では、ユーザーの期待もかつてないほど高まっています。サイトが即座に応答しない場合や、アプリが遅延なく動作しない場合、ユーザーはすぐに競合他社へ移ってしまいます。
たとえば、約10年前にAmazonが実施した調査では、当時でさえ、ページの読み込み時間を100ミリ秒短縮すると、収益が1%増加することが実証されました。また、最近の別の調査では、調査対象となったサイト所有者の半数以上が、アプリケーションのパフォーマンス低下により収益または顧客を失ったと回答しています。
Webサイトにはどの程度の速度が必要なのでしょうか。ページの読み込み時間が1秒増えるごとに、約4%のユーザーが離脱します。大手eコマースサイトでは、最初に操作できるようになるまでの時間が1~3秒で、この範囲でコンバージョン率が最も高くなります。Webアプリケーションのパフォーマンスがビジネスに与える影響は大きく、今後さらに拡大する可能性があります。
パフォーマンスを改善したいと考えるのは簡単ですが、実際に成果を上げるのは容易ではありません。そこで本ブログ記事では、Webサイトのパフォーマンスを最大10倍に高めるための10のヒントをご紹介します。本記事は、十分に検証された最適化手法とNGINXのサポートを活用して、アプリケーションのパフォーマンスを向上させる方法を詳しく解説するシリーズの第1回です。このシリーズでは、その過程で期待できるセキュリティ上の改善点についても説明します。
ヒント1 – リバースプロキシサーバーでアプリケーションを高速化し、セキュリティを確保
Webアプリケーションを1台のマシンで実行している場合、パフォーマンスの問題を解決する方法は明白に思えるかもしれません。プロセッサーやRAMを増強し、高速なディスクアレイを搭載するなど、より高速なマシンを用意すればよいという考え方です。新しいマシンなら、WordPressサーバーやNode.jsアプリケーション、Javaアプリケーションなどを、以前より高速に実行できます。(アプリケーションがデータベースサーバーにアクセスする場合も、より高速なマシンを2台用意し、その間の接続を高速化すればよいという単純な解決策に思えるかもしれません。)
問題は、マシンの速度が原因とは限らないことです。Webアプリケーションの動作が遅くなるのは、多くの場合、コンピューターが数千の接続を介したユーザーとのやり取り、ディスク上のファイルへのアクセス、アプリケーションコードの実行など、さまざまな種類のタスクを切り替えているためです。アプリケーションサーバーでは、メモリ不足に陥り、メモリの一部をディスクにスワップアウトし、多数のリクエストがディスクI/Oなどの単一タスクの完了を待つ、スラッシングが発生している可能性があります。
ハードウェアをアップグレードする代わりに、まったく異なるアプローチを採用できます。リバースプロキシサーバーを追加し、これらのタスクの一部をオフロードする方法です。リバースプロキシサーバーは、アプリケーションを実行するマシンの前段に配置され、インターネットトラフィックを処理します。インターネットに直接接続されるのはリバースプロキシサーバーのみで、アプリケーションサーバーとの通信には高速な内部ネットワークが使用されます。
リバースプロキシサーバーを使用すると、アプリケーションサーバーはユーザーによるWebアプリの操作を待つ必要がなくなり、リバースプロキシサーバーがインターネット経由で送信するページの生成に専念できます。クライアントからの応答を待つ必要がなくなったアプリケーションサーバーは、最適化されたベンチマークで達成される速度に近い速度で稼働できます。
リバースプロキシサーバーを追加すると、Webサーバー構成の柔軟性も高まります。たとえば、特定の種類のサーバーに負荷が集中した場合は、同じ種類のサーバーを簡単に追加できます。また、サーバーが停止した場合も、簡単に交換できます。
リバースプロキシサーバーは柔軟性をもたらすため、次のような、パフォーマンスを向上させるさまざまな機能を利用するための前提条件でもあります。
- 負荷分散(ヒント2を参照)— ロードバランサーはリバースプロキシサーバー上で動作し、複数のアプリケーションサーバーにトラフィックを均等に分散します。ロードバランサーを導入すれば、アプリケーションを一切変更せずにアプリケーションサーバーを追加できます。
- 静的ファイルのキャッシュ(ヒント 3を参照)— 画像ファイルやコードファイルなど、直接リクエストされるファイルをリバースプロキシサーバーに保存し、クライアントへ直接送信できます。これにより、アセットをより迅速に配信し、アプリケーションサーバーの負荷を軽減できるため、アプリケーションの処理速度が向上します。
- サイトのセキュリティ確保 – リバースプロキシサーバーは、高度なセキュリティを確保するように構成できるほか、攻撃を迅速に認識して対応できるよう監視することで、アプリケーションサーバーを保護できます。
NGINXソフトウェアは、リバースプロキシサーバーとして使用するために特別に設計されており、上記の追加機能も備えています。NGINXは、従来のサーバーよりも効率的なイベント駆動型の処理方式を採用しています。NGINX Plusでは、アプリケーションのヘルスチェック、特定用途向けのリクエストルーティング、高度なキャッシュ、サポートなど、より高度なリバースプロキシ機能が追加されています。

ヒント2 – ロードバランサーを追加する
比較的簡単な変更であるロードバランサーの追加により、サイトのパフォーマンスとセキュリティを大幅に向上できる可能性があります。中核となるWebサーバーを大型化、高性能化する代わりに、ロードバランサーを使用して複数のサーバーにトラフィックを分散します。アプリケーションの設計に問題がある場合や、スケーリングに問題がある場合でも、ロードバランサーを導入すれば、ほかに変更を加えることなくユーザーエクスペリエンスを向上できます。
ロードバランサーは、まずリバースプロキシサーバーです(ヒント1を参照)。インターネットトラフィックを受信し、リクエストを別のサーバーに転送します。ロードバランサーの特長は、2台以上のアプリケーションサーバーに対応し、複数のアルゴリズムから選択してサーバー間でリクエストを分散できることです。最もシンプルな負荷分散方式はラウンドロビンで、新しいリクエストをリスト上の次のサーバーに順番に送信します。ほかにも、アクティブな接続数が最も少ないサーバーにリクエストを送信する方式などがあります。NGINX Plusには、特定のユーザーセッションを同じサーバーで継続するための機能があります。これはセッションパーシステンスと呼ばれます。
ロードバランサーは、他のサーバーがトラフィックを待っている一方で、1台のサーバーに負荷が集中するのを防ぐため、パフォーマンスを大幅に向上できる可能性があります。また、比較的低コストのサーバーを追加して有効活用できるため、Webサーバーの処理能力も容易に拡張できます。
負荷分散が可能なプロトコルには、HTTP、HTTPS、SPDY、HTTP/2、WebSocket、FastCGI、SCGI、uwsgi、memcachedのほか、TCPベースのアプリケーションやその他のレイヤー4プロトコルを含む複数のアプリケーションタイプがあります。Webアプリケーションを分析し、使用しているプロトコルとパフォーマンスが低下している箇所を特定してください。
ロードバランシングに使用する同じサーバーは、SSL終端、クライアントによるHTTP/1.xおよびHTTP/2の利用のサポート、静的ファイルのキャッシュなど、その他の複数のタスクにも対応できます。
NGINXは、ロードバランシングによく使用されます。詳しくは、eBook「ソフトウェアロードバランサーを選ぶ5つの理由」をダウンロードしてください。基本的な設定手順については「NGINXおよびNGINX Plusによるロードバランシング、パート1」を、詳細なドキュメントについては「NGINX Plus管理ガイド」をご覧ください。NGINX PlusはF5の商用製品で、サーバーの応答時間に基づくロードルーティングや、MicrosoftのNTLMプロトコルを使用したロードバランシングなど、より高度なロードバランシング機能をサポートしています。
ヒント3 – 静的コンテンツと動的コンテンツをキャッシュする
キャッシュを利用すると、コンテンツをクライアントにより迅速に配信できるため、Webアプリケーションのパフォーマンスが向上します。キャッシュには、必要なときに迅速に配信できるようコンテンツを事前処理する、より高速なデバイスにコンテンツを保存する、クライアントに近い場所にコンテンツを保存する、またはこれらを組み合わせるといった複数の方法があります。
検討すべきキャッシュには、次の2種類があります。
- 静的コンテンツのキャッシュ – 画像ファイル(JPEG、PNG)やコードファイル(CSS、JavaScript)など、変更頻度の低いファイルは、メモリやディスクからすばやく取得できるよう、エッジサーバーに保存できます。
- 動的コンテンツのキャッシュ – 多くのWebアプリケーションでは、ページリクエストごとに新しいHTMLが生成されます。生成されたHTMLのコピーを短時間キャッシュすることで、要件を満たす十分に新しいコンテンツを配信しながら、生成が必要なページの総数を大幅に削減できます。
たとえば、あるページが1秒あたり10回閲覧され、そのページを1秒間キャッシュした場合、ページへのリクエストの90%はキャッシュから処理されます。静的コンテンツを別途キャッシュすれば、新たに生成されるページであっても、その大部分がキャッシュ済みコンテンツで構成される可能性があります。
Webアプリケーションが生成するコンテンツをキャッシュする主な手法は、次の3つです。
- コンテンツをユーザーの近くに配置 – コンテンツのコピーをユーザーの近くに保持することで、転送時間を短縮できます。
- コンテンツをより高速なマシンに移動 – コンテンツをより高速なマシンに保存することで、取得時間を短縮できます。
- 過負荷状態のマシンからコンテンツを移動 – マシンは他のタスクの処理でビジー状態になると、特定のタスクにおいてベンチマーク性能を大幅に下回る速度で動作することがあります。別のマシンにキャッシュすることでホストマシンの負荷が軽減されるため、キャッシュされたリソースだけでなく、キャッシュされていないリソースのパフォーマンスも向上します。
Webアプリケーションのキャッシュは、内側にあるWebアプリケーションサーバーから外側へと段階的に実装できます。まず、動的コンテンツをキャッシュして、アプリケーションサーバーの負荷を軽減します。次に、本来は動的コンテンツとなるデータの一時コピーを含む静的コンテンツをキャッシュし、アプリケーションサーバーの負荷をさらに軽減します。その後、キャッシュをアプリケーションサーバーから、より高速なマシンやユーザーに近いマシンへ移すことで、アプリケーションサーバーの負荷を軽減し、取得時間と転送時間を短縮します。
キャッシュを改善することで、アプリケーションを大幅に高速化できます。多くのWebページでは、大容量の画像ファイルなどの静的データがコンテンツの半分以上を占めています。キャッシュを使用しない場合、このようなデータの取得と転送に数秒かかることがありますが、ローカルにキャッシュすれば、わずか1秒未満に短縮できます。
キャッシュが実際にどのように使用されるかを示す例として、NGINXとNGINX Plusでは、2つのディレクティブを使用してキャッシュを設定します。その2つは、proxy_cache_pathとproxy_cacheです。キャッシュの場所とサイズ、ファイルをキャッシュに保持する最長時間、その他のパラメーターを指定します。さらに、3つ目の(非常によく使用される)ディレクティブであるproxy_cache_use_staleを使用すると、最新のコンテンツを提供するサーバーがビジー状態または停止している場合に、古いコンテンツを提供するようキャッシュに指示できます。これにより、クライアントに何も返さない事態を回避できます。ユーザーの観点では、サイトやアプリケーションの稼働時間が大幅に向上する可能性があります。
NGINX Plusには、高度なキャッシュ機能があり、キャッシュのパージのサポートや、リアルタイムのアクティビティ監視用ダッシュボードでのキャッシュステータスの可視化などが可能です。
NGINXでのキャッシュの詳細については、リファレンスドキュメントおよびNGINX Plus管理ガイドをご覧ください。
注記:キャッシュは、アプリケーション開発者、設備投資の意思決定者、ネットワークをリアルタイムで運用する担当者といった、組織内のさまざまな部門に関係します。ここで触れたような高度なキャッシュ戦略は、DevOpsの視点の価値を示す好例です。DevOpsでは、アプリケーション開発、アーキテクチャ、運用の各視点を統合することで、サイトの機能、応答時間、セキュリティ、および取引成立や売上などのビジネス成果に関する目標の達成を支援します。
ヒント4 – データを圧縮
圧縮には、パフォーマンスを大幅に向上させる可能性があります。写真(JPEG、PNG)、動画(MPEG‑4)、音楽(MP3)などには、綿密に設計された非常に効果的な圧縮規格があります。いずれの規格も、ファイルサイズを10分の1以下に縮小します。
プレーンテキストとHTMLタグで構成されるHTML、CSS、JavaScriptなどのコードを含むテキストデータは、圧縮されずに送信されることが少なくありません。こうしたデータを圧縮すると、特に低速または帯域幅に制約のあるモバイル接続を利用するクライアントでは、Webアプリケーションの体感パフォーマンスを大幅に向上できる可能性があります。
これは、ユーザーがページを操作するうえで、多くの場合はテキストデータだけで十分であり、マルチメディアデータは補助的または装飾的な役割にとどまることがあるためです。スマートなコンテンツ圧縮により、HTML、Javascript、CSSなどのテキストベースのコンテンツに必要な帯域幅を通常30%以上削減でき、それに応じて読み込み時間も短縮できます。
SSLを使用する場合、圧縮によってSSLエンコードが必要なデータ量が減少するため、データ圧縮に要するCPU時間の一部を相殺できます。
テキストデータの圧縮方法はさまざまです。たとえば、ヘッダーデータ向けに特化したSPDYおよびHTTP/2の新しいテキスト圧縮方式については、ヒント6を参照してください。テキスト圧縮のもう1つの例として、NGINXでGZIP圧縮を有効にできます。サービス上でテキストデータを事前圧縮すると、圧縮済みの .gzファイルをgzip_staticディレクティブを使用して直接配信できます。
ヒント5 – SSL/TLSの最適化
Secure Sockets Layer(SSL)プロトコルと、その後継であるTransport Layer Security(TLS)プロトコルを採用するWebサイトが増えています。SSL/TLSは、オリジンサーバーからユーザーに送信されるデータを暗号化し、サイトのセキュリティ向上に役立ちます。この傾向の一因として、GoogleがSSL/TLSの導入を検索エンジンのランキングにプラスの要素として考慮するようになったことが挙げられます。
普及が進む一方で、SSL/TLSによるパフォーマンス低下は、多くのサイトにとって導入の障壁となっています。SSL/TLSがWebサイトのパフォーマンスを低下させる理由は2つあります。
- 新しい接続を開くたびに、暗号鍵を確立するための初期ハンドシェイクが必要になります。HTTP/1.xを使用するブラウザーはサーバーごとに複数の接続を確立するため、そのパフォーマンスへの影響が増大します。
- サーバーでのデータ暗号化とクライアントでの復号に伴う継続的なオーバーヘッド。
SSL/TLSの利用を促進するため、HTTP/2とSPDY(次のヒントで説明)の開発者は、ブラウザセッションごとに必要な接続が1つだけになるよう、これらのプロトコルを設計しました。これにより、SSLのオーバーヘッドを生む2つの主な要因のうち、1つが大幅に軽減されます。ただし、SSL/TLS経由で配信されるアプリケーションのパフォーマンスを向上させるために、現在ではさらに多くの対策を講じることができます。
SSL/TLSを最適化する仕組みは、Webサーバーによって異なります。たとえば、NGINXは標準的な汎用ハードウェア上で動作するOpenSSLを使用し、専用ハードウェアソリューションと同等のパフォーマンスを実現します。NGINXのSSL パフォーマンスについては十分な資料が公開されており、SSL/TLSの暗号化と復号に伴う処理時間とCPU負荷を最小限に抑えます。
また、SSL/TLSのパフォーマンスを向上させる方法の詳細については、こちらのブログ記事をご覧ください。主な手法は次のとおりです。
- セッションキャッシュ –
ssl_session_cacheディレクティブを使用して、SSL/TLSで新しい接続を保護する際に使用するパラメーターをキャッシュします。 - セッションチケットまたはID – 特定のSSL/TLSセッションに関する情報をチケットまたはIDに保存することで、新たなハンドシェイクを行わずに接続をスムーズに再利用できます。
- OCSPステープリング – SSL/TLS証明書情報をキャッシュすることで、ハンドシェイク時間を短縮します。
NGINXおよびNGINX Plusは、他のサーバーとは平文で通信しながら、クライアントトラフィックの暗号化と復号を処理するSSL/TLS終端に使用できます。NGINXまたはNGINX PlusでSSL/TLS終端を処理するように設定するには、HTTPS接続および暗号化されたTCP接続の手順を参照してください。
ヒント6 – HTTP/2またはSPDYを実装する
すでにSSL/TLSを使用しているサイトでは、単一の接続で必要なハンドシェイクが1回だけで済むため、HTTP/2とSPDYによってパフォーマンスが向上する可能性が非常に高くなります。まだSSL/TLSを使用していないサイトでは、HTTP/2とSPDYを導入することで、通常はパフォーマンスが低下するSSL/TLSへの移行による影響を相殺でき、応答性の面では差し引きゼロになります。
Googleは2012年、HTTP/1.x上でパフォーマンスを向上させる手段としてSPDYを導入しました。HTTP/2は、SPDYをベースとして最近承認されたIETF標準です。SPDYは広くサポートされていますが、まもなく非推奨となり、HTTP/2に置き換えられる予定です。
SPDYとHTTP/2の主な特長は、複数の接続ではなく、単一の接続を使用することです。この単一の接続は多重化されるため、複数のリクエストとレスポンスの一部を同時に伝送できます。
1つの接続を最大限に活用することで、これらのプロトコルは、ブラウザーによるHTTP/1.xの実装で必要となる、複数の接続の確立と管理に伴うオーバーヘッドを回避します。単一接続の使用は、SSLで特に有効です。SSL/TLSがセキュアな接続を確立する際に必要とする、時間のかかるハンドシェイクを最小限に抑えられるためです。
SPDYプロトコルではSSL/TLSの使用が必須でした。HTTP/2では正式な要件ではありませんが、これまでのところ、HTTP/2をサポートするすべてのブラウザは、SSL/TLSが有効な場合にのみHTTP/2を使用します。つまり、HTTP/2をサポートするブラウザがHTTP/2を使用するのは、WebサイトがSSLを使用し、そのサーバーがHTTP/2トラフィックを受け入れる場合に限られます。それ以外の場合、ブラウザはHTTP/1.xで通信します。
SPDYまたはHTTP/2を実装すると、ドメインシャーディング、リソースの結合、画像のスプライト化といった一般的なHTTPパフォーマンス最適化は不要になります。これにより、コードとデプロイが簡素化され、管理しやすくなります。HTTP/2がもたらす変化について詳しくは、F5のホワイトペーパー「Webアプリケーション開発者向けHTTP/2」をご覧ください。
これらのプロトコルへの対応例として、NGINXは早い段階からSPDYをサポートしており、現在SPDYを使用しているほとんどのサイトがNGINX上で稼働しています。また、NGINXはHTTP/2への先駆的な対応も進めており、2015年9月時点でNGINXオープンソース版とNGINX PlusはHTTP/2をサポートしています。
今後、ほとんどのサイトでSSLが全面的に有効化され、HTTP/2への移行が進むとNGINXは予想しています。これによりセキュリティが向上し、新たな最適化手法が見つかり実装されるにつれて、コードがよりシンプルになり、パフォーマンスも向上します。
ヒント7:ソフトウェアのバージョンを更新する
アプリケーションのパフォーマンスを向上させる簡単な方法の1つは、安定性とパフォーマンスに定評のあるコンポーネントをソフトウェアスタックに採用することです。また、高品質なコンポーネントの開発者は、継続的にパフォーマンスの向上やバグの修正に取り組む可能性が高いため、ソフトウェアの最新の安定版を使用することにはメリットがあります。新しいリリースほど、開発者やユーザーコミュニティから多くの注目を集めます。また、新しいビルドでは、新しいハードウェア向けのチューニングなど、最新のコンパイラ最適化も活用できます。
安定版の新しいリリースは、通常、古いリリースよりも互換性とパフォーマンスに優れています。また、ソフトウェアを常に最新の状態に保つことで、チューニングの最適化、バグ修正、セキュリティアラートにも対応しやすくなります。
古いソフトウェアを使い続けると、新しい機能を活用できない場合もあります。たとえば、前述のHTTP/2には現在OpenSSL 1.0.1が必要です。2016年半ば以降、HTTP/2には2015年1月にリリースされたOpenSSL 1.0.2が必要になります。
NGINXユーザーは、まずNGINXまたはNGINX Plusを最新バージョンにアップグレードしてください。ソケットシャーディングやスレッドプールなどの新機能が搭載されており(ヒント9を参照)、いずれもパフォーマンス向上のために継続的に調整されています。次に、スタックの下位層にあるソフトウェアを確認し、可能な限り最新バージョンにアップグレードしてください。
ヒント8 – Linuxをチューニングしてパフォーマンスを向上
現在、ほとんどのWebサーバー実装ではLinuxが基盤となるオペレーティングシステムとして使用されています。インフラストラクチャの基盤であるLinuxを調整することで、パフォーマンスを大幅に向上できる可能性があります。多くのLinuxシステムはデフォルトで、リソース使用量を抑え、一般的なデスクトップのワークロードに適合するよう控えめにチューニングされています。そのため、Webアプリケーションで最大限のパフォーマンスを引き出すには、少なくともある程度のチューニングが必要です。
Linuxの最適化はWebサーバーごとに異なります。NGINXを例に、Linuxの高速化に向けて検討できる主な変更点をいくつか紹介します。
- バックログキュー – 接続が停止しているように見える場合は、
net.core.somaxconnの値を増やすことを検討してください。これは、NGINXによる処理を待機する接続をキューに入れられる最大数です。現在の接続上限が小さすぎる場合はエラーメッセージが表示されるため、表示されなくなるまでこのパラメーターを徐々に増やすことができます。 - ファイルディスクリプター – NGINXは接続ごとに最大2つのファイルディスクリプターを使用します。システムが多数の接続を処理している場合、増加した負荷に対応するために、
sys.fs.file_max(システム全体のファイルディスクリプター数の上限)と、nofile(ユーザーのファイルディスクリプター数の上限)を引き上げる必要がある場合があります。 - エフェメラルポート – NGINXをプロキシとして使用すると、各アップストリームサーバー用に一時的な(「エフェメラル」)ポートが作成されます。利用可能なポート数を増やすには、
net.ipv4.ip_local_port_rangeで設定されるポート値の範囲を拡大できます。また、net.ipv4.tcp_fin_timeoutの設定により、非アクティブなポートが再利用されるまでのタイムアウトを短縮し、ポートの再利用を早めることもできます。
NGINXについては、Linuxシステムを最適化し、大量のネットワークトラフィックを余裕をもって処理できるようにする方法をNGINXパフォーマンスチューニングガイドでご確認ください。
ヒント9 – Webサーバーのパフォーマンスをチューニング
どのWebサーバーを使用する場合でも、Webアプリケーションのパフォーマンスを高めるためのチューニングが必要です。以下の推奨事項は一般にどのWebサーバーにも適用できますが、具体的な設定についてはNGINXを例に説明します。主な最適化項目は次のとおりです。
- アクセスログ – リクエストごとにログエントリを即座にディスクへ書き込む代わりに、エントリをメモリにバッファリングし、まとめてディスクへ書き込むことができます。NGINXでは、
buffer=sizeパラメーターをaccess_logディレクティブに追加すると、メモリバッファがいっぱいになった時点でログエントリがディスクに書き込まれます。さらに、flush=timeパラメーターを追加すると、指定した時間が経過した時点でもバッファの内容がディスクに書き込まれます。 - バッファリング – バッファリングでは、バッファがいっぱいになるまでレスポンスの一部をメモリに保持するため、クライアントとの通信を効率化できます。メモリに収まらないレスポンスはディスクに書き込まれるため、パフォーマンスが低下する可能性があります。NGINXのバッファリングがonの場合は、
proxy_buffer_sizeおよびproxy_buffersディレクティブを使用して管理します。 - クライアントのキープアライブ – キープアライブ接続は、特にSSL/TLSを使用している場合にオーバーヘッドを削減します。NGINXでは、クライアントが特定の接続を介して実行できる
keepalive_requestsの最大数をデフォルトの100から増やすことができます。また、keepalive_timeoutを増やしてキープアライブ接続をより長く維持することで、後続のリクエストを高速化できます。 - アップストリームのキープアライブ – アプリケーションサーバーやデータベースサーバーなどへのアップストリーム接続でも、キープアライブ接続が有効です。アップストリーム接続では、各ワーカープロセスで開いたまま維持するアイドル状態のキープアライブ接続数を指定する
keepaliveの値を増やすことができます。これにより接続の再利用が増え、新しい接続を確立する必要性が減ります。詳しくは、F5のブログ記事「HTTPキープアライブ接続とWebパフォーマンス」をご覧ください。 - 制限 – クライアントが使用するリソースを制限することで、パフォーマンスとセキュリティを向上できます。NGINXでは、
limit_connディレクティブとlimit_conn_zoneディレクティブで特定の送信元からの接続数を制限し、limit_rateディレクティブで帯域幅を制限します。これらの設定により、正規ユーザーによるリソースの占有を防ぎ、攻撃の防止にも役立ちます。limit_reqディレクティブとlimit_req_zoneディレクティブは、クライアントからのリクエストを制限します。アップストリームサーバーへの接続には、upstream設定ブロック内のserverディレクティブでmax_connsパラメーターを使用します。これにより、アップストリームサーバーへの接続数を制限し、過負荷を防ぎます。関連するqueueディレクティブは、max_connsの上限に達した後、指定された数のリクエストを指定された時間保持するキューを作成します。 - ワーカープロセス – ワーカープロセスはリクエストの処理を担います。NGINXは、イベントベースのモデルとOS依存のメカニズムを使用して、リクエストをワーカープロセス間に効率的に分散します。
worker_processesの値は、CPUごとに1つに設定することを推奨します。worker_connectionsの最大数(デフォルトは512)は、必要に応じてほとんどのシステムで安全に増やせます。実際に試して、システムに最適な値を見つけてください。 - ソケットシャーディング – 通常、単一のソケットリスナーが新しい接続をすべてのワーカープロセスに分配します。ソケットシャーディングでは、ワーカープロセスごとにソケットリスナーが作成され、利用可能になったソケットリスナーにカーネルが接続を割り当てます。これにより、ロック競合が軽減され、マルチコアシステムのパフォーマンスが向上する可能性があります。ソケットシャーディングを有効にするには、
reuseportパラメーターをlistenディレクティブに追加します。 - スレッドプール – コンピューターのプロセスは、1つの低速な処理によって停滞することがあります。Webサーバーソフトウェアでは、ディスクアクセスによって、メモリ内の情報の計算やコピーなど、より高速な多数の処理が停滞する可能性があります。スレッドプールを使用すると、低速な処理は別のタスクセットに割り当てられ、メインの処理ループでは高速な処理が継続されます。ディスク処理が完了すると、結果がメインの処理ループに戻されます。NGINXでは、2つの処理(
read()システムコールとsendfile())がスレッドプールにオフロードされます。

ヒント。オペレーティングシステムや関連サービスの設定を変更する場合は、一度に1つの設定だけを変更し、その後パフォーマンスをテストしてください。変更によって問題が発生した場合や、サイトの処理速度が向上しない場合は、元の設定に戻してください。
NGINX Webサーバーのチューニングについて詳しくは、F5のブログ記事「パフォーマンス向上のためのNGINXチューニング」をご覧ください。
ヒント10 – リアルタイムのアクティビティを監視して問題とボトルネックを解消
アプリケーションの開発とデリバリで高いパフォーマンスを実現するには、実環境でのアプリケーションのパフォーマンスをリアルタイムで詳細に監視することが重要です。特定のデバイス内とWebインフラストラクチャ全体のアクティビティを監視できる必要があります。
サイトアクティビティの監視は、ほとんどが受動的です。状況は把握できますが、問題の発見と修正は自ら行う必要があります。
監視によって、さまざまな種類の問題を検出できます。たとえば、次のような問題があります。
- サーバーが停止している。
- サーバーの動作が不安定で、接続が切断されています。
- サーバーでキャッシュミスの割合が高くなっています。
- サーバーが正しいコンテンツを送信していない。
New RelicやDynatraceのようなグローバルなアプリケーションパフォーマンス監視ツールは、リモート拠点からのページ読み込み時間の監視に役立ちます。一方、NGINXはアプリケーションデリバリー側の監視に役立ちます。アプリケーションパフォーマンスデータから、最適化がユーザーに実質的な効果をもたらしているタイミングや、トラフィックを維持するためにインフラストラクチャのキャパシティ増強を検討すべきタイミングを把握できます。
問題を迅速に特定して解決できるよう、NGINX Plusにはアプリケーション対応のヘルスチェックが追加されています。これは、定期的に繰り返され、問題を通知するために使用される合成トランザクションです。NGINX Plusには、セッションドレイニングもあります。これは、既存のタスクが完了するまで新しい接続を停止する機能です。また、復旧したサーバーが負荷分散グループ内で徐々に通常の処理速度に戻れるようにするスロースタート機能も備えています。ヘルスチェックを効果的に使用すると、ユーザーエクスペリエンスに重大な影響が及ぶ前に問題を特定できます。また、セッションドレイニングとスロースタートを使用すると、体感パフォーマンスや稼働時間に悪影響を与えないようにしながら、サーバーを交換できます。図は、サーバー、TCP接続、キャッシュで構成されるWebインフラストラクチャ向けの、NGINX Plus組み込みのライブアクティビティモニタリングダッシュボードを示しています。
まとめ – 10倍のパフォーマンス向上を実現
個々のWebアプリケーションで実現可能なパフォーマンス向上の幅は大きく異なり、実際の改善効果は、予算、投入できる時間、既存の実装における不足点によって左右されます。では、自社のアプリケーションで10倍のパフォーマンス向上を実現するには、どうすればよいのでしょうか。
各最適化によって期待できる効果の目安として、上記の各ヒントで見込まれる改善幅を以下に示します。ただし、実際の効果はほぼ確実に異なります。
- リバースプロキシサーバーと負荷分散 – 負荷分散が行われていない場合や適切でない場合、パフォーマンスが一時的に著しく低下することがあります。NGINXなどのリバースプロキシサーバーを追加すると、Webアプリケーションでメモリとディスク間のスラッシングが発生するのを防ぐことができます。負荷分散により、過負荷状態のサーバーから余力のあるサーバーへ処理を移し、容易にスケールできるようになります。こうした変更によってパフォーマンスが劇的に向上する可能性があります。現在の実装でパフォーマンスが最も低下しているときと比べれば、10倍の向上も容易に達成でき、全体的なパフォーマンスについても、それより小幅ながら大幅な向上が見込めます。
- 動的コンテンツと静的コンテンツのキャッシュ – Webサーバーがアプリケーションサーバーを兼ねており、過負荷の状態にある場合、動的コンテンツをキャッシュするだけで、ピーク時のパフォーマンスを10倍に向上できます。静的ファイルをキャッシュすることでも、パフォーマンスを数倍に向上できます。
- データの圧縮 – 写真にはJPEG、グラフィックにはPNG、動画にはMPEG‑4、音楽ファイルにはMP3といったメディアファイル圧縮を使用することで、パフォーマンスを大幅に向上できます。これらをすべて使用したうえでテキストデータ(コードおよびHTML)を圧縮すると、初回のページ読み込み速度を2倍に向上できます。
- SSL/TLSの最適化 – セキュアなハンドシェイクはパフォーマンスに大きな影響を及ぼす可能性があるため、これを最適化することで、特にテキスト中心のサイトでは、初期応答性が約2倍向上する可能性があります。SSL/TLSでのメディアファイル転送を最適化しても、パフォーマンスの向上はわずかにとどまる可能性があります。
- HTTP/2とSPDYの実装 – SSL/TLSと併用すると、これらのプロトコルによりサイト全体のパフォーマンスが段階的に向上する可能性があります。
- LinuxおよびWebサーバーソフトウェア(NGINXなど)のチューニング – バッファリングの最適化、キープアライブ接続の使用、時間のかかるタスクの別スレッドプールへのオフロードといった改善により、パフォーマンスを大幅に向上できる可能性があります。たとえば、スレッドプールを使用すると、ディスク負荷の高いタスクを10倍近く高速化できます。
ぜひ、これらの手法をお試しください。アプリケーションのパフォーマンスがどの程度向上したか、ぜひお聞かせください。下のコメント欄で結果を共有するか、ハッシュタグ#NGINXと#webperfを付けて成果をツイートしてください。
インターネット統計情報のリソース
Statista.com – 2016年のG20諸国の国内総生産に占めるインターネット経済の割合
Kissmetrics – 読み込み時間が収益に与える影響(インフォグラフィック)
Econsultancy – サイト速度:コンバージョン率向上のための事例、ヒント、ツール
著者について

関連するブログ記事
チュートリアル:NGINXを使用してアプリケーション向けにOpenTelemetryを構成する
OpenTelemetryを使用してNGINXサーバーの状態と健全性をより明確に把握することで、問題のトラブルシューティングを行い、Webアプリケーションのパフォーマンスを向上できます。
AkitaのNGINX Plus認定モジュールでAPIエンドポイントの問題を特定・修正
Akita SoftwareのAPIオブザーバビリティ向け新しいNGINX Plus Certified Moduleを活用して、APIエンドポイントの問題をより迅速に特定し、修正できます。
JavaプロジェクトをスキャフォールディングしてKubernetesネイティブアプリを構築する方法
Red HatのシニアプリンシパルデベロッパーアドボケイトであるDaniel Oh氏が、Javaプロジェクトをゼロから構築するためのひな形を作成し、Kubernetesネイティブアプリケーションとしてビルドする方法を解説します。
F5 NGINXaaS for Azureのご紹介:Microsoft Azureでネイティブに利用できるSaaS型ロードバランシング
NGINXaaS for Azureは、NGINX PlusをAzureネイティブのSaaSとして利用できるサービスです。NGINXの設定を容易にリフト&シフトできるため、クラウド導入とモダンアプリの展開を加速できます。

SELinuxでNGINXおよびNGINX Plusを使用する
Red Hat Enterprise Linux(RHEL)および関連ディストリビューションでSecurity-Enhanced Linux(SELinux)を有効にすると、デフォルト設定によりNGINXとNGINX Plusの一部の操作が制限されます。この記事では、すべての機能を利用できるようにSELinuxの設定を変更する方法について説明します。
NGINX PlusによるAWS Auto Scalingグループの負荷分散
新しいnginx-asg-sync統合ソフトウェアにより、NGINX PlusはAWS Auto Scalingグループの負荷を直接分散できるため、クラウドでの負荷分散がさらに柔軟になります