一、HAProxy 核心理论

1 HAProxy 简介

HAProxy(全称 High Availability Proxy,高可用代理)是一款开源、高性能的负载均衡与反向代理软件,由法国开发者 Willy Tarreau 于 2000 年使用 C 语言开发,专为高可用、高并发的网络服务架构设计。它是目前业界最主流的开源负载均衡器之一,支撑大量高流量网站与服务。

社区版官网:

2 核心功能

功能说明
负载均衡将大量并发请求智能分发到多台后端服务器,提升吞吐量与资源利用率
反向代理作为客户端与服务端中间层,隐藏后端真实 IP,提供统一入口
高可用通过健康检查实时监控后端状态,自动隔离故障节点,保证服务可用
流量控制支持请求限速、连接数限制,防止后端服务过载
协议代理同时支持 四层(TCP)七层(HTTP/HTTPS) 代理,适用场景广
安全防护提供 ACL 访问控制、IP 过滤、HTTP 头部清洗等安全能力

3 负载均衡与工作模式

3.1 负载均衡定义

负载均衡是将海量并发请求/流量,按策略均匀、智能地分发到多台后端服务器的技术,是分布式架构的核心能力。

3.2 四层 / 七层代理模式

HAProxy 最核心的特点是同时支持四层和七层代理

  • 四层(TCP)代理

工作在 OSI 传输层,基于 IP + 端口 转发流量,不解析应用层内容

适合 MySQL、Redis、邮件、游戏等非 HTTP 服务,转发快、损耗低

  • 七层(HTTP/HTTPS)代理

工作在 OSI 应用层,能完整解析 HTTP 协议,可根据 URL、路径、Cookie、请求头做智能路由。

适合 Web 服务、API 网关,支持会话保持、SSL 卸载、灰度转发等高级功能。

3.3 常见负载均衡软件对比

  • 四层(TCP)负载均衡

    • LVS:内核级、性能极强的重量级四层负载均衡

    • Nginx:轻量级四层负载(基于 upstream 模块)

    • HAProxy:高性能、通用型 TCP 代理

  • 七层(HTTP)负载均衡

    • Nginx:Web 服务器 + 七层代理(基于 proxy_pass)

    • HAProxy:专注负载均衡,会话保持、健康检查、流量调度更强大

4 工作流程

  1. 客户端请求发送到 HAProxy

  2. HAProxy 根据负载均衡算法选择一台健康的后端服务器

  3. 与后端建立连接并转发请求

  4. 接收后端响应并返回给客户端

  5. 持续健康检查,动态维护可用节点列表

二、HAProxy基础与进阶实验

笔记时间:2026-1-23

1 前置环境搭建

1.1 实验环境图

1.2 环境搭建

  • haproxy主机

    1
    2
    3
    4
    5
    6
    [root@haproxy ~]# vmset.sh haproxy eth0 172.25.254.100
    [root@haproxy ~]# vmset.sh haproxy eth1 192.168.0.100 nogateway

    [root@haproxy ~]# echo net.ipv4.ip_forward=1 > /etc/sysctl.conf
    [root@haproxy ~]# sysctl -p
    net.ipv4.ip_forward = 1
  • webserver1

    1
    2
    3
    4
    5
    [root@webserver1 ~]# vmset.sh webserver1 eth0 192.168.0.10 nogateway
    [root@webserver1 ~]# dnf install httpd -y
    [root@webserver1 ~]# echo webserver1 - 192.168.0.10 > /var/www/html/index.html
    [root@webserver1 ~]# systemctl enable --now httpd
    Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service.
  • webserver2

    1
    2
    3
    4
    [root@webserver2 ~]# vmset.sh webserver2 eth0 192.168.0.20 nogateway
    [root@webserver2 ~]# echo webserver2 - 192.168.0.20 > /var/www/html/index.html
    [root@webserver2 ~]# systemctl enable --now httpd
    Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service.

1.3 环境验证

1
2
3
4
[root@haproxy ~]# curl  192.168.0.10
webserver1 - 192.168.0.10
[root@haproxy ~]# curl 192.168.0.20
webserver2 - 192.168.0.20

2 安装及配置

2.1 安装

1
2
3
4
#在调度器(双网卡主机中)
[root@haproxy ~]# dnf install haproxy.x86_64 -y
[root@haproxy ~]# systemctl enable --now haproxy
Created symlink /etc/systemd/system/multi-user.target.wants/haproxy.service → /usr/lib/systemd/system/haproxy.service.

2.2 参数详解

3 基础核心实验

笔记时间:2026-1-25

3.1 负载均衡核心算法实验

(1) 静态算法

static-rr

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
balance static-rr
hash-type consistent
server haha 192.168.0.10:80 check inter 3s fall 3 rise 5 weight 4
server hehe 192.168.0.20:80 check inter 3s fall 3 rise 5 weight 1

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

[kaitumei.DESKTOP-BMTM34T] ⮞ for i in {1..10}; do curl 172.25.254.100; done
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20

#检测是否支持热更新
[root@haproxy ~]# echo "get weight webcluster/haha" | socat stdio /var/lib/haproxy/stats
4 (initial 4)

[root@haproxy ~]# echo "set weight webcluster/haha 1" | socat stdio /var/lib/haproxy/stats
Backend is using a static LB algorithm and only accepts weights '0%' and '100%'.

first

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
balance first
hash-type consistent
server haha 192.168.0.10:80 maxconn 1 check inter 3s fall 3 rise 5 weight 4
server hehe 192.168.0.20:80 check inter 3s fall 3 rise 5 weight 1

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


[kaitumei.DESKTOP-BMTM34T] ⮞ while true; do curl 172.25.254.100; done
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10

# 再开一个终端
[kaitumei.DESKTOP-BMTM34T] ⮞ while true; do curl 172.25.254.100; done
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20

(2) 动态算法

roundrobin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
balance roundrobin
hash-type consistent
server haha 192.168.0.10:80 check inter 3s fall 3 rise 5 weight 4
server hehe 192.168.0.20:80 check inter 3s fall 3 rise 5 weight 1

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

[kaitumei.DESKTOP-BMTM34T] ⮞ for i in {1..10}; do curl 172.25.254.100; done
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20

# 动态权重更新
[root@haproxy ~]# echo "get weight webcluster/haha" | socat stdio /var/lib/haproxy/stats
4 (initial 4)

[root@haproxy ~]# echo "set weight webcluster/haha 1 " | socat stdio /var/lib/haproxy/stats
[root@haproxy ~]# echo "get weight webcluster/haha" | socat stdio /var/lib/haproxy/stats
1 (initial 4)

# 效果
[kaitumei.DESKTOP-BMTM34T] ⮞ for i in {1..10}; do curl 172.25.254.100; done
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20

leastconn

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
balance leastconn
hash-type consistent
server haha 192.168.0.10:80 check inter 3s fall 3 rise 5 weight 4
server hehe 192.168.0.20:80 check inter 3s fall 3 rise 5 weight 1

[root@haproxy ~]# systemctl restart haproxy

[kaitumei.DESKTOP-BMTM34T] ⮞ for i in {1..10}; do curl 172.25.254.100; done
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20

(3) 混合算法

source

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# 默认静态算法
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
balance source
server haha 192.168.0.10:80 check inter 3s fall 3 rise 5 weight 4
server hehe 192.168.0.20:80 check inter 3s fall 3 rise 5 weight 1

[root@haproxy ~]# systemctl restart haproxy

[kaitumei.DESKTOP-BMTM34T] ⮞ for i in {1..10}; do curl 172.25.254.100; done
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10


# 动态算法
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
balance source
hash-type consistent
server haha 192.168.0.10:80 check inter 3s fall 3 rise 5 weight 4
server hehe 192.168.0.20:80 check inter 3s fall 3 rise 5 weight 1

[root@haproxy ~]# systemctl restart haproxy

[kaitumei.DESKTOP-BMTM34T] ⮞ for i in {1..10}; do curl 172.25.254.100; done
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20

uri

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#主备实验环境
[root@webserver1 ~]# echo RS1 - 192.168.0.10 > /var/www/html/index1.html
[root@webserver1 ~]# echo RS1 - 192.168.0.10 > /var/www/html/index2.html
[root@webserver2 ~]# echo RS2 - 192.168.0.20 > /var/www/html/index1.html
[root@webserver2 ~]# echo RS2 - 192.168.0.20 > /var/www/html/index2.html


#设定uri算法
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
balance uri
hash-type consistent
server haha 192.168.0.10:80 check inter 3s fall 3 rise 5 weight 4
server hehe 192.168.0.20:80 check inter 3s fall 3 rise 5 weight 1

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

[kaitumei.DESKTOP-BMTM34T] ⮞ for i in {1..10}; do curl 172.25.254.100/index1.html; done
RS1 - 192.168.0.10
RS1 - 192.168.0.10
RS1 - 192.168.0.10
RS1 - 192.168.0.10
RS1 - 192.168.0.10
RS1 - 192.168.0.10
RS1 - 192.168.0.10
RS1 - 192.168.0.10
RS1 - 192.168.0.10
RS1 - 192.168.0.10

[kaitumei.DESKTOP-BMTM34T] ⮞ for i in {1..10}; do curl 172.25.254.100/index2.html; done
RS2 - 192.168.0.20
RS2 - 192.168.0.20
RS2 - 192.168.0.20
RS2 - 192.168.0.20
RS2 - 192.168.0.20
RS2 - 192.168.0.20
RS2 - 192.168.0.20
RS2 - 192.168.0.20
RS2 - 192.168.0.20
RS2 - 192.168.0.20

url_param

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 设定url_param算法
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
balance url_param name
hash-type consistent
server haha 192.168.0.10:80 check inter 3s fall 3 rise 5 weight 2
server hehe 192.168.0.20:80 check inter 3s fall 3 rise 5 weight 1

[root@haproxy ~]# systemctl restart haproxy

[kaitumei.DESKTOP-BMTM34T] ⮞ for i in {1..10}; do curl 172.25.254.100/index.html?name=hua; done
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20
webserver2 - 192.168.0.20

[kaitumei.DESKTOP-BMTM34T] ⮞ for i in {1..10}; do curl 172.25.254.100/index.html?name=huaaaaa; done
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10
webserver1 - 192.168.0.10

hdr

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
balance hdr(User-Agent)
hash-type consistent
server haha 192.168.0.10:80 check inter 3s fall 3 rise 5 weight 4
server hehe 192.168.0.20:80 check inter 3s fall 3 rise 5 weight 1

[root@haproxy ~]# systemctl restart haproxy

[kaitumei.DESKTOP-BMTM34T] ⮞ curl -A "hua" 172.25.254.100
webserver2 - 192.168.0.20

[kaitumei.DESKTOP-BMTM34T] ⮞ curl -A "Yeming" 172.25.254.100
webserver1 - 192.168.0.10

3.2 基于cookie的会话保持

1
2
3
4
5
6
7
8
9
10
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
balance roundrobin
hash-type consistent
cookie WEBCOOKIE insert nocache indirect
server haha 192.168.0.10:80 cookie web1 check inter 3s fall 3 rise 5 weight 4
server hehe 192.168.0.20:80 cookie web2 check inter 3s fall 3 rise 5 weight 1

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

3.3 HAProxy状态页

1
2
3
4
5
6
7
8
9
10
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen stats
mode http
bind 0.0.0.0:1234
stats enable
log global
# stats refresh
stats uri /status
stats auth hua:hua
[root@haproxy ~]# systemctl restart haproxy.service

4 进阶功能实验

笔记时间:2026-01-26

4.1 客户端IP透传配置

(1) 七层(HTTP) IP透传

环境搭建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Haproxy中
[root@Haproxy ~]# dnf install haproxy -y
[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
blance roundrobin
server haha 192.168.0.10:80 check inter 3s fall 3 rise 5 weight 1
server haha 192.168.0.20:80 check inter 3s fall 3 rise 5 weight 1

[root@Haproxy ~]# systemctl restart haproxy

# Webserver1与Webserver2中
## webserver1
[root@Webserver1 ~]# dnf install httpd -y --disablerepo=docker,epel
[root@Webserver1 ~]# echo "webserver1 --- 192.168.0.10" > /var/www/html/index.html
[root@Webserver1 ~]# systemctl restart httpd
## webserver2
[root@Webserver1 ~]# dnf install httpd -y --disablerepo=docker,epel
[root@Webserver1 ~]# echo "webserver2 --- 192.168.0.20" > /var/www/html/index.html
[root@Webserver1 ~]# systemctl restart httpd

测试环境

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# client中
[root@Client ~]# for i in {1..5};do curl 172.25.254.100;done
webserver1 --- 192.168.0.10
webserver2 --- 192.168.0.20
webserver1 --- 192.168.0.10
webserver2 --- 192.168.0.20
webserver1 --- 192.168.0.10



# 在rs主机中默认是未开启透传功能的
## webserver1 or 2中
[[root@Webserver1 ~]# cat /etc/httpd/logs/access_log
192.168.0.20 - - [27/Jan/2026:15:45:38 +0800] "GET / HTTP/1.1" 200 28 "-" "curl/7.76.1"
192.168.0.100 - - [27/Jan/2026:15:46:12 +0800] "GET / HTTP/1.1" 200 28 "-" "curl/7.76.1"


# 开启ip透传的方式
## haproxy中
[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8 #开启haproxy透传功能
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000


# 在rs中设定采集透传IP
## webserver1 or 2中
[root@Webserver1 ~]# vim /etc/httpd/conf/httpd.conf
201 LogFormat "%h %l %u %t \"%r\" %>s %b \"%{X-Forwarded-For}i\" \"%{Referer }i\" \"%{User-Agent}i\"" combined

[root@Webserver1 ~]# systemctl restart httpd

测试效果

1
2
3
4
5
6
7
# client中
[root@Client ~]# for i in {1..5};do curl 172.25.254.100;done

# webserver1 or 2中
[root@Webserver1 ~]# cat /etc/httpd/logs/access_log
192.168.0.100 - - [27/Jan/2026:15:55:39 +0800] "GET / HTTP/1.1" 200 28 "172.25.254.99" "-" "curl/7.76.1"
192.168.0.100 - - [27/Jan/2026:15:55:39 +0800] "GET / HTTP/1.1" 200 28 "172.25.254.99" "-" "curl/7.76.1"

(2) 四层(TCP)IP透传

环境搭建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 在RS中把apache停止
[root@Webserver1 ~]# systemctl disable --now httpd
[root@Webserver2 ~]# systemctl disable --now httpd

# 部署nginx
# webserver1
[root@Webserver1 ~]# dnf install nginx -y --disablerepo=docker,epel
[root@Webserver1 ~]# echo webserver1 - 192.168.0.10 > /usr/share/nginx/html/index.html
[root@Webserver1 ~]# systemctl enable --now nginx
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
# webserver2
[root@Webserver2 ~]# dnf install nginx -y --disablerepo=docker,epel
[root@Webserver2 ~]# echo webserver2 - 192.168.0.20 > /usr/share/nginx/html/index.html
[root@Webserver2 ~]# systemctl enable --now nginx
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.

测试环境

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# 启用nginx的四层访问控制
# webserver1 and 2
[root@webserver1 ~]# vim /etc/nginx/nginx.conf
server {
listen 80 proxy_protocol; # 启用四层访问
listen [::]:80;
server_name _;
root /usr/share/nginx/html;

# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;

error_page 404 /404.html;
location = /404.html {
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}

[root@Webserver1 ~]# systemctl restart nginx.service
[root@Webserver2 ~]# systemctl restart nginx.service

## client
[root@Client ~]# for i in {1..5}; do curl 172.25.254.100; done
<html><body><h1>502 Bad Gateway</h1>
The server returned an invalid or incomplete response.
</body></html>
<html><body><h1>502 Bad Gateway</h1>
The server returned an invalid or incomplete response.
</body></html>
<html><body><h1>502 Bad Gateway</h1>
The server returned an invalid or incomplete response.
</body></html>
<html><body><h1>502 Bad Gateway</h1>
The server returned an invalid or incomplete response.
</body></html>
<html><body><h1>502 Bad Gateway</h1>
The server returned an invalid or incomplete response.
</body></html>


# 出现上述报错标识nginx只支持四层访问

# 1.设定haproxy访问4层
## haproxy
[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
mode tcp # 开启四层访问
balance roundrobin
server haha 192.168.0.10:80 send-proxy check inter 3s fall 3 rise 5 weight 1
server hehe 192.168.0.20:80 send-proxy check inter 3s fall 3 rise 5 weight 1


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


# 2.设置4层ip透传
# Webserver1 and 2
[root@Webserver1 ~]# vim /etc/nginx/nginx.conf
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"';


[root@Webserver1 ~]# systemctl restart nginx.service

测试效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# client
[root@Client ~]# for i in {1..5}; do curl 172.25.254.100; done
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10
webserver2 - 192.168.0.20
webserver1 - 192.168.0.10


# webserver1 and 2
[root@Webserver1 ~]# cat /var/log/nginx/access.log
192.168.0.100 - - [27/Jan/2026:16:33:22 +0800] "GET / HTTP/1.1" "172.25.254.99" 200 26 "-" "curl/7.76.1" "-"
192.168.0.100 - - [27/Jan/2026:16:33:22 +0800] "GET / HTTP/1.1" "172.25.254.99" 200 26 "-" "curl/7.76.1" "-"
192.168.0.100 - - [27/Jan/2026:16:33:22 +0800] "GET / HTTP/1.1" "172.25.254.99" 200 26 "-" "curl/7.76.1" "-"

4.2 四层TCP负载均衡配置

环境搭建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# 部署mariadb数据库
# webserver1 and 2
[root@Webserver1 ~]# dnf install mariadb-server mariadb -y --disablerepo=docker,epel
[root@Webserver1 ~]# vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server_id=10 # webserver2中20
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mariadb/mariadb.log
pid-file=/run/mariadb/mariadb.pid

[root@Webserver1 ~]# systemctl restart mariadb

# 建立远程登录用户并授权
[root@Webserver1 ~]# mysql
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 5
Server version: 10.5.27-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> CREATE USER 'hua'@'%' identified by 'hua';
Query OK, 0 rows affected (0.001 sec)

MariaDB [(none)]> GRANT ALL ON *.* TO 'hua'@'%';
Query OK, 0 rows affected (0.001 sec)

MariaDB [(none)]> quit
Bye

[root@Webserver1 ~]# systemctl restart mariadb

# haproxy
[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen mariadbcluster
bind *:6663
mode tcp
balance roundrobin
server haha 192.168.0.10:3306 check inter 3s fall 3 rise 5 weight 1
server hehe 192.168.0.20:3306 check inter 3s fall 3 rise 5 weight 1

[root@Haproxy ~]# systemctl restart haproxy


[root@Haproxy ~]# netstat -antlupe | grep haproxy
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 0 49468 2525/haproxy
tcp 0 0 0.0.0.0:6663 0.0.0.0:* LISTEN 0 49469 2525/haproxy

环境测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# client
[root@Client ~]# mysql -uhua -phua -h172.25.254.100 -P 6663
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 6
Server version: 10.5.27-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> SELECT @@server_id;
+-------------+
| @@server_id |
+-------------+
| 20 |
+-------------+
1 row in set (0.001 sec)

MariaDB [(none)]> quit
Bye
[root@Client ~]# mysql -uhua -phua -h172.25.254.100 -P 6663
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 6
Server version: 10.5.27-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> SELECT @@server_id;
+-------------+
| @@server_id |
+-------------+
| 10 |
+-------------+
1 row in set (0.001 sec)

MariaDB [(none)]> quit
Bye

4.3 异常请求与错误页自定义

sorryserver的设定

正常的所有服务器如果出现宕机,那么客户将被定向到指定的主机中,这个当业务主机出问题时被临时访问的主机叫做 sorryserver

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 在新主机中安装apache(可以用haproxy主机代替)
# client
[root@Client ~]# dnf install httpd -y
[root@Client ~]# vim /etc/httpd/conf/httpd.conf
47 Listen 8080
[root@Client ~]# systemctl enable --now httpd
Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service.

[root@Client ~]# echo "哈哈哈" > /var/www/html/index.html


# 配置sorryserver上线
[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg
bind *:80
mode tcp
balance roundrobin
server haha 192.168.0.10:80 send-proxy check inter 3s fall 3 rise 5 weight 1
server hehe 192.168.0.20:80 send-proxy check inter 3s fall 3 rise 5 weight 1
server wuwu 172.25.254.99:8080 backup #sorryserver

[root@Haproxy ~]# systemctl restart haproxy

# 测试
# client
[root@Client ~]# curl 172.25.254.100
webserver1 - 192.168.0.10
[root@Client ~]# curl 172.25.254.100
webserver2 - 192.168.0.20

#关闭两台正常的业务主机
# webserver1 and 2
[root@Webserver1 ~]# systemctl stop httpd
[root@Webserver2 ~]# systemctl stop httpd

# client
[root@Client ~]# curl 172.25.254.100
哈哈哈

(1) 自定义错误页面

当所有主机包括sorryserver都宕机了,那么haproxy会提供一个默认访问的错误页面,这个错误页面跟报错代码有关,这个页面可以通过定义来机型设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# 出现的错误页面
[root@Webserver1 ~]# systemctl stop httpd
[root@Webserver2 ~]# systemctl stop httpd
[root@Client ~]# systemctl stop httpd

# 所有后端web服务都宕机
[Administrator.DESKTOP-VJ307M3] ➤ curl 172.25.254.100
<html><body><h1>503 Service Unavailable</h1>
No server is available to handle this request.
</body></html>


[root@haproxy ~]# mkdir /errorpage/html/ -p
[root@haproxy ~]# vim /errorpage/html/503.http
HTTP/1.0 503 Service Unavailable
Cache-Control: no-cache
Connection: close
Content-Type: text/html;charset=UTF-8

<html><body><h1>什么动物生气最安静</h1>
大猩猩!!
</body></html>
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
errorfile 503 /errorpage/html/503.http #error 页面

listen webcluster
bind *:80
mode http
balance roundrobin
server haha 192.168.0.10:80 check inter 3s fall 3 rise 5 weight 1
server hehe 192.168.0.20:80 check inter 3s fall 3 rise 5 weight 1
server wuwu 172.25.254.99:8080 backup

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


#测试
[root@Client ~]# curl 172.25.254.100
<html><body><h1>什么动物生气最安静</h1>
大猩猩!!
</body></html>

(2) 重定向错误到指定网站

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
errorloc 503 http://www.baidu.com #error 页面
[root@haproxy ~]# systemctl restart haproxy.service

#在浏览器中访问

4.4 ACL访问控制规则配置

(1) 实验素材

1
2
3
4
5
6
7
8
# 在浏览器或者curl主机中设定本地解析
以管理员身份打开 C:\Windows\System32\drivers\etc\hosts
172.25.254.100 www.kaitumei.com bbs.kaitumei.com news.kaitumei.com login.kaitumei.com
# #在Linux中设定解析
vim /etc/hosts
172.25.254.100 www.kaitumei.com bbs.kaitumei.com news.kaitumei.com login.kaitumei.com
#测试
ping bbs.timinglee.org

(2) 设定基础的haproxy实验配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webcluster
bind *:80
mode http
use_backend webserver-80-web1

backend webserver-80-web1
server web1 192.168.0.10:80 check inter 3s fall 3 rise 5

backend webserver-80-web2
server web2 192.168.0.20:80 check inter 3s fall 3 rise 5


[root@Haproxy ~]# systemctl restart haproxy

(3) 基础acl示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#在访问的网址中,所有以.com  结尾的访问10,其他访问20
[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webcluster
bind *:80
mode http

acl test hdr_end(host) -i .com #acl列表

use_backend webserver-80-web1 if test #acl列表访问匹配
default_backend webserver-80-web2 #acl列表访问不匹配

backend webserver-80-web1
server web1 192.168.0.10:80 check inter 3s fall 3 rise 5

backend webserver-80-web2
server web2 192.168.0.20:80 check inter 3s fall 3 rise 5

[root@Haproxy ~]# systemctl restart haproxy

#测试
[root@Client ~]# curl www.kaitumei.com
webserver1 --- 192.168.0.10
[root@Client ~]# curl www.kaitumei.org
webserver2 --- 192.168.0.20



#基于访问头部
[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webcluster
bind *:80
mode http
acl test hdr_end(host) -i .com #acl列表
acl head hdr_beg(host) -i bbs.

use_backend webserver-80-web1 if head #acl列表访问匹配
default_backend webserver-80-web2 #acl列表访问不匹配

backend webserver-80-web1
server web1 192.168.0.10:80 check inter 3s fall 3 rise 5

backend webserver-80-web2
server web2 192.168.0.20:80 check inter 3s fall 3 rise 5

[root@Haproxy ~]# systemctl restart haproxy

#测试效果
[root@Client ~]# curl bbs.kaitumei.com
webserver1 --- 192.168.0.10
[root@Client ~]# curl www.kaitumei.com
webserver2 --- 192.168.0.20


#base参数acl
[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webcluster
bind *:80
mode http

acl pathdir base_dir -i /yeming
use_backend webserver-80-web1 if pathdir
default_backend webserver-80-web2 #acl列表访问不匹配

backend webserver-80-web1
server web1 192.168.0.10:80 check inter 3s fall 3 rise 5

backend webserver-80-web2
server web2 192.168.0.20:80 check inter 3s fall 3 rise 5
[root@Haproxy ~]# systemctl restart haproxy

[root@Webserver1+2 ~]# mkdir -p /var/www/html/yeming/
[root@Webserver1+2 ~]# mkdir -p /var/www/html/yeming/test/


[root@Webserver1 ~]# echo yeming - 192.168.0.10 > /var/www/html/yeming/index.html
[root@Webserver1 ~]# echo yeming/test - 192.168.0.10 > /var/www/html/yeming/test/index.html
[root@Webserver2 ~]# echo yeming - 192.168.0.20 > /var/www/html/yeming/index.html
[root@Webserver2 ~]# echo yeming/test - 192.168.0.20 > /var/www/html/yeming/test/index.html


#测试
[root@Client ~]# curl 172.25.254.100/yeming/
yeming - 192.168.0.10
[root@Client ~]# curl 172.25.254.100/yeming/test/
yeming/test - 192.168.0.10
[root@Client ~]# curl 172.25.254.100/index.html
webserver2 --- 192.168.0.20



#acl禁止列表黑名单
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webcluster
bind *:80
mode http

acl test hdr_end(host) -i .com #acl列表

use_backend webserver-80-web1 if test #acl列表访问匹配
default_backend webserver-80-web2 #acl列表访问不匹配

acl invalid_src src 172.25.254.99
http-request deny if invalid_src

backend webserver-80-web1
server web1 192.168.0.10:80 check inter 3s fall 3 rise 5

backend webserver-80-web2
server web2 192.168.0.20:80 check inter 3s fall 3 rise 5

[root@Haproxy ~]# systemctl restart haproxy

#测试:
[root@Client ~]# curl 172.25.254.100
<html><body><h1>403 Forbidden</h1>
Request forbidden by administrative rules.
</body></html>



#禁止列表白名单
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webcluster
bind *:80
mode http
acl test hdr_end(host) -i .com #acl列表

use_backend webserver-80-web1 if test #acl列表访问匹配
default_backend webserver-80-web2 #acl列表访问不匹配

acl invalid_src src 172.25.254.99
http-request deny if ! invalid_src

backend webserver-80-web1
server web1 192.168.0.10:80 check inter 3s fall 3 rise 5

backend webserver-80-web2
server web2 192.168.0.20:80 check inter 3s fall 3 rise 5

#测试:
[root@Client ~]# curl 172.25.254.100
webserver2 --- 192.168.0.20

[root@Haproxy ~]# curl 172.25.254.100
<html><body><h1>403 Forbidden</h1>
Request forbidden by administrative rules.
</body></html>

Haproxy全站加密

制作证书

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@Haproxy ~]# mkdir /etc/haproxy/certs/
[[root@Haproxy ~]# openssl req -newkey rsa:2048 -nodes -sha256 -keyout /etc/haproxy/certs/yeming.key -x509 -days 365 -out /etc/haproxy/certs/yeming.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) []:Hunan
Locality Name (eg, city) [Default City]:Hengyang
Organization Name (eg, company) [Default Company Ltd]:hh
Organizational Unit Name (eg, section) []:hh
Common Name (eg, your name or your server's hostname) []:www.kaitumei.com
Email Address []:

[root@Haproxy ~]# ls /etc/haproxy/certs/
yeming.crt yeming.key
[root@Haproxy ~]# cat /etc/haproxy/certs/yeming.{key,crt} > /etc/haproxy/certs/yeming.pem

全站加密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
[root@Haproxy ~]# vim /etc/haproxy/haproxy.cfg 
frontend webcluster-http
bind *:80
redirect scheme https if ! { ssl_fc }

listen webcluster-https
bind *:443 ssl crt /etc/haproxy/certs/yeming.pem
mode http
balance roundrobin
server haha 192.168.0.10:80 check inter 3s fall 3 rise 5 weight 1
server hehe 192.168.0.20:80 check inter 3s fall 3 rise 5 weight 1

[root@Haproxy ~]# systemctl restart haproxy

#测试:
[root@Client ~]# curl -v -k -L http://172.25.254.100
* Trying 172.25.254.100:80...
* Connected to 172.25.254.100 (172.25.254.100) port 80 (#0)
> GET / HTTP/1.1
> Host: 172.25.254.100
> User-Agent: curl/7.76.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 302 Found
< content-length: 0
< location: https://172.25.254.100/
< cache-control: no-cache
<
* Connection #0 to host 172.25.254.100 left intact
* Clear auth, redirects to port from 80 to 443Issue another request to this URL: 'https://172.25.254.100/'
* Trying 172.25.254.100:443...
* Connected to 172.25.254.100 (172.25.254.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=Hunan; L=Hengyang; O=hh; OU=hh; CN=www.kaitumei.com
* start date: Jan 27 17:03:35 2026 GMT
* expire date: Jan 27 17:03:35 2027 GMT
* issuer: C=CN; ST=Hunan; L=Hengyang; O=hh; OU=hh; CN=www.kaitumei.com
* SSL certificate verify result: self-signed certificate (18), continuing anyway.
* TLSv1.2 (OUT), TLS header, Unknown (23):
> GET / HTTP/1.1
> Host: 172.25.254.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: Tue, 27 Jan 2026 17:09:23 GMT
< server: Apache/2.4.62 (Red Hat Enterprise Linux)
< last-modified: Tue, 27 Jan 2026 07:43:15 GMT
< etag: "1c-64959c6bf22d5"
< accept-ranges: bytes
< content-length: 28
< content-type: text/html; charset=UTF-8
<
webserver1 --- 192.168.0.10
* Connection #1 to host 172.25.254.100 left intact