我的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.