在香港服务器中如何部署 HAProxy 多节点集群,提升跨境商城站点的高并发处理能力
技术教程 2025-09-16 09:25 299


凌晨 2:40,我被监控的电话吵醒。香港机房的接入带宽冲到顶,商城站点(面向内地用户)在秒杀会场开启后的 3 分钟内,TLS 握手时延从 30ms 飙到 200ms,部分页面出现 502。那一刻我很清楚:单点或“主备式”的 HAProxy 已经扛不住双十一/黑五的并发洪峰,必须把入口层重构为多节点、可横向扩展、就地容灾的架构。

这篇文章就是我后来在香港机房从零搭建 HAProxy 多节点集群的完整复盘与操作手册。我把过程中的细节、坑点、以及每一个“现场热修”的动作都写进去:不止能跑起来,还要跑得稳、跑得久、跑得快。

目标架构(概览)

  • 地域与线路:香港单机房为主(BGP/CN2/GIA 线路优先,优化内地访问时延与丢包)。
  • 入口层:3 台 HAProxy 节点,双 VIP 的 VRRP 设计(Active-Active:A 组与 B 组各一套 VIP,DNS 返回双 A 记录做流量分摊)。
  • 后端应用:多台 Nginx/App(10.10.20.0/24),支持健康检查与弹性扩容。
  • 会话策略:建议无状态(JWT/Redis),HAProxy 层可选基于 Cookie 的一致性哈希。
  • 可观测性:HAProxy stats socket + Prometheus Exporter + 集中日志。
  • 灰度/热更新:零停机 reload,分批滚动。
ASCII 示意:

              +----------------- 公网 DNS (双A记录, TTL 30s) -----------------+
              |                                                               |
     shop.example.com ---> VIP-A (10.10.10.100)             VIP-B (10.10.10.101)
                         VRRP@node1,node2                     VRRP@node2,node3
                              |                                     |
                              v                                     v
                           [HAProxy node1]                      [HAProxy node3]
                               |                                     |
                               +------------------+------------------+
                                                  |
                                              [HAProxy node2]
                                                  |
                                     +------------+------------+
                                     |   Nginx/App 节点池      |
                                     | 10.10.20.11 .12 .13 ... |
                                     +-------------------------+

硬件与网络选型(香港机房)

角色 机型/CPU 内存 磁盘 网卡 备注
HAProxy 节点 ×3 Intel Xeon E-2288G(8C/16T)或同级别 32–64G NVMe 480–960G ×2 2×10GbE(多队列,支持 RSS/RPS) 入口层 TLS/HTTP2 压力大,频繁上下文切换,CPU 主频更重要
Nginx/App 池 Intel Xeon Silver/Gold 64G+ NVMe RAID1/DP 2×10GbE 靠近 HA 节点,同 VLAN 或低延二层
线路 BGP / CN2 GIA/CTGNet 优先 跨境丢包敏感,优先选质量与稳定性

建议:入口层更看重高主频、网卡队列、中断亲和与内核网络栈,存储不是瓶颈。

IP 规划

说明 地址/网段
管理网段 10.10.0.0/24
前端 VIP-A 10.10.10.100/24
前端 VIP-B 10.10.10.101/24
HA 节点 10.10.10.11(node1)、.12(node2)、.13(node3)
后端池 10.10.20.0/24

系统与版本

  • OS:CentOS 7.9(用户曾要求统一到 CentOS 7)
  • 内核:建议升级到 ELRepo 的 kernel-ml 5.4+,方便开启 BBR/优化 TCP(CentOS 7 默认 3.10 在高并发+TLS 下吃亏)
  • HAProxy:2.8 LTS(线程模型成熟,HTTP/2、cache、stick-table 完备)
  • Keepalived:2.2+(支持 VRRP,unicast 友好)
  • OpenSSL:1.1.1 或 3.0(握手性能、TLS1.3)

一、系统准备与内核优化

1)基础环境

# 时区与时间同步
timedatectl set-timezone Asia/Hong_Kong
yum install -y chrony && systemctl enable --now chronyd

# 基础仓库
yum install -y epel-release yum-utils
yum-config-manager --add-repo https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm
yum install -y https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm

2)升级内核(可选但强烈建议)

yum --enablerepo=elrepo-kernel install -y kernel-ml
grub2-set-default 0 && reboot
# 重启后确认
uname -r

3)内核网络栈调优(/etc/sysctl.d/99-hk-haproxy.conf)

cat >/etc/sysctl.d/99-hk-haproxy.conf <<'EOF'
# 提升并发连接与队列
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 250000
net.ipv4.tcp_max_syn_backlog = 262144

# TIME_WAIT/重用
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_tw_reuse = 1

# 端口范围
net.ipv4.ip_local_port_range = 10000 65000

# BBR(需要 4.9+ 内核)
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr

# RPF 注意:VRRP 会导致非对称路径,建议关闭严格 RPF
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0

# 关闭透明大页
vm.nr_hugepages = 0
EOF

sysctl --system

4)网卡与中断亲和

# 禁止 irqbalance(或保守模式)
systemctl stop irqbalance && systemctl disable irqbalance

# 查看队列与分配 CPU 中断亲和(示例,实际以 /proc/interrupts 为准)
ethtool -l eth0
# 将 RSS 队列中断绑核(示例:绑到 0-7 号核)
for i in /proc/irq/*/smp_affinity_list; do echo 0-7 > $i 2>/dev/null; done

现场经验:入口层 TLS+HTTP2 会触发大量小包与上下文切换,“多队列+中断亲和”能明显压低抖动;irqbalance 在强绑核策略下反而会打乱亲和,建议关掉或保守配置。

二、安装 HAProxy 2.8 LTS(CentOS 7)

CentOS 7 官方仓库版本过旧,建议源码安装(或使用社区可靠的 RPM 仓库)。下面以源码为例:

# 构建依赖
yum groupinstall -y "Development Tools"
yum install -y pcre2-devel zlib-devel systemd-devel lua-devel
# OpenSSL 建议 1.1.1/3.0:可以自编译并安装到 /usr/local/openssl
# 或启用兼容包,本文示例假定头文件可用

# 下载与编译
cd /usr/local/src
curl -LO https://www.haproxy.org/download/2.8/src/haproxy-2.8.5.tar.gz
tar xf haproxy-2.8.5.tar.gz && cd haproxy-2.8.5

make TARGET=linux-glibc \
     USE_SYSTEMD=1 USE_LUA=1 USE_PCRE2=1 USE_ZLIB=1 USE_OPENSSL=1 \
     CPU=native
make install

# 创建运行用户与目录
useradd -r -s /sbin/nologin haproxy
mkdir -p /etc/haproxy /var/lib/haproxy /var/log/haproxy
chown -R haproxy:haproxy /var/lib/haproxy

systemd 单元:/etc/systemd/system/haproxy.service

[Unit]
Description=HAProxy Load Balancer
After=network.target syslog.target

[Service]
Environment="CONFIG=/etc/haproxy/haproxy.cfg"
ExecStartPre=/usr/local/sbin/haproxy -f $CONFIG -c -q
ExecStart=/usr/local/sbin/haproxy -Ws -f $CONFIG -p /run/haproxy.pid
ExecReload=/usr/local/sbin/haproxy -Ws -f $CONFIG -p /run/haproxy.pid -sf $(cat /run/haproxy.pid)
User=haproxy
Group=haproxy
LimitNOFILE=100000
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target

三、Keepalived(VRRP 双 VIP 设计)

目标:用两套 VRRP 实例(VI_A、VI_B)分别保护 VIP-A 与 VIP-B,分布在 3 台节点上,从而实现 Active-Active 的前端能力(DNS 返回两个 A 记录,客户端会自然分摊)。

通信:香港机房多数是 L2 可达,也可用 unicast(避免多播限制)。

安装与配置:

yum install -y keepalived

/etc/keepalived/keepalived.conf(以 node1 为例,node2、node3 分别调整 priority 与 track_script)

vrrp_script chk_haproxy {
    script "pidof haproxy"
    interval 2
    weight -20
}

# VIP-A 由 node1 优先
vrrp_instance VI_A {
    state MASTER
    interface eth0
    virtual_router_id 10
    priority 120
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass S3cr3tA
    }
    virtual_ipaddress {
        10.10.10.100/24 dev eth0
    }
    unicast_src_ip 10.10.10.11
    unicast_peer {
        10.10.10.12
        10.10.10.13
    }
    track_script {
        chk_haproxy
    }
}

# VIP-B 在 node1 做 BACKUP
vrrp_instance VI_B {
    state BACKUP
    interface eth0
    virtual_router_id 11
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass S3cr3tB
    }
    virtual_ipaddress {
        10.10.10.101/24 dev eth0
    }
    unicast_src_ip 10.10.10.11
    unicast_peer {
        10.10.10.12
        10.10.10.13
    }
    track_script {
        chk_haproxy
    }
}

node2 上让 VI_B 优先(priority 高于其他),node3 做两个实例的次备。这样两套 VIP 分别有各自的 Master,天然实现 Active-Active。

四、HAProxy 配置精讲(HTTP/2、TLS、限流、后端健康)

/etc/haproxy/haproxy.cfg(关键片段,按需调整)

global
    log /dev/log local0
    log /dev/log local1 notice
    user haproxy
    group haproxy
    daemon
    # 线程模式(比多进程易用、共享监听),结合高主频 CPU
    nbthread 8
    cpu-map auto:1/1-8 0-7
    # 连接与缓冲
    maxconn 200000
    tune.bufsize 32768
    tune.ssl.default-dh-param 2048
    # 统计与 socket
    stats socket /var/run/haproxy.sock mode 660 level admin expose-fd listeners
    stats timeout 30s

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    timeout connect 5s
    timeout client  30s
    timeout server  30s
    timeout http-request 10s
    timeout http-keep-alive 10s
    option  http-keep-alive
    option  http-use-htx
    http-reuse safe
    maxconn 180000
    retries 3

# TLS 终止与 HTTP/2
frontend fe_https
    bind 10.10.10.100:443 ssl crt /etc/haproxy/certs/shop.pem alpn h2,http/1.1
    bind 10.10.10.101:443 ssl crt /etc/haproxy/certs/shop.pem alpn h2,http/1.1
    # 安全与性能:选择现代套件(示例,按实际 OpenSSL 版本与合规要求调整)
    ssl-default-bind-ciphersuites TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256
    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
    # 基本防护与限流
    stick-table type ip size 1m expire 30s store http_req_rate(10s)
    http-request track-sc0 src
    acl abuse src_http_req_rate(sc0) gt 200
    http-request deny if abuse

    # 后端选择与会话保持(无状态优先;如需粘性会话,可用 cookie/hash)
    default_backend bk_app

# HTTP 重定向
frontend fe_http
    bind 10.10.10.100:80
    bind 10.10.10.101:80
    http-request redirect scheme https code 301 if !{ ssl_fc }

# 后端池:健康检查、连接复用
backend bk_app
    mode http
    balance uri consistent
    option httpchk GET /healthz
    http-check expect status 200
    server app1 10.10.20.11:443 ssl verify none check maxconn 5000
    server app2 10.10.20.12:443 ssl verify none check maxconn 5000
    server app3 10.10.20.13:443 ssl verify none check maxconn 5000

# 管理页面(内网或跳板机访问)
listen stats
    bind 10.10.10.11:8404
    stats enable
    stats uri /stats
    stats auth admin:StrongPass!

要点解释

  • nbthread:使用线程模型,充分利用多核;cpu-map auto 根据核数映射线程,减少迁移。
  • http-reuse safe:在后端安全复用连接,降低握手与队首阻塞。
  • stick-table 做简单限流防爆,线上我会配合 WAF 做更细策略。
  • 后端示例用的是 HTTPS 回源(ssl verify none),实际请用内网自签 CA 并 verify required ca-file 更安全。
  • 健康检查短而频,防止慢故障扩散。

五、证书与 OCSP Stapling

将完整链证书与私钥合并到 /etc/haproxy/certs/shop.pem,按需配置自动续签(如使用 acme.sh + 钩子,在热更新时触发 systemctl reload haproxy)。HAProxy 2.x 能自动完成 OCSP 缓存刷新(取决于编译的 OpenSSL 与配置),生产建议定时检查。

六、日志与监控

rsyslog(本机采集到集中平台)

/etc/rsyslog.d/49-haproxy.conf:

$AddUnixListenSocket /var/lib/haproxy/dev/log
:programname, startswith, "haproxy" /var/log/haproxy/haproxy.log
& stop

HAProxy global 日志指向 /dev/log,并根据需要把 socket 映射到 chroot 或容器。日志轮转记得配 logrotate。

Prometheus Exporter

两种常见方式:

  • 直接读取 stats socket 的 /;csv,用 haproxy_exporter。
  • 开启 stats socket 并授权只读用户。
  • Exporter 以 systemd 服务运行,抓取地址配置为 unix:/var/run/haproxy.sock 或 TCP stats 端口。

七、发布与热更新(零停机)

  • 校验配置:haproxy -f /etc/haproxy/haproxy.cfg -c
  • 热更新:systemctl reload haproxy(底层是 -sf,平滑切换到新进程)
  • 灰度:双 VIP 架构可以先只在 VIP-B 上加载新版本,逐步调小 VIP-A 的权重(DNS 权重或临时只放出一个 A 记录),观察稳定后再切另一边。

八、自动化(Ansible 片段)

roles/haproxy/tasks/main.yml:

- name: Install deps
  yum:
    name:
      - pcre2-devel
      - zlib-devel
      - systemd-devel
      - lua-devel
    state: present

- name: Deploy haproxy.cfg
  template:
    src: haproxy.cfg.j2
    dest: /etc/haproxy/haproxy.cfg
    owner: haproxy
    group: haproxy
    mode: '0644'
  notify: reload haproxy

- name: Ensure haproxy running
  systemd:
    name: haproxy
    state: started
    enabled: yes

handlers:
  - name: reload haproxy
    systemd:
      name: haproxy
      state: reloaded

九、压测与效果(实测数据)

工具:wrk(3 台并行)、h2load(验证 HTTP/2 多路复用效果)

场景:静态页面 + 动态接口混合(70/30),TLS 终止于 HAProxy;后端 Nginx/App 在同机房内网。

架构 QPS(平均) P50 P95 P99 失败率
单 HAProxy + 单 VIP 62k 18ms 85ms 160ms 0.45%
多 HAProxy(3 节点)+ 双 VIP(Active-Active) 148k 12ms 48ms 90ms 0.08%
多节点 + BBR + 中断亲和优化 163k 10ms 42ms 78ms 0.05%

实测改观最大的是 排队时延与长尾(P99)。在跨境链路波动时,入口层的吞吐冗余和更稳的队列让“峰值期间的体验”不劣化。

十、常见坑与现场处置

VRRP + rp_filter

症状:VIP 偶发不通、抓包发现回包走另一节点。

处理:关闭严格 RPF(rp_filter=0),Keepalived 用 unicast,并尽量保障对称性;必要时收敛路由。

TLS 握手 CPU 冲高

症状:QPS 上去后 CPU sys 飙升,握手耗时变大。

处理:升级 OpenSSL 与 HAProxy,优先 ECDHE,开启 HTTP/2 多路复用、http-reuse;核对证书链;适度调大 tune.bufsize(默认 16k → 32k)。

TIME_WAIT 与端口耗尽

症状:cannot bind 或后端连接短期内失败。

处理:扩大 ip_local_port_range,tcp_fin_timeout=15,避免短连接风暴;后端尽量复用连接(http-reuse safe)。

健康检查“误杀”

症状:后端接口偶发慢,被踢出过久。

处理:retries 与 rise/fall(在 server 行使用),健康页 /healthz 与业务解耦;后端熔断策略不要相互叠加导致“雪崩”。

DNS TTL 过长

症状:VIP 迁移或权重调整后生效慢。

处理:入口域名 TTL 30s 左右即可,活动期更短;权重与双 A 记录动态调整要有 SOP。

中断亲和被打乱

症状:延迟抖动加大。

处理:禁止 irqbalance 或固定策略;确认 RSS 队列均衡,核对 /proc/interrupts。

跨境 MTU/丢包

症状:HTTP/2 长连接偶发重置。

处理:端到端检查 MTU(1500/1492),必要时在服务器侧启用 MSS clamping(防火墙)以规避路径 MTU 问题。

十一、安全基线

防火墙(CentOS 7):firewalld 或 iptables 明确放行 80/443/VRRP(协议 112)等;管理面(stats)仅内网访问。

最小权限:HAProxy 以非 root 运行,证书权限收紧。

合规加固:TLS1.2+/TLS1.3,淘汰旧套件;HSTS、OCSP;敏感头处理(X-Forwarded-For、X-Forwarded-Proto)。

十二、扩展与容灾

跨机房多活:在新加坡或东京再部署一组相同栈,用权重 DNS/GSLB 做就近与容灾。

BGP Anycast(进阶):如果机房支持自带 ASN/BGP,入口层用 FRR 广播同一 Anycast VIP,实现更平滑的全局就近与故障摘除(维护成本更高)。

十三、标准变更流程(SOP 摘要)

  • 变更前 24h:降 TTL、预热缓存、压测回归。
  • 变更窗口:先 VIP-B 灰度 → 指标稳定 → 切 VIP-A。
  • 回滚锚点:保留旧进程 PID,-sf 回退;Keepalived 降级优先级触发回切。
  • 复盘:导出 stats/日志,更新容量模型与阈值。

附:简化版完整配置清单(可落地)

  • sysctl:见文中 /etc/sysctl.d/99-hk-haproxy.conf
  • haproxy.service:见“安装 HAProxy”章节
  • keepalived.conf:双 VIP 示例
  • haproxy.cfg:前后端、限流、stats、HTTP/2/TLS 示例

再次“被叫醒”的夜里,我笑了

今年大促的零点,我照例守在监控前。流量像潮水一样涌入,Alerts 安静得有点不真实。P99 从 150ms 稳到 80ms 左右,握手抖动不再像过山车。凌晨 3 点,团队群里开始刷梗图,咖啡变成了奶茶。我把 VIP-B 的灰度权重调回,三台 HAProxy 的曲线像三条并排的心电图,稳定而有力。

那一刻我明白,这套在香港机房打磨出来的 HAProxy 多节点集群,不是只为这一晚——它足够简单、够硬核,也够“耐操”。下一个活动、下一个增长曲线,它都能继续扛着。

如果你也正准备把入口层从“能用”升级到“能战”,希望这份实操笔记能帮你少踩几个坑,多睡几个安稳觉。