1、系统优化准备
调整系统参数,避免高并发时会出现性能问题
# /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修改limits
# /etc/security/limits.d/99-haproxy.conf
haproxy soft nofile 1048576
haproxy hard nofile 1048576
haproxy soft nproc 65535
haproxy hard nproc 655352、核心配置详解
global:主要是配置相关进程及安全配置相关的参数 ,性能调整相关参数,Debug参数
proxies:代理配置段
defaults:为frontend, backend, listen提供默认配置。为前端和后端提供默认的配置参数,这些参数可以被后续级别的配置覆盖
frontend:前端,相当于nginx中的server {}。定义了客户端请求的接收方式以及如何将请求转发至后端服务器组
backend:后端,相当于nginx中的upstream {}。指定了实际服务器的相关配置,如服务器列表、负载均衡策略等
listen:同时拥有前端和后端配置,配置简单,生产推荐使用
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.luadefaults默认配置
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.httpfrontend:前端配置
# 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 端口
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_serversbackend:后端配置
# 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状态监控页面
# 统计页面 - 生产环境建议限制访问 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 }启动与验证
# 检查配置语法
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
# 查看后端状态
echo "show stat" | socat stdio /run/haproxy/admin.sock实际生产环境配置
# /etc/haproxy/haproxy.cfg
# 电商平台负载均衡配置 - HAProxy 3.0.5
# 最后更新: 2025-01-07
global
log /dev/log local0 info
user haproxy
group haproxy
daemon
# 8核服务器配置
nbthread 8
cpu-map auto:1/1-8 0-7
maxconn 200000
# SSL 加固
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"
# HTTP 入口
frontend http_in
bind *:80
# 强制跳转 HTTPS
http-request redirect scheme https unless { ssl_fc }
# HTTPS 入口
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
# 限流规则:单 IP 每 10 秒最多 200 请求,最多 50 并发
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 定义
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 is_search path_beg /search/
# 管理后台限制 IP
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
use_backend search_backend if is_search
default_backend web_backend
# Web 后端 - 主站页面
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
server web04 10.10.1.14:8080 weight 100 cookie s4 check inter 3s fall 3 rise 2
# API 后端 - 接口服务
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
server api03 10.10.2.13:3000 check inter 2s fall 2 rise 2 maxconn 2000
server api04 10.10.2.14: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
# 搜索服务后端
backend search_backend
balance roundrobin
option httpchk GET /search/health HTTP/1.1\r\nHost:\ localhost
http-check expect status 200
timeout server 30s # 搜索服务响应可能较慢
server search01 10.10.4.11:9200 check inter 5s fall 3 rise 2
server search02 10.10.4.12:9200 check inter 5s fall 3 rise 2
# 监控页面
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 }案例配置
灰度发布
我们做 AB 测试时,需要把 10% 的流量导到新版本:
backend web_backend
balance roundrobin
# 灰度发布:10% 流量到新版本
# 使用 ACL 基于 cookie 或随机数分流
acl is_canary rand(100) lt 10
acl has_canary_cookie req.cook(canary) -m found
# 设置灰度 cookie
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 web02 10.10.1.12:8080 check
server canary01 10.10.1.21:80mysql读写分离
# 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基于请求头的A/B测试
frontend https_in
bind *:443 ssl crt /etc/haproxy/certs/
# 检测 A/B 测试标识
acl ab_test_v2 hdr(X-AB-Test) -i v2
acl ab_test_v2 req.cook(ab_version) v2
use_backend web_v2 if ab_test_v2
default_backend web_v1
backend web_v1
balance roundrobin
server v1_01 10.10.1.11:8080 check
server v1_02 10.10.1.12:8080 check
backend web_v2
balance roundrobin
server v2_01 10.10.2.11:8080 check
server v2_02 10.10.2.12:8080 check最佳实践和注意事项
最佳实践
1. 健康检查优化
别用简单的 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
2. 连接复用策略
# 安全模式 - 只复用空闲连接
http-reuse safe
# 激进模式 - 复用所有连接(要确保后端支持)
http-reuse aggressive
# 对于 HTTP/2 后端
http-reuse always
3. 优雅下线
上线前先把服务器设置为 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
4. 日志优化
默认日志太简单,建议用自定义格式:
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"}'
注意事项
踩坑经历分享:
有一次线上出现大量 502 错误,排查了半天发现是后端服务在处理某些大请求时超过了 30 秒的默认超时。改了 timeout server 后问题解决。教训就是:超时时间要根据业务实际情况设置,不能一刀切。
还有一次更坑的,开了 http-reuse aggressive 后,部分请求串数据了。后来发现是后端有个老服务不支持 HTTP Keep-Alive 连接复用。所以上线新配置前,一定要在测试环境充分验证。
故障排查和监控
故障排查
查看实时日志:
# 配置 rsyslog
cat > /etc/rsyslog.d/haproxy.conf << 'EOF'
$AddUnixListenSocket /dev/log
# HAProxy 日志单独存放
if $programname startswith 'haproxy' then /var/log/haproxy/haproxy.log
& stop
EOF
systemctl restart rsyslog
# 实时查看
tail -f /var/log/haproxy/haproxy.log
使用 Runtime API 排查:
# 查看所有后端状态
echo "show stat" | socat stdio /run/haproxy/admin.sock
# 查看当前会话
echo "show sess" | socat stdio /run/haproxy/admin.sock
# 查看错误统计
echo "show errors" | socat stdio /run/haproxy/admin.sock
# 查看后端队列
echo "show pools" | socat stdio /run/haproxy/admin.sock
# 查看服务器详细信息
echo "show servers state" | socat stdio /run/haproxy/admin.sock
常用排查命令:
# 检查端口监听
ss -tlnp | grep haproxy
# 检查连接数
ss -s
# 检查 TIME_WAIT 连接
ss -ant | grep TIME-WAIT | wc -l
# 抓包分析
tcpdump -i any port 80 -nn -w haproxy.pcap
性能监控
Prometheus 集成:
HAProxy 3.0 内置了 Prometheus exporter,直接访问 /metrics 端口就能获取指标:
# haproxy.cfg 中配置
frontend stats
bind *:8404
http-request use-service prometheus-exporter if { path /metrics }
关键监控指标:
# 必须监控的指标
haproxy_frontend_current_sessions: 当前活跃会话数
haproxy_frontend_http_requests_total: 请求总数
haproxy_backend_active_servers: 活跃后端数量
haproxy_backend_http_responses_total: 后端响应统计(按状态码)
haproxy_backend_response_time_average_seconds: 平均响应时间
haproxy_server_status: 服务器状态(1=UP, 0=DOWN)
haproxy_server_current_queue: 服务器当前队列长度
# 报警阈值建议
活跃会话数 > maxconn * 0.8: 警告
后端服务器状态变化: 立即报警
5xx 错误率 > 1%: 警告
平均响应时间 > 2s: 警告
Grafana Dashboard:
推荐使用官方 Dashboard ID: 12693,包含了 HAProxy 的核心指标可视化。
备份与恢复
配置备份:
#!/bin/bash
# /usr/local/bin/haproxy-backup.sh
BACKUP_DIR="/backup/haproxy"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p ${BACKUP_DIR}
# 备份配置
tar czf ${BACKUP_DIR}/haproxy_config_${DATE}.tar.gz \
/etc/haproxy/ \
/etc/sysctl.d/99-haproxy.conf \
/etc/security/limits.d/99-haproxy.conf
# 备份证书
tar czf ${BACKUP_DIR}/haproxy_certs_${DATE}.tar.gz \
/etc/haproxy/certs/
# 保留最近 30 天的备份
find ${BACKUP_DIR} -type f -mtime +30 -delete
快速恢复流程:
# 1. 安装 HAProxy(同版本)
# 2. 恢复配置
tar xzf haproxy_config_${DATE}.tar.gz -C /
tar xzf haproxy_certs_${DATE}.tar.gz -C /
# 3. 验证配置
haproxy -c -f /etc/haproxy/haproxy.cfg
# 4. 启动服务
systemctl start haproxy
附录
A. 命令速查表
B. 配置参数详解
C. 术语表
参考资料:
HAProxy 官方文档: https://docs.haproxy.org/
HAProxy 3.0 配置手册: https://www.haproxy.org/download/3.0/doc/configuration.txt
HAProxy Enterprise Blog: https://www.haproxy.com/blog/
HAProxy GitHub: https://github.com/haproxy/haproxy
转载:https://mp.weixin.qq.com/s/PqkaS1u5cIgNaRMsKcjepw