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

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

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

NGINXを使用して、アップストリームサーバーからのレスポンスをキャッシュするように構成して、ローカルオリジンサーバーを高速化したり、コンテンツ配信ネットワーク(CDN)向けのエッジサーバーを作成したりできます。NGINXはいくつかの最大のCDNを支えています。

キャッシュとして構成された場合、NGINXは次のようになります:

  • 静的および動的コンテンツをキャッシュします。
  • マイクロキャッシングにより動的コンテンツのパフォーマンスを向上させます。
  • パフォーマンスを向上させるためにバックグラウンドで再検証しながら古いコンテンツを提供します。
  • Cache-Controlヘッダーをオーバーライドまたは設定し、その他の操作を行います。

この記事では、LinuxでNGINXコンテンツキャッシュとして構成する方法を学び、ウェブサーバーをできるだけ効率的に実行します。

前提条件:

LinuxサーバーにNGINXがインストールされている必要があります。インストールされていない場合は、次のガイドに従って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などのWebサーバーと連携させるための広く使用されているプロトコルです。これはCGICommon Gateway Interface)の拡張機能です。

FCGIの主な利点は、複数のCGIリクエストを1つのプロセスで管理できることです。これがないと、Webサーバーはサービスのためにクライアントリクエストごとに新しいプロセスを開く必要があります(それを制御し、リクエストを処理し、閉じる必要があります)。

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

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

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

サイトのサーバーブロック構成ファイルが/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;
Enable FastCGI Cache in NGINX

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

  • /var/cache/nginx – キャッシュのためのローカルディスクディレクトリへのパス。
  • levels – キャッシュの階層レベルを定義し、/var/cache/nginxの下に2レベルのディレクトリ階層を設定します。
  • keys_zone (name:size) – 全てのアクティブなキーとデータ(メタ情報)の情報を保存する共有メモリゾーンの作成を有効にします。キーをメモリに保存することで、NGINXがディスク上のステータスを確認する必要なく、MISSまたはHITかどうかを容易に判断できるようになります。
  • inactive – 指定された時間内にアクセスされないキャッシュされたデータが、新鮮さに関係なくキャッシュから削除されるまでの時間を指定します。例の構成では、60mの値は、60分間アクセスされなかったファイルがキャッシュから削除されることを意味します。
  • max_size – キャッシュの最大サイズを指定します。ここで使用できる他のパラメータがあります(詳細はNGINXのドキュメントを参照してください)。

fastcgi_cache_keyディレクティブの変数は以下のように記述されています。

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

  • $scheme – リクエストのスキーム、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;
Define Caching Zone and Time

キャッシュ時間のみが指定されている場合、200301、および302のレスポンスがキャッシュされます。ただし、レスポンスを明示的に指定するか、任意の(すべてのレスポンスコードに対して)使用することもできます:

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
Set Minimum Cache Usage

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

fastcgi_cache_revalidate on;
Set Cache Re-validation

NGINXに、オリジンサーバーまたはFCGIサーバーがダウンしている場合にキャッシュされたコンテンツを提供するよう指示するには、proxy_cache_use_staleディレクティブを、locationディレクティブ内に含めます。

このサンプル構成では、NGINXがエラー、タイムアウト、およびアップストリームサーバーから指定されたエラーのいずれかを受信し、キャッシュされたコンテンツに要求されたファイルの古いバージョンがある場合、古いファイルを提供します。

proxy_cache_use_stale error timeout http_500;
Enable Serving of Stale Data

別の有用な指令で FCGI キャッシュのパフォーマンスを調整する方法は、fastcgi_cache_background_update ディレクティブを使うことです。これは、proxy_cache_use_stale ディレクティブと連動して動作します。このディレクティブを「on」に設定すると、NGINX に対し、クライアントが期限切れまたはアップストリームサーバから更新中のファイルを要求した場合に、古いコンテンツを提供するよう指示します。

fastcgi_cache_background_update on;
Enable Cache Background Update

fastcgi_cache_lock も便利です。キャッシュのパフォーマンスを調整する際に、キャッシュに存在しないコンテンツを複数のクライアントが要求した場合、NGINX は最初のリクエストのみをアップストリームサーバに転送し、応答をキャッシュしてから他のクライアントの要求をキャッシュから提供します。

fastcgi_cache_lock on;
Enable Cache Lock

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

# nginx -t
# systemctl restart nginx
Check and Start Nginx Service

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

# curl -I http://testapp.tecmint.com
Test FastCGI Cache

以下は、NGINX が古いデータを提供しているスクリーンショットです。

Test Nginx Serving Stale Data

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

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

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

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

次に、PHPリクエストをPHP-FPMに渡すlocationディレクティブで、上記の例外をアクティブにします。これには、fastcgi_cache_bypassおよびfastcgi_no_cacheディレクティブを使用します。

 
fastcgi_cache_bypass $skip_cache; 
fastcgi_no_cache $skip_cache;

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

これを使用するには、環境に存在するものを反映するように変更します(ドメイン、パス、ファイル名など)。

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ディレクティブで定義されます)。このテストケースでは、NGINXをNode.jsウェブアプリケーションのリバースプロキシとして使用しているため、NGINXをNode.jsアプリケーションのキャッシュとして有効にします。ここで使用されるすべての構成ディレクティブは、前のセクションの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;

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

追加リソース:NGINXコンテンツキャッシングおよびWordPressパフォーマンスの改善に関するヒント

Source:
https://www.tecmint.com/cache-content-with-nginx/