情報科学屋さんを目指す人のメモ

方法・手順・解説を書き残すブログ。私と同じことを繰り返さずに済むように。

WordPressプラグインNginx Cache ControllerでPC用キャッシュとスマホ用キャッシュの両方を削除する設定メモ

Nginx (11) WordPress (76) WordPressプラグイン (25)

nginxをリバースプロキシキャッシュとして利用するようにしたのですが、記事を更新してもキャッシュが削除されない状態でした。今回Nginx Cache Controllerプラグインを使ってキャッシュを削除するようにしたので、そのときに気が付いた事をメモしておきます。不明点もあるのですが、とりあえず動いたので、その状態を資料としてメモ。

環境はCentOS+さくらのVPS+nginx(リバースプロキシ)->nginx(Webサーバ)->php-fpm->WordPressな感じです。詳しくは→「WordPressブログ引っ越しメモ(さくらのレンタルサーバ+Apache→さくらのVPS+Nginx)

Nginx Cache Controller に Nginx の設定を教えてあげる

このプラグインはnginxの設定によっては、プラグインをインストールするだけではさっぱり動作しません。なぜかというと、WordPress側から、リバースプロキシとして動作しているnginxの設定は分からないからです。したがって、その分の設定はこちらがやってあげなければなりません。

参考にすべきは、nginxの設定ファイルで、普通は「/etc/nginx/conf.d/default.conf」と「/etc/nginx/nginx.conf」を使っているはずです。

キャッシュディレクトリとキャッシュレベル

まず、設定ファイルの中の「http {}」に、「proxy_cache_path」という設定項目があるはずです。

私は現在次のようになっています。

proxy_cache_path /var/www/did2memo.net/cache levels=1 keys_zone=zone:128m inactive=7d max_size=256m;

Nginx Cache Controllerの設定画面で「キャッシュ削除の有効化」を「Yes」にしたら、「Nginx リバースプロキシ設定」の「キャッシュディレクトリ」に、ここに設定してあるキャッシュの場所(/var/www/did2memo.net/cache)を入力してください。また、「キャッシュレベル」には、「levels=」のところに書いてあるキャッシュレベル(1)を設定してください(キャッシュレベルは、ただの数字(1)だったり、コロン区切りで階層化されていたり(1:2)します)

キャッシュキー(の生成方法)

実は、もう一つ教えて上げる必要があります。それが、キャッシュキー(の生成方法)です。nginxは、このキャッシュキーをキーとして使って、キャッシュファイルを探します。

したがって、この設定が分からないと、特定のURLへのアクセス結果が、どこにキャッシュされているのかわからないのです。

Nginx Cache Controllerでは、そのキャッシュキーの生成方法として、「$scheme://$host$request_uri」がデフォルトで設定されているようです。これが重要な手がかりになります。

私の場合は、次のように設定していました。

    ## location /
    location / {

        set $mobile "";
        set $do_not_cache "";
        if ($http_cookie ~* "comment_author_|wordpress_(?!test_cookie)|wp-postpass_" ) {
            set $do_not_cache 1;
        }
        if ($http_user_agent ~* “2.0\ 2MMP|240×320|400X240|AvantGo|BlackBerry|Blazer|Cellphone|Danger|DoCoMo|Elaine/3.0|EudoraWeb|Googlebot-Mobile|hiptop|IEMobile|KYOCERA/WX310K|LG/U990|MIDP-2.|MMEF20|MOT-V|NetFront|Newt|Nintendo\ Wii|Nitro|Nokia|Opera\ Mini|Palm|PlayStation\ Portable|portalmmm|Proxinet|ProxiNet|SHARP-TQ-GX10|SHG-i900|Small|SonyEricsson|Symbian\ OS|SymbianOS|TS21i-10|UP.Browser|UP.Link|webOS|Windows\ CE|WinWAP|YahooSeeker/M1A1-R2D2|iPhone|iPod|Android|BlackBerry9530|LG-TU915\ Obigo|LGE\ VX|webOS|Nokia5800″) {
            set $mobile "@mobile"
        }
        proxy_no_cache $do_not_cache;
        proxy_cache_bypass $do_not_cache;

        proxy_pass http://backend;
        proxy_cache zone;
        proxy_cache_key "$scheme$proxy_host$uri$is_args$args$mobile";
        proxy_cache_valid 200 60m;
        proxy_cache_valid 404 5m;
    }

簡単に言えば、スマートフォンとPCとで、別のキャッシュキーを生成することで、スマートフォンとPCとが、別のキャッシュを探しに行くように設定していました。これで、wp_is_mobileなどを使ってスマートフォン用にページを工夫している場合も、上手く動作します(wp_is_mobileと同値ではないのでまだ要検証)。

しかし、ここで設定している「$scheme$proxy_host$uri$is_args$args$mobile」は、Nginx Cache Controllerのデフォルトである「$scheme://$host$request_uri」とは大きく異なります。

そこでまず、nginxの設定に「://」を追加して、「$scheme://$proxy_host$uri$is_args$args$mobile」にしました。ただ、「$mobile」というスマートフォンを識別する部分はどうにもなりません。消してしまったら本末転倒です(というかスマートフォンにPCのキャッシュが表示されたり、PCにスマートフォンのキャッシュが表示されたりしてしまう)。

そこでNginx Cache Controller側の設定を変更したいのですが、設定画面はありません。実は、公式サイトには、

You can customize proxy_cache_key with nginxchampuru_get_reverse_proxy_key hook. 引用元

と書いてあり、「設定画面なんてないよ」ということになっていました。しかし、nginxchampuru_get_reserse_proxy_keyフックの使い方の例などは紹介されておらず、このままではソースコードを読む必要がありますし、nginxの動作をPHPで再現しないといけないのかなぁとちらっと思いました。

そこで参考になったのが「網元で Ktai Style とか使う時の注意点 | dogmap.jp」の記事です。ここでは、nginxの設定はよくわかりませんが、$mobileと同じような事をしていることは推測できました。そこで、それを少し改造することで解決できないかと、次のようにfunctions.phpに追加してみました。

add_filter('nginxchampuru_get_cache', 'nginxchampuru_get_cache', 10, 2);
function nginxchampuru_get_cache($key, $url = null) {
    global $nginxchampuru;
    if (!$url) {
        $url = $nginxchampuru->get_the_url();
    }
    $keys = array(
        $key,
        $nginxchampuru->get_cache_key($url.'@mobile'),
    );
    if ($key !== $nginxchampuru->get_cache_key($url)) {
        $keys[] = $nginxchampuru->get_cache_key($url);
    }
    return $nginxchampuru->get_cache_file($keys);
}

nginxの設定ファイルで自分は「@mobile」という文字列をキーに追加してスマートフォンかどうかを判定していたので、紹介されていたコードの部分を「@mobile」に変更しました(実は、「://」の追加も、このコードを見てよさそうだな、と思いました)。

実は、先ほど紹介した公式サイトに載っているフック nginxchampuru_get_reverse_proxy_key では、一つのキーを複数のキーに複製する(数を増やす)ことはできません。というわけで、このnginxchampuru_get_cacheフィルタを使っているようでした。

結果

この設定の結果、Nginx Cache Controllerが上手く記事を更新した際に、PC用キャッシュとスマートフォン用のキャッシュの両方を削除してくれるようになりました

資料的メモ

以下、資料としてまとまりのないメモ書きを置いておきます。

Nginx Proxy Cache Purge を使わなかった理由

Nginx Cache Controllerを使っていて上手くいかず、「さくらVPSとnginxリバースプロクシで最速WordPressブログを作る方法(ベンチマーク付き) | さくらたんどっとびーず」を参考に「Nginx Proxy Cache Purge」プラグインを導入しようとしたのですが、これはnginxの「Cache Purge Plugin」がnginxに導入されていなければ動作しない仕組み(特定のURLにアクセスすると、キャッシュがクリアされる仕組みが必要)だったので、一端回避してしまいました(設定しても、再起動時にunknown directive "proxy_cache_purge" というエラーになってしまう←というかこれでプラグインが必要だと気が付いた)。その後、Nginx Cache Controllerで上手く動いたので、めでたしめでたし、ということで、Nginx Proxy Cache Purgeプラグインは使いませんでした。

キャッシュキー設定の違い

私の設定ファイルでは、キャッシュキーの設定が「$scheme://$proxy_host$uri$is_args$args$mobile」で、Nginx Cache Controllerでは「$scheme://$host$request_uri$mobile」相当になっていました。

これで上手く動作しているとすれば、「$proxy_host」と「$host」、「$uri$is_args$args」と「$request_url」がそれぞれ同じものを指していることになるのですが、いまのところ詳しく調べてはいません。ちなみに、記事を更新した際は、その記事のURLはもちろん、「?test=test」のようなダミーのパラメータをつけたページのキャッシュも削除されているようでした。

また、もっとちゃんと動きそうな「$scheme://$proxy_host$request_uri$mobile」や「http://did2memo.net$request_uri$mobile」ではさっぱりキャッシュ削除機能が動きませんでした。

なにかトラブルが起こったら、このあたりをもっと詳しく調査する必要がありそうです。

Nginx Cache Controller の設定画面の選択肢の意味

「表示中のページと単独投稿記事と単独固定ページ以外のキャッシュを削除」の日本語的な意味が分からなかったので、メモ。

「自動削除のフック」には、4つの選択肢があります。これらには、関連する次の用語が割り当てられていました。

  • none:「なし」→None
  • all:「すべてのキャッシュを削除。」→Flush All Caches.
  • almost:「表示中のページと単独投稿記事と単独固定ページ以外のキャッシュを削除。」→Flush all caches except the ones of the current page and single post / page.
  • single:「現在のページのキャッシュを削除」→Flush current page only.

「almost」と「single」という用語から、「表示中のページと単独投稿記事と単独固定ページ以外のキャッシュを削除」は、「『表示中のページ』と『単独投稿記事と単独固定ページ』以外のキャッシュを削除」という意味になりそうです。

より詳しくは、「nginx-champuru/nginx-champuru.php」の「flush_cache()」を見ると分かりやすいです。

「すべてのキャッシュを削除」が無難?

今回いくつか設定しましたが、「すべてのキャッシュを削除」が無難で、そうするとkeyの設定なんてあまり意味なく削除されるんじゃないか、と思いますが、実はkeyの設定をちゃんとしておかないと、削除できないようです(すべてのキャッシュを削除だけ例外的にキャッシュディレクトリの中身を削除するのではなく、あくまでキャッシュを一つずつ削除するらしい。

なので、例えば「/sitemap.xml」のような、記事でも固定ページでもトップページでも無い場合、フックが起動されても、削除されないようなので、気を付けてください。

コメント(0)

新しいコメントを投稿