Haproxy的介绍和安装
Haproxy是一个开源的高性能的反向代理或者说是负载均衡服务软件之一,它支持双机热备,虚拟主机,基于TCP和HTTP应用代理等功能。配置简单,而且拥有服务器节点的健康检查功能(相当于keepalived健康检查),当后端服务器宕机时,haproxy会自动将故障服务器摘除,当服务器故障恢复后,再自动加入到集群中。
Haproxy特别在适用于那些访问量很大,但又需要会话保持或七层应用的业务。支持两种主要的代理模式:4层Tcp代理(例如邮件服务,mysql业务,ssh等)和7层(HTTP代理)。在4层tcp模式下,haproxy仅在客户端和服务器之间转发双向流量。7层模式下haproxy会分析应用层协议,并且能通过允许,拒绝,交换,增加,修改或者删除请求或者回应里指定内容来控制协议
Haproxy采用的是NAT模式,数据包来去都会经过haproxy。
Haproxy软件的4层tcp代理应用非常优秀,配置非常简单方便,比lvs和nginx要方便的多,haproxy不需要在RS端执行脚本即可实现应用代理
从上图可以看出,haproxy采用的是NAT的工作模式,网站所有流量都经过haproxy,所以适用于那些访问量不是特别大的网站,在一般的中小型公司,建议使用haproxy做负载均衡。
Haproxy最大额优点在于其7层的根据URL请求头应用过滤的功能,在门户网站的高并发生产架构中。Haproxy软件一般用在LVS软件的下一层,或挂在硬件负载均衡althon、NS、F5下使用
cd /usr/src wget http://down1.chinaunix.net/distfiles/haproxy-1.4.21.tar.gz tar zxf haproxy-1.4.21.tar.gz cd haproxy-1.4.21 make TARGET=linux26 ARCH=x86_64 make PREFIX=/usr/local/haproxy-1.4.21 install ln -s /usr/local/haproxy-1.4.21/ /usr/local/haproxy 说明: 1. make TARGET=linux26 ARCH=x86_64 是64位系统的编译方式 32位系统的编译方式为: make TARGET=linux26 ARCH=x86 2. TARGET 后面是系统内核,不同版本的linux系统,内核版本不一样。可以 more README 查看详细信息 |
默认的文件结构为:
[root@localhost haproxy]# tree
├── doc
│ └── haproxy
│ ├── architecture.txt
│ ├── configuration.txt
│ ├── haproxy-en.txt
│ └── haproxy-fr.txt
├── sbin
│ └── haproxy
└── share
└── man
└── man1
└── haproxy.1
6 directories, 6 files
现在创建 bin conf logsvar/chroot var/run等目录
cd /usr/local/haproxy mkdir -p conf bin logs var/run var/chroot
查看: [root@localhost haproxy]# tree . ├── bin ├── conf ├── doc │ └── haproxy │ ├── architecture.txt │ ├── configuration.txt │ ├── haproxy-en.txt │ └── haproxy-fr.txt ├── logs ├── sbin │ └── haproxy ├── share │ └── man │ └── man1 │ └── haproxy.1 └── var ├── chroot └── run
12 directories, 6 files |
至此,haproxy已经安装完成。配置需要我们手动创建,下面先简单进行配置,并测试
cat >/usr/local/haproxy/conf/haproxy.conf <<EOF
#####################全局配置信息######################## global chroot /usr/local/haproxy/var/chroot #chroot运行的路径 daemon #以后台进程形式运行haproxy group haproxy #运行haproxy的用户组身份为haproxy user haproxy log 127.0.0.1 local0 info #日志记录 pidfile /usr/local/haproxy/var/run/haproxy.pid #pid文件位置 maxconn 25600 #最大连接数量 nbproc 8 #开启的进程数量 #####################默认的全局设置###################### defaults log global #默认应用全局日志格式 option httplog #日志类别http日志格式 option dontlognull #不记录健康检查的日志信息 option httpclose #每次请求完毕后主动关闭http通道 retries 3 #默认健康检查失败后尝试次数 option redispatch #serverId对应的服务器挂掉后,强制定向到其他健康的服务器 option forwardfor #向后面的RS传递客户端主机头 contimeout 5000 #连接超时时间 clitimeout 50000 #客户端超时时间 单位毫秒 srvtimeout 50000 #服务器超时时间单位毫秒 ####################监控页面的设置####################### listen admin_status bind *:8080 #监控页面采用8080端口 mode http stats enable #起开网页监控页面 stats uri /admin?status #监控页面的url stats auth admin:fuzj123 #监控页面的登录用户的账户名和密码,可以有多个 stats refresh 5 #监控页面的刷新时间 stats hide-version #隐藏监控页面的版本号 ####################集群设置####################### listen webserver bind 172.16.254.37:80 #客户端访问的外网IP,若和heartbeat结合使用的话即VIP mode http #模式为http balance roundrobin #调度算法为轮训 server web1 192.168.254.10:80 check server web2 192.168.254.20:80 check |
EOF |
这为haproxy简单的配置文件,可以实现对两个web 的负载均衡调度
此外需要增加haproxy用户
useradd -M -s /sbin/nologin haproxy |
#!/bin/bash #chkconfig: 35 35 - . /etc/init.d/functions BASE="/usr/local/haproxy" 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 [ $? -eq 0 ] && { action "haproxy start is OK..." /bin/true } || action "haproxy start is error..." /bin/false ;; 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) [ $? -eq 0 ] && { action "haproxy stop is OK..." /bin/true } || action "haproxy stop is error..." /bin/false ;; *) echo "USAGE: $0 start|restart|status|stop" exit 1 ;; esac
|
把启动文件放在bin目录下,并赋予执行权限,添加开机自启动
chmod 755 haproxy echo "/usr/local/haproxy/bin/haproxy start" >> /etc/rc.local tail -1 /etc/rc.local 查看结果: /usr/local/haproxy/bin/haproxy start |
启动haproxy,并测试
/usr/local/haproxy/bin/haproxy start 启动结果: [root@localhost bin]# /usr/local/haproxy/bin/haproxy start [WARNING] 269/165754 (1791) : Proxy 'admin_status': in multi-process mode, stats will be limited to process assigned to the current request. haproxy start is OK... [确定] [root@localhost bin]# netstat -anput | grep haproxy tcp 0 0 192.168.1.104:80 0.0.0.0:* LISTEN 1792/haproxy tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 1792/haproxy udp 0 0 0.0.0.0:38073 0.0.0.0:* 1792/haproxy [root@localhost bin]# ps -aux | grep haproxy Warning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ haproxy 1792 0.0 0.6 18312 3348 ? Ss 16:57 0:00 /usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/conf/haproxy.conf haproxy 1793 0.0 0.6 18312 3348 ? Ss 16:57 0:00 /usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/conf/haproxy.conf haproxy 1794 0.0 0.6 18312 3348 ? Ss 16:57 0:00 /usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/conf/haproxy.conf haproxy 1795 0.0 0.6 18312 3348 ? Ss 16:57 0:00 /usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/conf/haproxy.conf haproxy 1796 0.0 0.6 18312 3348 ? Ss 16:57 0:00 /usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/conf/haproxy.conf haproxy 1797 0.0 0.6 18312 3348 ? Ss 16:57 0:00 /usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/conf/haproxy.conf haproxy 1798 0.0 0.6 18312 3348 ? Ss 16:57 0:00 /usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/conf/haproxy.conf haproxy 1799 0.0 0.6 18312 3348 ? Ss 16:57 0:00 /usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/conf/haproxy.conf root 1804 0.0 0.1 103244 868 pts/0 S+ 16:59 0:00 grep haproxy haproxy已经成功启动。查看发现,80端口和8080端口已经监听,而且有8个进程在系统后台。下面开始测试 [root@localhost bin]# for ((i=1;i<7;i++)) do curl 192.168.1.104 ;sleep 1 ; done <h1>this is Apache Server</h1> <h1>this is Nginx Server</h1> <h1>this is Apache Server</h1> <h1>this is Nginx Server</h1> <h1>this is Apache Server</h1> <h1>this is Nginx Server</h1>
通过curl命令返回的结果可以看出,haproxy会把客户端的访问请求依次分发到后端RS上,即轮训算法
下一步,可以通过浏览器登录haproxy的健康检查状态页面,查看RS的健康状况 http://172.16.254.37:8080/admin?status 输入账户名密码之后,即可进入状态页面 下面进行对haproxy健康检查的测试,通过监控页面的RS状态显示颜色即可看 |
这就是简单的haproxy HTTP代理。4层代理的话需要把mode模式改为tcp
Haproxy默认是不记录日志的,需要开启系统syslog功能。以便记录haproxy的相关日志。CentOS-5版本中用syslog服务来记录系统日志,到CentOS-6版本中升级成rsyslog服务。
sed -i "s/\#\$ModLoad\ imudp/\$ModLoad\ imudp/g" /etc/rsyslog.conf sed -i "s/\#\$UDPServerRun\ 514/\$UDPServerRun\ 514/g" /etc/rsyslog.conf cat >>/etc/rsyslog.conf <<EOF # Haproxy local0.* /usr/local/haproxy/logs/haproxy.log #end /etc/syslog.conf EOF service rsyslog restart
[root@localhost conf]# egrep "$ModLoad imudp|$UDPServerRun 514" /etc/rsyslog.conf | head -2 && tail -3 /etc/rsyslog.conf $ModLoad imudp $UDPServerRun 514 # Haproxy local0.* /usr/local/haproxy/logs/haproxy.log #end /etc/syslog.conf 说明: 编辑rsyslog配置文件 vim /etc/rsyslog.conf #把下面这两个前面”#”注释去掉 $ModLoad imudp $UDPServerRun 514 #在行尾添加 # Haproxy local0.* /usr/local/haproxy/logs/haproxy.log #end /etc/syslog.conf 最后重启rsyslog服务 注意: local0.*这要和haproxy配置文件中的日志格式要对应 log 127.0.0.1 local0 info
此外,selinux会限制rsyslog,当配置好之后,若重启rsyslog发现没有生成日志文件,则查看selinux是否开启状态 [root@localhost haproxy]# getenforce 查看selinux状态 Enforcing [root@localhost haproxy]# setenforce 0 临时关闭selinux 永久关闭: sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config 重启生效
生产环境下,haproxy开启记录日志的级别最好设置为warning或者error以上,此时我们设置为info,haproxy会记录客户端的访问信息,大量往磁盘中写日志信息,造成负载过大。 |
生产环境下,往往需要做haproxy的高可用,需要做主备haproxy。当主haproxy宕机之后,由备haproxy接替主haproxy继续工作。其原理是:主备都同时监听VIP,而VIP由高可用软件提供(heartbeat或keepalived等),但是正常情况下VIP在主haproxy上,由主haproxy响应客户端请求。当主haproxy宕机之后,VIP漂移到备haproxy设备上,此时,备haproxy会继续响应客户端的请求。
由此可以看出:主备haproxy的配置文件必须保持一致
主备haproxy切换过程其实就是VIP的漂移过程,VIP漂移到哪个设备上,那个设备就开始响应请求
在haproxy启动过程中,有时候会遇到下面这个错误
[root@localhost haproxy]# bin/haproxy start ^[[6~[WARNING] 269/184851 (26188) : Proxy 'admin_status': in multi-process mode, stats will be limited to process assigned to the current request. [ALERT] 269/184851 (26188) : Starting proxy webserver: cannot bind socket haproxy start is error... [失败]
解决方法:
echo "net.ipv4.ip_nonlocal_bind = 1" >> /etc/sysctl.conf sysctl -p 所以这种方法有效解决了在主备haproxy环境下,VIP不在备haproxy上时,备haproxy能正常启动的问题 由于haproxy工作模式是NAT模式,为了更好的实现转发请求,需要开启linux本身的转发功能 sed -i "s/net.ipv4.ip_forward = 0/net.ipv4.ip_forward = 1/g" /etc/sysctl.conf sysctl -p |
Haproxy支持多实例,每个实例可以有自己的单独配置文件。启动的时候用-f指定配置文件即可。下面增加一个实例,用来代理ssh服务
cat > /usr/local/haproxy/conf/haproxy-ssh.conf <<EOF global chroot /usr/local/haproxy/var/chroot daemon group haproxy user haproxy log 127.0.0.1 local0 info pidfile /usr/local/haproxy/var/run/haproxy-ssh.pid maxconn 25600 nbproc 1 defaults log global contimeout 5000 clitimeout 50000 srvtimeout 50000 listen ssh bind 192.168.1.104:999 mode tcp server ssh 192.168.1.104:22 check EOFF
启动,并查看 [root@localhost haproxy]# /usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/conf/haproxy-ssh.conf [root@localhost haproxy]# netstat -anput | grep 999 tcp 0 0 192.168.1.104:999 0.0.0.0:* LISTEN 26234/sbin/haproxy |
FAQ
Haproxy命令参数
[root@localhostsbin]# ./haproxy -h
HA-Proxyversion 1.4.21 2012/05/21
Copyright2000-2012 Willy Tarreau <[email protected]>
Usage: haproxy [-f <cfgfile>]* [ -vdVD ] [ -n <maxconn> ] [ -N<maxpconn> ]
[ -p <pidfile> ] [ -m <maxmegs> ]
-v displays version ; -vv shows knownbuild options.
-d enters debug mode ; -db onlydisables background mode.
-V enters verbose mode (disables quietmode)
-D goes daemon
-q quiet mode : don't display messages
-c check mode : only check config filesand exit
-n sets the maximum total # ofconnections (2000)
-m limits the usable amount of memory(in MB)
-N sets the default, per-proxy maximum# of connections (2000)
-p writes pids of all children to thisfile
-de disables epoll() usage even whenavailable
-ds disables speculative epoll() usageeven when available
-dp disables poll() usage even whenavailable
-sf/-st [pid ]* finishes/terminates oldpids. Must be last arguments.
译文:
haproxy -f <配置文件> [-n 最大并发连接总数] [-N 每个侦听的最大并发数] [-d] [-D] [-q] [-V] [-c][-p] [-s] [-l] [-dk] [-ds] [-de] [-dp] [-db] [-m <内存限制M>] [{-sf|-st} pidlist...]
-d 前台,debug模式
-D daemon模式启动
-q 安静模式,不输出信息
-V 详细模式
-c 对配置文件进行语法检查
-s 显示统计数据
-l 显示详细统计数据
-dk 不使用kqueue
-ds 不使用speculative epoll
-de 不使用epoll
-dp 不使用poll
-db 禁用后台模式,程序跑在前台
-sf 程序启动后向pidlist里的进程发送FINISH信号,这个参数放在命令行的最后
-st 程序启动后向pidlist里的进程发送TERMINATE信号,这个参数放在命令行的最后