nginxでリバースプロキシ&キャッシュサーバー
アクセス数が多いサイトの場合は、負荷分散のために複数台のサーバーを並べて機能分けも同時に行います。私の場合は、フロントにnginxを設置してリバースプロキシとキャッシュサーバーとして静的コンテンツを処理させます。バックエンドにはNginxやApacheなどが動的コンテンツを処理させることが多いです。
関連記事 Let’s Encrypt ワイルドカード証明書の設定方法:すべてのサブドメインを保護
nginxは一つのプロセスで複数のリクエストを非同期で同時に処理します。アクセス数が増えてもパフォーマンスが落ちにくいという特性があります。特に静的コンテンツの場合は効果がとても大きいです。
CentOSでの Nginx 設定
リバースプロキシとキャッシュサーバーで動作させる場合、記載出来るディレクティブが異なっているため設定が散らばります。
リバースプロキシの設定
リバースプロキシだけの機能を動作させる際の設定方法です。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」が未記入の時に出力されます。