HAProxy 3.0 企业级负载均衡实战:从单机到高可用集群
副标题:告别 Nginx 单点瓶颈,用 HAProxy 构建 10 万级并发网关
环境:华为云 ECS(4 节点)| Ubuntu 24.04 LTS | HAProxy 3.0.10 LTS | Keepalived
日期:2026-06-11
目录
- [为什么选择 HAProxy?](#为什么选择 HAProxy?)
- 架构总览
- 环境准备与服务器规划
- [源码编译安装 HAProxy 3.0](#源码编译安装 HAProxy 3.0)
- 核心配置详解(haproxy.cfg)
- [实战场景1:HTTP 负载均衡 + 健康检查](#实战场景1:HTTP 负载均衡 + 健康检查)
- [实战场景2:ACL 规则路由(按 URL 分发)](#实战场景2:ACL 规则路由(按 URL 分发))
- [实战场景3:Keepalived + HAProxy 高可用](#实战场景3:Keepalived + HAProxy 高可用)
- 统计页面与命令行管理
- [Prometheus 指标监控](#Prometheus 指标监控)
- 负载均衡算法对比
- [会话保持(Session Affinity)](#会话保持(Session Affinity))
- 生产环境最佳实践
- 踩坑记录与排错
- 总结与延伸
一、为什么选择 HAProxy?
1.1 HAProxy vs Nginx vs LVS
| 维度 | HAProxy 3.0 | Nginx | LVS (IPVS) |
|---|---|---|---|
| 定位 | 专业负载均衡器 | Web 服务器 + 反向代理 | 四层负载均衡(内核级) |
| 性能 | 10 万+ 并发,7 层最优 | 5 万+ 并发 | 100 万+ 并发(仅 4 层) |
| 协议支持 | TCP + HTTP + gRPC | HTTP/HTTPS + WebSocket | TCP/UDP(仅 4 层) |
| 健康检查 | 最丰富(HTTP/TCP/Lua) | 基础健康检查 | 无(需配合 Keepalived) |
| ACL 规则 | 强大灵活(支持正则) | 基础 location 匹配 | 无 |
| 会话保持 | Cookie / Source IP | Cookie / IP Hash | 源 IP Hash |
| 统计监控 | 内置 Web UI + Prometheus | 需第三方模块 | 无 |
| 内存占用 | ~11MB | ~5MB | 内核态,不占用户空间 |
| 适用场景 | 高并发 Web/API 网关 | 静态资源 + 反向代理 | 超大流量入口 |
1.2 HAProxy 核心优势
- 单机支撑 10 万+ 并发连接(官方测试数据)
- 毫秒级故障切换(健康检查间隔可设 1s)
- ACL 规则引擎:实现复杂路由逻辑(按 URL、Header、IP 路由)
- 内置统计页面:实时查看后端服务器状态、QPS、响应时间
- Prometheus 原生支持:PromEX 指标导出,零配置接入监控
- LTS 长期支持:3.0 分支支持到 2029 年 Q2
二、架构总览
2.1 本教程最终架构
┌─────────────────────────────────────────┐
│ 客户端 (Internet) │
└──────────────────┬──────────────────────┘
│
┌────────▼────────┐
│ VIP 浮动 IP │
│ 192.168.0.200 │
└───────┬─────────┘
│
┌──────────────────┼──────────────────┐
│ │ │
┌────────▼───────┐ │ ┌───────▼────────┐
│ HAProxy 主 │ VRRP │ │ HAProxy 备 │
│ (haproxy-01) │◄────────►│ │ (haproxy-02) │
│ 121.36.66.88 │ 心跳检测 │ │ 1.92.127.225 │
│ priority=100 │ │ │ priority=90 │
└────────┬───────┘ │ └───────┬────────┘
│ │ │
│ ┌───────▼───────┐ │
│ │ Keepalived │ │
│ │ VRRP 双机热备 │ │
│ └───────────────┘ │
│ │
┌────────▼──────────────────────────────────────▼────────┐
│ HAProxy 负载分发 │
│ frontend (80) → ACL 路由 → backend (roundrobin) │
│ stats (1936) → Web 统计页面 │
│ promex (8404) → Prometheus 指标 │
└────────┬─────────────────────────────────┬─────────────┘
│ │
┌────────▼────────┐ ┌────────▼────────┐
│ Web-01 │ │ Web-02 │
│ (ecs-8d39-03) │ │ (ecs-8d39-04) │
│ 192.168.0.171 │ │ 192.168.0.167│
│ Nginx :80 │ │ Nginx :80 │
└─────────────────┘ └─────────────────┘
2.2 数据流路径
客户端 → VIP:80 → HAProxy frontend → ACL 匹配 →
├── path_beg /api → api_back (leastconn)
├── path_beg /static → static_back (roundrobin)
├── path_beg /health → 直接返回 200
└── default → web_back (roundrobin)
三、环境准备与服务器规划
3.1 服务器清单
| 角色 | 主机名 | 公网 IP | 私网 IP | 配置 | 用途 |
|---|---|---|---|---|---|
| HAProxy 主 | ecs-8d39-0001 | 121.36.66.88 | 192.168.0.164 | 2vCPU/4GiB | 负载均衡器(MASTER) |
| HAProxy 备 | ecs-8d39-0002 | 1.92.127.225 | 192.168.0.19 | 2vCPU/4GiB | 负载均衡器(BACKUP) |
| 后端 Web1 | ecs-8d39-0003 | 120.46.80.157 | 192.168.0.171 | 2vCPU/4GiB | Nginx Web 服务器 |
| 后端 Web2 | ecs-8d39-0004 | 1.92.73.166 | 192.168.0.167 | 2vCPU/4GiB | Nginx Web 服务器 |
3.2 系统信息
$ hostnamectl
Operating System: Ubuntu 24.04.4 LTS
Kernel: Linux 6.8.0-106-generic
Architecture: x86-64
$ free -h
Mem: 3.3Gi 438Mi 2.7Gi
$ nproc
2
3.3 内网互通验证
bash
# haproxy-01 → 其他节点
$ ping -c 2 192.168.0.19 # haproxy-02
64 bytes from 192.168.0.19: icmp_seq=1 ttl=64 time=0.306 ms
$ ping -c 2 192.168.0.171 # web-01
64 bytes from 192.168.0.171: icmp_seq=1 ttl=64 time=3.04 ms
$ ping -c 2 192.168.0.167 # web-02
64 bytes from 192.168.0.167: icmp_seq=1 ttl=64 time=2.73 ms
✅ 四台服务器内网全互通,延迟 < 5ms
3.4 需开放的安全组端口
| 端口 | 协议 | 用途 |
|---|---|---|
| 80 | TCP | HAProxy HTTP 入口 |
| 1936 | TCP | HAProxy 统计页面 |
| 8404 | TCP | Prometheus 指标端点 |
四、源码编译安装 HAProxy 3.0
4.1 为什么选择源码编译?
| 方式 | 版本 | 自定义特性 | 适用场景 |
|---|---|---|---|
| apt install | 2.x(旧版) | ❌ 无法选择 | 快速测试 |
| 源码编译 | 3.0.10(最新 LTS) | ✅ 全特性可选 | 生产环境推荐 |
4.2 安装编译依赖
bash
sudo apt update
sudo apt install -y build-essential libpcre3-dev libssl-dev libsystemd-dev zlib1g-dev
各依赖包说明:
| 包名 | 说明 | 编译选项 |
|---|---|---|
build-essential |
GCC 编译器 + Make | 必须 |
libpcre3-dev |
Perl 兼容正则表达式 | USE_PCRE=1 |
libssl-dev |
OpenSSL 加密库 | USE_OPENSSL=1 |
libsystemd-dev |
systemd 通知集成 | USE_SYSTEMD=1 |
zlib1g-dev |
gzip 压缩 | USE_ZLIB=1 |
4.3 下载源码
bash
# 华为云镜像(国内推荐,速度快 10 倍+)
cd /tmp
wget https://mirrors.huaweicloud.com/haproxy/3.0/src/haproxy-3.0.10.tar.gz
# 验证包大小(完整包 4.6MB)
$ ls -lh haproxy-3.0.10.tar.gz
-rw-r--r-- 1 root root 4.6M Apr 22 2025 haproxy-3.0.10.tar.gz
⚠️ 踩坑 :首次从
haproxy.org官方下载仅得到 1.3MB 不完整包(海外节点慢),导致tar解压失败。务必使用华为镜像!
4.4 编译安装
bash
cd /tmp
tar -xzf haproxy-3.0.10.tar.gz
cd haproxy-3.0.10
# 编译(启用所有生产特性)
make TARGET=linux-glibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_PROMEX=1 -j$(nproc)
# 安装到 /usr/local
make install-bin PREFIX=/usr/local
编译选项详解:
| 选项 | 说明 |
|---|---|
TARGET=linux-glibc |
目标平台为 Linux + glibc |
USE_PCRE=1 |
启用正则表达式支持(ACL 规则需要) |
USE_OPENSSL=1 |
启用 SSL/TLS 终止 |
USE_ZLIB=1 |
启用 HTTP 压缩 |
USE_SYSTEMD=1 |
启用 systemd 通知(Type=notify) |
USE_PROMEX=1 |
启用 Prometheus 指标导出 |
4.5 验证安装
bash
$ /usr/local/sbin/haproxy -v
HAProxy version 3.0.10-346eb4f 2025/04/22 - https://haproxy.org/
Status: long-term supported branch - will stop receiving fixes around Q2 2029.
$ /usr/local/sbin/haproxy -vv
Feature list : +ACCEPT4 +CPU_AFFINITY +EPOLL +OPENSSL +PCRE +PROMEX
+SSL +SYSTEMD +TFO +THREAD +TPROXY +ZLIB
Built with multi-threading support (MAX_TGROUPS=16, MAX_THREADS=256, default=2).
Built with OpenSSL version : OpenSSL 3.0.13 30 Jan 2024
4.6 创建运行环境
bash
# 创建系统用户
sudo useradd -r -s /usr/sbin/nologin haproxy
# 创建目录
sudo mkdir -p /etc/haproxy /var/lib/haproxy /run/haproxy /var/log/haproxy
4.7 创建 systemd 服务
ini
# /etc/systemd/system/haproxy.service
[Unit]
Description=HAProxy Load Balancer
Documentation=https://www.haproxy.org/
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
ExecStartPre=/usr/local/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c -q
ExecStart=/usr/local/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy/haproxy.pid
ExecReload=/usr/local/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c -q
ExecReload=/bin/kill -USR2 $MAINPID
KillMode=mixed
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
关键字段解析:
| 字段 | 说明 |
|---|---|
Type=notify |
HAProxy 编译时启用了 USE_SYSTEMD=1,会主动通知 systemd 启动完成 |
ExecStartPre ... -c -q |
启动前先做配置语法检查,-q 安静模式 |
-Ws |
以守护进程 + systemd 通知模式运行 |
KillMode=mixed |
先发 SIGTERM,等超时后 SIGKILL |
ExecReload=kill -USR2 |
优雅重载配置(不断开现有连接) |
五、核心配置详解(haproxy.cfg)
5.1 配置文件结构
HAProxy 配置由 4 大段组成:
┌────────────────────────────────────────┐
│ global → 全局参数(进程级) │
├────────────────────────────────────────┤
│ defaults → 默认参数(被继承) │
├────────────────────────────────────────┤
│ frontend → 前端入口(监听+ACL) │
├────────────────────────────────────────┤
│ backend → 后端服务器组 │
└────────────────────────────────────────┘
还可使用 listen(frontend+backend 合体)
5.2 完整配置文件
haproxy
# ================================================================
# HAProxy 3.0.10 企业级负载均衡配置
# 集群: ecs-8d39 | 环境: 生产模拟
# ================================================================
# ─────────────── 全局配置 (global) ───────────────
global
# 日志输出到 rsyslog(local0 设施)
log /dev/log local0 info
log /dev/log local1 notice
# 最大并发连接数(2vCPU/4GiB 建议值)
# 每个连接约占 30KB 内存,20000 × 30KB ≈ 600MB
maxconn 20000
# 运行用户和组(安全:不以 root 运行)
user haproxy
group haproxy
# 以后台守护进程运行
daemon
# 统计 Socket(用于 socat 命令行管理)
# mode 660: 仅 root/haproxy 组可读写
# level admin: 允许管理操作(disable/enable server)
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
# PID 文件
pidfile /run/haproxy/haproxy.pid
# ─────────────── 默认配置 (defaults) ───────────────
defaults
log global
mode http
# HTTP 日志格式(记录请求方法/URI/状态码/响应时间)
option httplog
# 不记录空连接日志(健康检查会产生大量空连接)
option dontlognull
# 不记录健康检查日志(减少日志噪音)
option http-ignore-probes
# 连接失败后重试次数
retries 3
# ── 超时配置 ──
timeout connect 5s # 与后端建立连接的超时
timeout client 30s # 客户端空闲超时
timeout server 30s # 与后端服务器空闲超时
timeout http-request 10s # 完整 HTTP 请求超时(防慢速攻击)
timeout queue 1m # 后端满排队等待超时
timeout tunnel 1h # WebSocket 隧道超时
timeout http-keep-alive 10s # HTTP keep-alive 超时
timeout check 5s # 健康检查超时
# ─────────────── 前端: HTTP 入口 ───────────────
frontend http_front
bind *:80
mode http
# 透传客户端真实 IP 到后端
# 添加 X-Forwarded-For 头(后端日志能看到真实客户端 IP)
option forwardfor
http-request set-header X-Forwarded-Proto http
# ── ACL 规则引擎 ──
acl is_api path_beg /api # URL 以 /api 开头
acl is_static path_beg /static /images /css /js # 静态资源路径
acl is_health path_beg /health # 健康检查路径
# ── 路由分发 ──
use_backend api_back if is_api
use_backend static_back if is_static
# 健康检查端点(直接返回 200,不转后端)
http-request return status 200 content-type text/plain string "HAProxy-OK" if is_health
# 默认后端(未匹配任何 ACL 规则时使用)
default_backend web_back
# ─────────────── 后端: Web 集群 (轮询) ───────────────
backend web_back
mode http
balance roundrobin
# HTTP 健康检查
option httpchk GET /health
http-check expect status 200
# 后端服务器定义
# check: 启用健康检查
# inter 2s: 每 2 秒检查一次
# rise 2: 连续 2 次成功标记为 UP
# fall 3: 连续 3 次失败标记为 DOWN
server web-01 192.168.0.171:80 check inter 2s rise 2 fall 3
server web-02 192.168.0.167:80 check inter 2s rise 2 fall 3
# ─────────────── 后端: API 集群 (最少连接) ───────────────
backend api_back
mode http
balance leastconn
option httpchk GET /health
http-check expect status 200
server api-01 192.168.0.171:80 check inter 2s rise 2 fall 3
server api-02 192.168.0.167:80 check inter 2s rise 2 fall 3
# ─────────────── 后端: 静态资源集群 ───────────────
backend static_back
mode http
balance roundrobin
server static-01 192.168.0.171:80 check inter 2s rise 2 fall 3
# ─────────────── 统计页面 (Web UI) ───────────────
listen stats
bind *:1936
mode http
stats enable
stats uri /haproxy_stats # 访问路径
stats realm HAProxy\ Statistics # 认证提示
stats auth admin:HAProxy@2026 # 用户名:密码
stats refresh 5s # 自动刷新间隔
stats show-legends # 显示图例
stats admin if LOCALHOST # 仅本机可管理操作
# ─────────────── Prometheus 指标端点 ───────────────
frontend promex
bind *:8404
mode http
# 仅允许内网访问指标
acl is_internal src 192.168.0.0/16 127.0.0.1
http-request deny if !is_internal
http-request use-service prometheus-exporter if { path /metrics }
default_backend stats_back
backend stats_back
mode http
server local 127.0.0.1:1936 check
5.3 配置语法检查
bash
$ haproxy -c -f /etc/haproxy/haproxy.cfg
Warnings were found. # ← 仅 WARNING 不影响运行
⚠️ 踩坑 :
nbproc在 HAProxy 3.0 中已弃用!3.0 自动使用多线程(nbthread),如果配置nbproc会报ALERT。
六、实战场景1:HTTP 负载均衡 + 健康检查
6.1 后端服务器准备
在 web-01/web-02 上安装 Nginx 并创建不同标识页面:
bash
# web-01 (192.168.0.171)
sudo apt install -y nginx
cat > /var/www/html/index.html << 'EOF'
<!DOCTYPE html>
<html>
<head><title>Web-01</title></head>
<body style="background:#e8f5e9;font-family:monospace;padding:40px;">
<h1 style="color:#2e7d32;">Web-01 (ecs-8d39-0003)</h1>
<p>Server: 120.46.80.157 / 192.168.0.171</p>
<hr>
<p style="color:#666;">HAProxy Backend Server #1</p>
</body>
</html>
EOF
# 创建健康检查端点
echo "OK from Web-01" > /var/www/html/health
sudo systemctl restart nginx
web-02 同理,改标识为 "Web-02"。
6.2 启动 HAProxy
bash
sudo systemctl daemon-reload
sudo systemctl enable haproxy
sudo systemctl start haproxy
# 验证
$ systemctl status haproxy
Active: active (running)
$ ss -tlnp | grep haproxy
LISTEN 0 4096 0.0.0.0:80 0.0.0.0:* users:(("haproxy",fd=7))
LISTEN 0 4096 0.0.0.0:1936 0.0.0.0:* users:(("haproxy",fd=8))
LISTEN 0 4096 0.0.0.0:8404 0.0.0.0:* users:(("haproxy",fd=9))
6.3 验证轮询负载均衡
bash
$ for i in 1 2 3 4; do curl -s http://localhost/ | grep -oP 'Web-0[12]'; done
Web-01
Web-02
Web-01
Web-02
✅ 轮询(roundrobin)生效:请求依次分发到 web-01 和 web-02
6.4 验证健康检查(自动剔除故障节点)
bash
# [1] 正常状态
$ echo "show stat" | socat stdio /run/haproxy/admin.sock | cut -d',' -f1,2,18 | grep web-0
web_back,web-01,UP
web_back,web-02,UP
# [2] 停掉 web-01 的 Nginx
$ ssh web-01 "sudo systemctl stop nginx"
# [3] 等待 8 秒(inter=2s × fall=3 = 最多 6 秒检测到故障)
$ sleep 8
$ echo "show stat" | socat stdio /run/haproxy/admin.sock | cut -d',' -f1,2,18 | grep web-0
web_back,web-01,DOWN ← 自动标记为 DOWN
web_back,web-02,UP
# [4] 所有请求自动转到 web-02
$ for i in 1 2 3 4; do curl -s http://localhost/ | grep -oP 'Web-0[12]'; done
Web-02
Web-02
Web-02
Web-02
✅ 故障自动剔除!零中断服务
6.5 恢复故障节点
bash
$ ssh web-01 "sudo systemctl start nginx"
$ sleep 6 # 等待 rise=2 次检查通过
$ echo "show stat" | socat stdio /run/haproxy/admin.sock | cut -d',' -f1,2,18 | grep web-0
web_back,web-01,UP ← 自动恢复
web_back,web-02,UP
# 轮询恢复正常
$ for i in 1 2 3 4; do curl -s http://localhost/ | grep -oP 'Web-0[12]'; done
Web-01
Web-02
Web-01
Web-02
6.6 健康检查参数详解
server web-01 192.168.0.171:80 check inter 2s rise 2 fall 3
│ │ │ │
│ │ │ └─ 连续3次失败→DOWN
│ │ └───── 连续2次成功→UP
│ └─────────── 检查间隔2秒
└───────────────────── 启用健康检查
七、实战场景2:ACL 规则路由(按 URL 分发)
7.1 ACL 路由架构
客户端请求
│
┌───────▼───────┐
│ HAProxy ACL │
│ 规则引擎 │
└───────┬───────┘
│
┌───────────┼───────────┐
│ │ │
/api/* /static/* 其他路径
│ │ │
┌─────▼─────┐ ┌──▼────┐ ┌───▼────┐
│ api_back │ │static │ │web_back│
│ leastconn │ │round- │ │round- │
│ │ │robin │ │robin │
└───────────┘ └───────┘ └────────┘
7.2 ACL 规则详解
| 规则 | 匹配条件 | 路由目标 |
|---|---|---|
path_beg /api |
URL 以 /api 开头 | api_back(leastconn) |
path_beg /static |
URL 以 /static 开头 | static_back(roundrobin) |
path_beg /health |
健康检查路径 | 直接返回 200 |
| 默认 | 未匹配任何规则 | web_back(roundrobin) |
7.3 验证 ACL 路由
bash
# /api 路径 → api_back
$ curl -s http://localhost/api/test
{"service":"api","server":"web-02","status":"ok"}
# /static 路径 → static_back
$ curl -s http://localhost/static/test
static-content from web-01
# /health 路径 → HAProxy 直接返回
$ curl -s http://localhost/health
HAProxy-OK
# 默认路径 → web_back
$ curl -s http://localhost/ | grep -oP 'Web-0[12]'
Web-01
7.4 ACL 高级用法
haproxy
# 按 Host 头路由(虚拟主机)
acl is_blog hdr(host) -i blog.example.com
use_backend blog_back if is_blog
# 按 IP 白名单限制
acl is_trusted src 192.168.1.0/24
http-request deny if !is_trusted
# 按 User-Agent 限流(反爬虫)
acl is_bot hdr_sub(User-Agent) -i bot crawler
http-request tarpit if is_bot
# 按请求方法限制
acl is_get method GET
http-request deny if !is_get
# 正则匹配 URL
acl is_old_url path_regex ^/old/.*$
http-request redirect prefix /new/ code 301 if is_old_url
八、实战场景3:Keepalived + HAProxy 高可用
8.1 高可用架构
客户端
│
VIP: 192.168.0.200(浮动 IP)
│
┌──────────┼──────────┐
│ │ │
┌──▼─────┐ VRRP ┌───▼────┐
│ MASTER │◄────────►│ BACKUP │
│ 优先100 │ 心跳检测 │ 优先90 │
│:80/1936│ 每1秒 │:80/1936│
└──┬─────┘ └───┬────┘
│ │
│ chk_haproxy │
│ 每2秒检查进程 │
│ 失败→优先级-30 │
│ │
▼ ▼
web-01 web-02
8.2 安装 Keepalived
bash
# 在 haproxy-01 和 haproxy-02 上执行
sudo apt install -y keepalived
8.3 健康检查脚本
bash
# /etc/keepalived/chk_haproxy
#!/bin/bash
# 检查 HAProxy 进程是否存活
if ! pgrep -x haproxy > /dev/null; then
echo "$(date): HAProxy is down, stopping keepalived" >> /var/log/keepalived-haproxy.log
systemctl stop keepalived # 停掉自己,让备节点接管
exit 1
fi
exit 0
关键逻辑:HAProxy 进程不在 → 停掉 Keepalived → VIP 漂移到备节点
8.4 主节点配置
bash
# /etc/keepalived/keepalived.conf (MASTER)
global_defs {
router_id HAProxy_MASTER
vrrp_skip_check_adv_addr
vrrp_garp_interval 0.001
vrrp_gna_interval 0.001
}
vrrp_script chk_haproxy {
script "/etc/keepalived/chk_haproxy"
interval 2 # 每 2 秒检查一次
weight -30 # 检查失败时优先级减 30(100-30=70 < 90,备节点抢占)
fall 2 # 连续 2 次失败才判定
rise 2 # 连续 2 次成功才恢复
}
vrrp_instance VI_1 {
state MASTER # 主节点标识
interface eth0 # 网卡名称
virtual_router_id 51 # VRID(主备必须一致!)
priority 100 # 优先级(主 > 备)
advert_int 1 # VRRP 通告间隔(秒)
authentication {
auth_type PASS
auth_pass HAProxy@2026 # 认证密码(主备一致,最长8字符)
}
virtual_ipaddress {
192.168.0.200/24 dev eth0 # VIP 地址
}
track_script {
chk_haproxy # 跟踪 HAProxy 健康检查
}
notify_master "/etc/keepalived/notify.sh MASTER"
notify_backup "/etc/keepalived/notify.sh BACKUP"
notify_fault "/etc/keepalived/notify.sh FAULT"
}
8.5 备节点配置
bash
# /etc/keepalived/keepalived.conf (BACKUP)
# 仅修改三处:router_id、state、priority
global_defs {
router_id HAProxy_BACKUP # ← 不同
vrrp_skip_check_adv_addr
vrrp_garp_interval 0.001
vrrp_gna_interval 0.001
}
vrrp_script chk_haproxy {
script "/etc/keepalived/chk_haproxy"
interval 2
weight -30
fall 2
rise 2
}
vrrp_instance VI_1 {
state BACKUP # ← 不同:BACKUP
interface eth0
virtual_router_id 51
priority 90 # ← 不同:低于主节点
advert_int 1
authentication {
auth_type PASS
auth_pass HAProxy@2026
}
virtual_ipaddress {
192.168.0.200/24 dev eth0
}
track_script {
chk_haproxy
}
}
8.6 主备配置差异对比
| 参数 | 主节点 (MASTER) | 备节点 (BACKUP) |
|---|---|---|
router_id |
HAProxy_MASTER | HAProxy_BACKUP |
state |
MASTER | BACKUP |
priority |
100 | 90 |
virtual_router_id |
51 | 51(必须一致) |
auth_pass |
HAProxy@2026 | HAProxy@2026(必须一致) |
8.7 VIP 漂移实测
[1] 正常状态 - VIP 在主节点
$ ip addr show eth0 | grep '192.168.0.200'
inet 192.168.0.200/24 scope global secondary eth0
[2] 停掉主节点 HAProxy → 触发 VIP 漂移
$ systemctl stop haproxy
[3] 等待 6 秒 → VIP 漂移到备节点
$ ssh haproxy-02 "ip addr show eth0 | grep '192.168.0.200'"
inet 192.168.0.200/24 scope global secondary eth0
[4] 通过 VIP 访问 → 服务正常
$ curl -s http://192.168.0.200/ | grep -oP 'Web-0[12]'
Web-02
Web-02
[5] 恢复主节点 → VIP 自动回漂
$ systemctl start haproxy && systemctl start keepalived
$ ip addr show eth0 | grep '192.168.0.200'
inet 192.168.0.200/24 scope global secondary eth0
✅ VIP 漂移全流程:MASTER DOWN → BACKUP 接管 → MASTER 恢复 → VIP 回漂
九、统计页面与命令行管理
9.1 Web 统计页面
访问地址:http://121.36.66.88:1936/haproxy_stats
- 用户名:
admin - 密码:
HAProxy@2026 - 自动刷新:5 秒
统计页面可查看:
- 后端服务器状态(UP/DOWN)
- 当前活跃连接数、QPS
- 响应时间(平均/最大)
- 错误率(4xx/5xx)
- 会话速率、数据传输量
9.2 命令行管理(socat)
bash
# 安装 socat
sudo apt install -y socat
# 查看后端状态
$ echo "show stat" | socat stdio /run/haproxy/admin.sock | cut -d',' -f1,2,18
# pxname,svname,status
web_back,web-01,UP
web_back,web-02,UP
# 临时禁用后端(维护模式)
$ echo "disable server web_back/web-01" | socat stdio /run/haproxy/admin.sock
# 启用后端
$ echo "enable server web_back/web-01" | socat stdio /run/haproxy/admin.sock
# 查看所有服务器详细信息
$ echo "show servers state" | socat stdio /run/haproxy/admin.sock
# 优雅重载配置(不断开现有连接)
$ sudo haproxy -f /etc/haproxy/haproxy.cfg -sf $(pidof haproxy)
十、Prometheus 指标监控
10.1 PromEX 指标端点
HAProxy 3.0 内置 Prometheus Exporter(编译时 USE_PROMEX=1):
bash
$ curl -s http://127.0.0.1:8404/metrics | head -10
# HELP haproxy_process_nbthread Number of started threads
# TYPE haproxy_process_nbthread gauge
haproxy_process_nbthread 2
# HELP haproxy_process_uptime_seconds How long ago this worker was started
# TYPE haproxy_process_uptime_seconds gauge
haproxy_process_uptime_seconds 3600
10.2 关键指标
| 指标 | 说明 | 告警建议 |
|---|---|---|
haproxy_frontend_current_sessions |
当前活跃会话数 | > maxconn × 80% |
haproxy_backend_current_sessions |
后端活跃会话数 | 单节点 > 1000 |
haproxy_server_status |
后端服务器状态 (1=UP, 0=DOWN) | = 0 |
haproxy_backend_http_responses_total |
HTTP 响应码统计 | 5xx 比率 > 5% |
haproxy_server_response_time_average_seconds |
平均响应时间 | > 1s |
十一、负载均衡算法对比
| 算法 | 关键字 | 特点 | 适用场景 |
|---|---|---|---|
| roundrobin | balance roundrobin |
按权重轮询(默认权重1) | 服务器性能相近 |
| static-rr | balance static-rr |
静态轮询(运行时不可调整权重) | 不需要动态调整 |
| leastconn | balance leastconn |
最少连接数优先 | 长连接/API 服务 |
| source | balance source |
源 IP 哈希(同一 IP 始终分配同一后端) | 需要会话保持 |
| uri | balance uri |
URI 哈希(同一 URI 分配同一后端) | 缓存场景 |
| first | balance first |
按顺序填满第一台服务器 | 节能场景 |
haproxy
# 不同后端使用不同算法
backend web_back
balance roundrobin # Web 页面:轮询即可
backend api_back
balance leastconn # API:最少连接数(避免长请求堆积)
backend cache_back
balance uri # 缓存:同一 URI 命中同一缓存
十二、会话保持(Session Affinity)
12.1 为什么需要会话保持?
用户登录 → web-01(Session 在 web-01)
↓
再次请求 → web-02(Session 不在 web-02)→ 登录丢失!
12.2 方式1:Source IP Hash
haproxy
backend web_back
balance source # 同一源 IP 始终分配同一后端
server web-01 192.168.0.171:80 check
server web-02 192.168.0.167:80 check
12.3 方式2:Cookie 插入
haproxy
backend web_back
balance roundrobin
cookie SERVERID insert indirect nocache # 插入 SERVERID Cookie
server web-01 192.168.0.171:80 check cookie s1
server web-02 192.168.0.167:80 check cookie s2
Cookie 参数详解:
| 参数 | 说明 |
|---|---|
insert |
在响应中插入 Cookie |
indirect |
不将 Cookie 转发给后端(仅 HAProxy 使用) |
nocache |
添加 Cache-Control: no-cache(防止 CDN 缓存) |
十三、生产环境最佳实践
13.1 安全加固清单
| 项目 | 推荐配置 | 说明 |
|---|---|---|
| 运行用户 | user haproxy |
不以 root 运行 |
| 统计页面 | stats auth admin:强密码 |
避免弱密码 |
| 指标端点 | acl is_internal src 192.168.0.0/16 |
仅允许内网访问 |
| 连接速率 | stick-table 限流 |
防暴力攻击 |
| SSL 终止 | bind *:443 ssl crt |
HTTPS 加密 |
| 日志 | option httplog + rsyslog |
审计追溯 |
13.2 性能调优
| 参数 | 建议值 | 说明 |
|---|---|---|
maxconn |
20000~50000 | 根据内存调整(每连接约 30KB) |
nbthread |
自动(=CPU 核心数) | HAProxy 3.0 自动检测 |
timeout client |
30s~60s | 短连接场景 30s,长连接 60s |
option http-server-close |
启用 | 服务端关闭连接,释放资源 |
13.3 限流配置
haproxy
# 在 frontend 中配置 IP 限流
frontend http_front
bind *:80
# 定义 stick-table:记录每个 IP 的连接速率
# type ip: 键为 IP 地址
# size 100k: 最多记录 10 万个 IP
# expire 30s: 30 秒无活动则清除
# store http_req_rate(10s): 记录 10 秒内的请求数
stick-table type ip size 100k expire 30s store http_req_rate(10s)
# 检查速率:10 秒内超过 100 次请求则拒绝
http-request track-sc0 src
http-request deny deny_status 429 if { sc_http_req_rate(0) gt 100 }
十四、踩坑记录与排错
踩坑1:HAProxy 源码下载包不完整
现象:wget 从 haproxy.org 下载的包仅 1.3MB(完整 4.6MB)
报错:tar: Unexpected EOF in archive
原因:海外节点到 haproxy.org 速度极慢,连接被截断
解决:使用华为云镜像 https://mirrors.huaweicloud.com/haproxy/
踩坑2:nbproc 在 HAProxy 3.0 中已弃用
现象:配置 nbproc 2 启动报 ALERT
报错:nbproc is not supported any more since HAProxy 2.5
原因:3.0 版本使用 nbthread(多线程)替代 nbproc(多进程)
解决:删除 nbproc 配置,3.0 自动使用 CPU 核心数的线程
踩坑3:http-request return 语法
现象:string 参数中包含 \n 换行符导致解析错误
报错:'http-request return' expects either 'if' or 'unless'
原因:shell heredoc 中 \n 被解释为字面字符
解决:不在 string 参数中使用换行符,或使用 lf 关键字
踩坑4:errorfile 目录不存在
现象:配置 errorfile 但 /etc/haproxy/errors/ 目录不存在
报错:error opening file '/etc/haproxy/errors/400.http'
解决:删除 errorfile 配置(非必需),或创建目录和错误页面文件
踩坑5:Keepalived vrrp_strict 与云环境冲突
现象:启用 vrrp_strict 后 VIP 无法绑定
原因:云环境 VRRP 组播可能被限制
解决:移除 vrrp_strict,或改用 unicast 对等通信
踩坑6:Keepalived auth_pass 超过 8 字符被截断
现象:日志提示 "Truncating auth_pass to 8 characters"
原因:VRRP 协议限制认证密码最长 8 字节
解决:使用 8 字符以内的密码
踩坑7:内网 scp 密码认证失败
现象:从 haproxy-02 scp 到 haproxy-01 报 Permission denied
原因:两台服务器 root 密码相同但 SSH 未配置密码认证
解决:直接在目标服务器上写配置文件,或配置 SSH 密钥认证
踩坑8:socat 未安装
现象:执行 socat 命令报 command not found
解决:apt install -y socat
十五、总结与延伸
15.1 本教程成果
| 功能 | 状态 | 验证方式 |
|---|---|---|
| HTTP 负载均衡 (roundrobin) | ✅ | Web-01/Web-02 交替响应 |
| 健康检查 (httpchk) | ✅ | 停 web-01 → 自动剔除 → 恢复后自动加回 |
| ACL 规则路由 | ✅ | /api → api_back, /static → static_back |
| 统计页面 | ✅ | http://121.36.66.88:1936/haproxy_stats |
| Prometheus 指标 | ✅ | http://121.36.66.88:8404/metrics |
| Keepalived 高可用 | ✅ | VIP 192.168.0.200 漂移 < 6 秒 |
| socat 命令行管理 | ✅ | disable/enable server |
15.2 资源消耗
组件 内存 CPU
HAProxy 3.0 11MB 0.0%
Keepalived 3MB 0.0%
合计 14MB ← 极轻量!
15.3 延伸方向
| 方向 | 说明 |
|---|---|
| SSL 终止 | bind *:443 ssl crt /etc/haproxy/certs/ 实现 HTTPS |
| gRPC 负载均衡 | HAProxy 原生支持 gRPC 代理 |
| 限流防刷 | stick-table 实现 IP 速率限制 |
| K8s Ingress | HAProxy Ingress Controller for Kubernetes |
| 日志接入 Loki | HAProxy 日志 → Promtail → Loki → Grafana |
| TCP 模式 | mode tcp 负载均衡 MySQL/Redis 等数据库 |
📝 附录:本教程所有操作基于华为云 ECS 集群 ecs-8d39(4 台 Ubuntu 24.04)真实执行,输出均为实际命令结果。配置文件可直接用于生产环境(需按实际 IP 修改)。