HAProxy负载均衡详细解释

目录

1、HAProxy的负载均衡

1.1socat工具的使用

1.1.1对于单进程

1.1.2对于多进程处理方法(对haproxy做热处理)

2、Haproxy的算法

2.1静态算法

<1>static-rr

<2>first

2.2动态算法

<1>roundrobin

<2>leastconn

<3>random

2.3其他算法(以下算法取决于hash-type 是否是consistent)

<1>Source

<2>map-base取模法

<3>一致性 hash

<4>uri

<5>url_param

<6>hdr(User-Agent)   #基于客户端请求报文

3、haproxy的状态页

4、haproxy高级算法及配置

4.1基于cookie的会话保持

4.2 IP透传

4.2.1七层透传

4.2.2 四层IP透传

5、ACL配置选项

5.1 ACL匹配模式

5.2 ACL匹配规范:

5.3 ACL实战

ACL示例1-域名匹配

ACL示例2-基于源IP或子网调度访问

ACL示例3-基于源地址的访问控制

 ACL示例4-匹配浏览器类型

ACL示例5-基于文件后缀名实现动静分离

ACL示例6-匹配访问路径实现动静分离

6、HAProxy自定义错误页面

7、MYSQL的负载均衡

8、HAProxy https 实现


1、HAProxy的负载均衡

HAProxy提供高可用性、负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费、快速并且可靠的一种解决方案。

HAProxy特别适用于那些负载特大的web站点,这些站点通常又需要会话保持或七层处理。HAProxy运行在当前的硬件上,完全可以支持数以万计的并发连接。

并且它的运行模式使得它可以很简单安全的整合进您当前的架构中, 同时可以保护你的web服务器不被暴露到网络上。

1.1socat工具的使用

对服务器动态权重和其它状态可以利用 socat工具进行调整,Socat 是 Linux 下的一个多功能的网络工具,名字来由是Socket CAT,相当于netCAT的增强版.Socat 的主要特点就是在两个数据流之间建立双向通道,且支持众多协议和链接方式。如IP、TCP、UDP、IPv6、Socket文件等 

                                                                                                ——动态调整haproxy中的参数

示例:

[root@haproxy ~]# dnf install socat -y

1.1.1对于单进程

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg

[root@haproxy ~]# systemctl restart haproxy.service

[root@haproxy ~]# echo "show info"    |   socat stdio /var/lib/haproxy/haproxy.sock

#显示详细信息

[root@haproxy ~l#echo "show servers state"    |  socat stdio   /var/lib/haproxy/haproxy.sock

#显示服务的状态

[root@haproxy ~]# echo "get weight webcluster/web1"  | socat stdio   /var/lib/haproxy/haproxy.sock

#查看web1这个服务的权重值

[root@haproxy ~]# echo "set weight webcluster/web1 2" | socat stdio  /var/lib/haproxy/haproxy.sock

#设置web1这个权重值为2

[root@haproxy ~]# echo "disable server  webcluster/web1"     |  socat stdio/var/lib/haproxy/stats

#关闭此服务的进程

[root@haproxy ~]# echo "enable server    webcluster/web1"   |  socat stdio/var/lib/haproxy/stats

#开启此服务的进程

[root@haproxy ~]# echo "help" | socat stdio /var/lib/haproxy/stats   #查看socat的帮助信息

1.1.2对于多进程处理方法(对haproxy做热处理)

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg

[root@haproxy ~]# systemctl restart haproxy.service

stats进程此时不能使用,但stats1和stats2可以使用

[root@haproxy ~]# echo "help" | socat stdio /var/lib/haproxy/stats

2024/08/08 23:51:38 socat[4832] E connect(5, AF=1 "/var/lib/haproxy/stats", 24): Connection refused

[root@haproxy ~]# echo "show info" | socat stdio /var/lib/haproxy/stats1

Name: HAProxy

Version: 1.8.27-493ce0b

Release_date: 2020/11/06

Nbthread: 1

Nbproc: 2

Process_num: 1

Pid: 4802

Uptime: 0d 0h02m09s

2、Haproxy的算法

Haproxy通过固定参数 balance 指明对后端服务器的调度算法

balance参数可以配置在listen或backend选项中

Haproxy的调度算法分为静态和动态调度算法

有些算法可以根据参数在静态和动态算法中相互转换。

2.1静态算法

静态算法只能重启生效

后端服务器理论上无限

<1>static-rr

基于权重的轮询调度,不支持运行时利用socat进行权重的动态调整(只支持0和1,不支持其它值)及后端服务器慢启动,其后端主机数量没有限制,相当于LVS中的 wrr

<2>first

根据服务器在列表中的位置,自上而下进行调度,但是其只会当第一台服务器的连接数达到上限,新请求才会分配给下一台服务,因此会忽略服务器的权重设置,此方式使用较少

不支持用socat进行动态修改权重,可以设置0和1,可以设置其它值但无效

2.2动态算法

基于后端服务器状态进行调度适当调整

新请求将优先调度至当前负载较低的服务器

权重可以在haproxy运行时动态调整无需重启

<1>roundrobin

基于权重的轮询动态调度算法,支持权重的运行时调整,不同于lvs中的轮询模式,

HAProxy中的roundrobin支持慢启动(新加的服务器会逐渐增加转发数),其每个后端backend中最多支持4095个real server,支持对real server权重动态调整,roundrobin为默认调度算法,此算法使用广泛

哪个后端服务器负载小就把请求转发给哪个后端服务器

<2>leastconn

leastconn 加权的最少连接的动态,支持权重的运行时调整和慢启动,即:根据当前连接最少的后端服务器而非权重进行优先调度(新客户端连接),比较适合长连接的场景使用,比如:MySQL等场景。

<3>random

在1.9版本开始增加 random的负载平衡算法,其基于随机数作为一致性hash的key,随机负载平衡对于大型服务器场或经常添加或删除服务器非常有用,支持weight的动态调整,weight较大的主机有更大概率获取新请求

2.3其他算法(以下算法取决于hash-type 是否是consistent)

<1>Source

源地址hash,基于用户源地址hash并将请求转发到后端服务器,后续同一个源地址请求将被转发至同一个后端web服务器。

此方式当后端服务器数据量发生变化时,会导致很多用户的请求转发至新的后端服务器,默认为静态方式,但是可以通过hash-type选项进行更改

这个算法一般是在不插入Cookie的TCP模式下使用,也可给不支持会话cookie的客户提供最好的会话粘性,适用于session会话保持但不支持cookie和缓存的场景

源地址有两种转发客户端请求到后端服务器的服务器选取计算方式,分别是取模法和一致性hash

<2>map-base取模法

取模法,对source地址进行hash计算,再基于服务器总权重的取模,最终结果决定将此

请求转发至对应的后端服务器。此方法是静态的,即不支持在线调整权重,不支持慢启动,可实现对后端服务器均衡调度。缺点是当服务器的总权重发生变化时,即有服务器上线或下线,都会因总权重发生变化而导致调度结果整体改变,hash-type 指定的默认值为此算法

<3>一致性 hash

一致性哈希,当服务器的总权重发生变化时,对调度结果影响是局部的,不会引起大的变动,hash(o)mod n ,该hash算法是动态的,支持使用 socat等工具进行在线权重调整,支持慢启动

1、key1=hash(source_ip)%(2^32) [0---4294967295]

2、keyA=hash(后端服务器虚拟ip)%(2^32)

3、将key1和keyA都放在hash环上,将用户请求调度到离key1最近的keyA对应的后端服务器

hash环偏斜问题

增加虚拟服务器IP数量,比如:一个后端服务器根据权重为1生成1000个虚拟IP,再hash。而后端服务器权重为2则生成2000的虚拟IP,再进行hash运算,最终在hash环上生成3000个节点,从而解决hash环偏斜问题

<4>uri

基于对用户请求的URI的左半部分或整个uri做hash,再将hash结果对总权重进行取模后,根据最终结果将请求转发到后端指定服务器,适用于后端是缓存服务器场景,默认是静态算法,也可以通过hash-type

指定map-based和consistent,来定义使用取模法还是一致性hash。

Url:网址要找的路径位置

uri不变访问的地址就不变

<5>url_param

url_param对用户请求的url中的 params 部分中的一个参数key对应的value值作hash计算,并由服务器总权重相除以后派发至某挑出的服务器;通常用于追踪用户,以确保来自同一个用户的请求始终发往同一个real server,如果无没key,将按roundrobin算法

<6>hdr(User-Agent)   #基于客户端请求报文

针对用户每个http头部(header)请求中的指定信息做hash,此处由 name 指定的http首部将会被取出并做hash计算,然后由服务器总权重取模以后派发至某挑出的服务器,如果无有效值,则会使用默认的轮询调度。

3、haproxy的状态页

状态页配置项:

           

4、haproxy高级算法及配置

4.1基于cookie的会话保持

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg

[root@localhost ~]# curl -b cookie=lhd1 192.168.182.151

webserver1

[root@localhost ~]# curl -b cookie=lhd2 192.168.182.151  #指定到cookie所设定的值

webserver2

[root@localhost ~]#

-b, --cookie <data> Send cookies from string/file

4.2 IP透传

4.2.1七层透传

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg

[root@webserver1 ~]# vim /etc/httpd/conf/httpd.conf    #修改apache服务日志

测试:

通过测试可以追踪到是192.168.182.154和192.168.182.153这两个用户端访问的本机服务端

4.2.2 四层IP透传

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg

[root@webserver2 ~]# vim /etc/nginx/nginx.conf       #nginx服务修改日志格式

测试:可以追踪到是哪个用户访问了本机

5、ACL配置选项

acl    <aclname>   <criterion>    [flags]       [operator]           [<value>]

acl        名称             匹配规范     匹配模式     具体操作符        操作对象类型

5.1 ACL匹配模式

-i 不区分大小写

-m 使用指定的正则表达式匹配方法

-n 不做DNS解析

-u 禁止acl重名,否则多个同名ACL匹配或关系

5.2 ACL匹配规范:

hdr string,提取在一个HTTP请求报文的首部

hdr([<name> [,<occ>]]):完全匹配字符串,header的指定信息,<occ> 表示在多值中使用的值的出

现次数

hdr_beg([<name> [,<occ>]]):前缀匹配,header中指定匹配内容的begin

hdr_end([<name> [,<occ>]]):后缀匹配,header中指定匹配内容end

hdr_dom([<name> [,<occ>]]):域匹配,header中的dom(host)

hdr_dir([<name> [,<occ>]]):路径匹配,header的uri路径

hdr_len([<name> [,<occ>]]):长度匹配,header的长度匹配

hdr_reg([<name> [,<occ>]]):正则表达式匹配,自定义表达式(regex)模糊匹配

hdr_sub([<name> [,<occ>]]):子串匹配,header中的uri模糊匹配 模糊匹配c 报文中a/b/c也会匹配

 

base : string

#返回第一个主机头和请求的路径部分的连接,该请求从主机名开始,并在问号之前结束,对虚拟主机有用

<scheme>://<user>:<password>@#<host>:<port>/<path>;<params>#?<query>#<frag>

base : exact string match

base_beg : prefix match

base_dir : subdir match

base_dom : domain match

base_end : suffix match

base_len : length match

base_reg : regex match

base_sub : substring match

 

path : string

#提取请求的URL路径,该路径从第一个斜杠开始,并在问号之前结束(无主机部分)

<scheme>://<user>:<password>@<host>:<port>#/<path>;<params>#?<query>#<frag>

path : exact string match

path_beg : prefix match #请求的URL开头,如/static、/images、/img、/css

path_end : suffix match #请求的URL中资源的结尾,如 .gif .png .css .js .jpg .jpeg

path_dom : domain match

path_dir : subdir match

path_len : length match

path_reg : regex match

path_sub : substring match

 

url : string

#提取请求中的整个URL。

url :exact string match

url_beg : prefix match

url_dir : subdir match

url_dom : domain match

url_end : suffix match

url_len : length match

url_reg : regex match

url_sub : substring match

dst           #目标IP

dst_port  #目标PORT

src           #源IP

src_port  #源PORT

5.3 ACL实战

ACL示例1-域名匹配

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg

frontend webcluster

    bind *:80

    mode http

    acl test hdr_dom(host) -i www.lhd.com  

    acl test hdr_end(host) -i .com

    use_backend webcluster-host if  test

    default_backend default-host

backend webcluster-host

    mode http

    server web1 192.168.182.152:80 check

backend default-host

    mode http

    server web2 192.168.182.153:80 check

测试结果:

[root@localhost ~]# cat /etc/hosts

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4

::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.182.151 www.lhd.com www.test.com

[root@localhost ~]# curl www.lhd.com

webserver1

[root@localhost ~]# curl www.test.com

webserver1

ACL示例2-基于源IP或子网调度访问

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg

frontend webcluster

    bind *:80

    mode http

    acl ctrl_ip src 192.168.182.154 192.168.182.153    #153和154这两个主机

    use_backend webcluster-host if  ctrl_ip               #如果是这两个主机就访问到web1的后端

    default_backend default-host

backend webcluster-host

    mode http

    server web1 192.168.182.152:80 check

backend default-host

    mode http

    server web2 192.168.182.153:80 check

测试结果:

[root@webserver2 ~]# curl 192.168.182.151      #192.168.182.153主机所访问的结果索引

web1服务上

webserver1

[root@localhost ~]# curl 192.168.182.151        #192.168.182.154主机所访问的结果

webserver1

[root@webserver1 ~]# curl 192.168.182.151      #192.168.182.152主机所访问的结果默认到web2服务上

webserver2

ACL示例3-基于源地址的访问控制

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg

frontend webcluster

    bind *:80

    mode http

    acl ctrl_ip src 192.168.182.154 192.168.182.153

    acl test hdr_dom(host) -i www.lhd.com                   test所指的是域名

    http-request deny if  test                                         拒绝访问test

    default_backend default-host

backend webcluster-host

    mode http

    server web1 192.168.182.152:80 check

backend default-host

    mode http

    server web2 192.168.182.153:80 check

测试结果:

[root@webserver2 ~]# curl 192.168.182.151   #在192.168.182.153主机上被索引到默认后端

webserver2

[root@localhost ~]# curl 192.168.182.151       #在192.168.182.154主机上被索引到默认后端

webserver2

[root@localhost ~]# curl www.lhd.com                域名被拒绝访问

<html><body><h1>403 Forbidden</h1>

Request forbidden by administrative rules.

</body></html>

 ACL示例4-匹配浏览器类型

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg

frontend webcluster

    bind *:80

    mode http

    acl badwebrowers hdr_sub(User-Agent) -i curl wget

    http-request deny if  badwebrowers

    default_backend default-host

backend webcluster-host

    mode http

    server web1 192.168.182.152:80 check

backend default-host

    mode http

    server web2 192.168.182.153:80 check

测试结果:

[root@localhost ~]# curl 192.168.182.151

<html><body><h1>403 Forbidden</h1>

Request forbidden by administrative rules.

</body></html>

被索引到默认web2主机上

ACL示例5-基于文件后缀名实现动静分离

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg

frontend webcluster

    bind *:80

    mode http

    acl static path_end -i .html .jpg .png .css .js

    acl dhcp path_end -i .php

    use_backend webcluster-host if  dhcp           #如果匹配的是dhcp就使用index.php访问到php默认主页上,如果是static就用index.jpg访问到web2服务上

    default_backend default-host

backend webcluster-host

    mode http

    server web1 192.168.182.152:80 check

backend default-host

    mode http

    server web2 192.168.182.153:80 check

测试结果:

[root@webserver1 ~]# echo php 192.168.182.152 > /var/www/html/index.php

[root@webserver2 ~]# echo jpg 192.168.182.153 > /usr/share/nginx/html/index.jpg

[root@localhost ~]# curl 192.168.182.151/index.php

php 192.168.182.152

[root@localhost ~]# curl 192.168.182.151/index.jpg

jpg 192.168.182.153

ACL示例6-匹配访问路径实现动静分离

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg

frontend webcluster

    bind *:80

    mode http

    acl static path_sub -m sub /static

    acl php path_sub -m sub /php                            

    use_backend webcluster-host if  php                #如果是匹配的是php就通过/php路径访问到web1服务上,否则则是访问到web2服务上

    default_backend default-host

backend webcluster-host

    mode http

    server web1 192.168.182.152:80 check

backend default-host

    mode http

    server web2 192.168.182.153:80 check

测试结果:

[root@webserver1 ~]# mkdir -p /var/www/html/php

[root@webserver1 ~]# echo php 192.168.182.152 > /var/www/html/php/index.html

[root@webserver2 ~]# mkdir -p /usr/share/nginx/html/static

[root@webserver2 ~]# echo static 192.168.182.153 > /usr/share/nginx/html/static/index.html

[root@localhost ~]# curl 192.168.182.151/php/

php 192.168.182.152

[root@localhost ~]# curl 192.168.182.151/static/

static 192.168.182.153

6、HAProxy自定义错误页面

先模拟停止两台web服务

[root@haproxy ~]# mkdir -p /etc/haproxy/errorpage

[root@haproxy ~]#

[root@haproxy ~]# cat /usr/share/haproxy/503.http

HTTP/1.0 503 Service Unavailable

Cache-Control: no-cache

Connection: close

Content-Type: text/html

<html><body><h1>503 Service Unavailable</h1>

No server is available to handle this request.

</body></html>

[root@haproxy ~]# cp /usr/share/haproxy/503.http /etc/haproxy/errorpage/bad.http

[root@haproxy ~]# cat /etc/haproxy/errorpage/bad.http

HTTP/1.0 503 Service Unavailable

Cache-Control: no-cache

Connection: close

Content-Type: text/html

<html><body><h1>你是不是没有生么事情</h1>

HAHAHA!!!

</body></html>

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg

# 将错误修改

[root@haproxy ~]# systemctl restart haproxy.service

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg

#将错误重定向到百度网页

7、MYSQL的负载均衡

[root@webserver1 ~]# vim /etc/my.cnf.d/mariadb-server.cnf

[root@webserver1 ~]# systemctl start mariadb.service

[root@webserver2 ~]# vim /etc/my.cnf.d/mariadb-server.cnf

[root@webserver2 ~]# systemctl start mariadb.service

Webserver1服务端:

MariaDB [mysql]> create user lhd@'%' identified by '123';

Query OK, 0 rows affected (0.000 sec)

MariaDB [mysql]> grant all on *.* to lhd@'%';

Query OK, 0 rows affected (0.000 sec)

Webserver2服务端:

MariaDB [(none)]> create user lhd@'%' identified by '123';

Query OK, 0 rows affected (0.001 sec)

MariaDB [(none)]> grant all on *.* to lhd@'%';

Query OK, 0 rows affected (0.000 sec)

测试

[root@haproxy ~]# for i in {1..6}; do mysql -ulhd -p123 -h 192.168.182.151 -e "select @@server_id"; done

+-------------+

| @@server_id |

+-------------+

|           1 |

+-------------+

+-------------+

| @@server_id |

+-------------+

|           2 |

+-------------+

+-------------+

| @@server_id |

+-------------+

|           1 |

+-------------+

+-------------+

| @@server_id |

+-------------+

|           2 |

+-------------+

+-------------+

| @@server_id |

+-------------+

|           1 |

+-------------+

+-------------+

| @@server_id |

+-------------+

|           2 |

+-------------+

8、HAProxy https 实现

1、制作证书

[root@haproxy ~]# mkdir -p /etc/haproxy/certs

[root@haproxy ~]# openssl req -newkey rsa:2048 -nodes -sha256 -keyout /etc/haproxy/certs/lhd.key -x509 -days 365 -out /etc/haproxy/certs/lhd.crt

[root@haproxy ~]# ls /etc/haproxy/certs/

lhd.crt  lhd.key

[root@haproxy ~]# cat /etc/haproxy/certs/lhd.crt /etc/haproxy/certs/lhd.key  > /etc/haproxy/certs/lhd.pem

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg

#全站加密之后,当访问IP时默认是80端口,会自动转到443端口登陆

测试:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值