Haproxy04-Haproxy的基本使用

1、HAProxy简介

  • HAProxy是使用C语言编写的开源软件,提供双机热备、高可用、负载均衡、虚拟主机、基于TCP(四层)和HTTP(七层)的应用代理、图形界面查看信息等功能。
  • HAProxy配置简单、维护方便,而且可以对后端服务器进行健康状态检测(相当于keepalived健康状态检测)。
    • 当其代理的后端服务器出现故障时,Haproxy会自动的将其摘除。
    • 当故障的后端服务器恢复后,Haproxy会自动将其加入进来,对外提供服务。
  • HAProxy特别适用于高负载、访问量大,且需要会话保持以及七层代理的业务应用。HAProxy运行在普通服务器上,就可以支持数以万计的并发连接。并且它的运行模式使得它可以很简单、安全的整合到各种已有的网站架构中。
  • Haproxy从1.3版本起,引入了frontend、backend的功能。
    • frontend(acl规则匹配)可以让运维管理人员根据任意HTTP请求头做规则匹配,然后把请求定向到相应的backend(事先定义好的server pools,等待前端把请求转过来的服务器组)。
    • 通过frontend和backend可以很容易的实现haproxy的各种7层代理功能。
  • HAProxy支持两种代理模式
    • (1)基于4层的tcp应用代理(例如,可用于邮件服务、内部协议通信服务器、MySQL、HTTPS服务等)。
    • (2)基于7层的http代理。在4层tcp代理模式下,HAProxy仅在客户端和服务器之间进行流量转发。但是在7层http代理模式下,HAProxy会分析应用层协议,能通过允许、拒绝、交换、增加、修改或者删除请求头(request)或者响应头(response)中的内容来控制。
  • HAProxy支持两种处理模式
    • 单进程处理模式:所有客户端连接全部都由同一个服务进程来处理,目标就是等待连接,来一个分配一个,主要消耗cpu。
    • 多线程处理模式:多线程模式消耗内存,会限制并发而且多线程需要进程间通信,也会消耗相当多的cpu资源。
  • Haproxy软件的最大优势是可以对请求头进行操作以及sesson会话功能。(七层)

2、健康状态检查

  • 是否对一个后端服务器进行健康状态检查:
    • 如果后端服务器没有设置check,就不进行健康状态检查,并且始终认为后端服务器是可用的。
    • 如果后端服务器设置了check,就进行健康状态检查。
      • 如果设置了check,但没有配置检查方法,仅进行简单的tcp检查
      • 如果设置了check,并配置检查方法,就按照指定的检查方法进行检查。
  • 如果要深入探究健康状态检测可以查看下面参数:
global段参数:
max-spread-checks
max-spread-checks
spread-checks

代理参数矩阵
-- keyword -------------------------- defaults - frontend - listen -- backend -
http-check comment                        X          -         X         X
http-check connect                        X          -         X         X
http-check disable-on-404                 X          -         X         X
http-check expect                         X          -         X         X
http-check send                           X          -         X         X
http-check send-state                     X          -         X         X
http-check set-var                        X          -         X         X
http-check unset-var                      X          -         X         X
tcp-check comment                         X          -         X         X
tcp-check connect                         X          -         X         X
tcp-check expect                          X          -         X         X
tcp-check send                            X          -         X         X
tcp-check send-lf                         X          -         X         X

option ldap-check                         X          -         X         X
option external-check                     X          -         X         X
option mysql-check                        X          -         X         X
option pgsql-check                        X          -         X         X
option redis-check                        X          -         X         X
option spop-check                         -          -         -         X
option tcp-check                          X          -         X         X
option ssl-hello-chk                      X          -         X         X
option smtpchk                            X          -         X         X
option smtpchk <hello> <domain>
option httpchk                            X          -         X         X
option httpchk <uri>
option httpchk <method> <uri>
option httpchk <method> <uri> <version>

option log-health-checks             (*)  X          -         X         X
timeout check                             X          -         X         X
View Code

2.1、基于端口的健康状态检测(TCP)

  • 在进行健康状态检查时,进检查端口是否存在。

1、创建配置文件

]# cat > /apps/haproxy/haproxy.cfg << EOF
global
    daemon
    pidfile /apps/haproxy/haproxy.pid
    chroot /apps/haproxy/empty
    user haproxy
    group haproxy
    log 127.0.0.1 local3 info
    maxconn  4096
    hard-stop-after 5m
    default-path config
    zero-warning
    node node_name1
    description 'global_hh1'
 
defaults
    mode http
    log global
    option httpslog
    option dontlognull
    option forwardfor
    option httpclose
    option http-server-close
    option redispatch
    retries 3
    timeout check 2000
    timeout http-request 10s
    timeout queue 15s
    timeout connect 10s
    timeout client 1m
    timeout server 1m
    timeout http-keep-alive 2m
    timeout tunnel 4h
    maxconn 2048

listen stats
    bind :18080
    stats enable
    stats uri /haproxystatus
    stats auth admin1:admin1
    stats auth admin2:admin2
    stats admin if TRUE
    stats realm Haproxy\ status
    stats refresh 10s
    stats hide-version

frontend frontend_hh1
    description "frontend frontend_hh1"
    bind  :80
    default_backend server_hh1
 
backend server_hh1
    balance roundrobin

    #check开启健康状态检查,inter检查的时间间隔,rise几次成功的检查就认为后端服务器可用,fall几次失败的检测就认为后端服务器不可用。
    server httpA 192.168.1.101:80 check inter 1500 rise 3 fall 2 weight 1
    server httpB 192.168.1.102:80 check inter 1500 rise 3 fall 2 weight 1
EOF

3、启动httpd服务

//启动两个后端服务器的httpd服务
]# systemctl start httpd.service

2、停止一个httpd服务

//登录HAProxy的状态页面观察变化(观察结果:相应的后端服务器停止了)
]# systemctl stop httpd.service

3、使用ns开启80端口

//登录HAProxy的状态页面观察变化(观察结果:相应的后端服务器启动了)
]# nc -l 80

2.2、基于后端主机文件的健康状态检测

1、创建配置文件

]# cat > /apps/haproxy/haproxy.cfg << EOF
global
    daemon
    pidfile /apps/haproxy/haproxy.pid
    chroot /apps/haproxy/empty
    user haproxy
    group haproxy
    log 127.0.0.1 local3 info
    maxconn  4096
    hard-stop-after 5m
    default-path config
    zero-warning
    node node_name1
    description 'global_hh1'
 
defaults
    mode http
    log global
    option httpslog
    option dontlognull
    option forwardfor
    option httpclose
    option http-server-close
    option redispatch
    retries 3
    timeout check 2000
    timeout http-request 10s
    timeout queue 15s
    timeout connect 10s
    timeout client 1m
    timeout server 1m
    timeout http-keep-alive 2m
    timeout tunnel 4h
    maxconn 2048

listen stats
    bind :18080
    stats enable
    stats uri /haproxystatus
    stats auth admin1:admin1
    stats auth admin2:admin2
    stats admin if TRUE
    stats realm Haproxy\ status
    stats refresh 10s
    stats hide-version

frontend frontend_hh1
    description "frontend frontend_hh1"
    bind  :80
    default_backend server_hh1
 
backend server_hh1
    balance roundrobin
    #通过url进行健康状态检查(IP:PORT/hh.html)
    option httpchk GET /hh.html HTTP/1.0
    #check开启健康状态检查,inter检查的时间间隔,rise几次成功的检查就认为后端服务器可用,fall几次失败的检测就认为后端服务器不可用。
    server httpA 192.168.1.101:80 check inter 1500 rise 3 fall 2 weight 1
    server httpB 192.168.1.102:80 check inter 1500 rise 3 fall 2 weight 1
EOF

2、提供测试页

//在192.168.1.101上执行
]# cat > /var/www/html/hh.html << EOF
<h1>192.168.1.101, check1</h1>
EOF
 
//在192.168.1.102上执行
]# cat > /var/www/html/hh.html << EOF
<h1>192.168.1.102, check2</h1>
EOF

3、启动httpd服务

//启动两个后端服务器的httpd服务
]# systemctl start httpd.service

4、删除测试文件

//登录HAProxy的状态页面观察变化(观察结果:相应的后端服务器停止了)
]# rm -f /var/www/html/hh.html

3、实现会话粘性

3.1、基于源IP实现会话绑定

1、创建配置文件

]# cat > /apps/haproxy/haproxy.cfg << EOF
global
    daemon
    pidfile /apps/haproxy/haproxy.pid
    chroot /apps/haproxy/empty
    user haproxy
    group haproxy
    log 127.0.0.1 local3 info
    maxconn  4096
    hard-stop-after 5m
    default-path config
    zero-warning
    node node_name1
    description 'global_hh1'
 
defaults
    mode http
    log global
    option httpslog
    option dontlognull
    option forwardfor
    option httpclose
    option http-server-close
    option redispatch
    retries 3
    timeout check 2000
    timeout http-request 10s
    timeout queue 15s
    timeout connect 10s
    timeout client 1m
    timeout server 1m
    timeout http-keep-alive 2m
    timeout tunnel 4h
    maxconn 2048

listen stats
    bind :18080
    stats enable
    stats uri /haproxystatus
    stats auth admin1:admin1
    stats auth admin2:admin2
    stats admin if TRUE
    stats realm Haproxy\ status
    stats refresh 10s
    stats hide-version

frontend frontend_hh1
    description "frontend frontend_hh1"
    bind  :80
    default_backend server_hh1
 
backend server_hh1
    #通过负载平衡算法实现基于源IP的会话绑定
    balance source
    server httpA 192.168.1.101:80 check inter 1500 rise 3 fall 2 weight 1
    server httpB 192.168.1.102:80 check inter 1500 rise 3 fall 2 weight 1
EOF

2、在不同的机器上访问测试页

]# for i in {1..10}; do curl http://10.1.1.12/index.html; done

3.2、基于cookie实现会话绑定

1、创建配置文件

]# cat > /apps/haproxy/haproxy.cfg << EOF
global
    daemon
    pidfile /apps/haproxy/haproxy.pid
    chroot /apps/haproxy/empty
    user haproxy
    group haproxy
    log 127.0.0.1 local3 info
    maxconn  4096
    hard-stop-after 5m
    default-path config
    zero-warning
    node node_name1
    description 'global_hh1'
 
defaults
    mode http
    log global
    option httpslog
    option dontlognull
    option forwardfor
    option httpclose
    option http-server-close
    option redispatch
    retries 3
    timeout check 2000
    timeout http-request 10s
    timeout queue 15s
    timeout connect 10s
    timeout client 1m
    timeout server 1m
    timeout http-keep-alive 2m
    timeout tunnel 4h
    maxconn 2048

listen stats
    bind :18080
    stats enable
    stats uri /haproxystatus
    stats auth admin1:admin1
    stats auth admin2:admin2
    stats admin if TRUE
    stats realm Haproxy\ status
    stats refresh 10s
    stats hide-version

frontend frontend_hh1
    description "frontend frontend_hh1"
    bind  :80
    default_backend server_hh1
 
backend server_hh1
    balance source
    #在后端启用基于cookie的会话粘性
    cookie SERVERID insert indirect nocache
    #为后端服务器的cookie设置一个值<value>
    server httpA 192.168.1.101:80 check inter 1500 rise 3 fall 2 weight 1 cookie s101
    #为后端服务器的cookie设置一个值<value>
    server httpB 192.168.1.102:80 check inter 1500 rise 3 fall 2 weight 1 cookie s102
EOF

2、在haproxy服务器上抓包分析

]# sudo tcpdump -i ens33 -s 0 -v -nn -l port ! 22 | grep index -A 3
#第一次请求的请求头,没有header头Cookie
	GET /index.html HTTP/1.1
	Host: 10.1.1.12
	Connection: keep-alive
	Pragma: no-cache
	Cache-Control: no-cache
	Upgrade-Insecure-Requests: 1
	User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Mobile Safari/537.36
	Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
	Accept-Encoding: gzip, deflate
	Accept-Language: zh-CN,zh;q=0.9
#第一次请求的响应头,haproxy的header头中有set-cookie
	HTTP/1.1 200 OK
	date: Mon, 25 Jul 2022 08:22:09 GMT
	server: Apache/2.4.6 (CentOS)
	last-modified: Sun, 24 Jul 2022 07:09:29 GMT
	etag: "1e-5e487bf955216"
	accept-ranges: bytes
	content-length: 30
	content-type: text/html; charset=UTF-8
	set-cookie: SERVERID=s102; path=/
	cache-control: private

#第二次请求的请求头,有header头Cookie
    GET /index.html HTTP/1.1
	Host: 10.1.1.12
	Connection: keep-alive
	Pragma: no-cache
	Cache-Control: no-cache
	Upgrade-Insecure-Requests: 1
	User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Mobile Safari/537.36
	Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
	Accept-Encoding: gzip, deflate
	Accept-Language: zh-CN,zh;q=0.9
	Cookie: SERVERID=s102
#第二次请求的响应头,haproxy返回header头中没有set-cookie
	HTTP/1.1 200 OK
	date: Mon, 25 Jul 2022 08:23:29 GMT
	server: Apache/2.4.6 (CentOS)
	last-modified: Sun, 24 Jul 2022 07:09:29 GMT
	etag: "1e-5e487bf955216"
	accept-ranges: bytes
	content-length: 30
	content-type: text/html; charset=UTF-8
	
	<h1>192.168.1.102, test2</h1>

4、不同的域名(header头)使用不同的后端

1、创建配置文件

]# cat > /apps/haproxy/haproxy.cfg << EOF
global
    daemon
    pidfile /apps/haproxy/haproxy.pid
    chroot /apps/haproxy/empty
    user haproxy
    group haproxy
    log 127.0.0.1 local3 info
    maxconn  4096
    hard-stop-after 5m
    #default-path config
    zero-warning
    node node_name1
    description 'global_hh1'
  
defaults
    mode http
    log global
    option httpslog
    option dontlognull
    option forwardfor
    option httpclose
    option http-server-close
    option redispatch
    retries 3
    timeout check 2000
    timeout http-request 10s
    timeout queue 15s
    timeout connect 10s
    timeout client 1m
    timeout server 1m
    timeout http-keep-alive 2m
    timeout tunnel 4h
    maxconn 2048
 
listen stats
    bind :18080
    stats enable
    stats uri /haproxystatus
    stats auth admin1:admin1
    stats auth admin2:admin2
    stats admin if TRUE
    stats realm Haproxy\ status
    stats refresh 10s
    stats hide-version
 
frontend frontend_hh1
    description "frontend frontend_hh1"
    bind  :80

    #过滤域名是www.hh1.com的请求
    acl hh1 hdr(host) -i www.hh1.com
    #访问www.hh1.com的请求被代理到
    use_backend server_hh1 if hh1

    #过滤域名是www.hh2.com的请求
    acl hh2 hdr(host) -i www.hh2.com
    #访问www.hh2.com的请求被代理到
    use_backend server_hh2 if hh2

backend server_hh1
    balance roundrobin
    server httpA 192.168.1.101:80 check inter 1500 rise 3 fall 2
backend server_hh2
    balance roundrobin
    server httpB 192.168.1.102:80 check inter 1500 rise 3 fall 2
EOF

2、测试

]# for i in {1..20}; do curl -H "HOST:www.hh1.com" http://10.1.1.12:80/; done
]# for i in {1..20}; do curl -H "HOST:www.hh2.com" http://10.1.1.12:80/; done

5、不同的url使用不同的后端

1、创建配置文件

]# cat > /apps/haproxy/haproxy.cfg << EOF
global
    daemon
    pidfile /apps/haproxy/haproxy.pid
    chroot /apps/haproxy/empty
    user haproxy
    group haproxy
    log 127.0.0.1 local3 info
    maxconn  4096
    hard-stop-after 5m
    #default-path config
    zero-warning
    node node_name1
    description 'global_hh1'
  
defaults
    mode http
    log global
    option httpslog
    option dontlognull
    option forwardfor
    option httpclose
    option http-server-close
    option redispatch
    retries 3
    timeout check 2000
    timeout http-request 10s
    timeout queue 15s
    timeout connect 10s
    timeout client 1m
    timeout server 1m
    timeout http-keep-alive 2m
    timeout tunnel 4h
    maxconn 2048
 
listen stats
    bind :18080
    stats enable
    stats uri /haproxystatus
    stats auth admin1:admin1
    stats auth admin2:admin2
    stats admin if TRUE
    stats realm Haproxy\ status
    stats refresh 10s
    stats hide-version
 
frontend frontend_hh1
    description "frontend frontend_hh1"
    bind  :80

    #过滤uri以/static1/开始的请求
    acl hh1 path_beg -i /static1/
    #访问/static1/的请求被代理到
    use_backend server_hh1 if hh1

    #过滤uri以/static2/开始的请求
    acl hh2 path_beg -i /static2/
    #访问/static2/的请求被代理到
    use_backend server_hh2 if hh2

backend server_hh1
    balance roundrobin
    server httpA 192.168.1.101:80 check inter 1500 rise 3 fall 2
backend server_hh2
    balance roundrobin
    server httpB 192.168.1.102:80 check inter 1500 rise 3 fall 2
EOF

2、提供测试页

//在192.168.1.101上执行
]# mkdir /var/www/html/static1/
]# echo '<h1>192.168.1.101, static1</h1>' > /var/www/html/static1/hh.html

//在192.168.1.102上执行
]# mkdir /var/www/html/static2/
]# echo '<h1>192.168.1.102, static2</h1>' > /var/www/html/static2/hh.html

3、测试

]# for i in {1..20}; do curl http://10.1.1.12/static1/hh.html; done
]# for i in {1..20}; do curl http://10.1.1.12/static2/hh.html; done

6、错误页面(有问题)

//haproxy本机提供错误页面
errorfile
//sorry server来提供错误页面
errorloc和errorloc302
errorloc303

问题1:errorfile

  • 使用haproxy 2.5.6和2.6.2版本,不能正常启动haproxy。
]# /apps/haproxy/sbin/haproxy -c -f /apps/haproxy/haproxy.cfg
[NOTICE]   (10990) : haproxy version is 2.6.2-16a3646
[NOTICE]   (10990) : path to executable is /apps/haproxy/sbin/haproxy
[ALERT]    (10990) : config : parsing [/apps/haproxy/haproxy.cfg:52] : errorfile : '/var/www/html/errorfiles/404.http': unabled to parse headers (error offset: -2)
[ALERT]    (10990) : config : Error(s) found in configuration file : /apps/haproxy/haproxy.cfg
[ALERT]    (10990) : config : Fatal errors found in configuration.

问题2:errorloc

  • 使用haproxy 2.5.6和2.6.2版本,可以正常启动haproxy,但跳转不到指定的错误页面。
frontend frontend_hh1
    #响应码404使用指定的错误页面
    errorfile 404 /var/www/html/errorfiles/404.http
    #errorloc 404 http://www.baidu.com
    #errorloc303 404 http://www.jingdong.com

7、使用Keepalived+HAProxy实现负载均衡RabbitMQ 

  • 参见:https://www.cnblogs.com/maiblogs/p/16482831.html
#                                                                                                                         #
posted @ 2022-07-23 22:14  麦恒  阅读(220)  评论(0编辑  收藏  举报