WordPress サイトにリバースプロキシサーバとして nginx を導入する際の tips。
nginx (エンジンエックス)とは、オープンソースの軽量高性能なHTTPサーバ且つリバースプロキシです。
従来の HTTP サーバのようにリクエストの処理をスレッドで行わず、非同期のアーキテクチャーを用いるイベントループモデルのサーバです、
そのため、多数のリクエストが着た場合に実行スタックをコピーする必要があるスレッドモデルのサーバと違い、1プロセスでリクエストを処理できるため、メモリ消費量が極端に少なくてすむという利点があります。
# 話題の node.js もイベントループモデルですね。
さて、そんな nginx を WordPress サイトに導入する際の tips です。
CentOS, RHEL に最新の nginx をインストールする
CentOS, RHEL に nginx をインストールしたい場合、EPEL リポジトリを有効にすることで yum からインストールすることができます。
ただし EPEL からインストールされる nginx は Ver.0.6 と、ちょっと古いです。
試してみたところ Ver.0.6 では proxy_cache が使えなかったため、最新の 0.8.5x (stable version) または 0.9.x (development version) をインストールしておきたいところです。
そこで、以下の手順で最新の nginx ソースを使って rpmbuild しました。
作業したサーバは RHEL4
# wget http://ftp.iij.ad.jp/pub/linux/fedora/epel/4/SRPMS/nginx-0.6.39-5.el4.src.rpm # rpm -i nginx-0.6.39-5.el5.src.rpm # cd /usr/src/redhat/SOURCES # wget http://nginx.org/download/nginx-0.9.4.tar.gz # cd ../SPECS/
続いて、nginx.spec を修正。
# vi nginx.spec %define _unpackaged_files_terminate_build 0 <- 追加 : Version: 0.9.4 : #Patch0: nginx-auto-cc-gcc.patch <- コメントアウト #Patch1: nginx-cve-2009-3555.patch <- コメントアウト : #%patch0 -p0 <- コメントアウト #%patch1 -p0 <- コメントアウト : %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}[/text] rpmbuild して、インストールする。 [text]# rpmbuild -ba nginx.spec # rpm -Uvh /usr/src/redhat/RPMS/i386/nginx-0.9.4-4.i386.rpm[/text] <cite>via. <a href="http://d.hatena.ne.jp/kopug/20100918/1284817454" title="CentOS5.5 x86_64 で 最新のnginx を rpmbuildする - 名古屋で働くWebプログラマの覚書">CentOS5.5 x86_64 で 最新のnginx を rpmbuildする - 名古屋で働くWebプログラマの覚書</a></cite> <h3>gzip 圧縮転送設定</h3> CSS, JavaScript, html などのテキストファイルを gzip 圧縮転送するように設定する方法。 gzip 圧縮転送する対象を MIME タイプで nginx.conf に以下のように設定しましょう。 [text] : http { : gzip on; gzip_http_version 1.0; gzip_vary on; gzip_comp_level 6; gzip_types text/html text/xml text/css application/xhtml+xml application/xml application/rss+xml application/atom_xml application/x-javascript application/x-httpd-php; gzip_disable "MSIE [1-6]\."; : }
MSIE 6.0 に対する gzip 圧縮転送は、不安定らしいので IE6 に対しては gzip 圧縮転送しないようにしています。
# gzip_disable "MSIE [1-6]\.";
という箇所
via. IE6ではgzip圧縮されたJavaScriptが、実行されたりされなかったりする? – 水の森ノート
PHP の出力結果は MIME 形式としては text/html 等になるため、php.ini で zlib.output_compression を on にしておかなくても gzip 圧縮転送されます。
expires ヘッダを追加する
expires ヘッダを追加して、送信するには expires xxd
と書くだけでおっけです。
: http { : server { listen 80; server_name example.com; # static files location ~ .*\.(txt|xml|html?|jpe?g|JPE?G|gif|GIF|png|PNG|swf|SWF|wmv|WMV|flv|FLV|css|CSS|js|JS|inc|ico|gz) { root /var/www/html; index index.html; expires 14d; break; } : } : }
これで、有効期限14日の expired ヘッダが出力されるようになります。
nginx + fastCGI で WordPress を動作させる
まずは spawn-fcgi のインストール
# yum install spawn-fcgi
続いて php fcgi 動作用のスクリプトを作成。
/etc/rc.d/init.d/php-fastcgi という名前で、こんな感じのスクリプトを作りましょう。
#!/bin/sh # # spawn-fcgi Start and stop FastCGI processes # # chkconfig: - 80 20 # description: Spawn FastCGI scripts to be used by web servers # Source function library. . /etc/rc.d/init.d/functions RETVAL=0 SPAWNFCGI="/usr/bin/spawn-fcgi" PHPFCGI="/usr/bin/php-cgi" FCGIPORT="9000" FCGIADDR="127.0.0.1" PHP_FCGI_CHILDREN=5 PHP_FCGI_MAX_REQUESTS=1000 ALLOWED_ENV="PATH USER" USER=nginx GROUP=nginx PIDFILE=/var/run/phpfcgi.pid ALLOWED_ENV="$ALLOWED_ENV PHP_FCGI_CHILDREN PHP_FCGI_MAX_REQUESTS FCGI_WEB_SERVER_ADDRS" case "$1" in start) PHPFCGI_START=$"Starting ${NAME} service: " echo -n $PHPFCGI_START # clean environment E= for i in $ALLOWED_ENV; do E="$E $i=${!i}"; done daemon $SPAWNFCGI -a ${FCGIADDR} -p ${FCGIPORT} -u ${USER} -g ${GROUP} -P ${PIDFILE} -C ${PHP_FCGI_CHILDREN} -f ${PHPFCGI} RETVAL=$? ;; stop) echo -n "Stopping php-fcgi: " killproc -p $PIDFILE phpfcgi echo RETVAL=$? ;; *) echo "Usage: $0 {start|stop}" exit 1 esac exit $RETVAL
サービスを登録して、起動しておきます。
# chmod a+x /etc/rc.d/init.d/php-fastcgi # chkconfig --add php-fastcgi # chkconfig php-fastcgi on # service php-fastcgi start
nginx.cnf には、こんな感じで登録しておけば良いはずです。
: http { : server { : listen 80; server_name example.com; access_log /var/log/nginx/example.com.access.log main; location / { root /var/www/html; index index.php index.html index.htm; # static files if (-f $request_filename) { expires 14d; break; } # request to index.php if (!-e $request_filename) { rewrite ^(.+)$ /index.php?q=$1 last; } } # # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 location ~ \.php$ { root html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /var/www/html/$fastcgi_script_name; include fastcgi_params; } } : }
via. WordPress on nginx with FastCGIのCentOSの場合 – stnard.jp
proxy cache を有効にする
proxy cache を有効にして WordPress の出力をキャッシュしちゃいましょう。
まずは、直前の設定(nginx + fastCGI で WordPress を動作させる)で listen 80;
と設定して80番ポートを見ていた所を listen 8080;
に修正して、Web サーバが8080番ポートでリクエストを待つように修正しておきましょう。
代わりにリバースプロキシサーバとして動作する nginx が80番ポートでリクエストを待ちます。
: http { : proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=czone:4m max_size=50m 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 X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; : upstream backend { ip_hash; server 127.0.0.1:8080; } : server { listen 80; server_name example.com; location /wp-admin { proxy_pass http://backend; } location ~ .*\.php { proxy_pass http://backend; } location / { set $mobile ""; if ($http_user_agent ~* '(DoCoMo|J-PHONE|Vodafone|MOT-|UP\.Browser|DDIPOCKET|ASTEL|PDXGW|Palmscape|Xiino|sharp pda browser|Windows CE|L-mode|WILLCOM|SoftBank|Semulator|Vemulator|J-EMULATOR|emobile|mixi-mobile-converter)') { set $mobile "@ktai"; } if ($http_user_agent ~* '(iPhone|iPod|Opera Mini|Android.*Mobile|NetFront|PSP|BlackBerry)') { set $mobile "@mobile"; } 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_cache czone; proxy_cache_key "$scheme://$host$request_uri$is_args$args$mobile"; proxy_cache_valid 200 301 302 10m; proxy_cache_valid 404 5m; proxy_pass http://backend; } } : }
この設定で、以下のような動作をするはずです。
- wp-admin 以下、または *.php と行ったファイルに対するアクセスは proxy cache せずにバックエンドのウェブサーバに直接リクエストを投げる
- UA を判断して、PC・ケータイ・スマートフォンからのアクセスは、別々にキャッシュする
- cookie を判断して、WordPress にログインしている場合は proxy cache せずにバックエンドのウェブサーバに直接リクエストを投げる
via. HsbtDiary(2010-04-27)
via. WordPressを100倍速くする! MySQLの調整やnginx proxy cache | KRAY Inc
また、バックエンドのサーバとして Apache を利用する場合、このままだと Apache のログには nginx が動作しているサーバのIPアドレスが記録されてしまいます。
mod_extract_forwarded とか mod_rpaf とかを使用して、あくせすログにクライアントのIPアドレスが記録されるようにしてあげましょう。
mod_extract_forwarded を使用する場合は mod_proxy も有効にしておいてあげないと、エラーが出るので注意が必要です。
via. reverse proxy 越しの IP アクセス制御 with mod_extract_forwarded 編 – にぽたん研究所
via. Apacheをnginxにリプレイスした | cloudrop
via. mod-rpaf
まとめ
とりあえず WordPress サイトに nginx を導入してみるための設定でした。
現在、このサイトを設置してあるサーバの構成は、右図のような感じです。
- クライアントからのリクエストを nginx が受ける
- 静的ファイルへのリクエストならば nginx が、そのまま返す
- 動的コンテンツへのリクエストならば proxy cache を通して、バックエンドの Apache サーバにリクエストを投げ、結果を返す
- PC・ケータイ・スマートフォンからのアクセスに応じて、それぞれ別のキャッシュを保持する
- WordPress にログインしている場合は proxy cache を通さず、直接バックエンドの Apache サーバから返す
もちろん、バックエンドのサーバは Apache + mod_php ではなく nginx + fastcgi でも構成できます。
メモリの最大量が少ない VPS で使用する場合は、バックエンドのサーバも nginx + fastcgi にしたほうが余裕を持って運用できるでしょう。
WordPress が遅いとか言ってる人は nginx とか Varnish とかのリバースプロキシを試したり、Apache に拘らずに nginx や lighttpd とかの高速軽量な Web サーバ+ fastcgi の環境を試してみれば良いと思うよ。
nginx は WordPress.com や WordPress.org でも採用されているので、大規模なサイトでも安心して使えるしね。
ピンバック: さくらVPS:Nginx + Apache 構成の設定方法 | ブレン
ピンバック: さくらの VPS に nginx を入れてリバースプロキシ設定するまでの作業メモ(検証用) | ウェブル
初めまして。WordPressとの連携時のキャッシュ設定周り、とても参考になりました。
設定内容について気付いたことがありますので、どうしたものか悩んだのですが失礼ながらコメントさせていただきます。
proxy_cache_keyについてなのですが、場合によっては閲覧対象と違うコンテンツのキャッシュを読みにいってしまう場合がありませんでしょうか。例えば下記のような場合です。
1.http://hogehoge.com/fugafugaとhttp://hogehoge.com/fugafuga2という2つのコンテンツを配置
2.fugafuga2にPCでアクセス → “…fugafuga2”のキーでキャッシュされる
3.キャッシュの有効期間内にiPhoneでfugafugaにアクセス → “…fugafuga”+“2”のキーが生成されるため、fugafuga2のキャッシュが返される
ですので、proxy_cache_keyとしては$request_uriと$mobileとの間に何か固定の記号等を挟んだ方が安全かも知れません。
突然のコメント失礼しました。
MorphMorph さん、はじめまして。
ですよねー。
なので、僕も最近は
みたいにして proxy_cache_key が、ユニークになるようにしてます。
ピンバック: nginxとWordPress – MorphMorph
ピンバック: Nginx + lsyncd で WordPress を負荷分散させる : dogmap.jp
ピンバック: ちょっとだけNGINXを « 12net.jp
ピンバック: 分からない人が書いたCentOSにnginxとfastcgiを入れてWordPressを動かすまでのメモなので、分からない人が読んだら分かりそうその2 - Shinichi Nishikawa's blog
ピンバック: ものすごく簡単に書いたCentOSにnginxとfastcgiを入れてWordPressを動かすまでのメモ - Shinichi Nishikawa's blog
ピンバック: WordPress サイトに nginx を導入する | WPPP - WordPress Powered Publishing
ピンバック: Tweets that mention WordPress サイトに nginx を導入する : dogmap.jp -- Topsy.com