ウェブサイト検索

NGINXでコンテンツをキャッシュする方法


NGINXは、コンテンストとアプリケーションの配信を高速化し、安全性を高め、スケーラビリティを向上させるための、統合されたオープンソースの高性能ウェブサーバーです。Nginxの最も一般的な使用例の一つはコンテンツキャッシュであり、これはウェブサイトのパフォーマンスを向上させるための最も効果的な方法です。

関連記事: Linux用のトップ10オープンソースキャッシングツール

ローカルオリジンサーバーを加速するために、NGINXを使用して、上流サーバーからの応答をキャッシュするように設定し、コンテンツ配信ネットワーク(CDN)用のエッジサーバーを作成することができます。NGINXは、いくつかの大規模なCDNを支えています。

キャッシュとして設定された場合、NGINXは次のことを行います:

  • 静的および動的コンテンツをキャッシュする。
  • マイクロキャッシングを使用して動的コンテンツのパフォーマンスを向上させる。
  • バックグラウンドで再検証しながら、古いコンテンツを提供してパフォーマンスを向上させる。
  • キャッシュ制御ヘッダーを上書きまたは設定し、その他のこと。

この記事では、Webサーバーをできるだけ効率的に動作させるために、LinuxでNGINXをコンテンツキャッシュとして構成する方法について学びます。

前提条件:

LinuxサーバーにNGINXがインストールされている必要があります。インストールされていない場合は、以下のガイドに従ってNginxをインストールしてください:

  • CentOS 8にNginxをインストールする方法
  • CentOS 7にNginxをインストールする方法

Nginxで静的コンテンツをキャッシュする

静的コンテンツとは、ページ間で変わらない(変更されない)ウェブサイトのコンテンツのことです。静的コンテンツの例としては、画像、動画、文書などのファイルや、CSSファイル、JavaScriptファイルが含まれます。

ウェブサイトが多くの静的コンテンツを利用している場合、ブラウザが静的コンテンツのコピーを保存し、より迅速にアクセスできるようにクライアント側のキャッシュを有効にすることで、パフォーマンスを最適化できます。

以下のサンプル設定は良いスタートです。www.example.com をあなたのウェブサイト名のURLに置き換え、他のパス名を適切に修正してください。

server {
    # substitute your web server's URL for www.example.com
    server_name www.example.com;
    root /var/www/example.com/htdocs;
    index index.php;

    access_log /var/log/nginx/example.com.access.log;
    error_log /var/log/nginx/example.com.error.log;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ .php$ {
        try_files $uri =404;
        include fastcgi_params;
        # substitute the socket, or address and port, of your WordPress server
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        #fastcgi_pass 127.0.0.1:9000;
 	}   

    location ~* .(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg
                  |jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid
                  |midi|wav|bmp|rtf)$ {
        expires max;
        log_not_found off;
        access_log off;
    }
}

Nginxで動的コンテンツをキャッシュする

NGINXは、ローカルファイルシステムのどこかにある永続的なディスクベースのキャッシュを使用します。最初に、キャッシュされたコンテンツを保存するためのローカルディスクディレクトリを作成してください。
# mkdir -p /var/cache/nginx

次に、キャッシュディレクトリに適切な所有権を設定します。これには、NGINX ユーザー (nginx) とグループ (nginx) が所有する必要があります。

# chown nginx:nginx /var/cache/nginx

次に、以下のセクションでNginxで動的コンテンツを有効にする方法を見ていきましょう。

NGINXでFastCGIキャッシュを有効にする

FastCGI(またはFCGI)は、PHPなどのインタラクティブなアプリケーションとNGINXのようなウェブサーバーを接続するための広く使用されているプロトコルです。これはCGI(共通ゲートウェイインターフェース)の拡張です。

FCGIの主な利点は、複数のCGIリクエストを単一のプロセスで管理できることです。これがないと、ウェブサーバーはサービスのために毎回クライアントからのリクエストごとに新しいプロセスを開かなければならず、そのプロセスを管理し、リクエストを処理し、閉じる必要があります。

PHPスクリプトをLEMPスタックのデプロイメントで処理するために、NGINXはFPM(FastCGI Process Manager)またはPHP-FPMという人気のあるPHP FastCGI実装を使用します。PHP-FPMプロセスが実行されると、NGINXはそれにリクエストをプロキシして処理するように設定されます。したがって、NGINXはPHP-FPMバックエンドアプリケーションサーバーからのレスポンスをキャッシュするようにも設定できます。

NGINXの下で、FastCGIコンテンツキャッシュは、NGINXの設定構造内の最上位http{}コンテキストでfastcgi_cache_pathというディレクティブを使用して宣言されます。また、キャッシュ用のキー(リクエスト識別子)を定義するfastcgi_cache_keyを追加することもできます。

さらに、上流キャッシュの状態を読み取るためには、add_header X-Cache-Statusディレクティブをhttp{}コンテキスト内に追加してください - これはデバッグ目的で便利です。

あなたのサイトのサーバーブロック設定ファイルが/etc/nginx/conf.d/testapp.confまたは/etc/nginx/sites-available/testapp.conf(Ubuntuおよびその派生版の下)にあると仮定すると、ファイルを開いて編集し、ファイルの先頭に以下の行を追加してください。

fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=CACHEZONE:10m; inactive=60m max_size=40m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
add_header X-Cache $upstream_cache_status;

この fastcgi_cache_path ディレクティブは、次のパラメータの数を指定します:

  • /var/cache/nginx – キャッシュのためのローカルディスクディレクトリへのパスです。
  • レベル – キャッシュの階層レベルを定義し、/var/cache/nginxの下に2層のディレクトリ階層を設定します。
  • keys_zone (name:size) – すべてのアクティブキーとデータに関する情報(メタ)が保存される共有メモリゾーンの作成を可能にします。メモリにキーを保存することで、NGINXが
    MISS または HIT であるかをディスクの状態を確認せずに判断するため、チェックプロセスが迅速化されることに注意してください。
  • 非アクティブ – 指定された時間内にアクセスされなかったキャッシュデータが、その鮮度に関わらずキャッシュから削除される時間量を指定します。例の設定での60mという値は、60分後にアクセスされなかったファイルがキャッシュから削除されることを意味します。
  • max_size – キャッシュの最大サイズを指定します。ここで使用できる他のパラメータもあります(詳細についてはNGINXのドキュメントを参照してください)。

fastcgi_cache_keyディレクティブの変数は以下に説明されています。

NGINXは、リクエストのキー(識別子)を計算するためにそれらを使用します。重要なことに、キャッシュされたレスポンスをクライアントに送信するためには、リクエストはキャッシュされたレスポンスと同じキーを持っている必要があります。

  • スキーム - リクエストスキーム、HTTPまたはHTTPSです。
  • $request_method - リクエストメソッド、通常は「GET」または「POST」です。
  • $host – これはリクエストラインからのホスト名、または「Host」リクエストヘッダーフィールドからのホスト名、または要求に一致するサーバー名の順に優先順位に従って使用されます。
  • $request_uri – 完全なオリジナルリクエストURI(引数を含む)を意味します。

また、$upstream_cache_status 変数は、NGINX が応答する各リクエストについて計算されます。これは、MISS(キャッシュに応答が存在せず、アプリケーションサーバーから取得した場合)か、HIT(キャッシュから提供された応答)または他のサポートされている値のいずれかにかかわらずです。

次に、PHPリクエストをPHP-FPMに渡すlocationディレクティブ内で、上で定義したキャッシュを有効にするためにfastcgi_cacheディレクティブを使用します。

また、fastcgi_cache_validディレクティブを使用して、異なるレスポンスのキャッシュ時間を設定します。

fastcgi_cache CACHEZONE;
fastcgi_cache_valid  60m;

キャッシュ時間が私たちのケースのように指定されている場合、200、301、および302のレスポンスのみがキャッシュされます。ただし、レスポンスを明示的に指定することもできますし、任意のレスポンスコードのために「any」を使用することもできます。

fastcgi_cache CACHEZONE;
fastcgi_cache_valid 200  301 203 60m;
fastcgi_cache_valid 404 10m;
OR
fastcgi_cache CACHEZONE;
fastcgi_cache_valid  any 10m;

NginxにおけるFastCGIキャッシング性能のファインチューニング

同じキーのリクエストがレスポンスをキャッシュされる前に必要な最小回数を設定するには、fastcgi_cache_min_usesディレクティブをhttp{}、server{}、またはlocation{}コンテキストのいずれかに含めてください。

fastcgi_cache_min_uses  3

有効期限切れのキャッシュアイテムを条件付きリクエストを使用して再検証できるようにするには、If-Modified-SinceおよびIf-None-Matchヘッダーフィールドを使用して、fastcgi_cache_revalidateディレクティブをhttp{}、server{}、またはlocation{}コンテキスト内に追加します。

fastcgi_cache_revalidate on;

また、NGINX に対して、オリジンサーバーやFCGIサーバーがダウンしている場合に、キャッシュされたコンテンツを配信するよう指示することもできます。そのためには、locationディレクティブ内でproxy_cache_use_staleディレクティブを使用します。

このサンプル設定は、NGINXがエラー、タイムアウト、または上流サーバーからの指定されたエラーのいずれかを受信し、キャッシュされたコンテンツにリクエストされたファイルの古いバージョンがある場合に、その古いファイルを配信することを意味します。

proxy_cache_use_stale error timeout http_500;

FCGIキャッシュパフォーマンスを微調整するためのもう一つの有用な指示は、fastcgi_cache_background_updateです。これは、proxy_cache_use_staleディレクティブと連携して機能します。オンに設定すると、NGINXは、クライアントが期限切れのファイルやアップストリームサーバーからの更新処理中のファイルをリクエストしたときに古いコンテンツを提供するように指示します。

fastcgi_cache_background_update on;

fastcgi_cache_lockは、キャッシュにない同じコンテンツを複数のクライアントがリクエストした場合に、キャッシュパフォーマンスの微調整に役立ちます。NGINXは最初のリクエストのみをアップストリームサーバーに転送し、そのレスポンスをキャッシュして、他のクライアントリクエストをキャッシュから提供します。

fastcgi_cache_lock on;

上記のようにNGINX設定ファイルのすべての変更を行った後、ファイルを保存して閉じます。その後、NGINXサービスを再起動する前に、構成の構造をチェックして構文エラーがないか確認します。

# nginx -t
systemctl restart nginx

次に、キャッシュが正常に機能しているかテストします。以下のcurlコマンドを使用して、ウェブアプリケーションまたはサイトにアクセスしてみてください(最初はMISSを示すべきですが、その後のリクエストはスクリーンショットに示されているようにHITを示すべきです)。

# curl -I http://testapp.linux-console.net

ここにNGINXが古いデータを提供していることを示す別のスクリーンショットがあります。

キャッシュをバイパスする例外の追加

NGINXがクライアントにキャッシュされたレスポンスを送信しない条件を設定することが可能です。これは、fastcgi_cache_bypassディレクティブを使用します。また、fastcgi_no_cacheを使用して、NGINXがアップストリームサーバーからのレスポンスを全くキャッシュしないように指示することができます。

例えば、POST リクエストとクエリ文字列を持つ URL が常に PHP に送信されるようにしたい場合は、まず、次のように条件を設定する if 文を宣言します。

set $skip_cache 0; 
if ($request_method = POST) { 
	set $skip_cache 1; 
} 

その後、fastcgi_cache_bypassとfastcgi_no_cacheディレクティブを使用して、PHPリクエストをPHP-FPMに渡すlocationディレクティブで上記の例外を有効にします。

 
fastcgi_cache_bypass $skip_cache; 
fastcgi_no_cache $skip_cache;

あなたのサイトには、コンテンツキャッシングを有効にしたくない他の多くの部分があります。以下は、nginx.comブログで提供されているWordPressサイトのパフォーマンスを向上させるためのNGINX設定の例です。

それを使用するには、環境に存在するものを反映するように、ドメイン、パス、ファイル名などに変更を加えてください。

fastcgi_cache_path /var/run/NGINX-cache levels=1:2 keys_zone=WORDPRESS:100m inactive=60m; 
fastcgi_cache_key "$scheme$request_method$host$request_uri"; 
server { 
	server_name example.com www.example.com; 
	root /var/www/example.com; 
	index index.php; 
	access_log /var/log/NGINX/example.com.access.log; 
	error_log /var/log/NGINX/example.com.error.log; 
	set $skip_cache 0; 
	# POST requests and URLs with a query string should always go to PHP 	
	if ($request_method = POST) { 
		set $skip_cache 1; 
	} 
	if ($query_string != "") {
		set $skip_cache 1; 
	} 
	# Don't cache URIs containing the following segments 
	if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php |sitemap(_index)?.xml") { 
		set $skip_cache 1; 
	} 
	# Don't use the cache for logged-in users or recent commenters 
	if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass |wordpress_no_cache|wordpress_logged_in") {
		set $skip_cache 1; 
	} 
	location / { 
		try_files $uri $uri/ /index.php?$args; 
	} 
	location ~ .php$ { 
		try_files $uri /index.php; 
		include fastcgi_params; 
		fastcgi_pass unix:/var/run/php5-fpm.sock; 
		fastcgi_cache_bypass $skip_cache; 
		fastcgi_no_cache $skip_cache; 
		fastcgi_cache WORDPRESS; 
		fastcgi_cache_valid 60m; 
	} 
	location ~ /purge(/.*) {
		fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1"; 
	} 
	location ~* ^.+.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg |gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi |wav|bmp|rtf)$ { 
		access_log off; 
		log_not_found off; 
		expires max; 
	} 
	location = /robots.txt { 
		access_log off; 
		log_not_found off; 
	}
	location ~ /. { 
		deny all; 
		access_log off; 
		log_not_found off; 
	} 
}

NGINXでプロキシキャッシュを有効にする

NGINXは、他のプロキシサーバーからの応答のキャッシュもサポートしています(proxy_passディレクティブによって定義されます)。このテストケースでは、Node.js WebアプリケーションのリバースプロキシとしてNGINXを使用するため、Node.jsアプリケーションのキャッシュとしてNGINXを有効にします。ここで使用されるすべての設定ディレクティブは、前のセクションのFastCGIディレクティブと類似の意味を持っているため、再度説明することはありません。

プロキシサーバーからの応答をキャッシュするには、最上位の http{} コンテキストに proxy_cache_path ディレクティブを含めます。リクエストがどのようにキャッシュされるかを指定するには、次のように proxy_cache_key ディレクティブを追加することもできます。

proxy_cache_path /var/cache/nginx app1 keys_zone=PROXYCACHE:100m inactive=60m max_size=500m;
proxy_cache_key  "$scheme$request_method$host$request_uri";
add_header X-Cache-Status $upstream_cache_status;
proxy_cache_min_uses 3;

次に、ロケーションディレクティブでキャッシュを有効にします。

location / {
	proxy_pass http://127.0.0.1:3000;
	proxy_cache        PROXYCACHE;
	proxy_cache_valid 200 302 10m;
	proxy_cache_valid 404      1m;
}

NGINXがキャッシュされたコンテンツを送信せず、アップストリームサーバーからのレスポンスをまったくキャッシュしない条件を定義するには、proxy_cache_bypassとproxy_no_cacheを含めます。

 
proxy_cache_bypass  $cookie_nocache $arg_nocache$arg_comment;
proxy_no_cache        $http_pragma $http_authorization;

ファインチューニングプロキシキャッシュパフォーマンス

以下の指示は、プロキシキャッシュのパフォーマンスを微調整するのに役立ちます。また、FastCGIの指示と同じ意味を持っています。

proxy_cache_min_uses 3;
proxy_cache_revalidate on;
proxy_cache_use_stale error timeout updating http_500;
proxy_cache_background_update on;
proxy_cache_lock on;

詳細な情報とキャッシュ構成ディレクティブについては、主な2つのモジュール ngx_http_fastcgi_module と ngx_http_proxy_module のドキュメントを参照してください。

追加リソース:NGINXコンテンツキャッシングとWordPressパフォーマンス向上のためのヒント。

関連記事: