【51CTO.com 独家特稿】由于公司的注册用户已超过八百万了,而且每天都有持续增涨的趋势,而PV/日已经有向千万靠扰的趋势;原有的Web架构越来越满足不了我们的需求了,所以我们也考虑上能抗高并发的HAProxy来作为我们网站的最前端的负载均衡器;因为我已经在东莞的二个项目上面成功实施了HAProxy+Keepalived双机方案,所以我在这里也尝试在公司的网站上这种负载均衡高可用架构,即HAProxy+Keepalived。
HAProxy+Keepalived配置过程如下:
1. 做好整个环境的准备工作。
两台服务器DELL 2950均要做好准备工作,比如设置好hosts文件及进行ntpd对时。
网络拓朴很简单,如下所示:
ha1.cn7789.com eth0:203.93.236.145
ha2.cn7789.com eth0:203.93.236.142
网卡用其自带的千兆网卡均可。
硬盘模式没有要求,Raid0或Raid1均可。
网站对外的VIP地址是:203.93.236.149,这是通过Keepalived来实现的,原理请参考前面的章节;同时这也是我们的网站的外网DNS对应的IP。
2. HAProxy和Keepalived的安装过程
关于此安装过程,请大家参考前面的内容,这里就不重复了,我们主要是注意关键位置的改动:
(1)首先是要建立HAProxy启动、重启、关闭等状态脚本,我这里的HAProxy脚本为/root/haproxy,我们给它执行权限,脚本内容如下所示:
- #!/bin/sh
- # chkconfig 35 on
- # description: HAProxy is a TCP/HTTP reverse proxy which is particularly suited for high availability environments.
- # Source function library.
- if [ -f /etc/init.d/functions ]; then
- . /etc/init.d/functions
- elif [ -f /etc/rc.d/init.d/functions ] ; then
- . /etc/rc.d/init.d/functions
- else
- exit 0
- fi
- # Source networking configuration.
- . /etc/sysconfig/network
- # Check that networking is up.
- [ ${NETWORKING} = "no" ] && exit 0
- [ -f /usr/local/haproxy/conf/haproxy.cfg ] || exit 1
- RETVAL=0
- start() {
- /usr/local/haproxy/sbin/haproxy -c -q -f /usr/local/haproxy/conf/haproxy.cfg
- if [ $? -ne 0 ]; then
- echo "Errors found in configuration file."
- return 1
- fi
- echo -n "Starting HAproxy: "
- daemon /usr/local/haproxy/sbin/haproxy -D -f /usr/local/haproxy/conf/haproxy.cfg -p /var/run/haproxy.pid
- RETVAL=$?
- echo
- [ $RETVAL -eq 0 ] && touch /var/lock/subsys/haproxy
- return $RETVAL
- }
- stop() {
- echo -n "Shutting down HAproxy: "
- killproc haproxy -USR1
- RETVAL=$?
- echo
- [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/haproxy
- [ $RETVAL -eq 0 ] && rm -f /var/run/haproxy.pid
- return $RETVAL
- }
- restart() {
- /usr/local/haproxy/sbin/haproxy -c -q -f /usr/local/haproxy/conf/haproxy.cfg
- if [ $? -ne 0 ]; then
- echo "Errors found in configuration file, check it with 'haproxy check'."
- return 1
- fi
- stop
- start
- }
- check() {
- /usr/local/haproxy/sbin/haproxy -c -q -V -f /usr/local/haproxy/conf/haproxy.cfg
- }
- rhstatus() {
- status haproxy
- }
- condrestart() {
- [ -e /var/lock/subsys/haproxy ] && restart || :
- }
- # See how we were called.
- case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- restart)
- restart
- ;;
- reload)
- restart
- ;;
- condrestart)
- condrestart
- ;;
- status)
- rhstatus
- ;;
- check)
- check
- ;;
- *)
- echo $"Usage: haproxy {start|stop|restart|reload|condrestart|status|check}"
- RETVAL=1
- esac
- exit $RETVAL
#p#
(2)/usr/local/haproxy/conf/haproxy.cfg文件的内容如下所示(两台HAProxy机器的配置内容一样):
- global
- log 127.0.0.1 local0
- maxconn 65535
- chroot /usr/local/haproxy
- uid 99
- gid 99
- daemon
- nbproc 8
- pidfile /usr/local/haproxy/haproxy.pid
- debug
- defaults
- log 127.0.0.1 local3
- mode http
- option httplog
- option httpclose
- option dontlognull
- option forwardfor
- option redispatch
- retries 2
- maxconn 2000
- stats uri /haproxy-stats
- contimeout 5000
- clitimeout 50000
- srvtimeout 50000
- frontend www.1paituan.com
- bind *:80
- mode http
- option httplog
- log global
- default_backend phppool
- backend phppool
- balance source
- option httpchk HEAD /index.jsp HTTP/1.0
- server web1 203.93.236.147:80 weight 5 check inter 2000 rise 2 fall 3
- server web2 203.93.236.146:80 weight 3 check inter 2000 rise 2 fall 3
配置文件建议写成这种frontend(前台)和backend(后台)的形式,方便我们根据需求也可以利用HAProxy的正则做成动静分离或根据特定的文件名后缀(比如.php或.jsp)访问指定的phppool池或javapool池(Nginx也能实现此项功能),我们还可以指定静态服务器池,让客户端对静态文件(比如bmp或jsp或html)访问我们的Nginx静态服务器,所以前后台的模型也是非常有用的,不喜欢frontend(前台)和backend(后台)的朋友可以对比下以前没有采用这种模式的配置文件,内容如下:
- global
- log 127.0.0.1 local0
- maxconn 65535
- chroot /usr/local/haproxy
- uid 99
- gid 99
- daemon
- nbproc 8
- pidfile /usr/local/haproxy/haproxy.pid
- debug
- defaults
- log 127.0.0.1 local3
- mode http
- option httplog
- option httpclose
- option dontlognull
- option forwardfor
- option redispatch
- retries 2
- maxconn 2000
- balance source
- stats uri /haproxy-stats
- contimeout 5000
- clitimeout 50000
- srvtimeout 50000
- listen www.1paituan.com
- bind *:80
- mode http
- option httplog
- log global
- option httpchk HEAD /index.jsp HTTP/1.0
- server web1 203.93.236.147:80 weight 5 check inter 2000 rise 2 fall 3
- server web2 203.93.236.146:80 weight 3 check inter 2000 rise 2 fall 3
HAProxy的正则功能虽然没Nginx强大灵活,但也是非常有用的;大家可以参考下面的文档来熟悉下HAProxy的正则写法,这些对于我们以后的工作帮助还是很大的,内容如下:
####################acl策略定义######################### #如果请求的域名满足正则表达式返回true -i是忽略大小写 acl denali_policy hdr_reg(host) -i ^(www.gemini.taobao.net|my.gemini.taobao.net|auction1.gemini.taobao.net)$ #如果请求域名满足trade.gemini.taobao.net 返回 true -i是忽略大小写 acl tm_policy hdr_dom(host) -i trade.gemini.taobao.net #在请求url中包含sip_apiname=,则此控制策略返回true,否则为false acl invalid_req url_sub -i sip_apiname= #在请求url中存在timetask作为部分地址路径,则此控制策略返回true,否则返回false acl timetask_req url_dir -i timetask #当请求的header中Content-length等于0时返回 true acl missing_cl hdr_cnt(Content-length) eq 0 ######################acl策略匹配相应################### #当请求中header中Content-length等于0 阻止请求返回403 block if missing_cl #block表示阻止请求,返回403错误,当前表示如果不满足策略invalid_req,或者满足策略timetask_req,则阻止请求。 block if !invalid_req || timetask_req #当满足denali_policy的策略时使用denali_server的backend use_backend denali_server if denali_policy #当满足tm_policy的策略时使用tm_server的backend use_backend tm_server if tm_policy #reqisetbe关键字定义,根据定义的关键字选择backend reqisetbe ^Host:\ img dynamic reqisetbe ^[^\ ]*\ /(img|css)/ dynamic reqisetbe ^[^\ ]*\ /admin/stats stats #以上都不满足的时候使用默认mms_server的backend default_backend mms_server Keepalived的配置过程比较简单,这里略过,大家可以参考我们前面的配置,配置成功后我们可以分别在二台机器上启动HAProxy及Keepalived服务(建议在Screen模式下开启HAProxy服务,不熟悉Sreen用法的朋友建议熟悉下)。 |
#p#
3.替HAProxy添加日志支持
我们编辑/etc/syslog.conf文件, 添加内容如下:
local3.* /var/log/haproxy.log
local0.* /var/log/haproxy.log
我们编辑/etc/sysconfig/syslog文件,修改内容如下:
SYSLOGD_OPTIONS="-r -m 0"
然后重启syslog服务,命令如下:
service syslog restart
4.验证此架构及注意事项
我们可以关闭主HAProxy机器或重新启动,看在此过程中,VIP地址有没有正确的转移到从HAProxy机器上,影响我们访问网站没,以上步骤我自己测试过多次,而且线上环境的稳定运行,证明HAProxy+Keeaplived双机方案确实是有效的。
关于HAProxy+Heartbeat这种负载均衡高可用架构,有些情况我也跟大家说明一下:
◆在此HAProxy+Keepalivp负载均衡高可用架构中,我们是如何解决session的问题呢?我们这里采用的是它自身的balance source机制,它跟Nginx的ip_hash机制原理类似,是让客户机访问时始终访问后端的某一台真实的web服务器,这样让session就固定下来了;
◆option httpchk HEAD /index.jsp HTTP/1.0 是网页监控,如果HAProxy检测不到Web的根目录下没有index.jsp,就会产生503报错。
◆有网友配置HAProxy时喜欢用listen 203.93.236.141:80这样的格式,这样其实不好,做负载均衡高可用时由于从机分配不到VIP地址,会导致从机启动不了,我建议用bind *:80的方式代替。
◆HAProxy的并发监控暂时没有Nginx中的相关模块,但可以考虑用SHELL命令或自行开发PHP或JSP程序来监控。
5.HAProxy的监控页面
我们可以在地址栏输入http://www.1paituan.com/haproxy-stats/,显示界面如下(HAProxy自带的监控页面,也是我非常喜欢的功能之一):
作者介绍:
余洪春(抚琴煮酒·微博),《构建高可用Linux服务器》一书作者,一拍网系统架构师、资深项目管理工程师,ChinaUnix集群和高可用版版主。
【51CTO.com独家特稿,非经授权谢绝转载!合作媒体转载请注明原文出处及出处!】