HAProxy(High Availability Proxy)是目前最流行的开源负载均衡和代理服务器软件之一,以其高性能、高可靠性和丰富的功能特性,广泛应用于生产环境的四层(TCP)和七层(HTTP/HTTPS)流量分发场景。本文将详细介绍 HAProxy 的安装配置、核心概念、负载均衡算法、健康检查、SSL 终结、性能调优以及生产环境最佳实践。
HAProxy 核心概念
架构组件
HAProxy 的配置围绕三个核心组件展开:
- frontend(前端):定义客户端连接的入口,指定监听地址和端口,以及默认后端服务器组
- backend(后端):定义一组实际提供服务的服务器,以及负载均衡算法和健康检查策略
- listen(监听):将 frontend 和 backend 合并为一个简洁的配置段,适用于简单场景
一个基本的流量路径为:客户端 → Frontend(监听入口) → Backend(服务器组) → 实际服务器
处理模式
- tcp 模式(四层代理):工作在传输层,转发 TCP/UDP 流量,性能极高,适用于数据库、Redis、MySQL 等
- http 模式(七层代理):工作在应用层,可解析 HTTP 请求内容(URL、Header、Cookie),支持高级路由和会话保持
HAProxy 安装
Ubuntu/Debian 系列
1 2 3 4 5 6 7 8 9
| sudo apt-get install --no-install-recommends software-properties-common sudo add-apt-repository ppa:vbernat/haproxy-2.9 -y sudo apt-get update sudo apt-get install haproxy -y
haproxy -v
|
RHEL/CentOS 系列
1 2 3 4 5 6 7 8
| sudo dnf install epel-release -y
sudo dnf install haproxy -y
sudo yum install haproxy -y
|
编译安装(获取最新版本)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| sudo apt-get install -y curl gcc libc6-dev libpcre3-dev libssl-dev libsystemd-dev zlib1g-dev make
curl -L https://www.haproxy.org/download/2.9/src/haproxy-2.9.7.tar.gz -o haproxy.tar.gz tar xzf haproxy.tar.gz cd haproxy-2.9.7
make -j$(nproc) TARGET=linux-glibc USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_PCRE=1 sudo make install
/usr/local/sbin/haproxy -v
|
安装后验证
1 2 3 4 5
| haproxy -c -f /etc/haproxy/haproxy.cfg
haproxy -vv
|
基础配置详解
HAProxy 的主配置文件通常位于 /etc/haproxy/haproxy.cfg,配置语法清晰,采用层级结构。
全局配置(global)
1 2 3 4 5 6 7 8 9 10 11 12
| global log /dev/log local0 info # 日志输出 log /dev/log local1 notice maxconn 65535 # 最大连接数 user haproxy # 运行用户 group haproxy # 运行组 nbproc 1 # 进程数(2.5+版本推荐默认单进程多线程) pidfile /var/run/haproxy.pid stats socket /var/run/haproxy/admin.sock mode 660 level admin tune.ssl.default-dh-param 2048 # SSL DH 参数强度 ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256 ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 # 禁用不安全的 TLS 版本
|
默认配置(defaults)
1 2 3 4 5 6 7 8 9 10 11 12
| defaults log global mode http # 默认七层代理模式 option httplog # HTTP 日志格式 option dontlognull # 不记录空连接 option redispatch # 服务器降权后重新分配请求 retries 3 # 连接重试次数 maxconn 10000 # 单进程最大连接 timeout connect 5s # 连接超时 timeout client 30s # 客户端超时 timeout server 30s # 服务器超时 timeout check 5s # 健康检查超时
|
负载均衡算法详解
HAProxy 提供多种负载均衡算法,适用于不同场景:
| 算法 |
配置关键字 |
适用场景 |
特点 |
| 轮询 |
roundrobin |
服务器配置均等的通用场景 |
按顺序分发,动态权重调整支持 |
| 加权轮询 |
static-rr |
服务器性能不均等时 |
权重静态配置,运行时不可修改 |
| 最少连接 |
leastconn |
长连接服务(WebSocket、数据库) |
分发到当前活跃连接最少的服务器 |
| 源地址哈希 |
source |
需要会话保持的场景 |
客户端 IP 哈希,同一 IP 始终到同一台服务器 |
| URI 哈希 |
uri |
HTTP 缓存加速(CDN、反向代理) |
按请求 URI 哈希,同一资源落到同一服务器 |
| URL 参数哈希 |
url_param |
API 网关会话保持 |
按指定 URL 参数值进行哈希分配 |
| 首字节响应时间 |
first |
短连接、低延迟场景 |
选择响应最快的服务器 |
| 随机 |
random |
大规模集群,避免轮询热点 |
基于随机数,2.4+ 版本支持两轮随机 |
实战配置示例
1. HTTP 七层负载均衡(Web 服务)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| frontend web_front bind *:80 mode http option forwardfor # 传递客户端真实IP default_backend web_servers
backend web_servers mode http balance roundrobin # 轮询算法 option httpchk GET /health HTTP/1.1\r\nHost:\ example.com http-check expect status 200
# 服务器定义(weight 设置权重,maxconn 限制单机最大连接) server web1 192.168.1.10:8080 weight 3 maxconn 1024 check inter 5s fall 3 rise 2 server web2 192.168.1.11:8080 weight 2 maxconn 1024 check inter 5s fall 3 rise 2 server web3 192.168.1.12:8080 weight 1 maxconn 1024 check inter 5s fall 3 rise 2
# 备用服务器(主服务器全部不可用时启用) server web-backup 192.168.1.100:8080 weight 1 backup
|
配置说明:
weight:服务器权重,数值越大分发越多请求
check:启用健康检查
inter 5s:每 5 秒检查一次
fall 3:连续 3 次失败视为宕机
rise 2:连续 2 次成功视为恢复
backup:标记为备用服务器
2. TCP 四层负载均衡(MySQL/Redis)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| frontend mysql_front bind *:3306 mode tcp default_backend mysql_servers
backend mysql_servers mode tcp balance leastconn # 最少连接,适合数据库长连接 option tcp-check tcp-check connect tcp-check send PING\r\n tcp-check expect string +OK
server mysql1 10.0.0.1:3306 check inter 5s server mysql2 10.0.0.2:3306 check inter 5s
|
1 2 3 4 5 6 7 8 9 10 11
| # Redis 负载均衡 frontend redis_front bind *:6379 mode tcp default_backend redis_servers
backend redis_servers mode tcp balance first # 优先使用第一个可用的 Redis server redis1 10.0.0.1:6379 check inter 3s server redis2 10.0.0.2:6379 check inter 3s
|
3. HTTPS SSL 终结(TLS/SSL Offloading)
1 2 3 4 5 6 7 8 9 10 11 12 13
| frontend https_front bind *:443 ssl crt /etc/haproxy/certs/example.com.pem mode http option forwardfor # 强制跳转 HTTPS(配合 HTTP 前端) http-request set-header X-Forwarded-Proto https if { ssl_fc } default_backend web_servers
# HTTP 自动跳转 HTTPS frontend http_front bind *:80 mode http redirect scheme https code 301 if !{ ssl_fc }
|
SSL 证书准备: HAProxy 需要 PEM 格式证书(证书 + 私钥合并):
1 2 3 4 5 6
| cat /etc/letsencrypt/live/example.com/fullchain.pem \ /etc/letsencrypt/live/example.com/privkey.pem \ > /etc/haproxy/certs/example.com.pem
chmod 600 /etc/haproxy/certs/example.com.pem
|
4. 多域名虚拟主机路由
1 2 3 4 5 6 7 8 9 10 11 12
| frontend multi_domain_front bind *:80 bind *:443 ssl crt /etc/haproxy/certs/ crt-list /etc/haproxy/crt-list.txt mode http
# 按域名分流 use_backend api_servers if { hdr(Host) -i api.example.com } use_backend app_servers if { hdr(Host) -i app.example.com } use_backend admin_servers if { hdr(Host) -i admin.example.com }
# 默认后端 default_backend web_servers
|
crt-list 文件格式(/etc/haproxy/crt-list.txt):
1 2 3
| /etc/haproxy/certs/example.com.pem [alpn h2,http/1.1] /etc/haproxy/certs/api.example.com.pem [alpn h2,http/1.1] /etc/haproxy/certs/admin.example.com.pem
|
健康检查配置
健康检查是保证高可用的核心机制,HAProxy 支持多种检查方式:
HTTP 健康检查
1 2 3 4 5 6 7 8 9 10
| backend web_servers # 基本 HTTP 检查:GET 请求指定路径,期望状态码 option httpchk GET /health HTTP/1.1\r\nHost:\ example.com http-check expect status 200
# 或使用关键字检查 http-check expect string OK
# 支持 rstring 正则匹配 http-check expect rstring ^(OK|alive)$
|
TCP 健康检查
1 2 3 4 5 6 7 8 9
| backend mysql_servers mode tcp option tcp-check tcp-check connect tcp-check send PING\r\n tcp-check expect string +OK tcp-check send QUIT\r\n
server mysql1 10.0.0.1:3306 check inter 5s rise 2 fall 3
|
自定义脚本健康检查
1 2 3 4
| backend custom_servers option external-check # 启用外部检查 external-check command /usr/local/bin/health-check.sh server app1 192.168.1.10:3000 check inter 10s
|
会话保持配置
Cookie 插入方式
1 2 3 4 5 6 7
| backend web_servers mode http balance roundrobin # 服务器响应中插入 COOKIE,后续同一客户端通过 cookie 路由 cookie SERVERID insert indirect nocache server web1 192.168.1.10:8080 cookie s1 check server web2 192.168.1.11:8080 cookie s2 check
|
Source IP 哈希
1 2 3 4 5 6
| backend web_servers mode http balance source # 基于客户端源 IP 哈希 hash-type consistent # 一致性哈希,减少服务器增减影响 server web1 192.168.1.10:8080 check server web2 192.168.1.11:8080 check
|
访问控制与限流
IP 白名单/黑名单
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| frontend web_front bind *:80 mode http
# 黑名单:拒绝特定 IP acl blacklist src 192.168.1.100 10.0.0.50 http-request deny if blacklist
# 白名单:仅允许指定 IP 访问管理页面 acl admin_path path_beg /admin acl admin_ips src 10.0.0.0/24 http-request deny if admin_path !admin_ips
default_backend web_servers
|
请求速率限制
1 2 3 4 5 6 7 8 9 10 11 12 13
| frontend web_front bind *:80 mode http
# 定义速率限制:每个源 IP 每 10 秒最多 100 个请求 stick-table type ip size 100k expire 30s store http_req_rate(10s) http-request track-sc0 src
# 触发限流:返回 429 Too Many Requests acl rate_limit sc_http_req_rate(0) gt 100 http-request deny deny_status 429 if rate_limit
default_backend web_servers
|
状态监控页面
HAProxy 内置了强大的统计监控页面:
1 2 3 4 5 6 7 8 9 10
| frontend stats_front bind *:8080 mode http stats enable stats uri /haproxy-stats # 访问路径 stats refresh 5s # 自动刷新间隔 stats auth admin:StrongPassword # 认证用户和密码 stats admin if TRUE # 允许通过管理界面启用/禁用服务器 stats hide-version # 隐藏版本号 stats realm "HAProxy Statistics"
|
建议通过 Nginx 反向代理对监控页面加一层 HTTPS 和 IP 限制:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| server { listen 443 ssl; server_name monitor.example.com; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Authorization "Basic YWRtaW46U3Ryb25nUGFzc3dvcmQ="; allow 10.0.0.0/8; allow 192.168.0.0/16; deny all; } }
|
日志配置
syslog 配置
1 2 3 4 5 6 7 8 9
| # 全局配置中启用日志 global log /dev/log local0 info log /dev/log local1 notice
# 前端配置 frontend web_front option httplog # HTTP 详细日志 log-format "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq %hs %{+Q}r"
|
rsyslog 独立日志文件
1 2 3 4 5 6 7 8
| if ($programname == 'haproxy') then { action(type="omfile" file="/var/log/haproxy.log") stop }
sudo systemctl restart rsyslog
|
性能调优
内核参数优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
net.core.somaxconn = 65535 net.ipv4.tcp_max_syn_backlog = 65535 net.ipv4.ip_local_port_range = 1024 65535 net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_rmem = 4096 87380 16777216 net.ipv4.tcp_wmem = 4096 65536 16777216 net.core.rmem_default = 16777216 net.core.wmem_default = 16777216 net.core.rmem_max = 16777216 net.core.wmem_max = 16777216
sudo sysctl -p /etc/sysctl.d/99-haproxy.conf
|
HAProxy 配置调优
1 2 3 4 5 6 7
| global maxconn 100000 # 从系统 ulimit 推导,确保足够大 tune.bufsize 32768 # 缓冲区大小(默认 16384) tune.maxrewrite 2048 # HTTP 头重写缓冲区预留空间 # 多线程配置(2.5+) nbthread 4 # 线程数,通常等于 CPU 核数 cpu-map auto:1/1-4 0-3 # 线程绑定 CPU 核心
|
systemd 参数优化
1 2 3 4 5
| [Service] LimitNOFILE=1048576 LimitNPROC=1048576 LimitMEMLOCK=infinity
|
高可用方案(Keepalived + HAProxy)
使用 Keepalived 实现 HAProxy 自身的高可用(主备切换):
Keepalived 安装
1
| sudo apt-get install keepalived -y
|
主节点配置(/etc/keepalived/keepalived.conf)
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
| vrrp_script chk_haproxy { script "pidof haproxy" interval 2 weight 2 }
vrrp_instance VI_1 { interface eth0 state MASTER # 主节点 virtual_router_id 51 priority 101 # 优先级,主节点高于备节点 advert_int 1
authentication { auth_type PASS auth_path 1234 }
virtual_ipaddress { 192.168.1.200/24 dev eth0 # 虚拟 IP(VIP) }
track_script { chk_haproxy } }
|
备节点配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| vrrp_instance VI_1 { interface eth0 state BACKUP virtual_router_id 51 priority 100 advert_int 1
authentication { auth_type PASS auth_path 1234 }
virtual_ipaddress { 192.168.1.200/24 dev eth0 }
track_script { chk_haproxy } }
|
安全加固
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| global # 以非 root 用户运行 user haproxy group haproxy
frontend web_front # 禁用不安全的方法 http-request deny if { method CONNECT } http-request deny if { method TRACE }
# HTTP 安全头(如果 HAProxy 直接响应客户端) http-response set-header X-Content-Type-Options nosniff http-response set-header X-Frame-Options SAMEORIGIN http-response set-header X-XSS-Protection "1; mode=block"
# 限制请求体大小(防大 POST 攻击) http-request reject if { req.body_size gt 10m }
# 限制 URL 长度 http-request reject if { url_len gt 4096 }
|
常用命令速查
| 场景 |
命令 |
| 测试配置语法 |
haproxy -c -f /etc/haproxy/haproxy.cfg |
| 启动 HAProxy |
sudo systemctl start haproxy |
| 停止 HAProxy |
sudo systemctl stop haproxy |
| 重启 HAProxy |
sudo systemctl restart haproxy |
| 重载配置(无缝) |
sudo systemctl reload haproxy |
| 查看运行状态 |
sudo systemctl status haproxy |
| 查看监听端口 |
ss -tlnp \| grep haproxy |
| 实时查看统计 |
watch -n 1 'echo "show stat" \| socat /var/run/haproxy/admin.sock stdio' |
| 通过 socket 管理服务器 |
echo "disable server web_servers/web1" \| socat /var/run/haproxy/admin.sock stdio |
| 启用服务器 |
echo "enable server web_servers/web1" \| socat /var/run/haproxy/admin.sock stdio |
| 查看 HAProxy 版本 |
haproxy -v |
| 查看编译选项 |
haproxy -vv |
常见问题排查
| 问题现象 |
可能原因 |
解决方案 |
| 后端服务器全部标记 DOWN |
健康检查路径/端口错误 |
用 curl 测试后端健康检查接口,确认路径和端口正确 |
| 客户端请求超时 |
timeout 值过小或后端响应慢 |
增大 timeout server,或检查后端服务性能 |
| SSL 证书错误 |
证书格式不对或权限错误 |
确认 PEM 格式正确、权限 600、所属用户 haproxy |
| 连接数达到上限 |
maxconn 值太小或 ulimit 不足 |
增加 maxconn 和系统 ulimit -n |
| 日志为空 |
rsyslog 未配置或不接收 HAProxy 日志 |
检查 rsyslog 配置和 /dev/log 权限 |
| 无法绑定端口(<1024) |
非 root 用户启动 |
使用 root 启动后切换用户,或设置 CAP_NET_BIND_SERVICE |
| 后端服务器权重失效 |
使用 static-rr 算法 |
改为 roundrobin 实现动态权重 |
| WebSocket 连接断开 |
超时时间不足 |
增大 timeout tunnel,WebSocket 场景建议 1h |
最佳实践总结
- 配置语法检查先行:每次修改配置后务必执行
haproxy -c -f haproxy.cfg
- 平滑重载:使用
systemctl reload haproxy 而非 restart,避免连接中断
- 健康检查务必精准:HTTP 检查应访问真实的健康检测接口,而非首页
- 合理设置超时:根据业务场景调整 timeout 参数,WebSocket 等长连接需要较大的
timeout tunnel
- 监控页面必加认证:统计页面使用
stats auth 认证,并通过 Nginx 做 HTTPS 代理和 IP 限制
- 日志单独存放:配置 rsyslog 将 HAProxy 日志写入独立文件,便于排查
- 主机高可用:使用 Keepalived + 虚拟 IP 实现 HAProxy 自身的主备切换
- 定期更新版本:关注 HAProxy 官方安全公告,及时升级到修复安全漏洞的版本
- 连接数监控:通过 stats 页面或 socket 实时监控各后端服务器连接数
- 配置版本管理:将 haproxy.cfg 纳入 Git 管理,变更留痕
本文由AI辅助生成,内容仅供参考