haproxy原理及实验演示(实现服务器集群的负载均衡)
Haproxy的七层代理
LVS是最前端的调度器,Haproxy是偏后端的调度器
一、负载均衡
1.1、什么是负载均衡
负载均衡:Load Balance,简称LB
是一种服务或基于硬件设备等实现的高可用反向代理技术,负载均衡将特定的业务(web服务、网络流量等)分担给指定的一个或多个后端特定的服务器或设备,从而提高了公司业务的并发处理能力、保证了业务的高可用性、方便了业务后期的水平动态扩展
基础结构图:
1.2、为什么用负载均衡
Web服务器的动态水平扩展使得用户无感知
增加业务并发访问及处理能力-->解决单服务器瓶颈问题
节约公网IP地址-->降低IT支出成本
隐藏内部服务器IP-->提高内部服务器安全性
配置简单-->固定格式的配置文件
功能丰富-->支持四层和七层,支持动态下线主机
性能较强-->并发数万甚至数十万
1.3、负载均衡类型
1.3.1硬件:
F5------美国F5网络公司
Netscaler------美国思杰公司
Array------华耀
AD-1000------深信服
1.3.2、四层负载均衡
四层负载,调度器和服务器之间会有真实网络连接
通过ip地址和port端口决定负载均衡的去向
对流量请求进行NAT处理,转发至后台服务器
记录tcp、udp流量分别是由哪台服务器处理,后续该请求连接的流量都通过该服务器处理
支持四层的软件
lvs:重量级四层负载均衡器
Nginx:轻量级四层负载均衡器,可缓存(nginx四层是通过upstream模块)
Haproxy:模拟四层转发
1.3.3、七层负载均衡
通过虚拟url或主机ip进行流量识别,根据应用层信息进行解析,决定是否需要进行负载均衡
代理后台服务器与客户端建立连接,如nginx可代理前后端,与前端客户端tcp连接,与后端服务器建立tcp连接
支持7层代理的软件:
Nginx:基于http协议(nginx七层是通过proxy_pass
Haproxy:七层代理,会话保持、标记、路径转移等。
1.3.4 四层和七层的区别
四到七层负载均衡,就是在对后台的服务器进行负载均衡时,依据四层的信息或七层的信息,通过调度算法,来决定怎么样转发流量
四层的负载均衡,就是通过发布三层的IP地址(VIP),然后加四层的端口号,来决定哪些流量需要做负载均衡,对需要处理的流量进行NAT处理,转发至后台服务器,并记录下这个TCP或者UDP的流量是由哪台服务器处理的,后续这个连接的所有流量都同样转发到同一台服务器处理
七层的负载均衡,就是在四层的基础上(没有四层是绝对不可能有七层的),再考虑应用层的特征,比如同一个Web服务器的负载均衡,除了根据VIP加80端口辨别是否需要处理的流量,还可根据七层的URL、浏览器类别、语言来决定是否要进行负载均衡。
分层位置:四层负载均衡在传输层及以下,七层负载均衡在应用层及以下
性能:四层负载均衡架构无需解析报文消息内容,在网络吞吐量与处理能力上较高;七层可支持解析应用层报文消息内容,识别URL、Cookie、HTTP header等信息
原理:四层负载均衡是基于ip+port;七层是基于虚拟的URL或主机IP等
功能类比:四层负载均衡类似于路由器;七层类似于代理服务器
安全性:四层负载均衡无法识别DDoS攻击;七层可防御SYN Cookie/Flood攻击
二、haproxy的安装和服务信息
haproxy软件安装
安装软件包:
haproxy ~]# dnf install haproxy -y
查看版本
[root@haproxy ~]# haproxy -v
HAProxy version 2.4.22-f8e3218 2023/02/14 - https://haproxy.org/
Status: long-term supported branch - will stop receiving fixes around Q2 2026.
Known bugs: http://www.haproxy.org/bugs/bugs-2.4.22.html
Running on: Linux 5.14.0-427.13.1.el9_4.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Apr 10
10:29:16 EDT 2024 x86_64
haproxy软件基本信息
软件安装包: haproxy-2.4.22-3.el9_3.x86_64.rpm 启动文件: /lib/systemd/system/haproxy.service 主配置目录: /etc/haproxy/ 主配置文件: /etc/haproxy/haproxy.cfg 子配置目录: /etc/haproxy/conf.d
主配置文件检查
haproxy -c -f /etc/haproxy/haproxy.cfg
haproxy的基本配置信息
HAProxy 的配置文件haproxy.cfg由两大部分组成,分别是:
全局配置段---global | 代理配置段---proxies |
---|---|
多线程和多进程 | defaults段:为frontend、backend、listen提供默认配置 |
进程及安全配置 | frontend段:前端配置 |
性能调整 | backend段:后端配置 |
Debug参数 | listen段:前端 + 后端配置,推荐使用 |
1.global配置-----全局配置段
进程及安全配置相关的参数
性能调整相关参数
Debug参数
global配置参数说明
globallog 127.0.0.1 local2 #定义全局的syslog服务器;日志服务器需要开启UDP协议,最多可以定义两个chroot /var/lib/haproxy #锁定运行目录pidfile /var/run/haproxy.pid #指定pid文件maxconn 100000 #指定最大连接数user haproxy #指定haproxy的运行用户group haproxy #指定haproxy的运行组daemon #指定haproxy以守护进程方式运行#turn on stats unix socketstats socket /var/lib/haproxy/stats #指定haproxy的套接字文件nbproc 2 #指定haproxy的work进程数量,默认是1个cpu-map 1 0 #指定第一个work绑定第一个cpu核心cpu-map 2 1 #指定第二个work绑定第二个cpu核心 nbthread 2 #指定haproxy的线程数量,默认每个进程一个线程,参数会与nbproc互斥maxsslconn 100000 #每个haproxy进程ssl最大连接数,用于haproxy配置了证书的场景下maxconnrate 100 #指定每个客户端每秒建立连接的最大数量
多进程和多线程
1.多进程和socket文件配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
globallog 127.0.0.1 local2
chroot /var/lib/haproxypidfile /var/run/haproxy.pidmaxconn 100000user haproxygroup haproxydaemon#turn on stats unix socketstats socket /var/lib/haproxy/haproxy.sock1 mode 600 level admin process 1 #启用多个sock文件stats socket /var/lib/haproxy/haproxy.sock2 mode 600 level admin process 2 #启用多进程,指定数量为2nbproc 2cpu-map 1 0 #进程和cpu核心绑定防止cpu抖动从而减少系统资源消耗cpu-map 2 1 #2 表示第二个进程,1表示第二个cpu核心
...下面内容省略 ...
查看多进程信息
[root@haproxy ~]# systemctl restart haproxy.service [root@haproxy ~]# pstree -p | grep haproxy #haproxy子进程id|-haproxy(2890)-+-haproxy(2892)| `-haproxy(2893)
2.启用多线程
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
globallog 127.0.0.1 local2
chroot /var/lib/haproxypidfile /var/run/haproxy.pidmaxconn 100000user haproxygroup haproxydaemon#turn on stats unix socketstats socket /var/lib/haproxy/haproxy.sock1 mode 600 level admin process 1 #启用多个sock文件stats socket /var/lib/haproxy/haproxy.sock2 mode 600 level admin process 2 #启用多进程,指定数量为2nbproc 2cpu-map 1 0 #进程和cpu核心绑定防止cpu抖动从而减少系统资源消耗cpu-map 2 1 #2 表示第二个进程,1表示第二个cpu核心
...下面内容省略 ...
多线程对比
未开启多线程 haproxy ~]# cat /proc/2892(haproxy子进程id)/status ...上面内容省略... Threads: 1 ...下面内容省略...开启多线程后 haproxy ~]# cat /proc/2892(haproxy子进程id)/status ...上面内容省略... Threads: 2 ...下面内容省略...
2.proxies配置------代理配置段
defaults:为frontend, backend, listen提供默认配置
frontend:前端,相当于nginx中的server {}
backend:后端,相当于nginx中的upstream {}
listen:同时拥有前端和后端配置,配置简单,生产推荐使用
参数 | 类型 | 作用 |
---|---|---|
defaults | proxies | 默认配置项,针对以下的frontend、backend和listen生效,可以多个name也可以没有name |
frontend | proxies | 前端servername,类似于Nginx的一个虚拟主机 server或者LVS服务集群 |
backend | proxies | 后端服务器组,类似于LVS中的RS服务器 |
listen | proxies | 将frontend和backend合并在一起配置 |
name字段只能使用大小写字母,数字,短杠“-”,下划线“ _ ”,点“ . ”和冒号“ : ”,并且严格区分大小写
defaults的配置分析
defaults 47 mode http #HAProxy实例使用的连接协议 48 log global #指定日志地址和记录日志条目的syslog/rsyslog日志设备#此处的 global表示使用 global配置段中设定的log值。 49 option httplog #日志记录选项,httplog表示记录与 HTTP会话相关的各种属性值#包括 HTTP请求、会话状态、连接数、源地址以及连接时间等 50 option dontlognull #dontlognull表示不记录空会话连接日志 51 option http-server-close #等待客户端完整HTTP请求的时间,此处为等 待10s 52 option forwardfor except 127.0.0.0/8 #透传客户端真实IP至后端web服务器#在apache配置文件中加入:<br>%{X-Forwarded-For}i#后在webserver中看日志即可看到地址透传信息 53 option redispatch #当server Id对应的服务器挂掉后,强制定向到其他健康的服务器,重新派发 54 option http-keep-alive #开启与客户端的会话保持 55 retries 3 #连接后端服务器失败次数 56 timeout http-request 10s #等待客户端请求完全被接收和处理的最长时 间 57 timeout queue 1m #设置删除连接和客户端收到503或服务不可 用等提示信息前的等待时间 58 timeout connect 120s #设置等待服务器连接成功的时间 59 timeout client 600s #设置允许客户端处于非活动状态,即既不发送数据也不接收数据的时间 60 timeout server 600s #设置服务器超时时间,即允许服务器处于既不接收也不发送数据的非活动时间 61 timeout http-keep-alive 60s #session 会话保持超时时间,此时间段内会转发到相同的后端服务器 62 timeout check 10s #指定后端服务器健康检查的超时时间 63 maxconn 3000 64 default-server inter 1000 weight 3
frontend 配置分析
参数: bind:指定HAProxy的监听地址,可以是IPV4或IPV6,可以同时监听多个IP或端口,可同时用于listen字段中 67 # frontend Webcluster 68 # bind *:80 69 # mode http 70 # use_backend Webculuster-host 调用backend的名称 #格式 bind <address>:<port_range> # 如果需要绑定在非本机的IP,需要开启内核参数:net.ipv4.ip_nonlocal_bind=1 backlog <backlog> #针对所有server配置,当前端服务器的连接数达到上限后的后援队列长度,注意:不支持backend
backend 配置分析
定义一组后端服务器
backend 的名称必须唯一,并且必须在listen或frontend中事先定义才可以使用,否则服务无法启动
mode http|tcp # 指定负载协议类型,必须和对应的frontend保持一致
option # 配置选项
server # 定义后端real server,必须指定IP和端口
Server 配置
参数 | 说明 |
---|---|
check | 对指定RS进行健康状态检查,如果不加此参数,默认不开启检查 默认对相应的 RS 的IP和端口,利用TCP连接进行周期性健康性检查,注意必须指定端口才能实现健康性检查 |
addr <IP> | 可指定的健康状态监测IP,可以是专门的数据网段 |
port <num> | 指定的健康状态监测端口 |
inter <num> | 健康状态检查间隔时间,默认2000 ms |
fall <num> | 后端服务器从线上转为线下的检查的连续失效次数,默认为3 |
rise <num> | 后端服务器从下线恢复上线的检查的连续有效次数,默认为2 |
weight <weight> | 权重值默认为1,最大值为256,0 表示不参与负载均衡,但仍接受持久连接 |
backup | 将后端服务器标记为备份状态,只在所有非备份主机Down机时提供服务 |
disabled | 将后端服务器标记为不可用状态,即维护状态,除了持久模式 将不再接受连接,状态为深黄色,不再接受新用户的请求 |
redirect prefix | 将请求临时重定向至其它URL,只适用于http模式 |
maxconn | 当前 RS 的最大并发连接数 |
代码示例:
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
backend lee-webserver-80-RSmode httpserver web1 192.168.0.101:80 check inter 3s fall 3 rise 5server web2 192.168.0.102:80 check inter 3s fall 3 rise 5
...上面内容省略...
listen 配置分析
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
linsten Webclusterbind *:80mode httpbalance static-rr
server web1 192.168.127.10:80 check inter 5s fall 3 weight 2server web1 192.168.127.20:80 check inter 5s fall 3 weight 1
#测试结果
[root@kehu ~]# for n in {1..10} #持续访问
#扩展:当无法服务器访问的时候,可以加个提示
server sorry 192.168.127.100:8080 backup
listen简化配置
使用listen替换 frontend和backend的配置方式,简化设置,通常只用于TCP协议的应用
listen配置示例:
haproxy ~]# vim /etc/haproxy/haproxy.cfg ...上面内容省略... listen webserver_80bind 172.25.254.100:80mode httpoption forwardforserver webserver1 192.168.127.10:80 check inter 3s fall 3 rise 5server webserver2 192.168.127.20:80 check inter 3s fall 3 rise 5 ...上面内容省略...
Socat工具
调整服务器动态权重和其它状态可以利用 socat工具
Socat 是 Linux 下的一个多功能的网络工具,名字来由是Socket CAT,相当于netCAT的增强版
Socat 的主要特点就是:在两个数据流之间建立双向通道,且支持众多协议和链接方式。如 IP、TCP、 UDP、IPv6、Socket文件等
[root@haproxy ~]# dnf install socat -y
# 首先修改 Haproxy 的配置文件,才能正常使用
vim /etc/haproxy/haproxy.cfg35 # turn on stats unix socket36 stats socket /var/lib/haproxy/stats # 默认情况下只能进行查看,不能进行更改--> stats socket /var/lib/haproxy/stats mode 600 level admin
# 安装Socat
dnf install socat -y
# 查看帮助
echo "help" | socat stdio /var/lib/haproxy/stats
......
enable server : enable a disabled server (use 'set server' instead) # 启用服务器
set maxconn server : change a server's maxconn setting
set server : change a server's state, weight or address # 设置服务器
get weight : report a server's current weight # 查看权重
set weight : change a server's weight (deprecated) # 设置权重
......
# 查看haproxy 状态
echo "show info" | socat stdio /var/lib/haproxy/stats
# 查看集群状态
echo "show servers state" | socat stdio /var/lib/haproxy/stats
# 查看集群权重
echo get weight webcluster/web1 | socat stdio
echo get weight webcluster/web2 | socat stdio
# 设置权重
echo "set weight webcluster/web1" | socat stdio
# 下线后端服务器
echo "disable server webcluster/web1" | socat stdio
# 上线后端服务器
echo "enable server webcluster/web1" | socat stdio
针对多进程处理方法
如果开启多进程那么我们在对进程的sock文件进行操作时其对进程的操作时随机的
如果需要指定操作进程那么需要用多soct文件方式来完成
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
stats socket /var/lib/haproxy/stats1 mode 600 level admin process 1
stats socket /var/lib/haproxy/stats2 mode 600 level admin process 2
nbproc 2
cpu-map 1 0
cpu-map 2 1
...上面内容省略...
这样每个进程就会有单独的sock文件来进行单独管理
[root@haproxy ~]# ll /var/lib/haproxy/
总用量 0
srw------- 1 root root 0 8月 8 13:43 stats
srw------- 1 root root 0 8月 8 13:46 stats1
srw------- 1 root root 0 8月 8 13:46 stats2
三、Haproxy的算法
是通过固定的参数balance,指明对后端服务器的调度算法中
参数balance一般是配置再listen或backend中的
Haproxy的调度算法是分为静态调度算法和动态调度算法
添加参数,可以使用frontend和backend或者两个要一起用
listen Webclusterbind *:80mode httpbalance roundrobinserver web1 192.168.147.10:80server web2 192.168.147.20:80
############################################
frontend Webclusterbind *:80mode httpdefault_backend web_backend
backend web_backendmode httpserver web1 192.168.147.10:80server web2 192.168.147.20:80
算法使用场景
算法 | 使用场景 |
---|---|
first | 使用较少 |
static-rr roundrobin random | 做 session 共享的 web 集群 |
leastconn | 数据库 |
source | 基于客户端公网 IP 的会话保持 |
基于客户端的公网IP会话保持 | |
uri | 缓存服务器,CDN 服务商,蓝汛、百度、阿里云、腾讯 |
url_param | 可以实现 session 保持 |
hdr | 基于客户端请求报文头部做下一步处理 |
rdp-cookie | 基于 Windows 主机,很少使用 |
一、静态调度算法
根据调度算法规则进行调度,不考虑后端服务器的负载情况
无法实时的进行修改权重,只能重启Haproxy才能生效
无限制后端的real server
1、static-rr:基于权重的轮询调度
不支持运行时利用socat进行热更新权重
不支持服务器慢启动
后端服务器数量没有限制
注意:慢启动
当服务器刚开始启动之后,调度不会把该服务器应该承担的压力分配给它,会一部分一部分进行分配处理
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
#----------------------
#custom web cluster
#----------------------
frontend Webclusterbind *:80mode httpdefault_backend web_backend
backend web_backendbalance static-rrserver server1 192.168.147.10:80 check inter 5s fall 3 weight 2server server2 192.168.147.20:80 check inter 5s fall 3 weight 1
#------------------------
# main frontend which proxys to the backends
#------------------------
...上面内容省略...
#权重查看
[root@Haproxy ~]# echo "get weight web_backend/server1" | socat stdio /var/lib/haproxy/stats
2 (initial 2)
无法修改权重
2、first---优先度调度
根据服务器在列表中的位置,从第一服务器开始进行调度
当第一台服务器的连接数达到上限,新请求才会分配给下一台服务器
#-------------------------------------------
#custom web cluster
#-------------------------------------------
frontend Webclusterbind *:80mode httpdefault_backend web_backend
backend web_backendbalance firstserver server1 192.168.147.10:80 maxconn 3 check inter 5s fall 3 rise 5server server2 192.168.147.20:80 check inter 5s fall 3 rise 5
#-------------------------------------------
# main frontend which proxys to the backends
#-------------------------------------------
#测试
[root@Haproxy ~]# for i in {1..10}; do curl 192.168.147.66;done
全部的流量都会打到第一台服务器上
#在两台主机上分别执行此循环,可以观察是否102被调度到
while true;do curl 172.25.254.100 ; sleep 0.1;done
二、动态调度算法
基于后端真实服务器的负载状态调度调整新的请求
权重调度可以直接运行在Haproxy,无需重启
1、roundrobin---基于权重的轮询动态调度算法
可以在权重运行时进行,动态的权重调度
支持轮询调度的慢启动
每个后端backend中最多支持4095个real server,并可以动态调整
这是HAProxy的默认调度算法,适用于大多数需要高可用性和负载均衡的场景
frontend Webclusterbind *:80mode httpdefault_backend web_backend
backend web_backendbalance roundrobinserver server1 192.168.147.10:80 weight 1 check inter 5s fall 3 rise 5server server2 192.168.147.20:80 weight 1 check inter 5s fall 3 rise 5
#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
进行动态调整权重
echo "set weight web_backend/webserver1 2" | socat stdio /var/lib/haproxy/haproxy.sock
2、leastconn---加权的最少连接的动态算法
根据当前连接最少的后端服务器而非权重进行优先调度(新客户端连接)
比较适合长连接的场景使用
frontend Webclusterbind *:80mode httpdefault_backend web_backend
backend web_backendbalance leastconnserver server1 192.168.147.10:80 weight 1 check inter 5s fall 3 rise 5server server2 192.168.147.20:80 weight 1 check inter 5s fall 3 rise 5
#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
三、其他算法
以下的调度算法可以作为静态算法,又可以通过选项成为动态算法
1、source---源地址哈希算法
进行源地址的哈希,基于用户的源地址,将数据请求转发到后端的服务器,在后续的同一源地址请求都会被转发到同一个后端的web服务器
当后端服务器进行改变的时候,就会导致很多用户的请求重新进行转发
默认是为静态模式,可以通过hash-type支持的选项更改这个算法一般是在不插入Cookie的TCP模式下使用,也可给拒绝会话cookie的客户提供最好的会话粘性,适用于session会话保持但不支持cookie和缓存的场景
源地址哈希有两种转发客户端请求到后端服务器的服务器选取计算方式:取模法和一致性hash
listen webserver_80bind 192.168.147.66:80mode httpbalance sourceserver webserver1 192.168.147.10:80 weight 1 check inter 3s fall 3 rise 5server webserver2 192.168.147.20:80 weight 1 check inter 3s fall 3 rise 5
#测试
for N in {1..6}; do curl 192.168.147.66; done
注意:如果一个源地址有多个流量进行访问请求,都会被定向到同一台服务器上,造成高负载
1.1.map-base取模法
原理:后端有多台服务器,服务器编号为0、1、2;该权重为3,用源地址IP除以权重数3进行取模,根据取模的结果转发请求到对应的服务器
缺点:当服务器的总权重发生变化时,即有服务器上线或下线,都会因总权重发生变化而导致调度结果整体改变
1.2.一致性hash
一致性哈希,当服务器的总权重发生变化时,对调度结果影响是局部的,不会引起大的变动
该算法是动态的,支持使用 socat等工具进行在线权重调整,支持慢启动
一致性哈希,给服务器和数据都编了号,按照逆时针方向,进行分配后端的服务器,按规则在一个「环形地址簿」上找对应关系,节点变动时只影响附近的少量数据,非常适合分布式系统
在配置文件中添加---hash-type consistent
listen webserver_80bind 192.168.147.66:80mode httpbalance sourcehash-type consistent #添加server webserver1 192.168.147.10:80 weight 1 check inter 3s fall 3 rise 5server webserver2 192.168.147.20:80 weight 1 check inter 3s fall 3 rise 5
2、uri
访问不同页面,可能访问的后端服务器也不一样
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag> 左半部分---/<path>;<params>加前面的内容 整个uri---/<path>;<params>?<query>#<frag> <host>---访问的网址 <port>---访问的端口 <params>---访问的命令,比如搜索 <query>---条件,比如搜索什么东西 <frag>---页面中里的片段
uri一致性hash配置示例
vim /etc/haproxy/haproxy.cfg
...上面内容省略...
listen webserver_80bind 172.25.254.100:80mode httpbalance urihash-type consistentserver webserver1 192.168.147.10:80 weight 1 check inter 3s fall 3 rise 5server webserver2 192.168.147.20:80 weight 1 check inter 3s fall 3 rise 5
...上面内容省略...
访问不同的uri,确认可以将用户同样的请求转发至相同的服务器
url_param
url_param对用户请求的url中的 params 部分中的一个参数key对应的value值作hash计算,并由服务器总权重相除以后派发至某挑出的服务器,后端搜索同一个数据会被调度到同一个服务器,多用与电商
通常用于追踪用户,以确保来自同一个用户的请求始终发往同一个real server
如果无没key,将按roundrobin算法
url_param取模法配置
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
listen webserver_80bind 192.168.147.66:80mode httpbalance url_param name,userid #支持对多个url_param hashserver webserver1 192.168.147.10:80 weight 1 check inter 3s fall 3 rise 5server webserver2 192.168.147.20:80 weight 1 check inter 3s fall 3 rise 5
...上面内容省略...
3、hdr
针对用户每个http头部(header)请求中的指定信息做hash由 name 指定的http首部将会被取出并做hash计算,然后由服务器总权重取模以后派发至某挑出的服务器,如果无有效值,则会使用默认的轮询调度。
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
listen webserver_80bind 192.168.147.66:80mode httpbalance hdr(User-Agent)hash-type consistentserver webserver1 192.168.147.10:80 weight 1 check inter 3s fall 3 rise 5server webserver2 192.168.147.20:80 weight 1 check inter 3s fall 3 rise 5
...上面内容省略...
#测试
[root@node10 ~]# curl -v 192.168.147.66
[root@node10 ~]# curl -vA "firefox" 192.168.147.66
[root@node10 ~]# curl -vA "sougou" 192.168.147.66
四、高级功能及配置
基于cookie的会话保持
通过 “客户端标识 + 服务器状态” 的配合解决了 HTTP 无状态的问题
为当前server指定cookie值,实现基于cookie的会话黏性
name | cookie 的 key名称,用于实现持久连接 |
---|---|
insert | 插入新的cookie,默认不插入cookie |
indirect | 如果客户端已经有cookie,则不会再发送cookie信息 |
nocache | 当client和hapoxy之间有缓存服务器(如:CDN)时,不允许中间缓存器缓存cookie,因为这会导致很多经过同一个CDN的请求都发送到同一台后端服务器 |
配置示例
[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg listen webserver_80bind 192.168.147.66:80option forwardformode httpbalance roundrobincookie WEBCOOKIE insert nocache indirectserver webserver1 192.168.147.10:80 cookie web1 weight 1 check inter 3s fall 3 rise 5server webserver2 192.168.147.20:80 cookie web2 weight 1 check inter 3s fall 3 rise 5[root@Haproxy ~]# systemctl restart haproxy.service
测试结果
haproxy的状态界面
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
listen statsmode httpbind 0.0.0.0:8888stats enablelog globalstats uri /haproxy-statusstats auth zym:zym
...下面内容省略...
#查看页面输入以下VIP地址
192.168.147.100:8888/status
IP透传
web服务器中需要记录客户端的真实IP地址,用于做访问统计、安全防护、行为分析、区域排行等场景。
四层IP透传
开启四层透传
#nginx 配置:在访问日志中通过变量$proxy_protocol_addr 记录透传过来的客户端IP
#修改真实服务器
[root@rs1 ~]# vim /etc/nginx/nginx.conf
...内容省略...
http {log_format main '$remote_addr - $remote_user [$time_local] "$request"'' "$proxy_protocol_addr"' #需添加此条'$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';
...内容省略...
server {listen 80 proxy_protocol; #启用此项,使得Nginx无法通过七层直接访问网站,只能通过四层代理访问listen [::]:80;server_name _;root /usr/share/nginx/html;
。。。内容省略。。。
}
#修改haproxy
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
listen webserver_80bind 192.168.147.100:80mode tcp #改成四层传输协议balance roundrobinserver webserver1 192.168.0.10:80 send-proxy weight 1 check inter 3s fall rise 5
...上面内容省略...
#查看日志内容
[root@rs1 ~]# tail -n 3 /var/log/nginx/access.log
七层透传
当haproxy工作在七层的时候,就可以透传客户端真实IP至后端真实服务器
#修改haproxy
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
listen webserver_80option forwardforbind 172.25.254.100:80mode httpbalance roundrobinserver webserver1 192.168.147.10:80 send-proxy weight 1 check inter 3s fall 3 rise 5server webserver1 192.168.147.20:80 send-proxy weight 1
check inter 3s fall 3 rise 5
...上面内容省略...
ALC
访问控制列表ACL(Access Control Lists)是一种基于包过滤的访问控制技术
对经过服务器传输的数据包接收到的报文进行匹配和过滤
基于请求报文头部中的源地址、源端口、目标地址、目标端口、请求方法、URL、文件后缀等信息内容进行匹配并执行进一步操作,比如允许其通过或丢弃
如果是基于ACL的访问过滤的话,需要frontend以及backend的格式
1、ACL配置选项
#用acl来定义或声明一个acl acl <aclname> <criterion> [flags] [operator] [<value>] acl 名称 匹配规范 匹配模式 具体操作符 操作对象类型
ACL-Name 名称 acl test path_end -m sub /a #ACL名称,可以使用大字母A-Z、小写字母a-z、数字0-9、冒号:、点.、中横线和下划线,并且严格区分大小写 #比如:my_acl和My_Acl就是两个完全不同的acl5.8.1.2 ACL-criterion
2、多个ACL的组合调用
多个ACL的逻辑处理
与:隐式(默认)使用 或:使用“or" 或 “||"表示 否定:使用 "!" 表示
多个ACL调用方式
#示例: if valid_src valid_port #与关系,ACL中A和B都要满足为true,默认为与 if invalid_src || invalid_port #或,ACL中A或者B满足一个为true if ! invalid_src #非,取反,不满足ACL才为true
3、ACL示例-域名匹配
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
frontend testaclbind :80mode http########### ACL settings #######################acl web_host hdr_dom(host) www.zym.org########### host ###########################use_backend zym_host if web_host########### default server ###################default_backend default_webserver
backend zym_hostmode httpserver web1 192.168.0.101:80 check weight 1 inter 3s fall 3 rise 5server web2 192.168.0.102:80 check weight 1 inter 3s fall 3 rise 5
backend default_webservermode httpserver web1 172.25.254.10:80 check weight 1 inter 3s fall 3 rise 5
...上面内容省略...
测试
#在浏览器所在主机中做地址解析
[root@node10 html]# vim /etc/hosts
172.25.254.100 www.zym.org
#测试结果
[root@node10 html]# curl www.zym.org
RS1 192.168.0.101
[root@node10 html]# curl www.zym.org
RS2 server - 192.168.0.102
[root@node10 html]# curl 172.25.254.100
default web server node10
4、ACL示例-基于源IP或子网调度访问
将指定的源地址调度至指定的web服务器组
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
frontend testaclbind :80mode http########### ACL settings #######################acl ip_test src 172.25.254.1 192.168.0.0/24########### host ###########################use_backend ip_test-host if ip_test########### default server ###################default_backend default_webserver
backend ip_test-hostmode httpserver web1 192.168.0.101:80 check weight 1 inter 3s fall 3 rise 5
backend default_webservermode httpserver web1 172.25.254.10:80 check weight 1 inter 3s fall 3 rise 5
测试
[172.25.254.10 root@node10 html]# curl 172.25.254.100
default web server node10
[172.25.254.1 Administrator.WIN-20240602BIS] ➤ curl 172.25.254.100
RS1 192.168.0.101
[192.168.0.102 root@rs1 ~]# curl 192.168.0.101
RS1 192.168.0.101
5、ACL示例-基于源地址的访问控制
拒绝指定IP或者IP范围访问haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
frontend testaclbind :80mode http########### ACL settings #######################acl web_host hdr_dom(host) www.zym.orgacl ip_test src 172.25.254.1 192.168.0.0/24########### host ###########################http-request deny if web_host########### default server ###################default_backend default_webserver
backend ip_test-hostmode httpserver web1 192.168.0.101:80 check weight 1 inter 3s fall 3 rise 5backend default_webservermode httpserver web1 172.25.254.10:80 check weight 1 inter 3s fall 3 rise 5
测试
[root@node10 ~]# curl www.zym.org
<html><body><h1>403 Forbidden</h1>
Request forbidden by administrative rules.
</body></html>
[root@node10 ~]# curl 172.25.254.100
default web server node10
6、ACL示例-匹配浏览器类型
匹配客户端浏览器,将不同类型的浏览器调动至不同的服务器组
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
frontend testaclbind :80mode http########### ACL settings #######################acl user_agent_block hdr_sub(User-Agent) -i curl wgetacl user_agent_redirect hdr_sub(User-Agent) -i Mozilla/5.0
########### host ###########################http-request deny if user_agent_blockredirect prefix https://www.baidu.com if user_agent_redirect########### default server ###################default_backend default_webserver
backend ip_test-hostmode httpserver web1 192.168.0.101:80 check weight 1 inter 3s fall 3 rise 5
backend default_webservermode httpserver web1 172.25.254.10:80 check weight 1 inter 3s fall 3 rise 5
测试
[root@node10 ~]# curl 172.25.254.100
[root@node10 ~]# wget http://172.25.254.100/index.html
7、ACL示例-基于文件后缀名实现动静分离
########### ACL settings ####################### acl url_static path_end -i .jpg .png .css .js .html acl url_php path_end -i .php ########### host ########################### use_backend static_host if url_static use_backend php_host if url_php ########### default server ################### default_backend default_webserver
8、ACL-匹配访问路径实现动静分离
########### ACL settings ####################### acl url_static path_end -i .jpg .png .css .js .html acl url_static path_end -m sub /static /images /javascript acl acl_app path_beg -m sub /api ########### host ########################### use_backend static_host if url_static use_backend api_host if acl_app ########### default server ################### default_backend default_webserver
基于http重定向错误页面
#错误页面重定向
errorloc <code> <url>
#相当于errorloc302 <code> <url>,利用302重定向至指URL
#示例:
errorloc 503 https://www.baidu.com
Haproxy四层负载
针对除HTTP以外的TCP协议应用服务访问的应用场景
MySQL
Redis
Memcache
RabbitMQ
四层负载示例
注意:如果使用frontend和backend,一定在 frontend 和 backend 段中都指定mode tcp范例:对 MySQL 服务实现四层负载
listen mysql-portbind 10.0.0.7:6379mode tcpbalance leastconnserver server1 10.0.0.17:3306 checkserver server2 10.0.0.27:3306 check backup
举例:对 MySQL 服务实现四层负载
#配置Haproxy
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
listen mysql_port
bind :3306
mode tcp
balance leastconn
server mysql1 192.168.147.10:3306 check
server mysql2 192.168.147.20:3306 check
#或者使用frontend和backend实现#
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
frontend mysql_portbind :3306mode tcpuse_backend mysql_rs
backend mysql_rsmode tcpbalance leastconnserver mysql1 192.168.0.101:3306 checkserver mysql2 192.168.0.102:3306 check
haproxy ~]# systemctl restart haproxy.service
在后端服务器安装和配置mariadb服务
rs1 ~]# yum install mariadb-server -y
rs2 ~]# yum install mariadb-server -y
rs1 ~]# vim /etc/my.cnf
[mysqld]
server-id=1 #在一台主机为
rs2 ~]# vim /etc/my.cnf
[mysqld]
server-id=2 #在另一台主机为
rs1 ~]# systemctl start mariadb
rs2 ~]# systemctl start mariadb
rs1 ~]# mysql -e "grant all on *.* to zym@'%' identified by 'zym';"
rs2 ~]# mysql -e "grant all on *.* to zym@'%' identified by 'zym';"
测试效果
[root@kehu ~]# mysql -ulee -plee -h 192.168.147.100 -e "show variables like 'hostname'"
+---------------+-------------+
| Variable_name | Value |
+---------------+-------------+
| hostname | RS1.zym.org |
+---------------+-------------+
[root@kehu ~]# mysql -ulee -plee -h 192.168.147.100 -e "show variables like 'hostname'"
+---------------+-------------+
| Variable_name | Value |
+---------------+-------------+
| hostname | RS2.zym.org |
+---------------+-------------+
[root@kehu ~]# mysql -ulee -plee -h192.168.147.100 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
| 1 |
+-------------+
[root@kehu ~]# mysql -ulee -plee -h192.168.147.100 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
| 2 |
+-------------+
HAProxy https实现
haproxy可以实现https的证书安全,从用户到haproxy为https,从haproxy到后端服务器用http通信
但基于性能考虑,生产中证书都是在后端服务器比如nginx上实现
#配置HAProxy支持https协议,支持ssl会话; bind *:443 ssl crt /PATH/TO/SOME_PEM_FILE #指令 crt 后证书文件为PEM格式,需要同时包含证书和所有私钥 cat demo.key demo.crt > demo.pem #把80端口的请求重向定443 bind *:80 redirect scheme https if !{ ssl_fc }
证书制作
haproxy ~]# mkdir /etc/haproxy/certs/
haproxy ~]# openssl req -newkey rsa:2048 \
-nodes -sha256 –keyout /etc/haproxy/certs/zym.org.key \
-x509 -days 365 -out /etc/haproxy/certs/zym.org.crt
haproxy ~]# cat zym.org.key zym.org.crt > zym.pem
https配置
haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webserverbind *:80redirect scheme https if !{ ssl_fc } #全栈加密mode httpuse_backend webcluster
frontend webserver-httpsbind *:443 ssl crt /etc/haproxy/certs/zym.pemmode httpuse_backend webcluster
backend webclustermode httpbalance roundrobinserver web1 172.25.254.200:80 check inter 3s fall 3 rise 5server web2 172.25.254.201:80 check inter 3s fall 3 rise 5