第14章 HAProxy:L4/L7、ACL、健康检查与 stick table
学习目标
- 掌握 HAProxy 的配置骨架(global/defaults/frontend/backend)与 L4/L7 双模式
- 用 ACL 做基于内容的路由,理解它比 Nginx
if更清晰强大 - 掌握 HAProxy 独门武器 stick table:会话保持 + 限流/防护一体
- 用好它最强的主动健康检查与可观测(stats/runtime API)
前置知识
- 第09章 L4 代理(PROXY protocol、连接级 LB)、第10章 L7
- 第13章 Nginx(对照)
原理
定位:专业负载均衡器
如果说 Nginx 是"会做反代的 Web 服务器",HAProxy 就是"专做负载均衡的代理"。它没有静态文件服务那些包袱,只干代理+负载均衡,且干到极致:性能稳定、健康检查强、可观测细、mode tcp(L4)和 mode http(L7)通吃。数据库(MySQL/PostgreSQL/Redis)的 L4 负载均衡,HAProxy 是首选。
配置骨架
global # 进程级:用户、日志、TLS 调优、线程数
defaults # 各段默认值:mode、超时、日志
frontend # 监听入口:bind 端口、ACL、按规则选 backend
backend # 后端组:server 列表、balance 算法、健康检查
listen # frontend+backend 的合体简写
frontend 与 backend 解耦是 HAProxy 的精髓:一个 frontend 可按 ACL 把流量分发到多个 backend。
三个超时(必配,少一个就出诡异问题)
timeout connect 5s # 连后端的超时
timeout client 30s # 客户端空闲超时
timeout server 30s # 等后端响应超时
HAProxy 不配超时会用很短/很长的默认值,导致"偶发断连"或"连接堆积"。这三个是配置第一课。
ACL:清晰的内容路由
ACL(Access Control List)是 HAProxy 路由的核心,比 Nginx 的 if/map 更声明式、可组合:
frontend web
bind *:80
acl is_api path_beg /api/ # 路径前缀
acl is_static path_end .jpg .css .js # 路径后缀
acl is_mobile hdr_sub(User-Agent) -i mobile # Header 子串
use_backend api_srv if is_api
use_backend static_srv if is_static
use_backend mobile_srv if is_mobile
default_backend web_srv
ACL 能匹配 path/header/method/cookie/源IP/SNI 等几乎一切,还能 and/or/! 组合。
stick table:HAProxy 的独门武器
stick table 是一张内存表,按 key(IP、cookie 等)记录状态(连接数、请求率、字节数)。它一物两用:
用途一:会话保持(比 第09章 源哈希精确) 用途二:限流/防护(记录每 IP 的请求率,超阈值就拦)——这是 Nginx 开源版要靠第三方模块才能做的:
backend web_srv
# 记录每个源 IP 在 10 秒内的 HTTP 请求率
stick-table type ip size 100k expire 30s store http_req_rate(10s)
http-request track-sc0 src
# 10 秒内请求 > 100 的 IP,拒绝(轻量级 CC 防护)
http-request deny if { sc_http_req_rate(0) gt 100 }
server s1 10.0.0.11:8080 check
一张 stick table 就实现了"按 IP 限流",还能在多 HAProxy 间用 peers 同步——这是 HAProxy 在抗 CC/限流场景的杀手锏。
最强的健康检查
HAProxy 的主动健康检查开箱即用、能力强(Nginx 开源版的短板):
backend api
option httpchk GET /healthz # 主动发 HTTP 探测
http-check expect status 200 # 期望 200
server s1 10.0.0.11:8080 check inter 2s fall 3 rise 2
# check:开启 / inter:间隔 / fall:连续3次失败摘除 / rise:连续2次成功恢复
还支持 check 多种协议(MySQL、Redis、PostgreSQL、SSL)的应用层探测。
PROXY protocol 与 SSL
- 向后端发真实客户端 IP:
server s1 ... send-proxy(第09章) - TLS 终止:
bind *:443 ssl crt /etc/haproxy/cert.pem - SNI 透传路由(不解密):用
req.ssl_sniACL(第02章 SNI 嗅探)
️ 实现 / 命令
实验一:L7 ACL 路由 + 主动健康检查 + stats
global
log stdout local0
maxconn 50000
nbthread 4
defaults
mode http
log global
timeout connect 5s
timeout client 30s
timeout server 30s
frontend web
bind *:80
stats enable # 内置监控页
stats uri /haproxy?stats
acl is_api path_beg /api/
use_backend api if is_api
default_backend web
backend api
balance leastconn
option httpchk GET /healthz
http-check expect status 200
server a1 10.0.0.11:8080 check inter 2s fall 3 rise 2
server a2 10.0.0.12:8080 check inter 2s fall 3 rise 2
backend web
balance roundrobin
server w1 10.0.0.20:8080 check
访问 http://lb/haproxy?stats 能看到每个后端的实时连接数、健康状态、请求统计——HAProxy 的可观测开箱即用。
实验二:stick table 按 IP 限流压测
# 用上面 stick-table 的配置,对同一 IP 猛打
for i in $(seq 1 200); do curl -s -o /dev/null -w "%{http_code} " http://lb/; done
# 前 ~100 个 200,之后变 403 —— 限流生效
实验三:L4(mode tcp)代理 MySQL
listen mysql
bind *:3306
mode tcp # L4:HTTP 代理做不到
balance leastconn
option mysql-check user haproxy_check # 应用层 MySQL 健康检查
server db1 10.0.0.31:3306 check
server db2 10.0.0.32:3306 check backup
实验四:Runtime API 动态改后端(无 reload)
# 通过 admin socket 运行时禁用一台后端(灰度/维护,不重启)
echo "disable server api/a1" | socat stdio /var/run/haproxy.sock
echo "enable server api/a1" | socat stdio /var/run/haproxy.sock
排错
| 现象 | 根因 | 解决 |
|---|---|---|
| 偶发断连/超时 | 没配 timeout 三件套 | 补全 connect/client/server |
| stick table 限流误伤 | 阈值太低,或 NAT 后共享 IP | 调阈值,或换更细粒度 key |
| 健康检查一直 DOWN | httpchk 路径/期望状态不符 | 核对 /healthz 返回、http-check expect |
| 后端拿不到真实 IP | 没 send-proxy,或后端没收 PROXY | 两端都配(第09章) |
mode http 代理非 HTTP 失败 | 用错模式 | 非 HTTP 用 mode tcp |
| reload 丢连接 | 老式 reload | 用 -sf/seamless reload(hitless) |
| stats 页打不开 | 没 stats enable/uri | 检查 frontend 的 stats 配置 |
本章小结
- HAProxy 是专业负载均衡器:
mode tcp(L4) +mode http(L7),frontend/backend 解耦。 - 三个超时(connect/client/server)是配置第一课,缺则诡异断连。
- ACL 做清晰可组合的内容路由;stick table 一物两用(会话保持 + 按 IP 限流),是独门武器。
- 主动健康检查强(含 MySQL/Redis 应用层探测),可观测开箱即用(stats + runtime API)。
- 选型:要专业 LB、强健康检查、限流防护、数据库 L4 代理 → HAProxy。
下一章 第15章 Envoy,进入云原生数据面的核心:xDS 动态配置如何让代理"配置秒级热推、永不 reload",以及为什么 Service Mesh 选了它。