目录
一、案例背景与工具对比
(一)案例目标与工具定位
本案例旨在通过Haproxy与Nginx结合搭建Web群集,实现负载均衡与高可用性。Haproxy是一款流行的开源群集调度工具,适用于高并发场景,常与LVS、Nginx对比:
- LVS:性能最强,基于四层负载均衡,但搭建复杂,适合流量超大场景。
- Nginx:支持七层负载均衡,配置简单,但节点健康检查较弱,高并发性能略逊于Haproxy。
- Haproxy:兼具四层与七层负载均衡能力,健康检查机制完善,高并发下表现优异,适合Web服务场景。
(二)核心技术点
- HTTP请求基础
- 请求方法:包括GET(参数显式附于URL)和POST(参数隐式传输,适合敏感数据提交)。
- 状态码:2XX(成功)、3XX(重定向)、4XX(客户端错误)、5XX(服务器错误)。
- 负载均衡调度算法
- RR(轮询算法):默认均匀分配请求,支持加权轮询(
weight
参数),适用于节点性能均衡场景。 - LC(最小连接数算法):动态分配请求到连接数最少的节点,避免节点过载,适用于连接数波动大的场景。
- SH(源地址哈希算法):基于源IP或Cookie实现会话保持,确保同一客户端始终访问同一节点,解决Session共享问题,但可能导致流量分布不均。
- RR(轮询算法):默认均匀分配请求,支持加权轮询(
二、案例环境准备
(一)拓扑与节点规划
主机角色 | 操作系统 | IP地址 | 服务 |
---|---|---|---|
Nginx节点1 | openEuler 24.03 | 192.168.10.101 | Nginx |
Nginx节点2 | openEuler 24.03 | 192.168.10.102 | Nginx |
Haproxy调度器 | openEuler 24.03 | 192.168.10.103 | Haproxy |
(二)环境要求
- 关闭防火墙:
systemctl stop firewalld
(简化测试环境,生产环境需配置安全策略)。 - 安装依赖工具:
gcc
、make
、pcre-devel
、zlib-devel
、openssl-devel
等编译工具。
三、Nginx节点搭建
(一)编译安装Nginx
以Nginx-node-1为例(Nginx-node-2步骤相同,仅测试页面内容不同):
- 安装依赖
dnf install gcc make pcre-devel zlib-devel openssl-devel perl-ExtUtils-MakelMaker git wget tar -y
- 创建用户
useradd -M -s /sbin/nologin nginx
- 解压安装包
tar zxf nginx-1.26.3.tar.gz
cd nginx-1.26.3
- 配置编译参数
./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-pcre
--prefix
:指定安装目录。--user/--group
:指定运行用户,提升安全性。--with-http_ssl_module
:启用HTTPS支持。
- 编译并安装
make && make install
- 验证安装
- 默认安装目录:
/usr/local/nginx
。 - 默认日志路径:
/usr/local/nginx/logs/
。 - 默认Web目录:
/usr/local/nginx/html
。 - 启动Nginx:
/usr/local/nginx/sbin/nginx
。 - 检查端口:
netstat -anpt | grep nginx
(应监听80端口)。
(二)创建测试页面
cd /usr/local/nginx/html
echo "Server 192.168.10.101" > test.html
- 访问测试:在客户端浏览器输入
http://192.168.10.101/test.html
,应显示Server 192.168.10.101
。
(三)Nginx-node-2配置
重复上述步骤,仅修改测试页面内容:
echo "Server 192.168.10.102" > test.html
四、Haproxy安装与配置
(一)安装Haproxy
dnf install haproxy -y
- 说明:openEuler软件源提供预编译包,直接通过
dnf
安装,避免手动编译。
(二)配置文件结构解析
Haproxy配置文件分为三个部分:global
(全局配置)、defaults
(默认配置)、listen
(应用组件配置)。
- global全局配置
global
log 127.0.0.1 local2 # 配置系统日志,local2为日志设备
maxconn 4000 # 全局最大连接数
user haproxy # 运行用户
group haproxy # 运行用户组
daemon # 以守护进程模式运行
pidfile /var/run/haproxy.pid # PID文件路径
chroot /var/lib/haproxy # 切换工作目录,提升安全性
- defaults默认配置
defaults
log global # 继承global日志配置
mode http # 工作模式为HTTP(七层负载均衡)
option httplog # 启用HTTP日志格式
option dontlognull # 忽略无效日志
retries 3 # 健康检查失败重试次数,3次失败则标记节点不可用
timeout connect 5s # 连接超时时间
timeout client 1m # 客户端超时时间
timeout server 1m # 服务器超时时间
timeout http-keepalive 5s # HTTP长连接超时时间
maxconn 3000 # 默认最大连接数(需小于global的maxconn)
- listen应用配置(Web群集)
listen webcluster
bind 0.0.0.0:80 # 监听所有网卡的80端口
option httpchk GET /index.html # 健康检查:发送GET请求到/index.html
balance roundrobin # 负载均衡算法:轮询(RR)
server inst1 192.168.10.101:80 check inter 2000 fall 3 # 后端节点1
server inst2 192.168.10.102:80 check inter 2000 fall 3 # 后端节点2
# 参数说明:
# check:启用健康检查
# inter 2000:检查间隔2000ms(2秒)
# fall 3:连续3次失败则下线节点
(三)完整配置文件示例
vim /etc/haproxy/haproxy.cfg
global
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
user haproxy
group haproxy
daemon
maxconn 4000
defaults
mode http
log global
option httplog
option dontlognull
retries 3
timeout http-request 5s
timeout queue 1m
timeout connect 5s
timeout client 1m
timeout server 1m
timeout http-keepalive 5s
timeout check 5s
maxconn 3000
listen webcluster
bind 0.0.0.0:80
option httpchk GET /index.html
balance roundrobin
server inst1 192.168.10.101:80 check inter 2000 fall 3
server inst2 192.168.10.102:80 check inter 2000 fall 3
(四)启动与验证Haproxy
- 启动服务
systemctl start haproxy
- 检查状态
systemctl status haproxy # 确保服务运行正常
netstat -anpt | grep haproxy # 检查80端口监听情况
五、群集功能测试
(一)高性能测试(负载均衡效果)
- 第一次访问:客户端浏览器输入
http://192.168.10.103/test.html
,应显示Nginx-node-1的测试页面(Server 192.168.10.101
)。 - 第二次访问:新开浏览器窗口或刷新页面,应显示Nginx-node-2的测试页面(
Server 192.168.10.102
)。
- 原理:Haproxy通过轮询算法(
roundrobin
)交替将请求转发到后端节点,实现负载均衡。
(二)高可用性测试(故障转移)
- 模拟节点故障:在Nginx-node-2上停止Nginx服务:
/usr/local/nginx/sbin/nginx -s stop
- 访问测试:客户端持续访问
http://192.168.10.103/test.html
,应始终显示Nginx-node-1的页面(Haproxy自动将故障节点下线)。 - 恢复节点:在Nginx-node-2上重启Nginx:
/usr/local/nginx/sbin/nginx
- 再次测试:访问应恢复轮询效果,验证节点自动恢复功能。
六、日志配置与管理
(一)独立日志配置
Haproxy默认日志输出到syslog
,为方便管理,配置独立日志文件:
- 修改Haproxy配置
vim /etc/haproxy/haproxy.cfg
global
log 127.0.0.1 local0 info # 修改日志设备为local0,级别info
# 注释chroot配置(避免权限问题)
# chroot /var/lib/haproxy
- 配置Rsyslog
创建日志规则文件:
vim /etc/rsyslog.d/9-haproxy.conf
# 捕获local0设备的日志,写入/var/log/haproxy.log
local0.* /var/log/haproxy.log
- 创建日志文件并设置权限
touch /var/log/haproxy.log
chmod 640 /var/log/haproxy.log # 赋予读写权限(所有者root,所属组adm)
chown root:adm /var/log/haproxy.log # 确保rsyslog用户(属于adm组)可写入
- 重启服务
systemctl restart rsyslog
systemctl restart haproxy
(二)日志格式解析
访问后查看日志:
tail -f /var/log/haproxy.log
典型日志条目:
[11/Apr/2025:22:06:20.941] webcluster webcluster/inst2 0/0/0/1/1 200 221 ----- 2/2/0/0/0 0/0 "GET /test.html HTTP/1.1"
- 字段说明:
webcluster
:监听实例名称。inst2
:后端节点名称。200
:响应状态码。"GET /test.html HTTP/1.1"
:请求方法与URL。
七、参数优化与生产建议
(一)核心参数优化表
参数 | 说明 | 生产环境建议值 |
---|---|---|
maxconn | 全局最大连接数 | 根据服务器性能调整,推荐10240(需大于defaults 中的maxconn ) |
nbproc | 并发进程数 | 等于CPU核数或其2倍(如4核CPU设为4或8) |
retries | 健康检查重试次数 | 节点多时设为2-3次,节点少时设为5-6次 |
option http-server-close | 主动关闭HTTP连接 | 启用(避免长连接堆积) |
timeout http-keepalive | 长连接超时时间 | 10s(根据应用特性调整) |
timeout client | 客户端超时时间 | 1min(访问量高时可缩短至30s) |
(二)优化示例
vim /etc/haproxy/haproxy.cfg
global
maxconn 10240 # 提升全局连接数
nbproc 4 # 假设CPU为4核
defaults
option http-server-close # 启用主动关闭连接
timeout http-keepalive 10s # 长连接超时10秒
八、总结与扩展
(一)Haproxy核心优势
- 多协议支持:同时处理TCP(四层)和HTTP(七层)流量,适用场景广泛。
- 健康检查机制:实时监测节点状态,自动隔离故障节点,保障服务可用性。
- 动态配置重载:通过
haproxy -f /etc/haproxy/haproxy.cfg -p /var/run/haproxy.pid -st $(cat /var/run/haproxy.pid)
命令可在不中断服务的情况下更新配置。
(二)扩展场景
- HTTPS支持:在
listen
配置中添加SSL相关参数,如bind 0.0.0.0:443 ssl crt /path/to/cert.pem
。 - 会话保持:使用
balance source
(源地址哈希)或cookie
机制实现会话粘连。 - 高可用集群:结合Keepalived实现Haproxy双机热备,避免单点故障。
(三)生产环境注意事项
- 安全配置:限制Haproxy服务器的网络访问,仅开放必要端口(如80/443)。
- 监控告警:通过Prometheus+Grafana监控Haproxy指标(如请求速率、节点健康状态),设置告警规则。
- 日志轮转:配置
logrotate
定期切割日志文件,避免日志占用过多磁盘空间。
九、Haproxy 配置文件深度解析与常见问题处理
(一)配置文件分段详解
1. global 段核心参数补充
log
参数扩展log 127.0.0.1 local2 info
:local2
为日志设备(可取值 local0~local7),info
为日志级别(可选 emerg、alert、crit、err、warning、notice、info、debug)。生产环境建议使用info
级别,避免调试日志(debug)影响性能。- 多日志服务1器配置:若需将日志发送到远程服务器,可改为
log 192.168.10.100:514 local2 info
(需确保远程服务器开启 rsyslog 服务并监听 514 端口)。
ulimit-n
参数
Haproxy 默认文件描述符限制可能较低,需在global
段添加ulimit-n 10240
(与maxconn
匹配),避免高并发时出现 “Too many open files” 错误。
2. defaults 段继承机制
- 参数覆盖规则:
listen
段配置会覆盖defaults
段同名参数。例如,若defaults
中timeout connect
为 5s,可在listen
中针对特定应用设置为 3s:listen webcluster timeout connect 3s # 仅对此监听实例生效 ...
3. listen 段高级配置
- TCP 模式负载均衡(四层代理,适用于数据库等非 HTTP 服务):
listen mysql_cluster mode tcp # 切换为TCP模式 bind 0.0.0.0:3306 balance roundrobin server db1 192.168.10.110:3306 check inter 2000 fall 3
- 权重配置(加权轮询):
server inst1 192.168.10.101:80 check weight 2 # 权重为2,接收双倍请求量 server inst2 192.168.10.102:80 check weight 1
(二)健康检查失效排查
1. 常见原因与解决方法
- 检查路径错误:
若option httpchk GET /index.html
配置的路径不存在于后端节点,需确保 Nginx 的/index.html
存在(可通过curl http://192.168.10.101/index.html
验证)。 - 端口未暴露:
后端节点防火墙未开放 80 端口,需执行firewall-cmd --add-port=80/tcp --permanent
并重启防火墙(生产环境需谨慎操作,建议通过安全组规则限制)。 - Haproxy 用户权限不足:
若启用chroot
配置,需确保/var/lib/haproxy
目录下的文件权限正确,且 Haproxy 用户对后端节点有网络访问权限。
2. 调试命令1
- 查看节点状态:
haproxy -f /etc/haproxy/haproxy.cfg -c # 检查配置文件语法 systemctl status haproxy # 查看服务运行日志 echo "show servers" | socat stdio /var/run/haproxy.sock # 实时查看后端节点状态
输出示例:# "webcluster" frontend servers: inst1 (192.168.10.101:80) up 1/3/0 0 active 0 backup 0 check 2000ms 3 fall 1 rise 2 inst2 (192.168.10.102:80) up 1/3/0 0 active 0 backup 0 check 2000ms 3 fall 1 rise 2
up
:节点状态正常;down
:节点不可用。3 fall
:连续 3 次失败下线节点,1 rise
:1 次成功恢复节点(可通过server
参数的rise
配置调整)。
(三)负载不均衡问题处理
1. 算法选择导致的不均
- SH 算法(源地址哈希)的局限性:
若某个 IP 访问量极高(如爬虫),会导致对应节点负载过高。解决方案:- 改用
LC
算法(最小连接数),或在balance
后添加spread-checks 5
(分散检查,降低突发流量冲击)。 - 结合
sticky-table
(粘性表)设置超时时间,避免永久会话保持:listen webcluster balance source stick-table type ip size 100k expire 30m # 基于IP的粘性表,存活30分钟 stick on src # 粘性键为源IP
- 改用
2. 节点性能差异未配置权重
- 若后端节点硬件配置不同(如一台 4 核、一台 2 核),需通过
weight
参数调整请求分配比例:server inst1 192.168.10.101:80 check weight 4 # 4核节点权重4 server inst2 192.168.10.102:80 check weight 2 # 2核节点权重2
十、Haproxy 与其他工具结合的扩展方案
(一)与 Keepalived 实现双机热备
1. 场景说明
避免 Haproxy 单点故障,通过 Keepalived 实现主备切换,共享虚拟 IP(VIP):
- 主节点:Haproxy+Keepalived,绑定 VIP 192.168.10.200。
- 备节点:Haproxy+Keepalived,监听主节点状态。
2. 主节点 Keepalived 配置示例
vim /etc/keepalived/keepalived.conf
global_defs {
router_id HAPROXY_MASTER # 节点标识
}
vrrp_instance VI_1 {
state MASTER # 主节点状态(备节点为BACKUP)
interface eth0 # 绑定网卡
virtual_router_id 51 # 虚拟路由ID(主备需一致)
priority 100 # 优先级(备节点设为90)
advert_int 1 # 心跳间隔(秒)
authentication {
auth_type PASS
auth_pass haproxy_keepalived # 认证密码
}
virtual_ipaddress {
192.168.10.200 # 虚拟IP
}
}
3. 验证切换
- 停止主节点 Haproxy 服务,Keepalived 会自动将 VIP 切换到备节点。
- 主节点恢复后,VIP 自动切回(需确保
priority
配置正确)。
(二)与 Prometheus 监控集成
1. 启用 Haproxy 统计页面
在listen
段添加统计页面配置:
listen stats
bind 0.0.0.0:1080 # 监听1080端口
mode http
option httplog
stats enable # 启用统计功能
stats uri /haproxy_stats # 访问路径
stats auth admin:admin # 用户名密码认证(生产环境需强密码)
- 访问
http://192.168.10.103:1080/haproxy_stats
可查看实时状态(如请求速率、连接数、节点健康度)。
2. Prometheus 配置
在 Prometheus 的prometheus.yml
中添加抓取任务:
scrape_configs:
- job_name: 'haproxy'
static_configs:
- targets: ['192.168.10.103:1080'] # Haproxy服务器IP:统计端口
labels:
instance: haproxy
- 通过 Grafana 导入 Haproxy 监控模板(如 ID 9629),展示请求量、错误率、节点负载等指标。
(三)与 Nginx 的分层架构优化
1. 场景说明
- Haproxy 作为四层负载均衡:负责 TCP 层流量分发,转发到多台 Nginx。
- Nginx 作为七层代理:处理 HTTP 请求,执行缓存、SSL 卸载、WAF 过滤等功能。
2. 拓扑结构
客户端 <----(80/443)----> Haproxy <----(8080)----> Nginx1 <----> 应用服务器
<----(8080)----> Nginx2 <----> 应用服务器
3. Haproxy 配置调整
listen webcluster
bind 0.0.0.0:80
mode tcp # 四层负载均衡(转发TCP流量到Nginx的8080端口)
balance roundrobin
server nginx1 192.168.10.101:8080 check inter 2000 fall 3
server nginx2 192.168.10.102:8080 check inter 2000 fall 3
- Nginx 需配置监听 8080 端口,并在
nginx.conf
中关闭端口复用:server { listen 8080; server_name _; location / { proxy_pass http://upstream; # 转发到后端应用服务器 } }
十一、生产环境部署 checklist
(一)安全加固
- 用户权限:
- Haproxy 运行用户(
haproxy
)仅赋予必要权限,禁止登录 Shell(/sbin/nologin
)。 - Nginx 运1行用户(
nginx
)同理,避免使用root
用户运行服务。
- Haproxy 运行用户(
- 配置文件权限:
chmod 600 /etc/haproxy/haproxy.cfg # 仅允许root读写 chown root:root /etc/haproxy/haproxy.cfg
- 网络策略:
- 通过防火墙限制 Haproxy 服务器的入站流量,仅开放 80/443(Web)、1080(监控)、514(日志)等必要端口。
- 后端 Nginx 节点禁止公网直接访问,仅允许 Haproxy 所在服务器发起连接。
(二)性能调优
- 内核参数优化:
在/etc/sysctl.conf
中添加:net.core.somaxconn = 65535 # 监听队列长度,避免高并发时连接丢失 net.ipv4.tcp_tw_reuse = 1 # 复用TIME-WAIT状态的Socket net.ipv4.tcp_fin_timeout = 30 # 缩短FIN_WAIT_2状态超时时间 sysctl -p # 生效配置
- CPU 绑定:
通过global
段cpu-map
参数将 Haproxy 进程绑定到指定 CPU 核心,减少上下文切换:global cpu-map 1 0 # 第1个进程绑定到CPU0 cpu-map 2 1 # 第2个进程绑定到CPU1(需配合`nbproc 2`使用)
(三)容灾与备份
- 配置备份:
cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bak$(date +%Y%m%d)
- 应急预案:
- 编写脚本实现 Haproxy 配置动态更新(如通过
curl -X POST http://haproxy-api/reload
接口)。 - 定期模拟节点故障,验证故障转移流程(如关闭一台 Nginx,观察 Haproxy 是否自动剔除节点)。
- 编写脚本实现 Haproxy 配置动态更新(如通过
十二、常见错误与解决方案
(一)启动失败类
错误信息 | 可能原因 | 解决方案 |
---|---|---|
Cannot open socket for logging | 日志设备配置错误 | 检查log 参数中的 IP、端口、设备名称是否正确(如local2 是否存在) |
chroot: No {insert\_element\_3\_}such file or directory | chroot 目录不存在 | 创建目录:mkdir -p /var/lib/haproxy ,并赋予haproxy 用户权限 |
bind() to 0.0.0.0:80 failed (13: Permission denied) | 端口权限不足 | 使用root 用户启动 Haproxy,或通过setcap 赋予普通用户绑定 80 端口权限:setcap 'cap_net_bind_service=+ep' $(which haproxy) |
(二)负载均衡异常类
现象 | 可能原因 | 解决方案 |
---|---|---|
客户端访问始终返回同一节点内容 | 会话保持配置错误(如误用SH 算法) | 检查balance 是否为roundrobin ,或移除stick 相关配置 |
节点状态显示down ,但手动访问节点正常 | 健康检查路径或方法错误 | 使用curl -I http://节点IP/检查路径 验证返回状态码是否为 200,调整option httpchk 的请求路径或方法(如改为 POST) |
高并发时请求超时 | 连接数或超时时间设置不足 | 增大maxconn 和defaults 中的timeout 参数,如timeout connect 10s |
(三)日志相关问题
问题 | 可能原因 | 解决方案 |
---|---|---|
日志无输出 | 日志配置未生效 | 检查 Haproxy 配置中的log 参数是否正确,重启 Haproxy 和 rsyslog 服务 |
日志内容乱码 | 字符集不匹配 | 在 rsyslog 配置中添加$ModLoad imudp 和$InputCharset utf-8 ,确保日志传输与存储使用 UTF-8 编码 |