1.为什么用haproxy
当后端主机有一个出现问题了的时候,我们需要访问的流量全部打到正常工作的后端主机,所以我们需要后端检测,lvs没有后端检测,所以就需要用到haproxy
2.负载均衡
2.1 什么是负载均衡
负载均衡,Load Balance 简称LB,是一种服务或基于硬件设备等实现的高可用反向代理技术,负载均衡将特定的业务(web服务,网络流量等)分担给指定的一个或多个后端特定的服务器或设备,从而提高了公司业务的并发处理能力。保证了业务的高可用性,方便业务后期水平动态扩展‘
2.2为什么用负载均衡
1.web服务器的动态水平扩展--->对用户无感知
2.增加业务并发访问及处理能力---->解决单服务器的瓶颈问题
3.节约公网IP地址---->降低IT支出成本
4.隐藏内部服务器IP---->提高内部服务器安全性
5.配置简单----> 固定格式的配置问价
6.功能丰富--->支持四层和七层,支持动态线下主机
7.性能较强---->并发数万甚至数十万
2.3负载均衡类型
2.3.1硬件
2.3.2四层负载均衡
1.通过IP+port决定负载均衡的去向
2.对流量请求进行NAT处理,转发到后台服务
3.记录tcp udp流量分别是由哪台服务器处理,后续改请求连接的流量都通过该服务器处理
4.支持四层的软件
lvs:重量级四层均衡负载均衡器
nginx:轻量级四层负载均衡器,可缓存(nginx四层是通过upstream模块)
Haproxy:模拟四层转发
2.3.3七层负载均衡
1.通过虚拟url或主机ip进行流量识别,根据应用层信息进行解析,决定是否需要进行负载均衡
2.代理后台服务器与客户端进行连接,如nginx可代理前后端,与前端客户端TCP连接,与后端服务器建立TCP连接
3.支持七层代理的软件
nginx:基于http协议(nginx七层是通过proxy_pass)
Haproxy:七层代理,会话保持,标记,路径转移等
3.haproxy的安装和服务信息
3.1实验环境
haproxy主机:172.25.250.100 server1:172.25.250.10 server2:172.25.250.20 #########server1、server2主机安装nginx yum install nginx -y #######server1: echo server1 - 172.25.250.10 > /usr/share/nginx/html/index.html ########server2: echo server2 - 172.25.250.20 > /usr/share/nginx/html/index.html ########haproxy主机: yum install haproxe -y rpm -qc haproxy //查找配置文件 vim /etc/haproxy/harpxy.cfg frontend webcluster bind *:80 ##bind 监听的端口 *:80 这台主机所有80端口 mode http ##四层还是七层,http是七层 use_backend webcluster-host ##use_backend 使用哪个后端 backend webcluster-host ##定义webcluster-host balance roundrobin ##balance 调度规则 server web1 172.25.250.10:80 server web2 172.25.250.20:80 或者用listen模块 listen webcluster bind *:80 mode http balance roundroubin server web1 172.25.250.10:80 server web2 172.25.250.20:80
3.2Haproxy的基本配置信息
Haproxy的配置文件haproxy.cfg由两大部分组成,分别是:
global:全局配置段
进程及安全配置相关的参数
性能调整相关参数
Debug参数
proxies:代理配置段:
defaults:为frontend,backend,listen提供默认配置
frontend:前端,相当于nginx中的server{}
backend:后端,相当于nginx中的upstream{}
listen:同时拥有前端和后端配置,配置简单,生产推荐使用
3.2.1global配置
3.2.1.1global配置参数说明
参数 | 类型 | 作用 |
chroot | 全局 | 锁定运行目录 |
deamom | 全局 | 以守护进程运行 |
user、group、uid、gid | 全局 | 运行haproxy的用户身份 |
stats socket | 全局 | 套接字文件 |
nbproc N | 全局 | 开启的haproxy worker进程数,摸摸人进程数是一个 |
nbthread 1 (和nbproc 互斥) | 全局 | 指定每个haproxy进程开启的线程数,默认为每个进程一个 线程 |
cpu-map 1 0 | 全局 | 绑定haproxy worker 进程至指定CPU,将第1个work进程绑 定至0号CPU |
cpu-map 2 1 | 全局 | 绑定haproxy worker 进程至指定CPU,将第2个work进程绑 定至1号CPU |
maxconn N | 全局 | 每个haproxy进程的最大并发连接数 |
maxsslconn N | 全局 | 每个haproxy进程ssl最大连接数,用于haproxy配置了证书的 场景下 |
maxconnrate N | 全局 | 每个进程每秒创建的最大连接数量 |
spread-checks N | 全局 | 后端server状态check随机提前或延迟百分比时间,建议2- 5(20%-50%)之间,默认值0 |
pidfile | 全局 | 指定pid文件路径 |
log 127.0.0.1 local2 info | 全局 | 定义全局的syslog服务器;日志服务器需要开启UDP协议, 最多可以定义两个 |
小实验:haproxy基本部署
[root@haproxy ~]# rpm -qc haproxy /etc/haproxy/haproxy.cfg //配置文件 /etc/logrotate.d/haproxy /etc/sysconfig/haproxy [root@haproxy ~]# vim /etc/haproxy/haproxy.cfg ....以上省略 # main frontend which proxys to the backends #--------------------------------------------------------------------- ########################################这里添加 frontend webcluster bind *:80 mode http use_backend webcluster-host backend webcluster-host balance roundrobin server webserver1 172.25.250.10:80 server webserver2 172.25.250.20:80 ###或 listen webcluster bind *:80 mode http balance roundrobin server webserver1 172.25.250.10:80 server webserver2 172.25.250.20:80 #######################################到这里 frontend main ...以下省略 ######测试 [root@localhost ~]# curl 172.25.250.100 server1 - 172.25.250.10 [root@localhost ~]# curl 172.25.250.100 server2 - 172.25.250.20 [root@localhost ~]# curl 172.25.250.100 server1 - 172.25.250.10 [root@localhost ~]# curl 172.25.250.100 server2 - 172.25.250.20 #####关闭server1(模拟坏掉) 后端检测 [root@webserver1 ~]# systemctl stop nginx.service [root@localhost ~]# curl 172.25.250.100 server2 - 172.25.250.20 [root@localhost ~]# curl 172.25.250.100 server2 - 172.25.250.20 [root@localhost ~]# curl 172.25.250.100 server2 - 172.25.250.20
进程
haproxy默认一个进程
多进程设定
[root@haproxy ~]# pstree -p | grep haproxy //一个进程 |-haproxy(4462)---haproxy(4464)---{haproxy}(4465) [root@haproxy ~]# vim /etc/haproxy/haproxy.cfg global log 127.0.0.1 local2 chroot /var/lib/haproxy pidfile /var/run/haproxy.pid maxconn 100000 user haproxy group haproxy daemon # turn on stats unix socket stats socket /var/lib/haproxy/stats # utilize system-wide crypto-policies ssl-default-bind-ciphers PROFILE=SYSTEM ssl-default-server-ciphers PROFILE=SYSTEM nbproc 2 ######这里添加nbproc 2 [root@haproxy ~]# systemctl restart haproxy.service [root@haproxy ~]# pstree -p | grep haproxy //两个进程 |-haproxy(4497)-+-haproxy(4499) | `-haproxy(4500) 这样就会出现一个问题,这两个进程在使用时可能会出现cpu使用的漂移,一会用第一个一会用第二个 [root@haproxy ~]# vim /etc/haproxy/haproxy.cfg # utilize system-wide crypto-policies ssl-default-bind-ciphers PROFILE=SYSTEM ssl-default-server-ciphers PROFILE=SYSTEM nbproc 2 cpu-map 1 0 //第一个进程用第一个核心,就是将第一个work进行绑定到0号cpu cpu-map 2 1 //第二个进程用第二个核心,将第二个work进程绑定到1号cpu [root@haproxy ~]# systemctl restart haproxy.service [root@haproxy ~]# pstree -p | grep haproxy |-haproxy(4510)-+-haproxy(4512) | `-haproxy(4513) [root@haproxy ~]# cat /proc/4513/status | grep -i thread Threads: 1 //可以看到子进程里面只有一个进程
线程
多线程
nbthread 1
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg # utilize system-wide crypto-policies ssl-default-bind-ciphers PROFILE=SYSTEM ssl-default-server-ciphers PROFILE=SYSTEM #nbproc 2 //多进程 #cpu-map 1 0 #cpu-map 2 1 nbthread 2 //多线程 #############多线程和多进程不能同时使用 [root@haproxy ~]# systemctl restart haproxy.service [root@haproxy ~]# pstree -p | grep haproxy |-haproxy(4534)---haproxy(4536)---{haproxy}(4537) [root@haproxy ~]# cat /proc/4536/status | grep -i thread Threads: 2
定义日志
[root@haproxy ~]# vim /etc/rsyslog.conf ...省略以上内容 #module(load="imudp") # needs to be done just once #input(type="imudp" port="514") # Provides TCP syslog reception # for parameters see http://www.rsyslog.com/doc/imtcp.html module(load="imtcp") # needs to be done just once //取消注释 input(type="imtcp" port="514") //取消注释 即打开UDP端口 #### RULES #### .....省略以上内容 # Save news errors of level crit and higher in a special file. uucp,news.crit /var/log/spooler # Save boot messages also to boot.log local7.* /var/log/boot.log local2.* /var/log/haproxy.log //添加这一行,定义local2到 /var/log/haproxy.log 文件里面 # ### sample forwarding rule ### ....省略以下内容
vim /etc/haproxy/haproxy.cfg
vim /etc/rsyslog.conf
3.2.2 proxies配置
代理配置
3.2.2.1 proxies参数说明proxies
defaults:
默认配置项,针对以下的forntend、backend和listen生效,可以多个name也可以没有name
forntend:
前端servername,类似于nginx的一个虚拟主机server和lvs服务集群
backend
后端服务组,等于nginx的upstream和lvs中的RS服务器
listen
将forntend和backend合并在一起配置,相对于forntend和backend配置更简洁,生产常用
server webserver1 172.25.250.10:80 check inter 2 fall 3 rise 5 weight 2 server webserver2 172.25.250.20:80 check inter 2 fall 3 rise 5 weight 1 ///每隔两秒检测一次,检测完了发现第一次没连上接着连第二次,第三次,第三次也没连上,宣告下线,检测5次为上限 [root@haproxy ~]# vim /etc/haproxy/haproxy.cfg ... listen webcluster bind *:80 mode http balance roundrobin server webserver1 172.25.250.10:80 check inter 2 fall 3 rise 5 weight 2 server webserver2 172.25.250.20:80 check inter 2 fall 3 rise 5 weight 1 ... #######检测 权重2:1 [root@localhost ~]# curl 172.25.250.100 server1 - 172.25.250.10 [root@localhost ~]# curl 172.25.250.100 server1 - 172.25.250.10 [root@localhost ~]# curl 172.25.250.100 server2 - 172.25.250.20 [root@localhost ~]# curl 172.25.250.100 server1 - 172.25.250.10
使用backup,
就是当server1和server2都停止工作时,为了给用户提示(自定义),它原本有提示
在haproxy主机安装httpd [root@haproxy ~]# yum install httpd -y [root@haproxy ~]# vim /etc/httpd/conf/httpd.conf //更改端口为8080 [root@haproxy ~]# systemctl enable --now httpd [root@haproxy ~]# vim /etc/haproxy/haproxy.cfg ... listen webcluster bind *:80 mode http balance roundrobin server webserver1 172.25.250.10:80 check inter 2 fall 3 rise 5 weight 2 server webserver2 172.25.250.20:80 check inter 2 fall 3 rise 5 weight 1 server webserver_sorry 172.25.250.100:8080 backup ... //当server全都不工作时才调动backup,即只要有一台工作,都不会调动backup [root@haproxy ~]# systemctl restart haproxy.service 测试 全都不工作时 [root@localhost ~]# curl 172.25.250.100 sorry 下班了 一台工作时 [root@localhost ~]# curl 172.25.250.100 server1 - 172.25.250.10 [root@localhost ~]# [root@localhost ~]# curl 172.25.250.100 server1 - 172.25.250.10 [root@localhost ~]# curl 172.25.250.100 server1 - 172.25.250.10 [root@localhost ~]# curl 172.25.250.100 server1 - 172.25.250.10
disable
两台都正常工作 [root@localhost ~]# curl 172.25.250.100 server2 - 172.25.250.20 [root@localhost ~]# curl 172.25.250.100 server1 - 172.25.250.10 [root@localhost ~]# curl 172.25.250.100 server1 - 172.25.250.10 [root@localhost ~]# curl 172.25.250.100 server2 - 172.25.250.20 然后现在一台机器维修 listen webcluster bind *:80 mode http balance roundrobin server webserver1 172.25.250.10:80 check inter 2 fall 3 rise 5 weight 2 disabled //server1维修 server webserver2 172.25.250.20:80 check inter 2 fall 3 rise 5 weight 1 server webserver_sorry 172.25.250.100:8080 backup [root@haproxy ~]# systemctl restart haproxy.service 测试 [root@localhost ~]# curl 172.25.250.100 server2 - 172.25.250.20 [root@localhost ~]# curl 172.25.250.100 server2 - 172.25.250.20 [root@localhost ~]# curl 172.25.250.100 server2 - 172.25.250.20 [root@localhost ~]# curl 172.25.250.100 server2 - 172.25.250.20
redirect prefix http://www.baidu.com/ 访问从定向定位到百度
listen webcluster bind *:80 mode http balance roundrobin redirect prefix http://www.baidu.com/ #server webserver1 172.25.250.10:80 check inter 2 fall 3 rise 5 weight 2 disabled #server webserver2 172.25.250.20:80 check inter 2 fall 3 rise 5 weight 1 #server webserver_sorry 172.25.250.100:8080 backup [root@haproxy ~]# systemctl restart haproxy.service
3.3socat工具
对服务器动态权重和其它状态可以利用socat工具进行调整,socat时LInux下的一个多功能的网络工具,名字来由 socat cat 相当于netcat的增强版。socat主要特点是在两个数据流之间建立双向通道,且支持众多协议和链接方式,如IP、TCP、UDP、ipv6、socket文件等
3.3.1利用socat对服务器动态权重调整
stats socket /var/lib/haproxy/stats //socket 套接字,定义到/var/lib/haproxy/stats文件里面,最开始记录状态,默认情况下,只能查看不能更改 stats socket /var/lib/haproxy/stats mode 600 level admin //对其提权, mode 600-- 权限为600 level admin---可以通过stats控制haproxy里面的配置,如果不加就是普通用户,加了就相当于管理员 [root@haproxy ~]# ll /var/lib/haproxy/stats srw------- 1 root root 0 Aug 9 22:37 /var/lib/haproxy/stats [root@haproxy ~]# yum install socat -y [root@haproxy ~]# echo "show info" | socat stdio /var/lib/haproxy/stats ///查看haproxy的状态 [root@haproxy ~]# echo "show servers state" | socat stdio /var/lib/haproxy/stats //查看server的状态 [root@haproxy ~]# echo get weight webcluster/webserver1 | socat stdio /var/lib/haproxy/stats //查看看权重 2 (initial 2) //当前权重为2,配置文件里面权重为2,以当前为准 [root@haproxy ~]# echo "set weight webcluster/webserver1 1" | socat stdio /var/lib/haproxy/stats //更改权重 [root@haproxy ~]# echo get weight webcluster/webserver1 | socat stdio /var/lib/haproxy/stats 1 (initial 2) //当前权重1,配置文件权重2 [root@haproxy ~]# echo "disable server webcluster/webserver2" | socat stdio /var/lib/haproxy/stats //指定server下线 [root@haproxy ~]# echo "enable server webcluster/webserver2" | socat stdio /var/lib/haproxy/stats //指定server上线
3.3.2针对多进程处理方法
如果开启多进程那么我们在对进程的sock文件进行操作时其对进程的操作是随机的
如果需要指定操作进程那么需要用多socat文件来完成
[root@haproxy ~]# ll /var/lib/haproxy/ total 0 srw------- 1 root root 0 Aug 9 23:01 stats //目前一个进程 [root@haproxy ~]# vim /etc/haproxy/haproxy.cfg //haproxy多进程如何热处理 stats socket /var/lib/haproxy/stats1 mode 600 level admin process 1 stats socket /var/lib/haproxy/stats2 mode 600 level admin process 2 # utilize system-wide crypto-policies ssl-default-bind-ciphers PROFILE=SYSTEM ssl-default-server-ciphers PROFILE=SYSTEM nbproc 2 cpu-map 1 0 cpu-map 2 1 [root@haproxy ~]# systemctl restart haproxy.service [root@haproxy ~]# ll /var/lib/haproxy/ total 0 srw------- 1 root root 0 Aug 9 23:01 stats srw------- 1 root root 0 Aug 9 23:12 stats1 srw------- 1 root root 0 Aug 9 23:12 stats2 [root@haproxy ~]# echo "show info" | socat stdio /var/lib/haproxy/stats ///原来的进程被拒绝,没有用原来的进程了,但是他没删除,现在是stats1和stats2 2024/08/09 23:13:32 socat[5166] E connect(5, AF=1 "/var/lib/haproxy/stats", 24): Connection refused [root@haproxy ~]# echo "show info" | socat stdio /var/lib/haproxy/stats1
4.haproxy算法
haproxy通过固定参数balance指明对后端服务器的调度算法
balance参数可以配置在listen或backend选项中
haproxy的调度算法分为动态和静态
有些算法可以根据参数在静态和动态中相互转换
4.1动态算法
基于后端服务器状态进行调度适当调整
新请求将优先调整到当前负载较低的服务器
权重可以在haproxy运行时动态调整无需重启(就是可以通过socat进行热设定)
4.1.1roundrobin
1.基于权重的轮询动态调度算法
2.支持权重的运行时调整,不同于lvs中的rr轮询
3.haproxy中的roundrobin支持慢启动(新加的服务器会逐渐增加转发数)
4.其每个后端backend中最多支持4095个real server
5.支持对real server权重动态调整
6.roundrobin为默认调度算法,此算法使用广泛
注意:他是把流量打到权重高且负载小的主机
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg listen webcluster bind *:80 mode http balance roundrobin //roundrobin #balance static-rr #balance first #redirect prefix http://www.baidu.com/ #cookie WEBCOOKIE insert nocache indirect server webserver1 172.25.250.10:80 check inter 2 fall 3 rise 5 weight 2 server webserver2 172.25.250.20:80 check inter 2 fall 3 rise 5 weight 1 #server webserver_sorry 172.25.250.100:8080 backup [root@haproxy ~]# echo set weight webcluster/webserver1 1 | socat stdio /var/lib/haproxy/stats //支持在线调整权重 echo "get weight webcluster/webserver1 " | socat stdio /var/lib/haproxy/stats 1 (initial 2) //当前权重1,配置文件权重2
4.1.2 leastconn
leastconnn加权的最少连接的动态(谁的连接最少给谁)
支持权重运行时调整和慢启动,即根据当前连接最少得后端服务器而非权重进行优先调度(新客户端连接)---当两个连接数差不多时,给权重最高的
比较合适长连接的场景使用 如MySQL...
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg listen webcluster bind *:80 mode http #balance roundrobin balance leastconn //leastconn #balance static-rr #balance first #redirect prefix http://www.baidu.com/ #cookie WEBCOOKIE insert nocache indirect server webserver1 172.25.250.10:80 check inter 2 fall 3 rise 5 weight 2 server webserver2 172.25.250.20:80 check inter 2 fall 3 rise 5 weight 1 #server webserver_sorry 172.25.250.100:8080 backup [root@haproxy ~]# systemctl restart haproxy.service
4.2静态算法
静态算法,按照事先定义好的规则轮询公平调度,不关心后端服务器的当前负载,连接数和响应速度等,且无法实现实时修改权重(只能0和1,不支持其他值),只能靠重启haproxy生效
4.2.1 static-rr:基于权重的轮询调度
不支持运行时利用socat进行权重的动态调整(只支持0和1,不支持其他值)
不支持后端服务器的慢启动
其后端主机数量没有限制,相当于lvs中的wrr
慢启动时指在服务器刚刚启动上不会把他所有的所该承担的压力全部给她,而是先给一部分,当没问提再给一部分
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg listen webcluster bind *:80 mode http #balance roundrobin balance static-rr //static-rr #redirect prefix http://www.baidu.com/ server webserver1 172.25.250.10:80 check inter 2 fall 3 rise 5 weight 2 server webserver2 172.25.250.20:80 check inter 2 fall 3 rise 5 weight 1 server webserver_sorry 172.25.250.100:8080 backup # turn on stats unix socket stats socket /var/lib/haproxy/stats1 mode 600 level admin #stats socket /var/lib/haproxy/stats2 mode 600 level admin process 2 //注释掉,不能开两个进程 # utilize system-wide crypto-policies ssl-default-bind-ciphers PROFILE=SYSTEM ssl-default-server-ciphers PROFILE=SYSTEM #nbproc 2 // #cpu-map 1 0 // #cpu-map 2 1 // #nbthread 2 // [root@haproxy ~]# systemctl restart haproxy.service 测试 [root@localhost ~]# for i in {1..10}; do curl 172.25.250.100; done server1 - 172.25.250.10 server1 - 172.25.250.10 server2 - 172.25.250.20 server1 - 172.25.250.10 server1 - 172.25.250.10 server2 - 172.25.250.20 server1 - 172.25.250.10 server1 - 172.25.250.10 server2 - 172.25.250.20 server1 - 172.25.250.10
4.2.2 first
根据服务器在列表中的位置,自上而下进行调度
其只会当第一服务器的连接数达到上限,新请求才会分配给下一台服务
其会忽略服务器的权重设置
不支持用socat进行动态修改权重,可以设置0和1,可以设置其他值但无效
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg listen webcluster bind *:80 mode http #balance roundrobin #balance static-rr balance first //first #redirect prefix http://www.baidu.com/ server webserver1 172.25.250.10:80 maxconn 1 check inter 2 fall 3 rise 5 weight 2 //为了显示效果,我们把server1设置最大承受连接数为1 maxconn 1 server webserver2 172.25.250.20:80 check inter 2 fall 3 rise 5 weight 1 [root@haproxy ~]# systemctl restart haproxy.service
4.3其他算法(可调)
既可以看作是静态也可以看作是动态
4.3.1 source
源地址hash,基于用户源地址hash并将请求转发到后端服务器,后续同一个源地址将被转发到同一个后端web服务器,此方式当后端服务器数量发送变化时,会导致很多用户的请求转发至新的后端服务器,默认为静态方式,但是可以通过hash-type支持的选项中更改这个算法,一般是在不插入cookie的tcp模式下使用,也可以拒绝 会话cookie的客户提供最好的会话粘性,适用于session会话保持但不支持cookie和缓存的场景
源地址有两种转发客户端请求到后端的服务器选取计算方式,分别是取模法和一致性hash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg listen webcluster bind *:80 mode http #balance roundrobin #balance leastconn #balance static-rr #balance first balance source //source #redirect prefix http://www.baidu.com/ #cookie WEBCOOKIE insert nocache indirect server webserver1 172.25.250.10:80 check inter 2 fall 3 rise 5 weight 2 server webserver2 172.25.250.20:80 check inter 2 fall 3 rise 5 weight 1 #server webserver_sorry 172.25.250.100:8080 backup [root@haproxy ~]# systemctl restart haproxy.service ####测试 [root@localhost ~]# for i in {1..10}; do curl 172.25.250.100; done //流量打到了同一台主机上,这样会导致算法失衡,这是source算法的缺陷 server2 - 172.25.250.20 server2 - 172.25.250.20 server2 - 172.25.250.20 server2 - 172.25.250.20 server2 - 172.25.250.20 server2 - 172.25.250.20 server2 - 172.25.250.20 server2 - 172.25.250.20 server2 - 172.25.250.20 server2 - 172.25.250.20
4.3.2 map-base 取模法
map-based:取模法,对source地址进行hash计算,再基于服务器权重的取模,最终结果决定将此请求转发至对应的后端服务器
此方法是静态的,即不支持在线调整权重,不支持慢启动,可实现对后端服务器均衡调度
缺点是当服务器权重发生变化时,即有服务器上线或下线,都会因总权重发生变化而导致调度结果整体改变
hash-type指定的默认值为此算法
取模运算:就是计算两个数相除后的余数,10%7=3
map-based算法:基于权重取模,hash(source_ip)%所有的后端服务器相加的总权重
就比如
当源hash值为1111,1112,1113 ,三台服务器a,b,c权重均为1,总权重为3,那么abc的调度就会分别被设定为0,1,2,a---0,b---1,c----2(1111%3=1,1112%3=2,1113%3=0)
即
1111------->b
1112------->c
1113-------->a
那么如果a下线了,总权重就变为2
1111%2=1,1112%2=0,1113%2=1
即
1111------>b
1112------>a 但是a已经下线
1113------->b
所以,1112和1113被调度到的主机都发生了变化,这样会导致会话丢失,故我们需要hash一致性来解决这个问题
4.3.3一致性hash
一致性hash:当服务器的总权重发生变化时,对调度结果影响是局部的,不会引起大的变动
该hash的算法是动态的,支持使用socat等工具进行在线权重调整,支持慢启动
1、后端服务器hash换点keyA=hash(后端服务器虚拟ip)%(2^32) 得到一个数落到hash环上,这个数范围:0—2^32-1
2、也对客户端ip进行hash运算,key1=hash(client_ip)%2^32,得到的值也落到hash环上
hash环是顺时针转
3、将keyA和key1都放在hash环上,将用户请求调度到离key1最近的keyA对应的后端服务器
上图
蓝色代表服务器,粉色代表访问请求(客户主机)
随机数的生成 //echo $RANDOM
10以内的随机数 //echo $[$RANDOM%10]
cat /dev/random 这个文件里面取,他是来自于鼠标的无轨迹运动和键盘的敲击生成
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg listen webcluster bind *:80 mode http #balance roundrobin #balance leastconn #balance static-rr #balance first balance source ##source运算 hash-type consistent ##hash一致性 #redirect prefix http://www.baidu.com/ #cookie WEBCOOKIE insert nocache indirect server webserver1 172.25.250.10:80 check inter 2 fall 3 rise 5 weight 2 server webserver2 172.25.250.20:80 check inter 2 fall 3 rise 5 weight 1 #server webserver_sorry 172.25.250.100:8080 backup [root@haproxy ~]# systemctl restart haproxy.service ###测试 [root@localhost ~]# for i in {1..10}; do curl 172.25.250.100; done server1 - 172.25.250.10 server1 - 172.25.250.10 server1 - 172.25.250.10 server1 - 172.25.250.10 server1 - 172.25.250.10 server1 - 172.25.250.10 server1 - 172.25.250.10 server1 - 172.25.250.10 server1 - 172.25.250.10 server1 - 172.25.250.10 [root@haproxy ~]# echo set weight webcluster/webserver1 1 | socat stdio /var/lib/haproxy/stats //支持在线调整权重 echo "get weight webcluster/webserver1 " | socat stdio /var/lib/haproxy/stats 1 (initial 2) //当前权重1,配置文件权重2 ####更改了权重,也不影响 [root@localhost ~]# for i in {1..10}; do curl 172.25.250.100; done server1 - 172.25.250.10 server1 - 172.25.250.10 server1 - 172.25.250.10 server1 - 172.25.250.10 server1 - 172.25.250.10 server1 - 172.25.250.10 server1 - 172.25.250.10 server1 - 172.25.250.10 server1 - 172.25.250.10 server1 - 172.25.250.10
4.3.4uri
基于对用户请求的URI的左半部分或整个uri,再将hash结果对总权重进行取模后,根据最终结果将请求转发到后端指定的服务器
默认是静态算法
也可以通过hash-type指定map-based和consistent,来定义使用取模法还是hash
注意:
此算法基于运用层,所以支持mode http
不支持mode tcp
<scheme>://<user>:<password>@<host>:<port>/<path>:<params>?<query>#<frag>
<scheme>:// ##http://
<host>: ##baidu.com
<port> ##端口
<path> ##文件路径
<params>?<query> ?前面是指令 ?后面想要看的东西
<frag> ##片段左半部分:/<path>:<params>
整个uri:/<path>:<params>?<query>#<frag>
[root@webserver1 ~]# echo 172.25.250.10 - index1.html > /usr/share/nginx/html/index1.html [root@webserver1 ~]# echo 172.25.250.10 - index2.html > /usr/share/nginx/html/index2.html [root@webserver1 ~]# echo 172.25.250.10 - index3.html > /usr/share/nginx/html/index3.html [root@webserver2 ~]# echo 172.25.250.20 - index1.html > /usr/share/nginx/html/index1.html [root@webserver2 ~]# echo 172.25.250.20 - index2.html > /usr/share/nginx/html/index2.html [root@webserver2 ~]# echo 172.25.250.20 - index3.html > /usr/share/nginx/html/index3.html [root@haproxy ~]# vim /etc/haproxy/haproxy.cfg listen webcluster bind *:80 mode http #balance roundrobin #balance leastconn #balance static-rr #balance first #balance source balance uri //uri hash-type consistent //启动动态 #redirect prefix http://www.baidu.com/ #cookie WEBCOOKIE insert nocache indirect server webserver1 172.25.250.10:80 check inter 2 fall 3 rise 5 weight 2 server webserver2 172.25.250.20:80 check inter 2 fall 3 rise 5 weight 1 #server webserver_sorry 172.25.250.100:8080 backup [root@haproxy ~]# systemctl restart haproxy.service ####测试 [root@localhost ~]# curl 172.25.250.100/index1.html //第一次访问index1,返回10 172.25.250.10 - index1.html [root@localhost ~]# curl 172.25.250.100/index2.html //第一次访问index2,返回20 172.25.250.20 - index2.html [root@localhost ~]# curl 172.25.250.100/index3.html //第一次访问index3,返回10 172.25.250.10 - index3.html [root@localhost ~]# curl 172.25.250.100/index1.html //第二次访问index1,返回10 就是uri不变,第一次返回啥第二次就返回啥 172.25.250.10 - index1.html [root@localhost ~]# curl 172.25.250.100/index2.html 172.25.250.20 - index2.html
4.3.5url_param
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg listen webcluster bind *:80 mode http #balance roundrobin #balance leastconn #balance static-rr #balance first #balance source #balance uri balance url_param name,userid hash-type consistent #redirect prefix http://www.baidu.com/ #cookie WEBCOOKIE insert nocache indirect server webserver1 172.25.250.10:80 check inter 2 fall 3 rise 5 weight 1 server webserver2 172.25.250.20:80 check inter 2 fall 3 rise 5 weight 1 #server webserver_sorry 172.25.250.100:8080 backup [root@haproxy ~]# systemctl restart haproxy.service ###测试 [root@localhost ~]# curl 172.25.250.100/index2.html?name=lee 172.25.250.10 - index2.html [root@localhost ~]# curl 172.25.250.100/index2.html?name=lee 172.25.250.10 - index2.html [root@localhost ~]# curl 172.25.250.100/index2.html?name=lee 172.25.250.10 - index2.html [root@localhost ~]# curl 172.25.250.100/index2.html?name=test 172.25.250.20 - index2.html [root@localhost ~]# curl 172.25.250.100/index2.html?name=test 172.25.250.20 - index2.html
4.3.6 hdr
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg listen webcluster bind *:80 mode http #balance roundrobin #balance leastconn #balance static-rr #balance first #balance source #balance uri #balance url_param name,userid balance hdr(User-Agent) ##hdr hash-type consistent #redirect prefix http://www.baidu.com/ #cookie WEBCOOKIE insert nocache indirect server webserver1 172.25.250.10:80 check inter 2 fall 3 rise 5 weight 1 server webserver2 172.25.250.20:80 check inter 2 fall 3 rise 5 weight 1 #server webserver_sorry 172.25.250.100:8080 backup [root@haproxy ~]# systemctl restart haproxy.service
测试
5.高级功能及配置
5.1基于cookie的会话保持
cookie value:为当前server指定cookie值,实现基于cookie的会话黏性,相对于基于 source 地址hash 调度算法对客户端的调度更精准,但同时也加大了haproxy负载,目前此模式使用较少, 已经被session 共享服务器代替
不支持 tcp mode,使用 http mode
5.1.1 配置选项
name: #cookie 的 key名称,用于实现持久连接
insert: #插入新的cookie,默认不插入cookie
indirect: #如果客户端已经有cookie,则不会再发送cookie信息
nocache: #当client和hapoxy之间有缓存服务器(如:CDN)时,不允许中间缓存器缓存cookie,
#因为这会导致很多经过同一个CDN的请求都发送到同一台后端服务器
配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg listen webcluster bind *:80 mode http balance roundrobin // #balance static-rr #balance first #redirect prefix http://www.baidu.com/ cookie WEBCOOKIE insert nocache indirect // server webserver1 172.25.250.10:80 cookie lee1 check inter 2 fall 3 rise 5 weight 2 // server webserver2 172.25.250.20:80 cookie lee2 check inter 2 fall 3 rise 5 weight 1 // #server webserver_sorry 172.25.250.100:8080 backup [root@haproxy ~]# systemctl restart haproxy.service
####命令行测试 [root@localhost ~]# curl -b WEBCOOKIE=lee1 172.25.250.100 server1 - 172.25.250.10 ##就是如果浏览器cookie缓存lee1,那么永远就会被调度到server1 [root@localhost ~]# curl -b WEBCOOKIE=lee2 172.25.250.100 server2 - 172.25.250.20
5.2haproxy状态页
5.2.1状态页配置项
stats enable #基于默认的参数启用stats page
stats hide-version #将状态页中haproxy版本隐藏
stats refresh <delay> #设定自动刷新时间间隔,默认不自动刷新
stats uri <prefix> #自定义stats page uri,默认值:/haproxy?stats
stats auth <user>:<passwd> #认证时的账号和密码,可定义多个用户,每行指定一个用户
#默认:no authentication
stats admin { if | unless } <cond> #启用stats page中的管理功能
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg listen stats mode http bind *:9999 stats enable stats uri /status stats auth lee:lee [root@haproxy ~]# systemctl restart haproxy.service
5.3 IP透传
web服务器中需要记录客户端的真实IP地址,用于做访问统计、安全防护、行为分析、区域排行等场景。
5.3.1 七层IP透传
option forwardfor except 127.0.0.0/8 IP透传用到这个fowardfor这个参数
vim /etc/haproxy/haproxy.conf
Apache
#####我们把172.25.250.10server1主机上的nginx停掉,下载httpd [root@webserver1 ~]# systemctl disable nginx.service Removed "/etc/systemd/system/multi-user.target.wants/nginx.service". [root@webserver1 ~]# systemctl stop nginx.service [root@webserver1 ~]# yum install httpd -y [root@webserver1 ~]# echo this is server1 - 172.25.250.10 > /var/www/html/index.html [root@webserver1 ~]# systemctl start httpd #####然后我们在客户端主机172.25.250.101主机curl 172.25.250.100 [root@localhost ~]# curl 172.25.250.100 this is server1 - 172.25.250.10 [root@localhost ~]# curl 172.25.250.100 server2 - 172.25.250.20 [root@localhost ~]# curl 172.25.250.100 this is server1 - 172.25.250.10 ####然后我们去172.25.250.10server1主机查看httpd是否可以看到客户端IP [root@webserver1 ~]# cat /etc/httpd/logs/access_log 172.25.250.100 - - [11/Aug/2024:11:24:55 +0800] "GET / HTTP/1.1" 200 32 "-" "curl/7.76.1" 172.25.250.100 - - [11/Aug/2024:11:24:59 +0800] "GET / HTTP/1.1" 200 32 "-" "curl/7.76.1" 可与看到没有IP传过来,因为Apache里面默认没有设定 ####Apache里面设定 [root@webserver1 ~]# vim /etc/httpd/conf/httpd.conf LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined LogFormat "%h %l %u %t \"%r\" %>s %b" common <IfModule logio_module> # You need to enable mod_logio.c to use %I and %O LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio </IfModule> [root@webserver1 ~]# systemctl restart httpd [root@localhost ~]# curl 172.25.250.100 server2 - 172.25.250.20 [root@localhost ~]# curl 172.25.250.100 this is server1 - 172.25.250.10 [root@localhost ~]# curl 172.25.250.100 server2 - 172.25.250.20 [root@localhost ~]# curl 172.25.250.100 this is server1 - 172.25.250.10 [root@webserver1 ~]# cat /etc/httpd/logs/access_log 172.25.250.101 172.25.250.100 - - [11/Aug/2024:12:36:30 +0800] "GET / HTTP/1.1" 200 32 "-" "curl/7.76.1" 172.25.250.101 172.25.250.100 - - [11/Aug/2024:12:36:32 +0800] "GET / HTTP/1.1" 200 32 "-" "curl/7.76.1"
vim /etc/httpd/conf/httpd.conf
测试
5.3.2 四层IP透传
nginx中做四层,Apache里面做不了
前提
测试
上面四层看不到IP透传,所以我们要做设定代理
测试
然后四层做完,要做七层,就需要把nginx里面刚才加的参数去掉
5.4ACL
访问控制列表ACL,(Access Control Lists)
是一种基于包过滤的访问控制技术
它可以根据设定的条件对经过服务器传输的数据包进行过滤(条件匹配)即对接收到的报文进行匹配和过 滤,基于请求报文头部中的源地址、源端口、目标地址、目标端口、请求方法、URL、文件后缀等信息内 容进行匹配并执行进一步操作,比如允许其通过或丢弃。
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg frontend webcluster bind *:80 mode http acl test hdr_dom(host) -i www.timinglee.org use_backend webcluster-host if test default_backend default-host backend webcluster-host mode http server webserver1 172.25.250.10:80 check inter 2 fall 2 rise 5 backend default-host mode http server webserver2 172.25.250.20:80 check inter 2 fall 2 rise 5 [root@haproxy ~]# systemctl restart haproxy.service
然后在Windows中做本地解析
C:\Windows\System32\drivers\etc
测试
测试 [root@localhost ~]# curl 172.25.250.100 server2 - 172.25.250.20 [root@localhost ~]# curl www.timinglee.org server1 - 172.25.250.10
基于域名
基于IP/网段
基于浏览器
基于后缀
5.5自定义错误页面
现在我们把server1和server2停用,然后客户主机去访问haproxy主机,就会出现503错误
[root@haproxy ~]# rpm -ql haproxyoxy | grep http
mkdir /etc/haproxy/errorpage -p vim /etc/haproxy/errorpage/503.http #####添加以下自定义内容 HTTP/1.0 503 Service Unavailable Cache-Control: no-cache Connection: close Content-Type: text/html;charset=UTF-8 <html><body><h1>什么动物生气最安静</h1> 大猩猩!! </body></html> vim /etc/haproxy/haproxy.cfg systemctl restart haproxy.service
测试
5.6haproxy四层负载
针对除http以外的tcp协议应用服务访问的应用场景
haproxy主机、server1、server2主机都安装mariadb数据库 [root@webserver1 ~]# yum install mariadb-server -y [root@webserver2 ~]# yum install mariadb-server -y [root@haproxy ~]# yum install mariadb-server -y
#####server1、server2主机 #####为了区分效果,我们把server1、server2主机的server_id分别改为1和2 [root@webserver1 ~]# vim /etc/my.cnf.d/mariadb-server.cnf [root@webserver1 ~]# systemctl start mariadb [root@webserver2 ~]# vim /etc/my.cnf.d/mariadb-server.cnf [root@webserver2 ~]# systemctl start mariadb
server1主机
server2主机
然后直接输入mysql进去数据库
然后为了让haproxy主机远程登录server1、server2主机的数据库,我们需要再server1、server2主机上做以下操作
server1主机和server2主机都要创建用户,都是一样的操作
server1主机和server2主机已经创建好用户,用户lee,密码lee
然后我们用haproxy主机做负载
以上情况之所以出现这样情况,是使用了轮询这个参数
5.7haproxy
前提是需要打开web服务
我的是server1主机是APache,server2是nginx
####建立一个目录,用来放密钥 [root@haproxy ~]# mkdir -p /etc/haproxy/certs [root@haproxy ~]# openssl req -newkey rsa:2048 -nodes -sha256 -keyout /etc/haproxy/certs/timinglee.org.key -x509 -days 365 -out /etc/haproxy/certs/timinglee.org.crt Country Name (2 letter code) [XX]:CN State or Province Name (full name) []:shanxi Locality Name (eg, city) [Default City]:xian Organization Name (eg, company) [Default Company Ltd]:timinglee Organizational Unit Name (eg, section) []:webserver Common Name (eg, your name or your server's hostname) []:www.timinglee.org Email Address []:admin@timinglee.org [root@haproxy ~]# ls /etc/haproxy/certs/ timinglee.org.crt timinglee.org.key [root@haproxy ~]# cat /etc/haproxy/certs/timinglee.org.key /etc/haproxy/certs/timinglee.org.crt > /etc/haproxy/certs/timinglee.org.pem[root@haproxy ~]# cat /etc/haproxy/certs/timinglee.org.pem
然后我们打开haproxy配置文件
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg listen web-https bind *:443 ssl crt /etc/haproxy/certs/timinglee.org.pem mode http balance roundrobin server webserver1 172.25.250.10:80 check inter 2 fall 2 rise 5 server webserver2 172.25.250.20:80 check inter 2 fall 2 rise 5 [root@haproxy ~]# systemctl restart haproxy.service [root@haproxy ~]# netstat -antlupe | grep haproxy
测试
全站加密
然后我们就不用手动加密了,它直接跳转到https
就比说输入
172.25.250.100
它自动加密为https://172.25.250.100