【HAProxy 数据面】HTX 与 HTTP 路径:内部表示、改写落点与协议分叉

💡 原文中文,约6400字,阅读约需16分钟。
📝

内容提要

本文介绍HAProxy内部HTTP表示机制HTX:用版本无关的结构化块表示HTTP消息,mux负责线协议与HTX互转,规则引擎在HTX上执行改写。H1/H2在mux分叉、在HTX汇合。相比L4路径,HTX增加解析、规则、改写及再编码成本。HTX边界是安全与一致性边界,需严格阶段纪律。

🔎

延伸解读

HTX 是安全与一致性的边界

HTX 作为内部表示,不仅是性能优化,更是安全与一致性的边界。规则引擎看到的是结构化 HTX 块,而非原始字节,因此畸形消息可能在 mux 阶段就被拒绝,规则根本看不到半包原文。同时,对首部的改写必须与出口编码一致,否则在错误阶段删除或保留 Connection、Transfer-Encoding 等 hop-by-hop 首部,会导致上游断流或客户端重试。HTX 让“半改写”变得可表达,因此需要严格的阶段纪律,避免部分成功导致的语义混乱。

H1/H2 在 mux 分叉,在 HTX 汇合

HTTP/1 和 HTTP/2 在线格式上差异巨大,但 HAProxy 通过 mux 将它们统一转换为 HTX 内部表示,规则引擎只需处理 HTX,无需关心线协议细节。这带来运维含义:H2 可重置单流,而 H1 常表现为连接级关闭;H2 的 HPACK 状态在连接上,改写头部会影响编码大小。观测时,不要用 H1 时代的“一条 access log = 一个 FD”硬套 H2,应按 stream/请求关联。

HTX 成本:用能力换税

相比纯 L4 路径,HTX 增加了解析、规则引擎、改写、缓冲管理和协议转换等成本。工程判断是:需要按 Host/路径/Cookie 做切换或改写时,付 HTX 税是买能力;纯透传 TLS 或二进制协议时,强行 mode http 是买噪音。反向判断也成立:为了“统一观测”把一切抬到 HTTP,可能把 L4 故障伪装成应用层 400。赢家是故障域是否与业务语义同层。

Q&A

HAProxy中的HTX是什么?

HTX是HAProxy内部用于表示HTTP消息的版本无关的结构化格式,由有序的块组成,包括起始行、首部、数据等。它替代了早期基于原始字节缓冲的模型,使得规则引擎可以在结构化的HTX上执行改写,而mux负责线协议与HTX之间的转换。

HAProxy中HTTP/1和HTTP/2在何处分叉和汇合?

HTTP/1和HTTP/2在mux层分叉,分别由mux_h1和mux_h2解析,然后都转换为统一的HTX表示,在HTX层汇合。规则引擎在HTX上处理,出口时再编码为相应的线协议。

HAProxy中HTTP改写操作(如http-request set-header)作用于什么?

HTTP改写操作作用于HTX表示的消息,而不是原始字节缓冲。规则引擎看到的是HTX视图,改写后由出口mux重新编码为线协议。

相比mode tcp,HAProxy的HTTP路径(mode http)成本高在哪里?

相比mode tcp,HTTP路径需要额外的解析(mux解析线协议为HTX)、规则引擎处理、可能的改写(如首部修改)以及协议转换(如H2到H1的重新编码)。这些都会增加CPU和内存开销。

HTX边界为什么是安全与一致性边界?

HTX边界是安全与一致性边界,因为规则在HTX上执行,如果对首部处理不当(如删除Connection或Transfer-Encoding),可能导致上游断流或客户端异常。此外,部分成功的改写(如起始行已改但首部未改完)需要严格的阶段纪律来保证一致性。

HAProxy中H2和H1在失败粒度和并发模型上有何不同?

H2可以重置单个流,而H1通常表现为连接级关闭或影响下一条事务。H2支持多路复用,同一连接上多个流并发,而H1通常串行处理事务。

HAProxy中HTX与Envoy的codec事件有何异同?

Envoy使用codec事件驱动HTTP filter,而HAProxy使用HTX作为中间表示来驱动规则和分析器。两者都将线协议细节隐藏在可编程层之外,但在半关闭和错误传播上仍会泄漏协议差异。

🏷️

标签

➡️

继续阅读