Nginx に cache purge モジュールを追加する

Nginx をリバースプロキシとして使用する場合、キャッシュされたページを削除したくなることがあります。
しかし、素の Nginx ではキャッシュを削除するには、キャッシュディレクトリ配下の全ファイルをすべて削除するしか方法はありません。
(もしくは、設定時間が経過して自動削除されるのを待つか)

ページ単位で Nginx リバースプロキシのキャッシュを削除するには、ngx_cache_purge というモジュールを追加することで実現できます。
この ngx_cache_purge モジュールを組み込んだ rpm パッケージを作成する方法を説明します。

rpm パッケージの作成方法については、以前書いたエントリ「nginx 1.0.0 が出てます」を参考にしてください。
このエントリでは、ここまでの作業が終わっているものとして解説します。

Nginx に ngx_cache_purge モジュールを組み込む

まずは http://labs.frickle.com/files/ から、最新の ngx_cache_purge モジュールのソースを取得してきます。
執筆時点では、1.4 が最新でした。

$ cd ~/rpm/SOURCES/
$ wget http://labs.frickle.com/files/ngx_cache_purge-1.4.tar.gz

次に .spec を修正します。

$ cd ~/rpm/SPECS/
$ vi nginx.spec

修正内容は、こんな感じです。

 :
%define _unpackaged_files_terminate_build 0 
%define ngx_cache_purge_version 1.4
 :
Source6:    nginx.conf
Source10:   ngx_cache_purge-%{ngx_cache_purge_version}.tar.gz
 :
%prep
%setup -q

%patch0 -p0
#%patch1 -p0
#%patch2 -p0
%setup -T -D -a 10
 :
%build
# nginx does not utilize a standard configure script.  It has its own
# and the standard configure options cause the nginx configure script
# to error out.  This is is also the reason for the DESTDIR environment
# variable.  The configure script(s) have been patched (Patch1 and
# Patch2) in order to support installing into a build environment.
export LANG='ja_JP.UTF-8'
export DESTDIR=%{buildroot}
./configure \
    --user=%{nginx_user} \
    --group=%{nginx_group} \
 :
    --with-cc-opt="%{optflags} $(pcre-config --cflags)" \
    --add-module=%{_builddir}/nginx-%{version}/ngx_cache_purge-%{ngx_cache_purge_version}
make %{?_smp_mflags}
 :

そんで、おもむろに rpm ビルド。

$ rpmbuild -bb nginx.spec

すでに同じバージョンの Nginx がインストールされている場合は、一度アンインストールしてからインストール。

$ sudo rpm -e nginx-1.x.x-1
$ cd ~/rpm/RPMS/x86_64/
$ sudo rpm -Uvh nginx-1.x.x-1.el5.x86_64.rpm

nginx.conf を修正して cache purge 用の url を用意する

こんな感じで修正します。

 :
http {
 :
  proxy_cache_path  /var/cache/nginx levels=1:2 keys_zone=czone:32m max_size=256m inactive=120m;
  proxy_temp_path   /var/tmp/nginx;
  proxy_cache_key   "$scheme://$host$request_uri";
  proxy_set_header  Host               $host;
  proxy_set_header  X-Real-IP          $remote_addr;
  proxy_set_header  Remote-Addr        $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_connect_timeout 30;
  proxy_send_timeout 30;
  proxy_read_timeout 60;
 :
  upstream backend {
    ip_hash;
    server 127.0.0.1:8000;
  }

  server {
    listen 80;
    server_name example.com;
     :
    if ($http_user_agent ~* '(DoCoMo|J-PHONE|Vodafone|MOT-|UP\.Browser|DDIPOCKET|ASTEL|PDXGW|Palmscape|Xiino|sharp pda browser|WindowsCE|L-mode|WILLCOM|SoftBank|Semulator|Vemulator|J-EMULATOR|emobile|mixi-mobile-converter)') {
      set $mobile 1;
    }
    if ($http_user_agent ~* '(iPhone|iPod|Opera Mini|Android.*Mobile|NetFront|PSP|BlackBerry|Windows Phone)') {
      set $mobile 2;
    }

    location /wp-admin { proxy_pass http://backend; }
    location ~ .*\.php { proxy_pass http://backend; }
    location ~ .*\.(txt|xml|html?|js|css|gz|ico|jpe?g|JPE?G|gif|GIF|png|PNG|wmv|WMV|flv|FLV|mpg|MPG) {
      index   index.html;
      if (-f $request_filename) {
        access_log  off;
        ssi     on;
        expires 30d;
        break;
      }
    }
    location ~ /\.ht { deny  all; }
    location / {
      if ($http_cookie ~* "comment_author_|wordpress_(?!test_cookie)|wp-postpass_" ) {
        set $do_not_cache 1;
      }
      proxy_no_cache     $do_not_cache;
      proxy_cache_bypass $do_not_cache;
      proxy_redirect off;
      proxy_cache czone;
      proxy_cache_key "$scheme://$host$request_uri$is_args$args$mobile";
      proxy_cache_valid  200 60m;
      proxy_cache_valid  404 5m;
      proxy_pass http://backend;
    }

    location ~ /purge(/.*) {
      proxy_cache_purge czone "$scheme://$host$1$is_args$args$mobile";
    }
  }
}

これで、http://example.com/archives/1 というページのキャッシュを削除したい時は http://example.com/purge/archives/1 にアクセスすれば削除できるようになります。
ただし、このままでは、管理者以外でもキャッシュを削除できる状態です。
実運用時は59行目以降を以下のように書き換えて、キャッシュを削除できるマシンを限定したほうが良いでしょう。

    location ~ /purge(/.*) {
      allow 127.0.0.1;
      allow xxx.xxx.xxx.xxx;
      deny all;
      proxy_cache_purge czone "$scheme://$host$1$is_args$args$mobile";
    }

あとは WordPress であれば Nginx Proxy Cache Purge プラグイン等を導入して、投稿時に自動でキャッシュを消せるようにしておけば良いでしょう。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください