找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2577

积分

0

好友

367

主题
发表于 4 小时前 | 查看: 2| 回复: 0

搞负载均衡这么多年,HAProxy一直是我心目中的“瑞士军刀”。从最早的1.4版本用到现在,看着它从一个单纯的TCP/HTTP代理,进化成了支持QUIC、HTTP/3的现代化负载均衡器。很多人一提负载均衡就想到Nginx,但在纯粹的代理转发场景下,HAProxy的性能和功能细粒度控制是Nginx比不了的。我在某电商平台做过对比测试,同等硬件条件下,HAProxy的QPS能高出约15-20%,而且高并发时CPU占用更低。

它的核心优势在于专注。不像Nginx要兼顾Web服务器功能,HAProxy所有的设计都围绕着“如何更高效地转发请求”,这种专注带来的就是更直观的配置和更极致的性能。

一、HAProxy 3.0 新特性与适用场景

HAProxy 3.0相比之前版本有几个值得关注的更新,尤其是在性能和可管理性上:

  • 原生QUIC/HTTP3支持:终于不用再依赖第三方补丁了。虽然标记为实验性,但在我们的测试环境里跑了三个月,稳定性没问题。
  • 成熟的多线程架构:从2.x开始的多线程模型在3.0里彻底稳定了。以前担心的锁竞争问题基本解决,nbthread参数可以放心大胆地用。
  • 增强的运行时API:通过Runtime API可以实现不重启热更新后端服务器,这在微服务动态伸缩的场景下太实用了。
  • 优化的内存管理:新的内存池机制让长连接场景下的内存占用更稳定。

根据我的实战经验,HAProxy最适合以下场景:

  • API网关:需要精细化流量控制、限流、熔断的场景。
  • 微服务入口:支持服务发现集成,动态后端管理。
  • 数据库代理:MySQL/PostgreSQL读写分离、连接池管理。
  • WebSocket长连接:稳定的长连接保持能力是强项。
  • 高性能HTTP代理:追求极致转发性能的场景。

不太适合的场景:需要复杂URL重写、静态文件服务(这些交给Nginx更合适)。

环境要求参考

组件 版本 说明
HAProxy 3.0.5 2025年1月稳定版
操作系统 Rocky Linux 9.3 / Ubuntu 24.04 LTS 推荐使用Rocky Linux
内核版本 5.14+ 需要支持io_uring
CPU 4核+ 生产环境建议8核起步
内存 4GB+ 根据连接数调整,每个连接约32KB
GCC 12+ 编译安装时需要
OpenSSL 3.0+ QUIC支持需要

二、从系统优化到HAProxy安装部署

在安装HAProxy之前,先调好系统参数。这些参数在生产环境高并发时至关重要,不调可能会出各种奇怪的问题。

2.1 系统内核与资源优化

首先,调整系统参数,创建一个配置文件 /etc/sysctl.d/99-haproxy.conf

# /etc/sysctl.d/99-haproxy.conf
# 文件描述符相关
fs.file-max = 2097152
fs.nr_open = 2097152

# 网络核心参数
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 65535
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 262144
net.core.wmem_default = 262144

# TCP 参数优化
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_max_tw_buckets = 1440000
net.ipv4.ip_local_port_range = 1024 65535

# 开启 TCP Fast Open
net.ipv4.tcp_fastopen = 3

# 连接追踪(如果用 iptables)
net.netfilter.nf_conntrack_max = 1048576

应用配置:

sysctl -p /etc/sysctl.d/99-haproxy.conf

然后,修改进程资源限制,创建文件 /etc/security/limits.d/99-haproxy.conf

# /etc/security/limits.d/99-haproxy.conf
haproxy soft nofile 1048576
haproxy hard nofile 1048576
haproxy soft nproc 65535
haproxy hard nproc 65535

这些调优是构建高性能代理服务的基础,涉及到核心的 网络/系统 参数。

2.2 安装 HAProxy 3.0

Rocky Linux 9的官方仓库版本可能较老,建议使用官方仓库或源码编译。

方法一:使用官方仓库安装(推荐)

# 添加 HAProxy 官方仓库
dnf install -y epel-release
dnf copr enable -y bors/haproxy

# 安装 HAProxy 3.0
dnf install -y haproxy30

方法二:源码编译安装(追求极致性能与控制)

# 安装依赖
dnf install -y gcc make pcre2-devel openssl-devel systemd-devel \
    lua-devel readline-devel zlib-devel

# 下载源码
cd /usr/local/src
wget https://www.haproxy.org/download/3.0/src/haproxy-3.0.5.tar.gz
tar xzf haproxy-3.0.5.tar.gz
cd haproxy-3.0.5

# 编译参数说明:
# TARGET=linux-glibc: 使用 glibc
# USE_OPENSSL=1: 启用 SSL 支持
# USE_PCRE2=1: 使用 PCRE2 正则库
# USE_SYSTEMD=1: 启用 systemd 集成
# USE_LUA=1: 启用 Lua 脚本支持
# USE_QUIC=1: 启用 QUIC/HTTP3(实验性)
# USE_PROMEX=1: 启用 Prometheus 导出器

make -j$(nproc) TARGET=linux-glibc \
    USE_OPENSSL=1 USE_PCRE2=1 USE_SYSTEMD=1 \
    USE_LUA=1 USE_QUIC=1 USE_PROMEX=1 \
    USE_THREAD=1

make install PREFIX=/usr/local/haproxy

对于编译安装,需要创建systemd服务文件 /etc/systemd/system/haproxy.service

# /etc/systemd/system/haproxy.service
[Unit]
Description=HAProxy Load Balancer
After=network-online.target
Wants=network-online.target

[Service]
Type=notify
EnvironmentFile=-/etc/sysconfig/haproxy
ExecStartPre=/usr/local/haproxy/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c -q
ExecStart=/usr/local/haproxy/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid
ExecReload=/bin/kill -USR2 $MAINPID
KillMode=mixed
Restart=always
LimitNOFILE=1048576

[Install]
WantedBy=multi-user.target

三、核心配置模块详解与实战示例

HAProxy配置分为四大块:globaldefaultsfrontendbackend。理解这个结构是玩转它的基础。

3.1 全局配置 (Global)

/etc/haproxy/haproxy.cfg 的全局部分,定义了进程级别的参数。

global
    # 日志配置 - 发送到本地 rsyslog
    log /dev/log local0 info
    log /dev/log local1 notice

    # 运行身份
    user haproxy
    group haproxy

    # 后台运行
    daemon

    # 多线程配置 - 关键参数
    # nbthread 建议设置为 CPU 核心数,但不超过 64
    nbthread 8

    # CPU 绑定 - 减少上下文切换
    cpu-map auto:1/1-8 0-7

    # 最大连接数 - 根据内存调整
    # 每个连接大约占用 32KB 内存
    maxconn 100000

    # SSL 配置
    ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
    ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets

    # 运行时 API - 用于动态管理
    stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
    stats timeout 30s

    # 性能调优
    tune.ssl.default-dh-param 2048
    tune.bufsize 32768
    tune.maxrewrite 1024
    tune.http.maxhdr 128

    # Lua 脚本路径
    lua-load /etc/haproxy/lua/init.lua

3.2 默认配置 (Defaults)

为后续的frontendbackend设置默认值。

defaults
    # 工作模式:http 或 tcp
    mode http

    # 继承全局日志配置
    log global

    # 记录 HTTP 请求日志
    option httplog

    # 不记录空连接
    option dontlognull

    # 启用 HTTP 连接关闭
    option http-server-close

    # 转发客户端 IP
    option forwardfor except 127.0.0.0/8

    # 后端服务器健康检查失败时重新派发
    option redispatch
    retries 3

    # 超时配置 - 生产环境调优后的结果
    timeout connect 5s      # 连接后端超时
    timeout client 60s      # 客户端超时
    timeout server 60s      # 服务端超时
    timeout http-request 10s # HTTP 请求超时
    timeout http-keep-alive 10s # Keep-Alive 超时
    timeout queue 30s       # 队列等待超时
    timeout check 5s        # 健康检查超时

    # 错误文件
    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

3.3 前端配置 (Frontend)

定义客户端如何连接进来,并进行初步的流量分类和策略应用。

HTTP前端 (端口80)

# HTTP 前端 - 80 端口
frontend http_front
    bind *:80

    # 定义 ACL 规则
    acl is_api path_beg /api/
    acl is_static path_end .css .js .png .jpg .gif .ico
    acl is_websocket hdr(Upgrade) -i WebSocket

    # 根据 Host 头分流
    acl host_app1 hdr(host) -i app1.example.com
    acl host_app2 hdr(host) -i app2.example.com

    # 限流 ACL - 每个 IP 每秒最多 100 个请求
    stick-table type ip size 100k expire 30s store http_req_rate(10s)
    acl is_abuse sc_http_req_rate(0) gt 100
    http-request deny deny_status 429 if is_abuse
    http-request track-sc0 src

    # 添加请求头
    http-request set-header X-Forwarded-Proto http
    http-request set-header X-Real-IP %[src]

    # 路由规则
    use_backend api_servers if is_api
    use_backend static_servers if is_static
    use_backend ws_servers if is_websocket
    use_backend app1_servers if host_app1
    use_backend app2_servers if host_app2

    # 默认后端
    default_backend web_servers

HTTPS前端 (端口443)

# HTTPS 前端 - 443 端口
frontend https_front
    # 绑定 443 端口,启用 SSL
    bind *:443 ssl crt /etc/haproxy/certs/ alpn h2,http/1.1

    # HTTP/2 相关配置
    http-request set-header X-Forwarded-Proto https

    # HSTS 头
    http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains"

    # 复用 HTTP 前端的 ACL 和路由
    acl is_api path_beg /api/
    use_backend api_servers if is_api
    default_backend web_servers

3.4 后端配置 (Backend)

定义请求被转发到哪一组服务器,以及该组服务器间的负载均衡策略。这里可以看到它如何与后端 数据库/中间件/技术栈 协同工作。

Web服务器后端

backend web_servers
    # 负载均衡算法
    balance roundrobin

    # 会话保持 - 基于 cookie
    cookie SERVERID insert indirect nocache

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

    # 后端服务器列表
    # weight: 权重
    # check: 启用健康检查
    # inter: 检查间隔
    # fall: 连续失败次数标记为 down
    # rise: 连续成功次数标记为 up
    server web1 192.168.1.11:8080 weight 100 cookie web1 check inter 3s fall 3 rise 2
    server web2 192.168.1.12:8080 weight 100 cookie web2 check inter 3s fall 3 rise 2
    server web3 192.168.1.13:8080 weight 100 cookie web3 check inter 3s fall 3 rise 2

    # 备用服务器 - 所有主服务器 down 时启用
    server web_backup 192.168.1.20:8080 backup

API服务器后端

backend api_servers
    balance leastconn  # API 适合用最少连接算法

    option httpchk GET /api/health HTTP/1.1\r\nHost:\ localhost
    http-check expect status 200

    # 连接复用 - 减少后端连接数
    http-reuse safe

    # 重试配置
    retry-on conn-failure empty-response response-timeout

    server api1 192.168.1.21:3000 check inter 2s fall 2 rise 2 maxconn 1000
    server api2 192.168.1.22:3000 check inter 2s fall 2 rise 2 maxconn 1000

WebSocket后端

backend ws_servers
    balance source # WebSocket 需要会话保持

    # WebSocket 超时要设长一些
    timeout tunnel 3600s
    timeout server 3600s

    server ws1 192.168.1.31:8080 check
    server ws2 192.168.1.32:8080 check

静态资源后端

backend static_servers
    balance roundrobin

    # 静态资源可以开启压缩
    compression algo gzip
    compression type text/html text/css text/javascript application/javascript

    # 缓存头
    http-response set-header Cache-Control "public, max-age=86400"

    server static1 192.168.1.41:80 check
    server static2 192.168.1.42:80 check

3.5 状态监控页面

# 统计页面 - 生产环境建议限制访问 IP
frontend stats
    bind *:8404
    mode http

    # IP 白名单
    acl allowed_ip src 10.0.0.0/8 192.168.0.0/16
    http-request deny unless allowed_ip

    stats enable
    stats uri /stats
    stats refresh 10s
    stats admin if TRUE
    stats auth admin:your_secure_password

    # Prometheus 指标导出
    http-request use-service prometheus-exporter if { path /metrics }

四、启动验证与生产级完整配置示例

4.1 启动与基础验证

# 检查配置语法
haproxy -c -f /etc/haproxy/haproxy.cfg

# 启动服务
systemctl daemon-reload
systemctl enable haproxy
systemctl start haproxy

# 查看状态
systemctl status haproxy

# 查看监听端口
ss -tlnp | grep haproxy

# 测试健康检查
curl -I http://localhost/health

# 查看后端状态(使用Runtime API)
echo "show stat" | socat stdio /run/haproxy/admin.sock

4.2 生产环境完整配置示例

这是一个来自某电商平台的真实配置精简版,日均处理数百万请求。

# /etc/haproxy/haproxy.cfg
# 电商平台负载均衡配置 - HAProxy 3.0.5

global
    log /dev/log local0 info
    user haproxy
    group haproxy
    daemon
    nbthread 8
    cpu-map auto:1/1-8 0-7
    maxconn 200000
    ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384
    ssl-default-bind-options ssl-min-ver TLSv1.2
    stats socket /run/haproxy/admin.sock mode 660 level admin
    tune.bufsize 32768
    tune.http.maxhdr 128
    tune.ssl.default-dh-param 2048

defaults
    mode http
    log global
    option httplog
    option dontlognull
    option http-server-close
    option forwardfor
    option redispatch
    retries 3
    timeout connect 5s
    timeout client 60s
    timeout server 60s
    timeout http-request 10s
    timeout http-keep-alive 30s
    timeout queue 30s
    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"

frontend http_in
    bind *:80
    http-request redirect scheme https unless { ssl_fc }

frontend https_in
    bind *:443 ssl crt /etc/haproxy/certs/example.com.pem alpn h2,http/1.1
    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"
    http-response set-header Strict-Transport-Security "max-age=31536000"
    stick-table type ip size 200k expire 30s store http_req_rate(10s),conn_cur
    acl is_rate_limited sc_http_req_rate(0) gt 200
    acl is_conn_limited sc_conn_cur(0) gt 50
    http-request track-sc0 src
    http-request deny deny_status 429 if is_rate_limited
    http-request deny deny_status 429 if is_conn_limited
    acl is_api path_beg /api/
    acl is_admin path_beg /admin/
    acl is_static path_end .css .js .png .jpg .jpeg .gif .ico .woff .woff2
    acl admin_ip src 10.10.0.0/16
    http-request deny if is_admin !admin_ip
    use_backend api_backend if is_api
    use_backend static_backend if is_static
    default_backend web_backend

backend web_backend
    balance roundrobin
    cookie WEBID insert indirect nocache httponly secure
    option httpchk GET /health HTTP/1.1\r\nHost:\ localhost
    http-check expect status 200
    http-reuse safe
    server web01 10.10.1.11:8080 weight 100 cookie s1 check inter 3s fall 3 rise 2
    server web02 10.10.1.12:8080 weight 100 cookie s2 check inter 3s fall 3 rise 2
    server web03 10.10.1.13:8080 weight 100 cookie s3 check inter 3s fall 3 rise 2

backend api_backend
    balance leastconn
    option httpchk GET /api/health HTTP/1.1\r\nHost:\ localhost
    http-check expect status 200
    http-reuse aggressive
    retry-on conn-failure empty-response response-timeout 502 503 504
    server api01 10.10.2.11:3000 check inter 2s fall 2 rise 2 maxconn 2000
    server api02 10.10.2.12:3000 check inter 2s fall 2 rise 2 maxconn 2000

backend static_backend
    balance roundrobin
    compression algo gzip
    compression type text/css text/javascript application/javascript application/json
    http-response set-header Cache-Control "public, max-age=604800"
    server static01 10.10.3.11:80 check
    server static02 10.10.3.12:80 check

frontend stats
    bind *:8404
    mode http
    acl internal_net src 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
    http-request deny unless internal_net
    stats enable
    stats uri /stats
    stats refresh 5s
    stats admin if TRUE
    stats auth admin:Ecm@2025$Prod
    http-request use-service prometheus-exporter if { path /metrics }

五、高级应用场景与故障排查

5.1 高级应用场景配置

灰度发布(10%流量导流)

backend web_backend
    balance roundrobin
    # 灰度发布:10% 流量到新版本
    acl is_canary rand(100) lt 10
    acl has_canary_cookie req.cook(canary) -m found
    http-response set-header Set-Cookie "canary=1; Path=/; Max-Age=3600" if is_canary !has_canary_cookie
    use-server canary01 if is_canary
    use-server canary01 if has_canary_cookie
    server web01 10.10.1.11:8080 check
    server canary01 10.10.1.21:8080 check weight 0  # weight=0 不参与正常轮询

MySQL读写分离代理

# MySQL 代理配置
frontend mysql_front
    bind *:3306
    mode tcp
    default_backend mysql_write

frontend mysql_read_front
    bind *:3307
    mode tcp
    default_backend mysql_read

backend mysql_write
    mode tcp
    balance first  # 写操作只发到第一个可用节点(主库)
    option mysql-check user haproxy
    server mysql_master 10.10.5.11:3306 check inter 3s fall 3 rise 2

backend mysql_read
    mode tcp
    balance leastconn
    option mysql-check user haproxy
    server mysql_slave1 10.10.5.12:3306 check inter 3s fall 3 rise 2 weight 100
    server mysql_slave2 10.10.5.13:3306 check inter 3s fall 3 rise 2 weight 100
    # 主库作为读的备用
    server mysql_master 10.10.5.11:3306 check inter 3s fall 3 rise 2 weight 50 backup

5.2 运维最佳实践与故障排查

健康检查优化
别用简单的TCP检查,一定要用HTTP检查,而且要检查真实的业务逻辑。

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

# 更好的健康检查 - 检查关键依赖
http-check connect
http-check send meth GET uri /health/deep ver HTTP/1.1 hdr Host localhost
http-check expect rstatus ^2

优雅下线服务器
上线前先把服务器设置为drain模式,等连接清空再下线,这是保障服务平滑发布的运维 & 测试关键一步。

# 通过 Runtime API 设置
echo "set server web_backend/web01 state drain" | socat stdio /run/haproxy/admin.sock

# 等待连接数降为 0
echo "show stat" | socat stdio /run/haproxy/admin.sock | grep web01

# 确认后下线
echo "set server web_backend/web01 state maint" | socat stdio /run/haproxy/admin.sock

关键监控与日志
自定义日志格式方便后续分析:

log-format '{"time":"%t","client":"%ci","backend":"%b","server":"%s","status":%ST,"bytes":%B,"time_total":%Ta,"time_connect":%Tc,"time_response":%Tr,"retries":%rc,"request":"%r"}'

内置的Prometheus exporter提供了丰富的指标,关键监控项包括:

  • haproxy_frontend_current_sessions: 当前活跃会话数
  • haproxy_backend_active_servers: 活跃后端数量
  • haproxy_server_status: 服务器状态 (1=UP, 0=DOWN)
  • 5xx错误率 > 1% 或平均响应时间 > 2s 需要告警。

常见故障排查表

错误现象 可能原因 解决方案
间歇性502 Bad Gateway 后端响应超时 增加 timeout server,检查后端性能
所有请求返回503 所有后端健康检查失败 检查健康检查配置与后端服务状态
新请求被拒绝 maxconn 全局连接数耗尽 增加 maxconn 或优化后端处理速度
会话Cookie丢失 Cookie配置错误或属性冲突 检查cookie配置,注意securehttponly属性
CPU单核跑满 未启用多线程 配置 nbthread 参数(建议等于CPU核心数)

有一次线上出现大量502错误,排查发现是后端处理大请求超过了默认的30秒超时。教训就是:超时时间必须根据业务实际情况设置。还有一次更坑,开了http-reuse aggressive后部分请求串数据了,原因是后端有个老服务不支持HTTP Keep-Alive。所以上线新配置前,一定要在测试环境充分验证

六、总结与进阶

技术要点回顾:

  1. HAProxy 3.0的多线程模型已成熟,生产环境可放心使用。
  2. 健康检查务必做到HTTP应用层,TCP检查不足以反映真实状态。
  3. 所有超时参数 (timeout server/client等) 必须根据实际业务调整,切忌使用默认值一刀切。
  4. Runtime API是运维利器,熟练掌握可实现动态、无损的服务管理。
  5. 自定义日志格式,为后续的监控分析和问题排查铺平道路。

进阶学习方向:

  • Lua脚本扩展:实现复杂的流量控制、请求/响应改写逻辑。
  • QUIC/HTTP3实战:探索下一代网络协议在负载均衡中的应用与调优。
  • Kubernetes服务网格集成:了解HAProxy作为Ingress Controller或服务网格数据平面的角色。
  • 安全加固:深入研究WAF规则集成与DDoS防护的高级配置。

掌握HAProxy的配置精髓,能让你在构建高可用、高性能的服务架构时游刃有余。如果在实践中遇到更复杂的问题,欢迎到 云栈社区 与更多的开发者和运维同行一起交流探讨。




上一篇:SaaS产品如何零成本获取流量:从Reddit营销到SEO内容与变现策略
下一篇:AI Agent时代软件工程思维的变革:从复杂架构到技能层开发
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-24 21:38 , Processed in 0.322167 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表