最近、め組ことデジタルキューブさんと、一緒に仕事をやらせてもらってます。
今の所は、主に 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