HiHuo
首页
博客
手册
工具
关于
首页
博客
手册
工具
关于
  • 代理技术全栈手册

    • 代理技术全栈手册 - HiHuo
    • 原理篇

      • 第01章 代理是什么:正向 / 反向 / 透明 / 隧道的统一模型
      • 第02章 代理与网络层级:L3 / L4 / L5 / L7 在哪里截断流量
      • 第03章 一个请求穿过代理的一生:连接生命周期全景
    • 协议篇

      • 第04章 HTTP 代理协议:绝对 URI、CONNECT 隧道、转发头与连接池
      • 第05章 HTTPS 与 TLS 代理:终止 / 透传 / MITM / SNI / mTLS
      • 第06章 SOCKS 协议:SOCKS4/4a/5 与 UDP ASSOCIATE 报文级解析
      • 第07章 HTTP/2、gRPC 与 HTTP/3(QUIC) 代理的挑战
      • 第08章 代理自动配置:PAC / WPAD / 系统代理 / NO_PROXY
    • 层级与转发篇

      • 第09章 L4 代理:TCP/UDP 转发与连接级负载均衡
      • 第10章 L7 代理:协议感知与基于内容的路由
      • 第11章 透明代理:iptables REDIRECT/DNAT、TPROXY 与 eBPF 劫持
      • 第12章 数据搬运的艺术:splice / sendfile / 零拷贝 / io_uring
    • 组件横评篇

      • 第13章 Nginx / OpenResty:反向代理、upstream 与 Lua 可编程
      • 第14章 HAProxy:L4/L7、ACL、健康检查与 stick table
      • 第15章 Envoy:xDS 动态配置与 filter chain,为何是云原生数据面
      • 第16章 Traefik / Caddy:自动服务发现与自动 HTTPS
      • 第17章 Squid 与正向/缓存代理:企业出网、缓存与审计
      • 第18章 mitmproxy:抓包、改包、脚本化调试
      • 第19章 内网穿透与隧道:frp / gost / SSH 隧道 / ngrok
      • 第20章 科学上网生态的技术原理(技术中立)
    • 多语言手写篇

      • 第21章 Go:100 行手写 HTTP/CONNECT + SOCKS5 代理
      • 第22章 Rust:基于 tokio 的高性能 TCP 代理
      • 第23章 Python:asyncio 实现,适合调试与脚本
      • 第24章 C:epoll 裸写与零拷贝,及语言选型对比
    • 容器与K8s篇

      • 第25章 Docker 里的代理:HTTP_PROXY、build/pull 与 daemon 配置
      • 第26章 Sidecar 与流量劫持:Istio init-container 的 iptables 原理
      • 第27章 Ingress 与南北流量:Ingress-nginx 与 Gateway API
      • 第28章 Egress 与出网治理:出口网关、registry mirror、审计
      • 第29章 Service Mesh 数据面:Envoy Sidecar 全链路
    • 进阶篇

      • 第30章 可编程代理:Lua / Wasm / eBPF / xDS,代理的"软件定义"
      • 第31章 性能调优:并发模型、连接池、超时与重试、压测
      • 第32章 排错决策树:502 / 504 / 握手失败 / 环路 / 泄漏
      • 第33章 代理安全:开放代理、SSRF、凭证泄漏与攻击面
    • 底层机制篇

      • 第34章 代理的背压与流控:一个代理最难的部分
      • 第35章 socket 与 TCP 状态机:半关闭、超时、连接生命周期
      • 第36章 HTTP/2 帧、流控与 HPACK:h2 代理的内部机制
      • 第37章 负载均衡算法推导与韧性状态机
      • 第38章 Capstone:把玩具代理改造成生产级骨架
    • 综合实战篇

      • 第39章 企业多跳转发链:拓扑、协议矩阵与贯穿性难题
      • 第40章 端到端实战:把 6 类流量全代理通
      • 第41章 更刁钻的流量:gRPC、长轮询、WebRTC、大文件、双向流
      • 第42章 可落地完整参考实现:一套能跑的多协议转发栈
    • 附录

      • 附录 A:代理协议报文速查(HTTP / SOCKS / PAC / PROXY protocol)
      • 附录 B:组件选型决策树
      • 附录 C:抓包与命令速查

第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_sni ACL(第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
健康检查一直 DOWNhttpchk 路径/期望状态不符核对 /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 选了它。

Prev
第13章 Nginx / OpenResty:反向代理、upstream 与 Lua 可编程
Next
第15章 Envoy:xDS 动态配置与 filter chain,为何是云原生数据面