前 13 篇把 HAProxy 钉成可排障的数据面内核:线程与 accept、stream/mux/HTX、ACL、上游与 stick-table、健康检查、TLS、Runtime 与 seamless reload。选型若再写成「各有优劣看场景」,等于把机制丢掉。
本文是终章:用机制排除树收束相对 Nginx / Envoy / eBPF 的位置,回收阅读路径,并列出仍开放的问题。不做跨产品延迟排行榜;产品叙事外链站内已有篇章。
本文是「HAProxy / 数据面代理内核」系列第 14 篇(共 14 篇 · 终章)。→ 系列目录
篇目 核心内容 第 13 篇 · 排障与可观测 五轴故障清单 第 14 篇 · 选型收束 排除树、阅读回收、开放问题
版本锚定:机制结论对齐 HAProxy 3.4.3。与 网关选型(network/60)、Envoy 选型收束、Nginx 深度、HAProxy 工程(network/56) 分工:那些文负责产品表与配置菜谱;本文负责「内核能力是否必要」。
一、先排除,再选择
flowchart TD
need{"Need rich L4/L7 LB<br/>+ Runtime ops without xDS?"}
need -->|"no, static reverse proxy"| ngx["Nginx file + reload"]
need -->|"yes"| api{"Need ACK-able API<br/>config tree + filters?"}
api -->|"yes"| env["Envoy / mesh dataplane"]
api -->|"no"| l7{"Need full HTTP policy<br/>stick-table / ACL depth?"}
l7 -->|"no, L3/L4 only"| ebpf["eBPF / IPVS path"]
l7 -->|"yes"| hap["HAProxy data plane"]
| 问题 | 若答案为「否」 | 倾向 |
|---|---|---|
| 要以代理/LB为主业,而不是 Web 静态站 + 反代? | 静态站权重高 | Nginx(55) |
| 配置必须 API 热更新且可 ACK、Filter 链组合? | 文件 + Runtime/reload 可接受 | 留在 HAProxy / Nginx 格 |
| 要深度 ACL + stick-table + Runtime 摘流? | 仅简单 upstream | Nginx 或 L4 |
| 只要 L3/L4 转发与身份? | 不需要完整 HTTP 应用语义 | eBPF / IPVS 等 |
| 要每服务独立身份与网格策略? | 边缘/节点 LB 足够 | 再评估 sidecar Envoy(Envoy 16) |
HAProxy 不是默认赢家:它赢在「经典 L4/L7 LB 内核 + 可热改运行态 + 强 ACL/粘滞」成为一等公民的时候;它输在组织已经押注 xDS 控制面经济学、或内核 L4 已够用的时候。
排除树要诚实对待编制:没有人维护配置真相与 Runtime 纪律时,强行上「复杂 stick-table + 频繁 reload」只会把故障藏进双进程窗口。
也要诚实对待「已经会用 Nginx」的沉没成本:若团队的故障手册、看板与证书流水线全挂在 Nginx 上,仅仅因为「HAProxy Runtime 更强」就迁移,往往低估排障方言切换成本。机制优势要能支付迁移税;否则先在 Nginx 格把 reload 纪律做干净,再评估是否值得换内核。反向亦然——已在 HAProxy 上跑深 ACL/stick-table 的团队,不必为「云原生」三字强行改 Envoy,除非 ACK 树与 Filter 组合已成为硬约束。
二、机制差:Nginx / HAProxy / Envoy / eBPF
| 维度 | Nginx | HAProxy(本系列) | Envoy | eBPF L3/L4 |
|---|---|---|---|---|
| 配置一等公民 | 文件 + reload | 文件 + Runtime + reload | xDS 资源树 + warming | 内核映射 / CNI 策略 |
| 请求内核 | 多进程 worker、阶段式处理 | 多线程、stream/mux/HTX | Main+Worker、Filter 链 | 内核转发,少 HTTP 语义 |
| 动态运维 | 较窄 | 权重/state/表/map 热改 | CDS/EDS/RDS… | 视实现热更新 map |
| 进程交接 | worker reload | -x / sockpair seamless |
hot-restart drain | 通常无用户态双进程交接 |
| 观测方言 | access/error + stub | stats / sess / table | admin 统一树 | 内核/cilium 可观测 |
站内 network/60 已有协议与生态横向表。本系列补充的判决句:
- 选 HAProxy:主路径是稳定、可深度策略的 L4/L7 LB;变更以文件为结构真相、Runtime 为运行态急救;需要 stick-table / 细健康检查,但不想买下整套 xDS。
- 选 Nginx:Web + 反代一体、生态与静态能力优先;动态面要求低于 HAProxy Runtime。
- 选 Envoy:控制面持续推送、Filter 组合与跨网关/mesh 同一数据面语义成为硬需求(Envoy 16)。
- 选 eBPF:L7 应用语义不是瓶颈;延迟与跳数税必须压在内核路径。
混合并不犯规:边缘 HAProxy 做 L7 入口,东西向 L4 交给 eBPF,少数服务再挂 Envoy sidecar。代价是多套排障坐标——第 13 篇清单要标明流量先进了哪一层。
进程交接对照一句就够:第 12 篇 的 seamless reload 与 Envoy hot-restart 同属「新听旧排」;差别在日常变更是否经常逼近进程级。HAProxy 用 Runtime 把大量变更留在单进程内;Envoy 用 xDS 做同类事。谁更「现代」不是判据;谁的失败模式你们排得动,才是。
再补一条组织层排除:若变更审批只认「改 conf 并 diff」,Runtime 热改会成为影子通道——要么把 Runtime 纳入同一审批与审计,要么禁止生产手工 socket。机制允许的事,流程可以收紧;反过来用流程假装有 ACK 树,填不满 xDS 那一格。
三、系列阅读路径回收
| 路径 | 篇目 | 收回什么 |
|---|---|---|
| 必读核心 | 01 → 02 → 04 → 08 → 12 → 13 | 坐标系 + stream + stick + reload + 排障 |
| 请求深挖 | 03 → 04 → 05 → 06 → 07 | accept 到上游 |
| 动态运维 | 11 → 12 → 13 | Runtime / reload 联调 |
| 对照选型 | 01 → 13 → 14 | 五轴 + 排除树 |
| 配置预习 | network/56 | 单篇菜谱;机制仍回本系列 |
五个关键问题(系列 index)到终章仍然够用:争议要么落在「要不要 API 驱动路径」,要么落在「粘滞/限流状态如何跨 reload 存活」,很少落在营销形容词上。
写给后续维护者:升 3.4.x patch 或改 master-worker/Reload 单元时,先重跑第 13 篇与 accept/reload 相关的门禁,再更新本篇排除树的假设。
若读者时间只够一篇:读 01 全景 建立缺口意识,再读本篇排除树,最后按自己的主轴跳进 08/11/12/13 之一。完整通读的收益是「症状能落格」;跳读的风险是把 Runtime 当成万能控制面,或把 seamless 当成零失败保证。
与站内相邻系列的接法:先修配置直觉读 56;要对照 worker 模型读 55;要对照 API 驱动读 Envoy 目录 与 16;产品勾选读 60。本系列不替代其中任何一篇,只补「一次连接与一次 reload 在内核里发生了什么」。
四、系列级开放问题
下列问题有工程与社区争议;本系列给了机制语言,但不假装已关闭。不用延迟排行榜代替回答。
4.1 Stick-table 规模与 peers 一致性
表容量、过期、跨线程更新与 peers
分片在极大键空间下,延迟与一致性如何权衡?单机 peers「抗
reload
丢表」与多机同步的失败模式是否共用同一套可观测信号?(入口:第
8、12、13 篇;Configuration Manual peers /
stick-table。)
可检验子问题:在给定 size 与
expire 下,满表驱逐与 peers 断连,能否被
show table / show peers
与日志充分区分,还是必须外挂指标?
进一步:当表用于安全封禁时,短暂的 peers 分区是否可能造成「一侧重放、一侧仍封」的策略分裂?这类分裂在文件驱动模型里没有 xDS 式的版本向量,只能靠运维约定与告警——这是机制间隙,不是配置笔误。
4.2 QUIC / HTTP/3 在 3.4 线上的成熟度边界
QUIC frontend 与 TCP/HTTP/1·2 路径在 mux、超时、连接迁移、排障信号上何处分叉?Runtime / reload 对 QUIC listener 的约束(文档已提示部分动态删除限制)如何写入发布门禁?(入口:第 4–5、10 篇;3.4 Configuration Manual / Management Guide 中 QUIC 相关命令说明。)
可检验子问题:同一套 ACL/backend 配置下,H3
特有失败能否被现有 httplog 终止码与 show sess
表达,还是必须协议专用计数器?
与 Envoy 16 列出的 HTTP/3 开放问题平行:两端都在追协议成熟度,谁「领先」随版本漂移;选型应比较你们要上的那条协议路径是否已有排障坐标,而不是比较营销页的 H3 勾选框。
4.3 Reload vs Runtime 运维模型的可观测性
结构走文件、运行态走 Runtime 时,「配置已生效」的 SLO
应钉在哪:磁盘 mtime、reload 完成、还是某条
show *
断言?混用导致的真相分叉,如何在不引入完整 xDS ACK
树的前提下可审计?(入口:第 11–13 篇;对照 Envoy
warming/ACK。)
可检验子问题:一次变更流水线能否输出机器可读的证据包(文件哈希
+ reload 世代 + 抽样 show stat 字段),使「Git
与内存一致」成为门禁而非口头约定?
子问题的反面:若证据包成本高于变更收益,组织是否应收敛变更面——少用动态 server、少用长期只活在内存的 map——而不是假装有 ACK。可观测性解决不了「故意让真相分叉」的流程问题。
与 network/60 的产品表合读时:表回答「生态与协议勾选」;本开放问题回答「勾选之后夜里能不能定位」。两者缺一,选型讨论会在会议里循环。
这些问题不要求终章拍板。它们要求后续文章或事故复盘带着五轴与排除树回去量:量的是表满驱逐率、peers 断连、reload 窗口失败、Runtime/文件漂移——而不是再写一张无口径的代理延迟榜。
终章立场可以收成一句:HAProxy 数据面值得写成系列,是因为它把经典 LB 的路径、热改与 seamless reload 变成可命名机制;选型与开放问题若离开这些名字,讨论会退回品牌口号。
回到系列开头的缺口陈述:站内已有配置菜谱与网关产品表,缺的是「路径与动态运维的可核对内核」。若读完 14 篇仍只能复述功能清单,说明阅读停在目录;若能在故障里说出「这是 stick-table 在 reload 未配 peers 时的预期清空」或「这是 Runtime 与文件分叉」,机制文才算交货。
最后提醒一次边界:本系列不写 Enterprise 专有能力、不写
Lua/SPOE
SDK、不做跨代理延迟榜。开放问题欢迎用事故数据与官方文档补完,不欢迎用无口径截图开战。版本钉在
3.4.3;升版时先重跑 Management Guide 中与
-x、Master CLI、QUIC 相关的章节差分。
若只用一句话向架构评审交代本系列:HAProxy 占据「文件为结构真相、Runtime 为运行态、seamless reload 为结构世代切换」这一格;Nginx 更偏 Web+反代与更窄动态面;Envoy 占据 ACK 式资源树与 Filter 组合;eBPF 占据 L3/L4 内核路径。选格先于选品牌,排障坐标先于延迟传说。
对平台团队的务实建议:先用第 13 篇清单跑通一次真实故障或演练,再决定要不要为了「动态配置」迁到 Envoy。若演练里卡在 stick-table 与 reload,优先补 peers 与变更门禁;若卡在「没有可编程 Filter」,再评估 Envoy。机制排除树的正确用法是缩短错误迁移,而不是证明某品牌永远正确。
至此,系列在机制层闭合:从 frontend 到 seamless reload,再到排障与选型。后续补丁级更新应改版本钉与开放问题进展,而不是重写排除树的问题顺序。
五、参考资料
规范 / 官方文档(A)
- HAProxy 3.4.3 Management Guide
/ Configuration Manual / Starter
Guide:
https://docs.haproxy.org/3.4/ - 源码 tag
v3.4.3:
https://github.com/haproxy/haproxy(机制核对)
站内对照
研究 / 争论入口(方向,非排名)
- 用户态事件驱动 LB vs 内核 eBPF 数据路径的分工(系统会议与 CNI 实践中的反复议题)。
- 文件/Runtime 运维模型 vs xDS ACK 经济学(对照 Envoy 控制面文献与本系列第 11–12 篇)。
读完这篇,下一步读什么
优先读同系列或同问题的下一篇,把单篇消费变成主题集群。
【Envoy 数据面】选型收束:机制排除树与系列开放问题
用机制排除树收束 Envoy 相对 Nginx/HAProxy、sidecar / 节点级 Envoy / eBPF 的选型;回顾阅读路径,并列出 xDS 规模、sidecar 税、Wasm 与 HTTP/3 等系列级开放问题。
【HAProxy 数据面】Runtime API:可热改边界与必须 reload 的配置面
按 HAProxy 3.4.3 Management Guide 钉住 Runtime API 能改什么、不能改什么;区分 worker stats socket 与 master CLI,说明热改与 seamless reload 的语义边界。
【HAProxy 数据面】ACL / 规则引擎:求值顺序、副作用与 stick-table 耦合
把 ACL 与 http-request / use_backend 当作数据面机制:说明连接期到 L7 的求值顺序、动作副作用如何改写后续条件,以及与 stick-table 限流/标记的耦合点;不写 ACL 关键字百科。
【HAProxy 数据面】Stick-table:键类型、容量、跨线程可见性与 peers/reload
说明 stick-table 的键类型、size/expire/store、nbthread 共享内存与 nbproc 不共享的边界,以及 peers 复制与 reload 继承;覆盖表满等容量失败模式。