haproxy高可用、高性能、高灵活负载均衡集群技术实验

一、负载均衡与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.comapi.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

浏览器查看证书

相关推荐
SuperEugene2 小时前
前端-后端-产品-项目-运维:互联网项目协作全流程解析
运维·前端·javascript
武汉禹力自动化科技2 小时前
ABB火检与火焰检测系统全解析 | 禹力自动化科技有限公司
运维·科技·自动化·abb火检
ren049182 小时前
Linux基础
linux·运维·服务器
江畔何人初2 小时前
Gateway API 的核心组件与作用
运维·网络·云原生·kubernetes·gateway
Wyawsl2 小时前
Linux系统安全
linux·运维·系统安全
一只鹿鹿鹿2 小时前
研发中心数据安全管理规定(文件)
java·运维·开发语言·数据库·后端
青灯文案12 小时前
Linux 常用目录及其用途
linux·运维·服务器
芒果披萨2 小时前
Linux磁盘挂载
linux·运维·服务器
中科三方2 小时前
实操指南:网站更换服务器IP后,域名解析如何修改和验证?
运维·服务器·tcp/ip