HAProxy实验搭建
HAProxy 介绍
HAProxy 是一款提供高可用性、负载均衡以及基于 TCP(第四层)和 HTTP(第七层)应用的代理软件,支持虚拟主机。它是免费、快速并且可靠的一种解决方案。
HAProxy 特别适用于负载较大的 Web 站点,这些站点通常又需要会话保持或七层处理。HAProxy 运行在当下的硬件上,完全可以支持数以万计的并发连接。并且它的运行模式使得它可以很简单、安全地整合进您当前的架构中,同时可以保护 Web 服务器不被暴露到网络上。
HAProxy 实现了一种事件驱动、单一进程模型,此模型支持非常大的并发连接数。多进程或多线程模型受内存限制、系统调度器限制以及无处不在的锁限制,很少能处理数千并发连接。事件驱动模型因为在用户端(User-Space)有更好的资源和时间管理来实现所有这些任务。此模型的弊端是,在多核系统上,这些程序通常扩展性较差,因此必须进行优化以使每个 CPU 时间片(Cycle)做更多的工作。
性能
HAProxy 借助于 OS 上几种常见的技术来实现性能的最大化:
- 单进程、事件驱动模型显著降低了上下文切换的开销及内存占用。
- O(1) 事件检查器(event checker)允许其在高并发连接中对任何连接的任何事件实现即时探测。
- 在任何可用的情况下,单缓冲(single buffering)机制能以不复制任何数据的方式完成读写操作,这会节约大量的 CPU 时钟周期及内存带宽。
- 借助于 Linux 2.6(>= 2.6.27.19)上的
splice()系统调用,HAProxy 可以实现零复制转发(Zero-copy forwarding);在 Linux 3.5 及以上的 OS 中还可以实现零复制启动(zero-starting)。 - 内存分配器在固定大小的内存池中可实现即时内存分配,能够显著减少创建一个会话的时长。
- 树型存储:使用弹性二叉树,以 O(log(N)) 的低开销保持计时器、运行队列及管理轮询与最少连接队列。
- 优化的 HTTP 首部分析:避免在 HTTP 首部分析过程中重读任何内存区域。
- 精心地降低了昂贵的系统调用,大部分工作都在用户空间完成,如时间读取、缓冲聚合及文件描述符的启用和禁用等。
所有这些细微优化,使 HAProxy 在中等规模负载之上依然有着相当低的 CPU 负载。在非常高的负载场景中,5% 的用户空间占用率和 95% 的系统空间占用率也非常普遍,这意味着 HAProxy 进程消耗比系统空间消耗低 20 倍以上。因此,对 OS 进行性能调优非常重要。即使用户空间的占用率提高一倍,其 CPU 占用率也仅为 10%,这也解释了为何七层处理对性能影响有限。在高端系统上,HAProxy 的七层性能可轻易超过硬件负载均衡设备。
在生产环境中,也常将 HAProxy 作为昂贵的高端硬件负载均衡设备故障时的七层应急方案。硬件负载均衡设备在「报文」级别处理请求,支持跨报文请求(request across multiple packets)难度较高,且不缓冲任何数据,响应时间较长。软件负载均衡设备使用 TCP 缓冲,可建立极长的请求,响应时间相对更灵活。
HAProxy 调度算法
HAProxy 有 8 种负载均衡算法(balance),分别如下:
| 算法 | 说明 |
|---|---|
roundrobin(rr) |
动态加权轮询,支持权重 |
static-rr |
静态轮询,不支持权重 |
leastconn |
最小连接优先处理 |
source |
源地址哈希 |
uri |
根据 URI 做哈希 |
url_param |
根据 URL 参数做哈希(需指定参数名) |
hdr(name) |
根据 HTTP 请求头锁定每一次请求 |
rdp-cookie(name) |
根据 Cookie 锁定并哈希每一次 TCP 请求 |
HAProxy 实践
通过 HAProxy 实现四层和七层负载均衡。
网络拓扑
| 主机名 | IP 地址 | 服务器角色 |
|---|---|---|
| client2.rich.cloud | 10.1.1.21 | 客户端 |
| client1.rich.cloud | 10.1.8.21 | 客户端 |
| router.rich.cloud | 10.1.8.20 / 10.1.1.20 | 路由器 |
| haproxy.rich.cloud | 10.1.8.10 / 10.1.1.10 | 代理服务器 |
| web1.rich.cloud | 10.1.8.11 | Web 和 SSH 服务器 |
| web2.rich.cloud | 10.1.8.12 | Web 和 SSH 服务器 |
| web3.rich.cloud | 10.1.8.13 | Web 和 SSH 服务器 |
网络说明:
- 所有主机:第一块网卡名为
ens33,第二块网卡名为ens192。 - 默认第一块网卡模式为 NAT,第二块网卡模式为 Host-Only。
- 网关设置:
10.1.1.0/24网段网关为10.1.1.20;10.1.8.0/24网段网关为10.1.8.20。
基础网络配置
bash
# 10.1.1.0/24 网段网关为 10.1.1.20
nmcli connection modify ens33 ipv4.gateway 10.1.1.20
nmcli connection up ens33
# 10.1.8.0/24 网段网关为 10.1.8.20(可以不改)
nmcli connection modify ens33 ipv4.gateway 10.1.8.20
nmcli connection up ens33
配置 router
bash
# 设置防火墙
systemctl enable firewalld.service --now
firewall-cmd --set-default-zone=trusted
firewall-cmd --add-masquerade --permanent
firewall-cmd --add-masquerade
# 开启路由
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
sysctl -p
HTTP 模式
配置 Web 服务器(web1--web3)
bash
# 部署 Web
yum install -y nginx
echo "Welcome to $(hostname)" > /usr/share/nginx/html/index.html
systemctl enable nginx.service --now
访问后端 Nginx:
bash
[root@client1 ~]# curl 10.1.8.11
Welcome to web1.rich.cloud
[root@client1 ~]# curl 10.1.8.12
Welcome to web2.rich.cloud
[root@client1 ~]# curl 10.1.8.13
Welcome to web3.rich.cloud
准备虚拟主机:
bash
cat > /etc/nginx/conf.d/vhost-test.conf <<'EOF'
server {
listen 81;
root /test;
}
EOF
systemctl restart nginx
# 准备测试文件
mkdir /test
echo "hello txt from $(hostname -s)" > /test/index.txt
echo "hello html from $(hostname -s)" > /test/index.html
测试:
bash
[root@client1 ~]# curl http://web1:81/
hello html from web1
[root@client1 ~]# curl http://web2:81/
hello html from web2
[root@client1 ~]# curl http://web3:81/
hello html from web3
配置 HAProxy(HTTP)
bash
# 安装 HAProxy
yum install -y haproxy
# 备份配置文件
cp /etc/haproxy/haproxy.cfg{,.ori}
# 在配置文件末尾追加以下内容
cat >> /etc/haproxy/haproxy.cfg <<'EOF'
######### web 代理 ###########
frontend front_web
bind *:80
default_backend back_web
# acl:固定关键字;test:规则名,可自定义
# url_reg:匹配方式;-i:忽略大小写;\.txt$:匹配 .txt 结尾
acl test url_reg -i \.txt$
# 若 acl 规则 test 匹配,则使用后端 back_test
use_backend back_test if test
backend back_web
balance roundrobin
# server:关键字,代表后端主机
# web1:后端主机名,可自定义,建议与主机名一致
# 10.1.8.11:80:后端实际地址和端口
# check:HAProxy 检查后端服务是否正常
server web1 10.1.8.11:80 check
server web2 10.1.8.12:80 check
server web3 10.1.8.13:80 check
backend back_test
balance roundrobin
server test1 10.1.8.11:81 check
server test2 10.1.8.12:81 check
server test3 10.1.8.13:81 check
EOF
# 启用并启动服务
systemctl enable haproxy.service --now
HTTP 模式测试
测试 .txt 结尾的 ACL 规则:
bash
[root@client1 ~]# for n in {1..90}; do curl http://10.1.8.10/index.txt -s; done | sort | uniq -c
[root@client2 ~]# for n in {1..90}; do curl http://10.1.1.10 -s; done | sort | uniq -c
30 Welcome to web1.rich.cloud
30 Welcome to web2.rich.cloud
30 Welcome to web3.rich.cloud
轮询测试(默认后端):
bash
[root@client1 ~]# for n in {1..90}; do curl http://10.1.8.10 -s; done | sort | uniq -c
30 Welcome to web1.rich.cloud
30 Welcome to web2.rich.cloud
30 Welcome to web3.rich.cloud
TCP 模式
配置 SSH(web1--web3)
bash
yum install -y openssh-server
systemctl enable sshd --now
配置 HAProxy(TCP / SSH)
bash
cp /etc/haproxy/haproxy.cfg{,.ori}
cat >> /etc/haproxy/haproxy.cfg <<'EOF'
######### ssh 代理 ###########
listen ssh
mode tcp
bind *:1022
balance roundrobin
server web1 10.1.8.11:22 check
server web2 10.1.8.12:22 check
server web3 10.1.8.13:22 check
EOF
systemctl restart haproxy.service
TCP 模式测试
bash
[root@client1 ~]# for n in {1..90}; do ssh root@haproxy -p 1022 hostname 2>/dev/null; done | sort | uniq -c
30 web1.rich.cloud
30 web2.rich.cloud
30 web3.rich.cloud
HAProxy 配置说明
HAProxy 的配置文件由两部分组成:
- global settings:定义 HAProxy 进程管理、安全及性能相关参数。
- proxies :对代理的设定,共分为 4 段:
- defaults :为其它配置段提供默认参数,可由下一个
defaults重新设定。 - frontend:定义监听的套接字,接受客户端请求并建立连接。
- backend:定义后端服务器,前端将请求调度至这些服务器。
- listen:将 frontend 与 backend 合并,通常用于 TCP(四层)代理。
- defaults :为其它配置段提供默认参数,可由下一个
所有代理的名称只能使用大写字母、小写字母、数字、-(中线)、_(下划线)、.(点号)和 :(冒号)。此外,ACL 名称区分大小写。
全局部分
进程管理及安全相关参数
haproxy
# log <address> <facility> [max level [min level]]:定义全局 syslog,最多两个
log 127.0.0.1 local2
# log-send-hostname [<string>]:在 syslog 首部添加主机名
log-send-hostname haproxy.rich.cloud
# chroot:变更工作目录并 chroot,提升安全(目录须为空且不可写)
chroot /var/lib/haproxy
# daemon:以守护进程方式在后台运行
daemon
# pidfile:进程 PID 文件路径
pidfile /var/run/haproxy.pid
# uid / user:以指定 UID 或用户身份运行
uid 188
user haproxy
# gid / group:以指定 GID 或组身份运行
gid 188
group haproxy
# stats socket:启用 Unix socket,用于访问统计数据
stats socket /var/lib/haproxy/stats
# node:当前节点名称(多 HAProxy 共享 IP 时使用)
node ha1.rich.cloud
# description:当前实例描述
description haproxy server 1
性能调整相关参数
haproxy
# nbproc <number>:进程个数(仅守护进程模式;调试困难,一般不推荐多进程)
nbproc 2
# ulimit-n:每进程最大文件描述符数(默认自动计算,不推荐修改)
# Linux 默认单进程约 1024
# maxconn <number>:每进程最大并发连接数,等同命令行 -n
maxconn 4000
# tune.bufsize:buffer 大小,默认 16384,强烈建议使用默认值
# tune.chksize:检查缓冲区大小,不建议修改
# tune.maxaccept:一次性可接受连接数,一般不建议修改
# tune.maxpollevents:单次系统调用可处理事件数
# tune.maxrewrite:首部重写预留缓冲,建议约 1024
# tune.rcvbuf.server:内核套接字接收缓冲,强烈推荐默认值
代理部分(defaults 示例)
haproxy
# mode:tcp 工作在四层,仅转发;http 工作在七层,可处理请求/响应
mode http
log global
log 127.0.0.1:514 local0 notice
option httplog # HTTP 日志格式,也可 tcplog
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 1m
timeout check 10s
HAProxy 使用总结
HAProxy 是高性能开源负载均衡器,支持 TCP 四层与 HTTP 七层代理,核心功能包括负载策略(轮询、加权、IP 哈希等)、后端健康检查(主动/被动)及会话保持。
通过 frontend / backend / listen 配置块定义转发规则,可实现 SSL 终止、请求过滤与流量控制。轻量且高并发,常用于 Web 服务、数据库等场景的高可用架构;搭配日志监控与故障转移,能有效提升服务稳定性与资源利用率。