HAProxy双机高可用方案之HAProxy+Keepalived

原创
网络 网络优化 网络运维
由于公司的注册用户已超过八百万了,而且每天都有持续增涨的趋势,而PV/日已经有向千万靠扰的趋势;原有的Web架构越来越满足不了我们的需求了,所以我们也考虑上能抗高并发的HAProxy来作为我们网站的最前端的负载均衡器...

【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,我们给它执行权限,脚本内容如下所示:

  1. #!/bin/sh  
  2. # chkconfig 35 on  
  3. # description: HAProxy is a TCP/HTTP reverse proxy which is particularly suited for high availability environments.  
  4.  
  5. # Source function library.  
  6. if [ -f /etc/init.d/functions ]; then  
  7.   . /etc/init.d/functions  
  8. elif [ -f /etc/rc.d/init.d/functions ] ; then  
  9.   . /etc/rc.d/init.d/functions  
  10. else  
  11.   exit 0  
  12. fi  
  13.  
  14. # Source networking configuration.  
  15. . /etc/sysconfig/network  
  16.  
  17. # Check that networking is up.  
  18. [ ${NETWORKING} = "no" ] && exit 0  
  19.  
  20. [ -f /usr/local/haproxy/conf/haproxy.cfg ] || exit 1  
  21.  
  22. RETVAL=0 
  23.  
  24. start() {  
  25.   /usr/local/haproxy/sbin/haproxy -c -q -f /usr/local/haproxy/conf/haproxy.cfg  
  26.   if [ $? -ne 0 ]; then  
  27.     echo "Errors found in configuration file."  
  28.     return 1  
  29.   fi  
  30.  
  31.   echo -n "Starting HAproxy: "  
  32.   daemon /usr/local/haproxy/sbin/haproxy -D -f /usr/local/haproxy/conf/haproxy.cfg -p /var/run/haproxy.pid  
  33.   RETVAL=$?  
  34.   echo  
  35.   [ $RETVAL -eq 0 ] && touch /var/lock/subsys/haproxy  
  36.   return $RETVAL  
  37. }  
  38.  
  39. stop() {  
  40.   echo -n "Shutting down HAproxy: "  
  41.   killproc haproxy -USR1  
  42.   RETVAL=$?  
  43.   echo  
  44.   [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/haproxy  
  45.   [ $RETVAL -eq 0 ] && rm -f /var/run/haproxy.pid  
  46.   return $RETVAL  
  47. }  
  48.  
  49. restart() {  
  50.   /usr/local/haproxy/sbin/haproxy -c -q -f /usr/local/haproxy/conf/haproxy.cfg  
  51.   if [ $? -ne 0 ]; then  
  52.     echo "Errors found in configuration file, check it with 'haproxy check'."  
  53.     return 1  
  54.   fi  
  55.   stop  
  56.   start  
  57. }  
  58.  
  59. check() {  
  60.   /usr/local/haproxy/sbin/haproxy -c -q -V -f /usr/local/haproxy/conf/haproxy.cfg  
  61. }  
  62.  
  63. rhstatus() {  
  64.   status haproxy  
  65. }  
  66.  
  67. condrestart() {  
  68.   [ -e /var/lock/subsys/haproxy ] && restart || :  
  69. }  
  70.  
  71. # See how we were called.  
  72. case "$1" in  
  73.   start)  
  74.     start  
  75.     ;;  
  76.   stop)  
  77.     stop  
  78.     ;;  
  79.   restart)  
  80.     restart  
  81.     ;;  
  82.   reload)  
  83.     restart  
  84.     ;;  
  85.   condrestart)  
  86.     condrestart  
  87.     ;;  
  88.   status)  
  89.     rhstatus  
  90.  ;;  
  91.   check)  
  92.     check  
  93.     ;;  
  94.   *)  
  95.     echo $"Usage: haproxy {start|stop|restart|reload|condrestart|status|check}"  
  96.     RETVAL=1 
  97. esac  
  98.  
  99. exit $RETVAL 

#p#

(2)/usr/local/haproxy/conf/haproxy.cfg文件的内容如下所示(两台HAProxy机器的配置内容一样):

  1. global  
  2.         log 127.0.0.1   local0  
  3.         maxconn 65535  
  4.         chroot /usr/local/haproxy  
  5.         uid 99   
  6.         gid 99  
  7.         daemon  
  8.         nbproc 8  
  9.         pidfile /usr/local/haproxy/haproxy.pid  
  10.         debug  
  11.  
  12. defaults    
  13.          log     127.0.0.1       local3    
  14.          mode   http    
  15.          option httplog    
  16.          option httpclose    
  17.          option dontlognull    
  18.          option forwardfor    
  19.          option redispatch    
  20.          retries 2    
  21.          maxconn 2000    
  22.          stats   uri     /haproxy-stats    
  23.          contimeout      5000    
  24.          clitimeout      50000    
  25.          srvtimeout      50000    
  26.  
  27. frontend www.1paituan.com  
  28.          bind *:80  
  29.          mode http   
  30.          option httplog  
  31.          log global   
  32.          default_backend phppool   
  33.  
  34. backend phppool  
  35.         balance source    
  36.         option httpchk HEAD /index.jsp HTTP/1.0  
  37.         server web1  203.93.236.147:80 weight 5  check inter 2000 rise 2 fall 3   
  38.      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(后台)的朋友可以对比下以前没有采用这种模式的配置文件,内容如下:

  1. global  
  2.         log 127.0.0.1   local0  
  3.         maxconn 65535  
  4.         chroot /usr/local/haproxy  
  5.         uid 99  
  6.         gid 99  
  7.         daemon  
  8.         nbproc 8  
  9.         pidfile /usr/local/haproxy/haproxy.pid  
  10.         debug  
  11.  
  12. defaults  
  13.          log     127.0.0.1       local3  
  14.          mode   http  
  15.          option httplog  
  16.          option httpclose  
  17.          option dontlognull  
  18.          option forwardfor  
  19.          option redispatch  
  20.          retries 2  
  21.          maxconn 2000  
  22.          balance source  
  23.          stats   uri     /haproxy-stats  
  24.          contimeout      5000  
  25.          clitimeout      50000  
  26.          srvtimeout      50000  
  27.  
  28. listen  www.1paituan.com  
  29.         bind *:80  
  30.         mode http  
  31.         option httplog  
  32.         log global  
  33.         option httpchk HEAD /index.jsp HTTP/1.0  
  34.         server web1  203.93.236.147:80 weight 5  check inter 2000 rise 2 fall 3  
  35.         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独家特稿,非经授权谢绝转载!合作媒体转载请注明原文出处及出处!】

责任编辑:佟健 来源: 51CTO.com
相关推荐

2011-09-30 13:02:10

51CTO博客一周热门Web架构

2018-08-24 08:51:10

haproxykeepalived均衡器

2023-10-13 18:57:22

2020-10-28 11:20:18

RabbitMQHAProxy运维

2011-09-22 10:48:20

MySQL集群HAProxy

2015-10-21 12:58:58

keepalived集群Linux

2022-07-22 20:00:01

高可用路由

2023-11-09 07:58:50

2023-05-15 08:20:56

2019-12-24 14:28:00

KeepalivedNginxTomcat

2012-02-15 00:15:48

2010-05-05 22:58:46

2024-01-31 09:11:16

HaproxyHttpTCP

2019-09-03 10:19:58

Kubernetes本地负载命令

2012-05-07 10:17:48

2012-02-15 23:09:16

haproxyserver

2011-12-02 10:10:34

RedisFailover

2010-12-08 08:57:11

keepalivedMySQL-HA

2012-02-15 00:01:34

2019-10-09 16:02:16

NginxKeepalivedLvs
点赞
收藏

51CTO技术栈公众号