一、负载均衡与haproxy
1.1 负载均衡的简介
是一种服务或基于硬件设备等实现的高可用反向代理技术,负载均 衡将特定的业务(web 服务、网络流量等 ) 分担给指定的一个或多个后端特定的服务器或设备,从而提高了公司业务的并发处理能力、保证了业务的高可用性、方便了业务后期的水平动态扩展。
1.2 负载均衡与haproxy的关系
1.2.1 haproxy的七层代理
工作在 HTTP/HTTPS 层面,可以根据域名、URL、路径分发、读写 Cookie、Header、HTTPS 卸载(SSL Termination)、重写请求 / 响应。其 本质HAProxy 作为七层代理实现精细的七层负载均衡
1.2.2 haproxy的四层代理
工作在 TCP/UDP 层面,只看 IP:Port,不关心上层协议内容,转发更快、开销更小。同样是负载均衡,只是更 "傻"、更快。
二、haproxy的环境部署
2.1 实验环境
|------------|---------------------------------------------------------------|------|
| 主机名 | IP | 角色 |
| haproxy | eth0:192.168.198.100 模式:NAT eth1:192.168.248.100 模式:host-only | 调度器 |
| webserve1 | 192.168.248.10 模式:host-only wg:192.168.248.2 | 服务器1 |
| webserver2 | 192.168.248.20 模式:host-only wg:192.168.248.2 | 服务器2 |
| client | 192.168.198.10 模式:host-only | 客户端 |
2.1.1 haproxy的ip配置

2.1.2 电脑虚拟机仅主机无法联网的问题
因为本人使用电脑虚拟机仅主机模式模拟内网环境,使内网虚拟机无法连接外网,我这有一个解决方案,创新创建一台nat和仅主机的双网卡虚拟机,仅主机网卡IP设置为内网虚拟机网关192.168.248.2,开启路由转发功能以及添加对从联网机的eth0网卡发出的数据包 进行IP伪装,让内网设备可以通过这台服务器的公网 IP 访问互联网。在内网机需要使用网络时打开并添加策略,内网不需要使用网络时关机。
bash
[root@n-w ~]# ip add
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:2d:75:90 brd ff:ff:ff:ff:ff:ff
altname enp3s0
altname ens160
inet 192.168.198.180/24 brd 192.168.198.255 scope global noprefixroute eth0
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe2d:7590/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:2d:75:9a brd ff:ff:ff:ff:ff:ff
altname enp19s0
altname ens224
inet 192.168.248.2/24 brd 192.168.248.255 scope global noprefixroute eth1
valid_lft forever preferred_lft forever
inet6 fe80::7ca5:72e:6acc:84d5/64 scope link noprefixroute
valid_lft forever preferred_lft forever
[root@n-w ~]# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
[root@n-w ~]# sysctl -p
net.ipv4.ip_forward = 1
[root@n-w ~]# iptables -t nat -A POSTROUTING -s 192.168.248.0/24 -o eth0 -j MASQUERADE
2.1.3 weberver1的ip配置及其httpd服务的开启
bash
[root@webserver1 ~]# ip add
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:50:db:6d brd ff:ff:ff:ff:ff:ff
altname enp3s0
altname ens160
inet 192.168.248.10/24 brd 192.168.248.255 scope global noprefixroute eth0
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe50:db6d/64 scope link noprefixroute
valid_lft forever preferred_lft forever
[root@webserver1 ~]# dnf install httpd -y
[root@webserver1 ~]# echo webserver1 - 192.168.248.10 > /var/www/html/index.html
2.1.4 weberver2的ip配置及其httpd服务的开启
bash
[root@webserver2 ~]# ip add
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:f2:dc:c4 brd ff:ff:ff:ff:ff:ff
altname enp3s0
altname ens160
inet 192.168.248.20/24 brd 192.168.248.255 scope global noprefixroute eth0
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fef2:dcc4/64 scope link noprefixroute
valid_lft forever preferred_lft forever
[root@webserver2 ~]# dnf install httpd -y
[root@webserver2 ~]# echo webserver2 - 192.168.248.20 > /var/www/html/index.html
2.1.5 测试
使用haproxy分别curl192.168.248.10和192.168.248.20。

三、Haproxy的安装及配置参数
3.1 在haproxy上安装
bash
[root@haproxy ~]# dnf install haproxy.x86_64 -y
[root@haproxy ~]# systemctl enable --now haproxy.service
Created symlink /etc/systemd/system/multi-user.target.wants/haproxy.service → /usr/lib/systemd/system/haproxy.service.
3.2 实现基本的负载
3.2.1 前后端分开设定写负载均衡
bash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
[root@haproxy ~]# systemctl restart haproxy.service
75 frontend webcluster
76 bind *:80
77 mode http
78 use_backend webserver-80
79
80 backend webserver-80
81 server web1 192.168.248.10:80 check inter 3s fall 3 rise 5
82 server web2 192.168.248.20:80 check inter 3s fall 3 rise 5
3.2.2 用listen方式书写负载均衡
bash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
[root@haproxy ~]# systemctl restart haproxy.service
75 listen webcluster
76 bind *:80
77 mode http
78 server web1 192.168.248.10:80 check inter 3s fall 3 rise 5
79 server web2 192.168.248.20:80 check inter 3s fall 3 rise 5
3.2.3 使用curl命令测试
bash
[root@haproxy ~]# for i in {1..10};do curl 192.168.248.100;done
webserver1 - 192.168.248.10
webserver2 - 192.168.248.20
webserver1 - 192.168.248.10
webserver2 - 192.168.248.20
webserver1 - 192.168.248.10
webserver2 - 192.168.248.20
webserver1 - 192.168.248.10
webserver2 - 192.168.248.20
webserver1 - 192.168.248.10
webserver2 - 192.168.248.20
3.3 启用日志
3.3.1 设置日志作用
(1) 集中管理:多台服务器(比如多台 HAProxy、Web 服务器)的日志都存在一台机器上,不用挨个登录查看。
(2) 故障排查:某台机器宕机后,日志已经存在远程服务器,不会丢失,方便事后分析。
(3) 安全审计:日志集中存储,避免被攻击者在入侵后删除本机日志掩盖痕迹。
(4) 实验场景:在你的 HAProxy + 后端 Web 集群实验里,用一台机器专门存日志,更贴近企业真实运维架构。
3.3.2 指定web1开启日志
因为电脑内存有限,现使用webserver1存储集群日志,现实里存放日志的机器不会用来服务外界客服。
在webserver1上先开启接受日志的514端口并重启日志服务
bash
[root@webserver1 ~]# vim /etc/rsyslog.conf
37 module(load="imudp") # needs to be done just once
38 input(type="imudp" port="514")
[root@webserver1 ~]# systemctl restart rsyslog.service
[root@webserver1 ~]# netstat -antlupe | grep rsyslog
tcp 0 0 0.0.0.0:514 0.0.0.0:* LISTEN 0 38499 2098/rsyslogd
tcp6 0 0 :::514 :::* LISTEN 0 38500 2098/rsyslogd
补充:tcp改成udp的原因
性能与开销: UDP 是无连接协议,发送日志时不需要建立连接,开销小、速度快,适合高并发场景下大量日志的传输。TCP 需要三次握手、可靠传输,在日志量极大时会增加延迟和资源消耗。
rsyslog 默认模块: imudp 是 rsyslog 内置的、轻量的 UDP 输入模块,配置简单,开箱即用。
日志场景特点:日志传输允许少量丢包(不影响核心业务),更看重传输效率,所以 UDP 更适合。
如果生产环境如果要求日志绝对不丢,也可以用 imtcp 模块开启 TCP 514 端口。
在haproxy主机的/etc/haproxy/haproxy.conf文件中设定日志发送位置
bash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
26 log 192.168.248.10 local2
[root@haproxy ~]# systemctl restart haproxy.service
测试:在电脑主机curl haproxy调度机,再查看日志


3.4 haproxy 多进程
3.4.1 简介
**概念:**把 HAProxy 启动为多个独立的操作系统进程,每个进程都可以处理请求,相当于多个 HAProxy 实例在同时工作。
就像开了好几家独立的连锁餐厅,每家店都有自己的厨房、服务员和食材,互不干扰,一家店出问题不影响其他店,但食材和人力成本更高。
特点:
(1) 进程之间是完全隔离的,有各自独立的内存空间和文件句柄。
(2) 可以通过 cpu-map 把进程绑定到特定 CPU 核心,避免进程间 CPU 切换开销,提升性能。
(3) 适合利用多核 CPU,分散负载压力。
局限:
(1) 进程间通信成本高,状态不共享(比如会话、统计信息)。
(2) 不能和多线程模式同时启用。
3.4.2 配置haproxy多进程
在haproxy虚拟机中
[root@haproxy ~]# pstree -p | grep haproxy
|-haproxy(884)---haproxy(899)-+-{haproxy}(900)
| |-{haproxy}(901)
| `-{haproxy}(910)
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
35 nbproc 2
[root@haproxy ~]# systemctl restart haproxy.service
[root@haproxy ~]# pstree -p | grep haproxy
|-haproxy(1668)-+-haproxy(1670)
| `-haproxy(1671)
也可以让多进程与cpu绑定,以避免频繁换核心带来的性能损耗。
bash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
35 nbproc 2
36 cpu-map 1 0
37 cpu-map 2 1
[root@haproxy ~]# systemctl restart haproxy.service
还可以为 HAProxy 的多进程模式,准备独立的管理统计套接字。彻底避免多进程的 "资源争抢",保障服务稳定。精准定位单个进程的问题,实现精细化监控 / 调试。权限粒度更细,提升系统安全性。不影响业务运行,支持 "热操作"。
bash
[root@haproxy ~]# systemctl stop haproxy.service
删除旧的统计文件(防止权限冲突)
[root@haproxy ~]# rm -rf /var/lib/haproxy/stats
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
stats socket <路径> <权限> <角色> <进程编号>
41 stats socket /var/lib/haproxy/haproxy1 mode 600 level admin process 1
42 stats socket /var/lib/haproxy/haproxy2 mode 600 level admin process 2
[root@haproxy ~]# systemctl start haproxy.service
[root@haproxy ~]# ll /var/lib/haproxy/
总用量 0
srw------- 1 root root 0 3月 11 16:55 haproxy1
srw------- 1 root root 0 3月 11 16:55 haproxy2
3.5 haproxy 多线程
3.5.1 简介
**概念:**在单个主进程内部,启动多个线程来处理请求,线程共享同一个进程的内存空间和资源。
像一家大餐厅里开了多个窗口,所有窗口共享同一个厨房和食材,效率更高、成本更低,但如果厨房出问题,所有窗口都得停摆。
特点:
(1) 线程共享进程资源,通信成本低,状态可以共享。
(2) 同样能利用多核 CPU,让单个进程的多个线程并行处理请求。
(3) 资源占用比多进程模式更小,管理更简单。
局限:
(1) 线程间共享内存,需要注意线程安全问题。
(2) 单个进程崩溃会影响所有线程。
3.5.2 配置haproxy多线程
bash
[root@haproxy ~]# pstree -p | grep haproxy
|-haproxy(1797)-+-haproxy(1799)
| `-haproxy(1800)
[root@haproxy ~]# cat /proc/1799/status | grep Threads
Threads: 1 未启用多线程
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
38 nbthread 2
[root@haproxy ~]# systemctl restart haproxy.service
[root@haproxy ~]# pstree -p | grep haproxy
|-haproxy(1884)---haproxy(1886)---{haproxy}(1887)
[root@haproxy ~]# cat /proc/1886/status | grep Threads
Threads: 2 启用2个线程
3.6 socat热更新工具更新
3.6.1 热更新
概念:在服务或软件不停止的情况下更新软件或服务的工作方式,完成对软件不停工更新,典型的热更新设备,usb,在使用usb进行插拔时,电脑系统时不需要停止工作的,这中设备叫热插拔设备。
3.6.2 热更新服务器权重
bash
[root@haproxy ~]# dnf install socat -y
[root@haproxy ~]# echo "show servers state" | socat stdio /var/lib/haproxy/stats
3 webcluster 1 web1 192.168.248.10 2 0 1 1 3474 6 3 7 6 0 0 0 - 80 - 0 0 - - 0
3 webcluster 2 web2 192.168.248.20 2 0 1 1 3474 6 3 7 6 0 0 0 - 80 - 0 0 - - 0
查看权重
[root@haproxy ~]# echo "get weight webcluster/web1" | socat stdio /var/lib/haproxy/stats
1 (initial 1)
[root@haproxy ~]# echo "get weight webcluster/web2" | socat stdio /var/lib/haproxy/stats
1 (initial 1)
给socat授权,否则使用socat更改信息时会报错
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
41 stats socket /var/lib/haproxy/stats mode 600 level admin
[root@haproxy ~]# systemctl restart haproxy.service
[root@haproxy ~]# echo "set weight webcluster/web1 3" | socat stdio /var/lib/haproxy/stats
[root@haproxy ~]# echo "get weight webcluster/web1" | socat stdio /var/lib/haproxy/stats
3 (initial 1)
测试:使用一台客户端curl 192.168.248.100 观察权重是否改写成功

3.7 Haproxy 算法实验
3.7.1 静态算法
(1) 简介:
调度决策仅依赖预先配置的权重、连接哈希、请求特征等静态元数据 ,不采集、不感知后端服务器实时运行状态 (连接数、负载、响应时延、健康度除外),调度表在运行期不根据后端负载动态调整。
(2) 优点:
极快、无计算开销
哈希类能实现会话保持
(3) 缺点:
完全不管后端忙不忙
后端负载不均时,会把请求继续压给忙的机器
高并发下容易 "越忙越忙**"**
(4) 应用场景:
请求处理时延相近的短连接业务
需要会话保持 / 请求粘性的场景
后端节点性能均等、负载均匀的稳定集群
3.7.2 动态算法
(1) 简介:
调度器实时采集后端服务器运行时状态 (活跃连接数、响应时间、负载等),并基于实时状态动态计算调度权重或选择目标后端 ,使流量向负载更低、处理能力更强 的节点倾斜,实现自适应负载均衡。
(2) 优点:
自动避开繁忙 / 高负载服务器
长连接、高耗时场景负载非常均衡
自适应流量波动
(3) 缺点:
需要额外计算(开销极小,可忽略)
不适合需要强会话绑定的业务
(4) 适应场景:
长连接、高时延、请求耗时差异大的业务(数据库代理、API 网关、文件服务)
后端节点性能异构
高并发、流量波动剧烈、易出现负载倾斜的集群
3.7.3 静态算法 static-rr**(静态加权轮询)**
(1) 简介:
原理 :基于预先配置的权重 进行轮询分发,权重在运行期不可动态修改,调度表固定。
特点:
性能极高,O (1) 复杂度
权重修改必须重启 HAProxy 才能生效
适合权重长期稳定、无需动态调整的场景
适用:后端性能固定、流量稳定的集群
(2) 给haproxy配置static-rr算法
bash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
81 listen webcluster
82 bind *:80
83 mode http
84 balance static-rr
85 server web1 192.168.248.10:80 check inter 3s fall 3 rise 5 weight 2
86 server web2 192.168.248.20:80 check inter 3s fall 3 rise 5 weight 1
[root@haproxy ~]# systemctl restart haproxy.service
注意: HAProxy 提供两种核心代理模式 :HTTP 模式**(七层代理)** 和 TCP 模式**(四层代理)** 。在配置 listen 段时 ,若未明确指定模式 ,系统会默认采用 HTTP 模式 。如需使用 TCP 代理 ,则必须显式声明 mode tcp。
(3) 测试:使用客户端curl 192.168.248.200,观察均衡效果。
bash
[root@client ~]# for i in {1..10};do curl 192.168.248.100;done
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
webserver2 - 192.168.248.20
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
webserver2 - 192.168.248.20
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
webserver2 - 192.168.248.20
webserver1 - 192.168.248.10
再次申明static-rr不支持热更新
bash
[root@haproxy ~]# echo "set weight webcluster/web2 2" | socat stdio /var/lib/haproxy/st
ats
Backend is using a static LB algorithm and only accepts weights '0%' and '100%'.
3.7.4 静态算法 first(优先选择)
(1) 简介
原理 :总是选择列表中第一个可用的后端服务器,只有当前一个节点不可用时才切换到下一个。
特点:
极端简单,几乎无计算开销
天然实现主备模式(Active-Standby)
流量完全集中在首节点,负载极不均衡
适用:主备架构、冷备场景,不适合负载均衡
(2) 给haproxy配置静态算法 first:
bash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
81 listen webcluster
82 bind *:80
83 #mode http
84 balance first
85 server web1 192.168.248.10:80 maxconn 1 check inter 3s fall 3 rise 5
86 server web2 192.168.248.20:80 check inter 3s fall 3 rise 5
[root@haproxy ~]# systemctl restart haproxy.service
(3)测试:
使用客户端curl 192.168.248.100,观察均衡效果。再关闭web1再次尝试curl 192.168.248.100观察是否将请求均衡给web2
bash
[root@client ~]# for i in {1..10};do curl 192.168.248.100;done
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
关闭web1 http服务
bash
[root@webserver1 ~]# systemctl stop httpd.service
bash
[root@client ~]# for i in {1..10};do curl 192.168.248.100;done
webserver2 - 192.168.248.20
webserver2 - 192.168.248.20
webserver2 - 192.168.248.20
webserver2 - 192.168.248.20
webserver2 - 192.168.248.20
webserver2 - 192.168.248.20
webserver2 - 192.168.248.20
webserver2 - 192.168.248.20
webserver2 - 192.168.248.20
webserver2 - 192.168.248.20
3.7.5 动态算法 roundrobin(动态加权轮询)
(1) 简介
原理 :基于动态权重平滑轮询,运行期可通过 socket 实时调整权重,无需重启。
特点:
平滑分发,避免突发流量集中
支持慢启动(slowstart),防止新节点被流量打满
是 HAProxy 默认算法
适用:Web 短连接、请求耗时相近的通用场景
(2) 给haproxy配置动态算法 roundrobin
bash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
81 listen webcluster
82 bind *:80
83 #mode http
84 balance roundrobin
85 server web1 192.168.248.10:80 check inter 3s fall 3 rise 5 weight 2
86 server web2 192.168.248.20:80 check inter 3s fall 3 rise 5 weight 1
[root@haproxy ~]# systemctl restart haproxy.service
(3) 使用客户端curl 192.168.248.100,观察均衡效果。
bash
[root@client ~]# for i in {1..10};do curl 192.168.248.100;done
webserver2 - 192.168.248.20
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
webserver2 - 192.168.248.20
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
webserver2 - 192.168.248.20
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
webserver2 - 192.168.248.20
注意:动态算法roundrobin支持动态权重热更新
bash
[root@haproxy ~]# echo "get weight webcluster/web1" | socat stdio /var/lib/haproxy/stats
2 (initial 2)
[root@haproxy ~]# echo "set weight webcluster/web1 1" | socat stdio /var/lib/haproxy/st
ats
[root@haproxy ~]# echo "get weight webcluster/web1" | socat stdio /var/lib/haproxy/stats
1 (initial 2)
3.7.6 动态算法 leastconn(最少连接)
(1) 简介:
原理 :将请求分发到当前活跃连接数最少的后端节点,自动规避繁忙节点。
特点:
自适应负载,长连接场景下负载均衡效果极佳
对节点性能异构、请求耗时差异大的场景友好
适用:数据库代理、API 网关、长连接服务(如 WebSocket)
(2) 给haprroxy配置静态算法 leastconn
bash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
81 listen webcluster
82 bind *:80
83 #mode http
84 balance leastconn
85 server web1 192.168.248.10:80 check inter 3s fall 3 rise 5 weight 2
86 server web2 192.168.248.20:80 check inter 3s fall 3 rise 5 weight 1
[root@haproxy ~]# systemctl restart haproxy.service
(3) 测试:
使用客户端curl 192.168.248.100,观察均衡效果。
bash
[root@client ~]# for i in {1..10};do curl 192.168.248.100;done
webserver1 - 192.168.248.10
webserver2 - 192.168.248.20
webserver1 - 192.168.248.10
webserver2 - 192.168.248.20
webserver1 - 192.168.248.10
webserver2 - 192.168.248.20
webserver1 - 192.168.248.10
webserver2 - 192.168.248.20
webserver1 - 192.168.248.10
webserver2 - 192.168.248.20
3.7.7 混合算法 source(源 IP 哈希)
(1) 原理: 对客户端源 IP 地址做哈希运算,将同一 IP 的请求固定绑定到同一后端节点。
特点:
实现会话保持,同一客户端始终访问同一节点
节点增减时会导致哈希重分布,部分会话失效
**适用:**需要会话粘性的场景(如登录状态、本地缓存)
(2) 给haproxy配置混合算法 source
bash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
81 listen webcluster
82 bind *:80
83 #mode http
84 balance source
85 hash-type consistent
86 server web1 192.168.248.10:80 check inter 3s fall 3 rise 5 weight 2
87 server web2 192.168.248.20:80 check inter 3s fall 3 rise 5 weight 1
[root@haproxy ~]# systemctl restart haproxy.service
consistent:启用一致性哈希(Consistent Hashing),这是 HAProxy 中最推荐的哈希模式。
一致性哈希的工作原理:
一致性哈希会将所有后端节点和请求哈希值映射到一个环形哈希空间:
每个请求的哈希值在环上找到顺时针最近的节点,并绑定到该节点。
当节点新增 / 下线时,只会影响哈希值落在该节点负责区间的一小部分请求,大部分请求仍保持原节点绑定。
对比普通哈希:普通哈希节点变化会导致全局哈希重分布,大量会话失效。一致性哈希节点变化仅影响受影响节点的区间请求,大部分会话不失效。
(3) 测试:
bash
[root@client ~]# for i in {1..10};do curl 192.168.248.100;done
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
3.7.8 混合算法 uri(URI 哈希)
(1) 简介
原理: 对请求的URI 路径做哈希,将同一资源的请求固定绑定到同一节点。
特点:
适合静态资源缓存(如图片、JS/CSS),提升缓存命中率
可配置哈希深度,避免过长 URI 导致计算开销
**适用:**静态资源服务、CDN 场景
(2) 给haproxy配置混合算法 uri
主备实验环境:
web1
bash
[root@webserver1 ~]# echo "rs1 - 192.168.248.10" > /var/www/html/index2.htm
l
[root@webserver1 ~]# echo "rs1 - 192.168.248.10" > /var/www/html/index1.htm
l
web2
bash
[root@webserver2 ~]# echo "rs2 - 192.168.248.20" > /var/www/html/index2.html
[root@webserver2 ~]# echo "rs2 - 192.168.248.20" > /var/www/html/index1.htm
l
配置算法
bash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
81 listen webcluster
82 bind *:80
83 #mode http
84 balance uri
85 hash-type consistent
86 server web1 192.168.248.10:80 check inter 3s fall 3 rise 5 weight 2
87 server web2 192.168.248.20:80 check inter 3s fall 3 rise 5 weight 1
[root@haproxy ~]# systemctl restart haproxy.service
(3) 测试:
两台客户端分别curl 192.168.248.100/index2.html和192.168.248.100/index1.html,观察同一资源的请求固定绑定到同一节点。


3.7.9 混合算法 url_param
(1) 简介
原理: 对 URL 中指定的查询参数(如 user_id、name)做哈希,将同一参数值的请求绑定到同一节点。
特点:
粒度更细,可按业务维度(如用户 ID、订单 ID)实现粘性
需指定参数名,未携带参数时默认回退到 roundrobin
**适用:**按用户 / 订单维度分片的业务
(2) 给haproxy配置混合算法 url_param
bash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
81 listen webcluster
82 bind *:80
83 #mode http
84 balance url_param name
85 hash-type consistent
86 server web1 192.168.248.10:80 check inter 3s fall 3 rise 5 weight 2
87 server web2 192.168.248.20:80 check inter 3s fall 3 rise 5 weight 1
[root@haproxy ~]# systemctl restart haproxy.service /haproxy.cfg
(3) 测试:在curl 192.168.248.100/index1/2.html文件时加上?name=名字
bash
[root@client ~]# for i in {1..2};do curl 192.168.248.100/index.html?name=bi;done
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
[root@client ~]# for i in {1..2};do curl 192.168.248.100/index.html?name=weiwen;done
webserver1 - 192.168.248.10
webserver1 - 192.168.248.10
[root@client ~]# for i in {1..2};do curl 192.168.248.100/index.html?name=tutu;done
webserver2 - 192.168.248.20
webserver2 - 192.168.248.20
[root@client ~]# for i in {1..2};do curl 192.168.248.100/index.html?name=wm;done
3.7.10 混合算法 hdr
(1) 简介
原理: 对指定的HTTP 请求头(如 Cookie、Authorization)做哈希,实现更灵活的会话粘性。
特点:
可基于 Cookie、Token 等实现强会话保持
支持 use_domain 等选项,适配 Cookie 域名场景
**适用:**需要基于登录态、Token 实现粘性的 Web 应用
(2) 给haproxy配置混合算法 hdr
bash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
81 listen webcluster
82 bind *:80
83 #mode http
84 balance hdr(User-Agent)
85 hash-type consistent
86 server web1 192.168.248.10:80 check inter 3s fall 3 rise 5 weight 2
87 server web2 192.168.248.20:80 check inter 3s fall 3 rise 5 weight 1
[root@haproxy ~]# systemctl restart haproxy.service
(3) 测试:
curl -A "自定义字符串" 172.25.254.100
bash
[root@client ~]# curl -A "weiwenbi" 192.168.248.100
webserver1 - 192.168.248.10
[root@client ~]# curl -A "weiwen" 192.168.248.100
webserver1 - 192.168.248.10
[root@client ~]# curl -A "bi" 192.168.248.100
webserver1 - 192.168.248.10
哈希映射到新节点
[root@client ~]# curl -A "tutu" 192.168.248.100
webserver2 - 192.168.248.20
[root@client ~]# curl -A "tuwenwen" 192.168.248.100
webserver2 - 192.168.248.20
会话粘性
[root@client ~]# curl -A "weiwenbi" 192.168.248.100
webserver1 - 192.168.248.10
[root@client ~]# curl -A "weiwenbi" 192.168.248.100
webserver1 - 192.168.248.10
[root@client ~]# curl -A "weiwenbi" 192.168.248.100
webserver1 - 192.168.248.10
[root@client ~]# curl -A "weiwenbi" 192.168.248.100
webserver1 - 192.168.248.10
3.8 基于cookie的会话保持
3.8.1 简介:
如果在haprorxy中设定算法为source,在同一台客户端主机中,无论使用什么浏览器访问的最终服务器是同一个
可以使用cookie值进行优化,让同一台客户端中同一个浏览器中访问的是同一个服务器
不同浏览器访问的是不同的服务器
3.8.2 配置cookie会话保持
先启用静态轮询,实验时观察效果更明显
bash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
81 listen webcluster
82 bind *:80
83 #mode http
84 balance roundrobin
85 cookie WEBCOOKIE insert nocache indirect
86 server web1 192.168.248.10:80 check inter 3s fall 3 rise 5 weight 2
87 server web2 192.168.248.20:80 check inter 3s fall 3 rise 5 weight 1
[root@haproxy ~]# systemctl restart haproxy.service
核心 Cookie 粘性配置:
WEBCOOKIE:自定义 Cookie 名称
insert:HAProxy 自动向响应中插入 Cookie,标记客户端应绑定的后端节点
nocache:禁止中间缓存(如 CDN)缓存该 Cookie
indirect:仅在客户端首次访问时插入 Cookie,后续请求由客户端携带
3.8.3 测试:
使用不同的浏览器多次浏览192.168.248.100
第一次

第二次
3.9 haproxy状态页
3.9.1 简介:
(1) 概念:
HAProxy 内置的 Web 可视化监控面板,专门用于实时查看负载均衡集群的运行状态和性能指标。
(2) 作用:
HAProxy 状态页是轻量、开箱即用的可视化监控工具
3.9.2 启用状态页
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
89 listen stats #定义一个专门用于监控统计的监听块(独立于业务流量)
90 mode http #强制使用 HTTP 模式,因为监控面板是 Web 页面(必须配置)
91 bind 0.0.0.0:4321 #监听所有网卡的 4321 端口,通过 http://服务器IP:4321/status 访问监控面板
92 stats enable #启用监控统计功能(默认关闭,必须显式开启)
93 log global #继承全局配置的日志规则,记录监控面板的访问日志
94 stats refresh 1 # 页面自动刷新间隔(10秒)
95 stats uri /status #监控面板的访问路径(自定义,如 /status)
96 stats auth bi:123 #设置监控面板的访问密码(用户名:bi,密码:123),防止未授权访问
[root@haproxy ~]# systemctl restart haproxy.service
对与配置文件的解释在代码框里
3.9.3 测试:
使用浏览器访问192.168.248.100:4321/status进入登录状态页界面,输入账号密码进入状态页


关闭web2的http服务在观察状态页,显示web2down
3.10 haproxy的ip透传
3.10.1 介绍
IP 透传(客户端源 IP 透传) :指在代理 / 负载均衡架构中,负载均衡设备将客户端真实源 IP 地址传递至后端上游服务器,使上游服务可获取原始客户端网络标识,而非仅获取代理节点自身 IP 的技术能力。
3.10.2 类型
(1) 七层IP透传
基于HTTP/HTTPS 应用层协议,通过在请求头中携带客户端 IP 信息,实现上游服务感知真实源地址。
适用场景:HTTP/HTTPS 业务、Web 服务、API 网关、日志审计、访问控制、地域识别、WAF / 风控策略。(因为MySQL、Redis、SSH、游戏、自定义 TCP 协议不是 HTTP,没法加请求头,只能用四层透传)
(2) 四层IP透传
基于TCP/UDP 传输层 ,不解析应用层报文,通过协议扩展或网络层地址伪装实现源 IP 透传。
适用场景: MySQL、Redis、SSH、自定义 TCP 协议、非 HTTP 业务、加密流量代理。
(3) 开启七层ip透传
开启haproxy的七层透传功能
bash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
59 option forwardfor except 127.0.0.0/8
[root@haproxy ~]# systemctl restart haproxy.service
option forwardfor:启用七层 IP 透传,在转发 HTTP 请求时自动添加 X-Forwarded-For 请求头,将客户端真实 IP 传递给后端服务。
except 127.0.0.0/8:排除规则,当客户端 IP 属于 127.0.0.0/8 网段(即本地回环地址)时,不向 X-Forwarded-For 头中追加该 IP,避免日志中混入本地访问记录。
在后端服务器中设定采集透传ip,以web2为例,将web1展示设置为日志服务器。
bash
[root@webserver2 ~]# vim /etc/httpd/conf/httpd.conf
206 LogFormat "%h %l %u %t \"%r\" %>s %b \"%{X-Forwarded-For}i\" \"%{Referer}i\" \"%{User-Agent}i\"" combined
[root@webserver2 ~]# systemctl restart httpd
设置日志机:
bash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
26 log 192.168.248.10 local2
[root@haproxy ~]# systemctl restart haproxy.service
bash
[root@webserver1 ~]# vim /etc/rsyslog.conf
37 module(load="imudp") # needs to be done just once
38 input(type="imudp" port="514")
[root@webserver1 ~]# systemctl restart rsyslog.service
(4) 测试:
bash
[root@client ~]# curl 192.168.248.100
webserver1 - 192.168.248.10
[root@client ~]# curl 192.168.248.100
webserver1 - 192.168.248.10
[root@client ~]# curl 192.168.248.100
webserver2 - 192.168.248.20
[root@client ~]# curl 192.168.248.100
webserver1 - 192.168.248.10
在web2 httpd日志文件中查看
bash
[root@webserver2 ~]# cat /etc/httpd/logs/access_log
192.168.248.100 - - [12/Mar/2026:20:41:07 +0800] "GET / HTTP/1.1" 200 28 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:148.0) Gecko/20100101 Firefox/148.0"
192.168.248.100 - - [12/Mar/2026:20:45:24 +0800] "GET /favicon.ico HTTP/1.1" 404 196 "http://192.168.248.100/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36 Edg/145.0.0.0"
192.168.248.100 - - [13/Mar/2026:13:41:45 +0800] "GET / HTTP/1.1" 200 28 "192.168.198.10" "-" "curl/7.76.1"
(5): 开启四层ip透传
修改web1和web2修改配置文件
bash
[root@webserver1 ~]# vim /etc/nginx/nginx.conf
38 server {
39 listen 80 proxy_protocol; #启用四层访问控制
40 listen [::]:80;
41 server_name _;
42 root /usr/share/nginx/html;
43
44 # Load configuration files for the default server block.
45 include /etc/nginx/default.d/*.conf;
46
47 error_page 404 /404.html;
48 location = /404.html {
49 }
50
51 error_page 500 502 503 504 /50x.html;
52 location = /50x.html {
53 }
54 }
[root@webserver1 ~]# systemctl restart nginx.service
[root@webserver1 ~]# echo "rs - 192.168.248.10" > /usr/share/nginx/html/index.html
bash
[root@webserver2 ~]# vim /etc/nginx/nginx.conf
38 server {
39 listen 80 proxy_protocol; #启用四层访问控制
40 listen [::]:80;
41 server_name _;
42 root /usr/share/nginx/html;
43
44 # Load configuration files for the default server block.
45 include /etc/nginx/default.d/*.conf;
46
47 error_page 404 /404.html;
48 location = /404.html {
49 }
50
51 error_page 500 502 503 504 /50x.html;
52 location = /50x.html {
53 }
54 }
[root@webserver2 ~]# systemctl restart nginx.service
[root@webserver2 ~]# echo "rs - 192.168.248.20" > /usr/share/nginx/html/index.html
在haproxy的配置文件上开启四层IP透传
bash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
82 listen webcluster
83 bind *:80
84 mode tcp
85 balance roundrobin
86 cookie WEBCOOKIE insert nocache indirect
87 server web1 192.168.248.10:80 send-proxy check inter 3s fall 3 rise 5 weight 1
88 server web2 192.168.248.20:80 send-proxy check inter 3s fall 3 rise 5 weight 1
[root@haproxy ~]# systemctl restart haproxy.service
send-proxy:在 TCP 连接建立初期,向后端服务器发送 PROXY 协议头部,携带客户端真实 IP、端口等信息,实现四层 IP 透传。
在web1和web2上设置四层IP透传
bash
[root@webserver1 ~]# vim /etc/nginx/nginx.conf
18 log_format main '$remote_addr - $remote_user [$time_local] "$request" '
19 '"$proxy_protocol_addr"'
20 '$status $body_bytes_sent "$http_referer" '
21 '"$http_user_agent" "$http_x_forwarded_for"';
[root@webserver1 ~]# systemctl restart nginx.service
bash
[root@webserver1 ~]# vim /etc/nginx/nginx.conf
17 http {
18 log_format main '$remote_addr - $remote_user [$time_local] "$request" '
19 '"$proxy_protocol_addr"'
20 '$status $body_bytes_sent "$http_referer" '
21 '"$http_user_agent" "$http_x_forwarded_for"';
[root@webserver2 ~]# systemctl restart nginx.service
(6)测试:
bash
[root@client ~]# for i in {1..5};do curl 192.168.248.100;done
rs - 192.168.248.10
rs - 192.168.248.20
rs - 192.168.248.10
rs - 192.168.248.20
rs - 192.168.248.10
bash
[root@webserver1 ~]# cat /var/log/nginx/access.log
192.168.248.100 - - [13/Mar/2026:14:47:05 +0800] "GET / HTTP/1.1" "192.168.198.10"200 20 "-" "curl/7.76.1" "-"
192.168.248.100 - - [13/Mar/2026:14:47:05 +0800] "GET / HTTP/1.1" "192.168.198.10"200 20 "-" "curl/7.76.1" "-"
192.168.248.100 - - [13/Mar/2026:14:47:05 +0800] "GET / HTTP/1.1" "192.168.198.10"200 20 "-" "curl/7.76.1" "-"
3.11 自定义HAProxy 错误界面
3.11.1 sorryserver的设定
当后端所有的正常服务器(server)全部宕机、健康检查失败或达到最大连接数时,HAProxy 不会直接返回 "503 Service Unavailable" 错误,而是将客户端请求强制转发到这台指定的 SorryServer。
正常的所有服务器如果出现宕机,那么客户将被定向到指定的主机中,这个当业务主机出问题时被临时访问的主机叫做sorryserver.
3.11.2 配置sorryserver页
bash
[root@haproxy ~]# vim /etc/httpd/conf/httpd.conf
47 Listen 8080
[root@haproxy ~]# systemctl restart httpd
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
82 listen webcluster
83 bind *:80
84 mode http
85 balance roundrobin
86 cookie WEBCOOKIE insert nocache indirect
87 server web1 192.168.248.10:80 check inter 3s fall 3 rise 5 weight 1
88 server web2 192.168.248.20:80 check inter 3s fall 3 rise 5 weight 1
89 server haproxy 192.168.248.100:8080 backup #sorryserver
[root@haproxy ~]# systemctl restart haproxy.service
[root@haproxy ~]# echo "所有服务机已下线" > /var/www/html/index.html
3.11.3 测试:
关闭所有服务机再访问192.168.248.100,查看错界面是否展示
bash
[root@haproxy ~]# curl 192.168.248.100
所有服务机已下线
3.12 自定义错误页面
3.12.1 简介
当所有主机包括sorryserver都宕机了,那么haproxy会提供一个默认访问的错误页面,这个错误页面跟报错代码有关,这个页面可以通过定义来机型设置。
3.12.2 配置自定义错误页面
创建自定义错误页面文件
bash
[root@haproxy ~]# mkdir /errorpage/html/ -p
[root@haproxy ~]# vim /errorpage/html/503.http
1 HTTP/1.0 503 Service Unavailable
2 Cache-Control: no-cache
3 Connection: close
4 Content-Type: text/html;charset=UTF-8
5
6 <html><body><h1>涂謦文最爱谁</h1>
7 猪猪!
8 </body></html>
在haproxy配置文件中开启自定义页面错误功能
bash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
60 option redispatch
61 retries 3
62 timeout http-request 10s
63 timeout queue 1m
64 timeout connect 10s
65 timeout client 1m
66 timeout server 1m
67 timeout http-keep-alive 10s
68 timeout check 10s
69 maxconn 3000
70 errorfile 503 /errorpage/html/503.http #错误界面路径
[root@haproxy ~]# systemctl restart haproxy.service
3.12.3 测试:
关闭haproxy、web1和web2再访问192.168.248.100,查看错界面是否展示
bash
[root@haproxy /]# systemctl stop httpd.service
[root@haproxy /]# curl 192.168.248.100
<html><body><h1>涂謦文最爱谁</h1>
猪猪!
</body></html>
3.12.4 从定向错误到指定网站
修改haproxy配置文件
bash
[root@haproxy /]# vim /etc/haproxy/haproxy.cfg
67 timeout http-keep-alive 10s
68 timeout check 10s
69 maxconn 3000
70 errorloc 503 http://www.baidu.com
[root@haproxy /]# systemctl restart haproxy.service
3.12.5 测试:
关闭haproxy、web1和web2的 httpd服务,使用浏览器访问192.168.248.100

3.13 Haproxy ACL访问控制
3.13.1 概念:
HAProxy 的 ACL(Access Control Lists,访问控制列表) 是一套强大的流量过滤与路由规则系统,用于根据客户端请求的各种属性(如 IP、域名、路径、请求头等)做出精准决策,实现访问控制、流量分流、安全防护等功能。
3.14.2 在haproxy配置文件做基于域名解析结尾匹配的配置:
bash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
82 listen webcluster
83 bind *:80
84 mode http
86
87 acl test hdr_end(host) -i .com #acl test hdr_end(host) -i .com
88 use_backend webserver-80-web1 if test #use_backend webserver-80-web2
89 default_backend webserver-80-web2
90
91 backend webserver-80-web1
92 server web1 192.168.248.10:80 check inter 3s fall 3 rise 5
94 backend webserver-80-web2
95 server web2 192.168.248.20:80 check inter 3s fall 3 rise 5
[root@haproxy ~]# systemctl restart haproxy.service
解析:
acl test:定义一个名为 test 的访问控制列表
hdr_end(host):匹配 HTTP 请求头中 Host 字段的后缀
-i:忽略大小写匹配
.com:匹配所有以 .com 结尾的域名(如 example.com、api.test.com)
use_backend:将匹配的请求转发到指定后端
webserver-80-web1:目标后端名称
if test:仅当请求满足 test ACL 规则时执行此动作
default_backend:所有未匹配上述 ACL 的请求,都会被转发到 webserver-80-web2 后端
在client中设定解析

3.14.3 测试:
使用client 访问分别以.com和非.com结尾的域名解析

3.14.4 在haproxy配置文件做基于域名解析头部匹配的配置:
bash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
82 listen webcluster
83 bind *:80
84 mode http
85
86 acl head hdr_beg(host) -i bbs.
87 use_backend webserver-80-web1 if head
88 default_backend webserver-80-web2
89
90 backend webserver-80-web1
91 server web1 192.168.248.10:80 check inter 3s fall 3 rise 5
92 backend webserver-80-web2
93 server web2 192.168.248.20:80 check inter 3s fall 3 rise 5
[root@haproxy ~]# systemctl restart haproxy.service
解析:
acl head: 定义一个名为 head 的访问控制列表
hdr_beg(host): 匹配 HTTP 请求头中 Host 字段的前缀
bbs.: 匹配所有以 bbs. 开头的域名
if head: 仅当请求满足 head ACL 规则时执行此动作
3.14.5 测试
使用client 访问分别以.bbs和非.bbs 开头结尾的域名解析

3.14.6 在haproxy配置文件做基于域名解析文件匹配的配置:
bash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
82 listen webcluster
83 bind *:80
84 mode http
85
86 acl pathdir base_dir -i /bi
87 use_backend webserver-80-web1 if pathdir
88 default_backend webserver-80-web2
89
90 backend webserver-80-web1
91 server web1 192.168.248.10:80 check inter 3s fall 3 rise 5
92 backend webserver-80-web2
93 server web2 192.168.248.20:80 check inter 3s fall 3 rise 5
[root@haproxy ~]# systemctl restart haproxy.service
解析:
acl pathdir: 定义一个名为 pathdir 的访问控制列表
base_dir: 匹配 URL 路径的基础目录部分(即 URL 中第一个 / 之后、下一个 / 之前的片段)
/bi: 匹配基础目录为 /bi 的 URL 路径(如 /bi、/bi/xxx、/BI/page.html 都会被匹配,而 /bio、/api/bi 不会被匹配)
if pathdir: 仅当请求满足 pathdir ACL 规则时执行此动作
在web1和web2上创建要匹配的文件
bash
[root@webserver1 ~]# mkdir -p /var/www/html/bi/weiwen/
[root@webserver1 ~]# echo bi - 192.168.248.10 > /var/www/html/bi/index.html
[root@webserver1 ~]# echo bi/weiwen - 192.168.248.10 > /var/www/html/bi/weiwen/index.html
bash
[root@webserver2 ~]# mkdir -p /var/www/html/bi/weiwen/
[root@webserver2 ~]# echo bi - 192.168.248.20 > /var/www/html/bi/index.html
[root@webserver2 ~]# echo bi/weiwen - 192.168.248.20 > /var/www/html/bi/weiwen/index.html
3.14.7 测试:
使用client 访问分别带上目录/bi/、/bi/weiwenbi/、和文件/index.html结尾的域名解析

说明规则只要匹配到/bi/目录就符合规则
3.14.8 acl允许列表白名单
在haproxy配置文件做白名单的配置:
bash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
82 listen webcluster
83 bind *:80
84 mode http
85
86 acl invalid_src src 192.168.198.10
87 http-request deny if !invalid_src
88
89 acl test hdr_end(host) -i .com
90 use_backend webserver-80-web1 if test
91 default_backend webserver-80-web2
92
93 backend webserver-80-web1
94 server web1 192.168.248.10:80 check inter 3s fall 3 rise 5
95 backend webserver-80-web2
96 server web2 192.168.248.20:80 check inter 3s fall 3 rise 5
[root@haproxy ~]# systemctl restart haproxy.service
解析:
acl invalid_src: 定义一个名为 invalid_src 的访问控制列表
src: 匹配客户端的来源 IP 地址
http-request deny: 执行拒绝 HTTP 请求的动作
if: 条件判断关键字,仅当满足后续规则时执行动作
!invalid_src: 逻辑 "非",表示不满足 invalid_src ACL 规则的请求(即来源 IP 不是 192.168.198.10 的请求)
3.14.9 测试:
使用haproxy(192.168.248.100)和client(192.168.198.10)访问192.168.248.100


3.14.8 acl禁止列表黑名单
在haproxy配置文件做黑名单的配置:
bash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
86 acl invalid_src src 192.168.198.10
87 http-request deny if invalid_src
88
89 acl test hdr_end(host) -i .com
90 use_backend webserver-80-web1 if test
91 default_backend webserver-80-web2
[root@haproxy ~]# systemctl restart haproxy.service
invalid_src: 逻辑 "是",表示满足 invalid_src ACL 规则的请求(即来源 IP 是 192.168.198.10 的请求)
测试:使用haproxy(192.168.248.100)和client(192.168.198.10)访问192.168.248.100


3.15 Haproxy全站加密
3.15.1 简介
指在 HAProxy 上实现客户端到负载均衡器的全链路 HTTPS 加密,通常包含强制 HTTP 跳转 HTTPS 与 TLS 终端两大核心能力。
整体逻辑:
(1) 客户端访问 80 端口(HTTP):
HAProxy 返回 301/302 重定向,强制浏览器访问 443 端口(HTTPS)。
(2) 客户端建立 HTTPS 连接:
HAProxy 完成 TLS 握手与解密,提取请求头(如 Host)进行路由决策。
(3) 流量分发与响应:
HAProxy 将明文请求转发给后端 Web 服务器,服务器返回响应后,HAProxy 重新加密并返回给客户端。
(4)最终效果:
实现业务的全站 HTTPS,保障数据传输机密性与完整性,同时保留 HAProxy 高性能的流量分发能力。
3.15.2 制作证书
bash
[root@haproxy ~]# mkdir /etc/haproxy/certs/
[root@haproxy certs]# openssl req -newkey rsa:2048 -nodes -sha256 -keyout /etc/haproxy/certs/weiwenbi.org.key -x509 -days 365 -out /etc/haproxy/certs/weiwenbi.org.crt
....+...+....+..+....+..+.......+......+.........+...+...+.....+.+.....+.+..+......+.........+.......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.......+...............+..+.........+..........+...+........+.........+...+.+......+........+.+..+....+.....+...+...+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.....+..+...+...+....+.........+......+.....+.........+..........+.....+.+.....+..........+...+..+.............+......+..+.........+...+..........+...+........+....+...........+.......+.........+...........+.........+.+...............+..+.......+...+.....+..........+......+..+...+....+..+...+...............+...+...+.+.....+...+............+.+........+....+.....+.+....................+.......+...+.....+.+......+...+......+......+..+.+......+...+..+...............+......+...+................+.........+..+.......+......+..+...+.+...+............+.......................+...........................+...+..........+......+.....+............+.........+...+.+......+......+.........+......+..+...+.......+..+.+...........................+..+...+......+....+...........+.........+.+.....+.........+...+.......+...+..+..................+..........+...+..............+......+.........+...+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
....+..+.......+...............+...+...+.....+.+.....+....+.....+......+.+..+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.....+..+.+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*......+......+.........+.....+......+.......+..+...+...+....+...........+.+.....+.........+....+...+.....+.......+.....+.+.....+............+...+.+.....+...+...............+..........+...........+....+..+......+...+....+...+.....+.......+............+...............+.....+.+...+.....+.......+...+.........+.....+.......+...+..+.+..............+.............+....................+.+...............+...........+.+..+......+....+.....+.......+......+...+.....+......+....+...........+....+............+............+.....+...............+.......+...+..+......+....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:GC
Locality Name (eg, city) [Default City]:GL
Organization Name (eg, company) [Default Company Ltd]:weiwenbi
Organizational Unit Name (eg, section) []:linux
Common Name (eg, your name or your server's hostname) []:www.weiwenbi.org
Email Address []:admin@weiwenbi.org
查看结果
bash
[root@haproxy certs]# ls
weiwenbi.org.crt weiwenbi.org.key
[root@haproxy certs]# cat /etc/haproxy/certs/weiwenbi.org.{key,crt} > /etc/haproxy/certs/weiwenbi.pem
[root@haproxy certs]# ls
weiwenbi.org.crt weiwenbi.org.key weiwenbi.pem
2.15.3 全站加密
bash
[root@haproxy certs]# vim /etc/haproxy/haproxy.cfg
82 listen webcluster-http
83 bind *:80
84 redirect scheme https if ! { ssl_fc }
85
86 listen webcluster-https
87 bind *:443 ssl crt /etc/haproxy/certs/weiwenbi.pem
88 mode http
89 balance roundrobin
90
91 server web1 192.168.248.10:80 check inter 3s fall 3 rise 5 weight 1
92 server web2 192.168.248.20:80 check inter 3s fall 3 rise 5 weight 1
[root@haproxy certs]# systemctl restart haproxy.service
解析:
listen webcluster-http: 定义一个名为 webcluster-http 的监听段,专门处理 HTTP 流量
bind *:80: 监听所有网卡的 80 端口(HTTP 默认端口)
redirect scheme https if !{ ssl_fc }: 强制将未加密的 HTTP 请求重定向到 HTTPS
redirect scheme https: 重定向到 HTTPS 协议
if !{ ssl_fc }: 条件判断,ssl_fc 表示已建立 TLS 加密连接,!{ ssl_fc } 即 "未加密的请求"
listen webcluster-https: 定义一个名为 webcluster-https 的监听段,专门处理 HTTPS 流量
bind *:443 ssl crt /etc/haproxy/certs/weiwenbi.pem: 监听 443 端口(HTTPS 默认端口)并启用 SSL/TLS
ssl: 启用 SSL/TLS 加密
crt /etc/haproxy/certs/weiwenbi.pem: 指定 PEM 格式的证书文件(需包含证书与私钥)
mode http: 工作在 HTTP 模式,支持七层流量路由
2.15.4 测试
bash
* Trying 192.168.248.100:80...
* Connected to 192.168.248.100 (192.168.248.100) port 80 (#0)
> GET / HTTP/1.1
> Host: 192.168.248.100
> User-Agent: curl/7.76.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 302 Found
< content-length: 0
< location: https://192.168.248.100/
< cache-control: no-cache
<
* Connection #0 to host 192.168.248.100 left intact
* Clear auth, redirects to port from 80 to 443Issue another request to this URL: 'https://192.168.248.100/'
* Trying 192.168.248.100:443...
* Connected to 192.168.248.100 (192.168.248.100) port 443 (#1)
* ALPN, offering h2
* ALPN, offering http/1.1
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Unknown (23):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.2 (IN), TLS header, Unknown (23):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS header, Unknown (23):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.2 (IN), TLS header, Unknown (23):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Unknown (23):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server did not agree to a protocol
* Server certificate:
* subject: C=CN; ST=GC; L=GL; O=weiwenbi; OU=linux; CN=www.weiwenbi.org; emailAddress=admin@weiwenbi.org
* start date: Mar 13 12:32:59 2026 GMT
* expire date: Mar 13 12:32:59 2027 GMT
* issuer: C=CN; ST=GC; L=GL; O=weiwenbi; OU=linux; CN=www.weiwenbi.org; emailAddress=admin@weiwenbi.org
* SSL certificate verify result: self-signed certificate (18), continuing anyway.
* TLSv1.2 (OUT), TLS header, Unknown (23):
> GET / HTTP/1.1
> Host: 192.168.248.100
> User-Agent: curl/7.76.1
> Accept: */*
>
* TLSv1.2 (IN), TLS header, Unknown (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.2 (IN), TLS header, Unknown (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* TLSv1.2 (IN), TLS header, Unknown (23):
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< date: Fri, 13 Mar 2026 12:40:42 GMT
< server: Apache/2.4.57 (Red Hat Enterprise Linux)
< last-modified: Wed, 11 Mar 2026 04:10:32 GMT
< etag: "1c-64cb7d12810c2"
< accept-ranges: bytes
< content-length: 28
< content-type: text/html; charset=UTF-8
<
webserver1 - 192.168.248.10
* Connection #1 to host 192.168.248.100 left intact
浏览器查看证书
