Posted at

nginxでリバースプロキシキャッシュして、キャッシュを削除する機能を付ける

More than 3 years have passed since last update.

nginxでリバースプロキシかましてキャッシュさせることでパフォーマンスを稼ぐっていうのは、わりとよくあるシチュエーションなんですが、キャッシュ自体のコントロールっていうのが、案外忘れがちというか、置いてけぼりになることが多いので、キャッシュを削除できる環境を作るメモです。


nginxのリバースプロキシ設定

まず、nginxはデフォルトでキャッシュする機能があるので設定するだけでいけます。下記の設定は、単なるWebサーバ https://example.com をバックエンドとして、全URLをキャッシュする設定です。


nginx.conf

http {

proxy_cache_path /var/cache/nginx/cache levels=1:2 keys_zone=zone1:4m inactive=7d max_size=50m;
proxy_temp_path /var/cache/nginx/tmp;

}



server.conf

server {

proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_ignore_headers Cache-Control;
proxy_cache zone1;
proxy_cache_key $uri;
proxy_cache_valid 200 302 1m;
proxy_cache_valid 404 10m;

location / {
proxy_pass https://example.com;
}

}



proxy_cache_path

ここのパラメータが毎回分からなくなるのでメモ。第1パラメータはキャッシュファイルを保存する場所です。

キー

levels
キャッシュを保存するディレクトリ階層とディレクトリ名に使用される文字数になります。1:2だと/1/01に、2:2:2だと/01/01/01になります。ただし階層を増やしたり、文字数を増やすとその分ディレクトリが作成されることになるので、inode枯渇で死ぬケースもあるようです。参考 nginxのキャッシュ階層を深くしすぎてinodeが枯渇した

keys_zone
proxy_cacheディレクティブで指定するキーです。コロン区切りで、共有メモリの容量指定ができます。1MBにつき約8000個のキャッシュメタデータを保存できるようです

inactive
指定した期間後、自動的にキャッシュが削除されます。デフォルトだと10分に設定されています

max_size
キャッシュのファイルサイズ上限です。keyz_zoneのメモリと、max_sizeどちらかが枯渇した時点でキャッシュが停止します


キャッシュを削除する

キャッシュを消したい場合は、proxy_cache_pathの中にある該当ファイルを消せばOKなのだけど、いちいちそんな手動で消すの面倒くさいし、ログインしなきゃいけないのでありえんとなるわけです。下記コマンドの様にURLからキャッシュファイルを特定するコマンドもありますけど…。

find /var/cache/nginx/example.com -type f -exec grep -l "KEY: http://example.com/$" {} \; | xargs rm -f


キャッシュ可能なURLを作成する

本題です。nginxデフォルトだとキャッシュを削除する機能はありません。そこでnginxモジュールngx_cache_purgeを使用します。

ngx_cache_purgeをnginxに組み込むには、nginxをソースからビルドして上げる必要があります。はい、面倒くさいですね。nginx自体パッケージからインストールしているし…という人には、nginxのビルドを自動化できるツールnginx-buildを利用しましょう。モジュールも超簡単に導入できます。

もしくは、Itamaeであれば僕が以前作ったItamaePluginがあるので、それを使っても良いと思います。

ngx_cache_purgeを導入したら、設定ファイルにキャッシュを削除する用のURLディレクティブを指定します。この例だと/hoge/piyoのURLをキャッシュしていたとしたら/purge/hoge/piyoにアクセスするとキャッシュが削除できます。


server.conf

server {

location ~ ^/purge(/.*) {
allow 127.0.0.1;
deny all;
proxy_cache_purge zone1 $1;
}
}

アプリケーション側からは、データソースの変更があったタイミングで削除用のURLを叩くとキャッシュがクリアされるように出来ると思います。簡単ですね。