我的Raspberry Pi工作了大约半年之后,文件系统开始出现莫名其妙的问题,各种文件都出现乱码,以至于某系统命令一执行就segment fault。到重新“安装”系统的时候了。
之前主要跑的服务是我的博客,nginx + wordpress搭的,在RPi上因为CPU的问题(php-fpm执行时几乎占满cpu),响应比较慢。既然重新弄了,考虑把某些请求交给家里的其它机器来处理。
家里还有一台跑Ubuntu的笔记本,希望满足如下要求:
1) 如果笔记本开机着,http请求(几乎)都交给笔记本处理;
2) 如果笔记本关机,http请求都由RPi来处理;
这些应该是完全自动实现的。
在Stackoverflow上问了这个问题,有人提示说可以通过nginx的load-balance功能来实现我的需求。于是开始google一番,找到了解决方案。
基本的思想是,把nginx配置成反向代理,笔记本和RPi都作为upstream来处理http请求;通过nfs共享同一个wordpress目录;配置mysql让wordpress访问同一个数据库。
一步一步来配置这些。
其中Raspberry Pi的地址固定为192.168.1.100,笔记本的地址固定为192.168.1.101,数据库名为minewpdb,数据库用户名为minedb
1. 配置Mysql
mysql仍然放在RPi上,让mysql接受网络的请求,这样不同的机器可以用同一个mysql数据库。
sudo vim /etc/mysql/my.cnf
==> 把 bind-address 改成RPi的ip地址
bind-address = 192.168.1.100
mysql -u root -p #登录mysql控制台
mysql> grant all on minewpdb.* to 'mineblog'@'192.168.1.100' identified by 'xxx'; # 本地RPi的wordpress访问
mysql> grant all on minewpdb.* to 'mineblog'@'192.168.1.101' identified by 'xxx'; # 笔记本的wordpress访问
mysql> quit;
sudo service mysql restart # 重启mysql服务
# 在RPi和笔记本上分别测试一下
mysql -u mineblog -h 192.168.1.100 -p # 如果能登录成功,就ok了
2. 配置wordpress
Wordpress仍然在RPi上,只要修改wordpress的config文件,把数据库的host,用户名和密码都设对就行了。
sudo vim /path/to/wordpress/wp-config.php
==> 修改DB_HOST等参数
define('DB_NAME', 'minewpdb');
define('DB_USER', 'mineblog');
define('DB_PASSWORD', 'xxx');
define('DB_HOST', '192.168.1.100');
3. 配置nfs
在RPi上设置nfs export,让笔记本mount它,这样可以保证跑的wordpress是同一份。
sudo vim /etc/exports
==> 添加wordpress目录到exports
/path/to/wordpress 192.168.1.101(rw,no_root_squash,insecure,sync,no_subtree_check)
sudo service rpcbind start # RPi的nfs依赖于rpcbind
sudo update-rc.d rpcbind enable # 设置rpcbind自动启动
sudo service nfs-kernel-server start # 重启nfs
在笔记本上,mount这个目录:
sudo mount -t nfs 192.168.1.100:/path/to/wordpress /path/to/wordpress
4. 配置nginx
在RPi上要把nginx配置成反向代理,upstream是RPi和笔记本,端口号都是8000,真正的wordpress运行在8000端口上。
添加新的配置文件 /etc/nginx/sites-available/wordpress-load-balance,注意我把http的访问全部重定向到https,以防GFW
# Upstream to abstract backend connection(s) for php
upstream php {
server unix:/var/run/php5-fpm.sock;
}
upstream mineservers {
# 设置两个upstream, 其中笔记本优先,同时设置5s的fail_timout
# 因为局域网很稳定,所以max_fails设成1就行了,
# 如果fail就说明笔记本关机中,让RPi自己来处理
server 192.168.1.101:8000 weight=999 fail_timeout=5s max_fails=1;
server 192.168.1.100:8000;
}
server {
listen 80;
server_name mine260309.me;
rewrite ^ https://$server_name$request_uri? permanent;
}
server {
listen 443 ssl;
server_name mine260309.me;
ssl_certificate /path/to/cert/mine260309.me.2014.chain.crt;
ssl_certificate_key /path/to/cert/mine260309.me.2014.key;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
access_log /path/to/wordpress/logs/proxy.log;
error_log /path/to/wordpress/logs/proxy_error.log;
location / {
# 代理到upstream
proxy_pass http://mineservers;
### force timeouts if one of backend is died ##
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
### Set headers ####
proxy_set_header Accept-Encoding "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
### Most PHP, Python, Rails, Java App can use this header ###
#proxy_set_header X-Forwarded-Proto https;##
#This is better##
proxy_set_header X-Forwarded-Proto $scheme;
add_header Front-End-Https on;
### By default we don't want to redirect it ####
proxy_redirect off;
}
}
server {
root /path/to/wordpress;
# 在8000端口监听
listen 8000;
server_name mine260309.me;
... # normal wordpress configurations
}
在笔记本上用同样的配置就可以了。
这样,任何一个请求到RPi,它会让nginx优先反向代理到笔记本的nginx的8000端口,由笔记本来处理;
如果笔记本关机,在5秒钟之后它会fail,于是再由RPi自己的8000端口处理。
Q.E.D.