HAProxy 负载均衡器部署与配置实战

一、HAProxy 概述

1.1 什么是 HAProxy

HAProxy(High Availability Proxy)是一款开源的高性能 TCP/HTTP 负载均衡器和代理服务器。它以其高可用性、高性能和稳定性著称,广泛应用于生产环境中的负载均衡场景。

1.2 核心特性

特性 说明
高性能 单实例可处理 10K+ 并发连接,延迟低于 1ms
高可用 支持健康检查、故障转移、会话保持
灵活性 支持 TCP/HTTP 负载均衡,丰富的路由规则
可观测性 内置统计页面,支持 Prometheus 指标导出
安全性 SSL/TLS 终止、IP 黑白名单、速率限制

1.3 适用场景

  • Web 应用负载均衡:HTTP/HTTPS 流量分发
  • 数据库读写分离:MySQL/PostgreSQL 连接池
  • 微服务网关:服务发现与路由
  • API 网关:限流、认证、日志
  • 高可用架构:Keepalived + HAProxy 双机热备

1.4 与其他负载均衡器对比

特性 HAProxy Nginx Traefik
HTTP 负载均衡 ✅ 优秀 ✅ 优秀 ✅ 优秀
TCP 负载均衡 ✅ 专业 ⚠️ 基础 ⚠️ 基础
动态配置 ⚠️ 需 reload ⚠️ 需 reload ✅ 自动发现
性能 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐
配置复杂度 中等 简单 简单
适用场景 专业负载均衡 Web 服务器+LB 云原生/K8s

二、HAProxy 安装部署

2.1 Ubuntu/Debian 安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 添加官方仓库
sudo apt-get update
sudo apt-get install -y software-properties-common
sudo add-apt-repository ppa:vbernat/haproxy-2.8

# 安装 HAProxy
sudo apt-get update
sudo apt-get install -y haproxy

# 验证安装
haproxy -v

# 查看服务状态
systemctl status haproxy

2.2 CentOS/RHEL 安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 添加 EPEL 仓库
sudo yum install -y epel-release

# 安装 HAProxy
sudo yum install -y haproxy

# 或者使用官方仓库
sudo yum install -y centos-release-scl
sudo yum install -y rh-haproxy18

# 验证安装
haproxy -v

# 启动服务
systemctl enable haproxy
systemctl start haproxy

2.3 Docker 部署

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 拉取镜像
docker pull haproxy:2.8

# 创建配置目录
mkdir -p /etc/haproxy

# 运行容器
docker run -d \
--name haproxy \
--restart always \
-p 80:80 \
-p 443:443 \
-p 8404:8404 \
-v /etc/haproxy:/usr/local/etc/haproxy:ro \
haproxy:2.8

2.4 Docker Compose 部署

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
# docker-compose.yml
version: '3.8'

services:
haproxy:
image: haproxy:2.8
container_name: haproxy
restart: always
ports:
- "80:80"
- "443:443"
- "8404:8404"
volumes:
- ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
- ./ssl:/etc/ssl/haproxy:ro
networks:
- haproxy-net
healthcheck:
test: ["CMD", "haproxy", "-c", "-f", "/usr/local/etc/haproxy/haproxy.cfg"]
interval: 30s
timeout: 10s
retries: 3

networks:
haproxy-net:
driver: bridge

三、配置文件详解

3.1 配置文件结构

HAProxy 配置文件位于 /etc/haproxy/haproxy.cfg,包含以下主要部分:

1
2
3
4
5
global          # 全局配置(进程级)
defaults # 默认配置(作用域级)
frontend # 前端配置(监听入口)
backend # 后端配置(服务器池)
listen # 前后端组合配置

3.2 最小可用配置

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# /etc/haproxy/haproxy.cfg

global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon

# SSL 配置
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets

defaults
log global
mode http
option httplog
option dontlognull
option forwardfor
option http-server-close
timeout connect 5s
timeout client 30s
timeout server 30s
timeout http-request 10s
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http

# 前端:监听 80 端口
frontend http_front
bind *:80
default_backend web_servers

# 后端:Web 服务器池
backend web_servers
balance roundrobin
server web1 192.168.1.10:80 check
server web2 192.168.1.11:80 check
server web3 192.168.1.12:80 check

3.3 Global 配置详解

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
27
28
global
# 日志配置
log /dev/log local0 info # 主日志
log /dev/log local1 notice # 次要日志
log-send-hostname # 日志中包含主机名

# 进程配置
chroot /var/lib/haproxy # 限制工作目录
user haproxy # 运行用户
group haproxy # 运行组
daemon # 后台运行
nbproc 1 # 进程数(建议 1,使用 nbthread 代替)
nbthread 4 # 线程数(根据 CPU 核心数设置)
cpu-map auto:1/1-4 0-3 # CPU 亲和性绑定

# 管理 Socket
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s

# 性能调优
maxconn 50000 # 最大连接数
tune.ssl.default-dh-param 2048 # SSL DH 参数大小

# SSL 默认配置
ssl-default-bind-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
ssl-default-server-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
ssl-default-server-options ssl-min-ver TLSv1.2 no-tls-tickets

3.4 Defaults 配置详解

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
27
28
29
30
31
32
defaults
log global
mode http # 模式:http|tcp|health

# 日志选项
option httplog # HTTP 详细日志
option dontlognull # 不记录空连接
option http-server-close # 服务器端关闭连接
option forwardfor # 添加 X-Forwarded-For 头
option redispatch # 服务器故障时重新分配
option abortonclose # 队列满时拒绝新连接

# 重试配置
retries 3 # 连接失败重试次数

# 超时配置(关键!)
timeout connect 5s # 连接后端超时
timeout client 30s # 客户端空闲超时
timeout server 30s # 服务器响应超时
timeout http-request 10s # HTTP 请求头超时
timeout http-keep-alive 10s # HTTP 长连接超时
timeout queue 30s # 队列等待超时
timeout tunnel 1h # WebSocket/Tunnel 超时

# 错误页面
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http

四、负载均衡算法

4.1 常用算法对比

算法 说明 适用场景
roundrobin 轮询,按顺序分配 服务器性能相近
static-rr 静态轮询,考虑权重 服务器性能有差异
leastconn 最少连接数优先 长连接场景
first 优先使用最先可用的服务器 快速故障恢复
source 基于源 IP 哈希 会话保持
uri 基于 URI 哈希 缓存服务器
url_param 基于 URL 参数哈希 特定路由需求
hdr 基于 HTTP 头哈希 自定义路由

4.2 配置示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
backend web_servers
# 轮询(默认)
balance roundrobin
server web1 192.168.1.10:80 check weight 100
server web2 192.168.1.11:80 check weight 50
server web3 192.168.1.12:80 check weight 50

backend api_servers
# 最少连接数
balance leastconn
server api1 192.168.1.20:8080 check
server api2 192.168.1.21:8080 check

backend cache_servers
# URI 哈希(相同 URI 总是路由到同一服务器)
balance uri
server cache1 192.168.1.30:6379 check
server cache2 192.168.1.31:6379 check

backend sticky_servers
# 源 IP 哈希(会话保持)
balance source
server app1 192.168.1.40:8080 check
server app2 192.168.1.41:8080 check

五、健康检查配置

5.1 HTTP 健康检查

1
2
3
4
5
6
7
8
9
10
backend web_servers
balance roundrobin

# HTTP 健康检查
option httpchk GET /health HTTP/1.1\r\nHost:\ localhost
http-check expect status 200

server web1 192.168.1.10:80 check inter 5s fall 3 rise 2
server web2 192.168.1.11:80 check inter 5s fall 3 rise 2
server web3 192.168.1.12:80 check inter 5s fall 3 rise 2

参数说明:

  • inter 5s:检查间隔 5 秒
  • fall 3:连续 3 次失败标记为下线
  • rise 2:连续 2 次成功标记为上线

5.2 TCP 健康检查

1
2
3
4
5
6
7
backend mysql_servers
balance leastconn
mode tcp

# TCP 连接检查
server mysql1 192.168.1.50:3306 check inter 10s fall 3 rise 2
server mysql2 192.168.1.51:3306 check inter 10s fall 3 rise 2

5.3 高级健康检查

1
2
3
4
5
6
7
8
9
10
11
12
13
backend api_servers
balance roundrobin
option httpchk

# 发送自定义请求头
http-check send meth GET uri /api/health ver HTTP/1.1 hdr Host api.example.com hdr Authorization "Bearer token123"

# 检查响应状态码和内容
http-check expect status 200
http-check expect string "status":"ok"

server api1 192.168.1.20:8080 check inter 5s fall 3 rise 2
server api2 192.168.1.21:8080 check inter 5s fall 3 rise 2

5.4 代理协议健康检查

1
2
3
4
5
6
backend servers_with_proxy
balance roundrobin

# 使用 PROXY 协议发送健康检查
server srv1 192.168.1.60:80 check send-proxy-v2
server srv2 192.168.1.61:80 check send-proxy-v2

六、SSL/TLS 配置

6.1 生成 SSL 证书

1
2
3
4
5
6
7
8
9
10
11
12
# 生成自签名证书(测试用)
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/ssl/haproxy/server.key \
-out /etc/ssl/haproxy/server.crt \
-subj "/C=CN/ST=Beijing/L=Beijing/O=Example/CN=example.com"

# 合并证书和私钥(HAProxy 要求)
cat /etc/ssl/haproxy/server.crt /etc/ssl/haproxy/server.key > /etc/ssl/haproxy/server.pem

# 设置权限
chmod 600 /etc/ssl/haproxy/server.pem
chown haproxy:haproxy /etc/ssl/haproxy/server.pem

6.2 HTTPS 前端配置

1
2
3
4
5
6
7
8
9
10
11
12
13
frontend https_front
bind *:443 ssl crt /etc/ssl/haproxy/server.pem alpn h2,http/1.1

# HTTP/2 支持
http-request set-header X-Forwarded-Proto https

# 安全头
http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
http-response set-header X-Frame-Options "SAMEORIGIN"
http-response set-header X-Content-Type-Options "nosniff"
http-response set-header X-XSS-Protection "1; mode=block"

default_backend web_servers

6.3 HTTP 重定向到 HTTPS

1
2
3
4
5
6
7
8
frontend http_front
bind *:80

# ACME 挑战放行(Let's Encrypt)
acl is_acme path_beg /.well-known/acme-challenge/

# 重定向到 HTTPS
http-request redirect scheme https unless is_acme

6.4 多域名 SSL 配置

1
2
3
4
5
6
7
8
9
10
11
frontend https_front
# 多证书配置(SNI)
bind *:443 ssl crt /etc/ssl/haproxy/example.com.pem \
ssl crt /etc/ssl/haproxy/api.example.com.pem \
alpn h2,http/1.1

# 根据域名路由
acl host_api hdr(host) -i api.example.com
use_backend api_servers if host_api

default_backend web_servers

七、会话保持(Stickiness)

1
2
3
4
5
6
7
8
9
backend web_servers
balance roundrobin

# 插入 Cookie
cookie SERVERID insert indirect nocache

server web1 192.168.1.10:80 check cookie web1
server web2 192.168.1.11:80 check cookie web2
server web3 192.168.1.12:80 check cookie web3

7.2 基于源 IP 的会话保持

1
2
3
4
5
6
7
8
9
backend web_servers
balance source
hash-type consistent # 一致性哈希,减少服务器变更时的影响

stick-table type ip size 100k expire 30m
stick on src

server web1 192.168.1.10:80 check
server web2 192.168.1.11:80 check

7.3 基于 URL 参数的会话保持

1
2
3
4
5
6
7
8
9
10
backend api_servers
balance uri
hash-type consistent

# 根据 user_id 参数哈希
stick-table type string size 100k expire 30m
stick on url_param(user_id)

server api1 192.168.1.20:8080 check
server api2 192.168.1.21:8080 check

八、访问控制与安全

8.1 IP 黑白名单

1
2
3
4
5
6
7
8
9
10
11
12
frontend http_front
bind *:80

# ACL 定义
acl allowed_ips src 192.168.1.0/24 10.0.0.0/8
acl blocked_ips src 1.2.3.4 5.6.7.8

# 黑名单优先
http-request deny if blocked_ips
http-request deny unless allowed_ips

default_backend web_servers

8.2 速率限制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
frontend http_front
bind *:80

# 定义 stick-table 跟踪请求速率
stick-table type ip size 100k expire 30s store http_req_rate(10s)

# 记录请求
http-request track-sc0 src

# 限制:10 秒内超过 100 次请求则拒绝
acl rate_abuse sc_http_req_rate(0) gt 100
http-request deny deny_status 429 if rate_abuse

default_backend web_servers

8.3 请求头过滤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
frontend http_front
bind *:80

# 删除敏感头
http-request del-header X-Powered-By
http-request del-header Server

# 添加安全头
http-request set-header X-Request-ID %[uuid()]

# 限制请求大小
http-request deny if { req.hdr_cnt(content-length) gt 1 }
http-request deny if { req.body_size gt 10485760 } # 10MB

default_backend web_servers

8.4 Basic Auth 认证

1
2
3
4
5
6
7
8
9
10
11
12
frontend admin_front
bind *:8080

# Basic Auth
userlist admin_users
user admin password $6$salt$hashed_password
user operator password $6$salt$hashed_password2

acl is_admin http_auth(admin_users)
http-request auth unless is_admin

default_backend admin_servers

生成密码哈希:

1
2
# 使用 openssl 生成
openssl passwd -6 "your_password"

九、统计页面配置

9.1 基础统计页面

1
2
3
4
5
6
7
# 在 defaults 或 frontend 之外添加
listen stats
bind *:8404
stats enable
stats uri /stats
stats refresh 10s
stats admin if TRUE # 启用管理功能(生产环境谨慎)

9.2 带认证的统计页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
listen stats
bind *:8404
stats enable
stats uri /stats
stats refresh 10s
stats hide-version
stats realm HAProxy\ Statistics

# Basic Auth
stats auth admin:SecurePassword123

# 仅允许特定 IP 访问
acl allowed_ips src 192.168.1.0/24
stats admin if allowed_ips

9.3 统计页面功能

访问 http://haproxy-ip:8404/stats 可查看:

  • 各 Frontend/Backend 的连接数、请求数
  • 服务器健康状态
  • 流量图表
  • 手动启用/禁用服务器
  • 清空统计计数器

十、日志配置

10.1 Rsyslog 配置

1
2
3
4
5
6
# /etc/rsyslog.d/49-haproxy.conf
local0.* /var/log/haproxy/access.log
local1.* /var/log/haproxy/admin.log

# 重启 rsyslog
systemctl restart rsyslog

10.2 HAProxy 日志格式

1
2
3
4
5
6
7
8
9
10
global
log /dev/log local0

defaults
log global
option httplog
option log-health-checks # 记录健康检查

# 自定义日志格式
log-format "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r"

10.3 日志字段说明

字段 说明
%ci 客户端 IP
%cp 客户端端口
%tr 请求接收时间
%ft 前端名称
%b 后端名称
%s 服务器名称
%ST HTTP 状态码
%B 响应字节数
%TR Tarpit 等待时间
%Tw 队列等待时间
%Tc 连接建立时间
%Tr 服务器响应时间
%Ta 总耗时

十一、性能调优

11.1 系统级调优

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# /etc/sysctl.conf
# 增加文件描述符限制
fs.file-max = 2097152

# 增加端口范围
net.ipv4.ip_local_port_range = 1024 65535

# 启用端口复用
net.ipv4.tcp_tw_reuse = 1

# 增加连接队列
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535

# 应用配置
sysctl -p

11.2 HAProxy 配置调优

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
27
global
# 增加最大连接数
maxconn 100000

# 线程数(建议与 CPU 核心数一致)
nbthread 8

# CPU 绑定
cpu-map auto:1/1-8 0-7

# 缓冲区调优
tune.bufsize 32768
tune.maxrewrite 4096

# SSL 会话缓存
ssl-cache-server 10000
ssl-cache-server-size 10485760

defaults
# 优化超时
timeout connect 3s
timeout client 60s
timeout server 60s

# 启用 HTTP 连接复用
option http-keep-alive
option http-server-close

11.3 监控指标

1
2
3
4
5
6
7
8
# 使用 socat 获取运行时统计
echo "show stat" | socat /run/haproxy/admin.sock stdio

# 关键指标
# - conn_rate: 连接速率
# - http_req_rate: HTTP 请求速率
# - sess_rate: 会话速率
# - srv_status: 服务器状态

十二、高可用架构

12.1 Keepalived + HAProxy 双机热备

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
27
28
29
# 主节点 Keepalived 配置
# /etc/keepalived/keepalived.conf

vrrp_script check_haproxy {
script "killall -0 haproxy"
interval 2
weight -50
}

vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1

authentication {
auth_type PASS
auth_pass haproxy123
}

virtual_ipaddress {
192.168.1.100/24 # VIP
}

track_script {
check_haproxy
}
}

12.2 架构示意图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
                ┌─────────────────┐
│ Virtual IP │
│ 192.168.1.100 │
└────────┬────────┘

┌────────────────┼────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐
│ HAProxy 1 │ │ HAProxy 2 │
│ (MASTER) │ │ (BACKUP) │
│ 192.168.1.10 │ │ 192.168.1.11 │
└───────┬───────┘ └───────┬───────┘
│ │
└────────┬───────┘

┌────────▼────────┐
│ Backend Servers│
│ 192.168.1.20-30│
└─────────────────┘

十三、故障排查

13.1 配置验证

1
2
3
4
5
# 检查配置文件语法
haproxy -c -f /etc/haproxy/haproxy.cfg

# 详细检查
haproxy -c -V -f /etc/haproxy/haproxy.cfg

13.2 常见问题

问题 1:后端服务器全部下线

1
2
3
4
5
6
7
8
# 检查健康检查日志
tail -f /var/log/haproxy/access.log | grep "Layer4 timeout"

# 手动测试后端
curl -v http://backend-ip:port/health

# 检查防火墙
iptables -L -n | grep backend-port

问题 2:连接超时

1
2
3
4
5
6
# 增加超时时间
timeout connect 10s
timeout server 60s

# 检查后端负载
top -p $(pgrep -d',' -f backend-process)

问题 3:SSL 握手失败

1
2
3
4
5
# 测试 SSL 连接
openssl s_client -connect haproxy-ip:443 -servername example.com

# 检查证书
openssl x509 -in /etc/ssl/haproxy/server.pem -noout -dates

13.3 调试模式

1
2
3
4
5
# 启动调试模式
haproxy -d -f /etc/haproxy/haproxy.cfg

# 或使用 strace
strace -f -e trace=network -p $(pgrep haproxy)

十四、常用命令速查

目的 命令
验证配置 haproxy -c -f /etc/haproxy/haproxy.cfg
重载配置 systemctl reload haproxy
重启服务 systemctl restart haproxy
查看状态 systemctl status haproxy
查看日志 tail -f /var/log/haproxy/access.log
运行时统计 echo "show stat" | socat /run/haproxy/admin.sock stdio
软停止服务器 echo "disable server backend/server1" | socat ...
软启动服务器 echo "enable server backend/server1" | socat ...

十五、总结

关键要点

  1. HAProxy 定位:专业的 TCP/HTTP 负载均衡器,性能卓越
  2. 配置核心:Global(全局)→ Defaults(默认)→ Frontend/Backend(前后端)
  3. 负载均衡算法:根据场景选择 roundrobin/leastconn/source 等
  4. 健康检查:配置合理的检查间隔和阈值,确保高可用
  5. SSL/TLS:正确配置证书和加密套件,保障传输安全
  6. 性能调优:系统参数 + HAProxy 参数协同优化
  7. 高可用:Keepalived + HAProxy 实现双机热备

最佳实践

  • ✅ 生产环境使用至少 2 个 HAProxy 实例
  • ✅ 配置合理的健康检查和超时时间
  • ✅ 启用统计页面并限制访问
  • ✅ 配置日志便于故障排查
  • ✅ 定期更新 HAProxy 版本获取安全补丁
  • ❌ 避免在生产环境使用 stats admin 功能
  • ❌ 不要设置过短的超时时间导致误判

参考文档:

作者: 脸脸
更新时间: 2026-03-26