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キャッシュの使い所は『個別情報を含まない動的ページ』
  • キャッシュは忘れずに更新(削除と再作成)する

お知らせ

現在、エンジニアルートではフリーエンジニアを中心とした、フリーランスの お仕事紹介、お悩み相談を承っております。

一対一のカウンセリングに基づき、スキルやキャリアプランなどのご要望をお伺いしピッタリの案件をご提案します。ご参画中のご相談・節税対策、適正な給与なのか知りたい、マージンを下げたいなど何でもサポートをいたします。
案件獲得までには早ければ1〜3日、平均的に2週間以内には複数案件から選べる状況になっています。将来的な独立の相談のみでも承っております。お気軽にご登録ください。

お仕事をご要望の方は、下記バナーより新規登録をお待ちしております。
非公開求人多数です。

フリーランスを考えてる方やお仕事をご要望、面接指導などをご希望の方は、下記バナーより新規登録をお待ちしております。非公開求人多数です。

よく読まれている記事

「技術について開発言語-ツール情報」でよく読まれている記事