0.Haproxy介绍
Haproxy是一个开源的、高性能的基干TCP和HTTP应用代理的高可用的、负载均衡服务软件,它支持双机热备、高可用、负载均衡、虚拟主机、基于TCP和HTTP的应用代理、图形界面查看信息等功能。其配置简单、维护力便,而且拥有很好的对服务器节点的健康检查功能(扩当于keepalived健康检查),当其代理的后端服务器出现故障时,Haproxy会自动的将该故障服务器摘除,当故障的服务器恢复后,Haproxy还会自功将该服务器自动加入进来提供服务。
和LVS与Nginx相比
Haproxy特别适用于那些高负载、访问量很大,但又需要会话保持及七层应用代理的业务应用。Haproxy运行在今天为普通的服务器硬件上,几乎不需要进行任何配优化就可以支持数以万计的并发连接。井且它的运行模式使得它可以很简单、轻松、安全的整合到各种已有的网站架构中,同时,Haproxy的代理模式,可以使得所有应用服务器不会暴露到公共网络上,即后面的节点服务器不需要公网IP地址。
从1.3版本起,Haproxy软件引入了frontend:backend的功能,frontend (acl规则匹配)可以让运维管理入员根据任意HTTP请求头内容做规则匹配,然后把请求定向到相关的backend〔这个是事先定义好的多个server pools,等待前端把请求转过来的服务器组〕。通过frontend和backend,我们可以很容易的实现haproxy的各种7层应用代理功能。
Haproxy支持的两种主要代理模式
- 基于4层的tcp代理(例如:可用于邮件服务,内部协议通信服务器、MySQL、https服务等)
- 基于7层的http代理。在4层tcp代理模式下,Haproxy仅在客户端和服务器之间进行流量转发,但是在7层http代理模式下,Haproxy会分析应用层协议,并且能通过允许、拒绝、交换、增加、修改或者删除请求(request)或者回应(response)里指定内容来控制协议。
- Haproxy L4负载均衡应用架构拓扑
Haproxy软件的四层tcp应用代理非常优秀,且配置非常简单、方便,比LVS和Nginx的配置要简单很多,首先,配置Haproxy不需要在RS端做任何特殊配置(只要对应服务开启就OK)就可以实现应用代理,其次,Haproxy的配置语法和增加虚拟主机功能等也比lvs/Nginx简单,并且和商业版的NS(Netscaler)、F5、A10等负载均衡硬件的使用方法和在架构中约位置一模一样,甚至老男孩曾经把haproxy配成入NS的高可用备节点。
说明:由于haproxy软件采用的是类NAT模式(本质不同)的应用代理,数据包来去都会经过haproxy,因此,在流量特别大的情况下(门户级别的流量吧),其效率和性能不如LVS的DR模式负载均衡。
在一般的中小型公司,老男孩老师建议大家采用Haproxy做负载均衡,而不要使用Lvs或Nginx,为什么强调中小型公司呢?换句话说,千万PV级别以下直接使用haproxy做负载均衡,会让我们负责维护的运维管理入员配置简单、快速、维护方便,出问题好排查。这其实就是老男孩老师常说的网站运维原则:简单、易用、高效。有关lvs、nginx、haproxy的区别,后面还会讲到。
- Haproxy L7负载均衡应用架构拓扑
Haproxy软件的最大优势在干其7层的根据URL请求头应用过滤的功能以及session会话功能,在门户网站的高并发生产架构中,haproxy软件一般用在4层LVS负载均衡软件的下一层,或者象haproxy官方推荐为也可以挂在硬件负载均衡althon、NS、F5、A10下使用,其表现非常好。从2009年起淘宝网,京东商城的业务也大面积使用了haproxy作为7层CACHA应用代理。
- haproxy服务安装
cd /server/tools/
wget http://www.haproxy.org/download/1.5/src/haproxy-1.5.18.tar.gz
tar zxvf haproxy-1.5.18.tar.gz
cd haproxy-1.5.18
make TARGET=linux2628 ARCH=x86_64
make install PREFIX=/usr/local/haproxy
sed -i ‘s#net.ipv4.ip_forward = 0#net.ipv4.ip_forward = 1#g’ /etc/sysctl.conf
sysctl -p
cd /usr/local/haproxy/
mkdir -p bin conf logs var/run var/chroot rrorfiles
注:haproxy作为代理,可以不用开启转发,但lvs的NAT模式需要开启。
- haproxy的配置文件说明
haproxy.cfg配置文件可以分五部分:
globa1:全局配置参数段,主要用来控制Haproxy启动前的进程及系统相关设置。
defaults:配置一些默认参数,如果frontend,backend,listen等段未设置则使用defaults段配置。
11sten:
frontend:用来匹配接收客户所请求的域名,uri等,并针对不同的匹配,做不同的请求处理。
backend:定义后端服务器集群,以及对后端服务器的一些权重、队列、连接数等选项的设置。
haproxy.cfg配置文件详解
vi /usr/local/haproxy/conf/haproxy.cfg
global # 全局参数的设置
log 127.0.0.1 local0 warning # log语法:log <address_1>[max_level_1] # 全局的日志配置,使用log关键字,指定使用127.0.0.1上的syslog服务中的local0日志设备,记录日志等级为warning的日志
chroot /usr/local/haproxy/var/chroot #改变当前工作目录
pidfile /usr/local/haproxy/var/run/haproxy.pid #当前进程id文件
maxconn 4000 #最大连接数
user haproxy #所属用户
group haproxy #所属组
daemon #以守护进程方式运行haproxy
stats socket /var/lib/haproxy/stats
defaults
mode http #默认的模式mode { tcp|http|health },tcp是4层,http是7层,health只会返回OK
log global #应用全局的日志配置
option httplog # 启用日志记录HTTP请求,默认haproxy日志记录是不记录HTTP请求日志
option dontlognull # 启用该项,日志中将不会记录空连接。所谓空连接就是在上游的负载均衡器或者监控系统为了探测该服务是否存活可用时,需要定期的连接或者获取某一固定的组件或页面,或者探测扫描端口是否在监听或开放等动作被称为空连接;官方文档中标注,如果该服务上游没有其他的负载均衡器的话,建议不要使用该参数,因为互联网上的恶意扫描或其他动作就不会被记录下来
option http-server-close #每次请求完毕后主动关闭http通道
option forwardfor except 127.0.0.0/8 #如果服务器上的应用程序想记录发起请求的客户端的IP地址,需要在HAProxy上配置此选项,这样HAProxy会把客户端的IP信息发送给服务器,在HTTP请求中添加”X-Forwarded-For”字段。 启用 X-Forwarded-For,在requests头部插入客户端IP发送给后端的server,使后端server获取到客户端的真实IP。
option redispatch # 当使用了cookie时,haproxy将会将其请求的后端服务器的serverID插入到cookie中,以保证会话的SESSION持久性;而此时,如果后端的服务器宕掉了,但是客户端的cookie是不会刷新的,如果设置此参数,将会将客户的请求强制定向到另外一个后端server上,以保证服务的正常。
retries 3 # 定义连接后端服务器的失败重连次数,连接失败次数超过此值后将会将对应后端服务器标记为不可用
timeout http-request 10s #http请求超时时间
timeout queue 1m #一个请求在队列里的超时时间
timeout connect 10s #连接超时
timeout client 1m #客户端超时
timeout server 1m #服务器端超时
timeout http-keep-alive 10s #设置http-keep-alive的超时时间
timeout check 10s #检测超时
maxconn 3000 #每个进程可用的最大连接数
frontend main *:80 #监听地址为80
acl url_static path_beg -i /static /images /javascript /stylesheets
acl url_static path_end -i .jpg .gif .png .css .js
use_backend static if url_static
default_backend my_webserver #定义一个名为my_app前端部分。此处将对于的请求转发给后端
backend static #使用了静态动态分离(如果url_path匹配 .jpg .gif .png .css .js静态文件则此后端)
balance roundrobin #负载均衡算法(#banlance roundrobin 轮询,balance source 保存session值,支持static-rr,leastconn,first,uri等参数)
server static 127.0.0.1:80 check 本机(也可以部署在其他机器或者squid缓存服务器)
backend my_webserver #定义一个名为my_webserver后端部分。PS:此处my_webserver只是一个自定义名字而已,但是需要与frontend里面配置项default_backend 值相一致
balance roundrobin #负载均衡算法
server web01 172.31.2.33:80 check inter 2000 fall 3 weight 30 #定义的多个后端
server web02 172.31.2.34:80 check inter 2000 fall 3 weight 30 #定义的多个后端
server web03 172.31.2.35:80 check inter 2000 fall 3 weight 30 #定义的多个后端
启动haproxy
/usr/local/haproxy/sbin/haproxy –help #查看帮助
/usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/conf/haproxy.cfg -c检查
/usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/conf/haproxy.cfg -D
- haproxy日志配置
配置rsyslog接受loca10设备的所有日志,写入到/usr/local/haproxy/logs/haproxy.log
cat >> /etc/rsyslog.conf <<EOF
#Haproxy
local0.* /usr/local/haproxy/logs/haproxy.log
#end /etc/rsyslog.conf
EOF
vi /etc/sysconfig/rsyslog
SYSLOGD_OPTIONS=”-c 2 -m 0 -r -x”
重启rsyslog
/etc/init.d/rsyslog restart
开启rsyslog日志端口配置
vi /etc/rsyslog.conf
$ModLoad imudp
$UDPServerRun 514
重启haproxy查看日志
如果开启了selinux,则有可能不会有日志,需要关闭selinux
- cfg配置文件配置
vi /usr/local/haproxy/conf/haproxy.cfg
# this config needs haproxy-1.1.28 or haproxy-1.2.1
global
log 127.0.0.1 local0 warning
#log loghost local0 info
maxconn 4096
chroot /data/haproxy/var/chroot
user haproxy
group haproxy
daemon
nbproc 4
#debug
#quiet
defaults
log global
mode http
option httplog
option dontlognull
retries 3
option redispatch
maxconn 2000
timeout connect 5000
timeout client 50000
timeout server 50000
listen www
bind *:80
mode http
no option splice-response
stats enable
stats uri /stats
stats auth admin:dingdingjinfu
balance roundrobin
option forwardfor
option httpclose
server www01 114.55.151.155:8000 cookie 1 maxconn 1024 weight 3 check port 8000 inter 2000 rise 3 fall 3
server www02 114.55.151.155:8001 cookie 2 maxconn 1024 weight 3 check port 8001 inter 2000 rise 3 fall 3
server www03 114.55.151.155:8002 cookie 3 maxconn 1024 weight 3 check port 8002 inter 2000 rise 3 fall 3
- haproxy启动脚本
[root@cacti ~]# vim /etc/init.d/haproxy
#!/bin/bash
# chkconfig: 35 85 15
# description: HAProxy is a free, very fast and reliable solution \
# offering high availability, load balancing, and \
# proxying for TCP and HTTP-based applications
# processname: haproxy
# config: /etc/haproxy.cfg
# pidfile: /var/run/haproxy.pid
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ “$NETWORKING” = “no” ] && exit 0
config=”/etc/haproxy.cfg”
exec=”/usr/local/haproxy/sbin/haproxy”
prog=$(basename $exec)
[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog
lockfile=/var/lock/subsys/haproxy
check() {
$exec -c -V -f $config
}
start() {
$exec -c -q -f $config
if [ $? -ne 0 ]; then
echo “Errors in configuration file, check with $prog check.”
return 1
fi
echo -n $”Starting $prog: ”
# start it up here, usually something like “daemon $exec”
daemon $exec -D -f $config -p /var/run/$prog.pid
retval=$?
echo
[ $retval -eq 0 ] && touch $lockfile
return $retval
}
stop() {
echo -n $”Stopping $prog: ”
# stop it here, often “killproc $prog”
killproc $prog
retval=$?
echo
[ $retval -eq 0 ] && rm -f $lockfile
return $retval
}
restart() {
$exec -c -q -f $config
if [ $? -ne 0 ]; then
echo “Errors in configuration file, check with $prog check.”
return 1
fi
stop
start
}
reload() {
$exec -c -q -f $config
if [ $? -ne 0 ]; then
echo “Errors in configuration file, check with $prog check.”
return 1
fi
echo -n $”Reloading $prog: ”
$exec -D -f $config -p /var/run/$prog.pid -sf $(cat /var/run/$prog.pid)
retval=$?
echo
return $retval
}
force_reload() {
restart
}
fdr_status() {
status $prog
}
case “$1″ in
start|stop|restart|reload)
$1
;;
force-reload)
force_reload
;;
checkconfig)
check
;;
status)
fdr_status
;;
condrestart|try-restart)
[ ! -f $lockfile ] || restart
;;
*)
echo $”Usage: $0 {start|stop|status|checkconfig|restart|try-restart|reload|force-reload}”
exit 2
esac
- Haproxy多种健康检查方法及实例
- 基于TCP的健康检查
使用这种检测方式,haproxy只会去检查后端server服务的对应端口,根据前面的经验,我们知道这并不能保证节点服务的完全可用,但却可以作为辅助的检查手段,不是非常严格业务环境下也是可以用的,例如:前不讲解过的keepalivd向下的健康检查默认就是基于端口的。对用户体验非常严格.就不要使用基于TCP瑞口的健康检查方案。
server www01 192.168.80.103:8080 check port 8080 inter 2000 rise 3 fall 3
server www02 192.168.80.105:80 check port 80 inter 2000 rise 3 fall 3
check port 80表示对80端口进行检查,也可以写成check
inter 2000表示每2s进行一次检查
rise 3表示在RS宕机恢复前如果3次检查都正常,认为其复活,并接入集群组中
fall 3表示检查3次,如果检查都不正常则认为其宕机,踢出集群组
- 基于HTTP直接IP URL方式的健康检查
httpchk帮助文档
option httpchk
option httpchk <uri>
option httpchk <method> <uri>
option httpchk <method> <uri> <version>
Enable HTTP protocol to check on the servers health
May be used in sections : defaults | frontend | listen | backend
yes | no | yes | yes
第一种:HEAD配置方法
option httpchk HEAD /check.html HTTP/1.0
server www01 192.168.80.103:8080 check port 8080 inter 2000 rise 3 fall 3
server www02 192.168.80.105:80 check port 80 inter 2000 rise 3 fall 3
注意:此时RS节点站点目录下必须要存在/check.html文件,默认会屏蔽下边节点端口的检查
第二种:GET配置方法
option httpchk GET /index.html
server www01 192.168.80.103:8080 check port 8080 inter 2000 rise 3 fall 3
server www02 192.168.80.105:80 check port 80 inter 2000 rise 3 fall 3
- 基于具体业务域名的URL健康检查
基于域名的URI健康检查:实际上,可以理解为haproxy用下面的方式在访问RS节点确认是否正常来检查。
curl http://www.etiantian.org/index.jsp或wget http://www.etiantian.org/index.jsp方式
这种检测方式,适用于更精细的基于具体业务的监测需求。实际上是带着head host头部信息向下健康检查,它的使用语法如下:
option httpchk HEAD /index.jsp HTTP/1.1\r\nHost:\ www.etiantian.org
- 其他服务的健康检查
option mysql-check [ user <username> [ post-41 ] ]
Use MySQL health checks for server testing
option ldap-check
Use LDAPv3 health checks for server testing
option log-health-checks
no option log-health-checks
Enable or disable logging of health checks status updates
- 生产环境如何正确选择健康检查方式
特别强调:本节内容适用于所有负载均衡软件的的健康检查。
l)常规业务可以使用基于TCP的方式做健康检查,我们在keepalived健康检查时就是这样做的,虽然keepalived也支持url健康检查。
2)由于基于URL的方式做健康检查相对来说也比较容易配置,所以,老男孩老师更推荐障用基于URL的健康检查。
可以用http://1O.O.O.8/check.html的方式,也可以使用基于域名的http://www.etiantian.org/check.html的方式,后者更高级一些。
3)实际生产环境中,最重要最关键的是,我们设置的check.html能否真正的代表rs上的业务状态,即访问check.html正常,整个业务是否正常,这个是需要我们运维及开发人员一去分析的
4)对于用户体验比较高的业务,可以请开发人员设置更加深入的健康检查文件,例如:oldboy.php或oldboy.jsp,这个健康检查可以深入到数据库,存储及各个接口,如果之一出现异常我就摘除,到底如何做还是需要去思考的,实际工作中不是做的越高级越好,根据业务需求达到要求就是可以的。
5)对于用户体验比较高的业务,除了健康检查文件更深入外,健康检查的频率、次数都要相应调整。例如:1秒检查一次,一次连不上就摘除RS,其实,这未必是是最好的策略,尤其是服务器节点少的时候,可能会导致haproxy后端瞬间全部被摘除的问题发生。