详细讲解:http://freeloda.blog.51cto.com/2033581/1294094

HAProxy提供高可用性、负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费、快速并且可靠的一种解决方案。HAProxy特别适用于那些负载特大的web站点,这些站点通常又需要会话保持或七层处理。HAProxy运行在当前的硬件上,完全可以支持数以万计的并发连接。并且它的运行模式使得它可以很简单安全的整合进您当前的架构中,同时可以保护你的web服务器不被暴露到网络上。


HAProxy实现了一种事件驱动, 单一进程模型,此模型支持非常大的并发连接数。多进程或多线程模型受内存限制、系统调度器限制以及无处不在的锁限制,很少能处理数千并发连接。事件驱动模型因为在有更好的资源和时间管理的用户端(User-Space)实现所有这些任务,所以没有这些问题。此模型的弊端是,在多核系统上,这些程序通常扩展性较差。这就是为什么他们必须进行优化以使每个CPU时间片(Cycle)做更多的工作。


拓扑介绍:前端两台服务器提供高可用和haproxy,,后端有动态和静态服务器组,haproxy将动态和静态页面请求分发到不同的服务器上;在测试情况下有异常发生,当跟踪的脚本失败后,没有按照预定的动作执行;但有一点是可以肯定的,当一台服务器宕机后,服务可以正常提供;由MASTER上的keepalived提供VIP和后端服务器的网关;(在本例中用不到后端服务器网关,因为后端服务器只需与代理服务器交互,它们是在同一个网段的,不需要网关。本例中给出配置,以备不时之需)

Haproxy配置详解_Haproxy



一、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 forkeepalived
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 forkeepalived
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}"
exit1;;
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 ifTRUE;当通过认证才可管理
stats uri /stats;访问路径
stats refresh 5;页面自动刷新间隔

效果如下:

Haproxy配置详解_解决方案_02

登录成功后:

Haproxy配置详解_配置详解_03

调度算法:

动态算法:

支持动态调整权重,可以在运行中调整而不用重启服务;

支持慢速启动(在刚开机时不起作用);

roundrobin 轮调

leastconn 最少连接

source

hash-type : consistent 一致性哈希算法,

静态算法:

支持权重,不支持动态调整,调整后需重启服务;

static-rr

source

hash-type map-based:将source IP进行hash后,对后端服务器的个数取余算法;

uri 根据uri分配服务器,适用于后端是缓存服务器;也支持2hash-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/10200 267 - - ---- 3/3/0/1/00/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/10200 267 - - ---- 3/3/0/1/00/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  ifgoodguys
tcp-request  content  reject
tcp-request content accept [{if| unless} <condition>]
Accept a connection if/unlessa content inspection condition is matched
#用法二、将源IP为172.16.254.52的用户禁止、将403的错误重定向到其他服务器;
acl  badguy  src  172.16.254.52
block ifbadguy
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 ifdstipaddr
#用法四、读写分离:
acl  readmethod GET
acl  readmethod HEAD
acl write method PUT
acl write method POST
use_backend imgservers ifread
use_backend uploadservers ifwrite
#用法五、限制某个IP访问的路径(文件)
acl  badguy  src  172.16.254.52
acl  denyfile  path  /index.html
http-request deny ifdenyfile  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          ifurl_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/7224.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 cleardst_port  80
acl secure     dst_port  8080
acl login_page url_beg   /login
acl logouturl_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           iflogin_page !secure
redirect prefix   http://mysite.com drop-query iflogin_page !uid_given
redirect location http://mysite.com/           if!login_page secure
redirect location / clear-cookie USERID=       iflogout



serverdefault-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 inservice.
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-typemap-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页面中将后端服务器禁用

Haproxy配置详解_解决方案_04

结果就是:

Haproxy配置详解_配置详解_05


fall<count> 检测失效的次数;

inter <delay> 检测的间隔

disabled 手动禁用服务器

maxconn <count>最大连接数

observe <mode> layer4”“layer7”观察模式

redir <prefix> 只能重定向HEADGET

# server node4.magedu.com 192.168.10.4:80 check weight 1 redir http://www.afwing.com


Haproxy配置详解_配置详解_06


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 ifsite_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后端一台主机查看情况)

Haproxy配置详解_解决方案_07

当后端主机大于2台时:

Haproxy配置详解_解决方案_08


更多信息请参考官方主站: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