Nginx の Proxy Cache を PC と Mobile 端末で振り分ける

本記事は最終更新日より 1 年以上経過しております。
スポンサーリンク

 最初に安定動作までこぎ着けた設定では、Mobile 端末に関しては User-Agent を見てキャッシュしない方向となっていたが、折角だからできる限りキャッシュをしてあげようと思ったので、ちょいちょい弄ってみた。
 Nginx では極力 if 文を使わない方がよろしいそうなので、User-Agent による振り分けを map ディレクティブに書き換えたりしたけど、結局 WordPress 周りの処理で if 文を使わざるを得ない様な事になったりもした。

設定の変更点

 前回のおさらいというか、キャッシュを行う部分の設定を抜粋する。

    location / {
        set $do_not_cache "";
        if ($http_user_agent ~* '(DoCoMo|UP.Browser|SoftBank|WILLCOM|emobile|iPhone|iPod|Android.*Mobile)') {
            set $do_not_cache 1;
        }
 
        proxy_pass         http://backend;
        proxy_cache        cache;
        proxy_no_cache     $do_not_cache;
        proxy_cache_bypass $do_not_cache;
        proxy_cache_key    $scheme$proxy_host$uri$request_uri$is_args$args;
        proxy_set_header Host                   $host;
        proxy_set_header X-Real-IP              $remote_addr;
        proxy_set_header X-Remote-Addr          $remote_addr;
        proxy_set_header X-Forwarded-Proto      https;
        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_cache_valid 200 1d;
    }

 if 文で User-Agent を見て正規表現にマッチしたら $do_not_cache に 1 をセットする手法。この $do_not_cache って変数名はどのサイトを参考にしても同じ名前だから、Nginx 固有の変数かと思ったらそうでも無いようで。なので好きなように変える事にした。

 これを map ディレクティブで書き換えると次の様になる。

# 0 = PC, 1 = Mobile, 2 = Ktai
map $http_user_agent $is_mobile {
    default 0;
    ~*iPhone          1;
    ~*iPad            1;
    ~*iPod            1;
    ~*Android         1;
    ~*Windows.*Phone  1;
    ~*BlackBerry      1;
    ~*Opera\ Mini     1;
    ~*PlayBook        1;
    ~*Mobile.*Firefox 1;
    ~*DoCoMo          2;
    ~*UP.Browser      2;
    ~*Softbank        2;
    ~*WILLCOM         2;
    ~*emobile         2;
    ~*J-PHONE         2;
    ~*MOT-            2;
}

server {
...
(中略
...
# Cache flags.
    set $do_not_cache 0;
    if ( $request_method != "GET" ) {
        set $do_not_cache 1;
    }
    if ( $http_cookie ~ ^.*(comment_author_|wordpress_logged_in|wp-postpass_).*$ ) {
        set $do_not_cache 1;
    }

    location / {
        proxy_pass         http://backend;
        proxy_cache        cache;
        proxy_no_cache     $do_not_cache;
        proxy_cache_bypass $do_not_cache;
        proxy_cache_key    $is_mobile$scheme$proxy_host$uri$request_uri$is_args$args;
        proxy_set_header   Host                   $host;
        proxy_set_header   X-Real-IP              $remote_addr;
        proxy_set_header   X-Remote-Addr          $remote_addr;
        proxy_set_header   X-Forwarded-Proto      https;
        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_cache_valid  200 1d;
    }
}

 map ディレクティブにて $http_user_agent にマップされた値を $is_mobile に格納する。$is_mobile が 0 なら PC と判断、1 なら Mobile 端末2 ならガラケーと振り分ける。WPtouch を使用しているなら、最低でも WPtouch で Mobile 端末として認識される User-Agent は追加しておかないとキャッシュが混ざってヤバいので注意。
 proxy_cache_key ディレクティブのパラメータの先頭か末尾にでも $is_mobile を付加すればキャッシュキーが変わるのでキャッシュ内容がコンフリクトする事も無くなる。
 GET メソッド以外はキャッシュしないだとか、コメント中、ログイン中、保護記事のキャッシュをしない設定もあるが「【nginx】WordPress でキャッシュしてはいけないページ(ファイル、ディレクトリ)設定!!! – oki2a24」を参考にさせて頂いた。

おわりに

 これで Nginx の WordPress 向けチューニングが進んだ感じがする。今では Mobile 端末からのアクセスも重要度の高い物になってきているから疎かにするわけにも行かない。
 実際、スマホからのアクセスをしてみるとアクセス時やリロード時のレスポンスが体感可能な位に早くなった。
 暫くはキャッシュに起因する不具合が起きないか長期的に様子を見ていこう。

 今後のチューニングネタも探しておかないとかな。

スポンサーリンク