|
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时会在两台主机之间相互轮询切换
轮询访问结果测试
for((i=0;i /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
Options FollowSymLinks
AllowOverride none
Order allow,deny
Allow from all
NameVirtualHost *:8000
NameVirtualHost *:9000
NameVirtualHost *:10000
ServerAdmin 824412801@qq.com
ServerName nginx.yan.org
ServerAlias yan.org
DocumentRoot "/var/nginx"
ServerAdmin 824412801@qq.com
ServerName php.yan.org
DocumentRoot "/var/php"
ServerAdmin 824412801@qq.com
ServerName resin.yan.org
DocumentRoot "/var/resin"
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
#prefix °×× ±¤·http://yan.org/a.html×http://nginx.yan.org/a.html
redirect prefix http://nginx.yan.org:8000 code 301 if short_dom
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
redirect prefix http://3g-iphone.yan.org if iphone_users
acl android_users hdr_sub(user-agent) -i android
redirect prefix http://3g-android.yan.org/ if android_users
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
此时笔记本打开浏览器访问http://yan.org:8000 会跳转到http://nginx.yan.org:8000
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://nginx.yan.org:8000/nginx/
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
浏览器访问http://nginx.yan.org/nginx/得到的结果为nginx123,说明跳转成功
以上内容实现了:
访问http://nginx.yan.org/nginx/ ==>nginxpools后端处理
访问http://nginx.yan.org/php/ ==>phppools后端处理
访问http://nginx.yan.org/resin/ ==>resinpools后端处理
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
当访问http://nginx.yan.org/nginx.jpg 会访问到图片
当访问http://resin.yan.org/resin.jpg 会访问到图片(跳转到nginx目录下找resin.jpg)
7.5 实现haproxy基于user_agent做7层跳转
acl iphone_users hdr_sub(user-agent) -i iphone
redirect prefix http://3g-iphone.yan.org if iphone_users
acl android_users hdr_sub(user-agent) -i android
redirect prefix http://3g-android.yan.org/ if android_users
问题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节点确认是否正常来检查
curl http://www.yan.org/index.jsp 或 wget http://www.yan.org/index.jsp 方式
这种检测方式,适用于更精细的基于具体业务的检测需求。实际上是带着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的健康检查
可以使用http://192.168.1.80/check.html的方式,也可以使用基于域名的http://www.yan.org/html方式,后者更高级一些
3)实际生产环境中,最重要最关键的是,我们设置的check.html能否真正的代表rs上的业务状态
4)对于用户体验比较高的业务,可以请开发人员设置更加深入的健康检查文件,例如:yan.php或yan.jsp,这个健康检查可以深入到数据库,存储及各个接口,如果之一出现异常我就摘除。
5)对于用户体验比较高的业务,除了健康检查文件更深入外,健康检查的频率、次数都要相应调整。例如:1秒检查一次,一次连不上就摘除RS
|
|
|