解密负载均衡:如何轻松提升业务性能

Web服务器动态水平扩展 --> 对用户完全透明
提升业务并发处理能力 --> 有效解决单服务器性能瓶颈
优化公网IP资源 --> 显著降低IT运营成本
保护内部服务器IP --> 增强系统安全性
简易配置 --> 采用标准化配置文件格式
功能全面 --> 同时支持四层和七层协议,支持主机动态移除
高性能表现 --> 轻松应对数万至数十万并发请求
F5
- 美国F5网络公司官网:F5 | 多云安全和应用交付
Netscaler
- 美国思杰公司产品页面:NetScaler: Application Delivery at Scale
Array
- 华耀官网:北京华耀科技有限公司
AD-1000
- 深信服官网:深信服 - 让每个用户的数字化更简单、更安全


HAProxy是由法国开发者威利塔罗(Willy Tarreau)于2000年使用C语言开发的开源软件。
作为一款高性能负载均衡器,它支持TCP和HTTP协议,具备万级以上的高并发处理能力。主要特性包括:
- 基于cookie的会话保持
- 自动故障转移
- 正则表达式支持
- 实时Web状态统计
资源链接:
- 企业版官网:HAProxy Technologies | Powering the World's Busiest Applications
- 社区版官网:http://www.haproxy.org
- GitHub仓库:https://github.com/haprox

功能 | IP |
客户端 | 172.25.254.111 |
haproxy | 172.25.254.100;192.168.0.10 |
RS1 | 172.25.254.10 |
RS2 | 172.25.254.20 |
dnf install haproxy -y
haproxy -v
软件安装包: haproxy-2.4.22-3.el9_3.x86_64.rpm
启动文件: /lib/systemd/system/haproxy.service
主配置目录: /etc/haproxy/
主配置文件: /etc/haproxy/haproxy.cfg
子配置目录: /etc/haproxy/conf.d
vim /etc/haproxy/haproxy.cfg
# turn on stats unix socket
stats socket /var/lib/haproxy/haproxy.sock1 mode 600 level admin process 1
#启用多个sock文件
stats socket /var/lib/haproxy/haproxy.sock2 mode 600 level admin process 2
nbproc 2
#启用多进程
cpu-map 1 0
#进程和cpu核心绑定防止cpu抖动从而减少系统资源消耗
cpu-map 2 1
#2 表示第二个进程,1表示第二个cpu核心
systemctl start haproxy.service
pstree -p | grep haproxy
vim /etc/haproxy/haproxy.cfg
nbthread 2 #启用多线程
systemctl restart haproxy.service
查看:
systemctl restart haproxy.service
cat /proc/xxxx(haproxy子进程id)/status
defaults
mode http #HAProxy实例使用的连接协议
log global #指定日志地址和记录日志条目的
syslog/rsyslog日志设备
#此处的 global表示使用 global配置段中
设定的log值。
option httplog #日志记录选项,httplog表示记录与 HTTP
会话相关的各种属性值
#包括 HTTP请求、会话状态、连接数、源地
址以及连接时间等
option dontlognull #dontlognull表示不记录空会话连接日志
option http-server-close #等待客户端完整HTTP请求的时间,此处为等
待10s。
option forwardfor except 127.0.0.0/8 #透传客户端真实IP至后端web服务器
#在apache配置文件中加入:<br>%{XForwarded-For}i
#后在webserver中看日志即可看到地址透传
信息
option redispatch #当server Id对应的服务器挂掉后,强制定
向到其他健康的服务器,重新派发
option http-keep-alive #开启与客户端的会话保持
retries 3 #连接后端服务器失败次数
3.3.2.3 Proxies配置-frontend
frontend 配置参数:
frontend 配置示例:
timeout http-request 10s #等待客户端请求完全被接收和处理的最长时
间
timeout queue 1m #设置删除连接和客户端收到503或服务不可
用等提示信息前的等待时间
timeout connect 120s #设置等待服务器连接成功的时间
timeout client 600s #设置允许客户端处于非活动状态,即既不发
送数据也不接收数据的时间
timeout server 600s #设置服务器超时时间,即允许服务器处于既
不接收也不发送数据的非活动时间
timeout http-keep-alive 60s #session 会话保持超时时间,此时间段内
会转发到相同的后端服务器
timeout check 10s #指定后端服务器健康检查的超时时间
maxconn 3000
default-server inter 1000 weight 3
systemctl restart haproxy.service
frontend lee-webserver-80
bind 172.25.254.100:80
mode http
use_backend lee-webserver-80-RS
backend lee-webserver-80-RS
mode http
server web1 172.25.254.10:80 check inter 3s fall 3 rise 5
server web2 172.25.254.20:80 check inter 3s fall 3 rise 5
systemctl restart haproxy.service
测试:
在RS1,RS2安装nginx:
dnf install nginx -y
开启:
systemctl start nginx
在网页文档中写入内容:
#写在RS1
echo RS1 -172.25.254.10 > /usr/share/nginx/html/index.html
#写在RS2
echo RS2 -172.25.254.20 > /usr/share/nginx/html/index.html
在客户端测试:
for N in {1..6};do curl 172.25.254.100;done
99 listen webserver
100 bind *:80
101 mode http
102 balance static-rr
103 server webserver1 172.25.254.10:80 check inter 3s fall 3 weight 2
104 server webserver2 172.25.254.20:80 check inter 3s fall 3 weight 2

systemctl restart haproxy.service
客户端测试:
for N in {1..6};do curl 172.25.254.100;done
dnf install socat -y
修改配置文件:
vim /etc/haproxy/haproxy.cfg
stats socket /var/lib/haproxy/stats mode 600 level adminsystemctl restart haproxy.service
socat -h
echo "help" | socat stdio /var/lib/haproxy/stats
echo "show info" | socat stdio /var/lib/haproxy/stats
echo "show servers state" | socat stdio /var/lib/haproxy/stats
echo get weight webserver/web1 | socat stdio /var/lib/haproxy/stats
echo set weight webserver/web1 1 | socat stdio /var/lib/haproxy/stats
echo "disable server webserver/web1 " | socat stdio /var/lib/haproxy/stats
上线:
echo "enable server webserver/web1 " | socat stdio /var/lib/haproxy/stats
vim /etc/haproxy/haproxy.cfg
...上面内容省略...
listen stats
mode http
bind *:1616
stats enable
log global
stats uri /haproxy-status
stats auth lee:lee
while true;do curl 172.25.254.100 ; sleep 0.1;done







echo "set weight webserver_80/webserver1 2" | socat stdio /var/lib/haproxy/haproxy.sock




原理一句话总结
用 源地址(source IP) 做哈希,再 对总权重取模,决定转发到哪台后端服务器。
优点
-
实现简单,计算快。
-
请求分布均匀,能做到较好的负载均衡。
-
无状态,不依赖历史连接或会话。
缺点
-
静态调度:一旦后端服务器数量或权重变化,所有哈希结果都会重新分布。
-
也就是说:上线/下线一台机器,所有连接都会被打乱重排。
-
-
不支持:
-
动态权重调整(不能在线改权重)
-
慢启动(slow-start)
-
会话保持(除非用一致性哈希)
-
举个例子
假设有三台后端服务器,权重分别为:
-
A:3
-
B:2
-
C:1
总权重 = 6
一个客户端 IP 哈希后得 17,则:
17 % 6 = 5
根据权重区间划分:
-
A:0~2
-
B:3~4
-
C:5
→ 请求会打到 C。
如果此时 C 下线,总权重变成 5,那么:
17 % 5 = 2
现在会打到 A,之前打到 C 的所有请求都变了。
总结一句话
取模哈希法简单高效,但服务器变化会导致“全量重排”,不适合对稳定性要求高的业务。
替代方案
-
一致性哈希调度(consistent hashing):服务器增减只影响局部请求,避免全量重排。
-
加权轮询(WRR)或 最少连接数(LC):支持动态权重和慢启动。

#不支持动态调整权重值
[root@haproxy ~]# echo "set weight webserver_80/webserver1 2" | socat stdio
/var/lib/haproxy/haproxy.sock
Backend is using a static LB algorithm and only accepts weights '0%' and '100%'.
#只能动态上线和下线
[root@haproxy ~]# echo "set weight webserver_80/webserver1 0" | socat stdio
/var/lib/haproxy/haproxy.sock
[root@haproxy ~]# echo "get weight webserver_80/webserver1" | socat stdio
/var/lib/haproxy/haproxy.sock
0 (initial 1)
-
基本概念
• 传统取模:hash(o) mod n
服务器数量 n 一变,所有结果重新洗牌 → 命中率雪崩。
• 一致性哈希:把服务器和对象都映射到 0~2³² 的「Hash 环」上。
对象顺时针找最近的服务器。
服务器数量变化时,只影响环上相邻的一小段 → 局部重映射。
-
环偏斜(Skew)与虚拟节点
• 问题:真实节点在环上可能分布不均,导致负载不均。
• 解决:每个物理节点拆成 w × k 个「虚拟节点」
HAProxy 中叫 id
,Nginx 中叫 weight
× consistent
参数。
虚拟节点越多,分布越均匀,但 CPU 略增。








curl 172.25.254.100/index.html?name=aaa



-
一句话解释
HAProxy 先看你指定的 HTTP 头字段(比如 User-Agent
、X-Real-IP
、X-Api-Key
等),
把这个头的值做 hash → 再按 服务器总权重取模 → 决定把请求扔给哪台后端。
• 头字段存在 → 用 hash 结果挑服务器(静态映射)。
• 头字段不存在 → 退化成普通轮询(round-robin)。
-
为什么用它
• 同一客户端或同一类客户端 始终落到同一台机器(会话粘滞、缓存亲和)。
• 头字段变化少,hash 结果就稳定,命中率高。
• 支持在线调权重(一致性哈希版本),也支持慢启动。

curl -v 172.25.254.100

curl -vA "firefox" 172.25.254.100
#静态
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
first #使用较少
static-rr #做了session共享的web集群
roundrobin
random
leastconn #数据库
source
#基于客户端公网IP的会话保持
Uri--------------->http #缓存服务器,CDN服务商,蓝汛、百度、阿里云、腾讯
url_param--------->http #可以实现session保持
hdr #基于客户端请求报文头部做下一步处理
(在响应里给客户端 种一个特定 cookie,以后客户端每次带着这个 cookie 来,HAProxy 就根据 cookie 值把请求 精确地送回上一次那台后端,实现会话黏着(sticky session)。)
】


curl -i 172.25.254.100
curl -b WEBCOOKIE=web1 172.25.254.100

curl -vb WEBCOOKIE=web1 172.25.254.100
listen statsmode httpbind *:1616stats enablelog globalstats uri /statusstats auth xyz:xyz

http://172.25.254.100:1616/status


vim /etc/nginx/nginx.conf

tail -n 3 /var/log/nginx/access.log
' "$proxy_protocol_addr"'80 proxy_protocol; #启用此项,将无法直接访问此网站,只能通过四层代理
vim /etc/nginx/nginx.conf
systemctl restart nginx


tail -n 3 /var/log/nginx/access.log
vim /etc/haproxy/haproxy.cfg

LogFormat "%{X-Forwarded-For}i %a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined





dnf install php -y
vim /usr/share/nginx/html/index.php<?phpphpinfo();
?>

[root@rs1 ~]# mkdir /usr/share/nginx/html/static
[root@rs1 ~]# echo static 192.168.0.101 > /usr/share/nginx/html/static/index.html
测试:


[root@haproxy ~]# mkdir /haproxy/errorpages/ -p
[root@haproxy ~]# cp /usr/share/haproxy/503.http /haproxy/errorpages/503page.http
[root@haproxy ~]# vim /haproxy/errorpages/503page.http



listen mysql_port
bind :3306
mode tcp
balance leastconn
server mysql1 192.168.0.101:3306 check
server mysql2 192.168.0.102:3306 check

yum install mariadb-server -yvim /etc/my.cnf[mysqld]
server-id=1 #在另一台主机为[mysqld]
server-id=2 #在另一台主机为
mysql -e "grant all on *.* to lee@'%' identified by 'lee';"
客户端测试:
mysql -ulee -plee -h 172.25.254.100 -e "show variables like
'hostname'"
mysql -ulee -plee -h172.25.254.100 -e "select @@server_id"
mkdir /etc/haproxy/certs/
openssl req -newkey rsa:2048 -nodes -sha256 -keyout /etc/haproxy/certs/timinglee.org.key -x509 -days 365 -out /etc/haproxy/certs/timinglee.org.crt
cat /etc/haproxy/certs/timinglee.org.crt \/etc/haproxy/certs/timinglee.org.key \> /etc/haproxy/timinglee.org.pem
frontend webserver
bind *:80
redirect scheme https if !{ ssl_fc }
mode http
use_backend webcluster
frontend webserver-https
bind *:443 ssl crt /etc/haproxy/timinglee.org.pem
mode http
use_backend webcluster
backend webcluster
mode http
balance roundrobin
server web1 172.25.254.10:80 check inter 3s fall 3 rise 5
server web2 172.25.254.20:80 check inter 3s fall 3 rise 5
curl -IkL http://172.25.254.100
haproxy -c -f /etc/haproxy/haproxy.cfg