NginxのFastCGIキャッシュで表示速度アップする方法

目次
Nginxによる2つのキャシュ機能
NGINXには大別してFastCGIキャッシュとプロキシキャッシュの2種類があります。
FastCGIキャッシュ
FastCGIキャッシュはFastCGIレスポンスをそのままNGINXにキャッシュする機能です。
動的なページの高速化に役立ちますが、注意すべき点もあります。
今回、紹介するのはこちらです。
プロキシキャッシュ
プロキシキャッシュは、NGINXをリバースプロキシサーバとして立てて、そこにキャッシュする機能です
クライアント → NGINX(リバースプロキシサーバ) → Apache or NGINX(WEBサーバ)という構成はよく耳にしますね。
最近ではAWS CloudFrontを利用するパターンも散見します。
FastCGIキャッシュの注意点
FastCGIキャッシュは速度改善に繋がりますが、注意も必要です。
ユーザー毎の個別情報
FastCGIキャッシュはFastCGIレスポンスをそのままキャッシュする為、
sessionやcookie等のキャッシュすべきでは無い情報も含まれてしまいます。
キャッシュに不備がある場合、この記事のような個人情報漏えいインシデントに繋がる恐れがあります。
その為、fcgi_cacheを使用するのに適しているのはWordPress記事の様な、
『ユーザー毎の個別情報を含まない動的ページ』です。
初回アクセス
FastCGIキャッシュは、未キャッシュ状態時にFastCGIから返される内容をキャッシュする仕組み上、初回アクセス時にはキャッシュを利用できません。
その為、事前に1度アクセスを行いキャッシュを作成しておく必要があります。
コンテンツ更新
FastCGIキャッシュは、キャッシュファイル内に識別用KEYとしてURLパスを保持しています。
その為、同一URLパスに対しての2回目以降のアクセスに対してはキャッシュを返却します。
例えば、キャッシュ後にサーバ内のコンテンツを更新した場合、ユーザーがアクセスした際に返却されるのは更新前のコンテンツになります。
更新を反映させる為には、キャッシュの削除を行う必要があります。
具体的なFastCGIキャッシュの設定
『キャッシュ設定』と『キャッシュの作成と更新(削除と再作成)』をそれぞれ用意します。
尚、本記事に記載した方法で想定されない動作をした場合でも、一切の責任を負いかねますので、実施される場合はあらかじめご了承ください。
キャッシュ設定
※FastCGIはPHP-FPMを利用する想定です。
※fastcgi_passはPHPコンテナ(docker)を利用する想定です。
http{
proxy_buffering on;
fastcgi_cache_path /var/cache/nginx/dirname keys_zone=fcgi_cache:30m levels=1:2 max_size=512M inactive=600m;
fastcgi_cache_key $scheme$request_method$host$request_uri;
fastcgi_ignore_headers X-Accel-Redirect X-Accel-Expires Cache-Control Expires Vary Set-Cookie;
fastcgi_cache_lock on;
map $request_uri $disable_cache {
default 1;
~/cached_page 0;
}
server {
location ~ \.php$ {
root /var/www/root;
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# === fcgi_cache ===
fastcgi_cache_bypass $disable_cache;
fastcgi_no_cache $disable_cache;
fastcgi_cache fcgi_cache;
fastcgi_connect_timeout 60;
fastcgi_read_timeout 90;
fastcgi_send_timeout 60;
fastcgi_cache_valid 200 30d;
fastcgi_cache_valid 302 2h;
fastcgi_cache_valid 301 4h;
fastcgi_cache_valid any 1m;
client_body_buffer_size 2m;
add_header SELF-Cache-Status $upstream_cache_status;
}
}
}
キャッシュの作成と更新(削除と再作成)
キャッシュ作成は対象ページにcurlでアクセスする形で実施します。
キャッシュ削除はキャッシュファイルを丸ごと削除する事で実施します。
※特定のキャッシュファイルのみを削除する方法もあります。
今回はCI時に実行する想定で『更新用シェルスクリプト』を用意する事にします。
#!/bin/bash
###############
# fcgi_cache.sh
###############
set -u
error_func() {
echo "Usage: $0 " 1>&2
exit 1
}
# キャッシュを作成するページのパス
PATH_NAMES=("path/name1" "path/name2" "path/name3")
URL=""
CONTAINER_NAME=""
# テストサイトのBasic認証用
BASIC_AUTH=""
while getopts u:c:b: optKey; do
case $optKey in
u) URL=$OPTARG ;;
c) CONTAINER_NAME=$OPTARG ;;
b) BASIC_AUTH=$OPTARG ;;
\?) error_func ;;
esac
done
# URLとコンテナ名の引数は必須
if [ -z "$URL" -o -z "$CONTAINER_NAME" ]; then
error_func
fi
# 対象のコンテナ内のキャッシュを削除
docker exec $CONTAINER_NAME sh -c 'rm -rf ./var/cache/nginx/dirname/*'
# キャッシュ作成
if [ -n "$BASIC_AUTH" ]; then
for path in ${PATH_NAMES[@]}; do
curl -u $BASIC_AUTH -s $URL/$path -o /dev/null -w "%{http_code}\n"
done
else
for path in ${PATH_NAMES[@]}; do
curl -s $URL/$path -o /dev/null -w "%{http_code}\n"
done
fi
実行時は以下のように引数を取ります。
sh fcgi_cache.sh -u https://example.com -c nginx_container
まとめ
とても便利なキャッシュですが、 危険性を理解した上で利用したいですね。
本記事のまとめです。
- Nginxのキャッシュ機能はFastCGIキャッシュとプロキシキャッシュがある
- 使い場所を誤ると個人情報漏えいインシデントに繋がる恐れがある
- FastCGIキャッシュの使い所は『個別情報を含まない動的ページ』
- キャッシュは忘れずに更新(削除と再作成)する