【実践】Nginx のリバースプロキシでファイルをキャッシュする方法

ソフトウエア

<景品表示法に基づく表記> 本サイトのコンテンツには、商品プロモーションが含まれている場合があります。

nginxでリバースプロキシ&キャッシュサーバー

アクセス数が多いサイトの場合は、負荷分散のために複数台のサーバーを並べて機能分けも同時に行います。私の場合は、フロントにnginxを設置してリバースプロキシとキャッシュサーバーとして静的コンテンツを処理させます。バックエンドにはNginxやApacheなどが動的コンテンツを処理させることが多いです。

関連記事 Let’s Encrypt ワイルドカード証明書の設定方法:すべてのサブドメインを保護

nginxは一つのプロセスで複数のリクエストを非同期で同時に処理します。アクセス数が増えてもパフォーマンスが落ちにくいという特性があります。特に静的コンテンツの場合は効果がとても大きいです。

CentOSでの Nginx 設定

リバースプロキシとキャッシュサーバーで動作させる場合、記載出来るディレクティブが異なっているため設定が散らばります。

Module ngx_http_proxy_module
Error 404
Error - file not found

リバースプロキシの設定

リバースプロキシだけの機能を動作させる際の設定方法です。server ディレクティブと location ディレクティブに設定します。

server, location ディレクティブ

serverディレクティブにヘッダーを追加しバックエンドサーバーに情報を引き渡します。

File : /etc/nginx/nginx.d/hogehoge.conf
server {
    # ヘッダーの追加
    proxy_set_header    X-Real-IP       $remote_addr;
    proxy_set_header    X-Forwarded-Proto $scheme;
    proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header    Host            $http_host;
    location / {
            proxy_pass      https://バックエンドサーバー;
    }
}

proxy_set_header

これは「おまじない」です。バックエンドサーバーに必要な情報を引き渡すために設定します。

この設定が無いとバックエンドサーバーのアクセスログは、接続元が全てリバースプロキシのIPになるので分析が出来なくなります。

この設定を入れるとバックエンドサーバーに接続元のIPやプロトコルなどを渡すので、アクセスログを見ると接続元の情報が表示されるようになります。

proxy_pass

バックエンドサーバーを指定します。

プロキシキャッシュの設定

リバースプロキシが動作している時に、全てをバックエンドに流さず静的コンテンツはキャッシュから返すように動作させます。この事により負荷分散が行われます。

http ディレクティブ

File : /etc/nginx/nginx.conf
http {
    # キャッシュの場所を指定する
    proxy_cache_path /var/cache/nginx/proxy_file_cache levels=2:2 keys_zone=cache_key:10m max_size=5g inactive=24h;
}

proxy_cache_path

キャッシュの保存先を指定します。場所の指定だけではなく色々とオプションがあります。

この指定したディレクトリは自動的に作られます。

levels

キャッシュを保存するサブディレクトリ階層を指定します。

Linuxの場合、同じディレクトリ内にファイル数が多いとinodeが不足してしまい、ファイルが作成できなくなったり、lsコマンドを打っても結果が返って来なくなったりします。

その為に、ディレクトリ階層を利用してファイルを分散させる必要があります。

“levels=2:2”  は  “/var/cache/nginx/proxy_file_cache/00/ff/xxxxxxxxx” のようにキャッシュが保存されます。

keys_zone

共有メモリのサイズとキーの名前を指定します。1MiBあたり約8000個のキーを保持できます。

max_size

全キャッシュファイルのサイズ合計の上限値です。

inactive

期間内にアクセスされなかったキャッシュファイルは、有効期間に関わらず削除されます。

server, location ディレクティブ

File : /etc/nginx/nginx.d/hogehoge.conf
server {
    location / {
            proxy_pass      https://バックエンドサーバー;

            # 基本はキャッシュしない
            set $do_not_cache 1;
            # 画像のみキャッシュさせる
            if ($uri ~* "\.(jpg|jpeg|png|gif|css|js|ico)$") {
                     set $do_not_cache 0;
            }
            proxy_no_cache $do_not_cache;

            # キャッシュの検索
            proxy_cache_bypass $do_not_cache;
            # バックエンド no-cache を無視
            proxy_ignore_headers Cache-Control;
            # キャッシュのキーゾーンを指定
            proxy_cache cache_key;
            # キャッシュの有効時間を指定
            proxy_cache_valid 200 302 60m;
            proxy_cache_valid 404 10m;
            # キャッシュのステータスヘッダーを追加
            add_header X-Cache-Status $upstream_cache_status;
    }
}

proxy_no_cache

location / {}なので全部のリクエストがバックエンドサーバーに流れます。

全てをキャッシュさせない設定を行い、静的コンテンツだけをキャッシュさせるように条件式を設定します。

始めに $do_not_cache 変数に 1 をセットします。これで全てをキャッシュしません。

if分で条件分けして静的コンテンツの場合は $do_not_cache 変数に 0 がセットされます。

proxy_cache_bypass

1がセットされていとファイルをキャッシュから探しません。上のproxy_no_cacheと同じ変数を与えてキャッシュせず、キャッシュからも取得しない動作になります。

proxy_ignore_headers

バックエンドサーバーの Cache-Control ヘッダーに no-cache や private が含まれるとキャッシュしないので、このヘッダーを無視させます。

proxy_cache

http ディレクティブにて設定した keys_zone を指定します。

proxy_cache_valid

キャッシュの対象と有効な時間を指定します。

HTTP レスポンスが “200” と “302” の場合は 60 分、 404 の場合は 10分という意味です。

add_header

レスポンスヘッダーにキャッシュヒットしたかどうかを含めます。ヘッダー名は何でも構いません。

レスポンスヘッダーにキャッシュヒットしたかどうか
レスポンスヘッダーにキャッシュヒットしたかどうか
  • HIT:キャッシュがあり、キャッシュを返した
  • MISS:キャッシュがないのでバックエンドサーバに問い合わせしたとき
  • BYPASS:キャッシュから返さない「 proxy_cache_bypass が 1」
  • EXPIRED:キャッシュが存在するが期限切れの場合

エラーについて

プロキシキャッシュの設定は滅多に行わないので設定を適当に行ってしまいます。

# nginx -t
nginx: [emerg] "proxy_cache" zone "cache_key" is unknown in /etc/nginx/nginx.conf:83
nginx: configuration file /etc/nginx/nginx.conf test failed

その結果、エラーログを表示させてしまうことがあります。

このエラーは、http ディレクティブの「proxy_cache_path」が未記入の時に出力されます。