详细讲解:http://freeloda.blog.51cto.com/2033581/1294094
HAProxy提供高可用性、负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费、快速并且可靠的一种解决方案。HAProxy特别适用于那些负载特大的web站点,这些站点通常又需要会话保持或七层处理。HAProxy运行在当前的硬件上,完全可以支持数以万计的并发连接。并且它的运行模式使得它可以很简单安全的整合进您当前的架构中,同时可以保护你的web服务器不被暴露到网络上。
HAProxy实现了一种事件驱动, 单一进程模型,此模型支持非常大的并发连接数。多进程或多线程模型受内存限制、系统调度器限制以及无处不在的锁限制,很少能处理数千并发连接。事件驱动模型因为在有更好的资源和时间管理的用户端(User-Space)实现所有这些任务,所以没有这些问题。此模型的弊端是,在多核系统上,这些程序通常扩展性较差。这就是为什么他们必须进行优化以使每个CPU时间片(Cycle)做更多的工作。
拓扑介绍:前端两台服务器提供高可用和haproxy,,后端有动态和静态服务器组,haproxy将动态和静态页面请求分发到不同的服务器上;在测试情况下有异常发生,当跟踪的脚本失败后,没有按照预定的动作执行;但有一点是可以肯定的,当一台服务器宕机后,服务可以正常提供;由MASTER上的keepalived提供VIP和后端服务器的网关;(在本例中用不到后端服务器网关,因为后端服务器只需与代理服务器交互,它们是在同一个网段的,不需要网关。本例中给出配置,以备不时之需)
一、keepalived配置:(配置选项含义请参考上篇)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | [root@node1 keepalived] # cat keepalived.conf ! Configuration File for keepalived global_defs {
notification_email {
root@localhost
}
notification_email_from ClusterAdmin@magedu.com
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id Node1 }
vrrp_script chk_state_down {
script "[ -f /etc/keepalived/down ] && exit 1 || exit 0"
interval 1
weight 30 }
vrrp_script chk_Haproxy {
script "killall -0 haproxy"
interval 1
fall 2
rise 1
weight 30 } vrrp_instance Haproxy {
state MASTER
interface eth0
virtual_router_id 10
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass Haproxy
}
virtual_ipaddress {
172.16.1.100
}
track_script {
chk_Haproxy
chk_state_down
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault" } vrrp_instance Gateway {
state MASTER
interface eth1
virtual_router_id 20
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass Gateway
}
virtual_ipaddress {
192.168.10.250
}
track_script {
chk_Haproxy
chk_state_down
} } [root@node2 keepalived] # cat keepalived.conf ! Configuration File for keepalived global_defs {
notification_email {
root@localhost
}
notification_email_from ClusterAdmin@magedu.com
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id Node2 }
vrrp_script chk_state_down {
script "[[ -f /etc/keepalived/down ]] && exit 1 || exit 0"
interval 1
weight 10 }
vrrp_script chk_Haproxy {
script "killall -0 haproxy"
interval 1
fall 2
rise 1
weight 10 } vrrp_instance Haproxy {
state BACKUP
interface eth0
virtual_router_id 10
priority 95
advert_int 1
authentication {
auth_type PASS
auth_pass Haproxy
}
virtual_ipaddress {
172.16.1.100
}
track_script {
chk_Haproxy
chk_state_down
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault" } vrrp_instance Gateway {
state BACKUP
interface eth1
virtual_router_id 20
priority 95
advert_int 1
authentication {
auth_type PASS
auth_pass Gateway
}
virtual_ipaddress {
192.168.10.250
}
track_script {
chk_Haproxy
chk_state_down
} } [root@node2 keepalived] # cat notify.sh #!/bin/bash # vip=172.16.1.100 contact= 'root@localhost' notify () {
mailsubject= "`hostname` became to $1 , $vip floated."
mailbody= "`date +" %F %T "`: vrrp status changed. `hostname` became $1"
echo $mailbody | mail -s "$mailsubject" $contact } case $1 in
master)
notify master ;;
backup)
notify backup;;
fault)
notify fault ;;
*)
echo "Usage: `basename $0` {master|backup|fault}"
exit 1;; esac |
二、Haproxy配置分析:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | global
chroot /var/haproxy #chroot运行的路径,增加安全性
uid 99 #程序运行的用户id
gid 99 #程序运行的用户组id
daemon #以后台形式运行haproxy
nbproc 1 #number of process进程数量,不建议修改
pidfile /var/run/haproxy .pid #haproxy的pid存放路径
maxconn 4000 #默认最大连接数 defaults
mode http ;工作模式
option dontlognull
log global;记录日志
option http-server-close ;启用服务器端关闭
option forwardfor except 127.0.0.0 /8 ;传递客户端ip
option redispatch ;当服务器组中的某台设备故障后,自动将请求重定向到组内其他主机。
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;同时处理的最大连接数
errorfile 403 /etc/haproxy/errorfiles/403 .http
errorfile 500 /etc/haproxy/errorfiles/500 .http
errorfile 502 /etc/haproxy/errorfiles/502 .http
errorfile 503 /etc/haproxy/errorfiles/503 .http
errorfile 504 /etc/haproxy/errorfiles/504 .http Haproxy 负载均衡实例: frontend webserver
bind 172.16.1.100:80
default_backend webservers backend webservers
balance roundrobin
server node3.magedu.com 192.168.10.3:80 check
server node4.magedu.com 192.168.10.4:80 check 或者 listen webservers
bind 172.16.1.100:80
server node3.magedu.com 192.168.10.3 check
server node4.magedu.com 192.168.10.4 check 启用stats查看,认证等功能: 默认在 /haproxy ?stats
listen stas
bind 172.16.1.100:1099;监听的地址和端口
stats enable ;启用状态监控
stats hide-version;隐藏软件版本号
stats auth admin:admin;登陆用户名和密码
stats realm HAproxy\ stats;提示信息,空格之前加\
stats admin if TRUE;当通过认证才可管理
stats uri /stats ;访问路径
stats refresh 5;页面自动刷新间隔 |
效果如下:
登录成功后:
调度算法:
动态算法:
支持动态调整权重,可以在运行中调整而不用重启服务;
支持慢速启动(在刚开机时不起作用);
roundrobin 轮调
leastconn 最少连接
source
hash-type : consistent 一致性哈希算法,
静态算法:
支持权重,不支持动态调整,调整后需重启服务;
static-rr
source
hash-type :map-based:将source IP进行hash后,对后端服务器的个数取余算法;
uri 根据uri分配服务器,适用于后端是缓存服务器;也支持2种hash-type;同source算法;还支持参数,len # 和depth # ,用法如下
balance uri [len <len>][depth <depth>]
URL syntax:
<scheme>://<user>:<password>@<host>:<port>/path;<params>?<query>#<frag>
url_param
常用于跟踪用户id,将具有特定的用户标示的GET请求发往特定的服务器;默认是静态算法,用hash-type修改;用法如下;
balance url_param <param>[check_post [<max_wait>]]
balance url_paramuserid
balance url_param session_id check_post 64
hdr,根据请求头部中的字段进行调度;
balancehdr(User-Agent)
balance hdr(host)
balance hdr(Host) use_domain_only
自定义日志输出位置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
frontend web
bind 172.16.1.100:80
default_backend webservers
log global
log 127.0.0.1:514 local2 info
option httplog 定义local2的记录位置:启用UDP syslog [root@node1 ~] # vi /etc/rsyslog.conf
# Provides UDP syslog reception
$ModLoad imudp
$UDPServerRun 514 # Log anything (except mail) of level info or higher. # Don't log private authentication messages!,添加local2.none *.info;mail.none;authpriv.none; cron .none;local2.none /var/log/messages 添加一行,自定义日志存放位置: local2.* /var/log/haproxy .log 然后重启syslog服务; [root@node1 ~] # service rsyslog restart 查看日志情况 [root@node1 ~] # tail /var/log/haproxy.log Sep 29 19:47:17 localhost haproxy[2847]: 172.16.254.52:53660 [29 /Sep/2013 :19:47:17.861] web webservers /node3 .magedu.com 9 /0/0/1/10 200 267 - - ---- 3 /3/0/1/0 0 /0 "GET /4.html HTTP/1.1" Sep 29 19:47:17 localhost haproxy[2847]: 172.16.254.52:53660 [29 /Sep/2013 :19:47:17.861] web webservers /node3 .magedu.com 9 /0/0/1/10 200 267 - - ---- 3 /3/0/1/0 0 /0 "GET /4.html HTTP/1.1" 在后端real server上记录真实客户端IP地址: 修改apache配置文件中日志格式,修改为: LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined 效果为: 172.16.254.52 - - [29 /Sep/2013 :14:30:44 +0800] "GET / HTTP/1.1" 200 50485 "-" "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36" |
Haproxy中ACL的使用:
acl <aclname> <criterion> [flags] [operator] <value> ...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | dst <ip_address> dst_port <port> src <ip_address> src_port <port> e.g. #用法一、允许10.0.0.0/24的用户访问,其他用户将禁止 acl goodguys src 10.0.0.0 /24 tcp-request content accept if goodguys tcp-request content reject tcp-request content accept [{ if | unless} <condition>] Accept a connection if /unless a content inspection condition is matched #用法二、将源IP为172.16.254.52的用户禁止、将403的错误重定向到其他服务器; acl badguy src 172.16.254.52 block if badguy errorloc 403 http: //www .afwing.com/ #用法三、当用户访问172.16.1.100时,重定向到http://www.afwing.com acl dstipaddr hdr(Host) 172.16.1.100 redirect location http: //www .afwing.com if dstipaddr #用法四、读写分离: acl read method GET acl read method HEAD acl write method PUT acl write method POST use_backend imgservers if read use_backend uploadservers if write #用法五、限制某个IP访问的路径(文件) acl badguy src 172.16.254.52 acl denyfile path /index .html http-request deny if denyfile badguy #用法六、动静分离 acl url_static path_beg -i /static /p_w_picpaths /javascript /stylesheets acl url_static path_end -i .jpg .gif .png .css .js #或者 acl url_static path_end -i .jpg$ .gif$ .png$ .css$ .js$ #或者 acl url_static hdr_beg(host) -i www acl url_static hdr_beg(host) -i news. video. download. ftp . use_backend static if url_static default_backend app backend static
balance roundrobin
server static 192.168.10.1:80 check maxconn 6000
server static 192.168.10.2:80 check maxconn 6000 backend app
balance roundrobin
server app1 192.168.10.3:80 check maxconn 1000
server app2 192.168.10.4:80 check maxconn 1000 #Additional examples acl invalid_src src 0.0.0.0 /7 224.0.0.0 /3 acl invalid_src src_port 0:1023 acl local_dst hdr(host) -i localhost Move the login URL only to HTTPS. acl clear dst_port 80 acl secure dst_port 8080 acl login_page url_beg /login acl logout url_beg /logout acl uid_given url_reg /login ?userid=[^&]+ acl cookie_set hdr_sub(cookie) SEEN=1 redirect prefix https: //mysite .com set -cookie SEEN=1 if !cookie_set redirect prefix https: //mysite .com if login_page !secure redirect prefix http: //mysite .com drop-query if login_page !uid_given redirect location http: //mysite .com/ if !login_page secure redirect location / clear -cookie USERID= if logout |
server和default-server options:
backup :当后端服务器都发生故障时,由backup服务器发送错误页面:
在haproxy服务器上启动http服务以apache为例,监听在127.0.0.1的某个端口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | [root@node1 haproxy] # vi /etc/httpd/conf/httpd.conf Listen 127.0.0.1:8888 [root@node1 haproxy] # service httpd restart Stopping httpd: [ OK ] Starting httpd: [ OK ] [root@node1 haproxy] # vi /var/www/html/index.html <h1> Sorry,our site is not in service. Please try again later. < /h1 > [root@node1 haproxy] # vi /etc/haproxy/haproxy.cfg
frontend web
bind 172.16.1.100:80
default_backend webservers
log 127.0.0.1:514 local2 info
option httplog
option forwardfor except 127.0.0.0 /8
rspadd x-via:\ 172.16.1.1
backend webservers
balance uri
hash - type map-based
server node3.magedu.com 192.168.10.3:80 check weight 3
server node4.magedu.com 192.168.10.4:80 check weight 1
server backup.magedu.com 127.0.0.1:8888 backup |
在stats页面中将后端服务器禁用
结果就是:
fall:<count> 检测失效的次数;
inter <delay> 检测的间隔
disabled 手动禁用服务器
maxconn <count>最大连接数
observe <mode> “layer4”“layer7”观察模式
redir <prefix> 只能重定向HEAD和GET
# server node4.magedu.com 192.168.10.4:80 check weight 1 redir http://www.afwing.com
rise <count>检测多少次才算是成功;
slowstart 支持慢启动,第一次启动时不算;
weight 权重
monitor-uri,通过访问monitor-uri显示集群总体状况,
1 2 3 4 5 6 7 8 | frontend www
mode http
acl site_dead nbsrv(appservers) lt 2
monitor-uri /test .html
monitor fail if site_dead backend appservers
server node4.magedu.com 192.168.10.4:80 check
server node3.magedu.com 192.168.10.3:80 check |
下图所示,当后端主机少于2台时的状况。(可以通过手动disable后端一台主机查看情况)
当后端主机大于2台时:
更多信息请参考官方主站:http://cbonte.github.io/haproxy-dconv/configuration-1.4.html
我的配置:
global
#log 127.0.0.1 local0
log 127.0.0.1 local3
#log loghost local0 info
maxconn 4096
chroot /usr/local/haproxy
uid nobody
gid nobody
daemon
#debug
#quiet
nbproc 2
pidfile /usr/local/haproxy/run/haproxy.pid
defaults
log global
mode http
option httplog
option dontlognull
retries 3
option redispatch
maxconn 2000
contimeout 5000
clitimeout 50000
srvtimeout 50000
listen http_80_in 0.0.0.0:80
mode http
option httpchk GET /index.html HTTP/1.0\n\nHost:10.0.2.90
# appli1-rewrite 0.0.0.0:10001
#cookie SERVERID rewrite
balance roundrobin
server app1_1 10.0.2.203:80 check inter 2000 rise 2 fall 5
server app1_2 10.0.2.202:80 check inter 2000 rise 2 fall 5
#server app1_3 10.0.2.202:8080 cookie app1inst3 check inter 2000 rise 2 fall 5
#server app1_4 10.0.2.202:8080 cookie app1inst4 check inter 2000 rise 2 fall 5
listen stats 0.0.0.0:1080
mode http
transparent
stats uri / haproxy-admin
stats realm Haproxy \ statistic
stats auth test:123456