Haproxy其他功能及配置

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介:

下面了解一下haproxy的其他功能设置,多是一些生产环境中常用的功能设置,所以列举如下。

一、haproxy健康检查

1、基于HEAD的检查方法

写法:

option httpchk HEAD /a.html HTTP/1.0

相当于curl http://*.*.*.*/a.html, 如果a.html不存在,即使http服务正常也会提示服务器不可用。

wKiom1fuogPiAQNyAAK1Dp4KTtQ418.png-wh_50

两个节点的状态原本都是正常的。

下面修改一下配置文件,内容添加httpchk一项:

1
2
3
4
5
6
7
listenwebsites
         bind  192.168.100.121:80
         option  httpchk HEAD  /check .html HTTP /1 .0
         timeout  server  15s
         timeout  connect 30s
         server  mylinux3  192.168.100.181:80 check port 80 inter 2000 fall 3
         server  mylinux4  192.168.100.182:80 check port 80 inter 2000 fall 3

再次查看服务器的状态:

wKioL1fuogeTUTGiAAKuIIlzPPk615.png-wh_50

发现两个Server都是宕机的状态。

wKiom1fuogrCnPmmAAFDguMoL7w956.png-wh_50

wKioL1fuogyCx9JtAAFAyCCFUjE731.png-wh_50

然而两个服务器的http服务都是正常的,只是没有check.html这个页面。

1
[root@mylinux3 ~] # echo check >>/var/www/html/check.html

在mylinux3上生成check.html这个页面,再次查看监控界面:

wKiom1fuoviB9ydFAAKS9v4ukc8327.png-wh_50

发现mylinux3的状态已经恢复,说明httpchk作用正常。

2、基于GET的检查方法

写法:

option httpchk GET /a.txt

相当于wget http://*.*.*.*/a.txt,如果a.txt不存在,则即使httpd服务正常也会提示服务不可用。

配置示例:

1
2
3
4
5
6
7
8
listenwebsites
         bind  192.168.100.121:80
         option   httpchk GET  /info .txt
         #option  httpchk HEAD /check.html HTTP/1.0
         timeout  server  15s
         timeout  connect 30s
         server  mylinux3  192.168.100.181:80 check port 80 inter 2000 fall 3
         server  mylinux4  192.168.100.182:80 check port 80 inter 2000 fall 3

wKioL1fupR2AuYP1AAKD7MSM92U396.png-wh_50

mylinux3和mylinux4上的httpd服务正常,浏览器可以正常访问,但是监控界面两个服务器都是宕机状态。

1
[root@mylinux4 ~] # touch /var/www/html/info.txt

在mylinux4上创建info.txt文件,再次刷新监控界面:

wKiom1fupcnwx8JIAAJ8jPek46U024.png-wh_50

此时,mylinux4已经重新恢复成活动状态。

3、httpchk默认检查方法

写法:

option httpchk

这种写法就相当于option httpchk / ,也就是检查对应web服务器的站点根目录是否存在,如果不存在则认为服务器宕机(这种方法类似上面的第一种方法,就不再补图实验了)。

二、配置后端web服务器日志记录客户端真实IP地址

1、先来看一下web服务器日志,如下:

1
2
3
4
5
6
[root@mylinux3 ~] # cat /etc/httpd/logs/access_log 
192.168.100.121 - - [02 /Oct/2016 :01:17:01 +0800]  "GET / HTTP/1.1"  200 222
192.168.100.121 - - [02 /Oct/2016 :01:17:01 +0800]  "GET / HTTP/1.1"  200 222  "-"  "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
192.168.100.121 - - [02 /Oct/2016 :01:20:53 +0800]  "GET / HTTP/1.1"  200 222
192.168.100.121 - - [02 /Oct/2016 :01:20:53 +0800]  "GET / HTTP/1.1"  200 222  "-"  "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"
192.168.100.121 - - [02 /Oct/2016 :01:20:53 +0800]  "GET /favicon.ico HTTP/1.1"  404 290

上面的日志中,第二行是我在mylinux1上使用curl访问的,而后面的都是在windows客户端通过haproxy的代理连接访问的,但是apache的日志中显示的用户IP地址都是192.168.100.121,也就是mylinux1的IP地址,这实际上不是真实的客户访问IP。如果想让web服务器记录真实的客户访问IP,则需要调整以下设置。

2、修改haproxy配置文件

在listen中添加forwardfor选项,注意:该选项只有放在listen段中才能生效,而放在global,default等其他段中无效。

1
2
3
4
5
6
7
8
9
listenwebsites
         bind  192.168.100.120:80
         option   forwardfor
         #option  httpchk GET /info.txt
         #option  httpchk HEAD /check.html HTTP/1.0
         timeout  server  15s
         timeout  connect 30s
         server  mylinux3  192.168.100.181:80 check port 80 inter 2000 fall 3
         server  mylinux4  192.168.100.182:80 check port 80 inter 2000 fall 3

3、修改web服务器日志格式

下面以apache为例,如果想要apache记录客户端的真实IP地址,还需要修改apache的日志格式。

[root@mylinux3 ~]# vi /etc/httpd/conf/httpd.conf 

[root@mylinux3 ~]# grep LogFormat /etc/httpd/conf/httpd.conf 

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

#LogFormat "%h %l %u %t \"%r\" %>s %b" common

LogFormat "\"%{X-Forwarded-For}i\" %V %A %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" common

LogFormat "%{Referer}i -> %U" referer

LogFormat "%{User-agent}i" agent

#LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio

注释掉原有的日志格式(我这里是common格式,如果是其他模式可以依样修改),然后添加一行新的common格式,使用蓝色部分中的模式匹配真实IP地址。

4、重启web服务

1
2
3
4
5
[root@mylinux3 ~] # /etc/init.d/httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd: httpd: apr_sockaddr_info_get() failed  for  mylinux3.contoso.com
httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1  for  ServerName
                                                            [  OK  ]

5、使用haproxy代理访问测试

1
2
3
4
5
[root@mylinux3 ~] # tail -f /etc/httpd/logs/access_log 
"192.168.100.1"  192.168.100.120 192.168.100.181 [02 /Oct/2016 :01:44:12 +0800]  "GET / HTTP/1.1"  200 222  "-"  "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)"
192.168.100.121 - - [02 /Oct/2016 :01:44:12 +0800]  "GET / HTTP/1.1"  200 222  "-"  "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)"
"192.168.100.1"  192.168.100.120 192.168.100.181 [02 /Oct/2016 :01:44:13 +0800]  "GET /favicon.ico HTTP/1.1"  404 290  "-"  "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"
192.168.100.121 - - [02 /Oct/2016 :01:44:13 +0800]  "GET /favicon.ico HTTP/1.1"  404 290  "-"  "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"

可以看到,已经可以记录客户端的真实IP了。

三、haproxy的后端服务器backup设置

haproxy可以设置后端服务器的高可用,也就是可以有多个服务器,但是正常情况下,只有一部分提供服务,而只有在正常提供服务的机器宕机之后,备用机器才会提供服务。

listenwebsites

        bind  192.168.100.120:80

        option   forwardfor

        #option  httpchk GET /info.txt

        #option  httpchk HEAD /check.html HTTP/1.0

        timeout  server  15s

        timeout  connect 30s

        server  mylinux3  192.168.100.181:80 check port 80 inter 2000 fall 3

        server  mylinux4  192.168.100.182:80 check port 80 inter 2000 fall 3 backup

这里设置mylinux4是备用机器,正常情况下只有mylinux3提供服务,而在haproxy认为mylinux3挂掉之后,才会启用mylinux4提供服务。

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
[root@mylinux1 ~] # service haproxy check
Configuration  file  is valid
[root@mylinux1 ~] # service haproxy restart
Stop haproxy successful.
Start haproxy successful.
[root@mylinux1 ~] # service haproxy check
Configuration  file  is valid
[root@mylinux1 ~] # service haproxy restart
Stop haproxy successful.
Start haproxy successful.
[root@mylinux1 ~] # curl http://192.168.100.181
mylinux3
[root@mylinux1 ~] # curl http://192.168.100.182
mylinux4
[root@mylinux1 ~] # for i in {1..20};do curl http://192.168.100.120/;done
mylinux3
mylinux3
mylinux3
mylinux3
mylinux3
mylinux3
mylinux3
mylinux3
mylinux3
mylinux3
mylinux3
mylinux3
mylinux3
mylinux3
mylinux3
mylinux3
mylinux3
mylinux3
mylinux3
mylinux3


说明在mylinux3正常的情况下,mylinux4是不提供服务的,只当做备用机器,下面将mylinux3的web服务关闭,再进行测试:

1
2
3
[root@mylinux3 ~] # /etc/init.d/httpd stop
Stopping httpd:                                            [  OK  ]
[root@mylinux3 ~] #

wKioL1fv-YSSuJufAAKc662TZNA159.png-wh_50

mylinux3已经关闭httpd服务,在监控界面显示为不可用状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@mylinux1 ~] # for i in {1..20};do curl http://192.168.100.120/;done
mylinux4
mylinux4
mylinux4
mylinux4
mylinux4
mylinux4
mylinux4
mylinux4
mylinux4
mylinux4
mylinux4
mylinux4
mylinux4
mylinux4
mylinux4
mylinux4
mylinux4
mylinux4
mylinux4
mylinux4

此时,访问haproxy代理链接,全部都是转发给mylinux4,即我在haproxy配置文件中设置的备用机器。

另外,这里backup主机提供服务的前提是所有正常服务的主机全部都不能通过健康检查,即haproxy认为所有的提供服务的主机都是宕机状态(我这里只有一台,如果有多台的话,必须是不加backup的所有主机都无法提供服务),才会启用第一个backup主机提供服务。当然这样实际上不太好,如果正常情况下提供服务的主机有多台,而backup的主机数量较少,我们可能希望启动所有的backup主机,就需要添加如下参数:

option allbackups

四、Acl规则

1、首先在web服务器上创建虚拟主机

1)mylinux3

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@mylinux3 conf] # cat vhost.conf 
<VirtualHost *:8001>
     ServerAdmin admin@web1.com
     DocumentRoot  /var/www/html/web1
     ServerName www.web1.com
     ErrorLog logs /web1-error .log
     CustomLog logs /web1-access .log common
< /VirtualHost >
<VirtualHost *:8002>
     ServerAdmin admin@web2.com
     DocumentRoot  /var/www/html/web2
     ServerName www.web2.com
     ErrorLog logs /web2-error .log
     CustomLog logs /web2-access .log common
< /VirtualHost >
[root@mylinux3 conf] # mkdir -p /var/www/html/{web1,web2}
[root@mylinux3 conf] # echo web1 >>/var/www/html/web1/index.html
[root@mylinux3 conf] # echo web2 >>/var/www/html/web2/index.html
[root@mylinux3 conf] # /etc/init.d/httpd start
Starting httpd:                                            [  OK  ]
[root@mylinux3 conf] # curl http://192.168.100.181:8001/
web1
[root@mylinux3 conf] # curl http://192.168.100.181:8002/
web2

2)mylinux4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@mylinux4 conf] # cat vhost.conf 
<VirtualHost *:8001>
     ServerAdmin admin@web3.com
     DocumentRoot  /var/www/html/web3
     ServerName www.web3.com
     ErrorLog logs /web3-error .log
     CustomLog logs /web3-access .log common
< /VirtualHost >
<VirtualHost *:8002>
     ServerAdmin admin@web4.com
     DocumentRoot  /var/www/html/web4
     ServerName www.web4.com
     ErrorLog logs /web4-error .log
     CustomLog logs /web4-access .log common
< /VirtualHost >
[root@mylinux4 conf] # mkdir -p /var/www/html/{web3,web4}
[root@mylinux4 conf] # for i in {3..4};do echo web$i >> /var/www/html/web$i/index.html;done
[root@mylinux4 conf] # /etc/init.d/httpd start
Starting httpd:                                            [  OK  ]
[root@mylinux4 conf] # curl http://192.168.100.182:8001/
web3
[root@mylinux4 conf] # curl http://192.168.100.182:8002/
web4

2、修改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
55
56
57
58
59
60
61
62
63
64
65
global
         #log 127.0.0.1  local0
log 127.0.0.1:514  local0  warning
         pidfile  /usr/local/haproxy/var/run/haproxy .pid
         daemon
maxconn 4096
chroot  /usr/local/haproxy/var/chroot
user haproxy
group haproxy
         nbproc 1
defaults
logglobal
         mode    http
retries3
         option  httplog
         option  httpclose
         option  dontlognull
         option  forwardfor
option  redispatch
maxconn2000
         balance roundrobin
timeout connect 5000
timeout client  50000
timeoutserver          50000
listen  haproxy_stats
         bind   *:8000
         mode   http
         option httplog
         maxconn 20
         stats  enable
         stats refresh 30s
         stats uri  /haproxy_status
         stats auth admin:123456
         stats hide-version
#listenwebsites  
#        bind  192.168.100.120:80
#        option   forwardfor
#        #option  httpchk GET /info.txt
#        #option  httpchk HEAD /check.html HTTP/1.0
#        timeout  server  15s
#        timeout  connect 30s
#        server  mylinux3  192.168.100.181:80 check port 80 inter 2000 fall 3
#        server  mylinux4  192.168.100.182:80 check port 80 inter 2000 fall 3 backup
#
frontend web
          bind 192.168.100.121:80
          acl mylinux3_dom hdr(host) -i www.mylinux3.com  #acl规则名称为mylinux3_dom,规则为检查访问域名是否为www.mylinux3.com,-i表示不区分大小写
          acl mylinux4_dom hdr(host) -i www.mylinux4.com
          use_backend mylinux3  if  mylinux3_dom  #如果符合mylinux3_dom规则,则转发给mylinux3的后端作用域
          use_backend mylinux4  if  mylinux4_dom  #如果符合mylinux4_dom规则,则转发给mylinux4的后端作用域
          default_backend mylinux3   #默认情况下转发给mylinux3的后端作用域
backend  mylinux3    #定义一个后端作用域
          balance  leastconn   #轮询方式,最小连接数
          option   httpclose   #每次请求完毕后,主动关闭http通道
          option   forwardfor   #如果后端服务器需要获得客户端真实ip需要配置的参数,可以从Http Header中获得客户端ip  
          server   web1  192.168.100.181:8001 check port 8001 inter 2000 fall 1
          server   web2  192.168.100.181:8002 check port 8002 inter 2000 fall 1
backend  mylinux4
          balance  roundrobin
          option   httpclose
          option   forwardfor
          option   redispatch   #当serverId对应的服务器挂掉后,强制定向到其他健康的服务器
          #option   httpchk  /index.html HTTP/1.0
          server   web1  192.168.100.182:8001 check port 8001 inter 1000 fall 2
          server   web2  192.168.100.182:8002 check port 8002 inter 1000 fall 2

3、重启haproxy服务

1
2
3
[root@mylinux1 conf] # service haproxy restart
Stop haproxy successful.
Start haproxy successful.

4、查看监控界面

wKiom1fwnkChCPR4AAa93Ldhmv0862.jpg-wh_50

5、修改windows客户端hosts文件

注:这里是因为没有DNS,所以windows要进行访问需要修改hosts文件,如果是生产环境,haproxy代理绑定外网IP,然后通过DNS将域名进行解析,就可以直接通过域名访问了。

wKioL1fwnxyBiDUeAAGFwY7RsTc681.jpg-wh_50

然后访问www.mylinux3.com

wKiom1fwn7TB2a5FAACKgGIW4Lc307.jpg-wh_50

wKioL1fwn7XDAfUdAACK-ALcqYw191.jpg-wh_50

然后访问www.mylinux4.com

wKioL1fwn9LS01qyAACc0qhvJig532.jpg-wh_50

wKiom1fwn9OwTolFAACc5kcVoZ8355.jpg-wh_50

而访问http://192.168.100.121/

wKioL1fwoNPRGSS8AACYPiM91ew336.jpg-wh_50

wKiom1fwoNSCzxjEAACanDnFNn0663.jpg-wh_50

6、在linux上进行测试

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
[root@mylinux1 conf] # vi /etc/hosts
[root@mylinux1 conf] # tail -1 /etc/hosts
192.168.100.121  www.mylinux3.com  www.mylinux4.com
[root@mylinux1 conf] # for i in {1..10};do curl http://www.mylinux3.com/;done
web1
web2
web1
web2
web1
web2
web1
web2
web1
web2
[root@mylinux1 conf] # for i in {1..10};do curl http://www.mylinux4.com/;done
web3
web4
web3
web4
web3
web4
web3
web4
web3
web4
[root@mylinux1 conf] # for i in {1..10};do curl http://192.168.100.121/;done
web1