1. Haproxy介绍
Haproxy是一个开源的高性能的反向代理或者说是负载均衡服务软件之一,它支持双机热备、虚拟主机、基于TCP和HTTP应用代理等功能。其配置简单,而且拥有很好的对服务器节点的健康检查功能(相当于keepalived健康检查),当其代理的后端服务器出现故障时,Haproxy会自动的将该故障服务器摘除,当服务器的故障恢复后Haproxy还会自动将RS服务器假如。 Haproxy特别使用与那些访问量很大。但又需要会话保持或七层应用的业务。Haproxy运行在普通的服务器硬件上,仅仅进行简单的优化就可以支持数以万计的并发连接。并且它的运行模式使得它可以很简单安全的整合到各种网站的架构中,同时使得应用服务器不会暴露到网络中。 Haproxy软件引入了frontend,backend的功能,frontend(acl规则匹配)可以运维管理人员根据任意HTTP请求头做规则匹配,然后把请求定向到相关的backend(server pools等待前端把请求转过来的服务器组)。通过frontend和backup,我们可以很容易的实现haproxy的7层代理功能,haproxy是一款不可多得的优秀代理服务软件 Haproxy支持两种主要代理模式:第一个是4层tcp代理(例如:可用于邮件服务内部协议通信服务器、Mysql服务等)。第二个是7层代理(如HTTP代理)。在4层tcp代理模式下,Haproxy仅在客户端和服务器之间双向转发流量。但是在7层模式下Haproxy会分析应用层协议,并且能通过运行、拒绝、交换、增加、修改或者删除请求(request)或者回应(reponse)里指定内容来控制协议。
2. Haproxy解决方案拓扑图
2.1 Haproxy L4负载均衡应用架构拓扑
Haproxy软件的四层tcp代理应用非常优秀,配置非常简单方便,比LVS和Nginx要方便很多,因为不需要在RS端执行脚本即可实现应用代理。 说明:由于Haproxy采用的是NAT模式,数据包来去都会经过Haproxy,因此,在流量特别大的情况下,其性能不如LVS。 在一般的中小型公司,建议采用haproxy做负载均衡,而不要使用LVS或者Nginx。 2.2 Haproxy L7负载均衡应用架构拓扑
Haproxy软件的最大优点在于其7层的根据URL请求头应用过滤的功能,一般用在LVS软件的下一层,或者像官方推荐的可以挂在硬件负载均衡NS、F5下使用。 2.3 实施部署前主机规划列表
名称
| 接口
| IP
| 用途
| MASTER
| eth0
| 192.168.1.81
| 外网管理IP,用于WAN数据转发
|
| eth1
| 192.168.2.81
| 内网管理IP,用于LAN数据转发
|
| eth2
| 192.168.3.81
| 用于服务器间心跳连接(直连)
| vip
|
| 192.168.1.181
| 用于提供应用程序A挂载服务
| BACKUP
| eth0
| 192.168.1.82
| 外网管理IP,用于WAN数据转发 |
| eth1
| 192.168.2.82
| 内网管理IP,用于LAN数据转发 |
| eth2
| 192.168.3.82
| 用于服务器间心跳连接(直连) | vip
|
| 192.168.1.182
| 用于提供应用程序B挂载服务 |
此表为heartbeat+haproxy生产环境中的正式IP环境,haproxy做四层应用时的IP信息 2.4 实施部署环境
Haproxy所有实施部署环境和前面讲过的heartbeat的环境一模一样。因为在生产环境中,haproxy服务就是和heartbeat服务配合使用的,当然和keepalived服务配合也是可以的。 3. 安装Haproxy软件
3.1 安装
mkdir -p /home/yan/tools cd /home/yan/tools tar -xf haproxy-1.4.21.tar.gz cd haproxy-1.4.21 make TARGET=linux26 ARCH=x86_64 make PREFIX=/application/haproxy-1.4.21 install ln -s /application/haproxy-1.4.21/ /application/haproxy 3.2 配置Haproxy实现L4负载均衡
3.2.1 初始化Haproxy目录
cd /application/haproxy/ ll 3.2.2 创建Haproxy相关目录
mkdir -p bin conf logs var/run var/chroot 3.2.3 L4Haproxy的配置文件(conf目录下)
vim conf/haproxy.conf global chroot /application/haproxy-1.4.21/var/chroot daemon group haproxy user haproxy log 127.0.0.1:514 local0 info pidfile /application/haproxy-1.4.21/var/run/haproxy.pid
maxconn 20480 spread-checks 3 # tune.maxaccept 100 # tune.maxpollevents 180 nbproc 8
defaults log global mode http # option httplog # option dontlognull retries 3 option redispatch contimeout 5000 clitimeout 50000 srvtimeout 50000
listen www01 192.168.1.81:80 mode http no option splice-response stats enable stats uri /admin?stats stats auth proxy:oldboy balance roundrobin #轮询算法rr option httpclose option forwardfor #记录客户端地址,而不是haproxy地址 option httpchk HEAD /checkstatus.html HTTP/1.0 #健康检查 server www01 192.168.1.80:80 check #增加RS server www02 192.168.1.100:80 check #check:对端口做检查 添加一个haproxy用户 useradd haproxy -s /sbin/nologin -M 3.2.4 Haproxy启动脚本(bin目录下存放)
vim bin/haproxy #!/bin/bash
BASE="/application/haproxy-1.4.21"
PROG=$BASE/sbin/haproxy PIDFILE=$BASE/var/run/haproxy.pid CONFFILE=$BASE/conf/haproxy.conf
case "$1" in start) #$PROG -f $CONFFILE >/dev/null 2>&1 $PROG -f $CONFFILE ;; status) if [ ! -f $PIDFILE ]; then echo "pid not found" exit 1 fi for pid in $(cat $PIDFILE); do kill -0 $pid RETVAL="$?" if [ ! "$RETVAL" = "0" ]; then echo "process $pid died" exit 1 fi done echo "process is running" ;; restart) $PROG -f $CONFFILE -sf $(cat $PIDFILE) >/dev/null 2>&1 ;; stop) kill $(cat $PIDFILE) ;; *) echo "USAGE: $0 start|restart|status|stop" exit 1 ;; esac chmod 700 haproxy 3.2.5 启动Haproxy服务
/application/haproxy/bin/haproxy start [WARNING] 162/092036 (34610) : Proxy 'www': in multi-process mode, stats will be limited to process assigned to the current request. [ALERT] 162/092036 (34610) : Starting proxy www: cannot bind socket 原因是不存在VIP导致启动Haproxy报错,80端口已经启动产生冲突 解决方法 echo 'net.ipv4.ip_nonlocal_bind = 1'>>/etc/sysctl.conf sysctl -p 并且关闭http服务 (net.ipv4.ip_nonlocal_bind=1 意思是启动haproxy的时候,允许忽视VIP的存在) 加入开机自启动 echo '/application/haproxy/bin/haproxy start' >> /etc/rc.local 检查服务: ps -ef | grep haproxy | grep -v grep haproxy 34645 1 0 09:31 ? 00:00:00 /application/haproxy-1.4.21/sbin/haproxy -f /application/haproxy-1.4.21/conf/haproxy.conf haproxy 34646 1 0 09:31 ? 00:00:00 /application/haproxy-1.4.21/sbin/haproxy -f /application/haproxy-1.4.21/conf/haproxy.conf haproxy 34647 1 0 09:31 ? 00:00:00 /application/haproxy-1.4.21/sbin/haproxy -f /application/haproxy-1.4.21/conf/haproxy.conf haproxy 34648 1 0 09:31 ? 00:00:00 /application/haproxy-1.4.21/sbin/haproxy -f /application/haproxy-1.4.21/conf/haproxy.conf haproxy 34649 1 0 09:31 ? 00:00:00 /application/haproxy-1.4.21/sbin/haproxy -f /application/haproxy-1.4.21/conf/haproxy.conf haproxy 34650 1 0 09:31 ? 00:00:00 /application/haproxy-1.4.21/sbin/haproxy -f /application/haproxy-1.4.21/conf/haproxy.conf haproxy 34651 1 0 09:31 ? 00:00:00 /application/haproxy-1.4.21/sbin/haproxy -f /application/haproxy-1.4.21/conf/haproxy.conf haproxy 34652 1 0 09:31 ? 00:00:00 /application/haproxy-1.4.21/sbin/haproxy -f /application/haproxy-1.4.21/conf/haproxy.conf 3.2.6 Haproxy日志配置(cat /etc/syslog.conf)
yum -y install rsyslog 编辑/etc/rsyslog.conf (末尾添加) vim /etc/rsyslog.conf #Haproxy local0.* /application/haproxy-1.4.21/logs/haproxy.log #end /etc/rsyslog.conf 3.2.7 配置/etc/sysconfig/rsyslog
vim /etc/sysconfig/rsyslog # Options to syslogd # -m 0 disables 'MARK' messages. # -r enables logging from remote machines # -x disables DNS lookups on messages recieved with -r # See syslogd(8) for more details SYSLOGD_OPTIONS="-m 0 -r -x" # Options to klogd # -2 prints all kernel oops messages twice; once for klogd to decode, and # once for processing with 'ksymoops' # -x disables all klogd processing of oops messages entirely # See klogd(8) for more details KLOGD_OPTIONS="-x" # SYSLOG_UMASK=077 # set this to a umask value to use for all log files as in umask(1). # By default, all permissions are removed for "group" and "other". 重启日志服务 /etc/init.d/rsyslog restart chkconfig rsyslog on ps -ef | grep rsyslog | grep -v grep root 34518 1 0 08:54 ? 00:00:00 /sbin/rsyslogd -i /var/run/syslogd.pid -m 0 -r -x
3.2.8 查看状态信息
检查备节点(192.168.1.82)http能正常访问 修改主节点(192.168.1.81)/application/haproxy/conf/haproxy.conf vim /application/haproxy/conf/haproxy.conf server www02 192.168.1.82:80 check (wget 192.168.1.82能通但是浏览器中显示不正常,原因是走了健康检查了,将option httpchk HEAD /checkstatus.html HTTP/1.0注释掉) /application/haproxy/bin/haproxy restart 此时查看浏览器上www02已经变绿 访问192.168.1.81(主节点)跟192.168.1.82(备)结果相同,表示四层负载均衡已经OK 3.3 测试haproxy负载均衡和健康检查功能
修改主节点(192.168.1.81)/application/haproxy/conf/haproxy.conf 再添加一个server www03 192.168.1.85:80 check 重启服务: /application/haproxy/bin/haproxy restart 当访问192.168.1.81时会在两台主机之间相互轮询切换 轮询访问结果测试
4. Haproxy健康检查功能
4.1 基于端口的健康检查配置
server www01 192.168.1.80:80 check server www02 192.168.1.82:80 check server www03 192.168.1.85:80 check 补全上面配置结果 server www01 192.168.1.80:80 cookie www01 check port 80 inter 5000 fall 5 提示: 1)check port 80 表示对80端口进行健康检查 2)inter 5000 fall 5 表示每5秒检查一次,一共检查5次。如果有问题就会摘掉出问题的机器。 3)如果结尾不加inter 5000 fall 5,则默认每2秒检查一次,一共检查3次。如果有问题就会摘掉出问题的机器。 4)The default values are the following ones : - inter : 2000 意思是不加该参数,正常情况默认没两秒检查一次 - rise : 2 意思是不加该参数,在RS宕机后恢复前,检查2次OK,认为其复活,并加入到群组中 - fall : 3 意思是不加该参数,检查3此后,认为RS宕机,剔除集群组 - port : default server port 不加该参数,默认就是端口检查 - addr : specific address for the test (default = address server) 4.2 基于URL的健康检查
1)基于IP的URL健康检查 option httpchk HEAD /checkstatus.html HTTP/1.0 server tmpbai51 192.168.1.51:80 maxconn 2048 weight 8 check inter 3000 fall rise 2 server tmpbai53 192.168.1.53:80 maxconn 2048 weight 8 check inter 3000 fall rise 2 server tmpbai54 192.168.1.54:80 maxconn 2048 weight 8 check inter 3000 fall rise 2 当打开option httpchk HEAD /checkstatus.html HTTP/1.0进行URL健康检查时浏览器上显示都是红色,原因是没有checkstatus.html 解决办法在apache站点目录下创建checkstatus.html,或者将checkstatus.html改为index.html 此时浏览器上的检查条目会变绿 2)基于域名的URL健康检查: option httpchk HEAD /index.jsp HTTP/1.1\r\nHost:\ www URL健康检查实践测试:实际上haproxy就是相当于用下面的方式在访问RS节点确认是否正常 3)第一种HEAD配置方法 option httpchk HEAD /checkstatus.html HTTP/1.0 4)健康检查的频率、时间等参数 maxconn 2048 最大连接数,连接数不是越大越好,衡量服务器的承受能力,设置其能承受的最大值不至于把服务器压垮 weight 8 权重(权重越大,承受的访问量越大) 5)第二种GET配置方法 option httpchk GET /checkstatus.html 5. Haproxy的相关生产功能应用
5.1 haproxy高可用参数backup功能测试
tail -3 haproxy.conf server www02 192.168.1.82:80 check #server www03 192.168.1.85:80 check server www21 192.168.1.85:80 check backup 打开浏览器 此时访问192.168.1.81(主节点)只能访问到192.168.1.82,不会轮询到85主机 当82主机宕掉后会立马切换到85主机
5.2 haproxy下的RS无法记录客户真实IP问题
当查看82主机的http日志是发现访问IP都是81,不会记录真实主机的IP 解决办法: 1)在haproxy配置文件里加如如下参数: listen www ...... option forwardfor ....... 提示:参数最好放在listen www里面 2)在RS上对日志格式进行修改 //传统日志和后抛Netscaler负载均衡的apache日志比较 LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined LogFormat "\"%{X-Forwarded-For}i\"%l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined 此时再从笔记本访问后查看82的日志,里面记录的就是笔记本的真实IP了,不是haproxy主机的IP 3)生产环境负载均衡后面的RS服务器不记录负载均衡的健康检查日志: 虚拟主机不记录健康检查文件日志(check.txt): SetEnvIf Request_URL "^/check\.txt$" dontlog LogLevel warn ErrorLog /var/log/httpd/vhost_error.log CustomLog /var/log/httpd/vhost_access.log combined env=!dontlog 5.3 在配置内核参数开发转发功能
在/etc/sysctl.conf中加入如下配置 net.ipv4.ip_forward=1 sysctl -p
6. Haproxy双机双主的相关生产应用
6.1 主备Haproxy配置文件区别
主备Haproxy配置文件完全一样,没有任何不同 将主节点的配置文件全部拷贝到备节点,启动服务 修改配置文件/application/haproxy/conf/haproxy.conf listen www bind 192.168.1.181:80 将IP改为VIP地址 重启服务 此时访问VIP:192.168.1.181 6.2 Haproxy主从端分别开启转发功能:
vim /etc/stsctl.cinf net.ipv4.ip_forward = 1 sysctl -p 6.3 生产环境防火墙iptables配置建议
(生产环境高访问量站点防火墙可能对LB性能有影响,最后前端加硬件防火墙或者干脆不用防火墙) 6.4 heartbeat与haproxy关联问题
在生产环境中,haproxy可能会配置heartbeat或keepalived使用,当Haproxy无法提供服务时,要不要把服务推到备机? 一般情况这个问题不会发生,如果严格去做的话可以单独写一个守护进程脚本,当haproxy一宕的时候,停掉heartbeat。 6.5 haproxy日志配置优化
将配置文件/application/haproxy/conf/haproxy.conf中的日志改为 log 127.0.0.1:514 local0 waring 6.6 haproxy多业务多VIP的配置
vim /application/haproxy/conf/haproxy.conf global chroot /application/haproxy-1.4.21/var/chroot daemon group haproxy user haproxy log 127.0.0.1:514 local0 warning pidfile /application/haproxy-1.4.21/var/run/haproxy.pid
maxconn 20480 spread-checks 3 # tune.maxaccept 100 # tune.maxpollevents 180 nbproc 8
defaults log global mode http # option httplog option httpclose # option dontlognull stats enable stats uri /admin?stats stats auth proxy:oldboy cookie SERVERID insert retries 3 option redispatch contimeout 5000 clitimeout 50000 srvtimeout 50000
listen www bind 192.168.1.181:80 mode http balance roundrobin option forwardfor option httpchk HEAD /checkstatus.html HTTP/1.0 server www01 192.168.1.80:80 check server www02 192.168.1.82:80 check server www21 192.168.1.85:80 check
listen ssh bind 192.168.1.181:900 mode tcp balance roundrobin server ssh85 192.168.1.82:22 check 启动后连接ssh -p900 [url=]yan@192.168.1.81测试[/url] 6.7 haproxy多实例解决方案
在/application/haproxy/conf/下再添加一个配置文件,比如haproxy.conf.simple-L4 (注意,两个配置文件pid文件名不能一样,listen不能一样,bind不能一样) vim /application/haproxy/conf/haproxy.conf.simple-L4 启动实例: /application/haproxy/sbin/haproxy -f haproxy.conf.simple-L4 检查:ps -ef | grep haproxy 6.8 heartbeat与haproxy配合生产场景维护
6.9 查看服务是否正常及VIP情况
查看日志情况 tail -f /application/haproxy/logs/haproxy.log tail -f /var/log/heartbeat.log tail -f /var/log/messages
7. haproxy的L7生产应用实践
7.1 rs web server测试环境准备
在/var/下分别建立php nginx resin3个站点目录,并增加index文件及内容,假设PHP,nginx、resin分别代表不同的业务服务: PHP 表示动态php程序服务 nginx表示静态图片、js、html等服务 resin表示动态jsp/java服务 操作命令: for name in php nginx resin;do mkdir -p /var/$name;echo $name > /var/$name/index.html;done 检查: for name in php nginx resin;do cat /var/$name/index.html;done 安装httpd: yum -y install httpd 添加虚拟主机 编辑httpd-vhost.conf最下面加 vim /etc/httpd/conf.d/httpd-vhost.conf <Directory "/var"> Options FollowSymLinks AllowOverride none Order allow,deny Allow from all </Directory> NameVirtualHost *:8000 NameVirtualHost *:9000 NameVirtualHost *:10000 <VirtualHost *:8000> ServerName nginx.yan.org ServerAlias yan.org DocumentRoot "/var/nginx" </VirtualHost>
<VirtualHost *:9000> ServerName php.yan.org DocumentRoot "/var/php" </VirtualHost>
<VirtualHost *:10000> ServerName resin.yan.org DocumentRoot "/var/resin" </VirtualHost> vim /etc/httpd/conf/httpd.conf 增加监听端口 Listen 8000 Listen 9000 Listen 10000 检查语法: /etc/init.d/httpd configtest 重启: /etc/init.d/httpd restart
7.2 实现haproxy301域名跳转
主节点(192.168.1.81)操作 修改笔记本hosts文件: vim /etc/hosts (将虚拟主机的域名解析为haproxy配置文件bind中的IP) 192.168.1.81 nginx.yan.org php.yan.org resin.yan.org yan.org 修改主节点(192.168.1.81)haproxy配置文件 vim /application/haproxy/conf/haproxy.conf global chroot /application/haproxy-1.4.21/var/chroot daemon group haproxy user haproxy #log 127.0.0.1:514 local0 info log 127.0.0.1:514 local0 warning pidfile /application/haproxy-1.4.21/var/run/haproxy.pid maxconn 20000 spread-checks 3 nbproc 8 defaults log global mode http retries 3 option redispatch contimeout 5000 clitimeout 50000 srvtimeout 50000 stats enable stats hide-version stats uri /admin?stats stats auth proxy:123456 option httpclose
frontend webserver bind 192.168.1.81:80 #1)301× #èó1.yan.org -->nginx.yan.org ¨301 #(short_domר hdr°üHost -i(·ó) yan.org acl short_dom hdr(Host) -i yan.org
acl oldboy_static path_beg /nginx/ acl oldboy_php path_beg /php/ acl oldboy_java path_beg /resin/ acl oldboy_pic path_end .gif .png .jpg .css .js
acl iphone_users hdr_sub(user-agent) -i iphone
acl android_users hdr_sub(user-agent) -i android
use_backend nginxpools if oldboy_static or oldboy_pic use_backend phppools if oldboy_php use_backend javapools if oldboy_java
default_backend nginxpools
# nginx static contents backend nginxpools balance roundrobin server oldboy_8000 192.168.1.80:8000
# php contents backend phppools balance roundrobin server oldboy_9000 192.168.1.80:9000
# java contents backend javapools balance roundrobin server oldboy_10000 192.168.1.80:10000 重启haproxy服务 /application/haproxy/bin/haproxy stop /application/haproxy/bin/haproxy start 7.3 实现haproxy基于url地址目录做7层跳转
acl oldboy_static path_beg /nginx/ #path_beg 域名后面是nginx时,把他定义为oldboy_static acl oldboy_php path_beg /php/ acl oldboy_java path_beg /resin/
use_backend nginxpools if oldboy_static #如果有oldboy_static就交给nginxpools use_backend phppools if oldboy_php use_backend javapools if oldboy_java 在真实服务器(192.168.1.80)上创建三个目录(nginx,php,resin): mkdir /var/nginx/nginx echo nginx123 > /var/nginx/nginx/index.html mkdir /var/nginx/nginx echo nginx123 > /var/nginx/nginx/index.html mkdir /var/php/php echo php123 > /var/php/php/index.html mkdir /var/resin/resin echo resin123 > /var/resin/resin/index.html 测试: 在客户机(笔记本)hosts文件加一条:192.168.1.80 nginx.yan.org php.yan.org resin.yan.org yan.org http://php.yan.org:9000/php/ http://resin.yan.org:10000/resin/ 将客户机hosts改回192.168.1.81 nginx.yan.org php.yan.org resin.yan.org yan.org 以上内容实现了: 7.4 实现haproxy基于文件扩展名做7层跳转
acl oldboy_pic path_end .gif .png .jpg .css .js use_backend nginxpools if oldboy_static or oldboy_pic 测试:在nginx目录下放三张图片nginx.jpg php.jpg resin.jpg 当访问  会访问到图片 当访问  会访问到图片(跳转到nginx目录下找resin.jpg) 7.5 实现haproxy基于user_agent做7层跳转
acl iphone_users hdr_sub(user-agent) -i iphone
acl android_users hdr_sub(user-agent) -i android 问题1:rsyslog没有生成日志文件
解决办法: 1)vim /etc/rsyslog.conf 改为 local0.* /var/log/haproxy.log 2)关闭selinux,重启rsyslog 此时/application/haproxy/logs/下会生成haproxy.log 问题2:日志文件没有记录日志,为空
解决: 编辑haproxy配置文件 vim /application/haproxy/conf/haproxy.conf 改为 log 127.0.0.1 local0 warning 8. Haproxy多种健康检查方法及实例
8.1 基于tcp端口的健康检查
使用这种检查方法,haproxy只会去检查后端server服务的对应端口,根据前面经验,我们知道这并不能保证服务的完全可用,但却可以作为辅助的检查手段,当在不是非常严格业务环境下也是可以用的,例如:前面讲解过的keepalived向下的健康检查默认就是基于端口的。对用户体验非常严格,就不要使用基于tcp端口的检查方式 8.4 基于具体业务域名的URL健康检查
基于域名的URL健康检查:实际上,可以理解为haproxy用下面的方式在访问RS节点确认是否正常来检查 这种检测方式,适用于更精细的基于具体业务的检测需求。实际上是带着head host头部信息向下健康检查 它的使用语法如下: option httpchk HEAD /index.jsp HTTP/1.1\r\nHost:\ www.yan.org根据具体业务对应的域名来进行更细化的监控。可以用HEAD和GET方式 option httpchk HEAD /index.jsp? HTTP/1.1\r\nHost:\ nginx.yan.org option httpchk GET /check.html HTTP/1.1\r\nHost:\php .yan.org 8.5 生产环境如何正确选择健康检查
1)常规业务可以使用基于tcp的方式做健康检查,我们在keepalived健康检查时就是这样做的,虽然,keepalived也支持url健康检查 2)由于基于URL的方式做健康检查相对来说也比较容易配置,所以推荐使用基于URL的健康检查 3)实际生产环境中,最重要最关键的是,我们设置的check.html能否真正的代表rs上的业务状态 4)对于用户体验比较高的业务,可以请开发人员设置更加深入的健康检查文件,例如:yan.php或yan.jsp,这个健康检查可以深入到数据库,存储及各个接口,如果之一出现异常我就摘除。 5)对于用户体验比较高的业务,除了健康检查文件更深入外,健康检查的频率、次数都要相应调整。例如:1秒检查一次,一次连不上就摘除RS
|