WordPress高速化: nginxのプロキシ・キャッシュ

Tablet PC deals and Promotion
ハイウェイ

前回はWordPressにWP Super Cacheプラグインを入れることによりパフォーマンスを劇的に向上させることに成功しました。

もうこれでよいかという気になってきましたが、もう一押しということでnginxのプロキシ・キャッシュ機能を使ってみることにしました。

参考文献

検索するといろいろ情報が出てきますが下記のWebページが参考になります。みんなやり方が微妙に違うので、内容を理解しつつ自分の環境にあわせるしかありません。

プロキシ・キャッシュの設定

共通の設定

複数のWordPressサイトがある場合(マルチサイトの場合)にも共通すると思われるものを抽出して、設定ファイルにしておきます。

まずはproxy_set_headerの設定を/etc/nginx/proxy_paramに記載します

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;

次にWordPress用のプロキシキャッシュの設定を/etc/nginx/globa/wordpress-proxy-cache.confに記載します。

location ~ /\. {deny all; access_log off; log_not_found off; }
location = /xmlrpc.php {deny all; access_log off; log_not_found off; }
location = /robots.txt  { access_log off; log_not_found off; }
location = /favicon.ico { access_log off; log_not_found off; }
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
log_not_found off;
proxy_pass http://unix:/var/lib/nginx/proxy.sock;
}

set $do_not_cache 0;
if ($uri ~* "\.php") {
set $do_not_cache 1;
}

set $proxy_cache_key "$scheme$proxy_host$request_uri";
if ($http_user_agent ~* "iPhone") {
#       set $do_not_cache 1;
set $proxy_cache_key "iphone::$proxy_cache_key";
}

if ($http_cookie ~ "(wordpress_logged_in_|comment_author_)(.*)") {
#       set $do_not_cache 1;
set $proxy_cache_key "$2::$proxy_cache_key";
}

location / {
proxy_no_cache $do_not_cache;
proxy_cache_bypass $do_not_cache;
proxy_cache_key $proxy_cache_key;
proxy_pass http://unix:/var/lib/nginx/proxy.sock;
}

個別のWordPressサイトの設定

ここのサイトの設定は/etc/nginx/sites-availableに作成します。このサイトの場合はscratchpad-blogとして次のような内容としています。

root /www/scratchpad.jp;
index index.php;

# for proxy cache
proxy_cache_path  /var/cache/nginx/scratchpad.jp levels=1 keys_zone=scratchpad.jp:128m;
proxy_cache scratchpad.jp;
proxy_cache_valid 200 404 60m;
include proxy_params;

# for frontend
server {
listen 80;
server_name scratchpad.jp;
error_log  /var/log/nginx/scratchpad-front-error.log warn;
access_log /var/log/nginx/scratchpad-front-access.log;

include global/wordpress-proxy-cache.conf;
}

# for backend
server {
listen unix:/var/lib/nginx/proxy.sock;
server_name scratchpad.jp;
try_files $uri $uri/ /index.php;

error_log  /var/log/nginx/scratchpad-back-error.log warn;
access_log /var/log/nginx/scratchpad-back-access.log;

include global/restrictions.conf;

# Additional rules go here.
rewrite_log off;

# Only include one of the files below.
#       include global/wordpress.conf;
include global/wordpress-ms.conf;
}

5~8行目はこのWordPressサイトのキャッシュの設定です。キャッシュファイルは/var/cache/nginx/scratchpad.jp以下に作られるようにしています。

11行目からのserverブロックで、scratchpad.jpへのアクセスを受け付け、wordpress-proxy-cache.confにしたがた処理をします。

キャッシュ対象外のファイルであった場合は、unixドメインソケット(unix:/var/lib/nginx/proxy.sock)を介して21行目以降のserverブロックに転送されます。

21行目からのserverブロックでは通常通りのWordPressの処理を行います。

プロキシキャッシュの有効化

ちょっとだけ準備が必要です。キャッシュ用のディレクトリを作成する必要があります。

sudo mkdir -p /var/cache/nginx
sudo chown www-data.www-data /var/cache/nginx

あとは設定ファイルを確認した後、問題がなければ設定ファイルをnginxに読み込ませます。

sudo nginx -t
sudo /etc/init.d/nginx reload

これでプロキシキャッシュが有効になった状態でWordPressが動作します。

付録

上記の設定ファイルから参照している設定ファイルを記載しておきます

  • /etc/nginx/conf.d/php-fpm.conf
        upstream php {
        server unix:/var/lib/php5/php-fpm.sock;
        }
  • /etc/nginx/global/restrictions.conf
        # Global restrictions configuration file.
        # Designed to be included in any server {} block.
    
        # Only allow these request methods
        # Do not accept DELETE, SEARCH and other methods
        if ($request_method !~ ^(GET|HEAD|POST)$ ) {
        return 444;
        }
    
        location = /favicon.ico {
        log_not_found off;
        access_log off;
        }
    
        location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
        }
    
        # Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac).
        # Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban)
        location ~ /\. {
        deny all;
        #       access_log off;
        #       log_not_found off;
        }
    
        # Deny access to any files with a .php extension in the uploads directory
        # Works in sub-directory installs and also in multisite network
        # Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban)
        location ~* /(?:uploads|files)/.*\.php$ {
        deny all;
        }
    
        # http://www.cyberciti.biz/tips/linux-unix-bsd-nginx-webserver-security.html
        ## Start: Size Limits & Buffer Overflows ##
        client_body_buffer_size  1K;
        client_header_buffer_size 1k;
        client_max_body_size 25M;
        large_client_header_buffers 2 1k;
        ## END: Size Limits & Buffer Overflows ##
    
        ## Deny certain Referers ###
        if ( $http_referer ~* (babes|forsale|girl|jewelry|love|nudit|organic|poker|porn|sex|teen) )
        {
        return 403;
        }
        
  • /etc/nginx/global/wordpress-ms.conf
        # WordPress multisite subdirectory/domain rules.
        # Designed to be included in any server {} block.
    
        # This order might seem weird - this is attempted to match last if rules below fail.
        # http://wiki.nginx.org/HttpCoreModule
        location / {
        index index.php;
        try_files $uri $uri/ /index.php?$args;
        }
    
        # Directives to send expires headers and turn off 404 error logging.
        location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
        expires 24h;
        log_not_found off;
        }
    
        location ~ ^/[_0-9a-zA-Z-]+/files/(.*)$ {
        try_files /wp-content/blogs.dir/$host/files/$2 /wp-includes/ms-files.php?file=$2 ;
        access_log off; log_not_found off; expires max;
        }
    
        #avoid php readfile()
        location ^~ /blogs.dir {
        internal;
        alias /var/lib/wordpress/blogs.dir/$host ;
        access_log off; log_not_found off;      expires max;
        }
    
        # Pass uploaded files to wp-includes/ms-files.php.
        rewrite /files/$ /index.php last;
    
        # For multisite:  Use a caching plugin that creates symlinks to the correct subdirectory structure to get some performance gains.
        set $cachetest "$document_root/wp-content/cache/ms-filemap/${host}${uri}";
        if ($uri ~ /$) {
        set $cachetest "";
        }
        if (-f $cachetest) {
        # Rewrites the URI and stops rewrite processing so it doesn't start over and attempt to pass it to the next rule.
        rewrite ^ /wp-content/cache/ms-filemap/${host}${uri} break;
        }
    
        if ($uri !~ wp-content/plugins) {
        rewrite /files/(.+)$ /wp-includes/ms-files.php?file=$1 last;
        }
    
        # Uncomment one of the lines below for the appropriate caching plugin (if used).
        include global/wordpress-ms-wp-super-cache.conf;
        #include global/wordpress-ms-w3-total-cache.conf;
    
        # Rewrite multisite '.../wp-.*' and '.../*.php'.
        if (!-e $request_filename) {
        rewrite /wp-admin$ $scheme://$host$uri/ permanent;
        rewrite ^/[_0-9a-zA-Z-]+(/wp-.*) $1 last;
        rewrite ^/[_0-9a-zA-Z-]+(/.*\.php)$ $1 last;
        }
    
        # Rewrite multisite /uploads/ -> /www/uploads/$host
        rewrite ^/uploads/(.*)$   /wp-content/blogs.dir/$host/$1;
        rewrite ^/(.*)(favicon.ico$) /wp-content/blogs.dir/$host/favicon.ico;
        rewrite ^/sitemap.xml$       /wp-content/blogs.dir/$host/sitemap.xml;
        rewrite ^/BingSiteAuth.xml$  /wp-content/blogs.dir/$host/BingSiteAuth.xml;
    
        # Pass all .php files onto a php-fpm/php-fcgi server.
        location ~ \.php$ {
        # Zero-day exploit defense.
        # http://forum.nginx.org/read.php?2,88845,page=3
        # Won't work properly (404 error) if the file is not stored on this server, which is entirely possible with php-fpm/php-fcgi.
        # Comment the 'try_files' line out if you set up php-fpm/php-fcgi on another machine.  And then cross your fingers that you won't get hacked.
        try_files $uri =404;
    
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        #NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
    
        include fastcgi_params;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        #       fastcgi_intercept_errors on;
        fastcgi_pass php;
        }
        
  • /etc/nginx/global/wordpress-ms-wp-super-cache.conf
        # WP Super Cache rules.
        # Designed to be included from a 'wordpress-ms-...' configuration file.
    
        # Enable detection of the .gz extension for statically compressed content.
        # Comment out this line if static gzip support is not compiled into nginx.
        gzip_static on;
    
        set $supercacheuri "";
        set $supercachefile "$document_root/wp-content/cache/supercache/${http_host}${uri}index.html";
        if (-e $supercachefile) {
        set $supercacheuri "/wp-content/cache/supercache/${http_host}${uri}index.html";
        }
    
        # If this is a POST request, pass the request onto WordPress.
        if ($request_method = POST) {
        set $supercacheuri "";
        }
    
        # If there is a query string, serve the uncached version.
        if ($query_string) {
        set $supercacheuri "";
        }
    
        # Logged in users and those who have posted a comment get the non-cached version.
        if ($http_cookie ~* comment_author_|wordpress_logged_in|wp-postpass_) {
        set $supercacheuri "";
        }
    
        # Mobile browsers get the non-cached version.
        # Wastes CPU cycles if there isn't a mobile browser WP theme for the site.
        if ($http_x_wap_profile) {
        set $supercacheuri "";
        }
    
        if ($http_profile) {
        set $supercacheuri "";
        }
    
        if ($http_user_agent ~* (2.0\ MMP|240x320|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 $supercacheuri "";
        }
    
        if ($http_user_agent ~* (w3c\ |w3c-|acs-|alav|alca|amoi|audi|avan|benq|bird|blac|blaz|brew|cell|cldc|cmd-|dang|doco|eric|hipt|htc_|inno|ipaq|ipod|jigs|kddi|keji|leno|lg-c|lg-d|lg-g|lge-|lg/u|maui|maxo|midp|mits|mmef|mobi|mot-|moto|mwbp|nec-|newt|noki|palm|pana|pant|phil|play|port|prox|qwap|sage|sams|sany|sch-|sec-|send|seri|sgh-|shar|sie-|siem|smal|smar|sony|sph-|symb|t-mo|teli|tim-|tosh|tsm-|upg1|upsi|vk-v|voda|wap-|wapa|wapi|wapp|wapr|webc|winw|winw|xda\ |xda-)) {
        set $supercacheuri "";
        }
    
        # Stop processing if the supercache file is valid.
        if ($supercacheuri) {
        rewrite ^ $supercacheuri break;
        }
        

まとめ

今回はnginxのプロキシキャッシュ機能を使ってさらなるWordPressの高速化にチャレンジしてみました。

何度か設定にミスってサイトが見れなくなったりしましたが、ようやくちゃんと動くようになりました。

次回はプロキシキャッシュの効果を見てみたいと思います。