最近、め組ことデジタルキューブさんと、一緒に仕事をやらせてもらってます。
今の所は、主に WordPress サイトの高速化とかやってるんですけど、その中で WordPress サイトを複数台のサーバで負荷分散させて高速化させる案件があったので、その時の作業内容をシェア。
最近はさくらの VPS とか、低価格の VPS が出てきてるので、個人でも手を出せる領域かもしれませんね。
今回は2台のサーバを使って PHP の処理を負荷分散しました。
構成は、こんな感じです。
- プライマリサーバ ( vps1.example.com : 192.168.0.1 )
- Nginx, Load Balancer、PHP FastCGI のアプリケーションサーバ
- lsyncd (リアルタイム rsync を実現するためのサービス)
- セカンダリサーバ ( vps2.example.com : 192.168.0.2 )
- Nginx, PHP FastCGI のアプリケーションサーバ
- MySQL
- rsyncd
※ 説明のため IP アドレスはローカルアドレスに設定していますが、実際にはグローバルアドレスを使用しています。
ブラウザからの要求は、すべてプライマリサーバ ( vps1.example.com ) が受け取り、PHP の処理を二台のサーバに分散させます。
もちろん、処理が重くなってきたら、3台目、4台目… と追加していくことが可能です。
実際に行った作業のメモ。
lsyncd の設定
WordPress フォルダのファイルはプライマリサーバで管理し、何か変更があった場合に lsyncd を通じて、セカンダリサーバに配信されます。
配信元のプライマリサーバ側では lsyncd を、配信先のセカンダリサーバ側では rsyncd を、それぞれ作動させます。
配信元プライマリサーバ ( 192.168.0.1 ) の /var/www/html のファイル/ディレクトリを、配信先セカンダリサーバ ( 192.168.0.2 ) の /var/www/html 以下にコピーする設定です。
配信先、セカンダリサーバの設定
rsync, xinetd がインストールされていない場合は yum でインストールしておきます。
$ sudo yum -y install rsync xinetd
rsyncd.conf の設定
$ sudo vi /etc/rsyncd.conf log file = /var/log/rsyncd.log ← ログファイル [site] ← 任意の名前 path = /var/www/html ← コピー先対象ディレクトリ hosts allow = 192.168.0.1 ← コピーを許可するホスト(配信元プライマリサーバを指定) hosts deny = * list = true uid = root gid = root read only = false
xinetd, rsync 起動
$ sudo /sbin/service xinetd start $ sudo /sbin/chkconfig xinetd on $ sudo /sbin/chkconfig rsync on
iptables でポートを閉じている場合は、配信元プライマリサーバ ( 192.168.0.1 ) から 873 番ポートが接続できるようにしておいてください。
$ sudo vi /etc/sysconfig/iptables : -A RH-Firewall-1-INPUT -s 192.168.0.1 -m state --state NEW -m tcp -p tcp --dport 873 -j ACCEPT $ sudo /sbin/service iptables restart
via. CentOS 5 – rsyncによるファイル/ディレクトリの同期 : Server World
配信元、プライマリサーバの設定
CentOS の場合は yum でインストールしちゃいましょう。rpmforge レポジトリにあります。
$ sudo yum -y install --enablerepo=rpmforge lsyncd
続いて、起動オプションファイルの修正
$ sudo vi /etc/sysconfig/lsyncd IGNORE_START_ERRORS="--stubborn"
lsyncd.conf の設定
$ sudo cp /usr/share/doc/lsyncd/lrsync.lua /etc/lsyncd.conf $ sudo vi /etc/lsyncd.conf ---- -- User configuration file for lsyncd. -- -- Simple example for default rsync. -- settings = { statusFile = "/tmp/lsyncd.stat", statusInterval = 1, logfile = "/var/log/lsyncd.log", ← ログファイル } sync{ default.rsync, source="/var/www/html/", ← 配信元ディレクトリ target="192.168.0.2::site", ← 配信先サーバ rsyncOps="-az", ← rsync オプション excludeFrom="/etc/rsync_exclude.lst", ← 配信除外フォルダのリスト }
17行目は、配信先セカンダリサーバのIPアドレスと、rsyncd.conf で設定した名前を記入してください。
配信除外フォルダの指定、WP Super Cache プラグインが使用する /wp-content/cache フォルダや、DB Cache Reloaded fix プラグインが使用する /wp-content/tmp/ は、配信除外フォルダとして設定しておきましょう。
$ sudo vi /etc/rsync_exclude.lst - /wp-content/cache/** - /wp-content/tmp/**
lsyncd 起動
$ sudo /sbin/service lsyncd start $ sudo /sbin/chkconfig lsyncd on
これで配信先サーバにファイルがコピーされていれば、おっけです。
via. CentOS 5 – lsyncによるリアルタイムミラーリング : Server World
MySQL サーバの設定
今回 MySQL サーバは、セカンダリサーバ( 192.168.0.2 ) に設置します。
iptables でポートを閉じている場合は、配信元プライマリサーバ ( 192.168.0.1 ) から 3306 番ポートが接続できるようにしておいてください。
$ sudo vi /etc/sysconfig/iptables : -A RH-Firewall-1-INPUT -s 192.168.0.1 -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT -A RH-Firewall-1-INPUT -s 192.168.0.2 -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT $ sudo /sbin/service iptables restart
続いて、ユーザがリモートサーバから接続できるように権限を付与しておきましょう。
WordPress ユーザは wordpress パスワードは password だとすると、こんな感じです。
$ mysql -u root -p mysql mysql> grant all privileges on *.* to wordpress @"192.168.0.1" identified by 'password ' with grant option ; mysql> grant all privileges on *.* to wordpress @"vps1.example.com" identified by 'password ' with grant option ; mysql> grant all privileges on *.* to wordpress @"192.168.0.2" identified by 'password ' with grant option ; mysql> grant all privileges on *.* to wordpress @"vps2.example.com" identified by 'password ' with grant option ; mysql> quit;
wp-config.php の DB_HOST の修正も忘れずに行ってください。
セカンダリサーバの IP アドレス、またはサーバ名を指定してください。
localhost のままにしていると、プライマリサーバに処理が振り分けられた場合、MySQL サーバに接続できなくなってしまいます。
mysql サーバをレプリケーションさせると、さらに面白いですね。
余裕のある人は、挑戦してみてください。
Nginx の設定
Nginx で2台のサーバで処理を分散するように設定します。
Nginx の基本的な設定方法は、以下を参照してみてください。
WordPress サイトに nginx を導入する : dogmap.jp
配信先、セカンダリサーバの設定
nginx.conf を修正してプライマリサーバから処理を受け取るように設定しましょう。
$ sudo vi /etc/nginx.conf : server { listen 8000; server_name vps1.example.com; access_log /var/log/nginx/$host.access.log main_x; location ~ /\.ht { deny all; } location / { root /var/www/html; index index.php index.html index.htm; if (-f $request_filename) { expires 30d; break; } if (!-e $request_filename) { rewrite ^(.+)$ /index.php?q=$1 last; } } location ~ \.php$ { root /var/www/html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /var/www/html/$fastcgi_script_name; #fastcgi_param HTTPS on; include fastcgi_params; } } :
設定を反映させるため Nginx を再起動します。
$ sudo /sbin/service nginx restart
iptables でポートを閉じている場合は、プライマリサーバ ( 192.168.0.1 ) から 8000 番ポートが接続できるようにしておいてください。
$ sudo vi /etc/sysconfig/iptables : -A RH-Firewall-1-INPUT -s 192.168.0.1 -m state --state NEW -m tcp -p tcp --dport 8000 -j ACCEPT $ sudo /sbin/service iptables restart
配信元、プライマリサーバの設定
nginx.conf を修正して2台のサーバに処理を振り分けるように設定しましょう。
$ sudo vi /etc/nginx.conf : upstream backend { ip_hash; server 127.0.0.1:8000; server 192.168.0.2:8000; } upstream admin { ip_hash; server 127.0.0.1:8000; } server { listen 8000; server_name vps1.example.com; access_log /var/log/nginx/$host.access.log main_x; location ~ /\.ht { deny all; } location / { root /var/www/html; index index.php index.html index.htm; if (-f $request_filename) { expires 30d; break; } if (!-e $request_filename) { rewrite ^(.+)$ /index.php?q=$1 last; } } location ~ \.php$ { root /var/www/html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /var/www/html/$fastcgi_script_name; #fastcgi_param HTTPS on; include fastcgi_params; } } server { listen 80; server_name vps1.example.com; access_log /var/log/nginx/$host.access.log main; location /wp-admin { proxy_pass http://admin; } location /wp-includes { proxy_pass http://admin; } location /wp-login.php { proxy_pass http://admin; } location /feed { proxy_pass http://backend; } location ~ .*\.php { proxy_pass http://backend; } location ~ .*\.sql { deny all; } location ~ /\.ht { deny all; } location ~ .*\.(txt|xml|html?|js|css|gz|ico|jpe?g|gif|png|wmv|flv|swf|mpg) { root /var/www/html; index index.html index.htm; if (-f $request_filename) { access_log off; ssi on; expires 30d; break; } } location / { root /var/www/html; index index.php index.html index.htm; if ($http_cookie ~* "comment_author_[^=]*=([^%]+)%7C|wordpress_logged_in_[^=]*=([^%]+)%7C") { proxy_pass http://admin; break; } proxy_pass http://backend; } :
5,6 行目で、2台のサーバをバックエンドとして使用するように設定しています。
ちゃんと処理がラウンドロビンされているかを確認するには Nginx のログを確認してみてください。
45〜47, 65〜68行目ではログインした場合は、必ずプライマリサーバに接続するように設定しています。
こうしておかないと、メディアアップロードした時とかセカンダリサーバにファイルがアップロードされてしまう可能性があるので、注意が必要です。
後は Nginx を再起動すれば、ロードバランスされるようになります。
$ sudo /sbin/service nginx restart
今回の設定ファイルの中には Proxy Cache の設定は含んでいませんが、実際のサイトでは Proxy Cache も有効にしています。
ピンバック: #Wordpress でHyperDBを使ったときの運用の疑問 | 5丁目通信(仮称)
ピンバック: 活動ログ 2011/07/19 « Lifelog « Laddy in