在微服务架构和分布式系统中,负载均衡是实现高并发与高可用的核心组件。HAProxy作为一款轻量级七层代理,凭借其出色的性能和灵活性,成为系统架构师的首选工具之一。本文将通过实战实验,带你深入理解HAProxy的核心特性与配置技巧。

一、环境搭建与基础配置

在开始实验前,我们需要准备三台主机:一台作为HAProxy代理服务器,另外两台作为后端Web服务器(WebServer1和WebServer2)。所有主机需配置在同一网段,确保网络互通。以下是IP地址规划:

在后端服务器上安装httpd服务用于测试:

[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
[root@webserver2 ~] dnf install httpd -y
[root@webserver2 ~]  echo webserver2 - 192.168.0.20 > /var/www/html/index.html
[root@webserver2 ~] systemctl enable --now httpd

验证环境连通性:

二、HAProxy安装与核心参数实验

2.1 安装与基础负载均衡

使用包管理器安装HAProxy:

[root@norouter ~] dnf install haproxy.x86_64 -y
[root@norouter ~] systemctl enable --now haproxy

实现最基本的负载均衡配置:

[root@norouter ~]# vim /etc/haproxy/haproxy.cfg
该文件中有:
    global:全局参数,在最顶部
    defaults:默认参数,在 global 之后
    frontend:定义客户端入口,在 defaults 之后
    backend:定义后端服务器池,在 frontend 之后(或同级)
在文件中写入以下内容:
frontend webcluster
    bind            *:80
    mode            http
    use_backend     webserver-80
#bind *:80:监听所有网卡的 80 端口,接收客户端请求。
#mode http:工作在 HTTP 模式,支持对 HTTP 报文进行处理。
#use_backend webserver-80:将所有请求转发到名为 webserver-80 的后端服务器组
backend webserver-80
    server web1 192.168.0.10:80 check inter 3s fall 3 rise 5
    server web2 192.168.0.20:80 check inter 3s fall 3 rise 5
#定义了两个后端服务器:
#web1:IP 地址为 192.168.0.10,端口 80。
#web2:IP 地址为 192.168.0.20,端口 80。
#check inter 3s fall 3 rise 5:启用健康检查,每 3 秒检查一次;连续 3 次失败则标记为宕机,连续 5 次成功则恢复服务。

修改主配置文件 /etc/haproxy/haproxy.cfg

重启服务后测试负载效果:

2.2 日志发送配置

日志集中管理是高可用架构中的重要环节。将日志发送到指定服务器(如192.168.0.10):

[root@webserver1 ~]  vim /etc/rsyslog.conf
在文件的31,32行去掉 #
[root@webserver1 ~] systemctl restart rsyslog.service

验证日志端口是否开启:

在HAProxy主机配置日志发送:

[root@norouter ~] vim /etc/haproxy/haproxy.cfg
[root@norouter ~] systemctl restart haproxy.service

在WebServer1上查看日志:

2.3 多进程与多线程优化

为应对高并发场景,HAProxy支持多进程和多线程模式,但两者不可同时启用。

多进程配置:

[root@norouter ~] vim /etc/haproxy/haproxy.cfg
写在global段中:
nbproc      2
[root@norouter ~] systemctl restart haproxy.service

验证多进程效果:

绑定CPU核心以提升性能:

[root@norouter ~] vim /etc/haproxy/haproxy.cfg
    nbproc      2
    cpu-map     1 0
    cpu-map     2 1
[root@norouter ~] systemctl restart haproxy.service

为不同进程分配独立套接字:

多线程配置:

[root@norouter ~] vim /etc/haproxy/haproxy.cfg
nbthread    2
[root@norouter ~] systemctl restart haproxy.service

测试效果:

三、socat热更新与动态管理

⚠️ 热更新能力是分布式系统中服务不中断的关键。socat工具允许在不重启HAProxy的情况下动态调整配置。

3.1 安装socat

[root@haproxy ~]# dnf install socat -y
[root@haproxy ~]# socat  -h

3.2 查看与修改HAProxy状态

通过socat查看运行时信息:

动态修改后端服务器权重:

为socket设置访问授权:

注意:socat修改是临时生效,重启后丢失:

四、负载均衡算法深度实验

HAProxy支持静态算法动态算法混合算法三类,理解其差异对系统架构设计至关重要。

4.1 静态算法

static-rr:基于权重的轮询,不支持运行时调整权重(只接受0或1)。

[root@haproxy ~] vim /etc/haproxy/haproxy.cfg
listen webcluster
    bind        *:80
    balance     static-rr
    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.service

测试效果:

0%100%

first:按服务器列表顺序调度,连接数达上限后才切换。

[root@haproxy ~] vim /etc/haproxy/haproxy.cfg
listen webcluster
    bind        *:80
    balance     first
    server haha 192.168.0.10:80 maxconn 1 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.service

持续访问测试:

4.2 动态算法

roundrobin:默认算法,支持权重动态调整和慢启动,最多支持4095台后端。

[root@haproxy ~] vim /etc/haproxy/haproxy.cfg
listen webcluster
    bind        *:80
    balance     roundrobin
    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.service

测试与动态权重更新:

leastconn:根据当前连接数最少优先调度,适合长连接场景(如MySQL)。

[root@haproxy ~] vim /etc/haproxy/haproxy.cfg
listen webcluster
    bind        *:80
    balance     leastconn
    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.service

4.3 混合算法

source:基于源IP地址hash,实现会话保持。

[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 2
    server hehe 192.168.0.20:80 check inter 3s fall 3 rise 5 weight 1
[root@haproxy ~] systemctl restart haproxy.service

动态模式配置:

listen webcluster
    bind        *:80
    balance     source
    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

测试:

uri:对URI进行hash,适用于缓存服务器场景。

[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
[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 2
    server hehe 192.168.0.20:80 check inter 3s fall 3 rise 5 weight 1
[root@haproxy ~] systemctl restart haproxy.service

测试:

url_param:对URL参数hash,常用于电商追踪用户。

[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
[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.service

测试:

hdr:基于HTTP头部信息hash。

[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 2
    server hehe 192.168.0.20:80 check inter 3s fall 3 rise 5 weight 1
[root@haproxy ~] systemctl restart haproxy.service

测试:

算法总结:

#静态
static-rr--------->tcp/http
first------------->tcp/http
#动态
roundrobin-------->tcp/http
leastconn--------->tcp/http
random------------>tcp/http
#以下静态和动态取决于hash_type是否consistent
source------------>tcp/http
Uri--------------->http
url_param--------->http
hdr--------------->http

五、会话保持与状态监控

5.1 基于Cookie的会话保持

通过Cookie实现浏览器级别的会话保持,确保同一浏览器访问同一后端:

[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 2
    server hehe 192.168.0.20:80 cookie web2 check inter 3s fall 3 rise 5 weight 1
[root@haproxy ~] systemctl restart haproxy.service

5.2 HAProxy状态页

配置状态页以实时监控后端服务器健康状态:

[root@haproxy ~] vim /etc/haproxy/haproxy.cfg
listen stats
    mode        http
    bind 0.0.0.0:4321
    stats       enable
    log         global
#   stats       refresh
    stats uri   /status
    stats auth  lee:lee
[root@haproxy ~] systemctl restart haproxy.service

测试访问:

开启自动刷新:

[root@haproxy ~] vim /etc/haproxy/haproxy.cfg
listen stats
    mode        http
    bind 0.0.0.0:4321
    stats       enable
    log         global
    stats       refresh   1
    stats uri   /status
    stats auth  lee:lee
[root@haproxy ~] systemctl restart haproxy.service

六、IP透传与四层负载

6.1 七层IP透传

IP透传让后端服务器获取客户端真实IP,对日志审计和安全策略至关重要。

[root@haproxy ~] vim /etc/haproxy/haproxy.cfg
listen webcluster
    bind        *:80
    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.service

测试环境:

默认未开启透传:

[root@webserver2 ~] cat /etc/httpd/logs/access_log
192.168.0.100 - - [19/Feb/2026:19:13:04 +0800] "GET / HTTP/1.1" 200 26 "-" "hao"
192.168.0.100 - - [19/Feb/2026:19:28:24 +0800] "GET / HTTP/1.1" 200 26 "-" "curl/7.76.1"
192.168.0.100 - - [19/Feb/2026:19:43:22 +0800] "GET / HTTP/1.1" 200 26 "-" "curl/7.76.1"
192.168.0.100 - - [19/Feb/2026:19:43:22 +0800] "GET / HTTP/1.1" 200 26 "-" "curl/7.76.1"

开启透传:

[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

配置后端采集透传IP:

[root@webserver2 ~]  vim /etc/httpd/conf/httpd.conf
  LogFormat "%h %l %u %t \"%r\" %>s %b \"%{X-Forwarded-For}i\" \"%{Referer}i\" \"%{User-Agent}i    \"" combined
[root@webserver2 ~] systemctl restart httpd

测试效果:

[root@webserver2 ~] cat /etc/httpd/logs/access_log
92.168.0.100 - - [19/Feb/2026:19:59:30 +0800] "GET / HTTP/1.1" 200 26 "192.168.0.1" "-" "curl/8.4.0    "
192.168.0.100 - - [19/Feb/2026:19:59:32 +0800] "GET / HTTP/1.1" 200 26 "192.168.0.1" "-" "curl/8.4.0    "

6.2 四层IP透传

#在RS中把apache停止
[root@webserver1 ~] systemctl disable --now httpd
[root@webserver2 ~] systemctl disable --now httpd
#部署nginx
[root@webserver1 ~] dnf install nginx -y
[root@webserver2 ~] dnf install nginx -y
[root@webserver1 ~] echo RS1 - 192.168.0.10 > /usr/share/nginx/html/index.html
[root@webserver2 ~] echo RS2 - 192.168.0.20 > /usr/share/nginx/html/index.html
[root@webserver1 ~] systemctl enable --now nginx
[root@webserver2 ~] systemctl enable --now nginx

测试:

启用nginx四层访问控制:

[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 {
        }
[root@webserver1 ~] systemctl restart nginx.service
[root@webserver2 ~] 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 {
        }
[root@webserver2 ~] systemctl restart nginx.service

测试:

配置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

测试四层访问:

设置四层IP透传:

[root@webserver1&2 ~] 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&2 ~] systemctl restart nginx.service

测试:

[root@webserver1 ~] cat /var/log/nginx/access.log
192.168.0.100 - - [19/Feb/2026:20:12:41 +0800] "GET / HTTP/1.1" "172.25.254.100"200 19 "-" "curl/7.76.1" "-"
192.168.0.100 - - [19/Feb/2026:20:12:41 +0800] "GET / HTTP/1.1" "172.25.254.100"200 19 "-" "curl/7.76.1" "-"

6.3 HAProxy四层负载

[root@webserver1+2 ~] dnf install mariadb-server mariadb  -y
[root@webserver1+1 ~] vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server_id=10			#设定数据库所在主机的id标识,在20上设定id为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@webserver2+1 ~] systemctl start mariadb
[root@webserver2+1 ~] mysql
MariaDB [(none)]>  CREATE USER 'lee'@'%' identified by 'lee';
Query OK, 0 rows affected (0.001 sec)
MariaDB [(none)]> GRANT ALL ON *.* TO 'lee'@'%';
Query OK, 0 rows affected (0.000 sec)

测试:

四层负载操作:

[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.service

测试:

backup参数配置:

[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 backup
[root@haproxy ~] systemctl restart haproxy.service

测试:

关闭主节点测试故障转移:

恢复后自动切换:

七、自定义错误页面与ACL访问控制

7.1 Sorry Server与自定义错误页

⚠️ 当所有后端宕机时,配置Sorry Server提供友好提示:

#在新主机中安装apache(可以用haproxy主机代替)
[root@haproxy ~] dnf install httpd -y
[root@haproxy ~] vim /etc/httpd/conf/httpd.conf
第47行:
Listen 8080
[root@haproxy ~]# systemctl enable --now httpd
Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service.
[root@haproxy ~]# echo "11111111111" > /var/www/html/index.html
#配置sorryserver上线
[root@haproxy ~] vim /etc/haproxy/haproxy.cfg
listen webcluster
    bind        *:80
    mode        tcp
    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 192.168.0.100:8080  backup					#sorryserver
[root@haproxy ~] systemctl restart haproxy.service

测试:

关闭所有业务主机:

自定义错误页面:

# 修改为http
[root@norouter ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
    bind        *:80
    mode        http
    option       httplog
    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@webserver1+2 ~]# systemctl stop httpd
[root@haproxy ~]# systemctl stop httpd
#所有后端web服务都宕机
[Administrator.DESKTOP-VJ307M3] ➤ curl 172.25.254.100

503 Service Unavailable

No server is available to handle this request.

创建错误文件并配置:

测试:

7.2 ACL访问控制

配置DNS解析:

基础配置:

[root@haproxy ~] vim /etc/haproxy/haproxy.cfg
[root@haproxy ~] systemctl restart haproxy.service

基础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列表访问不匹配
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.service

测试:

基于头部信息ACL:

base参数ACL:

测试:

黑名单配置:

测试:

白名单配置:

测试:

八、全站加密实战

为保障数据传输安全,HAProxy支持SSL/TLS全站加密。

8.1 制作证书

[root@haproxy ~] mkdir /etc/haproxy/certs/
[root@haproxy ~] openssl req -newkey rsa:2048 -nodes -sha256  -keyout /etc/haproxy/certs/timinglee.org.key -x509 -days 365 -out /etc/haproxy/certs/timinglee.org.crt
[root@haproxy ~] ls /etc/haproxy/certs/
timinglee.org.crt  timinglee.org.key
[root@haproxy ~] cat /etc/haproxy/certs/timinglee.org.{key,crt} > /etc/haproxy/certs/timinglee.pem

8.2 配置全站加密

测试:

[AFFILIATE_SLOT_1]

总结

本文从零开始搭建HAProxy七层代理环境,覆盖了基础负载均衡、多进程多线程优化、socat热更新、多种算法实验、会话保持、IP透传、四层负载、自定义错误页面、ACL访问控制及全站加密等核心功能。掌握这些技能,你将能够在微服务架构分布式系统中灵活运用HAProxy,构建高并发高可用系统架构

[AFFILIATE_SLOT_2]