跳转到主要内容

这是本节的多页打印视图。 .

返回本页常规视图.

HAProxy 3.4.4 中文文档

HAProxy 3.4 入门、配置与管理三套完整手册的简体中文译本

HAProxy 是一款免费、快速、可靠的反向代理,适用于高可用、TCP 与 HTTP 负载均衡及应用流量管理。本组件收录三套 HAProxy 3.4 核心手册的完整中文译文,并将其重新编排为适合 OINK 阅读器的扁平阅读顺序。

选择手册

  • 入门指南 — 用 9 个主题介绍负载均衡基础、HAProxy 架构、功能、容量规划、版本升级与周边生态。
  • 配置手册 — 用 12 章完整覆盖代理、ACL、样本提取、日志、过滤器及各类选项。
  • 管理指南 — 用 13 章讲解启动、重载、资源、日志、统计信息、运行时 CLI、故障排查与安全。

版本涵盖范围

手册上游篇幅本站编排
入门指南1,695 行9 个扁平主题页
配置手册33,148 行12 个扁平章节页
管理指南5,285 行13 个扁平章节页

全部 34 个阅读页面均直接位于 HAProxy 组件根目录下。侧边栏使用三个不可点击的分组占位页分隔三套手册,不增加目录层级,也不占用前后翻页节点。

固定版本的完整源文件及其 SHA-256 校验和保存在 sources/haproxy/ 下。上游许可声明 与 GPLv2 全文 随手册一并发布。本中文版本与英文原文逐页对应。

1 - 负载均衡基础

数据包、网络、服务器、L4 和 L7 负载均衡基础

本文旨在向所有尚未了解 HAProxy 的用户以及希望重新认识该软件(尤其是熟悉旧版本的用户)提供入门引导。本文主要目的在于为用户提供充分信息,以判断 HAProxy 是否符合其需求。高级用户可能在此发现某些解决方案的片段,仅因此前未意识到某项新功能的存在。此外,本文还提供了部分容量规划信息,说明了产品的生命周期,并对部分功能重叠的产品进行了对比。

本文不提供任何配置帮助或提示,但说明了如何查找相关文档。本指南以 HAProxy 侧边栏中的扁平主题页面序列形式呈现。

负载均衡是指将多个组件聚合在一起,以实现总处理能力超过单个组件的处理能力,且无需终端用户干预,并具备可扩展性。这使得在单个组件完成一次操作所需的时间内,能够同时执行更多操作。然而,单个操作仍需在单个组件上依次执行,其执行速度不会因负载均衡而加快。负载均衡的实现必须至少具备与可用组件数量相等的操作数,以及高效的负载均衡机制,才能充分利用所有组件并完全发挥负载均衡的优势。一个典型的例子是高速公路的车道数量,它能够在不提高单车速度的前提下,使更多车辆在相同时间段内通过。

负载均衡示例:

  • 多处理器系统中的进程调度
  • 链路负载均衡(例如 EtherChannel、Bonding)
  • IP 地址负载均衡(例如 ECMP、DNS 轮询)
  • 服务器负载均衡(通过负载均衡器实现)

执行负载均衡操作的机制或组件称为负载均衡器。在 Web 环境中,这些组件通常被称为“网络负载均衡器”,但更常见的是直接称为“负载均衡器”,因为此类应用无疑是负载均衡最广为人知的场景。

负载均衡器可执行以下操作:

  • 在链路层:这称为链路负载均衡,其原理是选择将数据包发送至哪个网络链路;

  • 在网络层面:这被称为网络负载均衡,其原理是选择一系列数据包所遵循的路由路径;

  • 在服务器级别:这称为服务器负载均衡,其作用是决定由哪台服务器处理连接或请求。

存在两种不同的技术,各自满足不同需求,部分能力有所重叠。无论采用哪一种,都必须牢记:负载均衡会改变流量的自然路径,因此必须谨慎处理,确保所有路由决策保持必要的一致性。

第一种技术在数据包层面运行,对数据包进行或多或少的独立处理。输入与输出数据包之间存在一对一的关系,因此可以使用常规网络嗅探工具在负载均衡器的两侧追踪流量。该技术通常成本低廉且速度极快。它通常通过硬件(ASIC)实现,可达到线路速率,例如执行 ECMP 的交换机。通常为无状态,但也支持有状态(考虑数据包所属会话),称为第 4 层负载均衡(L4),若数据包未被修改,还可支持 DSR(直接服务器返回,无需再次经过负载均衡器),但几乎不具备内容感知能力。该技术非常适合网络层负载均衡,尽管有时也用于高速场景下的基础服务器负载均衡。

第二种技术处理会话内容。它要求重组输入流并将其作为整体处理;内容可以修改,输出流则重新拆分为数据包。因此,这类操作通常由代理完成,此类代理常称为第 7 层负载均衡器或 L7 负载均衡器。负载均衡器两侧是两条相互独立的连接,输入与输出数据包的大小和数量没有对应关系。客户端与服务器也不必使用相同协议(例如 IPv4 与 IPv6、明文与 SSL)。这种操作始终是有状态的,返回流量必须经过负载均衡器。额外的处理开销通常使其无法达到线速,尤其是在处理小数据包时;另一方面,它提供了极大的灵活性,通常由纯软件实现,即使部署在硬件设备中也是如此。该技术非常适合服务器负载均衡。

基于数据包的负载均衡器通常以直通模式部署,因此被置于流量的正常路径上,并根据配置进行流量转发。返回流量不一定经过负载均衡器。为将流量导向正确目的地,可能需要对网络目标地址进行修改。在此情况下,必须确保返回流量经过负载均衡器。若路由无法实现此目的,负载均衡器还可将数据包的源地址替换为其自身地址,以强制返回流量经过它。

基于代理的负载均衡器以拥有独立 IP 地址和端口的服务器形式部署,无需更改架构。有时需要对应用程序进行一些调整,以确保客户端正确地被引导至负载均衡器的 IP 地址,而非直接连接到服务器。部分负载均衡器可能需要修改某些服务器的响应,以实现这一目标(例如,HTTP 重定向中使用的 HTTP Location 头字段)。某些基于代理的负载均衡器可能拦截其并不拥有的地址的流量,并在连接服务器时伪造客户端地址。这使得它们可以像普通路由器或防火墙一样部署,以近乎与基于数据包的负载均衡器相同的直通模式运行。对于同时支持数据包模式和代理模式的产品而言,这一点尤为实用。在此情况下,DSR 仍不可行,返回流量仍必须路由回负载均衡器。

一种高度可扩展的分层架构包括:前端路由器接收来自多个负载均衡链路的流量,并使用 ECMP 将流量分发至第一层的多个基于状态的包级负载均衡器(L4)。这些 L4 负载均衡器再将流量转发至数量更多的基于代理的负载均衡器(L7),后者需解析流量内容以决定最终接收流量的服务器。

组件数量和流量路径的增加提高了故障风险;在非常大型的环境中,永久存在少数故障组件并处于修复或更换状态是正常现象。若负载均衡未考虑整个堆栈的健康状况,将显著降低可用性。因此,任何合理的负载均衡器都会验证其计划分发流量的目标组件是否仍处于活跃且可达状态,并停止向故障组件分发流量。这可通过多种方式实现。

最常见的方法是定期发送探测请求,以确保组件仍处于正常运行状态。这些探测请求被称为“健康检查”。健康检查必须能够代表所要解决的故障类型。例如,基于 ping 的检查无法检测到 Web 服务器已崩溃且不再监听端口的情况,而连接到该端口的检查则可以验证这一点,更高级的请求甚至可以验证服务器是否仍在正常工作,以及其所依赖的数据库是否仍可访问。健康检查通常包含若干次重试,以应对偶尔的测量误差。健康检查之间的间隔必须足够短,以确保在发生错误后,故障组件不会被继续使用过长时间。

其他方法包括对发送至目标的生产流量进行采样,以观察其是否被正确处理,并移除返回异常响应的组件。然而,这种方法需要牺牲一部分生产流量,这并不总是可接受的。将这两种机制结合使用,可以兼顾两者的优点:两者均用于检测故障,而仅通过健康检查来检测故障的结束。最后一种方法涉及集中式报告:中央监控代理定期向所有负载均衡器更新所有组件的状态。这使所有组件都能获得基础设施的全局视图,尽管有时准确性或响应性可能较低。该方法最适合负载均衡器和服务器数量较多的环境。

第 7 层负载均衡器还面临另一个挑战,即会话粘性或持久性。其原理是,它们通常必须将来自同一来源(例如终端用户)的多个后续请求或连接导向同一目标服务器。最典型的例子是在线商店的购物车。如果每次点击都导致新的连接,用户必须始终被发送到保存其购物车的服务器。内容感知能力使得更容易在请求中识别某些元素以确定目标服务器,但这并不总是足够。例如,以源地址作为服务器选择键时,可以使用哈希算法,将地址对可用服务器数取模,从而把特定 IP 地址始终发送到同一服务器。但如果某台服务器发生故障,可用服务器数改变,取模结果也会变化,所有用户可能突然转到其他服务器并丢失购物车。解决办法是记住所选的目标服务器:以后每次遇到同一访问者时,无论可用服务器数量如何变化,都将其导向同一服务器。该信息可存储在负载均衡器的内存中;若存在多个负载均衡器,可能需要在它们之间复制。也可通过多种方式将信息保存在客户端,前提是客户端能在每次请求中将其带回(例如插入 Cookie、重定向到子域名等)。这样还无需依赖源 IP 地址等不稳定或分布不均的信息。这正是采用第 7 层而非第 4 层负载均衡器的首要原因。

为了提取诸如 Cookie、Host 头字段、URL 等信息,负载均衡器可能需要解密 SSL/TLS 流量,甚至在将流量转发至服务器时重新加密。这一高开销操作解释了为何在某些高流量基础设施中,负载均衡器的数量可能非常多。

由于第 7 层负载均衡器可能对流量执行多项复杂操作(如解密、解析、修改、匹配 Cookie、决定将请求转发至哪个服务器等),它确实可能引发诸多问题,且常常被误认为是许多问题的根源,而实际上它只是暴露了原本就存在的问题。通常会发现服务器不稳定,周期性地上下线;对于 Web 服务器而言,可能其返回的页面中包含硬编码的链接,导致客户端绕过负载均衡器直接连接至特定服务器;或者在高负载下响应时间极长,引发超时。因此,日志记录是第 7 层负载均衡中极为关键的环节。一旦出现故障报告,必须迅速判断负载均衡器是否做出了错误决策,以及错误的原因,从而防止问题再次发生。

2 - HAProxy 是什么及其实现原理

HAProxy 的角色、边界、事件驱动架构及请求处理模型

HAProxy 用于指代产品,而 HAProxy 用于指代可执行程序、软件包或进程。然而,两者常被互换使用,且均发音为 H-A-Proxy。早期,“HAProxy”曾代表“高可用性代理”,名称以两个独立单词书写,但如今其含义已仅限于“HAProxy”。

3.1. HAProxy 是与非

HAProxy 是:

  • TCP 代理:可从监听套接字接收 TCP 连接,连接至服务器,并将这两个套接字绑定在一起,从而实现双向流量传输;支持任一侧使用 IPv4、IPv6 或 Unix 套接字,因此可提供一种简便方式,实现不同地址族之间的地址转换。

  • 一个 HTTP 反向代理(在 HTTP 术语中称为“网关”):它表现为一个服务器,通过监听 TCP 套接字接收连接上的 HTTP 请求,并使用不同的连接将这些请求转发至服务器。它可在任一侧使用任意组合的 HTTP/1.x 或 HTTP/2,并在使用 ALPN 通过 TLS 时自动检测每侧所使用的协议。

  • SSL 终止器 / 初始化器 / 卸载器:客户端连接、服务器连接,或两者均可使用 SSL/TLS。可根据名称(SNI)应用大量设置,且可在不重启的情况下动态更新。此类配置具有极强的可扩展性,已有部署报告支持数万至数十万张证书。

  • TCP 正常化器:由于连接由操作系统本地终止,双方之间不存在关联,因此无效数据包、异常标志组合、窗口通告、序列号异常、不完整连接(如 SYN 洪水)等异常流量不会传递到另一方。这可保护脆弱的 TCP 栈免受协议攻击,同时允许在不修改服务器 TCP 栈设置的前提下,对客户端连接参数进行优化。

  • HTTP 正常化器:当配置为处理 HTTP 流量时,仅允许完整且有效的请求通过。这可有效防范多种基于协议的攻击。此外,对于规范中允许容忍的协议偏差,会进行修正,以避免其在服务器端引发问题(例如,多行头)。

  • 一个 HTTP 修复工具:可用于修改、修复、添加、删除或重写 URL,以及任意请求或响应头。这有助于解决复杂环境中的互操作性问题。

  • 基于内容的转发:可根据请求中的任意元素决定将请求或连接转发至哪个服务器。因此,可在同一端口上处理多种协议(例如 HTTP、HTTPS、SSH)。

  • 服务器负载均衡器:可对 TCP 连接和 HTTP 请求进行负载均衡。在 TCP 模式下,负载均衡决策针对整个连接作出。在 HTTP 模式下,决策针对每个请求作出。

  • 流量调节器:可在多个位置实施速率限制,防止服务器过载,根据流量内容调整流量优先级,甚至通过标记数据包将此类信息传递至下层及外部网络组件。

  • 防护 DDoS 和服务滥用:可针对每个 IP 地址、URL、Cookie 等维护大量统计信息,检测到滥用行为时采取动作(如降低攻击者速率、阻止其访问、将其引导至过时内容等)。

  • 网络故障排查的观察点:由于日志中报告的信息精度较高,常用于缩小某些网络相关问题的排查范围。

  • HTTP 压缩卸载器:可对服务器未压缩的响应进行压缩,从而降低客户端在连接质量较差或使用高延迟移动网络时的页面加载延迟。

  • 缓存代理:可将响应缓存在内存中,使后续对同一对象的请求无需再次从服务器进行网络传输,只要该对象仍存在且有效即可。但该代理不会将对象存储到任何持久化存储中。请注意,此缓存功能旨在实现免维护运行,仅专注于节省 HAProxy 的宝贵资源,而非节省服务器资源。旨在优化服务器的缓存需要更多的调优和灵活性。如需此类高级缓存功能,请使用 Varnish Cache,其与 HAProxy 集成良好,尤其在任一侧需要 SSL/TLS 时。

  • FastCGI 网关:FastCGI 可被视为 HTTP 的另一种表现形式,因此 HAProxy 可直接对任意组合的 FastCGI 应用服务器集群进行负载均衡,无需在它们之间插入额外的网关层。这可节省资源并降低维护成本。

HAProxy 不是:

  • 显式 HTTP 代理,即浏览器用于访问互联网的代理。此类任务已有诸多优秀的开源软件专门支持,例如 Squid。然而,可在此类代理前部署 HAProxy,以实现负载均衡和高可用性。

  • 数据清理器:不会修改请求或响应的正文内容。

  • 静态 Web 服务器:启动期间,它会将自身隔离在 chroot 环境中并放弃特权,因此启动后将不会执行任何文件系统访问操作。因此,它无法被用作静态 Web 服务器(动态服务器可通过 FastCGI 支持)。此类用途有众多优秀的开源软件可供选择,例如 Apache 或 NGINX,HAProxy 可轻松部署在它们前端,以提供负载均衡、高可用性和加速功能。

  • 基于数据包的负载均衡器:它不会处理 IP 数据包或 UDP 数据报,也不会执行 NAT 或更不用说 DSR。这些任务应由更低层级完成。某些基于内核的组件(如 IPVS(Linux 虚拟服务器))已能很好地完成此类工作,并与 HAProxy 完美互补。

3.2. HAProxy 的工作原理

HAProxy 是一个基于事件驱动、非阻塞的引擎,结合了极快的 I/O 层与基于优先级的多线程调度器。由于其设计目标是数据转发,架构经过优化,能够在最少的操作下尽可能快速地传输数据。它通过尽可能将连接绑定到同一 CPU 来提升 CPU 缓存的使用效率。因此,它采用分层模型,在每一层都提供绕行机制,确保数据仅在必要时才传递到更高层级。大部分处理工作在内核中完成,HAProxy 尽最大努力通过提供一些提示或在预判后续操作可合并时避免某些操作,来帮助内核尽可能高效地完成工作。结果表明,典型情况下,在 TCP 或 HTTP 关闭模式下,HAProxy 占用约 15% 的处理时间,内核占用 85%;在 HTTP 持久连接模式下,HAProxy 占用约 30%,内核占用 70%。

一个进程可以运行多个代理实例;有报告称单个进程中运行多达 300000 个不同代理实例也能正常工作。对于超过 99% 的用户而言,单核、单 CPU 的配置已完全足够,因此使用容器和虚拟机的用户应尽量采用最小的镜像,以降低运营成本并简化故障排查。然而,HAProxy 所运行的机器绝不能进行交换(swap),其 CPU 也不得被人为限速(如虚拟化环境中低于单 CPU 的分配),更不应与计算密集型进程共享,否则将导致极高的上下文切换延迟。

多线程机制可通过每个 CPU 核心使用一个线程的方式,充分利用所有可用的处理能力。该机制在处理 SSL 或需要超过 40 Gbps 的数据转发速率时尤为有用。在此类场景下,避免多个物理 CPU 之间的通信至关重要,否则可能导致网络栈及 HAProxy 本身出现严重瓶颈。尽管对部分用户而言看似反直觉,但在面对性能问题时,通常应优先考虑减少 HAProxy 所运行的 CPU 数量。

HAProxy 仅需 HAProxy 可执行文件和配置文件即可运行。为实现日志记录,强烈建议配置好 syslog 守护进程并设置日志轮转。日志也可发送至 stdout/stderr,这在容器环境中尤为有用。配置文件在启动前被解析,随后 HAProxy 会尝试绑定所有监听套接字,若任一绑定失败则拒绝启动。一旦越过此阶段,便不再可能失败。这意味着不存在运行时故障,若 HAProxy 确认启动,则将持续正常运行直至被停止。

HAProxy 启动后,将执行以下三项操作:

  • 处理入站连接;

  • 定期检查服务器状态(称为健康检查);

  • 与其他 HAProxy 节点交换信息。

处理传入连接是迄今为止最复杂的任务,因为它依赖于众多配置选项,但可以概括为以下 9 个步骤:

  • 接受来自属于名为“前端”(frontend)的配置实体的监听套接字的入站连接,该前端引用一个或多个监听地址;

  • 对这些连接应用前端特定的处理规则,可能造成连接被阻断、修改部分头信息,或拦截连接以执行某些内部小程序,例如统计页面或 CLI;

  • 将这些传入连接转发至另一个代表服务器集群的配置实体,即“后端”,该后端包含服务器列表以及此服务器集群的负载均衡策略;

  • 对这些连接应用后端特定的处理规则;

  • 根据负载均衡策略决定将连接转发至哪台服务器;

  • 对响应数据应用后端特定的处理规则;

  • 对响应数据应用前端特定的处理规则;

  • 发送日志以详细报告发生的情况;

  • 在 HTTP 中,返回第二步以等待新请求;否则,关闭连接。

前端和后端有时被视为半代理,因为它们仅关注端到端连接的一侧;前端仅关注客户端,而后端仅关注服务器。HAProxy 还支持全代理,其定义为前端与后端的完全并集。当需要进行 HTTP 处理时,配置通常会划分为前端和后端,因为这种结构提供了大量灵活性,任意前端均可将连接转发至任意后端。在仅使用 TCP 的代理场景中,使用前端和后端通常无法带来明显优势,采用全代理配置反而可能使配置更清晰易读。

3 - 基本功能

代理、TLS、监控、高可用性、负载均衡、会话粘性、日志、统计信息

本段将列举 HAProxy 实现的若干功能,其中部分功能是现代负载均衡器普遍具备的特性,另一些则是 HAProxy 架构带来的直接优势。更高级的功能将在下一节中详细说明。

3.3.1. 基本功能:代理

代理是指通过两个独立连接在客户端与服务器之间传输数据的动作。HAProxy 支持以下基本功能,涉及代理和连接管理:

  • 为服务器提供干净的连接,以保护其免受客户端缺陷或攻击的影响;

  • 监听多个 IP 地址和/或端口,包括端口范围;

  • 透明接收:拦截目标为任意 IP 地址的流量,即使该地址并不属于本地系统;

  • 服务器端口无需与监听端口相关,甚至可以通过固定偏移量进行转换(在使用端口范围时很有用);

  • 透明连接:在连接服务器时,如需可伪造客户端(或任意)IP 地址;

  • 为多站点负载均衡中的服务器提供可靠的返回 IP 地址;

  • 通过使用缓冲区并可能采用短时连接,减轻服务器负载,降低其并发连接数和内存占用;

  • 优化 TCP 栈(例如 SACK)、拥塞控制,并降低 RTT 影响;

  • 支持两侧使用不同的协议族(例如 IPv4/IPv6/Unix);

  • 超时控制:HAProxy 支持根据连接所处阶段的不同,设置多级超时,以防止客户端或服务器失效,或攻击者长期占用资源;

  • 协议验证:检查 HTTP、SSL 或负载内容,拒绝无效的协议元素,除非明确指示仍接受这些元素;

  • 策略执行:确保仅允许的内容可被转发;

  • 入站和出站连接均可限制在特定的网络命名空间内(仅限 Linux),从而轻松构建跨容器、多租户的负载均衡器;

  • PROXY 协议可将客户端 IP 地址传递给服务器,即使针对非 HTTP 流量亦然。这是 HAProxy 的一项扩展,目前已获得多项第三方产品的采纳,至少包括以下产品(以撰写本文时为准):

    • 客户端:HAProxy, stud, stunnel, exaproxy, ELB, squid
    • 服务器:HAProxy, stud, postfix, exim, NGINX, squid, node.js, varnish

3.3.2. 基本功能:SSL

HAProxy 的 SSL 栈被 Google 工程师公认为功能最丰富的之一(http://istlsfastyet.com/ )。最常使用的功能使其具备了相当完整的特性,包括:

  • 基于 SNI 的多主机支持,不限制站点数量,专注于性能。已知至少有一个部署实例成功运行了 50000 个域名及其对应的证书;

  • 支持通配符证书可减少对多个证书的需求;

  • 基于证书的客户端认证,支持在未提供有效证书时配置失败策略。此功能允许向客户端呈现不同的服务器集群,以重新生成客户端证书,例如;

  • 后端服务器的身份认证可确保后端服务器为真实服务器,而非中间人;

  • 与后端服务器进行认证,可使后端服务器确认连接它的确实是预期的 HAProxy 节点;

  • TLS NPN 和 ALPN 扩展可实现对 SPDY/HTTP2 连接的可靠卸载,并以明文形式将连接传递给后端服务器;

  • OCSP 装订可在客户端请求证书状态时直接随证书传递 OCSP 响应,进一步缩短首页加载时间;

  • 动态记录大小可同时实现高性能与低延迟,并通过允许浏览器在数据包传输过程中即开始获取新对象,显著减少页面加载时间;

  • 永久访问所有相关的 SSL/TLS 层信息,用于日志记录、访问控制、报告等。这些信息可嵌入 HTTP 头,甚至作为 PROXY 协议扩展,使卸载的服务器能够获得其自身执行 SSL 终止时所具备的全部信息。

  • 检测、记录并阻止针对易受攻击的 SSL 库(如影响某些版本 OpenSSL 的 Heartbleed 攻击)的特定已知攻击。

  • 支持无状态会话恢复(RFC 5077 TLS 会话票据扩展)。可通过 CLI 更新 TLS 会话票据密钥,并频繁轮换以保持前向安全性。

3.3.3. 基本功能:监控

HAProxy 高度关注可用性。因此,它会关注服务器状态,并向其他网络组件报告自身状态:

  • 通过服务器级参数持续监控服务器状态。这可确保通往服务器的路径对常规流量保持可用;

  • 健康检查支持两种滞后机制,用于上行和下行状态切换,以防止状态抖动;

  • 可以向不同的地址、端口或协议发送检查:这使得检查一个代表多个服务的单一服务变得简单,例如对 HTTP+HTTPS 服务器检查其 HTTPS 端口。

  • 服务器可跟踪其他服务器并同时宕机:这确保了托管多个服务的服务器能够原子性地故障,且不会有人被发送至部分故障的服务器;

  • 可在服务器上部署代理以监控负载和健康状态:服务器可能希望独立于健康检查结果,报告自身的负载、运行状态和管理状态。通过在服务器上运行一个简单的代理,可结合健康检查结果,同时考虑服务器自身对其健康状况的判断。

  • 支持多种检查方法:TCP 连接、HTTP 请求、SMTP Hello、SSL Hello、LDAP、SQL、Redis,以及带或不带 SSL 的 send/expect 脚本;

  • 状态变更会在日志和统计信息页面中通知,并附带故障原因(例如,检测到故障时接收到的 HTTP 响应)。在发生此类变更时,也可向可配置的地址发送电子邮件;

  • 服务器状态也会在统计信息界面中报告,可用于决定路由策略,从而根据服务器组的规模和/或健康状况将流量发送至不同的后端集群(例如,当跨数据中心链路丢失时)。

  • HAProxy 可通过健康检查请求向服务器传递信息,例如服务器名称、权重、所在服务器组中的其他服务器数量等,使服务器能够基于这些信息调整其响应和决策(例如推迟备份操作,以保留更多 CPU 资源)。

  • 服务器可使用健康检查报告比开关状态更详细的状态(例如:我想要停止服务,请停止向我发送新访客);

  • HAProxy 可以向外部组件(如路由器或其他负载均衡器)报告自身状态,从而构建非常完整的多路径和多层基础设施。

3.3.4. 基本功能:高可用性

与任何专业的负载均衡器一样,HAProxy 高度关注可用性,以确保最佳的全局服务连续性:

  • 仅使用有效的服务器;其他服务器会自动从负载均衡池中移除; 尽管如此,在特定条件下仍可强制使用它们;

  • 支持优雅关闭,以便在不影响任何连接的情况下将服务器从服务器组中移除;

  • 当活跃服务器宕机时,备用服务器会自动启用并替代其位置,以尽可能避免会话丢失。这还支持构建通往同一服务器的多条路径(例如,通过多个接口);

  • 当某个服务组中过多服务器离线时,支持返回全局失败状态。结合监控能力,可使上游组件为特定服务选择其他负载均衡节点。

  • 无状态设计便于构建集群:HAProxy 从设计上力求在发生故障时确保最高程度的服务连续性,无需存储可能因故障而丢失的信息。这确保了故障切换过程尽可能无缝。

  • 与标准的 VRRP 守护进程 keepalived 集成良好:HAProxy 可轻松向 keepalived 通告自身状态,并能很好地处理浮动虚拟 IP 地址。请注意:仅在基于集群的解决方案(如 Heartbeat 等)上使用 IP 冗余协议(VRRP/CARP),因为只有这些方案能提供最快、最无缝且最可靠的故障切换。

3.3.5. 基本功能:负载均衡

HAProxy 提供了相当完整的负载均衡功能,其中大部分功能在其他若干负载均衡产品中尚不可用:

  • 支持不少于 10 种负载均衡算法,其中部分算法可基于输入数据提供无限多的可能性。最常见的包括:轮询(适用于短连接,依次选择各服务器)、leastconn(适用于长连接,选择连接数最少且最近使用最少的服务器)、source(适用于 SSL 服务器集群或终端服务器集群,服务器直接依赖客户端的源地址)、URI(适用于 HTTP 缓存,服务器直接依赖 HTTP URI)、hdr(服务器直接依赖特定 HTTP 头字段的内容)、first(适用于短生命周期的虚拟机,将所有连接集中到尽可能少的服务器子集上,以便未使用的服务器可被关机)。

  • 上述所有算法均支持为每台服务器设置权重,以便在服务器集群中兼容不同代际的服务器,或定向将少量流量引导至特定服务器(例如用于调试模式,或运行软件的下一个版本等);

  • 轮询、最少连接和一致性哈希支持动态权重;这允许通过 CLI 实时修改服务器权重,甚至可由运行在服务器上的代理程序完成;

  • 当支持动态权重时,也支持慢启动(slow-start);这使得服务器可以逐步接管流量。该功能对于需要在运行时编译类的脆弱应用服务器,以及需要在全速运行前完成预热的冷缓存尤为重要;

  • 哈希算法可应用于多种元素,例如客户端的源地址、URL 组件、查询字符串元素、头字段值、POST 参数、RDP Cookie;

  • 一致性哈希可保护服务器集群在增减集群中的服务器时免受大规模重分配的影响。这一点在大型缓存集群中尤为重要,同时允许使用冷启动机制来重新填充冷缓存;

  • 多项内部指标(例如每台服务器、每个后端的连接数,后端中可用连接槽位数量等)使得构建非常复杂的负载均衡策略成为可能。

3.3.6. 基本功能:会话粘性

应用负载均衡若无会话粘性将毫无意义。HAProxy 提供了相当全面的机制,可在服务器添加/移除、启停周期等各类事件发生时,仍确保访问者始终被分配至同一台服务器。部分方法设计时即考虑了多台负载均衡节点间距离的影响,具备对节点间距离的抗性,无需任何数据复制。

  • 可根据需要从不同位置分别匹配和学习会话粘性信息。 例如,JSESSIONID cookie 可同时在 Cookie 和 URL 中进行匹配。最多可同时学习 8 个并行源,每个源可指向不同的会话表;

  • 会话粘性信息可来自请求或响应中可识别的任何内容,包括源地址、TCP 负载偏移与长度、HTTP 查询字符串元素、头字段值、Cookie 等。

  • stick-tables 在多主模式下于所有节点间进行复制;

  • 常用元素如 SSL-ID 或 RDP Cookie(用于 TSE 群集)可直接访问,以简化操作;

  • 所有粘性规则均可通过 ACL 动态条件化;

  • 可以选择不将流量固定到某些服务器,例如备用服务器,以便当主服务器恢复后,流量可自动重新切换回主服务器。这在多路径环境中经常使用;

  • 在 HTTP 中,通常更倾向于不学习任何信息,而是操作专用于会话粘性的 Cookie。为此,可以检测、重写、插入或添加前缀到此类 Cookie,以使客户端记住被分配的服务器。

  • 服务器可能在用户登出时更改或清除会话粘性 Cookie,以便使离开的访客自动与服务器解除绑定;

  • 使用基于 ACL 的规则,可选择性地忽略或强制实施会话粘性,而无需考虑服务器状态;结合高级健康检查,有助于系统管理能力在向全球用户开放前验证待安装的服务器是否已正常运行;

  • 一种创新机制可为 Cookie 设置最大空闲时间和持续时间,确保在永不关闭的设备(如智能手机、电视、家用电器)上,会话粘性可平滑停止,而无需将其存储在持久化存储中;

  • 多个服务器条目可共享相同的会话粘性键,以便在多路径环境中,当某条路径失效时,会话粘性不会丢失;

  • soft-stop 确保只有携带会话粘性信息的用户仍可访问其已分配的服务器,但不会有新用户被路由至此。

3.3.7. 基本功能:日志记录

日志记录是负载均衡器的一项极其重要的功能,首先因为负载均衡器常被错误地归咎于其揭示的问题,其次因为负载均衡器位于基础设施的关键位置,所有正常和异常活动都需要在此处进行分析,并与其他组件进行关联。

HAProxy 提供非常详细的日志,具备毫秒级精度,并记录精确的连接接受时间,该时间可用于在防火墙日志中进行搜索(例如用于 NAT 关联)。默认情况下,TCP 和 HTTP 日志内容非常详尽,包含故障排查所需的所有信息,例如源 IP 地址和端口、前端、后端、服务器、计时器(请求接收时长、队列时长、连接建立时间、响应头时长、数据传输时长)、全局进程状态、连接计数、队列状态、重试次数、详细的会话粘性动作以及断开连接原因,同时对头信息捕获采用安全的输出编码。因此,可以扩展或替换此格式,以包含任何采样数据、变量或捕获内容,从而生成极为详尽的信息。例如,可以记录客户端累计请求次数或访问的不同 URL 数量。

可通过标准 ACL 按请求调整日志级别,从而自动静默被视为污染的日志,并在少量流量出现异常行为时(例如,某个源地址的 URL 或 HTTP 错误过多)发出警告。系统管理日志也以独立级别输出,用于通知服务器的丢失或恢复等情况。

每个前端和后端均可使用多个独立的日志输出,有助于实现多租户。日志建议通过 UDP 发送,可选择 JSON 编码,并在达到可配置的最大行长度后截断,以确保日志送达。也可将日志发送至 stdout/stderr 或任意文件描述符,或发送至环形缓冲区,客户端可订阅该缓冲区以获取日志。

3.3.8. 基本功能:统计信息

本文提供基于 Web 的统计信息报告界面,支持认证、安全级别和作用域。因此,可为每个托管客户分配独立的页面,仅显示其自身的实例信息。该页面可置于常规网站的隐藏 URL 路径下,无需开放新端口。页面还可报告其他 HAProxy 节点的可用性,便于一目了然地判断整体运行是否正常。视图为综合展示,包含大量可访问的详细信息(如错误原因、最后访问时间、最后变更持续时间等),这些信息也可导出为 CSV 表格,供其他工具导入以生成图表。页面支持自动刷新,可用于大屏幕监控。在管理模式下,页面还允许更改服务器状态,以简化维护操作。

还提供了 Prometheus 导出器,以便根据部署情况以不同格式消费统计信息。

4 - 标准功能

样本提取、映射、ACL、内容切换、粘性表、重写和服务器保护

在本段中,列举了一些在 HAProxy 中非常常见但未必存在于其他负载均衡器上的功能。

3.4.1. 标准功能:采样与信息转换

HAProxy 支持使用多种“样本提取函数”进行信息采样。其原理是提取称为样本的信息片段,以供即时使用。该机制用于实现会话粘性、构建条件判断、生成日志信息或丰富 HTTP 头。

样本可从多种来源获取:

  • 常量:整数、字符串、IP 地址、二进制块;

  • 进程:日期、环境变量、服务器/前端/后端/进程状态、字节/连接数及速率、队列长度、随机数生成器等

  • 变量:会话级、请求级、响应级变量;

  • 客户端连接:源地址和目标地址及端口,以及所有相关统计信息计数器;

  • SSL 客户端会话:协议、版本、算法、加密套件、密钥长度、会话 ID、所有客户端和服务器证书字段、证书序列号、SNI、ALPN、NPN、客户端对特定扩展的支持情况;

  • 请求和响应缓冲区内容:偏移/长度处的任意负载、数据长度、RDP;Cookie;SSL Hello 类型解码;TLS SNI 解码

  • HTTP(请求和响应):方法、URI、路径、查询字符串参数、状态码、头字段值、位置头字段值、Cookie、捕获内容、认证信息、请求体元素;

一个样本随后可经过多个称为“转换器”的运算符,以实现某种转换。转换器会消耗一个样本并生成一个新的样本,新样本的类型可能完全不同。例如,转换器可用于仅返回输入字符串的整数长度,或可将字符串转换为大写。在最终使用前,可对样本依次应用任意数量的转换器。在所有可用的样本转换器中,以下几种最为常用:

  • 算术与逻辑运算符:可用于对输入数据执行高级计算,例如计算比率、百分比,或仅将一种单位转换为另一种单位;

  • IP 地址掩码在需要将某些地址按更大的网络进行分组时非常有用;

  • 数据表示:URL 解码、Base64、十六进制、JSON 字符串、哈希;

  • 字符串转换:在固定位置或固定长度处提取子字符串,按特定分隔符提取字段,提取特定单词,转换大小写,应用基于正则表达式的替换;

  • 日期转换:转换为 HTTP 日期格式,转换本地时间与 UTC 时间,以及添加或移除偏移量;

  • 在粘性表中查找条目,以获取统计信息或已分配的服务器;

  • 基于文件的映射(主要用于地理定位)的键值转换。

3.4.2. 标准功能:映射

映射是一种强大的转换器类型,其工作方式是在启动时将一个包含两列的文件加载到内存中,随后对每个输入样本在第一列中进行查找。若找到匹配项,则返回第二列对应的模式;若未找到,则返回默认值。由于输出信息本身也是一个样本,因此可进一步接受其他转换操作,包括其他映射查找。映射最常用于将客户端的 IP 地址转换为自治系统编号(AS number)或国家代码,因为其支持网络地址的最长前缀匹配。此外,映射也可用于多种其他用途。

其强大之处部分源于可随时通过 CLI 或使用其他样本执行特定动作进行更新,从而能够在后续访问之间存储和检索信息。另一大优势则来自基于二叉树的索引机制,即使包含数十万条条目,也能实现极高的处理速度,使地理位置定位变得极为廉价且易于部署。

3.4.3. 标准功能:ACL 和条件判断

HAProxy 中的大多数操作均可设置条件。条件通过使用逻辑运算符(AND、OR、NOT)组合多个 ACL 构建而成。每个 ACL 是一系列基于以下元素的测试:

  • 用于获取待测试元素的样本提取方法;

  • 可选的一系列转换器,用于转换元素;

  • 用于匹配的模式列表;

  • 用于指示如何将模式与样本进行比较的匹配方法

例如,样本可从 HTTP “Host” 头中获取,随后转换为小写,再使用正则匹配方法与多个正则模式进行匹配。

从技术上讲,ACL 与映射共享相同的底层核心,二者具有完全相同的内部结构、匹配方法和性能表现。唯一的实际区别在于,ACL 不返回样本,仅返回“找到”或“未找到”。在使用方面,ACL 模式可直接在配置文件中内联声明,无需单独的文件。ACL 可以命名,以方便使用或提升配置的可读性。命名的 ACL 可多次声明,系统将依次评估所有定义,直至匹配到第一个符合条件的规则。

本文提供约 13 种不同的模式匹配方法,其中包括 IP 地址掩码、整数范围、子字符串和正则表达式。这些方法的工作方式类似于函数,与任何编程语言一样,仅评估所需部分。因此,当涉及 OR 的条件已为真时,后续条件不再评估;同理,当涉及 AND 的条件已为假时,其余条件也不再评估。

声明的 ACL 数量没有实际限制,且提供了若干常用 ACL。然而,经验表明,使用大量命名 ACL 的配置较难排查故障,有时在分析范围内直接使用匿名 ACL 反而更简便,因为这样所需的外部引用更少。

3.4.4. 标准功能:内容切换

HAProxy 实现了一种称为基于内容切换的机制。其原理是:连接或请求到达前端后,会处理与该请求或连接一同携带的信息,此时可编写基于 ACL 的条件,利用这些信息决定由哪个后端处理请求。因此,流量可根据请求内容被导向不同的后端。最常见的示例是利用 Host 头和/或路径中的元素(子目录或文件名扩展名)判断 HTTP 请求是针对静态资源还是应用程序,并将静态资源流量路由至由快速轻量级服务器组成的后端,其余流量则路由至更复杂的应用服务器,从而构成细粒度的虚拟主机解决方案。这种方式非常便于多种技术共存,作为更全面的解决方案。

另一种内容切换的用例是根据不同的条件使用不同的负载均衡算法。缓存可使用 URI 哈希,而应用程序则使用轮询。

最后但同样重要的是,它通过为每个后端(即每个客户)强制实施连接限制,允许多个客户共享一个公共资源的少量份额。

内容切换规则的扩展性非常好,尽管其性能可能受当前使用的 ACL 数量和复杂度的影响。但也可以编写动态内容切换规则,使样本值直接转换为后端名称,完全无需使用 ACL。据报告,此类配置在生产环境中至少支持 300000 个后端时仍能正常工作。

3.4.5. 标准功能:粘性表

会话粘性通常通过会话表(stick-table)来存储,即记录某个访问者被引导至的服务器的引用。键(key)是与该访问者关联的标识符(如源地址、连接的 SSL ID、HTTP 或 RDP Cookie、从 URL 或负载中提取的客户编号等),而存储的值则是对应服务器的标识符。

粘性表可使用三种不同类型的样本作为键:整数、字符串和地址。 每个代理只能引用一个粘性表,且在所有位置均以代理名称进行标识。 最多可并行跟踪 8 个键。 在请求或响应处理过程中,一旦键和服务器均被确定,服务器标识即被确认。

粘性表内容可在活动-活动模式下与其他已知为“对等节点”的 HAProxy 节点同步,也可在重载操作期间与新进程同步,从而确保所有负载均衡节点共享相同信息,并在客户端请求分布于多个节点时做出相同的路由决策。

由于会话粘性表基于用于识别客户端的字段进行索引,因此它们通常也用于存储额外信息,例如客户端级别的统计信息。额外的统计信息会占用额外空间,且必须显式声明。可存储的统计类型包括输入和输出带宽、并发连接数、特定时间段内的连接速率与连接次数、错误发生量与频率、特定标签与计数器等。为支持在不强制绑定至特定服务器的情况下保留此类信息,引入了一项特殊“跟踪”功能,可同时跟踪来自不同表的最多 3 个不同键,且不受会话粘性规则限制。每项存储的统计信息均可通过 CLI 进行搜索、导出和清除,从而增强实时故障排查能力。

尽管该机制可用于区分返回访客或根据良好或不良行为调整服务质量,但其主要用途是防范服务滥用,更广泛地应对分布式拒绝服务(DDoS)攻击,因为它能够以高处理速度构建复杂模型,以检测特定不良行为。

3.4.6. 标准功能:格式化字符串

HAProxy 需要在多个位置操作字符字符串,例如日志记录、重定向、头字段添加等。为提供最大程度的灵活性,引入了“格式化字符串”概念,最初用于日志记录,因此至今仍称为“log-format”。这些字符串包含转义字符,可用于在字符串中插入各种动态数据,包括变量和样本提取表达式,甚至可在将结果转换为字符串时调整编码(例如添加引号)。这为构建头内容、生成响应数据或响应模板,以及自定义日志行提供了强大手段。此外,为简化常见字符串的构建,提供了约 50 个特殊标签,作为日志中常用信息的快捷方式。

3.4.7. 标准功能:HTTP 重写和重定向

在未针对此场景设计的应用程序前部署负载均衡器,若缺乏合适的工具,将是一项具有挑战性的任务。此类情况下最常被请求的操作之一,是调整请求和响应头,使负载均衡器看起来如同源服务器,并修复硬编码的信息。这包括修改请求中的路径(强烈建议避免)、修改 Host 头字段、修改重定向时的 Location 响应头字段、修改 Cookie 的路径和域名属性等。此外,部分服务器的响应信息较为冗余,容易泄露过多信息,从而增加遭受针对性攻击的风险。尽管从理论上讲,负载均衡器并不负责清理此类信息,但在实际部署中,它位于基础设施中最佳的位置,能够确保所有信息均被清理。

同样,有时负载均衡器必须拦截某些请求,并返回重定向至新的目标 URL。尽管有些人容易将重定向与重写混淆,但二者是完全不同的概念:重写会使客户端与服务器看到不同的内容(并就所访问页面的位置产生分歧),而重定向则要求客户端访问新的 URL,从而使客户端看到的位置与服务器一致。

为实现此目的,HAProxy 支持多种重写和重定向机制,其中包括:

  • 在请求和响应中基于正则表达式的 URL 和头重写。正则表达式是修改头值最常用的工具,因其易于操作且广为人知;

  • HTTP 头也可基于格式化字符串追加、删除或替换,以便在其中传递信息(例如客户端 TLS 算法和密码套件);

  • HTTP 重定向可使用任意 3xx 状态码,将请求重定向至相对 URI、绝对 URI 或完全动态(格式化字符串)的 URI;

  • HTTP 重定向还支持一些额外选项,例如设置或清除特定 Cookie、丢弃查询字符串、在缺少斜杠时追加斜杠等;

  • 强大的 return 指令允许使用动态内容甚至模板文件,自定义响应的各个部分,如状态码、头和正文。

  • 所有操作均支持基于 ACL 的条件;

3.4.8. 标准功能:服务器保护

HAProxy 通过多种手段最大限度地提升服务可用性,为此需投入大量努力以保护服务器免受过载和攻击。首要且最重要的原则是,仅将完整且有效的请求转发至服务器。首要原因在于,HAProxy 需要识别协议中所需的元素,以保持与字节流的同步;第二个原因是,在请求未完成前,无法判断某些元素是否会改变其语义。由此带来的直接好处是,服务器不会暴露于无效或不完整的请求之下。这一机制对 slowloris 攻击具有极强的防护效果,此类攻击对 HAProxy 几乎无影响。

另一个重要点是,HAProxy 包含用于存储请求和响应的缓冲区,通过仅在请求完整时才将其发送至服务器,并迅速从本地网络读取整个响应,可使服务器端连接的占用时间尽可能短,从而最大程度地节省服务器资源。

对这一机制的直接延伸是,HAProxy 可以人为限制发送至服务器的并发连接数或待处理请求数,从而确保即使在流量高峰期间服务器持续以 100% 的容量运行,也不会发生过载。所有超出限制的请求将被放入队列,待有空闲槽位时再进行处理。最终,这种巨大的资源节省通常能显著提升服务器响应速度,反而比让服务器过载更高效。队列中的请求可被重分派至其他服务器,或在客户端中断时于队列中中止,这同样可防止“刷新效应”——即访问者在页面加载缓慢时反复点击“刷新”按钮,通常会触发新的请求并使服务器长期处于过载状态。

慢启动机制还可防止重启中的服务器在启动完成或编译某些类期间遭受过高流量冲击。

关于协议层保护,可放宽 HTTP 解析器以接受非标准但无害的请求或响应,甚至可对其进行修复。这使得存在缺陷的应用程序在修复开发期间仍可访问。同时,违规消息会被完整捕获,并生成详细报告,有助于开发人员定位应用程序中的问题。最危险的协议违规行为将被正确检测并处理或修复。例如,包含两个 Content-Length 头的畸形请求或响应,若其值完全相同则予以修复,若不同则予以拒绝,因为这会引发安全问题。协议检查不仅限于 HTTP,还适用于 TLS、RDP 等其他协议。

当检测到协议违规或攻击时,可采取多种方式响应用户,例如返回常见的“HTTP 400 错误请求”、通过 TCP 重置关闭连接,或在长时间延迟后伪造错误(“tarpit”)以混淆攻击者。所有这些措施均有助于通过阻止违规客户端继续实施成本高昂的攻击来保护服务器。

HAProxy 还提供了一些更高级的选项,用于防范意外的数据泄露和会话交叉。它不仅能记录可疑的服务器响应,还会记录并可选地阻止可能影响特定访客隐私的响应。例如,当可缓存的响应中出现可缓存的 Cookie 时,可能导致中间缓存将该 Cookie 传递给其他访客,从而引发意外的会话共享。

5 - 高级功能

运行时管理、操作系统能力、Lua 脚本编写和实时跟踪

3.5.1. 高级功能:系统管理

HAProxy 旨在在常规生产环境中保持极高的稳定性与安全性。它以单个可执行文件的形式提供,无需任何安装过程。多个版本可轻松共存,因此建议按重要性顺序逐步升级实例,而非一次性全部迁移。配置文件易于版本化。配置检查可在离线状态下完成,无需重启可能失败的服务。在配置检查过程中,可检测到多种高级错误(例如规则相互隐藏,或无法生效的会话粘性),并提供详细的警告信息与配置建议以修复问题。配置文件的向后兼容性极为持久,版本 1.5 仍完全支持 13 年前为版本 1.1 编写的配置,而 1.6 仅移除了几乎不再使用、已过时的关键词,这些功能可通过其他方式实现。配置与软件升级机制平滑且无中断,允许旧版与新版进程在系统中共存,各自处理自身的连接。启动时会报告系统状态、构建选项及库兼容性信息。

某些高级功能允许应用管理员平稳地停止服务器,检测其是否已无活动,随后将其下线、停止、升级,并确保在升级期间不接收任何流量,然后通过正常路径再次测试,且无需向公众开放,所有这些操作均无需修改 HAProxy 配置。这确保了即使在复杂的生产环境中,也可在营业时间内完成操作,同时所有技术资源均保持可用。

该进程尽可能节省资源,使用内存池以减少分配时间并限制内存碎片,一旦数据包内容被发送即立即释放负载缓冲区,并支持强制执行严格的内存限制:当超过限制时,连接必须等待缓冲区可用,而非继续分配更多内存。该机制有助于在特定严格环境中保障内存使用。

提供命令行接口(CLI),可通过 UNIX 套接字或 TCP 套接字执行多项操作并获取故障排查信息。通过该套接字执行的所有操作均无需修改配置,因此主要用于临时变更。使用此接口可实现以下功能:更改服务器的地址、权重和状态,查询统计信息并清空计数器,转储并清空会话粘性表(可按键条件选择性操作),转储并终止客户端与服务器端的连接,转储捕获的错误并提供错误原因与位置的详细分析,转储、添加和删除 ACL 与映射中的条目,动态更新 TLS 共享密钥,对任意前端实时应用连接限制与速率限制(在共享托管环境中尤为有用),禁用特定前端以释放监听端口(在禁止白天操作但需修复时尤为有用)。支持动态更新证书及其配置,也支持启用并查阅流量处理每一步的追踪信息。

在 SNMP 为强制要求的环境中,至少存在两个代理程序。其中一个随 HAProxy 源码提供,依赖 Net-SNMP Perl 模块;另一个随商业版包提供,无需 Perl 支持。两者在功能覆盖范围上大致相当。

通常建议在部署 HAProxy 的机器上安装以下 4 个工具:

  • socat(用于连接 CLI,尽管某些 netcat 的分支在一定程度上也可实现此功能);

  • halog:来自最新 HAProxy 版本的日志分析工具,可极快速解析原生 TCP 和 HTTP 日志(每秒 1 至 2 GB),并提取有用信息与统计信息,例如按 URL 统计的请求数、按源地址统计的请求数、按响应时间或错误率排序的 URL、终止码等。该工具专为部署在生产服务器上以协助排查实时问题而设计,因此必须始终就绪,随时可用。

  • tcpdump:强烈建议使用该工具捕获网络流量,以便排查日志中显示的问题。当应用程序与 HAProxy 的分析结果出现分歧时,网络流量捕获是唯一能判断双方对错的方法。此外,借助 tcpdump 也常能发现网络栈和虚拟化平台中的缺陷。

  • strace:它是 tcpdump 的配套工具。它将报告 HAProxy 实际接收到的内容,有助于区分操作系统层面的问题与 HAProxy 自身的问题。当怀疑 HAProxy 存在缺陷时,通常会要求提供 strace 输出。

3.5.2. 高级功能:系统特定能力

根据 HAProxy 所部署的操作系统不同,某些额外功能可能可用或必需。尽管 HAProxy 支持多种平台,但其主要开发环境为 Linux,因此部分功能仅在该平台可用。

透明绑定和连接功能、将连接绑定到特定网络接口的支持,以及将多个进程绑定到同一 IP 地址和端口的能力,仅在 Linux 和 BSD 系统上可用,尽管只有 Linux 会在内核层面实现对可用进程间入站请求的负载均衡。

在 Linux 上,还提供了一系列额外功能和优化,包括对网络命名空间(也称为“容器”)的支持,使 HAProxy 可作为所有容器之间的网关;能够在客户端连接上设置 MSS、Netfilter 标记和 IP TOS 字段;支持在监听端启用 TCP FastOpen;通过 TCP 用户超时机制,当内核检测到客户端已断开但尚未达到配置超时时间时,可快速终止连接;支持 TCP 拼接,使内核能够直接在连接两端之间转发数据,避免多次内存拷贝;可启用“defer-accept”绑定选项,仅在内核缓冲区中有数据时才通知连接建立;还可通过“tcp-smart-connect”选项,使用 ACK 确认连接的同时发送请求(有时称为“捎带”)。在 Linux 上,HAProxy 还特别注重对 TCP 延迟 ACK 的处理,以尽可能减少网络中的数据包数量。

某些系统存在时钟不可靠的问题,其时间会在过去和未来之间来回跳变。过去,一些 NUMA 系统曾出现此类情况,由于多个处理器未能看到完全一致的当前时间,导致时间不同步;近期,虚拟化环境中此类问题更为常见,因为虚拟时钟与真实时钟无关联,从而引发巨大的时间跳跃(曾观察到长达 30 秒的跳变)。这在一般情况下对超时机制的执行造成了诸多困扰。由于此类系统存在缺陷,HAProxy 维护了自身的单调时钟,该时钟基于系统时钟,但会测量并补偿时钟漂移。这确保了即使系统时钟极不准确,定时器仍能保持合理精度,超时机制依然有效。请注意,该问题影响运行在这些系统上的所有软件,并非 HAProxy 特有。常见表现包括误报超时或应用程序冻结。因此,若在系统上检测到此类行为,必须予以修复,无论 HAProxy 是否已自行防护。

在 Linux 上,新启动的进程可与前一个进程通信,以复用其监听文件描述符,从而确保在进程替换过程中监听套接字始终不中断。

3.5.3. 高级功能:脚本编写

HAProxy 可以编译支持嵌入式 Lua 语言,这为请求或响应的复杂处理、路由决策、统计信息处理等场景打开了广阔的可能性。借助 Lua,甚至可以建立与其它服务器的并行连接以交换信息。这种方式使得开发认证系统等复杂功能成为可能(尽管实现较为复杂)。有关如何使用 Lua 的更多信息,请参阅文件 “doc/lua-api/index.rst” 中的文档。

3.5.4. 高级功能:跟踪

任何时刻,系统管理员均可通过 CLI 连接并启用各个内部子系统的追踪功能。默认情况下提供多种详细程度,实际可获取的追踪信息量介于每请求一行至每请求五百行之间。系统支持过滤器,以及自动捕获开启/关闭/暂停机制,因此完全可以等待特定事件发生,并对其进行详细观察。该功能对诊断由故障服务器或客户端引发的协议违规行为,或拒绝服务攻击极为便利。

6 - 性能与容量规划

容量规划原则、性能量级和实用规则

典型 CPU 使用率数据显示,在 TCP 或 HTTP 关闭模式下,HAProxy 占用约 15% 的处理时间,内核占用约 85%;在 HTTP 持久连接模式下,HAProxy 占用约 30%,内核占用约 70%。这表明操作系统及其调优对整体性能有显著影响。

不同用户的应用场景差异很大,有的关注带宽,有的关注请求速率,有的关注连接并发数,有的关注 SSL 性能。本节将提供一些容量规划的参考依据。

请注意,每次操作都会带来开销,因此每个独立操作都会在其余操作的基础上增加额外开销,这种开销在某些情况下可能微不足道,而在其他情况下则可能成为主要影响因素。

在处理来自连接的请求时,我们可以说:

  • 转发数据的开销低于解析请求或响应头;

  • 解析请求或响应头的开销小于建立并关闭与服务器的连接;

  • 建立和关闭一个连接的开销小于一次 TLS 恢复操作;

  • 一次 TLS 会话恢复操作的开销低于一次完整的 TLS 握手及密钥计算;

  • 空闲连接消耗的 CPU 资源少于缓冲区中持有数据的连接;

  • 一个 TLS 上下文所消耗的内存比包含数据的连接还要多;

因此,在实际应用中,处理负载字节的成本低于处理头字节,所以通过大对象(单位体积请求数较少)实现高网络带宽比通过小对象(单位体积请求数较多)更容易。这解释了为何最大带宽始终以大对象进行测量,而请求速率或连接速率则以小对象进行测量。

某些操作在多个 CPU 上分布的多个进程间可实现良好扩展,而另一些则扩展效果不佳。网络带宽的扩展能力有限,因为对于大对象而言,CPU 通常并非瓶颈,主要瓶颈在于网络带宽以及连接网络接口的数据总线。由于本地端口表操作涉及少量锁,连接速率在多进程间扩展效果不佳。持久连接上的请求速率扩展效果极佳,因其几乎不占用内存和网络带宽,也无需访问加锁结构。TLS 密钥计算扩展效果极佳,因其完全由 CPU 承载。TLS 会话恢复扩展效果中等,但在约 4 个进程时达到极限,此时访问共享表的开销抵消了因增加处理能力而预期获得的微小收益。

在经过充分调优的系统上,可预期的性能指标范围如下。应将其视为数量级参考,实际性能可能因处理器、IRQ 设置、内存类型、网络接口类型、操作系统调优等因素而出现显著波动。

以下数据来自一台运行在 3.7 GHz 的 Core i7 处理器,配备双端口 10 Gbps 网卡,运行 Linux 内核 3.10、HAProxy 1.6 和 OpenSSL 1.0.2 的系统。HAProxy 以单进程模式运行于单个专用 CPU 核心,另有两个核心专门用于网络中断处理:

  • 20 Gbps 的最大网络带宽(明文传输),适用于 256 kB 及以上对象,41 kB 及以上对象为 10 Gbps;

  • 使用 AES256-GCM 密码套件传输大对象时,TLS 流量可达 4.6 Gbps;

  • 每秒从客户端到服务器的 83000 个 TCP 连接;

  • 每秒 82000 个客户端到服务器的 HTTP 连接;

  • 每秒 97000 个 HTTP 请求,服务器关闭模式(与客户端保持持久连接,与服务器关闭连接);

  • 每秒 243000 个 HTTP 请求,处于端到端持久连接模式;

  • 每秒过滤 300000 个 TCP 连接(抗 DDoS);

  • 每秒 160000 个 HTTPS 请求,运行于持久 TLS 连接的持久连接模式下;

  • 使用会话恢复的 TLS 连接时,每秒可处理 13100 个 HTTPS 请求;

  • 每秒 1300 个 HTTPS 连接,使用 RSA2048 重新协商的 TLS 连接;

  • 每 GB 内存可支持 20000 个并发饱和连接,包含系统缓冲区所需的内存;通过精细调优可获得更优结果,但此配置易于实现。

  • 每 GB 内存可支持约 8000 个并发 TLS 连接(仅客户端侧),包含系统缓冲区所需的内存;

  • 每 GB 内存可支持约 5000 个并发端到端 TLS 连接(双向),包括系统缓冲区所需的内存;

一项较新的基准测试显示,在 AWS 的 64 核 ARM Graviton2 处理器上运行启用了多线程的 HAProxy 2.4,实现了每秒 200 万次 HTTPS 请求、响应时间低于毫秒级,以及 100 Gbps 的流量处理能力:

https://www.haproxy.com/blog/haproxy-forwards-over-2-million-http-requests-per-second-on-a-single-aws-arm-instance/

因此,一个值得牢记的实用原则是:在 TLS 持久连接与 TLS 会话恢复之间,以及在 TLS 会话恢复与 TLS 重新协商之间,请求速率会降低约 10 倍;而在 HTTP 持久连接与 HTTP 关闭之间,请求速率仅降低约 3 倍。另一个值得牢记的实用原则是:具备 AES 指令集的高频核心每核可实现约 20 Gbps 的 AES-GCM 加解密性能。

另一个良好的经验法则是,同一台服务器上,HAProxy 可以达到的饱和程度为:

  • 约 5 至 10 个静态文件服务器或缓存代理;

  • 约 100 个防病毒代理;

  • 以及根据所用技术,约 100 至 1000 台应用服务器。

7 - 发布、软件包与升级

稳定分支、发布源、版本标识、维护与升级

HAProxy 是一个采用 GPLv2 许可证的开源项目,这意味着只要在请求时提供源代码,任何人都可以自由分发该软件,尤其是当进行了任何修改时。

HAProxy 以名为“master”或“mainline”的主开发分支持续演进,当代码被认为稳定后,便会从该分支衍生出新的分支。许多网站自愿在生产环境中运行开发分支,或为参与项目,或因需要前沿功能,其反馈对修复缺陷、评估所开发版本的整体质量与稳定性具有极高价值。

当代码稳定到一定程度时创建的新分支即构成稳定版本,通常会维护数年,因此即使未处于最新分支,也无需紧急迁移至更新的分支。稳定分支发布后,仅会接收错误修复,极少情况下才会引入小幅功能更新,以提升用户使用体验。所有进入稳定分支的修复必然源自主分支。这一机制确保了升级后不会丢失任何修复。因此,若发现并修复了某个错误,请务必向主分支提交补丁,而非稳定分支;还可能发现该问题其实已经修复。此流程也确保了稳定分支中出现回归的情况极为罕见,因此没有理由不升级到当前分支的最新版本。

版本分支使用两位数字并以点分隔,例如“1.6”。自 1.9 版本起,第二位数字为奇数的分支主要聚焦于敏感的技术更新,更适用于高级用户,因为其可能引入的错误比其他分支更多。这类分支仅维护约一年,且在无法紧急回滚的环境中不得部署。完整版本号包含一个或两个次版本号,用以表示修复级别。例如,版本 1.5.14 是在 1.5.0 版本发布后,1.5 分支的第 14 次修复发布。该版本包含 126 个针对个别缺陷的修复,24 个文档更新,以及 75 个其他回溯补丁,其中大多数用于修复前述 126 个缺陷。在稳定分支中,现有功能不得被修改或移除,以确保同一分支内的升级始终无害。

HAProxy 可通过多个来源获取,发布节奏各不相同:

  • 官方社区网站:http://www.haproxy.org/ :该网站提供最新开发版本的源码、所有稳定版本,以及每个分支的每日快照。发布周期较慢,稳定版本之间或开发快照之间通常相隔数月。旧版本仍在此处获得支持。所有内容仅以源码形式提供,因此从该处获取的任何内容均需重新构建和/或重新打包;

  • GitHub: https://github.com/haproxy/haproxy/ :这是仅用于开发分支的镜像,提供与问题追踪器、持续集成及代码覆盖率工具的集成。仅限贡献者使用;

  • 许多操作系统,例如 Linux 发行版和 BSD 端口。这些系统通常提供长期维护的版本,虽然未必包含官方版本的所有修复,但至少包含关键修复。对于大多数不追求高级配置且希望保持更新简便的用户而言,这通常是一个不错的选择;

  • 可从 http://www.haproxy.com/ 获取商业版本:这些是针对各类操作系统构建、提供专业支持的软件包,或以设备形式交付。它们基于最新稳定版本,并包含从下一版本回溯移植的若干高需求功能。对于希望兼顾稳定分支可靠性与最新功能、获得最快缺陷修复响应,或在开源产品之上购买支持合同的用户,这是最佳选择;

为确保所用版本为当前分支的最新版本,请按以下方式操作:

  • 验证正在运行的 HAProxy 可执行文件:某些系统默认自带 HAProxy,而系统管理员可能将自定义版本安装在系统其他位置,因此在启动脚本中确认实际使用的版本至关重要;

  • 确定 HAProxy 版本的来源。通常只需输入 “haproxy -v”。开发版本会在分支号后显示 “dev” 字样:

HAProxy version 2.4-dev18-a5357c-137 2021/05/09 - https://haproxy.org/

稳定版本以及操作系统供应商提供的未修改稳定版本显示如下:

HAProxy version 1.5.14 2015/07/02

稳定版本的每日快照会在版本号后附加十六进制序列,并显示快照日期而非发布日期:

HAProxy version 1.5.14-e4766ba 2015/07/29

其他格式可能表示带有独立补丁集的系统专用软件包。例如,HAProxy Enterprise 使用以下格式(<branch>-<latest commit>-<revision>):

HAProxy version 1.5.0-994126-357 2015/07/02

请注意,历史上 2.4 版本之前的版本曾使用连字符在“HA”和“Proxy”之间报告进程名称,包括那些仅调整为显示正确格式的版本,因此建议在脚本中忽略该词或使用宽松匹配。此外,现代版本还添加了指向项目主页的 URL。

最后,版本 2.1 及以上版本将包含一行“状态”信息,用于指示该版本是否适合生产环境使用,以及适用的截止时间,并提供指向此版本已知问题列表的链接。

  • 对于系统专用软件包,必须查询供应商的软件仓库或更新系统,确认系统仍受支持,当前分支仍能获得修复。对于来自 HAProxy.org 的社区版本,只需访问网站查看当前分支状态,并将所用版本与最新版本比较。若不是最新版本,可以执行升级;若当前分支已停止维护,则说明版本严重落后,必须考虑升级至更新分支(升级时请仔细阅读 README)。

HAProxy 必须按其来源对应的方式更新。通常应遵循系统供应商的软件包升级流程。若使用源码,请在解压后阅读源码目录中的 README,并按相应操作系统的说明执行。

8 - 相关产品与替代方案

HAProxy 与 Apache、NGINX、Varnish、LVS、Envoy 及其他负载均衡器的关系

HAProxy 与以下列出的某些产品集成良好,因此尽管这些产品与 HAProxy 无直接关联,仍在此提及。

4.1. Apache HTTP 服务器

Apache 是事实上的标准 HTTP 服务器。它是一个功能完整且模块化的项目,支持静态文件服务和动态内容处理。Apache 可以作为某些应用服务器的前端。它甚至可以代理请求并缓存响应。在所有这些使用场景中,通常需要一个前端负载均衡器。Apache 可以在多种模式下运行,其中某些模式的开销较大。某些模块仍需依赖开销较大的预派生模型,这将导致 Apache 在连接数较高时难以良好扩展。在此情况下,HAProxy 可通过将每台服务器的连接数限制强制设定为安全值,显著提升服务器性能,并有效保护服务器资源,使这些资源能更高效地被应用程序利用。

Apache 可通过使用 “mod_rpaf” 扩展从 X-Forwarded-For 头中提取客户端地址。当 HAProxy 配置中指定 “option forwardfor” 时,HAProxy 会自动填充该头。当 Apache 暴露于互联网时,HAProxy 还可提供良好防护,使其更能抵御多种类型的拒绝服务攻击。

4.2. NGINX

NGINX 是另一款事实标准级 HTTP 服务器。与 Apache 类似,它涵盖了广泛的特性。NGINX 的架构与 HAProxy 类似,因此能够轻松处理数以万计的并发连接。当作为某些应用(例如使用内置的 PHP FPM)的网关时,设置前端连接限制通常有助于减轻 PHP 应用的负载。在此场景中,HAProxy 作为常规负载均衡器以及流量调节器,均可发挥显著作用,通过缓解拥堵来提升 PHP 处理速度。此外,由于两款产品均基于事件驱动架构,CPU 占用率极低,因此通常可轻松在同一系统上同时部署。NGINX 实现了 HAProxy 的 PROXY 协议,使得 HAProxy 能够将客户端连接信息传递给 NGINX,从而确保应用获取全部相关上下文信息。部分基准测试还表明,对于大规模静态文件服务,若在 NGINX 前端的 HAProxy 上实现一致性 URL 哈希,可通过优化操作系统的缓存命中率带来性能提升,该命中率基本与服务器节点数量成倍数关系。

4.3. Varnish

Varnish 是一款智能缓存反向代理,可被描述为 Web 应用加速器。Varnish 不实现 SSL/TLS,而是希望将全部 CPU 周期专注于其最擅长的任务。Varnish 还实现了 HAProxy 的 PROXY 协议,因此 HAProxy 可以非常容易地部署在 Varnish 前端,作为 SSL 卸载器、负载均衡器,并传递所有相关的客户端信息。

此外,当服务器提供已压缩的对象时,Varnish 可自然支持从缓存中解压缩,但本身不执行压缩。HAProxy 可用于在后端服务器未实现压缩时对传出数据进行压缩,但除非流量较低,否则通常不建议在负载均衡器上进行压缩。

在跨多个节点构建大型缓存集群时,HAProxy 可利用一致的 URL 哈希机制,智能地将负载分发至缓存节点,避免缓存重复,从而实现总缓存容量为所有缓存节点容量之和。此外,在 HAProxy 上对极小的简单对象进行短时缓存,有时可减少网络往返次数,并降低 HAProxy 与 Varnish 节点的 CPU 负载。此功能仅在 Varnish 上不对这些对象执行任何处理时才可启用(这通常被称为“favicon 缓存”概念,借此可避免相当比例的无用下游请求)。然而,切勿在任何其他缓存前长期启用 HAProxy 缓存(超过几秒),否则将显著增加故障排查难度,且无法带来真正可观的性能收益。

4.4. 替代方案

Linux 虚拟服务器(LVS 或 IPVS)是内置于 Linux 内核中的第 4 层负载均衡器。它在数据包层面工作,支持 TCP 和 UDP。在大多数情况下,它更像是一种补充而非替代方案,因为它完全不具备第 7 层知识。

Pound 是另一款广为人知的负载均衡器。相较于 HAProxy,它更加简单,功能也少得多,但在许多基础配置场景下,两者均可使用。其作者始终将代码可审计性放在首位,并致力于保持功能集的精简。Pound 采用基于线程的架构,在高连接数场景下的扩展性较差,但仍是值得信赖的产品。

Pen 是一款轻量级负载均衡器。它支持 SSL,通过固定大小的客户端 IP 地址表维持会话持久性。它支持面向数据包的模式,可在一定程度上实现直接服务器返回和 UDP 支持。该负载均衡器适用于低负载场景(会话持久性表仅包含 2048 个条目)。

NGINX 可在一定程度上实现负载均衡,尽管这显然并非其主要功能。 生产流量用于检测服务器故障,负载均衡算法较为有限,会话粘性也极为有限。但在某些已有 NGINX 的简单部署场景中,此举仍具合理性。值得庆幸的是,由于 NGINX 与 HAProxy 集成良好,当 NGINX 的能力达到极限时,后续添加 HAProxy 也完全可行。

Varnish 也对后端服务器执行负载均衡,并支持真正的健康检查。然而,它不支持会话粘性,因此与 NGINX 类似,只要不需要会话粘性,仅凭这些功能通常已足够起步。同样,由于 HAProxy 与 Varnish 集成效果极佳,后续很容易将其加入现有架构中,以补充功能集。

9 - 文档与社区

上游手册、源码位置、支持渠道、联系方式与许可证

1. 可用文档

HAProxy 的完整文档由以下文件组成。请先查阅与问题相关的文档,以节省时间并获得最准确的答案。如果这些文档已经给出答案,请勿再向邮件列表重复提问。

  • intro.txt (本文档):介绍负载均衡基础、HAProxy 产品及其能力边界、应避免的常见陷阱、部分操作系统特有限制、获取方式、演进过程、如何确认当前版本包含所有已知修复、升级方法,以及补充产品和替代方案。

  • management.txt :介绍如何启动 HAProxy,如何在运行时及多节点环境中管理 HAProxy,以及如何执行无缝升级。

  • configuration.txt :参考手册,详细说明所有配置关键字及其选项;需要更改配置时应查阅此文件。

  • coding-style.txt:面向希望为项目贡献代码的开发者,说明代码应遵循的风格。规范并非十分严格,现有代码也没有全部遵循,但偏离过大的贡献会被拒绝。

  • proxy-protocol.txt:HAProxy 及多个第三方产品所实现的 PROXY 协议事实标准规范。

  • security.txt:说明如何报告安全问题,以及哪些问题属于或不属于安全漏洞。

  • README:说明如何从源码构建 HAProxy。

5. 联系方式

如需就任何问题联系开发者或社区成员,通常最合适的方式是向 haproxy@formilux.org 发送邮件,使用公开邮件列表。请注意,邮件列表及其归档均为公开内容,切勿披露敏感信息。列表中有上千名经验各异的用户,即使是复杂问题,通常也能较快获得高质量答复;社区同样欢迎各类建议。

不便使用电子邮件的用户可以访问 http://discourse.haproxy.org/ 。不过,该平台的读者较少,大多数问题由一个很小的团队处理。无论使用哪种渠道,都请耐心等候,并尊重利用业余时间帮助他人的社区成员。

如果认为发现了缺陷但尚不确定,最好先在邮件列表中报告。如果基本确认问题属于缺陷、所用版本已包含当前分支的最新更新,并且已有 GitHub 账户,可以直接前往 https://github.com/haproxy/haproxy/ 创建议题,附上所有可提供的细节。议题内容同样完全公开,请勿提交日后可能后悔公开的信息。议题跟踪器以长讨论串形式呈现,因此不要直接粘贴数百行以上的长篇转储,应改用附件。

如果怀疑发现了安全问题,请参阅 doc/security.txt。该文件说明哪些问题属于或不属于 HAProxy 漏洞,以及如何通过私密渠道报告真正的安全问题。大多数疑似安全问题最终只是普通缺陷,更适合按上述方式报告。

本地完整手册

版本来源

10 - 1. 快速 HTTP 提示

HTTP 交易、请求、响应、头和协议术语

本文涵盖上述指定版本中实现的配置语言。 本文不提供任何提示、示例或建议。 如需此类文档,请参阅参考手册或架构手册。 编号章节在 HAProxy 扁平侧边栏中按顺序排列,支持直接导航。

当 HAProxy 以 HTTP 模式运行时,请求和响应均会被完整分析并索引,因此可基于内容中发现的几乎任何信息构建匹配条件。

然而,理解 HTTP 请求和响应的构成方式,以及 HAProxy 如何对其进行解析,至关重要。掌握这些原理后,编写正确的规则以及排查现有配置将变得更加容易。

首先,HTTP 由一系列 RFC 标准化,HAProxy 尽可能严格地遵循这些标准:

  • RFC 9110:HTTP 语义(解释协议元素的含义)
  • RFC 9111:HTTP 缓存(解释 HTTP 缓存应遵循的规则)
  • RFC 9112:HTTP/1.1(表示形式、互操作性规则、安全性)
  • RFC 9113:HTTP/2(表示形式、互操作性规则、安全性)
  • RFC 9114:HTTP/3(表示形式、互操作性规则、安全性)

此外,RFC 8999 至 9002 规定了 HTTP/3 协议所使用的 QUIC 传输层。

1.1. HTTP 事务模型

HTTP 协议是基于事务的。这意味着每个请求只会对应一个且仅一个响应。最初,在协议版本 1.0 时,每个连接仅支持一个请求:客户端与服务器建立 TCP 连接,客户端通过该连接发送请求,服务器返回响应,随后连接关闭。新的请求则需要建立新的连接:

[CON1] [REQ1] ... [RESP1] [CLO1] [CON2] [REQ2] ... [RESP2] [CLO2] ...

在该模式下,通常称为“HTTP 关闭”模式,连接建立次数与 HTTP 事务次数相同。由于服务器在发送响应后关闭连接,客户端无需知晓内容长度,当连接关闭时即认为响应已完整。这也意味着,若因网络错误导致部分响应被截断,客户端可能误认为响应已完整,从而导致图像偶尔出现渲染不全的情况。

由于协议的事务性特征,可以对其进行优化,以避免在两个后续事务之间关闭连接。然而,在此模式下,服务器必须为每个响应标明内容长度,以免客户端无限期等待。为此,使用了一个特殊头:“Content-length”。此模式称为 “keep-alive” 模式,随 HTTP/1.1 一同引入(部分 HTTP/1.0 客户端也支持),在请求间复用的连接被称为“持久连接”:

[CON] [REQ1] ... [RESP1] [REQ2] ... [RESP2] [CLO] ...

其优势在于事务间的延迟更低,服务器端所需的处理能力更少,并且能够检测到响应被截断的情况。通常情况下,该模式比关闭模式更快,但并非总是如此,因为部分客户端通常会将其并发连接数限制在较低值,这在网络连接较差时难以弥补。此外,部分服务器需长时间保持连接以等待可能到来的新请求,可能导致因连接数量过多而产生较高的内存使用,过快关闭连接可能中断恰好在连接关闭瞬间到达的请求。

在此模式下,响应大小需事先知晓,因此对于动态生成或压缩的内容,这并不总是可行。为此,实现了另一种模式,即“分块传输模式”,在该模式中,发送方不再一次性声明整个响应的大小,而是仅通告其当前缓冲区中已有的下一段 “chunk” 响应的大小,并可在任意时刻以大小为零的分块终止传输。在此模式下,不使用 Content-Length 头。

通信机制的另一项改进是流水线模式。该模式仍使用持久连接,但客户端在未收到首个响应时即可发送第二个请求。此模式在获取构成页面的大量图像时尤为有用:

[CON] [REQ1] [REQ2] ... [RESP1] [RESP2] [CLO] ...

这显然能显著提升性能,因为后续请求之间的网络延迟被消除。许多 HTTP 客户端不正确地支持流水线化,因为在 HTTP 中无法将响应与对应的请求关联。因此,服务器必须以与接收请求完全相同的顺序进行回复。实际上,经过多个客户端多次尝试部署后,由于在某些服务器上可靠性不足,该机制已被完全弃用。但服务器必须支持此功能。

下一个改进是多路复用模式,如 HTTP/2 和 HTTP/3 中所实现。在此模式下,多个事务(即请求-响应对)可在单个连接上并行传输,且各自以独立速度推进,互不干扰。采用多路复用协议时,引入了 “stream” 的新概念,用于表示在同一连接上发生的并行通信。每个流通常为特定连接分配唯一的标识符,两端均使用该标识符确定数据的交付位置。客户端在同一个连接上同时开启多个流(最多可达 100 个,有时更多)十分常见,由服务器负责排序,并根据响应的可用性以任意顺序进行响应。多路复用模式的主要优势在于显著减少了往返次数,从而加快了高延迟网络上的页面加载速度。在使用大量图片的网站上,这一特性有时可明显观察到所有图片几乎同时加载。

这些协议通过采用某些机制压缩头字段,以减少网络传输的字节数,因此在缺乏适当工具的情况下,它们无法像 HTTP/1 那样通过人工方式实际操作或肉眼直接阅读。出于这一原因,尽管协议版本更新,文献(包括本文)中仍继续使用 HTTP/1 语法来表示各种 HTTP 消息示例。

HTTP/2 存在一些设计上的局限性,例如数据包丢失会同时影响所有流,若客户端获取对象耗时过长(例如需要将其存储到磁盘),可能会导致其自身获取速度变慢,并在此期间无法访问其后方待处理的数据。这被称为“队首阻塞”或“HoL 阻塞”,有时也简称为 “HoL”。

HTTP/3 基于 QUIC 实现,而 QUIC 本身基于 UDP 实现。QUIC 通过独立处理流的方式,在传输层解决了队首阻塞问题。当发生丢包时,受影响的流不会影响其他流,所有流均可并行访问。QUIC 还提供连接迁移支持,但当前 HAProxy 尚不支持该功能。

默认情况下,HAProxy 以持久连接模式运行:对于每个连接,它在处理完每个请求和响应后,会在响应结束与新请求开始之间保持连接空闲。当从客户端接收 HTTP/2 连接时,它会并行处理所有请求,并保持连接空闲,等待新的请求,其行为与持久连接的 HTTP 连接相同。

HAProxy 本质上支持三种连接模式:

  • keep alive:所有请求和响应均被处理,客户端面向和服务器面向的连接将保持活跃,以供后续请求使用。这是默认行为,适用于现代 Web 及现代协议(HTTP/2 和 HTTP/3)。

  • 服务端关闭:在响应发送完成后,面向服务器的连接被关闭。

  • close:在双方响应结束后,主动关闭连接。

此外,默认情况下,面向服务器的连接可被任意客户端的任意请求复用,这是由 HTTP 协议规范所要求的,因此如需使用特定客户端的信息(例如客户端的源地址等),必须随每个请求一并传递。当使用 HTTP/2 与服务器通信时,默认情况下 HAProxy 会将该连接专用于同一客户端,以避免客户端之间出现队头阻塞风险。

1.2. 术语

在 HAProxy 中,术语随着时代演进而有所演变,以适应 HTTP 协议及其使用方式的发展。最初,连接、会话、流或事务之间并无显著区别,但随着时间推移,这些术语逐渐明确,以更贴近现代 HTTP 协议的实际形态,尽管部分术语仍保留在配置或命令行界面中,以维持历史兼容性。

以下是适用于当前 HAProxy 版本的一些定义:

  • 连接:连接是客户端或服务器等远程代理与 HAProxy 之间在最低层级上建立的单个双向通信通道。通常对应于一对 IP 地址和端口之间建立的 TCP 套接字。在面向客户端的一侧,当客户端连接到 HAProxy 时,连接是首先被实例化的实体,作用于连接层级的规则是最早生效的规则。

  • 会话:会话为连接附加了一些上下文信息,包括与传输层相关的信息(例如 TLS 密钥等)或变量。该术语长期以来在 HAProxy 中用于表示两端之间的端到端 HTTP/1.0 通信,因此尽管如今其含义已演变为流,但某些 CLI 命令或统计信息的名称中仍保留该术语,不过帮助消息和描述力求使其含义清晰明确。在网络层术语中(例如操作系统中的 TCP 会话,或防火墙两侧的 TCP 会话)或非 HTTP 的用户级应用中(例如 Telnet 会话或 SSH 会话),该术语仍然适用。不得将其与“应用会话”混淆,后者用于在 Cookie 中存储完整的用户上下文,并要求始终将请求发送至同一服务器。

  • 流:流在应用层精确对应于端到端的双向通信,可在其上应用分析和转换。在 HTTP 中,流包含一个请求及其关联的响应,由请求到达时创建,并在响应传输结束时终止。在此上下文中,此类流与多路复用协议的流之间存在一对一关系。在 TCP 通信中,每个连接对应单一的流。

  • transaction:事务仅指一个请求及其关联的响应。该术语在流出现之前曾与会话一同使用,但如今事务与流之间存在一对一关系。其本质体现在变量作用域 “txn” 中,该作用域贯穿整个事务,因此也覆盖整个流。

  • request:指从客户端流向服务器的流量。主要用于 HTTP,表示操作执行的位置。该术语在 TCP 操作中也存在,用于表示数据处理的位置。请求通常以流量或活动单位的形式出现在计数器中。请求不一定意味着存在响应(例如由于错误),但由于没有请求就不会有自发响应,因此请求仍是衡量整体活动的合理指标。在 TCP 中,请求的数量与连接数量相等。

  • response:此选项指定从服务器流向客户端的流量,或在 HAProxy 自行生成响应时从 HAProxy 流向客户端的流量(例如 HTTP 重定向)。

  • service:通常表示 HAProxy 内部无需服务器参与的处理过程,例如统计页面、缓存或用于实现小型应用的 Lua 代码。服务通常会读取请求,执行某些操作,并生成响应。

1.3. HTTP 请求

首先,考虑以下 HTTP 请求:

Line     Contents
number
   1     GET /serv/login.php?lang=en&profile=2 HTTP/1.1
   2     Host: www.mydomain.com
   3     User-agent: my small browser
   4     Accept: image/jpeg, image/gif
   5     Accept: image/png

1.3.1. 请求行

第 1 行为“请求行”。它始终由 3 个字段组成:

  • 方法:GET
  • URI:/serv/login.php?lang=en&profile=2
  • 版本标签:HTTP/1.1

所有字段均以标准所称的 LWS(线性空白字符)分隔,通常为空格,但也可能为制表符,或换行符/回车符后跟空格/制表符。方法本身不得包含冒号(’:’),且仅限字母字符。这些多种组合使得 HAProxy 自行执行分割操作更为可取,而非由用户编写复杂或不准确的正则表达式。

URI 本身可以有多种形式:

  • 相对 URI:
  /serv/login.php?lang=en&profile=2

It is a complete URL without the host part. This is generally what is
received by servers, reverse proxies and transparent proxies.
  • “绝对 URI”,也称为 “URL”:
  http://192.168.0.12:8080/serv/login.php?lang=en&profile=2

It is composed of a "scheme" (the protocol name followed by '://'), a host
name or address, optionally a colon (':') followed by a port number, then
a relative URI beginning at the first slash ('/') after the address part.
This is generally what proxies receive, but a server supporting HTTP/1.1
must accept this form too.
  • 星号(’*’):此形式仅在与 OPTIONS 方法关联时被接受,且不可中继。它用于查询下一跳的能力。

  • 地址:端口组合:192.168.0.12:80。此配置与 CONNECT 方法配合使用,该方法用于通过 HTTP 代理建立 TCP 隧道,通常用于 HTTPS,有时也用于其他协议。

在相对 URI 中,识别出两个子部分。问号之前的部分称为 “path”,通常为服务器上静态资源的相对路径。问号之后的部分称为“查询字符串”,主要用于发送至动态脚本的 GET 请求,其具体格式高度依赖于所使用的语言、框架或应用程序。

HTTP/2 和 HTTP/3 不会在请求中传递版本信息,因此默认认为其版本与底层协议一致(即 “HTTP/2”)。此外,这些协议不会将请求行作为一个整体发送,而是将其拆分为若干字段,称为 “pseudo-headers”,其名称以冒号开头,HAProxy 会将其方便地重新组合为等效的请求行。因此,日志中记录的请求行在 HTTP/1.x 与 HTTP/2 或 HTTP/3 之间可能存在细微差异。

1.3.2. 请求头

头从第二行开始。头由行首的名称组成,名称后立即跟一个冒号(’:’)。传统上,冒号后会添加一个线性空白字符(LWS),但并非必须。随后是值。多个相同的头可以合并为一行,通过逗号分隔值,前提是必须保持顺序。这在 “Cookie:” 字段中较为常见。如果后续行以 LWS 开头,头可以跨多行。在 1.3 节的示例中,第 4 行和第 5 行共同为 “Accept:” 头定义了总共 3 个值。最后,根据规范,头开头或结尾的所有 LWS 均被忽略,不计入值中。

与常见误解相反,头名称不区分大小写,其值在引用其他头名称(如“Connection:”头)时同样不区分大小写。在 HTTP/2 和 HTTP/3 中,头名称始终以小写形式发送,这一点在启用调试模式运行时可以观察到。内部实现中,所有头名称均被规范化为小写,以确保 HTTP/1.x 与 HTTP/2 或 HTTP/3 使用完全相同的表示形式,并在另一端原样发送。这解释了为何以驼峰命名法输入的 HTTP/1.x 请求在接收时会以小写形式呈现。

头的结束由第一个空行指示。人们常说这是两个换行符,这并不准确,尽管两个换行符是空行的一种有效形式。

幸运的是,HAProxy 在处理头索引、值检查和计数时会自动处理所有复杂的组合,因此无需担心头的写法,但若应用程序执行了非寻常但合法的操作,不应将其归咎于存在缺陷。

请注意:

As suggested by RFC7231, HAProxy normalizes headers by replacing line breaks
in the middle of headers by LWS in order to join multi-line headers. This
is necessary for proper analysis and helps less capable HTTP parsers to work
correctly and not to be fooled by such complex constructs.

1.4. HTTP 响应

HTTP 响应与 HTTP 请求非常相似。两者均称为 HTTP 消息。请考虑以下 HTTP 响应:

Line     Contents
number
   1     HTTP/1.1 200 OK
   2     Content-length: 350
   3     Content-Type: text/html

作为特例,HTTP 支持所谓的“信息性响应”,即状态码 1xx。这类消息的特殊之处在于,它们不携带响应的任何部分,仅用作一种信号,例如通知客户端继续发送其请求。对于状态码 100 的响应,所请求的信息将由后续非 100 状态码的响应消息携带。这意味着单个请求可能收到多个响应,且此机制仅在启用持久连接时有效(1xx 消息出现在 HTTP/1.1 中)。HAProxy 能够正确处理此类消息,可将其转发并跳过,仅处理下一个非 100 状态码的响应。因此,除非明确另行说明,否则这些消息既不会被记录,也不会被转换。状态码 101 的响应表示协议将在同一连接上发生变更,HAProxy 必须切换至隧道模式,如同发生了 CONNECT 请求一般。此时,Upgrade 头将包含关于连接所切换协议类型的附加信息。

1.4.1. 响应行

第 1 行是“响应行”。它始终由 3 个字段组成:

  • 版本标签:HTTP/1.1
  • 状态码:200
  • 原因:OK

状态码始终为三位数字。第一位数字表示总体状态:

  • 1xx = 信息性消息,应跳过(例如 100、101)
  • 2xx = 成功,后续有内容(例如 200、206)
  • 3xx = 成功,后续无内容(例如 302、304)
  • 4xx = 客户端引起的错误(例如 401、403、404)
  • 5xx = 服务器引起的错误(例如 500、502、503)

状态码大于 599 时,不得在通信中发出,尽管某些代理可能会在日志中生成此类状态码以报告其内部状态。有关所有此类状态码的详细含义,请参阅 RFC9110。HTTP/2 及以上版本不使用版本标签,而是使用 “:status” 伪头来报告状态码。

“reason” 字段仅作为提示,客户端不会解析该字段。该字段可包含任意内容,但通常建议遵循已确立的通用消息规范。其内容可由一个或多个单词组成,例如 “OK”、“Found” 或 “Authentication Required”。该字段在 HTTP/2 及以上版本中不存在,也不会在这些版本中发出。当从 HTTP/2 或更高版本返回的响应传输至 HTTP/1 客户端时,HAProxy 将生成与状态码匹配的通用原因字段。

HAProxy 可能自行发出以下状态码:

Code  When / reason
 200  access to stats page, and when replying to monitoring requests
 301  when performing a redirection, depending on the configured code
 302  when performing a redirection, depending on the configured code
 303  when performing a redirection, depending on the configured code
 307  when performing a redirection, depending on the configured code
 308  when performing a redirection, depending on the configured code
 400  for an invalid or too large request
 401  when an authentication is required to perform the action (when
      accessing the stats page)
 403  when a request is forbidden by a "http-request deny" rule
 404  when the requested resource could not be found
 408  when the request timeout strikes before the request is complete
 410  when the requested resource is no longer available and will not
      be available again
 413  when a HTTP/1.0 GET/HEAD/DELETE requests has a payload, also see
      the "h1-accept-payload-with-any-method" option
 500  when HAProxy encounters an unrecoverable internal error, such as a
      memory allocation failure, which should never happen
 501 when HAProxy is unable to satisfy a client request because of an
     unsupported feature
 502  when the server returns an empty, invalid or incomplete response, or
      when an "http-response deny" rule blocks the response.
 503  when no server was available to handle the request, or in response to
      monitoring requests which match the "monitor fail" condition
 504  when the response timeout strikes before the server responds

上述 4xx 和 5xx 错误码可自定义(参见 “errorloc” 在 第 4.2 节 )。其他状态码可通过特定动作主动发出(例如,参见 “deny”、“return” 和 “redirect” 动作在 第 4.3 节 )。

1.4.2. 响应头

响应头的工作方式与请求头完全相同,因此 HAProxy 对两者使用相同的解析函数。详情请参见第 1.3.2 段。

11 - 2. 配置 HAProxy

文件语法、引号、变量、条件、时间与大小格式、地址及示例

2.1. 配置文件格式

HAProxy 的配置过程涉及三个主要参数来源:

  • 命令行参数,始终具有最高优先级
  • 配置文件,其格式在此处描述
  • 运行进程的环境,若显式引用了某些环境变量

配置文件采用一种相对简单的分层格式,遵循若干基本规则:

1. a configuration file is an ordered sequence of statements

2. a statement is a single non-empty line before any unprotected "#" (hash)

3. a line is a series of tokens or "words" delimited by unprotected spaces or
   tab characters

4. the first word or sequence of words of a line is one of the keywords or
   keyword sequences listed in this document

5. all other words are all arguments of the first one, some being well-known
   keywords listed in this document, others being values, references to other
   parts of the configuration, or expressions

6. certain keywords delimit a section inside which only a subset of keywords
   are supported

7. a section ends at the end of a file or on a special keyword starting a new
   section

编写一个简单但可靠的配置生成器只需了解以上内容,但这些信息不足以可靠地解析任意配置,也无法确定如何处理某些特殊情况。

首先,上述规则带来若干后果。规则 6 和 7 意味着,用于定义新段的关键词在任何位置均有效,且在特定段中不可具有不同含义。这些关键词始终为单个单词(而非单词序列),传统上,其后跟随的段以相同名称进行标识。例如,提及“global 段”时,即指 “global” 关键字之后的配置段。此用法在错误消息中广泛使用,以帮助定位需处理的部分。

若干段会创建一个内部对象或配置空间,需与其他对象或空间区分开。此时,这些段将额外使用一个词来指定该特定段的名称。部分段的名称为必填项。例如,“frontend foo”将创建一个类型为 “frontend”、名称为 “foo” 的新段。通常,名称仅在其所属段内具有唯一性,不同类型段可使用相同名称,但不建议如此,因为这会增加配置管理的复杂性。

规则 7 的直接后果是,当同时读取多个文件时,每个文件都必须以新的段开始,且每个文件的结尾将结束一个段。文件中不能包含子段,也不能结束一个现有段并开始一个新的段。

规则 1 提到顺序至关重要。确实,某些关键字会创建可重复的指令,从而形成按特定顺序应用的规则序列。例如,“tcp-request” 可用于根据不同的条件交替使用 “accept” 和 “reject” 规则。因此,配置文件处理器在编辑文件时必须始终保留段的顺序。段的顺序通常无关紧要,但全局段必须置于其他段之前,必要时可重复出现。此外,某些自动标识符可能被自动分配给部分创建的对象(例如代理),通过重新排序段,其标识符将发生变化。这些标识符会在统计信息中出现。因此,以下配置将使 “foo” 的 ID 号小于其 “bar” 对应项的 ID 号。若两个段顺序互换,该 ID 号将随之对调:

listen foo
    bind:80

listen bar
    bind:81

另一个重要点是,根据上述规则 2 和 3,紧跟在未受保护的 “#” 字符之后的空行、空格、制表符以及注释均不属于配置内容,仅用作分隔符。这意味着以下配置在语法上完全等价:

    global#this is the global section
daemon#daemonize
    frontend         foo
mode             http   # or tcp

和:

global
    daemon

# this is the public web frontend
frontend foo
    mode http

通常的做法是,仅将启动新段的关键词左对齐,其余关键词则缩进(即在前面添加制表符或若干空格),以便立即看出它们属于同一段(如上文第二个示例所示)。在新段之前添加注释,有助于读者判断该段是否为所需内容。在段末留空行,也有助于在编辑时直观识别段的结束位置。

制表符在缩进时非常方便,但复制粘贴时表现不佳。若改用空格,建议避免使用过多空格(2 到 4 个),以免在不支持自动缩进的编辑器中编辑时造成负担。

在早期,人们常将参数按固定制表位分割,因为大多数关键字最多只需两个参数。随着现代版本引入复杂表达式,这种做法已不再适用,且不建议继续使用。

2.2. 引用与转义

在现代配置中,某些参数需要使用此前被视为纯分隔符的字符。为实现此目的,HAProxy 支持通过在待转义字符前添加反斜杠(’\’)进行字符转义,使用双引号("")对文本片段进行弱引号包围,以及使用单引号(’’)对文本片段进行强引号包围。

这与多种编程语言中的处理方式非常相似,也与 Bourne shell 中常见的做法极为接近。其原理如下:当配置解析器将行拆分为单词时,会同时处理引号和反斜杠,以判断某个字符是分隔符,还是当前单词中该字符的原始表示。随后,转义字符被移除,引号被去除,剩余部分直接作为关键字或参数使用。

如果在单词中需要使用反斜杠,必须通过自身转义(即双反斜杠)或使用强引号包围。

转义引号外的特殊字符需在该字符前添加反斜杠(’\’):

\    to mark a space and differentiate it from a delimiter
\#   to mark a hash and differentiate it from a comment
\\   to use a backslash
\'   to use a single quote and differentiate it from strong quoting
\"   to use a double quote and differentiate it from weak quoting

此外,部分不可打印字符可使用其常见的 C 语言表示法输出:

\n   to insert a line feed (LF, character \x0a or ASCII 10 decimal)
\r   to insert a carriage return (CR, character \x0d or ASCII 13 decimal)
\t   to insert a tab (character \x09 or ASCII 9 decimal)
\xNN to insert character having ASCII code hex NN (e.g \x0a for LF).

弱引用通过在字符或字符序列周围加上双引号("")来实现。弱引用可防止以下内容的解释:

     space or tab as a word separator
'    single quote as a strong quoting delimiter
#    hash as a comment start

弱引号允许通过在环境变量前加上美元符号($)来解释这些变量(变量仅在引号内求值)。若需在双引号内使用美元符号,必须使用反斜杠进行转义。

强引用通过在字符或字符序列周围使用单引号(’’)来实现,以保护其不被解释。在单引号内,任何内容均不会被解析,这是引用正则表达式最高效的方式。

因此,以下是不同上下文中特殊字符输入方式的对照矩阵(不可打印字符以尖括号内的名称代替)。请注意,部分仅能通过转义方式表示的字符在单引号内无法表示,故该处为空:

  Character  |  Unquoted     |  Weakly quoted              |  Strongly quoted
  -----------+---------------+-----------------------------+-----------------
    <TAB>    |  \<TAB>, \x09 |  "<TAB>", "\<TAB>", "\x09"  |  '<TAB>'
  -----------+---------------+-----------------------------+-----------------
    <LF>     |  \n, \x0a     |  "\n", "\x0a"               |
  -----------+---------------+-----------------------------+-----------------
    <CR>     |  \r, \x0d     |  "\r", "\x0d"               |
  -----------+---------------+-----------------------------+-----------------
    <SPC>    |  \<SPC>, \x20 |  "<SPC>", "\<SPC>", "\x20"  |  '<SPC>'
  -----------+---------------+-----------------------------+-----------------
    "        |  \", \x22     |  "\"", "\x22"               |  '"'
  -----------+---------------+-----------------------------+-----------------
    #        |  \#, \x23     |  "#", "\#", "\x23"          |  '#'
  -----------+---------------+-----------------------------+-----------------
    $        |  $, \$, \x24  |  "\$", "\x24"               |  '$'
  -----------+---------------+-----------------------------+-----------------
    '        |  \', \x27     |  "'", "\'", "\x27"          |
  -----------+---------------+-----------------------------+-----------------
    \        |  \\, \x5c     |  "\\", "\x5c"               |  '\'
  -----------+---------------+-----------------------------+-----------------

示例:

# those are all strictly equivalent:
log-format %{+Q}o\ %t\ %s\ %{-Q}r
log-format "%{+Q}o %t %s %{-Q}r"
log-format '%{+Q}o %t %s %{-Q}r'
log-format "%{+Q}o %t"' %s %{-Q}r'
log-format "%{+Q}o %t"' %s'\ %{-Q}r

在特定情况下,可能需要进行第二层引号或转义操作。某些关键字的参数位于括号内,有时由逗号分隔。这些参数通常为整数或预定义词,但当参数为任意字符串时,可能需要进行额外的转义处理,以明确区分属于参数本身的字符与用于分隔参数的字符。一个常见的情况是 “regsub” 转换器。该转换器的参数为正则表达式,若在正则表达式内部需要使用右括号,则该右括号必须使用自身的引号进行包裹。

关键字参数解析器在引号处理方面与顶层解析器完全相同,但不会处理 \#、\$ 和 \xNN 的转义序列。但并非总是显而易见的是,内部使用的分隔符必须先进行转义或加引号,以确保它们不会在顶层被解析。

本例使用 “regsub” 转换器,该转换器接受三个参数:一个正则表达式、一个替换字符串以及一组标志。

# replace all occurrences of "foo" with "blah" in the path:
http-request set-path %[path,regsub(foo,blah,g)]

此处无需特殊引号。但若现在我们想将 “foo” 或 “bar” 替换为 “blah”,则需要使用正则表达式 “(foo|bar)"。无法编写:

http-request set-path %[path,regsub((foo|bar),blah,g)]

因为我们希望字符串按如下方式截断:

    http-request set-path %[path,regsub((foo|bar),blah,g)]
                                       |---------|----|-|
                                 arg1 _/         /    /
                                 arg2 __________/    /
                                 arg3 ______________/

但实际传递的是括号内开头与结尾之间的字符串,随后是垃圾数据:

    http-request set-path %[path,regsub((foo|bar),blah,g)]
                                       |--------|--------|
                        arg1=(foo|bar _/        /
                    trailing garbage  _________/

显然,此处的解决方案似乎是需要对右括号进行转义,但仅这样做无效,因为如上所述,引号由顶层解析器处理,会在处理该单词之前被解析:

http-request set-path %[path,regsub("(foo|bar)",blah,g)]
------------ -------- ----------------------------------
   word1       word2    word3=%[path,regsub((foo|bar),blah,g)]

因此,我们未对第二层的参数解析器进行任何修改,它仍然将截断的正则表达式视为唯一参数,并将字符串末尾的垃圾数据视为无效输入。通过转义引号,这些引号将原样传递至第二层:

    http-request set-path %[path,regsub(\"(foo|bar)\",blah,g)]
    ------------ -------- ------------------------------------
       word1       word2    word3=%[path,regsub("(foo|bar)",blah,g)]
                                                |---------||----|-|
                                arg1=(foo|bar) _/          /    /
                                    arg2=blah  ___________/    /
                                        arg3=g _______________/

另一种方法是使用单引号包围整个字符串,而在字符串内部使用双引号(以避免双引号被再次去除):

    http-request set-path '%[path,regsub("(foo|bar)",blah,g)]'
    ------------ --------  ----------------------------------
       word1       word2    word3=%[path,regsub("(foo|bar)",blah,g)]
                                                |---------||----|-|
                                arg1=(foo|bar) _/          /    /
                                          arg2 ___________/    /
                                          arg3 _______________/

但在这种情况下,需要注意的是,嵌入到高层级字符串中的分隔符仍为纯字符,不再作为分隔符使用。这尤其意味着,逗号周围的空格和制表符属于字符串的一部分。以下示例在多个方面均存在错误:

    http-request set-path '%[path, regsub("(foo|bar)", blah, g)]'
    ------------ --------  --------------------------------------
       word1       word2    word3=%[path, regsub("(foo|bar)", blah, g)]
                                        |--------|---------||-----|--|
                       converter=" regsub" _/        /         /   /
                                    arg1=(foo|bar) _/         /   /
                                     arg2=" blah" ___________/   /
                                        arg3=" g" ______________/

仅因在逗号周围添加空格,导致空格成为字段本身的一部分,因此转换器 " regsub”(以空格开头)将无法被找到,从而触发错误;更微妙的是,替换字符串 " blah" 会在输出中插入一个空格。一个良好的经验是,切勿在表达式中插入不必要的空格。

使用正则表达式时,可能出现美元符号($)出现在表达式中,或在替换字符串中使用反斜杠(\)的情况。此时这些字符也会在双引号内被处理,因此建议使用单引号(或双重转义)。示例:

    http-request set-path '%[path,regsub("^/(here)(/|$)","my/\1",g)]'
    ------------ --------  -----------------------------------------
       word1       word2    word3=%[path,regsub("^/(here)(/|$)","my/\1",g)]
                                                |-------------| |-----||-|
                              arg1=(here)(/|$) _/               /      /
                                    arg2=my/\1 ________________/      /
                                          arg3 ______________________/

请注意,单引号内的反斜杠不是转义字符,且上述整个单词已通过单引号完全保护,避免了反斜杠的解析。反之,若整个表达式使用双引号包围,则单个美元符号和反斜杠将在顶层被解析,导致第二层参数内容被破坏。

由于单引号无法在强引用内部进行转义,若需在参数中包含单引号,必须对它们进行双重转义或双重引用。有几种实现方式:

http-request set-var(txn.foo) str("\\'foo\\'")
http-request set-var(txn.foo) str(\"\'foo\'\")
http-request set-var(txn.foo) str(\\\'foo\\\')

如有疑问,建议在任何位置均不使用引号,仅在需要逗号或右括号的参数周围添加单引号或双引号,并在字符串包含美元符号或反斜杠时考虑使用反斜杠进行转义。再次强调,这与在 Bourne shell 中对传递给 “eval” 的命令进行双重转义时的做法非常相似。对于 API 开发者而言,最稳妥的做法是无论参数内容如何,均对每个参数使用转义引号。用户可能会发现,将整个表达式用单引号包围,每个参数用双引号包围,可提供更具可读性的配置。

2.3. 环境变量

HAProxy 的配置支持环境变量。这些变量仅在双引号内被解析。变量在配置解析期间展开。变量名必须以美元符号($)开头,可选地用花括号({})括起,与 Bourne shell 中的做法类似。变量名可包含字母数字字符或下划线("_"),但不应以数字开头。若变量包含多个以空格分隔的值,可通过将变量用花括号括起并在闭合花括号前添加后缀 ‘[*]’,将其展开为独立参数。也可在变量名后紧接一个连字符 ‘-’ 并指定默认值,以在变量未设置时使用该值。请注意,此默认值仅替换未定义的变量,而非空值。

示例:

bind "fd@${FD_APP1}"

log "${LOCAL_SYSLOG-127.0.0.1}:514" local0 notice  # send to local server

user "$HAPROXY_USER"

HAProxy 定义了一些变量,可在配置文件中使用。这些变量列于下方矩阵中,并按四类进行分类:

  • usable:该变量可在配置中访问,既可直接解析使用,也可用于条件块或谓词中,以启用或禁用某些配置片段,具体说明参见 第 2.4 节 “条件块”。

  • 可修改:该变量可通过 “setenv”/“unsetenv” 关键字在配置中重新定义或取消设置。

  • listed:该变量会显示在 CLI 的 “show env” 命令输出中,详见管理指南 第 9.3 节 “Unix 套接字命令”。

此外,还存在两个子类别 “master” 和 “worker”,分别在下表中标记为 ‘M’ 和 ‘W’,展示了 HAProxy 以主从模式启动时两个进程之间的差异。

  • master:该变量在主进程(master process)中被设置并可访问。因此,它将出现在主进程 CLI 的 “show env” 输出中,并可用于条件块或指令中,以为主进程启用某些特殊设置(参见 第 2.4 节 “条件块”中的示例)。

  • worker:该变量在工作进程内设置并可访问。它将出现在工作进程 CLI 的 “show env” 命令(或主进程 CLI 的 “@1 show env” 命令)中,也可用于条件控制工作进程的某些参数(参见 第 2.4 节 “条件块” 中的示例)。

在独立模式下(未使用 “-W” 选项或 “master-worker” 关键字),进程的行为类似于工作进程,但变量 “HAPROXY_MASTER_CLI” 和 “HAPROXY_MWORKER” 未被定义。

部分变量标记为不可用且不可修改:

  • HAPROXY_CFGFILES
  • HAPROXY_MWORKER
  • HAPROXY_CLI
  • HAPROXY_MASTER_CLI
  • HAPROXY_LOCALPEER

在配置解析期间,这些变量的值未定义,它们将在初始化阶段被设置。因此,建议不要在条件块中使用这些变量,也不要在全局段的 “setenv”/“resetenv”/“unsetenv” 关键字中引用它们。

下表总结了各变量在不同工作模式下的状态:

  +---------------------------+---------+------------+-----------+
  |          variable         | usable  | modifiable |  listed   |
  |                           +---------+------------+-----------+
  |                           |  M | W  |   M  |  W  |  M  |  W  |
  +---------------------------+----+----+------+-----+-----+-----+
  | HAPROXY_STARTUP_VERSION   |  X | X  |      |     |  X  |  X  |
  | HAPROXY_BRANCH            |  X | X  |      |     |  X  |  X  |
  | HAPROXY_CFGFILES          |    |    |      |     |  X  |  X  |
  | HAPROXY_MWORKER           |    |    |      |     |  X  |  X  |
  | HAPROXY_CLI               |    |    |      |     |     |  X  |
  | HAPROXY_MASTER_CLI        |    |    |      |     |  X  |     |
  | HAPROXY_LOCALPEER         |    | X  |      |     |     |  X  |
  | HAPROXY_HTTP_LOG_FMT      |    | X  |      |  X  |     |     |
  | HAPROXY_HTTP_CLF_LOG_FMT  |    | X  |      |  X  |     |     |
  | HAPROXY_HTTPS_LOG_FMT     |    | X  |      |  X  |     |     |
  | HAPROXY_TCP_LOG_FMT       |    | X  |      |  X  |     |     |
  | HAPROXY_TCP_CLF_LOG_FMT   |    | X  |      |  X  |     |     |
  | HAPROXY_KEYLOG_FC_LOG_FMT |    | X  |      |  X  |     |     |
  | HAPROXY_KEYLOG_BC_LOG_FMT |    | X  |      |  X  |     |     |
  +---------------------------+----+----+------+-----+-----+-----+

相关变量如下:

  • HAPROXY_LOCALPEER:在包含本地对等节点名称的进程启动时定义。(参见管理指南中的 “-L”。)

  • HAPROXY_CFGFILES:HAProxy 加载的配置文件列表,各文件间以分号分隔。在指定目录的情况下可能有用。

  • HAPROXY_HTTP_LOG_FMT:包含默认 HTTP 日志格式的值,定义于 第 8.2.3 节 “HTTP 日志格式”。可用来覆盖默认日志格式,而无需复制完整的原始定义。

  • HAPROXY_HTTP_CLF_LOG_FMT:包含默认 HTTP CLF 日志格式的值,定义于 第 8.2.3 节 “HTTP 日志格式”。可用来覆盖默认日志格式,而无需复制完整的原始定义。

示例:

# Add the rule that gave the final verdict to the log
log-format "${HAPROXY_TCP_LOG_FMT} lr=%[last_rule_file]:%[last_rule_line]"
  • HAPROXY_HTTPS_LOG_FMT:与 HAPROXY_HTTP_LOG_FMT 类似,但适用于 第 8.2.4 节 中定义的 HTTPS 日志格式。

  • HAPROXY_TCP_LOG_FMT:与 HAPROXY_HTTP_LOG_FMT 类似,但适用于 第 8.2.2 节 “TCP 日志格式” 中定义的 TCP 日志格式。

  • HAPROXY_TCP_CLF_LOG_FMT:与 HAPROXY_HTTP_CLF_LOG_FMT 类似,但适用于 第 8.2.2 节 “TCP 日志格式” 中定义的 TCP CLF 日志格式。

  • HAPROXY_KEYLOG_FC_LOG_FMT:指定前端(客户端面向)TLS 连接的密钥日志格式,密钥条目以换行符分隔,因此可能与syslog 服务器不兼容。“tune.ssl.keylog on” 必须启用。

  • HAPROXY_KEYLOG_BC_LOG_FMT:与 HAPROXY_KEYLOG_FC_LOG_FMT 类似,但用于后端(服务器面向)的 TLS 连接。密钥条目以换行符分隔,可能与syslog 服务器不兼容。“tune.ssl.keylog on” 必须启用。

  • HAPROXY_MWORKER:在主进程/工作进程模式下,此变量被设置为 1。

  • HAPROXY_CLI:配置每个进程的统计信息套接字的监听器地址,地址之间以分号分隔。

  • HAPROXY_MASTER_CLI:在主进程/工作进程模式下,主进程 CLI 监听器地址,以分号分隔。

  • HAPROXY_STARTUP_VERSION:包含用于启动的版本信息。在主进程/工作进程模式下,即使更新了二进制文件并重载,该值仍为启动主进程时所用的版本。

  • HAPROXY_BRANCH:包含 HAProxy 分支版本(例如 “2.8”)。不包含完整版本号。在迁移场景下,若资源(如映射或证书)路径中包含分支号,则该信息可能有用。

此外,部分伪变量会内部解析,可作为普通变量使用。 伪变量始终以英文句点(’.’)开头,且仅此类变量允许使用句点。 当前支持的伪变量列表如下:

  • .FILE: 当前正在解析的配置文件的名称。

  • .LINE:当前正在解析的配置文件的行号,从 1 开始。

  • .SECTION:当前正在解析的段的名称,或若该段无名称则为其类型(例如 “global”),或在首个段之前为空字符串。

这些变量在被解析的位置进行解析。例如,若在 defaults 段中某个 “log-format” 指令里使用了 “.LINE” 变量,其行号将在解析和编译 “log-format” 指令之前被解析,因此后续代理将重用该行号。

通过这种方式,可以将信息输出至变量、日志、错误状态、健康检查、头字段值,甚至使用行号来命名某些配置对象(例如服务器),以帮助定位规则。

2.4. 条件块

有时,能够有条件地启用或禁用配置中的任意部分会非常方便,例如启用或禁用 SSL 或加密套件,无需修改配置即可启用或禁用某些预生产环境监听器,或调整配置语法以在迁移期间支持 HAProxy 的两个不同版本。HAProxy 提供了一组可嵌套的类似预处理器的指令,可用于集成或忽略某些文本块。这些指令必须单独占一行,且作用于其后的行。其中两个指令支持表达式,其余指令仅用于切换到备用块或结束当前层级。以下 4 个指令用于构成条件块:

  • .if <condition>
  • .elif <condition>
  • .else
  • .endif

“.if” 指令嵌套新层级,".elif" 保持在同一层级,".else" 同样如此,而 “.endif” 用于关闭层级。每个 “.if” 必须由对应的 “.endif” 结束。".elif" 仅可在 “.if” 或 “.elif” 之后放置,且 “.elif” 的链式连接数量无限制。每个 “.if” 中只能存在一个 “.else”,且其必须位于 “.if” 或区块中最后一个 “.elif” 之后。

注释可置于行尾,使用 ‘#’ 后跟注释内容,该部分将被忽略。指令的解析方式与其他配置指令相同,因此可在条件中使用环境变量。

也可以在启动时通过 -cc 参数评估条件。参见管理文档中的“3. 启动 HAProxy”节。

条件可以是空字符串(此时返回 false),或由以下任意组合构成的表达式:

  • 整数零(‘0’),始终返回 “false”
  • 非零整数(例如 ‘1’),始终返回 “true”
  • 一个可选的谓词,后接括号内的参数
  • 位于一对括号 ‘(’ 和 ‘)’ 之间的条件
  • 在上述任意非空元素前加上感叹号(’!’),用于对其状态取反
  • 使用逻辑与(’&&’)组合的表达式,从左到右依次求值,直到其中一个返回 false
  • 使用逻辑或(’||’)组合的表达式,从右到左依次求值,直到其中一个返回 true

与配置语言其余部分使用的行分词器和参数解析器相同。 单词在连续的一个或多个未加引号的空格或制表符处进行分割,并在评估前使用单个空格重新组合以分隔它们,从而避免用户必须对整行进行加引号。 但这同时也意味着,逗号或括号周围的空格肯定是值的一部分,这并不总是符合预期。例如,下面的表达式:

.if defined( HAPROXY_MWORKER )

将测试变量 " HAPROXY_MWORKER “(含空格)是否存在,以及此条:

.if streq("$ENABLE_SSL",     1)

将环境变量 “ENABLE_SSL” 与值 " 1”(前导单个空格)进行比较。 原因是该行首先被拆分为单词,格式如下:

   .if streq("$ENABLE_SSL",     1)
  |---|--------------------|   |--|
    1           2               3

然后应用弱引用,解析环境变量 “$ENABLE_SSL”(例如,假设 ENABLE_SSL=0),最后通过在各单词之间插入一个空格,将单词重新组合为一个字符串:

   .if streq(0, 1)
  |---|-------|--|
    1     2     3

且仅在此时,它才会被解析为单一表达式。插入在逗号与"1"之间的空格仍属于参数值的一部分,导致该参数为“ 1”:

   .if streq(0, 1)
  |---|-----|-|--|
    \    \    \  \_ argument2: " 1"
     \    \    \___ argument1: "0"
      \    \_______ function: "streq"
       \___________ directive: ".if"

可见,即使 ENABLE_SSL 等于 “1”,也不会匹配 " 1",因为字符串会因多一个空格而不同。

请注意:如第“2.2. 引号与转义”段所述,一个良好的经验是切勿在表达式中插入不必要的空格。

请注意,与其他语言类似,AND 运算符的优先级高于 OR 运算符,因此表达式“A && B || C && D”等价于“(A && B) || (C && D)”。

当前支持的谓词列表如下:

  • awslc_api_atleast(<ver>):若当前 awslc API 版本号不低于 <ver>,则返回 true,否则返回 false。示例:awslc_api_atleast(35)

  • awslc_api_before(<ver>):若当前 awslc API 版本号严格早于 <ver>,则返回 true,否则返回 false。示例:awslc_api_before(26)

  • defined(<name>) : 当环境变量 <name> 存在时返回 true,无论其内容为何

  • feature(<name>) : 当 “haproxy -vv” 报告的特性列表中包含 <name> 时返回 true(即在 ‘+’ 后出现 <name>)

  • openssl_version_atleast(<ver>):若当前 OpenSSL 版本不低于 <ver>,则返回 true,否则返回 false。LibreSSL、AWS-LC 和 WolfSSL 等库也提供伪 OpenSSL 版本。示例:

ssllib_name_startswith(OpenSSL) && openssl_version_atleast(1.1.1)
  • openssl_version_before(<ver>):若当前 OpenSSL 版本严格早于 <ver>,则返回 true,否则返回 false。LibreSSL、AWS-LC 和 WolfSSL 等库也提供伪 OpenSSL 版本。示例:openssl_version_before(3.5.0)

  • ssllib_name_startswith(<name>) :若 HAProxy 链接的 SSL 库名称以 <name> 开头,则返回 true。示例:ssllib_name_startswith(wolfSSL)

  • streq(<str1>,<str2>) : 仅当两个字符串相等时返回 true

  • strneq(<str1>,<str2>):仅当两个字符串不相等时返回 true

  • strstr(<str1>,<str2>):仅当第二个字符串在第一个字符串中找到时返回 true。

  • version_atleast(<ver>):若当前 HAProxy 版本不低于 <ver>,则返回 true,否则返回 false。版本语法与 “HAProxy -v” 所显示的相同,缺失的组件视为零。

  • version_before(<ver>):若当前 HAProxy 版本严格早于 <ver>,则返回 true,否则返回 false。版本语法与 “HAProxy -v” 所显示的相同,缺失的组件视为零。

  • enabled(<opt>) : 在运行时若选项 <opt> 已启用则返回 true。仅支持部分选项:

POLL, EPOLL, KQUEUE, EVPORTS, SPLICE,
GETADDRINFO, REUSEPORT, FAST-FORWARD,
SERVER-SSL-VERIFY-NONE

示例:

# 1. HAPROXY_MWORKER variable is set automatically by HAProxy in master and
# in worker process environments (see HAProxy variables matrix from
# 2.3. Environment variables). Its presence enables an additional listener.

global
  master-worker

.if defined(HAPROXY_MWORKER) listen mwcli_px bind:1111 … .endif

# 2. HAPROXY_BRANCH is set automatically by HAProxy in master and in worker
# process environments (see HAProxy variables matrix from 2.3. Environment
# variables). We check HAPROXY_BRANCH value and conditionally enable
# mworker-max-reloads parameter.

global
  master-worker

.if streq("$HAPROXY_BRANCH", 3.1) mworker-max-reloads 5 .endif

# 3. Some arbitrary environment variables are set by user in the global
# section. If HAProxy is started in master-worker mode, they are presented in
# master and in worker process environments. We check values of these
# variables and conditionally enable ports 80 and 443. Environment variables
# checks can be mixed with features and version checks.

global
  setenv WITH_SSL yes
  unsetenv SSL_ONLY

.if strneq("$SSL_ONLY", yes) bind:80 .endif

若 $WITH_SSL 的值为 yes 且 OpenSSL 功能可用,则绑定端口 443 并启用 SSL,指定证书文件为 …。

若启用 OpenSSL 功能且 “$WITH_SSL",yes) || streq("$SSL_ONLY” 的值为 yes,则绑定端口 443 并启用 SSL,使用 crt 参数指定证书…

.如果版本不低于 2.4-dev19,则启用内存分析功能 .结束条件

.if !feature(OpenSSL) .alert “SSL 支持为必需项” .endif

此外还提供了四个指令用于报告某些状态:

  • .diag “message” : 仅在诊断模式下(-dD)输出此消息
  • .notice “message” : 以 NOTICE 级别输出此消息
  • .warning “message” : 以 WARNING 级别输出此消息
  • .alert “message” : 以 ALERT 级别输出此消息

警告级别发出的消息在 “zero-warning” 启用时可能导致进程无法启动。警报级别发出的消息将始终导致致命错误。这些消息可用于检测某些不适当的状态,并向用户提供建议。

示例:

.if "${A}"
  .if "${B}"
     .notice "A=1, B=1"
  .elif "${C}"
     .notice "A=1, B=0, C=1"
  .elif "${D}"
     .warning "A=1, B=0, C=0, D=1"
  .else
     .alert "A=1, B=0, C=0, D=0"
  .endif
.else
     .notice "A=0"
.endif

.diag "WTA/2021-05-07: replace 'redirect' with 'return' after switch to 2.4"
      http-request redirect location /goaway if ABUSE

2.5. 时间格式

某些参数涉及表示时间的值,例如超时。这些值通常以毫秒为单位(除非另有明确说明),但也可以通过在数值后附加单位来表示其他单位。这一点非常重要,因为这不会在每个关键字中重复说明。支持的单位包括:

  • us:微秒。1 微秒 = 1/1000000 秒
  • ms:毫秒。1 毫秒 = 1/1000 秒。这是默认值。
  • s:秒。1s = 1000ms
  • m:分钟。1m = 60s = 60000ms
  • h:小时。1h = 60m = 3600s = 3600000ms
  • d:天。1d = 24h = 1440m = 86400s = 86400000ms

2.6. 大小格式

某些参数涉及表示大小的数值,例如带宽限制。这些数值通常以字节为单位(除非另有明确说明),但也可以通过在数值后附加单位来表示其他单位。这一点非常重要,因为这不会在每个关键字中重复说明。支持的单位不区分大小写:

  • k:千字节。1 千字节 = 1024 字节
  • m:兆字节。1 兆字节 = 1048576 字节
  • g:吉字节。1 吉字节 = 1073741824 字节

时间格式和大小格式均需使用整数,不支持小数表示。

2.7. 映射和 ACL 的名称格式

可以为映射或 ACL 使用模式列表。模式列表通过名称进行标识,可在配置中的多个位置使用。模式列表根据名称格式分为三类:

  • 基于常规文件的模式列表:这是默认情况。文件名(绝对或相对路径)用作名称。文件必须存在,否则将触发错误。但文件可以为空。也可指定 “file@” 前缀,但该前缀不参与标识列表的名称。无论是否包含前缀,文件名均引用同一组模式列表。

  • 基于可选文件的模式列表:文件名必须以“opt@”前缀开头。文件是否存在为可选。若文件存在,则加载其内容;若文件不存在,不报告错误。前缀不参与标识列表的名称。这意味着,对于给定的文件名,可选文件与普通文件引用的是同一组模式列表。

  • 基于虚拟文件的模式列表:名称仅作为标识符使用,不指向任何文件。必须使用 “virt@” 前缀,该前缀属于名称的一部分,因此不能与其他类型列表混合使用。

虚拟文件在模式完全动态管理且启动及重载时均无预设模式的情况下非常有用。在相同条件下,也可使用可选文件。但可通过外部脚本(例如基于 “show map” CLI 命令)将模式转储到文件中。借此方式,可在重载时保留模式。

请注意:即使可能性极低,这意味着无法加载任何以 “file@"、“opt@” 或 “virt@” 开头的普通文件,除非在文件名前显式添加 “./"(例如 “file@./virt@map”)。

2.8. 变量

在 HAProxy 配置中,变量可用于样本提取函数、转换器、日志格式字符串或 TCP/HTTP 动作中。进程级变量可被定义,其作用域覆盖整个进程生命周期,全局可访问。部分变量的生命周期较短。变量类似于 shell 脚本中的变量,是内存块的符号名称。变量大小无限制,且动态分配内存。因此必须谨慎使用,尤其在高频率使用场景下。然而,可通过设置 “tune.vars” 全局参数来限制变量所使用的最大内存总量。

变量必须使用格式 “<scope>.<name>” 进行指定。<scope> 为一个单词,用于表示变量的生命周期。<name> 部分在作用域内,仅可包含字符 ‘a-z’、‘A-Z’、‘0-9’ 和 ‘_’。该名称在当前作用域内唯一,但不同作用域中可使用相同名称,分别指向不同的变量。支持的作用域包括:

  • proc:用于定义在整个进程生命周期内始终存在且全局可访问的变量。“proc” 变量可通过 CLI 使用 “get var” 和 “set var” 命令进行操作。也可通过 “global” 段中的 “set-var” 和 “set-var-fmt” 指令进行设置。

  • sess:用于表示在整个会话生命周期内已知的变量。“sess” 变量仅属于特定会话,对外不可见,且不会与其他会话共享。

  • txn:用于在事务整个生命周期内已知的变量。“txn” 变量仅属于流,对外不可见,且不与其他流共享。

  • req:用于在特定流的请求处理过程中已知的变量。“req” 变量从流创建时起可见,直至首次尝试连接服务器为止。它们仅对流私有,外部不可见,且不与其他流共享。“req” 与 “res” 变量之间不存在任何重叠。

  • res : 用于在特定流的响应处理期间已知的变量。“res” 变量从首次服务器连接尝试起即可访问,直至流销毁为止。它们仅对流私有,外部不可见,且不与其他流共享。“req” 与 “res” 变量之间不存在任何重叠。

  • check: 用于在健康检查执行期间已知的变量。“check” 变量仅对健康检查私有,外部不可见,且不会与其他健康检查共享。可使用专用的 “tcp-check” 或 “http-check” 指令进行设置。

根据上下文,可使用额外的作用域来引用当前流的父级:

  • psess:与 “sess” 相同,但使用父流的会话(如果存在)。

  • ptxn:与 “txn” 相同,但使用父流的事务(若存在)。

  • preq : 与 “req” 相同,但使用父流(如有)。“preq” 变量仅在父流的请求处理期间可访问。

  • pres:与 “res” 相同,但使用父流(如果存在)。“pres” 变量仅在父流的响应处理期间可访问。

引用父流的范围从其定义之时起即可使用。大多数情况下,不存在父流。但若适用,将明确说明。目前,仅可获取父流作用域中定义的变量值,无法设置或取消设置此类变量。通常,子流会在特定时刻为父流执行某些处理,并阻止父流在该操作完成前继续推进。这意味着父流可能在请求处理或响应处理过程中被中断。因此,某些作用域从子流中不可用。例如,若请求需由子流执行分析,则该子流在 “pres” 作用域中将找不到任何变量,因为父流当前并未处理响应,因而其 “res” 作用域中也无任何变量。

变量的内容是样本提取表达式求值的结果,并继承该表达式输出的类型。在使用变量时,其类型必须与使用方式兼容。例如,用于“add()”转换器的字符串类型变量必须可转换为有效整数才能成功。当变量与静态值进行比较时,这一点尤为重要,必须使用正确的匹配方法。

2.9. 地址格式

多个语句,如 “bind, “server”, “nameserver” 和 “log”",需要指定地址。

该地址可以是主机名、IPv4 地址、IPv6 地址或 ‘’。’’ 等同于特殊地址 “0.0.0.0”,在 “bind” 或 “dgram-bind” 的情况下,可用于监听系统的所有 IPv4 地址。IPv6 的等效地址为 ‘::’。

根据语句类型,IP 地址后跟端口或端口范围。在 ‘bind’ 语句中为必选项,在 ‘server’ 语句中为可选项。

该地址也可以以斜杠 ‘/’ 开头。它被视为 “unix” 协议族,且必须包含斜杠 ‘/’ 及其后的路径字符。

默认套接字类型或传输方法 “datagram” 或 “stream” 取决于配置语句中显示的地址。实际上,‘bind’ 和 ‘server’ 默认将使用 “stream” 套接字类型,而 ’log’、’nameserver’ 或 ‘dgram-bind’ 将使用 “datagram”。

可选地,可使用前缀强制指定地址族和/或套接字类型及传输方法。

2.9.1. 地址族前缀

‘abns@<name>’ 后接 <name> 是一个抽象命名空间(仅限 Linux)。

‘abnsz@<name>’ 后跟 <name> 是一个以空字符结尾的抽象命名空间(仅限 Linux)。

‘fd@<n>’ 后跟的地址是一个由父进程继承的文件描述符 <n>。该文件描述符必须已绑定,且可能已处于监听状态,也可能尚未开始监听。

‘ip@<address>[:port1[-port2]]’ 在 <address> 后被视为 IPv4 或 IPv6 地址,具体取决于语法。根据使用该地址的语句,可能需要指定端口或端口范围,也可能必须指定。

‘ipv4@<address>[:port1[-port2]]’ 在 <address> 之后始终被视为 IPv4 地址。根据使用该地址的语句,可能需要指定端口或端口范围,也可能必须指定。

‘ipv6@<address>[:port1[-port2]]’ 在 <address> 之后始终被视为 IPv6 地址。根据使用此地址的语句,可能需要指定端口或端口范围,也可能必须指定。

‘sockpair@<n>’ 后跟的地址是已连接的 Unix 套接字或 socketpair 的文件描述符。在建立连接时,发起方创建一对已连接的套接字,并将其中一个文件描述符通过文件描述符传递给另一端。监听器等待从 Unix 套接字接收该文件描述符,并将其当作 accept() 返回的文件描述符使用。应谨慎使用。

           Bugs: This protocol is known to be unreliable on macOS because
           of an issue in the macOS sendmsg(2) implementation. The
           connection might not be accepted correctly.

‘unix@<path>’ 后跟的字符串被视为 Unix 套接字 <path>。此前缀可用于声明以斜杠 ‘/’ 以外字符开头的 Unix 套接字路径。

2.9.2. 套接字类型前缀

先前的“地址族前缀”也可附加以强制指定套接字类型和传输方法。默认值取决于使用该地址的语句,但在某些情况下用户可强制其采用其他类型。以 “log” 语句为例,其默认为通过 UDP 传输的 syslog,但可强制改为通过 TCP 传输的 syslog。

这些前缀专为内部用途设计,用户应改用下一节“2.9.3 协议前缀”中提供的别名。然而,在某些情况下,这些前缀也可能较为方便,例如与通过文件描述符编号识别的继承套接字配合使用时,此时地址族为 “fd”,且必须声明套接字类型。

如果用户需要使用这些前缀以实现预期行为,但无法通过协议前缀进行相同配置,则应向维护者报告此问题。

‘stream+<family>@<address>’ 强制指定套接字类型和传输方式为 “stream”

‘dgram+<family>@<address>’ 强制将套接字类型和传输方法设为 “datagram”。

‘quic+<family>@<address>’ 强制将套接字类型设为 “datagram”,传输方式设为 “stream”。

2.9.3. 协议前缀

‘quic4@<address>[:port1[-port2]]’ 中的 <address> 始终被视为 IPv4 地址,但套接字类型强制为 “datagram”,传输方式强制为 “stream”。根据使用该地址的语句,可能需要或必须指定 UDP 端口或端口范围。其效果等同于 “quic+ipv4@"。

‘quic6@<address>[:port1[-port2]]’ 中的 <address> 始终被视为 IPv6 地址,但套接字类型强制为 “datagram”,传输方式强制为 “stream”。根据使用该地址的语句,可能需要或必须指定 UDP 端口或端口范围。其效果等同于 “quic+ipv6@"。

’tcp@<address>[:port1[-port2]]’ 中的 <address> 被视为 IPv4 或 IPv6 地址,具体取决于语法,但套接字类型和传输方式强制为 “stream”。根据使用该地址的语句,可能需要或必须指定端口或端口范围。该地址被视为 ‘stream+ip@’ 的别名。

’tcp4@<address>[:port1[-port2]]’ 中的 <address> 始终被视为 IPv4 地址,但套接字类型和传输方式强制为 “stream”。根据使用此地址的语句,可能需要或必须指定端口或端口范围。该地址被视为 ‘stream+ipv4@’ 的别名。

’tcp6@<address>[:port1[-port2]]’ 中的 <address> 始终被视为 IPv6 地址,但套接字类型和传输方式强制为 “stream”。根据使用该地址的语句,可能需要或必须指定端口或端口范围。该地址被视为 ‘stream+ipv4@’ 的别名。

‘mptcp@<address>[:port1[-port2]]’ 依 <address> 的语法被视作 IPv4 或 IPv6 地址,但套接字类型和传输方式强制为 “stream”,使用 MPTCP 协议。根据使用该地址的语句,端口或端口范围可选或必须指定。

‘mptcp4@<address>[:port1[-port2]]’ 依附于 <address> 时始终被视为 IPv4 地址,但套接字类型和传输方式强制为 “stream”,使用 MPTCP 协议。根据使用此地址的语句,可能需要或必须指定端口或端口范围。

‘mptcp6@<address>[:port1[-port2]]’ 依附于 <address> 时始终被视为 IPv6 地址,但套接字类型和传输方式强制为 “stream”,使用 MPTCP 协议。根据使用该地址的语句,可能需要或必须指定端口或端口范围。

‘udp@<address>[:port1[-port2]]’ 中的 <address> 被视为 IPv4 或 IPv6 地址,具体取决于语法,但套接字类型和传输方式强制为 “datagram”。根据使用该地址的语句,可能需要指定端口或端口范围,也可能必须指定。该地址被视为 ‘dgram+ip@’ 的别名。

‘udp4@<address>[:port1[-port2]]’ 中,<address> 后始终被视为 IPv4 地址,但套接字类型和传输方式强制为 “datagram”。根据使用此地址的语句,可能需要或必须指定端口或端口范围。该地址被视为 ‘dgram+ipv4@’ 的别名。

‘udp6@<address>[:port1[-port2]]’ 中,<address> 后始终被视为 IPv6 地址,但套接字类型和传输方式强制为 “datagram”。根据使用该地址的语句,可能需要或必须指定端口或端口范围。该地址被视为 ‘dgram+ipv4@’ 的别名。

‘uxdg@<path>’ 后跟的字符串被视为 Unix 套接字 <path>,但传输方式被强制为 “datagram”。这被视为 ‘dgram+unix@’ 的别名。

‘uxst@<path>’ 后跟的字符串被视为 Unix 套接字 <path>,但传输方式被强制设为 “stream”。这被视为 ‘stream+unix@’ 的别名。

在后续版本中,可使用其他前缀来指定 QUIC 等协议,该协议基于类型为 “datagram” 的套接字提供流传输。

2.10. 示例

# Simple configuration for an HTTP proxy listening on port 80 on all
    # interfaces and forwarding requests to a single backend "servers" with a
    # single server "server1" listening on 127.0.0.1:8000
    global
        daemon
        maxconn 256

    defaults
        mode http
        timeout connect 5000ms
        timeout client 50000ms
        timeout server 50000ms

    frontend http-in
        bind *:80
        default_backend servers

    backend servers
        server server1 127.0.0.1:8000 maxconn 32


    # The same configuration defined with a single listen block. Shorter but
    # less expressive, especially in HTTP mode.
    global
        daemon
        maxconn 256

    defaults
        mode http
        timeout connect 5000ms
        timeout client 50000ms
        timeout server 50000ms

    listen http-in
        bind *:80
        server server1 127.0.0.1:8000 maxconn 32

假设 HAProxy 已在 $PATH 中,可在 shell 中执行以下测试:

$ sudo haproxy -f configuration.conf -c

12 - 3. 全局段

进程安全、性能调优、调试和 HTTP 客户端设置

“global” 段中的参数为进程级配置,通常与操作系统相关。这些参数通常只需一次性设置,一旦配置正确便无需再修改。部分参数在命令行中也有对应选项。

以下关键字在 “global” 段中受支持:

  • 进程管理与安全

    • 51degrees-allow-unmatched
    • 51degrees-cache-size
    • 51degrees-data-file
    • 51degrees-difference
    • 51degrees-drift
    • 51degrees-property-name-list
    • 51degrees-property-separator
    • 51degrees-use-performance-graph
    • 51degrees-use-predictive-graph
    • ca-base
    • chroot
    • cluster-secret
    • cpu-affinity
    • cpu-map
    • cpu-policy
    • cpu-set
    • crt-base
    • daemon
    • default-path
    • description
    • deviceatlas-json-file
    • deviceatlas-log-level
    • deviceatlas-properties-cookie
    • deviceatlas-separator
    • dns-accept-family
    • expose-deprecated-directives
    • expose-experimental-directives
    • external-check
    • fd-hard-limit
    • gid
    • grace
    • group
    • h1-accept-payload-with-any-method
    • h1-case-adjust
    • h1-case-adjust-file
    • h1-do-not-close-on-insecure-transfer-encoding
    • h2-workaround-bogus-websocket-clients
    • hard-stop-after
    • harden.reject-privileged-ports.tcp
    • harden.reject-privileged-ports.quic
    • insecure-fork-wanted
    • insecure-setuid-wanted
    • issuers-chain-path
    • jwt.decrypt_alg_list
    • jwt.decrypt_enc_list
    • key-base
    • limited-quic
    • localpeer
    • log
    • log-send-hostname
    • log-tag
    • lua-load
    • lua-load-per-thread
    • lua-prepend-path
    • max-threads-per-group
    • mworker-max-reloads
    • nbthread
    • node
    • numa-cpu-mapping
    • ocsp-update.disable
    • ocsp-update.maxdelay
    • ocsp-update.mindelay
    • ocsp-update.httpproxy
    • ocsp-update.mode
    • pidfile
    • pp2-never-send-local
    • presetenv
    • prealloc-fd
    • resetenv
    • set-dumpable
    • set-var
    • setenv
    • ssl-default-bind-ciphers
    • ssl-default-bind-ciphersuites
    • ssl-default-bind-client-sigalgs
    • ssl-default-bind-curves
    • ssl-default-bind-options
    • ssl-default-bind-sigalgs
    • ssl-default-server-ciphers
    • ssl-default-server-ciphersuites
    • ssl-default-server-client-sigalgs
    • ssl-default-server-curves
    • ssl-default-server-options
    • ssl-default-server-sigalgs
    • ssl-dh-param-file
    • ssl-propquery
    • ssl-provider
    • ssl-provider-path
    • ssl-security-level
    • ssl-server-verify
    • ssl-skip-self-issued-ca
    • stats
    • stats-file
    • strict-limits
    • uid
    • ulimit-n
    • unix-bind
    • unsetenv
    • user
    • wurfl-cache-size
    • wurfl-data-file
    • wurfl-information-list
    • wurfl-information-list-separator
  • 性能调优

    • busy-polling
    • max-spread-checks
    • maxcompcpuusage
    • maxcomprate
    • maxconn
    • maxconnrate
    • maxpipes
    • maxsessrate
    • maxsslconn
    • maxsslrate
    • maxzlibmem
    • no-memory-trimming
    • noepoll
    • noevports
    • nogetaddrinfo
    • nokqueue
    • noktls
    • nopoll
    • noreuseport
    • nosplice
    • profiling.memory
    • profiling.tasks
    • server-state-base
    • server-state-file
    • spread-checks
    • ssl-engine
    • ssl-mode-async
    • tune.applet.zero-copy-forwarding
    • tune.buffers.limit
    • tune.buffers.reserve
    • tune.bufsize
    • tune.bufsize.large
    • tune.bufsize.small
    • tune.cli.max-payload-size
    • tune.comp.maxlevel
    • tune.defaults.purge
    • tune.disable-fast-forward
    • tune.disable-zero-copy-forwarding
    • tune.epoll.mask-events
    • tune.events.max-events-at-once
    • tune.fail-alloc
    • tune.fd.edge-triggered
    • tune.h1.be.glitches-threshold
    • tune.h1.fe.glitches-threshold
    • tune.h1.zero-copy-fwd-recv
    • tune.h1.zero-copy-fwd-send
    • tune.h2.be.glitches-threshold
    • tune.h2.be.initial-window-size
    • tune.h2.be.max-concurrent-streams
    • tune.h2.be.max-frames-at-once
    • tune.h2.be.rxbuf
    • tune.h2.fe.glitches-threshold
    • tune.h2.fe.initial-window-size
    • tune.h2.fe.max-concurrent-streams
    • tune.h2.fe.max-frames-at-once
    • tune.h2.fe.max-rst-at-once
    • tune.h2.fe.max-total-streams
    • tune.h2.fe.rxbuf
    • tune.h2.header-table-size
    • tune.h2.initial-window-size
    • tune.h2.max-concurrent-streams
    • tune.h2.max-frame-size
    • tune.h2.zero-copy-fwd-send
    • tune.http.cookielen
    • tune.http.logurilen
    • tune.http.maxhdr
    • tune.idle-pool.shared
    • tune.idletimer
    • tune.lua.bool-sample-conversion
    • tune.lua.burst-timeout
    • tune.lua.forced-yield
    • tune.lua.log.loggers
    • tune.lua.log.stderr
    • tune.lua.maxmem
    • tune.lua.openlibs
    • tune.lua.service-timeout
    • tune.lua.session-timeout
    • tune.lua.task-timeout
    • tune.max-checks-per-thread
    • tune.maxaccept
    • tune.maxpollevents
    • tune.maxrewrite
    • tune.max-rules-at-once
    • tune.memory.hot-size
    • tune.pattern.cache-size
    • tune.peers.max-updates-at-once
    • tune.pipesize
    • tune.pool-high-fd-ratio
    • tune.pool-low-fd-ratio
    • tune.pt.zero-copy-forwarding
    • tune.quic.be.cc.cubic-min-losses
    • tune.quic.be.cc.hystart
    • tune.quic.be.cc.max-frame-loss
    • tune.quic.be.cc.max-win-size
    • tune.quic.be.cc.reorder-ratio
    • tune.quic.be.max-idle-timeout
    • tune.quic.be.sec.glitches-threshold
    • tune.quic.be.stream.data-ratio
    • tune.quic.be.stream.max-concurrent
    • tune.quic.be.stream.rxbuf
    • tune.quic.be.tx.pacing
    • tune.quic.be.tx.udp-gso
    • tune.quic.cc.cubic.min-losses (已弃用)
    • tune.quic.cc-hystart (已弃用)
    • tune.quic.disable-tx-pacing (已弃用)
    • tune.quic.disable-udp-gso (已弃用)
    • tune.quic.fe.cc.cubic-min-losses
    • tune.quic.fe.cc.hystart
    • tune.quic.fe.cc.max-frame-loss
    • tune.quic.fe.cc.max-win-size
    • tune.quic.fe.cc.reorder-ratio
    • tune.quic.fe.max-idle-timeout
    • tune.quic.fe.sec.glitches-threshold
    • tune.quic.fe.sec.retry-threshold
    • tune.quic.fe.sock-per-conn
    • tune.quic.fe.stream.data-ratio
    • tune.quic.fe.stream.max-concurrent
    • tune.quic.fe.stream.max-total
    • tune.quic.fe.stream.rxbuf
    • tune.quic.fe.tx.pacing
    • tune.quic.fe.tx.udp-gso
    • tune.quic.frontend.max-data-size (已弃用)
    • tune.quic.frontend.max-idle-timeout (已弃用)
    • tune.quic.frontend.max-streams-bidi (已弃用)
    • tune.quic.frontend.max-tx-mem (已弃用)
    • tune.quic.frontend.stream-data-ratio (已弃用)
    • tune.quic.frontend.default-max-window-size (已弃用)
    • tune.quic.listen
    • tune.quic.max-frame-loss (已弃用)
    • tune.quic.mem.tx-max
    • tune.quic.reorder-ratio (已弃用)
    • tune.quic.retry-threshold (已弃用)
    • tune.quic.socket-owner (已弃用)
    • tune.quic.zero-copy-fwd-send
    • tune.renice.runtime
    • tune.renice.startup
    • tune.rcvbuf.backend
    • tune.rcvbuf.client
    • tune.rcvbuf.frontend
    • tune.rcvbuf.server
    • tune.recv_enough
    • tune.ring.queues
    • tune.runqueue-depth
    • tune.sched.low-latency
    • tune.sndbuf.backend
    • tune.sndbuf.client
    • tune.sndbuf.frontend
    • tune.sndbuf.server
    • tune.streams-elasticity
    • tune.stick-counters
    • tune.ssl.cachesize
    • tune.ssl.capture-buffer-size
    • tune.ssl.capture-cipherlist-size (已弃用)
    • tune.ssl.certificate-compression
    • tune.ssl.default-dh-param
    • tune.ssl.force-private-cache
    • tune.ssl.hard-maxrecord
    • tune.ssl.keylog
    • tune.ssl.keyupdate-rate-limit
    • tune.ssl.lifetime
    • tune.ssl.maxrecord
    • tune.ssl.ssl-ctx-cache-size
    • tune.ssl.ocsp-update.maxdelay (已弃用)
    • tune.ssl.ocsp-update.mindelay (已弃用)
    • tune.takeover-other-tg-connections
    • tune.vars.global-max-size
    • tune.vars.proc-max-size
    • tune.vars.reqres-max-size
    • tune.vars.sess-max-size
    • tune.vars.txn-max-size
    • tune.zlib.memlevel
    • tune.zlib.windowsize
  • 调试

    • anonkey
    • debug.counters
    • force-cfg-parser-pause
    • quiet
    • warn-blocked-traffic-after
    • zero-warning
  • HTTPClient

    • httpclient.resolvers.disabled
    • httpclient.resolvers.id
    • httpclient.resolvers.prefer
    • httpclient.retries
    • httpclient.ssl.ca-file
    • httpclient.ssl.verify
    • httpclient.timeout.connect

3.1. 进程管理与安全

51degrees-data-file <file path>

51degrees-data-file <file path>

用于提供设备检测服务的 51Degrees 数据文件路径。该文件应已解压,并可由 HAProxy 以相应权限访问。

请注意,此选项仅在 HAProxy 编译时包含 USE_51DEGREES 时可用。

51degrees-property-name-list [<string> ...]

51degrees-property-name-list [<string> ...]

要从数据集加载的 51Degrees 属性名称列表。完整名称列表可在 51Degrees 官网获取:https://51degrees.com/resources/property-dictionary

请注意,此选项仅在 HAProxy 编译时包含 USE_51DEGREES 时可用。

51degrees-property-separator <char>

51degrees-property-separator <char>

在包含 51Degrees 结果的响应头中,每个属性值后将追加一个字符。若未设置,则默认为“,”。

请注意,此选项仅在 HAProxy 编译时包含 USE_51DEGREES 时可用。

51degrees-cache-size <number>

51degrees-cache-size <number>

设置 51Degrees 转换器缓存的大小为 <number> 项。该缓存为 LRU 缓存,用于保留之前的设备检测及其结果。默认情况下,此缓存处于禁用状态。

请注意,此选项仅在 HAProxy 编译时包含 USE_51DEGREES 时可用。

51degrees-use-performance-graph { on | off }

51degrees-use-performance-graph { on | off }

启用(‘on’)或禁用(‘off’)检测过程中对性能图的使用。默认值取决于 51Degrees 库。

请注意,此选项仅在 HAProxy 使用 USE_51DEGREES 和 51DEGREES_VER=4 编译时可用。

51degrees-use-predictive-graph { on | off }

51degrees-use-predictive-graph { on | off }

启用(‘on’)或禁用(‘off’)检测过程中对预测图的使用。默认值取决于 51Degrees 库。

请注意,此选项仅在 HAProxy 使用 USE_51DEGREES 和 51DEGREES_VER=4 编译时可用。

51degrees-drift <number>

51degrees-drift <number>

设置检测允许的漂移值。

请注意,此选项仅在 HAProxy 使用 USE_51DEGREES 和 51DEGREES_VER=4 编译时可用。

51degrees-difference <number>

51degrees-difference <number>

设置检测可允许的差异值。

请注意,此选项仅在 HAProxy 使用 USE_51DEGREES 和 51DEGREES_VER=4 编译时可用。

51degrees-allow-unmatched { on | off }

51degrees-allow-unmatched { on | off }

启用(‘on’)或禁用(‘off’)检测过程中使用未匹配节点。默认值取决于 51Degrees 库。

请注意,此选项仅在 HAProxy 使用 USE_51DEGREES 和 51DEGREES_VER=4 编译时可用。

acme.scheduler { auto | off }

acme.scheduler { auto | off }

启用或禁用 ACME 调度器。

ACME 调度器在 HAProxy 启动时开始运行,它将遍历所有证书,并在 notAfter 值超过当前时间加上 (notAfter - notBefore) / 12 时启动 ACME 证书续订任务;若 notBefore 未定义,则使用 7 天作为阈值。调度器随后将休眠,并在 12 小时后唤醒。

默认值为 “auto”。

另请参阅:acme

ca-base <dir>

ca-base <dir>

为当使用相对路径时,指定从何处获取 SSL CA 证书和 CRL 的默认目录,该目录适用于 “ca-file”、“ca-verify-file” 或 “crl-file” 指令。在 “ca-file”、“ca-verify-file” 和 “crl-file” 中指定的绝对路径具有优先权,并忽略 “ca-base”。

chroot { <jail dir> | auto }

chroot { <jail dir> | auto }

将当前目录切换至 <jail dir>,并在降权前在此处执行 chroot() 操作。 若存在未知漏洞被利用,此操作可显著提升安全性,使攻击者难以进一步利用系统。 必须确保 <jail dir> 对任何用户均为空且不可写。 当以超级用户权限启动进程时,将直接执行 chroot()。 在 Linux 系统上,若以非特权身份启动,HAProxy 会尝试通过 unshare(CLONE_NEWUSER) 创建的新用户命名空间内执行 chroot();若该机制不可用,chroot() 将以常规错误失败。

作为特殊情况,<jail dir> 可设置为 “auto”,此时 HAProxy 会创建一个匿名临时目录,将其删除,并 chroot 进入该目录。resulting jail 在文件系统中无名称,且为空且只读,从而无需预先准备专用的 jail 目录。

以超级用户权限启动时,若未使用 chroot,将显示警告信息,以鼓励用户始终使用该机制。若因特定原因必须不使用 chroot(例如通过路径不便的 Unix 套接字访问服务器),仍可通过显式添加 “chroot /” 来静默警告,此举的优点在于配置中可见。

close-spread-time <time>

close-spread-time <time>

在执行软停止时,定义一个时间窗口,用于分散空闲连接的关闭以及活跃连接的关闭过程。接收到 SIGUSR1 信号且宽限期(如有)结束后,若未设置此选项,所有空闲连接将立即全部关闭;而活跃的 HTTP 或 HTTP2 连接将在收到下一个请求后结束,方法是向 HTTP 响应中添加 “Connection: close” 头,或在 HTTP2 情况下发送 GOAWAY 帧。当设置此选项时,连接关闭将在此设定的 <time> 时间内逐步进行。若将 close-spread-time 设置为 “infinite”,则在软停止期间将禁用活跃连接的逐步关闭。HTTP 响应中将不再添加 “Connection: close” 头(HTTP2 亦不再发送 GOAWAY 帧),空闲连接仅在达到其超时时间后才会关闭(基于配置中设置的各种超时参数)。

参数:

<time>  is a time window (by default in milliseconds) during which
        connection closing will be spread during a soft-stop operation, or
        "infinite" if active connection closing should be disabled.

建议将此设置的值设为低于“hard-stop-after”选项所用值,以便在进程停止前,所有连接都有机会优雅关闭。

另请参阅:grace、hard-stop-after、idle-close-on-response

cluster-secret <secret>

cluster-secret <secret>

定义一个由同一集群中多个节点共享的 ASCII 字符串密钥。该密钥可用于多种用途。它至少用于为本进程创建的所有 QUIC 连接派生无状态重置令牌。同样,该密钥也用于派生用于加密重试令牌的密钥。

如果未设置此参数,进程启动时将随机选择一个值。这允许使用依赖该值的功能,尽管存在一些限制。

cpu-map [auto:]<thread-group>[/<thread-set>] <cpu-set>[,...] [...]

cpu-map [auto:]<thread-group>[/<thread-set>] <cpu-set>[,...] [...]

在某些操作系统上,可以将线程组或线程绑定到特定的 CPU 集。 这意味着指定的线程将始终仅在指定的 CPU 上运行。“cpu-map” 指令用于为单个线程或线程组指定 CPU 集。第一个参数为线程组范围,可选地后接线程集。这些范围的格式如下:

all | odd | even | number[-[number]]

<number> 必须是 1 到 32 或 64 之间的数字,具体取决于机器的字长。高于 ’thread-groups’ 的组 ID 以及超过机器字长的线程 ID 均被忽略。所有线程编号均相对于其所归属的组。可以使用连字符(’-’)分隔两个数字来指定一个范围。也可以使用 “all” 一次性指定所有线程,使用 “odd” 指定奇数线程,或使用 “even” 指定偶数线程,与 “thread” 绑定指令的用法一致。第二个及后续参数为 CPU 集合。每个 CPU 集合要么是起始于 0 的唯一编号(对应第一个 CPU),要么是两个此类编号之间用连字符(’-’)分隔的范围。这些 CPU 编号和范围可通过用逗号分隔或在同一条指令行中添加更多范围来重复指定。在 Linux 和 BSD 以外的操作系统中,最大 CPU 索引可能受限于 31 或 63。可以指定多个 “cpu-map” 指令,但当它们发生重叠时,后续的 “cpu-map” 指令将替换之前的指令。

范围可以部分定义。若省略上限,则用对应的最大值代替,该值为 32 或 64,具体取决于机器的字长。

在线程集前添加前缀 “auto:",可让 HAProxy 自动通过递增线程和 CPU 集的方式将一组线程绑定到 CPU。该配置有效需满足两个集合的大小相同。无论 CPU 集声明顺序如何,绑定将从最低编号到最高编号依次进行。不支持同时使用带有 “auto:” 前缀的组和线程范围。仅支持一个范围,另一个必须为固定数值。

请注意,组范围仅出于历史原因而受支持。如今,单独的数字表示一个线程组,若未使用线程组,则该数字必须为 1;若指定线程范围或数字,且未使用线程组,则必须在前面加上 “1/"。最后,“1” 严格等同于 “1/all”,表示该组中的所有线程。

示例:

cpu-map 1/all 0-3 # bind all threads of the first group on the
                  # first 4 CPUs

cpu-map 1/1- 0-   # will be replaced by "cpu-map 1/1-64 0-63"
                  # or "cpu-map 1/1-32 0-31" depending on the machine's
                  # word size.

# all these lines bind thread 1 to the cpu 0, the thread 2 to cpu 1
# and so on.
cpu-map auto:1/1-4   0-3
cpu-map auto:1/1-4   0-1 2-3
cpu-map auto:1/1-4   3 2 1 0
cpu-map auto:1/1-4   3,2,1,0

# bind each thread to exactly one CPU using all/odd/even keyword
cpu-map auto:1/all   0-63
cpu-map auto:1/even  0-31
cpu-map auto:1/odd   32-63

# invalid cpu-map because thread and CPU sets have different sizes.
cpu-map auto:1/1-4   0    # invalid
cpu-map auto:1/1     0-3  # invalid

# map 40 threads of those 4 groups to individual CPUs
cpu-map auto:1/1-10   0-9
cpu-map auto:2/1-10   10-19
cpu-map auto:3/1-10   20-29
cpu-map auto:4/1-10   30-39

# Map 80 threads to one physical socket and 80 others to another socket
# without forcing assignment. These are split into 4 groups since no
# group may have more than 64 threads.
cpu-map 1/1-40   0-39,80-119    # node0, siblings 0 & 1
cpu-map 2/1-40   0-39,80-119
cpu-map 3/1-40   40-79,120-159  # node1, siblings 0 & 1
cpu-map 4/1-40   40-79,120-159

cpu-affinity <affinity>

cpu-affinity <affinity>

定义线程与 CPU 的绑定方式。当前支持以下取值:

  • per-core:每个线程将绑定到单个核心的所有硬件线程。
  • per-group:每个线程将绑定到该组的所有硬件线程。除非在 “cpu-policy” 中使用了 “threads-per-core 1”,否则这是默认设置。“per-group” 接受一个可选参数,用于指定如何分配 CPU。当 CPU 列表的大小超过每组允许的最大 CPU 数量,需在多个组之间拆分时,额外选项允许选择组如何绑定到这些 CPU:
    • auto:每个线程组仅被分配其专属的、连续的 CPU 核心,且不与其他组共享。这是默认选项,通常更优。
    • loose:每个组仍可使用列表中的任意 CPU。这通常导致更高的竞争,但在某些情况下有助于更好地应对运行在相同 CPU 上的寄生负载。
  • auto:“per-group” 将被使用,除非在 “cpu-policy” 中使用了 “threads-per-core 1”,此时将使用 “per-core”。这是默认设置。
  • per-thread:每个线程仅绑定到一个硬件线程。如果在 “cpu-policy” 中使用了 “threads-per-core 1”,则每个线程将绑定到不同核心的一个硬件线程。
  • per-ccx:每个线程将绑定到一个 CCX 的所有硬件线程。

cpu-policy <policy> [threads-per-core 1 | auto]

cpu-policy <policy> [threads-per-core 1 | auto]

选择要使用的 CPU 分配策略。

在多 CPU 系统中,存在多种原因可能导致未使用全部可用的 CPU 核心,或需要将核心分组为不同的线程组,以实现性能、延迟、成本或系统级资源管理的优化。虽然“cpu-set”指令已支持排除部分核心,但完成此操作后,仍需决定如何将剩余核心分配给线程及线程组。

该映射通常通过 “cpu-map” 指令完成,但在异构系统上维护可能尤为困难。

“cpu-policy” 指令用于在未使用 “cpu-map” 时,选择一组有限的分配策略之一。当前支持以下策略,默认策略为 “performance”:

  • none 不执行特定的后选择操作。所有启用的 CPU 均可使用;若未设置线程数,将自动设为可用 CPU 数量,但每线程组最多不超过 32 个(32 位系统)或 64 个(64 位系统)。若未设置线程组数量,将设为 1。

  • 效率与下方的 “group-by-ccx” 完全相同,但会剔除性能高于下一个性能较低核心 25% 以上的 CPU 核心集群。这些通常是“大”核或“性能”核。这意味着,若检测到多种类型的 CPU 核心,仅会使用高效的核心。在中等负载下,这种策略可能有意义,以便为应用程序或安全组件保留最强大的核心。一些现代 CPU 拥有大量此类高效核心,它们可协同提供可观的性能,同时功耗更低。

  • first-usable-node:若 CPU 未在启动时被限制(例如使用 “taskset” 工具),且未设置 “nbthread” 指令,则将使用首个启用 CPU 的 NUMA 节点,并以此节点的 CPU 数量作为线程数。将启用单个线程组,包含全部线程,上限为 32 或 64,具体取决于系统。

  • group-by-2-ccx:与下方的 “group-by-ccx” 相同,但每两个 CCX 创建一个组。当 CPU 拥有多个 CCX 且每个 CCX 的核心数量较少时,此选项可能有意义,可避免创建过多组,或在并非所有核心均被使用时略微平滑负载分布。请注意,当 CCX 间通信较慢时,可能产生极差的性能影响。通常不建议使用。

  • group-by-2-clusters:与 “group-by-cluster” 相同,但每两个集群创建一个组。在每个 CPU 包含多个核心数量较少的集群时,此选项可能有意义,可避免创建过多组,或在并非所有核心均被使用时略微平滑分布。请注意,当集群间通信速度较慢时,可能导致性能显著下降。通常不建议使用。

  • group-by-3-ccx:与下方的 “group-by-ccx” 相同,但每三个 CCX 创建一个组。在每个 CCX 核心数量较少的多 CCX CPU 上,这可以避免创建过多组,或在并非所有核心均被使用时略微平滑负载分布。请注意,当 CCX 间通信较慢时,可能产生极差的性能影响。通常不建议使用。

  • group-by-3-clusters:与 “group-by-cluster” 相同,但每三个集群创建一个组。在每个集群包含少量核心的 CPU 上,此选项可避免创建过多组,或在并非所有核心均被使用时略微平滑负载分布。请注意,当集群间通信速度较慢时,可能产生极差的性能影响。通常不建议使用。

  • group-by-4-ccx:与下方的 “group-by-ccx” 相同,但每四个 CCX 创建一个组。当 CPU 拥有多个 CCX 且每个 CCX 核心数量较少时,此选项可避免创建过多组,或在并非所有核心均被使用时略微平滑负载分布。请注意,当 CCX 间通信较慢时,可能产生极差的性能影响。通常不建议使用。

  • group-by-4-clusters:与 “group-by-cluster” 相同,但每四个集群创建一个组。在每个集群包含少量核心的多集群 CPU 上,这可能有意义,以避免创建过多组,或在并非所有核心均被使用时略微平滑分布。请注意,当集群间通信较慢时,可能导致性能显著下降。通常不建议使用。

  • group-by-ccx:若未设置 “nbthread” 或 “nbtgroups”,则为每个拥有可用 CPU 的 CPU 核心复合体(“CCX”)创建一个线程组,每个线程组包含的线程数与该 CCX 中的 CPU 数量相同。CCX 将具有类似快速访问最后一级缓存(“LLC”,通常为 L3 缓存)的 CPU 组合在一起。在大多数现代机器上,性能至关重要,不应将来自不同 CCX 的 CPU 混合在同一个线程组中。随后,每个线程组的所有线程将绑定到该 CCX 的所有 CPU,以确保组内通信始终局限于 CCX 内部,同时避免强制过强的绑定。每个线程组的线程数限制和线程组数量限制均会被遵守。此配置在多路处理器和 NUMA 系统上,以及具有较差跨 CCX 延迟的 CPU 上被推荐使用。

  • group-by-cluster:若未设置 “nbthread” 或 “nbtgroups”,则为每个拥有可用 CPU 的 CPU 集群创建一个线程组,每个线程组包含的线程数与该集群的 CPU 数量相同。线程组内的所有线程均绑定到该集群的所有 CPU,以确保组内通信保持在集群内部,同时避免强制过强的绑定。将尊重每个线程组的线程数限制和线程组限制。在多路处理器和 NUMA 系统上,以及存在较差跨 CCX 延迟的 CPU 上,建议使用此配置。在大多数服务器设备中,集群与 CCX 相同,但在异构机器(如“性能”型与“效率”型,或“大核”与“小核”)上,集群通常仅由 CCX 的一部分组成,且该部分仅包含类型相同、频率差异最大不超过 -5% 的 CPU。这一差异在现代开发人员和管理员用于验证配置的笔记本电脑和台式机上尤为明显。

  • 性能表现与上述 “group-by-ccx” 完全一致,但会剔除由性能低于下一个更高效核心 80% 的核心组成的 CPU 集群。这类核心通常为“小核”或“高效核”,其加入通常无法带来显著性能提升,反而可能产生反效果(例如 TLS 握手)。通常情况下,将此类核心保留用于网络处理等其他任务更为有效。在开发系统中,也可用于运行辅助工具,如负载生成器和监控工具。这是默认策略。

  • resource 此项类似于上述的 “group-by-cluster”,但仅使用最小且最高效的 CPU 集群,其余集群将被忽略。此选项可用于将资源使用量限制在仍能提供良好性能的最低水平,例如用于进一步降低功耗,或在某些租用系统中减少 sidecar 部署所需的内核数量,以便更轻松地缩减系统规模。请注意,若仅存在单一集群,该集群仍会被完全使用。

可选关键字 “threads-per-core” 可被添加。该关键字可接受两个值:“1” 和 “auto”。若设置为 “1”,则每个核心仅创建一个线程,无论该核心具有多少个硬件线程。若设置为 “auto”,则每个硬件线程将创建一个线程。若未指定亲和性,且使用 threads-per-core 1,则默认亲和性为按核心。

另请参阅: “cpu-map”、“cpu-set”、“nbthread”

cpu-set <directive>...

cpu-set <directive>...

允许以符号方式描述运行的 CPU 集合。该指令支持以下关键字: - reset:重置,取消任何先前可能由服务管理器或 “taskset” 命令等继承的限制。 - drop-cpu <set>:不绑定到该集合中的 CPU。 - only-cpu <set>:不绑定到该集合外的 CPU。 - drop-node <set>:不绑定到该 NUMA 节点中的 CPU。 - only-node <set>:不绑定到不属于该 NUMA 节点的 CPU。 - drop-cluster <set>:不绑定到该硬件集群编号的 CPU。 - only-cluster <set>:不绑定到其他硬件集群编号的 CPU。 - drop-core <set>:不绑定到该硬件核心编号的 CPU。 - only-core <set>:不绑定到其他硬件核心编号的 CPU。 - drop-thread <set>:不绑定到该硬件线程编号的 CPU。 - only-thread <set>:不绑定到其他硬件线程编号的 CPU。

另请参阅:“cpu-policy”

crt-base <dir>

crt-base <dir>

当使用 crtfile 或 crt 指令并指定相对路径时,指定用于获取 SSL 证书的默认目录。绝对路径配置优先,且会忽略 crt-base。

daemon

daemon

使进程在后台运行。这是推荐的运行模式。其效果等同于命令行参数 “-D”。可通过命令行参数 “-db” 禁用。在 systemd 模式下,此选项将被忽略。

default-path { current | config | parent | origin <path> }

default-path { current | config | parent | origin <path> }

默认情况下,HAProxy 会从进程启动位置加载所有由相对路径指定的文件。在某些情况下,可能需要强制所有相对路径从另一个位置开始,如同进程从该位置启动一般。此指令即为此目的而设计。技术上,HAProxy 在处理每个配置文件期间,会临时将工作目录切换至指定位置,处理完成后返回原始目录。该指令接收一个参数,用于指定加载路径不以斜杠(’/’)开头的文件时所采用的策略:- “current” 表示所有相对路径文件均从进程启动目录加载;这是默认行为。

- "config" indicates that all relative files should be loaded from the
  directory containing the configuration file. More specifically, if the
  configuration file contains a slash ('/'), the longest part up to the
  last slash is used as the directory to change to, otherwise the current
  directory is used. This mode is convenient to bundle maps, errorfiles,
  certificates and Lua scripts together as relocatable packages. When
  multiple configuration files are loaded, the directory is updated for
  each of them.

- "parent" indicates that all relative files should be loaded from the
  parent of the directory containing the configuration file. More
  specifically, if the configuration file contains a slash ('/'), ".."
  is appended to the longest part up to the last slash is used as the
  directory to change to, otherwise the directory is "..". This mode is
  convenient to bundle maps, errorfiles,  certificates and Lua scripts
  together as relocatable packages, but where each part is located in a
  different subdirectory (e.g. "config/", "certs/", "maps/", ...).

- "origin" indicates that all relative files should be loaded from the
  designated (mandatory) path. This may be used to ease management of
  different HAProxy instances running in parallel on a system, where each
  instance uses a different prefix but where the rest of the sections are
  made easily relocatable.

每个 “default-path” 指令会立即替换之前的指令,并可能导致切换到不同的目录。虽然这通常能产生预期的行为,但使用多个 default-path 指令并非良好实践;若确实使用,应确保所有配置文件中的策略保持一致。

请注意:某些配置元素(如映射或证书)通过其配置路径进行唯一标识。采用可重定位布局后,多个元素可能产生相同的唯一名称,导致运行时更新变得困难,尤其是在从不同目录加载多个配置文件时。在采用相对路径之前,必须遵循严格的无冲突文件命名方案。一种稳健的做法是为所有文件名添加各自的站点名称前缀,或在目录级别实施该策略。

description <text>

description <text>

添加一段描述实例的文本。

请注意,必须转义某些字符(例如 #),且该文本将插入 HTML 页面,因此应避免使用 “<” 和 “>” 字符。

deviceatlas-json-file <path>

deviceatlas-json-file <path>

设置 API 加载的 DeviceAtlas JSON 数据文件路径。路径必须指向一个有效的 JSON 数据文件,且 HAProxy 进程可访问。

deviceatlas-log-level <value>

deviceatlas-log-level <value>

设置 API 返回信息的级别。该指令为可选指令,若未设置,默认值为 0。

deviceatlas-properties-cookie <name>

deviceatlas-properties-cookie <name>

设置用于检测请求期间是否使用了 DeviceAtlas 客户端组件的客户端 Cookie 名称。该指令为可选指令,若未设置,默认值为 DAPROPS。

deviceatlas-separator <char>

deviceatlas-separator <char>

设置 API 属性结果的字符分隔符。该指令为可选指令,若未设置,默认值为 |。

dns-accept-family <family>[,...]

dns-accept-family <family>[,...]

默认情况下,DNS 解析器接受 IPv4 和 IPv6 地址。这一行为可通过服务器行上的 “resolve-prefer” 关键字以及 “do-resolve” 动作的 family 参数进行影响,但这些仅表示偏好,不会阻止在仅存在一种地址族时使用另一种。在某些双栈不可用的环境中,遇到仅支持 IPv6 的不可达 DNS 记录可能导致严重问题,因为它会替换此前可能仍可正常工作的 IPv4 记录,直至下一次请求才可能恢复。全局选项 “dns-accept-family” 允许强制仅使用一种(或两种)地址族。该参数为以下单词的逗号分隔列表:- “ipv4”:查询并接受 IPv4 地址(“A” 记录) - “ipv6”:查询并接受 IPv6 地址(“AAAA” 记录) - “auto”:优先使用 IPv4,若系统存在默认网关则同时使用 IPv6。最后一次检查结果将被缓存 30 秒。

当仅使用单一地址族时,不会向解析器发送其他地址族的请求,且任何来自其他地址族的响应都将被忽略。自 3.3 版本起,默认值为 “auto”,该值在确认 IPv6 可路由后,会自动启用两个地址族;否则将仅使用 IPv4。另请参见:“resolve-prefer”、“do-resolve”

expose-deprecated-directives

expose-deprecated-directives

此语句必须在使用某些标记为已弃用的指令之前出现,以消除警告并确保配置文件不会被拒绝。并非所有已弃用的指令都受此影响,仅限于没有替代解决方案的指令。

expose-experimental-directives

expose-experimental-directives

此指令必须在使用标记为实验性的指令之前出现,否则配置文件将被拒绝。请注意,受此选项涵盖的功能无法保证运行良好,可能在维护周期内发生中断。在下一个版本开发期间,开发者将以尽力而为的方式维护这些功能,并会采取合理措施避免其中断,但不作任何保证。因此,这些功能预期不会在下一个 LTS 版本发布后继续得到支持。希望尝试实验性功能的用户应尽快升级,以受益于该功能的改进。要判断此指令是否仍有必要,方法很简单:若该指令已启用但未被任何此类功能使用,系统将发出警告,建议将其关闭。因此,若无任何警告,则说明该指令仍需保留。

external-check [preserve-env]

external-check [preserve-env]

允许使用外部代理执行健康检查。出于安全考虑,默认情况下此功能已禁用。即使启用,若未同时启用“insecure-fork-wanted”,健康检查仍可能失败。如果所启动的程序使用了 setuid 可执行文件(这应避免),还可能需要在全局段中设置“insecure-setuid-wanted”。默认情况下,健康检查以干净环境启动,仅包含后端段中“external-check”命令定义的变量。在某些情况下,保留环境变量可能是有益的,例如当复杂脚本从环境中获取额外路径或信息时。可通过附加“preserve-env”关键字实现此目的。但在此情况下,强烈建议不要以 setuid 方式运行或以特权用户身份运行,以免检查程序暴露于潜在攻击。详见“option external-check”、“insecure-fork-wanted”和“insecure-setuid-wanted”获取更多细节。

fd-hard-limit <number>

fd-hard-limit <number>

设置进程所使用的文件描述符数量的上限,该上限不受系统限制的影响。尽管可使用 “ulimit-n” 和 “maxconn” 来强制设定值,但当二者未设置时,进程将受限于由 “ulimit -n -H” 报告的 RLIMIT_NOFILE 硬限制。然而,一些现代操作系统现在允许在此处设置极高的数值(高达十亿量级),这将导致常规使用场景下消耗过多内存。为此提供了 fd-hard-limit 设置,用于强制设定该限制的可能下限。这意味着当系统施加的限制低于 <number> 时,将始终尊重系统限制;而当系统限制高于该值时,则使用指定的值。默认情况下,fd-hard-limit 设置为 1048576。该默认值可通过 DEFAULT_MAXFD 编译时变量进行修改,若 RLIMIT_NOFILE 硬限制极高,该变量可作为最大(内核)系统限制。在全局段中设置的 fd-hard-limit 可临时覆盖通过 DEFAULT_MAXFD 构建时提供的值。在以下示例中,未指定其他设置,maxconn 值将自动适应 “fd-hard-limit” 与 RLIMIT_NOFILE 限制中的较低者:

global
    # use as many FDs as possible but no more than 50000
    fd-hard-limit 50000

另请参阅:ulimit-n、maxconn

gid <number>

gid <number>

将进程的组 ID 更改为 <number>。建议该组 ID 专用于 HAProxy 或少量相似的守护进程。HAProxy 必须以属于该组的用户身份启动,或以超级用户权限启动。请注意,若 HAProxy 从具有附加组的用户启动,则仅当以超级用户权限启动时,才能移除这些附加组。另请参见“group”和“uid”。

grace <time>

grace <time>

定义 SIGUSR1 与实际软停止之间的延迟。

参数:

<time>  is an extra delay (by default in milliseconds) after receipt of the
        SIGUSR1 signal that will be waited for before proceeding with the
        soft-stop operation.

用于与旧式环境兼容,即在需要停止 HAProxy 进程时,某些外部组件需在监听器解除绑定前检测其状态。其原理是,内部“停止中”变量(由“stopping”样本提取函数报告)将被设为 true,但监听器将继续正常接收连接,直至延迟期结束,之后才执行常规的优雅停止。此机制不得与需要重载的进程一同使用,否则可能导致旧进程无法解除绑定,也可能阻止新进程启动,或引发其他问题。

示例:

global
  grace 10s

# Returns 200 OK until stopping is set via SIGUSR1
frontend ext-check
  bind:9999
  monitor-uri /ext-check
  monitor fail if { stopping }

请注意,更灵活且持久的方法是,由编排系统通过 CLI 设置全局变量,使用该变量响应外部检查,延迟后发送 SIGUSR1 信号。

示例:

# Returns 200 OK until proc.stopping is set to non-zero. May be done
# from HTTP using set-var(proc.stopping) or from the CLI using:
# > set var proc.stopping int(1)
frontend ext-check
  bind:9999
  monitor-uri /ext-check
  monitor fail if { var(proc.stopping) -m int gt 0 }

另请参阅:hard-stop-after、monitor

group <group name>

group <group name>

与 “gid” 类似,但使用来自 /etc/group. 的组名 <group name> 的 GID。另请参阅 “gid” 和 “user”。

h1-accept-payload-with-any-method

h1-accept-payload-with-any-method

不拒绝携带有效载荷的 HTTP/1.0 GET/HEAD/DELETE 请求,不返回 413 Payload Too Large HTTP 响应。

尽管 HTTP/1.1 明确允许,但 HTTP/1.0 在此问题上表述不清,部分旧版服务器不期望存在有效载荷,且从不检查正文长度(通过 Content-Length 或 Transfer-Encoding 头)。这意味着某些中间设备可能正确处理 HTTP/1.0 的 GET/HEAD/DELETE 请求的有效载荷,而另一些则可能完全忽略。这可能导致安全问题,因为存在请求走私攻击的风险。因此,默认情况下,HAProxy 会拒绝带有有效载荷的 HTTP/1.0 GET/HEAD/DELETE 请求。

然而,某些旧版客户端可能存在兼容性问题。在此情况下,可设置此全局选项。

h1-do-not-close-on-insecure-transfer-encoding

h1-do-not-close-on-insecure-transfer-encoding

根据 HTTP/1.1 规范(RFC9112#6.1)规定,若同一消息中同时存在 Transfer-Encoding 头字段和 Content-Length 头字段,则当上游或下游链路中存在任何 HTTP/1.0 代理时,可能引发内容走私攻击,此时代理必须在响应后绝对关闭连接,以防止被利用。但此行为可能对某些非常老旧的客户端造成性能影响,尤其是当它们需为每个请求重新协商 TLS 连接时。该选项用于指示 HAProxy 不强制执行此规则,仅对消息进行净化处理,响应后保持连接存活。此操作仅在完全确定链路中不存在任何 HTTP/1.0 代理,且 HAProxy 之前的所有实现均完全符合 HTTP/1.1 规范中关于这些头字段的规则时方可进行。无论如何,HAProxy 仍将继续忽略并丢弃多余的 Content-Length 头,以避免对下一跳造成混淆。

当启用此选项以绕过旧版存在缺陷的客户端或服务器时,必须理解,无论是否需要该选项,此类违反规则的代理均存在风险:其消息可能被旧版代理截断,因为这些旧版代理会依据 Content-Length 字段并忽略 Transfer-Encoding,而未考虑编码块大小的累计值。因此,上述规则不仅关乎安全,也涉及清除可能因与旧版代理不兼容而导致通信故障的代理。

h1-case-adjust <from> <to>

h1-case-adjust <from> <to>

定义启用时对头名称 <from> 执行的大小写调整,将其转换为 <to> 后再发送至 HTTP/1 客户端或服务器。<from> 必须为小写,<from> 与 <to> 除大小写外不得存在差异。若需调整多个头名称,可重复使用该指令。禁止重复条目。若需调整的头名称较多,建议使用 “h1-case-adjust-file”。请注意,除非在代理中指定 “option h1-case-adjust-bogus-client” 或 “option h1-case-adjust-bogus-server”,否则不会应用任何转换。

由于 RFC7230 明确指出,头名称没有标准大小写形式,因此其大小写不敏感。 应用程序必须以不区分大小写的方式处理头名称。 但某些不合规的应用程序违反标准,错误地依赖浏览器通常使用的大小写形式。 这一问题在 HTTP/2 中变得尤为关键,因为所有头名称必须以小写形式传输,HAProxy 也遵循相同约定。 无论 HTTP 版本为何,所有头名称均以小写形式发送至客户端和服务器。

某些无法正确处理请求或响应的应用程序可能需要暂时使用此类变通方法,以调整发送给它们的头名称,直至应用程序修复为止。请注意,需要此类变通方法的应用程序可能易受内容伪装攻击,必须绝对予以修复。

示例:

global
  h1-case-adjust content-length Content-Length

参见“h1-case-adjust-file”、“option h1-case-adjust-bogus-client”和“option h1-case-adjust-bogus-server”。

h1-case-adjust-file <hdrs-file>

h1-case-adjust-file <hdrs-file>

定义一个包含键/值对列表的文件,用于在将某些头名称发送给 HTTP/1 客户端或服务器之前调整其大小写。文件 <hdrs-file> 每行必须包含两个头名称。第一个必须为小写,且两者除大小写外不得有任何差异。以 ‘#’ 开头的行将被忽略,空行亦然。行首和行尾的制表符及空格将被去除。不允许重复条目。请注意,除非在代理中指定了 “option h1-case-adjust-bogus-client” 或 “option h1-case-adjust-bogus-server”,否则不会应用任何转换。

如果重复使用此指令,仅最后一个会被处理。当需要调整大量头名称时,可将其作为指令 “h1-case-adjust” 的替代方案。请阅读使用此功能相关的风险。

参见“h1-case-adjust”、“option h1-case-adjust-bogus-client”和“option h1-case-adjust-bogus-server”。

h2-workaround-bogus-websocket-clients

h2-workaround-bogus-websocket-clients

禁用向客户端通告对 h2 WebSocket 的支持。此设置可用于解决部分客户端在实现相对较新的 RFC8441 时出现的问题,例如 Firefox 88。若要允许客户端在 WebSocket 隧道中自动降级至 http/1.1,请在 bind 语句中通过指定 “alpn” 来启用 h2 支持,无需显式使用 “proto” 关键字。若此前已启用此设置,可通过在关键字前添加 “no” 来禁用。

hard-stop-after <time>

hard-stop-after <time>

定义允许执行干净的软停止的最大时间。

参数:

<time>  is the maximum time (by default in milliseconds) for which the
        instance will remain alive when a soft-stop is received via the
        SIGUSR1 signal.

这可用于确保实例在执行软停止时即使仍有连接保持打开也会退出(例如,当代理以 TCP 模式运行且超时时间较长时)。该设置在 TCP 模式和 HTTP 模式下均适用。

示例:

global
  hard-stop-after 30s

另请参见:grace

harden.reject-privileged-ports.tcp { on | off }

harden.reject-privileged-ports.tcp { on | off }
harden.reject-privileged-ports.quic { on | off }

启用按协议的保护机制,禁止与使用特权端口作为源端口的客户端通信。该端口范围依据 RFC 6335 定义。默认情况下,QUIC 协议的保护机制处于激活状态,因为此类行为具有可疑性,可能被用于伪造攻击或 DNS/NTP 放大攻击。

http-err-codes [+-]<range>[,...] [...]

http-err-codes [+-]<range>[,...] [...]

替换、减少或扩展定义为错误的状态码列表,这些错误将被计入终止码以及粘性表中的 “http_err_cnt” 计数器。默认的错误范围为 400 至 499,但在某些场景下,部分用户希望排除特定状态码,尤其是在追踪客户端错误时(例如,动态生成内容的系统中的 404)。另请参阅 “http-fail-codes” 和 “http_err_cnt”。

指定范围时若不包含 ‘+’ 或 ‘-’,则将现有范围重新定义为新范围。以 ‘+’ 开头的范围将扩展现有范围,使其包含指定范围,该范围可能与现有范围重叠,也可能不重叠。以 ‘-’ 开头的范围将从现有范围中移除指定范围。范围由 100 至 599 之间的数字组成,可选地后接连字符 ‘-’ 及另一个大于或等于首个数字的数字,用于表示范围的上限。同一 add/del/replace 操作中可使用逗号分隔多个范围。

示例:

http-err-codes 400,402-444,446-480,490   # sets exactly these codes
http-err-codes 400-499 -450 +500         # sets 400 to 500 except 450
http-err-codes -450-459                  # removes 450 to 459 from range
http-err-codes +501,505                  # adds 501 and 505 to range

http-fail-codes [+-]<range>[,...] [...]

http-fail-codes [+-]<range>[,...] [...]

替换、减少或扩展由终止码及粘性表中的 “http_fail_cnt” 计数器所定义的失败状态码列表。默认的失败状态码范围为 500 至 599,但排除 501 和 505,因为它们可能由客户端触发,通常表示服务器无法处理请求。部分用户在特定场景下希望排除某些状态码,例如在特定 SOAP 环境中排除 500,因为该状态码在该环境中并不表示服务器故障。语法与上文的 http-err-codes 完全相同。另请参见 “http-err-codes” 和 “http_fail_cnt”。

insecure-fork-wanted

insecure-fork-wanted

默认情况下,HAProxy 在启动后会尽力防止任何线程和进程的创建。在使用来源不明的 Lua 文件,或试验仍可能包含漏洞的开发版本时,这一点尤为重要,因为这些漏洞的可利用性尚不明确。总体而言,确保流量无法触发任何意外的后台活动,是一种良好的系统管理能力。但此机制会阻止外部检查正常工作,也可能破坏某些特定的 Lua 脚本,这些脚本依赖于 fork 能力。该选项用于禁用此保护机制。请注意,禁用该选项是不良做法,因为一旦禁用,库或 HAProxy 本身中的漏洞将更容易被利用。此外,从 Lua 或其他任何位置进行 fork 操作并不可靠,因为子进程可能随机继承其他线程设置的锁,从而无法完成操作。因此,强烈建议永远不要使用此选项,并重新评估任何需要此类 fork 的工作负载,改用更安全的解决方案(例如使用代理程序替代外部检查)。该选项支持使用 “no” 前缀来禁用。也可通过在 HAProxy 命令行中使用 “-dI” 激活。

insecure-setuid-wanted

insecure-setuid-wanted

HAProxy 无需在运行时调用可执行文件(使用外部检查时除外,但强烈建议避免使用),且应默认将其自身隔离至空的 chroot 环境中。因此,几乎不存在允许调用 setuid 可执行文件而不让用户充分知晓风险的合理理由。当 HAProxy 需要调用外部检查和/或禁用 chroot 时,若库或 HAProxy 本身存在漏洞,可能导致外部程序被执行。在 Linux 系统上,可将进程锁定,使此类可执行文件上存在的 setuid 位被忽略。这能显著降低此类情况下的权限提升风险。HAProxy 默认执行此操作。若该行为导致外部检查出现问题(例如需要调用 “ping” 命令),则可通过在 global 段中显式添加该指令来禁用此保护。启用后,可通过在指令前添加 “no” 关键字将其重新关闭。

issuers-chain-path <dir>

issuers-chain-path <dir>

指定用于加载证书链以完成颁发者信息的目录。所有文件必须采用 PEM 格式。对于使用 “crt” 或 “crt-list” 加载的证书,若 PEM 文件中未包含证书链(也称为中间证书),当证书的颁发者与通过 “issuers-chain-path” 加载的链中首个证书相匹配时,HAProxy 将自动补全证书链。一个包含 PrivateKey+Certificate+IntermediateCA2+IntermediateCA1 的 “crt” 文件可替换为仅包含 PrivateKey+Certificate 的文件。若在 “issuers-chain-path” 目录中存在包含 IntermediateCA2+IntermediateCA1 的文件,HAProxy 将自动补全证书链。所有具有相同颁发者的其他证书将在内存中共享该证书链。

OCSP 功能可在未使用 .issuer 或 PEM 中未提供证书链时,使用完整的证书链。

jwt.decrypt_alg_list <list>

jwt.decrypt_alg_list <list>

设置 jwt_decrypt_XXX 转换器中允许使用的算法列表。使用不支持或已禁用算法的 JWT 令牌将永远无法解密。指定的算法必须与 RFC7518 第 4.1 节 中的格式一致,且以冒号分隔。特殊名称 “ALL” 可用于启用所有支持的算法(详见 “jwt_decrypt_jwk” 转换器以获取完整列表),也可在算法名称后附加 “!” 以显式禁用该算法。请注意,除非明确指定 “ALL”,否则使用此选项将禁用未在所提供列表中明确列出的任何算法。

示例:

# Enable all algorithms but the "ECDH-ES" one
jwt.decrypt_alg_list ALL:!ECDH-ES

# Only enable ECDH-ES algorithms
jwt.decrypt_alg_list ECDH-ES:ECDH-ES+A128KW:ECDH-ES+A192KW:ECDH-ES+A256KW

jwt.decrypt_enc_list <list>

jwt.decrypt_enc_list <list>

设置 jwt_decrypt_XXX 转换器中允许的加密算法列表。使用不支持或已禁用的加密算法的 JWT 令牌将永远无法解密。指定的算法必须与 RFC7518 第 5.1 节 中的格式一致,且以冒号分隔。特殊名称 “ALL” 可用于启用所有支持的算法(详见 “jwt_decrypt_jwk” 转换器以获取完整列表),也可在算法名称后附加 “!” 以显式禁用该算法。请注意,除非明确指定 “ALL”,否则使用此选项将禁用未在所提供列表中明确列出的任何算法。

示例:

# Enable only AES GCM encrypting algorithms
jwt.decrypt_enc_list A128GCM:A192GCM:A256GCM

key-base <dir>

key-base <dir>

为在使用 “key” 指令时指定相对路径的 SSL 私钥获取目录。若指定绝对路径,则优先生效并忽略 “key-base”。此选项仅在使用 crt-store 加载行时有效。

limited-quic

limited-quic

此设置必须用于在 HAProxy 编译时使用不支持 QUIC 的 OpenSSL 版本的情况下显式启用 QUIC 监听器绑定。它会激活 HAProxy 内部兼容性层,该层必须在构建时通过 USE_QUIC_OPENSSL_COMPAT=1 选项选定。此兼容性层支持大部分必要的 TLS 操作,但不支持 QUIC 0-RTT 功能。

此功能主要针对 OpenSSL 3.5.2 之前版本,因为这些版本尚未实现 QUIC API 或仅部分实现。尽管可在 3.5.2 及以上版本中仍激活兼容层,但此举可能并无必要。

若设置了 limited-quic 但构建时未选择兼容层,则该选项将被静默忽略,QUIC TLS 操作将依赖 TLS 库。

localpeer <name>

localpeer <name>

设置本地实例的对等节点名称。若指定了 “-L” 命令行参数,或在 “peers” 段定义之后使用,该设置将被忽略。在此情况下,配置解析期间将发出警告消息。

此选项还将设置 HAPROXY_LOCALPEER 环境变量。另请参阅管理指南中的 “-L” 以及下方的 “对等节点” 段。

log <target> [len <length>] [format <format>] [sample <ranges>:<sample_size>]

log <target> [len <length>] [format <format>] [sample <ranges>:<sample_size>]
    [profile <prof>] <facility> [max level [min level]]

添加一个全局 syslog 服务器。可以定义多个全局服务器。它们将接收代理启动和退出时的日志,以及所有配置了“log global”的代理产生的日志。有关更多详细信息,请参阅代理的“log”选项。

log-send-hostname [<string>]

log-send-hostname [<string>]

设置 syslog 头中的主机名字段。若设置了可选的“string”参数,头字段将设为字符串内容;否则使用系统的主机名。通常在未通过中间 syslog 服务器转发日志时使用,或用于自定义日志中打印的主机名。

log-tag <string>

log-tag <string>

将 syslog 头中的标签字段设置为该字符串。默认值为从命令行启动时的程序名称,通常为 “haproxy”。在同一个主机上运行多个进程时,有时需要区分它们。另请参见代理级别的 “log-tag” 指令。

lua-load <file> [ <arg1> [ <arg2> [ ... ] ] ]

lua-load <file> [ <arg1> [ <arg2> [ ... ] ] ]

本文全局指令在共享上下文中加载并执行 Lua 文件,该上下文对所有线程可见。在该上下文中设置的任何变量均可被任意线程访问。这是加载 Lua 程序最简单且推荐的方式,但如果执行大量 Lua 调用,其扩展性将不佳,因为全局状态同一时间只能由一个线程运行。以这种方式加载的程序始终在 “core.thread” 变量中看到 0。该指令可多次使用。

可通过以下代码在 Lua 文件中访问参数。请注意,Lua 数组的索引从 1 开始。在文件中声明的“local”变量在整个文件中可用,但对其他文件不可见。

 local args = table.pack(...)

lua-load-per-thread <file> [ <arg1> [ <arg2> [ ... ] ] ]

lua-load-per-thread <file> [ <arg1> [ <arg2> [ ... ] ] ]

全局指令将 Lua 文件加载并执行到每个启动的线程中。任何全局变量均具有线程局部可见性,因此每个线程可看到不同的值。因此强烈建议在通过此方式加载的程序中不要使用全局变量。每个线程都会加载并初始化一份独立副本,所有操作按顺序执行,且按线程编号从 1 到 nbthread 依次进行。若某些操作仅需执行一次,程序应检查 “core.thread” 变量以确定当前正在初始化的线程。通过此方式加载的程序将在所有线程上并发运行,具有高度可扩展性。这是推荐的加载简单函数的方式,用于注册样本提取、转换器、动作或服务,前提是已确认程序不依赖全局变量。为简化使用,即使仅使用一个线程或线程功能被禁用时,该指令依然可用(此时等效于 lua-load)。该指令可多次使用。

请参阅 lua-load 了解 args 的使用方法。

lua-prepend-path <string> [<type>]

lua-prepend-path <string> [<type>]

在 Lua 的 package.<type> 变量前添加指定字符串,并以分号结尾。<type> 必须为 “path” 或 “cpath”。若未指定 <type>,则默认值为 “path”。

Lua 的路径是用分号分隔的模式列表,用于指定 require 函数查找库源文件的方式。模式中的问号(?)将被模块名替换。路径按从左到右的顺序进行评估,这意味着后续添加的路径将优先被检查。

以指定以下路径为例:

lua-prepend-path /usr/share/haproxy-lua/?/init.lua
lua-prepend-path /usr/share/haproxy-lua/?.lua

当调用 require "example" 时,HAProxy 会首先尝试加载 /usr/share/haproxy-lua/example.lua 脚本,若该脚本不存在,则尝试加载 /usr/share/haproxy-lua/example/init.lua,若仍不存在,则尝试默认路径。

请参阅 https://www.lua.org/pil/8.1.html 以获取 Lua 文档中的详细信息。

master-worker (deprecated)

master-worker (deprecated)

主进程/工作进程模式。其效果等同于命令行参数 “-W”。

此关键字已弃用,请使用“-W”或“-Ws”以主进程/工作进程模式启动。

此模式将启动一个“主进程”,在读取配置后,由其派生一个“工作进程”来处理流量。主进程用作进程管理器,负责监控“工作进程”。

使用此模式时,可通过向主进程发送 SIGUSR2 信号直接重载 HAProxy。 重载操作将使主进程重新读取配置并派生新的工作进程。旧的工作进程将保留至其当前任务完成为止。

主进程/工作进程模式与前台模式或守护进程模式均兼容。

默认情况下,如果某个工作进程以错误的返回码退出(例如发生段错误),所有工作进程将被终止,主进程也将退出。建议在 systemd 单元文件中结合使用 Restart=on-failure,以便重新启动整个进程。若不希望出现此行为,必须使用关键字 “no-exit-on-failure”。

另请参见管理指南中的 “-W”。

master-worker no-exit-on-failure

master-worker no-exit-on-failure

在主进程/工作进程模式下,默认情况下,若某个工作进程以错误的返回码退出(例如发生段错误),所有工作进程将被终止,主进程也将退出。建议在 systemd 单元文件中结合使用 Restart=on-failure,以便重新启动整个进程。

此关键字可在工作进程崩溃时保持其余进程运行,而非终止所有进程。使用时需谨慎,因为该功能仅用于调试,可能导致主进程进入异常状态。

max-threads-per-group <number>

max-threads-per-group <number>

定义线程组中的最大线程数。除非使用 “thread-groups” 指令固定线程组数量,否则 HAProxy 会创建足够多的线程组以满足所请求的线程数量。最小值为 1,最大值为 64(在 64 位系统上),或 32(在 32 位系统上)。较低的值可减少由共享状态上的原子操作引起的竞争,但可能增加创建所有监听器和保持空闲后端连接所需的套接字数量。较高的值可降低这些开销,但会带来更高的 CPU 使用率(在竞争情况下),以及更低的连接速率。默认值为 16,该值是在多种测试系统(包括来自多个厂商的 x86_64 处理器,以及裸金属和虚拟化环境中的大型 Arm64 系统)上通过实验得出的最佳权衡。

mworker-max-reloads <number>

mworker-max-reloads <number>

在主进程/工作进程模式下,此选项用于限制工作进程在一次重载后仍能存活的时间次数。若工作进程在重载后未退出,且其重载次数超过此数值,该工作进程将收到 SIGTERM 信号。此选项有助于控制工作进程的数量。参见管理指南中的“show proc”。

默认情况下,该值设为 50。

nbthread <number>

nbthread <number>

此设置仅在编译时启用了线程支持的情况下可用。它使 HAProxy 在 <number> 个线程上运行。“nbthread” 在 HAProxy 以前台模式启动时同样有效。在部分支持 CPU 亲和性的平台上,启动时默认的 “nbthread” 值会自动设置为进程绑定的 CPU 数量。这意味着可通过 “taskset” 或 “cpuset” 等命令从调用进程轻松调整线程数量。否则,该值默认为 1。默认值会在 “HAProxy -vv” 的输出中报告。请注意,此处设置或自动检测的值受 “thread-hard-limit”(若已设置)的限制。

numa-cpu-mapping

numa-cpu-mapping

在运行于支持 NUMA 的平台时,此选项可使 “cpu-policy” 指令检查拓扑结构,从而确定最佳的 CPU 集合及对应的线程数量。然而,若在特定架构上应用的绑定并非最优,可通过指令 ’no numa-cpu-mapping’ 禁用此自动绑定。若配置中存在 ’nbthread’ 指令,或进程亲和性已通过 ‘cpu-map’ 指令或 taskset 工具指定,或 ‘cpu-policy’ 设置为其他值,则不会应用此自动绑定。参见 “cpu-map”、“cpu-policy”、“cpu-set”。

ocsp-update.disable [ on | off ]

ocsp-update.disable [ on | off ]

完全禁用 HAProxy 中的 ocsp-update 功能。任何 ocsp-update 配置都将被忽略。 默认值为 “off”。有关自动更新机制的更多信息,请参见选项 “ocsp-update”。

ocsp-update.httpproxy <address>[:port]

ocsp-update.httpproxy <address>[:port]

允许通过 HTTP 代理进行 OCSP 更新。此选项仅适用于 HTTP,不支持 HTTPS。

此选项将允许 OCSP 更新程序在向代理发送请求时使用绝对 URI。

ocsp-update.maxdelay <number>

ocsp-update.maxdelay <number>
tune.ssl.ocsp-update.maxdelay <number> (deprecated)

设置同一 OCSP 响应自动更新之间的最大间隔时间。该时间以秒为单位,缺省值为 3600(1 小时)。必须设置为高于 “ocsp-update.mindelay” 的值。有关自动更新机制的更多信息,请参见选项 “ocsp-update”。

ocsp-update.mindelay <number>

ocsp-update.mindelay <number>
tune.ssl.ocsp-update.mindelay <number> (deprecated)

设置同一 OCSP 响应两次自动更新之间的最小间隔。该时间以秒为单位,缺省值为 300(5 分钟)。对于没有明确过期时间的 OCSP 响应尤为有用。必须设置为低于 “ocsp-update.maxdelay” 的值。有关自动更新机制的更多信息,请参见选项 “ocsp-update”。

ocsp-update.mode [ on | off ]

ocsp-update.mode [ on | off ]

设置配置中所有证书的默认 ocsp-update 模式。此全局选项可被 crt-list 的 “ocsp-update” 选项覆盖。该选项默认设置为 “off”。有关自动更新机制的更多信息,请参见选项 “ocsp-update”。

pidfile <pidfile>

pidfile <pidfile>

将所有守护进程的 PID 写入文件 <pidfile>,在守护进程模式下;或在主进程/工作进程模式下,将主进程的 PID 写入文件 <pidfile>。此选项等效于命令行参数 “-p”。写入文件必须对启动进程的用户可访问。另请参见 “daemon” 和 “master-worker”。

pp2-never-send-local

pp2-never-send-local

PROXY 协议 v2 实现中的一个缺陷存在于 HAProxy 2.1 版本之前,导致其在执行健康检查时发出 PROXY 命令而非 LOCAL 命令。该问题影响较小,但会干扰部分服务器的日志记录。遗憾的是,该缺陷发现较晚,且已确认某些服务器仅在 HAProxy 上测试其 PROXY 协议实现,无法正确处理 LOCAL 命令,当 HAProxy 执行健康检查时,这些服务器将永久处于“down”状态。发生此情况时,可启用此全局选项,暂时恢复旧版(错误)行为,直至联系受影响组件的厂商并完成修复。该选项默认禁用,且对所有包含 “send-proxy-v2” 语句的服务器生效。

presetenv <name> <value>

presetenv <name> <value>

将环境变量 <name> 设置为值 <value>。若该变量已存在,则不会被覆盖。更改立即生效,使得配置文件中的下一行可读取新值。另请参见 “setenv”、“resetenv” 和 “unsetenv”。

prealloc-fd

prealloc-fd

执行一次最大文件描述符的打开操作,从而预先分配内核的数据结构。当 nbthread > 1 且 HAProxy 打开文件描述符时,可避免内核扩展数据结构所导致的短暂停顿。

resetenv [<name> ...]

resetenv [<name> ...]

移除所有环境变量,仅保留参数中指定的变量。此操作可在使用 setenv 或 unsetenv 设置新值前,创建一个干净且受控的环境。请注意,某些内部函数可能依赖特定环境变量,例如时间操作函数、OpenSSL 或外部检查功能。必须谨慎使用,且仅在完成全面验证后方可执行。更改立即生效,因此配置文件中的下一行将立即看到新的环境状态。参见“setenv”、“presetenv”和“unsetenv”。

server-state-base <directory>

server-state-base <directory>

指定在所有不以 ‘/’ 开头的服务器状态文件名前添加的目录前缀。参见 “server-state-file”、“load-server-state-from-file” 和 “server-state-file-name”。

server-state-file <file>

server-state-file <file>

指定包含服务器状态的文件路径。若路径以斜杠(’/’)开头,则视为绝对路径;否则视为相对于通过 “server-state-base” 指定的目录(若已设置)或当前目录。在重载 HAProxy 前,可使用统计信息命令 “show servers state” 保存服务器的当前状态。该命令的输出必须写入 <file> 所指向的文件。启动时,在处理流量之前,HAProxy 将读取、加载并应用文件中所列且当前运行配置中可用的每个服务器的状态。参见 “server-state-base” 和 “show servers state”、“load-server-state-from-file” 以及 “server-state-file-name”

set-dumpable [ on | off | libs ]

set-dumpable [ on | off | libs ]

此选项用于在进程崩溃时选择核心转储行为。可用选项包括:

  • 启用此选项后,若此前已禁用,则将在进程级别启用核心转储。

  • off:禁用之前已启用的核心转储功能。

  • libs:此选项启用核心转储,并嵌入用于调试所必需的二进制文件和库的副本。开发者可能要求启用此功能。启用后,HAProxy 将尝试将所依赖的库加载到内存中并予以保留。若进程崩溃,这些库将被转储至核心文件,无需再从文件系统中获取,也避免了库版本不匹配的风险。此功能会额外占用数兆字节至数十兆字节的内存,因此在小型系统上应避免使用。

此选项应默认禁用,仅在开发人员请求时启用。默认情况下处于禁用状态。若未指定参数,其默认值为“on”。若已启用,仍可通过在前缀添加“no”关键字或将其设置为“off”来强制禁用。该选项对性能或稳定性无影响,但会尽力重新启用可能因文件大小限制(ulimit -f)、核心文件大小限制(ulimit -c)或进程更改 UID/GID 后的“可转储性”(如 /proc/sys/fs/suid_dumpable 在 Linux 上)而被禁用的核心转储。核心转储仍可能受当前目录权限限制(请检查文件启动目录)、chroot 目录权限限制(可能需要临时禁用 chroot 指令或将其移至专用可写位置),或其他系统特定约束。例如,某些 Linux 发行版以一个系统上甚至未安装的可执行文件路径替换默认核心文件(请检查 /proc/sys/kernel/core_pattern)。通常,仅需将核心文件名设为“core”、“core.%p”或“/var/log/core/core.%p”即可解决该问题。在尝试启用此选项以等待罕见问题重现时,建议首先通过向“HAProxy”进程发送“kill -11”等命令来尝试获取核心转储,并验证其在进程终止时是否按预期生成。

set-var <var-name> <expr>

set-var <var-name> <expr>

设置进程级变量 <var-name> 为样本表达式 <expr> 的计算结果。变量 <var-name> 必须为进程级变量(使用 ‘proc.’ 前缀)。其行为与 TCP 或 HTTP 规则中的 ‘set-var’ 动作完全相同,但表达式在配置解析时即被计算,且变量立即被设置。表达式中允许使用的样本提取函数和转换器仅限于使用内部数据的类型,通常为 ‘int(value)’ 或 ‘str(value)’。也可引用先前分配的变量。这些变量随后可在常规规则集中读取(及修改)。

示例:

global
    set-var proc.current_state str(primary)
    set-var proc.prio int(100)
    set-var proc.threshold int(200),sub(proc.prio)

set-var-fmt <var-name> <fmt>

set-var-fmt <var-name> <fmt>

设置进程级变量 <var-name> 为日志格式 <fmt> 求值后得到的字符串。变量 <var-name> 必须为进程级变量(使用 ‘proc.’ 前缀)。其行为与 TCP 或 HTTP 规则中的 ‘set-var-fmt’ 动作完全相同,但表达式在配置解析时即被求值,且变量立即被设置。表达式中允许使用的样本提取函数和转换器仅限于使用内部数据的类型,通常为 ‘int(value)’ 或 ‘str(value)’。也可引用先前分配的变量。这些变量随后可在常规规则集中读取(及修改)。有关自定义日志格式语法的详细信息,请参见 第 8.2.6 节 。

示例:

global
    set-var-fmt proc.current_state "primary"
    set-var-fmt proc.bootid        "%pid|%t"

setcap <name>[,<name>...]

setcap <name>[,<name>...]

设置在以非 root 用户(uid > 0)身份启动和运行,或以 uid 0(root)身份启动后切换至非 root 用户时必须保留的一组能力。默认情况下,uid 切换会导致所有权限丢失,但在透明代理过程中尝试从外部地址连接服务器,或绑定低于 1024 的端口时(例如使用 “tune.quic.fe.sock-per-conn default-on”),通常仍需保留部分权限,从而导致完全以 uid 0 运行的配置。设置能力通常更安全,因为仅保留所需的能力。该功能为操作系统特定功能,仅在构建时设置 USE_LINUX_CAP=1 时于 Linux 上启用。支持的能力列表取决于操作系统,当传递无效或空的能力名称时,错误消息中会列出可用的能力。可传递多个能力,以逗号分隔。常用能力中,“cap_net_raw” 允许透明绑定至外部地址,“cap_net_bind_service” 允许绑定至特权端口,可能被 QUIC 使用。若进程以相同非 root 用户身份启动和运行,所需能力应通过 setcap 在 HAProxy 二进制文件上设置,并配合此关键字使用。关于在 HAProxy 二进制文件上设置能力的详细信息,请参见管理指南第 13.1 节 Linux 能力支持。

示例:

global
    setcap cap_net_bind_service,cap_net_admin

setenv <name> <value>

setenv <name> <value>

将环境变量 <name> 设置为值 <value>。若该变量已存在,则将其覆盖。 更改立即生效,因此配置文件中的下一行将看到新值。 另请参见“presetenv”、“resetenv”和“unsetenv”。

shm-stats-file <name>

shm-stats-file <name>

当设置此指令时,将启用共享内存以存储统计信息计数器。<name> 用作 shm_open() 的参数,以在唯一位置打开共享内存。这也意味着该指令仅在支持 shm_open() 的系统上可用。当使用 SHM 存储统计信息时,所有前端、后端、监听器和服务器的可共享计数器将存储在 SHM 中,前提是它们已设置 GUID。重载 HAProxy 时,新进程将尝试扫描 SHM,查找可基于 GUID 和类型与配置中定义的对象关联的对象,目标是实现重载后部分计数器值的保留。另一方面,当 HAProxy 正常停止时,SHM 对象将被释放,这意味着计数器将被有效重置。也可以在启动新进程前手动删除文件,以强制重置计数器。

另请参见 “guid”、“guid-prefix” 和 “shm-stats-file-max-objects”

shm-stats-file-max-objects <number>

shm-stats-file-max-objects <number>

此设置定义了用于共享计数器的共享内存(shm)每线程组所能存储的最大对象数量。该值与共享内存的最大内存大小直接相关,用于预先映射共享内存至指定大小,以避免运行时重新映射。默认值为 2k,适用于大多数配置,且不会导致内存使用不当,但如需可轻松调整。若此值过低,无法注册预期存储于共享内存中的对象,HAProxy 在启动时将发出警告。此设置仅在定义了 “shm-stats-file” 时才有效。

参见“线程组”

ssl-default-bind-ciphers <ciphers>

ssl-default-bind-ciphers <ciphers>

此设置仅在编译时启用了 OpenSSL 支持时可用。它用于设置默认字符串,描述在 SSL/TLS 握手过程中协商的加密算法列表(“加密套件”),适用于所有未显式定义加密套件的 “bind” 语句,支持至 TLSv1.2。该字符串的格式由 OpenSSL 手册页中的 “man 1 ciphers” 定义。有关背景信息和建议,请参阅例如 (https://wiki.mozilla.org/Security/Server_Side_TLS ) 和 (https://mozilla.github.io/server-side-tls/ssl-config-generator/ )。对于 TLSv1.3 的加密套件配置,请参阅 “ssl-default-bind-ciphersuites” 关键字。有关更多详细信息,请参阅 “bind” 关键字。

ssl-default-bind-ciphersuites <ciphersuites>

ssl-default-bind-ciphersuites <ciphersuites>

本设置仅在编译时启用了 OpenSSL 支持且使用 OpenSSL 1.1.1 或更高版本构建 HAProxy 时可用。它用于设置默认字符串,描述在 TLSv1.3 握手过程中协商的加密算法列表(“加密套件”),适用于所有未显式定义加密套件的 “bind” 段。该字符串的格式由 OpenSSL 手册中的 “man 1 ciphers” 文档在“ciphersuites”章节中定义。对于 TLSv1.2 及更早版本的加密配置,请参阅 “ssl-default-bind-ciphers” 关键字。本设置可能接受 TLSv1.2 加密套件,但此行为未在文档中说明,不建议使用,因其可能存在不一致或缺陷。OpenSSL 的默认 TLSv1.3 加密套件为: “TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256”

TLSv1.3 仅支持 5 种密码套件:

  • TLS_AES_128_GCM_SHA256
  • TLS_AES_256_GCM_SHA384
  • TLS_CHACHA20_POLY1305_SHA256
  • TLS_AES_128_CCM_SHA256
  • TLS_AES_128_CCM_8_SHA256

请参阅“bind”关键字以获取更多信息。

示例:

global
    ssl-default-bind-ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256
    ssl-default-bind-ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256

ssl-default-bind-client-sigalgs <sigalgs>

ssl-default-bind-client-sigalgs <sigalgs>

本文仅在编译时启用 OpenSSL 支持时可用。该设置用于为所有未显式定义签名算法列表的 “bind” 段设置默认字符串,以描述与客户端认证相关的签名算法列表。字符串格式为以冒号分隔的签名算法列表。每个签名算法可采用以下两种形式之一:TLS1.3 签名方案名称(“rsa_pss_rsae_sha256”)或公钥算法 + 哈希算法形式(“ECDSA+SHA256”)。列表中可同时包含两种形式。有关格式的更多信息,请参阅 SSL_CTX_set1_client_sigalgs(3)。签名算法列表亦可在 RFC8446 第 4.2.3 节以及 OpenSSL 的 ssl/t1_lib.c 文件中找到。该设置不适用于 TLSv1.1 及更早版本协议,因为这些版本中签名算法不单独协商。除非需要与中间设备兼容,否则不建议更改此设置。

ssl-default-bind-curves <curves>

ssl-default-bind-curves <curves>

此设置仅在编译时启用 OpenSSL 支持时可用。它用于设置在使用 ECDHE 进行 SSL/TLS 握手时协商的椭圆曲线算法列表(“曲线套件”)的默认描述字符串。字符串格式为以冒号分隔的曲线名称列表。请参阅“bind”关键字以获取更多信息。

ssl-default-bind-options [<option>]...

ssl-default-bind-options [<option>]...

此设置仅在编译时启用 OpenSSL 支持时可用。它会将默认的 ssl-options 强制应用于所有 “bind” 语句。请查阅 “bind” 关键字以了解可用选项。

示例:

global
   ssl-default-bind-options ssl-min-ver TLSv1.0 no-tls-tickets

ssl-default-bind-sigalgs <sigalgs>

ssl-default-bind-sigalgs <sigalgs>

本设置仅在编译时启用了 OpenSSL 支持时可用。它用于设置默认字符串,描述在 TLSv1.2 和 TLSv1.3 握手过程中协商的签名算法列表,适用于所有未显式定义自身签名算法的 “bind” 段。字符串格式为以冒号分隔的签名算法列表。每个签名算法可采用以下两种形式之一:TLSv1.3 签名方案名称(“rsa_pss_rsae_sha256”)或公钥算法 + 哈希算法形式(“ECDSA+SHA256”)。列表中可同时包含两种形式。有关格式的更多信息,请参见 SSL_CTX_set1_sigalgs(3)。签名算法列表亦可在 RFC8446 第 4.2.3 节及 OpenSSL 的 ssl/t1_lib.c 文件中找到。此设置不适用于 TLSv1.1 及更早版本的协议,因为在这些版本中签名算法并非独立协商。除非需要与中间设备兼容,否则不建议更改此设置。

ssl-default-server-ciphers <ciphers>

ssl-default-server-ciphers <ciphers>

此设置仅在编译时启用 OpenSSL 支持时可用。它用于设置默认字符串,描述在 SSL/TLS 握手过程中与服务器协商的加密算法列表,适用于所有未显式定义加密算法的 “server” 行,支持至 TLSv1.2。字符串格式由 OpenSSL 手册页中的 “man 1 ciphers” 定义。有关背景信息和建议,请参阅例如 (https://wiki.mozilla.org/Security/Server_Side_TLS ) 和 (https://mozilla.github.io/server-side-tls/ssl-config-generator/ )。对于 TLSv1.3 的加密套件配置,请参阅 “ssl-default-server-ciphersuites” 关键字。有关更多信息,请参阅 “server” 关键字。

ssl-default-server-ciphersuites <ciphersuites>

ssl-default-server-ciphersuites <ciphersuites>

此设置仅在编译时启用了 OpenSSL 支持且使用 OpenSSL 1.1.1 或更高版本构建 HAProxy 时可用。它用于设置默认字符串,描述在与服务器进行 TLSv1.3 握手时协商的加密算法列表,适用于所有未显式定义加密算法的 “server” 行。该字符串的格式由 OpenSSL 手册页中 “man 1 ciphers” 的 “ciphersuites” 段落定义。对于 TLSv1.2 及更早版本的加密配置,请参阅 “ssl-default-server-ciphers” 关键字。有关更多信息,请参阅 “server” 关键字。

ssl-default-server-client-sigalgs <sigalgs>

ssl-default-server-client-sigalgs <sigalgs>

本设置仅在编译时启用 OpenSSL 支持时可用。它用于为所有未显式定义签名算法列表的 “server” 段设置默认字符串,该字符串描述与客户端认证相关的签名算法列表。字符串格式为以冒号分隔的签名算法列表。每个签名算法可采用两种形式之一:TLSv1.3 签名方案名称(“rsa_pss_rsae_sha256”)或公钥算法 + 哈希算法形式(“ECDSA+SHA256”)。列表中可同时包含两种形式。有关格式的更多信息,请参阅 SSL_CTX_set1_client_sigalgs(3)。签名算法列表亦可在 RFC8446 第 4.2.3 节以及 OpenSSL 的 ssl/t1_lib.c 文件中找到。此设置不适用于 TLSv1.1 及更早版本的协议,因为在这些版本中签名算法并非独立协商。除非需要与中间设备兼容,否则不建议更改此设置。

ssl-default-server-curves <curves>

ssl-default-server-curves <curves>

此设置仅在编译时启用 OpenSSL 支持时可用。它用于设置在使用 ECDHE 进行 SSL/TLS 握手时协商的椭圆曲线算法列表(“曲线套件”)的默认描述字符串。字符串格式为以冒号分隔的曲线名称列表。请参阅“server”关键字获取更多信息。

ssl-default-server-options [<option>]...

ssl-default-server-options [<option>]...

此设置仅在编译时启用 OpenSSL 支持时可用。它会将默认的 ssl-options 强制应用于所有 “server” 行。请参阅 “server” 关键字以查看可用选项。

ssl-default-server-sigalgs <sigalgs>

ssl-default-server-sigalgs <sigalgs>

当编译时启用了 OpenSSL 支持时,此设置才可用。它用于设置默认字符串,描述在 TLSv1.2 和 TLSv1.3 握手过程中协商的签名算法列表,适用于所有未显式定义签名算法的 “server” 行。字符串格式为以冒号分隔的签名算法列表。每个签名算法可采用以下两种形式之一:TLSv1.3 签名方案名称(“rsa_pss_rsae_sha256”)或公钥算法 + 哈希算法形式(“ECDSA+SHA256”)。列表中可同时包含两种形式。有关格式的更多信息,请参见 SSL_CTX_set1_sigalgs(3)。签名算法列表亦可在 RFC8446 第 4.2.3 节以及 OpenSSL 的 ssl/t1_lib.c 文件中找到。此设置不适用于 TLSv1.1 及更早版本的协议,因为在这些版本中签名算法并非独立协商。除非需要与中间设备兼容,否则不建议更改此设置。

ssl-dh-param-file <file>

ssl-dh-param-file <file>

当编译时启用了 OpenSSL 支持时,此设置才可用。它用于设置在使用临时 Diffie-Hellman(DHE)密钥交换进行 SSL/TLS 握手时的默认 DH 参数,适用于所有未显式定义自身参数的 “bind” 语句。若在 bind 证书文件中发现了自定义 DH 参数,则该设置将被覆盖。如果既未通过 ssl-dh-param-file 指定自定义 DH 参数,也未在证书文件中直接设置,除非设置了 tune.ssl.default-dh-param,否则将不会使用 DHE 密码套件。在后一种情况下,将使用指定大小的预定义 DH 参数。自定义参数被认为更加安全,因此建议使用。可通过 OpenSSL 命令 “openssl dhparam <size>” 生成自定义 DH 参数,其中 size 至少应为 2048,因为 1024 位的 DH 参数已不再被视为安全。

ssl-passphrase-cmd <cmd> <args> ...

ssl-passphrase-cmd <cmd> <args> ...

此设置仅在编译时启用了 OpenSSL 支持时可用。它允许定义一个完整的命令行,该命令行将在初始化过程中加载加密证书时被调用。该命令可以是脚本或其他程序。命令将接收加密私钥路径作为第一个参数,随后是用户定义的“args”参数,并应将解密加密私钥所需的密码短语输出到标准输出。在初始化过程中每次加载新的加密私钥时,HAProxy 会首先尝试所有已知的密码短语进行解密,若均失败,则最终再次调用密码短语命令。

ssl-propquery <query>

ssl-propquery <query>

当编译时启用了 OpenSSL 支持且 OpenSSL 版本不低于 3.0 时,此设置才可用。它允许定义一个默认属性字符串,用于在获取算法时指定提供者。其行为与 OpenSSL propquery 选项相同,语法也一致(详见 https://www.openssl.org/docs/man3.0/man7/property.html )。例如,若已加载两个提供者(foo 提供者和默认提供者),则使用 propquery “?provider=foo” 可默认选择由 foo 提供者提供的算法实现,若未找到则回退至默认提供者的实现。

ssl-provider <name>

ssl-provider <name>

此设置仅在编译时启用了 OpenSSL 支持且 OpenSSL 版本不低于 3.0 时可用。该设置允许在初始化时加载一个提供者。若加载成功,HAProxy 可使用该提供者提供的任何功能。可在配置文件中指定多个 ssl-provider 选项,提供者将按其出现的顺序依次加载。

请注意,显式加载提供者会阻止 OpenSSL 自动加载“default”提供者。OpenSSL 还允许在配置文件(例如 OpenSSL.cnf)中直接定义应加载的提供者,因此无需使用此 ‘ssl-provider’ 选项来加载提供者。可使用 “show ssl providers” CLI 命令查看所有成功加载的提供者。

OpenSSL 提供程序的默认搜索路径可在执行 “openssl version -a” 命令的输出中找到。若提供程序位于其他目录,请设置 OPENSSL_MODULES 环境变量,该变量指定提供程序所在目录。

另请参见 “ssl-propquery” 和 “ssl-provider-path”。

ssl-provider-path <path>

ssl-provider-path <path>

此设置仅在编译时启用了 OpenSSL 支持且 OpenSSL 版本不低于 3.0 时可用。它允许指定 OpenSSL 用于查找提供者时的搜索路径。其行为与 OPENSSL_MODULES 环境变量相同。该路径将用于后续所有 ‘ssl-provider’ 选项,直至定义新的 ‘ssl-provider-path’ 为止。参见 “ssl-provider”。

ssl-load-extra-del-ext

ssl-load-extra-del-ext

此设置用于配置 HAProxy 查找额外 SSL 文件的方式。默认情况下,HAProxy 会在文件名后添加新的扩展名(例如:使用 “foobar.crt” 加载 “foobar.crt.key”)。启用此选项后,HAProxy 会在添加新扩展名前移除原有扩展名(例如:使用 “foobar.crt” 加载 “foobar.key”)。

证书文件必须具有 “.crt” 扩展名,此选项才能生效。

此选项与捆绑扩展名(.ecdsa、.rsa、.dsa)不兼容,且不会尝试移除它们。

此选项默认已禁用。另请参见“ssl-load-extra-files”。

ssl-load-extra-files <none|all|bundle|sctl|ocsp|issuer|key>*

ssl-load-extra-files <none|all|bundle|sctl|ocsp|issuer|key>*

此设置会改变 HAProxy 在加载 SSL 证书时查找未指定文件的方式。该选项适用于与 “bind” 行及 “server” 行关联的证书,但部分额外文件对 “server” 行证书无功能性影响。

默认情况下,HAProxy 会自动发现配置中未指定的大量文件,若需要优化启动时间,建议禁用此行为。

“none”:仅加载配置中指定的文件。若文件不存在,不尝试加载证书捆绑包。在目录情况下,若证书文件的基名相同,则不会尝试进行证书捆绑。

“all”:这是默认行为,将尝试加载所有内容,包括证书包、sctl、OCSP、颁发者和密钥。

“bundle”: 当配置中指定的文件不存在时,HAProxy 将尝试加载一个证书捆绑包。证书捆绑包仅在前端侧进行管理,对后端证书无效。

从 HAProxy 2.3 开始,证书包不再加载到同一个 OpenSSL 证书存储中,而是将每个证书加载到独立的存储中,这等效于声明多个 “crt”。要实现此功能,需使用 OpenSSL 1.1.1 或更高版本。这意味着证书包现在仅用于向后兼容,不再强制要求用于混合 RSA/ECC 绑定配置。

要将这些 PEM 文件关联为 HAProxy 识别的“证书捆绑包”,文件名必须按照以下方式命名:所有需捆绑的 PEM 文件必须具有相同的基名,并附加表示密钥类型的后缀。目前支持三种后缀:rsa、dsa 和 ecdsa。例如,若 www.example.com 包含两个 PEM 文件,分别为 RSA 文件和 ECDSA 文件,则文件名必须分别为 “example.pem.rsa” 和 “example.pem.ecdsa”。文件名的前缀部分可任意指定;仅后缀部分具有意义。要将此捆绑包加载至 HAProxy,仅需指定基名即可:

示例:bind:8443 ssl crt example.pem

请注意,后缀不会传递给 HAProxy;这会指示 HAProxy 查找证书捆绑包。

HAProxy 会将捆绑包中的所有 PEM 文件当作在多个 “crt” 中分别配置一样进行加载。

证书包加载不再影响目录加载,因为文件已分别加载。

在命令行界面中,证书包被视为独立文件,提交时必须包含证书包扩展名。

支持 OCSP 文件(.ocsp)、颁发者文件(.issuer)、证书透明度(.sctl)以及私钥(.key)的多证书捆绑。

“sctl”:对每个 crt 关键字尝试加载 “<basename>.sctl”。若为后端证书提供该文件,将尝试加载,但不会产生任何功能影响。

“ocsp”: 为每个 crt 关键字尝试加载 “<basename>.ocsp”。若为后端证书提供该文件,将尝试加载,但不会产生任何功能影响。

“issuer”: 若 OCSP 文件的颁发者未在 PEM 文件中提供,则尝试加载 “<basename>.issuer”。若为后端证书提供,将被加载,但不会产生任何功能影响。

key: 如果私钥未通过 PEM 文件提供,请尝试加载包含私钥的文件 “<basename>.key”。

默认行为为 “all”。

示例:

ssl-load-extra-files bundle sctl
ssl-load-extra-files sctl ocsp issuer
ssl-load-extra-files none

另请参阅:“crt”,第 5.1 节 关于绑定选项,以及第 5.2 节 关于服务器选项。

ssl-security-level <number>

ssl-security-level <number>

该指令允许选择如 https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_security_level.html 所述的 OpenSSL 安全级别。安全级别将应用于 HAProxy 中的每个 SSL 上下文。仅支持 0 至 5 之间的数值。

默认值取决于所用 OpenSSL 版本、发行版以及库的编译方式。

该指令要求至少使用 OpenSSL 1.1.1 版本。

ssl-server-verify [none|required]

ssl-server-verify [none|required]

服务器端 SSL 验证的默认行为。若设置为 ’none’,则不验证服务器证书。默认值为 ‘required’,除非通过命令行选项 ‘-dV’ 强制指定。

ssl-skip-self-issued-ca

ssl-skip-self-issued-ca

自签名 CA,即 x509 根 CA,是证书链验证的锚点:作为服务器无用,客户端必须持有。标准配置需确保此类 CA 不包含在 PEM 文件中。此选项允许将此类 CA 保留在 PEM 文件中,但不发送给客户端。使用场景是提供 OCSP 发行者,无需 ‘.issuer’ 文件,并可通过 ‘issuers-chain-path’ 共享。此设置适用于所有无中间证书的证书。对 BoringSSL 无效,.issuer 字段被忽略,因 OCSP 位无需该信息。要求至少使用 OpenSSL 1.0.2。

stats calculate-max-counters [on|off]

stats calculate-max-counters [on|off]

启用或禁用统计信息最大值计数器的计算。若无需使用,禁用可略微提升性能。默认值为启用。

stats maxconn <connections>

stats maxconn <connections>

默认情况下,统计套接字最多允许 10 个并发连接。可以使用 “stats maxconn” 修改此值。

stats socket [<address:port>|<path>] [param*]

stats socket [<address:port>|<path>] [param*]

将 Unix 套接字绑定到 <path>,或将 TCPv4/v6 地址绑定到 <address:port>。连接至该套接字将返回各种统计信息输出,甚至允许发出某些命令以更改部分运行时设置。请参阅 本指南第 9.3 节 “Unix 套接字命令”以获取更多详细信息。

所有 “bind” 行支持的参数均受支持,例如用于限制某些用户或其访问权限。请参阅 第 5.1 节 获取更多信息。

stats timeout <timeout, in milliseconds>

stats timeout <timeout, in milliseconds>

默认情况下,统计信息套接字的超时时间为 10 秒。可以使用“stats timeout”更改此值。该值必须以毫秒为单位指定,或后缀时间单位之一:{ us, ms, s, m, h, d }。

stats-file <path>

stats-file <path>

用于生成 HAProxy 统计信息文件的路径。HAProxy 启动时会将其内部计数器预加载该文件中的值。使用 CLI 命令“dump stats-file”可生成此类统计信息文件。详情请参见管理手册。

stress-level <level>

stress-level <level>

激活用于对 HAProxy 二进制文件施加压力的备用代码。级别为 0 到 9 之间的整数。默认值 0 表示禁用所有压力执行。级别 1 到 9 将逐步增加对 HAProxy 二进制文件的压力。请注意,使用任何正值会显著影响性能。因此,除非出于调试目的且经开发者请求,否则不得启用。

strict-limits

strict-limits

在 setrlimit 失败时使进程在启动阶段失败。HAProxy 会根据已计算的结果尝试设置最佳的 setrlimit。若设置失败,将发出警告。此选项用于确保当这些限制失败时,HAProxy 明确失败。默认启用。可通过在选项前加上 “no” 关键字强制禁用。

thread-group <group> [<thread-range>...]

thread-group <group> [<thread-range>...]

此设置仅在编译时启用了线程支持的情况下可用。它用于列举将组成线程组 <group> 的线程列表。线程编号与组编号均从 1 开始。线程范围可通过单一线程编号指定,或通过指定下限和上限并以连字符 ‘-’ 分隔来定义(例如 “1-16”)。未分配的线程将自动分配至未分配的线程组,且通过本指令定义的线程组不会接收超过所定义数量的线程。多次定义同一组将覆盖先前的定义,以最新定义为准。另请参见 “nbthread” 和 “thread-groups”。

thread-groups <number>

thread-groups <number>

此设置仅在编译时启用了线程支持的情况下可用。它可使 HAProxy 将其线程划分为 <number> 个独立的组。当前默认值为 1。通过线程组可减少线程间的共享以降低竞争,但需付出额外的配置成本。这也是使用超过 64 个线程的唯一方式,因为每个组最多可配置 64 个线程。组的最大数量在编译时配置,默认值为 16。参见“nbthread”。

thread-hard-limit <number>

thread-hard-limit <number>

此设置用于强制限制线程数量,无论是自动检测的,还是配置指定的。

在某些操作系统中,线程数量会自动检测,此时在通用且可移植的配置中,可能希望线程数量低于 CPU 核心数。实际上,尽管 “nbthread” 会强制设置线程数,若该值高于可用 CPU 数量,将触发警告并导致性能下降;而 thread-hard-limit 仅对最大值进行上限限制,自动将线程数量限制在不超过该值,但不会对低于该值的情况进行干预。若 “nbthread” 被强制设置为更高值,则 thread-hard-limit 优先生效,并发出警告,以便修复配置异常。默认情况下无限制。参见 “nbthread”。

uid <number>

uid <number>

将进程的用户 ID 更改为 <number>。建议该用户 ID 专用于 HAProxy 或少量相似的守护进程。HAProxy 必须以超级用户权限启动,才能切换至其他用户。参见“gid”和“user”。

ulimit-n <number>

ulimit-n <number>

设置每个进程的最大文件描述符数量为 <number>。默认情况下,该值会自动计算,因此建议不要使用此选项。若仅意图限制文件描述符数量,建议改用 “fd-hard-limit”。

请注意,动态服务器不参与此自动资源计算。若使用大量动态服务器,可能需要手动指定该值。

另请参阅:fd-hard-limit、maxconn

绑定 Unix 域套接字,可选参数包括: - prefix <prefix> - mode <mode> - user <user> - uid <uid> - group <group> - gid <gid>

修复在 “bind” 语句中声明的 Unix 监听套接字的常见设置。此功能主要用于简化 Unix 套接字的声明,并降低出错风险,因为这些设置通常必需,但又与进程相关。<prefix> 设置可用于强制所有套接字路径相对于该目录。这可能用于访问另一个组件的 chroot 环境。请注意,这些路径在 HAProxy 执行 chroot 之前已被解析,因此均为绝对路径。<mode>、<user>、<uid>、<group> 和 <gid> 的含义与 “bind” 语句中同名设置完全相同。若两者均被指定,“bind” 语句具有优先权,即 “unix-bind” 设置可视为进程级默认设置。

unsetenv [<name> ...]

unsetenv [<name> ...]

移除参数中指定的环境变量。在某些操作过程中,用户环境偶尔会继承一些敏感信息,此功能可用于隐藏这些信息。未存在的变量将被静默忽略,因此操作完成后可确保这些变量均不存在。更改立即生效,配置文件中的下一行将无法再访问这些变量。参见“setenv”、“presetenv”和“resetenv”。

user <user name>

user <user name>

与 “uid” 类似,但使用用户名称 <user name> 在 /etc/passwd. 中的 UID。另请参阅 “uid” 和 “group”。

node <name>

node <name>

仅允许使用字母、数字、连字符和下划线,与 DNS 名称规则一致。

此语句在高可用性配置中非常有用,当两个或多个进程或服务器共享同一 IP 地址时。通过在所有节点上设置不同的 node-name,即可立即识别出正在处理流量的服务器。

wurfl-cache-size <size>

wurfl-cache-size <size>

设置 WURFL 用户代理缓存大小。为加快查找速度,已处理的用户代理将被保留在 LRU 缓存中:

  • “0” :不使用缓存。
  • <size>:LRU 缓存的元素数量。

请注意,此选项仅在 HAProxy 编译时将 USE_WURFL 设置为 1 时可用。

wurfl-data-file <file path>

wurfl-data-file <file path>

用于提供设备检测服务的 WURFL 数据文件路径。该文件必须对 HAProxy 可访问,并具备相应的权限。

请注意,此选项仅在 HAProxy 编译时将 USE_WURFL 设置为 1 时可用。

wurfl-information-list [<capability>]*

wurfl-information-list [<capability>]*

以空格分隔的 WURFL 功能、虚拟功能及属性名称列表,这些名称将用于注入的头中。功能和虚拟功能名称的完整列表可在 Scientiamobile 官网获取:

https://www.scientiamobile.com/wurflCapability

有效的 WURFL 属性包括:

  • wurfl_id 包含匹配设备的设备 ID。

  • wurfl_root_id 包含匹配设备的设备根 ID。

  • wurfl_isdevroot 用于判断匹配的设备是否为根设备。可能的取值为 “TRUE” 或 “FALSE”。

  • wurfl_useragent 来自此特定 Web 请求的原始用户代理。

  • wurfl_api_version 包含一个表示当前所用 Libwurfl API 版本的字符串。

  • wurfl_info 一个包含已解析的 wurfl.xml 信息及其完整路径的字符串。

  • wurfl_last_load_time 包含 WURFL 上次成功加载的 UNIX 时间戳。

  • wurfl_normalized_useragent 已归一化的用户代理。

请注意,此选项仅在 HAProxy 编译时将 USE_WURFL 设置为 1 时可用。

wurfl-information-list-separator <char>

wurfl-information-list-separator <char>

用于分隔包含 WURFL 结果的响应头中各值的字符。若未设置,则默认使用逗号(,)。

请注意,此选项仅在 HAProxy 编译时将 USE_WURFL 设置为 1 时可用。

wurfl-patch-file [<file path>]

wurfl-patch-file [<file path>]

WURFL 补丁文件路径列表。请注意,补丁在启动期间加载,因此在 chroot 之前。

请注意,此选项仅在 HAProxy 编译时将 USE_WURFL 设置为 1 时可用。

3.2. 性能调优

busy-polling

busy-polling

避免处理器睡眠以降低延迟

在某些情况下,尤其是在支持可变频率的处理器上处理低延迟,或在虚拟机中运行时,每当进程使用轮询器等待 I/O 操作,处理器可能长时间进入睡眠状态,或被分配给其他虚拟机,从而导致延迟显著升高。此选项通过在轮询器上始终使用空超时来防止处理器睡眠,从而提供解决方案。这可显著降低延迟(实测降低 30 至 100 微秒),但可能带来处理器过热的风险。该选项也可用于线程,但若线程绑定不当,可能导致严重冲突,造成性能下降,并在 “show info” 输出中显示 CPU 被窃取字段值过高,表明存在配置错误的线程。使用此选项时,务必避免让进程与网络中断共享同一处理器。同时,建议避免在共享同一核心的多个 CPU 线程上使用。该选项默认禁用。若已启用,仍可通过在选项前添加 “no” 关键字强制禁用。该选项对 “select” 和 “poll” 轮询器无效。

此选项在无缝重载的上下文中会自动禁用旧进程;当多个进程在一段时间内仍保留以等待当前连接结束时,可避免过多的 CPU 竞争。

max-spread-checks <delay in milliseconds>

max-spread-checks <delay in milliseconds>

默认情况下,HAProxy 会将健康检查的起始时间分散到群组中所有服务器的最小健康检查间隔内。其原则是避免对运行在同一服务器上的服务造成过大的冲击。但当使用较长的检查间隔(10 秒或更长)时,群组中最后的服务器需要一段时间才会开始被测试,这可能带来问题。该参数用于强制设定首次检查与最后一次检查之间的延迟上限,即使服务器的检查间隔较大也适用。当服务器使用较短的检查间隔时,其间隔仍会被遵守。

maxcompcpuusage <number>

maxcompcpuusage <number>

设置 HAProxy 在压缩新请求或降低当前请求压缩级别前可达到的最大 CPU 使用率。其工作方式类似于 ‘maxcomprate’,但测量的是 CPU 使用率而非传入数据带宽。该值以 HAProxy 所用 CPU 的百分比表示。值为 100 时表示禁用限制。默认值为 100。设置较低的值可防止压缩操作拖慢整个进程并避免引入高延迟。

maxcomprate <number>

maxcomprate <number>

设置每个进程的输入压缩速率上限为 <number> 千字节每秒。对于每个流,若达到上限,则在流过程中降低压缩级别。若在流开始时即达到上限,则该流将完全不进行压缩。若未达到上限,压缩级别将提升至 tune.comp.maxlevel。值为零表示无限制,此为默认值。

maxconn <number>

maxconn <number>

设置每个进程的最大并发连接数为 <number>。这等价于命令行参数 “-n”。通过命令行参数 “-n” 提供的值将优先于全局段中设置的 maxconn 值。HAProxy 进程也可在编译时使用 SYSTEM_MAXCONN 变量,此时该变量作为系统级 maxconn 上限。同样,命令行参数 “-n” 可在运行时绕过已设置的 SYSTEM_MAXCONN 限制。当达到 maxconn 时,代理将停止接受新的连接。进程的软文件描述符限制(可通过 “ulimit -n” 命令获取)将根据提供的 maxconn 值自动调整。参见 “ulimit-n”。请注意:在某些平台上,“select” 轮询器无法可靠地使用超过 1024 个文件描述符。若你的平台仅支持 select 且启动时报告 “select FAILED”,需降低 maxconn 值直至正常工作(通常略低于 500)。若未设置 maxconn 值,系统将基于 “ulimit -nH” 命令报告的当前文件描述符限制自动计算该值(取硬限制与软限制中的最大值),随后自动值可能被 “fd-hard-limit” 和内存限制进一步缩减,若后者通过 “-m” 命令行选项强制启用。自动值还取决于缓冲区大小、压缩所用内存、SSL 缓存大小,以及是否启用 SSL 和相应的 maxsslconn(后者也可为自动值)。

另请参阅:fd-hard-limit、ulimit-n

maxconnrate <number>

maxconnrate <number>

设置每进程每秒最大连接数为 <number>。当达到此限制时,代理将停止接受连接。该设置可用于限制全局容量,而不受各前端容量的限制。请注意,此设置仅可用作服务保护措施,因为当达到限制时,前端之间未必能公平分配连接,因此建议同时将每个前端的连接数限制为接近其预期份额的值。此外,降低 tune.maxaccept 可提升公平性。

maxpipes <number>

maxpipes <number>

设置每个进程的最大管道数量为 <number>。目前,管道仅由基于内核的 TCP 拼接功能使用。由于管道包含两个文件描述符,因此“ulimit-n”值将相应增加。默认值为 maxconn/4,对于大多数高负载场景而言似乎已足够。拼接代码会动态分配和释放管道,并可在必要时回退至标准复制,因此将此值设置过低可能仅影响性能。

maxsessrate <number>

maxsessrate <number>

设置每进程每秒最大会话数为 <number>。当达到此限制时,代理将停止接受连接。该设置可用于限制全局容量,而不受各前端容量的限制。请注意,此设置仅可用作服务保护措施,因为达到限制时各前端之间未必能公平分配资源,因此建议同时将每个前端的容量限制为接近其预期份额的值。此外,降低 tune.maxaccept 可提升公平性。

maxsslconn <number>

maxsslconn <number>

设置每个进程的最大并发 SSL 连接数为 <number>。默认情况下,不存在 SSL 特定的限制,这意味着全局的 maxconn 设置将适用于所有连接。设置此限制可避免 OpenSSL 占用过多内存,从而在 malloc 返回 NULL 时导致崩溃(因为 OpenSSL 不可靠地检查此类情况)。请注意,该限制同时适用于入站和出站连接,因此一个解密后又加密的连接计为 2 个 SSL 连接。如果未设置此值,但已施加内存限制,则该值将根据内存限制、maxconn、缓冲区大小、压缩所用内存、SSL 缓存大小以及前端、后端或两者中是否启用 SSL 自动计算得出。若在存在内存限制的情况下,maxconn 和 maxsslconn 均未指定,HAProxy 将自动调整这些值,以确保 100% 的连接均可通过 SSL 建立,且无风险,并考虑启用 SSL 的端点(前端、后端或两者)。

maxsslrate <number>

maxsslrate <number>

设置每进程每秒最大 SSL 会话数为 <number>。当达到此限制时,SSL 监听器将停止接受连接。该设置可用于限制全局 SSL CPU 使用率,而不受各前端容量的影响。请注意,此设置仅可用作服务保护措施,因为达到限制时各前端之间未必能公平分配资源,因此建议同时将每个前端的值限制在接近其预期份额的范围内。还请注意,会话数在进入 SSL 栈之前即被计入,而非之后,这同样可防止不良握手对栈造成影响。此外,降低 tune.maxaccept 可提升公平性。

maxzlibmem <number>

maxzlibmem <number>

设置每个进程可用于 zlib 的最大内存容量(单位:MB)。当达到最大值时,若内存不可用,后续流将不再进行压缩。设为 0 时表示无限制。默认值为 0。可通过 Unix 套接字执行 “show info” 命令,在 “MaxZlibMemUsage” 行查看该值(单位:字节),zlib 实际使用的内存为 “ZlibMemUsage”(单位:字节)。

no-memory-trimming

no-memory-trimming

禁用在内存不足或重载时尝试回收大量内存的几个时刻的内存缩减(“malloc_trim”)。缩减内存会强制系统分配器扫描所有未使用区域并释放它们。通常认为这是个良好动作,可在旧进程几乎不再使用内存时为新进程腾出更多可用内存。但处理数万至数十万并发连接的某些系统可能经历严重的内存碎片,导致此释放操作耗时极长。在此期间,进程不再处理任何流量,不再接受新连接,部分健康检查甚至可能失败,监控守护进程也可能触发并终止无响应的进程,留下巨大的核心转储文件。若发生此类情况,建议使用此选项禁用内存缩减,停止尝试对新进程保持友好。请注意,高级内存分配器通常不受此类问题影响。

noepoll

noepoll

禁用 Linux 上“epoll”事件轮询系统的使用。其效果等同于命令行参数 “-de”。下一个使用的轮询系统通常为 “poll”。参见 “nopoll”。

noevports

noevports

禁用在基于 Solaris 10 及更高版本的 SunOS 系统上使用事件端口事件轮询系统。其效果等同于命令行参数 “-dv”。后续使用的轮询系统通常为 “poll”。参见 “nopoll”。

nogetaddrinfo

nogetaddrinfo

禁用使用 getaddrinfo(3) 进行名称解析。等效于命令行参数 “-dG”。已弃用的 gethostbyname(3) 将被使用。

nokqueue

nokqueue

禁用在 BSD 上使用“kqueue”事件轮询系统。其效果等同于命令行参数“-dk”。下一个使用的轮询系统通常为“poll”。参见“nopoll”。

noktls

noktls

禁用 ktls 的使用。其效果等同于命令行参数 “-dT”。

nopoll

nopoll

禁用“poll”事件轮询系统的使用。其效果等同于命令行参数“-dp”。下一个使用的轮询系统将是“select”。由于“poll”在 HAProxy 支持的所有平台上均可用,因此应无需禁用它。另请参见“nokqueue”、“noepoll”和“noevports”。

noreuseport

noreuseport

禁用 SO_REUSEPORT 的使用——参见 socket(7)。其效果等同于命令行参数 “-dR”。

nosplice

nosplice

禁用 Linux 上套接字之间的内核 TCP 拼接功能。该选项等效于命令行参数 “-dS”。数据将改用传统的、更具可移植性的 recv/send 调用进行复制。内核 TCP 拼接仅适用于部分较新的 2.6 内核版本。2.6.25 至 2.6.28 之间的大多数版本存在缺陷,会导致转发损坏的数据,因此不得使用。当存在疑虑时,该选项可更方便地全局禁用内核拼接。另请参见 “option splice-auto”、“option splice-request” 和 “option splice-response”。

profiling.memory { on | off }

profiling.memory { on | off }

启用(on)或禁用(off)按功能的内存分析。该功能将记录进程内(包括库)任意位置的 malloc/calloc/realloc/free 调用使用统计信息,并可通过 CLI 命令 “show profiling” 报告。此功能主要用于在观察到异常内存使用且无法通过池及其他信息解释时进行排查。性能开销通常约为 1%,在高度多线程的机器上可能略高,因此通常适用于生产环境。也可通过 CLI 命令 “set profiling memory” 在运行时实现相同效果,请参阅管理手册。

profiling.tasks { auto | on | off | lock | no-lock | memory | no-memory }*

profiling.tasks { auto | on | off | lock | no-lock | memory | no-memory }*

启用(‘on’)或禁用(‘off’)任务级 CPU 性能分析。设置为 ‘auto’ 时,当线程在 “avg_loop_us” 活动字段中报告的平均延迟达到或超过 1000 微秒时,性能分析将自动开启;当延迟回落至 990 微秒以下时,性能分析将自动关闭(该值为最近 1024 次循环的平均值,因此不会快速波动,且能显著平滑短时峰值)。在系统过载、容器或虚拟机环境中,也可能偶尔自发触发,或在系统发生交换(swap)时触发(负载均衡器上绝对不应发生交换)。

当启用任务分析功能时,HAProxy 还可收集每个任务持有锁或等待锁所花费的时间,以及在池缓存未命中情况下等待内存分配成功所花费的时间。这些信息有时有助于理解延迟的某些成因。为此,可额外传递以下关键字:lock(启用锁时间收集)、no-lock(禁用锁时间收集)、memory(启用内存分配时间收集)或 no-memory(禁用内存分配时间收集)。默认情况下这些功能未启用,因为它们在高负载系统上可能带来不可忽略的 CPU 开销(3% 至 10%)。请注意,仅在实际运行分析时才会产生开销,因此在“auto”模式下,仅当 HAProxy 决定开启分析时才会出现该开销。

按任务进行 CPU 性能分析可方便地报告时间消耗位置以及各请求对其他请求的影响。启用该功能通常对整体性能的影响小于 1%,因此建议保持默认的 ‘auto’ 值,仅在识别出问题时才启用。该功能需要系统支持带有时钟标识符 CLOCK_MONOTONIC 和 CLOCK_THREAD_CPUTIME_ID 的 clock_gettime(2) 系统调用,否则报告的时间将为零。可通过 CLI 使用 “set profiling” 动态更改此选项。

spread-checks <0..50, in percent>

spread-checks <0..50, in percent>

有时希望避免以精确间隔向服务器发送代理和健康检查,例如当多个逻辑服务器位于同一物理服务器上时。借助此参数,可在 0 至 +/- 50% 之间引入检查间隔的随机性。数值在 2 至 5 之间时,效果似乎较好。默认值仍为 0。

ssl-engine <name> [algo <comma-separated list of algorithms>]

ssl-engine <name> [algo <comma-separated list of algorithms>]

设置 OpenSSL 引擎为 <name>。可通过命令 “openssl engine” 获取 <name> 的有效值列表。该语句可多次使用,用于启用多个加密引擎。引用不支持的引擎将导致 HAProxy 无法启动。请注意,许多引擎在现代处理器上会导致 HTTPS 性能低于纯软件实现。可选命令 “algo” 使用 OpenSSL 函数 ENGINE_set_default_string() 设置引擎默认提供的算法。值 “ALL” 表示使用引擎进行所有加密操作。若未指定算法列表,则默认使用 “ALL”。可指定以逗号分隔的不同算法列表,包括:RSA、DSA、DH、EC、RAND、CIPHERS、DIGESTS、PKEY、PKEY_CRYPTO、PKEY_ASN1。此格式与 OpenSSL 配置文件所用格式相同: https://www.openssl.org/docs/man1.0.2/apps/config.html

HAProxy 版本 2.6 已禁用默认构建中对引擎的支持。此选项仅在 HAProxy 编译时启用了相关支持后才可用。如需使用 ssl-engine,可使用 USE_ENGINE=1 标志重新编译 HAProxy。

ssl-mode-async

ssl-mode-async

向 SSL 上下文添加 SSL_MODE_ASYNC 模式。若使用支持异步的 SSL 引擎,此模式可启用异步 TLS I/O 操作。当前实现支持最多 32 个引擎。OpenSSL 的 ASYNC API 不支持移动读/写缓冲区,且与 HAProxy 的缓冲区管理机制不兼容。因此,异步模式在读/写操作中被禁用(仅在初始连接和重新协商握手阶段启用)。

tune.applet.zero-copy-forwarding { on | off }

tune.applet.zero-copy-forwarding { on | off }

启用(‘on’)或禁用(‘off’)应用程序的零拷贝数据转发功能。默认情况下已启用。

另请参阅:tune.disable-zero-copy-forwarding。

tune.buffers.limit <number>

tune.buffers.limit <number>

设置每个进程可分配的缓冲区数量的硬性上限。默认值为 0,表示无限制。该限制会自动调整,以满足紧急情况下的预留缓冲区需求,从而避免用户进行复杂的计算。强制设置此值特别有助于限制进程可占用的内存总量,同时保持合理的运行行为。当达到此限制时,请求缓冲区的任务将等待其他缓冲区被释放后才能继续。在大多数情况下,等待时间极短且不可察觉,前提是限制值保持合理。然而,某些历史限制已削弱了该机制的可靠性,已知在持续资源短缺的特定情况下,部分任务可能冻结,直至超时,因此建议仅在绝对必要时才使用此设置。

tune.buffers.reserve <number>

tune.buffers.reserve <number>

设置每个线程在内存不足导致内存分配失败时,预先分配并仅用于该情况的缓冲区数量。最小值为 0,默认值为 4。除非核心开发者针对特定原因建议修改,否则用户无需更改此值。

tune.bufsize <size>

tune.bufsize <size>

设置缓冲区大小为指定值(以字节为单位)。较小的值可在相同内存占用下支持更多流,较大的值则有助于某些具有超大 Cookie 的应用正常运行。默认值为 16384,可在构建时修改。强烈建议不要更改此默认值,过低的值可能导致统计信息等部分服务失效,而高于默认值的设置会增加内存使用量,可能引发系统内存不足。若增大该值,必须相应地将全局 maxconn 参数按相同比例减小。此外,使用 HTTP/2 时,该值必须为 16384 或更大。若 HTTP 请求大小超过 (tune.bufsize - tune.maxrewrite),HAProxy 将返回 HTTP 400(错误请求)错误。同理,若 HTTP 响应大小超过该值,HAProxy 将返回 HTTP 502(错误网关)错误。请注意,使用此参数设置的值在 32 位机器上会自动向上取整至下一个 8 的倍数,在 64 位机器上则取整至下一个 16 的倍数。

tune.bufsize.large <size>

tune.bufsize.large <size>

设置大缓冲区的大小(以字节为单位)。默认情况下,大缓冲区支持未启用,必须显式设置此值以启用。

这些缓冲区专为某些特定场景设计,在不改变常规缓冲区大小的前提下,需缓冲更多数据。大缓冲区不会被隐式使用。

请注意,当配置较大的缓冲区时,每个线程在启动期间将为内部使用分配三个特殊的大缓冲区。

tune.bufsize.small <size>

tune.bufsize.small <size>

设置小缓冲区的大小(字节)。默认值为 1024。

这些缓冲区专为某些内存使用受限的特定场景设计,此时似乎无需分配完整的缓冲区。然而,若小缓冲区不足以满足需求,系统将自动重新分配,切换至标准大小的缓冲区。

目前,该功能仅由 HTTP/3 协议自动使用以发出响应头。 对于其他情况,可通过 “use-small-buffers” 选项为特定代理启用小缓冲区支持。

另请参阅:option use-small-buffers

tune.cli.max-payload-size <size>

tune.cli.max-payload-size <size>

设置 CLI 上传递给命令的有效负载的最大允许大小。

在命令行界面(CLI)中,命令行受缓冲区大小限制。这意味着所有命令及其参数必须能够容纳在缓冲区中以供处理,不包括可传递给命令行最后一个命令的有效负载。如有必要,该有效负载可分配至专用区域。其大小受此参数限制。默认值为 128KB。

尽管该值对大多数使用场景已足够高,但若进行修改,必须谨慎选择。过大的值可能影响 HAProxy 的性能。根据具体命令,过大的负载可能需要较长时间处理,甚至可能触发看门狗机制。

请参阅管理手册以获取 CLI 的详细信息。

tune.comp.maxlevel <number>

tune.comp.maxlevel <number>

设置最大压缩级别。压缩级别会影响压缩过程中的 CPU 使用率。每个使用压缩的流均会以该值初始化压缩算法。默认值为 1。

tune.defaults.purge

tune.defaults.purge

为支持动态后端,所有命名的 defaults 段在解析后均会保留在内存中。这是必要的,因为运行时添加的后端必须基于命名的 defaults 段进行配置。

如果默认配置实例数量较多,此操作可能消耗大量内存。在此情况下,若无需动态后端功能,可使用此选项在解析后强制删除 defaults 段。但必须保留被引用的 defaults 段,因为其中包含无法被引用代理复制的设置。例如,当 defaults 段定义了 TCP/HTTP 规则或 tcpcheck 规则集时即属此类情况。

tune.disable-fast-forward

tune.disable-fast-forward

禁用数据快速转发。该机制通过直接在侧边之间传递数据而不唤醒流来优化数据转发。通过此指令,可禁用此优化。请注意,该指令同时禁用任何内核 TCP 拼接以及零拷贝转发。此命令并非用于常规使用,通常仅在复杂调试会话中由开发者建议使用。

tune.disable-zero-copy-forwarding

tune.disable-zero-copy-forwarding

全局禁用数据的零拷贝转发。该机制通过避免使用通道缓冲区来优化数据快速转发。通过此指令,可禁用此项优化。请注意,该指令同时也会禁用任何内核 TCP 拼接功能。

另请参阅:tune.pt.zero-copy-forwarding、tune.applet.zero-copy-forwarding、tune.h1.zero-copy-fwd-recv、tune.h1.zero-copy-fwd-send、tune.h2.zero-copy-fwd-send、tune.quic.zero-copy-fwd-send

tune.epoll.mask-events <event[,...]>

tune.epoll.mask-events <event[,...]>

与 epoll 机制相关的已知问题

在 HAProxy 的发展历程中,曾遇到若干由 Linux 内核 epoll 机制中的缺陷引发的复杂问题。此类问题通常极为罕见,且仅在报告者特定环境中可复现,通常只能通过禁用 epoll 并切换至 poll 模式来规避,这在高性能环境中并不理想。每次问题仅影响极少数(且罕见)的事件类型,因此提供屏蔽这些事件的能力,可构成更可接受的临时解决方案。本选项通过允许静默忽略若干不常见的事件,并以输入事件(报告未指定的入站事件)替代,实现此功能。其效果为避免在某些位置触发快速错误处理路径,仅使用通用处理路径。除非经专家指导,用于诊断或规避内核缺陷,否则不得使用此选项。

该选项接受一个参数,参数为以逗号分隔的单词列表,每个单词指定要屏蔽的事件。当前支持的事件列表如下:- “err”:屏蔽 EPOLLERR 事件 - “hup”:屏蔽 EPOLLHUP 事件 - “rdhup”:屏蔽 EPOLLRDHUP 事件

示例:

# mask all non-traffic epoll events:
tune.epoll.mask-events err,hup,rdhup

tune.events.max-events-at-once <number>

tune.events.max-events-at-once <number>

设置异步任务处理器(来自 event_hdl API)一次可处理的事件数量。<number> 应在 1 到 10000 之间。数值过大可能导致因任务在无中断情况下执行繁重工作而引发线程竞争;另一方面,数值过小则可能导致任务因每次运行无法处理足够事件而持续被重新调度,无法跟上事件生产者的节奏。默认值可在编译时强制指定,否则默认为 100。

tune.fail-alloc

tune.fail-alloc

若使用 DEBUG_FAIL_ALLOC 编译或以 “-dMfail” 启动,表示内存分配尝试失败的概率百分比。必须介于 0(无失败)至 100(完全失败)之间。此选项有助于调试,确保内存分配失败时能被妥善处理。未设置时,该比例为 0。但命令行选项 “-dMfail” 会自动将其设为 1% 的失败率,因此测试时无需修改配置。

tune.fd.edge-triggered { on | off } [ EXPERIMENTAL ]

tune.fd.edge-triggered { on | off }  [ EXPERIMENTAL ]

启用(‘on’)或禁用(‘off’)支持该模式的文件描述符(FD)的边缘触发轮询模式。当前仅支持 epoll。在某些场景下,此功能可显著减少 epoll_ctl() 调用次数,并略微提升性能。此功能仍处于实验阶段,若存在缺陷可能导致连接冻结,且默认情况下已禁用。

tune.glitches.kill.cpu-usage <number>

tune.glitches.kill.cpu-usage <number>

设置最小 CPU 使用率,范围为 0 到 100,当连接出现过多抖动时将被终止。此设置适用于已达到抖动阈值限制的连接。在某些环境中,长时间连接可能在不造成性能影响的情况下表现异常,此时可能希望即使连接行为异常也予以保留,仅当 CPU 使用率较高时才开始终止此类连接。该参数允许指定:当 CPU 使用率处于或高于此水平时,达到抖动阈值的连接将被主动终止;而当 CPU 使用率低于此水平时则不会终止。请注意,CPU 使用率按线程测量,因此单个异常连接可能被终止。默认值为 0,表示达到抖动阈值的连接将自动被终止。经验法则为:将此值设为通常观测到的 CPU 使用率的两倍,或通常观测到的 CPU 使用率加上空闲使用率的一半(例如,若 CPU 通常达到 60%,则此处设为 80 可能合理)。若未设置 tune.h2.fe.glitches-threshold、tune.quic.fe.sec.glitches-threshold 或 tune.h1.fe.glitches-threshold,此参数无效。另请参见全局参数 “tune.h2.fe.glitches-threshold”、“tune.h1.fe.glitches-threshold” 和 “tune.quic.fe.sec.glitches-threshold”。

tune.h1.be.glitches-threshold <number>

tune.h1.be.glitches-threshold <number>

设置 HTTP/1 后端连接上允许的异常事件阈值,当异常事件数量超过该阈值时,该连接将被自动终止。这可实现对行为异常连接的自动关闭,而无需编写显式规则。默认值为 0,表示未设置阈值,因此不会因任何事件导致连接关闭。典型事件包括:尽管已通过 “accept-unsafe-violations-in-http-response” 接受,但仍格式错误的头。此处的非零值通常应设为数百或数千,以在不影响轻微异常服务器的前提下生效。也可通过使用 “tune.glitches.kill.cpu-usage” 实现仅在 CPU 使用率超过特定水平时才终止连接。请注意,当达到配置阈值的 75% 时,将尝试优雅关闭,方法是为未来流发送 GOAWAY 消息。这确保了轻微异常的连接将在一段时间后停止使用,同时避免中断正在进行的传输。

另请参阅:tune.h1.fe.glitches-threshold、bc_glitches 以及 tune.glitches.kill.cpu-usage

tune.h1.fe.glitches-threshold <number>

tune.h1.fe.glitches-threshold <number>

设置 HTTP/1 前端连接上允许的错误事件阈值,当错误事件数量超过该阈值时,该连接将被自动终止。这可实现对行为异常连接的自动终止,而无需编写显式的规则。默认值为 0,表示未设置阈值,因此不会因任何事件导致连接关闭。典型事件包括:尽管已通过 “accept-unsafe-violations-in-http-request” 接受,但格式不正确的头。此处的非零值通常应设为数百或数千,以在不影响轻微不合规客户端的前提下生效。也可通过使用 “tune.glitches.kill.cpu-usage” 实现仅在 CPU 使用率超过特定水平时终止连接。请注意,当达到配置阈值的 75% 时,将尝试优雅关闭,通过为未来流发送 GOAWAY 通知。这确保轻微不合规的客户端有机会建立新连接并继续正常工作,而不会触发硬关闭,从而避免中断正在进行的传输。

另请参阅:tune.h1.be.glitches-threshold、fc_glitches 和 tune.glitches.kill.cpu-usage

tune.h1.zero-copy-fwd-recv { on | off }

tune.h1.zero-copy-fwd-recv { on | off }

启用(‘on’)或禁用(‘off’)H1 多路复用器的数据零拷贝接收。默认启用。

另请参阅:tune.disable-zero-copy-forwarding、tune.h1.zero-copy-fwd-send

tune.h1.zero-copy-fwd-send { on | off }

tune.h1.zero-copy-fwd-send { on | off }

启用(‘on’)或禁用(‘off’)H1 多路复用器的数据零拷贝发送。默认情况下已启用。

另请参阅:tune.disable-zero-copy-forwarding、tune.h1.zero-copy-fwd-recv

tune.h2.be.glitches-threshold <number>

tune.h2.be.glitches-threshold <number>

设置后端连接的抖动阈值,当连接的抖动次数达到该阈值时,连接将被自动终止。这可实现对行为异常连接的自动终止,而无需编写显式的规则。默认值为 0,表示未设置阈值,因此不会因任何事件导致连接关闭。请注意,某些 H2 服务器在长时间连接期间偶尔会产生少量抖动,因此此处的非零值应设为数百或数千,以确保有效且不影响轻微异常的服务器。也可通过使用 “tune.glitches.kill.cpu-usage” 实现仅在 CPU 使用率超过特定水平时终止连接。请注意,当达到配置阈值的 75% 时,将尝试优雅关闭连接,方法是为未来流发送 GOAWAY 通知。这确保了轻微异常的连接将在一段时间后停止使用,同时避免中断正在进行的传输。

另请参阅:tune.h2.fe.glitches-threshold、bc_glitches 以及 tune.glitches.kill.cpu-usage

tune.h2.be.initial-window-size <number>

tune.h2.be.initial-window-size <number>

设置传出连接的 HTTP/2 初始窗口大小,即服务器在等待 HAProxy 确认前可响应的字节数。此设置仅影响负载内容,不影响头信息。未设置时,采用由 tune.h2.initial-window-size 定义的默认值。适度增大该值可提升下载速度或降低服务器 CPU 使用率,但可能导致客户端间不公平。建议改用 tune.h2.be.rxbuf,该设置不会引发不公平现象。此设置不影响资源使用。

另请参见:tune.h2.initial-window-size。

tune.h2.be.max-concurrent-streams <number>

tune.h2.be.max-concurrent-streams <number>

设置每个出站连接的 HTTP/2 最大并发流数(即单个连接上对服务器的未完成请求数量)。未设置时,将使用 tune.h2.max-concurrent-streams 的默认值。将该值设为低于默认值 100 可能会提升网站的响应速度,但会增加与服务器保持的已建立连接数量。当设置 “http-reuse” 为 “always” 时,建议降低此值,以避免在同一连接上混合过多不同客户端,因为若某个客户端较慢,一种称为“队首阻塞”的机制容易导致共享该连接的所有客户端下载速度出现级联下降(此时建议保持 tune.h2.be.initial-window-size 较低)。强烈建议不要提高此值;部分用户可能发现设置为较低值(通常为 1 至 5)更为理想。

tune.h2.be.max-frames-at-once <number>

tune.h2.be.max-frames-at-once <number>

设置后端连接上一次最多处理的 HTTP/2 入站帧数量。当处理非常大的缓冲区时,将其设置为较低值(几十到几百)可能有助于维持较低延迟,并在多个连接之间实现更好的公平性。默认值为 0,表示不施加任何限制。

tune.h2.be.rxbuf <size>

tune.h2.be.rxbuf <size>

设置出站连接的 HTTP/2 接收缓冲区大小,单位为字节。该大小将向上舍入至 tune.bufsize 的下一个倍数,并在所有上传数据的流(包括 HEADERS 和 DATA 帧)之间共享。无论如何,每个流始终会分配一个缓冲区,未使用的缓冲区中 7/8 的空间将在下载负载的流之间共享,从而显著提升上传性能,并避免在多个客户端共享后端连接且 http-reuse 设置为 “always” 时出现队首阻塞(HoL)。每个流的通告窗口大小会自动调整以反映可用空间,因此实际上无需手动调整 tune.h2.be.initial-window-size。若设置的大小不足以应对所有流,则将使用该最小值。默认值约为 1600k(100 个流,每个流 16kB 缓冲区)。

另请参阅:tune.h2.be.initial-window-size、tune.h2.fe.rxbuf、http-reuse。

tune.h2.fe.glitches-threshold <number>

tune.h2.fe.glitches-threshold <number>

设置前端连接上允许的抖动次数阈值,当连接的抖动次数达到该阈值时,连接将被自动终止。这可实现对行为异常连接的自动终止,而无需编写显式的规则。默认值为 0,表示未设置阈值,因此不会因任何事件导致连接关闭。请注意,某些 H2 客户端在长时间连接期间可能偶尔引发少量抖动,因此此处的非零值应设为数百或数千,以在不影响轻微异常客户端的前提下有效发挥作用。也可通过使用 “tune.glitches.kill.cpu-usage” 实现仅在 CPU 使用率超过特定水平时才终止连接。请注意,当达到配置阈值的 75% 时,将尝试优雅关闭连接,方法是为未来流发送 GOAWAY 消息。这确保了轻微不合规的客户端有机会建立新连接并继续正常工作,而不会触发硬关闭,从而避免中断正在进行的传输。

另请参阅:tune.h2.be.glitches-threshold、fc_glitches 和 tune.glitches.kill.cpu-usage

tune.h2.fe.initial-window-size <number>

tune.h2.fe.initial-window-size <number>

设置传入连接的 HTTP/2 初始窗口大小,即客户端在等待 HAProxy 确认前可上传的字节数。此设置仅影响负载内容(即 POST 请求的正文),不影响头信息。未设置时,采用 tune.h2.initial-window-size 定义的默认值。适当增大该值可提升上传速度。默认值等于 tune.bufsize(16384),在 100 毫秒延迟下可支持每流至少 1.25 Mbps 的带宽,在 1 毫秒延迟下可支持 125 Mbps。该设置不影响资源使用。若设置过大,当页面与大文件上传并行访问时,可能导致客户端响应迟滞。建议改用 tune.h2.fe.rxbuf,该设置不会造成不公平性。

另请参见:tune.h2.initial-window-size。

tune.h2.fe.max-concurrent-streams <number> [args...]

tune.h2.fe.max-concurrent-streams <number> [args...]

设置每个入站连接的 HTTP/2 最大并发流数(即客户端单个连接上未完成的请求数量)。未设置时,将使用 tune.h2.max-concurrent-streams 定义的默认值。在高延迟网络上,对于包含大量小对象的复杂站点,设置大于默认值 100 的值有时可略微改善页面加载时间,但也可能导致客户端一次性占用更多资源,从而增加内存使用。默认值 100 通常已足够,建议不要更改此值。较高的并发度在处理大量连接且每个连接本身使用多个流时,会对处理负载和延迟产生影响,并可能降低拒绝服务攻击的门槛。该命令支持在数字之后添加以下可选参数:

  • rq-load { <number> | auto | ignore }:
The optional argument "rq-load" permits to dynamically adjust the
advertised concurrency based on the executing thread's run-queue load:
as long as the thread's load remains below the indicated threshold, the
configured streams limit will be advertised. When the thread's load
increases beyond the configured limit, the advertised streams limit will be
decreased proportionally to the square of the excess ratio. Target load
levels between 50 and 100 generally show very good moderation under heavy
loads. Alternately, instead of specifying an explicit number, the keyword
accepts "ignore", which is the default and means that the thread's
run-queue load will not be considered to moderate the advertised streams
limit, and "auto", which sets the limit to the "tune.runqueue-depth"
value, which generally provides good results without having to tweak
the configuration any further.
  • min <number>:
This sets the minimum advertised concurrency level when rq-load is used,
even if this results in a higher load than the configured target. This
allows to maintain a good level of interactivity on a site under very
heavy load. The minimum and default value is 1, but values between 5
and 15 can improve user experience.

示例:

tune.h2.fe.max-concurrent-streams 100 rq-load auto min 15

tune.h2.fe.max-frames-at-once <number>

tune.h2.fe.max-frames-at-once <number>

设置前端连接上一次最多处理的 HTTP/2 入站帧数量。当处理非常大的缓冲区时,将其设置为较低值(几十到几百)可能有助于保持低延迟,并在多个连接之间实现更好的公平性。默认值为 0,表示不施加限制。

tune.h2.fe.max-rst-at-once <number>

tune.h2.fe.max-rst-at-once <number>

设置前端连接上同时处理的 HTTP/2 RST_STREAM 的最大数量。当接收到指定数量的 RST_STREAM 帧后,连接处理器将被放入低优先级队列,并在所有其他任务之后处理。将此值设为非常低的数值(1 或几个单位)可能有助于显著降低 RST_STREAM 洪水带来的影响。RST_STREAM 在用户点击浏览器中的停止按钮时确实会发生,但由此引起的额外毫秒延迟通常难以察觉,不过通常能有效显著降低此类洪水造成的负载。默认值为零,表示不施加限制。

tune.h2.fe.max-total-streams <number>

tune.h2.fe.max-total-streams <number>

设置每个入站连接处理的 HTTP/2 最大总流数。达到此限制后,HAProxy 将发送一个优雅的 GOAWAY 帧,通知客户端在所有待处理流关闭后将关闭连接。实际上,客户端在收到该帧后通常会尽快关闭连接,并为后续请求建立新连接。在某些客户端长时间保持连接且导致服务器组内部负载失衡的情况下,这种行为有时是有用且期望的。例如,在某些高度动态的环境中,可能需要动态实例化新的负载均衡器以应对负载增加,而在负载下降后应停止这些实例,同时不中断已建立的连接。通过在此处设置限制,连接将具有有限的生命周期,并会被频繁重连,部分连接可能被建立到其他节点,从而实现现有资源的快速释放。

必须理解,此限制与上方的 “tune.h2.fe.max-concurrent-streams” 存在隐式关联。实际上,HAProxy 会始终接受客户端与前端之间可能正在传输的任何待处理流,因此所声明的限制值将始终自动增加 max-concurrent-streams 中配置的数值,该数值将作为硬性上限,任何不合规客户端超过此上限的行为都将导致连接被关闭。因此,在从日志中统计每个连接的请求数量时,可能观察到的数值介于 max-total-streams 与 (max-total-streams + max-concurrent-streams) 之间,具体取决于客户端创建流的速度。

默认值为 0,表示除协议本身隐含的限制外(2^30 ≈ 10.7 亿)不施加任何限制。数值接近 1000 时,可能已导致大多数客户端无感知延迟的情况下频繁重连。设置过低可能导致因频繁 TLS 重连而增加 CPU 使用率,同时加重页面加载时间。请注意,部分负载测试工具不支持重连,使用此设置时可能报告错误;因此在运行性能基准测试时可能需要禁用该设置。参见 “tune.h2.fe.max-concurrent-streams”。

tune.h2.fe.rxbuf <size>

tune.h2.fe.rxbuf <size>

设置传入连接的 HTTP/2 接收缓冲区大小,单位为字节。该大小将向上舍入至 tune.bufsize 的下一个倍数,并在所有上传数据的流(包括 HEADERS 和 DATA 帧)之间共享。无论如何,每个流始终会分配一个缓冲区,未使用的缓冲区中 7/8 的空间将在上传有效载荷的流之间共享,从而显著提升上传性能。每个流的通告窗口大小会自动调整以反映可用空间,因此实际使用中通常无需手动调整 tune.h2.fe.initial-window-size。若设置的值小于处理所有流所需的最小值,则将采用该最小值。默认值 1600k(100 个流,每个流 16kB 缓冲区)可支持客户端在 100ms RTT 下实现约 130 Mbps 的上传速度。

另请参见:tune.h2.fe.initial-window-size 和 tune.h2.be.rxbuf。

tune.h2.header-table-size <number>

tune.h2.header-table-size <number>

设置 HTTP/2 动态头表大小。默认值为 4096 字节,最大不得超过 65536 字节。较大的值可能有助于某些客户端发送更紧凑的请求,具体取决于其能力。每个 HTTP/2 连接都会消耗此数量的内存。建议不要更改此值。

tune.h2.initial-window-size <number>

tune.h2.initial-window-size <number>

设置 HTTP/2 初始窗口大小的默认值,适用于入站和出站连接。当未设置 tune.h2.fe.initial-window-size 时,该值用于入站连接;当未设置 tune.h2.be.initial-window-size 时,该值用于出站连接。此设置既作为每流的初始值,也作为每流的最小值。默认值为 16384(即 tune.bufsize),在 100 ms 网络延迟下,此值大致允许每流上传带宽不低于 1.25 Mbps,或在 1 ms 本地网络下不低于 125 Mbps。当接收缓冲区使用量低于 tune.h2.be.rxbuf 和 tune.h2.fe.rxbuf 所定义的上限时,未使用的缓冲区将在接收流之间共享。因此,通常无需更改此默认设置。由于更改此默认值会同时提高上传速度并加剧客户端间下载的不公平性,建议改用针对方向的设置 tune.h2.fe.initial-window-size 和 tune.h2.be.initial-window-size。

tune.h2.log-errors { none | connection | stream }

tune.h2.log-errors { none | connection | stream }

设置 H2 解复用器中将生成日志的错误级别。默认值为 “stream”,表示解复用器中遇到的任何解码错误都会触发日志输出。“connection” 值表示仅当错误导致连接失效时才生成日志。最后,“none” 表示任何解码错误都不会生成日志。建议至少设置为 “connection”,以便检测协议异常,即使在困难时期暂时切换至 “none” 也应如此。

tune.h2.max-concurrent-streams <number>

tune.h2.max-concurrent-streams <number>

设置每个连接的默认 HTTP/2 最大并发流数(即单个连接上未完成的请求数量)。当未设置 tune.h2.fe.max-concurrent-streams 时,该值用于入站连接;当未设置 tune.h2.be.max-concurrent-streams 时,该值用于出站连接。默认值为 100。影响因方向而异,请参阅上述两个设置以获取详细信息。建议不要使用此设置,而改用按方向设置的选项。设为零将禁用限制,单个客户端可创建尽可能多的流,只要 HAProxy 可分配即可。强烈建议不要修改此值。

tune.h2.max-frame-size <number>

tune.h2.max-frame-size <number>

设置 HAProxy 向对等节点通告其愿意接收的 HTTP/2 最大帧大小。默认值为 16384 与缓冲区大小(tune.bufsize)中的较大者。无论如何,HAProxy 不会通告支持超过缓冲区大小的帧大小。此设置的主要目的是在使用大缓冲区时,限制最大帧大小的设定。过大的帧大小可能影响性能,或导致某些对等节点行为异常。强烈建议不要更改此值。

tune.h2.zero-copy-fwd-send { on | off }

tune.h2.zero-copy-fwd-send { on | off }

启用(‘on’)或禁用(‘off’) H2 多路复用器的数据零拷贝发送。默认启用。

另请参阅:tune.disable-zero-copy-forwarding

tune.http.cookielen <number>

tune.http.cookielen <number>

设置捕获的 Cookie 的最大长度。此值为“capture cookie xxx len yyy”允许设置的最大值,任何超过该值的配置将自动截断至该值。设置过高可能导致内存浪费,因为所有 Cookie 捕获均会分配此大小的内存空间(共享同一内存池)。该值按每个请求每响应计算,因此每连接分配的内存为该值的两倍。未指定时,默认限制为 63 个字符。建议不要修改此值。

tune.http.logurilen <number>

tune.http.logurilen <number>

设置日志中请求 URI 的最大长度。这可防止日志行中截断包含重要查询字符串的长请求 URI。此设置与 syslog 限制无关。若增大此限制,也应相应增加 ’log … len yyy’ 参数。syslog 守护进程也可能需要特定的配置指令。默认值为 1024。

tune.http.maxhdr <number>

tune.http.maxhdr <number>

设置接收的 HTTP 消息中允许的最大头数量。当消息包含的头数量超过此值(包括首行)时,请求将被拒绝并返回“400 Bad Request”状态码,响应则返回“502 Bad Gateway”状态码。默认值为 101,该值足以满足所有使用场景,考虑到广泛部署的 Apache 服务器也采用相同的限制。在应用程序修复前,适当提高此限制可临时允许存在缺陷的应用程序正常运行。允许的取值范围为 1..32767。请注意,每个新头在每个流中会消耗 32 位内存,因此请勿将此限制设置得过高。

请注意,HTTP/1.1 是文本协议,因此在发送消息时并无特殊限制。消息解析阶段的限制已足够。HTTP/2 和 HTTP/3 为二进制协议,需要编码步骤。在对头进行编码以符合协议限制时,也设置了相应限制。该限制值足够大,但出于故意未予文档化。出于相同原因,解码的初始步骤也应用了相同的限制。

tune.idle-pool.shared { full | on | off }

tune.idle-pool.shared { full | on | off }

控制同一服务器的空闲连接池在多线程间的共享。可设置为在同一线程组内的所有线程中启用(‘on’),在所有线程中启用(‘full’),或禁用(‘off’)。默认值为在同一线程组内的线程间共享连接池(‘on’),以最小化对服务器的持久连接数量,并优化连接复用率。与其它线程组的线程共享连接池可能带来性能影响,因此默认不启用,但在优先考虑最大化连接复用时可能有用。为便于调试或在怀疑 HAProxy 在连接复用方面存在缺陷时,可方便地强制禁用多线程间的空闲连接池共享,并将此选项设为 ‘off’。强烈建议在禁用此选项时,为依赖连接复用以实现高性能的全部服务器设置保守的 “pool-low-conn” 值,否则随着线程数量增加,连接可能被频繁关闭。

tune.idletimer <timeout>

tune.idletimer <timeout>

设置 HAProxy 在认为空缓冲区可能与空闲流相关联之前等待的时长。该设置用于在转发大块和小块数据时,优化调整某些数据包大小。是否使用 splice() 或在 SSL 中发送大缓冲区,由该参数调节。值的单位为毫秒,范围在 0 到 65535 之间。值为 0 表示 HAProxy 不会尝试检测空闲流。默认值为 1000,该值似乎能正确识别终端用户暂停(例如,阅读页面后再点击)。不应更改此值。请检查 tune.ssl.maxrecord。

tune.listener.default-shards { by-process | by-thread | by-group }

tune.listener.default-shards { by-process | by-thread | by-group }

默认情况下,所有“bind”指令将创建单个分片,即一个由进程内所有线程监听的单一套接字。当线程数量较多时,这种做法效率不高,甚至可能在内核中引入显著开销,例如更新轮询状态或向各个线程分发事件。现代操作系统支持入站连接的负载均衡机制,该机制允许将多个套接字绑定到同一地址和端口,并将所有入站连接均匀地分发到这些套接字,使得每个线程仅看到其绑定套接字中等待的连接。这显著降低了内核侧开销,并提升了入站连接路径的性能。

通常通过在“bind”指令中使用“shards”设置来启用此功能,其默认值为 1,表示每个监听器在进程内唯一。在多处理器系统中,建议将默认设置更改为“by-thread”,以确保每个线程始终创建一个监听套接字;或改为“by-group”,以确保每个线程组始终创建一个监听套接字。使用“by-thread”时请注意文件描述符的使用情况,因为每个监听器需要的套接字数量等于线程总数。此外,某些操作系统(如 FreeBSD)对同一地址的套接字数量有限制,最多不超过 256 个。

请注意,“by-group”在默认配置(仅涉及一个线程组)下等同于“by-process”,在不支持该机制的系统上将回退至共享同一套接字。默认设置为“by-group”,在不支持多绑定的系统或套接字族上将回退至“by-process”。

tune.listener.multi-queue { on | fair | off }

tune.listener.multi-queue { on | fair | off }

启用(‘on’ / ‘fair’)或禁用(‘off’)监听器的多队列接受机制,该机制将传入流量分散到所有“bind”指令允许运行的线程,而非由单个线程独占。此机制可实现更平滑的流量分发,并显著提升扩展性,尤其适用于因外部活动(例如网络中断与某一特定线程冲突)导致线程负载不均的环境。默认模式 ‘on’ 通过采样选择连接数最少的线程,优化线程选择。当连接为长连接时,此模式通常为最佳选择,能够有效保持所有线程处于繁忙状态。第二种模式 ‘fair’ 则不考虑当前负载水平,循环遍历所有线程。该模式更适合短连接场景,或在拥有大量线程的机器上使用,此时第一种模式找到负载最低线程的概率较低。最后,可通过设置 ‘off’ 强制禁用负载均衡机制,用于故障排查,或在连接为短连接且操作系统已提供足够良好分发的情况下使用。默认值为 ‘on’。

tune.lua.bool-sample-conversion { normal | pre-3.1-bug }

tune.lua.bool-sample-conversion { normal | pre-3.1-bug }

明确告知 HAProxy 在将 HAProxy 样本对象推送至 Lua 时应如何处理。实际上,当使用原生转换器、从 Lua 脚本中提取样本或使用变量时(仅举几例),HAProxy 会将内部的 smp 类型转换为等效的 Lua 类型。由于历史实现原因,布尔值处理存在歧义:在执行 Lua → HAProxy smp 转换时,布尔值能正确保留;但在执行 HAProxy smp → Lua 转换时,布尔值被错误地转换为整数。这意味着,当从 Lua 中调用返回布尔值的样本提取或转换器时,会返回整数 0 或 1。不幸的是,在 Lua 中,布尔值与整数不可互换。因此,为避免歧义,“tune.lua.bool-sample-conversion” 必须显式设置为 “normal”(表示放弃历史行为以提升一致性)或 “pre-3.1-bug”(强制保留历史行为,防止现有脚本逻辑出现异常)。若未显式设置该选项,且配置中加载了 Lua 脚本,HAProxy 将发出警告,该选项将隐式默认为 “pre-3.1-bug”,以保持与历史行为一致。建议在确认正在使用的 Lua 脚本能够正确处理布尔类型的 HAProxy 样本后,将此选项设置为 “normal”。

该设置必须在任何 “lua-load” 或 “lua-load-per-thread” 指令之前设置才有效,否则将被忽略。

tune.lua.burst-timeout <timeout>

tune.lua.burst-timeout <timeout>

“burst” 执行超时适用于任何 Lua 处理器。如果处理器在超时到达前未能完成或主动让出控制权,将被中止,以防止线程争用,避免流量长时间无法被处理,并最终防止因看门狗触发而导致进程崩溃。与其它 Lua 超时机制不同,burst-timeout 不是基于 yield 累积的,而是确保单次 Lua 执行窗口内所花费的时间不超过配置的超时值。

此处“yield”表示 Lua 执行被有效中断,可能是通过显式调用 Lua 休眠函数(如 core.(m)sleep() 或 core.yield()),或因自动强制休眠(参见 tune.lua.forced-yield)所致,且将在相关任务被设置为重新调度时稍后恢复。并非所有 Lua 处理器均可休眠:必须区分可休眠处理器与不可休眠处理器。

对于可中断的处理器(任务、动作等),达到超时意味着 “tune.lua.forced-yield” 可能过高,降低该值可能改善情况,但也建议检查在 Lua 函数的关键点手动插入 yield 是否有助于缓解问题。这还可能表明处理器在某个无法中断的 Lua 库函数中花费了过多时间。

对于无法放弃的处理器(Lua 转换器、样本提取),这可能仅表示处理器正在进行过多的计算,这可能是由于设计不当所致,因为此类处理器通常会阻塞请求执行流程,应尽快终止以确保请求处理得以继续。此处常见的解决方法是尝试进一步优化 Lua 函数以提升速度,因为减少 “tune.lua.forced-yield” 并无帮助。

此超时仅计算纯 Lua 运行时。若 Lua 执行 core.sleep,睡眠时间不计入超时。默认超时为 1000 ms。

请注意:如果从处理程序中启动了 Lua 垃圾回收周期(无论是显式请求还是在经过一段时间后由 Lua 自动触发),该垃圾回收周期所花费的时间也将被计入。

实际上,无法推断垃圾回收(GC)周期时间,因此在系统饱和时可能导致一些误报(此时 GC 难以跟上进度,并消耗了大部分可用执行时间)。如果出现这种情况,可参考以下解决方向:

- checking if the script could be optimized to reduce lua memory footprint
- fine-tuning lua GC parameters and / or requesting manual GC cycles
  (see: https://www.lua.org/manual/5.4/manual.html#pdf-collectgarbage)
- increasing tune.lua.burst-timeout

将值设为 0 会完全禁用此保护机制。

tune.lua.forced-yield <number>

tune.lua.forced-yield <number>

该指令强制 Lua 引擎在每执行 <number> 条指令后进行一次 yield 操作。 这允许中断长时间运行的脚本,并使 HAProxy 调度器能够处理其他任务,例如接收连接或转发流量。 默认值为:使用 “lua-load-per-thread” 加载的脚本为 10000 条指令;使用 “lua-load” 加载的脚本为 MAX(500, 10000 / nbthread) 条指令(该值被证实为在兼顾性能的同时,有效避免多个线程竞争全局 Lua 锁所导致的线程争用问题的最优选择)。

如果 HAProxy 频繁执行某些 Lua 代码但需要更高的响应性,可降低此值。若 Lua 代码较长且其结果必须用于处理数据,可增加 <number>,但应谨慎设置,因为在多线程环境下可能增加竞争。

tune.lua.log.loggers { on | off }

tune.lua.log.loggers { on | off }

启用(‘on’)或禁用(‘off’)通过当前代理适用的日志记录器记录 LUA 脚本的输出,若存在适用的日志记录器。

默认值为 ‘on’。

tune.lua.log.stderr { on | auto | off }

tune.lua.log.stderr { on | auto | off }

启用(‘on’)或禁用(‘off’)通过 stderr 记录 LUA 脚本的输出。当设置为 ‘auto’ 时,若满足以下任一条件,则通过 stderr 的日志记录将自动启用:

- tune.lua.log.loggers is set to 'off'
- the script is executed in a non-proxy context with no global logger
- the script is executed in a proxy context with no logger attached

请注意,启用后,此日志记录将与通过 tune.lua.log.loggers 配置的日志记录并存。

默认值为 ‘auto’。

tune.lua.maxmem <number>

tune.lua.maxmem <number>

设置每个进程可用于 Lua 的最大内存容量(单位:兆字节)。默认值为 0,表示无限制。必须设置限制,以确保脚本中的缺陷不会导致系统内存耗尽。

tune.lua.openlibs [all | none | <lib>[,<lib>...]]

tune.lua.openlibs [all | none | <lib>[,<lib>...]]

选择在初始化 Lua 状态时加载的 Lua 标准库。参数为从以下集合中选取的库名称组成的逗号分隔列表:table、io、os、string、math、utf8、package、debug。可使用特殊值 “all” 或 “none” 替代列表。“none” 不能与库名称同时使用。默认值为 “all”。

无论此设置如何,基础库和协程库始终会被加载:base 提供 HAProxy 依赖的核心 Lua 函数,而 coroutine 是必需的,因为 HAProxy 用其自身的安全实现覆盖了 coroutine.create()。

请注意,无论此设置如何,HAProxy 默认已阻止 fork() 和新建线程操作,且仅可通过全局指令 “insecure-fork-wanted” 重新启用。进一步限制可加载库的集合可降低 Lua 脚本暴露的攻击面。具体包括: - 省略 “os” 可防止使用 os.execute() 和 os.exit() - 省略 “io” 可防止使用 io.open() 和 io.popen() - 省略 “package” 可防止通过 require() 加载原生 C 模块 - 省略 “debug” 可防止通过 debug.getupvalue()、debug.getmetatable() 或 debug.sethook() 探查 HAProxy 内部结构

示例:

tune.lua.openlibs none                    # only base + coroutine
tune.lua.openlibs string,math,table,utf8  # safe subset, no I/O or OS
tune.lua.openlibs all                     # default, load everything

此设置必须在任何 “lua-load”、“lua-load-per-thread” 或 “lua-prepend-path” 指令之前设置,否则将返回解析错误。

tune.lua.service-timeout <timeout>

tune.lua.service-timeout <timeout>

这是 Lua 服务的执行超时。该设置有助于防止出现无限循环或在 Lua 中花费过多时间。此超时仅计算纯 Lua 运行时时间。若 Lua 执行了睡眠操作,该睡眠时间不计入超时。默认超时时间为 4s。

tune.lua.session-timeout <timeout>

tune.lua.session-timeout <timeout>

这是 Lua 会话的执行超时时间。该设置有助于防止出现无限循环或在 Lua 中花费过多时间。此超时仅计算纯 Lua 运行时时间。若 Lua 执行了睡眠操作,该睡眠时间不计入超时。默认超时时间为 4s。

tune.lua.task-timeout <timeout>

tune.lua.task-timeout <timeout>

用途与 “tune.lua.session-timeout” 相同,但此超时专门用于任务。默认情况下,该超时未设置,因为任务可能在 HAProxy 的整个生命周期内保持活跃。例如,用于检查服务器的任务。

tune.max-checks-per-thread <number>

tune.max-checks-per-thread <number>

设置每个线程上活跃健康检查数量的阈值,当超过该阈值时,线程将主动尝试寻找负载较低的线程来执行健康检查,或将其排队,直到该线程上正在运行的活跃健康检查数量减少。默认值为 0,表示未设置此类限制。在某些环境中,当使用大量线程运行极多昂贵的健康检查时,若负载分布不均,可能导致健康检查在启动时随机超时,尤其是在使用 OpenSSL 3.0 时,其健康检查的 CPU 消耗约为旧版本的 20 倍。此设置将有助于在所有线程间均衡健康检查负载。绝大多数配置无需调整此参数。请注意,过低的值可能导致健康检查执行缓慢时显著降低检查效率。

tune.maxaccept <number>

tune.maxaccept <number>

设置进程在切换至其他工作前可连续接受的最大连接数。在单进程模式下,较高的数值曾在高连接速率下带来更好的性能,但随着多队列机制的引入,这一情况已不再成立。该值对每个监听器独立生效,因此会考虑监听器绑定的进程数量。默认值为 4,该值表现最佳。若从旧配置中继承了显著更高的数值,建议将其移除,此举既能提升性能,又能降低响应时间。在多进程模式下,该值将除以监听器绑定进程数的两倍。将该值设为 -1 可完全禁用此限制。通常无需调整此值。

tune.maxpollevents <number>

tune.maxpollevents <number>

设置单次调用轮询系统时可处理的最大事件数。默认值会根据操作系统自动调整。观察发现,将该值降低至 200 以下会略微降低延迟,但会牺牲网络带宽;将该值提高至 200 以上则会以略微增加的带宽为代价换取延迟降低。配置的值必须小于或等于 1000000。

tune.maxrewrite <number>

tune.maxrewrite <number>

设置保留缓冲区空间的大小(以字节为单位)。保留空间用于头重写或追加。套接字的首次读取操作永远不会填满超过 bufsize - maxrewrite 的空间。历史上,该值默认为 bufsize 的一半,但这种设定并无太大意义,因为通常无需添加大量头。设置过高会阻碍大型请求或响应的处理;设置过低则会妨碍向已较大的请求或 POST 请求中添加新头。通常建议将其设为约 1024。若该值大于 bufsize 的一半,将自动调整为 bufsize 的一半。这意味着在调整 bufsize 时无需担心此值。

tune.max-rules-at-once <number>

tune.max-rules-at-once <number>

设置在规则集评估函数中可同时评估的最大规则数量,前提是这些规则支持中断(yielding)。实际上,配置中存在大量“tcp-request content”或“http-request”规则的情况并不少见。当大量规则与高 CPU 消耗的动作(例如:处理内容的动作)结合时,若评估未被中断,同一规则集中的所有规则均在同一个轮询循环中执行,可能导致线程争用。此选项确保对于面向内容的规则集(因内容检查已支持 yielding 的规则集),同一轮询循环中最多仅执行 <number> 条规则。其作用是强制评估函数中断,以便在下一个轮询循环中恢复评估。

受影响的规则集包括:

  • tcp-request content
  • tcp-response content
  • http-request
  • http-response

默认值为 50。

tune.memory.hot-size <number>

tune.memory.hot-size <number>

设置每个线程在本地缓存中保持热态且永不被其他线程回收的内存大小。对该内存的访问速度极快(无锁),在高线程竞争情况下,保持足够的内存大小对维持良好性能至关重要。该值以字节为单位,其默认值在构建时通过 CONFIG_HAP_POOL_CACHE_SIZE 配置,缺省值为 524288(512 kB)。在某些使用场景中,增大该值可能提升性能,特别是当性能分析显示内存分配压力较大时。经验表明,一个合适的值通常介于每个 CPU 核心 L2 缓存大小的 1 到 2 倍之间。值过大将因 CPU L3 缓存利用效率低下而对性能产生负面影响,并消耗更多内存。建议不要修改此值,或仅以小幅度逐步调整。若要完全禁用每个线程的 CPU 缓存,可设置极小值,但更推荐在命令行中使用 “-dMno-cache”。

tune.notsent-lowat.client <size>

tune.notsent-lowat.client <size>
tune.notsent-lowat.server <size>

调整内核的每个套接字缓冲区大小,使得当缓冲区中的数据量达到该值加上测量到的窗口大小时,报告套接字发送端已满。其原理是仅在套接字缓冲区中保留最少必需的字节数,并额外预留一小部分缓冲空间,以覆盖 HAProxy 尝试再次发送数据时可能传输的数据量。将该值设为较低值(通常约为 tune.bufsize)可显著降低系统缓冲区的内存占用,并减少因刷新缓冲数据而产生的应用层延迟。对于支持该特性的系统,此设置通常比 tune.sndbuf.client 和 tune.sndbuf.server 更为有效且准确。该设置按连接生效(根据配置,针对客户端连接或服务器连接),仅适用于 TCP 连接。默认值为 0,表示无限制。此功能仅在 Linux 系统上可用。

tune.pattern.cache-size <number>

tune.pattern.cache-size <number>

设置模式查找缓存的大小为 <number> 项。该缓存为 LRU 缓存,用于记忆先前的查找及其结果。它在 ACL 和映射中用于慢速模式查找,即使用 “sub”、“reg”、“dir”、“dom”、“end”、“bin” 匹配方法以及不区分大小写的字符串时。该设置适用于模式表达式,意味着它能够记忆配置行中指定的所有模式(包括从文件加载的模式)的查找结果。当通过 HTTP 动作或 CLI 更新条目时,缓存会自动失效。默认缓存大小为 10000 项,这使得在 32 位系统上每个进程/线程的内存占用约为 5 MB,在 64 位系统上约为 8 MB,因为缓存是线程/进程本地的。该缓存发生冲突的风险极低,约为缓存大小除以 2^64 的数量级。通常,在默认缓存大小为 10000 项、每秒处理 10000 个请求的情况下,暴力攻击在 60 年后导致单次冲突的概率为 1%,在 6 年后为 0.1%。该风险被认为远低于由老化组件引起的内存损坏风险。若此风险不可接受,可通过将该参数设为 0 来禁用缓存。

tune.peers.max-updates-at-once <number>

tune.peers.max-updates-at-once <number>

设置 HAProxy 在发送消息时一次性尝试处理的最大 stick-table 更新数量。获取这些更新的数据需要执行一些锁定操作,若未加限制,在多线程机器上可能造成较高的 CPU 消耗,也可能在旧进程与新进程之间的初始批量传输期间增加延迟。相反,过低的值也可能导致更高的 CPU 开销,并延长完成时间。默认值为 200,建议不要更改。

tune.pipesize <size>

tune.pipesize <size>

设置内核管道缓冲区大小为指定值(以字节为单位)。默认情况下,管道大小为系统默认值。但在使用 TCP 拼接时,增大管道大小有时可提升性能,特别是当怀疑管道未被填满且频繁调用 splice() 时。此设置会影响内核的内存占用,因此在未充分理解其影响前,不得更改。

tune.pool-high-fd-ratio <number>

tune.pool-high-fd-ratio <number>

此设置定义了 HAProxy 全局使用的文件描述符最大数量(以百分比表示),相对于 HAProxy 在无法复用连接且必须创建新连接时可使用的文件描述符上限。当空闲连接被终止时,该值用于控制可保留的空闲连接数量。默认值为 25(即文件描述符总量的四分之一),这意味着大约一半的最大前端连接数可以维持空闲连接。在一般情况下,超过此值通常并无实际意义,尤其是在以连接复用为目标时。

tune.pool-low-fd-ratio <number>

tune.pool-low-fd-ratio <number>

此设置用于定义 HAProxy 全局使用的文件描述符最大数量(以百分比表示),该数值相对于 HAProxy 在停止将连接放入空闲池以供复用之前可使用的文件描述符上限。默认值为 20。

tune.pt.zero-copy-forwarding { on | off }

tune.pt.zero-copy-forwarding { on | off }

启用(on)或禁用(off)透传多路复用器的数据零拷贝转发功能。需配合内核拼接(splicing)功能使用。默认启用。

另请参阅:tune.disable-zero-copy-forwarding、option splice-auto、option splice-request 和 option splice-response

tune.quic.be.cc.cubic-min-losses <number>

tune.quic.be.cc.cubic-min-losses <number>
tune.quic.fe.cc.cubic-min-losses <number>

定义 Cubic 拥塞控制算法真正将丢包事件视为拥塞事件所需的丢包数量。通常情况下,任何丢包事件均被视为拥塞所致,且足以使 Cubic 从较小的窗口重新开始。但实验表明,丢包可能由多种非拥塞原因引起,可简单归类为误判丢包,此时调整窗口大小并无实际效果,只会降低通信速率。信号质量差、报文乱序到达、客户端 CPU 使用率过高导致随机延迟,以及系统定时器精度不足等,均可能成为此类丢包的常见原因。该设置允许 Cubic 对误判丢包更具容忍度,通过调整两个 ACK 之间累计丢包数量以判定为丢包事件的最小值,其默认值为 1。实验中已观察到显著性能提升,但始终伴随重传所浪费带宽的增加,以及拥塞链路饱和风险的上升。值 2 可用于短时间内的指标对比。未经专家事先分析,切勿将该值设为超过 2。默认值和最小值均为 1。始终使用 1。

tune.quic.cc.cubic.min-losses <number> (deprecated)

tune.quic.cc.cubic.min-losses <number> (deprecated)

该关键字已在 3.3 版本中弃用,并将在 3.5 版本中移除。它是对 QUIC 配置进行简化处理的一部分。若使用,此设置仅对前端连接生效。

tune.quic.be.cc.hystart { on | off }

tune.quic.be.cc.hystart { on | off }
tune.quic.fe.cc.hystart { on | off }

启用(on)或禁用(off)用于 QUIC 连接的 HyStart++(RFC 9406)算法,该算法可替代拥塞控制算法的慢启动阶段,避免造成高丢包率。默认情况下处于禁用状态。

tune.quic.cc-hystart { on | off } (deprecated)

tune.quic.cc-hystart { on | off } (deprecated)

该关键字已在 3.3 版本中弃用,并将在 3.5 版本中移除。它是对 QUIC 配置进行简化处理的一部分。若使用,此设置仅对前端连接生效。

tune.quic.be.cc.max-frame-loss <number>

tune.quic.be.cc.max-frame-loss <number>
tune.quic.fe.cc.max-frame-loss <number>

设置单个 QUIC 帧被标记为丢失的上限。超过该上限时,连接被视为失败,并立即关闭。

默认值为 10。

tune.quic.max-frame-loss <number> (deprecated)

tune.quic.max-frame-loss <number> (deprecated)

该关键字已在 3.3 版本中弃用,并将在 3.5 版本中移除。它是对 QUIC 配置进行简化处理的一部分。若使用,此设置仅对前端连接生效。

tune.quic.be.cc.max-win-size <size>

tune.quic.be.cc.max-win-size <size>
tune.quic.fe.cc.max-win-size <size>

设置前端或后端侧单个 QUIC 连接的拥塞控制器的默认最大窗口大小。值必须以整数形式书写,可选后缀为 ‘k’、’m’ 或 ‘g’。取值范围必须在 10k 至 4g 之间。

QUIC 多路复用器在数据发送时,也使用当前的拥塞窗口大小来判断是否可以分配新的流缓冲区。因此,最大拥塞窗口大小同样作为该分配器的限制。

默认值为 480k。

另请参见 “quic-cc-algo” 绑定和服务器选项。

tune.quic.frontend.default-max-window-size <size> (deprecated)

tune.quic.frontend.default-max-window-size <size> (deprecated)

该关键字已在 3.3 版本中弃用,并将在 3.5 版本中移除。它是对 QUIC 配置进行简化处理的一部分。若使用,此设置仅对前端连接生效。

tune.quic.be.cc.reorder-ratio <0..100, in percent>

tune.quic.be.cc.reorder-ratio <0..100, in percent>
tune.quic.fe.cc.reorder-ratio <0..100, in percent>

应用于计算数据包重排序阈值的比率。若设置过小,可能触发高数据包丢失检测。

默认值为 50。

tune.quic.reorder-ratio <0..100, in percent> (deprecated)

tune.quic.reorder-ratio <0..100, in percent> (deprecated)

该关键字已在 3.3 版本中弃用,并将在 3.5 版本中移除。它是对 QUIC 配置进行简化处理的一部分。若使用,此设置仅对前端连接生效。

tune.quic.be.max-idle-timeout <timeout>

tune.quic.be.max-idle-timeout <timeout>
tune.quic.fe.max-idle-timeout <timeout>

设置前端或后端侧的 QUIC max_idle_timeout 传输参数。该参数遵循 HAProxy 的时间格式,单位为毫秒。此参数决定在连接于有效时间段内保持空闲后,经过多长时间将被静默关闭。两端均依赖于协商后的相同值:— 若两者均非空,则取两者中的最小值;— 若仅有一方非空,则取非空值;— 若两者均为空,则此功能被禁用。

默认值为 30 秒。

tune.quic.frontend.max-idle-timeout <timeout> (deprecated)

tune.quic.frontend.max-idle-timeout <timeout> (deprecated)

该关键字已在 3.3 版本中弃用,并将在 3.5 版本中移除。它是对 QUIC 配置进行简化处理的一部分。若使用,此设置仅对前端连接生效。

tune.quic.be.sec.glitches-threshold <number>

tune.quic.be.sec.glitches-threshold <number>
tune.quic.fe.sec.glitches-threshold <number>

设置前端或后端侧每连接的故障阈值,当连接的故障次数达到该阈值时,连接将被自动终止。这可实现对行为异常连接的自动终止,而无需编写显式的规则。默认值为 0,表示未设置阈值,因此不会因任何事件导致连接关闭。请注意,某些 QUIC 客户端在长时间连接期间可能偶尔引发少量故障,因此此处的非零值建议设为数百或数千,以在不影响轻微异常客户端的前提下生效。也可通过使用 “tune.glitches.kill.cpu-usage” 实现仅在 CPU 使用率超过特定水平时终止连接。

另请参阅:fc_glitches、tune.glitches.kill.cpu-usage

tune.quic.frontend.glitches-threshold <number> (deprecated)

tune.quic.frontend.glitches-threshold <number> (deprecated)

该关键字已在 3.3 版本中弃用,并将在 3.5 版本中移除。它是对 QUIC 配置进行简化处理的一部分。若使用,此设置仅对前端连接生效。

tune.quic.fe.sec.retry-threshold <number>

tune.quic.fe.sec.retry-threshold <number>

动态启用所有已配置的 QUIC 监听器的重试功能,一旦达到此数量的半开连接。半开连接是指握手尚未成功完成或失败的连接。此设置需配置集群密钥方可生效,否则将被静默忽略(参见“cluster-secret”设置)。若强制使用 QUIC 重试(参见“quic-force-retry”设置),此设置也将被静默忽略。

默认值为 100。

有关 QUIC 重试的更多信息,请参见 https://www.rfc-editor.org/rfc/rfc9000.html#section-8.1.2 。

tune.quic.retry-threshold <number> (deprecated)

tune.quic.retry-threshold <number> (deprecated)

该关键字已在 3.3 版本中弃用,并将在 3.5 版本中移除。它是对 QUIC 配置进行简化处理的一部分。若使用,此设置仅对前端连接生效。

tune.quic.fe.sock-per-conn { default-on | force-off }

tune.quic.fe.sock-per-conn { default-on | force-off }

指定全局范围内 QUIC 前端连接在接收和发送操作中如何使用套接字。 连接可共享监听器套接字,或每个连接可分配独立的套接字。

默认值为 “default-on”。该选项用于为每个 QUIC 连接分配专用套接字。在处理大量 QUIC 流量时,此选项是实现最佳性能的首选方式。这也是确保 QUIC 连接在执行软停止时能正确处理且不丢失数据的唯一方法,同时可高效处理 sendto() 操作期间的瞬时错误情况。然而,该选项依赖于 UDP 网络栈的某些高级功能。如果系统平台被判定为不兼容,HAProxy 将在启动时自动切换至 “force-off” 模式。请注意,运行在特权端口上的 QUIC 监听器可能需要以 uid 0 身份运行,或需进行特定操作系统调优以允许目标 uid 绑定此类端口,例如使用系统能力。参见 “setcap” 全局指令。

“force-off” 值表示 QUIC 传输将在共享监听器套接字上进行。对于小流量场景,此选项可作为良好折衷方案,有助于降低文件描述符(FD)消耗。然而,由于在多个线程间共享监听器或同时使用大量 QUIC 连接时会导致更高的 CPU 使用率,性能无法达到最优。

此设置与每个“quic-socket”绑定选项同时生效。若全局调优中使用“default-on”模式,将对每个监听器生效,但“quic-socket listener”除外。若全局使用“force-off”模式,则将应用于每个监听器实例,无论其独立配置如何。

tune.quic.socket-owner { connection | listener } (deprecated)

tune.quic.socket-owner { connection | listener } (deprecated)

3.3 版本中已弃用此关键字,将在 3.5 版本中移除。该关键字属于对 QUIC 配置进行简化处理的一部分。新选项名为 “tune.quic.fe.sock-per-conn”,其中旧值 “connection” 对应 “default-on”,“listener” 对应 “force-off”。

tune.quic.be.stream.data-ratio <0..100, in percent>

tune.quic.be.stream.data-ratio <0..100, in percent>
tune.quic.fe.stream.data-ratio <0..100, in percent>

此设置用于配置每个流中在途数据字节数的硬性上限。该值以相对于 QUIC 流 rxbuf 连接设置的百分比表示,结果向上取整至 bufsize。

默认值为 90。此值适用于最常见的 Web 场景,即上传仅针对一个或少数几个流进行,其余流仅用于下载。若流 rxbuf 连接限制保持在合理水平,可确保仅部分已打开的流能够分配至其最大容量。

当应用程序同时使用多个并行上传流且这些流之间存在不公平现象时,降低该比例可能更为合理,以提升公平性并减少每流的带宽占用。

参见:“tune.quic.be.stream.rxbuf”、“tune.quic.fe.stream.rxbuf”、“tune.quic.be.stream.max-concurrent”、“tune.quic.fe.stream.max-concurrent”

tune.quic.frontend.stream-data-ratio <0..100, in percent> (deprecated)

tune.quic.frontend.stream-data-ratio  <0..100, in percent> (deprecated)

该关键字已在 3.3 版本中弃用,并将在 3.5 版本中移除。它是对 QUIC 配置进行简化处理的一部分。若使用,此设置仅对前端连接生效。

tune.quic.be.stream.max-concurrent <number>

tune.quic.be.stream.max-concurrent <number>
tune.quic.fe.stream.max-concurrent <number>

在前端,此值用作通告的 initial_max_streams_bidi 传输参数的值。该值被强制作为远程对等节点在连接生命周期内可同时打开的双向流的最大数量。这有效限制了并发 HTTP/3 客户端请求的数量。

默认值为 100。请注意,若减小该值,可能会限制接收流的缓冲能力,导致上传吞吐量下降。可通过增大 QUIC 流 rxbuf 连接设置来修正此问题。

在后端侧,HAProxy 会本地强制执行此设置,以限制通过单个连接复用的并发请求数量。该限制可能进一步受到对等节点流量控制的影响。为提升站点响应速度,可适当降低默认值 100,代价是增加后端连接的打开数量。与前端侧类似,此设置同样直接影响接收缓冲区能力,但此时是限制 HTTP 下载容量。当主要处理大于 “tune.bufsize” 的 HTTP 响应时,可适当增大 QUIC 流接收缓冲区设置。

参见:“tune.quic.be.stream.rxbuf”、“tune.quic.fe.stream.rxbuf”、“tune.quic.be.stream.data-ratio”、“tune.quic.fe.stream.data-ratio”

tune.quic.fe.stream.max-total <number>

tune.quic.fe.stream.max-total <number>

设置单个 QUIC 连接可处理的最大请求数。达到此上限后,连接将被优雅关闭。在 HTTP/3 中,这表现为 GOAWAY 帧。当所有剩余传输完成后,连接最终关闭。

此设置通过 QUIC 流控制机制作为连接的硬性限制。若对等节点违反该限制,连接将立即关闭。

此设置可用于强制客户端定期打开新的连接,以持续发送请求,并避免长时间维持连接。然而,过低的值会增加客户端的延迟,并由于 TLS 握手导致双方 CPU 消耗上升。

默认值为 0,表示除 QUIC 协议编码限制(2^60,超过一亿亿)外,无其他特定限制。

tune.quic.frontend.max-streams-bidi <number> (deprecated)

tune.quic.frontend.max-streams-bidi <number> (deprecated)

该关键字已在 3.3 版本中弃用,并将在 3.5 版本中移除。它是对 QUIC 配置进行简化处理的一部分。若使用,此设置仅对前端连接生效。

tune.quic.be.stream.rxbuf <size>

tune.quic.be.stream.rxbuf <size>
tune.quic.fe.stream.rxbuf <size>

此设置是 QUIC 前端连接中在途数据字节数的硬性上限。该值被复用为初始_max_data 传输参数的取值。其直接影响对等节点的上传带宽,具体取决于延迟以及 HAProxy 中每个连接的内存消耗。

默认值为 0,表示将自动根据 max-concurrent 与 bufsize 的乘积生成该值。例如,当后端应用依赖高延迟网络上的大量上传时,可适当增大此值。

参见:“tune.quic.be.stream.max-concurrent”、“tune.quic.fe.stream.max-concurrent”、“tune.quic.be.stream.data-ratio”、“tune.quic.fe.stream.data-ratio”

tune.quic.frontend.max-data-size <size> (deprecated)

tune.quic.frontend.max-data-size <size> (deprecated)

该关键字已在 3.3 版本中弃用,并将在 3.5 版本中移除。它是对 QUIC 配置进行简化处理的一部分。若使用,此设置仅对前端连接生效。

tune.quic.be.tx.pacing { on | off }

tune.quic.be.tx.pacing { on | off }
tune.quic.fe.tx.pacing { on | off }

启用(on)或禁用(off)QUIC 发送的速率控制支持。默认情况下,该功能处于激活状态。速率控制的目的是平滑数据发送,以减少网络丢包。在大多数场景下,通过避免重传可显著提升网络吞吐量。然而,在带宽极高且延迟极低的网络中,禁用该功能可防止不必要的延迟并降低 CPU 消耗。

另请参见 “quic-cc-algo” 绑定和服务器选项。

tune.quic.disable-tx-pacing (deprecated)

tune.quic.disable-tx-pacing (deprecated)

该关键字已在 3.3 版本中弃用,并将在 3.5 版本中移除。它是对 QUIC 配置进行简化处理的一部分。若使用,此设置仅对前端连接生效。

tune.quic.be.tx.udp-gso { on | off }

tune.quic.be.tx.udp-gso { on | off }
tune.quic.fe.tx.udp-gso { on | off }

启用(‘on’)或禁用(‘off’)QUIC 发送时的 UDP GSO 支持。默认情况下,该功能处于激活状态。此内核特性允许通过单个系统调用发送多个数据报,对大容量传输更为高效。当怀疑发送环节存在问题时,可依据开发人员建议禁用该功能。

tune.quic.disable-udp-gso (deprecated)

tune.quic.disable-udp-gso (deprecated)

该关键字已在 3.3 版本中弃用,并将在 3.5 版本中移除。它是对 QUIC 配置进行简化处理的一部分。若使用,此设置仅对前端连接生效。

tune.quic.listen { on | off }

tune.quic.listen { on | off }

在前端侧禁用 QUIC 传输协议。所有 QUIC 监听器仍会创建,但不会监听传入的数据报。因此,HAProxy 在前端侧不会处理任何 QUIC 流量。

默认值为 “on”。若怀疑 QUIC 流量存在问题,可使用此选项轻松切换 QUIC 监听器,而无需逐行修改配置。

另请参见 “quic_enabled” 样本提取。

tune.quic.mem.tx-max <size>

tune.quic.mem.tx-max <size>

设置传输层 QUIC 栈可用于发送的最大内存容量。该值同时作为飞行中字节数和多路复用器输出缓冲区的上限。请注意,为避免线程竞争,此限制并非严格强制执行,因此在某些情况下可能被超出。此外,每个连接始终可使用至少 2 个数据报的窗口,因此应配合使用适当的 maxconn 设置。

tune.quic.frontend.max-tx-mem <size> (deprecated)

tune.quic.frontend.max-tx-mem <size> (deprecated)

该关键字已在 3.3 版本中弃用,并将在 3.5 版本中移除。它是对 QUIC 配置进行简化处理的一部分。若使用,此设置仅对前端连接生效。

tune.quic.zero-copy-fwd-send { on | off }

tune.quic.zero-copy-fwd-send { on | off }

启用(‘on’)或禁用(‘off’)QUIC 多路复用器的数据零拷贝发送。默认启用。

另请参阅:tune.disable-zero-copy-forwarding

tune.renice.runtime <number>

tune.renice.runtime <number>

该配置选项的取值范围为 -20 至 19。其调度优先级按照 man 2 setpriority 文档所述进行应用。该优先级在配置解析完成后生效,因此仅工作进程或独立进程会应用此优先级。通常将其配置为高于执行配置解析的进程(tune.renice.startup)的优先级。

另请参见:tune.renice.startup

tune.renice.startup <number>

tune.renice.startup <number>

此配置选项的取值范围为 -20 至 19。它会应用调度优先级,具体行为参见 man 2 setpriority 文档。该优先级在应用其余配置之前生效,若需降低配置解析过程的优先级,此设置尤为有用。该优先级在独立进程或工作进程启动后、配置解析前应用。配置解析完成后,除非使用 tune.renice.runtime,否则将恢复之前的优先级。

另请参见:tune.renice.runtime

tune.rcvbuf.backend <size>

tune.rcvbuf.backend  <size>
tune.rcvbuf.frontend <size>

对于非连接套接字的内核套接字接收缓冲区大小,可设置为此值。此设置可用于监听器模式下的 QUIC 以及前端的 log-forward。默认系统缓冲区有时可能过小,无法应对大量聚合流量的接收,导致部分数据丢失,可能引发重传(QUIC 情况下),并在高流量下可能减缓连接建立速度。该值以字节为单位,对每个套接字生效。在监听器模式下,套接字在所有连接间共享,套接字总数取决于 “bind” 行的 “shards” 值。无固定最优值,合适的值应为预期每连接大小乘以预期连接数。内核可能裁剪过大的值。另请参见 “tune.rcvbuf.client” 和 “tune.rcvbuf.server” 用于连接套接字的对应设置,以及 “tune.sndbuf.backend” 和 “tune.sndbuf.frontend” 用于发送设置。

tune.rcvbuf.client <size>

tune.rcvbuf.client <size>
tune.rcvbuf.server <size>

强制将客户端或服务器端的内核套接字接收缓冲区大小设置为指定的字节数。该值适用于所有 TCP/HTTP 前端和后端。通常不应设置此值,使用默认值(0)可让内核根据可用内存自动调整该值。然而,在某些情况下,将其设置为非常低的值(例如 4096)可能有助于节省内核内存,防止其缓冲过多接收到的数据。不过,较低的值会显著增加 CPU 使用率。

tune.recv_enough <size>

tune.recv_enough <size>

HAProxy 使用一些提示来判断短读操作是否表示套接字缓冲区已结束。其中之一是:读取返回的字节数超过 <recv_enough>,该值默认为 10136(即 7 个 1448 字节的分段)。可通过此设置调整该默认值,以更好地应对包含大量短消息的负载,例如 telnet 或 SSH 会话。

tune.ring.queues <number>

tune.ring.queues <number>

设置环形缓冲区前方的写入队列数量。该设置可能影响调试会话期间的 CPU 使用率,值过低或过高均可能产生显著影响。开发人员通过实验确定了合适的取值,除非为解决特定问题而被明确指示,否则不应尝试更改。此设置不应在版本升级时保留在配置中,因为其最优值可能随时间演变。

tune.runqueue-depth <number>

tune.runqueue-depth <number>

设置运行任务时可同时处理的最大任务数量。默认值取决于线程数,通常在 35 到 280 之间,该范围往往能实现最高的请求速率和最低的延迟。增大该值在处理 I/O 时可能导致延迟增加,设置过小则会引入额外开销。线程数较多时,较低的值更有利。在尝试使用远大于默认值的设置时,建议同时启用 tune.sched.low-latency,并可能启用 tune.fd.edge-triggered,以将最大延迟控制在最低可能水平。

tune.sched.low-latency { on | off }

tune.sched.low-latency { on | off }

启用(on)或禁用(off)低延迟任务调度器。默认情况下,HAProxy 会逐类处理多个任务类别中的任务,这种方式效率最高。但在设置较大的 tune.runqueue-depth 值时,这可能会对请求或连接延迟产生可测量的影响。启用此低延迟设置后,若存在低优先级类别的任务,将始终优先于其他类别执行。这可以在大规模流量期间降低新请求或连接所经历的最大延迟,但会增加对大规模流量的影响。对于常规使用,建议保持该设置为关闭状态。默认值为 off。

tune.sndbuf.backend <size>

tune.sndbuf.backend  <size>
tune.sndbuf.frontend <size>

对于非连接套接字,将内核套接字发送缓冲区大小设置为此值。该设置可用于后端的 Unix 套接字和 UDP 日志记录,以及前端监听器模式下的 QUIC。默认系统缓冲区有时可能过小,尤其在多个连接(或日志发送方)共享套接字时,可能导致部分数据丢失,甚至引发重传,从而在高流量下减缓新连接的建立速度。该值以字节为单位,对每个套接字生效。在监听器模式下,套接字由所有连接共享,套接字总数取决于 “bind” 行的 “shards” 值。不存在最优值,合适的值应为预期每连接大小乘以预期连接数。内核可能会裁剪过大的值。另请参见 “tune.sndbuf.client” 和 “tune.sndbuf.server” 的连接套接字对应设置,以及 “tune.rcvbuf.backend” 和 “tune.rcvbuf.frontend” 的接收设置。

tune.sndbuf.client <size>

tune.sndbuf.client <size>
tune.sndbuf.server <size>

强制将客户端或服务器端的内核套接字发送缓冲区大小设置为指定的字节数。该值适用于所有 TCP/HTTP 前端和后端。通常不应设置此值,使用默认值(0)可让内核根据可用内存自动调优该值。然而,在某些情况下,将其设置为极低值(例如 4096)有助于节省内核内存,防止其缓冲过多接收数据。但较低值会显著增加 CPU 使用率。另一种使用场景是防止因内核等待大量缓冲区数据被读取完毕后再通知 HAProxy,而导致极慢客户端出现写超时。有关更有效的设置以更精细地控制 Linux 系统上的内存使用和响应性,同时不影响性能,请参阅 tune.notsent-lowat.client 和 tune.notsent-lowat.server。

tune.ssl.cachesize <number>

tune.ssl.cachesize <number>

设置全局 SSL 会话缓存的大小,单位为块数。每块大小足以存储一个未包含对等节点证书的编码会话。若包含对等节点证书,编码会话将根据对等节点证书的大小占用多个块。每块约使用 200 字节内存(基于 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE 计算,用于 shctx_init 函数)。默认值可在编译时强制指定,否则默认为 20000。当缓存满时,将清除最不活跃的条目并重新分配。增大该值可减少此类清除操作,从而降低因 SSL 握手带来的 CPU 开销,确保所有用户尽可能长时间保持会话。所有条目在启动时即预先分配。将该值设为 0 可禁用 SSL 会话缓存。

tune.ssl.capture-buffer-size <number>

tune.ssl.capture-buffer-size <number>
tune.ssl.capture-cipherlist-size <number> (deprecated)

设置用于捕获客户端 Hello 中加密套件列表、扩展列表、椭圆曲线列表及椭圆曲线点格式的最大缓冲区大小。若值为 0(默认值),则禁用捕获;否则,将为每个 SSL/TLS 连接分配一个缓冲区。

tune.ssl.certificate-compression { auto | off }

tune.ssl.certificate-compression { auto | off }

此设置用于配置证书压缩支持,该功能是 TLS 1.3 的扩展(RFC 8879)。

当设置为 “auto” 时,使用 TLS 库的默认值。

使用 “off” 时,会显式禁用该功能的支持。HAProxy 将不再尝试发送压缩证书,也不会接受压缩证书。

配置后端和前端两侧。

该关键字由 OpenSSL >= 3.2.0 支持。

默认值为 auto。

tune.ssl.default-dh-param <number>

tune.ssl.default-dh-param <number>

设置在使用 DHE 密钥交换时生成临时 Diffie-Hellman 密钥所用的 Diffie-Hellman 参数的最大尺寸。最终尺寸将尝试匹配服务器 RSA(或 DSA)密钥的尺寸(例如,2048 位 RSA 密钥对应 2048 位临时 DH 密钥),但不会超过此最大值。仅允许 1024 或更高数值。较高数值会增加 CPU 负载,且大于 1024 位的值不被 Java 7 及更早客户端支持。若通过证书文件直接提供静态 Diffie-Hellman 参数,或使用 ssl-dh-param-file 参数指定,则此值不生效。若未定义 default-dh-param 且未设置 ssl-dh-param-file,且给定前端的服务器 PEM 文件未指定其自身的 DH 参数,则该前端将无法使用 DHE 密码套件。

tune.ssl.force-private-cache

tune.ssl.force-private-cache

此选项禁用所有进程之间的 SSL 会话缓存共享。通常不应使用此选项,因为客户端随机命中某个进程会导致大量重协商。但在某些操作系统上,若无法使用任何 SSL 缓存同步方法时,可能需要启用此选项。此时,在 SSL 层之前添加基于哈希的首层负载均衡,可降低缺乏会话共享带来的影响。

tune.ssl.hard-maxrecord <number>

tune.ssl.hard-maxrecord <number>

设置每次调用 SSL_write() 时传递的最大字节数。默认值 0 表示无限制。与 tune.ssl.maxrecord 不同,此设置不会动态调整。较小的记录可能降低吞吐量,但在处理低开销客户端时可能是必需的。

tune.ssl.keylog { on | off }

tune.ssl.keylog { on | off }

此选项用于启用 TLS 密钥的日志记录。使用时应谨慎,因为它会增加每个 SSL 会话的内存消耗,可能导致性能下降。默认情况下已禁用。

这些样本提取应用于生成 SSLKEYLOGFILE,以在 Wireshark 中解密流量。

https://tlswg.org/sslkeylogfile/draft-ietf-tls-keylogfile.html

SSLKEYLOG 是一系列以如下格式排列的行:

<Label> <space> <ClientRandom> <space> <Secret>

客户端随机数由 %[ssl_fc_client_random,hex] 样本提取提供,密钥和标签可从下方数组中获取。需生成包含此数组中所有标签的 SSLKEYLOGFILE。

以下样本提取结果为十六进制字符串,无需进行转换。

  SSLKEYLOGFILE Label             |  Sample fetches for the Secrets
  --------------------------------|-----------------------------------------
  CLIENT_EARLY_TRAFFIC_SECRET     |  %[ssl_xx_client_early_traffic_secret]
  CLIENT_HANDSHAKE_TRAFFIC_SECRET |  %[ssl_xx_client_handshake_traffic_secret]
  SERVER_HANDSHAKE_TRAFFIC_SECRET |  %[ssl_xx_server_handshake_traffic_secret]
  CLIENT_TRAFFIC_SECRET_0         |  %[ssl_xx_client_traffic_secret_0]
  SERVER_TRAFFIC_SECRET_0         |  %[ssl_xx_server_traffic_secret_0]
  EXPORTER_SECRET                 |  %[ssl_xx_exporter_secret]
  EARLY_EXPORTER_SECRET           |  %[ssl_xx_early_exporter_secret]

这些获取操作适用于前端(fc)或后端(bc)侧,请将“xx”替换为“fc”或“bc”以使用正确的侧。

仅在使用 OpenSSL 1.1.1 时可用,且在 TLS 1.3 会话中具有实用价值。

若要生成 TLS < 1.3 时的 SSLKEYLOGFILE 内容,仅需以下这一行:

CLIENT_RANDOM %[ssl_fc_client_random,hex] %[ssl_fc_session_key,hex]

使用此类日志格式生成完整的密钥日志是可能的,尽管这并非 syslog 的理想选择。

log-format "CLIENT_EARLY_TRAFFIC_SECRET %[ssl_bc_client_random,hex] %[ssl_bc_client_early_traffic_secret]\n
            CLIENT_HANDSHAKE_TRAFFIC_SECRET %[ssl_bc_client_random,hex] %[ssl_bc_client_handshake_traffic_secret]\n
            SERVER_HANDSHAKE_TRAFFIC_SECRET %[ssl_bc_client_random,hex] %[ssl_bc_server_handshake_traffic_secret]\n
            CLIENT_TRAFFIC_SECRET_0 %[ssl_bc_client_random,hex] %[ssl_bc_client_traffic_secret_0]\n
            SERVER_TRAFFIC_SECRET_0 %[ssl_bc_client_random,hex] %[ssl_bc_server_traffic_secret_0]\n
            EXPORTER_SECRET %[ssl_bc_client_random,hex] %[ssl_bc_exporter_secret]\n
            EARLY_EXPORTER_SECRET %[ssl_bc_client_random,hex] %[ssl_bc_early_exporter_secret]"

HAProxy 还提供了上述格式作为预定义环境变量,可直接在 “log-format” 指令中使用:

$HAPROXY_KEYLOG_FC_LOG_FMT   frontend (client-facing) connection keys
$HAPROXY_KEYLOG_BC_LOG_FMT   backend (server-facing) connection keys

tune.ssl.keyupdate-rate-limit <limit>

tune.ssl.keyupdate-rate-limit <limit>

每秒允许接受的 KeyUpdate 数量上限设为 <limit>,超过该值即视为洪水攻击并终止连接。处理 KeyUpdate 操作消耗大量 CPU 资源,且极少有必要接收大量此类消息。设置为 “0” 可禁用速率限制。默认值为 100。

tune.ssl.lifetime <timeout>

tune.ssl.lifetime <timeout>

设置缓存 SSL 会话的有效时长。该时间以秒为单位,默认值为 300(5 分钟)。需要注意的是,这并不能保证会话一定持续那么久,因为当缓存已满时,即使会话的配置生命周期尚未到期,最长时间处于空闲状态的会话仍会被清除。此设置的实际意义在于防止会话被使用过久。

tune.ssl.maxrecord <number>

tune.ssl.maxrecord <number>

设置数据传输开始时传递给 SSL_write() 的最大字节数。 默认值 0 表示无限制。在 SSL/TLS 下,客户端必须接收到完整记录后才能解密数据。对于较大的记录,这意味着客户端可能需要下载最多 16kB 的数据才能开始处理。限制该值可改善位于高延迟或低带宽网络中的浏览器的页面加载时间。建议找到适合 1 或 2 个 TCP 段的最优值(通常在启用 TCP 时间戳时为 1448 字节,禁用时为 1460 字节),同时注意 SSL/TLS 会引入一定开销。测试中,1419 和 2859 为典型有效值。使用 “strace -e trace=write” 可查找最佳值。HAProxy 在检测到空闲流后将自动切换至该设置(参见上述 tune.idletimer)。另请参阅 tune.ssl.hard-maxrecord。

tune.ssl.ssl-ctx-cache-size <number>

tune.ssl.ssl-ctx-cache-size <number>

设置用于存储生成的证书的缓存大小为 <number> 项。该缓存为 LRU 缓存。由于动态生成 SSL 证书的开销较大,因此将其缓存。默认缓存大小为 1000 项。

tune.streams-elasticity <number>

tune.streams-elasticity <number>

定义前端连接在所有连接建立时,相对于最大并发连接数(maxconn)的流(stream)目标百分比。该指标适用于 HTTP/2 或 QUIC 等多路复用协议,其中每个连接可接收多个流。至少保证一个流,因此该百分比必须不低于 100%。在连接建立过程中,HAProxy 会动态通告额外的流,直至达到配置的上限,以维持目标比例。连接建立时,每个前端连接至少分配一个流;额外流根据目标百分比和配置的流限制进行分配。这确保了在不同负载条件下实现高效的流分配(低负载时分配更多流,高负载时分配较少流)。

每页包含大量对象的高动态站点可受益于较高的比率,从而实现每个连接多个流。平均使用较少流的站点(如 WebSocket、应用代码)可能更倾向于选择接近 120 或 150 的较小比率(比连接数多 20 至 50% 的流),以避免在持续负载下流数量过多。

默认值为 0,表示在此级别不强制执行,因此仅 H2 和 QUIC 配置生效(在默认设置下每连接 100 个流,相当于 10000%)。对于小型部署(maxconn 约为千级),此设置仍为推荐值。中等规模部署(连接数为数千至数万)通常将该比例设置在 1000 至 5000 之间,使在满负载时每连接可支持 10 至 50 个流。大规模部署(连接数为数十万至数百万)可能采用更低的值(120 至 200),以在满负载时平均支持每连接 1.2 至 2 个流。

与 HTTP/2 不同,QUIC 能够在连接生命周期内动态调整并发流的数量。然而,QUIC 的流量控制比 HTTP/2 更严格,因此在使用时建议指定足够大的值,以避免连接上产生额外延迟。此外,对于启用了 0-RTT 的 QUIC 监听器存在一项限制:在此情况下,向对等节点通告的初始值将忽略流弹性机制,而仅依赖 “tune.quic.fe.stream.max-concurrent” 设置。不过,在连接生命周期内,流弹性原则仍将在该初始通告之后继续生效。

监控后端的活跃流总数(包括队列)可提供一个实用的指标,用于判断可持续的目标负载,并有助于避免过度配置。

tune.stick-counters <number>

tune.stick-counters <number>

设置通过 “tcp-request” 或 “http-request” 规则中的 “track-sc*” 动作,同时跟踪的连接或请求的 stick-counter 数量。默认值由宏 MAX_SESS_STK_CTR 在编译时设定,缺省值为 3。通过此设置可更改该值并忽略编译时传入的值,但不可设为超过 100 的数值。在将复杂配置迁移到 HAProxy 时可能需要增加此值,但用户应警惕其开销:每个条目占用每个连接 16 字节和每个请求 16 字节,所有请求即使未使用也需分配并清零。因此,值设为 10 会使每个请求的内存消耗增加 320 字节,并导致每次请求均需清空该内存,这会产生可测量的 CPU 影响。相反,当未使用 “track-sc” 规则时,该值可降低(0 为有效值,用于完全禁用 stick-counter)。

tune.takeover-other-tg-connections <value>

tune.takeover-other-tg-connections <value>

默认情况下,我们不会尝试使用其他线程组中的空闲连接。此行为可以更改。<value> 的有效值为:“none”(默认值),若使用该值,则不会尝试从其他线程组获取空闲连接;“restricted”,在此模式下,仅当使用无法创建新连接的协议(如反向 HTTP)或启用 strict-maxconn 时,才会尝试从其他线程组获取空闲连接;“full”,在此模式下,始终会检查其他线程组中是否存在空闲连接。请注意,从其他线程组使用连接可能带来性能开销,因此除非确实需要,否则不应启用。请注意,此行为现已由 tune.idle-pool.shared 控制,该关键字仅用于与旧配置的兼容性,未来将被弃用。

tune.vars.global-max-size <size>

tune.vars.global-max-size <size>
tune.vars.proc-max-size <size>
tune.vars.reqres-max-size <size>
tune.vars.sess-max-size <size>
tune.vars.txn-max-size <size>

这五个配置项用于管理变量系统所使用的最大内存数量。“global”限制所有作用域可用的总内存数量。“proc”限制进程作用域的内存使用,“sess”限制会话作用域的内存使用,“txn”限制事务作用域的内存使用,而“reqres”则限制每个请求或响应处理所使用的内存。内存计数采用分层机制,即更粗粒度的限制包含更细粒度的限制:“proc”包含“sess”,“sess”包含“txn”,“txn”包含“reqres”。

例如,当 “tune.vars.sess-max-size” 限制为 100 时,“tune.vars.txn-max-size” 和 “tune.vars.reqres-max-size” 也不得超过 100。若创建一个包含 100 字节的变量 “txn.var”,所有可用空间将被耗尽。请注意,运行时超出限制不会导致错误消息,但数值可能被截断或损坏。务必准确规划存储所有变量所需的空间。

tune.zlib.memlevel <number>

tune.zlib.memlevel <number>

设置每个流在 zlib 初始化时的 memLevel 参数。该参数定义了为内部压缩状态分配的内存大小。值为 1 时使用最少内存,但速度较慢且压缩比降低;值为 9 时使用最大内存以获得最佳速度。可取值范围为 1 到 9。默认值为 8。

tune.zlib.windowsize <number>

tune.zlib.windowsize <number>

设置窗口大小(历史缓冲区的大小)作为每个流的 zlib 初始化参数。该参数值越大,压缩效果越好,但内存使用量也越高。取值范围为 8 到 15,默认值为 15。

3.3. 排查故障

anonkey <key>

anonkey <key>

将全局匿名化密钥设置为 <key>,该密钥必须为 0 到 4294967295 之间的 32 位数字。当启用匿名化模式时,CLI 命令将默认使用此密钥。该密钥也可通过 CLI 命令 “set anon global-key” 在运行时设置。另请参阅管理手册中的命令行参数 “-dC”。

debug.counters { on | off }

debug.counters { on | off }

启用(‘on’)或禁用(‘off’)代码中事件计数器的更新。这些计数器在 CLI 命令 “debug counters” 中以类型 “CNT” 报告。仅当代码编译时 DEBUG_COUNTERS 的值设置为 1 或以上时,这些计数器才可用。当值为 1 时,计数器默认不更新(“debug.counters off”);当值为 2 时,计数器默认更新(“debug.counters on”)。通常情况下,除非开发者要求,或怀疑其消耗异常高的 CPU 资源(此时需向开发者报告并附上计数器转储),否则不应更改此设置。也可通过 “debug counters” CLI 命令在运行时更改此状态。请参阅管理手册。

force-cfg-parser-pause <timeout>

force-cfg-parser-pause <timeout>

此指令会暂停配置解析器 <timeout> 毫秒。在开发或测试初始化脚本超时场景时非常有用,尤其适用于模拟极长的重载过程。该功能需要将 expose-experimental-directives 设置为启用状态。

<timeout> 是默认以毫秒为单位指定的超时值,但如果在数字后附加单位,则可使用任意其他单位,具体说明请参见本文档顶部。

示例:

global
    expose-experimental-directives
    force-cfg-parser-pause 10s

quick-exit

quick-exit

通过跳过释放内存对象和监听器,可加快重载时旧进程的退出速度,因为这些资源在进程终止时将由操作系统自动回收。该优化带来的收益仅限于小幅提升(对于极大型配置,最多仅几毫秒)。实际上,其主要用途是在发现 deinit() 代码中存在缺陷时,可绕过该问题。除非开发人员明确指示,否则不应使用此选项。

quiet

quiet

启动时不要显示任何消息。这等效于命令行参数 “-q”。

warn-blocked-traffic-after <time>

warn-blocked-traffic-after <time>

这允许调整在阻塞流量的卡住任务触发标准错误输出警告前的延迟时间。延迟以毫秒为单位,缺省值为 100 毫秒。允许的取值范围必须在 1 毫秒至 1000 毫秒之间(含)。较低的值会导致警告频繁触发,较高的值则很少触发。监控守护进程无论如何都会终止连续一秒钟内两次无响应的失控任务,因此 1000 毫秒的警告延迟通常不会触发任何警告。建议将该值保持在 10 毫秒至 100 毫秒之间,以检测可能影响用户体验的配置异常,例如导致响应时间过长或交互会话出现卡顿的情况。例如,一个设计不佳的 Lua 样本提取函数执行大量计算,或一个评估成本极高的 large map_reg 或 map_regm 映射文件,都可能引发此类问题。作为对比,一次 TLS 握手耗时约为 1 至 2 毫秒,压缩一个 16 kB 的 HTTP 响应缓冲区大约耗时 1 毫秒。该输出包含被判定为问题任务的线程转储,包含回溯信息以及有助于判断时间消耗位置的上下文信息。

zero-warning

zero-warning

当设置此选项时,HAProxy 在处理配置并应用时若发出任何警告,将拒绝启动。这意味着关于参数组合不当的警告、关于无法设置过高限制的警告等,均会导致进程在启动期间以错误退出。少数启动后期的警告无法通过此选项捕获,例如在“daemon”或“master-worker”模式下更改组 ID 时无法丢弃附加组,或在 fork() 后无法标记进程为可转储。此选项不会捕获运行时发出的警告。建议对不常变更的配置设置此选项,以帮助发现细微错误,保持配置的整洁性与向前兼容性。请注意,“HAProxy -c”在此类情况下也会报告错误。此选项等效于命令行参数“-dW”。

3.4. HTTP 客户端调优

HTTPClient 是一个内部 HTTP 库,可被多个子系统使用,例如在 LUA 脚本中。HTTPClient 不参与数据路径,换句话说,它与通过 HAProxy 传输的 HTTP 流量无关。

httpclient.resolvers.disabled <on|off>

httpclient.resolvers.disabled <on|off>

禁用 httpclient 的 DNS 解析。阻止创建“default”解析器段。

默认值为 off。

httpclient.resolvers.id <resolvers id>

httpclient.resolvers.id <resolvers id>

该选项定义了 httpclient 尝试解析时所使用的解析器段。

默认选项为“default”解析器 ID。默认情况下,若未使用此选项,当该段未找到时将直接禁用解析。

然而,当此选项被显式启用时,若加载失败将触发配置错误。

httpclient.resolvers.prefer <ipv4|ipv6>

httpclient.resolvers.prefer <ipv4|ipv6>

此选项允许选择解析时使用的 IP 协议族,当网络中不可用 IPv6 时尤为方便。默认选项为 “ipv6”。

httpclient.retries <number>

httpclient.retries <number>

此选项用于配置当请求失败时,httpclient 尝试重试的次数。其功能与后端配置中的 “retries” 关键字相同。

默认值为 3。

httpclient.ssl.ca-file <cafile>

httpclient.ssl.ca-file <cafile>

此选项定义用于验证服务器证书的 ca-file。其参数与服务器行上的 “ca-file” 选项相同。

默认情况下,若未使用此选项,值为 “@system-ca”,表示尝试加载系统的 CA。若加载失败,httpclient 的 SSL 将被禁用。

然而,当此选项被显式启用时,若失败将触发配置错误。

httpclient.ssl.verify [none|required]

httpclient.ssl.verify [none|required]

与服务器行上的 verify 选项作用方式相同。指定为 “none” 时,不验证服务器证书。默认选项为 “required”。

默认情况下,若未使用此选项,值为“required”。若验证失败,httpclient 的 SSL 将被禁用。

然而,当此选项被显式启用时,若失败将触发配置错误。

httpclient.timeout.connect <timeout>

httpclient.timeout.connect <timeout>

设置默认情况下 httpclient 连接尝试的最大等待时间。

参数:

<timeout> is the timeout value specified in milliseconds by default, but
          can be in any other unit if the number is suffixed by the unit,
          as explained at the top of this document.

默认值为 5000 毫秒。

13 - 4. 代理

默认设置、前端、后端、监听器、代理关键字及动作引用

代理配置可位于一组段中:

  • defaults [<name>] [ from <defaults_name> ]
  • frontend <name> [ from <defaults_name> ]
  • backend <name> [ from <defaults_name> ]
  • listen <name> [ from <defaults_name> ]

前端段描述了一组用于接收客户端连接的监听套接字。

后端段描述了一组代理将连接以转发传入连接的服务器。

段 “listen” 定义了一个完整的代理,其前端和后端部分合并于同一段中。该配置通常适用于仅 TCP 流量的场景。

默认设置段

“defaults” 段将所有设置重置为文档中定义的默认值,并为后续段落预设新的默认值。所有“frontend”、“backend”和“listen”段始终从一个“defaults”段获取初始设置,默认情况下使用在新创建段之前出现的最新一个“defaults”段。可以通过在段行中使用可选关键字“from”后指定名称,显式指定某个特定的“defaults”段作为初始设置来源。尽管“defaults”段不强制命名,但建议命名以提高可读性。这也是唯一一种指定使用特定段而非默认前一个段的方式。由于“defaults”段名称为可选,因此默认对名称采用非常宽松的校验,甚至允许名称重叠。然而,若某个“defaults”段被其他段引用,则其名称必须符合所有代理名称的语法要求,且在所有“defaults”段中必须唯一。请注意,尽管当前允许重复段名称,但建议一般情况下避免重复,并遵循与代理名称相同的命名语法。此规则未来版本中可能被强制执行。此外,若某个“defaults”段被某个代理显式引用,同时又因是最后一个定义的段而被另一个代理隐式引用,将发出警告。强烈建议避免混合使用显式引用和隐式引用,应始终使用显式引用,或添加一个专用于所有隐式引用的最后通用“defaults”段。

请注意,defaults 段甚至可以从另一个 defaults 段获取初始设置,从而跨多个层级的 defaults 段继承设置。这种方式可以方便地建立特定的配置模板,以承载一组默认设置(例如 TCP 与 HTTP 或短超时与长超时),但可能很快变得难以追踪。

默认情况下,命名的 defaults 段会在配置解析后保留,以便创建动态后端时复用。可通过全局关键字 tune.defaults.purge 改变此行为。

所有代理名称必须由大写字母、小写字母、数字、"-"(连字符)、’_’(下划线)、’.’(点号)和 “:"(冒号)组成。ACL 名称区分大小写,这意味着 “www” 和 “WWW” 是两个不同的代理。

历史上,当满足某些条件时(例如,当代理不具备相同的前端/后端能力时),所有代理名称之间可以重叠,但这曾导致日志中出现过多问题,以及在 CLI 操作、stick-table 名称和统计信息检索方面造成混淆。现在,无论代理的具体能力如何,两个代理的名称必须不同。

目前,HAProxy 支持两种主要代理模式:“tcp”(也称为第 4 层)和 “http”(也称为第 7 层)。在第 4 层模式下,HAProxy 仅在两端之间转发双向流量。在第 7 层模式下,HAProxy 会分析协议,并可根据任意条件,对请求或响应中的任意内容执行允许、阻止、切换、添加、修改或移除操作。

在 HTTP 模式下,通过连接传输的请求和响应所应用的处理方式,取决于前端的 HTTP 选项与后端选项的组合。HAProxy 支持三种连接模式:

  • KAL:持久连接(“option http-keep-alive”)为默认模式:所有请求和响应均被处理,连接在响应与新请求之间保持打开状态但处于空闲状态。

  • SCL:服务端关闭(“option http-server-close”):在收到响应结束后,关闭面向服务器的连接,但保持面向客户端的连接打开。

  • CLO:关闭(“option httpclose”):在响应结束之后关闭连接,并在两个方向上附加 “Connection: close”。

通过前端和后端的连接所采用的有效模式,可根据两个代理模式按以下矩阵确定,但简而言之,模式具有对称性,持久连接为最弱选项,关闭为最强选项。

               Backend mode
                | KAL | SCL | CLO
            ----+-----+-----+----
            KAL | KAL | SCL | CLO
            ----+-----+-----+----
   mode     SCL | SCL | SCL | CLO
            ----+-----+-----+----
            CLO | CLO | CLO | CLO

可以将 TCP 前端与 HTTP 后端串联使用。若仅处理 HTTP 流量,则此举毫无意义。但可用于在同一个前端中处理多种协议。在此情况下,客户端连接首先作为原始 TCP 连接处理,随后升级为 HTTP。升级前,内容处理基于原始数据进行。升级后,数据将使用一种称为 HTX 的内部表示形式进行解析和存储,此时不再可能依赖原始表示形式。无法回退。

有两种升级方式:就地升级和破坏性升级。第一种涉及从 TCP 升级至 HTTP/1。在 HTTP/1 中,请求处理是串行的,因此应用层流可以被保留。第二种涉及从 TCP 升级至 HTTP/2。由于 HTTP/2 是多路复用协议,应用层流无法与任何 HTTP/2 流关联,因而被破坏。当 HAProxy 在底层 H2 多路复用器中接收到新的 HTTP/2 流时,会创建新的应用层流。理解这一差异至关重要,因为它会显著改变数据处理方式。执行 HTTP/1 升级时,对原始数据已执行的应用层处理既不会丢失也不会重新执行;而执行 HTTP/2 升级时,应用层流彼此独立,每个流都会系统性地重新评估所有前端规则。如前所述,第一个流(即 TCP 流)会被破坏,但仅在前端规则评估完成后。

当在 TCP 代理中执行 HTTP 处理时,还有一个重要点需要理解。 虽然 HAProxy 能够在 tcp-request 内容规则中实时解析 HTTP/1,但无法解析 HTTP/2。 仅能解析 HTTP/2 的前导信息(preface)。这在 TCP 环境下的 HTTP 内容分析中是一个重大限制。 具体而言,仅能判断接收到的数据是否为 HTTP。例如,无法根据 Host 头的值选择后端,而这一操作在 HTTP/1 中极为简单。 值得庆幸的是,存在一种解决方案可缓解此缺陷。

有两种方式执行 HTTP 升级。第一种是传统方法,即选择一个 HTTP 后端。当后端被设置时,升级即发生。因此,在就地升级场景下,仅考虑后端配置对 HTTP 数据处理的影响。在破坏性升级场景下,应用流被销毁,其处理过程也随之停止。采用此方法时,选择支持 HTTP/2 连接的后端的可能性极为有限,如上所述,且基本无实际意义,因为流已被销毁。第二种方法是在 tcp-request content 规则评估期间,通过 “switch-mode http” 动作执行升级。在此情况下,升级在前端上下文中进行,可以在该前端中定义 HTTP 指令。对于就地升级,可尽早获得 HTTP 分析的全部功能。其行为与 HTTP 前端非常接近。对于破坏性升级,除无法基于有限信息选择后端外,其余无实质影响。此方法为推荐方案。因此,仅需在 tcp-request content 规则中检测请求协议以执行 HTTP 升级即可。其余所有 HTTP 操作可移至前端 http-request 规则集。请注意,tcp-request content 规则始终在每个流上评估,此行为不可更改。

4.1. 代理关键字矩阵

以下关键词列表受支持。大多数关键词仅可在有限的段类型中使用。部分关键词标有“已弃用”,因其继承自旧语法,可能造成混淆或功能受限,现已推荐使用新关键词替代。标有“(*)”的关键词可选择性地通过“no”前缀进行反转,例如“no option contstats”。当某选项默认已启用,而需在特定实例中禁用时,此用法有意义。此类选项还可使用“default”前缀,以恢复默认设置,无论此前“defaults”段中如何配置。标有“(!)”的关键词仅在命名的“defaults”段中受支持,不适用于匿名段。

请注意:部分危险且不推荐使用的指令故意未列在下表中。此举出于刻意。这些指令已有文档说明,但不在下方列出,也是为了进一步劝阻用户使用。

 keyword                              defaults   frontend   listen    backend
------------------------------------+----------+----------+---------+---------
acl                                       X (!)      X         X         X
backlog                                   X          X         X         -
balance                                   X          -         X         X
be-unpublished                            -          -         X         X
bind                                      -          X         X         -
capture cookie                            -          X         X         -
capture request header                    -          X         X         -
capture response header                   -          X         X         -
clitcpka-cnt                              X          X         X         -
clitcpka-idle                             X          X         X         -
clitcpka-intvl                            X          X         X         -
compression                               X          X         X         X
cookie                                    X          -         X         X
crt                                       -          X         X         -
declare capture                           -          X         X         -
default-server                            X          -         X         X
default_backend                           X          X         X         -
description                               -          X         X         X
disabled                                  X          X         X         X
dispatch                    (deprecated)  -          -         X         X
email-alert from                          X          X         X         X
email-alert level                         X          X         X         X
email-alert mailers                       X          X         X         X
email-alert myhostname                    X          X         X         X
email-alert to                            X          X         X         X
enabled                                   X          X         X         X
errorfile                                 X          X         X         X
errorfiles                                X          X         X         X
errorloc                                  X          X         X         X
errorloc302                               X          X         X         X
-- keyword -------------------------- defaults - frontend - listen -- backend -
errorloc303                               X          X         X         X
error-log-format                          X          X         X         -
external-check command                    X          -         X         X
external-check path                       X          -         X         X
force-persist                             -          -         X         X
force-be-switch                           -          X         X         -
filter                                    -          X         X         X
filter-sequence                           -          X         X         X
fullconn                                  X          -         X         X
guid                                      -          X         X         X
hash-balance-factor                       X          -         X         X
hash-preserve-affinity                    X          -         X         X
hash-type                                 X          -         X         X
http-after-response                       X (!)      X         X         X
http-check comment                        X          -         X         X
http-check connect                        X          -         X         X
http-check disable-on-404                 X          -         X         X
http-check expect                         X          -         X         X
http-check send                           X          -         X         X
http-check send-state                     X          -         X         X
http-check set-var                        X          -         X         X
http-check unset-var                      X          -         X         X
http-error                                X          X         X         X
http-request                              X (!)      X         X         X
http-response                             X (!)      X         X         X
http-reuse                                X          -         X         X
http-send-name-header                     X          -         X         X
id                                        -          X         X         X
ignore-persist                            -          -         X         X
load-server-state-from-file               X          -         X         X
log                                  (*)  X          X         X         X
log-format                                X          X         X         -
log-format-sd                             X          X         X         -
log-tag                                   X          X         X         X
log-steps                                 X          X         X         -
max-keep-alive-queue                      X          -         X         X
max-session-srv-conns                     X          X         X         -
maxconn                                   X          X         X         -
mode                                      X          X         X         X
monitor fail                              -          X         X         -
monitor-uri                               X          X         X         -
option abortonclose                  (*)  X          X         X         X
option allbackups                    (*)  X          -         X         X
option checkcache                    (*)  X          -         X         X
option clitcpka                      (*)  X          X         X         -
option contstats                     (*)  X          X         X         -
option disable-h2-upgrade            (*)  X          X         X         -
option dontlog-normal                (*)  X          X         X         -
option dontlognull                   (*)  X          X         X         -
-- keyword -------------------------- defaults - frontend - listen -- backend -
option external-check                     X          -         X         X
option forwardfor                         X          X         X         X
option forwarded                     (*)  X          -         X         X
option h1-case-adjust-bogus-client   (*)  X          X         X         -
option h1-case-adjust-bogus-server   (*)  X          -         X         X
option http-buffer-request           (*)  X          X         X         X
option http-drop-request-trailers    (*)  X          -         -         X
option http-drop-response-trailers   (*)  X          -         X         -
option http-ignore-probes            (*)  X          X         X         -
option http-keep-alive               (*)  X          X         X         X
option http-no-delay                 (*)  X          X         X         X
option http-pretend-keepalive        (*)  X          -         X         X
option http-restrict-req-hdr-names        X          X         X         X
option http-server-close             (*)  X          X         X         X
option http-use-proxy-header         (*)  X          X         X         -
option httpchk                            X          -         X         X
option httpclose                     (*)  X          X         X         X
option httplog                            X          X         X         -
option httpslog                           X          X         X         -
option idle-close-on-response        (*)  X          X         X         -
option independent-streams           (*)  X          X         X         X
option ldap-check                         X          -         X         X
option log-health-checks             (*)  X          -         X         X
option log-separate-errors           (*)  X          X         X         -
option logasap                       (*)  X          X         X         -
option mysql-check                        X          -         X         X
option nolinger                      (*)  X          X         X         X
option originalto                         X          X         X         X
option persist                       (*)  X          -         X         X
option pgsql-check                        X          -         X         X
option prefer-last-server            (*)  X          -         X         X
option redispatch                    (*)  X          -         X         X
option redis-check                        X          -         X         X
option smtpchk                            X          -         X         X
option socket-stats                  (*)  X          X         X         -
option splice-auto                   (*)  X          X         X         X
option splice-request                (*)  X          X         X         X
option splice-response               (*)  X          X         X         X
option spop-check                         X          -         X         X
option srvtcpka                      (*)  X          -         X         X
option ssl-hello-chk                      X          -         X         X
-- keyword -------------------------- defaults - frontend - listen -- backend -
option tcp-check                          X          -         X         X
option tcp-smart-accept              (*)  X          X         X         -
option tcp-smart-connect             (*)  X          -         X         X
option tcpka                              X          X         X         X
option tcplog                             X          X         X         -
option transparent      (deprecated) (*)  X          -         X         X
option use-small-buffers             (*)  X          -         X         X
persist rdp-cookie                        X          -         X         X
quic-initial                              X (!)      X         X         -
rate-limit sessions                       X          X         X         -
redirect                                  -          X         X         X
-- keyword -------------------------- defaults - frontend - listen -- backend -
retries                                   X          -         X         X
retry-on                                  X          -         X         X
server                                    -          -         X         X
server-state-file-name                    X          -         X         X
server-template                           -          -         X         X
source                                    X          -         X         X
srvtcpka-cnt                              X          -         X         X
srvtcpka-idle                             X          -         X         X
srvtcpka-intvl                            X          -         X         X
stats admin                               -          X         X         X
stats auth                                X          X         X         X
stats enable                              X          X         X         X
stats hide-version                        X          X         X         X
stats http-request                        -          X         X         X
stats realm                               X          X         X         X
stats refresh                             X          X         X         X
stats scope                               X          X         X         X
stats show-desc                           X          X         X         X
stats show-legends                        X          X         X         X
stats show-node                           X          X         X         X
stats show-version                        X          X         X         X
stats uri                                 X          X         X         X
-- keyword -------------------------- defaults - frontend - listen -- backend -
stick match                               -          -         X         X
stick on                                  -          -         X         X
stick store-request                       -          -         X         X
stick store-response                      -          -         X         X
stick-table                               -          X         X         X
tcp-check comment                         X          -         X         X
tcp-check connect                         X          -         X         X
tcp-check expect                          X          -         X         X
tcp-check send                            X          -         X         X
tcp-check send-lf                         X          -         X         X
tcp-check send-binary                     X          -         X         X
tcp-check send-binary-lf                  X          -         X         X
tcp-check set-var                         X          -         X         X
tcp-check unset-var                       X          -         X         X
tcp-request connection                    X (!)      X         X         -
tcp-request content                       X (!)      X         X         X
tcp-request inspect-delay                 X (!)      X         X         X
tcp-request session                       X (!)      X         X         -
tcp-response content                      X (!)      -         X         X
tcp-response inspect-delay                X (!)      -         X         X
timeout check                             X          -         X         X
timeout client                            X          X         X         -
timeout client-fin                        X          X         X         -
timeout client-hs                         X          X         X         -
timeout connect                           X          -         X         X
timeout http-keep-alive                   X          X         X         X
timeout http-request                      X          X         X         X
timeout queue                             X          -         X         X
timeout server                            X          -         X         X
timeout server-fin                        X          -         X         X
timeout tarpit                            X          X         X         X
timeout tunnel                            X          -         X         X
transparent                 (deprecated)  X          -         X         X
unique-id-format                          X          X         X         X
unique-id-header                          X          X         X         -
use_backend                               -          X         X         -
use-fcgi-app                              -          -         X         X
use-server                                -          -         X         X
------------------------------------+----------+----------+---------+---------
 keyword                              defaults   frontend   listen    backend

4.2. 按字母顺序排序的关键字参考

本段描述了每个关键字及其用法。

acl <aclname> <criterion> [flags] [operator] <value> ...

acl <aclname> <criterion> [flags] [operator] <value> ...

声明或完成访问控制列表。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes(!) | yes | yes | yes

该指令仅可在命名的 defaults 段中使用,不可在匿名段中使用。在 defaults 段中定义的 ACL 不可被使用该段的其他段访问。

示例:

acl invalid_src  src          0.0.0.0/7 224.0.0.0/3
acl invalid_src  src_port     0:1023
acl local_dst    hdr(host) -i localhost

请参阅 第 7 节 了解 ACL 的使用方法。

backlog <conns>

backlog <conns>

向系统提供关于期望监听队列大小的近似提示

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:

<conns>   is the number of pending connections. Depending on the operating
          system, it may represent the number of already acknowledged
          connections, of non-acknowledged ones, or both.

此选项仅对流监听器(包括 QUIC 监听器)有意义。然而,其行为与 QUIC 实例并不完全相同。

对于除 QUIC 以外的所有监听器,为防范 SYN 洪水攻击,一种解决方案是增大系统的 SYN 队列长度。根据系统不同,该参数有时可通过系统参数调整,有时则完全不可调,有时系统会依赖应用程序在调用 listen() 系统调用时提供的提示。默认情况下,HAProxy 会将前端的 maxconn 值传递给 listen() 系统调用。在能够利用该值的系统上,有时指定不同的值会更有用,因此引入了 backlog 参数。

在 Linux 2.4 上,该参数会被系统忽略。在 Linux 2.6 上,它作为提示使用,系统最多接受小于等于最小大于该值的 2 的幂次,且永远不会超过某些限制(通常为 32768)。

对于 QUIC 监听器,backlog 为活跃握手的最大数量和待接受连接的数量设定了共享上限。握手阶段主要依赖于与远端对等节点的网络延迟,而第二阶段则完全取决于 HAProxy 的负载。当任一限制达到时,HAProxy 将开始丢弃 INITIAL 数据包的接收,阻止任何新连接的分配,直至连接数量超出部分开始下降。此情况可能导致浏览器静默降级 HTTP 版本并切换至 TCP。

另请参阅:“maxconn”以及目标操作系统的调优指南。

balance <algorithm> [ <arguments> ]

balance <algorithm> [ <arguments> ]
balance url_param <param> [check_post]

定义后端所使用的负载均衡算法。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<algorithm> is the algorithm used to select a server when doing load
            balancing. This only applies when no persistence information
            is available, or when a connection is redispatched to another
            server. <algorithm> may be one of the following:

  roundrobin  Each server is used in turns, according to their weights.
              This is the smoothest and fairest algorithm when the server's
              processing time remains equally distributed. This algorithm
              is dynamic, which means that server weights may be adjusted
              on the fly for slow starts for instance. It is limited by
              design to 4095 active servers per backend. Note that in some
              large farms, when a server becomes up after having been down
              for a very short time, it may sometimes take a few hundreds
              requests for it to be re-integrated into the farm and start
              receiving traffic. This is normal, though very rare. It is
              indicated here in case you would have the chance to observe
              it, so that you don't worry. Note: weights are ignored for
              backends in LOG mode.

  static-rr   Each server is used in turns, according to their weights.
              This algorithm is as similar to roundrobin except that it is
              static, which means that changing a server's weight on the
              fly will have no effect. On the other hand, it has no design
              limitation on the number of servers, and when a server goes
              up, it is always immediately reintroduced into the farm, once
              the full map is recomputed. It also uses slightly less CPU to
              run (around -1%). This algorithm is not usable in LOG mode.

  leastconn   The server with the lowest number of connections receives the
              connection. Round-robin is performed within groups of servers
              of the same load to ensure that all servers will be used. Use
              of this algorithm is recommended where very long sessions are
              expected, such as LDAP, SQL, TSE, etc... but is not very well
              suited for protocols using short sessions such as HTTP. This
              algorithm is dynamic, which means that server weights may be
              adjusted on the fly for slow starts for instance. It will
              also consider the number of queued connections in addition to
              the established ones in order to minimize queuing. This
              algorithm is not usable in LOG mode.

  first       The first server with available connection slots receives the
              connection. The servers are chosen from the lowest numeric
              identifier to the highest (see server parameter "id"), which
              defaults to the server's position in the farm. Once a server
              reaches its maxconn value, the next server is used. It does
              not make sense to use this algorithm without setting maxconn.
              The purpose of this algorithm is to always use the smallest
              number of servers so that extra servers can be powered off
              during non-intensive hours. This algorithm ignores the server
              weight, and brings more benefit to long session such as RDP
              or IMAP than HTTP, though it can be useful there too. In
              order to use this algorithm efficiently, it is recommended
              that a cloud controller regularly checks server usage to turn
              them off when unused, and regularly checks backend queue to
              turn new servers on when the queue inflates. Alternatively,
              using "http-check send-state" may inform servers on the load.
              This algorithm is not usable in LOG mode.

  hash        Takes a regular sample expression in argument. The expression
              is evaluated for each request and hashed according to the
              configured hash-type. The result of the hash is divided by
              the total weight of the running servers to designate which
              server will receive the request. This can be used in place of
              "source", "uri", "hdr()", "url_param()", "rdp-cookie" to make
              use of a converter, refine the evaluation, or be used to
              extract data from local variables for example. When the data
              is not available, round robin will apply. This algorithm is
              static by default, which means that changing a server's
              weight on the fly will have no effect, but this can be
              changed using "hash-type". This algorithm is not usable for
              backends in LOG mode, please use "log-hash" instead.

  source      The source IP address is hashed and divided by the total
              weight of the running servers to designate which server will
              receive the request. This ensures that the same client IP
              address will always reach the same server as long as no
              server goes down or up. If the hash result changes due to the
              number of running servers changing, many clients will be
              directed to a different server. This algorithm is generally
              used in TCP mode where no cookie may be inserted. It may also
              be used on the Internet to provide a best-effort stickiness
              to clients which refuse session cookies. This algorithm is
              static by default, which means that changing a server's
              weight on the fly will have no effect, but this can be
              changed using "hash-type". See also the "hash" option above.
              This algorithm is not usable for backends in LOG mode.

  uri         This algorithm hashes either the left part of the URI (before
              the question mark) or the whole URI (if the "whole" parameter
              is present) and divides the hash value by the total weight of
              the running servers. The result designates which server will
              receive the request. This ensures that the same URI will
              always be directed to the same server as long as no server
              goes up or down. This is used with proxy caches and
              anti-virus proxies in order to maximize the cache hit rate.
              Note that this algorithm may only be used in an HTTP backend.
              This algorithm is static by default, which means that
              changing a server's weight on the fly will have no effect,
              but this can be changed using "hash-type".

              This algorithm supports two optional parameters "len" and
              "depth", both followed by a positive integer number. These
              options may be helpful when it is needed to balance servers
              based on the beginning of the URI only. The "len" parameter
              indicates that the algorithm should only consider that many
              characters at the beginning of the URI to compute the hash.
              Note that having "len" set to 1 rarely makes sense since most
              URIs start with a leading "/".

              The "depth" parameter indicates the maximum directory depth
              to be used to compute the hash. One level is counted for each
              slash in the request. If both parameters are specified, the
              evaluation stops when either is reached.

              A "path-only" parameter indicates that the hashing key starts
              at the first '/' of the path. This can be used to ignore the
              authority part of absolute URIs, and to make sure that HTTP/1
              and HTTP/2 URIs will provide the same hash. See also the
              "hash" option above.

  url_param   The URL parameter specified in argument will be looked up in
              the query string of each HTTP GET request.

              If the modifier "check_post" is used, then an HTTP POST
              request entity will be searched for the parameter argument,
              when it is not found in a query string after a question mark
              ('?') in the URL. The message body will only start to be
              analyzed once either the advertised amount of data has been
              received or the request buffer is full. In the unlikely event
              that chunked encoding is used, only the first chunk is
              scanned. Parameter values separated by a chunk boundary, may
              be randomly balanced if at all. This keyword used to support
              an optional <max_wait> parameter which is now ignored.

              If the parameter is found followed by an equal sign ('=') and
              a value, then the value is hashed and divided by the total
              weight of the running servers. The result designates which
              server will receive the request.

              This is used to track user identifiers in requests and ensure
              that a same user ID will always be sent to the same server as
              long as no server goes up or down. If no value is found or if
              the parameter is not found, then a round robin algorithm is
              applied. Note that this algorithm may only be used in an HTTP
              backend. This algorithm is static by default, which means
              that changing a server's weight on the fly will have no
              effect, but this can be changed using "hash-type". See also
              the "hash" option above.

  hdr(<name>) The HTTP header <name> will be looked up in each HTTP
              request. Just as with the equivalent ACL 'hdr()' function,
              the header name in parenthesis is not case sensitive. If the
              header is absent or if it does not contain any value, the
              roundrobin algorithm is applied instead.

              An optional 'use_domain_only' parameter is available, for
              reducing the hash algorithm to the main domain part with some
              specific headers such as 'Host'. For instance, in the Host
              value "haproxy.1wt.eu", only "1wt" will be considered.

              This algorithm is static by default, which means that
              changing a server's weight on the fly will have no effect,
              but this can be changed using "hash-type". See also the
              "hash" option above.

  random
  random(<draws>)
              A random number will be used as the key for the consistent
              hashing function. This means that the servers' weights are
              respected, dynamic weight changes immediately take effect, as
              well as new server additions. Random load balancing can be
              useful with large farms or when servers are frequently added
              or removed as it may avoid the hammering effect that could
              result from roundrobin or leastconn in this situation. The
              hash-balance-factor directive can be used to further improve
              fairness of the load balancing, especially in situations
              where servers show highly variable response times. When an
              argument <draws> is present, it must be an integer value one
              or greater, indicating the number of draws before selecting
              the least loaded of these servers. It was indeed demonstrated
              that picking the least loaded of two servers is enough to
              significantly improve the fairness of the algorithm, by
              always avoiding to pick the most loaded server within a farm
              and getting rid of any bias that could be induced by the
              unfair distribution of the consistent list. Higher values N
              will take away N-1 of the highest loaded servers at the
              expense of performance. With very high values, the algorithm
              will converge towards the leastconn's result but much slower.
              In addition, for large server farms with very low loads (or
              perfect balance), comparing loads will often lead to a tie,
              so in case of equal loads between all measured servers, their
              request rate over the last second are compared, which allows
              to better balance server usage over time in the same spirit
              as roundrobin does, and smooth consistent hash unfairness.
              The default value is 2, which generally shows very good
              distribution and performance. For large farms with low loads
              (less than a few requests per second per server), it may help
              to raise it to 3 or even 4. This algorithm is also known as
              the Power of Two Random Choices and is described here:
              http://www.eecs.harvard.edu/~michaelm/postscripts/handbook2001.pdf

              For backends in LOG mode, the number of draws is ignored and
              a single random is picked since there is no notion of server
              load. Random log balancing can be useful with large farms or
              when servers are frequently added or removed from the pool of
              available servers as it may avoid the hammering effect that
              could result from roundrobin in this situation.

  rdp-cookie
  rdp-cookie(<name>)
              The RDP cookie <name> (or "mstshash" if omitted) will be
              looked up and hashed for each incoming TCP request. Just as
              with the equivalent ACL 'req.rdp_cookie()' function, the name
              is not case-sensitive. This mechanism is useful as a degraded
              persistence mode, as it makes it possible to always send the
              same user (or the same session ID) to the same server. If the
              cookie is not found, the normal roundrobin algorithm is
              used instead.

              Note that for this to work, the frontend must ensure that an
              RDP cookie is already present in the request buffer. For this
              you must use 'tcp-request content accept' rule combined with
              a 'req.rdp_cookie_cnt' ACL.

              This algorithm is static by default, which means that
              changing a server's weight on the fly will have no effect,
              but this can be changed using "hash-type". See also the
              "hash" option above.

  log-hash    Takes a comma-delimited list of converters in argument. These
              converters are applied in sequence to the input log message,
              and the result will be cast as a string then hashed according
              to the configured hash-type. The resulting hash will be used
              to select the destination server among the ones declared in
              the log backend. The goal of this algorithm is to be able to
              extract a key within the final log message using string
              converters and then be able to stick to the same server thanks
              to the hash. Only "map-based" hashes are supported for now.
              This algorithm is only usable for backends in LOG mode, for
              others, please use "hash" instead.

  sticky      Tries to stick to the same server as much as possible. The
              first server in the list of available servers receives all
              the log messages. When the server goes DOWN, the next server
              in the list takes its place. When a previously DOWN server
              goes back UP it is added at the end of the list so that the
              sticky server doesn't change until it becomes DOWN.

<arguments> is an optional list of arguments which may be needed by some
            algorithms. Right now, only "url_param", "uri" and "log-hash"
            support an optional argument.

当后端未设置其他算法、模式或选项时,其负载均衡算法默认为“random”。每个后端的算法只能设置一次。

对于需要同一连接的认证方案(如 NTLM),不得使用基于 URI 的算法,否则后续请求可能被路由至不同的后端服务器,从而破坏 NTLM 所依赖的无效假设。

TCP/HTTP 示例:

balance roundrobin
balance url_param userid
balance url_param session_id check_post 64
balance hdr(User-Agent)
balance hdr(host)
balance hdr(Host) use_domain_only
balance hash req.cookie(clientid)
balance hash var(req.client_id)
balance hash req.hdr_ip(x-forwarded-for,-1),ipmask(24)

日志后端示例:

global
  log backend@mylog-rrb local0 # send all logs to mylog-rrb backend
  log backend@mylog-hash local0 # send all logs to mylog-hash backend

backend mylog-rrb
  mode log
  balance roundrobin

  server s1 udp@127.0.0.1:514 # will receive 50% of log messages
  server s2 udp@127.0.0.1:514

backend mylog-hash
  mode log

  # extract "METHOD URL PROTO" at the end of the log message,
  # and let haproxy hash it so that log messages generated from
  # similar requests get sent to the same syslog server:
  balance log-hash 'field(-2,\")'

  # server list here
  server s1 127.0.0.1:514
  #...

请注意:在使用 “check_post” 扩展与 “url_param” 时,必须考虑以下注意事项和限制:

- all POST requests are eligible for consideration, because there is no way
  to determine if the parameters will be found in the body or entity which
  may contain binary data. Therefore another method may be required to
  restrict consideration of POST requests that have no URL parameters in
  the body. (see acl http_end)

- using a `<max_wait>` value larger than the request buffer size does not
  make sense and is useless. The buffer size is set at build time, and
  defaults to 16 kB.

- Content-Encoding is not supported, the parameter search will probably
  fail; and load balancing will fall back to Round Robin.

- Expect: 100-continue is not supported, load balancing will fall back to
  Round Robin.

- Transfer-Encoding (RFC7230 3.3.1) is only supported in the first chunk.
  If the entire parameter value is not present in the first chunk, the
  selection of server is undefined (actually, defined by how little
  actually appeared in the first chunk).

- This feature does not support generation of a 100, 411 or 501 response.

- In some cases, requesting "check_post" MAY attempt to scan the entire
  contents of a message body. Scanning normally terminates when linear
  white space or control characters are found, indicating the end of what
  might be a URL parameter list. This is probably not a concern with SGML
  type message bodies.

另请参阅: “dispatch”、“cookie”、“transparent”、“hash-type”。

be-unpublished

be-unpublished

指示后端以未发布状态启动。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend no | no | yes | yes

使用此指令后,其他代理中引用当前代理的 use_backend 和 default_backend 规则会被忽略,并继续评估后续的内容切换规则。不过,force-be-switch 规则可以绕过这一限制。

该状态与禁用状态类似,但有几点不同。首先,未发布的后端仍会完整初始化,包括继续运行服务器健康检查。其次,可通过 CLI 的 publish backend 命令将后端公开发布。详见管理手册。

另请参阅:force-be-switch

bind [<address>]:<port_range> [, ...] [param*]

bind [<address>]:<port_range> [, ...] [param*]
bind /<path> [, ...] [param*]

在前端中定义一个或多个监听地址和/或端口。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend 否 | 是 | 是 | 否

参数:

<address>     is optional and can be a host name, an IPv4 address, an IPv6
              address, or '*'. It designates the address the frontend will
              listen on. If unset, all IPv4 addresses of the system will be
              listened on. The same will apply for '*' or the system's
              special address "0.0.0.0". The IPv6 equivalent is '::'. Note
              that for UDP, specific OS features are required when binding
              on multiple addresses to ensure the correct network interface
              and source address will be used on response. In other way,
              for QUIC listeners only bind on multiple addresses if running
              with a modern enough systems.

              Optionally, an address family prefix may be used before the
              address to force the family regardless of the address format,
              which can be useful to specify a path to a unix socket with
              no slash ('/'). Currently supported prefixes are:
                - 'ipv4@'  -> address is always IPv4
                - 'ipv6@'  -> address is always IPv6
                - 'udp@'   -> address is resolved as IPv4 or IPv6 and
                  protocol UDP is used. Currently those listeners are
                  supported only in log-forward sections.
                - 'udp4@'  -> address is always IPv4 and protocol UDP
                  is used. Currently those listeners are supported
                  only in log-forward sections.
                - 'udp6@'  -> address is always IPv6 and protocol UDP
                  is used. Currently those listeners are supported
                  only in log-forward sections.
                - 'unix@'  -> address is a path to a local unix socket
                - 'abns@'  -> address is in abstract namespace (Linux only).
                - 'abnsz@'  -> address is in abstract namespace (Linux only)
                   but it is explicitly zero-terminated. This means no \0
                   padding is used to complete sun_path. It is useful to
                   interconnect with programs that don't implement the
                   default abns naming logic that haproxy uses.
                - 'fd@<n>' -> use file descriptor <n> inherited from the
                  parent. The fd must be bound and may or may not already
                  be listening.
                - 'sockpair@<n>'-> like fd@ but you must use the fd of a
                  connected unix socket or of a socketpair. The bind waits
                  to receive a FD over the unix socket and uses it as if it
                  was the FD of an accept(). Should be used carefully.
                - 'quic4@' -> address is resolved as IPv4 and protocol UDP
                  is used. Note that to achieve the best performance with a
                  large traffic you should keep "tune.quic.fe.sock-per-conn
                  default-on". Else QUIC connections will be multiplexed
                  over the listener socket. Another alternative would be to
                  duplicate QUIC listener instances over several threads,
                  for example using "shards" keyword to at least reduce
                  thread contention.
                - 'quic6@' -> address is resolved as IPv6 and protocol UDP
                  is used. The performance note for QUIC over IPv4 applies
                  as well.
                - 'rhttp@' [ EXPERIMENTAL ] -> used for reverse HTTP.
                  Address must be a server with the format
                  '<backend>/<server>'. The server will be used to
                  instantiate connections to a remote address. The listener
                  will try to maintain "nbconn" connections. This is an
                  experimental features which requires
                  "expose-experimental-directives" on a line before this
                  bind.

              You may want to reference some environment variables in the
              address parameter, see section 2.3 about environment
              variables.

<port_range>  is either a unique TCP port, or a port range for which the
              proxy will accept connections for the IP address specified
              above. The port is mandatory for TCP listeners. Note that in
              the case of an IPv6 address, the port is always the number
              after the last colon (':'). A range can either be:
               - a numerical port (ex: '80')
               - a dash-delimited ports range explicitly stating the lower
                 and upper bounds (ex: '2000-2100') which are included in
                 the range.

              Particular care must be taken against port ranges, because
              every <address:port> couple consumes one socket (= a file
              descriptor), so it's easy to consume lots of descriptors
              with a simple range, and to run out of sockets. Also, each
              <address:port> couple must be used only once among all
              instances running on a same system. Please note that binding
              to ports lower than 1024 generally require particular
              privileges to start the program, which are independent of
              the 'uid' parameter.

<path>        is a UNIX socket path beginning with a slash ('/'). This is
              alternative to the TCP listening port. HAProxy will then
              receive UNIX connections on the socket located at this place.
              The path must begin with a slash and by default is absolute.
              It can be relative to the prefix defined by "unix-bind" in
              the global section. Note that the total length of the prefix
              followed by the socket path cannot exceed some system limits
              for UNIX sockets, which commonly are set to 107 characters.

<param*>      is a list of parameters common to all sockets declared on the
              same line. These numerous parameters depend on OS and build
              options and have a complete section dedicated to them. Please
              refer to section 5 to for more details.

可以指定以逗号分隔的地址:端口组合列表。前端将在此列出的所有地址上监听。前端可监听的地址和端口数量没有固定限制,同时前端中“bind”语句的数量也没有限制。

示例:

listen http_proxy
    bind:80,:443
    bind 10.0.0.1:10080,10.0.0.1:10443
    bind /var/run/ssl-frontend.sock user root mode 600 accept-proxy

listen http_https_proxy
    bind:80
    bind:443 ssl crt /etc/haproxy/site.pem

listen http_https_proxy_explicit
    bind ipv6@:80
    bind ipv4@public_ssl:443 ssl crt /etc/haproxy/site.pem
    bind unix@ssl-frontend.sock user root mode 600 accept-proxy

listen external_bind_app1
    bind "fd@${FD_APP1}"

listen h3_quic_proxy
    bind quic4@10.0.0.1:8888 ssl crt /etc/mycrt

请注意:关于 Linux 的抽象命名空间套接字,“abns” HAProxy 套接字使用 sun_path 的完整长度作为地址长度。其他一些程序(如 socat)默认仅使用字符串长度。如需使 socat 的抽象套接字定义与 HAProxy 兼容,请向 socat 的任意抽象套接字定义传递选项 “,unix-tightsocklen=0”,或改用 “abnsz” HAProxy 套接字族。

另请参阅:“source”、“option forwardfor”、“unix-bind”以及 PROXY 协议文档,以及关于绑定选项的第 5 节 。

capture cookie <name> len <length>

capture cookie <name> len <length>

捕获并记录请求和响应中的 Cookie。

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend 否 | 是 | 是 | 否

参数:

<name>    is the beginning of the name of the cookie to capture. In order
          to match the exact name, simply suffix the name with an equal
          sign ('='). The full name will appear in the logs, which is
          useful with application servers which adjust both the cookie name
          and value (e.g. ASPSESSIONXXX).

<length>  is the maximum number of characters to report in the logs, which
          include the cookie name, the equal sign and the value, all in the
          standard "name=value" form. The string will be truncated on the
          right if it exceeds <length>.

仅捕获第一个 Cookie。同时监控“cookie”请求头和“set-cookie”响应头。此功能特别适用于检查应用程序缺陷导致的用户间会话交叉或会话窃取问题,因为通常情况下用户的 Cookie 仅在登录页面发生变更。

当客户端未提供 Cookie 时,相关日志列将报告“-”。当请求未导致服务器分配 Cookie 时,响应列将报告“-”。

捕获操作仅在前端执行,因为必须确保某个前端的日志格式不随后端变化而改变。此行为未来可能会调整。请注意,一个前端中只能存在一条“capture cookie”语句。捕获的最大长度由全局 “tune.http.cookielen” 设置决定,默认值为 63 个字符。无法在“defaults”段中指定捕获。

示例:

capture cookie ASPSESSION len 32

另请参阅:“捕获请求头”、“捕获响应头”,以及关于日志记录的 第 8 节 。

capture request header <name> len <length>

capture request header <name> len <length>

捕获并记录指定请求头的最后一次出现。

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend 否 | 是 | 是 | 否

参数:

<name>    is the name of the header to capture. The header names are not
          case-sensitive, but it is a common practice to write them as they
          appear in the requests, with the first letter of each word in
          upper case. The header name will not appear in the logs, only the
          value is reported, but the position in the logs is respected.

<length>  is the maximum number of characters to extract from the value and
          report in the logs. The string will be truncated on the right if
          it exceeds <length>.

捕获最后一个出现的头的完整值。该值将被添加到日志中,用大括号(’{}’)括起。若捕获多个头,它们将按配置中声明的顺序以竖线(’|’)分隔,并依次出现。不存在的头将被记录为空字符串。请求头捕获的常见用途包括:在虚拟主机环境中捕获“Host”字段,在支持上传时捕获“Content-length”,通过“User-agent”快速区分真实用户与机器人,以及在代理环境中捕获“X-Forwarded-For”以确定请求来源。

请注意,捕获如 “User-agent” 等头时,日志中可能包含空格,这会使日志分析更加困难。因此,如果已知日志解析器不够智能,无法依赖大括号解析,请谨慎选择记录的内容。

对捕获的请求头数量和长度均无限制,但建议保持较低数量以降低每流的内存使用量。为确保同一前端的日志格式一致,头捕获只能在前端段中声明。无法在“defaults”段中指定捕获。

示例:

capture request header Host len 15
capture request header X-Forwarded-For len 15
capture request header Referer len 15

另请参阅:“捕获 cookie”、“捕获响应头”,以及关于日志记录的 第 8 节 。

capture response header <name> len <length>

capture response header <name> len <length>

捕获并记录指定响应头的最后一次出现。

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend 否 | 是 | 是 | 否

参数:

<name>    is the name of the header to capture. The header names are not
          case-sensitive, but it is a common practice to write them as they
          appear in the response, with the first letter of each word in
          upper case. The header name will not appear in the logs, only the
          value is reported, but the position in the logs is respected.

<length>  is the maximum number of characters to extract from the value and
          report in the logs. The string will be truncated on the right if
          it exceeds <length>.

最后一次出现的头字段的完整值将被捕获。捕获结果将被添加到日志中,位于捕获的请求头之后,用大括号(’{}’)括起。若捕获了多个头字段,它们将以竖线(’|’)分隔,并按配置中声明的顺序出现。不存在的头字段将被记录为空字符串。响应头捕获的常见用途包括“Content-length”头,用于指示预期返回的字节数,以及“Location”头,用于追踪重定向。

对响应头的捕获数量和长度均无限制,但建议保持较低数量以控制每流的内存使用量。为确保同一前端的日志格式一致,头捕获只能在前端中声明。无法在“defaults”段中指定捕获。

示例:

capture response header Content-length len 9
capture response header Location len 15

另请参阅:“捕获 cookie”、“捕获请求头”,以及关于日志记录的 第 8 节 。

clitcpka-cnt <count>

clitcpka-cnt <count>

设置 TCP 在客户端侧丢弃连接前应发送的最大保活探测次数。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:

<count>   is the maximum number of keepalive probes.

此关键字对应套接字选项 TCP_KEEPCNT。若未指定此关键字,则使用系统级 TCP 参数(tcp_keepalive_probes)。该设置的可用性取决于操作系统。已知其在 Linux 上可用。

另请参见:“option clitcpka”、“clitcpka-idle”、“clitcpka-intvl”。

clitcpka-idle <timeout>

clitcpka-idle <timeout>

设置连接在 TCP 开始发送保活探测前需保持空闲的时间,若启用,则在客户端侧发送 TCP 保活数据包。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:

<timeout> is the time the connection needs to remain idle before TCP starts
          sending keepalive probes. It is specified in seconds by default,
          but can be in any other unit if the number is suffixed by the
          unit, as explained at the top of this document.

此关键字对应套接字选项 TCP_KEEPIDLE。若未指定此关键字,则使用系统级 TCP 参数(tcp_keepalive_time)。该设置的可用性取决于操作系统。已知其在 Linux 上可用。

另请参见:“option clitcpka”、“clitcpka-cnt”、“clitcpka-intvl”。

clitcpka-intvl <timeout>

clitcpka-intvl <timeout>

设置客户端侧单个 keepalive 探测之间的时间间隔。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:

<timeout> is the time between individual keepalive probes. It is specified
          in seconds by default, but can be in any other unit if the number
          is suffixed by the unit, as explained at the top of this
          document.

此关键字对应套接字选项 TCP_KEEPINTVL。若未指定此关键字,则使用系统级 TCP 参数(tcp_keepalive_intvl)。该设置的可用性取决于操作系统。已知其在 Linux 上可用。

另请参见:“option clitcpka”、“clitcpka-cnt”、“clitcpka-idle”。

compression algo <algorithm> ...

compression algo <algorithm> ...
compression algo-req <algorithm>
compression algo-res <algorithm>
compression type <mime type> ...

启用 HTTP 压缩。

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:

algo     is followed by the list of supported compression algorithms for
         responses (legacy keyword)
algo-req is followed by compression algorithm for request (only one is
  provided).
algo-res is followed by the list of supported compression algorithms for
         responses.
type     is followed by the list of MIME types that will be compressed for
         responses (legacy keyword).
type-req is followed by the list of MIME types that will be compressed for
         requests.
type-res is followed by the list of MIME types that will be compressed for
         responses.

当前支持的算法如下:

identity     this is mostly for debugging, and it was useful for developing
             the compression feature. Identity does not apply any change on
             data.

gzip         applies gzip compression. This setting is only available when
             support for zlib or libslz was built in.

deflate      same as "gzip", but with deflate algorithm and zlib format.
             Note that this algorithm has ambiguous support on many
             browsers and no support at all from recent ones. It is
             strongly recommended not to use it for anything else than
             experimentation. This setting is only available when support
             for zlib or libslz was built in.

raw-deflate  same as "deflate" without the zlib wrapper, and used as an
             alternative when the browser wants "deflate". All major
             browsers understand it and despite violating the standards,
             it is known to work better than "deflate", at least on MSIE
             and some versions of Safari. Do not use it in conjunction
             with "deflate", use either one or the other since both react
             to the same Accept-Encoding token. This setting is only
             available when support for zlib or libslz was built in.

压缩功能将根据请求头中的 Accept-Encoding 决定是否启用。若设置为 identity,则忽略该请求头。若后端服务器支持 HTTP 压缩,这些指令将无操作:HAProxy 会识别已压缩的响应,不再进行二次压缩。若后端服务器不支持 HTTP 压缩,且请求中包含 Accept-Encoding 头,则 HAProxy 将对匹配的响应进行压缩。

当满足以下任一条件时,压缩功能将被禁用: - 请求未在 “Accept-Encoding” 头中声明支持的压缩算法 - 响应消息的协议版本低于 HTTP/1.1 - HTTP 状态码不是 200、201、202 或 203 之一 - 响应既不包含 “Content-Length” 头,也不包含 “Transfer-Encoding” 头且其最后一个值不是 “chunked” - 响应包含 “Content-Type” 头,且其首个值以 “multipart” 开头 - 响应包含 “Cache-control” 头且其值包含 “no-transform” - User-Agent 匹配 “Mozilla/4”,除非其为 MSIE 6 且运行于 XP SP2,或 MSIE 7 及更高版本 - 响应包含 “Content-Encoding” 头,表明响应已压缩(参见压缩卸载) - 响应包含无效的 “ETag” 头或多个 ETag 头 - 负载大小小于最小大小(参见 compression minsize-res)

请注意:压缩功能不会发出 Warning 头。

示例:

compression algo gzip
compression type text/html text/plain

另请参见:“compression offload”、“compression direction”、“compression minsize-req”和“compression minsize-res”

compression minsize-req <size>

compression minsize-req <size>
compression minsize-res <size>

设置应用压缩功能的最小负载大小(以字节为单位)。

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

小于该大小的负载将不会被压缩,以避免对无法显著受益于压缩的数据造成不必要的 CPU 开销。“minsize-req” 适用于请求,“minsize-res” 适用于响应。默认值为 0。

compression offload

compression offload

使 HAProxy 仅作为压缩卸载器工作。

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend 否 | 是 | 是 | 是

offload 设置会使 HAProxy 移除 Accept-Encoding 头,以防止后端服务器对响应进行压缩。强烈建议不要执行此操作,因为这意味着所有压缩工作都将集中于 HAProxy 所在的单一节点上。然而在某些部署场景中,HAProxy 可能位于存在缺陷的网关前端,而该网关的 HTTP 压缩实现存在缺陷且无法关闭。在此情况下,HAProxy 可用于防止该网关发出无效负载。在这种场景下,仅在配置中移除头信息无效,因为该操作在头信息被解析前执行,从而阻止了 HAProxy 自身进行压缩。此时应使用 offload 设置。

如果在 defaults 段中使用此设置,将发出警告并忽略该选项。

另请参见:“压缩类型”、“压缩算法”、“压缩方向”

compression direction <direction> (deprecated)

compression direction <direction> (deprecated)

使 HAProxy 能够压缩请求和响应。有效值为 “request”,仅压缩请求;“response”,仅压缩响应;或 “both”,当需要同时压缩请求和响应时使用。默认值为 “response”。

该指令仅在启用旧版“过滤器压缩”时才相关,因为当显式使用 comp-req 和 comp-res 过滤器时,压缩方向已冗余。

可以用于以下上下文:http

另请参阅:“compression type”、“compression algo”、“compression offload”

cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ]

cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ]
              [ postonly ] [ preserve ] [ httponly ] [ secure ]
              [ domain <domain> ]* [ maxidle <idle> ] [ maxlife <life> ]
              [ dynamic ] [ attr <value> ]*

在后端中启用基于 Cookie 的持久性。

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<name>    is the name of the cookie which will be monitored, modified or
          inserted in order to bring persistence. This cookie is sent to
          the client via a "Set-Cookie" header in the response, and is
          brought back by the client in a "Cookie" header in all requests.
          Special care should be taken to choose a name which does not
          conflict with any likely application cookie. Also, if the same
          backends are subject to be used by the same clients (e.g.
          HTTP/HTTPS), care should be taken to use different cookie names
          between all backends if persistence between them is not desired.

rewrite   This keyword indicates that the cookie will be provided by the
          server and that HAProxy will have to modify its value to set the
          server's identifier in it. This mode is handy when the management
          of complex combinations of "Set-cookie" and "Cache-control"
          headers is left to the application. The application can then
          decide whether or not it is appropriate to emit a persistence
          cookie. Since all responses should be monitored, this mode
          doesn't work in HTTP tunnel mode. Unless the application
          behavior is very complex and/or broken, it is advised not to
          start with this mode for new deployments. This keyword is
          incompatible with "insert" and "prefix".

insert    This keyword indicates that the persistence cookie will have to
          be inserted by HAProxy in server responses if the client did not

          already have a cookie that would have permitted it to access this
          server. When used without the "preserve" option, if the server
          emits a cookie with the same name, it will be removed before
          processing. For this reason, this mode can be used to upgrade
          existing configurations running in the "rewrite" mode. The cookie
          will only be a session cookie and will not be stored on the
          client's disk. By default, unless the "indirect" option is added,
          the server will see the cookies emitted by the client. Due to
          caching effects, it is generally wise to add the "nocache" or
          "postonly" keywords (see below). The "insert" keyword is not
          compatible with "rewrite" and "prefix".

prefix    This keyword indicates that instead of relying on a dedicated
          cookie for the persistence, an existing one will be completed.
          This may be needed in some specific environments where the client
          does not support more than one single cookie and the application
          already needs it. In this case, whenever the server sets a cookie
          named <name>, it will be prefixed with the server's identifier
          and a delimiter. The prefix will be removed from all client
          requests so that the server still finds the cookie it emitted.
          Since all requests and responses are subject to being modified,
          this mode doesn't work with tunnel mode. The "prefix" keyword is
          not compatible with "rewrite" and "insert". Note: it is highly
          recommended not to use "indirect" with "prefix", otherwise server
          cookie updates would not be sent to clients.

indirect  When this option is specified, no cookie will be emitted to a
          client which already has a valid one for the server which has
          processed the request. If the server sets such a cookie itself,
          it will be removed, unless the "preserve" option is also set. In
          "insert" mode, this will additionally remove cookies from the
          requests transmitted to the server, making the persistence
          mechanism totally transparent from an application point of view.
          Note: it is highly recommended not to use "indirect" with
          "prefix", otherwise server cookie updates would not be sent to
          clients.

nocache   This option is recommended in conjunction with the insert mode
          when there is a cache between the client and HAProxy, as it
          ensures that a cacheable response will be tagged non-cacheable if
          a cookie needs to be inserted. This is important because if all
          persistence cookies are added on a cacheable home page for
          instance, then all customers will then fetch the page from an
          outer cache and will all share the same persistence cookie,
          leading to one server receiving much more traffic than others.
          See also the "insert" and "postonly" options.

postonly  This option ensures that cookie insertion will only be performed
          on responses to POST requests. It is an alternative to the
          "nocache" option, because POST responses are not cacheable, so
          this ensures that the persistence cookie will never get cached.
          Since most sites do not need any sort of persistence before the
          first POST which generally is a login request, this is a very
          efficient method to optimize caching without risking to find a
          persistence cookie in the cache.
          See also the "insert" and "nocache" options.

preserve  This option may only be used with "insert" and/or "indirect". It
          allows the server to emit the persistence cookie itself. In this
          case, if a cookie is found in the response, HAProxy will leave it
          untouched. This is useful in order to end persistence after a
          logout request for instance. For this, the server just has to
          emit a cookie with an invalid value (e.g. empty) or with a date in
          the past. By combining this mechanism with the "disable-on-404"
          check option, it is possible to perform a completely graceful
          shutdown because users will definitely leave the server after
          they logout.

httponly  This option tells HAProxy to add an "HttpOnly" cookie attribute
          when a cookie is inserted. This attribute is used so that a
          user agent doesn't share the cookie with non-HTTP components.
          Please check RFC6265 for more information on this attribute.

secure    This option tells HAProxy to add a "Secure" cookie attribute when
          a cookie is inserted. This attribute is used so that a user agent
          never emits this cookie over non-secure channels, which means
          that a cookie learned with this flag will be presented only over
          SSL/TLS connections. Please check RFC6265 for more information on
          this attribute.

domain    This option allows to specify the domain at which a cookie is
          inserted. It requires exactly one parameter: a valid domain
          name. If the domain begins with a dot, the browser is allowed to
          use it for any host ending with that name. It is also possible to
          specify several domain names by invoking this option multiple
          times. Some browsers might have small limits on the number of
          domains, so be careful when doing that. For the record, sending
          10 domains to MSIE 6 or Firefox 2 works as expected.

maxidle   This option allows inserted cookies to be ignored after some idle
          time. It only works with insert-mode cookies. When a cookie is
          sent to the client, the date this cookie was emitted is sent too.
          Upon further presentations of this cookie, if the date is older
          than the delay indicated by the parameter (in seconds), it will
          be ignored. Otherwise, it will be refreshed if needed when the
          response is sent to the client. This is particularly useful to
          prevent users who never close their browsers from remaining for
          too long on the same server (e.g. after a farm size change). When
          this option is set and a cookie has no date, it is always
          accepted, but gets refreshed in the response. This maintains the
          ability for admins to access their sites. Cookies that have a
          date in the future further than 24 hours are ignored. Doing so
          lets admins fix timezone issues without risking kicking users off
          the site.

maxlife   This option allows inserted cookies to be ignored after some life
          time, whether they're in use or not. It only works with insert
          mode cookies. When a cookie is first sent to the client, the date
          this cookie was emitted is sent too. Upon further presentations
          of this cookie, if the date is older than the delay indicated by
          the parameter (in seconds), it will be ignored. If the cookie in
          the request has no date, it is accepted and a date will be set.
          Cookies that have a date in the future further than 24 hours are
          ignored. Doing so lets admins fix timezone issues without risking
          kicking users off the site. Contrary to maxidle, this value is
          not refreshed, only the first visit date counts. Both maxidle and
          maxlife may be used at the time. This is particularly useful to
          prevent users who never close their browsers from remaining for
          too long on the same server (e.g. after a farm size change). This
          is stronger than the maxidle method in that it forces a
          redispatch after some absolute delay.

dynamic   Activate dynamic cookies. When used, a session cookie is
          dynamically created for each server, based on the IP and port
          of the server, and a secret key, specified in the
          "dynamic-cookie-key" backend directive.
          The cookie will be regenerated each time the IP address change,
          and is only generated for IPv4/IPv6.

attr      This option tells HAProxy to add an extra attribute when a
          cookie is inserted. The attribute value can contain any
          characters except control ones or ";". This option may be
          repeated.

每个 HTTP 后端只能有一个持久性 cookie,该 cookie 可在 defaults 段中声明。cookie 的值将为服务器语句中 “cookie” 关键字后指定的值。若未为某个服务器声明 cookie,则不会设置 cookie。

示例:

cookie JSESSIONID prefix
cookie SRV insert indirect nocache
cookie SRV insert postonly indirect
cookie SRV insert indirect nocache maxidle 30m maxlife 8h

另请参见:“balance source”、“capture cookie”、“server”和“ignore-persist”。

declare capture [ request | response ] len <length>

declare capture [ request | response ] len <length>

声明一个捕获槽。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend 否 | 是 | 是 | 否

参数:

<length> is the length allowed for the capture.

此声明仅可在前端或 listen 段中使用,但预留的槽位可在后端中使用。“request”关键字用于为请求分配一个捕获槽位,“response”关键字用于为响应分配一个捕获槽位。

另请参阅:“capture-req”、“capture-res”(样本转换器)、“capture.req.hdr”、“capture.res.hdr”(样本提取)、“http-request capture”和“http-response capture”。

default-server [param*]

default-server [param*]

更改后端中服务器的默认选项

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<param*>  is a list of parameters for this server. The "default-server"
          keyword accepts an important number of options and has a complete
          section dedicated to it. Please refer to section 5 for more
          details.

示例:

default-server inter 1000 weight 13

另请参阅:“服务器”以及 第 5 节 中关于服务器选项的内容

default_backend <backend>

default_backend <backend>

当未匹配任何 “use_backend” 规则时,指定要使用的后端。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:

<backend> is the name of the backend to use.

使用 “use_backend” 关键字在前端与后端之间进行内容切换时,通常需要明确指定当无规则匹配时将使用的后端。这通常是动态后端,用于捕获所有未确定的请求。

如果后端被禁用或未发布,针对该后端的 default_backend 规则将被忽略,流处理将继续在原始代理上进行。

示例:

use_backend     dynamic  if  url_dyn
use_backend     static   if  url_css url_img extension_img
default_backend dynamic

参见:“use_backend”

description <string>

description <string>

描述一个 listen、frontend 或 backend。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend 否 | 是 | 是 | 是

参数:string

允许在 HAProxy HTML 统计信息页面中为相关对象添加描述语句。描述内容将显示在所描述对象名称的右侧。<string> 参数中无需转义空格。

disabled

disabled

禁用代理、前端或后端。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:无

“disabled” 关键字用于禁用实例,主要用于释放监听端口或临时停用服务。实例仍将被创建并进行配置检查,但将以“已停止”状态创建,并在统计信息中显示为已停止状态。该实例不会接收任何流量,也不会发送健康检查或日志。可以通过在“defaults”段中添加“disabled”关键字,一次性禁用多个实例。

默认情况下,无法选择已禁用的后端进行内容切换。然而,当使用 “force-be-switch” 时,部分流量可忽略此限制。

另请参阅: “enabled”,“force-be-switch”

dispatch <address>:<port> (deprecated)

dispatch <address>:<port>   (deprecated)

设置默认服务器地址

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend

参数:

<address> is the IPv4 address of the default server. Alternatively, a
          resolvable hostname is supported, but this name will be resolved
          during start-up.

<ports>   is a mandatory port specification. All connections will be sent
          to this port, and it is not permitted to use port offsets as is
          possible with normal servers.

dispatch 指令

“dispatch” 指令用于指定在无法连接到其他服务器时使用的默认服务器。过去,该指令曾用于将非持久连接转发至辅助负载均衡器。由于其语法简单,也曾被用于实现简单的 TCP 中继。为提高配置清晰度,建议不再使用该指令,而应改用 “server” 指令。

该关键字已在 3.3 版本中弃用,并将在 3.5 版本中移除,原因在于存在一些内部限制(例如不支持 SSL 或空闲连接等)。使用该关键字将发出警告,可通过在全局段启用指令 “expose-deprecated-directives” 来静默此警告。

正确做法是,不使用该指令时,只需声明一个地址和端口相同的服务器。如果“dispatch”指令与其他服务器混合使用,则应将这些服务器的权重配置为零,以确保负载均衡算法永远不会选择它们。

示例:

backend deprecated_setup
    dispatch 192.168.100.100:80 # external load balancer's address
    server s1 192.168.100.1:80 cookie S1 check
    server s2 192.168.100.2:80 cookie S2 check

backend modern_setup
    server external_lb 192.168.100.100:80
    server s1 192.168.100.1:80 cookie S1 check weight 0
    server s2 192.168.100.2:80 cookie S2 check weight 0

另请参见:服务器

dynamic-cookie-key <string>

dynamic-cookie-key <string>

为后端设置动态 Cookie 密钥。

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:用于的密钥。

当启用动态 cookie(参见 cookie 指令中的 “dynamic” 选项)时,将为每个服务器创建一个动态 cookie(除非在 “server” 指令中显式指定),该 cookie 通过服务器的 IP 地址、TCP 端口和密钥的哈希值生成。这样可确保在多个负载均衡器之间实现会话持久性,即使服务器动态添加或移除也能保持会话连续。

enabled

enabled

启用代理、前端或后端。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:无

“enabled” 关键字用于显式启用实例,当默认值已设为 “disabled” 时使用。此用法极为罕见。

另请参见: “be-unpublished”、“disabled”

errorfile <code> <file>

errorfile <code> <file>

返回文件内容,而非 HAProxy 生成的错误信息

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:

<code>    is the HTTP status code. Currently, HAProxy is capable of
          generating codes 200, 400, 401, 403, 404, 405, 407, 408, 410,
          413, 414, 425, 429, 431, 500, 501, 502, 503, and 504.

<file>    designates a file containing the full HTTP response. It is
          recommended to follow the common practice of appending ".http" to
          the filename so that people do not confuse the response with HTML
          error pages, and to use absolute paths, since files are read
          before any chroot is performed.

必须理解,该关键字并非用于重写服务器返回的错误,而是用于重写 HAProxy 检测并返回的错误。这也是为何支持的错误列表被限制在较小的集合中。

状态码 200 在响应匹配 “monitor-uri” 规则的请求时发出。

HAProxy 启动时会解析这些文件,且必须符合 HTTP 规范。文件大小不得超过配置的缓冲区大小(BUFSIZE),通常为 16 kB,否则将返回内部错误。建议不要引用本地内容(例如图片),以避免在所有服务器均不可用时,客户端与 HAProxy 之间产生循环,导致返回错误而非图片。最后,响应大小不得超过(tune.bufsize - tune.maxrewrite),以确保“http-after-response”规则仍有操作空间(参见 “tune.maxrewrite”)。

文件在读取配置的同时被加载并保留在内存中。因此,即使进程已执行 chroot,错误仍会持续返回,且在进程运行期间不会考虑文件的任何变更。开发这些文件的一种简单方法是将其与 403 状态码关联,并查询一个被阻止的 URL。

另请参见: “http-error”, “errorloc”, “errorloc302”, “errorloc303”

示例:

errorfile 400 /etc/haproxy/errorfiles/400badreq.http
errorfile 408 /dev/null  # work around Chrome pre-connect bug
errorfile 403 /etc/haproxy/errorfiles/403forbid.http
errorfile 503 /etc/haproxy/errorfiles/503sorry.http

errorfiles <name> [<code> ...]

errorfiles <name> [<code> ...]

导入在 <name> http-errors 段中定义的错误文件,可全部或部分导入。

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:

<name>  is the name of an existing http-errors section.

<code>  is a HTTP status code. Several status code may be listed.
        Currently, HAProxy is capable of generating codes 200, 400, 401,
        403, 404, 405, 407, 408, 410, 413, 414, 425, 429, 431, 500, 501,
        502, 503, and 504.

在 http-errors 段中定义的名称为 <name> 的错误会被导入当前代理。

若未指定状态码,则导入 http-errors 段中的所有错误文件。否则,仅导入与所列状态码关联的错误文件。这些错误文件将覆盖代理中已定义的自定义错误,且可能被后续导入的错误文件覆盖。

在功能上,这与手动使用 “errorfile” 指令声明所有错误文件完全相同。

有关 HTTP 错误的更多信息,请参阅 “http-error”、“errorfile”、“errorloc”、“errorloc302”、“errorloc303” 以及 第 12.4 节 。

示例:

errorfiles generic
errorfiles site-1 403 404

errorloc <code> <url>

errorloc <code> <url>
errorloc302 <code> <url>

返回 HTTP 重定向至指定 URL,而非 HAProxy 生成的错误

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:

<code>    is the HTTP status code. Currently, HAProxy is capable of
          generating codes 200, 400, 401, 403, 404, 405, 407, 408, 410,
          413, 414, 425, 429, 431, 500, 501, 502, 503, and 504.

<url>     it is the exact contents of the "Location" header. It may contain
          either a relative URI to an error page hosted on the same site,
          or an absolute URI designating an error page on another site.
          Special care should be given to relative URIs to avoid redirect
          loops if the URI itself may generate the same error (e.g. 500).

必须理解,该关键字并非用于重写服务器返回的错误,而是用于重写 HAProxy 检测并返回的错误。这也是为何支持的错误列表被限制在较小的集合中。

状态码 200 在响应匹配 “monitor-uri” 规则的请求时发出。

请注意,这两个关键字均返回 HTTP 302 状态码,指示客户端使用相同的 HTTP 方法获取指定的 URL。在使用非 GET 方法(如 POST)时,这可能会造成问题,因为发送给客户端的 URL 可能不允许用于除 GET 以外的其他方法。为规避此问题,请使用 “errorloc303”,该关键字发送 HTTP 303 状态码,指示客户端必须使用 GET 请求获取该 URL。

另请参阅: “http-error”、“errorfile”、“errorloc303”

errorloc303 <code> <url>

errorloc303 <code> <url>

返回 HTTP 重定向至指定 URL,而非 HAProxy 生成的错误

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:

<code>    is the HTTP status code. Currently, HAProxy is capable of
          generating codes 200, 400, 401, 403, 404, 405, 407, 408, 410,
          413, 414, 425, 429, 431, 500, 501, 502, 503, and 504.

<url>     it is the exact contents of the "Location" header. It may contain
          either a relative URI to an error page hosted on the same site,
          or an absolute URI designating an error page on another site.
          Special care should be given to relative URIs to avoid redirect
          loops if the URI itself may generate the same error (e.g. 500).

必须理解,该关键字并非用于重写服务器返回的错误,而是用于重写 HAProxy 检测并返回的错误。这也是为何支持的错误列表被限制在较小的集合中。

状态码 200 在响应匹配 “monitor-uri” 规则的请求时发出。

请注意,这两个关键字均返回 HTTP 303 状态码,该码指示客户端使用相同的 HTTP GET 方法获取指定的 URL。这解决了与“errorloc”和 302 状态码相关联的常见问题。尽管可能存在一些在 HTTP/1.1 之前设计的老旧浏览器不支持此行为,但截至目前尚未报告此类问题。

另请参见:“http-error”、“errorfile”、“errorloc”、“errorloc302”

email-alert from <emailaddr>

email-alert from <emailaddr>

声明用于邮件警报信封和头中的发件人地址。此地址即为邮件警报的发送来源。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:

<emailaddr> is the from email address to use when sending email alerts

还要求设置 “email-alert mailers” 和 “email-alert to”,若已设置,则为该代理启用邮件告警功能。

参见:“email-alert level”、“email-alert mailers”、“email-alert myhostname”、“email-alert to”,以及关于邮件发送器的第 12.3 节 。

email-alert level <level>

email-alert level <level>

声明将发送邮件告警的消息最大日志级别。这将作为邮件告警发送的过滤器。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:

<level> One of the 8 syslog levels:
          emerg alert crit err warning notice info  debug
        The above syslog levels are ordered from lowest to highest.

默认级别为 alert

还要求设置 “email-alert from”、“email-alert mailers” 和 “email-alert to”,若已设置,则为该代理启用邮件告警功能。

当满足以下条件时发送告警:

  • 未暂停的服务器被标记为不可用,且 <level> 的日志级别为 alert 或更低
  • 暂停的服务器被标记为不可用,且 <level> 的日志级别为 notice 或更低
  • 服务器被标记为可用或进入 drain 状态,且 <level> 的日志级别为 notice 或更低
  • 启用了 “option log-health-checks”,<level> 的日志级别为 info 或更低,且发生健康检查状态更新

参见:“email-alert from”、“email-alert mailers”、“email-alert myhostname”、“email-alert to”,以及关于邮件发送器的第 12.3 节 。

email-alert mailers <mailersect>

email-alert mailers <mailersect>

声明用于发送邮件告警的邮件发送器

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:

<mailersect> is the name of the mailers section to send email alerts.

还要求设置 “email-alert from” 和 “email-alert to”,若已设置,则为该代理启用邮件告警功能。

参见: “email-alert from”、“email-alert level”、“email-alert myhostname”、“email-alert to”,以及关于邮件发送器的第 12.3 节 。

email-alert myhostname <hostname>

email-alert myhostname <hostname>

声明用于与邮件发送器通信时的主机名地址。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:

<hostname> is the hostname to use when communicating with mailers

默认情况下,使用系统的主机名。

还要求设置 “email-alert from”、“email-alert mailers” 和 “email-alert to”,若已设置,则为该代理启用邮件告警功能。

另请参阅:“email-alert from”、“email-alert level”、“email-alert mailers”、“email-alert to”,以及关于邮件发送器的第 12.3 节 。

email-alert to <emailaddr>

email-alert to <emailaddr>

声明邮件警报信封中的收件人地址以及邮件头中的收件人地址。 此地址为邮件警报的发送目标。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:

<emailaddr> is the to email address to use when sending email alerts

还要求设置 “email-alert mailers” 和 “email-alert to”,若已设置,则为该代理启用邮件告警功能。

参见: “email-alert from”、“email-alert level”、“email-alert mailers”、“email-alert myhostname”,以及关于邮件发送器的 第 12.3 节 。

error-log-format <fmt>

error-log-format <fmt>

指定在前端发生连接错误时所使用的日志格式字符串。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

该指令指定用于记录与错误、超时、重试、重分派或 HTTP 状态码 5xx 相关信息的日志格式字符串。该格式将简要用于所有受“log-separate-errors”选项影响的日志行,包括 第 8.2.5 节 中描述的连接错误。

若该指令在 defaults 段中使用,则后续所有前端均将采用相同的日志格式。请参见 section 8.2.6 ,其中详细介绍了自定义日志格式字符串。

“error-log-format” 指令会覆盖之前的 “error-log-format” 指令。

force-persist { if | unless } <condition>

force-persist { if | unless } <condition>

声明一个条件,以强制对已关闭的服务器保持持久性

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend

默认情况下,请求不会被分派至处于关闭状态的服务器。可以使用“option persist”强制分派,但该选项无条件生效,若设置了“option redispatch”,则会在有可用服务器时进行重分派。这使得强制某些请求到达因维护操作而被人为标记为关闭的服务器变得几乎不可能。

force-persist 语句

“force-persist” 语句允许声明多种基于 ACL 的条件,当这些条件满足时,请求将忽略服务器的宕机状态,仍尝试与其建立连接。这使得可以在服务器启动后,仍对健康检查返回错误,同时使用经过特殊配置的浏览器来测试服务。其中一种便捷的方法是使用特定的源 IP 地址,或特定的 Cookie。Cookie 的优势在于,可通过测试页面轻松地在浏览器中添加或移除。服务验证完成后,即可通过向健康检查返回有效响应,将服务对公众开放。

当满足 “if” 条件时,强制持久化功能被启用,或在满足 “unless” 条件时被禁用。使用此功能时,最终的重分派始终被禁用。

另请参阅:“option redispatch”、“ignore-persist”、“persist”以及第 7 节 中关于 ACL 使用的说明。

external-check command <command>

external-check command <command>

执行外部检查时运行的可执行文件

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<command> is the external command to run

传递给命令的参数如下:

<proxy_address> <proxy_port> <server_address> <server_port>

<proxy_address> 和 <proxy_port> 由首个 IPv4、IPv6 或 Unix 套接字类型的监听器推导得出。若监听器为 Unix 套接字,则代理地址(proxy_address)为套接字路径,<proxy_port> 的值为字符串 “NOT_USED”。在后端段中,无法确定监听器,因此 <proxy_address> 和 <proxy_port> 的值均为字符串 “NOT_USED”。

部分值也可通过环境变量提供。

环境变量:

HAPROXY_PROXY_ADDR      The first bind address if available (or empty if not
                        applicable, for example in a "backend" section).

HAPROXY_PROXY_ID        The backend id.

HAPROXY_PROXY_NAME      The backend name.

HAPROXY_PROXY_PORT      The first bind port if available (or empty if not
                        applicable, for example in a "backend" section or
                        for a UNIX socket).

HAPROXY_SERVER_ADDR     The server address.

HAPROXY_SERVER_CURCONN  The current number of connections on the server.

HAPROXY_SERVER_ID       The server id.

HAPROXY_SERVER_MAXCONN  The server max connections.

HAPROXY_SERVER_NAME     The server name.

HAPROXY_SERVER_PORT     The server port if available (or empty for a UNIX
                        socket).

HAPROXY_SERVER_SSL      "0" when SSL is not used, "1" when it is used

HAPROXY_SERVER_PROTO    The protocol used by this server, which can be one
                        of "cli" (the haproxy CLI), "syslog" (syslog TCP
                        server), "peers" (peers TCP server), "h1" (HTTP/1.x
                        server), "h2" (HTTP/2 server), or "tcp" (any other
                        TCP server).

PATH                    The PATH environment variable used when executing
                        the command may be set using "external-check path".

如果执行的命令退出状态为零,则认为检查通过;否则认为检查失败。

示例:

external-check command /bin/true

另请参阅: “external-check”、“option external-check”、“external-check path”

external-check path <path>

external-check path <path>

运行外部检查时所使用的 PATH 环境变量的值

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<path> is the path used when executing external command to run

默认路径为空字符串。

示例:

external-check path "/usr/bin:/bin"

另请参阅:“external-check”、“option external-check”、“external-check command”

force-be-switch { if | unless } <condition>

force-be-switch { if | unless } <condition>

允许内容切换选择已禁用或未发布的后端实例。此规则可供管理员在将服务对外暴露前,用于测试流量。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend 否 | 是 | 是 | 否

另请参见: “disabled”

filter <name> [param*]

filter <name> [param*]

在附加到代理的过滤器列表中添加过滤器 <name>。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend 否 | 是 | 是 | 是

参数:

<name>     is the name of the filter. Officially supported filters are
           referenced in section 9.

<param*>   is a list of parameters accepted by the filter <name>. The
           parsing of these parameters are the responsibility of the
           filter. Please refer to the documentation of the corresponding
           filter (section 9) for all details on the supported parameters.

同一代理可多次使用过滤器行。如需,同一过滤器可被多次引用。

示例:

listen
  bind *:80

  filter trace name BEFORE-HTTP-COMP
  filter compression
  filter trace name AFTER-HTTP-COMP

  compression algo gzip
  compression offload

  server srv1 192.168.0.1:80

参见:第 9 节 ,“filter-sequence”

过滤器序列 { 请求 | 响应 } <filter_list>

指定在代理上声明的过滤器的执行顺序。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend 否 | 是 | 是 | 是

以逗号分隔的过滤器名称列表(<filter_list>),用于指定在代理上声明的过滤器在请求路径或响应路径上应按何种顺序执行。

当未为特定路径(即请求或响应)指定 filter-sequence 时,将使用代理上声明过滤器的顺序。

如果过滤器序列省略了代理上声明的某些过滤器,这些过滤器将不会被执行。 这是一种临时禁用过滤器的有效方式,无需将其从配置中移除。

示例:

global
   lua-load my-filter.lua # defines custom "lua.my-filter"
frontend myfront
   filter comp-req
   filter comp-res
   filter lua.my-filter

   filter-sequence request lua.my-filter,comp-req
   filter-sequence response lua.my-filter,comp-res

另请参见:“过滤器”

fullconn <conns>

fullconn <conns>

指定后端负载达到多少时,服务器将达到最大连接数

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<conns>   is the number of connections on the backend which will make the
          servers use the maximal number of connections.

当服务器配置了 “maxconn” 参数时,表示其并发连接数将不会超过该值。此外,若同时配置了 “minconn” 参数,则表示该限制为动态值,随后端负载变化而调整。此时,服务器将始终至少接受 <minconn> 个连接,且不会超过 <maxconn> 个连接,当后端并发连接数低于 <conns> 时,该限制将在两个数值之间动态调整。这使得在正常负载下可限制服务器负载,而在重要负载时可适度提升负载能力,同时在异常负载情况下避免服务器过载。

由于很难准确设置该值,HAProxy 会自动将其设为所有可能转向此后端的前端(基于 “use_backend” 和 “default_backend” 规则)的 maxconns 之和的 10%。因此,可以安全地不显式设置该值。然而,涉及动态名称的 “use_backend” 不会被计入,因为无法判断其是否可能匹配。

示例:

# The servers will accept between 100 and 1000 concurrent connections each
# and the maximum of 1000 will be reached when the backend reaches 10000
# connections.
backend dynamic
   fullconn   10000
   server     srv1   dyn1:80 minconn 100 maxconn 1000
   server     srv2   dyn2:80 minconn 100 maxconn 1000

另请参阅:“maxconn”、“server”

guid <string>

guid <string>

为该代理指定一个区分大小写的全局唯一 ID。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend 否 | 是 | 是 | 是

<string> 必须在所有 HAProxy 配置中针对每种对象类型保持唯一。格式未作限定,以允许用户自行选择命名策略。唯一限制是其长度不得超过 127 个字符。所有字母数字字符以及 ‘.’、’:’、’-’ 和 ‘_’ 均为有效字符。参见“shm-stats-file”。

hash-balance-factor <factor>

hash-balance-factor <factor>

指定有界负载一致性哈希的均衡因子

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | no | no | yes

参数:

<factor> is the control for the maximum number of concurrent requests to
         send to a server, expressed as a percentage of the average number
         of concurrent requests across all of the active servers.

为使用 “hash-type consistent” 的服务器指定 “hash-balance-factor” 可启用一种算法,该算法可防止任一服务器在短时间内接收过多请求,即使某些哈希桶接收的请求远多于其他桶。将 <factor> 设置为 0(默认值)可禁用此功能。否则,<factor> 必须为大于 100 的百分比。例如,若 <factor> 为 150,则任一服务器的负载不得超过平均负载的 1.5 倍。若使用服务器权重,将予以尊重。

如果首选服务器被排除,算法将根据请求哈希选择另一台服务器,直至找到具有额外容量的服务器。较高的 <factor> 会导致服务器间负载不平衡程度增加,而较低的 <factor> 意味着平均需检查的服务器数量更多,从而影响性能。合理的取值范围为 125 至 200。

此设置也由“balance random”使用,后者内部依赖一致性哈希机制。

另请参见:“balance” 和 “hash-type”。

hash-preserve-affinity { always | maxconn | maxqueue }

hash-preserve-affinity { always | maxconn | maxqueue }

指定在服务器已饱和或队列已满时,使用哈希负载均衡将流分配至服务器的方法。

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

以下值可以指定:

- "always"  : this is the default strategy. A stream is assigned to a
               server based on hashing irrespective of whether the server
               is currently saturated.

- "maxconn" : when selected, servers that have "maxconn" set and are
               currently saturated will be skipped. Another server will be
               picked by following the hashing ring. This has no effect on
               servers that do not set "maxconn". If all servers are
               saturated, the request is enqueued to the last server in the
               hash ring before the initially selected server.

- "maxqueue": when selected, servers that have "maxconn" set, "maxqueue"
               set to a non-zero value (limited queue size) and currently
               have a full queue will be skipped. Another server will be
               picked by following the hashing ring. This has no effect on
               servers that do not set both "maxconn" and "maxqueue".

另请参阅:“maxconn”、“maxqueue”、“hash-balance-factor”

hash-type <method> <function> <modifier>

hash-type <method> <function> <modifier>

指定用于将哈希映射到服务器的方法

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<method> is the method used to select a server from the hash computed by
         the <function>:

  map-based   the hash table is a static array containing all alive servers.
              The hashes will be very smooth, will consider weights, but
              will be static in that weight changes while a server is up
              will be ignored. This means that there will be no slow start.
              Also, since a server is selected by its position in the array,
              most mappings are changed when the server count changes. This
              means that when a server goes up or down, or when a server is
              added to a farm, most connections will be redistributed to
              different servers. This can be inconvenient with caches for
              instance.

  consistent  the hash table is a tree filled with many occurrences of each
              server. The hash key is looked up in the tree and the closest
              server is chosen. This hash is dynamic, it supports changing
              weights while the servers are up, so it is compatible with the
              slow start feature. It has the advantage that when a server
              goes up or down, only its associations are moved. When a
              server is added to the farm, only a few part of the mappings
              are redistributed, making it an ideal method for caches.
              However, due to its principle, the distribution will never be
              very smooth and it may sometimes be necessary to adjust a
              server's weight or its ID to get a more balanced distribution.
              In order to get the same distribution on multiple load
              balancers, it is important that all servers have the exact
              same IDs. Note: consistent hash uses sdbm and avalanche if no
              hash function is specified.

<function> is the hash function to be used:

   sdbm   this function was created initially for sdbm (a public-domain
          reimplementation of ndbm) database library. It was found to do
          well in scrambling bits, causing better distribution of the keys
          and fewer splits. It also happens to be a good general hashing
          function with good distribution, unless the total server weight
          is a multiple of 64, in which case applying the avalanche
          modifier may help.

   djb2   this function was first proposed by Dan Bernstein many years ago
          on comp.lang.c. Studies have shown that for certain workload this
          function provides a better distribution than sdbm. It generally
          works well with text-based inputs though it can perform extremely
          poorly with numeric-only input or when the total server weight is
          a multiple of 33, unless the avalanche modifier is also used.

   wt6    this function was designed for HAProxy while testing other
          functions in the past. It is not as smooth as the other ones, but
          is much less sensible to the input data set or to the number of
          servers. It can make sense as an alternative to sdbm+avalanche or
          djb2+avalanche for consistent hashing or when hashing on numeric
          data such as a source IP address or a visitor identifier in a URL
          parameter.

   crc32  this is the most common CRC32 implementation as used in Ethernet,
          gzip, PNG, etc. It is slower than the other ones but may provide
          a better distribution or less predictable results especially when
          used on strings.

   none   don't hash the key, the key will be used as a hash, this can be
          useful to manually hash the key using a converter for that purpose
          and let haproxy use the result directly. The operation will
          convert the key to a string if it is not already, and parse it as
          an integer whose value will be used as the key. Some input key
          types might not be relevant here (e.g. IP addresses).

<modifier> indicates an optional method applied after hashing the key:

   avalanche   This directive indicates that the result from the hash
               function above should not be used in its raw form but that
               a 4-byte full avalanche hash must be applied first. The
               purpose of this step is to mix the resulting bits from the
               previous hash in order to avoid any undesired effect when
               the input contains some limited values or when the number of
               servers is a multiple of one of the hash's components (64
               for SDBM, 33 for DJB2). Enabling avalanche tends to make the
               result less predictable, but it's also not as smooth as when
               using the original function. Some testing might be needed
               with some workloads. This hash is one of the many proposed
               by Bob Jenkins.

默认哈希类型为“基于映射”(map-based),适用于大多数使用场景。默认函数为“sdbm”,函数的选择应基于被哈希值的取值范围。

另请参阅:“balance”、“hash-balance-factor”、“hash-preserve-affinity”、“server”

http-after-response <action> <options...> [ { if | unless } <condition> ]

http-after-response <action> <options...> [ { if | unless } <condition> ]

对所有第 7 层响应(服务器、应用程序/服务及内部响应)的访问控制。

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes(!) | yes | yes | yes

第 7 层处理中,http-after-response 语句定义了一组规则。这些规则在前端、监听或后端段中按声明顺序进行评估。由于这些规则作用于响应,因此先应用后端规则,再应用前端规则。任何规则均可选择性地跟随一个基于 ACL 的条件,此时仅当该条件为真时才进行评估。

与 http-response 规则不同,此类规则适用于所有响应,包括服务器响应以及 HAProxy 生成的所有响应。这些规则在响应分析结束时进行评估,位于数据转发阶段之前。

条件在动作执行前进行评估,且该动作仅执行一次。因此,即使某个动作改变了作为条件一部分的元素,也不会造成问题。这也意味着多个动作可以依赖同一条件,只要首个改变条件评估结果的动作执行后,其余动作便会自动隐式禁用。例如,当变量为空时,从多个来源为其赋值,即采用此机制。每个实例中对“http-after-response”语句的数量无限制。

在语法中,“http-after-response”之后的第一个关键字是规则的动作,可选地后接该动作所需的若干参数。支持的动作及其相应语法详见 第 4.3 节 “动作”(请查找标记为“HTTP Aft”的动作)。

该指令仅在命名的 defaults 段中可用,不可用于匿名段。在关联的代理段之前,将先评估 defaults 段中定义的规则。为避免歧义,在此情况下,同一 defaults 段不可同时被具备前端能力的代理和具备后端能力的代理使用。这意味着,listen 段不可使用定义了此类规则的 defaults 段。

请注意:在请求解析早期阶段产生的错误由多路复用器在较低层级处理,早于任何 HTTP 分析阶段。因此,这些错误不会触发 http-after-response 规则集的评估。

示例:

http-after-response set-header Strict-Transport-Security "max-age=31536000"
http-after-response set-header Cache-Control "no-store,no-cache,private"
http-after-response set-header Pragma "no-cache"

http-check comment <string>

http-check comment <string>

为后续的 http-check 规则定义注释,若该规则执行失败,将在日志中报告。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<string>  is the comment message to add in logs if the following http-check
          rule fails.

仅适用于 connect、send 和 expect 规则。可用于生成用户友好的错误报告。

另请参阅:“option httpchk”、“http-check connect”、“http-check send”和“http-check expect”。

http-check connect [default] [port <expr>] [addr <ip>] [send-proxy]

http-check connect [default] [port <expr>] [addr <ip>] [send-proxy]
                   [via-socks4] [ssl] [sni <sni>] [alpn <alpn>] [linger]
                   [proto <name>] [comment <msg>]

打开一个新连接以执行 HTTP 健康检查

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

comment <msg>  defines a message to report if the rule evaluation fails.

default      Use default options of the server line to do the health
             checks. The server options are used only if not redefined.

port <expr>  if not set, check port or server port is used.
             It tells HAProxy where to open the connection to.
             <port> must be a valid TCP port source integer, from 1 to
             65535 or an sample-fetch expression.

addr <ip>    defines the IP address to do the health check.

send-proxy   send a PROXY protocol string

via-socks4   enables outgoing health checks using upstream socks4 proxy.

ssl          opens a ciphered connection

sni <sni>    specifies the SNI to use to do health checks over SSL.

alpn <alpn>  defines which protocols to advertise with ALPN. The protocol
             list consists in a comma-delimited list of protocol names,
             for instance: "h2,http/1.1". If it is not set, the server ALPN
             is used.

proto <name> forces the multiplexer's protocol to use for this connection.
             It must be an HTTP mux protocol and it must be usable on the
             backend side. The list of available protocols is reported in
             haproxy -vv.

linger       cleanly close the connection instead of using a single RST.

与 tcp-check 健康检查类似,可配置用于执行 HTTP 健康检查的连接。该指令还应用于描述涉及多个请求/响应交互的场景,这些交互可能在不同端口上进行,或涉及不同的服务器。

当服务器行中未配置 TCP 端口,且未使用 server port 指令时,http-check 序列的第一步必须使用 “http-check connect” 指定端口。

在 http-check 规则集中,必须包含一个 ‘connect’ 规则,且规则集必须以 ‘connect’ 规则开头。此举旨在确保管理员清楚了解其操作意图。

当连接必须启动规则集时,仍可由 set-var、unset-var 或 comment 规则先行。

示例:

# check HTTP and HTTPs services on a server.
# first open port 80 thanks to server line port directive, then
# tcp-check opens port 443, ciphered and run a request on it:
option httpchk

http-check connect
http-check send meth GET uri / ver HTTP/1.1 hdr host haproxy.1wt.eu
http-check expect status 200-399
http-check connect port 443 ssl sni haproxy.1wt.eu
http-check send meth GET uri / ver HTTP/1.1 hdr host haproxy.1wt.eu
http-check expect status 200-399

server www 10.0.0.1 check port 80

另请参阅:“option httpchk”、“http-check send”、“http-check expect”

http-check disable-on-404

http-check disable-on-404

在健康检查返回 HTTP/404 响应时启用维护模式

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:无

当启用此选项时,返回 HTTP 状态码 404 的服务器将不再参与后续的负载均衡,但仍会接收持久连接。这为 Web 管理员提供了一种非常便捷的服务器优雅关闭方式。需要注意的是,处于此模式下检测到失败的服务器不会触发告警,仅生成通知。若服务器再次返回 2xx 或 3xx 响应,将立即被重新加入服务器池。统计信息页面中,该服务器的状态显示为“NOLB”。请注意,此选项仅在与“httpchk”选项配合使用时生效。若与“http-check expect”选项一同使用,则本选项具有更高优先级,即 404 响应仍被视为软停止。此外,已停止的服务器即使返回 404,仍将持续处于停止状态。此选项仅对运行中的服务器进行评估。

另请参见:“option httpchk” 和 “http-check expect”。

http-check expect [min-recv <int>] [comment <msg>]

http-check expect [min-recv <int>] [comment <msg>]
                  [ok-status <st>] [error-status <st>] [tout-status <st>]
                  [on-success <fmt>] [on-error <fmt>] [status-code <expr>]
                  [!] <match> <pattern>

使 HTTP 健康检查考虑响应内容或特定状态码

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

comment <msg>  defines a message to report if the rule evaluation fails.

min-recv  is optional and can define the minimum amount of data required to
          evaluate the current expect rule. If the number of received bytes
          is under this limit, the check will wait for more data. This
          option can be used to resolve some ambiguous matching rules or to
          avoid executing costly regex matches on content known to be still
          incomplete. If an exact string is used, the minimum between the
          string length and this parameter is used. This parameter is
          ignored if it is set to -1. If the expect rule does not match,
          the check will wait for more data. If set to 0, the evaluation
          result is always conclusive.

ok-status <st>     is optional and can be used to set the check status if
                   the expect rule is successfully evaluated and if it is
                   the last rule in the tcp-check ruleset. "L7OK", "L7OKC",
                   "L6OK" and "L4OK" are supported:
                     - L7OK : check passed on layer 7
                     - L7OKC: check conditionally passed on layer 7, set
                               server to NOLB state.
                     - L6OK : check passed on layer 6
                     - L4OK : check passed on layer 4
                   By default "L7OK" is used.

error-status <st>  is optional and can be used to set the check status if
                   an error occurred during the expect rule evaluation.
                   "L7OKC", "L7RSP", "L7STS", "L6RSP" and "L4CON" are
                   supported:
                     - L7OKC: check conditionally passed on layer 7, set
                               server to NOLB state.
                     - L7RSP: layer 7 invalid response - protocol error
                     - L7STS: layer 7 response error, for example HTTP 5xx
                     - L6RSP: layer 6 invalid response - protocol error
                     - L4CON: layer 1-4 connection problem
                   By default "L7RSP" is used.

tout-status <st>   is optional and can be used to set the check status if
                   a timeout occurred during the expect rule evaluation.
                   "L7TOUT", "L6TOUT", and "L4TOUT" are supported:
                     - L7TOUT: layer 7 (HTTP/SMTP) timeout
                     - L6TOUT: layer 6 (SSL) timeout
                     - L4TOUT: layer 1-4 timeout
                   By default "L7TOUT" is used.

on-success <fmt>   is optional and can be used to customize the
                   informational message reported in logs if the expect
                   rule is successfully evaluated and if it is the last rule
                   in the tcp-check ruleset. <fmt> is a Custom log format
                   string (see section 8.2.6).

on-error <fmt>     is optional and can be used to customize the
                   informational message reported in logs if an error
                   occurred during the expect rule evaluation. <fmt> is a
                   Custom log format string (see section 8.2.6).

status-code <expr> is optional and can be used to set the check status code
                   reported in logs, on success or on error. <expr> is a
                   standard HAProxy expression formed by a sample-fetch
                   followed by some converters.

<match>   is a keyword indicating how to look for a specific pattern in the
          response. The keyword may be one of "status", "rstatus", "hdr",
          "fhdr", "string", or "rstring". The keyword may be preceded by an
          exclamation mark ("!") to negate the match. Spaces are allowed
          between the exclamation mark and the keyword. See below for more
          details on the supported keywords.

<pattern> is the pattern to look for. It may be a string, a regular
          expression or a more complex pattern with several arguments. If
          the string pattern contains spaces, they must be escaped with the
          usual backslash ('\').

默认情况下,“option httpchk”认为响应状态码为 2xx 和 3xx 时有效,其余状态码为无效。当使用“http-check expect”时,它将定义何为有效或无效。一个后端中仅支持一条“http-check”语句。若服务器无响应或超时,检查显然会失败。可用的匹配项包括:

status <codes>:  test the status codes found parsing <codes> string. it
                  must be a comma-separated list of status codes or range
                  codes. A health check response will be considered as
                  valid if the response's status code matches any status
                  code or is inside any range of the list. If the "status"
                  keyword is prefixed with "!", then the response will be
                  considered invalid if the status code matches.

rstatus <regex>: test a regular expression for the HTTP status code.
                  A health check response will be considered valid if the
                  response's status code matches the expression. If the
                  "rstatus" keyword is prefixed with "!", then the response
                  will be considered invalid if the status code matches.
                  This is mostly used to check for multiple codes.

hdr  { name | name-lf } [ -m <meth> ] <name>
     [ { value | value-lf } [ -m <meth> ] <value>:
                  test the specified header pattern on the HTTP response
                  headers. The name pattern is mandatory but the value
                  pattern is optional. If not specified, only the header
                  presence is verified. <meth> is the matching method,
                  applied on the header name or the header value. Supported
                  matching methods are "str" (exact match), "beg" (prefix
                  match), "end" (suffix match), "sub" (substring match) or
                  "reg" (regex match). If not specified, exact matching
                  method is used. If the "name-lf" parameter is used,
                  <name> is evaluated as a Custom log format string (see
                  section 8.2.6). If "value-lf" parameter is used, <value>
                  is evaluated as a log-format string. These parameters
                  cannot be used with the regex matching method. Finally,
                  the header value is considered as comma-separated
                  list. Note that matchings are case insensitive on the
                  header names.

fhdr { name | name-lf } [ -m <meth> ] <name>
     [ { value | value-lf } [ -m <meth> ] <value>:
                  test the specified full header pattern on the HTTP
                  response headers. It does exactly the same as the "hdr"
                  keyword, except the full header value is tested, commas
                  are not considered as delimiters.

string <string>: test the exact string match in the HTTP response body.
                  A health check response will be considered valid if the
                  response's body contains this exact string. If the
                  "string" keyword is prefixed with "!", then the response
                  will be considered invalid if the body contains this
                  string. This can be used to look for a mandatory word at
                  the end of a dynamic page, or to detect a failure when a
                  specific error appears on the check page (e.g. a stack
                  trace).

rstring <regex>: test a regular expression on the HTTP response body.
                  A health check response will be considered valid if the
                  response's body matches this expression. If the "rstring"
                  keyword is prefixed with "!", then the response will be
                  considered invalid if the body matches the expression.
                  This can be used to look for a mandatory word at the end
                  of a dynamic page, or to detect a failure when a specific
                  error appears on the check page (e.g. a stack trace).

string-lf <fmt>: test a Custom log format string (see section 8.2.6) match
                  in the HTTP response body. A health check response will
                  be considered valid if the response's body contains the
                  string resulting of the evaluation of <fmt>, which
                  follows the log-format rules. If prefixed with "!", then
                  the response will be considered invalid if the body
                  contains the string.

请注意,响应大小将受到全局 “tune.bufsize” 选项的限制,该选项默认值为 16384 字节。因此,使用 “string” 或 “rstring” 时,过大的响应可能不包含必需的模式。若确实需要处理大响应,可通过设置全局变量更改默认最大大小。但需注意,解析非常大的响应可能会浪费部分 CPU 周期,尤其是在使用正则表达式时,且始终建议将检查聚焦于较小的资源。

在 http-check 规则集中,最后一个 expect 规则可以是隐式的。如果在最后一个 “http-check send” 之后未指定 expect 规则,则会定义一个隐式的 expect 规则,用于匹配 2xx 或 3xx 状态码。这意味着,即使完全未设置 “http-check” 规则,仅设置了 “option httpchk” 时,该规则同样会被定义。

最后,如果将“http-check expect”与“http-check disable-on-404”结合使用,则当服务器响应 404 时,后者具有优先权。

示例:

# only accept status 200 as valid
http-check expect status 200,201,300-310

# be sure a sessid coookie is set
http-check expect hdr name "set-cookie" value -m beg "sessid="

# consider SQL errors as errors
http-check expect ! string SQL\ Error

# consider status 5xx only as errors
http-check expect ! rstatus ^5

# check that we have a correct hexadecimal tag before /html
http-check expect rstring <!--tag:[0-9a-f]*--></html>

另请参阅:“option httpchk”、“http-check connect”、“http-check disable-on-404”和“http-check send”。

http-check send [meth <method>] [{ uri <uri> | uri-lf <fmt> }>] [ver <version>]

http-check send [meth <method>] [{ uri <uri> | uri-lf <fmt> }>] [ver <version>]
                [hdr <name> <fmt>]* [{ body <string> | body-lf <fmt> }]
                [comment <msg>]

在 HTTP 健康检查发送的请求中添加可能的头字段列表和/或请求体。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

comment <msg>  defines a message to report if the rule evaluation fails.

meth <method>  is the optional HTTP method used with the requests. When not
               set, the "OPTIONS" method is used, as it generally requires
               low server processing and is easy to filter out from the
               logs. Any method may be used, though it is not recommended
               to invent non-standard ones.

uri <uri>      is optional and set the URI referenced in the HTTP requests
               to the string <uri>. It defaults to "/" which is accessible
               by default on almost any server, but may be changed to any
               other URI. Query strings are permitted.

uri-lf <fmt>   is optional and set the URI referenced in the HTTP requests
               using the Custom log format <fmt> (see section 8.2.6). It
               defaults to "/" which is accessible by default on almost any
               server, but may be changed to any other URI. Query strings
               are permitted.

ver <version>  is the optional HTTP version string. It defaults to
               "HTTP/1.0" but some servers might behave incorrectly in HTTP
               1.0, so turning it to HTTP/1.1 may sometimes help. Note that
               the Host field is mandatory in HTTP/1.1, use "hdr" argument
               to add it.

hdr <name> <fmt>  adds the HTTP header field whose name is specified in
                  <name> and whose value is defined by <fmt>, which follows
                  the Custom log format rules described in section 8.2.6.

body <string>  add the body defined by <string> to the request sent during
               HTTP health checks. If defined, the "Content-Length" header
               is thus automatically added to the request.

body-lf <fmt>  add the body defined by the Custom log format <fmt> (see
               section 8.2.6) to the request sent during HTTP health
               checks. If defined, the "Content-Length" header is thus
               automatically added to the request.

除了由 “option httpchk” 指令定义的请求行外,以下方式是向 HTTP 健康检查请求中添加头字段并可选地添加请求体的正确方法。若定义了请求体,则会自动添加相应的 “Content-Length” 头字段。因此,在 “http-check send” 提供的请求中,不应包含该头字段或 “Transfer-encoding” 头字段,否则将被忽略。在 “option httpchk” 行中版本字符串后添加头字段的旧方法现已弃用。

此外,“http-check send” 不支持 HTTP 持久连接。请注意,除非通过 hdr 条目已配置 Connection 头,否则它会自动附加一个 “Connection: close” 头。

请注意,当 Host 头和请求授权信息均被定义时,二者会自动同步。这意味着在发送 HTTP 请求时,若在请求中插入 Host 头,则请求授权信息会相应更新。因此,若发现 Host 头值覆盖了配置的请求授权信息,无需感到意外。

请注意,目前在 HTTP/1.1 及以上版本的请求中,不会自动添加 Host 头。应显式添加。

另请参见:“option httpchk”、“http-check send-state”和“http-check expect”。

http-check send-state

http-check send-state

启用 HTTP 健康检查时发送状态头

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:无

当启用此选项时,HAProxy 会始终向每个服务器发送一个特殊头字段 “X-Haproxy-Server-State”,其中包含一组参数,用于指示 HAProxy 对各服务器的当前状态判断。例如,当服务器在未访问 HAProxy 的情况下被操作时,管理员可借此确认 HAProxy 是否仍认为该服务器处于运行状态,或该服务器是否为某服务器组中的最后一个成员。

头由分号分隔的字段组成,第一个字段为一个单词(“UP”、“DOWN”、“NOLB”),后接在状态转换前有效的检查次数,格式与统计信息界面中显示的一致。后续字段格式为 “<variable>=<value>",以任意顺序表示统计信息界面中可用的某些值:- 变量 “address”,包含后端服务器的地址。该值对应服务器声明中的 <address> 字段。对于 Unix 域套接字,其值为 “unix”。

- a variable "port", containing the port of the backend server. This
  corresponds to the `<port>` field in the server declaration. For unix
  domain sockets, it will read "unix".

- a variable "name", containing the name of the backend followed by a slash
  ("/") then the name of the server. This can be used when a server is
  checked in multiple backends.

- a variable "node" containing the name of the HAProxy node, as set in the
  global "node" variable, otherwise the system's hostname if unspecified.

- a variable "weight" indicating the weight of the server, a slash ("/")
  and the total weight of the farm (just counting usable servers). This
  helps to know if other servers are available to handle the load when this
  one fails.

- a variable "scur" indicating the current number of concurrent connections
  on the server, followed by a slash ("/") then the total number of
  connections on all servers of the same backend.

- a variable "qcur" indicating the current number of requests in the
  server's queue.

应用服务器接收到的头示例:

>>>  X-Haproxy-Server-State: UP 2/3; name=bck/srv2; node=lb1; weight=1/2; \
       scur=13/22; qcur=0

另请参阅:“option httpchk”、“http-check disable-on-404” 和 “http-check send”。

http-check set-var(<var-name>[,<cond>...]) <expr>

http-check set-var(<var-name>[,<cond>...]) <expr>
http-check set-var-fmt(<var-name>[,<cond>...]) <fmt>

此操作用于设置变量的内容。变量在行内声明。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<var-name>   The name of the variable. Only "proc", "sess" and "check"
             scopes can be used. See section 2.8 about variables for details.

 <cond>      A set of conditions that must all be true for the variable to
             actually be set (such as "ifnotempty", "ifgt" ...). See the
             set-var converter's description for a full list of possible
             conditions.

 <expr>      Is a sample-fetch expression potentially followed by converters.

 <fmt>       This is the value expressed using Custom log format (see Custom
             Log Format in section 8.2.6).

示例:

http-check set-var(check.port) int(1234)
http-check set-var-fmt(check.port) "name=%H"

http-check unset-var(<var-name>)

http-check unset-var(<var-name>)

释放变量在其作用域内的引用。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<var-name>   The name of the variable. Only "proc", "sess" and "check"
             scopes can be used. See section 2.8 about variables for details.

示例:

http-check unset-var(check.port)

http-error status <code> [content-type <type>]

http-error status <code> [content-type <type>]
           [ { default-errorfiles | errorfile <file> | errorfiles <name> |
           file `<file>` | lf-file `<file>` | string `<str>` | lf-string `<fmt>` } ]
       [ hdr `<name>` `<fmt>` ]*

定义自定义错误消息,用于替代 HAProxy 生成的错误信息。

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:

status <code>        is the HTTP status code. It must be specified.
                     Currently, HAProxy is capable of generating codes
                     200, 400, 401, 403, 404, 405, 407, 408, 410, 413,
                     414, 425, 429, 431, 500, 501, 502, 503, and 504.

content-type <type>  is the response content type, for instance
                     "text/plain". This parameter is ignored and should be
                     omitted when an errorfile is configured or when the
                     payload is empty. Otherwise, it must be defined.

default-errorfiles   Reset the previously defined error message for current
                     proxy for the status <code>. If used on a backend, the
                     frontend error message is used, if defined. If used on
                     a frontend, the default error message is used.

errorfile <file>     designates a file containing the full HTTP response.
                     It is recommended to follow the common practice of
                     appending ".http" to the filename so that people do
                     not confuse the response with HTML error pages, and to
                     use absolute paths, since files are read before any
                     chroot is performed.

errorfiles <name>    designates the http-errors section to use to import
                     the error message with the status code <code>. If no
                     such message is found, the proxy's error messages are
                     considered.

file <file>          specifies the file to use as response payload. If the
                     file is not empty, its content-type must be set as
                     argument to "content-type", otherwise, any
                     "content-type" argument is ignored. <file> is
                     considered as a raw string.

string <str>         specifies the raw string to use as response payload.
                     The content-type must always be set as argument to
                     "content-type".

lf-file <file>       specifies the file to use as response payload. If the
                     file is not empty, its content-type must be set as
                     argument to "content-type", otherwise, any
                     "content-type" argument is ignored. <file> is
                     evaluated as a Custom log format (see section 8.2.6).

lf-string <str>      specifies the log-format string to use as response
                     payload. The content-type must always be set as
                     argument to "content-type".

hdr <name> <fmt>     adds to the response the HTTP header field whose name
                     is specified in <name> and whose value is defined by
                     <fmt>, which follows the Custom log format rules (see
                     section 8.2.6). This parameter is ignored if an
                     errorfile is used.

此指令可用于替代 “errorfile”,以定义自定义错误消息。与 “errorfile” 指令相同,它用于处理 HAProxy 检测并返回的错误。若定义了 errorfile,则 HAProxy 启动时会对其进行解析,且必须符合 HTTP 标准。生成的响应不得超过配置的缓冲区大小(BUFFSIZE),否则将返回内部错误。最后,若考虑使用某些 http-after-response 规则来重写这些错误,应确保预留的缓冲区空间可用(参见 “tune.maxrewrite”)。

配置文件与之同时读取并保留在内存中。因此,即使进程已执行 chroot,错误仍会持续返回,且在进程运行期间不会考虑任何文件变更。

请注意:在请求解析早期阶段产生的 400/408/500 错误由多路复用器在较低层级处理。此层级不支持自定义格式化。因此,仅支持使用 “errorfile” 指令定义的静态错误消息。然而,此限制仅存在于请求头解析期间或两次事务之间。

参见:“errorfile”、“errorfiles”、“errorloc”、“errorloc302”、“errorloc303”以及 第 12.4 节 关于 http-errors 的内容。

http-request <action> [options...] [ { if | unless } <condition> ]

http-request <action> [options...] [ { if | unless } <condition> ]

第 7 层请求的访问控制

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes(!) | yes | yes | yes

第 7 层处理中,http-request 语句用于定义一组规则。这些规则在前端、监听或后端段中按声明顺序进行评估。每条规则可选择性地跟随一个基于 ACL 的条件,此时仅当该条件求值为真时,规则才会被评估。

条件在动作执行前进行评估,且该动作仅执行一次。因此,即使某个动作改变了作为条件一部分的元素,也不会造成问题。这也意味着多个动作可以依赖同一条件,只要首个改变条件评估结果的动作执行后,其余动作便会自动隐式禁用。例如,当变量为空时,从多个来源为其赋值,即采用此机制。每个实例中“http-request”语句的数量无限制。

在 “http-request” 语法中,首个关键字为规则的动作,可选地后接该动作所需的若干参数。支持的动作及其对应语法详见 第 4.3 节 “动作”(请查找标记为“HTTP Req”的动作)。

该指令仅在命名的 defaults 段中可用,不可用于匿名段。在关联的代理段之前,将先评估 defaults 段中定义的规则。为避免歧义,在此情况下,同一 defaults 段不可同时被具备前端能力的代理和具备后端能力的代理使用。这意味着,listen 段不可使用定义了此类规则的 defaults 段。

示例:

acl nagios src 192.168.129.3
acl local_net src 192.168.0.0/16
acl auth_ok http_auth(L1)

http-request allow if nagios
http-request allow if local_net auth_ok
http-request auth realm Gimme if local_net auth_ok
http-request deny

示例:

acl key req.hdr(X-Add-Acl-Key) -m found
acl add path /addacl
acl del path /delacl

acl myhost hdr(Host) -f myhost.lst

http-request add-acl(myhost.lst) %[req.hdr(X-Add-Acl-Key)] if key add
http-request del-acl(myhost.lst) %[req.hdr(X-Add-Acl-Key)] if key del

示例:

acl value  req.hdr(X-Value) -m found
acl setmap path /setmap
acl delmap path /delmap

use_backend bk_appli if { hdr(Host),map_str(map.lst) -m found }

http-request set-map(map.lst) %[src] %[req.hdr(X-Value)] if setmap value
http-request del-map(map.lst) %[src]                     if delmap

另请参阅:“stats http-request”,第 12.2 节 关于 userlists 的说明,以及 第 7 节 关于 ACL 使用的说明。

http-response <action> <options...> [ { if | unless } <condition> ]

http-response <action> <options...> [ { if | unless } <condition> ]

第 7 层响应的访问控制

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes(!) | yes | yes | yes

第 7 层处理中,http-response 语句定义了一组规则。这些规则在前端、监听或后端段中按声明顺序进行评估。由于这些规则作用于响应,因此先应用后端规则,再应用前端规则。任何规则均可选择性地跟随一个基于 ACL 的条件,此时仅当该条件求值为真时才进行评估。

条件在动作执行前进行评估,且该动作仅执行一次。因此,即使某个动作改变了作为条件一部分的元素,也不会造成问题。这也意味着多个动作可以依赖同一条件,只要首个改变条件评估结果的动作执行后,其余动作便会自动隐式禁用。例如,当变量为空时,从多个来源为其赋值,即采用此机制。每个实例中“http-response”语句的数量无限制。

在语法中,“http-response”之后的第一个关键字是规则的动作,可选地后接该动作所需的若干参数。支持的动作及其各自语法详见 第 4.3 节 “动作”(请查找标记为“HTTP 响应”的动作)。

该指令仅在命名的 defaults 段中可用,不可用于匿名段。在关联的代理段之前,将先评估 defaults 段中定义的规则。为避免歧义,在此情况下,同一 defaults 段不可同时被具备前端能力的代理和具备后端能力的代理使用。这意味着,listen 段不可使用定义了此类规则的 defaults 段。

示例:

acl key_acl res.hdr(X-Acl-Key) -m found

acl myhost hdr(Host) -f myhost.lst

http-response add-acl(myhost.lst) %[res.hdr(X-Acl-Key)] if key_acl
http-response del-acl(myhost.lst) %[res.hdr(X-Acl-Key)] if key_acl

示例:

acl value  res.hdr(X-Value) -m found

use_backend bk_appli if { hdr(Host),map_str(map.lst) -m found }

http-response set-map(map.lst) %[src] %[res.hdr(X-Value)] if value
http-response del-map(map.lst) %[src]                     if ! value

另请参阅:“http-request”,第 12.2 节 关于 userlists 的说明以及 第 7 节 关于 ACL 使用的说明。

http-reuse { never | safe | aggressive | always }

http-reuse { never | safe | aggressive | always }

声明空闲 HTTP 连接在请求之间如何共享

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

为避免为每个 HTTP 请求建立与后端服务器的新连接所带来的开销,HAProxy 会在使用后尽量保持这些空闲连接处于打开状态。这些连接与特定服务器相关,并存储在一个称为连接池的列表中,且根据一组共同的关键属性进行分组。后续的 HTTP 请求将触发对关联连接池中具有相同属性的兼容连接的查找,从而复用该连接,而非建立新的连接。

可通过服务器关键字 “pool-max-conn” 指定服务器上保持的空闲连接数量上限。未使用的连接将根据 “pool-purge-delay” 间隔周期性地清除。

以下连接属性用于确定空闲连接在特定请求上是否可重用:

  • 源地址和目标地址
  • PROXY 协议
  • TOS 和 mark 套接字选项
  • 连接名称,由 “pool-conn-name” 表达式求值结果确定,若该表达式不存在,则由 “sni” 表达式确定,其默认值为 “req.hdr(host),field(1,:)",即使用入站请求的 “Host” 头字段,不包含冒号和端口号。

在某些情况下,由于额外的限制,不会执行连接查找或复用。这由通过关键字参数指定的复用策略决定:

- "never" : idle connections are never shared between sessions. This mode
             may be enforced to cancel a different strategy inherited from
             a defaults section or for troubleshooting. For example, if an
             old bogus application considers that multiple requests over
             the same connection come from the same client and it is not
             possible to fix the application, it may be desirable to
             disable connection sharing in a single backend. An example of
             such an application could be an old HAProxy using cookie
             insertion in tunnel mode and not checking any request past the
             first one.

- "safe"  : this is the default and the recommended strategy. The first
             request of a session is always sent over its own connection,
             and only subsequent requests may be dispatched over other
             existing connections. This ensures that in case the server
             closes the connection when the request is being sent, the
             browser can decide to silently retry it. Since it is exactly
             equivalent to regular keep-alive, there should be no side
             effects. There is also a special handling for the connections
             using protocols subject to Head-of-line blocking (backend with
             h2 or fcgi). In this case, when at least one stream is
             processed, the used connection is reserved to handle streams
             of the same session. When no more streams are processed, the
             connection is released and can be reused.

- "aggressive": this mode may be useful in webservices environments where
             all servers are not necessarily known and where it would be
             appreciable to deliver most first requests over existing
             connections. In this case, first requests are only delivered
             over existing connections that have been reused at least once,
             proving that the server correctly supports connection reuse.
             It should only be used when it's sure that the client can
             retry a failed request once in a while and where the benefit
             of aggressive connection reuse significantly outweighs the
             downsides of rare connection failures.

- "always": this mode is only recommended when the path to the server is
             known for never breaking existing connections quickly after
             releasing them. It allows the first request of a session to be
             sent to an existing connection. This can provide a significant
             performance increase over the "safe" strategy when the backend
             is a cache farm, since such components tend to show a
             consistent behavior and will benefit from the connection
             sharing. It is recommended that the "http-keep-alive" timeout
             remains low in this mode so that no dead connections remain
             usable. In most cases, this will lead to the same performance
             gains as "aggressive" but with more risks. It should only be
             used when it improves the situation over "aggressive".

请注意,使用某些依赖连接的伪造认证机制(如 NTLM)的连接,若可能将被标记为私有,且永不共享。然而,当使用具备多路复用能力的协议,并启用大于默认“安全”策略的重用模式级别时,情况将不同,此时无法阻止连接已被共享。

决定在处理完成后是否保持空闲连接打开或关闭的规则,同样由 “tune.pool-low-fd-ratio”(默认值:20%)和 “tune.pool-high-fd-ratio”(默认值:25%)控制。这两个参数分别对应于空闲连接所占用的总文件描述符比例阈值,当超过该阈值时,HAProxy 将分别停止在响应后保持连接打开,或主动终止空闲连接。某些配置中空闲连接比例极高,可能是由于全局 “maxconn” 值过低,或前端存在大量 HTTP/2 或 HTTP/3 流量(连接数少),而后端使用 HTTP/1 连接,可能导致连接复用率下降,因为保持打开的连接过少。在此情况下,调整这些阈值或简单地提高全局 “maxconn” 值可能是有益的。

在某些罕见情况下,当主机名用于区分出站 TLS 连接(例如正向代理)且大多数请求的目标主机不同时,连接复用率会非常低。此时,在连接有机会被复用之前,系统可能已触发对使用频率较低连接的自动淘汰机制。这是因为该机制会持续测量维持服务所需的平均连接数,以避免资源耗尽。在此类场景中,将“pool-low-conn”设置为接近预期空闲连接平均数的值,有助于通过鼓励线程建立自己的连接,而非尝试选取其他线程的连接,从而减少可用连接池的收缩,保留更多连接。

如果本地托管的服务器使用单个证书(包含多个主机名或通配符)并运行多个站点,建议在“server”行上使用“no-sni-auto”而非保留对单一主机名的连接,以提升连接复用率。部分服务器可能在主机名与 SNI 之间执行过多检查,导致拒绝后续请求,因此该选项需预先验证。默认行为(“sni-auto”)旨在确保与此类服务器的兼容性,更为安全。

当显式启用线程组时,需注意空闲连接仅可在同一组内的线程之间复用。因此,组间负载不均可能导致需要更多空闲连接,从而降低复用率。可采用相同解决方案(增加全局 “maxconn” 值或提高池比例)。

参见: “option http-keep-alive”、“pool-conn-name”、“pool-max-conn”、“pool-purge-delay”、“server maxconn”、“sni”、“thread-groups”、“tune.pool-high-fd-ratio”、“tune.pool-low-fd-ratio”

http-send-name-header [<header>]

http-send-name-header [<header>]

将服务器名称添加到请求中。使用由 <header> 提供的头字符串

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<header>  The header string to use to send the server name

“http-send-name-header” 语句会导致名为 <header> 的头字段在请求即将通过网络发送时被设置为目标服务器的名称。该头字段中任何已存在的实例均会被移除。在重试和重分派过程中,该头字段会更新,始终反映当前尝试连接的服务器。由于该头字段在连接建立过程的后期才被修改,可能对已修改的其他头字段产生意外影响。例如,与传输层头(如 connection、content-length、transfer-encoding 等)一起使用时,很可能导致向服务器发送无效请求。因此,以下头字段被禁止使用:host、content-length、transfer-encoding 和 connection。

另请参见:服务器

id <value>

id <value>

为代理设置持久化 ID。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend 否 | 是 | 是 | 是

参数:无

为代理设置一个持久化 ID。该 ID 必须唯一且为正数。若未设置,将自动分配一个未使用的 ID。由于历史行为,除非显式设置,否则值 1 不会被使用。因此,自动分配的最小值为 2。该 ID 当前仅在统计信息中返回。

ignore-persist { if | unless } <condition>

ignore-persist { if | unless } <condition>

声明一个条件以忽略持久性

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend

默认情况下,启用 cookie 持久性后,所有包含该 cookie 的请求将无条件保持持久性(前提是目标服务器处于运行状态)。

本节中的 “ignore-persist” 语句允许声明多种基于 ACL 的条件,当这些条件满足时,将导致请求忽略持久性。这在对静态文件请求进行负载均衡时有时很有用,因为这类请求通常不需要持久性。该功能也可用于针对特定 User-Agent 完全禁用持久性(例如,某些网络爬虫机器人)。

当满足 “if” 条件时,持久性将被忽略,或除非满足 “unless” 条件。

示例:

acl url_static  path_beg         /static /images /img /css
acl url_static  path_end         .gif .png .jpg .css .js
ignore-persist  if url_static

另请参阅:“force-persist”、“cookie”以及 第 7 节 中关于 ACL 使用的说明。

load-server-state-from-file { global | local | none }

load-server-state-from-file { global | local | none }

允许 HAProxy 无缝重载

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

本指令用于指定 HAProxy 从何处加载前一次运行进程保存的服务器状态文件。这样,在启动过程中、处理流量之前,新进程可以将旧状态精确地应用到服务器上,如同未发生重载一般。load-server-state-from-file 指令的作用是告知 HAProxy 使用哪个文件。目前,该指令仅支持两个参数:一个用于禁止加载状态,另一个用于从包含所有后端和服务器状态的文件中加载状态。状态文件可通过在统计信息套接字上执行命令 show servers state 并重定向输出生成。

文件格式已版本化,且非常具体。如需理解,请阅读“show servers state”命令的文档(管理指南第 9.3 章)。

参数:

global     load the content of the file pointed by the global directive
           named "server-state-file".

local      load the content of the file pointed by the directive
           "server-state-file-name" if set. If not set, then the backend
           name is used as a file name.

none       don't load any stat for this backend

注意:默认情况下,服务器的 IP 地址在重载过程中得以保留,但可通过服务器的 “init-addr” 设置更改其顺序。这意味着通过 CLI 在运行时执行的 IP 地址变更将被保留,且若启用了状态文件,对本地解析器(例如 /etc/hosts)的任何更改可能不会产生效果。

- server's weight is applied from previous running process unless it has
  has changed between previous and new configuration files.

示例:最小配置

  global
   stats socket /tmp/socket
   server-state-file /tmp/server_state

  defaults
   load-server-state-from-file global

  backend bk
   server s1 127.0.0.1:22 check weight 11
   server s2 127.0.0.1:22 check weight 12

然后可以运行:

socat /tmp/socket - <<< "show servers state" > /tmp/server_state

/tmp/server_state 文件的内容应如下所示:

1
# <field names skipped for the doc example>
1 bk 1 s1 127.0.0.1 2 0 11 11 4 6 3 4 6 0 0
1 bk 2 s2 127.0.0.1 2 0 12 12 4 6 3 4 6 0 0

示例:最小配置

global
 stats socket /tmp/socket
 server-state-base /etc/haproxy/states

defaults
 load-server-state-from-file local

backend bk
 server s1 127.0.0.1:22 check weight 11
 server s2 127.0.0.1:22 check weight 12

然后可以运行:

socat /tmp/socket - <<< "show servers state bk" > /etc/haproxy/states/bk

/etc/haproxy/states/bk 文件内容如下:

1
# <field names skipped for the doc example>
1 bk 1 s1 127.0.0.1 2 0 11 11 4 6 3 4 6 0 0
1 bk 2 s2 127.0.0.1 2 0 12 12 4 6 3 4 6 0 0

另请参见:“server-state-file”、“server-state-file-name”和“show servers state”

log global

log global
log <target> [len <length>] [format <format>] [sample <ranges>:<sample_size>]
    [profile <prof>] <facility> [<level> [<minlevel>]]
no log

启用每个实例的事件和流量日志记录。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

前缀:

no         should be used when the logger list must be flushed. For example,
           if you don't want to inherit from the default logger list. This
           prefix does not allow arguments.

参数:

global     should be used when the instance's logging parameters are the
           same as the global ones. This is the most common usage. "global"
           replaces all log arguments with those of the log entries found
           in the "global" section. Only one "log global" statement may be
           used per instance, and this form takes no other parameter.

<target>   indicates where to send the logs. It takes the same format as
           for the "global" section's logs, and can be one of:

           - An IPv4 address optionally followed by a colon (':') and a UDP
             port. If no port is specified, 514 is used by default (the
             standard syslog port).

           - An IPv6 address followed by a colon (':') and optionally a UDP
             port. If no port is specified, 514 is used by default (the
             standard syslog port).

           - A filesystem path to a UNIX domain socket, keeping in mind
             considerations for chroot (be sure the path is accessible
             inside the chroot) and uid/gid (be sure the path is
             appropriately writable).

           - A file descriptor number in the form "fd@<number>", which may
             point to a pipe, terminal, or socket. In this case unbuffered
             logs are used and one writev() call per log is performed. This
             is a bit expensive but acceptable for most workloads. Messages
             sent this way will not be truncated but may be dropped, in
             which case the DroppedLogs counter will be incremented. The
             writev() call is atomic even on pipes for messages up to
             PIPE_BUF size, which POSIX recommends to be at least 512 and
             which is 4096 bytes on most modern operating systems. Any
             larger message may be interleaved with messages from other
             processes.  Exceptionally for debugging purposes the file
             descriptor may also be directed to a file, but doing so will
             significantly slow HAProxy down as non-blocking calls will be
             ignored. Also there will be no way to purge nor rotate this
             file without restarting the process. Note that the configured
             syslog format is preserved, so the output is suitable for use
             with a TCP syslog server. See also the "short" and "raw"
             formats below.

           - "stdout" / "stderr", which are respectively aliases for "fd@1"
             and "fd@2", see above.

           - A ring buffer in the form "ring@<name>", which will correspond
             to an in-memory ring buffer accessible over the CLI using the
             "show events" command, which will also list existing rings and
             their sizes. Such buffers are lost on reload or restart but
             when used as a complement this can help troubleshooting by
             having the logs instantly available. See section 12.5 about
             rings.

           - A log backend in the form "backend@<name>", which will send
             log messages to the corresponding log backend responsible for
             sending the message to the proper server according to the
             backend's lb settings. A log backend is a backend section with
             "mode log" set (see "mode" for more information).

           - An explicit stream address prefix such as "tcp@","tcp6@",
             "tcp4@" or "uxst@" will allocate an implicit ring buffer with
             a stream forward server targeting the given address.

           You may want to reference some environment variables in the
           address parameter, see section 2.3 about environment variables.

<length>   is an optional maximum line length. Log lines larger than this
           value will be truncated before being sent. The reason is that
           syslog servers act differently on log line length. All servers
           support the default value of 1024, but some servers simply drop
           larger lines while others do log them. If a server supports long
           lines, it may make sense to set this value here in order to avoid
           truncating long lines. Similarly, if a server drops long lines,
           it is preferable to truncate them before sending them. Accepted
           values are 80 to 65535 inclusive. The default value of 1024 is
           generally fine for all standard usages. Some specific cases of
           long captures or JSON-formatted logs may require larger values.
           You may also need to increase "tune.http.logurilen" if your
           request URIs are truncated.

<ranges>   A list of comma-separated ranges to identify the logs to sample.
           This is used to balance the load of the logs to send to the log
           server. The limits of the ranges cannot be null. They are numbered
           from 1. The size or period (in number of logs) of the sample must
           be set with <sample_size> parameter.

<sample_size>
           The size of the sample in number of logs to consider when balancing
           their logging loads. It is used to balance the load of the logs to
           send to the syslog server. This size must be greater or equal to the
           maximum of the high limits of the ranges.
           (see also <ranges> parameter).

<format> is the log format used when generating syslog messages. It may be
         one of the following:

  local     Analog to rfc3164 syslog message format except that hostname
            field is stripped. This is the default.
            Note: option "log-send-hostname" switches the default to
            rfc3164.

  rfc3164   The RFC3164 syslog message format.
            (https://tools.ietf.org/html/rfc3164)

  rfc5424   The RFC5424 syslog message format.
            (https://tools.ietf.org/html/rfc5424)

  priority  A message containing only a level plus syslog facility between
            angle brackets such as '<63>', followed by the text. The PID,
            date, time, process name and system name are omitted. This is
            designed to be used with a local log server.

  short     A message containing only a level between angle brackets such as
            '<3>', followed by the text. The PID, date, time, process name
            and system name are omitted. This is designed to be used with a
            local log server. This format is compatible with what the
            systemd logger consumes.

  timed     A message containing only a level between angle brackets such as
            '<3>', followed by ISO date and by the text. The PID, process
            name and system name are omitted. This is designed to be
            used with a local log server.

  iso       A message containing only the ISO date, followed by the text.
            The PID, process name and system name are omitted. This is
            designed to be used with a local log server.

  raw       A message containing only the text. The level, PID, date, time,
            process name and system name are omitted. This is designed to
            be used in containers or during development, where the severity
            only depends on the file descriptor used (stdout/stderr).

<prof>     name of the optional "log-profile" section that will be
           considered during the log building process to override some
           log options. Check out "8.3.5. Log profiles" for more info.

<facility> must be one of the 24 standard syslog facilities:

               kern   user   mail   daemon auth   syslog lpr    news
               uucp   cron   auth2  ftp    ntp    audit  alert  cron2
               local0 local1 local2 local3 local4 local5 local6 local7

           Note that the facility is ignored for the "short" and "raw"
           formats, but still required as a positional field. It is
           recommended to use "daemon" in this case to make it clear that
           it's only supposed to be used locally.

<level>    is optional and can be specified to filter outgoing messages. By
           default, all messages are sent. If a level is specified, only
           messages with a severity at least as important as this level
           will be sent. An optional minimum level can be specified. If it
           is set, logs emitted with a more severe level than this one will
           be capped to this level. This is used to avoid sending "emerg"
           messages on all terminals on some default syslog configurations.
           Eight levels are known:

             emerg  alert  crit   err    warning notice info  debug

请注意,决定从连接中记录哪些内容的是前端,若发生内容切换,则后端生成的日志条目将被忽略。连接日志记录级别为 “info”。

然而,后端日志声明定义了服务器状态变更的记录方式和位置。状态变为“上线”时使用级别“notice”记录,收到终止信号或服务永久终止时使用级别“warning”记录,服务器宕机时使用级别“alert”记录。

请注意:根据 RFC3164,消息在发出前会被截断至 1024 字节。

示例:

log global
log stdout format short daemon          # send log to systemd
log stdout format raw daemon            # send everything to stdout
log stderr format raw daemon notice     # send important events to stderr
log 127.0.0.1:514 local0 notice         # only send important events
log tcp@127.0.0.1:514 local0 notice notice  # same but limit output
                                            # level and send in tcp
log "${LOCAL_SYSLOG}:514" local0 notice   # send to local server

log-format <fmt>

log-format <fmt>

指定用于流量日志的自定义日志格式字符串

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

该指令指定将用于通过此行配置的前端处理流量所产生的所有日志的日志格式字符串。若该指令在 defaults 段中使用,则后续所有前端将采用相同的日志格式。请参见 section 8.2.6 ,其中详细介绍了自定义日志格式字符串。

也可定义仅在连接错误情况下使用的特定日志格式,详见 “error-log-format” 选项。

“log-format” 指令会覆盖之前的 “option tcplog”、“log-format”、“option httplog” 和 “option httpslog” 指令。

log-format-sd <fmt>

log-format-sd <fmt>

指定用于生成 RFC5424 结构化数据的自定义日志格式字符串

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

该指令指定 RFC5424 结构化数据日志格式字符串,该字符串将用于通过此行配置的前端处理流量所产生的所有日志。若该指令在 defaults 段中使用,则后续所有前端均将采用相同的日志格式。请参见 第 8.2.6 节 ,其中深入介绍了日志格式字符串。

有关 RFC5424 结构化数据部分的更多信息,请参见 https://tools.ietf.org/html/rfc5424#section-6.3 。

请注意:此日志格式字符串仅适用于将日志格式设置为 “rfc5424” 的记录器。

示例:

log-format-sd [exampleSDID@1234\ bytes=\"%B\"\ status=\"%ST\"]

log-steps <steps>

log-steps <steps>

指定在事务处理过程中应在哪些步骤生成日志。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

在处理 TCP/HTTP 事务时,HAProxy 可能在处理过程的不同阶段生成日志(例如:接受连接、建立连接、接收请求、发送响应、关闭连接)。

默认情况下,HAProxy 每个事务仅生成一条日志,且仅在日志格式表达式中使用的所有项均满足后才发出日志,这意味着在实际应用中,日志通常在事务结束时发出(HTTP 为响应结束后,TCP 为连接结束后),除非使用了 “option logasap”。

指令 “log-steps” 允许精确控制日志的输出时机,甚至支持为同一事务输出多条日志。特殊值 “all” 可用于启用所有可用的日志来源,从而实现从连接接收至连接关闭的完整事务追踪。也可通过用逗号分隔的名称指定个别日志来源,以选择性地启用日志输出。

常见的日志来源包括:accept、connect、request、response、close。

示例:

frontend myfront
    option httplog
    log-steps accept,close         #only log accept and close for the txn

可直接在日志配置文件中使用以“logging steps”(如 accept、close)指定的日志来源(在 ‘on’ 指令之后)。将“log-steps”与日志配置文件结合使用,能够对 HAProxy 在事务处理过程中自动生成的日志实现细粒度控制,具有很高的实用价值。

此设置仅对前端有效,后端将忽略该设置。

另请参阅:“log-profile”

log-tag <string>

log-tag <string>

指定用于所有出站日志的日志标签

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

设置 syslog 头中的标签字段为该字符串。默认值为全局段中设置的 log-tag,否则为从命令行启动时的程序名称,通常为 “HAProxy”。在同一个主机上运行多个进程时,或在同一个进程中运行多个客户实例时,有时需要加以区分。在后端中,关于服务器启停的日志将使用此标签。作为提示,可以在 defaults 段中设置与托管客户相关的 log-tag,然后将该客户的全部前端和后端配置放在此段中,再在新的 defaults 段中开始配置另一个客户。参见全局段中的 “log-tag” 指令。

max-keep-alive-queue <value>

max-keep-alive-queue <value>

设置用于维持持久连接的服务器队列最大大小

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

HTTP 持久连接会尽可能复用相同的服务器连接,但在某些情况下可能适得其反,例如当某些服务器连接数较多而其他服务器处于空闲状态时。这一点在静态服务器上尤为明显。

本设置的目的是设定一个队列中连接数量的阈值,当超过该阈值时,HAProxy 停止尝试复用同一台服务器,转而优先选择其他服务器。默认值 -1 表示无限制。值为 0 表示持久连接永远不会被排队。对于延迟较低、且对中断持久连接不敏感的近距离服务器,建议使用较低的值(例如,本地静态服务器可使用 10 或更小的值)。对于延迟较高的远程服务器,可能需要更高的值以弥补延迟和/或选择其他服务器的开销。

请注意,此设置对连续发送至同一服务器的响应无影响,即使这些响应需被排队。在收到 401 响应后,它们仍会发送至同一服务器。

另请参见:“option http-server-close”、“option prefer-last-server”、服务器“maxconn”和 cookie 持久性。

max-session-srv-conns <nb>

max-session-srv-conns <nb>

设置单个客户端会话可保持空闲的最大出站连接数。默认值为 5(精确等于在编译时定义的 MAX_SRV_LIST)。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

maxconn <conns>

maxconn <conns>

修复前端的最大并发连接数

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:

<conns>   is the maximum number of concurrent connections the frontend will
          accept to serve. Excess connections will be queued by the system
          in the socket's listen queue and will be served once a connection
          closes.

如果系统支持,对于大型站点而言,将此限制值设得非常高可能很有用,以便 HAProxy 管理连接队列,而非让客户端处于未响应的连接尝试状态。该值不应超过全局 maxconn。同时请注意,每个连接包含两个 tune.bufsize(默认为 16 kB)的缓冲区,以及一些其他数据,导致每个已建立的连接大约消耗 33 kB 的内存。这意味着,经过适当调优的中等规模系统,配备 1 GB 内存时,可承受约 20000 至 25000 个并发连接。

此外,当 <conns> 设置为较大值时,服务器可能无法承受如此高的负载,因此通常建议为其分配合理的连接限制。

当该值设置为零时(即默认值),将使用全局的 “maxconn” 值。

另请参阅:“server”、global 段的 “maxconn”、“fullconn”

mode { tcp|http|log|spop }

mode { tcp|http|log|spop }

设置实例的运行模式或协议。 可在以下段中使用:defaults | frontend | listen | backend 支持:是 | 是 | 是 | 是

参数:

tcp       The instance will work in pure TCP mode. A full-duplex connection
          will be established between clients and servers, and no layer 7
          examination will be performed. This is the default mode. It
          should be used for SSL, SSH, SMTP, ...

http      The instance will work in HTTP mode. The client request will be
          analyzed in depth before connecting to any server. Any request
          which is not RFC-compliant will be rejected. Layer 7 filtering,
          processing and switching will be possible. This is the mode which
          brings HAProxy most of its value.

haterm    The frontend will work in haterm HTTP benchmark mode. This is
          not supported by backends. See doc/haterm.txt for details.

log       When used in a backend section, it will turn the backend into a
          log backend. Such backend can be used as a log destination for
          any "log" directive by using the "backend@<name>" syntax. Log
          messages will be distributed to the servers from the backend
          according to the lb settings which can be configured using the
          "balance" keyword. Log backends support UDP servers by prefixing
          the server's address with the "udp@" prefix. Common backend and
          server features are supported, but not TCP or HTTP specific ones.

spop      When used in a backend section, it will turn the backend into a
          spop backend. This mode is mandatory if the backend contains
          SPOA servers, but when mode is tcp, it will automatically be
          converted to mode spop if such servers are detected.

进行内容切换时,前端和后端必须处于相同模式(通常为 HTTP),否则配置将被拒绝。

示例:

defaults http_instances
    mode http

monitor fail { if | unless } <condition>

monitor fail { if | unless } <condition>

为监控 HTTP 请求添加一个失败报告条件。

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend 否 | 是 | 是 | 否

参数:

if <cond>     the monitor request will fail if the condition is satisfied,
              and will succeed otherwise. The condition should describe a
              combined test which must induce a failure if all conditions
              are met, for instance a low number of servers both in a
              backend and its backup.

unless <cond> the monitor request will succeed only if the condition is
              satisfied, and will fail otherwise. Such a condition may be
              based on a test on the presence of a minimum number of active
              servers in a list of backends.

此语句添加一个条件,可强制对监控请求的响应报告失败。默认情况下,当外部组件查询专用于监控的 URI 时,将返回 200 响应。当满足上述任一条件时,HAProxy 将返回 503 而非 200。此机制对于向外部组件报告站点故障非常有用,外部组件可能基于 HAProxy 报告的可用性状态在多个站点间进行路由通告。在此场景中,应依赖包含 “nbsrv” 条件的 ACL。请注意,“monitor fail” 仅在 HTTP 模式下有效。如需调整,可使用 “errorfile” 或 “errorloc” 自定义状态消息。

示例:

frontend www
   mode http
   acl site_dead nbsrv(dynamic) lt 2
   acl site_dead nbsrv(static)  lt 2
   monitor-uri   /site_alive
   monitor fail  if site_dead

另请参阅:“monitor-uri”、“errorfile”、“errorloc”

monitor-uri <uri>

monitor-uri <uri>

拦截外部组件监控请求所使用的 URI

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:

<uri>     is the exact URI which we want to intercept to return HAProxy's
          health status instead of forwarding the request.

当在前端接收到引用 <uri> 的 HTTP 请求时,HAProxy 不会转发该请求,也不会记录日志,而是返回“HTTP/1.0 200 OK”或“HTTP/1.0 503 服务不可用”,具体取决于通过“monitor fail”定义的故障条件。通常情况下,任何前端 HTTP 探针均可据此判断服务处于正常运行状态,而无需将请求转发至后端服务器。请注意,HTTP 方法、版本及所有头字段均被忽略,但请求在 HTTP 层面必须至少有效。该关键字仅可与 HTTP 模式前端一同使用。

监控请求在解析后立即处理,甚至早于任何 “http-request” 规则。在此之前仅应用了 tcp-request 规则集。这些请求无法被记录,这是设计目的。监控仅可配置一个 URI;当存在多个 “monitor-uri” 语句时,最后一个将决定所使用的 URI。它们仅用于向高层组件报告 HAProxy 的健康状态,除此之外无其他用途。然而,可以使用 “monitor fail” 和 ACLs 添加任意数量的条件,从而根据任何可设想的检查结果进行调整(最常见的场景是后端中可用服务器的数量)。

请注意:如果 <uri> 以斜杠(’/’)开头,则匹配将基于请求路径而非请求 URI 执行。此做法为一种变通方案,用于使 HTTP/2 请求能够匹配 monitor-uri。在 HTTP/2 中,客户端被建议仅发送绝对 URI。

示例:

# Use /haproxy_test to report HAProxy's status
frontend www
    mode http
    monitor-uri /haproxy_test

另请参见:“monitor fail”

option abortonclose

option abortonclose
no option abortonclose

启用或禁用客户端关闭时对未开始处理的早期中止

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:无

TCP 连接支持在每个方向上独立关闭,仅单向关闭的连接通常被称为“半关闭”。最初,在 HTTP 生态系统主要采用“关闭模式”时,每个连接仅传输一次请求和一次响应后即关闭,此时脚本化客户端发送请求后关闭发送方向,等待响应,接收关闭指示后即完成操作的情况十分常见。然而,随着持久连接及更高级协议的出现,这种做法已基本消失。目前,客户端在未收到响应前关闭连接的情况,本质上仅出现在用户希望中止传输,或超时触发导致连接被关闭的场景中。

这两种情况(半关闭与中止)从服务器端(此处为 HAProxy 监听器)无法区分。这是一个问题,因为当客户端中止连接后仍保持连接并继续处理请求,会消耗大量资源,尤其是当连接关闭是由于用户点击“重载”按钮所致时,意味着新请求被排队,而先前的请求并未被中止。反之,若在遇到此类半关闭情况时一律中止连接,将导致大量 TCP 应用程序以及部分内部网络中与旧版代理交互的 HTTP 应用程序无法正常工作。

abortonclose 选项

“abortonclose” 选项允许选择期望的行为:当该选项存在于前端时,将避免处理处于半关闭连接上的待处理 TLS 握手。这可能是由于用户在高负载下执行 HTTPS 请求时触发“重载”操作,例如在主 HAProxy 节点与备用节点之间发生 VRRP 故障转移时:所有客户端同时重新连接至新节点,且所有客户端均需执行开销较高的完整 TLS 握手。若该过程耗时超过数秒,很可能导致部分用户放弃连接,此时继续为其执行握手将毫无意义。鉴于 TLS 握手的 CPU 开销较高,建议在面向互联网的前端上保持该选项启用。对于入站 TLS 连接,此为默认行为。

- when present in a backend, it will cause half-closed connections to try
  to abort a request that was not yet sent to a server (i.e. when it's
  pending in the queue or when trying to connect). If the request is
  already being served by a server, then the connection to the server is
  in turn switched to half-close to indicate the same condition to the
  server, which will then decide how to proceed. This is the default for
  HTTP-mode backends.

建议在面向互联网的 TLS 终端节点和 HTTP 服务上启用此选项,并在纯 TCP 服务以及未暴露的旧环境里禁用。HTTP 后端中默认启用此选项,可通过在后端段或其继承的“defaults”段中前置“no”关键字强制禁用。TLS 监听器也默认启用此选项,同样可通过在前端段或其继承的“defaults”段中指定“no option abortonclose”强制禁用。

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

另请参见:“timeout queue” 以及服务器的 “maxconn” 和 “maxqueue” 参数

option accept-invalid-http-request (deprecated)

option accept-invalid-http-request     (deprecated)
no option accept-invalid-http-request  (deprecated)

启用或禁用对 HTTP 请求解析的宽松处理

“accept-invalid-http-request” 关键字已弃用,请改用 “option accept-unsafe-violations-in-http-request”。

option accept-invalid-http-response (deprecated)

option accept-invalid-http-response     (deprecated)
no option accept-invalid-http-response  (deprecated)

启用或禁用对 HTTP 响应解析的宽松处理

“accept-invalid-http-response” 关键字已弃用,请改用 “option accept-unsafe-violations-in-http-response”。

option accept-unsafe-violations-in-http-request

option accept-unsafe-violations-in-http-request
no option accept-unsafe-violations-in-http-request

启用或禁用对 HTTP 请求解析的宽松处理

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:无

默认情况下,HAProxy 会遵循不同的 HTTP RFC 规范进行消息解析。这意味着消息解析非常严格,对于格式错误的消息会向客户端返回错误。这种行为是期望的,因为格式错误的消息本质上常被用于利用服务器弱点的攻击,或绕过安全过滤。有时,由于某种原因(配置、实现等),某些存在缺陷的浏览器可能不遵守这些 RFC,而问题不会立即得到修复。在此情况下,可以通过指定该选项来放宽 HAProxy 的解析规则,以接受部分无效请求。大多数规则出于历史原因主要针对 H1 解析。较新的 HTTP 版本趋向于更加规范,应用程序也更严格地遵循这些协议。

当设置此选项时,遵循以下规则:

* In H1 only, invalid characters, including NULL character, in header name
  will not be rejected; however the header will be dropped.

* In H1 only, NULL character in header value will be accepted;

* In H1 only, characters above 127 in the URI will be accepted. The list of
  characters allowed to appear in a URI is well defined by RFC3986, and
  chars 0-31, 32 (space), 34 ('"'), 60 ('<'), 62 ('>'), 92 ('&#92;'), 94 ('^'),
  96 ('`'), 123 ('{'), 124 ('|'), 125 ('}'), 127 (delete) and anything
  above are normally not allowed. In H1, all character between (0..32) and
  127 will always be blocked. All characters above 127 (excluded) will also
  be blocked, except when this option is enabled. Other characters
  (33..126) will not be checked at all.

* In H1 and H2, URLs containing fragment references ('#' after the path)
  will be accepted;

* In H1 only, no check will be performed on the authority for CONNECT
  requests;

* In H1 only, no check will be performed against the authority and the Host
  header value.

* In H1 only, tests on the HTTP version will be relaxed. It will allow
  HTTP/0.9 GET requests to pass through (no version specified), as well as
  different protocol names (e.g. RTSP), and multiple digits for both the
  major and the minor version.

* In H1 only, WebSocket (RFC6455) requests failing to present a valid
  "Sec-Websocket-Key" header field will be accepted.

此选项默认情况下绝不可启用,因为它会隐藏应用程序的缺陷和安全漏洞。仅在确认问题存在后方可部署。

启用此选项后,无效但被接受的 H1 请求将被捕获,以便后续通过 UNIX 统计套接字上的 “show errors” 请求进行分析。执行此操作还有助于确认问题已解决。

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

另请参阅:stats 套接字上的“option accept-unsafe-violations-in-http-response” 和 “show errors”。

option accept-unsafe-violations-in-http-response

option accept-unsafe-violations-in-http-response
no option accept-unsafe-violations-in-http-response

启用或禁用对 HTTP 响应解析的宽松处理

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:无

与“option accept-unsafe-violations-in-http-request”类似,此选项可用于放宽对 HTTP 响应的解析规则。仅当目标服务器为可信的旧版服务器时,才应启用此选项以接受部分无效响应。大多数规则出于历史原因针对 H1 解析。较新的 HTTP 版本通常更为规范,应用程序也更严格遵循这些协议。

当设置此选项时,遵循以下规则:

* In H1 only, status codes longer than 3 digits but whose value fits in 16
  bits are not rejected.

* In H1 only, invalid characters, including NULL character, in header name
  will not be rejected; however the header will be dropped.

* In H1 only, NULL character in header value will be accepted;

* In H1 only, empty values or several "chunked" value occurrences for
  Transfer-Encoding header will be accepted;

* In H1 only, no check will be performed against the authority and the Host
  header value.

* In H1 only, tests on the HTTP version will be relaxed. It will allow
  different protocol names (e.g. RTSP), and multiple digits for both the
  major and the minor version.

* In H1 only, WebSocket (RFC6455) responses failing to present a valid
  "Sec-Websocket-Accept" header field will be accepted.

此选项默认情况下绝不可启用,因为它会隐藏应用程序的缺陷和安全漏洞。仅在确认问题存在后方可部署。

启用此选项后,响应中的错误头名称仍会被接受,但会完整捕获响应内容,以便后续通过 UNIX 统计套接字上的 “show errors” 请求进行分析。执行此操作还有助于确认问题已解决。

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

另请参阅:stats 套接字上的“option accept-unsafe-violations-in-http-request”和“show errors”。

option allbackups

option allbackups
no option allbackups

可同时使用所有备用服务器,或仅使用第一个备用服务器。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:无

默认情况下,当所有正常服务器均不可用时,首个处于运行状态的备用服务器将接收全部流量。 有时可能更希望同时使用多个备用服务器,因为仅使用一个可能不够。当启用 “option allbackups” 时,若所有正常服务器均不可用,负载均衡将在所有备用服务器之间进行。将使用相同的负载均衡算法,并尊重服务器的权重。因此,备用服务器之间将不再存在优先级顺序。

该选项通常用于静态服务器集群,当应用程序完全离线时,返回“抱歉”页面。

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

option checkcache

option checkcache
no option checkcache

分析所有服务器响应,并阻止包含可缓存 Cookie 的响应

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:无

某些高级框架会在所有位置设置应用 Cookie,且并不总是为开发者提供足够的控制权,以管理响应的缓存方式。当缓存对象返回会话 Cookie 时,用户通过相同缓存时发生会话交叉或窃取的风险极高。在某些情况下,阻止响应比让敏感会话信息暴露在外更为妥当。

选项 “checkcache” 启用对所有服务器响应的深度检查,以确保其严格符合 HTTP 规范中关于可缓存性的要求。该选项会仔细检查服务器响应中的 “Cache-Control”、“Pragma” 和 “Set-Cookie” 头,以判断是否存在客户端代理缓存 Cookie 的风险。启用此选项后,仅以下响应可传递给客户端: - 所有不含 “Set-Cookie” 头的响应; - 所有返回码非 200、203、204、206、300、301、404、405、410、414、501 的响应,前提是服务器未设置 “Cache-Control: public” 头字段; - 所有通过非 GET、HEAD、OPTIONS、TRACE 方法发起的请求所导致的响应,前提是服务器未设置 “Cache-Control: public” 头字段; - 所有包含 “Pragma: no-cache” 头的响应; - 所有包含 “Cache-Control: private” 头的响应; - 所有包含 “Cache-Control: no-store” 头的响应; - 所有包含 “Cache-Control: max-age=0” 头的响应; - 所有包含 “Cache-Control: s-maxage=0” 头的响应; - 所有包含 “Cache-Control: no-cache” 头的响应; - 所有包含 “Cache-Control: no-cache="set-cookie"” 头的响应; - 所有包含 “Cache-Control: no-cache="set-cookie,” 头的响应(允许 “set-cookie” 之后包含其他字段)。

如果响应不满足这些要求,则其将被阻止,效果等同于来自 “http-response deny” 规则的响应,返回 “HTTP 502 bad gateway”。会话状态显示为 “PH–",表示代理在处理头时阻断了响应。此外,日志中将发送告警,以便管理员知晓需进行修复。

由于该选项对应用影响较大,应用在上线生产环境前应充分测试启用该选项的情况。在测试过程中,即使生产环境不使用该选项,也建议始终启用,以便报告潜在危险的应用行为。

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

option clitcpka

option clitcpka
no option clitcpka

启用或禁用在客户端侧发送 TCP keepalive 数据包

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:无

当客户端与服务器之间存在防火墙或其他会话感知组件,且协议涉及长时间会话及较长空闲期(例如远程桌面)时,中间组件可能因会话空闲时间过长而决定终止该会话,从而带来风险。

启用套接字级别的 TCP 持久连接可使系统定期向连接的另一端发送数据包,从而保持连接处于活跃状态。持久连接探测之间的延迟由系统控制,且取决于操作系统及其调优参数。

必须理解,持久连接报文不会在应用层发出或接收,仅网络协议栈能够感知到它们。因此,即使代理的一端已使用持久连接来维持连接活跃,这些持久连接报文也不会被转发至代理的另一端。

请注意,这与 HTTP 持久连接无关。

使用选项 “clitcpka” 可在连接的客户端一侧启用 TCP 持久连接探测,当 HAProxy 与客户端之间的会话超时被察觉时,此功能应能提供帮助。

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

另请参阅:“option srvtcpka”、“option tcpka”

option contstats

option contstats

启用持续的流量统计信息更新

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:无

默认情况下,用于统计信息计算的计数器仅在流结束时才递增。在提供小对象时,该机制工作良好;但在处理大对象(例如大型图片或归档文件)或音视频流时,由 HAProxy 计数器生成的图表会呈现类似刺猬的形态。启用此选项后,计数器会在流过程中频繁递增,通常每 5 秒一次,这通常足以生成清晰的图表。由于重新计数会直接触碰热点路径,因此默认不启用,因为这可能导致会话数量极大时产生大量唤醒,从而造成轻微性能下降。

option disable-h2-upgrade

option disable-h2-upgrade
no option disable-h2-upgrade

启用或禁用从 HTTP/1.x 客户端连接隐式升级至 HTTP/2。

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:无

默认情况下,HAProxy 能够在从特定 HTTP 连接接收到的首个请求与 HTTP/2 连接前缀匹配时,隐式将 HTTP/1.x 客户端连接升级为 HTTP/2 连接(即字符串 “PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n”)。 通过这种方式,可在非 SSL 连接上同时支持 HTTP/1.x 与 HTTP/2 客户端。 必须使用此选项以禁用隐式升级。 请注意,此隐式升级仅支持 HTTP 代理,因此该选项也仅适用于 HTTP 代理。 此外,可通过在 bind 行指定 “proto h2” 强制在明文连接上启用 HTTP/2。 最后,此选项适用于所有 bind 行。 如需禁用特定 bind 行的隐式 HTTP/2 升级,可使用 “proto h1”。

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

option dontlog-normal

option dontlog-normal
no option dontlog-normal

启用或禁用正常、成功的连接日志记录

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:无

某些大型站点每秒需处理数千个连接,日志记录成为一大难题。部分站点甚至被迫关闭日志功能,无法对生产环境问题进行调试。启用此选项后,正常连接(即未发生错误、超时、重试或重分派的连接)将不会被记录。此举可为异常情况保留磁盘空间。在 HTTP 模式下,将检查响应状态码,状态码为 5xx 的响应仍会被记录。

强烈不建议使用此选项,因为大多数情况下,复杂问题的关键信息存在于常规日志中,而这些日志不会在此处记录。如需分离日志,请改用 log-separate-errors 选项。

另请参阅:“log”、“dontlognull”、“log-separate-errors”以及 第 8 节 中关于日志记录的内容。

option dontlognull

option dontlognull
no option dontlognull

启用或禁用空连接日志记录

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:无

在某些环境中,存在一些组件会定期连接到各个系统,以确保其仍处于活跃状态。这可能是来自另一台负载均衡器,也可能是来自监控系统。默认情况下,即使是一个简单的端口探测或扫描也会产生日志。如果这些连接导致日志过于冗杂,可以启用选项 dontlognull,以指示未传输任何数据的连接将不会被记录,这通常对应于此类探测。请注意,错误仍会返回给客户端,并计入统计信息。若不希望如此,可改用选项 http-ignore-probes。

在不受控制的环境(例如互联网)中,通常不建议使用此选项,否则扫描及其他恶意活动将不会被记录。

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

另请参阅:“log”、“http-ignore-probes”、“monitor-uri”以及关于日志记录的第 8 节 。

option external-check

option external-check

使用外部进程进行服务器健康检查

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

可以使用外部命令测试服务器的健康状态。这通过运行使用 “external-check command” 设置的可执行文件来实现。

必须设置全局选项 “external-check”。

另请参阅: “external-check”、“external-check command”、“external-check path”

option forwarded [ proto ]

option forwarded [ proto ]
                 [ host | host-expr <host_expr> ]
                 [ by | by-expr <by_expr> ] [ by_port | by_port-expr <by_port_expr>]
                 [ for | for-expr <for_expr> ] [ for_port | for_port-expr <for_port_expr>]
no option forwarded

启用在发送至服务器的请求中插入 rfc 7239 forwarded 头

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<host_expr>     optional argument to specify a custom sample expression
                those result will be used as 'host' parameter value

<by_expr>       optional argument to specify a custom sample expression
                those result will be used as 'by' parameter nodename value

<for_expr>      optional argument to specify a custom sample expression
                those result will be used as 'for' parameter nodename value

<by_port_expr>  optional argument to specify a custom sample expression
                those result will be used as 'by' parameter nodeport value

<for_port_expr> optional argument to specify a custom sample expression
                those result will be used as 'for' parameter nodeport value

由于 HAProxy 以反向代理模式运行,服务器会丢失部分请求上下文(例如请求来源:客户端 IP 地址、所用协议等…)

一种常见的应对此限制的方法是使用广为人知的 X-Forwarded-For 和 X-Forwarded-* 等头字段,将部分上下文信息暴露给底层服务器或应用程序。尽管过去该方法曾有效且广泛部署,但并未得到 IETF 的官方支持,可能引发互操作性及安全问题。

为解决此问题,IETF 已定义了一种新的 HTTP 扩展:forwarded 头(RFC7239)。更多信息请参见 https://www.rfc-editor.org/rfc/rfc7239.html

此单一头字段的使用可在同一头中传递大量信息,且最重要的是,解决了代理链问题。(RFC 允许多个级联代理向已存在的头字段追加各自的值。)

该选项可在 defaults、listen 或 backend 段中指定,但在 frontend 段中将被忽略。

设置选项 forwarded 且不带参数时,将使用默认隐式行为。默认行为启用 proto 参数,并注入原始客户端 IP。

等效的显式/手动配置如下:

option forwarded proto for

关键字 ‘by’ 用于在转发头中启用 ‘by’ 参数(“nodename”)。该功能允许嵌入请求代理信息。若不可用(例如:UNIX 监听器),‘by’ 值将设为 “unknown”。

关键字 ‘by-expr’ 用于在转发头中启用 ‘by’ 参数(“nodename”)。它允许嵌入请求代理信息。若样本表达式 <by_expr> 有效,则 ‘by’ 值将被设置为该表达式的计算结果;否则,将被设置为 “unknown”。

关键字 ‘for’ 用于在转发头中启用 ‘for’ 参数(“nodename”)。它允许嵌入请求客户端信息。若不可用(例如:UNIX 监听器),‘for’ 值将设为 “unknown”。

关键字 ‘for-expr’ 用于在转发头中启用 ‘for’ 参数(“nodename”)。它允许嵌入请求客户端信息。若样本表达式 <for_expr> 有效,则 ‘for’ 值将被设置为该表达式的计算结果;否则,将被设置为 “unknown”。

关键字 ‘by_port’ 用于向 ‘by’ 参数提供“nodeport”信息。‘by_port’ 要求必须设置 ‘by’ 或 ‘by-expr’,否则将被忽略。若可用,“nodeport”将被设为代理(目标)端口,否则将被忽略。

关键字 ‘by_port-expr’ 用于向 ‘by’ 参数提供“nodeport”信息。‘by_port-expr’ 要求必须设置 ‘by’ 或 ‘by-expr’,否则将被忽略。若样本表达式 <by_port_expr> 有效,“nodeport”将被设置为该表达式的计算结果,否则将被忽略。

关键字 ‘for_port’ 用于向 ‘for’ 参数提供“nodeport”信息。‘for_port’ 要求必须设置 ‘for’ 或 ‘for-expr’,否则将被忽略。“nodeport”将在可用时设为客户端(源)端口,否则将被忽略。

关键字 ‘for_port-expr’ 用于向 ‘for’ 参数提供“nodeport”信息。‘for_port-expr’ 要求必须设置 ‘for’ 或 ‘for-expr’,否则将被忽略。“nodeport”将被设置为样本表达式 <for_port_expr> 的结果(若有效),否则将被忽略。

示例:

# Those servers want the ip address and protocol of the client request
# Resulting header would look like this:
#   forwarded: proto=http;for=127.0.0.1
backend www_default
    mode http
    option forwarded
    #equivalent to: option forwarded proto for

# Those servers want the requested host and hashed client ip address
# as well as client source port (you should use seed for xxh32 if ensuring
# ip privacy is a concern)
# Resulting header would look like this:
#   forwarded: host="haproxy.org";for="_000000007F2F367E:60138"
backend www_host
    mode http
    option forwarded host for-expr src,xxh32,hex for_port

# Those servers want custom data in host, for and by parameters
# Resulting header would look like this:
#   forwarded: host="host.com";by=_haproxy;for="[::1]:10"
backend www_custom
    mode http
    option forwarded host-expr str(host.com) by-expr str(_haproxy) for for_port-expr int(10)

# Those servers want random 'for' obfuscated identifiers for request
# tracing purposes while protecting sensitive IP information
# Resulting header would look like this:
#   forwarded: for=_000000002B1F4D63
backend www_for_hide
    mode http
    option forwarded for-expr rand,hex

另请参阅:“option forwardfor”、“option originalto”

option forwardfor [ except <network> ] [ header <name> ] [ if-none ]

option forwardfor [ except <network> ] [ header <name> ] [ if-none ]

启用向发送至服务器的请求插入 X-Forwarded-For 头

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:

<network> is an optional argument used to disable this option for sources
          matching <network>
<name>    an optional argument to specify a different "X-Forwarded-For"
          header name.

由于 HAProxy 以反向代理模式运行,服务器看到的客户端地址为其 IP 地址。 当服务器日志需要记录客户端的真实 IP 地址时,这种情况有时会造成困扰。为解决此问题,HAProxy 可在发送至服务器的所有请求中添加知名的 HTTP 头 “X-Forwarded-For”。该头包含表示客户端 IP 地址的值。由于此头始终被追加到现有头列表的末尾,服务器必须配置为仅使用该头的最后一个出现位置。请参阅服务器手册,了解如何启用对这一标准头的使用。请注意,仅应使用该头的最后一个出现位置,因为客户端可能已携带了该头。

关键字 “header” 可用于指定一个不同的头名称,以替代默认的 “X-Forwarded-For”。当可能已从其他应用(例如 stunnel)接收到 “X-Forwarded-For” 头时,此功能非常有用,可确保保留原有头信息。此外,若后端服务器不使用 “X-Forwarded-For” 头,而需要其他头(例如 Zeus Web 服务器要求使用 “X-Cluster-Client-IP”),也可通过此方式指定。

有时,同一个 HAProxy 实例可能同时用于直接客户端访问和反向代理访问(例如,当使用 SSL 反向代理解密 HTTPS 流量时)。可以通过添加 “except” 关键字并指定网络地址,禁用对已知源地址或网络的头信息添加。在此情况下,任何与该网络匹配的源 IP 都不会触发该头信息的添加。常见用法包括私有网络或 127.0.0.1。支持 IPv4 和 IPv6。

此外,关键字 “if-none” 表示仅当该头不存在时才添加该头。 此选项仅应在完全可信的环境中使用,因为如果传入 HAProxy 的头由终端用户控制,可能会引发安全问题。

该选项可在前端或后端中指定。若其中至少一个使用了该选项,将添加对应头信息。请注意,若前端和后端均定义了该头信息的子参数,则后端的设置优先于前端。对于 “if-none” 参数,若前端或后端中至少有一方未指定该参数,则其要求添加操作为强制性,因此该方优先。

示例:

# Public HTTP address also used by stunnel on the same machine
frontend www
    mode http
    option forwardfor except 127.0.0.1  # stunnel already adds the header

# Those servers want the IP Address in X-Client
backend www
    mode http
    option forwardfor header X-Client

另请参阅:“option httpclose”、“option http-server-close”、“option http-keep-alive”

option h1-case-adjust-bogus-client

option h1-case-adjust-bogus-client
no option h1-case-adjust-bogus-client

启用或禁用向伪造客户端发送的 HTTP/1 头的大小写调整

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:无

由于 RFC7230 明确指出,头名称没有标准大小写形式,因此其大小写不敏感。 应用程序必须以不区分大小写的方式处理头名称。 但某些不合规的应用程序违反标准,错误地依赖浏览器通常使用的大小写形式。 这一问题在 HTTP/2 中变得尤为关键,因为所有头名称必须以小写形式传输,HAProxy 也遵循相同约定。 无论 HTTP 版本为何,所有头名称均以小写形式发送给客户端和服务器。

当 HAProxy 收到 HTTP/1 响应时,其头名称会被转换为小写形式,经处理后以该格式发送给客户端。若已知某客户端违反 HTTP 标准,且无法正确处理来自 HAProxy 的响应,则可通过启用此选项,并使用全局指令 h1-case-adjust 或 h1-case-adjust-file 指定需重新格式化的头列表,将小写头名称转换为其他格式后再发送给客户端。此操作仅应作为临时解决方案,待客户端修复期间使用,因为依赖此类 workaround 的客户端可能易受内容伪装攻击,必须彻底修复。

请注意,此选项不会影响符合标准的客户端。

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

另请参阅:“option h1-case-adjust-bogus-server”、“h1-case-adjust”、“h1-case-adjust-file”。

option h1-case-adjust-bogus-server

option h1-case-adjust-bogus-server
no option h1-case-adjust-bogus-server

启用或禁用向伪造服务器发送的 HTTP/1 头的大小写调整

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:无

由于 RFC7230 明确指出,头名称没有标准大小写形式,因此其大小写不敏感。 应用程序必须以不区分大小写的方式处理头名称。 但某些不合规的应用程序违反标准,错误地依赖浏览器通常使用的大小写形式。 这一问题在 HTTP/2 中变得尤为关键,因为所有头名称必须以小写形式传输,HAProxy 也遵循相同约定。 无论 HTTP 版本为何,所有头名称均以小写形式发送给客户端和服务器。

当 HAProxy 收到 HTTP/1 请求时,其请求头名称会被转换为小写形式,并以该格式发送至服务器。若已知某服务器违反 HTTP 标准,无法正确处理来自 HAProxy 的请求,则可通过启用此选项,并使用全局指令 h1-case-adjust 或 h1-case-adjust-file 指定需重新格式化的请求头列表,将小写请求头名称转换为其他格式后再发送至服务器。此操作仅应作为临时解决方案,用于等待服务器修复的过渡期间,因为依赖此类 workaround 的服务器可能易受内容伪装攻击,必须彻底修复。

请注意,此选项不会影响符合标准的服务器。

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

另请参阅:“option h1-case-adjust-bogus-client”、“h1-case-adjust”、“h1-case-adjust-file”。

option http-buffer-request

option http-buffer-request
no option http-buffer-request

启用或禁用在继续处理前等待接收完整的 HTTP 请求体

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:无

有时需要在获取 HTTP 请求体之后再做出决策。例如,“balance url_param” 就是这样做的。第一个用例是在连接到服务器之前,缓冲来自慢速客户端的请求。第二个用例是根据请求体的内容做出路由决策。在前端或后端中设置此选项,将强制 HTTP 处理等待,直到接收完整个请求体或请求缓冲区已满。对于某些滥用 HTTP 协议、期望前端与后端之间实现无缓冲传输的应用程序,此选项可能产生不良副作用,因此应务必避免默认启用。

另请参阅:“option http-no-delay”、“timeout http-request”、“http-request wait-for-body”

option http-drop-request-trailers

option http-drop-request-trailers
no option http-drop-request-trailers

从请求发送至服务器时移除 HTTP trailers

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | no | no | yes

参数:无

启用此选项后,请求中发现的任何 HTTP 追随者(trailers)将在发送至服务器前被丢弃。

RFC9110#section-6.5.1 指出,尾部字段可以与头字段合并。这应为有意为之,但可能对某些应用程序造成问题,尤其是当恶意客户端将敏感头字段隐藏在尾部部分,而某些中间节点在未进行特定检查的情况下将其与头字段合并时。在此情况下,可在后端启用此选项,以在将请求发送至服务器前丢弃任何发现的尾部字段。

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

另请参见:“option http-drop-response-trailers”

option http-drop-response-trailers

option http-drop-response-trailers
no option http-drop-response-trailers

从响应中移除 HTTP trailers 后再发送给客户端

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:无

此选项与“option http-drop-request-trailers”类似,但必须用于在向客户端发送响应前丢弃响应中的尾部字段。

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

另请参阅:“option http-drop-request-trailers”

option http-ignore-probes

option http-ignore-probes
no option http-ignore-probes

启用或禁用对空连接和请求超时的日志记录

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:无

最近,一些浏览器开始实现“预连接”功能,即在用户可能访问最近浏览过的网站时,预先建立连接。这导致大量连接被建立到网站,若超时先触发,则结果为 408 请求超时;若浏览器先决定关闭连接,则结果为 400 错误请求。这些情况会污染日志并增加错误计数器。虽然已有“option dontlognull”,但在此场景下仍不充分。相反,此选项执行以下操作:— 若连接关闭前未收到任何数据,则阻止向客户端发送任何 400/408 消息;— 在此情况下阻止生成任何日志;— 阻止任何错误计数器被递增

这样,空连接将被静默忽略。请注意,除非明确需要,否则不建议使用此选项,因为它会隐藏真实问题。未收到请求并看到 408 错误的最常见原因是客户端与中间设备(如 VPN)之间存在 MTU 不一致,导致过大数据包被阻断。此类问题通常也出现在 POST 请求以及携带大 Cookie 的 GET 请求中。日志通常是检测此类问题的唯一途径。

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

另请参阅:“log”、“dontlognull”、“errorfile”以及 第 8 节 中关于日志记录的内容。

option http-keep-alive

option http-keep-alive
no option http-keep-alive

启用或禁用客户端到服务器的 HTTP/1.x 连接中的 HTTP 持久连接

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:无

默认情况下,HAProxy 以持久连接模式处理 HTTP/1.x 的持久连接:对于每个连接,它会处理每个请求和响应,并在两端保持连接空闲。可通过多个选项更改此模式,例如“option http-server-close”或“option httpclose”。此选项可恢复持久连接模式,当在 defaults 段中使用了其他模式时,此功能尤为有用。

设置 “option http-keep-alive” 可在客户端和服务器端启用 HTTP 持久连接模式。该模式在客户端侧可实现最低延迟(尤其适用于慢速网络),在服务器侧可实现最快会话复用,但需以维持与服务器的空闲连接为代价。通常情况下,使用此选项可使小对象的请求速率大约达到 “http-server-close” 选项的两倍。此选项主要适用于以下两种场景:

- when the server is non-HTTP compliant and authenticates the connection
  instead of requests (e.g. NTLM authentication)

- when the cost of establishing the connection to the server is significant
  compared to the cost of retrieving the associated object from the server.

最后一种情况可能出现在服务器是快速静态缓存服务器时。

目前,日志不会标明请求是否来自同一会话。日志中报告的接受时间对应于前一个请求的结束时间,请求时间对应于等待新请求所花费的时间。若未设置,持久连接的请求时间仍受 “timeout http-keep-alive” 或 “timeout http-request” 定义的超时限制。

此选项会禁用并替换任何先前配置的 “option httpclose” 或 “option http-server-close”。

另请参阅:“option httpclose”、“option http-server-close”、“option prefer-last-server”和“option http-pretend-keepalive”。

option http-no-delay

option http-no-delay
no option http-no-delay

请系统优先考虑较低的交互延迟,而非 HTTP 性能。

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:无

在 HTTP 中,每个数据负载均为单向传输,且不涉及交互性概念。任何代理都应合理地对数据进行排队,以保证较低的延迟。极少数服务器到服务器的应用程序滥用 HTTP 协议,期望数据负载阶段具有高度交互性,即在单个请求中双向交错传输大量数据块。这完全不符合 HTTP 规范,且在大多数代理或服务器上无法正常工作。当此类应用程序通过 HAProxy 尝试实现时,虽然可以运行,但由于网络优化机制倾向于通过等待足够数据以发送完整数据包来提升性能,因此会遭遇显著延迟。典型延迟约为每往返一次 200 毫秒。请注意,这种情况仅出现在异常使用场景中。正常使用场景,如 CONNECT 请求或 WebSocket,不受影响。

当“option http-no-delay”出现在连接所使用的前端或后端中时,所有此类优化都将被禁用,以实现最快的数据交换。当然,这并不能保证功能正常,因为可能在其他任何位置出现故障。但如果应用程序通过 HAProxy 可以正常工作,那么其性能将达到最优。该选项不应默认启用,除非发现存在此类缺陷的应用程序,否则不应使用。启用该选项会导致带宽和 CPU 使用率上升,在高延迟环境中可能显著降低性能。

参见:“option http-buffer-request”

option http-pretend-keepalive

option http-pretend-keepalive
no option http-pretend-keepalive

定义 HAProxy 是否向服务器通告 HTTP/1.x 连接的保持连接状态。

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:无

当启用 “option http-server-close” 或 “option httpclose” 时,HAProxy 会在转发至服务器的 HTTP/1.x 请求中添加 “Connection: close” 头。不幸的是,当某些服务器检测到该头时,会自动停止对长度未知的响应使用分块编码,而这一行为与实际无关。结果是,客户端或缓存可能接收到不完整的响应却未察觉,误认为响应已完整。

通过设置 “option http-pretend-keepalive”,HAProxy 会令服务器误以为连接将保持活跃。服务器因此不会回退到上述异常的非期望状态。当 HAProxy 收到完整的响应后,将关闭与服务器的连接,其行为与启用 “option httpclose” 时一致。这样,客户端可获得正常的响应,且服务器端的连接得以正确关闭。

建议默认情况下不要启用此选项,因为大多数服务器在收到最后一个数据包后会更高效地自行关闭连接,并略微提前释放其缓冲区。此外,网络中增加的数据包可能会略微降低整体峰值性能。然而需要注意的是,启用此选项后,HAProxy 需要完成的工作量会略微减少。因此,如果 HAProxy 是整个架构中的性能瓶颈,启用此选项可能节省少量 CPU 周期。

该选项可在后端和 listen 段中设置。在前端段中使用将被忽略,并在启动时报告警告。此选项与后端相关,因此在前端设置并无实际意义。

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

另请参见:“option httpclose”、“option http-server-close” 和 “option http-keep-alive”

option http-restrict-req-hdr-names { preserve | delete | reject }

option http-restrict-req-hdr-names { preserve | delete | reject }

设置 HAProxy 对包含非 “[a-zA-Z0-9-]” 字符集字符的 HTTP 请求头名称的处理策略

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:

preserve  disable the filtering. It is the default mode for HTTP proxies
          with no FastCGI application configured.

delete    remove request headers with a name containing a character
          outside the "[a-zA-Z0-9-]" charset. It is the default mode for
          HTTP backends with a configured FastCGI application.

reject    reject the request with a 403-Forbidden response if it contains a
          header name with a character outside the "[a-zA-Z0-9-]" charset.

此选项可用于限制请求头名称仅包含字母、数字和连字符字符([A-Za-z0-9-])。在与不遵循 HTTP 协议的服务器互操作时,此限制可能是必须的,因为这些服务器无法正确处理头名称中的某些字符。对于 FastCGI 应用程序而言,此限制也可能为必须,因为头名称中所有非字母数字字符均会被下划线替换(’_’)。因此,很容易混淆头名称并绕过某些规则。例如,“X-Forwarded-For” 和 “X_Forwarded-For” 头均会被转换为 “HTTP_X_FORWARDED_FOR”。

请注意,此选项按代理逐个评估,且在完成 http-request 规则评估之后进行。

option http-server-close

option http-server-close
no option http-server-close

在服务器端启用或禁用 HTTP/1.x 连接关闭

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:无

默认情况下,HAProxy 以持久连接模式运行,针对持久的 HTTP/1.x 连接:对于每个连接,HAProxy 会处理每个请求和响应,并在两端保持连接空闲。可通过多个选项更改此模式,例如“option http-server-close”或“option httpclose”。设置“option http-server-close”可在服务器端启用 HTTP connection-close 模式,同时保留客户端侧支持 HTTP 持久连接和流水线化的能力。该模式可实现客户端侧(慢速网络)最低延迟,并在服务器端实现最快会话复用,以节省服务器资源,与“option httpclose”效果类似。此外,只要服务器符合 RFC7230 的要求,该模式还允许非持久连接能力的服务器以持久连接模式向客户端提供服务。请注意,部分服务器在收到请求中的“Connection: close”时,可能并不完全符合这些要求。其结果是持久连接将永远无法使用。一种解决方法是启用“option http-pretend-keepalive”。

目前,日志不会标明请求是否来自同一会话。日志中报告的接受时间对应于前一个请求的结束时间,请求时间对应于等待新请求所花费的时间。若未设置,持久连接的请求时间仍受 “timeout http-keep-alive” 或 “timeout http-request” 定义的超时限制。

该选项可在前端和后端中设置。若持有连接的前端或后端中至少有一个启用了此选项,则该选项生效。启用后将禁用并替换任何先前配置的“option httpclose”或“option http-keep-alive”。请查阅 第 4 节 (“代理”)了解当前端与后端选项不同时,此选项如何与其他选项协同工作。

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

另请参见:“option httpclose”、“option http-pretend-keepalive” 和 “option http-keep-alive”。

option http-use-proxy-header

option http-use-proxy-header
no option http-use-proxy-header

使用非标准的 Proxy-Connection 头代替 Connection 头

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:无

根据 RFC7230 明确规定,HTTP/1.1 代理必须使用 Connection 头来表明其希望维持持久连接或非持久连接。然而,浏览器和代理在代理连接中均忽略该头,并改用未公开、非标准的 Proxy-Connection 头。当尝试在浏览器与此类代理之间部署负载均衡器时,问题便随之产生,因为 HAProxy 所理解的行为与客户端和代理之间所达成的共识存在差异。

通过在前端中设置此选项,HAProxy 可在检测到代理请求时自动切换至使用该非标准头。此处定义的代理请求是指 URI 既不以 ‘/’ 也不以 ‘*’ 开头的请求。此选项与 HTTP 隧道模式不兼容。请注意,该选项只能在前端中指定,并将影响请求的整个生命周期。

此外,当设置此选项时,若请求需要认证,且该请求本身是通过代理转发的,则会自动切换为使用代理认证头。这使得可在现有代理前端检查或强制执行认证。

此选项通常不应使用,仅在代理前端使用时例外。

另请参见:“option httpclose” 和 “option http-server-close”。

option httpchk

option httpchk
option httpchk <uri>
option httpchk <method> <uri>
option httpchk <method> <uri> <version>
option httpchk <method> <uri> <version> <host>

启用 HTTP 协议检查服务器健康状态

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<method>  is the optional HTTP method used with the requests. When not set,
          the "OPTIONS" method is used, as it generally requires low server
          processing and is easy to filter out from the logs. Any method
          may be used, though it is not recommended to invent non-standard
          ones.

<uri>     is the URI referenced in the HTTP requests. It defaults to " / "
          which is accessible by default on almost any server, but may be
          changed to any other URI. Query strings are permitted.

<version> is the optional HTTP version string. It defaults to "HTTP/1.0"
          but some servers might behave incorrectly in HTTP 1.0, so turning
          it to HTTP/1.1 may sometimes help. Note that the Host field is
          mandatory in HTTP/1.1.

<host>    is the optional HTTP Host header value. It is not set by default.
          It is a log-format string.

默认情况下,服务器健康检查仅包含尝试建立 TCP 连接。当指定 “option httpchk” 时,在建立 TCP 连接后会发送完整的 HTTP 请求,响应码为 2xx 或 3xx 被视为有效,而所有其他响应均表示服务器故障,包括无任何响应的情况。

与 “http-check” 指令结合使用时,可自定义 HTTP 健康检查期间发送的请求,或配置对响应的匹配规则。也可配置 send/expect 序列,方式与 TCP 健康检查中的 “tcp-check” 指令相同。

默认情况下,服务器配置用于打开连接以执行 HTTP 健康检查。也可通过使用 “http-check connect” 规则覆盖服务器参数。

httpchk 选项并不要求必须使用 HTTP 后端,它同样适用于普通的 TCP 后端。这在使用 inetd 守护进程绑定到特定端口的简单脚本检测时尤为有用。然而,它始终内部依赖 HTX 多路复用器。因此,这意味着请求格式化和响应解析将严格遵循规范。

示例:

# Relay HTTPS traffic to Apache instance and check service availability
# using HTTP request "OPTIONS * HTTP/1.1" on port 80.
backend https_relay
    mode tcp
    option httpchk OPTIONS * HTTP/1.1
    http-check send hdr Host www
    server apache1 192.168.1.1:443 check port 80

另请参见:option ssl-hello-chk、option smtpchk、option mysql-check、option pgsql-check、http-check 以及 check、port 和 inter 服务器选项。

option httpclose

option httpclose
no option httpclose

启用或禁用 HTTP/1.x 连接关闭

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:无

默认情况下,HAProxy 以持久连接模式运行,针对持久的 HTTP/1.x 连接:每个连接在处理完每个请求和响应后,会在两端保持空闲状态。可通过多个选项更改此模式,例如 “option http-server-close” 或 “option httpclose”。

若设置 “option httpclose”,HAProxy 将根据该选项的设置位置关闭客户端或服务器连接。前端用于客户端连接,后端用于服务器连接。若在监听器上设置该选项,则同时作用于客户端和服务器连接。HAProxy 会检查每个方向是否已设置 “Connection: close” 头,若缺失则添加。

此选项还可与 “option http-pretend-keepalive” 一同使用,该选项将禁用发送 “Connection: close” 请求头,但接收完整响应后仍会关闭连接。

它会禁用并替换任何先前配置的 “option http-server-close” 或 “option http-keep-alive”。

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

另请参见:“option http-server-close”。

option httplog [ clf ]

option httplog [ clf ]

启用 HTTP 请求、流状态和计时器的日志记录

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:

clf       if the "clf" argument is added, then the output format will be
          the CLF format instead of HAProxy's default HTTP format. You can
          use this when you need to feed HAProxy's logs through a specific
          log analyzer which only support the CLF format and which is not
          extensible.

默认情况下,日志输出格式非常简陋,仅包含源地址和目标地址以及实例名称。通过指定 “option httplog”,每行日志将变为更丰富的格式,包括但不限于:HTTP 请求、连接计时器、流状态、连接数量、捕获的头字段和 Cookie、前端、后端及服务器名称,当然还包括源地址和端口。

仅指定 “option httplog” 时,将自动清除默认设置的 ‘clf’ 模式。

“option httplog” 会覆盖之前设置的 “log-format” 指令。

另请参阅 第 8 节 中关于日志记录的内容。

option httpslog

option httpslog

启用 HTTPS 请求、流状态及计时器的日志记录

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

默认情况下,日志输出格式非常简陋,仅包含源地址和目标地址以及实例名称。通过指定 “option httpslog”,每行日志将变为更丰富的格式,包括但不限于:HTTP 请求、连接计时器、流状态、连接数量、捕获的头和 Cookie、前端、后端和服务器名称、SSL 证书验证状态和 SSL 握手状态,以及当然的源地址和端口。

“option httpslog” 会覆盖之前所有的 “log-format” 指令。

另请参阅 第 8 节 中关于日志记录的内容。

option idle-close-on-response

option idle-close-on-response
no option idle-close-on-response

如果正在进行软停止,则避免关闭空闲的前端连接

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:无

默认情况下,软停止期间空闲连接将被关闭。在某些环境中,客户端与代理之间可能已建立一些空闲连接,以便稍后发送请求。如果未对写入错误进行适当的重试,这可能导致 HAProxy 重载时出现错误。尽管正确的实现应在连接或写入错误时重试,但此选项的引入是为了支持与 2.4 版本之前 HAProxy 的向后兼容性。事实上,在 2.4 版本之前,HAProxy 会在关闭连接前等待最后一个请求和响应,并添加 “Connection: close” 头,从而通知客户端该连接不可重用。

在实际案例中,此行为曾在 AWS 环境下观察到,即在 HAProxy 前端部署 ALB 时出现。最终结果为 ALB 在 HAProxy 重载期间返回 502 错误。

请注意,使用此选项可能导致连接空闲时间过长时旧进程数量增加。在频繁重载的情况下,可能需要相应调整客户端超时设置和/或“hard-stop-after”参数。

另请参阅:“timeout client”、“timeout client-fin”、“timeout http-request”、“hard-stop-after”

option independent-streams

option independent-streams
no option independent-streams

启用或禁用双向独立超时处理

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:无

默认情况下,当通过套接字发送数据时,该套接字的写超时和读超时都会被刷新,因为我们认为该套接字存在活动,且没有其他方式判断是否应接收数据。

当大多数应用程序均期望此默认行为时,仍存在一种情形下希望禁用该行为,仅在有传入数据时才刷新读取超时。这种情况常见于超时时间较长且交换数据量较小的流,例如 telnet 会话。若服务器突然消失,输出数据会累积在系统的套接字缓冲区中,两个超时均会被正确刷新,但无法得知服务器是否已无法接收这些数据,因此不会触发超时。然而,当底层协议始终回显已发送的数据时,仅通过读取超时即可自行检测该问题。请注意,该问题不会出现在更冗余的协议中,因为数据不会在套接字缓冲区中长时间累积。

当此选项在前端设置时,将禁用向客户端发送数据时的读取超时更新。此情况可能用途有限。当此选项在后端设置时,将禁用向服务器发送数据时的读取超时更新。此举通常会导致慢速链路上的大规模 HTTP 上传失败,因此应谨慎使用。

另请参阅:“timeout client”、“timeout server” 和 “timeout tunnel”

option ldap-check

option ldap-check

使用 LDAPv3 健康检查测试服务器

可以用于以下上下文:tcp

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:无

可以测试服务器是否正确使用 LDAPv3 协议,而不仅仅是测试其是否接受 TCP 连接。启用此选项后,会向服务器发送 LDAPv3 匿名简单绑定消息,并分析响应以确认是否收到 LDAPv3 绑定响应消息。

仅当 LDAP 响应包含成功 resultCode(http://tools.ietf.org/html/rfc4511#section-4.1.9 )时,服务器才被视为有效。

绑定请求的日志记录取决于服务器,具体配置方法请参阅相关文档。

示例:

option ldap-check

另请参见:“option httpchk”

option log-health-checks

option log-health-checks
no option log-health-checks

启用或禁用健康检查状态更新的日志记录

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:无

默认情况下,当服务器处于 UP 状态时,会记录失败的健康检查;当服务器处于 DOWN 状态时,会记录成功的健康检查,因此额外信息的记录量有限。

当启用此选项时,健康检查状态或服务器健康状况的任何变化都将被记录,从而能够知晓某服务器在崩溃前是否曾间歇性地检查失败,或确切地了解其何时未能响应有效的 HTTP 状态,何时端口开始拒绝连接,以及何时服务器完全停止响应。

请注意,由健康检查以外的原因引起的状态变更(例如通过 CLI 执行的启用/禁用操作)不会被此选项记录。

另请参阅:“option httpchk”、“option ldap-check”、“option mysql-check”、“option pgsql-check”、“option redis-check”、“option smtpchk”、“option tcp-check”、“log”以及 第 8 节 关于日志记录的内容。

option log-separate-errors

option log-separate-errors
no option log-separate-errors

更改非完全成功连接的日志级别

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:无

有时在日志中查找错误并不容易。此选项可提升包含潜在重要信息的日志级别,例如错误、超时、重试、重分派或 HTTP 状态码 5xx。日志级别将从“info”提升至“err”。这使得大多数 syslog 守护进程能够将这些日志单独记录到不同的文件中。请注意,不要从原始文件中移除这些日志,否则将丢失顺序信息,而顺序信息提供了非常重要的上下文。

使用此选项,处理每秒数千个连接的大型站点可将正常流量日志记录至循环缓冲区,仅归档较小的错误日志。

另请参阅:“log”、“dontlognull”、“dontlog-normal”以及 第 8 节 中关于日志记录的内容。

option logasap

option logasap
no option logasap

启用或禁用早期日志记录。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:无

默认情况下,当日志格式别名和样本提取项在日志格式字符串定义中全部返回值,或流终止时,将输出日志。这使得内置日志格式字符串能够计入传输时间,或日志消息中的字节数。

当处理长连接(如大文件传输或 RDP)时,请求或连接在日志中出现可能需要较长时间。使用 “option logasap” 选项后,日志消息将在 TCP 模式下服务器连接建立时,或 HTTP 模式下服务器发送完整头信息时立即生成。日志中缺失的信息包括总字节数,该值仅反映消息生成前已传输的数据量,以及总时间,该值未计入连接剩余生命周期或传输时间。对于 HTTP 情况,建议捕获 Content-Length 响应头,以便日志至少能指示预期传输的字节数。

示例:

listen http_proxy 0.0.0.0:80
    mode http
    option httplog
    option logasap
    log 192.168.2.200 local3
    >>> Feb  6 12:14:14 localhost \
          haproxy[14389]: 10.0.1.2:33317 [06/Feb/2009:12:14:14.655] http-in \
          static/srv1 9/10/7/14/+30 200 +243 - - ---- 3/1/1/1/0 1/0 \
          "GET /image.iso HTTP/1.0"

参见: “option httplog”、“capture response header”,以及 section 8 关于日志记录的内容。

option mysql-check [ user <username> [ { post-41 | pre-41 | post-80 } ] ]

option mysql-check [ user <username> [ { post-41 | pre-41 | post-80 } ] ]

使用 MySQL 健康检查对服务器进行测试

可以用于以下上下文:tcp

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<username> This is the username which will be used when connecting to MySQL
           server.
post-41    Send post v4.1 client compatible checks (the default)
pre-41     Send pre v4.1 client compatible checks
post-80    Send post v8.0 client compatible checks with CLIENT_PLUGIN_AUTH
           capability set and mysql_native_password as the authentication
           plugin. Use this option when connecting to MySQL 8.0+ servers
           where the health check user is created with mysql_native_password
           authentication. Example:
             CREATE USER 'haproxy'@'%' IDENTIFIED WITH mysql_native_password BY '';

若指定用户名,检查过程将发送两个 MySQL 数据包:一个客户端认证数据包和一个 QUIT 数据包,以正确关闭 MySQL 会话。随后,解析 MySQL 握手初始化数据包和/或错误数据包。这是一种基础但实用的测试,不会在服务器端产生错误或中断连接。然而,该测试要求存在一个未锁定且无密码的授权用户。要在 MySQL 中创建一个基本的受限用户并可选地设置资源限制:

CREATE USER '<username>'@'<ip_of_haproxy|network_of_haproxy/netmask>'
/*!50701 WITH MAX_QUERIES_PER_HOUR 1 MAX_UPDATES_PER_HOUR 0 */
/*M!100201 MAX_STATEMENT_TIME 0.0001 */;

如果不指定用户名(该做法已弃用且不推荐),检查仅包括解析 MySQL 握手初始化数据包或错误数据包,此模式下不会发送任何内容。有报告指出,若检查频率过高和/或流量不足,可能导致锁定。实际上,在此情况下,需检查 MySQL “max_connect_errors” 值,即如果在前一次连接中断后,服务器在少于 MySQL “max_connect_errors” 次尝试内成功建立连接,则该主机的错误计数将被清零。若 HAProxy 服务器被阻塞,“FLUSH HOSTS” 语句是解除阻塞的唯一方法。

请注意,这不会检查数据库是否存在或数据库一致性。如需执行此类检查,可以使用 xinetd 等外部检查工具。

该检查要求 MySQL 版本 ≥ 3.22,对于较旧版本,请使用 TCP 检查。

通常情况下,传入的 MySQL 服务器需要看到客户端的 IP 地址,以实现多种用途,包括 IP 权限匹配和连接日志记录。在可能的情况下,建议在通过 “source” 关键字的 “usesrc” 参数连接服务器时,对客户端 IP 地址进行伪装,这需要透明代理功能已编译启用,并且 MySQL 服务器需通过运行 HAProxy 的主机来路由客户端连接。

另请参见:“option httpchk”

option nolinger

option nolinger
no option nolinger

启用或禁用会话关闭后立即清理资源

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:无

当客户端或服务器以非正常方式中止连接(例如,物理断开连接)时,会话超时将被触发,会话随之关闭。但该会话将在系统中保持 FIN_WAIT1 状态一段时间,占用部分资源,并可能限制建立新连接的能力。

当发生此情况时,可以启用“option nolinger”选项,强制系统在关闭连接时立即清除套接字中待处理的数据。此时会发出 TCP RST,待处理数据被截断,会话将立即从系统的表中清除。对客户端而言,通常可见的效果是:若关闭操作发生在最后一个数据块时(例如重定向或错误响应),响应数据会被截断。在服务器端,当通过隧道转发时,若客户端中断连接,该选项有助于立即释放源端口。两种情况下均会发出 TCP 重置,由于会话被立即销毁,因此不会发生重传。在丢包率较高的网络中,这可能加剧问题,尤其是在丢包侧存在防火墙时,因为防火墙可能接收到并处理该重置(从而清除其会话状态),并阻止该会话的后续流量,包括来自另一侧的重传数据。因此,若另一侧未收到该重置,将永远无法再次接收 RST,而防火墙可能会记录大量被阻断的数据包。

出于上述所有原因,强烈建议不要使用此选项,除非在万不得已的情况下作为最后手段。在大多数场景中,使用 “client-fin” 或 “server-fin” 超时可实现类似效果,且行为更加可靠。在 Linux 上,还可选择使用 “tcp-ut” 绑定或服务器设置。

该选项可在前端和后端中使用,具体取决于其所需的位置。 在前端使用以处理客户端,在后端使用以处理服务器。 尽管该选项在“defaults”段中技术上受支持,但应避免在此处使用,以免意外传播至本不应使用该选项的段,从而引发问题。

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

另请参见:“timeout client-fin”、“timeout server-fin”、“tcp-ut” 绑定或服务器关键字。

option originalto [ except <network> ] [ header <name> ]

option originalto [ except <network> ] [ header <name> ]

启用向发送至服务器的请求中插入 X-Original-To 头

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:

<network> is an optional argument used to disable this option for sources
          matching <network>
<name>    an optional argument to specify a different "X-Original-To"
          header name.

由于 HAProxy 可以工作在透明模式下,客户端的每个请求都可能被重定向至代理,而 HAProxy 本身可将每个请求转发至复杂的 SQUID 环境,此时 SO_ORIGINAL_DST 的目标主机将丢失。当需要基于目标 IP 地址设置访问规则时,这种情况会带来困扰。为解决此问题,HAProxy 可向发送至服务器的所有请求添加新的 HTTP 头 “X-Original-To”。该头包含表示原始目标 IP 地址的值。必须配置为仅使用该头的最后一次出现。请注意,仅应使用该头的最后一次出现,因为客户端可能已携带了该头。

关键字 “header” 可用于指定一个不同的头名称,以替换默认的 “X-Original-To”。当可能已从其他应用接收了 “X-Original-To” 头,且需要保留该头时,此功能非常有用。此外,若后端服务器不使用 “X-Original-To” 头,而需要其他头名称时,也可使用此功能。

有时,同一个 HAProxy 实例可能同时用于直接客户端访问和反向代理访问(例如,当使用 SSL 反向代理解密 HTTPS 流量时)。可以通过添加 “except” 关键字并指定网络地址,禁用对已知目标地址或网络的头字段添加。在此情况下,任何与该网络匹配的目标 IP 都不会触发该头字段的添加。常见用法包括私有网络或 127.0.0.1。支持 IPv4 和 IPv6。

该选项可在前端或后端中指定。若其中至少一个使用了该选项,将添加该头。请注意,若前后端均定义了该头的子参数,后端的设置将优先于前端。

示例:

# Original Destination address
frontend www
    mode http
    option originalto except 127.0.0.1

# Those servers want the IP Address in X-Client-Dst
backend www
    mode http
    option originalto header X-Client-Dst

另请参见:“option httpclose”、“option http-server-close”。

option persist

option persist
no option persist

启用或禁用对已关闭服务器的强制持久化

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:无

当 HTTP 请求到达一个包含引用已失效服务器的 cookie 的后端时,默认情况下会将其重分派至另一台服务器。若确实需要,可使用“option persist”强制请求首先发送至该已失效服务器。常见应用场景为服务器处于极端负载状态,导致其频繁波动。在此情况下,用户仍会被引导至其会话初始连接的服务器,以期获得正确服务。建议与该选项配合使用“option redispatch”,以便在无法连接至该服务器(服务器已彻底失效)时,最终将客户端重定向至另一台有效服务器。

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

另请参见:“option redispatch”、“retries”、“force-persist”

option pgsql-check user <username>

option pgsql-check user <username>

使用 PostgreSQL 健康检查对服务器进行测试

可以用于以下上下文:tcp

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<username> This is the username which will be used when connecting to
           PostgreSQL server.

该检查发送一个 PostgreSQL StartupMessage,并等待收到 Authentication request 或 ErrorResponse 消息。这是一种基础但实用的测试,不会在服务器端产生错误或中断连接。此检查与 “mysql-check” 完全相同。

另请参见:“option httpchk”

option prefer-last-server

option prefer-last-server
no option prefer-last-server

允许多个负载均衡的请求保持在同一个服务器上

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:无

当所使用的负载均衡算法不具备确定性时,若此前请求已发送至 HAProxy 仍保持连接的服务器,则在同一会话中尽可能将后续请求也发送至同一服务器,有时是可取的。请注意,这与会话保持不同,因为此处仅表示一种偏好,HAProxy 会尝试应用该偏好,但不提供任何形式的保证。此功能的实际用途在于对服务器发起的持久连接。启用该选项后,HAProxy 将尝试复用与服务器关联的现有连接,而非重新均衡至另一服务器,从而避免关闭连接。该机制对静态文件服务器具有实际意义。与哈希算法结合使用时,此选项意义不大。请注意,当负载均衡算法不具备确定性时,HAProxy 已自动尝试保持与返回 401 响应的服务器或返回 407 响应的代理(需认证)的连接。在处理存在缺陷的 NTLM 认证挑战时,此行为为强制要求,且对排查部分异常应用具有显著帮助。在这些环境中,启用 prefer-last-server 选项也可能有益,以避免每次响应后重新分配流量。

本文档中明确指出,哪些负载均衡算法属于确定性算法较为有用。

确定性算法在可用服务器集合未发生变化的前提下,对给定客户端数据始终选择相同的服务器。通常情况下,确定性算法通过哈希或查找传入请求中的信息来选择目标服务器。然而,这并非总是成立;例如,“static-rr”算法也可视为确定性算法,因为服务器选择基于服务器的静态权重,使得选择结果可预测。“sticky”算法为返回客户端提供确定性路由。

对于非确定性算法,这些算法根据动态服务器状态或简单轮询选择服务器,因此两个连续的请求无法保证落在同一台服务器上。option prefer-last-server 专门为此类算法设计。roundrobin 和 leastconn 即为这类算法的示例。

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

另请参见:“option http-keep-alive”

option redispatch

option redispatch
option redispatch <interval>
no option redispatch

在连接失败时启用或禁用会话重分配

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<interval> The optional integer value that controls how often redispatches
           occur when retrying connections. Positive value P indicates a
           redispatch is desired on every Pth retry, and negative value
           N indicate a redispatch is desired on the Nth retry prior to the
           last retry. For example, the default of -1 preserves the
           historical behavior of redispatching on the last retry, a
           positive value of 1 would indicate a redispatch on every retry,
           and a positive value of 3 would indicate a redispatch on every
           third retry. You can disable redispatches with a value of 0.

在 HTTP 模式下,如果客户端通过 Cookie 指定的服务器宕机,客户端可能会持续连接到该服务器,例如使用 “option persist” 或 “force-persist” 时,因为客户端无法清除 Cookie,将无法再访问服务。

启用 “option redispatch” 可使代理打破基于 cookie 或一致性哈希的持久性,将请求重新分派至可用的服务器。

从可用服务器列表的子集中选择活跃服务器。未处于宕机或维护状态(即未进行健康检查,或已被检查为“正常”)的活跃服务器,按以下顺序进行选择:

1. Any active, non-backup server, if any, or,

2. If the "allbackups" option is not set, the first backup server in the
   list, or

3. If the "allbackups" option is set, any backup server.

重试时,HAProxy 会尝试选择除上一次以外的另一台服务器。新服务器将从当前服务器列表中选取。

有时,如果在重试期间更新了列表(例如,发生大量重试且耗时超过检查服务器是否已宕机所需的时间,导致将其从列表中移除并回退到备用服务器列表),连接仍可能被重定向至备用服务器。

它还允许在发生多次连接失败时,重试连接到另一台服务器。当然,这要求将“retries”设置为非零值。

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

另请参阅: “option persist”、“force-persist”、“retries”

option redis-check

option redis-check

使用 Redis 健康检查对服务器进行测试

可以用于以下上下文:tcp

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:无

可以测试服务器是否正确使用 REDIS 协议,而不仅仅是测试其是否接受 TCP 连接。启用此选项后,HAProxy 会向服务器发送 PING REDIS 命令,并分析响应以查找 “+PONG” 响应消息。

示例:

option redis-check

另请参见:“option httpchk”、“option tcp-check”、“tcp-check expect”

option smtpchk

option smtpchk
option smtpchk <hello> <domain>

使用 SMTP 健康检查测试服务器

可以用于以下上下文:tcp

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<hello>   is an optional argument. It is the "hello" command to use. It can
          be either "HELO" (for SMTP) or "EHLO" (for ESMTP). All other
          values will be turned into the default command ("HELO").

<domain>  is the domain name to present to the server. It may only be
          specified (and is mandatory) if the hello command has been
          specified. By default, "localhost" is used.

当设置 “option smtpchk” 时,健康检查将包含 TCP 连接后跟一个 SMTP 命令。默认情况下,该命令为 “HELO localhost”。服务器返回的响应码将被分析,仅以 “2” 开头的响应码被视为有效。所有其他响应,包括无响应的情况,均视为错误,并表示服务器已失效。

此测试适用于 SMTP 服务器或中继。根据请求的不同,某些服务器可能不会记录每次连接尝试,因此建议进行试验以优化行为。使用 telnet 连接端口 25 通常比调整配置更简便。

大多数情况下,传入的 SMTP 服务器需要查看客户端的 IP 地址,以实现多种目的,包括垃圾邮件过滤、防伪造和日志记录。在可能的情况下,建议在使用 “source” 关键字的 “usesrc” 参数连接服务器时,对客户端 IP 地址进行伪装,这需要编译时启用透明代理功能。

示例:

option smtpchk HELO mydomain.org

另请参阅: “option httpchk”、“source”

option socket-stats no option socket-stats

启用或禁用为每个套接字单独收集和提供统计信息。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:无

option splice-auto

option splice-auto
no option splice-auto

启用或禁用套接字在两个方向上的自动内核加速

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:无

当在前端或后端启用此选项时,HAProxy 将自动评估是否可利用内核 TCP 拼接技术在客户端与服务器之间双向转发数据。HAProxy 使用启发式算法估算拼接是否可能提升性能。两个方向的处理相互独立。请注意,所采用的启发式算法并不激进,以避免拼接的过度使用。此选项要求在编译时启用拼接功能,并可通过全局选项 “nosplice” 全局禁用。由于拼接使用管道,因此使用该功能需确保有足够的空闲管道。

重要提示:基于内核的 TCP 拼接是 Linux 特有的功能,最早出现在内核 2.6.25 版本中。该功能通过在内核层面直接在套接字之间传输数据,无需将数据复制到用户空间,从而显著提升性能并节省 CPU 周期。由于早期实现存在缺陷,可能导致数据损坏或效率低下,因此该功能默认未启用,使用时应格外谨慎。尽管无法检测实现的正确性,但 2.6.29 版本是首个提供正确实现的版本。如有疑问,可使用全局配置项 “nosplice” 全局禁用拼接功能。

示例:

option splice-auto

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

另请参阅:option splice-request、option splice-response 以及全局选项 nosplice 和 maxpipes

option splice-request

option splice-request
no option splice-request

启用或禁用请求的套接字自动内核加速

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:无

当在前端或后端启用此选项时,HAProxy 将尽可能使用内核 TCP 拼接技术,将客户端到服务器的数据直接转发。若无可用的管道资源,仍可能采用 recv/send 方式。此选项需在编译时启用拼接功能,且可通过全局选项 “nosplice” 全局禁用。由于拼接依赖管道,使用该功能要求系统具备足够的空闲管道资源。

请注意:有关使用限制,请参阅“option splice-auto”。

示例:

option splice-request

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

另请参见:“option splice-auto”、“option splice-response” 以及全局选项 “nosplice” 和 “maxpipes”

option splice-response

option splice-response
no option splice-response

启用或禁用对响应的套接字自动进行内核加速

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:无

当在前端或后端启用此选项时,HAProxy 将尽可能使用内核 TCP 拼接技术,将数据从服务器转发至客户端。若无可用的管道资源,仍可能采用 recv/send 方式。此选项需在编译时启用拼接功能,且可通过全局选项 “nosplice” 全局禁用。由于拼接依赖管道,使用该功能要求系统具备足够的空闲管道资源。

请注意:有关使用限制,请参阅“option splice-auto”。

示例:

option splice-response

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

另请参见:“option splice-auto”、“option splice-request” 以及全局选项 “nosplice” 和 “maxpipes”

option spop-check

option spop-check

使用 SPOP 健康检查对服务器进行测试

可以用于以下上下文:tcp

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:无

可以测试服务器是否正确地使用 SPOP 协议,而不仅仅是测试其是否接受 TCP 连接。启用此选项后,HAProxy 与服务器之间将执行 HELLO 握手,随后分析响应以检查是否报告了错误。

示例:

option spop-check

另请参见:“option httpchk”

option srvtcpka

option srvtcpka
no option srvtcpka

启用或禁用在服务器端发送 TCP keepalive 数据包

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:无

当客户端与服务器之间存在防火墙或其他会话感知组件,且协议涉及长时间会话及较长空闲期(例如远程桌面)时,中间组件可能因会话空闲时间过长而决定终止该会话,从而带来风险。

启用套接字级别的 TCP 持久连接可使系统定期向连接的另一端发送数据包,从而保持连接处于活跃状态。持久连接探测之间的延迟由系统控制,且取决于操作系统及其调优参数。

必须理解,持久连接报文不会在应用层发出或接收,仅网络协议栈能够感知到它们。因此,即使代理的一端已使用持久连接来维持连接活跃,这些持久连接报文也不会被转发至代理的另一端。

请注意,这与 HTTP 持久连接无关。

使用选项 “srvtcpka” 可在连接的服务器端启用 TCP 持久连接探测,当 HAProxy 与服务器之间的会话超时被察觉时,此功能应能提供帮助。

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

另请参阅:“option clitcpka”、“option tcpka”

option ssl-hello-chk

option ssl-hello-chk

使用 SSLv3 客户端问候消息进行服务器健康检查

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:无

当通过 HAProxy 以 TCP 模式中继某些基于 SSL 的协议时,可以测试服务器是否正确地使用 SSL 通信,而不仅仅是测试其是否接受 TCP 连接。当设置 “option ssl-hello-chk” 时,连接建立后会向服务器发送一个纯 SSLv3 客户端问候消息,然后分析响应以查找 SSL 服务器问候消息。只有当响应中包含该服务器问候消息时,才认为服务器有效。

所有服务器均经过测试,确保其能正确响应 SSLv3 客户端握手消息,且大多数服务器甚至不会记录仅包含握手消息的请求,这一点值得肯定。

请注意,即使 HAProxy 未编译 SSL 支持,此健康检查仍可正常工作,因为它会伪造 SSL 消息。当 SSL 支持可用时,建议使用原生 SSL 健康检查,而非此方法。

另请参阅:“option httpchk”、“check-ssl”

option tcp-check

option tcp-check

使用 tcp-check send/expect 序列执行健康检查

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

此健康检查方法旨在与“tcp-check”命令列表结合使用,以支持发送/期望类型的健康检查序列。

TCP 健康检查目前支持 4 种操作模式: - 无 “tcp-check” 指令:健康检查仅包含一次连接尝试,此为默认模式。

- "tcp-check send" or "tcp-check send-binary" only is mentioned: this is
  used to send a string along with a connection opening. With some
  protocols, it helps sending a "QUIT" message for example that prevents
  the server from logging a connection error for each health check. The
  check result will still be based on the ability to open the connection
  only.

- "tcp-check expect" only is mentioned: this is used to test a banner.
  The connection is opened and HAProxy waits for the server to present some
  contents which must validate some rules. The check result will be based
  on the matching between the contents and the rules. This is suited for
  POP, IMAP, SMTP, FTP, SSH, TELNET.

- both "tcp-check send" and "tcp-check expect" are mentioned: this is
  used to test a hello-type protocol. HAProxy sends a message, the server
  responds and its response is analyzed. the check result will be based on
  the matching between the response contents and the rules. This is often
  suited for protocols which require a binding or a request/response model.
  LDAP, MySQL, Redis and SSL are example of such protocols, though they
  already all have their dedicated checks with a deeper understanding of
  the respective protocols.
  In this mode, many questions may be sent and many answers may be
  analyzed.

第五种模式可用于在脚本的不同步骤中插入注释。

对于每个创建的 tcp-check 规则,可以添加一个 “comment” 指令,后接一个字符串。该字符串将在日志中以及调试模式下的 stderr 中输出。此功能有助于实现用户友好的错误报告。“comment” 指令为可选。

在执行健康检查期间,可通过使用 “tcp-check set-var” 操作,提供变量作用域以存储数据样本。可使用 “tcp-check unset-var” 释放这些变量。

示例:

# perform a POP check (analyze only server's banner)
option tcp-check
tcp-check expect string +OK\ POP3\ ready comment POP\ protocol

# perform an IMAP check (analyze only server's banner)
option tcp-check
tcp-check expect string *\ OK\ IMAP4\ ready comment IMAP\ protocol

# look for the redis master server after ensuring it speaks well
# redis protocol, then it exits properly.
# (send a command then analyze the response 3 times)
option tcp-check
tcp-check comment PING\ phase
tcp-check send PING\r\n
tcp-check expect string +PONG
tcp-check comment role\ check
tcp-check send info\ replication\r\n
tcp-check expect string role:master
tcp-check comment QUIT\ phase
tcp-check send QUIT\r\n
tcp-check expect string +OK

forge a HTTP request, then analyze the response
(send many headers before analyzing)
option tcp-check
tcp-check comment forge\ and\ send\ HTTP\ request
tcp-check send HEAD\ /\ HTTP/1.1\r\n
tcp-check send Host:\ www.mydomain.com\r\n
tcp-check send User-Agent:\ HAProxy\ tcpcheck\r\n
tcp-check send \r\n
tcp-check expect rstring HTTP/1\..\ (2..|3..) comment check\ HTTP\ response

另请参见:“tcp-check connect”、“tcp-check expect” 和 “tcp-check send”。

option tcp-smart-accept

option tcp-smart-accept
no option tcp-smart-accept

启用或禁用在连接建立过程中保存一个 ACK 数据包

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:无

当 HTTP 连接请求到达时,系统会代表 HAProxy 进行确认,随后客户端立即发送请求,系统在通知 HAProxy 新连接的同时也对该请求进行确认。HAProxy 随后读取请求并发送响应。这意味着系统会额外发送一次 TCP ACK,而该 ACK 实际上是多余的,因为 HAProxy 完全可以在发送响应时一并确认该请求。

因此,在 HTTP 模式下,HAProxy 会自动请求系统在支持该功能的平台(目前至少包括 Linux)上避免发送此无用的 ACK。这不会造成任何问题,因为如果响应耗时超过预期,系统将在 40 毫秒后仍会发送该 ACK。

在复杂的网络故障排查会话中,可能需要禁用此优化,因为延迟确认(delayed ACKs)会使排查数据包延迟位置时更加复杂。此时可通过指定“no option tcp-smart-accept”恢复到正常行为。

也可以通过简单地指定“option tcp-smart-accept”来强制对非 HTTP 代理生效。例如,对于 SMTP 等某些服务,服务器会先发起通信,此时该选项可能具有实际意义。

建议避免在 defaults 段中强制设置此选项。如有疑问,可通过在该选项前添加 “default” 关键字将其恢复为自动值,或使用 “no” 关键字禁用该选项。

另请参见:“option tcp-smart-connect”

option tcp-smart-connect

option tcp-smart-connect
no option tcp-smart-connect

启用或禁用在连接过程中保存一个 ACK 数据包

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:无

在某些系统(至少为 Linux)上,HAProxy 可以请求内核在收到连接请求时,不立即发送空的 ACK,而是直接发送缓冲区请求。此举可减少网络中一个数据包的传输,从而提升性能。对于某些服务器而言,此机制也具有实用性,因为它们能随连接建立立即获取请求数据。

当后端中设置 “option tcp-smart-connect” 时,此功能被启用。由于该功能会增加网络故障排查的复杂性,因此默认情况下未启用。

仅在客户端率先发起通信的协议(如 HTTP)中启用此功能才有意义。在其他情况下,若无数据可替代 ACK 发送,则发送正常的 ACK。

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

另请参见:“option tcp-smart-accept”

option tcpka

option tcpka

启用或禁用在两端发送 TCP keepalive 数据包

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:无

当客户端与服务器之间存在防火墙或其他会话感知组件,且协议涉及长时间会话及较长空闲期(例如远程桌面)时,中间组件可能因会话空闲时间过长而决定终止该会话,从而带来风险。

启用套接字级别的 TCP 持久连接可使系统定期向连接的另一端发送数据包,从而保持连接处于活跃状态。持久连接探测之间的延迟由系统控制,且取决于操作系统及其调优参数。

必须理解,持久连接报文不会在应用层发出或接收,仅网络协议栈能够感知到它们。因此,即使代理的一端已使用持久连接来维持连接活跃,这些持久连接报文也不会被转发至代理的另一端。

请注意,这与 HTTP 持久连接无关。

启用选项 “tcpka” 可在连接的客户端和服务器两端均发送 TCP 持久连接探测。请注意,此选项仅在 “defaults” 或 “listen” 段中有效。若在前端中使用此选项,仅客户端会启用持久连接;若在后端中使用此选项,仅服务器端会启用持久连接。因此,强烈建议在配置跨前端和后端分布时,显式使用 “option clitcpka” 和 “option srvtcpka”。

另请参阅: “option clitcpka”、“option srvtcpka”

option tcplog [clf]

option tcplog [clf]

启用 TCP 连接的高级日志记录,包括流状态和计时器信息

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:

clf       if the "clf" argument is added, then the output format will be
          the CLF format instead of HAProxy's default TCP format. You can
          use this when you need to feed HAProxy's logs through a specific
          log analyzer which only support the CLF format and which is not
          extensible.  Since this expects an HTTP format some of the
          values have been pre set. The http request will show as TCP and
          the response code will show as 000.

默认情况下,日志输出格式非常简陋,仅包含源地址和目标地址以及实例名称。通过指定“option tcplog”,每条日志行将变为更丰富的格式,包含但不限于连接计时器、流状态、连接数量、前端、后端和服务器名称,以及源地址和端口。该选项适用于纯 TCP 代理,以便确定是客户端还是服务器端断开连接或超时。对于常规 HTTP 代理,建议使用“option httplog”,其信息更为完整。

“option tcplog” 会覆盖之前所有的 “log-format” 指令。

另请参阅:“option httplog”,以及 第 8 节 关于日志记录的内容。

option transparent (deprecated)

option transparent        (deprecated)
no option transparent     (deprecated)

启用客户端透明代理

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:无

此选项的引入旨在为第 3 层负载均衡器提供第 7 层持久性。其原理是利用操作系统将来自远程地址的入站连接重定向至本地进程(此处为 HAProxy),并让该进程知晓最初请求的地址。启用此选项后,未携带 Cookie 的会话将被转发至入站请求的原始目标 IP 地址(该地址应与另一台设备的地址匹配),而携带 Cookie 的请求仍会被转发至相应的服务器。

请注意,与普遍认知相反,此选项并不会在建立连接时向服务器呈现客户端的 IP 地址。

从 3.3 版本开始,该选项已被弃用,因其曾存在多项内部技术限制。使用该选项将发出警告,如确需使用,可通过全局关键字 “expose-deprecated-directives” 避免警告。

正确做法是在地址 0.0.0.0 上声明一个服务器,该服务器将负责连接到预期的目标地址。服务器还将正确处理与目标服务器的空闲连接。

示例:

# option transparent  ## before 3.3
server transparent 0.0.0.0

另请参阅“source”关键字的“usesrc”参数,以及“bind”关键字的“transparent”选项。

option use-small-buffers [ queue | l7-retries | check ]*

为指定类别启用小缓冲区支持。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

此选项可用于在不同位置启用小缓冲区支持,以节省内存。默认情况下,不带参数时,尽可能在所有可能的位置使用小缓冲区。否则,可将其限制为仅在以下位置启用:

  • queue:启用后,若连接被排队,将使用小缓冲区存储请求,前提是请求足够小。
  • l7-retries:启用后,启用 L7 重试时将使用小缓冲区保存请求。
  • check:启用后,健康检查请求将使用小缓冲区。

启用后,将使用小缓冲区,但仅在可行时。若数据过大,则自动改用常规缓冲区。小缓冲区的大小可通过 “tune.bufsize.small” 全局设置进行配置。

如果该选项在“defaults”段中已启用,可以在特定实例中通过在其前添加“no”关键字来禁用。

另请参见:tune.bufsize.small

persist rdp-cookie

persist rdp-cookie
persist rdp-cookie(<name>)

启用基于 RDP 会话 Cookie 的持久性

可以用于以下上下文:tcp

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<name>    is the optional name of the RDP cookie to check. If omitted, the
          default cookie name "msts" will be used. There currently is no
          valid reason to change this name.

此语句启用基于 RDP Cookie 的会话保持功能。RDP Cookie 包含在已知服务器列表中定位服务器所需的所有信息。因此,当在后端中设置此选项时,请求将被分析;若发现 RDP Cookie,则对其进行解码。若解码结果匹配某个仍处于 UP 状态的已知服务器(或已设置 “option persist”),则连接将被转发至该服务器。

请注意,此配置仅在 TCP 后端中有效,但要使其生效,前端必须等待足够长的时间,以确保 RDP Cookie 已存在于请求缓冲区中。这与使用“rdp-cookie”负载均衡方法的要求相同。因此,强烈建议将所有配置项置于单一的“listen”段中。

此外,必须理解,仅当终端服务器配置为“令牌重定向模式”时,才会发出此 RDP 令牌,这意味着已禁用“IP 地址重定向”选项。

示例:

listen tse-farm
    bind:3389
    # wait up to 5s for an RDP cookie in the request
    tcp-request inspect-delay 5s
    tcp-request content accept if RDP_COOKIE
    # apply RDP cookie persistence
    persist rdp-cookie
    # if server is unknown, let's balance on the same cookie.
    # alternatively, "balance leastconn" may be useful too.
    balance rdp-cookie
    server srv1 1.1.1.1:3389
    server srv2 1.1.1.2:3389

参见: “balance rdp-cookie”、“tcp-request” 以及 “req.rdp_cookie” ACL。

quic-initial <action> [ { if | unless } <condition> ]

quic-initial <action> [ { if | unless } <condition> ]

对传入的 QUIC Initial 数据包执行一个动作。与 “tcp-request connection” 不同,该动作在任何连接元素实例化之前、SSL 握手启动和完成之前执行,因此在需要拒绝连接尝试时效率更高。

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes(!) | yes | yes | no

参数:

<action>    defines the action to perform if the condition applies. See
            below.

<condition> is a standard layer4-only ACL-based condition (see section 7).
            However, QUIC initial rules are executed too early even for
            some layer4 sample fetch methods despite no configuration
            warning and may result in unspecified runtime behavior,
            although they will not crash. Consider that only internal
            samples and layer4 "src*" and "dst*" are considered as
            supported for now.

此动作在 QUIC 数据包解析的早期阶段执行。因此,仅支持极少量的动作: - accept - dgram-drop - reject - send-retry

rate-limit sessions <rate>

rate-limit sessions <rate>

在前端上设置每秒可接受的新会话数量限制

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:

<rate>    The <rate> parameter is an integer designating the maximum number
          of new sessions per second to accept on the frontend.

当前端每秒新建会话数达到指定数量时,将停止接受新的连接,直至速率再次低于限制。在此期间,待处理的会话将保留在套接字的连接队列(系统缓冲区)中,HAProxy 甚至不会察觉到会话正在等待。在对高负载服务设置极低限制时,建议使用 “backlog” 关键字增加套接字的连接队列长度。

该功能在阻止基于连接的攻击或对脆弱服务器的服务滥用方面尤为高效。由于会话速率每毫秒测量一次,因此精度极高。此外,限制立即生效,无需任何延迟即可检测到阈值。

示例:将 SMTP 的连接速率限制为每秒最多 10 次

listen smtp mode tcp bind :25 rate-limit sessions 10 server smtp1 127.0.0.1:1025

请注意:当达到最大速率时,前端的状态不会改变,但如果启用了“socket-stats”选项,其套接字将在统计信息中显示为“WAITING”。

参见:backlog 关键字以及 “fe_sess_rate” ACL 条件。

redirect location <loc> [code <code>] <option> [{if | unless} <condition>]

redirect location <loc> [code <code>] <option> [{if | unless} <condition>]
redirect prefix   <pfx> [code <code>] <option> [{if | unless} <condition>]
redirect scheme   <sch> [code <code>] <option> [{if | unless} <condition>]

若满足条件,则返回 HTTP 重定向

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend 否 | 是 | 是 | 是

如果满足条件,则 HTTP 请求将导致重定向响应。若未指定条件,则重定向无条件生效。

参数:

<loc>     With "redirect location", the exact value in <loc> is placed into
          the HTTP "Location" header. When used in an "http-request" rule,
          <loc> value follows the Custom log format rules and can include
          some dynamic values (see Custom log format in section 8.2.6).

<pfx>     With "redirect prefix", the "Location" header is built from the
          concatenation of <pfx> and the complete URI path, including the
          query string, unless the "drop-query" option is specified (see
          below). As a special case, if <pfx> equals exactly "/", then
          nothing is inserted before the original URI. It allows one to
          redirect to the same URL (for instance, to insert a cookie). When
          used in an "http-request" rule, <pfx> value follows the Custom
          Log Format rules and can include some dynamic values (see Custom
          Log Format in section 8.2.6).

<sch>     With "redirect scheme", then the "Location" header is built by
          concatenating <sch> with "://" then the first occurrence of the
          "Host" header, and then the URI path, including the query string
          unless the "drop-query" option is specified (see below). If no
          path is found or if the path is "*", then "/" is used instead. If
          no "Host" header is found, then an empty host component will be
          returned, which most recent browsers interpret as redirecting to
          the same host. This directive is mostly used to redirect HTTP to
          HTTPS. When used in an "http-request" rule, <sch> value follows
          the Custom log format rules and can include some dynamic values
          (see Custom log format in section 8.2.6).

<code>    The code is optional. It indicates which type of HTTP redirection
          is desired. Only codes 301, 302, 303, 307 and 308 are supported,
          with 302 used by default if no code is specified. 301 means
          "Moved permanently", and a browser may cache the Location. 302
          means "Moved temporarily" and means that the browser should not
          cache the redirection. 303 is equivalent to 302 except that the
          browser will fetch the location with a GET method. 307 is just
          like 302 but makes it clear that the same method must be reused.
          Likewise, 308 replaces 301 if the same method must be used.

<option>  There are several options which can be specified to adjust the
          expected behavior of a redirection:

  - "drop-query"
    When this keyword is used in a prefix-based redirection, then the
    location will be set without any possible query-string, which is useful
    for directing users to a non-secure page for instance. It has no effect
    with a location-type redirect.

  - "append-slash"
    This keyword may be used in conjunction with "drop-query" to redirect
    users who use a URL not ending with a '/' to the same one with the '/'.
    It can be useful to ensure that search engines will only see one URL.
    For this, a return code 301 is preferred.

  - "ignore-empty"
    This keyword only has effect when a location is produced using a log
    format expression (i.e. when used in http-request or http-response).
    It indicates that if the result of the expression is empty, the rule
    should silently be skipped. The main use is to allow mass-redirects
    of known paths using a simple map.

  - "set-cookie NAME[=value]"
    A "Set-Cookie" header will be added with NAME (and optionally "=value")
    to the response. This is sometimes used to indicate that a user has
    been seen, for instance to protect against some types of DoS. No other
    cookie option is added, so the cookie will be a session cookie. Note
    that for a browser, a sole cookie name without an equal sign is
    different from a cookie with an equal sign.

  - "set-cookie-fmt <fmt>"
    It is equivaliant to the option above, except the "Set-Cookie" header
    will be filled with the result of the log-format string <fmt>
    evaluation. Be careful to respect the "NAME[=value]" format because no
    special check are performed during the configuration parsing.

  - "clear-cookie NAME[=]"
    A "Set-Cookie" header will be added with NAME (and optionally "="), but
    with the "Max-Age" attribute set to zero. This will tell the browser to
    delete this cookie. It is useful for instance on logout pages. It is
    important to note that clearing the cookie "NAME" will not remove a
    cookie set with "NAME=value". You have to clear the cookie "NAME=" for
    that, because the browser makes the difference.

  - "keep-query"
    When this keyword is used in a location-based redirection, then the
    query-string of the original URI, if any, will be appended to the
    location. If no query-string is found, nothing is added. If the
    location already contains a query-string, the original one will be
    appended with the '&' delimiter.

示例:仅将登录 URL 重定向至 HTTPS。acl clear dst_port 80 acl secure dst_port 8080 acl login_page url_beg /login acl logout url_beg /logout acl uid_given url_reg /login?userid=[^&]+ acl cookie_set hdr_sub(cookie) SEEN=1

    redirect prefix   https://mysite.com set-cookie SEEN=1 if !cookie_set
    redirect prefix   https://mysite.com           if login_page !secure
    redirect prefix   http://mysite.com drop-query if login_page !uid_given
    redirect location http://mysite.com/           if !login_page secure
    redirect location / clear-cookie USERID=       if logout

示例:对未带斜杠的文章请求发送重定向 acl missing_slash path_reg ^/article/[^/]*$ redirect code 301 prefix / drop-query append-slash if missing_slash

示例:当 SSL 由 HAProxy 处理时,将所有 HTTP 流量重定向至 HTTPS。redirect scheme https if !{ ssl_fc }

示例:在所有未包含 ‘www.’ 前缀的主机前添加该前缀 http-request redirect code 301 location \ http://www.%[hdr(host)]%[capture.req.uri] \ unless { hdr_beg(host) -i www }

示例:仅将旧网址永久重定向至新网址 http-request redirect code 301 location \ %[path,map_str(old-blog-articles.map)] ignore-empty

请参阅 第 7 节 了解 ACL 的使用方法。

retries <value>

retries <value>

设置在服务器发生故障后执行的重试次数

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<value>   is the number of times a request or connection attempt should be
          retried on a server after a failure.

默认情况下,重试仅适用于新的连接尝试。然而,当使用“retry-on”指令时,其他条件也可能触发重试(例如,空响应、非期望的状态码),每种情况均计为一次尝试,当尝试次数累计达到此处指定的值时,将返回错误。

为避免在服务器重启时立即重新连接,对同一服务器的重试操作前会应用一个倒转计时器,其时长为 min(“timeout connect”, 1 秒)。

当启用 “option redispatch” 时,即使 Cookie 指向另一台服务器,也可能在其他服务器上执行重试。默认情况下,这仅限于最后一次重试,除非向 “option redispatch” 传递参数。

另请参见:“option redispatch”

retry-on [space-delimited list of keywords]

retry-on [space-delimited list of keywords]

指定在何时尝试自动重试失败的请求。此设置仅在“mode”设置为 http 时有效,其他情况下将被静默忽略。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

 <keywords>  is a space-delimited list of keywords or HTTP status codes, each
             representing a type of failure event on which an attempt to
             retry the request is desired. Please read the notes at the
             bottom before changing this setting. The following keywords are
             supported:

   none              never retry

   conn-failure      retry when the connection or the SSL handshake failed
                     and the request could not be sent. This is the default.

   empty-response    retry when the server connection was closed after part
                     of the request was sent, and nothing was received from
                     the server. This type of failure may be caused by the
                     request timeout on the server side, poor network
                     condition, or a server crash or restart while
                     processing the request.

   junk-response     retry when the server returned something not looking
                     like a complete HTTP response. This includes partial
                     responses headers as well as non-HTTP contents. It
                     usually is a bad idea to retry on such events, which
                     may be caused a configuration issue (wrong server port)
                     or by the request being harmful to the server (buffer
                     overflow attack for example).

   response-timeout  the server timeout stroke while waiting for the server
                     to respond to the request. This may be caused by poor
                     network condition, the reuse of an idle connection
                     which has expired on the path, or by the request being
                     extremely expensive to process. It generally is a bad
                     idea to retry on such events on servers dealing with
                     heavy database processing (full scans, etc) as it may
                     amplify denial of service attacks.

   0rtt-rejected     retry requests which were sent over early data and were
                     rejected by the server. These requests are generally
                     considered to be safe to retry.

   <status>          any HTTP status code among "401" (Unauthorized), "403"
                     (Forbidden), "404" (Not Found), "408" (Request Timeout),
"421" (Misdirected Request), "425" (Too Early),
"429" (Too Many Requests), "500" (Server Error),
"501" (Not Implemented), "502" (Bad Gateway),
"503" (Service Unavailable), "504" (Gateway Timeout).

   all-retryable-errors
                     retry request for any error that are considered
                     retryable. This currently activates "conn-failure",
                     "empty-response", "junk-response", "response-timeout",
                     "0rtt-rejected", "500", "502", "503", and "504".

使用此指令会替换之前的所有设置,而非累加。

请注意,使用除 “none” 和 “conn-failure” 以外的任何值都需要分配缓冲区并将整个请求复制到其中,因此会产生内存和性能影响。无法放入单个缓冲区的请求将永远不会重试(参见全局设置 tune.bufsize)。

必须确保应用程序内置了重放保护机制,例如在请求中传递唯一事务 ID,或确保重放相同请求无任何后果。否则,除 “conn-failure” 和 “none” 外,使用任何其他重试值都极为危险。静态文件服务器和缓存通常被认为对任何类型的重试均安全。使用状态码可快速将连接从表现出异常行为(如内存不足、文件系统问题等)的服务器中移除,但此时建议立即执行重分派,将连接转至另一台服务器(请参见 “option redispatch”)。最后,必须理解,大多数故障的根本原因在于请求本身,对导致服务器异常的请求进行重试,通常会使该服务器状况更糟,或在发生重分派时导致整个服务状况恶化。

除非确切了解应用程序如何处理重放请求,否则不应使用此指令。

默认值为 “conn-failure”。

示例:

retry-on 503 504

另请参阅: “retries”,“option redispatch”,“tune.bufsize”

server <name> <address>[:[port]] [param*]

server <name> <address>[:[port]] [param*]

在后端中声明服务器

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend

参数:

<name>    is the internal name assigned to this server. This name will
          appear in logs and alerts. If "http-send-name-header" is
          set, it will be added to the request header sent to the server.
          This name must be unique within the backend section.

<address> is the IPv4 or IPv6 address of the server. Alternatively, a
          resolvable hostname is supported, but this name will be resolved
          during start-up. Address "0.0.0.0" or "*" has a special meaning.
          It indicates that the connection will be forwarded to the same IP
          address as the one from the client connection. This is useful in
          transparent proxy architectures where the client's connection is
          intercepted and HAProxy must forward to the original destination
          address. This is more or less what the "transparent" keyword does
          except that with a server it's possible to limit concurrency and
          to report statistics. Optionally, an address family prefix may be
          used before the address to force the family regardless of the
          address format, which can be useful to specify a path to a unix
          socket with no slash ('/'). Currently supported prefixes are:
                - 'ipv4@'  -> address is always IPv4
                - 'ipv6@'  -> address is always IPv6
                - 'unix@'  -> address is a path to a local unix socket
                - 'abns@'  -> address is in abstract namespace (Linux only)
                - 'abnsz@'  -> address is in abstract namespace (Linux only)
                   but it is explicitly zero-terminated. This means no \0
                   padding is used to complete sun_path. It is useful to
                   interconnect with programs that don't implement the
                   default abns naming logic that haproxy uses.
                - 'sockpair@' -> address is the FD of a connected unix
                  socket or of a socketpair. During a connection, the
                  backend creates a pair of connected sockets, and passes
                  one of them over the FD. The bind part will use the
                  received socket as the client FD. Should be used
                  carefully.
                - 'quic4@' [ EXPERIMENTAL] -> address is resolved as IPv4
                  and protocol UDP is used. QUIC on the backend side is
                  considered experimental mainly because this prevents the
                  server removal at runtime. This requires the global
                  keyword "expose-experimental-directives" to use it.
                - 'quic6@' [ EXPERIMENTAL] -> address is resolved as IPv6
                  and protocol UDP is used. It is considered similarly
                  flagged as experimental.
                - 'rhttp@' [ EXPERIMENTAL ] -> custom address family for a
                  passive server in HTTP reverse context. This is an
                  experimental features which requires
                  "expose-experimental-directives" on a line before this
                  server.
          You may want to reference some environment variables in the
          address parameter, see section 2.3 about environment
          variables. The "init-addr" setting can be used to modify the way
          IP addresses should be resolved upon startup.

<port>    is an optional port specification. If set, all connections will
          be sent to this port. If unset, the same port the client
          connected to will be used. The port may also be prefixed by a "+"
          or a "-". In this case, the server's port will be determined by
          adding this value to the client's port.

<param*>  is a list of parameters for this server. The "server" keywords
          accepts an important number of options and has a complete section
          dedicated to it. Please refer to section 5 for more details.

示例:

server first  10.1.1.1:1080 cookie first  check inter 1000
server second 10.1.1.2:1080 cookie second check inter 1000
server transp ipv4@
server backup "${SRV_BACKUP}:1080" backup
server www1_dc1 "${LAN_DC1}.101:80"
server www1_dc2 "${LAN_DC2}.101:80"

请注意:关于 Linux 的抽象命名空间套接字,“abns” HAProxy 套接字使用 sun_path 的完整长度作为地址长度。其他一些程序(如 socat)默认仅使用字符串长度。如需使 socat 的抽象套接字定义与 HAProxy 兼容,请向 socat 的任意抽象套接字定义传递选项 “,unix-tightsocklen=0”,或改用 “abnsz” HAProxy 套接字族。

另请参阅:“default-server”、“http-send-name-header”以及第 5 节 中关于服务器选项的说明

server-state-file-name [ { use-backend-name | <file> } ]

server-state-file-name [ { use-backend-name | <file> } ]

设置服务器状态文件为可读,加载并应用到此后端中可用的服务器。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend

仅当指令 “load-server-state-from-file” 设置为 “local” 时生效。若未提供 <file>,且使用了 “use-backend-name” 或该指令未设置,则使用后端名称。若 <file> 以斜杠 ‘/’ 开头,则视为绝对路径。否则,将 <file> 与全局指令 “server-state-base” 拼接。

示例:以下最小配置将使 HAProxy 查找状态服务器文件 ‘/etc/haproxy/states/bk’:

global
  server-state-file-base /etc/haproxy/states

backend bk
  load-server-state-from-file

另请参阅:“server-state-base”、“load-server-state-from-file” 和 “show servers state”

server-template <prefix> <num | range> <fqdn>[:<port>] [params*]

server-template <prefix> <num | range> <fqdn>[:<port>] [params*]

设置模板以使用共享参数初始化服务器。这些服务器的名称由 <prefix> 和 <num | range> 参数构建。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend

参数:

<prefix>  A prefix for the server names to be built.

<num | range>
          If <num> is provided, this template initializes <num> servers
          with 1 up to <num> as server name suffixes. A range of numbers
          <num_low>-<num_high> may also be used to use <num_low> up to
          <num_high> as server name suffixes.

<fqdn>    A FQDN for all the servers this template initializes.

<port>    Same meaning as "server" <port> argument (see "server" keyword).

<params*>
          Remaining server parameters among all those supported by "server"
          keyword.

示例:

# Initializes 3 servers with srv1, srv2 and srv3 as names,
# google.com as FQDN, and health-check enabled.
server-template srv 1-3 google.com:80 check

# or
server-template srv 3 google.com:80 check

# would be equivalent to:
server srv1 google.com:80 check
server srv2 google.com:80 check
server srv3 google.com:80 check

source <addr>[:<port>] [usesrc { <addr2>[:<port2>] | client | clientip } ]

source <addr>[:<port>] [usesrc { <addr2>[:<port2>] | client | clientip } ]
source <addr>[:<port>] [usesrc { <addr2>[:<port2>] | hdr_ip(<hdr>[,<occ>]) } ]
source <addr>[:<port>] [interface <name>]

设置传出连接的源地址

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<addr>    is the IPv4 address HAProxy will bind to before connecting to a
          server. This address is also used as a source for health checks.

          The default value of 0.0.0.0 means that the system will select
          the most appropriate address to reach its destination. Optionally
          an address family prefix may be used before the address to force
          the family regardless of the address format, which can be useful
          to specify a path to a unix socket with no slash ('/'). Currently
          supported prefixes are:
            - 'ipv4@' -> address is always IPv4
            - 'ipv6@' -> address is always IPv6
            - 'unix@' -> address is a path to a local unix socket
            - 'abns@' -> address is in abstract namespace (Linux only)
            - 'abnsz@'  -> address is in zero-terminated abstract namespace
                           (Linux only)

          You may want to reference some environment variables in the
          address parameter, see section 2.3 about environment variables.

<port>    is an optional port. It is normally not needed but may be useful
          in some very specific contexts. The default value of zero means
          the system will select a free port. Note that port ranges are not
          supported in the backend. If you want to force port ranges, you
          have to specify them on each "server" line.

<addr2>   is the IP address to present to the server when connections are
          forwarded in full transparent proxy mode. This is currently only
          supported on some patched Linux kernels. When this address is
          specified, clients connecting to the server will be presented
          with this address, while health checks will still use the address
          <addr>.

<port2>   is the optional port to present to the server when connections
          are forwarded in full transparent proxy mode (see <addr2> above).
          The default value of zero means the system will select a free
          port.

<hdr>     is the name of a HTTP header in which to fetch the IP to bind to.
          This is the name of a comma-separated header list which can
          contain multiple IP addresses. By default, the last occurrence is
          used. This is designed to work with the X-Forwarded-For header
          and to automatically bind to the client's IP address as seen
          by previous proxy, typically Stunnel. In order to use another
          occurrence from the last one, please see the <occ> parameter
          below. When the header (or occurrence) is not found, no binding
          is performed so that the proxy's default IP address is used. Also
          keep in mind that the header name is case insensitive, as for any
          HTTP header.

<occ>     is the occurrence number of a value to be used in a multi-value
          header. This is to be used in conjunction with "hdr_ip(<hdr>)",
          in order to specify which occurrence to use for the source IP
          address. Positive values indicate a position from the first
          occurrence, 1 being the first one. Negative values indicate
          positions relative to the last one, -1 being the last one. This
          is helpful for situations where an X-Forwarded-For header is set
          at the entry point of an infrastructure and must be used several
          proxy layers away. When this value is not specified, -1 is
          assumed. Passing a zero here disables the feature.

<name>    is an optional interface name to which to bind to for outgoing
          traffic. On systems supporting this features (currently, only
          Linux), this allows one to bind all traffic to the server to
          this interface even if it is not the one the system would select
          based on routing tables. This should be used with extreme care.
          Note that using this option requires root privileges.

“source” 关键字在复杂环境中非常有用,当仅允许特定地址连接到服务器时尤为必要。例如,当必须通过公共网关使用私有地址时,系统可能无法自行确定合适的源地址,此时该关键字便显得尤为重要。

通过“usesrc”可选关键字,可使用某些修补版 Linux 内核提供的扩展。该功能允许代理使用不属于本机系统的 IP 地址连接服务器。此模式称为“完全透明代理模式”。要使该模式正常工作,目标服务器必须通过运行 HAProxy 的机器将流量返回至该地址,且通常需在该机器上启用 IP 转发功能。

在“完全透明代理”模式下,可以强制指定一个特定的 IP 地址呈现给服务器。实际上,这种用法并不常见。更常见的做法是让 HAProxy 向服务器呈现客户端的 IP 地址。实现这一点有两种方法:

- present the client's IP and port addresses. This is the most transparent
  mode, but it can cause problems when IP connection tracking is enabled on
  the machine, because a same connection may be seen twice with different
  states. However, this solution presents the huge advantage of not
  limiting the system to the 64k outgoing address+port couples, because all
  of the client ranges may be used.

- present only the client's IP address and select a spare port. This
  solution is still quite elegant but slightly less transparent (downstream
  firewalls logs will not match upstream's). It also presents the downside
  of limiting the number of concurrent connections to the usual 64k ports.
  However, since the upstream and downstream ports are different, local IP
  connection tracking on the machine will not be upset by the reuse of the
  same session.

此选项为后端中所有服务器设置默认源地址。也可在“defaults”段中指定。更精细的源地址配置可通过“source”服务器选项在服务器级别实现。详情请参见 第 5 节 。

要使 “usesrc” 正常工作,需具备 root 权限,或在支持的系统上具备 “cap_net_raw” 能力。另请参阅 “setcap” 全局指令。

示例:

backend private
    # Connect to the servers using our 192.168.1.200 source address
    source 192.168.1.200

backend transparent_ssl1
    # Connect to the SSL farm from the client's source address
    source 192.168.1.200 usesrc clientip

backend transparent_ssl2
    # Connect to the SSL farm from the client's source address and port
    # not recommended if IP conntrack is present on the local machine.
    source 192.168.1.200 usesrc client

backend transparent_ssl3
    # Connect to the SSL farm from the client's source address. It
    # is more conntrack-friendly.
    source 192.168.1.200 usesrc clientip

backend transparent_smtp
    # Connect to the SMTP farm from the client's source address/port
    # with Tproxy version 4.
    source 0.0.0.0 usesrc clientip

backend transparent_http
    # Connect to the servers using the client's IP as seen by previous
    # proxy.
    source 0.0.0.0 usesrc hdr_ip(x-forwarded-for,-1)

另请参见:第 5 节 中的 “source” 服务器选项、Linux 内核的 Tproxy 补丁(位于 www.balabit.com ),以及 “bind” 关键字。

srvtcpka-cnt <count>

srvtcpka-cnt <count>

设置 TCP 在服务器端丢弃连接前应发送的最大保活探测次数。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<count>   is the maximum number of keepalive probes.

此关键字对应套接字选项 TCP_KEEPCNT。若未指定此关键字,则使用系统级 TCP 参数(tcp_keepalive_probes)。该设置的可用性取决于操作系统。已知其在 Linux 上可用。

另请参见:“option srvtcpka”、“srvtcpka-idle”、“srvtcpka-intvl”。

srvtcpka-idle <timeout>

srvtcpka-idle <timeout>

设置连接在 TCP 开始发送保活探测前需保持空闲的时间,若启用,则在服务器端发送 TCP 保活数据包。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<timeout> is the time the connection needs to remain idle before TCP starts
          sending keepalive probes. It is specified in seconds by default,
          but can be in any other unit if the number is suffixed by the
          unit, as explained at the top of this document.

此关键字对应套接字选项 TCP_KEEPIDLE。若未指定此关键字,则使用系统级 TCP 参数(tcp_keepalive_time)。该设置的可用性取决于操作系统。已知其在 Linux 上可用。

另请参见:“option srvtcpka”、“srvtcpka-cnt”、“srvtcpka-intvl”。

srvtcpka-intvl <timeout>

srvtcpka-intvl <timeout>

设置服务器端单个 keepalive 探测之间的间隔时间。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<timeout> is the time between individual keepalive probes. It is specified
          in seconds by default, but can be in any other unit if the number
          is suffixed by the unit, as explained at the top of this
          document.

此关键字对应套接字选项 TCP_KEEPINTVL。若未指定此关键字,则使用系统级 TCP 参数(tcp_keepalive_intvl)。该设置的可用性取决于操作系统。已知其在 Linux 上可用。

另请参见:“option srvtcpka”、“srvtcpka-cnt”、“srvtcpka-idle”。

stats admin { if | unless } <cond>

stats admin { if | unless } <cond>

若满足/不满足某一条件,则启用统计信息管理级别

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend 否 | 是 | 是 | 是

此语句在满足(或不满足)特定条件时,启用统计信息管理级别。

管理级别允许通过 Web 界面启用或禁用服务器。出于安全考虑,统计信息页面默认为只读。若在段中设置了“stats scope”指令,则仅限这些指令指定的代理可接受状态变更;对其他代理的访问将被拒绝。

当前,POST 请求的大小受限于缓冲区大小减去预留缓冲区空间,这意味着如果服务器列表过长,请求将无法被处理。建议一次仅修改少量服务器。

管理员 POST 请求容易受到 CSRF 攻击。虽然通过检查 Origin(若无 Origin,则检查 Referer)是否与 Host 头匹配在一定程度上缓解了该问题,但不足以完全防止攻击。无法完全防范此类攻击。建议避免在公共接口上暴露该功能,并限制可访问的用户范围。

示例:

# statistics admin level only for localhost
backend stats_localhost
    stats enable
    stats admin if LOCALHOST

示例:

# statistics admin level always enabled because of the authentication
backend stats_auth
    stats enable
    stats auth  admin:AdMiN123
    stats admin if TRUE

示例:

# statistics admin level depends on the authenticated user
userlist stats-auth
    group admin    users admin
    user  admin    insecure-password 'AdMiN123'
    group readonly users haproxy
    user  haproxy  insecure-password 'haproxy'

backend stats_auth
    stats enable
    acl AUTH       http_auth(stats-auth)
    acl AUTH_ADMIN http_auth_group(stats-auth) admin
    stats http-request auth unless AUTH
    stats admin if AUTH_ADMIN

另请参阅:“stats enable”、“stats auth”、“stats http-request”、“stats scope”、第 12.2 节 关于 userlists 的说明以及 第 7 节 关于 ACL 使用的说明。

ssl-f-use [<sslbindconf> ...]*

ssl-f-use [<sslbindconf> ...]*

为当前前端分配证书。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend 否 | 是 | 是 | 否

参数:

<sslbindconf> supports the following keywords from the bind line
(see Section 5.1. Bind options):

- allow-0rtt
- alpn
- ca-file
- ca-verify-file
- ciphers
- ciphersuites
- client-sigalgs
- crl-file
- curves
- ecdhe
- ktls
- no-alpn
- no-ca-names
- npn
- sigalgs
- ssl-min-ver
- ssl-max-ver
- verify

sslbindconf also supports the following keywords from the crt-store load
keyword (see Section 12.7.1. Load options):

- crt
- key
- ocsp
- issuer
- sctl
- ocsp-update

为证书 <crtname> 分配至由前端名称自动创建的 crt-list,该列表名称以 @ 为前缀(例如:@frontend1)。

此隐式 crt-list 将被分配给当前前端中的每一行 “ssl” 绑定。

通过 stats socket 发出的 crt-list 命令对此 crt-list 生效,因此可以替换、移除或添加证书和 SSL 选项。

示例:

frontend https
    bind:443 ssl
    bind quic4@:443 ssl
    ssl-f-use crt foobar.pem.rsa sigalgs "RSA-PSS+SHA256"
    ssl-f-use crt test.foobar.pem
    ssl-f-use crt test2.foobar.crt key test2.foobar.key ocsp test2.foobar.ocsp ocsp-update on

另请参阅:crt-list 和 crt。

stats auth <user>:<passwd>

stats auth <user>:<passwd>

启用统计信息并配置认证,授予账户访问权限

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:

<user>    is a user name to grant access to

<passwd>  is the cleartext password associated to this user

此语句启用默认设置的统计信息,并仅限制已声明的用户访问。可根据需要重复此语句,以允许任意数量的用户。当用户尝试访问统计信息但未提供有效账户时,将返回“401 Forbidden”响应,浏览器会提示用户输入有效的用户名和密码。返回给浏览器的“realm”可使用“stats realm”进行配置。

由于认证方法为 HTTP Basic 认证,密码在网络中以明文形式传输。因此,决定配置文件也使用明文密码,以提醒用户此类密码不应具有敏感性,且不得与任何其他账户共享。

还可以通过使用 “stats scope” 缩小报告中显示的代理范围。

尽管仅凭此语句即可启用统计信息报告,但建议设置所有其他参数,以避免依赖默认的非显式参数。

示例:

# public access (limited to this backend only)
backend public_www
    server srv1 192.168.0.1:80
    stats enable
    stats hide-version
    stats scope   .
    stats uri     /admin?stats
    stats realm   HAProxy\ Statistics
    stats auth    admin1:AdMiN123
    stats auth    admin2:AdMiN321

# internal monitoring access (unlimited)
backend private_monitoring
    stats enable
    stats uri     /admin?stats
    stats refresh 5s

另请参见:“stats enable”、“stats realm”、“stats scope”、“stats uri”

stats enable

stats enable

启用统计信息报告并使用默认设置

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:无

此语句启用统计信息报告,并使用编译时定义的默认设置。除非另有说明,否则以下设置将被采用: - stats uri : /haproxy?stats - stats realm: “HAProxy 统计信息” - stats auth : 无认证 - stats scope: 无限制

尽管仅凭此语句即可启用统计信息报告,但建议设置所有其他参数,以避免依赖默认的非显式参数。

示例:

# public access (limited to this backend only)
backend public_www
    server srv1 192.168.0.1:80
    stats enable
    stats hide-version
    stats scope   .
    stats uri     /admin?stats
    stats realm   HAProxy\ Statistics
    stats auth    admin1:AdMiN123
    stats auth    admin2:AdMiN321

# internal monitoring access (unlimited)
backend private_monitoring
    stats enable
    stats uri     /admin?stats
    stats refresh 5s

另请参阅:“stats auth”、“stats realm”、“stats uri”

stats hide-version

stats hide-version

启用统计信息并隐藏 HAProxy 版本报告

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:无

统计信息页面可报告一些有用的状态信息,包括 HAProxy 的版本。然而,通常认为向任何人披露精确版本号存在风险,因为这可能帮助攻击者针对已知漏洞实施特定攻击。使用“stats hide-version”语句可从统计信息报告中移除版本信息。对于公开站点或登录凭证较弱的站点,建议启用此设置,且该选项为默认值。

尽管仅凭此语句即可启用统计信息报告,但建议设置所有其他参数,以避免依赖默认的非显式参数。

示例:

# public access (limited to this backend only)
backend public_www
    server srv1 192.168.0.1:80
    stats enable
    stats hide-version
    stats scope   .
    stats uri     /admin?stats
    stats realm   HAProxy\ Statistics
    stats auth    admin1:AdMiN123
    stats auth    admin2:AdMiN321

# internal monitoring access (unlimited)
backend private_monitoring
    stats enable
    stats uri     /admin?stats
    stats refresh 5s

另请参阅:“stats auth”、“stats enable”、“stats realm”、“stats uri”、“stats show-version”

stats http-request { allow | deny | auth [realm <realm>] }

stats http-request { allow | deny | auth [realm <realm>] }
             [ { if | unless } <condition> ]

统计信息访问控制

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend

与 “http-request” 类似,这些选项允许精细控制对统计信息的访问。每个选项后可跟 if/unless 和 ACL。首个条件匹配的选项(或无条件的选项)为最终结果。对于 “deny”,返回 403 错误;对于 “allow”,执行正常处理;对于 “auth”,返回 401/407 错误码,客户端需输入用户名和密码。

每个实例中可配置的 http-request 语句数量没有固定限制。

另请参阅:“http-request”,第 12.2 节 关于 userlists 的说明以及 第 7 节 关于 ACL 使用的说明。

stats realm <realm>

stats realm <realm>

启用统计信息并设置认证域

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:

<realm>   is the name of the HTTP Basic Authentication realm reported to
          the browser. The browser uses it to display it in the pop-up
          inviting the user to enter a valid username and password.

领域以单个单词读取,因此其中的任何空格都应使用反斜杠(’\’)进行转义。

此语句仅在与 “stats auth” 配合使用时才有用,因为其仅与认证相关。

尽管仅凭此语句即可启用统计信息报告,但建议设置所有其他参数,以避免依赖默认的非显式参数。

示例:

# public access (limited to this backend only)
backend public_www
    server srv1 192.168.0.1:80
    stats enable
    stats hide-version
    stats scope   .
    stats uri     /admin?stats
    stats realm   HAProxy\ Statistics
    stats auth    admin1:AdMiN123
    stats auth    admin2:AdMiN321

# internal monitoring access (unlimited)
backend private_monitoring
    stats enable
    stats uri     /admin?stats
    stats refresh 5s

另请参见:“stats auth”、“stats enable”、“stats uri”

stats refresh <delay>

stats refresh <delay>

启用统计信息并自动刷新

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:

<delay>   is the suggested refresh delay, specified in seconds, which will
          be returned to the browser consulting the report page. While the
          browser is free to apply any delay, it will generally respect it
          and refresh the page this every seconds. The refresh interval may
          be specified in any other non-default time unit, by suffixing the
          unit after the value, as explained at the top of this document.

此语句在显示负载均衡器活动的持续页面监控界面中非常有用。启用后,HTML 报告页面将包含一个“刷新”/“停止刷新”的链接,用户可选择是否需要页面自动刷新。

尽管仅凭此语句即可启用统计信息报告,但建议设置所有其他参数,以避免依赖默认的非显式参数。

示例:

# public access (limited to this backend only)
backend public_www
    server srv1 192.168.0.1:80
    stats enable
    stats hide-version
    stats scope   .
    stats uri     /admin?stats
    stats realm   HAProxy\ Statistics
    stats auth    admin1:AdMiN123
    stats auth    admin2:AdMiN321

# internal monitoring access (unlimited)
backend private_monitoring
    stats enable
    stats uri     /admin?stats
    stats refresh 5s

另请参见:“stats auth”、“stats enable”、“stats realm”、“stats uri”

stats scope { <name> | "." }

stats scope { <name> | "." }

启用统计信息并限制访问范围

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:

<name>    is the name of a listen, frontend or backend section to be
          reported. The special name "." (a single dot) designates the
          section in which the statement appears.

当指定此语句时,报告中仅显示通过该语句列出的段。其余所有段将被隐藏,且在管理模式下尝试更改其状态的操作将被拒绝。若需报告多个段,可多次使用此语句。请注意,名称检查仅通过简单的字符串比较执行,且不会验证指定的段名称是否真实存在。

尽管仅凭此语句即可启用统计信息报告,但建议设置所有其他参数,以避免依赖默认的非显式参数。

示例:

# public access (limited to this backend only)
backend public_www
    server srv1 192.168.0.1:80
    stats enable
    stats hide-version
    stats scope   .
    stats uri     /admin?stats
    stats realm   HAProxy\ Statistics
    stats auth    admin1:AdMiN123
    stats auth    admin2:AdMiN321

# internal monitoring access (unlimited)
backend private_monitoring
    stats enable
    stats uri     /admin?stats
    stats refresh 5s

另请参见:“stats auth”、“stats enable”、“stats realm”、“stats uri”和“stats admin”

stats show-desc [ <desc> ]

stats show-desc [ <desc> ]

在统计信息页面上启用描述信息的报告。

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

`<desc>`    is an optional description to be reported. If unspecified, the
          description from global section is automatically used instead.

此语句对向客户提供共享服务的用户很有用,其中节点或描述应针对每位客户有所不同。

尽管仅凭此语句即可启用统计信息报告,但建议设置所有其他参数,以避免依赖默认的非显式参数。默认情况下,描述信息不会显示。

示例:

# internal monitoring access (unlimited)
backend private_monitoring
    stats enable
    stats show-desc Master node for Europe, Asia, Africa
    stats uri       /admin?stats
    stats refresh   5s

另请参见全局段中的 “show-node”、“stats enable”、“stats uri” 和 “description”。

stats show-legends

stats show-legends

启用在统计信息页面报告附加信息

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:无

启用在统计信息页面报告附加信息: - cap:功能(代理) - mode:tcp、http 或 health 之一(代理) - id:SNMP ID(代理、套接字、服务器) - IP(套接字、服务器) - cookie(后端、服务器)

尽管仅此语句已足以启用统计信息报告,但建议设置所有其他参数,以避免依赖默认的非显式参数。默认行为是不显示此信息。

另请参见:“stats enable”、“stats uri”。

stats show-modules

stats show-modules

在统计信息页面启用额外的统计信息模块

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:无

新增列将作为提示工具栏,添加到包含额外统计信息值的行末尾。

尽管仅此语句已足以启用统计信息报告,但建议设置所有其他参数,以避免依赖默认的非显式参数。默认行为是不显示此信息。

另请参见:“stats enable”、“stats uri”。

stats show-node [ <name> ]

stats show-node [ <name> ]

在统计信息页面上启用主机名报告。

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:

<name>    is an optional name to be reported. If unspecified, the
          node name from global section is automatically used instead.

此语句对向客户提供共享服务的用户很有用,当为每位客户提供的统计页面中节点或描述信息不同时尤为适用。默认行为是不显示主机名。

尽管仅凭此语句即可启用统计信息报告,但建议设置所有其他参数,以避免依赖默认的非显式参数。

示例:

# internal monitoring access (unlimited)
backend private_monitoring
    stats enable
    stats show-node Europe-1
    stats uri       /admin?stats
    stats refresh   5s

另请参见全局段中的“show-desc”、“stats enable”、“stats uri”和“node”。

stats show-version

stats show-version

启用统计信息并显示 HAProxy 版本报告

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:无

统计信息页面可报告一些有用的运行状态信息,包括 HAProxy 的版本。然而,通常认为向任何人披露精确版本号存在风险,因为这可能帮助攻击者针对已知漏洞实施特定攻击,因此默认情况下该功能被禁用。“stats show-version” 可启用版本信息的显示。对于公开站点或登录凭证较弱的站点,不建议启用此功能。

另请参阅:“stats auth”、“stats enable”、“stats realm”、“stats uri”、“stats hide-version”

stats uri <prefix>

stats uri <prefix>

启用统计信息,并定义用于访问统计信息的 URI 前缀

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:

<prefix>  is the prefix of any URI which will be redirected to stats. This
          prefix may contain a question mark ('?') to indicate part of a
          query string.

统计信息 URI 会在中继流量中被拦截,因此它会作为正常应用页面的一部分显示。强烈建议确保所选 URI 永远不会出现在应用中,否则将无法在应用中访问该页面。

HAProxy 内置的默认 URI 为 “/haproxy?stats”,但此值可在构建时更改,因此建议在此处始终显式指定。通常建议在 URI 中包含问号,以确保中间代理不会缓存结果。此外,由于任何以该前缀开头的字符串均会被视为统计信息请求,问号有助于确保没有任何有效 URI 会以相同字符串开头。

有时使用“/”作为 URI 前缀非常方便,可将该语句单独置于一个“listen”实例中。这样便于将某个地址或端口专门用于统计信息。

尽管仅凭此语句即可启用统计信息报告,但建议设置所有其他参数,以避免依赖默认的非显式参数。

示例:

# public access (limited to this backend only)
backend public_www
    server srv1 192.168.0.1:80
    stats enable
    stats hide-version
    stats scope   .
    stats uri     /admin?stats
    stats realm   HAProxy\ Statistics
    stats auth    admin1:AdMiN123
    stats auth    admin2:AdMiN321

# internal monitoring access (unlimited)
backend private_monitoring
    stats enable
    stats uri     /admin?stats
    stats refresh 5s

另请参阅:“stats auth”、“stats enable”、“stats realm”

stick match <pattern> [table <table>] [{if | unless} <cond>]

stick match <pattern> [table <table>] [{if | unless} <cond>]

定义一个请求模式匹配条件,以将用户绑定到某台服务器

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend

参数:

<pattern>  is a sample expression rule as described in section 7.3. It
           describes what elements of the incoming request or connection
           will be analyzed in the hope to find a matching entry in a
           stickiness table. This rule is mandatory.

<table>    is an optional stickiness table name. If unspecified, the same
           backend's table is used. A stickiness table is declared using
           the "stick-table" statement.

<cond>     is an optional matching condition. It makes it possible to match
           on a certain criterion only when other conditions are met (or
           not met). For instance, it could be used to match on a source IP
           address except when a request passes through a known proxy, in
           which case we'd match on a header containing that IP address.

某些协议或应用需要复杂的会话粘性规则,无法始终依赖 Cookie 或哈希机制。“stick match” 语句用于描述从传入请求或连接中提取会话粘性准则的规则。详见 第 7 节 ,其中列出了所有可能的模式和转换规则。

必须使用 “stick-table” 语句声明表格。表格类型必须与模式兼容。默认情况下,使用同一后端中存在的类型。可以通过使用 “table” 关键字引用其他后端的表格来共享表格。若引用了其他表格,则使用后端内服务器的 ID。默认情况下,每个后端内的服务器 ID 均从 1 开始,因此服务器顺序已足够。但若有疑问,强烈建议通过 “id” 设置显式指定服务器 ID。

可以使用“if”或“unless”后跟条件,来限制“stick match”语句适用的条件。参见 第 7 节 了解基于 ACL 的条件。

对“stick match”语句的数量没有限制。第一个匹配的语句将导致请求被导向与创建该条目时所用服务器相同的服务器。通过这种方式,可使用多个匹配作为备选方案。

会话粘性规则在持久化 Cookie 之后进行检查,因此如果已使用 Cookie 选择服务器,则这些规则不会影响会话粘性。通过这种方式,可以非常方便地插入 Cookie 并基于 IP 地址进行匹配,从而在 HTTP 与 HTTPS 之间维持会话粘性。

示例:

# forward SMTP users to the same server they just used for POP in the
# last 30 minutes
backend pop
    mode tcp
    balance roundrobin
    stick store-request src
    stick-table type ip size 200k expire 30m
    server s1 192.168.1.1:110
    server s2 192.168.1.1:110

backend smtp
    mode tcp
    balance roundrobin
    stick match src table pop
    server s1 192.168.1.1:25
    server s2 192.168.1.1:25

另请参阅:“stick-table”、“stick on”、第 11 节 关于 stick-table 的说明,以及 第 7 节 关于 ACL 和样本提取的说明。

stick on <pattern> [table <table>] [{if | unless} <condition>]

stick on <pattern> [table <table>] [{if | unless} <condition>]

定义一个请求模式,用于将用户关联到服务器

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend

请注意:此形式与“stick match”后接“stick store-request”完全等价,两者使用相同的参数。详情请参阅这两个关键字。仅作为编写更易维护配置的便利性而提供。

示例:

# The following form ...
stick on src table pop if !localhost

# ...is strictly equivalent to this one:
stick match src table pop if !localhost
stick store-request src table pop if !localhost


# Use cookie persistence for HTTP, and stick on source address for HTTPS as
# well as HTTP without cookie. Share the same table between both accesses.
backend http
    mode http
    balance roundrobin
    stick on src table https
    cookie SRV insert indirect nocache
    server s1 192.168.1.1:80 cookie s1
    server s2 192.168.1.1:80 cookie s2

backend https
    mode tcp
    balance roundrobin
    stick-table type ip size 200k expire 30m
    stick on src
    server s1 192.168.1.1:443
    server s2 192.168.1.1:443

另请参阅:“stick match”、“stick store-request”以及 第 11 节 中关于 stick-tables 的内容。

stick store-request <pattern> [table <table>] [{if | unless} <condition>]

stick store-request <pattern> [table <table>] [{if | unless} <condition>]

定义用于在会话粘性表中创建条目的请求模式

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend

参数:

<pattern>  is a sample expression rule as described in section 7.3. It
           describes what elements of the incoming request or connection
           will be analyzed, extracted and stored in the table once a
           server is selected.

<table>    is an optional stickiness table name. If unspecified, the same
           backend's table is used. A stickiness table is declared using
           the "stick-table" statement.

<cond>     is an optional storage condition. It makes it possible to store
           certain criteria only when some conditions are met (or not met).
           For instance, it could be used to store the source IP address
           except when the request passes through a known proxy, in which
           case we'd store a converted form of a header containing that IP
           address.

某些协议或应用需要复杂的会话粘性规则,无法始终依赖 Cookie 或哈希。stick store-request 语句用于定义规则,说明应从请求中提取什么内容以及何时提取,以便将其存储到会话粘性表中,供后续请求通过 stick match 语句进行匹配。显然,所提取的部分必须具有实际意义,并且在后续请求中具备匹配的可能性。例如,存储客户端 IP 地址通常具有意义;存储 URL 参数中的 ID 也具有意义。而存储源端口几乎永远没有意义,因为其值会随机变化。有关可能的模式和转换规则的完整列表,请参见 section 7 。

必须使用 “stick-table” 语句声明表格。表格类型必须与模式兼容。默认情况下,使用同一后端中存在的类型。可以通过使用 “table” 关键字引用其他后端的表格来共享表格。若引用了其他表格,则使用后端内服务器的 ID。默认情况下,每个后端内的服务器 ID 均从 1 开始,因此服务器顺序已足够。但若有疑问,强烈建议通过 “id” 设置显式指定服务器 ID。

可以使用“if”或“unless”后跟条件,来限制“stick store-request”语句适用的条件。该条件将在解析请求时进行评估,因此可使用任意判断标准。参见 第 7 节 了解基于 ACL 的条件。

无限制“stick store-request”语句的数量,但每个请求或响应最多允许同时存储 8 个。这使得无论规则数量多少,均可从请求或响应中提取最多 8 个条件并进行存储。仅保留前 8 个匹配的条件。利用此机制,可同时向多个表写入数据,以提高在其他协议或访问方式下识别用户的可能性。可以使用多个针对同一表的 store-request 规则,通过按优先级降序排列规则,以确定最可靠的判定依据。对于给定表,仅存储首个提取的条件。后续引用同一表的 store-request 规则将被跳过,其 ACL 也不会被评估。

“store-request” 规则在建立服务器连接后进行评估,因此表中将包含实际处理请求的服务器。

示例:

# forward SMTP users to the same server they just used for POP in the
# last 30 minutes
backend pop
    mode tcp
    balance roundrobin
    stick store-request src
    stick-table type ip size 200k expire 30m
    server s1 192.168.1.1:110
    server s2 192.168.1.1:110

backend smtp
    mode tcp
    balance roundrobin
    stick match src table pop
    server s1 192.168.1.1:25
    server s2 192.168.1.1:25

另请参阅:“stick-table”、“stick on”、第 11 节 关于 stick-table 的说明,以及 第 7 节 关于 ACL 和样本提取的内容。

stick store-response <pattern> [table <table>] [{if | unless} <condition>]

stick store-response <pattern> [table <table>] [{if | unless} <condition>]

定义用于在会话粘性表中创建条目的响应模式

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend

参数:

<pattern>  is a sample expression rule as described in section 7.3. It
           describes what elements of the response or connection will
           be analyzed, extracted and stored in the table once a
           server is selected.

<table>    is an optional stickiness table name. If unspecified, the same
           backend's table is used. A stickiness table is declared using
           the "stick-table" statement.

<cond>     is an optional storage condition. It makes it possible to store
           certain criteria only when some conditions are met (or not met).
           For instance, it could be used to store the SSL session ID only
           when the response is a SSL server hello.

某些协议或应用需要复杂的会话粘性规则,无法始终依赖 Cookie 或哈希。stick store-response 语句用于定义规则,说明从响应中提取什么内容以及何时提取,以便将其存储到会话粘性表中,供后续请求通过 stick match 语句进行匹配。显然,所提取的内容必须具有意义,并且在后续请求中具备匹配的可能性。例如,从响应头中提取 ID 是合理的。详见 第 7 节 ,获取所有可能的匹配模式和转换规则的完整列表。

必须使用 “stick-table” 语句声明表格。表格类型必须与模式兼容。默认情况下,使用同一后端中存在的类型。可以通过使用 “table” 关键字引用其他后端的表格来共享表格。若引用了其他表格,则使用后端内服务器的 ID。默认情况下,每个后端内的服务器 ID 均从 1 开始,因此服务器顺序已足够。但若有疑问,强烈建议通过 “id” 设置显式指定服务器 ID。

可以使用“if”或“unless”后跟条件来限制“stick store-response”语句适用的条件。该条件将在解析响应时进行评估,因此可使用任意判断标准。参见 第 7 节 了解基于 ACL 的条件。

本节中,“stick store-response” 语句的数量没有限制,但每个请求或响应最多只能同时存储 8 个数据。这使得无论规则数量多少,均可从请求或响应中提取最多 8 个条件并进行存储。仅保留前 8 个匹配的条件。利用此机制,可同时向多个表写入数据,以提高在其他协议或访问方式下识别用户的可能性。可以使用多个针对同一表的 store-response 规则,通过按优先级降序排列规则,以确定最可靠的判定依据。对于给定表,仅存储第一个提取的条件。后续引用同一表的 store-response 规则将被跳过,其 ACL 也不会被评估。然而,即使某个 store-request 规则引用了某表,store-response 规则仍可使用同一表。这意味着每个表可同时从请求和响应中各学习一个元素。

该表将包含处理请求的真实服务器。

示例:

# Learn SSL session ID from both request and response and create affinity.
backend https
    mode tcp
    balance roundrobin
    # maximum SSL session ID length is 32 bytes.
    stick-table type binary len 32 size 30k expire 30m

    acl clienthello req.ssl_hello_type 1
    acl serverhello res.ssl_hello_type 2

    # use tcp content accepts to detects ssl client and server hello.
    tcp-request inspect-delay 5s
    tcp-request content accept if clienthello

    # no timeout on response inspect delay by default.
    tcp-response content accept if serverhello

    # SSL session ID (SSLID) may be present on a client or server hello.
    # Its length is coded on 1 byte at offset 43 and its value starts
    # at offset 44.

    # Match and learn on request if client hello.
    stick on req.payload_lv(43,1) if clienthello

    # Learn on response if server hello.
    stick store-response resp.payload_lv(43,1) if serverhello

    server s1 192.168.1.1:443
    server s2 192.168.1.1:443

另请参阅:“stick-table”、“stick on”、section 11 关于 stick-table 的说明,以及 section 7 关于 ACL 和模式提取的内容。

stick-table type <type> size <size> [expire <expire>] [args...]

stick-table type <type> size <size> [expire <expire>] [args...]

配置当前段的会话粘性表

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend 否 | 是 | 是 | 是

用于声明和配置 stick-table。请参阅 第 11.1 节 以获取完整说明及支持的参数列表。仅类型和大小为必填项。

tcp-check comment <string>

tcp-check comment <string>

为后续的 tcp-check 规则定义注释,若该规则执行失败,将在日志中报告。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<string>  is the comment message to add in logs if the following tcp-check
          rule fails.

仅适用于 connect、send 和 expect 规则。可用于生成用户友好的错误报告。

另请参见:“option tcp-check”、“tcp-check connect”、“tcp-check send”和“tcp-check expect”。

tcp-check connect [default] [port <expr>] [addr <ip>] [send-proxy] [via-socks4]

tcp-check connect [default] [port <expr>] [addr <ip>] [send-proxy] [via-socks4]
                  [ssl] [sni <sni>] [alpn <alpn>] [linger]
                  [proto <name>] [comment <msg>]

打开一个新连接

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

comment <msg>  defines a message to report if the rule evaluation fails.

default      Use default options of the server line to do the health
             checks. The server options are used only if not redefined.

port <expr>  if not set, check port or server port is used.
             It tells HAProxy where to open the connection to.
             <port> must be a valid TCP port source integer, from 1 to
             65535 or an sample-fetch expression.

addr <ip>    defines the IP address to do the health check.

send-proxy   send a PROXY protocol string

via-socks4   enables outgoing health checks using upstream socks4 proxy.

ssl          opens a ciphered connection

sni <sni>    specifies the SNI to use to do health checks over SSL.

alpn <alpn>  defines which protocols to advertise with ALPN. The protocol
             list consists in a comma-delimited list of protocol names,
             for instance: "http/1.1,http/1.0" (without quotes).
             If it is not set, the server ALPN is used.

proto <name> forces the multiplexer's protocol to use for this connection.
             It must be a TCP mux protocol and it must be usable on the
             backend side. The list of available protocols is reported in
             haproxy -vv.

linger       cleanly close the connection instead of using a single RST.

当应用程序运行在多个 TCP 端口上,或 HAProxy 在单个后端中对多个服务进行负载均衡时,在将服务器视为正常运行之前,分别探测所有服务是有意义的。

当服务器行上未配置 TCP 端口,且未使用 server port 指令时,则必须将 ’tcp-check connect port <port>’ 作为序列中的第一步。

在 tcp-check 规则集中,必须包含一个 ‘connect’ 规则,且规则集必须以 ‘connect’ 规则开头。此举旨在确保管理员清楚了解其操作意图。

当连接必须启动规则集时,仍可由 set-var、unset-var 或 comment 规则先行。

示例:

# check HTTP and HTTPs services on a server.
# first open port 80 thanks to server line port directive, then
# tcp-check opens port 443, ciphered and run a request on it:
option tcp-check
tcp-check connect
tcp-check send GET\ /\ HTTP/1.0\r\n
tcp-check send Host:\ haproxy.1wt.eu\r\n
tcp-check send \r\n
tcp-check expect rstring (2..|3..)
tcp-check connect port 443 ssl
tcp-check send GET\ /\ HTTP/1.0\r\n
tcp-check send Host:\ haproxy.1wt.eu\r\n
tcp-check send \r\n
tcp-check expect rstring (2..|3..)
server www 10.0.0.1 check port 80

# check both POP and IMAP from a single server:
option tcp-check
tcp-check connect port 110 linger
tcp-check expect string +OK\ POP3\ ready
tcp-check connect port 143
tcp-check expect string *\ OK\ IMAP4\ ready
server mail 10.0.0.1 check

另请参见:“option tcp-check”、“tcp-check send”、“tcp-check expect”

tcp-check expect [min-recv <int>] [comment <msg>]

tcp-check expect [min-recv <int>] [comment <msg>]
                 [ok-status <st>] [error-status <st>] [tout-status <st>]
                 [on-success <fmt>] [on-error <fmt>] [status-code <expr>]
                 [!] <match> <pattern>

指定在通用健康检查期间要收集和分析的数据

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

comment <msg>  defines a message to report if the rule evaluation fails.

min-recv  is optional and can define the minimum amount of data required to
          evaluate the current expect rule. If the number of received bytes
          is under this limit, the check will wait for more data. This
          option can be used to resolve some ambiguous matching rules or to
          avoid executing costly regex matches on content known to be still
          incomplete. If an exact string (string or binary) is used, the
          minimum between the string length and this parameter is used.
          This parameter is ignored if it is set to -1. If the expect rule
          does not match, the check will wait for more data. If set to 0,
          the evaluation result is always conclusive.

ok-status <st>     is optional and can be used to set the check status if
                   the expect rule is successfully evaluated and if it is
                   the last rule in the tcp-check ruleset. "L7OK", "L7OKC",
                   "L6OK" and "L4OK" are supported:
                     - L7OK : check passed on layer 7
                     - L7OKC: check conditionally passed on layer 7, set
                               server to NOLB state.
                     - L6OK : check passed on layer 6
                     - L4OK : check passed on layer 4
                    By default "L7OK" is used.

error-status <st>  is optional and can be used to set the check status if
                   an error occurred during the expect rule evaluation.
                   "L7OKC", "L7RSP", "L7STS", "L6RSP" and "L4CON" are
                   supported:
                     - L7OKC: check conditionally passed on layer 7, set
                               server to NOLB state.
                     - L7RSP: layer 7 invalid response - protocol error
                     - L7STS: layer 7 response error, for example HTTP 5xx
                     - L6RSP: layer 6 invalid response - protocol error
                     - L4CON: layer 1-4 connection problem
                   By default "L7RSP" is used.

tout-status <st>   is optional and can be used to set the check status if
                   a timeout occurred during the expect rule evaluation.
                   "L7TOUT", "L6TOUT", and "L4TOUT" are supported:
                     - L7TOUT: layer 7 (HTTP/SMTP) timeout
                     - L6TOUT: layer 6 (SSL) timeout
                     - L4TOUT: layer 1-4 timeout
                   By default "L7TOUT" is used.

on-success <fmt>   is optional and can be used to customize the
                   informational message reported in logs if the expect
                   rule is successfully evaluated and if it is the last rule
                   in the tcp-check ruleset. <fmt> is a Custom log format
                   (see section 8.2.6).

on-error <fmt>     is optional and can be used to customize the
                   informational message reported in logs if an error
                   occurred during the expect rule evaluation. <fmt> is a
                   Custom log format (see section 8.2.6).

status-code <expr> is optional and can be used to set the check status code
                   reported in logs, on success or on error. <expr> is a
                   standard HAProxy expression formed by a sample-fetch
                   followed by some converters.

<match>   is a keyword indicating how to look for a specific pattern in the
          response. The keyword may be one of "string", "rstring", "binary" or
          "rbinary".
          The keyword may be preceded by an exclamation mark ("!") to negate
          the match. Spaces are allowed between the exclamation mark and the
          keyword. See below for more details on the supported keywords.

<pattern> is the pattern to look for. It may be a string or a regular
          expression. If the pattern contains spaces, they must be escaped
          with the usual backslash ('\').
          If the match is set to binary, then the pattern must be passed as
          a series of hexadecimal digits in an even number. Each sequence of
          two digits will represent a byte. The hexadecimal digits may be
          used upper or lower case.

可用的匹配项与它们的 http-check 对应项故意设计得相似:

string <string>: test the exact string matches in the response buffer.
                  A health check response will be considered valid if the
                  response's buffer contains this exact string. If the
                  "string" keyword is prefixed with "!", then the response
                  will be considered invalid if the body contains this
                  string. This can be used to look for a mandatory pattern
                  in a protocol response, or to detect a failure when a
                  specific error appears in a protocol banner.

rstring <regex>: test a regular expression on the response buffer.
                  A health check response will be considered valid if the
                  response's buffer matches this expression. If the
                  "rstring" keyword is prefixed with "!", then the response
                  will be considered invalid if the body matches the
                  expression.

string-lf <fmt>: test a Custom log format match in the response's buffer.
                  A health check response will be considered valid if the
                  response's buffer contains the  string resulting of the
                  evaluation of <fmt>, which follows the Custom log format
                  rules described in section 8.2.6. If prefixed with "!",
                  then the response will be considered invalid if the
                  buffer contains the string.

binary <hexstring>: test the exact string in its hexadecimal form matches
                     in the response buffer. A health check response will
                     be considered valid if the response's buffer contains
                     this exact hexadecimal string.
                     Purpose is to match data on binary protocols.

rbinary <regex>: test a regular expression on the response buffer, like
                  "rstring". However, the response buffer is transformed
                  into its hexadecimal form, including NUL-bytes. This
                  allows using all regex engines to match any binary
                  content.  The hexadecimal transformation takes twice the
                  size of the original response. As such, the expected
                  pattern should work on at-most half the response buffer
                  size.

binary-lf <hexfmt>: test a Custom log format in its hexadecimal form match
                     in the response's buffer. A health check response will
                     be considered valid if the response's buffer contains
                     the hexadecimal string resulting of the evaluation of
                     <fmt>, which follows the Custom log format rules (see
                     section 8.2.6). If prefixed with "!", then the
                     response will be considered invalid if the buffer
                     contains the hexadecimal string. The hexadecimal
                     string is converted in a binary string before matching
                     the response's buffer.

请注意,响应内容大小将受到全局 “tune.bufsize” 选项的限制,该选项默认值为 16384 字节。因此,当使用 “string”、“rstring” 或二进制模式时,过大的响应可能无法包含必需的模式。若确实需要处理大尺寸响应,可通过设置全局变量更改默认最大尺寸。但需注意,解析非常大的响应会消耗部分 CPU 资源,尤其是在使用正则表达式时,且始终建议将检查聚焦于较小的资源。此外,当前状态下,检查无法在响应中的空字符之后匹配任何字符串或正则表达式。同样,无法请求匹配空字符。

示例:

# perform a POP check
option tcp-check
tcp-check expect string +OK\ POP3\ ready

# perform an IMAP check
option tcp-check
tcp-check expect string *\ OK\ IMAP4\ ready

# look for the redis master server
option tcp-check
tcp-check send PING\r\n
tcp-check expect string +PONG
tcp-check send info\ replication\r\n
tcp-check expect string role:master
tcp-check send QUIT\r\n
tcp-check expect string +OK

另请参见:option tcp-check、tcp-check connect、tcp-check send、tcp-check send-binary、http-check expect、tune.bufsize

tcp-check send <data> [comment <msg>]

tcp-check send <data> [comment <msg>]
tcp-check send-lf <fmt> [comment <msg>]

指定一个字符串或自定义日志格式,作为通用健康检查中的问题发送

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

comment <msg>  defines a message to report if the rule evaluation fails.

<data>         is the string that will be sent during a generic health
               check session.

<fmt>          is the Custom log format that will be sent, once evaluated,
               during a generic health check session (see section 8.2.6).

示例:

# look for the redis master server
option tcp-check
tcp-check send info\ replication\r\n
tcp-check expect string role:master

参见: “option tcp-check”、“tcp-check connect”、“tcp-check expect”、“tcp-check send-binary”、“tune.bufsize”

tcp-check send-binary <hexstring> [comment <msg>]

tcp-check send-binary <hexstring> [comment <msg>]
tcp-check send-binary-lf <hexfmt> [comment <msg>]

指定十六进制数字字符串或十六进制数字自定义日志格式,作为原始 TCP 健康检查期间的二进制查询发送

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

comment <msg>  defines a message to report if the rule evaluation fails.

<hexstring>    is the hexadecimal string that will be send, once converted
               to binary, during a generic health check session.

<hexfmt>       is the hexadecimal Custom log format that will be send, once
               evaluated and converted to binary, during a generic health
               check session (see section 8.2.6).

示例:

# redis check in binary
option tcp-check
tcp-check send-binary 50494e470d0a # PING\r\n
tcp-check expect binary 2b504F4e47 # +PONG

参见: “option tcp-check”、“tcp-check connect”、“tcp-check expect”、“tcp-check send”、“tune.bufsize”

tcp-check set-var(<var-name>[,<cond>...]) <expr>

tcp-check set-var(<var-name>[,<cond>...]) <expr>
tcp-check set-var-fmt(<var-name>[,<cond>...]) <fmt>

此操作用于设置变量的内容。变量在行内声明。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<var-name>   The name of the variable. Only "proc", "sess" and "check"
             scopes can be used. See section 2.8 about variables for details.

 <cond>      A set of conditions that must all be true for the variable to
             actually be set (such as "ifnotempty", "ifgt" ...). See the
             set-var converter's description for a full list of possible
             conditions.

 <expr>      Is a sample-fetch expression potentially followed by converters.

 <fmt>       This is the value expressed using Custom log format rules (see
             Custom log format in section 8.2.6).

示例:

tcp-check set-var(check.port) int(1234)
tcp-check set-var-fmt(check.name) "%H"

tcp-check unset-var(<var-name>)

tcp-check unset-var(<var-name>)

释放变量在其作用域内的引用。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<var-name>   The name of the variable. Only "proc", "sess" and "check"
             scopes can be used. See section 2.8 about variables for details.

示例:

tcp-check unset-var(check.port)

tcp-request connection <action> <options...> [ { if | unless } <condition> ]

tcp-request connection <action> <options...> [ { if | unless } <condition> ]

根据第 4 层条件对传入连接执行相应动作

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes(!) | yes | yes | no

参数:

<action>    defines the action to perform if the condition applies. See
            below.

<condition> is a standard layer4-only ACL-based condition (see section 7).

在新连接建立后立即,可评估某些条件,以决定该连接是否应被接受、丢弃或对其计数器进行跟踪。由于连接尚未读取,缓冲区也尚未分配,因此这些条件无法使用任何数据内容。此机制可用于以极低开销,快速且有选择性地接受或丢弃来自不同源的连接。若需检查部分内容才能做出决策,则应改用 “tcp-request content” 语句。

“tcp-request connection” 规则按其声明顺序精确评估。若无规则匹配或未定义规则,缺省动作是接受入站连接。可插入的规则数量无特定限制。任何规则均可选择性地跟随一个基于 ACL 的条件,此时仅当该条件求值为真时才进行评估。

条件在动作执行前进行评估,且该动作仅执行一次。因此,即使某个动作改变了作为条件一部分的元素,也不会造成问题。这也意味着多个动作可以依赖同一条件,只要首个改变条件评估结果的动作执行后,其余动作便会自动隐式禁用。例如,当变量为空时,从多个来源为其赋值时即采用此机制。

在 “tcp-request connection” 语法中,首个关键字为规则的动作,可选地后接该动作所需的若干参数。支持的动作及其对应语法详见 第 4.3 节 “动作”(请查找标记为“TCP RqCon”的动作)。

该指令仅在命名的 defaults 段中可用,不可用于匿名段。在关联的代理段之前,将先评估 defaults 段中定义的规则。为避免歧义,在此情况下,同一 defaults 段不可同时被具备前端能力的代理和具备后端能力的代理使用。这意味着,listen 段不可使用定义了此类规则的 defaults 段。

请注意,“if/unless” 条件是可选的。若未在动作中设置条件,则该动作将无条件执行。这在执行 “track-sc*” 动作时同样有用,也可用于将默认动作更改为拒绝。

示例:接受白名单主机的所有连接,拒绝过快的连接(不计入统计),并跟踪已接受的连接。这会导致来自恶意源的连接速率被限制。

    tcp-request connection accept if { src -f /etc/haproxy/whitelist.lst }
    tcp-request connection reject if { src_conn_rate gt 10 }
    tcp-request connection track-sc0 src

示例:接受来自白名单主机的所有连接,统计其他所有连接,并拒绝过快的连接。这会导致滥用行为被阻止,只要其未降低速率。

    tcp-request connection accept if { src -f /etc/haproxy/whitelist.lst }
    tcp-request connection track-sc0 src
    tcp-request connection reject if { sc0_conn_rate gt 10 }

示例:为所有已知代理传入的流量启用 PROXY 协议。

    tcp-request connection expect-proxy layer4 if { src -f proxies.lst }

请参阅 第 7 节 了解 ACL 的使用方法。

另请参见:“tcp-request session”、“tcp-request content”、“stick-table”

tcp-request content <action> [{if | unless} <condition>]

tcp-request content <action> [{if | unless} <condition>]

根据第 4 层至第 7 层的条件,对新会话执行相应动作

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes(!) | yes | yes | yes

参数:

<action>    defines the action to perform if the condition applies. See
            below.

<condition> is a standard layer 4-7 ACL-based condition (see section 7).

在称为“TCP 内容检查”的请求处理早期阶段,可以分析请求内容。在此阶段,每当请求内容更新时,都会评估基于 ACL 的规则,直到匹配到“accept”、“reject”或“switch-mode”规则,或者 TCP 请求检查延迟超时且未匹配任何规则为止。

第一个区别在于,“tcp-request content” 规则可以利用内容来做出决策。大多数情况下,这些决策会涉及协议识别或有效性判断。第二个区别在于,基于内容的规则可在前端和后端中使用。在客户端启用 HTTP 持久连接的情况下,所有 “tcp-request content” 规则都会被重新评估,因此 HAProxy 会记录由 “tcp-request connection” 规则与 “tcp-request content” 规则分配的粘性计数器,且在处理完一个 HTTP 请求后,会清除所有与内容相关的计数器,以便在下一个请求的规则重新评估时再次进行判断。当规则跟踪某些 L7 信息,或基于 L7 ACL 条件时,这一点尤为重要,因为跟踪状态可能在请求之间发生变化。

基于内容的规则按其声明顺序逐一评估。若无规则匹配或未定义规则,缺省动作是接受内容。可插入的规则数量无特定限制。

尽管并非强制要求,但建议在“tcp-request connection”规则中使用 track-sc0,在前端的“tcp-request content”规则中使用 track-sc1,在后端的“tcp-request content”规则中使用 track-sc2。这样做可使配置更具可读性,更易于排查故障,但此仅为指导建议,所有计数器均可在任意位置使用。

在语法中,“tcp-request content” 后的第一个关键字是规则的动作,可选地后接该动作所需的若干参数。支持的动作及其相应语法详见 第 4.3 节 “动作”(请查找标记为“TCP RqCnt”的动作)。

该指令仅在命名的 defaults 段中可用,不可用于匿名段。在关联的代理段之前,将先评估 defaults 段中定义的规则。为避免歧义,在此情况下,同一 defaults 段不可同时被具备前端能力的代理和具备后端能力的代理使用。这意味着,listen 段不可使用定义了此类规则的 defaults 段。

请注意,“if/unless” 条件是可选的。若未在动作中设置条件,则该动作将无条件执行。这在执行 “track-sc*” 动作时同样有用,也可用于将默认动作更改为拒绝。

请注意,建议使用“tcp-request session”规则来跟踪不依赖第 7 层内容的信息,尤其是在 HTTP 前端中。部分 HTTP 处理在会话级别执行,可能导致请求被提前拒绝。在这种情况下,内容级别的跟踪可能会受到影响。启动时会发出警告,以尽可能防止此类不可靠的使用方式。

可以在 TCP 代理中使用“tcp-request content”规则匹配第 7 层内容,因为 HTTP 特定的 ACL 匹配能够在提取所需数据前,预先解析缓冲区中的内容。如果缓冲区内容无法解析为有效的 HTTP 消息,则 ACL 不会匹配。此处涉及的解析器与所有其他 HTTP 处理所用的解析器完全相同,因此不存在解析结果不同的风险。在 HTTP 前端或 HTTP 后端中,可以保证在规则首次评估时,HTTP 内容始终立即可用,因为 HTTP 解析在连接处理的早期阶段、会话级别即已完成。但对于此类代理,使用“http-request”规则更为自然且建议采用。

跟踪 Layer7 信息也是可行的,前提是规则处理时相关信息已存在。规则处理引擎在待跟踪数据尚未可用时,能够等待直到检查延迟到期。

示例:

tcp-request content use-service lua.deny if { src -f /etc/haproxy/blacklist.lst }

示例:

tcp-request content set-var(sess.my_var) src
tcp-request content set-var-fmt(sess.from) %[src]:%[src_port]
tcp-request content unset-var(sess.my_var2)

示例:

# Accept HTTP requests containing a Host header saying "example.com"
# and reject everything else. (Only works for HTTP/1 connections)
acl is_host_com hdr(Host) -i example.com
tcp-request inspect-delay 30s
tcp-request content accept if is_host_com
tcp-request content reject

# Accept HTTP requests containing a Host header saying "example.com"
# and reject everything else. (works for HTTP/1 and HTTP/2 connections)
acl is_host_com hdr(Host) -i example.com
tcp-request inspect-delay 5s
tcp-request content switch-mode http if HTTP
tcp-request content reject   # non-HTTP traffic is implicit here
...
http-request reject unless is_host_com

示例:

# reject SMTP connection if client speaks first
tcp-request inspect-delay 30s
acl content_present req.len gt 0
tcp-request content reject if content_present

# Forward HTTPS connection only if client speaks
tcp-request inspect-delay 30s
acl content_present req.len gt 0
tcp-request content accept if content_present
tcp-request content reject

示例:

# Track the last IP(stick-table type string) from X-Forwarded-For
tcp-request inspect-delay 10s
tcp-request content track-sc0 hdr(x-forwarded-for,-1)
# Or track the last IP(stick-table type ip|ipv6) from X-Forwarded-For
tcp-request content track-sc0 req.hdr_ip(x-forwarded-for,-1)

示例:

# track request counts per "base" (concatenation of Host+URL)
tcp-request inspect-delay 10s
tcp-request content track-sc0 base table req-rate

示例:跟踪每个前端和后端的计数器,当后端检测到滥用行为(并标记 gpc0)时,在前端阻止滥用者。

    frontend http
        # Use General Purpose Counter 0 in SC0 as a global abuse counter
        # protecting all our sites
        stick-table type ip size 1m expire 5m store gpc0
        tcp-request connection track-sc0 src
        tcp-request connection reject if { sc0_get_gpc0 gt 0 }
        ...
        use_backend http_dynamic if { path_end .php }

    backend http_dynamic
        # if a source makes too fast requests to this dynamic site (tracked
        # by SC1), block it globally in the frontend.
        stick-table type ip size 1m expire 5m store http_req_rate(10s)
        acl click_too_fast sc1_http_req_rate gt 10
        acl mark_as_abuser sc0_inc_gpc0(http) gt 0
        tcp-request content track-sc1 src
        tcp-request content reject if click_too_fast mark_as_abuser

请参阅 第 7 节 了解 ACL 的使用方法。

另请参阅:“tcp-request connection”、“tcp-request session”、“tcp-request inspect-delay” 和 “http-request”。

tcp-request inspect-delay <timeout>

tcp-request inspect-delay <timeout>

设置内容检查期间允许等待数据的最大时间

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes(!) | yes | yes | yes

参数:

<timeout> is the timeout value specified in milliseconds by default, but
          can be in any other unit if the number is suffixed by the unit,
          as explained at the top of this document.

主要用 HAProxy 作为 TCP 中继的用户,通常会担心未经分析就将任意类型的协议传递给服务器所带来的风险。为了能够分析请求内容,我们必须首先暂存数据,然后再进行分析。此配置项仅用于指定最多暂存数据的时间。

TCP 内容检查在连接到达前端时即刻生效,随后在连接被转发至后端时再次立即生效。这意味着,若前端和后端均配置了 tcp-request 规则,连接可能会经历一次前端延迟和一次后端延迟。

请注意,执行内容检查时,HAProxy 会针对每个新到达的数据块完整评估所有规则,同时考虑这些数据是不完整的事实。如果在前述延迟时间之前没有规则匹配,则在延迟到期时会进行最后一次检查,此时将视内容为最终确定。若未设置延迟,HAProxy 将不会等待,而是立即根据现有信息作出判定。显然,这种情况通常无实际用途,甚至可能产生竞态条件,因此不建议采用此类配置。

请注意,若发生连接错误或关闭,或请求缓冲区显示为满,则检查延迟将缩短。

一旦规则匹配,请求即被释放,并继续正常处理。如果达到超时且无规则匹配,将采用默认策略,允许请求不受影响地通过。

对于大多数协议,将其设置为几秒即可,因为大多数客户端在建立连接后会立即发送完整请求。为覆盖 TCP 重传情况,可额外增加 3 秒或更多,但无需更多。对于某些协议,使用较大值可能更合理,例如确保客户端在服务器之前从不发送数据(如 SMTP),或等待客户端先发送数据后再将数据传递给服务器(如 SSL)。请注意,客户端超时必须至少覆盖检查延迟,否则将先于检查延迟到期。若客户端关闭连接或缓冲区已满,延迟将立即失效,因为内容已无法再更改。

该指令仅在命名的默认段中可用,不可用于匿名段。代理会从其默认段继承此值。

另请参阅:“tcp-request content accept”、“tcp-request content reject”、“timeout client”。

tcp-request session <action> [{if | unless} <condition>]

tcp-request session <action> [{if | unless} <condition>]

根据第 5 层条件,对已验证的会话执行相应动作

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes(!) | yes | yes | no

参数:

<action>    defines the action to perform if the condition applies. See
            below.

<condition> is a standard layer5-only ACL-based condition (see section 7).

会话验证完成后(即所有握手均已结束),可评估某些条件,以决定该会话是否应被接受、丢弃或对其计数器进行跟踪。这些条件无法使用任何数据内容,因为此时尚未分配缓冲区,且处理在此阶段不能等待。主要用例是将一些早期信息复制到变量中(因为变量在会话中可访问),或跟踪握手后收集的信息,例如 SSL 层级元素(SNI、加密套件、客户端证书的 CN)或 PROXY 协议头中的信息(例如,跟踪通过此方式转发的源地址)。提取的信息可复制到变量中,或使用 “track-sc” 规则进行跟踪。当然,也可在此处决定接受或拒绝,如同其他规则集一样。此处执行的大多数操作也可在 “tcp-request content” 规则中完成,但 HTTP 情况下这些规则会对每个新请求进行评估,这可能并不总是可接受的。例如,规则可能在每次评估时递增计数器。也有可能通过地理位置解析源 IP 地址,将其赋值给会话级变量,然后对所有请求重写源地址为 HTTP 头中的值。若需检查某些内容以作出决策,则必须改用 “tcp-request content” 语句。

“tcp-request session” 规则按其声明顺序精确评估。若无规则匹配或未定义规则,缺省动作是接受入站会话。可插入的规则数量无特定限制。

在 “tcp-request session” 语法中,首个关键字为规则的动作,可选地后接该动作所需的若干参数。支持的动作及其对应语法详见 第 4.3 节 “动作”(请查找标记为“TCP RqSes”的动作)。

该指令仅在命名的 defaults 段中可用,不可用于匿名段。在关联的代理段之前,将先评估 defaults 段中定义的规则。为避免歧义,在此情况下,同一 defaults 段不可同时被具备前端能力的代理和具备后端能力的代理使用。这意味着,listen 段不可使用定义了此类规则的 defaults 段。

请注意,“if/unless” 条件是可选的。若未在动作中设置条件,则该动作将无条件执行。这在执行 “track-sc*” 动作时同样有用,也可用于将默认动作更改为拒绝。

示例:默认跟踪原始源地址,或来自本地代理的连接中 PROXY 协议所通告的地址。第一条连接级别规则启用对这些连接的 PROXY 协议接收,第二条规则跟踪在可选解码后我们决定保留的任意地址。

    tcp-request connection expect-proxy layer4 if { src -f proxies.lst }
    tcp-request session track-sc0 src

示例:接受来自白名单主机的所有会话,拒绝过快的会话而不进行计数,并跟踪已接受的会话。这会导致来自恶意源的会话速率被限制。

    tcp-request session accept if { src -f /etc/haproxy/whitelist.lst }
    tcp-request session reject if { src_sess_rate gt 10 }
    tcp-request session track-sc0 src

示例:接受来自白名单主机的所有会话,统计其他所有会话,并拒绝过快的会话。这会导致滥用行为在未放慢速度前持续被阻止。

    tcp-request session accept if { src -f /etc/haproxy/whitelist.lst }
    tcp-request session track-sc0 src
    tcp-request session reject if { sc0_sess_rate gt 10 }

请参阅 第 7 节 了解 ACL 的使用方法。

另请参阅:“tcp-request connection”、“tcp-request content”、“stick-table”

tcp-response content <action> [{if | unless} <condition>]

tcp-response content <action> [{if | unless} <condition>]

根据第 4 层至第 7 层的条件,对会话响应执行动作

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes(!) | no | yes | yes

参数:

<action>    defines the action to perform if the condition applies. See
            below.

<condition> is a standard layer 4-7 ACL-based condition (see section 7).

响应内容可在响应处理的早期阶段——“TCP 内容检查”阶段进行分析。在此阶段,每当响应内容更新时,都会评估基于 ACL 的规则,直到满足以下任一条件:匹配到最终规则,或设置了 TCP 响应内容检查延迟且该延迟超时而未匹配到任何规则。

通常情况下,这些决策会考虑协议识别或有效性。

基于内容的规则按其声明顺序逐一评估。若无规则匹配或未定义规则,缺省动作是接受内容。可插入的规则数量无特定限制。

在语法中,“tcp-response content”之后的第一个关键字是规则的动作,可选地后接该动作所需的任意数量参数。支持的动作及其相应语法详见 第 4.3 节 “动作”(请查找标记为“TCP RsCnt”的动作)。

该指令仅在命名的 defaults 段中可用,不可用于匿名段。在关联的代理段之前,将先评估 defaults 段中定义的规则。为避免歧义,在此情况下,同一 defaults 段不可同时被具备前端能力的代理和具备后端能力的代理使用。这意味着,listen 段不可使用定义了此类规则的 defaults 段。

请注意,“if/unless” 条件是可选的。若未在动作中设置条件,则该动作将无条件执行。这在将默认动作更改为拒绝时可能很有用。

支持多种类型的动作:

可以使用 “tcp-response content” 规则匹配第 7 层内容,但必须确保已完整缓冲响应内容,否则将无法匹配任何内容。为实现此目的,最佳方案是在检测期间识别 HTTP 协议。

请参阅 第 7 节 了解 ACL 的使用方法。

另请参阅:“tcp-request content”,“tcp-response inspect-delay”

tcp-response inspect-delay <timeout>

tcp-response inspect-delay <timeout>

设置在内容检查期间等待响应的最大允许时间

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes(!) | no | yes | yes

参数:

<timeout> is the timeout value specified in milliseconds by default, but
          can be in any other unit if the number is suffixed by the unit,
          as explained at the top of this document.

该指令仅在命名的默认段中可用,不可用于匿名段。代理会从其默认段继承此值。

另请参见:“tcp-response content”、“tcp-request inspect-delay”。

timeout check <timeout>

timeout check <timeout>

设置额外的检查超时,但仅在连接已成功建立后生效。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<timeout> is the timeout value specified in milliseconds by default, but
          can be in any other unit if the number is suffixed by the unit,
          as explained at the top of this document.

若启用,HAProxy 将使用 min(“timeout connect”, “inter”) 作为检查的连接超时,同时使用 “timeout check” 作为额外的读取超时。使用 “min” 是为了避免那些设置了极长 “timeout connect”(例如因队列或 tarpit 机制而需要如此设置)的用户降低检查速度。(请注意,没有任何合理理由需要设置如此长的连接超时,因为始终可以使用 “timeout queue” 和 “timeout tarpit” 来避免这种情况)。

若未设置“timeout check”,HAProxy 将使用“inter”作为完整检查超时(连接 + 读取)时间,与所有 <1.3.15 版本的行为完全一致。

在大多数情况下,检查请求的处理比普通请求更简单、更快,因此人们可能希望将性能滞后的服务器剔除,故该超时值应小于“timeout server”。

该参数仅适用于后端,但可在“defaults”段中统一指定一次。 实际上,这是避免遗漏的最简便解决方案之一。

另请参阅:“timeout connect”、“timeout queue”、“timeout server”、“timeout tarpit”。

timeout client <timeout>

timeout client <timeout>

设置客户端的最大不活动时间。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:

<timeout> is the timeout value specified in milliseconds by default, but
          can be in any other unit if the number is suffixed by the unit,
          as explained at the top of this document.

空闲超时适用于客户端预期确认或发送数据的场景。在 HTTP 模式下,该超时在以下两个阶段尤为重要:客户端发送请求的初始阶段,以及客户端读取服务器发送数据的响应阶段。尽管如此,在初始阶段,建议将“timeout http-request”设置为更小值,以更好地防范类似 Slowloris 的攻击。默认情况下,该值以毫秒为单位指定,但若在数值后附加单位,也可使用其他单位,具体单位说明请参见本文档顶部。在 TCP 模式(以及在一定程度上的 HTTP 模式)下,强烈建议客户端超时与服务器超时保持一致,以避免复杂且难以排查的情况。建议将超时值设置为略高于 3 秒的整数倍(例如 4 秒或 5 秒),以覆盖一个或多个 TCP 数据包丢失的情况。若存在长生命周期流与短生命周期流混合的情况(例如 WebSocket 与 HTTP 混用),建议考虑使用“timeout tunnel”,该设置将覆盖“timeout client”和“timeout server”对隧道的设定,同时也会覆盖“timeout client-fin”对半关闭连接的设定。

该参数仅适用于前端,但可在“defaults”段中统一指定一次。 这实际上是避免遗漏的最简单方法之一。未指定超时将导致无限超时,这不推荐使用。虽然这种用法被接受且可正常工作,但在启动时会报告警告,因为如果系统未配置超时,可能导致已过期会话在系统中累积。

另请参阅:“timeout server”、“timeout tunnel”、“timeout http-request”。

timeout client-fin <timeout>

timeout client-fin <timeout>

设置半关闭连接在客户端一侧的不活动超时。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:

<timeout> is the timeout value specified in milliseconds by default, but
          can be in any other unit if the number is suffixed by the unit,
          as explained at the top of this document.

当客户端在某一方向连接已关闭的情况下仍需确认或发送数据时,将应用不活跃超时。该超时与“timeout client”不同,仅适用于单向关闭的连接。此设置特别有助于避免在客户端未正常断开时,连接长时间处于 FIN_WAIT 状态。此类问题在长连接(如 RDP 或 WebSocket)中尤为常见。请注意,当连接单向关闭时,该超时可覆盖“timeout tunnel”。在向 HTTP/2 连接发送 GOAWAY 帧后,该超时将应用于空闲连接,通常表明连接应快速结束。

此参数仅适用于前端,但可在“defaults”段中统一指定一次。 默认情况下未设置,因此半关闭连接将使用其他超时设置(timeout.client 或 timeout.tunnel)。

另请参见:“timeout client”、“timeout server-fin” 和 “timeout tunnel”。

timeout client-hs <timeout>

timeout client-hs <timeout>

设置等待客户端 TLS 握手完成的最大时间。该设置对 TCP 和 QUIC 连接均适用。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:

<timeout> is the timeout value specified in milliseconds by default, but
          can be in any other unit if the number is suffixed by the unit,
          as explained at the top of this document.

如果未设置此握手超时,则使用客户端超时作为替代。

timeout connect <timeout>

timeout connect <timeout>

设置连接尝试连接服务器时等待成功的最长时间。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<timeout> is the timeout value specified in milliseconds by default, but
          can be in any other unit if the number is suffixed by the unit,
          as explained at the top of this document.

如果服务器与 HAProxy 位于同一局域网内,连接应立即建立(小于几毫秒)。无论如何,建议通过设置略高于 3 秒倍数的超时值(例如 4 秒或 5 秒),以覆盖一个或多个 TCP 数据包丢失的情况。默认情况下,若未指定,连接超时还会将队列超时和 tarpit 超时设置为相同值。

此参数仅适用于后端,但可在“defaults”段中统一指定一次。 实际上,这是避免遗漏的最简便方法之一。未指定超时将导致无限超时,这不推荐使用。虽然此类用法被接受且可正常工作,但在启动时会报告警告,因为若系统未配置超时,可能导致系统中积聚大量失败会话。

另请参阅:“timeout check”、“timeout queue”、“timeout server”、“timeout tarpit”。

timeout http-keep-alive <timeout>

timeout http-keep-alive <timeout>

设置等待新 HTTP 请求出现的最大允许时间

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:

<timeout> is the timeout value specified in milliseconds by default, but
          can be in any other unit if the number is suffixed by the unit,
          as explained at the top of this document.

默认情况下,持久连接在等待新请求时的超时时间由“timeout http-request”设置。然而,这并不总是方便的,因为部分用户希望设置非常短的持久连接超时时间以更快释放连接,而另一些用户则倾向于设置较长的超时时间,但一旦请求开始处理,仍希望保持较短的超时时间。

本文档中的“http-keep-alive”超时用于满足这些需求。该超时将定义在发送响应后,等待下一个 HTTP 请求开始的最长时间。一旦收到请求的第一个字节,将使用“http-request”超时来等待完整请求的到达。请注意,新请求前的空行不会重置超时,也不会被计为新的请求。

此外,两者之间还存在另一差异:当连接在 http-keep-alive 超时期间到期时,不会返回错误,连接仅被关闭。若连接在等待请求完成期间于 “http-request” 超时到期,则会在关闭连接前向客户端返回 HTTP 408 错误,除非前端中设置了 “option http-ignore-probes”。

在一般情况下,“timeout http-keep-alive” 用于防止客户端在访问大量短连接的网站时,长时间保持空闲连接。可通过在 HTTP/1.1 中将该值设置为几十至几百毫秒来实现。这样,在客户端请求页面后,连接将立即关闭,无需保持连接以等待客户端后续活动。在此场景下,浏览器的下一次活动将导致在 TCP 和/或 SSL 层进行新的握手。一个常见用例是仅向 HTTPS 页面重定向的 HTTP 站点。此类连接不应保持空闲过久,因为它们不会被重用,除非可能用于获取 favicon。

另一种用例恰恰相反:某些网站希望允许客户端长时间复用空闲连接(例如 30 秒至 1 分钟),但不希望为首个请求等待如此长时间,以避免成为一种极为廉价的攻击向量。此时,可将 http-keep-alive 超时设置为较大值,而 http-request 超时保持较低(几秒)。

当设置为极小值时,未启用流水线化的额外请求很可能通过另一条连接进行处理,除非请求确实实现了流水线化,而这一点在 HTTP/1.1 中极为罕见(即不等待响应即连续发送请求)。大多数 HTTP/1.1 实现均采用发送请求、等待响应后再发送下一个请求的方式。对于拥有数十万客户端的站点,此处对 HTTP/1.1 使用较小值可节省内存和套接字资源,但会增加握手计算开销。

处理 HTTP/2 时,对小数值需格外注意。HTTP/2 的特性是将多个请求复用到单一连接上,以减少重新建立 TCP 和/或 SSL 层的开销。该协议还使用控制帧,对早期关闭 TCP 连接的处理效果较差。极少数情况下,这可能导致数据在离开 HAProxy 后于传输途中被截断(此时 HAProxy 甚至无法记录错误)。建议为 HTTP/2 连接设置的最低起始值约为 4 秒。该值可防止大多数现代持久连接实现无谓地保持已失效的连接,同时仍允许后续请求复用连接。然而,应根据实际需求进行调整,此值仅作为参考起点。

如果未设置此参数,则使用“http-request”超时;若两者均未设置,则“timeout client”仍会在较低层级生效。该参数应在前端设置以生效,除非前端处于 TCP 模式,此时将使用 HTTP 后端的超时设置。

另请参阅:“timeout http-request”,“timeout client”。

timeout http-request <timeout>

timeout http-request <timeout>

设置等待完整 HTTP 请求的最大允许时间

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:

<timeout> is the timeout value specified in milliseconds by default, but
          can be in any other unit if the number is suffixed by the unit,
          as explained at the top of this document.

为提供拒绝服务(DoS)防护,可能需要降低接收完整 HTTP 请求的最大允许时间,而不会影响客户端超时设置。此举有助于防范已建立但无任何数据发送的连接。客户端超时无法有效防护此类滥用,因其为非活动超时机制,即攻击者若偶尔发送一个字符,超时将不会触发。而通过 HTTP 请求超时机制,无论客户端输入速度如何,只要请求未能在规定时间内完成,即会被中止。超时触发后,将向客户端发送 HTTP 408 响应以告知问题,并关闭连接。日志中将记录终止码 “cR”。部分较新浏览器对这一标准且有明确文档记录的行为存在兼容性问题,因此可能需要通过 “option http-ignore-probes” 或 “errorfile 408 /dev/null” 隐藏 408 状态码。更多详情请参见 第 8.5 节 中对 “cR” 终止码的说明。

默认情况下,此超时仅适用于请求头部分,而不适用于任何数据。一旦接收到空行,该超时将不再生效。当与“option http-buffer-request”结合使用时,此超时也适用于请求体。在持久连接中,若未设置“timeout http-keep-alive”,该超时将在等待第二个请求时再次使用。

通常将该值设置为几秒即可,因为大多数客户端在建立连接后会立即发送完整请求。增加 3 秒或更多以覆盖 TCP 重传情况,仅此而已。在本地网络且无丢包的情况下,设置为极低值(例如 50 ms)通常可行。此举可防止用户通过 telnet 发送未经封装的 HTTP 请求。

如果未设置此参数,客户端超时仍会在接收请求的每个数据块之间生效。该参数应在前端设置以生效,除非前端处于 TCP 模式,此时将使用 HTTP 后端的超时设置。

另请参阅:“errorfile”、“http-ignore-probes”、“timeout http-keep-alive”和“timeout client”,以及“option http-buffer-request”。

timeout queue <timeout>

timeout queue <timeout>

设置连接槽位空闲前在队列中等待的最大时间

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<timeout> is the timeout value specified in milliseconds by default, but
          can be in any other unit if the number is suffixed by the unit,
          as explained at the top of this document.

当服务器的 maxconn 限制达到时,连接将被置于队列中,该队列可以是服务器特定的,也可以是后端全局的。为避免无限期等待,对队列中等待的请求应用了超时机制。如果超时时间到达,认为该请求几乎不可能被处理,因此将被丢弃,并向客户端返回 503 错误。

“timeout queue” 语句用于设置请求在队列中等待的最大时间。若未指定,则使用后端连接超时(“timeout connect”)的值,以保持与旧版本的向后兼容性(旧版本不支持“timeout queue”参数)。

另请参见:timeout connect。

timeout server <timeout>

timeout server <timeout>

设置服务器端的最大不活动时间。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<timeout> is the timeout value specified in milliseconds by default, but
          can be in any other unit if the number is suffixed by the unit,
          as explained at the top of this document.

空闲超时适用于服务器预期确认或发送数据的场景。在 HTTP 模式下,该超时在服务器响应的第一阶段尤为重要,即服务器必须发送头信息时,因为该值直接反映了服务器处理请求的耗时。为确定合适的取值,通常建议从可接受的最差响应时间开始,随后检查日志以观察响应时间分布情况,并据此调整该值。

默认情况下,该值以毫秒为单位指定,但若在数字后附加单位,也可使用其他单位,具体单位定义见本文档顶部。在 TCP 模式下(在 HTTP 模式下程度稍低),强烈建议客户端超时与服务器超时保持一致,以避免复杂情况带来的调试困难。无论预期的服务器响应时间如何,建议将超时时间设置为略高于 3 秒的倍数(例如最小 4 或 5 秒),以覆盖至少一次或多次 TCP 数据包丢失。若存在长生命周期流与短生命周期流混合的情况(例如 WebSocket 与 HTTP 混合),建议考虑使用“timeout tunnel”,该配置将覆盖“timeout client”和“timeout server”对隧道的设置。

此参数仅适用于后端,但可在“defaults”段中统一指定一次。 这实际上是一种避免遗漏的最简便解决方案。未指定超时将导致无限超时,这不被推荐。虽然此类用法被接受且可正常工作,但在启动时会报告警告,因为如果系统未配置超时,可能导致过期会话在系统中累积。

另请参阅:“timeout client” 和 “timeout tunnel”。

timeout server-fin <timeout>

timeout server-fin <timeout>

设置服务器端半关闭连接的不活动超时时间。

可用于以下上下文:tcp、http、log

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<timeout> is the timeout value specified in milliseconds by default, but
          can be in any other unit if the number is suffixed by the unit,
          as explained at the top of this document.

当服务器在某一方向已关闭的情况下仍需确认或发送数据时,将应用不活动超时。此超时与“timeout server”不同,仅适用于单向关闭的连接。该设置特别有助于避免在远程服务器未正常断开时,使连接在 FIN_WAIT 状态下维持过长时间。此类问题在长连接(如 RDP 或 WebSocket)中尤为常见。请注意,当连接在某一方向关闭时,此超时可覆盖“timeout tunnel”。该设置仅出于完整性考虑提供,在大多数情况下无需使用。

此参数仅适用于后端,但可在“defaults”段中统一指定一次。默认情况下未设置,因此半关闭连接将使用其他超时设置(timeout.server 或 timeout.tunnel)。

另请参阅:“timeout client-fin”、“timeout server”和“timeout tunnel”。

timeout tarpit <timeout>

timeout tarpit <timeout>

设置被限制的连接将维持的时长

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:

<timeout> is the tarpit duration specified in milliseconds by default, but
          can be in any other unit if the number is suffixed by the unit,
          as explained at the top of this document.

当使用 “http-request tarpit” 时,连接将保持打开状态且无任何活动,持续一段时间后关闭。“timeout tarpit” 定义了连接保持打开的时长。

默认情况下,该值以毫秒为单位指定,但若在数字后附加单位,则可使用任意其他单位,具体单位定义见本文档顶部。若未指定,则使用与后端连接超时(“timeout connect”)相同的值,以保持与旧版本的向后兼容性(旧版本无 “timeout tarpit” 参数)。

另请参见:timeout connect。

timeout tunnel <timeout>

timeout tunnel <timeout>

设置隧道在客户端和服务器端的最大不活动时间。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:

<timeout> is the timeout value specified in milliseconds by default, but
          can be in any other unit if the number is suffixed by the unit,
          as explained at the top of this document.

隧道超时

隧道超时适用于客户端与服务器之间建立双向连接,且连接在两个方向上均处于空闲状态的情况。一旦连接成为隧道,该超时将覆盖客户端和服务器的超时设置。在 TCP 中,当任一连接上不再有分析器附加时(例如,已接受 TCP 内容规则),即开始使用此超时。在 HTTP 中,当连接被升级时(例如,切换至 WebSocket 协议,或将 CONNECT 请求转发至代理),或在首次响应后未指定 keepalive/close 选项时,即开始使用此超时。

由于此超时通常与长连接配合使用,因此建议同时设置 “timeout client-fin”,以处理客户端突然从网络中断且未确认关闭,或发送关闭请求后不再确认待处理数据的情况。这种情况可能出现在存在防火墙的丢包网络中,可通过 FIN_WAIT 状态下会话数量大幅增加来检测。

默认情况下,该值以毫秒为单位指定,但若在数字后附加单位,也可使用其他单位,具体单位定义见本文档顶部。无论预期的正常空闲时间为何,建议将超时设置为略高于 3 秒的倍数(例如最小值为 4 秒或 5 秒),以覆盖至少一次或多次 TCP 数据包丢失的情况。

该参数仅适用于后端,但可在“defaults”段中统一指定一次。 实际上,这是避免遗漏的最简便解决方案之一。

示例:

defaults http
    option http-server-close
    timeout connect 5s
    timeout client 30s
    timeout client-fin 30s
    timeout server 30s
    timeout tunnel  1h    # timeout to use with WebSocket and CONNECT

另请参阅:“timeout client”、“timeout client-fin”、“timeout server”。

transparent (deprecated)

transparent (deprecated)

启用客户端透明代理

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | no | yes | yes

参数:无

该关键字的引入旨在为第 3 层负载均衡器提供第 7 层持久性。其原理是利用操作系统将来自远程地址的入站连接重定向至本地进程(此处为 HAProxy),并让该进程知晓最初请求的地址。启用此选项后,未携带 Cookie 的会话将被转发至入站请求的原始目标 IP 地址(该地址应与另一台设备的地址匹配),而携带 Cookie 的请求仍会被转发至相应的服务器。

“transparent” 关键字已弃用,请改用 “option transparent”。

请注意,与普遍认知相反,此选项并不会在建立连接时向服务器呈现客户端的 IP 地址。

另请参见:“option transparent”

unique-id-format <fmt>

unique-id-format <fmt>

为每个请求生成唯一的 ID。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | yes

参数:

<fmt>   is a Custom log format string (see section 8.2.6).

此关键字使用自定义日志格式为每个请求创建 ID。唯一 ID 有助于追踪请求在复杂基础设施多个组件间的流转过程。新创建的 ID 也可通过自定义日志格式字符串中的 %ID 别名进行记录。

格式应由组合后保证唯一的元素构成。 例如,若涉及多个 HAProxy 实例,可能需要包含节点名称。 通常需要记录入站连接的源地址和目标地址及端口。 请注意,由于多个请求可能通过同一连接执行,包含请求计数器有助于区分它们。 类似地,添加时间戳可防止计数器溢出。 记录进程 ID 可避免服务重启后发生冲突。

建议对多个字段使用十六进制表示法,因其可使字段更紧凑,并在日志中节省空间。

对于常规连接,使用前端中配置的格式生成唯一 ID。对于健康检查,当在 tcp-check 或 http-check 规则集中使用 “unique-id” 获取字段时,采用后端的格式。

示例:

unique-id-format %{+X}o\ %ci:%cp_%fi:%fp_%Ts_%rt:%pid

will generate:

       7F000001:8296_7F00001E:1F90_4F7B0A69_0003:790A

另请参见:“unique-id-header”

unique-id-header <name>

unique-id-header <name>

在 HTTP 请求中添加唯一 ID 头。

可以用于以下上下文:http

可出现在以下段中:defaults | frontend | listen | backend yes | yes | yes | no

参数:

<name>   is the name of the header.

在发送至服务器的 HTTP 请求中添加一个 unique-id 头,使用 unique-id-format 格式。若 unique-id-format 不存在,则无法生效。

示例:

    unique-id-format %{+X}o\ %ci:%cp_%fi:%fp_%Ts_%rt:%pid
    unique-id-header X-Unique-ID

    will generate:

       X-Unique-ID: 7F000001:8296_7F00001E:1F90_4F7B0A69_0003:790A

See also: "unique-id-format"

use_backend <backend> [{if | unless} <condition>]

use_backend <backend> [{if | unless} <condition>]

若 ACL 条件匹配,则切换至指定后端;否则不切换。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend 否 | 是 | 是 | 否

参数:

<backend>   is the name of a valid backend or "listen" section, or a
            Custom log format resolving to a backend name (see Custom
            Log Format in section 8.2.6).

<condition> is a condition composed of ACLs, as described in section 7. If
            it is omitted, the rule is unconditionally applied.

在执行内容切换时,连接会先到达前端,然后根据若干条件被分发至不同的后端。条件与后端之间的关联通过 “use_backend” 关键字描述。尽管该关键字通常用于 HTTP 处理,也可用于纯 TCP 场景,既可不依赖内容而使用无状态 ACL(例如源地址验证),也可与 “tcp-request” 规则结合,以等待部分有效载荷。

可以定义任意数量的 “use_backend” 规则。所有规则按声明顺序逐一评估,首个匹配的规则将指定后端。即使该后端被视为不可用,此规则依然生效。然而,若匹配的规则指向一个已禁用或未发布的后端,则该规则将被忽略,规则评估继续进行。

在第一种形式中,若满足条件,则使用该后端。在第二种形式中,若条件不满足,则使用该后端。若无有效条件,将使用以 “default_backend” 定义的默认后端,除非该后端已被禁用或未发布。若无可用地默认后端,则在“listen”段中使用同一段内的服务器,或在前端中不使用任何服务器,并返回 503 服务不可用响应。

请注意,可以从 TCP 前端切换至 HTTP 后端。在此情况下,要么前端已确认协议为 HTTP,后端处理将立即开始,要么后端将等待完整的 HTTP 请求到达。当前端必须在单一端口上解码多种协议(其中一种为 HTTP)时,此功能非常有用。

当 <backend> 为简单名称时,将在配置时解析,若指定的后端不存在,则报告错误。若 <backend> 为自定义日志格式,则配置时可能无法进行检查,因此后端名称将在运行时动态解析。若解析出的后端名称不对应任何有效后端,则不再评估其他规则,而是应用 default_backend 指令。请注意,使用动态后端名称时,强烈建议使用其他后端均不使用的前缀,以确保无法通过请求强制指定未经授权的后端。

值得注意的是,带有显式名称的 “use_backend” 规则用于检测前端与后端之间的关联,以计算后端的 “fullconn” 设置。动态名称无法执行此操作。

另请参阅:“default_backend”、“tcp-request”、“fullconn”、“log-format” 以及关于 ACL 的 第 7 节 。

use-fcgi-app <name>

use-fcgi-app <name>

定义后端所使用的 FastCGI 应用。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend

参数:

<name>    is the name of the FastCGI application to use.

有关 FastCGI 应用设置的详细信息,请参见 第 10.1 节 。

use-server <server> if <condition>

use-server <server> if <condition>
use-server <server> unless <condition>

仅在匹配基于 ACL 的条件时,才使用特定服务器。

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend

参数:

<server>    is the name of a valid server in the same backend section
            or a Custom log format string resolving to a server name
            (see section 8.2.6).

<condition> is a condition composed of ACLs, as described in section 7.

默认情况下,到达后端的连接会根据配置的算法,在可用服务器之间进行负载均衡,除非请求中包含如 cookie 等持久性机制并被识别到。

有时需要将特定请求转发至某个特定服务器,而无需为该服务器声明专用的后端。这可以通过使用“use-server”规则实现。这些规则在“redirect”规则之后、评估 Cookie 之前进行处理,并优先于 Cookie 评估。可以定义任意数量的“use-server”规则。所有规则按声明顺序逐一评估,首个匹配的规则将指定目标服务器。

如果某条规则指定的服务器处于离线状态,且未使用“option persist”选项,也未验证任何“force-persist”规则,则该规则将被忽略,评估将继续执行后续规则,直至匹配到一条为止。

在第一种形式中,若满足条件,则使用该服务器。在第二种形式中,若条件不满足,则使用该服务器。若无任何条件有效,处理将继续,并根据其他持久性机制分配服务器。

请注意,即使匹配了某条规则,仍会执行 cookie 处理,但不会分配服务器。这使得带前缀的 cookie 可以去除其前缀。

“use-server” 语句在 HTTP 和 TCP 模式下均有效。这使其适用于基于内容的检测。例如,在使用具有隐式 TLS 的协议时,可根据 TLS SNI 字段在服务器池中选择服务器(另见 “req.ssl_sni”)。若这些服务器的权重设置为零,则它们将不会用于其他流量。

示例:

# intercept incoming TLS requests based on the SNI field
use-server www if { req.ssl_sni -i www.example.com }
server     www 192.168.0.1:443 weight 0
use-server mail if { req.ssl_sni -i mail.example.com }
server     mail 192.168.0.1:465 weight 0
use-server imap if { req.ssl_sni -i imap.example.com }
server     imap 192.168.0.1:993 weight 0
# all the rest is forwarded to this server
server  default 192.168.0.2:443 check

当 <server> 为简单名称时,会检查其是否存在于配置中的现有服务器列表中,若指定的服务器不存在,则报告错误。若为自定义日志格式,则在解析配置时不会执行检查;若运行时无法解析出有效的服务器名称,但 use-server 规则受 ACL 条件控制且返回 true,则不再应用其他 use-server 规则,并回退至负载均衡。

另请参阅:“use_backend”、第 5 节 中关于服务器的内容,以及第 7 节 中关于 ACL 的内容。

4.3. 动作关键字矩阵

在请求或响应处理的各个阶段,会评估多个规则集,对于这些规则集中发现的每条规则,若满足可选条件,则可执行相应动作。

默认提供了大量动作,可用于修改内容、接受或阻断处理、更改内部状态等。也可在 Lua 中定义新动作(此时其名称将始终以 “lua.” 为前缀)。

尽管历史上某些动作仅限于特定规则集使用,但如今许多动作可在多种规则集中使用。本节列出的内容将标明每种受支持的动作可在哪些规则集中使用,方法是勾选以下规则集对应的简写条目名称:

  • QUIC Ini:该动作适用于“quic-initial”规则
  • TCP RqCon:该动作适用于“tcp-request connection”规则
  • TCP RqSes:该动作适用于“tcp-request session”规则
  • TCP RqCnt:该动作适用于“tcp-request content”规则
  • TCP RsCnt:该动作适用于“tcp-response content”规则
  • HTTP Req:该动作适用于“http-request”规则
  • HTTP Res:该动作适用于“http-response”规则
  • HTTP Aft:该动作适用于“http-after-response”规则

相同的缩写在下文 第 4.4 节 的参考部分中同样使用。

 keyword                QUIC: Ini   TCP: RqCon RqSes RqCnt RsCnt   HTTP: Req Res Aft
----------------------+-----------+-----------+-----+-----+------+----------+---+----
accept                         X           X     X     X     X            -   -   -
add-acl                        -           -     -     -     -            X   X   -
add-header                     -           -     -     -     -            X   X   X
add-headers-bin                -           -     -     -     -            X   X   X
allow                          -           -     -     -     -            X   X   X
attach-srv                     -           -     X     -     -            -   -   -
auth                           -           -     -     -     -            X   -   -
cache-store                    -           -     -     -     -            -   X   -
cache-use                      -           -     -     -     -            X   -   -
capture                        -           -     -     X     -            X   X   X
close                          -           -     -     -     X            -   -   -
del-acl                        -           -     -     -     -            X   X   -
del-header                     -           -     -     -     -            X   X   X
del-headers-bin                -           -     -     -     -            X   X   X
del-map                        -           -     -     -     -            X   X   X
deny                           -           -     -     -     -            X   X   -
dgram-drop                     X           -     -     -     -            -   -   -
disable-l7-retry               -           -     -     -     -            X   -   -
do-log                         X           X     X     X     X            X   X   X
do-resolve                     -           -     -     X     -            X   -   -
early-hint                     -           -     -     -     -            X   -   -
expect-netscaler-cip           -           X     -     -     -            -   -   -
expect-proxy layer4            -           X     -     -     -            -   -   -
normalize-uri                  -           -     -     -     -            X   -   -
pause                          -           -     -     -     -            X   X   -
redirect                       -           -     -     -     -            X   X   -
reject                         X           X     X     X     X            X   -   -
replace-header                 -           -     -     -     -            X   X   X
replace-path                   -           -     -     -     -            X   -   -
replace-pathq                  -           -     -     -     -            X   -   -
replace-uri                    -           -     -     -     -            X   -   -
replace-value                  -           -     -     -     -            X   X   X
return                         -           -     -     -     -            X   X   -
sc-add-gpc                     -           X     X     X     X            X   X   X
--keyword---------------QUIC--Ini---TCP--RqCon-RqSes-RqCnt-RsCnt---HTTP--Req-Res-Aft-sc-inc-gpc                     -           X     X     X     X            X   X   X
sc-inc-gpc0                    -           X     X     X     X            X   X   X
sc-inc-gpc1                    -           X     X     X     X            X   X   X
sc-set-gpt                     -           X     X     X     X            X   X   X
sc-set-gpt0                    -           X     X     X     X            X   X   X
send-retry                     X           -     -     -     -            -   -   -
send-spoe-group                -           -     -     X     X            X   X   -
set-bandwidth-limit            -           -     -     X     X            X   X   -
set-bc-mark                    -           -     -     X     -            X   -   -
set-bc-tos                     -           -     -     X     -            X   -   -
set-dst                        -           X     X     X     -            X   -   -
set-dst-port                   -           X     X     X     -            X   -   -
set-fc-mark                    -           X     X     X     X            X   X   -
set-fc-tos                     -           X     X     X     X            X   X   -
set-header                     -           -     -     -     -            X   X   X
set-headers-bin                -           -     -     -     -            X   X   X
set-log-level                  -           -     -     X     X            X   X   X
set-map                        -           -     -     -     -            X   X   X
set-mark (deprecated)          -           X     X     X     X            X   X   -
set-method                     -           -     -     -     -            X   -   -
set-nice                       -           -     -     X     X            X   X   -
set-path                       -           -     -     -     -            X   -   -
set-pathq                      -           -     -     -     -            X   -   -
set-priority-class             -           -     -     X     -            X   -   -
set-priority-offset            -           -     -     X     -            X   -   -
--keyword---------------QUIC--Ini---TCP--RqCon-RqSes-RqCnt-RsCnt---HTTP--Req-Res-Aft-set-query                      -           -     -     -     -            X   -   -
set-retries                    -           -     -     X     -            X   -   -
set-src                        -           X     X     X     -            X   -   -
set-src-port                   -           X     X     X     -            X   -   -
set-status                     -           -     -     -     -            -   X   X
set-timeout                    -           -     -     -     -            X   X   -
set-tos (deprecated)           -           X     X     X     X            X   X   -
set-uri                        -           -     -     -     -            X   -   -
set-var                        -           X     X     X     X            X   X   X
set-var-fmt                    -           X     X     X     X            X   X   X
silent-drop                    -           X     X     X     X            X   X   -
strict-mode                    -           -     -     -     -            X   X   X
switch-mode                    -           -     -     X     -            -   -   -
tarpit                         -           -     -     -     -            X   -   -
track-sc0                      -           X     X     X     -            X   X   -
track-sc1                      -           X     X     X     -            X   X   -
track-sc2                      -           X     X     X     -            X   X   -
unset-var                      -           X     X     X     X            X   X   X
use-service                    -           -     -     X     -            X   -   -
wait-for-body                  -           -     -     -     -            X   X   -
wait-for-handshake             -           -     -     -     -            X   -   -
--keyword---------------QUIC--Ini---TCP--RqCon-RqSes-RqCnt-RsCnt---HTTP--Req-Res-Aft-

4.4. 按字母顺序排序的动作参考

本节详细描述了每个动作及其用法,采用与上文 第 4.3 节 所述规则集术语标记一致的规范。

accept

accept

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft X | X | X | X | X | - | - | -

此动作停止规则的评估,并允许请求或响应通过检查。该动作为最终动作,即当前段中不再评估同一规则集中的其他规则。此动作与“allow”动作的区别仅在于历史兼容性:在 TCP 和 QUIC 规则中使用“accept”,在 HTTP 规则中使用“allow”。参见下方“allow”动作。

add-acl(<file-name>) <key fmt>

add-acl(<file-name>) <key fmt>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | -

用于向 ACL 添加新条目。ACL 必须从文件加载(即使是一个空的占位文件)。要更新的 ACL 文件名需置于括号内传递。该指令接受一个参数:<key fmt>,其格式需遵循 第 8.2.6 节 中描述的自定义日志格式规则,用于收集新条目的内容。插入前会执行 ACL 查找,以避免重复(或更多)值。其功能等同于统计套接字中的“add acl”命令,但可通过 HTTP 请求触发。

add-header <name> <fmt>

add-header <name> <fmt>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | X

在指定的 <name> 头字段名后追加一个 HTTP 头,其值由 <fmt> 定义,遵循自定义日志格式规则(参见 第 8.2.6 节 )。该规则特别适用于向服务器传递与连接相关的特定信息(例如客户端的 SSL 证书),或合并多个头为一个。该规则非最终规则,因此可以添加其他类似规则。请注意,头添加操作会立即执行,因此一条规则可重用前一条规则生成的头。

add-headers-bin <expr> [ prefix <str> ]

add-headers-bin <expr> [ prefix <str> ]

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | X

这是“add-header”动作的一种变体,其中头名称和值以 varint 编码的二进制字符串形式传递。有关 varint 格式的详情,请参阅 “req.hdrs_bin” 样本提取。当需要一次性设置多个头而无需预先知晓头名称时,此方法非常有用。请注意,这些头未经过 HTTP 解析器验证,可能导致发出无效消息,最严重情况下可能引发请求走私攻击。插入头的数量同样重要,因为其受 tune.http.maxhdr 限制。可选前缀仅对编码字符串中以 <str> 开头的头进行设置。

示例:

# This would reset the Accept/UA/Host headers to their initial values
http-request set-var(txn.oldheaders) req.hdrs_bin
http-request del-header Accept
http-request del-header User-Agent
http-request del-header Host
http-request add-headers-bin var(txn.oldheaders)

allow

allow

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | X

此动作停止规则的评估,并允许请求通过检查。该动作为最终动作,即当前段中不再评估同一规则集中的其他规则。此动作与“accept”动作的区别仅在于历史兼容性:TCP 规则使用“accept”,HTTP 规则使用“allow”。参见上方的“accept”动作。

attach-srv <srv> [name <expr>] [ EXPERIMENTAL ]

attach-srv <srv> [name <expr>] [ EXPERIMENTAL ]

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | X | - | - | - | - | -

在正确建立 HTTP/2 连接后,用于拦截连接。连接将被反转至后端侧,并插入到服务器 <srv> 的空闲连接池中。此功能仅可与地址为 ‘rhttp@’ 的服务器配合使用。

连接将根据 <expr> 求值结果定义的名称插入到服务器空闲连接池中。该名称将用于匹配受 “pool-conn-name” 或 “sni” 参数约束的请求。详情请参见 “http-reuse”。

反向 HTTP 当前仍处于积极开发阶段。配置机制未来可能发生变化。因此,该功能在内部被标记为实验性,这意味着必须在本指令之前单独一行出现 “expose-experimental-directives” 指令。

请注意,一种非常相似但独立的协议正在开发中。详见 https://www.ietf.org/archive/id/draft-bt-httpbis-reverse-http-00.html 。

auth [realm <realm>]

auth [realm <realm>]

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

停止规则的评估,并立即返回 HTTP 401 或 407 错误码,以提示用户提交有效的用户名和密码。后续的“http-request”规则不再评估。支持可选的“realm”参数,用于设置随响应返回的认证域(通常为应用程序名称)。

使用对应代理的错误消息。可通过“errorfile”或“http-error”指令进行自定义。对于 401 响应,所有 WWW-Authenticate 头均被移除,并替换为一个全新的头,其中包含针对领域 “<realm>” 的基本认证挑战。对于 407 响应,同样操作适用于 Proxy-Authenticate 头。若错误消息不得更改,请考虑使用“http-request return”规则替代。

示例:

acl auth_ok http_auth_group(L1) G1
http-request auth unless auth_ok

cache-store <name>

cache-store <name>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | - | X | -

将 HTTP 响应存储至缓存。响应头的存储在此步骤完成,这意味着可在响应存储前或后使用其他 http-response 动作来修改头。此动作负责缓存存储过滤器的设置。

请参阅 第 6.2 节 了解缓存设置。

cache-use <name>

cache-use <name>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

尝试从缓存 <name> 中提供缓存对象。该指令也是存储缓存所必需的,因为它会计算缓存哈希值。若希望对存储和提供均使用相同条件,建议将该条件置于本指令之后。

请参阅 第 6.2 节 了解缓存设置。

capture <sample> [ len <length> | id <id> ]

capture <sample> [ len <length> | id <id> ]

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | - | X | X | X

此规则从请求或响应缓冲区中捕获样本表达式 <sample>,并将其转换为最多 <len> 个字符的字符串。结果字符串将存储到下一个“捕获”槽位(请求或响应)中,因此可能与某些捕获的 HTTP 头并列出现。随后该字符串将自动出现在日志中,并可通过样本提取方法提取,用于填充头或其他用途。由于该长度将在整个流生命周期内为每次捕获分配内存,因此必须加以限制。请注意,该长度仅适用于 “http-request” 规则。请参阅 第 7.3 节 (样本提取)、“捕获请求头” 和 “捕获响应头” 以获取更多信息。

如果使用关键字 “id” 代替 “len”,该动作会尝试将捕获的字符串存储到先前声明的捕获槽中。这在后端中运行捕获时非常有用。捕获槽 ID 可通过先前的指令 “http-request capture” 或使用 “declare capture” 关键字声明。

在后端中使用此动作时,请务必确认相关前端已具备所需的捕获槽位,否则该规则在运行时将被忽略。由于 HAProxy 具备在运行时动态解析后端名称的能力,此问题无法在配置解析阶段被检测到。

close

close

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | X | - | - | -

此动作用于立即关闭与服务器的连接。后续不会再评估任何“tcp-response content”规则。该动作的主要用途是在应用协议预期需先经历较长时间超时后,强制完成客户端与服务器之间的连接交换。其目标是消除某些协议下占用大量服务器资源的空闲连接。

del-acl(<file-name>) <key fmt>

del-acl(<file-name>) <key fmt>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | -

用于从 ACL 中删除条目。ACL 必须从文件加载(即使是一个空的虚拟文件)。要更新的 ACL 文件名需置于括号内传递。该指令接受一个参数:<key fmt>,其遵循 第 8.2.6 节 中定义的自定义日志格式规则,用于收集待删除条目的内容。此操作等效于通过统计套接字执行的 “del acl” 命令,但可通过 HTTP 请求或响应触发。

del-header <name> [ -m <meth> ]

del-header <name> [ -m <meth> ]

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | X

此操作会移除 HTTP 头字段名在 <name> 中指定的所有字段。<meth> 为匹配方法,应用于头名称。支持的匹配方法包括 “str”(精确匹配)、“beg”(前缀匹配)、“end”(后缀匹配)、“sub”(子串匹配)和 “reg”(正则匹配)。若未指定,则使用精确匹配方法。

del-headers-bin <expr> [ -m <meth> ]

del-headers-bin <expr> [ -m <meth> ]

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | X

此操作会移除所有名称在 <expr> 中指定的 HTTP 头。<expr> 必须返回一个以 varint 编码的二进制字符串,其中包含所有应被删除的头名称。编码方式及示例请参见 “add-headers-bin” 和 “set-headers-bin”。<meth> 为匹配方法,应用于所有头名称。支持的匹配方法包括 “str”(精确匹配)、“beg”(前缀匹配)、“end”(后缀匹配)和 “sub”(子串匹配)。由于运行时性能不可预测,不支持 “reg”(正则表达式匹配)。若未指定,默认使用精确匹配方法。

del-map(<map-name>) <key fmt>

del-map(<map-name>) <key fmt>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | X

用于从映射中删除条目。<map-name> 必须遵循 2.7 节所述的格式,关于映射和 ACL 的名称格式。要更新的映射名称需置于括号内。该指令接受一个参数:<key fmt>,其格式需符合第 8.2.6 节 中自定义日志格式规则,用于收集待删除条目的内容。该指令接受一个参数:“文件名”。其功能等同于统计套接字中的“del map”命令,但可通过 HTTP 请求或响应触发。

deny [ { status | deny_status } <code> ] [ content-type <type> ]

deny [ { status | deny_status } <code> ] [ content-type <type> ]
     [ { default-errorfiles | errorfile <file> | errorfiles <name> |
   file `<file>` | lf-file `<file>` | string `<str>` | lf-string `<fmt>` } ]
 [ hdr `<name>` `<fmt>` ]*

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | -

此动作停止规则的评估,并立即拒绝请求或响应。默认情况下,对请求返回 HTTP 403 错误,对响应返回 502 错误,但可通过与“return”动作相同的语法自定义返回的响应。具体细节请参见下方“return”动作说明。为保持兼容性,当未定义参数,或仅定义 “deny_status” 时,隐含参数为 “default-errorfiles”。这意味着 “deny [deny_status <status>]” 是 “deny [status <status>] default-errorfiles” 的别名。该动作为最终动作,即当前段中同一规则集的后续规则不再被评估。有关高级语法,请参见“return”动作。

dgram-drop

dgram-drop

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft X | - | - | - | - | - | - | -

此操作会静默忽略 QUIC 初始数据包的接收,否则该数据包将导致新的 QUIC 连接实例化及其 SSL 握手执行。

disable-l7-retry

disable-l7-retry

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

若请求因非连接失败以外的任何原因而失败,将禁用重试尝试。例如,这可用于确保 POST 请求在失败时不会被重试。

do-log [profile <log_profile>]

do-log [profile <log_profile>]

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft X | X | X | X | X | X | X | X

此动作手动触发代理的日志输出。这意味着将考虑代理上的日志选项(包括“log-format”等格式化选项),但不会干扰代理在事务处理过程中自动产生的日志。

使用 “log-profile” 可以精确描述在每个可用上下文中执行该动作时日志的输出方式。即,在 “on” 关键字后跟随以下值之一:‘quic-init’、’tcp-req-conn’、’tcp-req-sess’、’tcp-req-cont’、’tcp-res-cont’、‘http-req’、‘http-res’、‘http-after-res’。

此外,使用 “%OG” 日志格式别名时,它们将被正确报告。

可选的 “profile” 参数可用于指定日志配置文件段名称,以替代默认应用于当前日志记录器的配置文件段,从而专门为此 do-log 动作指定日志配置文件。

示例:

log-profile my-dft-prof
  on tcp-req-conn format "Connect: %ci"

log-profile my-local-prof
  on tcp-req-conn format "Local Connect: %ci"

frontend myfront
  log stdout format rfc5424 profile my-dft-prof local0
  log-format "log generated using proxy logformat, from '%OG'"
  acl local src 127.0.0.1
  # on connection use either log-profile from the logger (my-dft-prof) or
  # explicit my-local-prof if source ip is localhost
  tcp-request connection do-log if !local
  tcp-request connection do-log profile my-local-prof if local
  # on content use proxy logformat, since no override was specified
  # in my-dft-prof
  tcp-request content do-log

do-resolve(<var>,<resolvers>[,ipv4|ipv6]) <expr>

do-resolve(<var>,<resolvers>[,ipv4|ipv6]) <expr>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | - | X | - | -

该动作对 <expr> 的输出结果执行 DNS 解析,并将结果存储至变量 <var>。解析过程使用 <resolvers> 指向的 DNS 解析器配置段。可选参数 ‘ipv4’ 或 ‘ipv6’ 用于指定解析偏好。另请参阅全局配置项 “dns-accept-family”,以强制限定使用特定地址族。

在执行 DNS 解析时,客户端连接将暂停,直至解析完成。若成功获取 IP 地址,则将其存储至 <var>。若发生任何错误,则 <var> 不会被设置。可使用此动作在运行时根据请求中获取的信息(例如 Host 头)发现服务器 IP 地址。若使用此动作查找服务器 IP 地址(通过 “set-dst” 动作),则后端中的服务器 IP 地址必须设置为 0.0.0.0。do-resolve 动作仅接受主机名参数,字符串中必须移除任何端口号。

示例:

resolvers mydns
  nameserver local 127.0.0.53:53
  nameserver google 8.8.8.8:53
  timeout retry   1s
  hold valid 10s
  hold nx 3s
  hold other 3s
  hold obsolete 0s
  accepted_payload_size 8192

frontend fe
  bind 10.42.0.1:80
  http-request do-resolve(txn.myip,mydns,ipv4) hdr(Host),host_only
  http-request capture var(txn.myip) len 40

  # return 503 when the variable is not set,
  # which mean DNS resolution error
  use_backend b_503 unless { var(txn.myip) -m found }

  default_backend be

backend b_503
  # dummy backend used to return 503.
  # one can use the errorfile directive to send a nice
  # 503 error page to end users

backend be
  # rule to prevent HAProxy from reconnecting to services
  # on the local network (forged DNS name used to scan the network)
  http-request deny if { var(txn.myip) -m ip 127.0.0.0/8 10.0.0.0/8 }
  http-request set-dst var(txn.myip)
  server clear 0.0.0.0:0

请注意:务必设置“保护”规则,以确保 HAProxy 不会被用于扫描网络,或更糟的情况——自身形成循环…

early-hint <name> <fmt>

early-hint <name> <fmt>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

在生成任何其他响应之前,用于构建 HTTP 103 Early Hints 响应。该指令将一个 HTTP 头字段附加到此响应中,头字段名称由 <name> 指定,其值由 <fmt> 定义,遵循自定义日志格式规则(参见 第 8.2.6 节 )。此功能特别适用于向客户端传递 Link 头,以预加载渲染 HTML 文档所需的资源。

有关更多信息,请参阅 RFC 8297。

expect-netscaler-cip layer4

expect-netscaler-cip layer4

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | - | - | - | - | - | -

此配置使面向客户端的连接在从套接字读取任何字节之前接收 NetScaler 客户端 IP 插入协议头。这等效于在 “bind” 行上使用 “accept-netscaler-cip” 关键字,但使用 TCP 规则可仅通过 ACL 对特定 IP 地址范围接受 PROXY 协议。当来自公网主机的流量经过多层负载均衡器时,此方式较为便捷。

expect-proxy layer4

expect-proxy layer4

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | - | - | - | - | - | -

此配置使面向客户端的连接在从套接字读取任何字节之前接收 PROXY 协议头。这等效于在 “bind” 行上使用 “accept-proxy” 关键字,但使用 TCP 规则可仅对特定 IP 地址范围通过 ACL 接受 PROXY 协议。当来自公网主机的流量需经过多层负载均衡器时,该方式尤为方便。

normalize-uri <normalizer>

normalize-uri <normalizer>
normalize-uri fragment-encode
normalize-uri fragment-strip
normalize-uri path-merge-slashes
normalize-uri path-strip-dot
normalize-uri path-strip-dotdot [ full ]
normalize-uri percent-decode-unreserved [ strict ]
normalize-uri percent-to-uppercase [ strict ]
normalize-uri query-sort-by-name

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

对请求的 URI 执行规范化处理。

HAProxy 2.4 中的 URI 正常化功能目前作为实验性技术预览提供。因此,必须先启用全局指令 expose-experimental-directives,才能使用该功能。请注意,正常化器的行为可能会发生变化以修复潜在问题,这可能导致基础设施中请求处理出现异常。

每个归一化器处理一种类型的归一化,以实现对适用于所支持后端的归一化级别进行细粒度选择。

例如,“path-strip-dotdot” 正则化器对于直接将请求的 URI 映射到本地文件系统路径的静态文件服务器可能很有用。然而,它可能会破坏期望路径中包含特定段数的 API 的路由。

请注意,某些规范化器对格式错误的 URI 可能导致不安全的转换。也有可能,即使每个规范化器单独使用时都是安全的,但不当组合后仍可能导致不安全的转换。

例如,“percent-decode-unreserved” 正则化器在处理包含裸露百分号的损坏 URI 时,可能导致意外结果。一个典型的损坏 URI 是 “/%%36%36”,其解码后变为 “/%66”,而该结果等价于 “/f”。通过指定 “strict” 选项,对这类损坏 URI 的请求将被安全地拒绝。

以下可用的规范化器包括:

  • fragment-encode: 将 “#” 编码为 “%23”。

应优先使用“fragment-strip”归一化器,除非已知存在无法正确编码路径组件中“#”符号的异常客户端。

示例:

  • /#foo -> /%23foo

  • fragment-strip:移除 URI 的“片段”组件。

根据 RFC 3986#3.5,URI 的“片段”组件不应被发送,而应由用户代理在获取资源后进行处理。

此规范化器应优先应用,以确保片段不会被解释为请求路径组件的一部分。

示例:

  • /#foo -> /

  • path-strip-dot: 删除 “path” 组件中的 “/./” 段(RFC 3986#6.2.2.3)。

包含百分号编码点号("%2E”)的段落将不会被识别。如需避免此情况,请先使用 “percent-decode-unreserved” 正则化器。

示例:

  • /. -> /

  • /./bar/ -> /bar/

  • /a/./a -> /a/a

  • /.well-known/ -> /.well-known/ (no change)

  • path-strip-dotdot:规范化“path”组件中的“/../”段(RFC 3986#6.2.2.3)。

这会将尝试访问父目录的段与前一个段合并。

空段落不会获得特殊处理。若不希望如此,请先使用“merge-slashes”归一化器。

包含百分号编码点号("%2E”)的段落将不会被识别。如需避免此情况,请先使用 “percent-decode-unreserved” 正则化器。

示例:

  • /foo/../ -> /
  • /foo/../bar/ -> /bar/
  • /foo/bar/../ -> /foo/
  • /../bar/ -> /../bar/
  • /bar/../../ -> /../
  • /foo//../ -> /foo/
  • /foo/%2E%2E/ -> /foo/%2E%2E/

如果指定了 “full” 选项,则开头的 “../” 也会被移除:

示例:

  • /../bar/ -> /bar/

  • /bar/../../ -> /

  • path-merge-slashes:将“path”组件内的相邻斜杠合并为单个斜杠。

示例:

  • // -> /

  • /foo//bar -> /foo/bar

  • percent-decode-unreserved:将未保留的百分号编码字符解码为其对应的普通字符表示(RFC 3986#6.2.2.2)。

未保留字符集包括所有字母、所有数字、“-”、”."、”_" 以及“~”。

示例:

  • /%61dmin -> /admin
  • /foo%3Fbar=baz -> /foo%3Fbar=baz (no change)
  • /%%36%36 -> /%66 (unsafe)
  • /%ZZ -> /%ZZ

如果指定了“strict”选项,则无效的序列将导致返回 HTTP 400 错误请求。

示例:

  • /%%36%36 -> HTTP 400

  • /%ZZ -> HTTP 400

  • percent-to-uppercase:将百分号编码序列中的字母转为大写(RFC 3986#6.2.2.1)。

示例:

  • /%6f -> /%6F
  • /%zz -> /%zz

如果指定了“strict”选项,则无效的序列将导致返回 HTTP 400 错误请求。

示例:

  • /%zz -> HTTP 400

  • query-sort-by-name:按参数名称对查询字符串参数进行排序。参数假定以“&”分隔。名称较短的参数排在名称较长的参数之前,相同参数名称保持其相对顺序。

示例:

  • /?c=3&a=1&b=2 -> /?a=1&b=2&c=3
  • /?aaa=3&a=1&aa=2 -> /?a=1&aa=2&aaa=3
  • /?a=3&b=4&a=1&b=5&a=2 -> /?a=3&a=1&a=2&b=4&b=5

pause { <timeout> | <expr> }

pause { <timeout> | <expr> }

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | -

此操作将暂停指定毫秒数的消息分析。超时可指定为毫秒,或在数字后附加单位符号(如秒、分钟等),具体单位用法请参见本文档顶部说明。也可编写一个表达式,其结果必须为一个数值,interpreted as a timeout in milliseconds。若表达式求值失败,或返回无效值,则该动作被忽略,继续执行后续评估。

此动作可用于调试目的。但也可根据特定条件用于减缓部分客户端的处理速度。例如,可通过“track-sc”规则追踪客户端,当其请求速率过高时,实施限速。

redirect <rule>

redirect <rule>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | -

此动作根据重定向规则执行 HTTP 重定向。其行为与“redirect”语句完全相同,但会插入一条在其他“http-request”或“http-response”规则中间处理的重定向规则,且这些规则使用自定义日志格式。对于响应,仅允许“location”类型的重定向。此外,当在响应过程中执行重定向时,服务器到 HAProxy 的数据传输将被中断,因此无法向客户端转发任何有效载荷。这可能导致部分 HTTP/1 连接被关闭。此动作为最终动作,即当前段中同一规则集的后续规则不再被评估。有关规则语法,请参见“redirect”关键字。

reject

reject

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft X | X | X | X | X | X | - | -

这会停止规则的评估,并立即关闭连接,且不发送任何响应。对于 HTTP 规则,其行为类似于 “tcp-request content reject” 规则。在 HTTP/2 连接上强制立即关闭连接时,此操作可能有用。

在 “tcp-request connection” 规则中,被拒绝的连接甚至不会形成会话,因此在统计信息中被单独计入“被拒绝的连接”。这些连接不会被计入会话速率限制,也不会被记录日志。原因在于,此类规则仅应用于过滤极高连接速率的情况,例如大规模 DDoS 攻击期间所遇到的连接速率。在这些极端条件下,仅记录每个事件这一简单操作就可能导致系统崩溃,并显著降低过滤能力。若确实需要日志记录,则应改用 “tcp-request content” 规则,因为 “tcp-request session” 规则同样不会记录日志。

在“tcp-response content”规则中使用时,服务器连接将被关闭,响应将被中止。通常用于防止敏感信息泄露,通常在结合使用“wait-for-body”动作检查内容后执行。

此动作也可用于 “quic-initial” 规则。新建立的 QUIC 连接将立即关闭,且不执行任何 SSL 握手处理,客户端将通过 CONNECTION_REFUSED 错误码收到通知。

replace-header <name> <match-regex> <replace-fmt>

replace-header <name> <match-regex> <replace-fmt>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | X

匹配所有出现的头字段 <name> 的值与 <match-regex>。匹配过程区分大小写。匹配到的值将被完全替换为 <replace-fmt>。<replace-fmt> 中允许使用格式字符,其作用方式与 “http-request add-header” 中的 <fmt> 参数相同。支持使用反斜杠(\)后接数字的标准反向引用。

此动作作用于整行头,无论其包含多少个值。因此,它非常适合处理值中天然包含逗号的头,例如 If-Modified-Since 或 Set-Cookie。对于包含逗号分隔值列表的头,如 Accept 或 Cache-Control,应使用“replace-value”动作进行处理。另请参见“replace-value”动作。

示例:

http-request replace-header Cookie foo=([^;]*);(.*) foo=\1;ip=%bi;\2

# applied to:
Cookie: foo=foobar; expires=Tue, 14-Jun-2016 01:40:45 GMT;

# outputs:
Cookie: foo=foobar;ip=192.168.1.20; expires=Tue, 14-Jun-2016 01:40:45 GMT;

# assuming the backend IP is 192.168.1.20

http-request replace-header User-Agent curl foo

# applied to:
User-Agent: curl/7.47.0

# outputs:
User-Agent: foo

示例:

http-response replace-header Set-Cookie (C=[^;]*);(.*) \1;ip=%bi;\2

# applied to:
Set-Cookie: C=1; expires=Tue, 14-Jun-2016 01:40:45 GMT

# outputs:
Set-Cookie: C=1;ip=192.168.1.20; expires=Tue, 14-Jun-2016 01:40:45 GMT

# assuming the backend IP is 192.168.1.20.

replace-path <match-regex> <replace-fmt>

replace-path <match-regex> <replace-fmt>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

这与 “replace-header” 的工作方式类似,但其作用对象为请求的路径组件,而非头字段。路径组件从可选的协议+授权信息后的第一个 “/” 开始,到问号前结束。因此,替换操作不会修改协议、授权信息和查询字符串。

请注意,正则表达式在评估时可能比某些 ACL 更耗费资源,因此在极少情况下,可通过添加条件来避免执行评估,以提升性能。

示例:

# prefix /foo: turn /bar?q=1 into /foo/bar?q=1:
http-request replace-path (.*) /foo\1

# strip /foo: turn /foo/bar?q=1 into /bar?q=1
http-request replace-path /foo/(.*) /\1
# or more efficient if only some requests match:
http-request replace-path /foo/(.*) /\1 if { url_beg /foo/ }

replace-pathq <match-regex> <replace-fmt>

replace-pathq <match-regex> <replace-fmt>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

这与“http-request replace-path”效果相同,不同之处在于,若存在查询字符串,则路径中会包含该查询字符串。因此,路径和查询字符串均会被替换。

示例:

# suffix /foo: turn /bar?q=1 into /bar/foo?q=1:
http-request replace-pathq ([^?]*)(\?(.*))? \1/foo\2

replace-uri <match-regex> <replace-fmt>

replace-uri <match-regex> <replace-fmt>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

其功能类似于 “replace-header”,但作用于请求的 URI 部分,而非请求头。URI 部分可能包含可选的方案、授权信息或查询字符串。这些均被视为与匹配值相关的部分。

请注意,正则表达式在评估时可能比某些 ACL 更耗费资源,因此在极少情况下,可通过添加条件来避免执行评估,以提升性能。

请注意:在 HTTP/1.x 中,浏览器发送的绝大多数请求使用“源形式”,其与“绝对形式”的区别在于 URI 部分不包含方案或权威信息。绝大多数仅通过代理发送的请求、手工构造的请求以及某些应用程序生成的请求才会使用绝对形式。因此,在 HTTP/1.x 中,以“/”开头的规则通常可以正常工作。但在 HTTP/2 中,客户端被建议仅发送绝对 URI,这类 URI 的格式与 HTTP/1 客户端与代理通信时使用的格式一致。因此,当某些仅部分替换 URI 的规则在 HTTP/1 中有效时,可能在 HTTP/2 中失效。应将规则调整为可选地匹配方案和权威信息,或改用 replace-path。

示例:

# rewrite all "http" absolute requests to "https":
http-request replace-uri ^http://(.*) https://\1

# prefix /foo: turn /bar?q=1 into /foo/bar?q=1:
http-request replace-uri ([^/:]*://[^/]*)?(.*) \1/foo\2

replace-value <name> <match-regex> <replace-fmt>

replace-value <name> <match-regex> <replace-fmt>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | X

这与 “replace-header” 的行为类似,但会将正则表达式与头字段中每个以逗号分隔的值 <name> 进行匹配,而非整个头字段。此功能适用于允许携带多个值的所有头字段。例如 Accept 请求头,或请求或响应中的 Cache-Control 头。

示例:

http-request replace-value X-Forwarded-For ^192\.168\.(.*)$ 172.16.\1

# applied to:
X-Forwarded-For: 192.168.10.1, 192.168.13.24, 10.0.0.37

# outputs:
X-Forwarded-For: 172.16.10.1, 172.16.13.24, 10.0.0.37

示例:

http-after-response replace-value Cache-control ^public$ private

# applied to:
Cache-Control: max-age=3600, public

# outputs:
Cache-Control: max-age=3600, private

return [ status <code> ] [ content-type <type> ]

return [ status <code> ] [ content-type <type> ]
       [ { default-errorfiles | errorfile <file> | errorfiles <name> |
     file `<file>` | lf-file `<file>` | string `<str>` | lf-string `<fmt>` } ]
   [ hdr `<name>` `<fmt>` ]*

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | -

这会停止规则的评估,并立即返回响应。默认使用的响应状态码为 200。可选地,可通过 “status” 指定状态码。响应的 Content-Type 也可作为 “content-type” 的参数指定。最后,可定义响应内容本身。响应可以是完整的 HTTP 响应,指定要使用的错误文件,也可以是响应负载,指定要使用的文件或字符串。创建响应时遵循以下规则:

  • 若未定义错误文件或要使用的负载内容,则返回一个虚拟响应。仅考虑 “status” 参数。其值可以是范围 [200, 599] 内的任意状态码。若指定 “content-type” 参数,将被忽略。

  • 若设置了 “default-errorfiles” 参数,则使用代理的错误文件。若定义了 “status” 参数,其值必须为 HAProxy 支持的 HTTP 状态码之一(200、400、403、404、405、408、410、413、414、425、429、431、500、501、502、503 或 504)。若存在 “content-type” 参数,将被忽略。

  • 若定义了特定的 errorfile,通过 “errorfile” 参数指定,将返回对应文件中的完整 HTTP 响应。仅考虑 “status” 参数。其值必须为 HAProxy 支持的 HTTP 状态码之一(200、400、403、404、405、408、410、413、414、425、429、431、500、501、502、503 或 504)。若存在 “content-type” 参数,将被忽略。

  • 若定义了 http-errors 段,并包含 “errorfiles” 参数,则返回指定 http-errors 段中对应的文件,该文件包含完整的 HTTP 响应。仅考虑 “status” 参数。其值必须为 HAProxy 支持的状态码之一(200、400、403、404、405、408、410、413、414、425、429、431、500、501、502、503 或 504)。若存在 “content-type” 参数,将被忽略。

  • 若指定 “file” 或 “lf-file” 参数,则文件内容将用作响应负载。若文件非空,其内容类型必须作为 “content-type” 参数指定;否则,任何 “content-type” 参数均被忽略。使用 “lf-file” 参数时,文件内容将按自定义日志格式解析(参见 第 8.2.6 节 )。使用 “file” 参数时,内容被视为原始数据。

  • 若指定 “string” 或 “lf-string” 参数,则使用定义的字符串作为响应负载。必须始终将 content-type 作为 “content-type” 的参数进行设置。使用 “lf-string” 参数时,字符串将按自定义日志格式进行解析(参见 第 8.2.6 节 )。使用 “string” 参数时,视为原始字符串。

当响应不基于 errorfile 时,可以使用 “hdr” 参数向响应中附加 HTTP 头字段。否则,所有 “hdr” 参数均被忽略。每个参数的头名称由 <name> 指定,其值由 <fmt> 定义,该值需遵循 第 8.2.6 节 中描述的自定义日志格式规则。

请注意,生成的响应必须小于缓冲区大小。为避免任何警告,当加载 errorfile 或原始文件时,用于头重写预留的缓冲区空间也必须为空。

此动作为最终动作,即当前段中不再评估同一规则集中的其他规则。

示例:

http-request return errorfile /etc/haproxy/errorfiles/200.http \
    if { path /ping }

http-request return content-type image/x-icon file /var/www/favicon.ico  \
    if { path /favicon.ico }

http-request return status 403 content-type text/plain    \
    lf-string "Access denied. IP %[src] is blacklisted."  \
    if { src -f /etc/haproxy/blacklist.lst }

sc-add-gpc(<idx>,<sc-id>) { <int> | <expr> }

sc-add-gpc(<idx>,<sc-id>) { <int> | <expr> }

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | X | X | X | X

此动作将与 <sc-id> 指定的粘性计数器关联的数组中索引 <idx> 处的通用计数器(GPC)值,增加 <int> 的整数值或表达式 <expr> 的整数计算结果。整数和表达式均限于无符号 32 位值。若发生错误,此动作静默失败,后续动作的评估继续进行。<idx> 为 0 至 99 之间的整数,<sc-id> 为 0 至 2 之间的整数。若该索引处未存储 GPC 值,此动作也静默失败。即使值为零,表中的条目也会被刷新。‘gpc_rate’ 会自动调整以反映 GPC 值的平均增长速率。

此动作仅适用于 ‘gpc’ 和 ‘gpc_rate’ 数组数据类型(不适用于旧版的 ‘gpc0’、‘gpc1’、‘gpc0_rate’ 及 ‘gpc1_rate’ 数据类型)。旧版数据类型无对应函数,但如果值始终为 1,请参阅 ‘sc-inc-gpc()’、‘sc-inc-gpc0()’ 和 ‘sc-inc-gpc1()’。无法执行减操作,但可使用 ‘sc-set-gpt()’ 在通用标签中存储精确值。

此动作的主要用途是统计评分或总量(例如,服务器或 WAF 报告的每个源 IP 的估算风险等级、上传的总字节数等)。

sc-inc-gpc(<idx>,<sc-id>)

sc-inc-gpc(<idx>,<sc-id>)

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | X | X | X | X

此动作会将与 <sc-id> 指定的粘性计数器关联的数组中索引 <idx> 处的通用计数器(GPC)值加一。若发生错误,此动作静默失败,动作评估继续进行。<idx> 为 0 至 99 之间的整数,<sc-id> 为 0 至 2 之间的整数。若该索引处未存储 GPC,则此动作同样静默失败。此动作仅适用于 ‘gpc’ 和 ‘gpc_rate’ 数据类型(不适用于旧版 ‘gpc0’、‘gpc1’、‘gpc0_rate’ 及 ‘gpc1_rate’ 数据类型)。

sc-inc-gpc0(<sc-id>)

sc-inc-gpc0(<sc-id>)
sc-inc-gpc1(<sc-id>)

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | X | X | X | X

此动作根据 <sc-id> 指定的粘性计数器,递增 GPC0 或 GPC1 计数器。若发生错误,此动作静默失败,动作的评估将继续进行。

sc-set-gpt(<idx>,<sc-id>) { <int> | <expr> }

sc-set-gpt(<idx>,<sc-id>) { <int> | <expr> }

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | X | X | X | X

此动作将位于与 <sc-id> 指定的粘性计数器关联的数组中索引 <idx> 处的 32 位无符号 GPT 设置为 <int>/<expr> 的值。预期结果为布尔值。

若发生错误,该动作将静默失败,动作评估将继续进行。<idx> 为 0 至 99 之间的整数,<sc-id> 为 0 至 2 之间的整数。若该索引处未存储 GPT,同样会静默失败。

此动作仅适用于 ‘gpt’ 数组数据类型(不适用于旧版 ‘gpt0’ 数据类型)。

sc-set-gpt0(<sc-id>) { <int> | <expr> }

sc-set-gpt0(<sc-id>) { <int> | <expr> }

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | X | X | X | X

此动作根据由 <sc-id> 指定的粘性计数器以及 <int>/<expr> 的值,设置 32 位无符号 GPT0 标签。预期结果为布尔值。若发生错误,此动作将静默失败,动作的评估将继续进行。此动作是 “sc-set-gpt(0,<sc-id>)” 的别名。另请参阅 “sc-set-gpt” 动作。

send-retry

send-retry

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft X | - | - | - | - | - | - | -

此动作强制在收到客户端 Initial 数据包(无令牌)时发送重试(Retry)响应。此举有助于确保在实例化任何连接元素并开始握手前,客户端地址已通过验证。

send-spoe-group <engine-name> <group-name>

send-spoe-group <engine-name> <group-name>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | X | X | X | -

此动作用于触发发送一组 SPOE 消息。为此,必须定义用于发送消息的 SPOE 引擎以及要发送的 SPOE 组。当然,SPOE 引擎必须指向一个已存在的 SPOE 过滤器。若在 SPOE 过滤器行中未提供引擎名称,则必须使用 SPOE 代理名称。

参数:

<engine-name>  The SPOE engine name.

<group-name>   The SPOE group name as specified in the engine
               configuration.

set-bandwidth-limit <name> [limit {<expr> | <size>}] [period {<expr> | <time>}]

set-bandwidth-limit <name> [limit {<expr> | <size>}] [period {<expr> | <time>}]

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | X | X | X | -

本动作用于启用带宽限制过滤器 <name>,具体在上传或下载方向上生效,取决于过滤器类型。仅当 <name> 指向每流带宽限制过滤器时,方可自定义限制值和周期。执行 set-bandwidth-limit 规则时,会先将过滤器的所有设置重置为默认值,然后再启用该过滤器。因此,若对同一过滤器执行多个 “set-bandwidth-limit” 动作,仅最后一个生效。同一流上可启用多个带宽限制过滤器。

请注意,此动作不能在 defaults 段中使用,因为带宽限制过滤器无法在 defaults 段中定义。此外,仅限制 HTTP 负载传输,HTTP 头不计入限制。

参数:

<expr>  Is a standard HAProxy expression formed by a sample-fetch followed
        by some converters. The result is converted to an integer. It is
        interpreted as a size in bytes for the "limit" parameter and as a
        duration in milliseconds for the "period" parameter.

<size>  Is a number. It follows the HAProxy size format and is expressed in
        bytes.

<time>  Is a number. It follows the HAProxy time format and is expressed in
        milliseconds.

示例:

http-request set-bandwidth-limit global-limit
http-request set-bandwidth-limit my-limit limit 1m period 10s

请参阅 第 9.7 节 了解带宽限制过滤器的配置方法。

set-bc-mark { <mark> | <expr> }

set-bc-mark { <mark> | <expr> }

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | - | X | - | -

用于在支持该功能的平台上,将 Netfilter/IPFW MARK 设置为后端连接(发送至服务器的所有数据包)的值 <mark> 或 <expr>。该值为无符号 32 位整数,可通过 Netfilter/IPFW 匹配,也可通过路由表匹配或使用 DTrace 监控数据包。<mark> 可以采用十进制或十六进制格式表示(以 “0x” 为前缀)。或者,也可使用 <expr>:其为标准 HAProxy 表达式,由一个样本提取操作后接若干转换器组成,必须解析为整数类型。该动作可用于强制特定数据包走不同路径(例如,为大批量下载选择成本更低的网络路径)。此功能在 Linux 内核 2.6.32 及以上版本中可用,需具备管理员权限,同时在 FreeBSD 和 OpenBSD 上也支持。标记将在后端/服务器连接的整个持续时间内生效(从连接建立到关闭)。

set-bc-tos { <tos> | <expr> }

set-bc-tos { <tos> | <expr> }

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | - | X | - | -

用于设置后端连接(发送至服务器的所有数据包)的 TOS 或 DSCP 字段值为 <tos> 或 <expr> 所指定的值,仅在支持该功能的平台上生效。该值表示 IP TOS 字段的全部 8 位。请注意,DSCP 或 TOS 仅使用其中的高 6 位,低 2 位始终为 0。或者,也可使用 <expr>:其为标准 HAProxy 表达式,由一个样本提取操作后接若干转换器构成,必须解析为整数类型。该动作可用于根据请求中的某些信息调整内部路由器的路由行为。TOS 将在后端/服务器连接的整个持续时间内生效(从连接建立到关闭)。

有关更多信息,请参见 RFC 2474、2597、3260 和 4594。

set-dst <expr>

set-dst <expr>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | - | X | - | -

用于将目标 IP 地址设置为指定表达式的值。当 HAProxy 前置代理重写了目标 IP,但通过 HTTP 头提供了正确的 IP 时,此功能非常有用;或当需要出于隐私考虑隐藏 IP 地址时。若要连接到新的地址/端口,请在后端中将服务器地址设为 0.0.0.0:0。

参数:

<expr>  Is a standard HAProxy expression formed by a sample-fetch followed
        by some converters.

示例:

http-request set-dst hdr(x-dst)
http-request set-dst dst,ipmask(24)

在可能的情况下,set-dst 会保留原始目标端口,只要地址族允许;否则,目标端口将被设为 0。

set-dst-port <expr>

set-dst-port <expr>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | - | X | - | -

用于将目标端口地址设置为指定表达式的值。若要连接到新的地址/端口,请在后端中将服务器地址设为 ‘0.0.0.0:0’。

参数:

<expr>  Is a standard HAProxy expression formed by a sample-fetch
        followed by some converters.

示例:

http-request set-dst-port hdr(x-port)
http-request set-dst-port int(4000)

在可能的情况下,set-dst-port 会保留原始目标地址,只要地址族支持端口;否则,它会在重写端口前将目标地址强制转换为 IPv4 “0.0.0.0”。

set-fc-mark { <mark> | <expr> }

set-fc-mark { <mark> | <expr> }

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | X | X | X | -

用于在支持该功能的平台上,将发送至客户端的所有数据包的 Netfilter/IPFW MARK 设置为传入的值 <mark> 或 <expr>。该值为无符号 32 位整数,可被 netfilter/ipfw 匹配,也可通过路由表进行匹配,或通过 DTrace 监控数据包。<mark> 可以采用十进制或十六进制格式表示(以 “0x” 为前缀)。或者,也可使用 <expr>:其为标准 HAProxy 表达式,由一个样本提取操作后接若干转换器组成,且必须解析为整数类型。该动作可用于强制特定数据包走不同的路由(例如,为大批量下载选择成本更低的网络路径)。此功能在 Linux 内核 2.6.32 及以上版本中可用,需管理员权限;在 FreeBSD 和 OpenBSD 上同样适用。

set-fc-tos { <tos | <expr> }

set-fc-tos { <tos | <expr> }

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | X | X | X | -

用于将发送至客户端的数据包的 TOS 或 DSCP 字段值设置为传入的 <tos> 或 <expr> 值,适用于支持该功能的平台。该值表示 IP TOS 字段的全部 8 位。请注意,DSCP 或 TOS 仅使用其中的 6 个高位,而两个低位始终为 0。或者,也可使用 <expr>:它是一个标准的 HAProxy 表达式,由一个 sample-fetch 后接若干转换器组成,且必须解析为整数类型。该动作可用于根据请求中的某些信息调整边界路由器的路由行为。

有关更多信息,请参见 RFC 2474、2597、3260 和 4594。

set-header <name> <fmt>

set-header <name> <fmt>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | X

此动作与“add-header”动作功能相同,不同之处在于,若该头已存在,则会先将其移除。 当向服务器传递安全信息时,该头必须不受外部用户篡改,或用于强制设置某些响应头(如“Server”),以隐藏外部信息,此时此动作尤为有用。请注意,新值在移除操作前已计算完成,因此可将新值与现有头合并。

示例:

http-request set-header X-Haproxy-Current-Date %T
http-request set-header X-SSL                  %[ssl_fc]
http-request set-header X-SSL-Session_ID       %[ssl_fc_session_id,hex]
http-request set-header X-SSL-Client-Verify    %[ssl_c_verify]
http-request set-header X-SSL-Client-DN        %{+Q}[ssl_c_s_dn]
http-request set-header X-SSL-Client-CN        %{+Q}[ssl_c_s_dn(cn)]
http-request set-header X-SSL-Issuer           %{+Q}[ssl_c_i_dn]
http-request set-header X-SSL-Client-NotBefore %{+Q}[ssl_c_notbefore]
http-request set-header X-SSL-Client-NotAfter  %{+Q}[ssl_c_notafter]

set-headers-bin <expr> [ prefix <str> ]

set-headers-bin <expr> [ prefix <str> ]

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | X

这是“set-header”动作的一种变体,其中头名称和值以 varint 编码的二进制字符串形式传递。请参阅 “req.hdrs_bin” 样本提取关于 varint 格式的说明。当需要一次性设置多个头而无需预先知晓头名称时,此方法非常有用。请注意,这些头未经过 HTTP 解析器验证,可能导致发出无效消息,最严重情况下可能引发请求走私攻击。插入头的数量同样重要,因为其受 tune.http.maxhdr 限制。可选前缀仅会设置编码字符串中以 <str> 开头的头。

示例:

# This would reset the Accept/UA/Host headers to their initial values
http-request set-var(txn.oldheaders) req.hdrs_bin
http-request del-header Accept
http-request del-header User-Agent
http-request del-header Host
http-request set-headers-bin var(txn.oldheaders)

set-log-level <level>

set-log-level <level>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | X | X | X | X

当满足特定条件时,用于更改当前请求的日志级别。有效级别包括 8 个 syslog 级别(参见“log”关键字),以及特殊级别“silent”,该级别将禁用此请求的日志记录。该规则非最终规则,因此最后一个匹配的规则生效。此规则可用于禁用来自其他设备的健康检查。

set-map(<map-name>) <key fmt> <value fmt>

set-map(<map-name>) <key fmt> <value fmt>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | X

用于向映射中添加新条目。<map-name> 必须遵循 2.7 段中描述的名称格式,关于映射和 ACL 的名称格式。要更新的 MAP 名称置于括号之间。该指令接受两个参数:<key fmt>,其格式遵循自定义日志格式规则,如第 8.2.6 节 所述,用于收集映射键;以及 <value fmt>,同样遵循自定义日志格式规则,用于收集新条目的内容。插入前会先执行映射查找,以避免重复(或更多)值。此操作等效于通过统计信息套接字执行的“set map”命令,但可通过 HTTP 请求触发。

set-mark <mark> (deprecated)

set-mark <mark> (deprecated)

这是 “set-fc-mark” 的别名(应改用后者)。

set-method <fmt>

set-method <fmt>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

使用格式字符串 <fmt> 的求值结果重写请求方法。除非有极少数合理原因,否则不应执行此操作,因为这更可能造成破坏而非修复问题。

set-nice <nice>

set-nice <nice>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | X | X | X | -

设置当前正在处理的请求/响应的“nice”优先级。该设置仅对同时处理的其他请求产生影响。默认值为 0,除非通过 “bind” 行上的 “nice” 设置进行了修改。允许的取值范围为 -1024..1024.。数值越高,请求越“友好”(优先级越低);数值越低,请求相对于其他请求的优先级越高。该设置可用于提升某些请求的处理速度,或降低非重要请求的优先级。未经事先试验直接使用此设置,可能导致显著的性能下降。

set-path <fmt>

set-path <fmt>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

This rewrites the request path with the result of the evaluation of format
string `<fmt>`. The query string, if any, is left intact. If a scheme and
authority is found before the path, they are left intact as well. If the
request doesn't have a path ("*"), this one is replaced with the format.
This can be used to prepend a directory component in front of a path for
example. See also "http-request set-query" and "http-request set-uri".

示例:

# prepend the host name before the path
http-request set-path /%[hdr(host)]%[path]

set-pathq <fmt>

set-pathq <fmt>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

这与“http-request set-path”效果相同,不同之处在于查询字符串也会被重写。可以使用此指令移除查询字符串,包括问号(使用“http-request set-query”无法实现)。

set-priority-class <expr>

set-priority-class <expr>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | - | X | - | -

用于设置当前请求的队列优先级类别。该值必须为一个样本表达式,其结果需为 -2047..2047. 范围内的整数。超出此范围的结果将被截断。优先级类别决定队列中请求的处理顺序,数值越低优先级越高。

set-priority-offset <expr>

set-priority-offset <expr>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | - | X | - | -

用于设置当前请求的队列优先级时间戳偏移量。该值必须为一个样本表达式,其结果需为介于 -524287..524287. 范围内的整数。超出此范围的结果将被截断。当请求进入队列时,其排序顺序首先按优先级类别,其次按当前时间戳减去指定偏移量(单位为毫秒)后的值确定。数值越小,优先级越高。请注意,所记录的时间戳仅具备足够精度以区分 524,287ms(8m44s287ms)内的差异。若请求在队列中等待时间过长,导致调整后的时间戳超过该值,将被错误识别为最高优先级。因此,务必设置 “timeout queue” 为一个合适的值,确保其与偏移量之和不超过此限制。

set-query <fmt>

set-query <fmt>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

此操作将请求的查询字符串(位于首个问号“?”之后的部分)替换为格式字符串 <fmt> 的求值结果。问号之前的部分保持不变。若请求中未包含问号且新值非空,则在 URI 末尾添加问号,后接新值。若原请求中已存在问号,则即使新值为空,问号也不会被移除。此功能可用于向查询字符串中添加或移除参数。

另请参见 “http-request set-query” 和 “http-request set-uri”。

示例:

# replace "%3D" with "=" in the query string
http-request set-query %[query,regsub(%3D,=,g)]

set-retries <int> | <epxr>

set-retries <int> | <epxr>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | - | X | - | -

此动作仅覆盖当前流指定的“retries”值。其值可以是整数,范围为 [0, 100],也可以是返回整数且范围在 [0, 100] 内的表达式。

请注意,此动作仅在后端侧有效,因此该规则仅适用于具备后端能力的代理。在“defaults”段中不允许使用此规则。当该动作用于监听器时,其评估上下文为前端。因此,仅当流未通过 use-backend 规则等路由至其他后端时,重试次数才会被保留。否则,将采用所选后端的默认重试次数。

示例:

tcp-request content set-retries 3
http-request set-retries var(txn.retries)

set-src <expr>

set-src <expr>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | - | X | - | -

用于将源 IP 地址设置为指定表达式的值。当 HAProxy 前方的代理重写了源 IP,但通过 HTTP 头提供了正确的 IP 时,此功能非常有用;或当你希望出于隐私保护目的隐藏源 IP 时。后续所有对 “src” 获取操作均返回该值(参见示例)。

参数:

<expr>  Is a standard HAProxy expression formed by a sample-fetch followed
        by some converters.

另请参见“option forwardfor”。

示例:

http-request set-src hdr(x-forwarded-for)
http-request set-src src,ipmask(24)

# After the masking this will track connections
# based on the IP address with the last byte zeroed out.
http-request track-sc0 src

在可能的情况下,set-src 会保留原始源端口,只要地址族允许;否则,源端口将被设为 0。

set-src-port <expr>

set-src-port <expr>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | - | X | - | -

用于将源端口地址设置为指定表达式的值。

参数:

<expr>  Is a standard HAProxy expression formed by a sample-fetch followed
        by some converters.

示例:

http-request set-src-port hdr(x-port)
http-request set-src-port int(4000)

当可能时,set-src-port 会保留原始源地址,前提是地址族支持端口;否则,它会在重写端口前将源地址强制转换为 IPv4 “0.0.0.0”。

set-status <status> [reason <str>]

set-status <status> [reason <str>]

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | - | X | X

将响应状态码替换为 <status>,该值必须为 100 至 999 之间的整数。 可选地,可提供由 <str> 定义的自定义原因文本,或使用指定代码的默认原因作为回退。请注意,原因字符串仅存在于 HTTP/1.x 中,其他协议版本将忽略它。

示例:

# return "431 Request Header Fields Too Large"
http-response set-status 431
# return "503 Slow Down", custom reason
http-response set-status 503 reason "Slow Down".

set-timeout { client | connect | queue | server | tarpit | tunnel } { <timeout> | <expr> }

set-timeout { client | connect | queue | server | tarpit | tunnel } { <timeout> | <expr> }

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | -

此动作仅覆盖当前流的指定“client”、“connect”、“queue”、“server”、“tarpit”或“tunnel”超时。更改某一超时不会影响其他任何超时,即使它们在配置解析过程中相互继承(参见最后一个示例)。超时可指定为毫秒,或在数字后附加单位(如“s”、“m”等),具体单位用法请参见本文档顶部说明。也可编写表达式,其结果必须为一个以毫秒为单位的数值。

请注意,connect、queue、server 和 tunnel 超时仅在后端侧有效,因此该规则仅适用于具备后端能力的代理。同理,client 超时仅在前端侧有效。tarpit 超时对两侧均可用。超时值必须非空,才能获得预期结果。当动作用于监听器时,其在前端上下文中进行评估。因此,仅当流未通过 use-backend 规则等路由至其他后端时,自定义的后端侧超时值才会被保留。否则,将采用所选后端的默认值。

示例:

http-request set-timeout tunnel 5s
http-request set-timeout server req.hdr(host),map_int(host.lst)

示例:

http-response set-timeout tunnel 5s
http-response set-timeout server res.hdr(X-Refresh-Seconds),mul(1000)

示例:

defaults
  # This will set both tarpit and queue timeout to 5s as they are not
  # defined
  timeout connect 5s
  timeout client 30s
  timeout server 30s

listen foo
  # This will only change the connect timeout to 10s without affecting
  # queue or tarpit timeouts
  http-request set-timeout connect 10s

set-tos <tos> (deprecated)

set-tos <tos> (deprecated)

这是 “set-fc-tos” 的别名(应改用后者)。

set-uri <fmt>

set-uri <fmt>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

此操作使用格式字符串 <fmt> 的计算结果重写请求 URI。协议、授权信息、路径和查询字符串将同时被替换。可用于重写代理前端的主机名,或对 URI 执行复杂修改,例如在路径与查询字符串之间移动部分内容。若设置绝对 URI,将原样发送至 HTTP/1.1 服务器。若非期望行为,应分别设置主机、路径和/或查询字符串。参见“http-request set-path”和“http-request set-query”。

set-var(<var-name>[,<cond>...]) <expr>

set-var(<var-name>[,<cond>...]) <expr>
set-var-fmt(<var-name>[,<cond>...]) <fmt>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | X | X | X | X

用于设置变量的内容。变量在行内声明。

参数:

<var-name>   The name of the variable. Variable of the parent stream cannot
             be set. See section 2.8 about variables for details.

 <cond>      A set of conditions that must all be true for the variable to
             actually be set (such as "ifnotempty", "ifgt" ...). See the
             set-var converter's description for a full list of possible
             conditions.

 <expr>      Is a standard HAProxy expression formed by a sample-fetch
             followed by some converters.

 <fmt>       This is the value expressed using Custom log format rules (see
             Custom log format in section 8.2.6).

所有作用域均可用于 HTTP 规则,但规则集若无法访问内容(如 “tcp-request connection” 和 “tcp-request session”),则仅可使用作用域 “proc” 和 “sess”。

示例:

http-request set-var(req.my_var) req.fhdr(user-agent),lower
http-request set-var-fmt(txn.from) %[src]:%[src_port]

silent-drop [ rst-ttl <ttl> ]

silent-drop [ rst-ttl <ttl> ]

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | X | X | X | -

这会停止规则的评估,并通过依赖系统的手段突然使面向客户端的连接消失,以尽量避免通知客户端。调用时若未指定 rst-ttl 参数,将尝试使用 TCP_REPAIR 防止向客户端发送任何 FIN 或 RST 数据包。若失败(主要由于权限不足),则退回到发送 TTL 为 1 的 RST 数据包。

客户端仍会看到已建立的连接,而 HAProxy 上并无实际连接,从而节省资源。然而,位于 HAProxy 与客户端之间的有状态设备(如防火墙、代理、负载均衡器)也会在其会话表中保持该连接。

可选的 rst-ttl 可更改此行为:TCP_REPAIR 不再使用,而是发送一个 TTL 可配置的 RST 数据包。当设置为合理值时,该 RST 数据包会穿过本地基础设施,清除防火墙及其他系统中的连接,但在到达客户端前消失。此后客户端发出的后续数据包将被前端设备直接丢弃。此类本地 RST 保护本地资源,但不保护客户端。除非完全理解其后果,否则不得使用。

strict-mode { on | off }

strict-mode { on | off }

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | X

启用或禁用后续规则的严格重写模式。该设置不影响其之前的规则,且仅适用于对请求执行重写的规则。启用严格模式后,任何重写失败都会触发内部错误;否则,此类错误将被静默忽略。严格重写模式的目的是使部分重写可选,而其他重写则必须执行以继续请求处理。

默认情况下,严格重写模式已启用。当规则集评估结束时,其值也会被重置。例如,如果在前端更改了该模式,HAProxy 开始评估后端规则时将恢复默认模式。

switch-mode http [ proto <name> ]

switch-mode http [ proto <name> ]

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | - | - | - | -

用于执行连接升级的动作。目前仅支持 HTTP 升级。协议可选指定。该动作仅适用于具备前端能力的代理。连接升级会立即执行,后续不会评估“tcp-request content”规则。建议优先使用此方法,而非依赖后端模式的隐式升级方式。使用该方法时,可在前端中设置 HTTP 指令而无需警告。若执行了 HTTP 升级,这些指令将有条件地被评估。但必须仍选择一个 HTTP 后端。目前仍不支持将 HTTP 连接(无论是否已升级)路由至 TCP 服务器。

有关 HTTP 升级的更多详情,请参见 第 4 节 中的代理相关内容。

tarpit [ { status | deny_status } <code>] [content-type <type>]

tarpit [ { status | deny_status } <code>] [content-type <type>]
       [ { default-errorfiles | errorfile <file> | errorfiles <name> |
       file `<file>` | lf-file `<file>` | string `<str>` | lf-string `<fmt>` } ]
   [ hdr `<name>` `<fmt>` ]*

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

此规则会停止规则的进一步评估,并立即阻止请求,且不响应,延迟时间由 “timeout tarpit” 或 “timeout connect” 指定,若前者未设置则使用后者。延迟结束后,若客户端仍保持连接,则返回响应,以避免客户端怀疑已被陷井捕获。日志将报告标志 “PT”。陷井规则的目标是在攻击期间,针对并发请求数受限的机器人进行减速。该规则对非常简单的机器人极为有效,相比 “deny” 规则可显著降低防火墙的负载。但面对“正确”开发的机器人时,可能适得其反,迫使 HAProxy 和前端防火墙支持极高的并发连接数。默认情况下返回 HTTP 错误 500。但可通过与 “http-request return” 规则相同的语法自定义响应。详见 “http-request return”。

为保持兼容性,当未定义参数,或仅定义 “deny_status” 时,将隐式使用参数 “default-errorfiles”。这意味着 “http-request tarpit [deny_status <status>]” 是 “http-request tarpit [status <status>] default-errorfiles” 的别名。后续不再评估其他 “http-request” 规则。参见 “http-request return” 和 “http-request silent-drop”。

track-sc0 <key> [table <table>]

track-sc0 <key> [table <table>]
track-sc1 <key> [table <table>]
track-sc2 <key> [table <table>]

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | - | X | X | -

此选项启用对当前请求的粘性计数器进行跟踪。这些规则不会停止评估,也不会更改默认动作。同一连接可同时跟踪的计数器数量由全局 “tune.stick-counters” 设置决定,若在构建时设置,则其值为 MAX_SESS_STKCTR(在 HAProxy -vv 中报告),否则默认值为 3,因此 track-sc 的数值范围为 0 至 (tune.stick-counters-1)。首个执行的 “track-sc0” 规则启用指定表的计数器作为第一组。首个执行的 “track-sc1” 规则启用指定表的计数器作为第二组。首个执行的 “track-sc2” 规则启用指定表的计数器作为第三组。建议将第一组计数器用于前端级计数,第二组用于后端级计数。但这仅为指导建议,所有组均可在任意位置使用。

参数:

<key>   is mandatory, and is a sample expression rule as described in
        section 7.3. It describes what elements of the incoming connection,
        request or response will be analyzed, extracted, combined, and used
        to select which table entry to update the counters.

<table> is an optional table to be used instead of the default one, which
        is the stick-table declared in the current proxy. All the counters
        for the matches and updates for the key will then be performed in
        that table until the session ends.

一旦执行了 “track-sc*” 规则,便会查找该键对应的表项。若未找到,则为该键分配一个表项。随后,在会话的整个生命周期内,该表项的指针将被保留,并且每当会话的计数器更新时,该表项的计数器都会尽可能频繁地同步更新,且在会话结束时也会系统性地更新。计数器仅对跟踪开始后发生的事件进行更新。例外情况是,连接计数器和请求计数器会系统性地更新,以确保其反映有用信息。

如果条目跟踪并发连接计数器,则只要条目被跟踪,该连接即被计入,且在此期间条目不会过期。与仅检查键值相比,跟踪计数器还能带来性能优势,因为所有使用该计数器的 ACL 检查仅需执行一次表查找。

unset-var(<var-name>)

unset-var(<var-name>)

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | X | X | X | X

用于清除变量。有关 <var-name> 的详细信息,请参阅 “set-var” 动作。

示例:

http-request unset-var(req.my_var)

use-service <service-name>

use-service <service-name>

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | - | X | - | -

该动作根据其所在规则集的配置,执行相应的 TCP 或 HTTP 服务以响应请求。该规则为最终规则,即在同一规则集中不再评估后续规则。

服务可以选择发送任意有效的响应,也可以在不发送任何响应的情况下立即关闭连接。对于 HTTP 服务,有效的响应必须包含有效的 HTTP 响应。在原生服务之外,例如针对 HTTP 服务的 Prometheus 导出器,可以使用 Lua 编写自定义的 TCP 和 HTTP 服务。

参数:

<service-name>  is mandatory. It is the service to call

示例:

http-request use-service prometheus-exporter if { path /metrics }

wait-for-body time <time> [ at-least <bytes> ] [use-large-buffer]

wait-for-body time <time> [ at-least <bytes> ] [use-large-buffer]

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | -

这将延迟请求或响应的处理,直至满足以下任一条件:

  • 完整的请求体已接收,此时处理流程正常进行。
  • 已接收 <bytes> 字节,且提供了 “at-least” 参数,同时 <bytes> 非零,此时处理流程正常进行。
  • 请求缓冲区已满,此时处理流程正常进行。该缓冲区的大小由 “tune.bufsize” 选项决定。
  • 请求等待时间已超过 <time> 毫秒。此时 HAProxy 将向客户端返回 408 “请求超时” 错误并停止处理请求。请注意,若其他任一条件先发生,即使尚未接收完整请求体,此超时也不会触发。

“use-large-buffer” 选项可设置为在常规缓冲区不足以存储消息体时分配一个大缓冲区。若要使用,必须定义 “tune.bufsize.large” 全局选项。

此动作可作为 “option http-buffer-request” 的替代方案。

参数:

<time>    is mandatory. It is the maximum time to wait for the body. It
          follows the HAProxy time format and is expressed in milliseconds.

<bytes>   is optional. It is the minimum payload size to receive to stop to
          wait. It follows the HAProxy size format and is expressed in
          bytes. A value of 0 (the default) means no limit.

示例:

http-request wait-for-body time 1s at-least 1k if METH_POST

参见:“option http-buffer-request” 和 “tune.bufsize.large”

wait-for-handshake

wait-for-handshake

适用范围: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

这将延迟请求的处理,直到完成 SSL 握手。此举主要用于在确认早期数据有效之前延迟其处理。

14 - 5. 绑定与服务器选项

监听器、服务器、默认服务器和 DNS 解析选项

“bind”、“server” 和 “default-server” 关键字支持多种设置,具体取决于构建选项以及 HAProxy 所基于的系统。这些设置通常由一个单词组成,有时后接一个值,与 “bind” 或 “server” 语句位于同一行。所有这些选项均在本节中描述。

5.1. 绑定选项

“bind” 关键字支持若干设置,这些设置均作为参数在同一行中传递。参数的排列顺序无关紧要,只要它们出现在绑定地址之后即可。所有这些参数均为可选。部分参数为单个单词(布尔值),而其他参数则需要在其后提供值。对于后者,值必须紧随参数名称之后提供。

当前支持的设置如下:

accept-netscaler-cip <magic number>

accept-netscaler-cip <magic number>

强制使用 NetScaler 客户端 IP 插入协议,适用于在同一行中声明的任意 TCP 套接字所接受的连接。NetScaler 客户端 IP 插入协议规定,在任何使用地址的场景中均应采用传入连接的第 3/4 层地址,唯一例外是“tcp-request connection”规则仅能获取真实的连接地址。日志将反映协议中指示的地址,除非协议被违反,此时仍使用真实地址。该关键字结合外部组件支持,可作为 X-Forwarded-For 机制的高效且可靠的替代方案,后者并不总是可靠,甚至在某些情况下不可用。有关更细粒度地设置允许使用该协议的客户端,请参见“tcp-request connection expect-netscaler-cip”。

accept-proxy

accept-proxy

强制在由同一行中声明的任意套接字接收的每个连接上使用 PROXY 协议。支持 PROXY 协议版本 1 和版本 2,并能正确识别。PROXY 协议规定,所有使用地址的场景均应采用协议中指示的第 3/4 层地址,唯一例外是“tcp-request connection”规则仅能获取真实的连接地址。日志将反映协议中指示的地址,除非协议被违反,此时仍使用真实地址。该关键字结合外部组件支持,可作为 X-Forwarded-For 机制的高效且可靠的替代方案,后者并非始终可靠,甚至在某些情况下不可用。有关更细粒度地设置允许使用该协议的客户端,请参见“tcp-request connection expect-proxy”。

allow-0rtt

allow-0rtt

在使用 TLSv1.3 时允许接收早期数据。由于安全考虑,此功能默认已禁用。由于存在重放攻击风险,仅当请求可安全重放时才应启用,即仅限幂等请求。对于不适用于早期数据的请求,可使用“wait-for-handshake”动作。在 QUIC 场景下,0-RTT 支持 QuicTLS、OpenSSL >= 3.5.2 和 AWS-LC。在 TCP/TLS 场景下,0-RTT 仅支持 OpenSSL,且要求客户端发送 ALPN,否则早期数据在握手完成前不会被接受。

alpn <protocols>

alpn <protocols>

启用 TLS ALPN 扩展,并在 ALPN 上声明指定的协议列表作为支持的协议。协议列表由逗号分隔的协议名称组成,例如:http/1.1,http/1.0(不带引号)。此功能要求 SSL 库在编译时启用了 TLS 扩展支持(请通过 HAProxy -vv 检查)。ALPN 扩展取代了初始的 NPN 扩展。在协议层,ALPN 是在 HTTPS 前端启用 HTTP/2 以及在 QUIC 前端启用 HTTP/3 所必需的。然而,当此类前端未设置 “npn”、“alpn” 或 “no-alpn” 时,常规 HTTPS 前端将默认使用 “h2,http/1.1”,QUIC 前端则默认使用 “h3”。OpenSSL 1.0.2 之前的版本不支持 ALPN,仅支持现已废弃的 NPN 扩展。截至本文撰写时,大多数浏览器仍同时支持 ALPN 和 NPN 以实现 HTTP/2,因此短期内回退至 NPN 仍可能有效。但应尽可能使用 ALPN。未声明的协议不会被协商。例如,仅接受 HTTP/2 连接可配置如下:

bind:443 ssl crt pub.pem alpn h2  # explicitly disable HTTP/1.1

QUIC 仅支持 h3 和 hq-interop 作为 ALPN。h3 用于 HTTP/3,hq-interop 用于 HTTP/0.9 和 QUIC 互操作性测试工具(参见 https://interop.seemann.io )。每个 “alpn” 语句将替换之前的设置。如需移除这些设置,请使用 “no-alpn”。

请注意,某些旧版浏览器(如 Firefox 88)曾对 H2 上的 WebSocket 存在兼容性问题。若遇到此类配置,可能需要显式地在 “alpn” 字符串中禁用 HTTP/2,将其强制设为 “http/1.1” 或 “no-alpn”,或全局启用 “h2-workaround-bogus-websocket-clients”。

backlog <backlog>

backlog <backlog>

将套接字的队列长度设置为该值。若未指定或值为 0,则使用前端的队列长度,通常默认为 maxconn 的值。

ca-file <cafile>

ca-file <cafile>

此设置仅在编译时启用 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载用于验证客户端证书的 CA 证书。可加载包含多个 CA 的目录,在此情况下,HAProxy 将尝试加载目录中所有 “.pem”、".crt"、".cer" 和 .crl 文件,以点开头的文件将被忽略。

请注意:可使用 @system-ca 参数替代 cafile,以使用系统中受信任的 CA,方式与 server 指令相同。除非明确了解其安全影响,否则不得使用该参数。以这种方式配置意味着绑定将接受由系统中任意 CA 生成的客户端证书,这极其不安全。

ca-ignore-err [all|<errorID>,...]

ca-ignore-err [all|<errorID>,...]

此设置仅在编译时启用了 OpenSSL 支持时可用。设置一个以逗号分隔的错误 ID 列表,用于在验证深度大于 0 时忽略这些错误。错误 ID 可以是数值,也可以是 OpenSSL 文档中提供的常量名(X509_V_ERR): https://www.openssl.org/docs/manmaster/man3/X509_STORE_CTX_get_error.html#ERROR-CODES 建议使用常量名,因为数值可能在 OpenSSL 新版本中发生变化。若设置为 ‘all’,则忽略所有错误。忽略错误时不会中止 SSL 握手。

ca-sign-file <cafile>

ca-sign-file <cafile>

此设置仅在编译时启用 OpenSSL 支持时可用。它指定一个 PEM 文件,其中包含用于生成和签署服务器证书的 CA 证书及 CA 私钥。当启用证书动态生成时,此项为必填设置。详情请参见 ‘generate-certificates’。

ca-sign-pass <passphrase>

ca-sign-pass <passphrase>

此设置仅在编译时启用了 OpenSSL 支持时可用。它是 CA 私钥的密码。此设置为可选,仅在启用证书动态生成时使用。详情请参见 ‘generate-certificates’。

ca-verify-file <cafile>

ca-verify-file <cafile>

此设置指定一个 PEM 文件,从中加载用于验证客户端证书的 CA 证书。该设置指定的 CA 证书不得包含在服务器 Hello 消息中发送的 CA 名称列表内。通常,“ca-file”应配置为中间证书,而“ca-verify-file”应配置为用于构建证书链末端的证书,例如根 CA 证书。

cc <algo>

cc <algo>

此设置仅在定义了 TCP_CONGESTION 的系统上可用,并已在 Linux 和 FreeBSD 上完成验证。该设置指定一个 TCP 拥塞控制算法名称,并配置监听器在从该监听器接受的所有连接上使用此算法。典型名称包括 “reno”、“cubic”,具体取决于操作系统。在某些系统上,配置特定算法可能需要特殊权限。在 Linux 上,可用算法列表可在 sysctl “net.ipv4.tcp_available_congestion_control” 中找到,而无需特权即可使用的算法列表位于 “net.ipv4.tcp_allowed_congestion_control”。若需访问需要额外权限的算法,可能需要 “cap_net_admin” 能力(参见全局段中的 “setcap”)。若无法配置特定拥塞控制算法,将保持默认算法不变,并发出警告以报告该问题。另请参阅:“cc” 服务器关键字(第 5.2 节 )。示例:

frontend public
    bind:443 cc bbr   # use the BBR algorithm for high bandwidths

ciphers <ciphers>

ciphers <ciphers>

此设置仅在编译时启用了 OpenSSL 支持时可用。它用于设置在 SSL/TLS 握手过程中协商的加密算法列表(“加密套件”)的描述字符串,适用于 TLSv1.2 及以下版本。该字符串的格式由 OpenSSL 手册页中的“man 1 ciphers”定义。有关背景信息和建议,请参阅例如 (https://wiki.mozilla.org/Security/Server_Side_TLS ) 和 (https://mozilla.github.io/server-side-tls/ssl-config-generator/ )。对于 TLSv1.3 的加密套件配置,请参阅 “ciphersuites” 关键字。

ciphersuites <ciphersuites>

ciphersuites <ciphersuites>

当编译时启用了 OpenSSL 支持且使用 OpenSSL 1.1.1 或更高版本构建 HAProxy 时,此设置才可用。该设置用于指定在 TLSv1.3 握手过程中协商的加密算法列表(“加密套件”)的描述字符串。字符串格式由 OpenSSL 手册页中 “man 1 ciphers” 的 “ciphersuites” 部分定义。对于 TLSv1.2 及更早版本的加密配置,请参阅 “ciphers” 关键字。此设置可能接受 TLSv1.2 加密套件,但该行为未在文档中说明,不建议使用,因其可能存在不一致或缺陷。OpenSSL 的默认 TLSv1.3 加密套件为: “TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256”

TLSv1.3 仅支持 5 种密码套件:

  • TLS_AES_128_GCM_SHA256
  • TLS_AES_256_GCM_SHA384
  • TLS_CHACHA20_POLY1305_SHA256
  • TLS_AES_128_CCM_SHA256
  • TLS_AES_128_CCM_8_SHA256

示例:

ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256
ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256

client-sigalgs <sigalgs>

client-sigalgs <sigalgs>

此设置仅在编译时启用 OpenSSL 支持时可用。它用于设置描述与客户端认证相关的签名算法列表的字符串,该列表在协商过程中确定。字符串格式由 OpenSSL 手册页中的“man 3 SSL_CTX_set1_client_sigalgs”定义。若未明确特定使用场景,不建议使用此设置。

crl-file <crlfile>

crl-file <crlfile>

此设置仅在编译时启用了 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载证书吊销列表,以验证客户端证书。需要为证书信任链中每个证书颁发机构的证书提供相应的证书吊销列表。

crt <cert>

crt <cert>

此设置仅在编译时启用了 OpenSSL 支持的情况下可用。

HAProxy 使用缓存系统,证书文件仅在证书存储中加载一次,后续每次使用 “crt” 关键字时均会使用该缓存版本。当证书在 “crt-store” 中声明时,证书存储将从此处填充,不再通过检测文件扩展名尝试加载额外文件。

指定一个包含所需证书及关联私钥的 PEM 文件。 该文件可通过将多个 PEM 文件合并为一个来构建(例如:cat cert.pem key.pem > combined.pem)。 如果CA 要求提供中间证书,也可将其合并到此文件中。 中间证书也可通过 “issuers-chain-path” 指令在目录中共享。

如果该文件不包含私钥,HAProxy 将尝试在相同路径下、附加 “.key” 后缀的位置加载密钥。

如果所使用的 OpenSSL 支持 Diffie-Hellman,则会加载此文件中的参数。

如果使用目录名而非 PEM 文件,则该目录中所有文件将按字母顺序加载,除非文件名以 ‘.key’、’.issuer’、’.ocsp’ 或 ‘.sctl’ 结尾(保留扩展名)。以点号开头的文件也会被忽略。该指令可多次指定,以从多个文件或目录加载证书。当客户端提供有效的 TLS 服务器名称指示(SNI)字段,且该字段匹配证书中的 CN 或备用主题之一时,证书将被呈现给客户端。支持通配符,其中通配符字符 ‘*’ 用于替代主机名的第一个组件(例如 *.example.org 匹配 www.example.org ,但不匹配 www.sub.example.org )。若使用空目录,HAProxy 将不会启动,除非使用了 “strict-sni” 关键字。

如果客户端未提供 SNI,或 SSL 库不支持 TLS 扩展,或客户端提供的 SNI 主机名与任何证书均不匹配,则将呈现第一个加载的证书。这意味着在从目录加载证书时,强烈建议首先加载默认证书文件,或确保其始终为目录中的第一个文件。若需选择多个默认证书(1 个 RSA 和 1 个 ECDSA),有以下 3 种选项:

  • 可将多证书捆绑配置为首个证书(crt foobar.pem),其中现有文件为 foobar.pem.ecdsa 和 foobar.pem.rsa。
  • 或在 crt-list 行中为每个证书配置 ‘*’ 过滤器。
  • 可使用 ‘default-crt’ 关键字。

请注意,同一证书可多次加载而不会产生副作用。

部分证书颁发机构(如 GoDaddy)在申请证书时提供服务器类型下拉列表,但该列表中不包含 HAProxy。若出现此情况,请务必选择证书颁发机构认为需要中间证书的 Web 服务器类型(例如,GoDaddy 选择 Apache Tomcat 可获取正确的证书包,但选择其他类型如 NGINX 等可能导致获取错误的证书包,部分客户端将无法正常工作)。

对于每个 PEM 文件,HAProxy 会检查同路径下是否存有以 “.ocsp” 为后缀的文件。若找到该文件,将自动启用 TLS 证书状态请求扩展(亦称“OCSP 站点绑定”)支持。该文件内容为可选项。若不为空,必须包含以 DER 格式编码的有效 OCSP 响应。有效的 OCSP 响应必须满足以下规则:状态必须为良好,必须是针对 PEM 文件中证书的单一响应,且在添加时必须处于有效状态。若不满足上述规则,OCSP 响应将被忽略,并发出警告。为确定 OCSP 响应适用于哪个证书,需提供颁发者证书。若 PEM 文件中未找到颁发者证书,HAProxy 将尝试从与 PEM 文件同路径下以 “.issuer” 为后缀的文件中加载,若该文件不存在则操作失败并报错。

对于每个 PEM 文件,HAProxy 还会检查同路径下附加 “.sctl” 后缀的文件是否存在。若找到该文件,将启用证书透明度(Certificate Transparency,RFC6962)TLS 扩展。该文件必须包含符合 RFC 描述的有效签名证书时间戳列表。HAProxy 会解析文件以检查基本语法,但不会验证签名。

在某些情况下,支持多种密钥类型(例如,在向客户端提供的加密套件中同时支持 RSA 和 ECDSA)是可取的。这使得支持 EC 证书的客户端能够使用 EC 加密算法,同时仍可兼容仅支持 RSA 的旧版客户端。

为实现此功能,需使用 OpenSSL 1.1.1。可通过为每种证书类型提供一个 crt 条目,或像 HAProxy 1.8 之前那样配置“证书捆绑包”来实现此行为。参见“ssl-load-extra-files”。

crt-ignore-err <errors>

crt-ignore-err <errors>

此设置仅在编译时启用了 OpenSSL 支持时可用。设置一个以逗号分隔的错误 ID 列表,用于在验证深度 == 0 时忽略这些错误。错误 ID 可以是数值,也可以是常量名称(X509_V_ERR),该名称可在 OpenSSL 文档中找到: https://www.openssl.org/docs/manmaster/man3/X509_STORE_CTX_get_error.html#ERROR-CODES 建议使用常量名称,因为数值可能在 OpenSSL 新版本中发生变化。若设置为 ‘all’,则忽略所有错误。忽略错误时不会中止 SSL 握手。

crt-list <file>

crt-list <file>

此设置仅在编译时启用 OpenSSL 支持时可用。它指定一个 PEM 文件列表,每个证书可选配 SSL 配置和 SNI 过滤器,每行格式如下:

<crtfile> [\[<sslbindconf> ...\]] [[!]<snifilter> ...]

空行以及以井号(’#’)开头的行将被忽略。

可通过统计信息套接字动态操作 crt-list。(参见管理指南中的“add ssl crt-list”、“del ssl crt-list”和“show ssl crt-list”)

crt-list 通常为专用文件,但通过 “crt” 指令加载的目录在内部也表示为 crt-list。前端中的 “ssl-f-use” 指令同样声明了一个与该前端关联的 crt-list。

crtfile:

This is the filename of the certificate, or an identifier if it was declared
elsewhere (over the CLI or in a crt-store with an alias for example).

It is possible to use the same <crtfile> on multiple lines with different
options and filters.

Multi-cert bundling (see "ssl-load-extra-files") is supported in a
crt-list, as long as only the base name is given in <crtfile>. HAProxy
will duplicate the crt-list line internally, adding an algorithm extension
(.rsa, .ecdsa, .dsa) when loading the file.

sslbindconf:

 <sslbindconf> supports the following keywords from the bind line (see
 Section 5.1. Bind options):

 - allow-0rtt
 - alpn
 - ca-file
 - ca-verify-file
 - ciphers
 - ciphersuites
 - client-sigalgs
 - crl-file
 - curves
 - ecdhe
 - no-alpn
 - no-ca-names
 - npn
 - sigalgs
 - ssl-min-ver
 - ssl-max-ver
 - verify

 <sslbindconf> also supports the following keywords from the crt-store load
 keyword (see Section 12.7.1. Load options):

 - crt
 - key
 - ocsp
 - issuer
 - sctl
 - ocsp-update

Parameters from the bind line are inherited in <sslbindconf>, if none were
specified, the default options are inherited, the parameters specified in
<sslbindconf> overwrite those inherited settings.

snifilter:

When the <snifilter> parameter is used on a crt-list line, the CN and SAN
are not used anymore to select the certificate on this line during the
handshake but the <snifilter> is used instead.

<snifilter> is a list of entries separated by spaces. This list can contain
domains, or wildcards. The wildcards are in wildcard DNS format, using a
single asterisk as the first character of the entry. It is possible to
exclude a domain from a wildcard with a negative filter by specifying a '!'
in front of a single domain. Having a ! in front of a * is ignored. Having
negative filters without a wildcard on the same line is not supported as
well. The special entry '*' is used to specify default certificates, which
are used as fallback when no domain matched.

The certificates will be presented to clients who provide a valid TLS
Server Name Indication field matching one of the SNI filters, or the CN and
SAN of a <crtfile>. The matching algorithm first looks for a positive domain
entry in the list, if not found it will try to look for a wildcard in the
list. If a wildcard match, haproxy checks for a negative filter from the
same line and unmatch if necessary. In case of multiple key algorithms
(RSA,ECDSA,DSA), HAProxy will try to match one certificate per type and
chose the right one depending on what is supported by the client.

If no SNI is presented by the client or if no certificate matched, this
will fallback to one of the default certificate. To disable the default
certificate fallback, the 'strict-sni' option may be used.
When multiple default certificates are defined, HAProxy is able to chose
the right ECDSA or RSA one depending on what the client supports.

The first declared certificate of a bind line is used as a default
certificate, either from crt or crt-list option.
It is also possible to declare a '*' filter, which will add this
certificate to the list of default certificates. To clarify the
configuration, the default certificates could be explicit (with a '*'
filter) at the beginning of the list, so an implicit default is not added
before.
Due to multi-cert bundles being duplicated for each algorithm in the
crt-list, only one algorithm will occupy the first line in the crt-list and
be considered as default. Either specify the entire bundle as default by
declaring '*' as the filter or setting it on the bind line.

The "show ssl sni" command on the stats socket could be used to debug your
configuration. (See "show ssl sni" in the management guide)

示例:

# comment
default.pem.rsa *
default.pem.ecdsa *
cert2.pem [alpn h2,http/1.1]
certW.pem *.domain.tld !secure.domain.tld
certS.pem [curves X25519:P-256 ciphers ECDHE-ECDSA-AES256-GCM-SHA384] secure.domain.tld
foo.crt [key bar.pem ocsp foo.ocsp ocsp-update on] foo.bar.com

default-crt <cert>

default-crt <cert>

此选项的功能与 “crt” 选项相同,区别在于该证书也将作为默认证书使用。可以添加多个默认证书,例如同时配置 ECDSA 和 RSA 证书,但添加更多默认证书并无实际意义。

此选项不会禁用隐式默认证书。若在任何 ‘default-crt’ 或其他 ‘crt’ 之前声明了 ‘crt’ 证书,该证书仍会被用作默认证书。

当绑定行未使用 “strict-sni” 选项时,将使用默认证书。当客户端未使用服务器名称扩展,或服务器名称与任何已配置的证书不匹配时,将提供默认证书。

示例:

# this bind line has 2 default certificates
bind *:443 default-crt foobar.pem.rsa default-crt foobar.pem.ecdsa crt website.pem.rsa

# this bind line has 3 default certificates
bind *:443 crt website.pem.rsa default-crt foobar.pem.rsa default-crt foobar.pem.ecdsa

另请参见“crt”关键字。

curves <curves>

curves <curves>

此设置仅在编译时启用 OpenSSL 支持时可用。它用于设置在使用 ECDHE 进行 SSL/TLS 握手时协商的椭圆曲线算法列表(“曲线套件”)的描述字符串。字符串格式为以冒号分隔的曲线名称列表。示例:X25519:P-256(不含引号)。当设置 “curves” 时,“ecdhe” 参数将被忽略。

defer-accept

defer-accept

是一个可选关键字,仅在某些 Linux 内核上受支持。它表示连接仅在有数据到达时才会被接受,最迟在首次重传后被接受。该选项应仅用于客户端首先发起通信的协议(例如 HTTP)。通过确保在连接建立时大部分请求数据已就绪,可略微提升性能。另一方面,该选项无法检测未发送数据的连接。请注意,所有版本低于 2.6.31 的内核均存在此选项失效的问题,因为连接始终不会被接受,直到客户端发送数据。这可能导致前端防火墙看到已建立的连接,而代理仅在 SYN_RECV 时才看到该连接。此选项仅对 TCPv4/TCPv6 套接字有效,其他类型的套接字将忽略该选项。

ecdhe <named curve>

ecdhe <named curve>

此设置仅在编译时启用了 OpenSSL 支持时可用。它用于设置生成 ECDH 临时密钥所使用的命名曲线(RFC 4492)。默认使用的命名曲线为 prime256v1。

ech <dir> [ EXPERIMENTAL ]

ech <dir> [ EXPERIMENTAL ]

将 <dir> 中的所有 ECH 密钥应用到绑定行。文件必须具有 .ech 扩展名,并且 ECH 必须使用 PEM 文件格式。(https://datatracker.ietf.org/doc/draft-farrell-tls-pemesni/ )

此关键字用于在共享模式下启用 ECH,由 HAProxy 同时充当 TLS 终端与 ECH 终端。参见 https://datatracker.ietf.org/doc/draft-ietf-tls-esni/

本文为实验性功能,需在 global 段中启用 “expose-experimental-directives” 指令。该功能还要求使用支持 ECH 的 OpenSSL 版本(https://github.com/openssl/openssl/tree/feature/ech ),且 HAProxy 必须以 USE_ECH=1 编译。AWS-LC 的 ECH API 不受支持。

示例:

$ openssl ech -public_name foobar.com -out /etc/haproxy/echkeydir/foobar.com.ech

$ cat haproxy.cfg
[...]
bind:443 ech /etc/haproxy/echkeydir/ ssl crt example.com.pem

// Use the ECHCONFIG section of your .ech file
$ openssl s_client -tls1_3 -connect example.com:443 -servername example.com \
-ech_config_list AD3+DQA5cwAgACB6ybtgtFYoM5r8nJSotus4c7K0EG..9vYmFyLmNvbQAA

expose-fd listeners

expose-fd listeners

此选项仅在使用统计信息套接字时可用。它使统计信息套接字具备将监听器文件描述符传递给另一个 HAProxy 进程的能力。在主进程/工作进程模式下,此操作已不再必要,监听器将通过主进程与工作进程之间的内部套接字对自动传递。参见管理指南中的 “-x”。

force-sslv3

force-sslv3

此选项强制仅在从该监听器创建的 SSL 连接中使用 SSLv3。在高连接速率场景下,SSLv3 通常比 TLS 对应版本的开销更低。此选项也可在全局语句 “ssl-default-bind-options” 中使用。另请参见 “ssl-min-ver” 和 “ssl-max-ver”。

force-tlsv10

force-tlsv10

此选项强制仅在从此监听器创建的 SSL 连接中使用 TLSv1.0。该选项也可在全局语句 “ssl-default-bind-options” 中使用。另请参见 “ssl-min-ver” 和 “ssl-max-ver”。

force-tlsv11

force-tlsv11

此选项强制仅在从此监听器创建的 SSL 连接中使用 TLSv1.1。该选项也可在全局语句 “ssl-default-bind-options” 中使用。另请参见 “ssl-min-ver” 和 “ssl-max-ver”。

force-tlsv12

force-tlsv12

此选项强制仅在从此监听器创建的 SSL 连接中使用 TLSv1.2。该选项也可在全局语句 “ssl-default-bind-options” 中使用。另请参阅 “ssl-min-ver” 和 “ssl-max-ver”。

force-tlsv13

force-tlsv13

此选项强制仅在从此监听器创建的 SSL 连接中使用 TLSv1.3。该选项也可在全局语句 “ssl-default-bind-options” 中使用。另请参见 “ssl-min-ver” 和 “ssl-max-ver”。

generate-certificates

generate-certificates

此设置仅在编译时启用 OpenSSL 支持时可用。它可启用动态 SSL 证书生成。需要 CA 证书及其私钥(参见 ‘ca-sign-file’)。当 HAProxy 配置为透明正向代理时,由于向客户端呈现的证书存在通用名称不匹配问题,SSL 请求会出错。启用此选项后,HAProxy 将尝试使用客户端提供的 SNI 主机名伪造证书。仅当没有证书与 SNI 主机名匹配时(参见 ‘crt-list’)才执行此操作。

发生证书生成错误时,连接将回退到默认证书。使用 ‘strict-sni’ 时,不会使用默认证书,连接将导致握手失败。

当 HAProxy 配置为反向代理时,也可用于简化包含多个后端的架构部署。

创建 SSL 证书是一项开销较大的操作,因此使用 LRU 缓存来存储伪造的证书(参见 ’tune.ssl.ssl-ctx-cache-size’)。该机制会增加 HAProxy 的内存占用,以降低同一证书被多次使用时的延迟。

gid <gid>

gid <gid>

设置 Unix 套接字的组为指定的系统 gid。也可在全局段的 “unix-bind” 语句中默认设置。请注意,某些平台会直接忽略此设置。此设置与 “group” 设置等效,不同之处在于使用组 ID 而非组名。此设置对非 Unix 套接字无效。

group <group>

group <group>

设置 Unix 套接字所属的系统组。该设置也可在全局段的 “unix-bind” 语句中默认指定。请注意,某些平台会直接忽略此设置。此设置与 “gid” 设置等效,区别在于使用组名而非其 gid。该设置对非 Unix 套接字无效。

guid-prefix <string>

guid-prefix <string>

为当前绑定行上分配的每个监听套接字生成区分大小写的全局唯一 ID。前缀将与当前绑定行上监听器的位置索引连接,以字符“-”作为分隔符。有关其格式的更多信息,请参见“guid”代理关键字的描述。另请参见“shm-stats-file”。

id <id>

id <id>

修复套接字 ID。默认情况下,套接字 ID 会自动分配,但有时固定套接字 ID 可以更方便地进行监控。该值必须为严格正数,且在监听器/前端范围内唯一。此选项仅在定义单个套接字时可用。

idle-ping <delay>

idle-ping <delay>

可用于以下上下文:tcp、http、log

定义空闲前端连接的周期性存活检测间隔。如果对等节点在下一次预定检测前无法响应,则关闭连接;否则,刷新客户端超时并保持连接。请注意,http-request/http-keep-alive 定时器与 idle-ping 定时器并行运行,且不会因 idle-ping 而刷新。

此功能依赖于特定底层协议支持。目前,仅 H2 mux 实现了该功能。 其他协议会直接忽略空闲 ping。

此选项在使用反向 HTTP 时尤为有用。在 bind 行上设置该选项,对负责主动发起连接的对等节点尤为有用,该节点随后将通过这些连接接收入站流量。

interface <interface>

interface <interface>

限制套接字绑定到特定网络接口。指定后,仅来自该特定接口的数据包会被套接字处理。此功能当前仅在 Linux 上受支持。接口必须是主系统接口,而非别名接口。若前端绑定到不同接口,可将多个前端绑定至同一地址。请注意,绑定到网络接口需要 root 权限。该参数仅与 TCPv4/TCPv6 套接字兼容。指定后,返回流量将使用与入站流量相同的接口及其关联的路由表,即使已配置通过不同接口的显式路由。此机制在需使同一客户端 IP 地址能够访问位于不同接口上的前端时,可用于解决非对称路由问题。

ktls <on|off> [ EXPERIMENTAL ]

ktls <on|off> [ EXPERIMENTAL ]

启用或禁用套接字的 kTLS。若启用,当内核支持且加密算法兼容时,将使用 kTLS。此功能仅在 Linux 内核 4.17 及以上版本中可用。请注意,部分网络驱动程序和/或 TLS 栈可能将 kTLS 使用限制为仅支持 TLS v1.2。参见“force-tlsv12”。

label <label>

label <label>

为这些套接字设置一个可选标签。该标签可用于按标签分组套接字,与 bind 语句的声明位置无关。

level <level>

level <level>

此设置仅用于统计信息套接字,以限制可通过套接字发出的命令类型。其他套接字会忽略此设置。<level> 可能为以下之一:

  • “user” 为最低权限级别;仅可读取非敏感的统计信息,且不允许进行任何更改。在难以限制对套接字访问的系统上,此级别具有实际意义。
  • “operator” 为默认级别,适用于大多数常见场景。所有数据均可读取,仅允许执行非敏感的更改(例如,清空最大计数器)。
  • “admin” 应谨慎使用,因为所有操作均被允许(例如,清空所有计数器)。

maxconn <maxconn>

maxconn <maxconn>

限制每个套接字的并发连接数。多余的连接将保留在系统的队列中,直到有连接被释放。若未指定,该限制将与前端的 maxconn 值相同。请注意,当使用端口范围或多地址时,该值将应用于每个套接字。此设置可对高成本套接字(例如 SSL 套接字)施加不同的限制,这类套接字可能轻易耗尽全部内存。

mode <mode>

mode <mode>

设置用于定义 Unix 套接字访问权限的八进制模式。该设置也可在全局段的 “unix-bind” 语句中默认配置。请注意,某些平台会直接忽略此设置。该设置对非 Unix 套接字无效。

mss <maxseg>

mss <maxseg>

设置要通告的 TCP 最大段大小(MSS)值,用于传入连接。此选项可用于对特定端口强制设置较低的 MSS,例如通过 VPN 传输的连接。请注意,该功能依赖于内核特性,理论上在 Linux 下受支持,但所有 2.6.28 之前版本均存在缺陷。在其他操作系统上可能无法正常工作。该功能也可能不会改变通告的值,而是改变传出段的实际有效大小。在以太网网络上,TCPv4 的常见通告值为 1460 = 1500(MTU) - 40(IP + TCP)。若该值为正,将作为通告的 MSS 使用;若为负,则表示将传入连接的通告 MSS 减少指定数值,用于传出段。此参数仅与 TCP v4/v6 套接字兼容。

name <name>

name <name>

为这些套接字设置一个可选名称,该名称将在统计信息页面上报告。

namespace <name>

namespace <name>

在 Linux 上,可以指定套接字所属的网络命名空间。该指令允许显式地将监听器绑定到与默认命名空间不同的命名空间。请参阅操作系统的文档以获取有关网络命名空间的更多详细信息。

nbconn <nbconn> [ EXPERIMENTAL ]

nbconn <nbconn> [ EXPERIMENTAL ]

此设置仅适用于使用反向 HTTP 的监听器实例。它将定义并行挂载的连接数量。若未指定,默认值为 1。

反向 HTTP 当前仍处于积极开发阶段。配置机制未来可能发生变化。因此,该功能在内部被标记为实验性,这意味着必须在本指令之前出现一行 “expose-experimental-directives”。

nice <nice>

nice <nice>

设置从套接字发起的连接的“优先级”值。该值必须在 -1024..1024 范围内(含),默认值为零。正值表示此类连接对其他连接更友好,更容易让出调度器中的执行位置。相反,负值表示连接希望以高于其他连接的优先级运行。该差异仅在系统负载较高、接近饱和时显现。对于低延迟或系统管理服务,建议使用负值;对于 CPU 密集型任务(如 SSL 处理或大批量传输),通常推荐使用高值,因为这些任务对延迟不敏感。例如,可对 SMTP 套接字使用正值,对 RDP 套接字使用负值。

no-alpn

no-alpn

禁用 ALPN 处理(技术上讲,这会将 ALPN 字符串设置为空,使其不会被通告)。此选项可用于取消先前配置的 “alpn” 设置,并禁用应用层协议协商。也可用于阻止 HTTPS 或 QUIC 监听器与客户端协商 ALPN;默认情况下,HTTPS 监听器会通告 “h2,http/1.1”,QUIC 监听器会通告 “h3”。参见上方的 “alpn” 配置项。请注意,使用 “crt-list” 时,证书可能会覆盖 “alpn” 设置并重新启用其处理。

no-ca-names

no-ca-names

此设置仅在编译时启用 OpenSSL 支持时可用。当使用 ca-file 时,该设置可防止在 Server Hello 消息中发送 CA 名称。请使用 “ca-verify-file” 替代 “ca-file”,并配合 “no-ca-names” 使用。

no-sslv3

no-sslv3

此设置仅在编译时启用 OpenSSL 支持时可用。当 SSL 受支持时,它会禁用从监听器实例化的所有套接字上的 SSLv3 支持。请注意,SSLv2 在代码中已被强制禁用,无法通过任何配置选项启用。此选项也可在全局语句 “ssl-default-bind-options” 中使用。请改用 “ssl-min-ver” 和 “ssl-max-ver”。

no-strict-sni

no-strict-sni

此设置仅在编译时包含 OpenSSL 支持时可用。它会禁用之前“strict-sni”指令所强制执行的严格 SNI 检查。当通过“ssl-default-bind-options”全局启用严格 SNI 后,可能需要在特定“bind”行上选择性地禁用严格 SNI,此时可使用此设置。参见“strict-sni”绑定选项。

no-tls-tickets

no-tls-tickets

此设置仅在编译时启用 OpenSSL 支持时可用。它禁用无状态会话恢复(RFC 5077 TLS 会话票据扩展),强制使用有状态会话恢复。无状态会话恢复的 CPU 消耗更高。该选项也可在全局语句 “ssl-default-bind-options” 中使用。TLS Ticket 机制仅适用于 TLS 1.2 及以下版本。除非通过重载或使用 “tls-ticket-keys” 定期轮换票据密钥,否则使用 TLS Ticket 会损害前向安全性。

no-tlsv10

no-tlsv10

此设置仅在编译时启用 OpenSSL 支持时可用。当监听器支持 SSL 时,该设置会禁用所有由此监听器实例化套接字的 TLSv1.0 支持。请注意,SSLv2 在代码中已被强制禁用,无法通过任何配置选项启用。该选项也可用于全局语句 “ssl-default-bind-options” 中。建议改用 “ssl-min-ver” 和 “ssl-max-ver”。

no-tlsv11

no-tlsv11

此设置仅在编译时启用 OpenSSL 支持时可用。当 SSL 受支持时,该设置会禁用从监听器实例化的所有套接字上的 TLSv1.1 支持。请注意,SSLv2 在代码中已被强制禁用,无法通过任何配置选项启用。该选项也可用于全局语句 “ssl-default-bind-options”。建议改用 “ssl-min-ver” 和 “ssl-max-ver”。

no-tlsv12

no-tlsv12

此设置仅在编译时启用 OpenSSL 支持时可用。当 SSL 受支持时,该设置会禁用从监听器实例化的所有套接字上的 TLSv1.2 支持。请注意,SSLv2 在代码中已被强制禁用,无法通过任何配置选项启用。此选项也可在全局语句 “ssl-default-bind-options” 中使用,请改用 “ssl-min-ver” 和 “ssl-max-ver”。

no-tlsv13

no-tlsv13

此设置仅在编译时启用 OpenSSL 支持时可用。当 SSL 受支持时,该设置会禁用从监听器实例化的所有套接字上的 TLSv1.3 支持。请注意,SSLv2 在代码中已被强制禁用,无法通过任何配置选项启用。该选项也可用于全局语句 “ssl-default-bind-options”。建议改用 “ssl-min-ver” 和 “ssl-max-ver”。

npn <protocols>

npn <protocols>

启用 NPN TLS 扩展,并在 NPN 基础上通告指定的协议列表作为支持的协议。协议列表由逗号分隔的协议名称组成,例如:http/1.1,http/1.0(不带引号)。此功能要求 SSL 库在编译时启用了 TLS 扩展支持(请通过 HAProxy -vv 检查)。请注意,NPN 扩展已被 ALPN 扩展取代(参见 “alpn” 关键字),但 ALPN 仅在 OpenSSL 1.0.2 及以上版本中可用。若需在较旧版本的 OpenSSL 上使用 HTTP/2,NPN 仍可使用,因为截至本文撰写时,大多数客户端仍支持该功能。尽管可以同时启用 NPN 和 ALPN,但通常仅用于测试目的,实际并无必要。

prefer-client-ciphers

prefer-client-ciphers

使用客户端偏好选择加密套件,默认情况下强制使用服务器偏好。此选项也可在全局语句 “ssl-default-bind-options” 中使用。

请注意,当 OpenSSL 版本 ≥ 1.1.1 时,即使未设置此选项,若客户端密钥列表中首位为 ChaCha20-Poly1305 密码套件,HAProxy 也会自动将其优先级提升。

在使用双算法配置(RSA + ECDSA)时,选择算法将在这两种算法之间进行选择,并始终优先选择 ECDSA。选定正确的证书后,将由 SSL 库负责优先选择加密算法、椭圆曲线等。因此,该选项无法用于优先选择 RSA 证书而非 ECDSA 证书。

proto <name>

proto <name>

强制多路复用器协议用于传入连接。该协议必须与前端的模式(TCP 或 HTTP)兼容,且必须可在前端侧使用。可用协议列表见 HAProxy -vv.。协议属性包括:模式(TCP/HTTP)、侧边(FE/BE)、多路复用器名称及其标志。

部分协议在服务器端存在队首阻塞问题(flag=HOL_RISK)。此外,部分协议不支持升级(flag=NO_UPG)。HTX 兼容性状态亦已报告(flag=HTX)。

以下协议可用于绑定行中 “proto” 指令的参数:

quic: mode=HTTP  side=FE|BE  mux=QUIC  flags=HTX|NO_UPG|FRAMED
 qmux: mode=HTTP  side=FE|BE  mux=QMUX  flags=HTX|NO_UPG
 h2  : mode=HTTP  side=FE|BE  mux=H2    flags=HTX|HOL_RISK|NO_UPG
 h1  : mode=HTTP  side=FE|BE  mux=H1    flags=HTX|NO_UPG
 none: mode=TCP   side=FE|BE  mux=PASS  flags=NO_UPG

此选项的原理是绕过从该监听套接字创建的所有连接所采用的最佳多路复用协议选择机制。例如,可通过在绑定行中指定 “proto h2”,强制在明文 TCP 上使用 HTTP/2。

如果配置了 ALPN 或 NPN 设置,指定的协议应与多路复用器的协议兼容,以避免出现任何问题。例如,若设置为 “proto h1”,则不应将 ALPN 设置为 “h2”。

QMux 是 QUIC 的一个子集,运行于 TCP 之上。它对应于以下草案协议 https://www.ietf.org/archive/id/draft-ietf-quic-qmux-01.html 。目前在 HAProxy 中仍处于实验阶段。

quic-cc-algo { cubic | newreno | bbr | nocc }[(<args,...>)]

quic-cc-algo { cubic | newreno | bbr | nocc }[(<args,...>)]

这是针对 QUIC 的特定设置,用于选择连接到已配置的 QUIC 监听器时所采用的拥塞控制算法。其选项与 TCP 所使用的类似。

在拥塞算法基础上启用速率控制,以降低丢包率并提升吞吐量。可通过 “tune.quic.fe.tx.pacing” 全局关键字关闭此功能。在大多数情况下,应保持速率控制开启,尤其是在使用 BBR 时,因为 BBR 依赖该功能以按预期工作。在未启用速率控制的情况下使用 BBR 可能导致传输期间出现性能下降或高丢包率。

默认值:cubic

如需进一步自定义,可在算法标记后指定参数列表。参数必须用括号括起,并以逗号分隔。每个参数均为可选,必要时可为空。各参数的必需顺序如下:

  • 最大窗口大小(以字节为单位)。必须大于 10k 且小于 4g。默认情况下使用 “tune.quic.fe.cc.max-win-size” 值。

示例:

# newreno congestion control algorithm
quic-cc-algo newreno
# cubic congestion control algorithm with one megabytes as window
quic-cc-algo cubic(1m)

特殊值 “nocc” 可用于强制将拥塞窗口始终设置为最大值。该值专用于调试场景,以消除拥塞控制器引起的任何副作用。在生产环境中必须禁止使用,否则可能导致网络问题,例如高丢包率。

quic-force-retry

quic-force-retry

本设置为 QUIC 特有选项,强制对所有连接到已配置 QUIC 监听器的连接尝试均启用 QUIC Retry 功能。该机制通过验证对等节点是否能够接收其用于发起新连接的传输地址上的数据包来实现,随后向其发送包含令牌的 Retry 数据包。该令牌必须由对等节点返回给 Retry 数据包发送方,仅该发送方能够验证令牌的有效性。请注意,即使设置了 Retry 阈值(参见 “tune.quic.fe.sec.retry-threshold” 设置),QUIC Retry 仍始终启用。

此设置要求已配置集群密钥,否则启动时将报告错误(参见“cluster-secret”)。

有关 QUIC 重试的更多信息,请参见 https://www.rfc-editor.org/rfc/rfc9000.html#section-8.1.2 。

quic-socket [ connection | listener ]

quic-socket [ connection | listener ]

此 QUIC 特定设置允许为特定监听器定义套接字分配模式。 请参阅 “tune.quic.fe.sock-per-conn” 以获取每种模式优缺点的完整说明。

此设置与全局 “tune.quic.fe.sock-per-conn” 选项协同生效。若全局调优启用“default-on”模式(此为默认值),则每个 QUIC 连接将使用其专属套接字,但监听器配置为“quic-socket listener”的情况除外。若全局模式设置为“force-off”,则将忽略单个监听器的配置。

severity-output <format>

severity-output <format>

此设置仅用于统计套接字,用于配置附加到信息反馈消息前的严重性级别输出。消息的严重性级别范围为 0 至 7,符合 syslog RFC5424 标准。请求数据的有效且成功的套接字命令(例如 “show map”、“get acl foo” 等)不会附加严重性级别。其他套接字会忽略此设置。<format> 可以是:

  • “none”(默认值):反馈消息前不添加严重性级别。
  • “number”:严重性级别以数字形式添加。
  • “string”:严重性级别以字符串形式添加,遵循 rfc5424 规范。

shards { <number> | by-thread | by-group }

shards { <number> | by-thread | by-group }

在多线程模式下,若操作系统支持在同一 IP:端口上绑定多个监听器,则会自动为同一配置行创建指定数量的相同监听器,所有监听器均公平分配与该监听器关联的线程数量。当使用极高的线程数时,此机制可能有所帮助,因为单个套接字的内核锁开销开始产生显著影响。此时,传入流量被分散到多个套接字上,竞争程度得以降低。请注意,这样做可能会因更多线程同时工作而略微增加 CPU 使用率。

如果分片数量超过可用线程数量,系统将自动将其缩减至线程数量(即每个线程对应一个分片)。特殊值 “by-thread” 也会根据 “bind” 行上的线程数量创建相应数量的分片。由于系统会将传入流量均匀分配到所有这些分片,因此该数值必须是线程数量的整数因子。另一种特殊值 “by-group” 则每个线程组创建一个分片。当处理大量线程且不希望创建过多套接字时,此选项较为有用。虽然负载分布的优化程度稍低,但竞争(尤其是系统层面的竞争)仍低于使用单个套接字的情况。

在不支持将多个套接字绑定到同一地址的操作系统上,“按线程”和“按组”模式将自动回退到单个分片。对于“按组”模式,由于单个组的配置不变,不会发出任何警告,且无论如何都会导致每个组的套接字被重复创建。然而,若“按线程”模式发生此类回退,将发出诊断警告,因为最终的监听器数量将与预期不符。

sigalgs <sigalgs>

sigalgs <sigalgs>

此设置仅在编译时启用了 OpenSSL 支持时可用。它用于设置在 TLSv1.2 和 TLSv1.3 握手过程中协商的签名算法列表的描述字符串。字符串格式由 OpenSSL 手册页中的“man 3 SSL_CTX_set1_sigalgs”定义。除非需要与中间设备兼容,否则不建议使用此设置。

ssl

ssl

此设置仅在编译时启用 OpenSSL 支持时可用。它可启用从此监听器建立的连接上的 SSL 解密功能。需要提供证书(参见上文的 “crt”)。缓冲区中的所有内容将以明文形式呈现,因此 ACL 和 HTTP 处理仅能访问解密后的数据。默认情况下禁用 SSLv3,如需启用,请使用 “ssl-min-ver SSLv3”。

ssl-max-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]

ssl-max-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]

此选项强制在从此监听器创建的 SSL 连接中使用 <version> 或更低版本。 若未设置 “ssl-min-ver” 而使用此选项,可能产生歧义,因为未来 HAProxy 版本中的默认 ssl-min-ver 值可能发生变化。 此选项也可在全局语句 “ssl-default-bind-options” 中使用。 另请参阅 “ssl-min-ver”。

ssl-min-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]

ssl-min-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]

此选项强制在从此监听器创建的 SSL 连接中使用 <version> 或更高版本。 默认值为 “TLSv1.2”。此选项也可在全局语句 “ssl-default-bind-options” 中使用。 另请参见 “ssl-max-ver”。

strict-sni

strict-sni

此设置仅在编译时启用 OpenSSL 支持时可用。仅当客户端提供的 SNI 与某个证书匹配时,才允许进行 SSL/TLS 协商。默认证书不会被使用。此选项还允许在绑定行上不配置任何证书的情况下启动,因此可使用空目录,并稍后通过统计信息套接字填充证书。此选项也可在全局语句 “ssl-default-bind-options” 中使用,并可通过在 “bind” 行上使用 “no-strict-sni” 选择性禁用。有关更多信息,请参见 “crt” 选项。详见管理指南中的 “add ssl crt-list” 命令。

tcp-md5sig <password>

tcp-md5sig <password>

启用 TCP MD5 签名(RFC 2385 通过 TCP MD5 签名选项保护 BGP 会话)功能,对从此监听套接字创建的所有入站连接生效。此选项仅在 Linux 上可用。启用后,使用 <password> 字符串为每个 TCP 段生成 16 字节的 MD5 摘要进行签名。此举可防范 TCP 连接遭受伪造攻击。该选项的主要用途是使 BGP 能够防范伪造 TCP 段被引入连接流。但对任何长时间持续的 TCP 连接亦可能具有实用价值。

tcp-ss <mode>

tcp-ss <mode>

设置此监听套接字创建的所有传入连接的 TCP Save SYN 选项。 该选项自 Linux 4.3 版本起可用。它指示内核尝试保存包含 TCP SYN 标志的传入 IP 数据包副本,以便后续通过 “fc_saved_syn” 样本提取函数进行检查。该选项支持 3 种模式: - 0:禁用 SYN 数据包保存,这是默认值 - 1:启用 SYN 数据包保存,包含 IP 和 TCP 头 - 2:启用 SYN 数据包保存,包含 ETH、IP 和 TCP 头

仅对常规 TCP 连接有效,对其他协议(例如 Unix 套接字)则被忽略。 另请参阅 “fc_saved_syn”。

tcp-ut <delay>

tcp-ut <delay>

设置此监听套接字创建的所有传入连接的 TCP 用户超时。该选项自 Linux 2.6.37 版本起可用。它允许 HAProxy 为包含尚未收到确认数据的套接字配置超时,超时时间为指定延迟。在长时间保持连接且经历长时间空闲的场景中尤为有用,例如远程终端或数据库连接池,此时客户端和服务器的超时必须设置得较高以允许较长的空闲期,但又必须能够检测到客户端已断开,以便释放与该连接(及服务器会话)相关的所有资源。参数为延迟时间,默认单位为毫秒。该选项仅适用于常规 TCP 连接,对其他协议无效。

tfo

tfo

是可选关键字,仅在 Linux 内核版本 ≥ 3.7 时受支持。该选项在监听套接字上启用 TCP 快速打开功能,意味着支持此特性的客户端在建立第二个及后续连接时,可在三次握手过程中发送请求并接收响应,从而在首次连接后节省一次往返通信。此功能仅在请求速率较高且每次往返均至关重要的协议中才有意义。该选项可能与许多不接受 SYN 包中携带数据的防火墙产生冲突,因此建议在充分测试后再启用。该选项仅对 TCPv4/TCPv6 套接字有效,其他类型的套接字将忽略此设置。若所用 C 库未定义 TCP_FASTOPEN,可能需要使用 USE_TFO=1 编译 HAProxy。

thread [<thread-group>/]<thread-set>[,...]

thread [<thread-group>/]<thread-set>[,...]

此选项限制了该监听器可运行的线程列表。它不会强制执行其中任何线程,而是排除不匹配的线程。此设置限制了可处理该监听器传入连接的线程范围。

有两种编号方案。默认情况下,线程编号为进程内的绝对编号,范围介于 1 和 global.nbthread 中指定的值之间。也可以通过指定线程组编号,后跟斜杠(’/’)和相对线程编号来标识线程编号。此时,线程编号同样从 1 开始,终止于 32 或 64,具体取决于平台。当指定绝对线程编号时,一旦确定线程组,将自动将其转换为相对编号。通常,简单配置中建议使用绝对编号,而在涉及 CPU 布局对性能有影响的复杂配置中,建议使用相对编号。

在可选的线程组编号之后,“thread-set” 规定必须采用以下格式:

"all" | "odd" | "even" | [number][-[number]]

如其名称所示,“all” 验证指定集合中的所有线程(指定组时为该组全部线程,否则为进程全部线程),“odd” 验证所有奇数编号线程(从 1 开始每隔一个线程),适用于进程或组,“even” 验证所有偶数编号线程(从 2 开始每隔一个线程)。若使用线程编号范围,则验证从第一个编号到最后一个编号之间的所有线程。编号为相对编号或绝对编号,取决于是否指定了线程组编号。若未指定第一个线程编号,则使用 “1”,表示该组的第一个线程或进程的第一个线程。若未指定最后一个线程编号,则使用该组的最后一个线程编号(32 或 64),或进程的最后一个线程编号(global.nbthread)。

这些范围可以重复,并用逗号分隔,以便指定不连续的线程集合,且每个新范围都必须重新指定组(如果存在)。请注意,不允许混合使用组相对和绝对指定方式,因为整个 “bind” 行必须统一使用绝对格式或相对格式,未设置的部分将在解析结束时进行解析。

请注意,由“bind”指令描述的每个监听器至少会创建一个套接字,该套接字由至少一个文件描述符表示。由于文件描述符无法跨多个线程组共享,若“bind”指令指定的线程范围覆盖了多个线程组,则会自动创建多个文件描述符,以确保每个线程组至少拥有一个。从技术上讲,它们在内核中均指向同一个套接字,但在 HAProxy 中将获得不同的标识符,并且在启用“option socket-stats”时,每个文件描述符还将拥有独立的统计信息条目。

主要目的是让多个 bind 行共享相同的 IP:端口,但不共享监听器中的同一线程,从而使系统能够将传入的连接分发到多个队列,绕过 HAProxy 内部的队列负载均衡。目前,已知 Linux 3.9 及以上版本支持此功能。另请参见上方的“shards”关键字,该关键字可自动复制“bind”行,并将其分配到多个线程组中。

该关键字与反向 HTTP 绑定兼容。然而,禁止为此类监听器指定跨越多个线程组的线程集,因为这可能导致 “nbconn” 无法按预期工作。

tls-tickets

tls-tickets

此设置仅在编译时启用 OpenSSL 支持时可用。它启用无状态会话恢复(RFC 5077 TLS 票据扩展)。默认启用,但若通过“ssl-default-bind-options”中提到的“no-tls-tickets”全局禁用了该功能,则可能需要在“bind”行上选择性地重新启用此功能。另请参阅“no-tls-tickets”绑定关键字。

tls-ticket-keys <keyfile>

tls-ticket-keys <keyfile>

设置用于加载 TLS 会话票证密钥的文件。密钥长度需为 48 字节或 80 字节,具体取决于使用 aes128 或 aes256,以 base64 编码,每行一个密钥(例如:OpenSSL rand 80 | OpenSSL base64 -A | xargs echo)。第一个密钥决定后续密钥所用的长度:不可混合使用 aes128 和 aes256 密钥。密钥数量由 TLS_TICKETS_NO 构建选项指定(默认值为 3),文件中至少需存在相同数量的密钥。最后 TLS_TICKETS_NO 个密钥用于解密,倒数第二个密钥用于加密。通过仅向文件追加新密钥并重载进程,即可实现密钥的简便轮换。密钥必须定期轮换(例如每 12 小时一次),否则完美前向保密将被破坏。建议将密钥存储于非持久化存储(如 tmpfs)中,避免写入硬盘(提示:使用 tmpfs 并禁用交换这些文件)。生命周期提示可通过 tune.ssl.timeout 进行调整。

transparent

transparent

为可选关键字,仅在特定 Linux 内核上受支持。该关键字表示即使地址不属于本地主机,也应将其绑定,并且针对这些地址的任何数据包都将被拦截,效果如同这些地址已本地配置。通常需要启用 IP 转发。请注意!请勿将此关键字与默认地址 ‘*’ 一同使用,否则会导致指定端口的所有流量被重定向。该关键字仅在 HAProxy 编译时 USE_LINUX_TPROXY=1 时可用。此参数仅与 TCPv4 和 TCPv6 套接字兼容,具体取决于内核版本。部分发行版内核包含该功能的后向移植,因此请向供应商确认支持情况。

uid <uid>

uid <uid>

设置 Unix 套接字的所有者为指定的系统用户 ID。该设置也可在全局段的 “unix-bind” 语句中默认配置。请注意,某些平台会直接忽略此设置。该设置与 “user” 设置等效,区别在于使用用户数字 ID 而非用户名。该设置对非 Unix 套接字无效。

user <user>

user <user>

设置 Unix 套接字的所有者为指定的系统用户。该设置也可在全局段的 “unix-bind” 语句中默认配置。请注意,某些平台会直接忽略此设置。此设置等效于 “uid” 设置,区别在于使用用户名而非其 UID。该设置对非 Unix 套接字无效。

v4v6

v4v6

为可选关键字,仅在大多数最新系统(包括 Linux 内核版本 ≥ 2.4.21)中受支持。当使用默认地址时,该关键字用于将套接字同时绑定至 IPv4 和 IPv6。在默认仅绑定 IPv6 的系统上,此操作有时为必需。对非 IPv6 套接字无影响,且会被 “v6only” 选项覆盖。

v6only

v6only

可选关键字,仅在最新系统(包括 Linux 内核版本 ≥ 2.4.21)中受支持。当监听器使用默认地址时,该关键字用于将套接字绑定至 IPv6。与全局设置相比,此方式按监听器粒度进行绑定,有时更受青睐。该选项对非 IPv6 套接字无影响,且优先级高于 “v4v6” 选项。

verify [none|optional|required]

verify [none|optional|required]

此设置仅在编译时启用了 OpenSSL 支持时可用。若设置为 none,则不请求客户端证书。这是默认行为。其他情况下,将请求客户端证书。若客户端在请求后未提供证书,且 verify 设置为 required,则握手将被中止;若设置为 optional,则握手将继续。客户端提供的证书始终使用 ca-file 中的 CA 以及可选的 crl-file 中的 CRL 进行验证。验证失败时,无论 verify 选项为何,握手均会被中止,除非错误码与 ca-ignore-err 或 crt-ignore-err 中列出的错误码完全匹配。

5.2. 服务器和默认服务器选项

“server” 和 “default-server” 关键字支持若干设置,这些设置均作为参数形式在服务器行中传递。参数的出现顺序无关紧要,且所有设置均为可选。部分设置为单个单词(布尔值),而其他设置在其后需跟一个或多个值。此时,值必须紧随设置名称之后。除 default-server 外,若使用这些设置,必须在服务器地址之后指定:

server <name> <address>[:port] [settings ...]
default-server [settings ...]

请注意,所有这些设置均同时支持 server 和 default-server 关键字,但 id 仅支持 server 关键字。

当前支持的设置如下:

addr <ipv4|ipv6>

addr <ipv4|ipv6>

可用于以下上下文:tcp、http、log

使用 “addr” 参数,可指定不同的 IP 地址用于发送健康检查或探测 agent-check。在某些服务器上,为特定组件分配一个独立的 IP 地址可能是有益的,该组件能够执行更复杂的测试,这些测试相较于应用程序本身更适合用于健康检查。若未设置 “check” 参数,则此参数将被忽略。另请参见 “port” 参数。

agent-check

agent-check

可用于以下上下文:tcp、http、log

启用一个独立于常规健康检查的辅助代理检查。代理健康检查通过向由 “agent-port” 参数设置的端口建立 TCP 连接,并读取以首个遇到的 ‘\r’ 或 ‘\n’ 结尾的 ASCII 字符串来完成。该字符串由一系列以空格、制表符或逗号分隔的单词组成,顺序不限,每个单词由以下内容构成:

  • 以 ASCII 格式表示的正整数百分比,例如 “75%"。采用此格式的值将根据 HAProxy 启动时配置的服务器初始权重按比例设置权重。请注意,权重为零时在统计信息页面上显示为 “DRAIN”,因为其对服务器的影响相同(服务器被从负载均衡池中移除)。这是设置服务器权重的旧有方式。建议使用 “weight:” 前缀进行设置。

  • 字符串 “weight:” 后接一个正整数或正整数百分比,中间无空格。若值以 ‘%’ 符号结尾,则新权重将按服务器初始权重成比例计算。否则,该值被视为绝对权重,必须介于 0 到 256 之间。属于运行静态负载均衡算法的服务器组的服务器具有更严格的限制,因为权重一旦设定便不可更改。因此,此类服务器仅接受 0 和 100%(或 0 和初始权重)作为有效值。更改立即生效,但某些负载均衡算法需要一定数量的请求才能考虑权重变化。请注意,统计信息页面上权重为 0 的服务器会显示为 “DRAIN”,因其对服务器的影响相同(即从负载均衡组中移除)。

  • 字符串 “maxconn:” 后跟一个整数(两者之间无空格)。以这种格式指定的值将设置服务器的 maxconn。需将通告的最大连接数乘以使用此健康检查的负载均衡器数量以及不同后端的数量,以获得服务器可能接收的总连接数。例如:maxconn:30

  • 字符串 “ready”。这将把服务器的管理状态切换至 READY 模式,从而取消任何 DRAIN 或 MAINT 状态

  • 关键字 “drain”。这会将服务器的管理状态设为 DRAIN 模式,使其不再接受任何新的连接,除非是通过会话保持机制已接受的连接。

  • 单词 “maint”。这将把服务器的管理状态设为 MAINT 模式,使其完全不再接受任何新连接,并停止健康检查。

  • “down”、“fail” 或 “stopped” 这些词,可选地后跟一个由井号(#)分隔的描述字符串。以上所有标记均将服务器的运行状态设为 DOWN,但由于这些词本身会显示在统计信息页面上,因此管理员可以据此判断该状态是预期的还是意外的:服务可能被有意停止,可能显示为运行状态但未能通过某些有效性检测,或可能因进程缺失或端口无响应等原因被识别为 DOWN。

  • 字符串 “up” 将服务器的操作状态设为 UP,前提是健康检查也报告服务可访问。

代理未通告的参数不会被更改。例如,某个代理可能仅用于监控 CPU 使用率,仅报告相对权重,且从不干预运行状态。类似地,代理也可设计为终端用户界面,包含三个单选按钮,允许管理员仅更改服务器的管理状态。然而,需要注意的是,只有代理自身才能撤销其操作,因此若通过代理将服务器设置为 DRAIN 模式或 DOWN 状态,则代理必须实现相应的等效动作,以使服务恢复运行。

连接代理失败不被视为错误,因为连接性由启用“check”参数的常规健康检查进行测试。请注意,停止报告“down”的代理并非良策,因为只有报告“up”的代理才能再次将服务器置为可用状态。请注意,Unix 统计套接字上的 CLI 也能够强制代理结果,以便在必要时绕过故障代理。

必须设置 “agent-port” 参数。另请参见 “agent-inter” 和 “no-agent-check” 参数。

agent-send <string>

agent-send <string>

可用于以下上下文:tcp、http、log

若指定此选项,HAProxy 将在连接时将给定字符串(原样)发送至代理服务器。例如,可将后端名称编码至该字符串中,从而使代理能够根据后端发送不同的响应。若希望以换行符终止请求,请确保包含 ‘\n’。

agent-inter <delay>

agent-inter <delay>

可用于以下上下文:tcp、http、log

“agent-inter” 参数设置两次代理检查之间的间隔为 <delay> 毫秒。若未指定,延迟默认为 2000 毫秒。

与所有其他基于时间的参数一样,该参数可使用以下任意显式单位输入:{us, ms, s, m, h, d}。若未设置“timeout check”,则“agent-inter”参数也用作代理检查的超时值。为减少在相同硬件上托管多个服务器时产生的“共振”效应,所有服务器的代理检查和健康检查将按微小的时间偏移依次启动。也可通过全局配置项“spread-checks”在代理检查和健康检查间隔中添加一定的随机噪声。例如,当多个后端使用相同服务器时,此设置具有实际意义。

另请参见 “agent-check” 和 “agent-port” 参数。

agent-addr <addr>

agent-addr <addr>

可用于以下上下文:tcp、http、log

“agent-addr” 参数用于设置代理检查的地址。

可以将 agent-check 任务委派至其他目标,从而实现统一管理 HAProxy 中定义的服务器状态和权重,尤其适用于无法实现自感知和自管理的服务场景。可指定 IP 地址或主机名,系统将自动解析。

agent-port <port>

agent-port <port>

可用于以下上下文:tcp、http、log

“agent-port” 参数用于设置代理检查所使用的 TCP 端口。

另请参见 “agent-check” 和 “agent-inter” 参数。

allow-0rtt

allow-0rtt

可用于以下上下文:tcp、http、log、peers、ring

在使用 TLS 1.3 时,允许向服务器发送早期数据。请注意,仅当客户端使用了早期数据,或后端配置了 “retry-on” 并包含 “0rtt-rejected” 关键字时,才会发送早期数据。使用 QUIC 时,0-RTT 支持 QuicTLS、OpenSSL >= 3.5.2 和 AWS-LC。使用 TCP/TLS 时,0-RTT 仅支持 OpenSSL。

alpn <protocols>

alpn <protocols>

可用于以下上下文:tcp、http

启用 TLS ALPN 扩展,并在 ALPN 上声明指定的协议列表作为支持的协议。协议列表由逗号分隔的协议名称组成,例如:http/1.1,http/1.0(不带引号)。此功能要求 SSL 库在编译时启用了 TLS 扩展支持(可通过 HAProxy -vv 检查)。ALPN 扩展取代了早期的 NPN 扩展。连接至 HTTP/2 服务器时必须使用 ALPN。若需通过 QUIC 服务器使用 HTTP/3,同样必须启用 ALPN;当 QUIC 服务器未设置 “alpn” 时,“h3” 作为默认值。OpenSSL 1.0.2 之前的版本不支持 ALPN,仅支持现已废弃的 NPN 扩展。若预期同时支持 HTTP/2 和 HTTP/1.1,可按优先级顺序声明两者,如下所示:

server 127.0.0.1:443 ssl crt pub.pem alpn h2,http/1.1

另请参见 “ws”,以对 WebSocket 流使用替代的 ALPN。

backup

backup

可用于以下上下文:tcp、http、log

当服务器行中包含 “backup” 时,仅当所有其他非备用服务器均不可用时,该服务器才会参与负载均衡。尽管如此,携带引用该服务器的持久性 Cookie 的请求仍会始终被服务。默认情况下,仅使用第一个运行正常的备用服务器,除非在后端中设置了 “allbackups” 选项。参见 “no-backup” 和 “allbackups” 选项。

ca-file <cafile>

ca-file <cafile>

可用于以下上下文:tcp、http、log、peers、ring

此设置仅在编译时启用 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载用于验证服务器证书的 CA 证书。可以加载包含多个 CA 的目录,在此情况下,HAProxy 将尝试加载目录中所有 “.pem”、".crt”、".cer" 和 .crl 文件,以点开头的文件将被忽略。

为使用系统自带的受信任 CA,可将 @system-ca 参数用于替代 cafile。该目录的位置可通过设置 SSL_CERT_DIR 环境变量进行覆盖。

cc <algo>

cc <algo>

可用于以下上下文:tcp、http、log、peers、ring

此设置仅在定义了 TCP_CONGESTION 的系统上可用,并已在 Linux 和 FreeBSD 上完成验证。该设置指定一个 TCP 拥塞控制算法名称,并配置出站连接使用该算法。典型名称包括 “reno” 或 “cubic”,具体取决于操作系统。在某些系统上,配置特定算法可能需要特殊权限。在 Linux 上,可用算法列于 sysctl “net.ipv4.tcp_available_congestion_control”,无需权限即可使用的算法位于 “net.ipv4.tcp_allowed_congestion_control”。若需访问需要额外权限的算法,可能需要 “cap_net_admin” 能力(参见全局段中的 “setcap”)。若无法配置特定拥塞控制算法,将保持默认算法不变。另请参阅:“cc” 绑定关键字(第 5.1 节 )。

check

check

可用于以下上下文:tcp、http、log

本选项用于启用对服务器的健康检查: - 未设置时,不执行健康检查,服务器始终被视为可用。 - 设置但未配置其他检查方法时,当在最高配置的传输层成功建立连接时,认为服务器可用。默认情况下为 TCP,当设置 “ssl” 或 “check-ssl” 时则为 SSL/TLS,且可与连接前缀(如启用 “send-proxy” 或 “check-send-proxy” 时的 PROXY 协议头)结合使用。动态服务器的处理行为略有不同,请参阅以下段落获取详细信息。 - 设置且定义了应用层健康检查时,应用层交互将在配置的传输层之上执行,且仅当所有交互均成功时,才认为服务器可用。

默认情况下,健康检查在服务器配置的相同地址和端口上执行,使用相同的封装参数(如 SSL/TLS、proxy-protocol 头等)。可以使用“addr”更改目标地址,使用“port”更改端口。设置后,系统将认为服务器不在服务端口上进行健康检查,且不再复用配置的封装参数。如需发送连接头,必须显式设置“check-send-proxy”;如需使用 SSL/TLS,必须显式设置“check-ssl”。

请注意,动态服务器不会隐式配置 ssl 和 PROXY 协议。 在此情况下,即使未覆盖检查端口,若需启用,也必须显式使用 “check-ssl” 和 “check-send-proxy”。

当在服务器行中设置 “sni” 或 “alpn” 时,其值不会用于健康检查,必须使用 “check-sni” 或 “check-alpn”。

健康检查流量的默认源地址与后端中定义的地址相同。 可以使用“source”关键字进行更改。

可以使用 “inter” 关键字设置健康检查的间隔时间,使用 “rise” 和 “fall” 关键字可定义需要多少次成功或失败的健康检查,才能将服务器标记为可用或不可用。

可选的应用层健康检查可通过配置 “option httpchk”、“option mysql-check”、“option smtpchk”、“option pgsql-check”、“option ldap-check” 或 “option redis-check” 实现。

示例:

# simple tcp check
backend foo
  server s1 192.168.0.1:80 check
# this does a tcp connect + tls handshake
backend foo
  server s1 192.168.0.1:443 ssl check
# simple tcp check is enough for check success
backend foo
  option tcp-check
  tcp-check connect
  server s1 192.168.0.1:443 ssl check

check-reuse-pool

check-reuse-pool

可用于以下上下文:tcp、http

此选项允许在可用时复用空闲连接,而非打开专用连接。检查完成后,连接将重新插入连接池。主要目标是限制对特定服务器的连接打开与关闭次数。此功能仅与 http-check 规则集兼容,对其他检查类型将静默忽略。此外,后端的复用策略应设置为积极模式,因为每次检查尝试均在专用会话上执行。

为简化配置,若在服务器行或通过自定义的 tcp-check connect 规则定义了任何特定的检查连接选项,则此选项将被静默忽略。

此选项在充当被动反向 HTTP 网关的服务器上会自动启用,因为此类服务器仅支持通过复用连接。

另请参见:“check-pool-conn-name”

check-send-proxy

check-send-proxy

可用于以下上下文:tcp、http

此选项强制在发出出站健康检查时发送 PROXY 协议行,无论服务器在正常流量中是否使用 send-proxy。默认情况下,若健康检查已启用正常流量的 PROXY 协议,且未指定“port”或“addr”指令,则健康检查会启用 PROXY 协议。然而,若存在此类指令,则需使用“check-send-proxy”选项以强制启用该协议。有关更多信息,请参见“send-proxy”指令。

check-alpn <protocols>

check-alpn <protocols>

可用于以下上下文:tcp、http

定义通过 ALPN 广告的协议。协议列表由逗号分隔的协议名称组成,例如:http/1.1,http/1.0(不带引号)。若未设置,则使用服务器 ALPN。

check-pool-conn-name <name>

check-pool-conn-name <name>

可用于以下上下文:tcp、http

当对检查执行连接复用时,若已设置 <name>,则将其用作连接标识符,以匹配连接池中的对应连接。此设置相当于 “pool-conn-name” 服务器关键字。若当前选项未使用,则 “check-sni” 将作为备用方案。

另请参见:“check-reuse-pool”

check-proto <name>

check-proto <name>

可用于以下上下文:tcp、http

强制 multiplexer 协议用于服务器健康检查连接。该协议必须与健康检查类型(TCP 或 HTTP)兼容,且必须可在后端侧使用。可用协议列表请参见 HAProxy -vv.。协议属性包括:模式(TCP/HTTP)、侧边(FE/BE)、multiplexer 名称及其标志。

部分协议在服务器端存在队首阻塞问题(flag=HOL_RISK)。此外,部分协议不支持升级(flag=NO_UPG)。HTX 兼容性状态亦已报告(flag=HTX)。

以下协议可用于服务器行中 “check-proto” 指令的参数:

h2  : mode=HTTP  side=FE|BE  mux=H2    flags=HTX|HOL_RISK|NO_UPG
fcgi: mode=HTTP  side=BE     mux=FCGI  flags=HTX|HOL_RISK|NO_UPG
h1  : mode=HTTP  side=FE|BE  mux=H1    flags=HTX|NO_UPG
none: mode=TCP   side=FE|BE  mux=PASS  flags=NO_UPG
quic: mode=HTTP  side=FE|BE  mux=QUIC  flags=HTX|NO_UPG|FRAMED
spop: mode=SPOP  side=BE     mux=SPOP  flags=HOL_RISK|NO_UPG

此选项的原理是绕过为连接到该服务器的健康检查连接选择最佳多路复用协议。若未定义,则使用服务器配置中指定的协议;若已设置,则使用该设置。

如果配置了 ALPN 或 NPN 设置,指定的协议应与多路复用器的协议兼容,以避免出现任何问题。例如,若设置为 “proto h1”,则不应将 ALPN 设置为 “h2”。

QUIC 检查配置尚未完全实现。首先,QUIC 检查仅可对 QUIC 服务器执行。其次,若在 QUIC 服务器上指定了一个或多个检查专用的连接参数,检查协议将回退至使用 TCP。

check-sni-auto

check-sni-auto

可用于以下上下文:tcp、http、log

此选项在通过 SSL 执行健康检查时,若尚未设置值,则启用自动 SNI 选择。默认启用,但可作为“server”指令的设置,用于重置从“default-server”指令继承的任何“no-check-sni-auto”设置。也可作为“default-server”设置,用于重置之前设置的“default-server”“no-check-sni-auto”设置。

对于 HTTPS 连接,SNI 会自动选择,但前提是不存在 “http-check connect” 规则。在此情况下,所选 SNI 基于通过 “option httpchk” 指令或 “http-check send” 规则指定的主机头值。对于 “http-check connect” 规则,不进行自动选择。对于其他协议,该选项被忽略。

若在健康检查中使用 SNI 的自动选择,则当设置 “check-reuse-pool” 时,该值将被分配给连接名称,除非被服务器关键字 “check-pool-conn-name” 覆盖。

请参阅“sni-auto”选项,以启用代理流量的自动 SNI 选择。

check-sni <sni>

check-sni <sni>

可用于以下上下文:tcp、http、log

此选项允许指定在通过 SSL 执行健康检查时使用的 SNI。仅可使用字符串设置 <sni>。如需为代理流量设置 SNI,请参阅 “sni”。

check-ssl

check-ssl

可用于以下上下文:tcp、http、log

此选项强制对所有健康检查使用 SSL 加密,无论服务器在正常流量中是否使用 SSL。当显式指定 “port” 或 “addr” 指令且健康检查不继承 SSL 设置时,通常使用此选项。需要注意的是,此选项在检查下方插入了 SSL 传输层,使得简单的 TCP 连接检查变为 SSL 连接检查,从而取代了旧的 ssl-hello-chk。最常见的用法是结合 “httpchk” 与 SSL 检查发送 HTTPS 检查。所有 SSL 设置对健康检查和流量均通用(例如加密套件)。有关更多信息,请参阅 “ssl” 选项,使用 “no-check-ssl” 可禁用此选项。

check-via-socks4

check-via-socks4

可用于以下上下文:tcp、http、log

此选项启用通过上游 SOCKS4 代理发起的出站健康检查。默认情况下,即使正常流量已启用 SOCKS 隧道,健康检查也不会经过 SOCKS 隧道。

ciphers <ciphers>

ciphers <ciphers>

可用于以下上下文:tcp、http、log、peers、ring

此设置仅在编译时启用了 OpenSSL 支持时可用。该选项用于设置在与服务器进行 SSL/TLS 握手时协商的加密算法列表描述字符串。字符串格式由 OpenSSL 手册页中的“man 1 ciphers”定义。有关背景信息和建议,请参阅例如 (https://wiki.mozilla.org/Security/Server_Side_TLS ) 和 (https://mozilla.github.io/server-side-tls/ssl-config-generator/ )。对于 TLSv1.3 加密套件配置,请参阅“ciphersuites”关键字。

ciphersuites <ciphersuites>

ciphersuites <ciphersuites>

可用于以下上下文:tcp、http、log、peers、ring

此设置仅在编译时启用了 OpenSSL 支持且使用 OpenSSL 1.1.1 或更高版本构建 HAProxy 时可用。该选项用于设置在与服务器进行 TLS 1.3 握手时协商的加密算法列表描述字符串。字符串格式由 OpenSSL 手册页中“ciphersuites”章节下的“man 1 ciphers”定义。关于 TLSv1.2 及更早版本的加密算法配置,请参阅“ciphers”关键字。

client-sigalgs <sigalgs>

client-sigalgs <sigalgs>

可用于以下上下文:tcp、http、log、peers、ring

此设置仅在编译时启用 OpenSSL 支持时可用。它用于设置描述与客户端认证相关的签名算法列表的字符串,该列表在协商过程中确定。字符串格式由 OpenSSL 手册页中的“man 3 SSL_CTX_set1_client_sigalgs”定义。若未明确特定使用场景,不建议使用此设置。

cookie <value>

cookie <value>

可以用于以下上下文:http

“cookie” 参数用于设置分配给服务器的 cookie 值 <value>。该值将在传入的请求中被检查,首个拥有相同值的可用服务器将被选中。在 cookie 插入或重写模式下,该值将被分配给发送给客户端的 cookie。多个服务器共享相同的 cookie 值并无不妥,实际上在正常服务器与备用服务器之间这种情况较为常见。另请参见后端段中的 “cookie” 关键字。

crl-file <crlfile>

crl-file <crlfile>

可用于以下上下文:tcp、http、log、peers、ring

此设置仅在编译时启用 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载证书吊销列表,以验证服务器证书。

crt <cert>

crt <cert>

可用于以下上下文:tcp、http、log、peers、ring

此设置仅在编译时启用 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载证书及其关联的私钥。该文件可通过将两个 PEM 文件合并而成。当服务器发送客户端证书请求时,将发送此证书。

如果文件中不包含私钥,HAProxy 将尝试在相同路径下加载以 “.key” 为后缀的密钥(前提是已相应设置 “ssl-load-extra-files” 选项)。

curves <curves>

curves <curves>

可用于以下上下文:tcp、http、log、peers、ring

此设置仅在编译时启用 OpenSSL 支持时可用。它用于设置在使用 ECDHE 进行 SSL/TLS 握手时协商的椭圆曲线算法列表(“曲线套件”)的描述字符串。字符串格式为以冒号分隔的曲线名称列表。例如:X25519 : P-256(不带引号)

disabled

disabled

可用于以下上下文:tcp、http、log

“disabled” 关键字将服务器置于“disabled”状态。这意味着该服务器在维护模式下被标记为不可用,除持久连接模式允许的连接外,其他任何连接均无法到达它。该设置非常适合用于部署新服务器,因为正常流量永远不会触及这些服务器,同时仍可通过使用 force-persist 机制对服务进行测试。另请参见“enabled”设置。

enabled

enabled

可用于以下上下文:tcp、http、log

此选项可作为服务器指令使用,用于重置从 default-server 指令继承的任何 disabled 设置。也可作为 default-server 指令使用,用于重置之前设置的 default-server disabled 设置。

error-limit <count>

error-limit <count>

可用于以下上下文:tcp、http、log

若启用健康检查,参数 “error-limit” 指定触发 “on-error” 选项所选事件的连续错误次数。默认值为 10 次连续错误。

另请参阅“check”、“error-limit”和“on-error”。

fall <count>

fall <count>

可用于以下上下文:tcp、http、log

“fall” 参数表示,当服务器连续出现 <count> 次健康检查失败后,将被视为不可用。若未指定,该值默认为 3。另请参阅 “check”、“inter” 和 “rise” 参数。

force-sslv3

force-sslv3

可用于以下上下文:tcp、http、log、peers、ring

此选项强制在与服务器通信时仅使用 SSLv3。在高连接速率场景下,SSLv3 通常比 TLS 对应版本的开销更低。该选项也可在全局语句 “ssl-default-server-options” 中使用。另请参见 “ssl-min-ver” 和 “ssl-max-ver”。

force-tlsv10

force-tlsv10

可用于以下上下文:tcp、http、log、peers、ring

此选项强制在与服务器通信时仅使用 TLSv1.0 版本的 SSL。该选项也可在全局语句 “ssl-default-server-options” 中使用。另请参阅 “ssl-min-ver” 和 “ssl-max-ver”。

force-tlsv11

force-tlsv11

可用于以下上下文:tcp、http、log、peers、ring

此选项强制在与服务器通信时仅使用 TLSv1.1 版本的 SSL。该选项也可在全局语句 “ssl-default-server-options” 中使用。另请参阅 “ssl-min-ver” 和 “ssl-max-ver”。

force-tlsv12

force-tlsv12

可用于以下上下文:tcp、http、log、peers、ring

此选项强制在与服务器通信时仅使用 TLSv1.2 版本,前提是使用 SSL。该选项也可在全局语句 “ssl-default-server-options” 中使用。另请参阅 “ssl-min-ver” 和 “ssl-max-ver”。

force-tlsv13

force-tlsv13

可用于以下上下文:tcp、http、log、peers、ring

此选项强制在与服务器通信时仅使用 TLSv1.3 版本,前提是启用 SSL。该选项也可在全局语句 “ssl-default-server-options” 中使用。另请参阅 “ssl-min-ver” 和 “ssl-max-ver”。

guid <string>

guid <string>

可用于以下上下文:tcp、http、log

为该服务器指定一个区分大小写的全局唯一 ID。该 ID 必须在所有 HAProxy 配置中所有对象类型间保持唯一。有关其格式的更多信息,请参阅 “guid” 代理关键字的描述。另请参阅 “shm-stats-file”。

hash-key <key>

hash-key <key>

可用于以下上下文:tcp、http、log

指定“hash-type consistent”节点键的计算方式

参数:

<key>   <key> may be one of the following:

  id         The node keys will be derived from the server's numeric
             identifier as set from "id" or which defaults to its position
             in the server list. This is the default. Note that only the 28
             lowest bits of the ID will be used (i.e. (id % 268435456)), so
             better only use values comprised between 1 and this value to
             avoid overlap.

  id32       The node keys will be derived from the server's numeric
             identifier as set from "id" or which defaults to its position
             in the server list, but the full 32 bits of the ID will be
             used so that there is no collision. This one is not scaled
             like "id" is, so it is recommended to either always use it
             with a hash function (see "hash-key") or with explicitly
             assigned ID values that are evenly distributed over the 32-bit
             space.

  guid       The node keys will be derived from the server's guid, when
             available, otherwise they will fall back on "id". The benefit
             is that it does not depend on ordering at all, only on an
             internal stable identifier that can be replicated across many
             load balancers.

  addr       The node keys will be derived from the server's address, when
             available, or else fall back on "id".

  addr-port  The node keys will be derived from the server's address and
             port, when available, or else fall back on "id".

“addr” 和 “addr-port” 选项在多个 HAProxy 进程对同一组服务器进行流量负载均衡的场景中可能非常有用。如果每个进程的服务器顺序不同(例如,由于 DNS 记录解析顺序不同),则此机制可使各个独立的 HAProxy 进程就路由决策达成一致。请注意:“balance random” 也使用 “hash-type consistent”,其分发质量取决于键的质量。

healthcheck <name>

healthcheck <name>

可用于以下上下文:tcp、http

指定用于对服务器执行检查的健康检查段。

参数:

<name>    is the health-check section name.

借助此选项,可使用预服务器健康检查配置,而非使用代理配置。另请参见“健康检查段”。

id <value>

id <value>

可用于以下上下文:tcp、http、log

为服务器设置持久化 ID。该 ID 必须为 32 位正整数,且在代理范围内唯一。若未设置,将自动分配一个未使用的 ID。首次分配的值为 1。当前该 ID 仅在统计信息中返回,当使用一致性哈希算法且“hash-key”设置为“id”(默认值)时,用于定位负载均衡节点。此时仅使用该值的低 28 位(即 (id % 268435356)),因此建议仅使用 1 至该值之间的数值,以避免重叠。

idle-ping <delay>

idle-ping <delay>

可用于以下上下文:tcp、http、log

定义用于对空闲后端连接进行周期性存活检测的时间间隔。如果对等节点在下一次预定检测前无法响应,则关闭该连接。此关键字针对后端侧,因此可用于检查空闲连接是否仍可用。请注意,这不会阻止连接在空闲连接池清理时被销毁。

此功能依赖于特定底层协议支持。目前,仅 H2 mux 实现了该功能。 其他协议会直接忽略空闲 ping。

此选项在使用反向 HTTP 时尤为有用。在服务器行上设置该选项,有助于对等节点监听传入连接,并将其关联到相应的服务器,以便后续重用流量转发。

init-addr {last | libc | none | <ip>},[...]*

init-addr {last | libc | none | <ip>},[...]*

可用于以下上下文:tcp、http、log

在服务器使用完全限定域名(FQDN)时,指定其地址在启动时应按何种顺序进行解析。

将依次尝试列表中以逗号分隔的方法,直至某方法成功为止。若遍历完列表仍未找到有效方法,则抛出错误。方法 “last” 表示采用状态文件中记录的地址(参见 “server-state-file”)。方法 “libc” 使用 libc 内部解析器(根据操作系统和构建选项,使用 gethostbyname() 或 getaddrinfo())。方法 “none” 明确表示服务器应以无有效 IP 地址的 down 状态启动。该选项可用于在启动时忽略某些 DNS 问题,待后续情况修复后再恢复。最后,可直接提供一个 IP 地址(IPv4 或 IPv6)。该地址可以是服务器当前已知的地址(例如由配置生成器填充),也可以是用于捕获旧会话的虚拟服务器地址,以便向客户端返回合理的错误信息。当使用 “first” 负载均衡算法时,该 IP 地址可指向一个假服务器,用于触发动态创建新实例。此选项默认值为 “last,libc”,表示优先使用状态文件中记录的上一次地址(若存在),否则使用 libc 解析器。这确保了与历史行为的持续兼容性。使用内部解析器时,通常建议禁用基于 libc 的解析,或显式指定(详见 section 5.3 )。

示例 1:

defaults
    # never fail on address resolution
    default-server init-addr last,libc,none

示例 2:

defaults
    # disable libc resolution in combination with resolvers
    default-server init-addr last,none

inter <delay>

inter <delay>
fastinter <delay>
downinter <delay>

可用于以下上下文:tcp、http、log

“inter” 参数用于设置两次连续健康检查之间的间隔,单位为 <delay> 毫秒。若未指定,延迟默认为 2000 毫秒。也可使用 “fastinter” 和 “downinter” 根据服务器状态优化检查间隔:

             Server state                   |         Interval used
    ----------------------------------------+----------------------------------
     UP 100% (non-transitional)             | "inter"
    ----------------------------------------+----------------------------------
     Transitionally UP (going down "fall"), | "fastinter" if set,
     Transitionally DOWN (going up "rise"), | "inter" otherwise.
     or yet unchecked.                      |
    ----------------------------------------+----------------------------------
     DOWN 100% (non-transitional)           | "downinter" if set,
                                            | "inter" otherwise.
    ----------------------------------------+----------------------------------

与所有其他基于时间的参数一样,它们可以以任意其他显式单位输入,包括 { us, ms, s, m, h, d }。若未设置 “timeout check”,则 “inter” 参数还用作发送至服务器的健康检查的超时值。为减少在相同硬件上托管多个服务器时产生的“共振”效应,所有服务器的代理和健康检查将按微小的时间偏移依次启动。也可通过全局配置项 “spread-checks” 在代理和健康检查间隔中添加随机噪声。例如当多个后端使用相同服务器时,此设置具有实际意义。全局 “tune.max-checks-per-thread” 设置(若定义为非零值)将限制任意线程上同时执行的健康检查数量。为实现此目的,HAProxy 会将即将在已达到限制的线程上启动的检查放入队列,直至其他检查完成。这将导致有效检查间隔延长。在此情况下,降低 “inter” 设置的效果将非常有限,因为其无法减少检查在队列中等待的时间。

init-state { fully-up | up | down | fully-down | none }

init-state { fully-up | up | down | fully-down | none }

可用于以下上下文:tcp、http

可出现在以下段中:defaults | frontend | listen | backend

“init-state” 指令用于设置服务器的初始状态: - 当设置为 ‘fully-up’ 时,服务器被视为立即可用;若为此服务器启用了健康检查,则当所有健康检查均失败时,服务器将被置为 DOWN 状态。 - 当设置为 ‘up’ 时,服务器被视为立即可用;若为此服务器启用了健康检查,则在下一次健康检查失败时,服务器将立即被置为 DOWN 状态。 - 当设置为 ‘down’ 时,服务器初始被视为不可用;若为此服务器启用了健康检查,则在下一次健康检查成功时,服务器可被置为 UP 状态。 - 当设置为 ‘fully-down’ 时,服务器初始被视为不可用;若为此服务器启用了健康检查,则当所有健康检查均成功时,服务器将被置为 UP 状态。 - 当设置为 ’none’(默认值)时,禁用 init-state 管理。该设置可用于在该参数从 ‘default-server’ 指令继承时恢复默认行为。

服务器的初始状态在 HAProxy 实例(重新)启动时、检测到新服务器(例如通过服务发现或 DNS 解析)、动态服务器被激活、服务器退出维护模式等情况下被考虑。当服务器正在跟踪其他服务器时,此指令不可用。

示例:

# pass client traffic ONLY to Redis "master" node
backend redis-master
  mode tcp
  balance first
  option tcp-check
  tcp-check send role\r\n
  tcp-check expect string master
  server-template redis 3 _redis._tcp.redis-headless-service.sandbox.svc.cluster.local:6379 check ... init-state down

# pass traffic to the server only after 3 successful health checks
backend google-backend
  mode http
  server srv1 google.com:80 check init-state fully-down rise 3
  server srv2 google.com:80 check init-state fully-down rise 3

另请参见:“option tcp-check”,“option httpchk”

ktls <on|off> [ EXPERIMENTAL ]

ktls <on|off> [ EXPERIMENTAL ]

可用于以下上下文:tcp、http、log、peers、ring

启用或禁用套接字的 kTLS。若启用,当内核支持且加密算法兼容时,将使用 kTLS。此功能仅在 Linux 4.17 及以上版本中可用。请注意,部分网络驱动程序和/或 TLS 栈可能将 kTLS 使用限制为仅支持 TLS v1.2。参见 “force-tlsv12”。

log-bufsize <bufsize>

log-bufsize <bufsize>

可以用于以下上下文:log

“log-bufsize” 指定用于与日志后端中隐式环形缓冲区关联的日志服务器的环形缓冲区大小。未指定时,默认值为 BUFSIZE。使用更大的值会增加内存占用,但有助于防止因服务器响应缓慢而导致日志消息丢失,因为缓冲区能够容纳更多待处理的消息。此关键字仅可在日志后端段(使用 “mode log” 时)中使用。

log-proto <logproto>

log-proto <logproto>

可用于以下上下文:log、ring

“log-proto” 指定用于将事件消息转发至 log 或 ring 段中配置的服务器所使用的协议。可能的取值为 “legacy” 和 “octet-count”,分别对应 RFC6587 中的 “Non-transparent-framing” 和 “Octet counting”。“legacy” 为默认值。

maxconn <maxconn>

maxconn <maxconn>

可用于以下上下文:tcp、http

maxconn 参数指定将发送到该服务器的最大并发连接数。当传入的并发连接数超过此值时,连接将被排队,等待空闲槽位释放。该参数非常重要,可防止脆弱服务器在极端负载下宕机。若同时指定了 minconn 参数,限制将变为动态。默认值为 0,表示无限制。另请参见 minconn 和 maxqueue 参数,以及后端的 fullconn 关键字。

在 HTTP 模式下,该参数限制的是并发请求数量,而非连接数量。多个请求可能复用至服务器的单个 TCP 连接。例如,若指定 maxconn 为 50,则实际服务器连接数可能在 1 到 50 之间,但并发请求数不会超过 50。

maxqueue <maxqueue>

maxqueue <maxqueue>

可用于以下上下文:tcp、http

maxqueue 参数指定将等待在该服务器队列中的最大连接数。若达到此限制,后续请求将被重分派至其他服务器,而非无限期等待服务。此举会中断持久性,但可在目标服务器即将失效时,帮助用户快速重新登录。某些负载均衡算法(如 leastconn)会考虑此设置,若显式设置为大于零的值,则允许将请求加入服务器队列至该数值,这通常有助于在处理单数字 maxconn 值时更平滑地分摊负载。默认值为 “0”,表示队列无限制。另请参见 “maxconn” 和 “minconn” 参数以及 “balance leastconn”。

max-reuse <count>

max-reuse <count>

可用于以下上下文:http、ring

在 http 上下文中使用时:

“max-reuse” 参数指示 HTTP 连接处理器,向服务器发送新请求时,不应超过此次数复用现有连接。允许的值为 -1(默认值),表示禁用此限制,或任意正整数值。值为零将有效禁用持久连接。该参数仅用于绕过某些服务器缺陷导致的资源随时间泄漏问题。由于底层技术限制,该参数可能无法被下层完全遵守。至少对于 HTTP/2 到服务器的连接,该参数将被遵守。

在环形缓冲区上下文中使用时:

“max-reuse” 参数表示接收端 TCP 连接处理器应限制对服务器连接的复用次数,不得超过指定次数。这意味着,当同一连接上处理的消息数量达到 “max-reuse + 1” 次时,该服务器连接将被强制关闭。随后,连接将自动重新建立。在多线程环境下处理大量消息时,此举有助于更均衡地将环形缓冲区的负载分摊至多个线程。每个连接在其生命周期内始终绑定至同一 CPU 线程:与 HTTP 不同,不存在类似 syslog 事务的概念,因此只要服务器未主动关闭连接或未发生网络错误,该连接可能长期持续存在。通过定期关闭连接,可为其他线程轮流处理消息创造机会。这在 HAProxy 与日志服务器之间存在额外负载均衡层的场景中,也有助于实现日志服务器的优雅轮换。然而请注意,每次连接回收后,出站端口将进入 TIME_WAIT 状态,现代操作系统下该端口约需一分钟才能重新可用。因此,必须谨慎避免设置过低的值,以防源端口迅速耗尽。一般建议,每秒关闭连接的次数不应超过数次,且最好远低于此频率。允许的取值为 -1(默认值),表示禁用此限制,或任意正整数。与 HTTP 上下文不同,当用于接收端服务器时,“max-reuse” 为尽力而为机制:消息以批处理方式发送,因此该限制仅在每批消息处理完毕后检查一次。

minconn <minconn>

minconn <minconn>

可用于以下上下文:tcp、http

当设置 “minconn” 参数时,maxconn 限制将变为动态限制,随后端负载变化而调整。服务器始终至少接受 <minconn> 个连接,且不超过 <maxconn> 个连接。当后端并发连接数少于 <fullconn> 时,该限制将在两个数值之间动态调整。这使得在正常负载下可限制服务器负载,而在重要负载下可进一步提升处理能力,同时在异常负载期间避免服务器过载。另请参见 “maxconn” 和 “maxqueue” 参数,以及 “fullconn” 后端关键字。

namespace <name>

namespace <name>

可用于以下上下文:tcp、http、log、peers、ring

在 Linux 上,可以指定套接字所属的网络命名空间。该指令允许显式地将服务器绑定到与默认命名空间不同的命名空间。有关网络命名空间的更多详细信息,请参阅操作系统的文档。

no-agent-check

no-agent-check

可用于以下上下文:tcp、http、log

此选项可作为“server”指令使用,以重置从“default-server”指令继承的任何“agent-check”设置作为默认值。也可作为“default-server”指令使用,以重置之前设置的“default-server”“agent-check”设置。

no-backup

no-backup

可用于以下上下文:tcp、http、log

此选项可作为“服务器”指令使用,以重置从“default-server”指令继承的任何“backup”设置作为默认值。也可作为“default-server”指令使用,以重置之前设置的“default-server”“backup”设置。

no-check

no-check

可用于以下上下文:tcp、http、log

此选项可作为“server”指令使用,用于重置从“default-server”指令继承的任何“check”设置作为默认值。也可作为“default-server”指令使用,用于重置之前设置的“default-server”“check”设置。

no-check-reuse-pool

no-check-reuse-pool

可用于以下上下文:tcp、http

此选项会取消从 “default-server” 继承的任何先前设置的 “check-reuse-pool”。所有检查将在其专用连接上执行。

no-check-sni-auto

no-check-sni-auto

可用于以下上下文:tcp、http、log

此选项可作为“server”设置使用,以禁用默认启用的 SSL 健康检查中的自动 SNI 选择。

请参阅 “no-sni-auto” 选项,以禁用代理流量的自动 SNI 选择。

no-check-ssl

no-check-ssl

可用于以下上下文:tcp、http、log

此选项可作为“server”指令使用,用于重置从“default-server”指令继承的“check-ssl”设置(作为默认值)。也可作为“default-server”指令使用,用于重置之前设置的“default-server”“check-ssl”设置。

no-renegotiate

no-renegotiate

可用于以下上下文:tcp、http、log

此设置仅在编译时启用 OpenSSL 支持时可用。它会禁用指定 SSL 后端的重新协商机制,无论是传统的不安全方式,还是较新的“安全重新协商”方式(RFC 5746 TLS 重新协商指示扩展)。该选项也可在全局语句 ssl-default-server-options 中使用。TLS 1.3 中已不再支持重新协商。若未指定 renegotiate 或 no-renegotiate,则保留 SSL 库的默认行为。请注意,例如 OpenSSL 库默认启用安全重新协商,而 AWS-LC 则默认禁用。另见 renegotiate。

no-send-proxy

no-send-proxy

可用于以下上下文:tcp、http

此选项可作为“server”指令使用,用于重置从“default-server”指令继承的“send-proxy”设置(默认值)。也可作为“default-server”指令使用,用于重置之前设置的“default-server”“send-proxy”选项。

no-send-proxy-v2

no-send-proxy-v2

可用于以下上下文:tcp、http

此选项可作为“server”指令使用,用于重置从“default-server”指令继承的任何“send-proxy-v2”设置。也可作为“default-server”指令使用,用于重置之前设置的“default-server”“send-proxy-v2”选项。

no-send-proxy-v2-ssl

no-send-proxy-v2-ssl

可用于以下上下文:tcp、http

此选项可作为“server”指令使用,用于重置从“default-server”指令继承的任何“send-proxy-v2-ssl”设置。也可作为“default-server”指令使用,用于重置之前设置的“default-server”“send-proxy-v2-ssl”设置。

no-send-proxy-v2-ssl-cn

no-send-proxy-v2-ssl-cn

可用于以下上下文:tcp、http

此选项可作为“server”指令使用,用于重置从“default-server”指令继承的任何“send-proxy-v2-ssl-cn”设置。也可作为“default-server”指令使用,用于重置之前设置的“default-server”“send-proxy-v2-ssl-cn”设置。

no-sni-auto

no-sni-auto

可用于以下上下文:tcp、http、log、peers、ring

此选项可作为“server”设置使用,以禁用默认启用的自动 SNI 选择功能。

请参阅 “no-check-sni-auto” 选项,以禁用 SSL 健康检查中的自动 SNI 选择。

no-ssl

no-ssl

可用于以下上下文:tcp、http、log、peers、ring

此选项可作为“server”指令使用,用于重置从“default-server”指令继承的任何“ssl”设置。也可作为“default-server”指令使用,用于重置之前设置的“default-server”“ssl”设置。

请注意,使用 default-server ssl 设置和 no-ssl 在服务器上将初始化 SSL 连接,因此后续可通过运行时 API 启用:参见管理文档中的 set server 命令。

no-ssl-reuse

no-ssl-reuse

可用于以下上下文:tcp、http、log、peers、ring

此选项在与服务器通信时使用 SSL 时禁用 SSL 会话复用。它将强制服务器为每个新连接执行完整的握手过程。该选项可能仅适用于基准测试、故障排查,以及对安全极度敏感的用户。

no-sslv3

no-sslv3

可用于以下上下文:tcp、http、log、peers、ring

此选项在与服务器通信时使用 SSL 时禁用对 SSLv3 的支持。请注意,SSLv2 已在代码中禁用,无法通过任何配置选项启用。请改用 “ssl-min-ver” 和 “ssl-max-ver”。

默认服务器中不支持

no-tls-tickets

no-tls-tickets

可用于以下上下文:tcp、http、log、peers、ring

此设置仅在编译时启用 OpenSSL 支持时可用。它禁用无状态会话恢复(RFC 5077 TLS 会话票据扩展),强制使用有状态会话恢复。无状态会话恢复对服务器的 CPU 使用率更高。此选项也可在全局语句 “ssl-default-server-options” 中使用。TLS 会话票据机制仅适用于 TLS 1.2 及以下版本。使用 TLS 会话票据会损害前向安全性,除非定期轮换票据密钥(通过重载或使用 “tls-ticket-keys”)。参见 “tls-tickets”。

no-tlsv10

no-tlsv10

可用于以下上下文:tcp、http、log、peers、ring

此选项在使用 SSL 与服务器通信时禁用对 TLSv1.0 的支持。请注意,SSLv2 在代码中已禁用,无法通过任何配置选项启用。由于 TLSv1 的开销高于 SSLv3,因此在与本地服务器通信时,禁用 TLSv1 通常更为合理。此选项也可在全局语句 “ssl-default-server-options” 中使用,请改用 “ssl-min-ver” 和 “ssl-max-ver”。

默认服务器中不支持

no-tlsv11

no-tlsv11

可用于以下上下文:tcp、http、log、peers、ring

此选项在使用 SSL 与服务器通信时禁用对 TLSv1.1 的支持。请注意,SSLv2 在代码中已禁用,无法通过任何配置选项启用。由于 TLSv1 的开销高于 SSLv3,因此在与本地服务器通信时,禁用 TLSv1 通常更为合理。此选项也可在全局语句 “ssl-default-server-options” 中使用,请改用 “ssl-min-ver” 和 “ssl-max-ver”。

默认服务器中不支持

no-tlsv12

no-tlsv12

可用于以下上下文:tcp、http、log、peers、ring

此选项在使用 SSL 与服务器通信时禁用对 TLSv1.2 的支持。请注意,SSLv2 在代码中已禁用,无法通过任何配置选项启用。由于 TLSv1 的开销高于 SSLv3,因此在与本地服务器通信时,禁用 TLSv1 通常更为合理。此选项也可在全局语句 “ssl-default-server-options” 中使用,请改用 “ssl-min-ver” 和 “ssl-max-ver”。

默认服务器中不支持

no-tlsv13

no-tlsv13

可用于以下上下文:tcp、http、log、peers、ring

此选项在使用 SSL 与服务器通信时禁用对 TLSv1.3 的支持。请注意,SSLv2 在代码中已禁用,无法通过任何配置选项启用。由于 TLSv1 的开销高于 SSLv3,因此在与本地服务器通信时,通常建议禁用 TLSv1。此选项也可在全局语句 “ssl-default-server-options” 中使用,请改用 “ssl-min-ver” 和 “ssl-max-ver”。

默认服务器中不支持

no-verifyhost

no-verifyhost

可用于以下上下文:tcp、http、log、peers、ring

此选项可作为“server”指令使用,用于重置从“default-server”指令继承的“verifyhost”设置(默认值)。也可作为“default-server”指令使用,用于重置之前设置的“default-server”“verifyhost”设置。

no-tfo

no-tfo

可用于以下上下文:tcp、http、log、peers、ring

此选项可作为“server”指令使用,以重置从“default-server”指令继承的任何“tfo”设置作为默认值。也可作为“default-server”指令使用,以重置之前设置的“default-server”“tfo”设置。

non-stick

non-stick

可用于以下上下文:tcp、http

不要将分配给此服务器的连接添加到粘性表中。此选项可与 backup 配合使用,以确保备用服务器的粘性表持久性被禁用。

npn <protocols>

npn <protocols>

可用于以下上下文:tcp、http

启用 NPN TLS 扩展,并在 NPN 基础上通告指定的协议列表作为支持协议。协议列表由逗号分隔的协议名称组成,例如:http/1.1,http/1.0(不带引号)。此功能要求 SSL 库在编译时启用了 TLS 扩展支持(请通过 HAProxy -vv 检查)。请注意,NPN 扩展已被 ALPN 扩展取代(参见 “alpn” 关键字),但 ALPN 仅在 OpenSSL 1.0.2 及以上版本中可用。

observe <mode>

observe <mode>

可用于以下上下文:tcp、http

本选项启用基于观察与服务器通信情况的健康状态调整功能。默认情况下,此功能处于禁用状态,启用该功能还需同时启用健康检查。目前支持两种模式:“layer4” 和 “layer7”。在 layer4 模式下,仅成功或失败的 TCP 连接具有意义。在 layer7 模式下,仅适用于 HTTP 代理,会验证从服务器接收到的响应,例如有效的或错误的 HTTP 状态码、无法解析的头、超时等。有效的状态码包括 100 至 499、501 和 505。

另请参见“check”、“on-error”和“error-limit”。

on-error <mode>

on-error <mode>

可用于以下上下文:tcp、http、log

当检测到足够多的连续错误时,指定应执行的操作。当前支持四种模式:

  • fastinter:强制启用 fastinter
  • fail-check:模拟健康检查失败,同时强制启用 fastinter(默认)
  • sudden-death:模拟致命前的健康检查失败,再有一次检查失败即标记服务器为不可用,强制启用 fastinter
  • mark-down:立即标记服务器为不可用,并强制启用 fastinter

另请参见 “check”、“observe” 和 “error-limit”。

on-marked-down <action>

on-marked-down <action>

可用于以下上下文:tcp、http、log

修改服务器被标记为不可用时的处理方式。当前可用一个动作:

  • shutdown-sessions:关闭对等节点的流。启用此设置后,当服务器宕机时,所有到该服务器的连接将立即终止。若健康检查检测到的情况比简单的连接状态更为复杂,且长时间超时会导致服务长时间无响应,可使用此选项。例如,健康检查可能发现数据库已卡死,现有连接已无法再复用。通过此方式终止的连接会在日志中以 ‘D’ 终止码(表示“宕机”)记录。

动作默认被禁用

on-marked-up <action>

on-marked-up <action>

可用于以下上下文:tcp、http、log

修改服务器被标记为上线时的处理行为。当前可用一个动作:

  • shutdown-backup-sessions:在所有备用服务器上关闭流。仅当服务器未处于备用状态且未被禁用时执行(其有效权重必须大于 0)。在处理长会话(例如 LDAP、SQL 等)时,此选项可用于强制活跃服务器在恢复后重新接管全部流量。使用此功能可能带来的问题多于其解决的问题(例如未完成的事务),因此应极其谨慎地使用。因服务器上线而被终止的流,其终止码记录为 ‘U’(表示“上线”)。

动作默认被禁用

pool-conn-name <expr>

pool-conn-name <expr>

可以用于以下上下文:http

后端连接建立后,将评估此表达式以生成连接名称。该名称是空闲服务器池中连接的关键属性之一。参见“http-reuse”关键字。当请求查找现有空闲连接时,将评估此表达式以匹配完全相同的连接。

在使用 SSL SNI 进行后端连接的场景中,连接名称会自动设置为 “sni” 表达式的计算结果。这适用于最常见的使用场景。对于更高级的配置,可以使用 “pool-conn-name” 来覆盖此行为。

另请参见:“http-reuse”,“sni”

pool-low-conn <max>

pool-low-conn <max>

可以用于以下上下文:http

设置服务器空闲连接数的低阈值,低于该阈值时,线程将不会尝试从其他线程窃取连接。在涉及大量极快服务器的场景中,此设置有助于优化 CPU 使用模式,确保所有线程始终维持少量空闲连接,而非让连接集中在单一线程上并频繁在不同线程间迁移。通常,将该值设为线程数的两倍即可实现极佳性能,响应时间可低至亚毫秒级。默认值为 0,表示任何空闲连接均可随时使用。这是正常使用场景下的推荐设置。该设置仅适用于可按与 “http-reuse” 相同原则共享的连接。若通过 “tune.idle-pool.shared” 禁用了线程间的连接共享,则使用此设置变得尤为重要,以确保每个线程始终拥有少量连接,否则随着线程数量增加,连接复用率将下降。

pool-max-conn <max>

pool-max-conn <max>

可以用于以下上下文:http

设置服务器的最大空闲连接数。-1 表示无连接数限制,0 表示不允许空闲连接。默认值为 -1.。启用空闲连接后,不再属于任何客户端会话的孤立空闲连接将被移至专用池,以便未来客户端继续使用。此机制仅适用于可根据与“http-reuse”相同原则共享的连接。

pool-purge-delay <delay>

pool-purge-delay <delay>

可以用于以下上下文:http

设置开始清除空闲连接的延迟时间。每个 <delay> 间隔,一半的空闲连接将被关闭。0 表示不保留任何空闲连接。默认值为 5s。

port <port>

port <port>

可用于以下上下文:tcp、http、log

使用 “port” 参数,可指定不同的端口用于发送健康检查或探测 agent-check。在某些服务器上,可能需要为特定组件专门分配一个端口,该组件能够执行复杂的测试,这些测试比应用程序本身更适用于健康检查。例如,通常会在 inetd 中运行一个简单的脚本。若未设置 “check” 参数,则此参数将被忽略。另请参见 “addr” 参数。

proto <name>

proto <name>

可用于以下上下文:tcp、http

强制 multiplexer 协议用于与此服务器的出站连接。该协议必须与后端的模式(TCP 或 HTTP)兼容,且必须可在后端侧使用。可用协议列表在 HAProxy -vv.The 中报告,协议属性包括:模式(TCP/HTTP)、侧边(FE/BE)、mux 名称及其标志。

部分协议在服务器端存在队首阻塞问题(flag=HOL_RISK)。此外,部分协议不支持升级(flag=NO_UPG)。HTX 兼容性状态亦已报告(flag=HTX)。

以下协议可用于服务器行中 “proto” 指令的参数:

quic: mode=HTTP  side=FE|BE  mux=QUIC  flags=HTX|NO_UPG|FRAMED
qmux: mode=HTTP  side=FE|BE  mux=QMUX  flags=HTX|NO_UPG
h2  : mode=HTTP  side=FE|BE  mux=H2    flags=HTX|HOL_RISK|NO_UPG
fcgi: mode=HTTP  side=BE     mux=FCGI  flags=HTX|HOL_RISK|NO_UPG
h1  : mode=HTTP  side=FE|BE  mux=H1    flags=HTX|NO_UPG
none: mode=TCP   side=FE|BE  mux=PASS  flags=NO_UPG
spop: mode=SPOP  side=BE     mux=SPOP  flags=HOL_RISK|NO_UPG

此选项的设计理念是绕过为连接到该服务器的所有连接选择最佳多路复用协议的步骤。

如果配置了 ALPN 或 NPN 设置,指定的协议应与多路复用器的协议兼容,以避免出现任何问题。例如,若设置为 “proto h1”,则不应将 ALPN 设置为 “h2”。

另请参见 “ws”,以使用替代协议处理 WebSocket 流。

QMux 是 QUIC 的一个子集,运行于 TCP 之上。它对应于以下草案协议 https://www.ietf.org/archive/id/draft-ietf-quic-qmux-01.html 。目前在 HAProxy 中仍处于实验阶段。

quic-cc-algo { cubic | newreno | bbr | nocc }[(<args,...>)]

quic-cc-algo { cubic | newreno | bbr | nocc }[(<args,...>)]

这是针对 QUIC 的特定设置,用于为指向该服务器的任意连接选择拥塞控制算法。其选项与 TCP 使用的类似。有关所有自定义选项的完整说明,请参见名称相似的 bind 选项。

默认值:cubic

另请参阅:“tune.quic.be.tx.pacing” 和 “tune.quic.be.cc.max-win-size”

redir <prefix>

redir <prefix>

可以用于以下上下文:http

“redir” 参数为所有针对此服务器的 GET 和 HEAD 请求启用重定向模式。这意味着 HAProxy 不会将请求转发至服务器,而是立即发送“HTTP 302”响应,其中“Location”头由该前缀紧接请求的 URI 组成,URI 从路径组件的起始“/”开始。这意味着在 <prefix> 之后不应使用尾随斜杠。所有无效请求将被拒绝,所有非 GET 或 HEAD 请求将由服务器正常处理。请注意,由于响应完全由 HAProxy 伪造,无法在响应中进行头字段处理或插入 Cookie。然而,请求中的 Cookie 仍会被分析,因此该方案完全可用于在本地发生灾难时将用户引导至远程位置。主要用途在于通过让客户端直接连接静态服务器来提升带宽。注意:切勿在此处使用相对路径,否则会导致客户端与 HAProxy 之间产生循环!

示例:服务器 srv1 192.168.1.1:80 redir http://image1.mydomain.com check

renegotiate

renegotiate

可用于以下上下文:tcp、http、log

此选项为指定的 SSL 后端启用安全重新协商机制(RFC 5746 TLS 重新协商指示扩展)。它并不表示 SSL 客户端将发送重新协商请求,仅允许后端在服务器请求时进行重新协商。该功能仍需底层 SSL 库实际支持重新协商。此选项也可在全局语句 “ssl-default-server-options” 中使用。在 TLS 1.3 中,重新协商已不可行。若未指定 “renegotiate” 或 “no-renegotiate”,则保留 SSL 库的默认行为。请注意,例如 OpenSSL 库默认启用安全重新协商,而 AWS-LC 则禁用该功能。

rise <count>

rise <count>

可用于以下上下文:tcp、http、log

“rise” 参数表示,服务器在连续成功完成 <count> 次健康检查后将被视为正常运行。若未指定,该值默认为 2。另请参阅 “check”、“inter” 和 “fall” 参数。

resolve-opts <option>、<option>、… 可用于以下上下文:tcp、http、log

以逗号分隔的选项列表,用于应用到与此服务器关联的 DNS 解析。

可用选项:

  • allow-dup-ip 默认情况下,当运行时执行 DNS 解析时,HAProxy 会阻止后端中 IP 地址的重复。然而,在某些情况下,同一后端中由相同完全限定域名(FQDN)解析的两个服务器具有相同 IP 地址是合理的。对于此类情况,只需启用此选项。此选项与 prevent-dup-ip 相反。

  • ignore-weight 忽略 SRV 记录中设置的权重。当希望使用其他方法(例如通过 “agent-check” 或运行时 API)控制权重时,此选项非常有用。

  • prevent-dup-ip 确保 HAProxy 的默认行为在服务器上生效:防止在同一个后端中复用已分配给其他服务器的 IP 地址,且这些服务器共享相同的完全限定域名(fqdn)。这与 allow-dup-ip 的行为相反。

示例:

backend b_myapp
  default-server init-addr none resolvers dns
  server s1 myapp.example.com:80 check resolve-opts allow-dup-ip
  server s2 myapp.example.com:81 check resolve-opts allow-dup-ip

启用 allow-dup-ip 选项时:

  • 若名称服务器返回单个 IP 地址,则两个服务器将使用该地址
  • 若名称服务器返回两个 IP 地址,则每个服务器将选择不同的地址

默认值:未设置

resolve-prefer <family>

resolve-prefer <family>

可用于以下上下文:tcp、http、log

当为服务器启用 DNS 解析且返回了来自不同地址族的多个 IP 地址时,HAProxy 将优先使用 “resolve-prefer” 参数中指定的地址族的 IP 地址。另请参阅全局配置项 “dns-accept-family”,以强制严格使用特定地址族。可用地址族:ipv4 和 ipv6。

默认值:ipv6

示例:

server s1 app1.domain.com:80 resolvers mydns resolve-prefer ipv6

resolve-net <network>[,<network[,...]]

resolve-net <network>[,<network[,...]]

可用于以下上下文:tcp、http、log

此选项优先选择与网络匹配的 IP 地址。在云环境中,这有助于优先选择本地 IP。在某些情况下,云高可用性服务可能在多个不同数据中心通告多个 IP 地址。数据中心之间的延迟不可忽略,因此该配置可优先选择本地数据中心。若没有地址匹配配置的网络,则选择其他地址。

示例:

server s1 app1.domain.com:80 resolvers mydns resolve-net 10.0.0.0/8

resolvers <id>

resolvers <id>

可用于以下上下文:tcp、http、log

指向一个现有的 “resolvers” 段,用于解析当前服务器的主机名。当使用 resolvers 时,通常建议禁用基于 libc 的解析,尽管存在例外情况(参见 section 5.3.1 )。无论如何,使用 resolvers 时应显式指定 “init-addr”,以避免遗漏此元素。

示例:

server s1 app1.domain.com:80 init-addr last,none check resolvers mydns

有关实现细节及需注意的陷阱,请参阅 第 5.3 节 。

send-proxy

send-proxy

可用于以下上下文:tcp、http

send-proxy 指令强制对与此服务器建立的任何连接使用 PROXY 协议。PROXY 协议可向对端告知传入连接的第 3/4 层地址,从而使对端能够获知客户端地址或其访问的公网地址,无论上层协议为何。对于由 “accept-proxy” 或 “accept-netscaler-cip” 监听器接受的连接,将使用通告地址。仅支持 TCPv4 和 TCPv6 地址族,其他地址族(如 Unix 套接字)将报告为 UNKNOWN 家族。使用此选项的服务器可完全与另一个启用 “accept-proxy” 设置的 HAProxy 实例级联。若服务器不支持该协议,则不得使用此设置。当向服务器发送健康检查时,若已设置此选项,将自动使用 PROXY 协议,除非存在显式的 “port” 或 “addr” 指令;此时还需显式添加 “check-send-proxy” 指令,方可使用 PROXY 协议。另请参阅本段的 “no-send-proxy” 选项,以及 “bind” 关键字的 “accept-proxy” 和 “accept-netscaler-cip” 选项。

send-proxy-v2

send-proxy-v2

可用于以下上下文:tcp、http

在本段中,“send-proxy-v2” 参数强制对与此服务器建立的任何连接均使用 PROXY 协议版本 2。PROXY 协议可向对端告知传入连接的第 3/4 层地址,从而使对端能够获知客户端地址或其访问的公网地址,无论上层协议为何。若已协商 ALPN,则该设置还会发送 ALPN 信息。若服务器不支持此协议版本,则不得使用此设置。另请参见本段中的 “no-send-proxy-v2” 选项,以及 “bind” 关键字中的 “send-proxy” 选项。

set-proxy-v2-tlv-fmt(<id>) <fmt>

set-proxy-v2-tlv-fmt(<id>) <fmt>

可用于以下上下文:tcp、http

“set-proxy-v2-tlv-fmt” 参数用于发送任意的 PROXY 协议版本 2 TLV。对于已定义 TLV 类型的类型(<id>)范围,请参阅 PROXY 协议规范的第 2.2.8 段。但该值可自由选择,只要不超过最大长度 65,535 字节即可。也可通过使用 fetch “fc_pp_tlv” 从前端获取接收到的 TLV 来实现 TLV 的转发。该参数可作为服务器或 default-server 选项使用。必须与 send-proxy-v2 一同使用,以确保实际发送 PPv2 TLV。

示例:server srv1 192.168.1.1:80 send-proxy-v2 set-proxy-v2-tlv-fmt(0x20) %[fc_pp_tlv(0x20)]

在此情况下,我们将类型为 0x20 的 TLV 作为字符串获取,并将其设置为一个新创建的类型同样为 0x20 的 TLV 的值。

proxy-v2-options <option>[,<option>]*

proxy-v2-options <option>[,<option>]*

可用于以下上下文:tcp、http

“proxy-v2-options” 参数用于在使用 “send-proxy-v2” 时,向 PROXY 协议版本 2 添加发送选项。可用选项包括:

  • ssl : 参见 “send-proxy-v2-ssl”。
  • cert-cn : 参见 “send-proxy-v2-ssl-cn”。
  • ssl-cipher:所用加密套件的名称。
  • cert-sig:所用证书的签名算法。
  • cert-key:所用证书的密钥算法。
  • authority:客户端传入的主机名值(仅支持来自 TLS 连接的 SNI)。
  • crc32c:PROXYv2 头的校验和。
  • unique-id:在 PROXYv2 头中发送由前端的 “unique-id-format” 生成的唯一 ID。该唯一 ID 主要用于 “mode tcp”。在 “mode http” 中使用可能导致意外结果,因为生成的唯一 ID 也会用于持久连接中的首个 HTTP 请求。

send-proxy-v2-ssl

send-proxy-v2-ssl

可用于以下上下文:tcp、http

“send-proxy-v2-ssl” 参数强制在与该服务器建立的任何连接上使用 PROXY 协议版本 2。PROXY 协议可向对端告知传入连接的第 3/4 层地址,从而使对端能够获知客户端地址或其访问的公网地址,无论上层协议为何。此外,PROXY 协议头中还添加了 SSL 信息扩展。若服务器不支持此协议版本,则不得使用此设置。另请参阅本段中的 “no-send-proxy-v2-ssl” 选项,以及 “bind” 关键字的 “send-proxy-v2” 选项。

send-proxy-v2-ssl-cn

send-proxy-v2-ssl-cn

可用于以下上下文:tcp、http

在本段中,“send-proxy-v2-ssl” 参数强制在与该服务器建立的任何连接上使用 PROXY 协议版本 2。PROXY 协议可向对端告知传入连接的第 3/4 层地址,从而使对端能够获知客户端地址或其访问的公网地址,无论上层协议为何。此外,PROXY 协议的 SSL 信息扩展,以及客户端证书主体中的通用名称(如存在),将被添加至 PROXY 协议头中。若服务器不支持此协议版本,则不得使用该设置。另请参见本段中的 “no-send-proxy-v2-ssl-cn” 选项,以及 “bind” 关键字中的 “send-proxy-v2” 选项。

shard <shard>

shard <shard>

可用于以下上下文:对等节点

该参数仅在与对等节点的 stick-table 同步协议上下文中使用。“shard” 参数标识将接收以该分片作为分发哈希的所有 stick-table 键更新的对等节点。可接受的值范围为 0 至 “peers” 段中指定的 “shards” 参数值。0 值为默认值,表示该对等节点将接收所有键的更新。大于 “shards” 值的任何数值将被忽略。本地对等节点提供的任何值亦同此处理。

示例:

peers mypeers shards 3 peer A 127.0.0.1:40001 # local peer without shard value (0 internally) peer B 127.0.0.1:40002 shard 1 peer C 127.0.0.1:40003 shard 2 peer D 127.0.0.1:40004 shard 3

sigalgs <sigalgs>

sigalgs <sigalgs>

可用于以下上下文:tcp、http、log、peers、ring

此设置仅在编译时启用了 OpenSSL 支持时可用。它用于设置在 TLSv1.2 和 TLSv1.3 握手过程中协商的签名算法列表的描述字符串。字符串格式由 OpenSSL 手册页中的“man 3 SSL_CTX_set1_sigalgs”定义。除非需要与中间设备兼容,否则不建议使用此设置。

slowstart <start_time_in_ms>

slowstart <start_time_in_ms>

可用于以下上下文:tcp、http

“slowstart” 参数用于指定服务器在重新上线后经过多长时间(以毫秒为单位)开始以全速运行。与所有其他基于时间的参数一样,该值可以使用以下任意显式单位表示:{ us, ms, s, m, h, d }。在此期间,服务器速度将线性地从 0 增长至 100%。该限制适用于以下两个参数:

  • maxconn:服务器接受的连接数将从 1 增长至由 (minconn, maxconn, fullconn) 定义的常规动态限制的 100%。

  • weight:当后端使用动态加权算法时,权重从 1 线性增长至 100%。在此情况下,权重会在每次健康检查时更新。因此,必须确保“inter”参数小于“slowstart”参数,以最大化步进数量。

慢启动机制在 HAProxy 启动时不会生效,否则将对正在运行的服务器造成影响。该机制仅在服务器先前曾被识别为失败时才生效。

sni <expression>

sni <expression>

可用于以下上下文:tcp、http、log、peers、ring

“sni” 参数会评估样本提取表达式,将其转换为字符串,并将结果用作在 TLS SNI 扩展中发送至服务器的主机名。典型用例是在桥接 TCP/SSL 场景中,将客户端传入的 SNI 原样转发,使用 “ssl_fc_sni” 样本提取作为表达式。本文必须不得用于 HTTPS 场景,应改用 req.hdr(host),因为 HTTPS 中的 SNI 必须始终与 Host 字段一致,且客户端允许在同一条连接上使用不同的主机名。若设置 “verify required”(推荐设置),结果主机名还将与服务器证书中的名称进行匹配。有关详情,请参见 “verify” 指令。如需为健康检查设置 SNI,请参见 “check-sni” 指令获取更多信息。

默认情况下,SNI 会被分配给“http-reuse”的连接名称,除非被服务器关键字“pool-conn-name”覆盖。

sni-auto

sni-auto

可用于以下上下文:tcp、http、log、peers、ring

“sni-auto” 参数启用自动 SNI 选择,前提是未预先设置任何值。该参数将 “sni” 表达式设为 “req.hdr(host),field(1,:)",表示将使用发送至服务器的请求中的 Host 名称作为 SNI,但会去除端口号。该功能默认启用,但也可作为 “server” 指令使用,以重置从 “default-server” 指令继承的任何 “no-sni-auto” 设置。此外,也可作为 “default-server” 指令使用,以重置之前设置的 “default-server” “no-sni-auto” 设置。

对于 HTTPS 连接,若请求头中包含 Host 字段,则所选 SNI 基于该字段的值;否则保持未设置。对于其他协议,该选项被忽略。

若使用自动选择 SNI 的方式,则该值将被分配给连接名称,用于 “http-reuse”,除非被 “pool-conn-name” 服务器关键字覆盖。

请参阅“check-sni-auto”选项,以启用 SSL 健康检查的自动 SNI 选择。

source <addr>[:<pl>[-<ph>]] [usesrc { <addr2>[:<port2>] | client | clientip } ]

source <addr>[:<pl>[-<ph>]] [usesrc { <addr2>[:<port2>] | client | clientip } ]
source <addr>[:<port>] [usesrc { <addr2>[:<port2>] | hdr_ip(<hdr>[,<occ>]) } ]
source <addr>[:<pl>[-<ph>]] [interface <name>] ...

可用于以下上下文:tcp、http、log、peers、ring

“source” 参数用于设置连接服务器时所使用的源地址。其参数和原理与后端的 “source” 关键字完全相同,但仅适用于引用它的服务器。请参阅 “source” 关键字以获取详细信息。

此外,服务器行上的“source”语句允许通过指定用连字符(’-’)分隔的下限和上限来定义源端口范围。某些操作系统在指定源端口范围时可能要求提供有效的 IP 地址。可以为多个服务器指定相同的 IP 地址或地址范围。这样做可绕过 64k 总并发连接数的限制,此时每台服务器的连接数上限将提升至 64k。

自 Linux 4.2/libc 2.23 起,IP_BIND_ADDRESS_NO_PORT 用于指定源地址但不包含端口的连接。

ssl

ssl

可用于以下上下文:tcp、http、log、peers、ring

此选项在向服务器发起的出站连接上启用 SSL 加密。使用 SSL 连接服务器时,必须通过 “verify” 选项验证服务器证书,否则通信极易受到简单的中间人攻击,导致 SSL 完全失效。启用此选项后,健康检查也会自动通过 SSL 发送,除非存在 “port” 或 “addr” 指令明确指示检查应发送至其他位置。请参阅 “no-ssl” 以禁用 “ssl” 选项,或使用 “check-ssl” 选项强制健康检查使用 SSL。

ssl-max-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]

ssl-max-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]

可用于以下上下文:tcp、http、log、peers、ring

当使用 SSL 与服务器通信时,此选项强制使用 <version> 或更低版本。

此选项也可在全局语句 “ssl-default-server-options” 中使用。另请参见 “ssl-min-ver”。

ssl-min-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]

ssl-min-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]

可用于以下上下文:tcp、http、log、peers、ring

当使用 SSL 与服务器通信时,此选项强制使用 <version> 或更高版本。 此选项也可在全局语句 “ssl-default-server-options” 中使用。参见 “ssl-max-ver”。

ssl-reuse

ssl-reuse

可用于以下上下文:tcp、http、log、peers、ring

此选项可作为“服务器”指令使用,以重置从“default-server”指令继承的“no-ssl-reuse”设置(默认值)。也可作为“default-server”指令使用,以重置之前设置的“default-server”“no-ssl-reuse”设置。

stick

stick

可用于以下上下文:tcp、http

此选项可作为“服务器”指令使用,以重置从“default-server”指令继承的任何“non-stick”设置作为默认值。也可作为“default-server”指令使用,以重置之前设置的“default-server”“non-stick”设置。

strict-maxconn

strict-maxconn

可用于以下上下文:tcp、http

maxconn 限制服务器的连接数这一说法有些误导,实际上它配置的是我们发送至服务器的最大请求数。但由于存在空闲连接,实际与服务器建立的总连接数可能更多。若需对服务器连接数施加严格限制,可使用 strict-maxconn。启用后,我们绝不会建立超过 maxconn 数量的连接,必要时会尝试复用或终止现有连接。请注意,这可能导致请求失败,尤其是在无法建立新连接且无空闲连接可用的情况下。这种情况可能发生在建立“私有”连接时,即仅与会话绑定的连接,例如认证已发生的情形。

socks4 <addr>:<port>

socks4 <addr>:<port>

可用于以下上下文:tcp、http、log、peers、ring

此选项为发往服务器的出站连接启用上游 SOCKS4 隧道。使用此选项不会默认强制健康检查通过 SOCKS4 进行。如需启用该功能,必须使用关键字 “check-via-socks4”。

tcp-md5sig <password>

tcp-md5sig <password>

可用于以下上下文:tcp、http、log、peers、ring

启用 TCP MD5 签名(RFC 2385 通过 TCP MD5 签名选项保护 BGP 会话)功能,对所有发往该服务器的出站连接生效。此选项仅在 Linux 上可用。启用后,使用 <password> 字符串为每个 TCP 段生成 16 字节的 MD5 摘要进行签名。这可防止 TCP 连接遭受伪造攻击。该选项的主要用途是使 BGP 能够防范伪造 TCP 段被引入连接流。但对任何长时间持续的 TCP 连接均可能具有实用价值。

tcp-ut <delay>

tcp-ut <delay>

可用于以下上下文:tcp、http、log、peers、ring

设置此服务器所有出站连接的 TCP 用户超时。该选项自 Linux 2.6.37 版本起可用。它允许 HAProxy 为包含尚未收到确认数据的套接字配置超时,超时时间为指定的延迟时间。在长时间保持连接且经历长时间空闲的场景下尤为有用,例如远程终端或数据库连接池,此时客户端与服务器的超时必须设置得较高以允许较长的空闲期,但同时又必须能够检测到服务器已失效,以便释放与该连接(以及客户端会话)相关的所有资源。一个典型用例是,在健康检查过慢或执行平滑重载期间强制终止已失效的服务器连接,因为此时健康检查已被禁用。该参数默认以毫秒为单位表示延迟时间。此功能仅适用于常规 TCP 连接,对其他协议无效。

tfo

tfo

可用于以下上下文:tcp、http、log、peers、ring

此选项在支持该功能的系统上(目前仅限 Linux 内核 ≥ 4.11)启用与服务器连接时使用 TCP 快速打开。有关 TCP 快速打开的更多信息,请参见“tfo”绑定选项。请注意,使用 tfo 时,应同时使用“conn-failure”、“empty-response”和“response-timeout”作为“retry-on”的关键字,否则 HAProxy 将无法在连接失败时重试。另请参见“no-tfo”。

track [<backend>/]<server>

track [<backend>/]<server>

可用于以下上下文:tcp、http、log

此选项允许通过跟踪另一个服务器来设置当前服务器的状态。可以跟踪一个自身也在跟踪其他服务器的服务器,前提是链的末端必须有一个启用了健康检查的服务器。如果省略 <backend>,则使用当前服务器。若使用 disable-on-404,必须在两个代理上均启用该选项。

示例:

backend A
server a1 1.1.1.1:80 track B/b1
server a2 1.1.1.2:80 track B/b1

backend B
server b1 2.2.2.2:80 check

tls-tickets

tls-tickets

可用于以下上下文:tcp、http、log、peers、ring

此选项可作为“server”指令使用,用于重置从“default-server”指令继承的任何“no-tls-tickets”设置。TLS 会话票证机制仅在 TLS 1.2 及以下版本中使用。若未定期轮换票证密钥(通过重载或使用“tls-ticket-keys”),则使用 TLS 票证会损害前向安全性。该选项也可作为“default-server”指令使用,用于重置此前设置的“default-server”“no-tls-tickets”设置。

verify [none|required]

verify [none|required]

可用于以下上下文:tcp、http、log、peers、ring

当编译时启用了 OpenSSL 支持时,此设置才可用。若设置为 ’none’,则不验证服务器证书。否则,将在确认证书中的 subject 和 subjectAlternateNames 属性所包含的名称与通过 “sni” 指令传递的名称匹配,或未提供时与通过 “verifyhost” 指令传递的静态主机名匹配后,使用 ‘ca-file’ 中的 CA 以及可选的 ‘crl-file’ 中的 CRL 对服务器提供的证书进行验证。若未找到匹配名称,则忽略证书中的名称。因此,在未使用 SNI 时,务必使用 “verifyhost”。验证失败时,握手将被中止。使用 SSL 连接服务器时,必须验证服务器证书,否则通信极易受到简单的中间人攻击,导致 SSL 完全失效。除非 “ssl_server_verify” 出现在全局段中,否则 “verify” 默认设置为 “required”。

verifyhost <hostname>

verifyhost <hostname>

可用于以下上下文:tcp、http、log、peers、ring

此设置仅在编译时启用了 OpenSSL 支持时可用,且仅在同时指定 “verify required” 时才生效。该指令设置一个默认的静态主机名,用于在未使用 SNI 连接服务器时验证服务器证书。若未使用 SNI,此静态主机名是启用主机名验证的唯一方式。设置该静态主机名后,该名称也将用于健康检查(健康检查无法提供 SNI 值)。若证书中的任意主机名均不匹配指定主机名,握手将被中止。服务器提供的证书中的主机名可包含通配符。另请参见 “verify”、“sni” 和 “no-verifyhost” 选项。

weight <weight>

weight <weight>

可用于以下上下文:tcp、http

weight 参数

weight 参数用于调整服务器相对于其他服务器的权重。所有服务器将按其权重占总权重之和的比例接收负载,因此权重越高,接收的负载越大。默认权重为 1,最大值为 256。权重值为 0 表示该服务器不参与负载均衡,但仍可接受持久连接。若使用该参数根据服务器容量分配负载,建议初始值设置为可增可减的范围,例如在 10 到 100 之间,以便为后续调整留出足够的上下空间。

ws { auto | h1 | h2 }

ws { auto | h1 | h2 }

可以用于以下上下文:http

此选项用于配置中继 WebSocket 流时所使用的协议。当使用不支持通过 RFC8441 实现 H2 WebSocket 的 HTTP/2 后端时,该选项尤为有用。

默认模式为“auto”。该模式将复用主协议。唯一区别在于使用 ALPN 时,若配置的服务器 ALPN 包含“http/1.1”,则可仅对 WebSocket 流尝试将 ALPN 降级为“http/1.1”。

值 “h1” 用于强制对 WebSocket 流使用 HTTP/1.1,若服务器启用了 SSL ALPN,则通过 ALPN 实现。类似地,可使用 “h2” 强制使用 HTTP/2.0 WebSocket。使用此值时需谨慎:服务器必须支持 RFC8441,否则 HAProxy 在中继 WebSocket 时将报告错误。

请注意,NPN 未被考虑,因其使用已被弃用,取而代之的是 ALPN 扩展。

另请参见 “alpn” 和 “proto”。

5.3. 服务器 IP 地址的 DNS 解析

本文档描述了 HAProxy 如何在服务器行中使用主机名,通过域名服务器获取其 IP 地址。

默认情况下,HAProxy 在解析配置文件时、启动时进行名称解析,并将结果缓存至进程生命周期结束。在某些场景下,此机制不足以满足需求,例如在 Amazon 环境中,服务器的 IP 地址可能在重启后发生变化,或 ELB 虚拟 IP 地址可能根据当前负载动态调整。

本节描述如何配置 HAProxy,使其在运行时处理服务器的名称解析。

无论运行时服务器名称解析是否启用,HAProxy 默认会在启动时通过 libc 执行首次解析,除非通过 “init-addr” 参数禁用。

5.3.1. 全局概述

如我们在简介中所见,HAProxy 中的名称解析发生在进程生命周期的两个不同阶段:

1. when starting up, HAProxy parses the server line definition and matches a
   host name. It uses libc functions to get the host name resolved. This
   resolution relies on /etc/resolv.conf file.

2. at run time, HAProxy performs periodically name resolutions for servers
   requiring DNS resolutions.

以下其他事件也可能在运行时触发名称解析:

  • 当服务器的健康检查因连接超时而失败时:这可能是由于服务器的 IP 地址已更改。因此,需要触发一次名称解析以获取该新 IP 地址。

使用解析器时,服务器名称可以是主机名,也可以是 SRV 标签。HAProxy 将以下划线开头的任何内容视为 SRV 标签。若指定了 SRV 标签,则会从 DNS 服务器获取相应的 SRV 记录,并使用提供的主机名。SRV 标签将被定期检查,若任何服务器被添加或移除,HAProxy 会自动执行相应操作。

请注意以下几点:

  • 同时查询所有名称服务器。HAProxy 将处理第一个有效的响应。

  • 当所有服务器均返回错误时,该解析被视为无效(NX、超时、拒绝)。

  • HAProxy 内置的 DNS 客户端功能非常基础,无法理解操作系统解析器能够处理的大量选项和高级配置。因此,除非是极为简单的场景——例如,仅通过完全限定域名(FQDN)标识的服务器在任意时刻仅有一个 IP 地址,且偶尔会重新获取(如重启后),强烈建议避免在初始化时使用基于 libc 的解析与运行时基于 DNS 的解析混合使用,此类配置已知会在地址更新时导致故障。综上所述,除非确切了解自身操作,否则在服务器行使用“resolvers”时,应始终将“libc”从“init-addr”中排除。

5.3.2. 解析器段

本段专门用于配置与 HAProxy 中名称解析相关的主机信息。可根据需要配置多个 resolvers 段。每个段可包含多个名称服务器。

启动时,HAProxy 会尝试生成一个名为 “default” 的 resolvers 段,前提是配置中未显式命名该段。此段默认由 httpclient 使用,并采用 parse-resolv-conf 关键字。若 HAProxy 无法自动生成该段,不会发出任何错误或警告。

当在 resolvers 段中配置了多个名称服务器时,HAProxy 将采用首个有效的响应。若出现无效响应,仅最后一个响应会被处理。此机制旨在为响应较慢的服务器提供机会,在快速但错误或过时的服务器之后返回有效答案。

当每个服务器返回不同的错误类型时,HAProxy 仅使用最后一个错误。对该错误应用以下处理:

1. HAProxy retries the same DNS query with a new query type. The A queries are
   switch to AAAA or the opposite. SRV queries are not concerned here. Timeout
   errors are also excluded.

2. When the fallback on the query type was done (or not applicable), HAProxy
   retries the original DNS query, with the preferred query type.

3. HAProxy retries previous steps <resolve_retries> times. If no valid
   response is received after that, it stops the DNS resolution and reports
   the error.

例如,在 resolvers 段中配置了 2 台域名服务器时,以下场景是可能的:

  • 第一个响应有效,并直接应用,第二个响应被忽略

  • 第一个响应无效,第二个响应有效,则应用第二个响应

  • 首个响应为 NXDOMAIN,第二个响应为截断响应,则 HAProxy 会使用新的类型重试查询

  • 首个响应为 NXDOMAIN,第二个响应为超时,则 HAProxy 会使用新的类型重试查询

  • 对两个域名服务器的查询均超时后,HAProxy 会使用相同的查询类型重试该请求

由于 DNS 服务器可能无法在一次 DNS 请求中返回所有 IP 地址,HAProxy 会缓存之前的响应结果。若在 <hold obsolete> 秒内未返回该 IP 地址,则认为该响应已过期。

resolvers <resolvers id>

resolvers <resolvers id>

创建一个标记为 <resolvers id> 的新名称服务器列表。如上所述,特殊名称 “default” 始终存在,若未显式声明,将自动创建;内部服务(如 httpclient)依赖此名称。声明 “default” 条目将影响此类服务执行名称解析的方式。

resolvers 段接受以下参数:

accepted_payload_size <nb>

accepted_payload_size <nb>

定义 HAProxy 接受的最大有效负载大小,并向本解析器段中配置的所有域名服务器通告该值。<nb> 的单位为字节。若未设置,HAProxy 默认通告 512。最小值由 RFC 6891 定义。

请注意:最大允许值为 65535。对于 UDP,推荐值为 4096,除非确定系统和网络能够处理,否则不建议超过 8192(超过 65507 无意义,因为这是最大 UDP 负载大小)。如果仅使用 TCP 名称服务器处理大型 DNS 响应,应将此值设为最大值:65535。

nameserver <name> <address>[:port] [param*]

nameserver <name> <address>[:port] [param*]

用于配置名称服务器。<name> 的名称服务器应具有唯一性。默认情况下,<address> 被视为数据报类型。这意味着,若配置了 IPv4 或 IPv6 地址但未使用特殊地址前缀(参见第 11 节),将使用 UDP 协议。若使用流协议地址前缀,则名称服务器将被视为流服务器(例如 TCP),且第 5.2 节中与 DNS 解析相关的 “server” 参数将被考虑。 请注意:当前在 TCP 模式下,同一连接上会并行处理 4 个查询。每 5 秒移除一批空闲连接。可通过配置 “maxconn” 限制并发连接数量,若服务器支持,TLS 也可启用。

parse-resolv-conf

parse-resolv-conf

将 /etc/resolv.conf 中找到的所有名称服务器添加到此解析器的名称服务器列表中。顺序与将 /etc/resolv.conf 中每个名称服务器单独放置于解析器段中、取代此指令时的顺序一致。

hold <status> <period>

hold <status> <period>

收到 DNS 响应 <status> 后,判断是否应将服务器的状态从 UP 变更为 DOWN。为做出此判断,它会检查在过去 <period> 内是否曾收到任何有效状态,以抵消刚刚收到的无效状态。

`<status>`: last name resolution status.
       nx        After receiving an NXDOMAIN status, check for any valid
                 status during the concluding period.

       refused   After receiving a REFUSED status, check for any valid
                 status during the concluding period.

       timeout   After the "timeout retry" has struck, check for any
                 valid status during the concluding period.

       other     After receiving any other invalid status, check for any
                 valid status during the concluding period.

       valid     Applies only to "http-request do-resolve" and
                 "tcp-request content do-resolve" actions. It defines the
                 period for which the server will maintain a valid response
                 before triggering another resolution. It does not affect
                 dynamic resolution of servers.

       obsolete  Defines how long to wait before removing obsolete DNS
                 records after an updated answer record is received. It
                 applies to SRV records.

`<period>`: Amount of time into the past during which a valid response must
           have been received. It follows the HAProxy time format and is in
           milliseconds by default.

对于依赖动态 DNS 解析来确定其 IP 地址的服务器,若收到无效的 DNS 响应(例如 NXDOMAIN),将导致服务器状态从 UP 变为 DOWN。hold 指令定义了回溯有效响应的时间范围。如果在 <period> 内曾收到过有效响应,则本次接收到的无效状态将被忽略。

如果在结束周期内未收到有效响应,该服务器将被标记为 DOWN。例如,若设置“hold nx 30s”,且最后一次收到的 DNS 响应为 NXDOMAIN,则除非在最近 30 秒内收到有效响应,否则该服务器将被标记为 DOWN。

当服务器处于 DOWN 状态时,一旦从 DNS 服务器接收到有效的状态信息,将立即被标记为 UP。

对于“保持有效”和“保持过时”存在独立的行为。

默认值为“valid”时为 10 秒,“obsolete”时为 0 秒,其他情况为 30 秒。

resolve_retries <nb>

resolve_retries <nb>

定义解析服务器名称时,在放弃前发送的查询次数 <nb>。默认值:3

重试发生在域名服务器超时,或当全部 DNS 查询类型故障转移序列结束后,需从默认的 ANY 查询类型重新开始时。

timeout <event> <time>

timeout <event> <time>

定义与名称解析相关的超时 <event>:<time> 超时周期适用的事件。可用事件包括: - resolve:当无其他时间设置时,触发名称解析的默认时间。默认值:1s - retry:在未收到有效响应时,两次 DNS 查询之间的间隔时间。默认值:1s <time>:与事件相关的超时时间。遵循 HAProxy 时间格式。<time> 以毫秒为单位。

示例:

resolvers mydns
  nameserver dns1 10.0.0.1:53
  nameserver dns2 10.0.0.2:53
  nameserver dns3 tcp@10.0.0.3:53
  parse-resolv-conf
  resolve_retries       3
  timeout resolve       1s
  timeout retry         1s
  hold other           30s
  hold refused         30s
  hold nx              30s
  hold timeout         30s
  hold valid           10s
  hold obsolete        30s

15 - 6. 缓存

缓存段和代理段中的缓存限制与配置

HAProxy 提供一个缓存,专为小型对象(如 favicon、CSS 等)的缓存而设计。 这是一个极简且低维护成本的缓存,运行于内存中。

缓存基于所有线程共享的内存区域,并划分为 1kB 的块。

若某个对象不再被使用,即使未过期,也可被删除以腾出空间存储新对象。当尝试分配新对象时,将优先删除最旧的对象。

缓存使用主机头和 URI 的哈希值作为键。

可通过 Unix 套接字命令 “show cache” 查看缓存状态,详见管理指南 第 9.3 节 “Unix 套接字命令”。

当缓存直接提供对象时,日志中的服务器名称将被替换为 “<CACHE>"。

6.1. 限制

缓存不会在以下情况下存储或提供对象:

  • 如果响应状态码不是 200

  • 如果响应包含 Vary 头,且满足以下任一条件:process-vary 选项被禁用,或 Vary 值中指定了当前未管理的头(目前仅接受 accept-encoding、referer 和 origin 为已管理头)

  • 如果 Content-Length 与头大小之和大于 “max-object-size”

  • 如果响应不可缓存

  • 如果响应未指定明确的过期时间(s-maxage 或 max-age Cache-Control 指令,或 Expires 头),且未提供验证器(ETag 或 Last-Modified 头)

  • 如果 process-vary 选项已启用,且当前响应的主键已存在 max-secondary-entries 个相同主键的条目

  • 如果 process-vary 选项已启用,响应使用了未知编码(未在 https://www.iana.org/assignments/http-parameters/http-parameters.xhtml 中列出),并以客户端 accept-encoding 头作为 Vary 条件

  • 如果请求方法不是 GET

  • 如果请求的 HTTP 版本小于 1.1

  • 如果请求包含 Authorization 头

6.2. 配置

要设置缓存,必须定义一个缓存段,并在代理中通过相应的 http-request 和 http-response 动作使用该缓存。

6.2.1. 缓存段

cache <name>

cache <name>

声明一个缓存段,分配一个名为 <name> 的共享缓存内存,缓存大小为必填项(参见下方关键字 “total-max-size”)。

max-age <seconds>

max-age <seconds>

定义最大过期时长。过期时间以 Cache-Control 响应头中 s-maxage 或 max-age(按此顺序)指令的最小值与该值之间的较小者为准。默认值为 60 秒,表示默认情况下无法缓存对象超过 60 秒。

max-object-size <bytes>

max-object-size <bytes>

定义缓存对象的最大大小。不得大于 “total-max-size” 的一半。若未设置,其值等于缓存大小的 1/256。所有大小超过 “max-object-size” 的对象将不会被缓存。

max-secondary-entries <number>

max-secondary-entries <number>

定义缓存中具有相同主键的二级条目最大并发数量。 此设置需要启用 Vary 支持。默认值为 10,应设置为严格正整数。

process-vary <on/off>

process-vary <on/off>

启用或禁用对 Vary 头的处理。禁用时,包含该头的响应将永远不会被缓存。启用时,需对所有入站请求的请求头子集计算初步哈希值(可能带来 CPU 开销),该哈希值将用于为特定请求构建二级键(参见 RFC 7234#4.1)。目前,二级键由 ‘accept-encoding’、‘referer’ 和 ‘origin’ 头的内容构成。根据 RFC,‘origin’ 和 ‘referer’ 都是单值头,因此包含多个此类头实例的请求应视为格式错误。对于这类请求,HAProxy 不会构建二级键,也不会从缓存返回响应,而是交由服务器决定如何处理。默认值为 off(禁用)。

total-max-size <megabytes>

total-max-size <megabytes>

定义缓存的 RAM 大小,单位为兆字节。该大小将被划分为 1kB 的块,供缓存条目使用。最大值为 4095。

6.2.2. 代理段

使用缓存的代理段需在 “http-request” 规则集中包含 “cache-use” 动作,以从缓存中查找请求的对象;并在 “http-response” 规则集中包含 “cache-store” 动作,以将获取的对象存储或更新至缓存。这些动作均可选择性地附加条件。例如,可决定对某个已知不可缓存的子目录跳过 “cache-use” 动作,或对某些已知无价值的内容类型跳过 “cache-store” 动作。请注意,缓存索引键在执行 “cache-use” 动作时计算,因此若跳过该动作,响应路径上将不会尝试更新缓存。

示例:

backend bck1
  mode http

  http-request cache-use foobar
  http-response cache-store foobar
  server srv1 127.0.0.1:80

cache foobar
  total-max-size 4
  max-age 240

16 - 7. ACL 与样本提取

ACL 匹配、条件、转换器、样本提取和预定义 ACL

HAProxy 可从请求或响应流、客户端或服务器信息、表格、环境信息等来源提取数据。提取此类数据的动作称为获取样本。获取后,这些样本可用于多种用途,例如作为粘性表的键,但最常见的用法是将其与称为模式的预定义常量数据进行匹配。

7.1. ACL 基础

访问控制列表(ACL)用于声明一种命名的匹配方法,以将任意信息与预先定义的模式列表进行比较。ACL 可视为大多数编程语言中函数的实际等价物,其声明使得该方法可在后续需要时被调用。ACL 的评估结果仅返回匹配或不匹配,这与许多编程语言中的布尔值类似。与编程语言中的函数不同,ACL 可以针对同一名称多次重载,以定义额外的匹配方法。在此情况下,所有 ACL 将按声明顺序依次评估,直到其中一个匹配为止。

ACL 的使用提供了一种灵活的解决方案,用于执行内容切换,或基于从请求、响应或任何环境状态中提取的内容做出决策。其原理十分简单:

  • 从流、表或环境提取数据样本
  • 可选地对提取的样本应用格式转换
  • 对该样本应用一个或多个模式匹配方法
  • 仅当模式与样本匹配时执行动作

动作通常包括阻止请求、选择后端或添加头。

要定义一个测试,需使用 “acl” 关键字。语法如下:

acl <aclname> <criterion> [flags] [operator] [<value>] ...

创建一个新的 ACL <aclname>,或对已存在的 ACL 添加新的测试条件。这些测试条件适用于 <criterion> 指定的请求/响应部分,可使用可选标志 [flags] 进行调整。部分条件支持指定操作符,操作符可置于值集合之前。可选地,可对样本应用转换操作符,转换操作符需以逗号分隔的关键词列表形式紧随首个关键词之后指定。值的类型由条件所支持,各值之间以空格分隔。

ACL 名称必须由大写字母、小写字母、数字、’-’(连字符)、’_’(下划线)、’.’(点)和 ‘:’(冒号)组成。ACL 名称区分大小写,这意味着 “my_acl” 和 “My_Acl” 是两个不同的 ACL。

ACL 的数量没有强制限制。未使用的 ACL 不会影响性能,仅会占用少量内存。

判断标准通常为样本提取方法的名称,或其 ACL 特定形式之一。默认的测试方法由该样本提取方法的输出类型决定。ACL 特定形式可用于描述同一样本提取方法的其他匹配方法。样本提取方法是唯一支持转换的类型。

样本提取方法返回的数据类型如下:

  • 布尔值
  • 整数(有符号或无符号)
  • IPv4 或 IPv6 地址
  • 字符串
  • 数据块

转换器可将任意数据转换为任意其他数据。例如,某些转换器可将字符串转换为小写字符串,而其他转换器则可将字符串转换为 IPv4 地址,或对 IP 地址应用子网掩码。最终生成的样本类型为应用于列表的最后一个转换器的类型,其默认值为样本提取方法的类型。

每个样本或转换器返回特定类型的数据,该类型在本文档中通过其关键字指定。当使用标准样本提取方法声明 ACL 时,某些类型会自动关联默认匹配方法,具体如下表所示:

   +---------------------+-----------------+
   | Sample or converter | Default         |
   |    output type      | matching method |
   +---------------------+-----------------+
   | boolean             | bool            |
   +---------------------+-----------------+
   | integer             | int             |
   +---------------------+-----------------+
   | ip                  | ip              |
   +---------------------+-----------------+
   | string              | str             |
   +---------------------+-----------------+
   | binary              | none, use "-m"  |
   +---------------------+-----------------+

请注意,若要匹配二进制样本,必须指定匹配方法,详见下文。

ACL 引擎可将这些类型与以下类型的模式进行匹配:

  • 布尔值
  • 整数或整数范围
  • IP 地址 / 网络
  • 字符串(精确匹配、子串、后缀、前缀、子目录、域名)
  • 正则表达式
  • 十六进制块

以下 ACL 标志当前受支持:

-i: ignore case during matching of all subsequent patterns.
-f: load patterns from a list.
-m: use a specific pattern matching method
-n: forbid the DNS resolutions
-M: load the file pointed by -f like a map.
-u: force the unique id of the ACL
--: force end of flags. Useful when a string looks like one of the flags.

“-f” 标志后跟的名称必须符合第 2.7 节中关于映射和 ACL 名称格式的描述。如果需从多个列表加载模式,可以传递多个“-f”参数。若引用了现有文件,所有行将被读取为独立的值。空行以及以井号(’#’)开头的行将被忽略。所有前导空格和制表符将被去除。若必须插入以井号开头的有效模式,只需在其前添加一个空格,以避免被误认为是注释。根据数据类型和匹配方式,HAProxy 可能会将行加载到二叉树中,从而实现极快的查找。IPv4 和精确字符串匹配即属此类情况,此时重复项将自动被移除。

“-M” 标志允许 ACL 使用映射。若设置此标志,列表将被解析为两列条目。第一列包含 ACL 使用的模式,第二列包含样本。该样本后续可被映射使用。在某些罕见场景中,这可用于在应用映射前,仅通过 ACL 检查模式是否存在于映射中。

“-u” 标志强制 ACL 的唯一 ID。该唯一 ID 用于套接字接口,以标识 ACL 并动态修改其值。请注意,即使设置了 ID,文件仍始终通过其名称进行标识。

此外请注意,“-i” 标志仅适用于其后的条目,而不适用于其前从文件加载的条目。例如:

acl valid-ua hdr(user-agent) -f exact-ua.lst -i -f generic-ua.lst test

在本例中,“exact-ua.lst” 中的每一行将与请求的 “user-agent” 头进行精确匹配。随后,“generic-ua” 中的每一行将不区分大小写进行匹配。然后,单词 “test” 也将不区分大小写进行匹配。

“-m” 标志用于在输入样本上选择特定的模式匹配方法。所有 ACL 特定的条件均隐含模式匹配方法,通常无需此标志。然而,该标志在使用通用样本提取方法时非常有用,用于说明样本将如何与模式进行匹配。对于返回无明显匹配方法数据类型(例如字符串或二进制数据)的样本提取操作,此标志为必需。当指定 “-m” 并后接模式匹配方法名称时,该方法将取代条件的默认匹配方法。这使得能够以最初未计划的方式进行内容匹配,或与返回字符串的样本提取方法配合使用。匹配方法还会影响模式的解析方式,因此不得与带有匹配后缀(_beg、_end、_sub…)的样本提取操作一同使用。此外,禁止指定多个 “-m” 模式匹配方法。

“-n” 标志禁止 DNS 解析。该标志与 IP 文件加载配合使用。默认情况下,若解析器无法解析 IP 地址,会认为被解析的字符串可能为域名并尝试进行 DNS 解析。标志 “-n” 可禁用此解析行为。该选项有助于检测格式错误的 IP 列表。请注意,若 DNS 服务器不可达,HAProxy 配置解析过程可能持续数分钟,等待超时。在此期间不会显示任何错误消息。标志 “-n” 可禁用此行为。此外,在运行时,该功能对于动态 ACL 修改将被禁用。

然而,存在一些限制。并非所有匹配方法均可与所有样本提取方法配合使用。 此外,若将 “-m” 与 “-f” 一同使用,必须将 “-m” 置于首位。模式匹配方法必须为以下之一:

  • “found”: 仅检查请求的样本是否存在于流中,而不与任何模式进行比较。建议不要传递任何模式,以避免混淆。此匹配方法特别适用于检测特定内容(如头、Cookie 等)是否存在,即使其为空,也无需与任何内容比较或计数。

  • “bool” : 将值作为布尔类型进行检查。仅可应用于返回布尔值或整数值的 fetch 操作,且不接受任何模式。值为零或 false 时不匹配,其余所有值均匹配。

  • int:将值匹配为整数。可用于整数和布尔值样本。布尔值 false 对应整数 0,true 对应整数 1。

  • “ip” : 以 IPv4 或 IPv6 地址形式匹配值。仅与 IP 地址样本兼容,因此为隐含项,无需显式指定。

  • “bin” : 将内容与表示二进制序列的十六进制字符串进行匹配。此选项可用于二进制或字符串样本。

  • “len” : 以整数形式匹配样本的长度。可与二进制或字符串样本配合使用。

  • “str” : 精确匹配:将内容与字符串进行匹配。此选项可用于二进制或字符串样本。

  • “sub” : 子串匹配:检查内容中是否包含至少一个提供的字符串模式。此模式可用于二进制或字符串样本。

  • “reg” : 正则表达式匹配:将内容与一组正则表达式进行匹配。此选项可用于二进制或字符串样本。

  • “beg” : 前缀匹配:检查内容是否以提供的字符串模式开头。此模式可用于二进制或字符串样本。

  • “end” : 后缀匹配:检查内容是否以提供的字符串模式结尾。此模式可用于二进制或字符串样本。

  • “dir” : subdir 匹配:检查内容中以斜杠分隔的部分是否与提供的某个字符串模式完全匹配。此功能可用于二进制或字符串样本。

  • “dom” : 域名匹配:检查内容中以点分隔的部分是否与提供的某个字符串模式完全匹配。此模式可用于二进制或字符串样本。

例如,要快速检测 HTTP 请求中是否存在 Cookie “JSESSIONID”,可以执行:

acl jsess_present req.cook(JSESSIONID) -m found

为在缓冲区的前 500 字节数据上应用正则表达式,可使用以下 ACL:

acl script_tag req.payload(0,500) -m reg -i <script>

在正则表达式库在使用 “-i” 时性能显著降低的系统上,可在匹配前将样本转换为小写,例如:

acl script_tag req.payload(0,500),lower -m reg <script>

所有 ACL 特定条件均隐含一个默认匹配方法。大多数情况下,这些条件通过将原始样本提取方法名称与匹配方法拼接而成。例如,“hdr_beg” 对使用 “hdr” 样本提取方法获取的样本应用 “beg” 匹配。该匹配方法仅在关键字单独使用、未附加任何转换器时可用。若在该 ACL 关键字后应用任何转换器,则 ACL 关键字的默认匹配方法将被忽略,因为匹配所依据的是最后一个转换器的输出类型。由于所有 ACL 特定条件均依赖样本提取方法,因此始终可改用原始样本提取方法并显式指定匹配方法,通过 “-m” 实现。

如果在 ACL 特定条件中使用 “-m” 指定备用匹配方式,则匹配方法将直接应用于底层的样本提取方法。例如,以下所有 ACL 均完全等价:

acl short_form  hdr_beg(host)        www.
acl alternate1  hdr_beg(host) -m beg www.
acl alternate2  hdr_dom(host) -m beg www.
acl alternate3  hdr(host)     -m beg www.

下表总结了样本或转换器类型与用于获取数据的模式类型之间的兼容性矩阵。对于每种兼容组合,列出了应使用的匹配方法名称,当该方法为默认方法且无需显式指定即可默认生效时,方法名称用尖括号 “>” 和 “<” 包围。该方法将在未指定 “-m” 时自动生效。

                           +-------------------------------------------------+
                           |                Input sample type                |
    +----------------------+---------+---------+---------+---------+---------+
    |     pattern type     | boolean | integer |   ip    | string  | binary  |
    +----------------------+---------+---------+---------+---------+---------+
    | none (presence only) |  found  |  found  |  found  |  found  |  found  |
    +----------------------+---------+---------+---------+---------+---------+
    | none (boolean value) |>  bool <|   bool  |         |   bool  |         |
    +----------------------+---------+---------+---------+---------+---------+
    | integer (value)      |   int   |>  int  <|   int   |   int   |         |
    +----------------------+---------+---------+---------+---------+---------+
    | integer (length)     |   len   |   len   |   len   |   len   |   len   |
    +----------------------+---------+---------+---------+---------+---------+
    | IP address           |         |         |>   ip  <|    ip   |    ip   |
    +----------------------+---------+---------+---------+---------+---------+
    | exact string         |   str   |   str   |   str   |>  str  <|   str   |
    +----------------------+---------+---------+---------+---------+---------+
    | prefix               |   beg   |   beg   |   beg   |   beg   |   beg   |
    +----------------------+---------+---------+---------+---------+---------+
    | suffix               |   end   |   end   |   end   |   end   |   end   |
    +----------------------+---------+---------+---------+---------+---------+
    | substring            |   sub   |   sub   |   sub   |   sub   |   sub   |
    +----------------------+---------+---------+---------+---------+---------+
    | subdir               |   dir   |   dir   |   dir   |   dir   |   dir   |
    +----------------------+---------+---------+---------+---------+---------+
    | domain               |   dom   |   dom   |   dom   |   dom   |   dom   |
    +----------------------+---------+---------+---------+---------+---------+
    | regex                |   reg   |   reg   |   reg   |   reg   |   reg   |
    +----------------------+---------+---------+---------+---------+---------+
    | hex block            |         |         |         |   bin   |   bin   |
    +----------------------+---------+---------+---------+---------+---------+

7.1.1. 匹配布尔值

要匹配布尔值,无需提供值,所有值均被忽略。所有类型为“boolean”的 fetch 方法默认使用布尔匹配。使用布尔匹配时,获取的值将原样返回,即布尔值“true”始终匹配,布尔值“false”从不匹配。

布尔匹配也可通过在返回整数值的 fetch 方法中使用 “-m bool” 强制执行。此时,整数值 0 被转换为布尔值 “false”,其余所有值均被转换为 “true”。

7.1.2. 匹配整数

整数匹配默认适用于整数获取方法。也可通过使用 “-m int” 强制对布尔值获取进行整数匹配。此时,“false” 将被转换为整数 0,“true” 将被转换为整数 1。

整数匹配还支持整数范围和运算符。请注意,整数匹配仅适用于正值。范围以冒号分隔的下界和上界表示,两者均可省略。

例如,“1024:65535” 是表示非特权端口范围的有效范围,而 “1024:” 也同样有效。“0:1023” 是表示特权端口的有效表示方式,而 “:1023” 也同样适用。

作为特例,某些 ACL 函数支持小数形式的数值,这些数值实际上是由两个整数通过英文句点分隔构成。例如,在某些版本检查中会用到此类格式。所有整数属性均适用于此类小数,包括范围和运算符。

为便于使用,也支持比较运算符。请注意,将运算符与范围结合使用意义不大,强烈不建议这样做。同理,对一组值执行顺序比较也不合理。

整数匹配可用的运算符如下:

eq: true if the tested value equals at least one value
ge: true if the tested value is greater than or equal to at least one value
gt: true if the tested value is greater than at least one value
le: true if the tested value is less than or equal to at least one value
lt: true if the tested value is less than at least one value

例如,以下 ACL 匹配任意负值的 Content-Length 头:

acl negative-length req.hdr_val(content-length) lt 0

此规则匹配 SSL 版本在 3.0 至 3.1 之间(包含两端)的情况:

acl sslv3 req.ssl_ver 3:3.1

7.1.3. 匹配字符串

字符串匹配适用于字符串或二进制获取方法,共有六种不同形式:

  • 精确匹配(-m str):提取的字符串必须与模式完全匹配;

  • 子串匹配(-m sub):在提取的字符串中查找模式,若其中任意一个模式被找到,则 ACL 匹配成功;

  • 前缀匹配(-m beg):模式与提取字符串的开头进行比较,只要其中任意一个匹配,ACL 即视为匹配。

  • 后缀匹配(-m 结尾):模式与提取字符串的末尾进行比较,只要其中任意一个匹配,ACL 即匹配。

  • subdir match (-m dir):模式将在提取的字符串任意位置进行匹配,字符串以斜杠("/")分隔,包括字符串开头或结尾。只要其中任意一个模式匹配,ACL 即视为匹配。例如,字符串 “/images/png/logo/32x32.png” 会匹配 “/images”、"/images/png"、“images/png”、"/png/logo"、“logo/32x32.png” 或 “32x32.png”,但不会匹配 “png” 或 “32x32”。

  • 域名匹配(-m dom):模式将在提取的字符串中任意位置进行查找,分隔符包括点号(".")、冒号(":")、斜杠("/")、问号("?")、字符串开头或结尾。此功能专为 URL 设计。模式中的前导和尾随分隔符会被忽略。只要任一模式匹配即判定为匹配。例如在字符串 “http://www1.dc-eu.example.com:80/blah ” 中,“http”、“www1”、".www1"、“dc-eu”、“example”、“com”、“80”、“dc-eu.example”、“blah”、":www1:"、“dc-eu.example:80” 均可匹配,但 “eu” 和 “dc” 不匹配。使用该方式匹配域名后缀以实现过滤或路由通常并非良策,因为路由可能轻易被欺骗,例如在另一个域名前添加匹配前缀即可绕过规则。

字符串匹配适用于原样传递的字面量字符串,唯一例外是反斜杠("\"),可用于转义空格等字符。 若在第一个字符串前传递 “-i” 标志,则匹配时将忽略大小写。 要匹配字符串 “-i”,可将其置于第二个位置,或在第一个字符串前传递 “–” 标志。 同理,匹配字符串 “–” 时也适用相同规则。

对于可能包含空字节(0x00)的二进制获取操作,不得使用字符串匹配,因为比较会在遇到第一个空字节时停止。应首先使用 hex 转换器将二进制获取结果转换为十六进制字符串。

示例:

# matches if the string <tag> is present in the binary sample
acl tag_found req.payload(0,0),hex -m sub 3C7461673E

7.1.4. 匹配正则表达式(regexes)

与字符串匹配类似,正则表达式匹配会原样处理传入的字面量字符串,唯一例外是反斜杠("\"),可用于转义空格等字符。若在第一个正则表达式前传递 “-i” 标志,则匹配时将忽略大小写。要匹配字符串 “-i”,可将其置于第二个位置,或在第一个字符串前传递 “–” 标志。同理,匹配字符串 “–” 也遵循相同原则。

7.1.5. 匹配任意数据块

可以将某些提取的样本与二进制块进行匹配,该二进制块可能无法安全地表示为字符串。为此,当匹配方法设置为 binary 时,模式必须以偶数个十六进制数字的形式传递。每两个数字组成一个字节。十六进制数字可使用大写或小写。

示例:

# match "Hello\n" in the input stream (\x48 \x65 \x6c \x6c \x6f \x0a)
acl hello req.payload(0,6) -m bin 48656c6c6f0a

7.1.6. 匹配 IPv4 和 IPv6 地址

IPv4 地址值可指定为纯地址,或在地址后附加子网掩码,此时只要 IPv4 地址位于该网络范围内即视为匹配。纯地址也可替换为可解析的主机名,但此做法通常不建议,因其会增加配置的可读性和调试难度。若使用主机名,应至少确保其存在于 /etc/hosts 中,以免配置解析时依赖任意 DNS 匹配结果。

点分十进制 IPv4 地址表示法支持常规形式以及简写形式,后者可省略所有为 0 的字节:

    +------------------+------------------+------------------+
    |   Example 1      |     Example 2    |     Example 3    |
    +------------------+------------------+------------------+
    |  192.168.0.1     |   10.0.0.12      |   127.0.0.1      |
    |  192.168.1       |   10.12          |   127.1          |
    |  192.168.0.1/22  |   10.0.0.12/8    |   127.0.0.1/8    |
    |  192.168.1/22    |   10.12/8        |   127.1/8        |
    +------------------+------------------+------------------+

请注意,这与 RFC 4632 CIDR 地址表示法不同,在后者中,192.168.42/24 等价于 192.168.42.0/24。

IPv6 地址可按其常规形式输入,可带也可不带子网掩码。IPv6 子网掩码仅接受位数形式。为避免与随机解析的 IP 地址产生任何潜在问题,IPv6 模式中禁止使用主机名。

HAProxy 还能够在以下情况下匹配 IPv4 地址与 IPv6 地址:

  • 测试地址为 IPv4,模式地址为 IPv4,匹配在 IPv4 环境下使用提供的掩码进行。
  • 测试地址为 IPv6,模式地址为 IPv6,匹配在 IPv6 环境下使用提供的掩码进行。
  • 测试地址为 IPv6,模式地址为 IPv4,匹配在 IPv4 环境下使用模式的掩码进行,前提是 IPv6 地址符合 2002:IPV4::、::IPV4 或 ::ffff:IPV4 格式,否则匹配失败。
  • 测试地址为 IPv4,模式地址为 IPv6,首先将 IPv4 地址通过在前面添加 ::ffff: 转换为 IPv6 格式,然后在 IPv6 环境下使用提供的 IPv6 掩码进行匹配。

7.2. 使用 ACL 形成条件

某些动作仅在满足有效条件时执行。条件是由 ACL 与运算符组合而成。支持以下 3 种运算符:

  • AND(隐式)
  • OR(显式,使用“or”关键字或“||”运算符)
  • 使用感叹号(“!”)进行否定

条件以析取形式构成:

[!]acl1 [!]acl2 ... [!]acln  { or [!]acl1 [!]acl2 ... [!]acln } ...

此类条件通常用于 “if” 或 “unless” 语句之后,表示在何种情况下触发动作。

例如,阻止对 “*” URL 发起的 HTTP 请求(方法非 “OPTIONS” 时),以及未指定 content-length 的 POST 请求,还有 content-length 大于 0 的 GET 或 HEAD 请求,最后是所有不属于 GET/HEAD/POST/OPTIONS 方法的请求。

acl missing_cl req.hdr_cnt(Content-length) eq 0 http-request deny if HTTP_URL_STAR !METH_OPTIONS || METH_POST missing_cl http-request deny if METH_GET HTTP_CONTENT http-request deny unless METH_GET or METH_POST or METH_OPTIONS

为请求“www”站点的静态内容,以及“img”、“video”、“download”和“ftp”主机上的所有请求,选择不同的后端:

acl url_static  path_beg         /static /images /img /css
acl url_static  path_end         .gif .png .jpg .css .js
acl host_www    hdr_beg(host) -i www
acl host_static hdr_beg(host) -i img. video. download. ftp.
# now use backend "static" for all static-only hosts, and for static URLs
# of host "www". Use backend "www" for the rest.
use_backend static if host_static or host_www url_static
use_backend www    if host_www

也可以使用“匿名 ACL”构建规则。这些是未命名的 ACL 表达式,可在无需声明的情况下动态构建。它们必须用大括号括起,大括号前后均需留一个空格(因为大括号必须被视为独立的词)。示例:

The following rule:

    acl missing_cl req.hdr_cnt(Content-length) eq 0
    http-request deny if METH_POST missing_cl

Can also be written that way:

    http-request deny if METH_POST { req.hdr_cnt(Content-length) eq 0 }

通常不建议使用此结构,因为以这种方式编写配置时更容易引入错误。然而,对于仅匹配单一源 IP 地址等非常简单的规则,使用它们可能比声明带有随机名称的 ACL 更为合理。另一个合适的使用示例是:

With named ACLs:

     acl site_dead nbsrv(dynamic) lt 2
     acl site_dead nbsrv(static)  lt 2
     monitor fail  if site_dead

With anonymous ACLs:

     monitor fail if { nbsrv(dynamic) lt 2 } || { nbsrv(static) lt 2 }

请参阅 第 4.2 节 ,以获取关于 “http-request deny” 和 “use_backend” 关键字的详细说明。

7.3. 获取样本

历史上,样本提取方法仅用于通过 ACL 匹配模式来检索数据。随着粘性表(stick-tables)的引入,一类新的样本提取方法被创建,通常与对应的 ACL 语法保持一致。这些样本提取方法也被称为“提取操作”。截至目前,ACL 与提取操作已实现统一。所有 ACL 提取方法均已作为提取方法提供,ACL 也可使用任意样本提取方法。

本节详细说明所有可用的样本提取方法及其输出类型。部分样本提取方法拥有已弃用的别名,用于保持与现有配置的兼容性。这些别名已被明确标记为已弃用,新配置中不应使用。

当可用时,也会标明 ACL 衍生项及其对应的匹配方法。这些项均具有明确的默认模式匹配方法,因此无需(尽管允许)传递 “-m” 选项来指定样本如何通过 ACL 进行匹配。

如上文样本类型与匹配兼容性矩阵所示,在 ACL 中使用通用样本提取方法时,除非样本类型为 boolean、integer、IPv4 或 IPv6,否则必须指定 “-m” 选项。当同一关键字同时作为 ACL 关键字和标准样本提取方法存在时,ACL 引擎默认将自动选择仅适用于 ACL 的版本。

部分关键字支持一个或多个必选参数,以及一个或多个可选参数。这些参数具有严格的类型,并在配置解析时进行检查,以确保不会因错误参数(例如未解析的后端名称)而运行。获取函数的参数用圆括号括起,并以逗号分隔。当某个参数为可选时,将在其下方用方括号(’[’ 和 ‘]’)标明。当所有参数均为可选时,圆括号可省略。

因此,标准样本提取方法的语法如下之一:

  • name
  • name(arg1)
  • name(arg1, arg2)

7.3.1. 转换器

样本提取方法可与转换器结合使用,以在提取的样本上应用转换(也称为“转换器”)。这些组合构成了所谓的“样本表达式”,其结果为一个“样本”。最初,这一功能仅由“stick on”和“stick store-request”指令支持,现已扩展至所有可使用样本的场景(ACL、日志格式、唯一 ID 格式、添加头、…)。

这些转换以一系列特定关键字的形式列出,紧跟在样本提取方法之后。 这些关键字也可以直接附加在 fetch 关键字的参数之后,以逗号分隔。 这些关键字还可能支持某些参数(例如,网络掩码),参数必须用括号括起传递。

某些类型的转换器为位运算和算术运算符,支持对整数执行基本操作。支持部分位运算(and、or、xor、cpl),以及部分算术运算(add、sub、mul、div、mod、neg)。还提供了一些比较器(odd、even、not、bool),可实现无需编写 ACL 即报告匹配结果。

以下关键字受支持:

   keyword                                         input type   output type
------------------------------------------------+-------------+----------------
51d.single(prop[,prop*])                           string       string
add(value)                                         integer      integer
add_item(delim[,var[,suff]])                       string       string
aes_cbc_dec(bits,nonce,key[,<aad>])                binary       binary
aes_cbc_enc(bits,nonce,key[,<aad>])                binary       binary
aes_gcm_dec(bits,nonce,key,aead_tag[,aad])         binary       binary
aes_gcm_enc(bits,nonce,key,aead_tag[,aad])         binary       binary
and(value)                                         integer      integer
b64dec                                             string       binary
base2                                              binary       string
base64                                             binary       string
be2dec(separator,chunk_size[,truncate])            binary       string
le2dec(separator,chunk_size[,truncate])            binary       string
be2hex([separator[,chunk_size[,truncate]]])        binary       string
bool                                               integer      boolean
bytes(offset[,length])                             binary       binary
capture-req(id)                                    string       string
capture-res(id)                                    string       string
concat([start[,var[,end]]])                        string       string
cpl                                                integer      integer
crc32([avalanche])                                 binary       integer
crc32c([avalanche])                                binary       integer
cut_crlf                                           string       string
da-csv-conv(prop[,prop*])                          string       string
date                                               string       integer
debug([prefix][,destination])                       any          same
-- keyword -------------------------------------+- input type + output type -
digest(algorithm)                                  binary       binary
div(value)                                         integer      integer
djb2([avalanche])                                  binary       integer
eth.data                                           binary       binary
eth.dst                                            binary       binary
eth.hdr                                            binary       binary
eth.proto                                          binary       integer
eth.src                                            binary       binary
eth.vlan                                           binary       integer
even                                               integer      boolean
fe_exists                                          string       boolean
field(index,delimiters[,count])                    string       string
fix_is_valid                                       binary       boolean
fix_tag_value(tag)                                 binary       binary
has_ctl([mask])                                    binary       boolean
hex                                                binary       string
hex2i                                              binary       integer
hmac(algorithm,key)                                binary       binary
host_only                                          string       string
htonl                                              integer      integer
http_date([offset[,unit]])                         integer      string
iif(true,false)                                    boolean      string
in_table([table])                                  any          boolean
ip.data                                            binary       binary
ip.df                                              binary       integer
ip.dst                                             binary       address
ip.fp                                              binary       binary
ip.hdr                                             binary       binary
ip.proto                                           binary       integer
ip.src                                             binary       address
ip.tos                                             binary       integer
ip.ttl                                             binary       integer
ip.ver                                             binary       integer
ipmask(mask4[,mask6])                              address      address
json([input-code])                                 string       string
json_query(json_path[,output_type])                string       _outtype_
jwt_decrypt_jwk(<jwk>)                             string       binary
jwt_decrypt_cert(<cert>)                           string       binary
jwt_decrypt_secret(<secret>)                       string       binary
jwt_header_query([json_path[,output_type]])        string       string
jwt_payload_query([json_path[,output_type]])       string       string
-- keyword -------------------------------------+- input type + output type -
jwt_verify(alg,key)                                string       integer
jwt_verify_cert(alg,cert)                          string       integer
language(value[,default])                          string       string
length                                             string       integer
lower                                              string       string
ltime(format[,offset])                             integer      string
ltrim(chars)                                       string       string
map(map_name[,default_value])                      string       string
map_match(map_name[,default_value])                _match_      string
map_match_output(map_name[,default_value])         _match_      _output_
mod(value)                                         integer      integer
mqtt_field_value(pkt_type,fieldname_or_prop_ID)    binary       binary
mqtt_is_valid                                      binary       boolean
ms_ltime(format[,offset])                          integer      string
ms_utime(format[,offset])                          integer      string
mul(value)                                         integer      integer
nbsrv                                              string       integer
neg                                                integer      integer
not                                                integer      boolean
odd                                                integer      boolean
or(value)                                          integer      integer
-- keyword -------------------------------------+- input type + output type -
param(name[,delim])                                string       string
port_only                                          string       integer
protobuf(field_number[,field_type])                binary       binary
regsub(regex,subst[,flags])                        string       string
reverse                                            string       string
reverse_dom                                        string       string
rfc7239_field(field)                               string       string
rfc7239_is_valid                                   string       boolean
rfc7239_n2nn                                       string       address / str
rfc7239_n2np                                       string       integer / str
rfc7239_nn                                         address/str  string
rfc7239_np                                         integer/str  string
rtrim(chars)                                       string       string
sdbm([avalanche])                                  binary       integer
secure_memcmp(var)                                 string       boolean
set-var(var[,cond...])                              any          same
sha1                                               binary       binary
sha2([bits])                                       binary       binary
srv_is_up                                          string       boolean
srv_queue                                          string       integer
strcmp(var)                                        string       boolean
sub(value)                                         integer      integer
table_bytes_in_rate([table])                       any          integer
table_bytes_out_rate([table])                      any          integer
table_clr_gpc(idx[,table])                         any          integer
table_clr_gpc0([table])                            any          integer
table_clr_gpc1([table])                            any          integer
table_conn_cnt([table])                            any          integer
-- keyword -------------------------------------+- input type + output type -
table_conn_cur([table])                            any          integer
table_conn_rate([table])                           any          integer
table_expire([table[,default_value]])              any          integer
table_glitch_cnt([table])                          any          integer
table_glitch_rate([table])                         any          integer
table_gpc(idx[,table])                             any          integer
table_gpc0([table])                                any          integer
table_gpc0_rate([table])                           any          integer
table_gpc1([table])                                any          integer
table_gpc1_rate([table])                           any          integer
table_gpc_rate(idx[,table])                        any          integer
table_gpt(idx[,table])                             any          integer
table_gpt0([table])                                any          integer
table_http_err_cnt([table])                        any          integer
table_http_err_rate([table])                       any          integer
table_http_fail_cnt([table])                       any          integer
table_http_fail_rate([table])                      any          integer
table_http_req_cnt([table])                        any          integer
table_http_req_rate([table])                       any          integer
table_idle([table[,default_value]])                any          integer
table_inc_gpc(idx[,table])                         any          integer
table_inc_gpc0([table])                            any          integer
table_inc_gpc1([table])                            any          integer
table_kbytes_in([table])                           any          integer
-- keyword -------------------------------------+- input type + output type -
table_kbytes_out([table])                          any          integer
table_server_id([table])                           any          integer
table_sess_cnt([table])                            any          integer
table_sess_rate([table])                           any          integer
table_trackers([table])                            any          integer
tcp.dst                                            binary       integer
tcp.flags                                          binary       integer
tcp.options.mss                                    binary       integer
tcp.options.sack                                   binary       integer
tcp.options.tsopt                                  binary       integer
tcp.options.tsval                                  binary       integer
tcp.options.wscale                                 binary       integer
tcp.options.wsopt                                  binary       integer
tcp.options_list                                   binary       binary
tcp.seq                                            binary       integer
tcp.src                                            binary       integer
tcp.win                                            binary       integer
ub64dec                                            string       string
ub64enc                                            string       string
ungrpc(field_number[,field_type])                  binary       binary / int
unset-var(var)                                      any          same
upper                                              string       string
url_dec([in_form])                                 string       string
url_enc([enc_type])                                string       string
us_ltime(format[,offset])                          integer      string
us_utime(format[,offset])                          integer      string
utime(format[,offset])                             integer      string
when(condition)                                     any          same
word(index,delimiters[,count])                     string       string
wt6([avalanche])                                   binary       integer
x509_v_err_str                                     integer      string
xor(value)                                         integer      integer
-- keyword -------------------------------------+- input type + output type -
xxh3([seed])                                       binary       integer
xxh32([seed])                                      binary       integer
xxh64([seed])                                      binary       integer

转换器关键字的详细列表如下:

51d.single(<prop>[,<prop>*])

51d.single(<prop>[,<prop>*])

以字符串形式返回所请求属性的值,各值之间使用“51degrees-property-separator”指定的分隔符分隔。设备通过传递给转换器的 User-Agent 头进行识别。该函数最多可传入五个属性名,若某属性名无法找到,则返回值为 “NoData”。

示例:

# Here the header "X-51D-DeviceTypeMobileTablet" is added to the request,
# containing values for the three properties requested by using the
# User-Agent passed to the converter.
frontend http-in
  bind *:8081
  default_backend servers
  http-request set-header X-51D-DeviceTypeMobileTablet \
    %[req.fhdr(User-Agent),51d.single(DeviceType,IsMobile,IsTablet)]

add(<value>)

add(<value>)

将 <value> 加到类型为有符号整数的输入值上,并以有符号整数形式返回结果。<value> 可以是数值或变量名。有关变量的详细信息,请参阅 第 2.8 节 。

add_item(<delim>[,<var>[,<suff>]])

add_item(<delim>[,<var>[,<suff>]])

将当前样本之后至少 2 个、最多 3 个字段连接起来,然后转换为字符串。第一个字段 <delim> 为常量字符串,若当前样本非空,且 <var> 或 <suff> 至少一个非空,则该常量字符串将立即追加到现有样本之后。第二个字段 <var> 为变量名,将查找该变量,将其内容转换为字符串,并立即追加到 <delim> 部分之后。若变量未找到,则不追加任何内容。该字段为可选,可选择性地后接常量字符串 <suff>,但若 <var> 被省略,则 <suff> 必须存在。该转换器与 concat 转换器类似,可用于由多个变量串联构建新变量,但主要区别在于其会检查添加分隔符是否合理,而不会像使用 concat 转换器时那样出现当前样本为空却仍添加分隔符的情况。若需使用逗号或右括号作为分隔符,必须用引号或反斜杠保护,且这些保护措施本身也需被保护,以防止被第一层解析器去除(请参见 本指南第 2.2 段 中关于引号与转义的说明)。请参见下方示例。

示例:

http-request set-var(req.tagged) 'var(req.tagged),add_item(",",req.score1,"(site1)") if src,in_table(site1)'
http-request set-var(req.tagged) 'var(req.tagged),add_item(",",req.score2,"(site2)") if src,in_table(site2)'
http-request set-var(req.tagged) 'var(req.tagged),add_item(",",req.score3,"(site3)") if src,in_table(site3)'
http-request set-header x-tagged %[var(req.tagged)]

http-request set-var(req.tagged) 'var(req.tagged),add_item(",",req.score1),add_item(",",req.score2)'
http-request set-var(req.tagged) 'var(req.tagged),add_item(",",,(site1))' if src,in_table(site1)

aes_cbc_dec(<bits>,<nonce>,<key>[,<aad>])

aes_cbc_dec(<bits>,<nonce>,<key>[,<aad>])

使用 AES128-CBC、AES192-CBC 或 AES256-CBC 算法解密原始字节输入,具体算法取决于 <bits> 参数。所有其他参数必须为 Base64 编码格式,返回结果为原始字节格式。<aad> 参数为可选。若 <aad> 验证失败,转换器不返回任何数据。<nonce>、<key> 和 <aad> 可为字符串或变量。该转换器要求至少使用 OpenSSL 1.0.1。

示例:

http-response set-header X-Decrypted-Text %[var(txn.enc),\
  aes_cbc_dec(128,txn.nonce,Zm9vb2Zvb29mb29wZm9vbw==)]

aes_cbc_enc(<bits>,<nonce>,<key>[,<aad>])

aes_cbc_enc(<bits>,<nonce>,<key>[,<aad>])

使用 AES128-CBC、AES192-CBC 或 AES256-CBC 算法对原始字节输入进行加密,具体算法取决于 <bits> 参数。<nonce>、<key> 和 <aad> 参数必须为 Base64 编码。<aad> 参数为可选。返回结果为原始字节格式。<nonce>、<key> 和 <aad> 可为字符串或变量。此转换器要求至少使用 OpenSSL 1.0.1。

示例:

http-response set-header X-Encrypted-Text %[var(txn.plain),\
  aes_cbc_enc(128,txn.nonce,Zm9vb2Zvb29mb29wZm9vbw==)]

aes_gcm_dec(<bits>,<nonce>,<key>,<aead_tag>[,<aad>])

aes_gcm_dec(<bits>,<nonce>,<key>,<aead_tag>[,<aad>])

使用 AES128-GCM、AES192-GCM 或 AES256-GCM 算法解密原始字节输入,具体算法由 <bits> 参数决定。所有其他参数必须以 Base64 编码,返回结果为原始字节格式。若 <aead_tag> 或 <aad> 验证失败,转换器将不返回任何数据。<aad> 参数为可选。<nonce>、<key>、<aead_tag> 和 <aad> 可为字符串或变量。该转换器要求至少使用 OpenSSL 1.0.1。

示例:

http-response set-header X-Decrypted-Text %[var(txn.enc),\
  aes_gcm_dec(128,txn.nonce,Zm9vb2Zvb29mb29wZm9vbw==,txn.aead_tag)]

aes_gcm_enc(<bits>,<nonce>,<key>,<aead_tag>[,<aad>])

aes_gcm_enc(<bits>,<nonce>,<key>,<aead_tag>[,<aad>])

使用 AES128-GCM、AES192-GCM 或 AES256-GCM 算法对原始字节输入进行加密,具体取决于 <bits> 参数。<nonce>、<key> 和 <aad> 参数必须为 Base64 编码。参数 <aead_tag> 必须为变量。AEAD 标签将以 Base64 编码形式存储于该变量中。<aad> 参数为可选。返回结果为原始字节格式。<nonce>、<key> 和 <aad> 可为字符串或变量。此转换器要求至少使用 OpenSSL 1.0.1。

示例:

http-response set-header X-Encrypted-Text %[var(txn.plain),\
  aes_gcm_enc(128,txn.nonce,Zm9vb2Zvb29mb29wZm9vbw==,txn.aead_tag)]

and(<value>)

and(<value>)

对 <value> 与输入的有符号整数类型值执行按位“与”运算,并将结果以有符号整数形式返回。<value> 可以是数值或变量名。有关变量的详细信息,请参阅 第 2.8 节 。

b64dec

b64dec

将 base64 编码的输入字符串转换(解码)为其二进制表示。该操作与 base64() 执行相反。对于 base64url(“URL 和文件名安全字母表” (RFC 4648)) 变体,请参见 “ub64dec”。

base2

base2

将二进制输入样本转换为二进制字符串,每个输入字节对应八个二进制数字。该功能用于在原生表示形式不支持前缀匹配的类型上执行最长前缀匹配,例如 IP 前缀。

base64

base64

将二进制输入样本转换为 base64 字符串。该功能用于以可可靠传输的方式记录或传输二进制内容(例如,SSL ID 可以复制到头中)。有关 base64url(“URL 和文件名安全字母表”(RFC 4648))变体,请参见 “ub64enc”。

be2dec(<separator>,<chunk_size>[,<truncate>])

be2dec(<separator>,<chunk_size>[,<truncate>])

将大端字节序的二进制输入样本转换为字符串,每 <chunk_size> 个输入字节对应一个无符号整数。若指定,每 <chunk_size> 个二进制输入字节之间插入 <separator>。<truncate> 标志表示二进制输入是否在 <chunk_size> 边界处被截断。<chunk_size> 的最大值受 long long int 大小限制(8 字节)。

示例:

bin(01020304050607),be2dec(:,2)   # 258:772:1286:7
bin(01020304050607),be2dec(-,2,1) # 258-772-1286
bin(01020304050607),be2dec(,2,1)  # 2587721286
bin(7f000001),be2dec(.,1)         # 127.0.0.1

le2dec(<separator>,<chunk_size>[,<truncate>])

le2dec(<separator>,<chunk_size>[,<truncate>])

将小端格式的二进制输入样本转换为字符串,每 <chunk_size> 个输入字节对应一个无符号整数。若指定,每 <chunk_size> 个二进制输入字节之间插入 <separator>。<truncate> 标志表示二进制输入是否在 <chunk_size> 边界处截断。<chunk_size> 的最大值受 long long int 大小限制(8 字节)。

示例:

bin(01020304050607),le2dec(:,2)   # 513:1284:2055:7
bin(01020304050607),le2dec(-,2,1) # 513-1284-2055
bin(01020304050607),le2dec(,2,1)  # 51312842055
bin(7f000001),le2dec(.,1)         # 127.0.0.1

be2hex([<separator>[,<chunk_size>[,<truncate>]]])

be2hex([<separator>[,<chunk_size>[,<truncate>]]])

将大端字节序的二进制输入样本转换为每输入字节对应两个十六进制数字的十六进制字符串。该功能用于以可可靠传输的方式记录或传输某些二进制输入数据的十六进制转储(例如,可将 SSL ID 复制到头中)。若指定,每 <chunk_size> 个二进制输入字节插入一次 <separator>。<truncate> 标志表示二进制输入是否在 <chunk_size> 边界处被截断。

示例:

bin(01020304050607),be2hex         # 01020304050607
bin(01020304050607),be2hex(:,2)    # 0102:0304:0506:07
bin(01020304050607),be2hex(--,2,1) # 0102--0304--0506
bin(0102030405060708),be2hex(,3,1) # 010203040506

bool

bool

如果输入值为有符号整数类型且非空,则返回布尔值 TRUE,否则返回 FALSE。与 and() 配合使用时,可用于对输入值进行位测试,报告真或假(例如,验证标志是否存在)。

bytes(<offset>[,<length>])

bytes(<offset>[,<length>])

从输入的二进制样本中提取部分字节。结果为一个二进制样本,起始于原始样本的指定偏移量(以字节为单位),并可选地在指定长度处截断。<offset> 和 <length> 可以是数值或变量名。若 <offset> 或 <length> 无效,则转换器返回空样本。无效的 <offset> 指负值或大于输入样本长度的值。无效的 <length> 指负值。

示例:

http-request set-var(txn.input) req.hdr(input) # let's say input is "012345"

http-response set-header bytes_0 "%[var(txn.input),bytes(0)]"  # outputs "012345"
http-response set-header bytes_1_3 "%[var(txn.input),bytes(1,3)]"  # outputs "123"

http-response set-var(txn.var_start) int(1)
http-response set-var(txn.var_length) int(3)
http-response set-header bytes_var1_var3    "%[var(txn.input),bytes(txn.var_start,txn.var_length)]"  # outputs "123"

capture-req(<id>)

capture-req(<id>)

捕获请求槽 <id> 中的字符串条目,并原样返回该条目。若槽不存在,捕获将静默失败。

另请参阅:“declare capture”、“http-request capture”、“http-response capture”、“capture.req.hdr” 和 “capture.res.hdr”(样本提取)。

capture-res(<id>)

capture-res(<id>)

捕获响应槽 <id> 中的字符串条目,并原样返回该条目。若槽不存在,捕获操作将静默失败。

另请参阅:“declare capture”、“http-request capture”、“http-response capture”、“capture.req.hdr” 和 “capture.res.hdr”(样本提取)。

concat([<start>[,<var>[,<end>]]])

concat([<start>[,<var>[,<end>]]])

将当前样本之后最多 3 个字段拼接为字符串。第一个字段 <start> 为常量字符串,将在现有样本之后立即追加。若未使用,可省略。第二个字段 <var> 为变量名,将查找该变量,将其内容转换为字符串,并立即追加至 <first> 部分之后。若变量未找到,则不追加任何内容。该字段也可省略。第三个字段 <end> 为常量字符串,将在变量之后追加。该字段同样可省略。上述元素共同支持将带分隔符的变量与现有变量集进行拼接。可用于构建由多个其他变量组成的复合变量,例如以冒号分隔的值。若需使用逗号或右括号作为分隔符,必须用引号或反斜杠保护,且这些保护字符本身也需被保护,以防止被第一层解析器去除。通常用于从其他变量构建复合变量,但有时使用包含多个字段的格式字符串可能更为便捷。参见下方示例。

示例:

tcp-request session set-var(sess.src) src
tcp-request session set-var(sess.dn)  ssl_c_s_dn
tcp-request session set-var(txn.sig) str(),concat(<ip=,sess.ip,>),concat(<dn=,sess.dn,>)
tcp-request session set-var(txn.ipport) "str(),concat('addr=(',sess.ip),concat(',',sess.port,')')"
tcp-request session set-var-fmt(txn.ipport) "addr=(%[sess.ip],%[sess.port])"  ## does the same
http-request set-header x-hap-sig %[var(txn.sig)]

cpl

cpl

对类型为有符号整数的输入值执行按位取反(翻转所有位)操作,并将结果以有符号整数形式返回。

crc32([<avalanche>])

crc32([<avalanche>])

使用 CRC32 哈希函数将二进制输入样本哈希为无符号 32 位整数。 可选地,若可选参数 <avalanche> 等于 1,则可对输出应用完整的雪崩哈希函数。 该转换器使用与各种基于哈希的负载均衡算法相同的函数,因此将提供完全相同的结果。 其设计目的是为了与其他希望对某些输入键计算 CRC32 的软件保持兼容,因此遵循以太网、Gzip、PNG 等中常见的实现方式。 相比其他算法,该方法速度较慢,但可能提供更优或至少更不可预测的分布效果。 不得用于安全目的,因为 32 位哈希极易被破解。 另请参见 “djb2”、“sdbm”、“wt6”、“crc32c” 以及 “hash-type” 指令。

crc32c([<avalanche>])

crc32c([<avalanche>])

使用 CRC32C 哈希函数将二进制输入样本哈希为无符号 32 位整数。 可选地,如果可选参数 <avalanche> 等于 1,则可对输出应用完整的雪崩哈希函数。 该转换器使用 RFC4960 附录 B [8] 中所述的相同函数。 此功能用于与其他希望对某些输入键计算 CRC32C 的软件保持兼容性。 该算法速度较慢,且不得用于安全目的,因为 32 位哈希极易被破解。 另请参阅 “djb2”、“sdbm”、“wt6”、“crc32” 以及 “hash-type” 指令。

cut_crlf

cut_crlf

在首个回车符(’\r’)或换行符(’\n’)处截断输入样本的字符串表示形式。仅更新字符串长度。

da-csv-conv(<prop>[,<prop>*])

da-csv-conv(<prop>[,<prop>*])

请求 DeviceAtlas 转换器识别传入的 User Agent 字符串,并输出由参数中列出的属性拼接而成的字符串,属性之间使用全局关键字 “deviceatlas-property-separator” 定义的分隔符分隔,或默认使用竖线字符 (’|’)。HAProxy 配置语言对不同属性的数量限制为 12 个。

示例:

frontend www
  bind *:8881
  default_backend servers
  http-request set-header X-DeviceAtlas-Data %[req.fhdr(User-Agent),da-csv(primaryHardwareType,osName,osVersion,browserName,browserVersion,browserRenderingEngine)]

date

date

此转换器用于从 HTTP 头中转换日期。它可以是 IMF 日期、ASCTIME 日期或 RFC850 日期。转换结果将输出为 UNIX 时间戳。

示例:

http-request return lf-string "%[str('Sun, 06 Nov 1994 08:49:37 GMT'),date]\n" content-type text/plain

debug([<prefix][,<destination>])

debug([<prefix][,<destination>])

本文中的转换器用作调试工具。它捕获输入样本,并将其发送至事件接收端 <destination>,该接收端可指定环形缓冲区(如 “buf0”),也可指定 “stdout” 或 “stderr”。可通过在 CLI 中执行 “show events” 命令实时检查可用的接收端。若未指定,输出默认为 “buf0”,可通过 CLI 的 “show events” 命令查阅。可选前缀 <prefix> 可传递,以帮助区分多个表达式产生的输出。该前缀将出现在输出消息的冒号之前。输入样本将原样输出,因此可安全地将调试转换器插入链中的任意位置,即使样本类型包含不可打印字符亦可。

示例:

tcp-request connection track-sc0 src,debug(track-sc)

digest(<algorithm>)

digest(<algorithm>)

将二进制输入样本转换为消息摘要。结果为二进制样本。<algorithm> 必须为 OpenSSL 消息摘要名称(例如 sha256)。

请注意,仅当 HAProxy 编译时包含 USE_OPENSSL 时,此转换器才可用。

div(<value>)

div(<value>)

将类型为有符号整数的输入值除以 <value>,并将结果以有符号整数形式返回。若 <value> 为 null,则返回最大无符号整数(通常为 2^63-1)。<value> 可为数值或变量名。有关变量的详细信息,请参见 第 2.8 节 。

djb2([<avalanche>])

djb2([<avalanche>])

使用 DJB2 哈希函数将二进制输入样本哈希为无符号 32 位整数。 可选地,若可选参数 <avalanche> 等于 1,则可对输出应用完整的雪崩哈希函数。 该转换器使用与各种基于哈希的负载均衡算法相同的函数,因此将提供完全相同的结果。 其主要用途为调试,但也可用作粘性表条目以收集粗略统计信息。 不得用于安全目的,因为 32 位哈希极易被破解。 另请参见 “crc32”、“sdbm”、“wt6”、“crc32c” 以及 “hash-type” 指令。

eth.data

eth.data

此功能与表示二进制以太网帧的输入样本配合使用,该样本由 “fc_saved_syn” 与 “tcp-ss” 绑定选项设置为 “2” 时返回。它跳过所有以太网头(包括可能的 VLAN)并返回从第 3 层协议(通常为 IPv4 或 IPv6)开始的二进制数据块。参见 “fc_saved_syn” 和 “tcp-ss”。

eth.dst

eth.dst

此功能与表示二进制以太网帧的样本配合使用,该样本由 “fc_saved_syn” 与设置为 “2” 的 “tcp-ss” 绑定选项共同返回。它返回对应于帧目标地址的以太网头的 6 字节内容,以二进制块形式输出。另请参见 “fc_saved_syn” 和 “tcp-ss”。

eth.hdr

eth.hdr

此功能与表示二进制以太网帧的输入样本配合使用,该样本由 “fc_saved_syn” 与 “tcp-ss” 绑定选项设置为 “2” 时返回。它会裁剪以太网头之后的内容,但保留可能存在的 VLAN 信息,并将此头作为二进制数据块返回。参见 “fc_saved_syn” 和 “tcp-ss”。

eth.proto

eth.proto

此功能用于处理表示二进制以太网帧的输入样本,该样本由 “fc_saved_syn” 与 “tcp-ss” 绑定选项设置为 “2” 时返回。它将返回以太网头中在任何可选 VLAN 之后的协议号(也称为 EtherType),以整数值形式表示。通常情况下,该值应为 0x800(表示 IPv4)或 0x86DD(表示 IPv6)。另请参见 “fc_saved_syn” 和 “tcp-ss”。

eth.src

eth.src

此功能与表示二进制以太网帧的输入样本配合使用,该样本由 “fc_saved_syn” 返回,并配合设置 “tcp-ss” 绑定选项为 “2”。它返回对应于帧源地址的以太网头的 6 字节内容,以二进制块形式输出。另请参见 “fc_saved_syn” 和 “tcp-ss”。

eth.vlan

eth.vlan

此功能与表示二进制以太网帧的输入样本配合使用,该样本由 “fc_saved_syn” 与设置为 “2” 的 “tcp-ss” 绑定选项共同生成。它返回以太网头中找到的最后一个 VLAN ID,以整数值形式输出。参见 “fc_saved_syn” 和 “tcp-ss”。

even

even

如果输入值为有符号整数类型且为偶数,则返回布尔值 TRUE;否则返回 FALSE。其功能等价于 “not,and(1),bool”。

field(<index>,<delimiters>[,<count>])

field(<index>,<delimiters>[,<count>])

使用给定的分隔符切分输入字符串,并提取指定索引处的子串。正索引从开头计数,负索引从结尾计数。索引从 1 或 -1 开始;分隔符为格式化字符列表。可以指定要提取的字段数 <count>(默认值:1)。值 0 表示提取所有剩余字段。

示例:

str(f1_f2_f3__f5),field(4,_)    # <empty>
str(f1_f2_f3__f5),field(5,_)    # f5
str(f1_f2_f3__f5),field(2,_,0)  # f2_f3__f5
str(f1_f2_f3__f5),field(2,_,2)  # f2_f3
str(f1_f2_f3__f5),field(-2,_,3) # f2_f3_
str(f1_f2_f3__f5),field(-3,_,0) # f1_f2_f3

fe_exists

fe_exists

接收前端名称作为输入值,若当前配置中存在同名前端,则返回布尔值 TRUE,否则返回 FALSE。可在需要验证动态名称对应的前端是否存在时使用,例如映射查找或响应外部检查。

示例:

http-request deny unless { var(txn.fe_name),fe_exists }

fix_is_valid

fix_is_valid

解析二进制负载,并对 FIX(金融信息交换)协议执行合理性检查:

  • 检查所有标签 ID 和值均不为空,且标签 ID 为有效数值
  • 检查 BeginString 标签为具有有效 FIX 版本的第一个标签
  • 检查 BodyLength 标签为第二个标签,且其值与报文长度一致
  • 检查 MsgType 标签为第三个标签
  • 检查报文最后一个标签为 CheckSum 标签,且校验和有效

由于当前 HAProxy 的设计限制,仅能解析客户端与服务器发送的首个消息。

该转换器返回一个布尔值,若负载包含有效的 FIX 消息则为 true,否则为 false。

另请参见 fix_tag_value 转换器。

示例:

tcp-request inspect-delay 10s
tcp-request content reject unless { req.payload(0,0),fix_is_valid }

fix_tag_value(<tag>)

fix_tag_value(<tag>)

解析一个 FIX(Financial Information eXchange)消息,并从标签 <tag> 中提取值。<tag> 可以是字符串或整数,指向所需标签。接受任意整数值,但仅以下字符串会被转换为对应的整数值:BeginString、BodyLength、MsgType、SenderCompID、TargetCompID、CheckSum。可轻松添加更多标签名称。

由于当前 HAProxy 的设计限制,仅能解析客户端与服务器发送的首条消息。该转换器不会对消息进行验证。强烈建议在使用本转换器前,先通过 fix_is_valid 转换器对消息进行验证。

另请参见 fix_is_valid 转换器。

示例:

tcp-request inspect-delay 10s
tcp-request content reject unless { req.payload(0,0),fix_is_valid }
# MsgType tag ID is 35, so both lines below will return the same content
tcp-request content set-var(txn.foo) req.payload(0,0),fix_tag_value(35)
tcp-request content set-var(txn.bar) req.payload(0,0),fix_tag_value(MsgType)

has_ctl([mask])

has_ctl([mask])

按照 mask 参数的定义,检查输入的二进制样本中是否包含控制字符。掩码是一个 33 位数字(可使用十进制,或以 0x 为前缀的十六进制):其中每一位分别对应 0x00 至 0x1F 范围内的一个字符,第 32 位用于匹配 DEL 字符(0x7F)。未指定掩码时,转换器使用 0x1FFFFFDFF,匹配除 TAB(0x09)以外的所有控制字符;TAB 常用于 HTTP 头。特殊掩码 any 等于 0x1FFFFFFFF,会匹配包括 TAB 在内的全部控制字符。特殊掩码 http 等于 0x2401,仅匹配 HTTP 头值中禁止出现的 CR(0x0D)、LF(0x0A)和 NUL(0x00)。

示例:

# reject presence of DEL, CR, LF, NUL characters in the referer header
http-request deny if { req.fhdr(referer),has_ctl(0x100002401) }
# reject presence of any control char but tab in any HTTP header value
http-request deny if { req.hdr(),has_ctl }

hex

hex

将二进制输入样本转换为十六进制字符串,每个输入字节对应两个十六进制数字。该功能用于以可可靠传输的方式记录或传输某些二进制输入数据的十六进制转储(例如,可将 SSL ID 复制到头中)。

hex2i

hex2i

将包含每输入字节两个十六进制数字的十六进制字符串转换为整数。如果输入值无法转换,则返回零。

hmac(<algorithm>,<key>)

hmac(<algorithm>,<key>)

使用指定密钥将二进制输入样本转换为消息认证码。结果为二进制样本。<algorithm> 必须为已注册的 OpenSSL 消息摘要名称之一(例如 sha256)。<key> 参数必须以 Base64 编码,可以为字符串或变量。

请注意,仅当 HAProxy 编译时包含 USE_OPENSSL 时,此转换器才可用。

host_only

host_only

将包含 Host 头值的字符串转换为不带端口的形式。输入必须符合 Host 头值的格式(rfc9110#section-7.2)。该函数支持以下格式的输入:hostname、hostname:80、127.0.0.1、127.0.0.1:80、[::1]、[::1]:80。

此转换器还会将字符串转换为小写。

另请参见:“port_only” 转换器,该转换器将返回端口。

htonl

htonl

将输入的整数值转换为以网络字节序表示的 32 位二进制形式。 由于样本提取操作自身使用有符号 64 位整数,因此使用此转换器时,输入的整数值会首先被转换为无符号 32 位整数。

http_date([<offset[,<unit>]])

http_date([<offset[,<unit>]])

将一个表示自纪元以来日期的整数转换为适合在 HTTP 头字段中使用的字符串格式。若指定偏移值,则在转换前将其加到日期上。此功能特别适用于在响应中生成 Date 头字段、Expires 值(当偏移值为正时),或 Last-Modified 值(当偏移值为负时)。若指定单位值,则将时间戳视为“s”(秒,默认行为)、“ms”(毫秒)或“us”(微秒)自纪元以来的值。偏移值的单位与输入时间戳的单位一致。

iif(<true>,<false>)

iif(<true>,<false>)

输入值为真时返回 <true> 字符串,否则返回 <false> 字符串。

示例:

http-request set-header x-forwarded-proto %[ssl_fc,iif(https,http)]

in_table([<table>])

in_table([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中执行查找。如果键在表中未找到,返回布尔值 false。否则返回布尔值 true。此功能可用于验证表中是否已存在某个特定键(例如,源 IP 地址或 Authorization 头是否已被记录)。

ip.data

ip.data

此功能用于处理表示二进制以太网帧的输入样本,该样本由 “fc_saved_syn” 与 “tcp-ss” 绑定选项设置为 “1” 时返回,或由 “eth.data” 的输出提供。它跳过 IP 头以及任何可选选项或扩展,返回从传输协议(通常为 TCP 或 UDP)开始的二进制数据块。另请参见 “fc_saved_syn”、“tcp-ss” 和 “eth.data”。

ip.df

ip.df

此功能用于处理表示二进制以太网帧的输入样本,由 “fc_saved_syn” 与 “tcp-ss” 绑定选项设置为 “1” 时返回,或由 “eth.data” 输出所得。若 IP 头中的 DF(不分片)标志被设置,则返回整数值 1;否则返回 0。IPv6 无 DF 标志,且默认不分片,因此始终返回 1。另请参见 “fc_saved_syn”、“tcp-ss” 和 “eth.data”。

ip.dst

ip.dst

此功能用于处理表示二进制以太网帧的输入样本,该样本由 “fc_saved_syn” 与 “tcp-ss” 绑定选项设置为 “1” 时返回,或由 “eth.data” 的输出提供。它从 IPv4/v6 头中返回目标地址。另请参见 “fc_saved_syn”、“tcp-ss” 和 “eth.data”。

ip.fp([<mode>])

ip.fp([<mode>])

此转换器用于处理表示二进制以太网帧的输入样本,该样本由 “fc_saved_syn” 与 “tcp-ss” 绑定选项设为 “1” 时返回,或由 “eth.data” 的输出提供。它检查 IP 头和 TCP 头的多个部分,以构建一种指纹,该指纹包含可用于区分多个看似相同的主机的不变部分。实际应用场景是,在共享 IP 地址的情况下,精确定位行为异常的主机,从而避免因仅一个主机异常而阻断所有合法用户。该转换器基于输入构建最小长度为 8 字节的二进制块。指纹字节的排列方式如下: - 字节 0:IP TOS 字段(参见 ip.tos) - 字节 1: - 位 7:IPv6(1)/ IPv4(0) - 位 6:ip.df - 位 5..4:0:ip.ttl ≤ 32;1:ip.ttl ≤ 64;2:ip.ttl ≤ 128;3:ip.ttl ≤ 255 - 位 3:IP 选项存在(1)/ 不存在(0) - 位 2:TCP 数据存在(1)/ 不存在(0) - 位 1:TCP.flags 中 CWR 位已设置(1)/ 已清除(0) - 位 0:TCP.flags 中 ECE 位已设置(1)/ 已清除(0) - 字节 2: - 位 7..4:TCP 头长度(以 4 字节为单位) - 位 3..0:TCP 窗口缩放值 + 1(1..15)/ 0(未通告 WS) - 字节 3..4:tcp.win - 字节 5..6:tcp.options.mss,若不存在则为零 - 字节 7:每种存在的 TCP 选项对应 1 位,其中选项 2 至 8 分别映射到位 0 至 6,位 7 表示选项 9 至 255 中是否存在任一选项

<mode> 参数允许向指纹中附加更多信息。默认情况下,当 <mode> 参数未设置或值为零时,指纹仅由上述 8 字节构成。若 <mode> 指定为其他值,则其对应以下各项的总和,相应组件将按以下顺序拼接到指纹中: - 1:接收的 TTL 值附加到指纹中(1 字节) - 2:由 “tcp.options_list” 返回的 TCP 选项类型列表,包含 0 至 40 字节的额外数据,附加到指纹中 - 4:源 IP 地址附加到指纹中,IPv4 增加 4 字节,IPv6 增加 16 字节

示例:使用基础指纹(FP)、TTL 和源地址生成长度为 13..25 字节的指纹(1+4=5):

frontend test
    mode http
    bind:4445 tcp-ss 1
    tcp-request connection set-var(sess.syn) fc_saved_syn
    http-request return status 200 content-type text/plain lf-string &#92;
          "src=%[var(sess.syn),ip.src] fp=%[var(sess.syn),ip.fp(5),hex]&#92;n"

另请参见 “fc_saved_syn”、“tcp-ss”、“eth.data”、“ip.df”、“ip.ttl”、“tcp.win”、“tcp.options.mss” 及 “tcp.options_list”。

ip.hdr

ip.hdr

此功能用于处理表示二进制以太网帧的输入样本,由 “fc_saved_syn” 与 “tcp-ss” 绑定选项设置为 “1” 时返回,或由 “eth.data” 的输出提供。它返回一段二进制数据块,起始于 IP 头,终止于最后一个选项或扩展之后、传输层协议头之前。另请参见 “fc_saved_syn”、“tcp-ss” 以及 “eth.data”。

ip.proto

ip.proto

此功能用于处理表示二进制以太网帧的输入样本,该样本由 “fc_saved_syn” 与 “tcp-ss” 绑定选项设置为 “1” 时返回,或由 “eth.data” 的输出提供。该功能返回传输层协议号,通常为 6(表示 TCP)或 17(表示 UDP)。另请参见 “fc_saved_syn”、“tcp-ss” 以及 “eth.data”。

ip.src

ip.src

此功能用于处理表示二进制以太网帧的输入样本,该样本由 “fc_saved_syn” 与 “tcp-ss” 绑定选项设置为 “1” 时返回,或由 “eth.data” 的输出提供。它从 IPv4/v6 头中返回源地址。另请参见 “fc_saved_syn”、“tcp-ss” 和 “eth.data”。

ip.tos

ip.tos

此功能用于处理表示二进制以太网帧的输入样本,该样本由 “fc_saved_syn” 与 “tcp-ss” 绑定选项设置为 “1” 时返回,或由 “eth.data” 输出所得。它返回一个整数,对应 IPv4 头中的服务类型(TOS)字段或 IPv6 头中的流量类别(TC)字段的值。请注意,在现代互联网中,该字段通常在高 6 位中包含 DSCP(区分服务代码点)值,而低 2 位可能未使用,或由 IP ECN 使用。请参阅 RFC2474 和 RFC8436 了解 DSCP 值,参阅 RFC3168 了解 IP ECN 字段。另请参见 “fc_saved_syn”、“tcp-ss” 和 “eth.data”。

ip.ttl

ip.ttl

此功能用于处理表示二进制以太网帧的样本,该样本由 “fc_saved_syn” 与 “tcp-ss” 绑定选项设置为 “1” 时返回,或由 “eth.data” 的输出提供。 该功能返回一个整数,对应 IPv4/IPv6 头中的 TTL(生存时间)或 HL(跳数限制)字段。该值通常预设为固定值,并在数据包经过每个路由器时递减。当已知初始值时,可借此推断客户端连接距离。请注意,大多数现代操作系统初始值均为 64。另请参见 “fc_saved_syn”、“tcp-ss” 和 “eth.data”。

ip.ver

ip.ver

此功能用于处理表示二进制以太网帧的输入样本,该样本由 “fc_saved_syn” 与 “tcp-ss” 绑定选项设置为 “1” 时返回,或由 “eth.data” 的输出提供。该功能返回 IP 头中的 IP 版本,通常为 4 或 6。请注意,此功能不会检查上层以太网帧中的协议号是否匹配,但由于预期使用的是有效数据包,因此操作系统应已验证该匹配关系。另请参见 “fc_saved_syn”、“tcp-ss” 和 “eth.data”。

ipmask(<mask4>[,<mask6>])

ipmask(<mask4>[,<mask6>])

对 IP 地址应用掩码,并使用结果进行查找和存储。此功能可用于使特定掩码范围内的所有主机共享相同的表项,从而使用同一台服务器。mask4 可以以点分十进制形式(例如 255.255.255.0)或 CIDR 形式(例如 24)传递。mask6 可以以四组形式(例如 ffff:ffff::)或 CIDR 形式(例如 64)传递。若未指定 mask6,出于向后兼容性考虑,IPv6 地址将无法转换。

json([<input-code>])

json([<input-code>])

转义输入字符串,并生成一个可直接用作 JSON 字符串的 ASCII 输出字符串。转换器会根据 <input-code> 参数尝试解码输入字符串。该参数可取值为 “ascii”、“utf8”、“utf8s”、“utf8p” 或 “utf8ps”。“ascii” 解码器始终不会失败。“utf8” 解码器可检测三种错误:

  • 无效的 UTF-8 序列(孤立的延续字节、延续字节数量错误等)
  • 无效的范围(解码后的值位于 UTF-8 禁止范围内)
  • 编码过长(该值使用的字节数多于必要数量)

UTF-8 JSON 编码在 UTF-8 字符大于 0xffff 时可能产生“值过长”错误,因为 JSON 字符串转义规范仅允许使用 4 位十六进制数字进行值编码。UTF-8 解码器存在 4 种变体,由两个后缀字母的组合指定:“p”表示“宽松模式”,“s”表示“静默忽略”。解码器的行为如下:

  • “ascii” : 始终成功;
  • “utf8” : 检测到任何错误时失败;
  • “utf8s” : 始终成功,但会移除对应错误的字符;
  • “utf8p” : 接受并修复过长错误,但遇到其他任何错误时失败;
  • “utf8ps” : 始终成功,接受并修复过长错误,但会移除对应其他错误的字符。

该转换器特别适用于为日志服务器生成经过正确转义的 JSON,这些日志服务器接收格式化的 JSON 流量日志。

示例:

capture request header Host len 15
capture request header user-agent len 150
log-format '{"ip":"%[src]","user-agent":"%[capture.req.hdr(1),json(utf8s)]"}'

客户端 127.0.0.1 发送的请求:

GET / HTTP/1.0
User-Agent: Very "Ugly" UA 1/2

输出日志:

{"ip":"127.0.0.1","user-agent":"Very \"Ugly\" UA 1\/2"}

json_query(<json_path>[,<output_type>])

json_query(<json_path>[,<output_type>])

本文档中的 json_query 转换器支持 string、boolean、number 和 array 类型。浮点数将以字符串形式返回。通过指定 output_type 为 int,值将被转换为整数。数组将以字符串形式返回,以方括号开头和结尾,内容为 CSV 格式。根据数据类型,数组元素可能被引号包围。若数组元素为复杂类型,字符串中将包含每个元素的完整 JSON 表示形式,元素间以逗号分隔。JWT 的 roles 查询示例结果如下:

["manage-account","manage-account-links","view-profile"]

如果无法进行转换,json_query 转换器将失败。

<json_path> 必须是符合 https://datatracker.ietf.org/doc/draft-ietf-jsonpath-base/ 定义的有效 JSON 路径字符串

请注意:根据上下文和底层实现的不同,重复 JSON 键的提取行为未定义,可能返回输入内容中相同键的首个、末个或任意其他出现位置,且若键名以编码形式传入,可能无法始终匹配。简言之,该转换器不适用于内容净化。

示例:

# get a integer value from the request body
# "{"integer":4}" => 5
http-request set-var(txn.pay_int) req.body,json_query('$.integer','int'),add(1)

# get a key with '.' in the name
# {"my.key":"myvalue"} => myvalue
http-request set-var(txn.pay_mykey) req.body,json_query('$.my\\.key')

# {"boolean-false":false} => 0
http-request set-var(txn.pay_boolean_false) req.body,json_query('$.boolean-false')

# get the value of the key 'iss' from a JWT Bearer token
http-request set-var(txn.token_payload) req.hdr(Authorization),word(2,.),ub64dec,json_query('$.iss')

jwt_decrypt_cert(<cert>)

jwt_decrypt_cert(<cert>)

按照 JSON Web 加密格式(参见 RFC 7516)对输入的 JSON Web Token 执行签名验证,并通过提供的证书解密返回其内容。<cert> 参数必须指向一个已加载的证书路径(可通过 “dump ssl cert” CLI 命令导出)。该证书必须显式将 “jwt” 选项设置为 “on”(参见 “jwt” crt-list 选项)。证书可直接提供,也可通过变量提供。目前仅支持使用紧凑序列化格式的令牌(由五个以点号分隔的 base64-url 编码字符串组成)。

此转换器可用于具有以下算法(JOSE 头中的 “alg” 字段)的令牌:RSA-OAEP、RSA-OAEP-256、ECDH-ES、ECDH-ES+A128KW、ECDH-ES+A192KW 或 ECDH-ES+A256KW。RSA1_5 算法已实现,但默认情况下已禁用,符合 RFC 8725 第 section 3.2 段的建议。如需启用,可借助 ‘jwt.decrypt_alg_list’ 全局选项重新激活。

支持的算法和加密算法(分别对应 JOSE 头中的 “alg” 和 “enc” 字段)可通过 ‘jwt.decrypt_alg_list’ 和 ‘jwt.decrypt_enc_list’ 全局选项进行修改。

JWE 令牌必须以 base64url 编码形式提供,输出将以“原始”形式返回。若在令牌解析、签名验证或内容解密过程中发生错误,将返回空字符串。

示例:

# Get a JWT from the authorization header, put its decrypted content in an
# HTTP header
http-request set-var(txn.bearer) http_auth_bearer
http-request set-header X-Decrypted %[var(txn.bearer),jwt_decrypt_cert("/foo/bar.pem")]

jwt_decrypt_jwk(<jwk>)

jwt_decrypt_jwk(<jwk>)

按照 JSON Web 加密格式(参见 RFC 7516)对输入的 JSON Web Token 执行签名验证,并通过提供的 JSON Web Key(RFC 7517)解密返回其内容。<jwk> 参数必须为类型为 ‘oct’、‘EC’ 或 ‘RSA’ 的有效 JWK(JSON 密钥中的 ‘kty’ 字段),可作为字符串提供,或通过变量传递。

目前仅支持管理使用紧凑序列化格式的令牌(由五个以点号分隔的 Base64-URL 编码字符串组成)。

此转换器可用于解码采用对称算法类型(JOSE 头中的 “alg” 字段)的令牌,支持的算法包括:A128KW、A192KW、A256KW、A128GCMKW、A192GCMKW、A256GCMKW 和 dir。在此情况下,预期提供的 JWK 类型为 ‘oct’。

该转换器在提供 ‘RSA’ JWK 时,会管理属于 RSA 系列(RSA-OAEP 或 RSA-OAEP-256)的算法(JOSE 头中的 “alg” 字段);在提供 ‘EC’ JWK 时,会管理属于 ECDH 系列(ECDH-ES、ECDH-ES+A128KW、ECDH-ES+A192KW 或 ECDH-ES+A256KW)的算法。RSA1_5 算法已实现,但默认处于禁用状态,符合 RFC 8725 第 3.2 节的建议。如需启用,可借助 ‘jwt.decrypt_alg_list’ 全局选项重新激活。

请注意,A128KW 和 A192KW 算法在 AWS-LC 上不可用,因此 A128KW、A192KW、ECDH-ES+A128KW 和 ECDH-ES+A192KW 算法将无法使用。

支持的算法和加密算法(分别对应 JOSE 头中的 “alg” 和 “enc” 字段)可通过 ‘jwt.decrypt_alg_list’ 和 ‘jwt.decrypt_enc_list’ 全局选项进行修改。

JWE 令牌必须以 base64url 编码形式提供,输出将以“原始”形式返回。若在令牌解析、签名验证或内容解密过程中发生错误,将返回空字符串。

由于配置中对引号、逗号和双引号的处理方式,JWK 的内容必须正确转义,才能使该转换器正常工作(详见 第 2.2 节 )。

示例:

 # Get a JWT from the authorization header, put its decrypted content in an
 # HTTP header
 http-request set-var(txn.bearer) http_auth_bearer
 http-request set-header X-Decrypted %[var(txn.bearer),jwt_decrypt_jwk(\'{\"kty\":\"oct\",\"k\":\"wAsgsg\"}\')

# or via a variable
 http-request set-var(txn.bearer) http_auth_bearer
 http-request set-var(txn.jwk) str(\'{\"kty\":\"oct\",\"k\":\"Q-NFLlghQ\"}\')
 http-request set-header X-Decrypted %[var(txn.bearer),jwt_decrypt_jwk(txn.jwk)

jwt_decrypt_secret(<secret>)

jwt_decrypt_secret(<secret>)

按照 JSON Web 加密格式(参见 RFC 7516)对输入的 JSON Web Token 执行签名验证,并通过提供的 base64 编码密钥解密其内容。密钥可作为字符串或通过变量提供。目前仅支持使用紧凑序列化格式的令牌(由五个以点号分隔的 base64-url 编码字符串组成)。

此转换器可用于具有以下算法(JOSE 头中的 “alg” 字段)的令牌:A128KW、A192KW、A256KW、A128GCMKW、A192GCMKW、A256GCMKW、dir。请注意,A128KW 和 A192KW 算法在 AWS-LC 上不可用,解密将无法正常工作。

JWE 令牌必须以 base64url 编码形式提供,输出将以“原始”形式返回。若在令牌解析、签名验证或内容解密过程中发生错误,将返回空字符串。

示例:

# Get a JWT from the authorization header, put its decrypted content in an
# HTTP header
http-request set-var(txn.bearer) http_auth_bearer
http-request set-header X-Decrypted %[var(txn.bearer),jwt_decrypt_secret("GawgguFyGrWKav7AX4VKUg")]

jwt_header_query([<json_path>[,<output_type>]])

jwt_header_query([<json_path>[,<output_type>]])

当输入包含 JSON Web Token (JWT) 时,若未提供参数,则返回该令牌解码后的头部(JWT 中第一个采用 base64-url 编码的部分);否则,对令牌解码后的头部执行 json_query 操作。有关 json_path 和 output_type 参数可接受值的详细信息,请参见 “json_query” 转换器。该转换器可用于 JWS 或 JWE 格式的令牌,只要它们采用紧凑序列化格式即可。

请注意,仅当 HAProxy 编译时包含 USE_OPENSSL 时,此转换器才可用。

jwt_payload_query([<json_path>[,<output_type>]])

jwt_payload_query([<json_path>[,<output_type>]])

当输入为 JSON Web 签名(JWS)格式的 JSON Web 令牌(JWT)时,若未提供参数,则返回令牌的解码载荷部分(即 JWT 的第二个 base64-url 编码部分);否则,对令牌的解码载荷部分执行 json_query 操作。有关接受的 json_path 和 output_type 参数的详细信息,请参见 “json_query” 转换器。

请注意,仅当 HAProxy 编译时包含 USE_OPENSSL 时,此转换器才可用。

jwt_verify(<alg>,<key>)

使用 <alg> 算法和 <key> 参数,对输入的 JSON Web Token (JWT) 执行签名验证。目前仅支持采用紧凑序列化格式(三个以点号分隔的 base64-url 编码字符串)的 JWS 令牌。该转换器仅验证令牌的签名,不执行 RFC7519 第 7.2 段所规定的完整 JWT 验证。例如,解码后的头和载荷内容是否为完全有效的 JSON,不作保证,且不对它们的内容进行任何检查。

  • <alg> 可以是字符串或变量名(参见“set-var”),其值为用于验证的算法名称。

    支持 RFC7518 第 3.1 节 中列出的算法:

   +--------------+---------------------------------------------------------+
   | "alg" Param  | Digital Signature or MAC Algorithm                      |
   | Value        |                                                         |
   +--------------+---------------------------------------------------------+
   | HS256        | HMAC using SHA-256                                      |
   | HS384        | HMAC using SHA-384                                      |
   | HS512        | HMAC using SHA-512                                      |
   | RS256        | RSASSA-PKCS1-v1_5 using SHA-256                         |
   | RS384        | RSASSA-PKCS1-v1_5 using SHA-384                         |
   | RS512        | RSASSA-PKCS1-v1_5 using SHA-512                         |
   | ES256        | ECDSA using P-256 and SHA-256                           |
   | ES384        | ECDSA using P-384 and SHA-384                           |
   | ES512        | ECDSA using P-521 and SHA-512                           |
   | PS256        | RSASSA-PSS using SHA-256 and MGF1 with SHA-256          |
   | PS384        | RSASSA-PSS using SHA-384 and MGF1 with SHA-384          |
   | PS512        | RSASSA-PSS using SHA-512 and MGF1 with SHA-512          |
   | none         | No digital signature or MAC performed                   |
   +--------------+---------------------------------------------------------+
  • <key> 可以是字符串或变量名(参见“set-var”),用于存储密钥或公钥路径。

仅在使用 HMAC 算法时,密钥才适用。

公钥必须采用 PKCS#1 格式(RSA 密钥,以 BEGIN RSA PUBLIC KEY 开头)或 SPKI 格式(主题公钥信息,以 BEGIN PUBLIC KEY 开头)。公钥必须在配置解析期间可用,且无法在运行时更新或加载。参见 “jwt_verify_cert” 转换器,用于基于完整 PEM 证书的 JWT 令牌验证。

所有可能用于验证 JWT 的公钥必须在初始化阶段已知,以便添加至专用缓存中,从而在运行时无需访问磁盘。

验证成功时返回 1,验证失败时返回 0,其他任何错误返回严格负值。由于所有非零错误返回值的存在,此转换器的返回结果不应转换为布尔值。有关可能返回值的完整列表,请参见下文。

可能的返回值如下:

  +----+----------------------------------------------------------------------+
  | ID | message                                                              |
  +----+----------------------------------------------------------------------+
  |  1 | "Verification success"                                               |
  |  0 | "Verification failure"                                               |
  | -1 | "Unknown algorithm (not mentioned in RFC7518)"                       |
  | -2 | "Unmanaged algorithm"                                                |
  | -3 | "Invalid token"                                                      |
  | -4 | "Out of memory"                                                      |
  | -5 | "Unknown pubkey/certificate"                                         |
  | -6 | "Internal error"                                                     |
  +----+----------------------------------------------------------------------+

请注意,仅当 HAProxy 编译时包含 USE_OPENSSL 时,此转换器才可用。

示例:

# Get a JWT from the authorization header, extract the "alg" field of its
# JOSE header and use a public key to verify a signature
http-request set-var(txn.bearer) http_auth_bearer
http-request set-var(txn.jwt_alg) var(txn.bearer),jwt_header_query('$.alg')
http-request deny unless { var(txn.jwt_alg) -m str "RS256" }
http-request deny unless { var(txn.bearer),jwt_verify(txn.jwt_alg,"/path/to/pubkey.pem") 1 }

jwt_verify_cert(<alg>,<cert>)

使用 <alg> 算法和 <cert> 参数,对输入的 JSON Web Token (JWT) 执行签名验证。目前仅支持采用紧凑序列化格式的 JWS 令牌(由三个以英文句点分隔的 base64-url 编码字符串组成)的处理。该转换器仅验证令牌的签名,不执行 RFC7519 第 7.2 段所规定的完整 JWT 验证。我们不保证解码后的头和载荷内容为完全有效的 JSON,且不对它们的具体内容进行任何检查。

  • <alg> 可以是字符串或变量名(参见“set-var”),其值为用于验证的算法名称。与 “jwt_verify” 转换器不同,该转换器仅期望第二个参数为证书,因此不应用于使用 HMAC 算法的令牌。

    支持 RFC7518 第 3.1 节 中列出的算法(HMAC 算法除外):

   +--------------+---------------------------------------------------------+
   | "alg" Param  | Digital Signature or MAC Algorithm                      |
   | Value        |                                                         |
   +--------------+---------------------------------------------------------+
   | RS256        | RSASSA-PKCS1-v1_5 using SHA-256                         |
   | RS384        | RSASSA-PKCS1-v1_5 using SHA-384                         |
   | RS512        | RSASSA-PKCS1-v1_5 using SHA-512                         |
   | ES256        | ECDSA using P-256 and SHA-256                           |
   | ES384        | ECDSA using P-384 and SHA-384                           |
   | ES512        | ECDSA using P-521 and SHA-512                           |
   | PS256        | RSASSA-PSS using SHA-256 and MGF1 with SHA-256          |
   | PS384        | RSASSA-PSS using SHA-384 and MGF1 with SHA-384          |
   | PS512        | RSASSA-PSS using SHA-512 and MGF1 with SHA-512          |
   | none         | No digital signature or MAC performed                   |
   +--------------+---------------------------------------------------------+
  • <key> 可以是字符串或变量名(参见“set-var”),其值为证书路径。

证书必须为标准的 PEM 格式证书(以 BEGIN CERTIFICATE 开头)。证书路径可直接传递给转换器,或通过变量引用。若使用变量,对应的证书可声明在 crt-store 中,或通过 stats socket 动态加载。若直接指定路径,且对应的证书尚未加载至内部证书存储,则将在配置解析期间加载该证书,因此证书文件必须已存在,否则将引发错误。

仅可使用显式定义为可用于 JWT 验证的证书。参见“jwt” crt-store 选项。

可以动态更新证书,并通过统计信息套接字添加新证书。 参见管理指南中的“set ssl cert”和“new ssl cert”。

验证成功时返回 1,验证失败时返回 0,其他任何错误返回严格负值。由于所有非零错误返回值的存在,此转换器的返回结果不应转换为布尔值。有关可能返回值的完整列表,请参见下文。

可能的返回值如下:

  +----+----------------------------------------------------------------------+
  | ID | message                                                              |
  +----+----------------------------------------------------------------------+
  |  1 | "Verification success"                                               |
  |  0 | "Verification failure"                                               |
  | -1 | "Unknown algorithm (not mentioned in RFC7518)"                       |
  | -2 | "Unmanaged algorithm"                                                |
  | -3 | "Invalid token"                                                      |
  | -4 | "Out of memory"                                                      |
  | -5 | "Unknown pubkey/certificate"                                         |
  | -6 | "Internal error"                                                     |
  | -7 | "Unavailable certificate" (see "jwt")                                |
  +----+----------------------------------------------------------------------+

请注意,仅当 HAProxy 编译时包含 USE_OPENSSL 时,此转换器才可用。

示例:

# Get a JWT from the authorization header, extract the "alg" field of its
# JOSE header and use a public certificate to verify a signature
http-request set-var(txn.bearer) http_auth_bearer
http-request set-var(txn.jwt_alg) var(txn.bearer),jwt_header_query('$.alg')
http-request deny unless { var(txn.jwt_alg) -m str "RS256" }
http-request deny unless { var(txn.bearer),jwt_verify_cert(txn.jwt_alg,"/path/to/cert.pem") 1 }

language(<value>[,<default>])

language(<value>[,<default>])

从 “accept-language” 头中提取的列表中,返回 q-factor 最高的值,使用 “req.fhdr” 进行解析。未指定 q-factor 的值,其 q-factor 默认为 1。q-factor 为 0 的值将被丢弃。仅考虑属于分号分隔的 <values> 列表中的值。参数 <value> 的语法为 “lang[;lang[;lang[;…]]]"。若无值匹配给定列表且提供了默认值,则返回默认值。请注意,语言名称后可跟连字符(’-’)分隔的变体。若变体存在于列表中,则进行匹配;若不存在,则仅检查基础语言。匹配区分大小写,输出字符串始终为参数中提供的值之一。参数顺序无关紧要,仅请求中值的顺序有效,当多个值具有相同 q-factor 时,优先使用其中第一个值。

示例:

# this configuration switches to the backend matching a
# given language based on the request:

acl es req.fhdr(accept-language),language(es;fr;en) -m str es
acl fr req.fhdr(accept-language),language(es;fr;en) -m str fr
acl en req.fhdr(accept-language),language(es;fr;en) -m str en
use_backend spanish if es
use_backend french  if fr
use_backend english if en
default_backend choose_your_language

length

length

获取字符串的长度。此指令只能置于字符串样本提取函数之后,或置于返回字符串类型的转换关键字之后。结果类型为整数。

lower

lower

将字符串样本转换为小写。此操作只能置于字符串样本提取函数之后,或置于返回字符串类型的转换关键字之后。结果类型为字符串。

ltime(<format>[,<offset>])

ltime(<format>[,<offset>])

将一个表示自纪元以来日期的整数转换为以本地时间表示的字符串,使用由 <format> 字符串定义的格式,该格式遵循 strftime(3) 的规范。此功能旨在允许在日志中使用任意日期格式。可选地,可在输入日期上应用一个以秒为单位的 <offset> 值(正或负)。有关操作系统支持的格式,请参阅 strftime() 手册页。另请参见 utime 转换器。

示例:

# Emit two colons, one with the local time and another with ip:port
# e.g.  20140710162350 127.0.0.1:57325
log-format %[date,ltime(%Y%m%d%H%M%S)]\ %ci:%cp

ltrim(<chars>)

ltrim(<chars>)

跳过输入样本的字符串表示形式开头的 <chars> 中的任意字符

map(<map_name>[,<default_value>])

map(<map_name>[,<default_value>])
map_<match_type>(<map_name>[,<default_value>])
map_<match_type>_<output_type>(<map_name>[,<default_value>])

使用 <match_type> 匹配方法在 <map_name> 中搜索输入值,并将关联值转换为 <output_type> 类型返回。若输入值在 <map_name> 中未找到,转换器返回 <default_value>。若 <default_value> 未设置,转换器将失败,并表现为无法获取输入值。若 <match_type> 未设置,其默认值为 “str”。同理,若 <output_type> 未设置,其默认值也为 “str”。为方便起见,“map” 关键字是 “map_str” 的别名,用于将字符串映射到另一字符串。<map_name> 必须遵循 2.7 节中关于映射和 ACL 名称格式的描述。

避免键之间发生重叠非常重要:IP 地址和字符串存储在树结构中,因此将采用匹配程度最细的首个结果。其他键存储在列表中,因此将采用首个匹配项。

以下数组按输入类型、匹配类型和输出类型排序,列出了所有可用映射函数的列表。

  input type | match method | output type str | output type int | output type ip | output type key
  -----------+--------------+-----------------+-----------------+----------------+----------------
    str      | str          | map_str         | map_str_int     | map_str_ip     | map_str_key
  -----------+--------------+-----------------+-----------------+----------------+----------------
    str      | beg          | map_beg         | map_beg_int     | map_end_ip     | map_end_key
  -----------+--------------+-----------------+-----------------+----------------+----------------
    str      | sub          | map_sub         | map_sub_int     | map_sub_ip     | map_sub_key
  -----------+--------------+-----------------+-----------------+----------------+----------------
    str      | dir          | map_dir         | map_dir_int     | map_dir_ip     | map_dir_key
  -----------+--------------+-----------------+-----------------+----------------+----------------
    str      | dom          | map_dom         | map_dom_int     | map_dom_ip     | map_dom_key
  -----------+--------------+-----------------+-----------------+----------------+----------------
    str      | end          | map_end         | map_end_int     | map_end_ip     | map_end_key
  -----------+--------------+-----------------+-----------------+----------------+----------------
    str      | reg          | map_reg         | map_reg_int     | map_reg_ip     | map_reg_key
  -----------+--------------+-----------------+-----------------+----------------+----------------
    str      | reg          | map_regm        | map_reg_int     | map_reg_ip     | map_reg_key
  -----------+--------------+-----------------+-----------------+----------------+----------------
    int      | int          | map_int         | map_int_int     | map_int_ip     | map_int_key
  -----------+--------------+-----------------+-----------------+----------------+----------------
    ip       | ip           | map_ip          | map_ip_int      | map_ip_ip      | map_ip_key
  -----------+--------------+-----------------+-----------------+----------------+----------------

名为 “map_regm” 的特殊映射会期望在正则表达式中匹配区域,并修改输出,将反向引用(如 “\1”)替换为对应的匹配文本。

输出类型 “key” 表示将返回匹配条目的键(即映射文件中找到的键),而非值。请注意,当使用 “key” 输出类型时,不支持可选的 <default_value> 参数。

<map_name> 中的文件每行包含一个键值对。以 ‘#’ 开头的行会被忽略,与空行处理方式相同。行首的制表符和空格将被去除。键为第一个“词”(非空格或制表符字符的连续序列),值为该词之后至行尾(不包括末尾的空格或制表符)的部分。

示例:

     # this is a comment and is ignored
        2.22.246.0/23    United Kingdom      \n
     <-><-----------><--><------------><---->
      |       |       |         |        `- trailing spaces ignored
      |       |       |         `---------- value
      |       |       `-------------------- middle spaces ignored
      |       `---------------------------- key
      `------------------------------------ leading spaces ignored

mod(<value>)

mod(<value>)

将类型为有符号整数的输入值除以 <value>,并以有符号整数形式返回余数。若 <value> 为 null,则返回零。<value> 可以是数值或变量名。有关变量的详细信息,请参见 第 2.8 节 。

mqtt_field_value(<packettype>,<fieldname_or_property_ID>)

mqtt_field_value(<packettype>,<fieldname_or_property_ID>)

返回在输入 MQTT 负载中找到的 <fieldname> 值,该负载类型为 <packettype>。<packettype> 可以是字符串(不区分大小写匹配)或与需提取数据的报文类型对应的数值。支持的字符串和整数值请参见:https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718021 https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901022

<fieldname> 依赖 <packettype>,可为以下任意一种。 (请注意,<fieldname> 匹配不区分大小写。)<property id> 仅可在 MQTT v5.0 流中找到。请查看下表:https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901029

  • CONNECT(或 1):flags、protocol_name、protocol_version、client_identifier、will_topic、will_payload、username、password、keepalive,或任意属性 ID(以数值形式表示,仅适用于 MQTT v5.0 数据包):
17: Session Expiry Interval
33: Receive Maximum
39: Maximum Packet Size
34: Topic Alias Maximum
25: Request Response Information
23: Request Problem Information
21: Authentication Method
22: Authentication Data
18: Will Delay Interval
 1: Payload Format Indicator
 2: Message Expiry Interval
 3: Content Type
 8: Response Topic
 9: Correlation Data

暂不支持:

38: User Property
  • CONNACK(或 2):flags、protocol_version、reason_code 或任意属性 ID 作为数值(仅限 MQTT v5.0 数据包):
17: Session Expiry Interval
33: Receive Maximum
36: Maximum QoS
37: Retain Available
39: Maximum Packet Size
18: Assigned Client Identifier
34: Topic Alias Maximum
31: Reason String
40; Wildcard Subscription Available
41: Subscription Identifiers Available
42: Shared Subscription Available
19: Server Keep Alive
26: Response Information
28: Server Reference
21: Authentication Method
22: Authentication Data

暂不支持:

38: User Property

由于当前 HAProxy 的设计限制,仅能解析客户端和服务器发送的首个消息。因此,该转换器仅可从 CONNECT 和 CONNACK 报文类型中提取数据。CONNECT 是客户端发送的第一个消息,CONNAK 是服务器发送的第一个响应。

示例:

acl data_in_buffer req.len ge 4
tcp-request content set-var(txn.username) \
        req.payload(0,0),mqtt_field_value(connect,protocol_name) \
        if data_in_buffer
# do the same as above
tcp-request content set-var(txn.username) \
        req.payload(0,0),mqtt_field_value(1,protocol_name) \
        if data_in_buffer

mqtt_is_valid

mqtt_is_valid

检查二进制输入是否为有效的 MQTT 数据包。返回布尔值。

由于当前 HAProxy 的设计限制,仅能解析客户端和服务器发送的首个消息。因此,该转换器仅可从 CONNECT 和 CONNACK 报文类型中提取数据。CONNECT 是客户端发送的第一个消息,CONNAK 是服务器发送的第一个响应。

仅支持 MQTT 3.1、3.1.1 和 5.0。

示例:

acl data_in_buffer req.len ge 4
tcp-request content reject unless { req.payload(0,0),mqtt_is_valid }

ms_ltime(<format>[,<offset>])

ms_ltime(<format>[,<offset>])

这与 “ltime” 类似,但输入单位为毫秒。它还支持受 date(1) 启发的 %N 转换说明符。将一个表示自纪元以来日期的整数转换为字符串,该字符串以本地时间格式表示该日期,格式由 <format> 字符串定义,使用 strftime(3)。此功能旨在允许日志中使用任意日期格式。可选地,可在输入日期上应用 <offset> 毫秒(正或负)。请参阅 strftime() 手册页,了解操作系统支持的格式。

%N 转换说明符可用于输出日期的纳秒部分,由于输入精度为毫秒级,因此其精度受限(取值范围为 000000000..999000000)。%N 可接受位于 % 与 N 之间的宽度参数。该参数可用于显示毫秒(%3N)或微秒(%6N)。默认及最大宽度为 9(%N 等价于 %9N)。

另请参阅用于 UTC 的 utime 转换器,以及 “ltime” 和 “us_ltime” 转换器。

示例:

# Emit 3 colons, the local time, the timezone and another with ip:port
# e.g. 2023/07/24/11:53:02.196 +0200 127.0.0.1:41530
log-format %[accept_date(ms),ms_ltime("%Y/%m/%d/%H:%M:%S.%3N %z")]\ %ci:%cp

ms_utime(<format>[,<offset>])

ms_utime(<format>[,<offset>])

这与 “utime” 类似,但输入单位为毫秒。它还支持受 date(1) 启发的 %N 转换说明符。将一个表示自纪元以来日期的整数转换为字符串,该字符串以 UTC 时间表示该日期,格式由 <format> 字符串定义,使用 strftime(3)。此功能旨在允许在日志中使用任意日期格式。可选地,可在输入日期上应用一个以毫秒为单位的 <offset> 值(正或负)。有关操作系统支持的格式,请参阅 strftime() 手册页。

%N 转换说明符可用于输出日期的纳秒部分,由于输入精度为毫秒级,因此其精度受限(取值范围为 000000000..999000000)。%N 可接受位于 % 与 N 之间的宽度参数。该参数可用于显示毫秒(%3N)或微秒(%6N)。默认及最大宽度为 9(%N 等价于 %9N)。

另请参阅 ltime 转换器,用于本地时间以及 “utime” 和 “us_utime” 转换器。

示例:

# Emit 3 colons, the UTC time, the timezone and another with ip:port
# e.g. 2023/07/24/09:53:02.196 +0000 127.0.0.1:41530
log-format %[accept_date(ms),ms_utime("%Y/%m/%d/%H:%M:%S.%3N %z")]\ %ci:%cp

mul(<value>)

mul(<value>)

将类型为有符号整数的输入值乘以 <value>,并将结果以有符号整数形式返回。若发生溢出,将返回该符号所能表示的最大值,以避免操作结果发生环绕。<value> 可以是数值或变量名。有关变量的详细信息,请参见 第 2.8 节 。

nbsrv

nbsrv

接收类型为字符串的输入值,将其解释为后端名称,并返回该后端中可用服务器的数量。可在需要从动态名称查找后端的场景中使用,例如映射查找的结果。

neg

neg

取类型为有符号整数的输入值,计算其相反数,并返回余数作为有符号整数。0 为恒等值。该运算符用于反向减法:若需从常量中减去输入值,只需执行“neg,add(value)”操作。

not

not

如果输入值为非空的有符号整数类型,则返回布尔值 FALSE;否则返回 TRUE。与 and() 配合使用时,可用于对输入值进行位测试,报告真或假(例如,验证标志位的缺失)。

odd

odd

如果输入值为有符号整数类型且为奇数,则返回布尔值 TRUE;否则返回 FALSE。其功能等价于 “and(1),bool”。

or(<value>)

or(<value>)

对 <value> 与输入的有符号整数类型值执行按位“或”运算,并将结果以有符号整数形式返回。<value> 可以是数值或变量名。有关变量的详细信息,请参见 第 2.8 节 。

param(<name>[,<delim>])

param(<name>[,<delim>])

提取输入字符串中首个出现的参数 <name>,参数之间以 <delim> 分隔,默认值为 “&",参数名与值之间以 “=” 分隔。若参数段末尾前未出现 “=” 及其后的值,则视为值为空字符串。

这在从查询字符串或可能的 x-www-form-urlencoded 请求体中提取参数时非常有用。特别是,query,param(<name>) 可作为 urlp(<name>) 的替代方案,后者仅以 “&” 作为分隔符,而 “urlp” 还会使用 “?” 和 “;"。

请注意,此转换器对 URL 编码字符不做特殊处理。如需解码值,可在输出上使用 url_dec 转换器。若输入中参数名称可能包含编码字符,建议在调用 “param” 前先对输入进行归一化处理。可使用 “http-request normalize-uri” 实现,特别是启用 percent-decode-unreserved 和 percent-to-uppercase 选项。

示例:

str(a=b&c=d&a=r),param(a)   # b
str(a&b=c),param(a)         # ""
str(a=&b&c=a),param(b)      # ""
str(a=1;b=2;c=4),param(b,;) # 2
query,param(redirect_uri),urldec()

port_only

port_only

将包含 Host 头值的字符串转换为整数,通过返回其端口号实现。输入必须符合 Host 头值的格式(rfc9110#section-7.2)。支持的输入格式包括:主机名、主机名:80、127.0.0.1、127.0.0.1:80、[::1]、[::1]:80。

如果输入中未提供端口,则返回 0。

参见:“host_only” 转换器,该转换器将返回主机。

protobuf(<field_number>[,<field_type>])

protobuf(<field_number>[,<field_type>])

此操作以原始模式提取协议缓冲区消息字段,针对协议缓冲区消息的二进制样本表示,使用 <field_number> 作为字段编号(点号表示法)。若 <field_type> 不存在,则提取为整数样本;若该字段存在,则提取为整数样本(参见下方 “ungrpc”)。允许的类型列表如下:对于“varint”线缆类型 0,支持 “int32”、“int64”、“uint32”、“uint64”、“sint32”、“sint64”、“bool”、“enum”;对于 64 位线缆类型 1,支持 “fixed64”、“sfixed64”、“double”;对于线缆类型 5,支持 “fixed32”、“sfixed32”、“float”。请注意,“string” 被视为长度限定类型,因此提取时无需任何 <field_type> 参数。关于协议缓冲区消息字段类型的更多信息,请参见 https://developers.google.com/protocol-buffers/docs/encoding 。

regsub(<regex>,<subst>[,<flags>])

regsub(<regex>,<subst>[,<flags>])

对输入字符串应用基于正则表达式的替换操作。其功能与广为人知的“sed”工具执行“s/<regex>/<subst>/”操作相同。默认情况下,它将在输入字符串中将与正则表达式 <regex> 匹配的最大部分的首个出现位置,替换为替换字符串 <subst>。可通过在第三个参数 <flags> 中添加标志“g”来替换所有匹配项。也可通过在 <flags> 中添加标志“i”使正则表达式不区分大小写。由于 <flags> 是一个字符串,因此由所有所需标志连接而成。因此,若同时需要“i”和“g”标志,使用“gi”或“ig”效果相同。此转换器的首次用途是将某些字符或字符序列替换为其他字符。

强烈建议使用保护引号包裹正则表达式部分,以提高清晰度,并避免正则表达式中的右括号与函数中的括号混淆。与 Bourne shell 类似,第一层引号用于在行上界定词组,第二层引号可用于参数。建议在外层使用单引号,因为单引号不会尝试解析反斜杠或美元符号。

示例:

# de-duplicate "/" in header "x-path".
# input:  x-path: /////a///b/c/xzxyz/
# output: x-path: /a/b/c/xzxyz/
http-request set-header x-path "%[hdr(x-path),regsub('/+','/','g')]"

# copy query string to x-query and drop all leading '?', ';' and '&'
http-request set-header x-query "%[query,regsub([?;&]*,'')]"

# capture groups and backreferences
# both lines do the same.
http-request redirect location %[url,'regsub("(foo|bar)([0-9]+)?","\2\1",i)']
http-request redirect location %[url,regsub(\"(foo|bar)([0-9]+)?\",\"\2\1\",i)]

reverse

reverse

按字节反转输入字符串。

该转换器与编码无关,且反转的是字节而非字符;它不适用于反转以 UTF-8 编码的文本。

这可将原始字符串的后缀查找转换为反转字符串的前缀查找,从而可在大型映射上使用索引前缀匹配器,例如 “map_beg”。

示例:

"example.com" -> "moc.elpmaxe"
"ab cd" -> "dc ba"

# Given a map file where each key contains a reversed hostname:
#   moc.elpmaxe.ppa app1
#   moc.elpmaxe.bd  dbcluster
# Pick a backend based on the domain suffix of the Host header:
use_backend %[req.hdr(host),lower,reverse,map_beg(/etc/haproxy/hosts.map,default)]

reverse_dom

reverse_dom

将包含类似 FQDN 主机名的字符串转换为其反向标签形式。输入中的单个尾随句点会被忽略。空标签会导致转换器失败。

此转换器不会将其输入转换为小写,也不会去除任何端口。在需要时,应将其与现有的转换器(如 “lower” 或 “host_only”)结合使用。

尾随句点的处理策略有意交由调用方决定。这使得调用方能够自行决定是否匹配域名根(apex)或仅匹配子域名。

反向标签形式在大型域名映射中非常有用,因为它将域名后缀查找转换为前缀查找,从而可使用索引前缀匹配器(如 “map_beg”)。

示例:

"example.com" -> "com.example"
"mail.example.com" -> "com.example.mail"
"example.com." -> "com.example"

# match only subdomains of example.net, not the apex
acl example_net_sub req.hdr(Host),host_only,reverse_dom -m beg net.example.

# match only the apex
acl example_net_apex req.hdr(Host),host_only,reverse_dom -i net.example

# exact-or-subdomain prefix lookup using an explicit dotted form
http-request set-var(txn.rev_host) req.hdr(Host),host_only,reverse_dom,concat(.)
use_backend %[var(txn.rev_host),map_beg(/etc/haproxy/domains.map)]

rfc7239_field(<field>)

rfc7239_field(<field>)

从符合 RFC 7239 规范的头值输入中提取单个字段/参数。

支持的字段包括: - proto:取值为 ‘http’ 或 ‘https’ - host:符合 HTTP 规范的 host - for:RFC7239 中定义的 node - by:RFC7239 中定义的 node

更多信息请见此处:

https://www.rfc-editor.org/rfc/rfc7239.html#section-6

示例:

# extract host field from forwarded header and store it in req.fhost var
http-request set-var(req.fhost) req.hdr(forwarded),rfc7239_field(host)
#input: "proto=https;host=\"haproxy.org:80\""
#  output: "haproxy.org:80"

# extract for field from forwarded header and store it in req.ffor var
http-request set-var(req.ffor) req.hdr(forwarded),rfc7239_field(for)
#input: "proto=https;host=\"haproxy.org:80\";for=\"127.0.0.1:9999\""
#  output: "127.0.0.1:9999"

rfc7239_is_valid

rfc7239_is_valid

如果输入头符合 RFC 7239 规范,则返回 true,否则返回 false。

示例:

acl valid req.hdr(forwarded),rfc7239_is_valid
#input: "for=127.0.0.1;proto=http"
#  output: TRUE
#input: "proto=custom"
#  output: FALSE

rfc7239_n2nn

rfc7239_n2nn

将 RFC7239 节点(由 ‘for’ 或 ‘by’ 7239 头字段提供)转换为其对应的节点名称 最终形式:- IPv4 地址 - IPv6 地址 - ‘unknown’ - ‘_obfs’ 标识符

示例:

# extract 'for' field from forwarded header, extract nodename from
# resulting node identifier and store the result in req.fnn
http-request set-var(req.fnn) req.hdr(forwarded),rfc7239_field(for),rfc7239_n2nn
#input: "127.0.0.1:9999"
#  output: 127.0.0.1 (ipv4)
#input: "[ab:cd:ff:ff:ff:ff:ff:ff]:9998"
#  output: ab:cd:ff:ff:ff:ff:ff:ff (ipv6)
#input: "_name:_port"
#  output: "_name" (string)

rfc7239_n2np

rfc7239_n2np

将 RFC7239 节点(由 ‘for’ 或 ‘by’ 7239 头字段提供)转换为其对应的节点端口 最终形式:无符号整数 - ‘_obfs’ 标识符

示例:

# extract 'by' field from forwarded header, extract node port from
# resulting node identifier and store the result in req.fnp
http-request set-var(req.fnp) req.hdr(forwarded),rfc7239_field(by),rfc7239_n2np
#input: "127.0.0.1:9999"
#  output: 9999 (integer)
#input: "[ab:cd:ff:ff:ff:ff:ff:ff]:9998"
#  output: 9998 (integer)
#input: "_name:_port"
#  output: "_port" (string)

rfc7239_nn

rfc7239_nn

将提供的地址或字符串输入转换为符合 RFC7239 规范的节点名称。可用于手动构建 ‘for’ 或 ‘by’ 7239 头字段。

当输入为字符串时,将自动在其前缀添加 ‘_’ 字符,以表示混淆标识符。字符串必须符合 RFC7239 字符集要求。若字符串为空,则将其转换为 “unknown” 标识符。

示例:

#input: ipv6(ab:cd:ff:ff:ff:ff:ff:ff)
#  output: "[ab:cd:ff:ff:ff:ff:ff:ff]"
#input: str(test)
#  output: "_test"
#input: str()
#  output: "unknown"

参见:“rfc7239_np”

rfc7239_np

rfc7239_np

将提供的无符号整数或字符串输入转换为符合 RFC7239 规范的节点端口。可用于手动构建 ‘for’ 或 ‘by’ 7239 头字段。

当输入为字符串时,将自动在其前缀添加 ‘_’ 字符,以表示混淆标识符。字符串必须符合 RFC7239 字符集要求,且不能为空。

示例:

#input: int(12)
#  output: "12"
#input: str(test)
#  output: "_test"

# build 'for' forwarded header field
http-request set-var-fmt(txn.test) "for=\"%[ipv6(::1),rfc7239_nn]:%[int(8080),rfc7239_np]\";"
#  output: "for=\"[::1]:8080\";"

# build RFC-compliant 7239 header:
http-request set-var-fmt(txn.forwarded) "for=\"%[ipv6(::1),rfc7239_nn]:%[str(8888),rfc7239_np]\";host=\"haproxy.org\";proto=http"
# check RFC-compliancy:
http-request set-var(txn.test) "var(txn.forwarded),debug(test,stderr),rfc7239_is_valid,debug(test,stderr)"
#  stderr output:
#    [debug] test: type=str <for="[::1]:_8888";host="haproxy.org";proto=http>
#    [debug] test: type=bool <1>

参见:“rfc7239_nn”

rtrim(<chars>)

rtrim(<chars>)

跳过输入样本的字符串表示形式末尾的 <chars> 中的任意字符。

sdbm([<avalanche>])

sdbm([<avalanche>])

使用 SDBM 哈希函数将二进制输入样本哈希为无符号 32 位整数。 可选地,若可选参数 <avalanche> 等于 1,则可对输出应用完整的雪崩哈希函数。 该转换器使用与各种基于哈希的负载均衡算法相同的函数,因此将提供完全相同的结果。 其主要用途为调试,但也可用作粘性表条目以收集粗略统计信息。 不得用于安全目的,因为 32 位哈希极易被破解。 另请参见 “crc32”、“djb2”、“wt6”、“crc32c” 以及 “hash-type” 指令。

secure_memcmp(<var>)

secure_memcmp(<var>)

将 <var> 的内容与输入值进行比较。两个值均被视为二进制字符串。 返回一个布尔值,指示两个二进制字符串是否匹配。

如果两个二进制字符串长度相同,则比较操作将在常量时间内完成。

请注意,仅当 HAProxy 编译时包含 USE_OPENSSL 时,此转换器才可用。

示例:

http-request set-var(txn.token) hdr(token)
# Check whether the token sent by the client matches the secret token
# value, without leaking the contents using a timing attack.
acl token_given str(my_secret_token),secure_memcmp(txn.token)

set-var(<var>[,<cond>...])

set-var(<var>[,<cond>...])

设置一个变量,将其输入内容赋值,并在所有指定条件均为真时,将内容原样返回至输出(详见下文可能条件列表)。该变量将保留其值及关联的输入类型。有关变量的详细信息,请参见 第 2.8 节 。

可向转换器传递最多四个以下可能的条件:

  • ifexists / ifnotexists:
Checks if the variable already existed before the current set-var call.
A variable is usually created through a successful set-var call.
Note that variables of scope "proc" are created during configuration
parsing so the "ifexists" condition will always be true for them.
  • “ifempty”/“ifnotempty”:
Checks if the input is empty or not.
Scalar types are never empty so the ifempty condition will be false for
them regardless of the input's contents (integers, booleans, IPs ...).
  • ifset / ifnotset:
Checks if the variable was previously set or not, or if unset-var was
called on the variable.
A variable that does not exist yet is considered as not set. A "proc"
variable can exist while not being set since they are created during
configuration parsing.
  • ifgt / iflt:
Checks if the content of the variable is "greater than" or "less than"
the input. This check can only be performed if both the input and
the variable are of type integer. Otherwise, the check is considered as
true by default.

sha1

sha1

将二进制输入样本转换为 SHA-1 摘要。结果为长度为 20 字节的二进制样本。

sha2([<bits>])

sha2([<bits>])

将二进制输入样本转换为 SHA-2 系列摘要。结果为长度为 <bits>/8 字节的二进制样本。

<bits> 的有效值为 224、256、384 或 512,分别对应 SHA-<bits>。默认值为 256。

请注意,仅当 HAProxy 编译时包含 USE_OPENSSL 时,此转换器才可用。

srv_is_up

srv_is_up

接收类型为字符串的输入值,可以是服务器名称,也可以是 <backend>/<server> 格式,当指定的服务器当前处于 UP 状态时返回 true。可在需要从动态名称(例如 Cookie 值,如 req.cook(SRVID), srv_is_up)查询服务器状态并据此决定将请求转发至其他位置的场景中使用。使用前请注意,对不受控数据使用此转换器可能使外部观察者查询整个配置中任意服务器的状态,这在某些环境中可能不可接受。

srv_queue

srv_queue

接受类型为字符串的输入值,可以是服务器名称,也可以是 <backend>/<server> 格式, 返回该服务器上的队列流数量。可在需要根据动态名称查询队列流的场景中使用,例如从 Cookie 值(如 req.cook(SRVID), srv_queue)获取后, 决定是否中断持久性或将请求导向其他位置。使用前请注意,若在不受控数据上使用此转换器, 可能允许外部观察者查询整个配置中任意服务器的状态,这在某些环境中可能不可接受。

strcmp(<var>)

strcmp(<var>)

比较 <var> 与类型为字符串的输入值。返回结果为与 strcmp(3) 兼容的有符号整数:若两个字符串完全相同,则返回 0;若左侧字符串在字典序上小于右侧字符串,或左侧字符串较短,则返回小于 0 的值;否则返回大于 0 的值(即右侧字符串大于左侧字符串,或右侧字符串较短)。

如需以恒定时间比较两个二进制字符串,请参阅 secure_memcmp 转换器。

示例:

http-request set-var(txn.host) hdr(host)
# Check whether the client is attempting domain fronting.
acl ssl_sni_http_host_match ssl_fc_sni,strcmp(txn.host) eq 0

sub(<value>)

sub(<value>)

从类型为有符号整数的输入值中减去 <value>,并将结果以有符号整数形式返回。请注意:若需从常量中减去输入值,只需执行“neg,add(value)”操作。<value> 可以是数值或变量名。有关变量的详细信息,请参阅 第 2.8 节 。

table_bytes_in_rate([<table>])

table_bytes_in_rate([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中进行查找。若键值在表中未找到,返回整数值 0。否则,转换器返回输入样本在指定表中关联的客户端到服务器字节速率的平均值,单位为字节,该值基于表中配置的周期进行测量。另请参见 sc_bytes_in_rate 样本提取关键字。

table_bytes_out_rate([<table>])

table_bytes_out_rate([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中进行查找。若键值在表中未找到,返回整数值零。否则,转换器返回输入样本在指定表中对应的平均服务器到客户端字节速率,单位为字节,该速率基于表中配置的周期进行测量。另请参见 sc_bytes_out_rate 样本提取关键字。

table_clr_gpc(<idx>[,<table>])

table_clr_gpc(<idx>[,<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中执行查找。清除 gpc 数组中索引 <idx> 处的通用计数器,并返回其先前的值。<idx> 是介于 0 到 99 之间的整数。若未找到条目,则创建新条目并返回 0。此转换器仅适用于 ‘gpc’ 数组 data_type(不适用于旧版 ‘gpc0’ 或 ‘gpc1’ data_type)。另请参见 sc_clr_gpc 样本提取关键字。

table_clr_gpc0([<table>])

table_clr_gpc0([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中执行查找。清空第一个通用计数器 ‘0’ 并返回其先前的值。若未找到条目,则创建新条目并返回 0。通常作为表达式中的第二个 ACL 使用,以便在首个 ACL 验证通过时标记连接:

示例:

# block if 5 consecutive requests continue to come faster than 10 sess
# per second, and reset the counter as soon as the traffic slows down.
acl abuse src_http_req_rate gt 10
acl kill  src,table_inc_gpc0 gt 5
acl save  src,table_clr_gpc0 ge 0
tcp-request connection accept if !abuse save
tcp-request connection reject if abuse kill

另请参见 sc_clr_gpc0 样本提取关键字。

table_clr_gpc1([<table>])

table_clr_gpc1([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中执行查找。清除第一个通用计数器 ‘1’ 并返回其先前值。若未找到条目,则创建新条目并返回 0。通常作为表达式中的第二个 ACL 使用,以便在首个 ACL 验证通过时标记连接。参见 sc_clr_gpc1 样本提取关键字。

table_conn_cnt([<table>])

table_conn_cnt([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中进行查找。若键值在表中未找到,返回整数值零。否则,转换器返回指定表中与输入样本关联的累计入站连接数。另请参见 sc_conn_cnt 样本提取关键字。

table_conn_cur([<table>])

table_conn_cur([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中进行查找。若键值在表中未找到,返回整数值零。否则,转换器返回指定表中与输入样本关联的当前并发连接数。另请参见 sc_conn_cur 样本提取关键字。

table_conn_rate([<table>])

table_conn_rate([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中进行查找。若键值在表中未找到,返回整数值 0。否则,转换器返回指定表中与输入样本关联的平均入站连接速率。参见 sc_conn_rate 样本提取关键字。

table_expire([<table>[,<default_value>]])

table_expire([<table>[,<default_value>]])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中执行查找。如果键在表中未找到,转换器将失败,除非设置了 <default_value>:此时转换器将成功并返回 <default_value>。如果键被找到,转换器将返回输入样本在指定表中关联的键过期延迟。另请参见 table_idle 样本提取关键字。

table_glitch_cnt([<table>])

table_glitch_cnt([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中进行查找。若键值在表中未找到,返回整数值 0。否则,转换器返回指定表中与输入样本关联的前端连接异常累计次数。另请参见 sc_glitch_cnt 样本提取关键字以及 fc_glitches,后者用于获取当前前端连接上测量到的值。

table_glitch_rate([<table>])

table_glitch_rate([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中进行查找。若键值在表中未找到,返回整数值零。否则,转换器返回指定表中与输入样本关联的平均前端连接异常率。另请参见 sc_glitch_rate 样本提取关键字。

table_gpc(<idx>[,<table>])

table_gpc(<idx>[,<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中执行查找。若键未在表中找到,返回整数值 0。否则,转换器返回指定 <table> 中与输入样本关联的数组在索引 <idx> 处的通用计数器(GPC)当前值。<idx> 为 0 至 99 之间的整数。若该索引处未存储 GPC,则同样返回整数值 0。此行为仅适用于 ‘gpc’ 数组 data_type(不适用于旧版 ‘gpc0’ 或 ‘gpc1’ data_type)。另请参见 sc_get_gpc 样本提取关键字。

table_gpc0([<table>])

table_gpc0([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中进行查找。若键值在表中未找到,返回整数值零。否则,转换器返回指定表中与输入样本关联的第一个通用计数器的当前值。另请参见 sc_get_gpc0 样本提取关键字。

table_gpc0_rate([<table>])

table_gpc0_rate([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中进行查找。若键值在表中未找到,返回整数值零。否则,转换器返回在指定表中与输入样本关联的 gpc0 计数器在配置周期内被递增的频率。参见 sc_get_gpc0_rate 样本提取关键字。

table_gpc1([<table>])

table_gpc1([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中执行查找。若在表中未找到该键,则返回整数值零。否则,转换器返回指定表中与输入样本关联的第二个通用计数器的当前值。另请参见 sc_get_gpc1 样本提取关键字。

table_gpc1_rate([<table>])

table_gpc1_rate([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中执行查找。若键在表中未找到,返回整数值零。否则,转换器返回在指定表中与输入样本关联的 gpc1 计数器在配置周期内被递增的频率。参见 sc_get_gpc1_rate 样本提取关键字。

table_gpc_rate(<idx>[,<table>])

table_gpc_rate(<idx>[,<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中执行查找。若键未在表中找到,返回整数值 0。否则,转换器返回在配置周期内,与指定 stick-table <table> 中输入样本关联的数组中索引 <idx> 处的通用计数器(GPC)的增量频率。<idx> 为 0 至 99 之间的整数。若该索引处未存储 gpc_rate,则同样返回整数值 0。此行为仅适用于 ‘gpc_rate’ 数组 data_type(不适用于旧版 ‘gpc0_rate’ 及 ‘gpc1_rate’ data_type)。另请参阅 sc_gpc_rate 样本提取关键字。

table_gpt(<idx>[,<table>])

table_gpt(<idx>[,<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中执行查找。若键在表中未找到,返回整数值 0。否则,转换器返回指定 <table> 中与输入样本关联的数组在索引 <idx> 处的通用标签(GPT)当前值。<idx> 是介于 0 到 99 之间的整数。若该索引处未存储 GPT,同样返回整数值 0。此行为仅适用于 ‘gpt’ 数组 data_type(不适用于旧版 ‘gpt0’ data-type)。另请参见 sc_get_gpt 样本提取关键字。

table_gpt0([<table>])

table_gpt0([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中执行查找。若键值在表中未找到,返回整数值零。否则,转换器返回指定表中与输入样本关联的第一个通用标签的当前值。另请参见 sc_get_gpt0 样本提取关键字。

table_http_err_cnt([<table>])

table_http_err_cnt([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中进行查找。若键值在表中未找到,返回整数值零。否则,转换器返回指定表中与输入样本关联的累计 HTTP 错误数量。另请参见 sc_http_err_cnt 样本提取关键字。

table_http_err_rate([<table>])

table_http_err_rate([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中进行查找。若键值在表中未找到,返回整数值零。否则,返回指定表中与输入样本关联的 HTTP 错误平均速率,单位为表中配置周期内的错误数量。参见 sc_http_err_rate 样本提取关键字。

table_http_fail_cnt([<table>])

table_http_fail_cnt([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中进行查找。若键值在表中未找到,返回整数值零。否则,转换器返回指定表中与输入样本关联的累计 HTTP 失败次数。另请参见 sc_http_fail_cnt 样本提取关键字。

table_http_fail_rate([<table>])

table_http_fail_rate([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中进行查找。若键值在表中未找到,返回整数值 0。否则返回指定表中与输入样本关联的 HTTP 失败平均速率,单位为表中配置周期内的失败次数。参见 sc_http_fail_rate 样本提取关键字。

table_http_req_cnt([<table>])

table_http_req_cnt([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中进行查找。若键值在表中未找到,返回整数值 0。否则,转换器返回指定表中与输入样本关联的累计 HTTP 请求数量。另请参见 sc_http_req_cnt 样本提取关键字。

table_http_req_rate([<table>])

table_http_req_rate([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中进行查找。若键值在表中未找到,返回整数值 0。否则返回指定表中与输入样本关联的 HTTP 请求的平均速率,单位为请求数量,按表中配置的周期进行测量。另请参见 sc_http_req_rate 样本提取关键字。

table_idle([<table>[,<default_value>]])

table_idle([<table>[,<default_value>]])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中执行查找。如果键在表中未找到,转换器将失败,除非设置了 <default_value>:此时转换器将成功并返回 <default_value>。如果找到键,转换器将返回指定表中与输入样本关联的键条目自上次更新以来保持空闲的时间。参见 table_expire 样本提取关键字。

table_inc_gpc(<idx>[,<table>])

table_inc_gpc(<idx>[,<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中执行查找。将数组中索引 <idx> 处的通用计数器加 1,并返回其新值。<idx> 为 0 至 99 之间的整数。若未找到条目,则创建新条目并返回 1。此转换器仅适用于 ‘gpc’ 数组数据类型(不适用于旧版 ‘gpc0’ 或 ‘gpc1’ 数据类型)。参见 sc_inc_gpc。

table_inc_gpc0([<table>])

table_inc_gpc0([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中执行查找。递增通用计数器 ‘0’ 并返回其新值。若未找到条目,则创建条目并返回 1。参见 sc0/sc2/sc2_inc_gpc0。通常作为表达式中的第二个 ACL 使用,以便在第一个 ACL 验证通过时标记连接:

示例:

acl abuse src,table_req_rate gt 10
acl kill  src,table_inc_gpc0 gt 0
tcp-request connection reject if abuse kill

table_inc_gpc1([<table>])

table_inc_gpc1([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中执行查找。递增通用计数器 ‘1’ 并返回其新值。若未找到条目,则创建新条目并返回 1。参见 sc0/sc2/sc2_inc_gpc1。通常作为表达式中的第二个 ACL 使用,以便在第一个 ACL 验证通过时标记连接。

table_kbytes_in([<table>])

table_kbytes_in([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中执行查找。若键值在表中未找到,返回整数值零。否则,转换器返回指定表中与输入样本关联的客户端到服务器数据的累计数量,单位为千字节。当前测试基于 32 位整数,因此数值上限为 4 太字节。另请参见 sc_kbytes_in 样本提取关键字。

table_kbytes_out([<table>])

table_kbytes_out([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中执行查找。若键值在表中未找到,返回整数值零。否则,转换器返回指定表中与输入样本关联的客户端数据累计量,单位为千字节。当前测试基于 32 位整数,因此数值上限为 4 太字节。另请参见 sc_kbytes_out 样本提取关键字。

table_server_id([<table>])

table_server_id([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中执行查找。若键在表中未找到,返回整数值零。否则,转换器返回指定表中与输入样本关联的服务器 ID。当连接到服务器成功时,通过“stick”规则将服务器 ID 与样本关联。服务器 ID 为零表示该键未关联任何服务器。

table_sess_cnt([<table>])

table_sess_cnt([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中进行查找。若键值在表中未找到,返回整数值 0。否则,转换器返回指定表中与输入样本关联的累计入站会话数。请注意,此处的会话指由 “tcp-request connection” 规则集接受的入站连接。另请参见 sc_sess_cnt 样本提取关键字。

table_sess_rate([<table>])

table_sess_rate([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中进行查找。若键值在表中未找到,返回整数值 0。否则,转换器返回输入样本在指定表中关联的平均入站会话速率。请注意,此处的会话指被 “tcp-request connection” 规则集接受的入站连接。另请参见 sc_sess_rate 样本提取关键字。

table_trackers([<table>])

table_trackers([<table>])

使用输入样本在当前代理的 stick-table 或指定的 stick-table 中执行查找。若键值在表中未找到,返回整数值零。否则,转换器返回指定表中与输入样本相同键值所跟踪的当前并发连接数量。与 table_conn_cur 的区别在于,它不依赖于任何存储信息,而是基于表的引用计数(即 CLI 中 “show table” 命令返回的“use”值)。在某些情况下,此方法更适合用于第 7 层跟踪。可用于告知服务器来自特定地址的并发连接数量。另请参见 sc_trackers 样本提取关键字。

tcp.dst

tcp.dst

此功能与表示二进制 TCP 头的输入样本配合使用,该样本由 “ip.data” 返回。它返回一个整数,表示 TCP 头中的目标端口。另请参阅 “fc_saved_syn”、“tcp-ss” 和 “ip.data”。

tcp.flags

tcp.flags

此功能与表示二进制 TCP 头的输入样本配合使用,该样本由 “ip.data” 返回。它返回一个整数,表示来自该 TCP 头的 TCP 标志。从 FIN 到 CWR 的全部 8 个标志均被提取。每个标志均可通过 “and()” 转换器进行测试。请参阅 RFC9293 以获取每个标志的取值。另请参见 “fc_saved_syn”、“tcp-ss” 和 “ip.data”。

tcp.options.mss

tcp.options.mss

此功能用于处理由 “ip.data” 返回的表示二进制 TCP 头的输入样本。它查找类型为“MSS”的 TCP 选项,若找到,则返回该选项中通告值对应的整数值,否则返回零。MSS 表示最大段大小,以字节为单位,指示对等节点可接收的最大段大小。另请参见 “fc_saved_syn”、“tcp-ss”以及 “ip.data”。

tcp.options.sack

tcp.options.sack

此功能用于处理表示二进制 TCP 头的输入样本,该样本由 “ip.data” 返回。它查找类型为“Sack-Permitted”的 TCP 选项,若找到则返回 1,否则返回 0。另请参见 “fc_saved_syn”、“tcp-ss” 和 “ip.data”。

tcp.options.tsopt

tcp.options.tsopt

此功能用于处理表示二进制 TCP 头的输入样本,该样本由 “ip.data” 返回。它查找类型为“Timestamp”的 TCP 选项,若找到则返回 1,否则返回 0。另请参见 “fc_saved_syn”、“tcp-ss” 和 “ip.data”。

tcp.options.tsval

tcp.options.tsval

此功能用于处理由 “ip.data” 返回的、表示二进制 TCP 头的输入样本。它查找类型为“Timestamp”的 TCP 选项,若找到则返回对等节点发出的时间戳值,否则不返回任何内容。请注意,时间戳为 32 位无符号值,无特定单位,仅由对等节点决定,且不同连接之间的时间戳应相互独立。另请参见 “fc_saved_syn”、“tcp-ss” 及 “ip.data”。

tcp.options.wscale

tcp.options.wscale

此函数用于处理表示二进制 TCP 头的输入样本,该样本由 “ip.data” 返回。它查找类型为“窗口缩放”的 TCP 选项,若找到则返回对等节点发出的窗口缩放值,否则返回零。请注意,虽然实际值通常不会超过 14,但并无技术限制阻止其发送更大数值。如需检测是否使用了窗口缩放选项,请使用 “tcp.options.wsopt”。另请参阅 “tcp-ss”、“fc_saved_syn”、“ip.data” 及 “tcp.options.wsopt”。

tcp.options.wsopt

tcp.options.wsopt

此功能用于处理表示二进制 TCP 头的输入样本,即 “ip.data” 返回的结果。它查找类型为“窗口缩放”的 TCP 选项,若找到则返回 1,否则返回 0。另请参见 “fc_saved_syn”、“tcp-ss”、“ip.data” “tcp.options.wscale”。

tcp.options_list

tcp.options_list

此功能与表示二进制 TCP 头的输入样本配合使用,该样本由 “ip.data” 返回。它按 TCP 头中出现的顺序,构建所有 TCP 选项类型的二进制序列。输出长度可在 0 到 60 字节之间(最坏情况)。不会发出选项结束标记。另请参见 “fc_saved_syn”、“tcp-ss” 和 “ip.data”。

tcp.seq

tcp.seq

此功能用于处理表示二进制 TCP 头的输入样本,如 “ip.data” 所返回。它返回一个整数,表示对等节点在 TCP 头中使用的序列号。序列号为 32 位无符号值。另请参见 “fc_saved_syn”、“tcp-ss” 和 “ip.data”。

tcp.src

tcp.src

此函数用于处理表示二进制 TCP 头的输入样本,该样本由 “ip.data” 返回。它返回一个整数,表示 TCP 头中的源端口。另请参见 “fc_saved_syn”、“tcp-ss” 和 “ip.data”。

tcp.win

tcp.win

此功能用于处理表示二进制 TCP 头的输入样本,即 “ip.data” 返回的结果。它返回一个整数,表示对等节点在 TCP 头中通告的窗口大小。该值以原始 16 位无符号整数形式提供,未应用窗口缩放因子。参见 “fc_saved_syn”、“tcp-ss” 及 “ip.data”。

ub64dec

ub64dec

此转换器是 b64dec 转换器的 base64url 变体。base64url 编码是 base64 编码的“URL 和文件名安全字母表”变体,也是 JWT(JSON Web Token)标准中所使用的编码方式。

示例:

# Decoding a JWT payload:
http-request set-var(txn.token_payload) req.hdr(Authorization),word(2,.),ub64dec

ub64enc

ub64enc

此转换器是 base64 转换器的 base64url 变体。

ungrpc(<field_number>[,<field_type>])

ungrpc(<field_number>[,<field_type>])

此操作以原始模式提取 gRPC 消息输入二进制样本表示中的 Protocol Buffers 消息字段,字段编号为 <field_number>(点号表示法),若 <field_type> 不存在,则以整数样本形式提取该字段;若该字段存在,则以整数样本形式提取。允许的类型列表如下:“int32”、“int64”、“uint32”、“uint64”、“sint32”、“sint64”、“bool”、“enum”对应“varint”线缆类型 0;“fixed64”、“sfixed64”、“double”对应 64 位线缆类型 1;“fixed32”、“sfixed32”、“float”对应线缆类型 5。请注意,“string”被视为长度限定类型,因此提取时无需提供 <field_type> 参数。有关 Protocol Buffers 消息字段类型的更多信息,请参见 https://developers.google.com/protocol-buffers/docs/encoding 。

示例:

// with such a protocol buffer .proto file content adapted from
// https://github.com/grpc/grpc/blob/master/examples/protos/route_guide.proto

message Point {
  int32 latitude = 1;
  int32 longitude = 2;
}

message PPoint {
  Point point = 59;
}

message Rectangle {
  // One corner of the rectangle.
  PPoint lo = 48;
  // The other corner of the rectangle.
  PPoint hi = 49;
}

假设一个请求体包含一个“Rectangle”对象值(两个 PPoint 协议缓冲区消息),可通过以下“ungrpc”指令提取四个协议缓冲区字段:

req.body,ungrpc(48.59.1,int32) # "latitude" of "lo" first PPoint
req.body,ungrpc(48.59.2,int32) # "longitude" of "lo" first PPoint
req.body,ungrpc(49.59.1,int32) # "latitude" of "hi" second PPoint
req.body,ungrpc(49.59.2,int32) # "longitude" of "hi" second PPoint

我们也可以将中间的 48.59 字段作为二进制样本提取,如下所示:

req.body,ungrpc(48.59)

由于 gRPC 消息始终由 gRPC 头后接 Protocol Buffers 消息组成,因此在前述示例中,可通过以下等效指令提取 “lo” 的第一个 PPoint 的 “latitude”:

req.body,ungrpc(48.59),protobuf(1,int32)
req.body,ungrpc(48),protobuf(59.1,int32)
req.body,ungrpc(48),protobuf(59),protobuf(1,int32)

请注意,首个转换必须为 “ungrpc”,其余转换必须为 “protobuf”,且仅最后一个转换可选择性地接收第二个参数,用于解释前一个二进制样本。

unset-var(<var>)

unset-var(<var>)

如果输入内容已定义,则取消设置变量。变量名称以表示其作用域的前缀开头。有关变量的详细信息,请参见 第 2.8 节 。

upper

upper

将字符串样本转换为大写形式。此操作只能置于字符串样本提取函数之后,或置于返回字符串类型的结果的转换关键字之后。结果类型为字符串。

url_dec([<in_form>])

url_dec([<in_form>])

将作为输入提供的 URL 编码字符串解码,并返回解码后的结果。输入和输出均为字符串类型。若 <in_form> 参数设置为非零整数值,则输入字符串被视为表单或查询字符串的一部分,加号字符(’+’)将被转换为空格(’ ‘)。否则,仅在问号字符(’?’)之后才执行此转换。

url_enc([<enc_type>])

url_enc([<enc_type>])

接收作为输入的字符串,并返回编码后的输出结果。输入和输出均为字符串类型。默认情况下,编码类型适用于 query 类型。目前不支持其他类型,但保留可选参数以备未来扩展。

us_ltime(<format>[,<offset>])

us_ltime(<format>[,<offset>])

这与 “ltime” 类似,但输入单位为微秒。它还支持受 date(1) 启发的 %N 转换说明符。将一个表示自纪元以来日期的整数转换为字符串,该字符串以本地时间格式表示该日期,格式由 <format> 字符串定义,使用 strftime(3)。此功能旨在允许在日志中使用任意日期格式。可选地,可在输入日期上应用一个以微秒为单位的 <offset> 值(正或负)。有关操作系统支持的格式,请参阅 strftime() 手册页。

%N 转换说明符可用于输出日期的纳秒部分,由于输入精度为微秒,因此精度受限(取值范围为 000000000..999999000)。%N 可以在 % 和 N 之间指定宽度参数。该功能可用于显示毫秒(%3N)或微秒(%6N)。默认及最大宽度为 9(%N 等价于 %9N)。

另请参阅“utime”转换器以处理 UTC 时间,以及“ltime”和 “ms_ltime” 转换器。

示例:

# Emit 3 colons, the local time, the timezone and another with ip:port
# e.g. 2023/07/24/09:53:02.196234 +0000 127.0.0.1:41530
log-format %[accept_date(us),us_ltime("%Y/%m/%d/%H:%M:%S.%6N %z")]\ %ci:%cp

us_utime(<format>[,<offset>])

us_utime(<format>[,<offset>])

这与 “utime” 类似,但输入单位为微秒。它还支持受 date(1) 启发的 %N 转换说明符。将一个假设包含自纪元以来日期的整数转换为字符串,表示该日期在 UTC 时间下的格式,使用由 <format> 字符串定义的格式,该格式由 strftime(3) 解析。此功能旨在允许在日志中使用任意日期格式。可选地,可在输入日期上应用 <offset> 微秒(正或负)。请参阅 strftime() 手册页,了解操作系统支持的格式。

%N 转换说明符可用于输出日期的纳秒部分,由于输入精度为微秒,因此精度受限(取值范围为 000000000..999999000)。%N 可以在 % 和 N 之间指定宽度参数。该功能可用于显示毫秒(%3N)或微秒(%6N)。默认及最大宽度为 9(%N 等价于 %9N)。

另请参阅“ltime”转换器以处理本地时间,以及“utime”和 “ms_utime” 转换器。

示例:

# Emit 3 colons, the UTC time, the timezone and another with ip:port
# e.g. 2023/07/24/09:53:02.196234 +0000 127.0.0.1:41530
log-format %[accept_date(us),us_utime("%Y/%m/%d/%H:%M:%S.%6N %z")]\ %ci:%cp

utime(<format>[,<offset>])

utime(<format>[,<offset>])

将一个表示自纪元以来日期的整数转换为以 UTC 时间表示的字符串,使用由 <format> 字符串定义的格式,该格式遵循 strftime(3)。此功能旨在允许在日志中使用任意日期格式。可选地,可对输入的日期(正或负)应用 <offset> 秒的偏移量。有关操作系统支持的格式,请参阅 strftime() 手册页。另请参见 “ltime” 转换器以及 “ms_utime” 和 “us_utime”。

示例:

# Emit two colons, one with the UTC time and another with ip:port
# e.g.  20140710162350 127.0.0.1:57325
log-format %[date,utime(%Y%m%d%H%M%S)]\ %ci:%cp

when(<condition>[,<args>...])

when(<condition>[,<args>...])

评估条件,当条件为真时,将输入样本原样传递至输出,否则不返回任何内容。此功能专为在特定条件下生成极少数需要的数据而设计,例如在遇到错误时输出调试信息。

条件由以下列表中的关键字构成,可选择性地在前面加上感叹号(’!’)以否定该条件,并可选择性地在后面附加与该条件相关的特定参数:

- "error" returns true when an error was encountered during the processing
  of the request or stream. It uses the same rules as "dontlog-normal"
  (e.g. a successful redispatch counts as an error).

- "forwarded" returns true when the request was forwarded to a backend
  server

- "normal" returns true when no error happened (this is equivalent to
  "!error").

- "processed" returns true when the request was either forwarded to a
  backend server, or processed by an applet.

- "stopping" returns true if the process is currently stopping when the
  rule is evaluated

- "toapplet" returns true when the request was processed by an applet.

- "acl" returns true when the ACL designated by the next argument evaluates
  to true. Note that the ACL is evaluated inline by the converter, so that
  what it refers to must be valid in that context. A particular use case
  consists in evaluating if the total transfer time is too long or not
  before deciding to log detauls from abnormally long transfers.

请注意,无论何种情况都会评估内容,因此执行此操作并不能避免生成相关信息。其目的仅在于避免输出该信息。

例如,仅在处理过程中遇到错误时,才在日志中添加后端流的调试信息,或在停止时记录额外信息等。

示例:

# log "dbg={-}" when fine, or "dbg={... debug info ...}" on error:
log-format "$HAPROXY_HTTP_LOG_FMT dbg={%[bs.debug_str,when(!normal)]}"

Here, the "dbg" field in the log will only contain an dash ('-') to
indicate a missing content when the rule is not validated, and will emit a
whole debugging block when it is.

示例 # 当传输正常时记录 “dbg={-}",在慢速传输时记录 “dbg={… debug info …}” acl slow_xfer res.timer.data ge 10000 # 超过 10 秒视为慢速传输 log-format “$HAPROXY_HTTP_LOG_FMT \ fsdbg={%[fs.debug_str,when(acl,slow_xfer)]} \ bsdbg={%[bs.debug_str,when(acl,slow_xfer)]}”

示例 # 仅在建立真实连接时输出后端 src/port:log-format “$HAPROXY_HTTP_LOG_FMT \ src=[%[bc_src,when(forwarded)]:%[bc_src_port,when(forwarded)]]”

由于该表达式在不成立时会终止评估,因此也可用于阻止后续转换器被调用。例如,可仅在出现错误时调用 debug() 转换器,或仅在绝对必要时记录元素。

示例:

# emit the whole response headers list to stderr only on error and only
# when the output is a connection. We abuse a dummy variable here.
http-after-response set-var(res.test) \
              res.hdrs,when(error),when(forwarded),debug(hdrs,stderr)

另请参见:调试转换器

word(<index>,<delimiters>[,<count>])

word(<index>,<delimiters>[,<count>])

使用给定分隔符切分输入字符串,并提取从开头(正索引)或结尾(负索引)数起的第 n 个词。索引从 1 或 -1 开始;分隔符为格式化字符列表。空词会被跳过:输入字符串开头或结尾的分隔符将被忽略,连续分隔符视为单个分隔符。可以指定要提取的词数 <count>(默认值:1)。值 0 表示提取所有剩余词。

示例:

str(f1_f2_f3__f5),word(4,_)    # f5
str(f1_f2_f3__f5),word(5,_)    # <not found>
str(f1_f2_f3__f5),word(2,_,0)  # f2_f3__f5
str(f1_f2_f3__f5),word(3,_,2)  # f3__f5
str(f1_f2_f3__f5),word(-2,_,3) # f1_f2_f3
str(f1_f2_f3__f5),word(-3,_,0) # f1_f2
str(/f1/f2/f3/f4),word(1,/)    # f1
str(/f1////f2/f3/f4),word(1,/) # f2

wt6([<avalanche>])

wt6([<avalanche>])

使用 WT6 哈希函数将二进制输入样本哈希为无符号 32 位整数。 可选地,若可选参数 <avalanche> 等于 1,则可对输出应用完整的雪崩哈希函数。 该转换器使用与各种基于哈希的负载均衡算法相同的函数,因此将提供完全相同的结果。 其主要用途为调试,但也可用作粘性表条目以收集粗略统计信息。 不得用于安全目的,因为 32 位哈希极易被破解。 另请参见 “crc32”、“djb2”、“sdbm”、“crc32c” 以及 “hash-type” 指令。

x509_v_err_str

x509_v_err_str

将数值转换为其对应的 X509_V_ERR 常量名称。在 ACL 中使用时非常有用,可确保配置在多个 OpenSSL 版本下均能正常工作,因为某些代码在版本变更时可能发生变化。

当未找到对应的常量名称时,将以字符串形式输出数值。

OpenSSL 提供的常量列表可在以下位置找到: https://www.openssl.org/docs/manmaster/man3/X509_STORE_CTX_get_error.html#ERROR-CODES 请注意 务必阅读对应 OpenSSL 版本的页面。

示例:

bind:443 ssl crt common.pem ca-file ca-auth.crt verify optional crt-ignore-err X509_V_ERR_CERT_REVOKED,X509_V_ERR_CERT_HAS_EXPIRED

acl cert_expired ssl_c_verify,x509_v_err_str -m str X509_V_ERR_CERT_HAS_EXPIRED
acl cert_revoked ssl_c_verify,x509_v_err_str -m str X509_V_ERR_CERT_REVOKED
acl cert_ok      ssl_c_verify,x509_v_err_str -m str X509_V_OK

http-response add-header X-SSL Ok if cert_ok
http-response add-header X-SSL Expired if cert_expired
http-response add-header X-SSL Revoked if cert_revoked

http-response add-header X-SSL-verify %[ssl_c_verify,x509_v_err_str]

xor(<value>)

xor(<value>)

对 <value> 与输入值(有符号整数类型)执行按位“异或”(XOR)运算,并将结果以有符号整数形式返回。<value> 可以是数值或变量名。有关变量的详细信息,请参见 第 2.8 节 。

xxh3([<seed>])

xxh3([<seed>])

使用 XXhash 哈希函数的 XXH3 64 位变体,将二进制输入样本哈希为有符号 64 位整数。该哈希支持种子值,其默认值为零,但可作为 <seed> 参数传入其他值。该哈希算法以性能优异且速度极快著称,可用于对 URL 和/或 URL 参数进行哈希,作为粘性表键值以收集统计信息,且碰撞率较低。请注意,由于该算法不被视为具有密码学安全性,因此使用时需谨慎。

xxh32([<seed>])

xxh32([<seed>])

使用 XXHash 的 32 位变体哈希函数,将二进制输入样本哈希为无符号 32 位整数。该哈希支持种子值,其默认值为零,但可作为 <seed> 参数传入其他值。该哈希算法以高效且性能优异著称,可用于对 URL 和/或 URL 参数进行哈希,作为粘性表键值以收集统计信息,碰撞率较低。请注意,该算法不被视为具有密码学安全性,使用时需谨慎。

xxh64([<seed>])

xxh64([<seed>])

使用 XXHash 哈希函数的 64 位变体,将二进制输入样本哈希为有符号 64 位整数。该哈希支持种子,其默认值为零,但可作为 <seed> 参数传入其他值。该哈希算法以性能优异且速度极快著称,可用于对 URL 和/或 URL 参数进行哈希,作为粘性表键以收集统计信息,且碰撞率较低。请注意,由于该算法不被视为具有密码学安全性,因此使用时需谨慎。

7.3.2. 从内部状态获取样本

本节介绍的第一组样本提取方法适用于与任何客户端信息均无关的内部信息。这些方法有时与“monitor fail”指令配合使用,用于向外部观察者报告内部状态。本节所述的样本提取方法可在任何位置使用。

本节中各类样本提取方法及其对应类型的摘要:

  keyword                                          output type
-------------------------------------------------+-------------
acl([!]<name>[,...])                               boolean
act_conn                                           integer
always_false                                       boolean
always_true                                        boolean
avg_queue([<backend>])                             integer
be_conn([<backend>])                               integer
be_conn_free([<backend>])                          integer
be_sess_rate([<backend>])                          integer
bin(<hex>)                                         bin
bool(<bool>)                                       bool
connslots([<backend>])                             integer
cpu_calls                                          integer
cpu_ns_avg                                         integer
cpu_ns_tot                                         integer
date([<offset>[,<unit>]])                          integer
date_us                                            integer
env(<name>)                                        string
fe_conn([<frontend>])                              integer
fe_req_rate([<frontend>])                          integer
fe_sess_rate([<frontend>])                         integer
hostname                                           string
int(<integer>)                                     signed
ipv4(<ipv4>)                                       ipv4
ipv6(<ipv6>)                                       ipv6
last_entity                                        string
last_rule_file                                     string
last_rule_line                                     integer
lat_ns_avg                                         integer
lat_ns_tot                                         integer
meth(<method>)                                     method
nbsrv([<backend>])                                 integer
pid                                                integer
prio_class                                         integer
prio_offset                                        integer
proc                                               integer
queue([<backend>])                                 integer
quic_enabled                                       boolean
rand([<range>])                                    integer
srv_conn([<backend>/]<server>)                     integer
srv_conn_free([<backend>/]<server>)                integer
srv_is_up([<backend>/]<server>)                    boolean
srv_iweight([<backend>/]<server>)                  integer
srv_queue([<backend>/]<server>)                    integer
srv_sess_rate([<backend>/]<server>)                integer
srv_uweight([<backend>/]<server>)                  integer
srv_weight([<backend>/]<server>)                   integer
stopping                                           boolean
str(<string>)                                      string
table_avl([<table>])                               integer
table_cnt([<table>])                               integer
term_events                                        string
thread                                             integer
txn.id32                                           integer
txn.sess_term_state                                string
uptime                                             integer
uuid([<version>])                                  string
var(<var-name>[,<default>])                        undefined
wait_end                                           boolean
waiting_entity                                     string
-------------------------------------------------+-------------

详细列表:

acl([!]<name>[,...]): boolean

acl([!]<name>[,...]): boolean

如果所有指定的 ACL 的评估结果均为真,则返回真;否则返回假。最多可提供 12 个 ACL,各以逗号分隔。每个命名的 ACL 可以用 “!” 前缀来反转结果。如果任意评估产生错误,则样本同样返回错误。请注意,HAProxy 不会对引用的 ACL 执行任何验证检查,例如,使用 HTTP 请求样本的 ACL 是否在响应上下文中被使用。此行为未来可能会更改。

act_conn: integer 返回进程当前活跃的并发连接总数。

always_false: boolean 始终返回布尔值“false”。在调整配置时,可将其用作 ACL 中另一个 ACL 的临时替代。

always_true:boolean 始终返回布尔值“true”。在调整配置时,可将其用作 ACL 中另一个 ACL 的临时替代。

avg_queue([<backend>]): integer

avg_queue([<backend>]): integer

返回指定后端的已排队连接总数除以活跃服务器数量。若未指定后端,则使用当前后端。此指标与“queue”非常相似,但考虑了服务器集群规模,以更准确地衡量新连接可能需要等待的处理时间。主要用途是配合 ACL,在确定新用户将遭遇服务质量下降时返回抱歉页面,或将其传递至后端服务器的头中,使后端服务器自行决定进入降级模式,或禁用部分功能以加快处理速度。请注意,若已无任何活跃服务器,将把已排队连接数的两倍作为测量值。这一估算合理,因为预计总有一台服务器会很快恢复,但若存在状态更优的其他后端,仍建议将新流量导向该后端。另请参见“queue”、“be_conn” 和 “be_sess_rate” 样本提取。

be_conn([<backend>]): integer

be_conn([<backend>]): integer

应用于后端当前已建立的连接数量,可能包含正在评估的连接。若未指定后端名称,则使用当前后端。也可用于检查其他后端。当名义后端已满时,可借此使用特定农场。另见 “fe_conn”、“queue”、“be_conn_free” 及 “be_sess_rate” 条件。

be_conn_free([<backend>]): integer

be_conn_free([<backend>]): integer

返回一个整数值,表示后端中可用服务器的可用连接总数。队列槽位不计入其中。除非所有其他服务器均处于宕机状态,否则不会包含备用服务器。若未指定后端名称,则使用当前后端。也可用于检查其他后端。当名义后端已满时,可借此使用特定农场。另请参见 “be_conn”、“connslots” 和 “srv_conn_free” 条件。

其他注意事项:如果任意服务器的 maxconn 或 maxqueue 为 0(表示无限制),则此 fetch 操作显然无意义,此时返回的值为 -1.

be_sess_rate([<backend>]): integer

be_sess_rate([<backend>]): integer

返回一个整数值,表示后端每秒创建的会话数量。该值可用于 ACL 中,当某个耗资源或不稳定的后端会话创建速率过高时,切换至备用后端;也可用于限制服务滥用(例如防止在线词典被过度访问)。此外,可通过 log-format 指令将此元素添加至日志中。

示例:

# Redirect to an error page if the dictionary is requested too often
backend dynamic
    mode http
    acl being_scanned be_sess_rate gt 100
    redirect location /denied.html if being_scanned

bin(<hex>): bin

bin(<hex>): bin

返回一个二进制链。输入为字符串的十六进制表示。

bool(<bool>): bool

bool(<bool>): bool

返回布尔值。<bool> 可以是 ’true’、‘false’、‘1’ 或 ‘0’。‘false’ 和 ‘0’ 表示相同含义。 ’true’ 和 ‘1’ 表示相同含义。

connslots([<backend>]): integer

connslots([<backend>]): integer

返回一个整数值,表示后端中仍可用的连接槽位数量,该值通过统计所有服务器的最大连接数与最大队列大小之和得出。此值通常仅用于 ACL。

此处的基本思路是能够测量仍可用的连接“槽位”数量(连接 + 队列),以便超出该数量的请求(预期用途;参见 “use_backend” 关键字)可被重定向至其他后端。

‘connslots’ = 可用服务器连接槽位数,加可用服务器队列槽位数。

请注意,尽管可以使用 “fe_conn”,但当流量指向单一 IP 地址并分发至多个后端(例如使用 ACL 实现基于名称的负载均衡)时,“connslots”尤为有用,此时可区分不同后端及其可用的“connslots”数量。此外,“nbsrv”仅统计实际处于 down 状态的服务器,而此获取方式更为精细,还会检查可用连接槽位数量。另请参见“queue”和 “avg_queue”。

其他注意事项:截至目前,代码尚未处理动态连接。 此外,若任意服务器的 maxconn 或 maxqueue 值为 0,则此获取操作显然无意义,此时返回的值将为 -1.

cpu_calls: integer 返回自分配以来,处理流或当前请求的任务调用次数。在 HTTP 持久连接情况下,同一连接上的每个新请求都会重置此数值。该值通常应保持较低且稳定(典型简单请求约为 2 次调用),但如果执行了某些处理操作(如压缩、缓存或分析),该值可能升高。此指标仅用于性能监控。

cpu_ns_avg: 整数 返回处理流或当前请求时,每次调用任务所花费的平均纳秒数。在 HTTP 持久连接情况下,每次新请求都会重置该值。该值表示每次调用处理请求或连接的整体开销。并无所谓的好或坏值,但调用所花费的时间会自动导致其他处理的延迟(参见下文的 lat_ns_avg),并可能影响其他连接的响应时间表现。某些操作如压缩、复杂的正则表达式匹配或繁重的 Lua 操作可能直接影响该值,将其记录在日志中将有助于识别需要修复以恢复良好性能的故障处理环节。请注意:该值等于 cpu_ns_tot 除以 cpu_calls。

cpu_ns_tot: 整数 返回每次调用任务处理流或当前请求所花费的总纳秒数。在 HTTP 持久连接情况下,每次新请求都会重置该数值。该值表示每次调用处理请求或连接的整体开销。并无所谓的好或坏数值,但调用所花费的时间会自动导致其他处理的延迟(参见下文的 lat_ns_avg),增加机器的 CPU 开销,并可能影响其他连接的响应时间感知。某些操作如压缩、复杂的正则表达式匹配或繁重的 Lua 操作可能直接影响该值,将其记录在日志中将有助于识别需要修复以恢复良好性能的故障处理环节。由于高 cpu_calls 计数(例如处理大量 HTTP 数据块)可能导致该值被人为抬高,因此通常更建议记录 cpu_ns_avg。

cpu_usage_grp: 整数 返回上一次轮询周期内测得的 CPU 使用率,取值范围为 0 至 100,该值为当前线程组中所有线程的平均值。可用于故障排查和日志记录。该测量值波动性极强,但在持续负载下仍能保持准确,因为每个线程均在处理数十至数百个请求的过程中进行测量。

cpu_usage_proc: 整数 返回上一次轮询周期内测得的 CPU 使用率,取值范围为 0 到 100,该值为所有运行线程的平均值。可用于故障排查和日志记录。该测量值波动极强,但在持续负载下仍保持准确,因为每个线程会基于数十至数百个请求进行测量。该值等于统计信息页面及 “show info” 命令中空闲比率所报告值的 100 减去该值。

cpu_usage_thr: integer 返回调用线程在上一次轮询周期内测得的 CPU 使用率,取值范围为 0 至 100,可用于故障排查和日志记录。该测量值波动极强,但在持续负载下仍保持准确,因其基于数十至数百个请求的测量结果。该值与判断是否因 CPU 使用率过高而启用连接终止,或是否禁用压缩的决策依据相同。另见 “tune.glitches.kill.cpu-usage” 和 “maxcompcpuusage”。

date([<offset>[,<unit>]]): integer

date([<offset>[,<unit>]]): integer

返回当前日期的纪元时间(自 01/01/1970 起的秒数)。

如果指定了偏移值,则在返回值前将其加到当前日期上。 这特别适用于计算相对日期,因为允许使用正负偏移值。 与 http_date 转换器结合使用时尤为有用。

<unit> 为可选配置,可设置为 “s” 表示秒(默认行为)、“ms” 表示毫秒或 “us” 表示微秒。若指定单位,返回值为自纪元以来的整数,单位为秒、毫秒或微秒,并包含偏移量。当需要小于秒级的时间分辨率时,该配置非常有用。

示例:

# set an expires header to now+1 hour in every response
http-response set-header Expires %[date(3600),http_date]

# set an expires header to now+1 hour in every response, with
# millisecond granularity
http-response set-header Expires %[date(3600000,ms),http_date(0,ms)]

date_us: integer 返回日期的微秒部分(“秒”部分由 date_sample 返回)。该样本与 date_sample 保持一致,因为其来自相同的 timeval 结构。

env(<name>): string

env(<name>): string

返回一个包含环境变量 <name> 值的字符串。请注意,环境变量是进程级的,仅在进程启动时采样。此功能可用于向下一跳服务器传递某些信息,或配合 ACL 在进程以特定方式启动时执行特定动作。

示例:

# Pass the Via header to next hop with the local hostname in it
http-request add-header Via 1.1\ %[env(HOSTNAME)]

# reject cookie-less requests when the STOP environment variable is set
http-request deny if !{ req.cook(SESSIONID) -m found } { env(STOP) -m found }

fe_conn([<frontend>]): integer

fe_conn([<frontend>]): integer

返回前端当前建立的连接数,可能包含正在评估的连接。若未指定前端名称,则使用当前前端。也可用于检查其他前端。可用于在强制阻断前返回抱歉页面,或在服务端组被认为已满时,使用特定后端处理新请求。该功能主要与 ACL 配合使用,也可用于将部分统计信息传递至服务器的 HTTP 头中。参见 “dst_conn”、“be_conn”、“fe_sess_rate” 获取操作。

fe_req_rate([<frontend>]): integer

fe_req_rate([<frontend>]): integer

返回一个整数值,表示发送至前端的每秒 HTTP 请求数。 在启用客户端持久连接的情况下,该数值可能与 “fe_sess_rate” 不同。

fe_sess_rate([<frontend>]): integer

fe_sess_rate([<frontend>]): integer

返回一个整数值,表示前端的会话创建速率,单位为每秒新建会话数。该值可用于 ACL 中,将传入会话速率限制在可接受范围内,以便在最早时刻防止服务被滥用,例如与其他第 4 层 ACL 结合使用,强制客户端在速率降至限制以下前等待。也可通过 log-format 指令将此元素添加至日志中。另请参见前端中使用的“rate-limit sessions”指令。

示例:

# This frontend limits incoming mails to 10/s with a max of 100
# concurrent connections. We accept any connection below 10/s, and
# force excess clients to wait for 100 ms. Since clients are limited to
# 100 max, there cannot be more than 10 incoming mails per second.
frontend mail
    bind:25
    mode tcp
    maxconn 100
    acl too_fast fe_sess_rate ge 10
    tcp-request inspect-delay 100ms
    tcp-request content accept if ! too_fast
    tcp-request content accept if WAIT_END

hostname: string 返回系统主机名。

int(<integer>): signed integer

int(<integer>): signed integer

返回一个有符号整数。

ipv4(<ipv4>): ipv4

ipv4(<ipv4>): ipv4

返回 IPv4 地址。

ipv6(<ipv6>): ipv6

ipv6(<ipv6>): ipv6

返回 IPv6 地址。

last_entity: string 该字段返回流分析过程中最后一个被评估的实体的身份。可能是最后一个匹配的规则,也可能是中断处理的过滤器。

最终规则是指终止规则集评估的规则(如“accept”、“deny”或“redirect”)。该机制适用于作用于“content”规则集的 TCP 请求和响应规则,以及“http-request”、“http-response”和“http-after-response”规则集中的 HTTP 规则。不支持旧版“redirect”规则集(相关信息未存储于此),也不支持“tcp-request connection”和“tcp-request session”规则集,因为相关信息存储在流级别,而这些规则执行时流尚不存在。此时,返回值等价于“last_rule_file:last_rule_line”。参见 “last_rule_file”、“last_rule_line”。

对于过滤器,其标识符按开发人员定义的方式返回。若未定义标识符,则返回对应唯一内部标识符的十六进制值。

此函数的主要目的是在日志中记录中断处理的最后一个实体,以协助排查问题。返回的实体信息可能会随时间变化,不得用于除调试以外的其他用途。

示例:

# Log the last entity, if any, and only if an error is reported
log-format "$HAPROXY_HTTP_LOG_FMT %{Q}[last_entity,when(error)]

last_rule_file: string 此函数返回在流分析过程中匹配到的最后一个最终规则所在的配置文件名称。最终规则是指终止规则集评估的规则(例如“accept”、“deny”或“redirect”)。该功能适用于作用于“content”规则集的 TCP 请求和响应规则,以及来自“http-request”、“http-response”和“http-after-response”规则集的 HTTP 规则。不支持旧版“redirect”规则集(此类信息未被存储),也不支持“tcp-request connection”或“tcp-request session”规则集,因为相关信息存储在流级别,而这些规则执行时流尚不存在。此函数的主要用途是能够在日志中报告最终判定结果所依据的规则位置,以便排查请求被拒绝的原因等情形。参见 “last_rule_line”。

last_rule_line: integer 此函数返回在流分析过程中匹配到的最后一个终态规则在配置文件中的行号。终态规则是指终止规则集评估的规则(如“accept”、“deny”或“redirect”)。该功能适用于作用于“content”规则集的 TCP 请求和响应规则,以及“http-request”、“http-response”和“http-after-response”规则集中的 HTTP 规则。不支持旧版“redirect”规则集(相关信息未在其中存储),也不支持“tcp-request connection”和“tcp-request session”规则集,因为相关信息存储在流级别,而这些规则执行时流尚未存在。此函数的主要用途是能够在日志中报告最终判定结果所对应的规则位置,以便排查请求被拒绝的原因等情形。参见 “last_rule_file”。

lat_ns_avg: 整数 返回在处理流的任务被唤醒至实际被调用之间所花费的平均纳秒数。在启用 HTTP 持久连接的情况下,每次新请求到达同一连接时该数值将被重置。该值表示当前请求因并行处理的其他请求而承受的整体延迟,是受“噪音邻居”影响导致感知性能下降的直接指标。为保持该值较低,可采取以下措施:使用 “tune.runqueue-depth” 降低调度器运行队列深度,使用 “tune.maxpollevents” 减少单次处理的并发事件数量,通过 “bind” 语句或前端配置中的 “nice” 选项降低流的 nice 值,启用低延迟调度模式 “tune.sched.low-latency”,或检查日志中是否存在其他耗时较长的请求(表现为 “cpu_ns_avg” 值较大),并调整或修复其处理逻辑。大缓冲区的压缩可能为问题根源,如复杂的正则表达式或过长的正则表达式列表。注意:该值等于 lat_ns_tot 除以 cpu_calls。

lat_ns_tot: integer 返回从处理流的任务被唤醒时刻到其实际被调用时刻之间所花费的总纳秒数。在启用 HTTP 持久连接的情况下,每次新请求到达时该数值将被重置。该值反映了当前请求因并行处理的其他请求而遭受的整体延迟,是受“噪音邻居”影响感知性能的直接指标。为保持该值较低,可采取以下措施:使用 “tune.runqueue-depth” 降低调度器运行队列深度;使用 “tune.maxpollevents” 减少单次处理的并发事件数量;通过在 “bind” 行或前端中使用 “nice” 选项降低流的 nice 值;启用低延迟调度模式 “tune.sched.low-latency”;或检查日志中是否存在其他处理耗时较长的请求(表现为 “cpu_ns_avg” 值较大),并调整或修复其处理逻辑。大缓冲区的压缩可能为问题根源,如复杂的正则表达式或过长的正则表达式列表。请注意:尽管直观上可能认为总延迟会增加传输时间,但实际情况几乎从不如此,因为当任务等待 CPU 时,网络缓冲区仍在持续填充,下一次调用将一次性处理更多数据。该值可能因 cpu_calls 计数过高而被人为抬高,例如在处理大量 HTTP 数据块时,因此通常更建议记录 lat_ns_avg,其作为性能指标更具参考价值。

meth(<method>): method

meth(<method>): method

返回一个方法。

nbsrv([<backend>]): integer

nbsrv([<backend>]): integer

返回一个整数值,表示当前后端或指定后端中可用服务器的数量。该功能主要用于 ACL,也可用于日志记录。通常在服务器数量过低、无法处理负载时,用于切换至备用后端。与“monitor fail”结合使用时,可用于报告故障。

pid: integer 返回当前进程的 PID。在大多数情况下,这是工作进程的 PID。

prio_class: integer 返回当前流在 HTTP 模式下的优先级类别,或在 TCP 模式下的连接优先级类别。该值为最近一次调用 “http-request set-priority-class” 或 “tcp-request content set-priority-class” 所设置的值。

prio_offset: integer 返回当前流在 HTTP 模式下的优先级偏移量,或在 TCP 模式下的连接优先级偏移量。该值为最近一次调用 “http-request set-priority-offset” 或 “tcp-request content set-priority-offset” 所设置的值。

proc: integer 始终返回值 1(历史上会返回调用进程的编号)。

queue([<backend>]): integer

queue([<backend>]): integer

返回指定后端的排队连接总数,包括所有服务器队列中的连接。若未指定后端名称,则使用当前后端,也可检查其他后端。此功能在 ACL 中或向后端服务器传递统计信息时非常有用。当排队连接数超过已知阈值时,可采取相应动作,通常表明流量激增或服务器出现严重性能下降。一种可能的动作是拒绝新用户连接,但仍接受旧连接。另请参见 “avg_queue”、“be_conn” 和 “be_sess_rate” 获取操作。

quic_enabled: boolean 当编译时启用了对 QUIC 传输协议的支持,且未通过 “tune.quic.listen” 全局选项禁用 QUIC 监听器时,返回 true。参见 “tune.quic.listen” 全局选项。

rand([<range>]): integer

rand([<range>]): integer

返回一个介于 0 到 <range> 个可能值范围内的随机整数。若未指定范围,则默认为 2^32,生成的数值范围为 0 到 4294967295。该功能可用于传递某些用于路由决策的值,或仅用于调试目的。请注意,此随机数生成器不得用于安全用途。

srv_conn([<backend>/]<server>): integer

srv_conn([<backend>/]<server>): integer

返回一个整数值,表示指定服务器上当前建立的连接数量,可能包含正在评估的连接。如果省略 <backend>,则在当前后端中查找服务器。可用于在某台服务器满载时切换至特定农场,或向服务器通报我们对其当前活跃连接数的统计视图。另请参见 “fe_conn”、“be_conn”、“queue” 和 “srv_conn_free” 获取方法。

srv_conn_free([<backend>/]<server>): integer

srv_conn_free([<backend>/]<server>): integer

返回一个整数值,表示指定服务器上可用连接的数量,可能包含正在评估的连接。该值不包含队列槽位。若省略 <backend>,则在当前后端中查找服务器。可用于在某台服务器满载时切换至特定农场,或向服务器通报我们对其当前活跃连接数的观测值。另请参见 “be_conn_free” 和 “srv_conn” 获取方法。

其他注意事项和说明:如果服务器的 maxconn 为 0,则此获取操作显然无意义,此时返回的值为 -1.

srv_is_up([<backend>/]<server>): boolean

srv_is_up([<backend>/]<server>): boolean

当指定服务器处于运行状态时返回 true,处于关闭状态或维护模式时返回 false。若省略 <backend>,则在当前后端中查找服务器。该功能主要用于根据通过健康检查报告的外部状态采取动作(例如,某个地理站点的可用性)。另一种可能的用法更像一种技巧,即使用虚拟服务器作为布尔变量,可通过 CLI 启用或禁用,从而实现实时调整依赖于这些 ACL 的规则。

srv_iweight([<backend>/]<server>): integer

srv_iweight([<backend>/]<server>): integer

返回对应服务器初始权重的整数值。若省略 <backend>,则在当前后端中查找服务器。参见 “srv_weight” 和 “srv_uweight”。

srv_queue([<backend>/]<server>): integer

srv_queue([<backend>/]<server>): integer

返回一个整数值,表示指定服务器队列中当前挂起的连接数量。若省略 <backend>,则在当前后端中查找服务器。该指令可与 “use-server” 指令配合使用,当某服务器负载不重时,强制使用已知响应更快的服务器。另请参见 “srv_conn”、“avg_queue” 和 “queue” 样本提取方法。

srv_sess_rate([<backend>/]<server>): integer

srv_sess_rate([<backend>/]<server>): integer

返回指定服务器的会话创建速率对应的整数,单位为每秒新建会话数。若省略 <backend>,则在当前后端中查找服务器。该功能主要用于 ACL,但也可用于日志记录。当昂贵或脆弱的后端会话速率过高时,可用于切换至备用后端,或限制服务滥用(例如防止延迟请求导致服务器过载)。

示例:

# Redirect to a separate back
acl srv1_full srv_sess_rate(be1/srv1) gt 50
acl srv2_full srv_sess_rate(be1/srv2) gt 50
use_backend be2 if srv1_full or srv2_full

srv_uweight([<backend>/]<server>): integer

srv_uweight([<backend>/]<server>): integer

返回对应用户可见服务器权重的整数值。若省略 <backend>,则在当前后端中查找服务器。参见 “srv_weight” 和 “srv_iweight”。

srv_weight([<backend>/]<server>): integer

srv_weight([<backend>/]<server>): integer

返回当前(或生效)服务器的权重值,该值为整数。若省略 <backend>,则在当前后端中查找服务器。参见 “srv_iweight” 和 “srv_uweight”。

stopping: boolean 如果调用函数的进程当前正在停止,则返回 TRUE。此信息可用于日志记录,或在优雅关闭期间放松某些检查,或协助关闭特定连接。

str(<string>): string

str(<string>): string

返回一个字符串。

table_avl([<table>]): integer

table_avl([<table>]): integer

返回当前代理的 stick-table 中可用条目的总数,或指定 stick-table 中的可用条目总数。参见 “table_cnt”。

table_cnt([<table>]): integer

table_cnt([<table>]): integer

返回当前代理的 stick-table 中当前正在使用的条目总数,或指定 stick-table 中的条目总数。另请参见 “table_conn_cnt” 和 table_avl 以了解其他条目计数方法。

term_events: string 返回与流关联的所有实体(客户端和服务器端)已知的终止事件。返回包含七个元素的元组,内容如下:

- the termination events of the frontend connection
- the termination events of the frontend mux connection
- the termination events of the frontend stream endpoint descriptor
  (the mux stream or the applet)
- the termination events of the stream
- the termination events of the backend stream endpoint descriptor
  (the mux stream or the applet)
- the termination events of the backend mux connection
- the termination events of the backend connection

在每个级别上,前四个事件会被报告。若某一特定级别尚未报告任何事件,则返回空字符串。若不支持终止事件,则返回“-”。

仅可用于调试目的。确切格式未记录,因为其可能根据开发人员需求而变化。

tgroup: integer 返回一个整数值,表示调用该函数的线程组的位置,取值范围为 0 到 (global.thread-groups - 1)。此功能在日志记录和调试时非常有用。

thread: integer 返回一个整数值,表示调用函数的线程位置,取值范围为 0 到 (global.nbthread - 1)。该值在日志记录和调试时非常有用。

txn.id32: integer 返回内部事务 ID。该值为 32 位整数。因此,从绝对值上看,其值并非唯一,事务 ID 可能发生回绕。回绕周期取决于请求速率。实践中通常不会造成问题。如需真正的唯一 ID,请参见 “unique-id-format” 指令。

txn.sess_term_state: string 返回日志中报告的 TCP 或 HTTP 流终止状态。该值为 2 个字符的字符串,格式为“最终流状态 + 导致其终止的事件”。有关断开连接时流状态的可能事件列表,请参见 第 8.5 节 。返回样本提取评估时刻的当前值,该值可能发生变化。除非在 “http-after-response” 规则集中与 ACL 一起使用,或用于日志消息中,否则该值始终为 “–"。

示例:

# Return a 429-Too-Many-Requests if stream timed out in queue
http-after-response set-status 429 if { txn.sess_term_state  "sQ" }

uptime: integer 返回当前 HAProxy 工作进程的运行时间(单位:秒)。

uuid([<version>]): string

uuid([<version>]): string

按照 RFC 9562 标准返回一个 UUID。若未指定版本,则返回 UUID 版本 4(完全随机)。

版本 4 和 7 受支持。

var(<var-name>[,<default>]): undefined

var(<var-name>[,<default>]): undefined

返回存储类型的变量。如果该变量未设置,样本提取将失败,除非提供了默认值,此时将返回该默认值作为字符串。允许空字符串。有关变量的详细信息,请参见 第 2.8 节 。

dump_all_vars([<scope>][,<prefix>][,<delimiter>]): string

dump_all_vars([<scope>][,<prefix>][,<delimiter>]): string

返回指定作用域中的所有变量列表,可选择按名称前缀进行过滤,并支持自定义分隔符。

输出格式:var1=value1<delim>var2=value2<delim>…

按类型进行值编码:

  • 字符串:使用引号包围并转义("、\、\r、\n、\b、\0)示例:txn.name=“John \“Doe\”
  • 二进制:以 x 开头的十六进制编码,不加引号 示例:txn.data=x48656c6c6f
  • 整数:不加引号的十进制数 示例:txn.count=42
  • 布尔值:不加引号的 “true” 或 “false” 示例:txn.active=true
  • 地址:不加引号的 IP 地址字符串 示例:txn.client=192.168.1.1
  • HTTP 方法:加引号的字符串 示例:req.method=“GET”

参数:

  • <scope>(可选):sess、txn、req、res 或 proc。若省略,则按此处所示顺序遍历所有这些作用域。

  • <prefix>(可选):过滤名称以指定前缀开头的变量(在移除作用域前缀后)。性能提示:使用前缀过滤时,仍会遍历作用域内的所有变量。请勿在涉及数千个变量的配置中使用。

  • <delimiter>(可选):用于分隔变量的字符串。默认值为“, ”(逗号加空格)。可自定义为任意字符串。请注意,若需在函数参数中传递逗号或空格,必须将其用单引号或双引号括起(若表达式本身已在引号内,请使用另一类引号)。

返回值:

  • 成功时:包含所有匹配变量的字符串
  • 失败时:若输出缓冲区太小,则返回空值(样本提取失败)。该函数不会截断输出;失败时将完全终止,以避免产生部分数据。

这在调试、日志记录或导出变量状态时尤为有用。

示例:

# Dump all transaction variables
http-request return string %[dump_all_vars(txn)]

# Dump only variables starting with "user"
http-request set-header X-User-Vars "%[dump_all_vars(txn,user)]"

# Dump all process variables
http-request return string %[dump_all_vars(proc)]

# Custom delimiter (semicolon)
http-request set-header X-Vars "%[dump_all_vars(txn,,; )]"

# Force the default delimiter (comma space)
http-request set-header X-Vars "%[dump_all_vars(txn,,', ')]"

# Prefix filter with custom delimiter
http-request set-header X-Session "%[dump_all_vars(sess,user,|)]"

wait_end: boolean 此获取操作在检查周期结束时返回 true,或不返回任何结果。仅在 ACL 中与内容分析配合使用,以避免过早得出错误结论。也可用于延迟某些动作,例如对特定地址的延迟拒绝。由于该获取操作要么停止规则评估,要么立即返回 true,建议将此 ACL 作为规则中的最后一个使用。请注意,默认 ACL “WAIT_END” 始终可直接使用,无需预先声明。此测试专为与 TCP 请求内容检查配合使用而设计。

示例:

# delay every incoming request by 2 seconds
tcp-request inspect-delay 2s
tcp-request content accept if WAIT_END

# don't immediately tell bad guys they are rejected
tcp-request inspect-delay 10s
acl goodguys src 10.0.0.0/24
acl badguys  src 10.0.1.0/24
tcp-request content accept if goodguys
tcp-request content reject if badguys WAIT_END
tcp-request content reject

waiting_entity: string 当发生错误或超时时,此字段返回正在等待继续处理的实体的身份。该实体可能是一个规则或过滤器。然而,此列表并非详尽无遗,所有可能实体的格式也未强制记录。

当实体为规则时,将返回其位置。位置信息为包含该规则的配置文件,后跟规则在该文件中的行号,两者以冒号分隔。

对于过滤器,其标识符按开发人员定义的方式返回。若未定义标识符,则返回对应唯一内部标识符的十六进制值。

此函数的主要目的是在遇到错误或超时并中断处理时,能够将阻塞流分析的实体记录到日志中,以协助排查问题。返回的实体信息可能会随时间变化,不得用于除调试以外的其他用途。

示例:

# Log the waiting entity, if any, and only if an error is reported
log-format "$HAPROXY_HTTP_LOG_FMT %{Q}[waiting_entity,when(error)]

7.3.3. 获取第 4 层样本

第 4 层通常仅描述传输层,HAProxy 中该层最接近连接,此时尚未提供任何内容。此处描述的获取方法可应用于最低至 “tcp-request connection” 规则集,除非它们需要未来信息。这些方法通常包括 TCP/IP 地址和端口,以及与入站连接相关的粘性表元素。若需从粘性计数器中获取值,可使用预定义的 “sc0_"、“sc1_” 或 “sc2_” 前缀显式指定计数器编号为 0、1 或 2。这三个预定义前缀仅在全局 “tune.stick-counters” 值不超过 3 时可用;否则,可使用 “sc_” 前缀并从 “sc_0” 到 “sc_N” 指定计数器编号,其中 N 为 (tune.stick-counters-1)。可选地,可通过 “sc*” 形式指定表,此时将查找当前跟踪键在该备用表中的值,而非当前正在跟踪的表。

本节中各类样本提取方法及其对应类型的摘要:

  keyword                                          output type
-------------------------------------------------+-------------
accept_date([<unit>])                              integer
bc.timer.connect                                   integer
bc_be_queue                                        integer
bc_dst                                             ip
bc_dst_port                                        integer
bc_err                                             integer
bc_err_name                                        string
bc_err_str                                         string
bc_glitches                                        integer
bc_http_major                                      integer
bc_nb_streams                                      integer
bc_reused                                          boolean
bc_rtt(<unit>)                                     integer
bc_rttvar(<unit>)                                  integer
bc_settings_streams_limit                          integer
bc_src                                             ip
bc_src_port                                        integer
bc_srv_queue                                       integer
be_id                                              integer
be_name                                            string
be_connect_timeout                                 integer
be_queue_timeout                                   integer
be_server_timeout                                  integer
be_tarpit_timeout                                  integer
be_tunnel_timeout                                  integer
bytes_in                                           integer
bytes_out                                          integer
cur_connect_timeout                                integer
cur_client_timeout                                 integer
cur_queue_timeout                                  integer
cur_server_timeout                                 integer
cur_tarpit_timeout                                 integer
cur_tunnel_timeout                                 integer
dst                                                ip
dst_conn                                           integer
dst_is_local                                       boolean
dst_port                                           integer
fc.timer.handshake                                 integer
fc.timer.total                                     integer
fc_dst                                             ip
fc_dst_is_local                                    boolean
fc_dst_port                                        integer
fc_err                                             integer
fc_err_name                                        string
fc_err_str                                         string
fc_fackets                                         integer
fc_glitches                                        integer
fc_http_major                                      integer
fc_lost                                            integer
fc_nb_streams                                      integer
fc_pp_authority                                    string
fc_pp_tlv(<id>)                                    string
fc_pp_unique_id                                    string
fc_rcvd_proxy                                      boolean
fc_reordering                                      integer
fc_retrans                                         integer
fc_rtt(<unit>)                                     integer
fc_rttvar(<unit>)                                  integer
fc_sacked                                          integer
fc_saved_syn                                       binary
fc_settings_streams_limit                          integer
fc_src                                             ip
fc_src_is_local                                    boolean
fc_src_port                                        integer
fc_unacked                                         integer
fe_tarpit_timeout                                  integer
fe_client_timeout                                  integer
fe_defbe                                           string
fe_id                                              integer
fe_name                                            string
req.bytes_in                                       integer
req.bytes_out                                      integer
res.bytes_in                                       integer
res.bytes_out                                      integer
res.timer.data                                     integer
sc0_bytes_in_rate([<table>])                       integer
sc0_bytes_out_rate([<table>])                      integer
sc0_clr_gpc0([<table>])                            integer
sc0_clr_gpc1([<table>])                            integer
sc0_conn_cnt([<table>])                            integer
sc0_conn_cur([<table>])                            integer
sc0_conn_rate([<table>])                           integer
sc0_get_gpc0([<table>])                            integer
sc0_get_gpc1([<table>])                            integer
sc0_get_gpt0([<table>])                            integer
sc0_glitch_cnt([<table>])                          integer
sc0_glitch_rate([<table>])                         integer
sc0_gpc0_rate([<table>])                           integer
sc0_gpc1_rate([<table>])                           integer
sc0_http_err_cnt([<table>])                        integer
sc0_http_err_rate([<table>])                       integer
sc0_http_fail_cnt([<table>])                       integer
sc0_http_fail_rate([<table>])                      integer
sc0_http_req_cnt([<table>])                        integer
sc0_http_req_rate([<table>])                       integer
sc0_inc_gpc0([<table>])                            integer
sc0_inc_gpc1([<table>])                            integer
sc0_kbytes_in([<table>])                           integer
sc0_kbytes_out([<table>])                          integer
sc0_key                                            any
sc0_sess_cnt([<table>])                            integer
sc0_sess_rate([<table>])                           integer
sc0_tracked([<table>])                             boolean
sc0_trackers([<table>])                            integer
sc1_bytes_in_rate([<table>])                       integer
sc1_bytes_out_rate([<table>])                      integer
sc1_clr_gpc0([<table>])                            integer
sc1_clr_gpc1([<table>])                            integer
sc1_conn_cnt([<table>])                            integer
sc1_conn_cur([<table>])                            integer
sc1_conn_rate([<table>])                           integer
sc1_get_gpc0([<table>])                            integer
sc1_get_gpc1([<table>])                            integer
sc1_get_gpt0([<table>])                            integer
sc1_glitch_cnt([<table>])                          integer
sc1_glitch_rate([<table>])                         integer
sc1_gpc0_rate([<table>])                           integer
sc1_gpc1_rate([<table>])                           integer
sc1_http_err_cnt([<table>])                        integer
sc1_http_err_rate([<table>])                       integer
sc1_http_fail_cnt([<table>])                       integer
sc1_http_fail_rate([<table>])                      integer
sc1_http_req_cnt([<table>])                        integer
sc1_http_req_rate([<table>])                       integer
sc1_inc_gpc0([<table>])                            integer
sc1_inc_gpc1([<table>])                            integer
sc1_kbytes_in([<table>])                           integer
sc1_kbytes_out([<table>])                          integer
sc1_key                                            any
sc1_sess_cnt([<table>])                            integer
sc1_sess_rate([<table>])                           integer
sc1_tracked([<table>])                             boolean
sc1_trackers([<table>])                            integer
sc2_bytes_in_rate([<table>])                       integer
sc2_bytes_out_rate([<table>])                      integer
sc2_clr_gpc0([<table>])                            integer
sc2_clr_gpc1([<table>])                            integer
sc2_conn_cnt([<table>])                            integer
sc2_conn_cur([<table>])                            integer
sc2_conn_rate([<table>])                           integer
sc2_get_gpc0([<table>])                            integer
sc2_get_gpc1([<table>])                            integer
sc2_get_gpt0([<table>])                            integer
sc2_glitch_cnt([<table>])                          integer
sc2_glitch_rate([<table>])                         integer
sc2_gpc0_rate([<table>])                           integer
sc2_gpc1_rate([<table>])                           integer
sc2_http_err_cnt([<table>])                        integer
sc2_http_err_rate([<table>])                       integer
sc2_http_fail_cnt([<table>])                       integer
sc2_http_fail_rate([<table>])                      integer
sc2_http_req_cnt([<table>])                        integer
sc2_http_req_rate([<table>])                       integer
sc2_inc_gpc0([<table>])                            integer
sc2_inc_gpc1([<table>])                            integer
sc2_kbytes_in([<table>])                           integer
sc2_kbytes_out([<table>])                          integer
sc2_key                                            any
sc2_sess_cnt([<table>])                            integer
sc2_sess_rate([<table>])                           integer
sc2_tracked([<table>])                             boolean
sc2_trackers([<table>])                            integer
sc_bytes_in_rate(<ctr>[,<table>])                  integer
sc_bytes_out_rate(<ctr>[,<table>])                 integer
sc_clr_gpc(<idx>,<ctr>[,<table>])                  integer
sc_clr_gpc0(<ctr>[,<table>])                       integer
sc_clr_gpc1(<ctr>[,<table>])                       integer
sc_conn_cnt(<ctr>[,<table>])                       integer
sc_conn_cur(<ctr>[,<table>])                       integer
sc_conn_rate(<ctr>[,<table>])                      integer
sc_get_gpc(<idx>,<ctr>[,<table>])                  integer
sc_get_gpc0(<ctr>[,<table>])                       integer
sc_get_gpc1(<ctr>[,<table>])                       integer
sc_get_gpt(<idx>,<ctr>[,<table>])                  integer
sc_get_gpt0(<ctr>[,<table>])                       integer
sc_glitch_cnt(<ctr>[,<table>])                     integer
sc_glitch_rate(<ctr>[,<table>])                    integer
sc_gpc0_rate(<ctr>[,<table>])                      integer
sc_gpc1_rate(<ctr>[,<table>])                      integer
sc_gpc_rate(<idx>,<ctr>[,<table>])                 integer
sc_http_err_cnt(<ctr>[,<table>])                   integer
sc_http_err_rate(<ctr>[,<table>])                  integer
sc_http_fail_cnt(<ctr>[,<table>])                  integer
sc_http_fail_rate(<ctr>[,<table>])                 integer
sc_http_req_cnt(<ctr>[,<table>])                   integer
sc_http_req_rate(<ctr>[,<table>])                  integer
sc_inc_gpc(<idx>,<ctr>[,<table>])                  integer
sc_inc_gpc0(<ctr>[,<table>])                       integer
sc_inc_gpc1(<ctr>[,<table>])                       integer
sc_kbytes_in(<ctr>[,<table>])                      integer
sc_kbytes_out(<ctr>[,<table>])                     integer
sc_key(<ctr>)                                      any
sc_sess_cnt(<ctr>[,<table>])                       integer
sc_sess_rate(<ctr>[,<table>])                      integer
sc_tracked(<ctr>[,<table>])                        boolean
sc_trackers(<ctr>[,<table>])                       integer
so_id                                              integer
so_name                                            string
src                                                ip
src_bytes_in_rate([<table>])                       integer
src_bytes_out_rate([<table>])                      integer
src_clr_gpc(<idx>[,<table>])                       integer
src_clr_gpc0([<table>])                            integer
src_clr_gpc1([<table>])                            integer
src_conn_cnt([<table>])                            integer
src_conn_cur([<table>])                            integer
src_conn_rate([<table>])                           integer
src_get_gpc(<idx>[,<table>])                       integer
src_get_gpc0([<table>])                            integer
src_get_gpc1([<table>])                            integer
src_get_gpt(<idx>[,<table>])                       integer
src_get_gpt0([<table>])                            integer
src_glitch_cnt([<table>])                          integer
src_glitch_rate([<table>])                         integer
src_gpc0_rate([<table>])                           integer
src_gpc1_rate([<table>])                           integer
src_gpc_rate(<idx>[,<table>])                      integer
src_http_err_cnt([<table>])                        integer
src_http_err_rate([<table>])                       integer
src_http_fail_cnt([<table>])                       integer
src_http_fail_rate([<table>])                      integer
src_http_req_cnt([<table>])                        integer
src_http_req_rate([<table>])                       integer
src_inc_gpc(<idx>[,<table>])                       integer
src_inc_gpc0([<table>])                            integer
src_inc_gpc1([<table>])                            integer
src_is_local                                       boolean
src_kbytes_in([<table>])                           integer
src_kbytes_out([<table>])                          integer
src_port                                           integer
src_sess_cnt([<table>])                            integer
src_sess_rate([<table>])                           integer
src_updt_conn_cnt([<table>])                       integer
srv_id                                             integer
srv_name                                           string
txn.conn_retries                                   integer
txn.redispatched                                   boolean
-------------------------------------------------+-------------

详细列表:

accept_date([<unit>]): integer

accept_date([<unit>]): integer

这是 HAProxy 接收到连接的确切时间(如果系统队列中存在延迟,该时间可能与网络上观察到的时间略有差异)。该时间通常与上游防火墙日志中出现的时间一致。在 HTTP 模式下,accept_date 字段将在连接首次准备好接收新请求时重置(HTTP/1 为上一个响应结束时,HTTP/2 为上一个请求结束后立即)。

返回自纪元以来的秒数。

<unit> 为可选配置,可设置为 “s” 表示秒(默认行为)、“ms” 表示毫秒或 “us” 表示微秒。若指定单位,返回值为整数,表示自纪元以来的秒、毫秒或微秒数。当需要小于秒级的时间分辨率时,该配置非常有用。

bc.timer.connect: integer 建立与服务器的 TCP 连接所花费的总时间。此值等同于日志格式中的 %Tc。单位为毫秒(ms)。更多信息请参见 Section 8.4 “Timing events”

bc_be_queue: 整数,表示在等待目标后端连接槽位时,从队列中取出的流数量。这等价于日志格式中的 %bq。

bc_dst: ip 这是连接在服务器端的目标 IP 地址,即 HAProxy 所连接的服务器地址。该字段类型为 IP,适用于 IPv4 和 IPv6 表。在 IPv6 表中,IPv4 地址根据 RFC 4291 映射为其对应的 IPv6 形式。

bc_dst_port: integer 返回一个整数值,表示服务器端连接的目标 TCP 端口,即 HAProxy 所连接的端口。

bc_err: integer 返回当前后端连接中可能发生的错误的 ID。有关错误代码及其对应错误消息的完整列表,请参见 “fc_err_str” fetch。

bc_err_name: string 返回描述后端内部错误的名称,说明连接失败的原因。该字符串由单个单词组成,当无错误时为空。其对应于 “fc_err_str” 关键字所列表格中的“name”列。

bc_err_str: string 返回描述当前后端发生问题的错误消息,导致连接失败。请参见 “fc_err_str” fetch 以获取完整的错误码及其对应的错误消息列表。

bc_glitches: integer 返回后端连接上计数的协议异常数量。 这些异常通常涵盖协议违规行为,以及可能表明服务器伪造或行为异常的小型异常,这类问题可能在基础设施中引发问题(例如导致连接提前终止,或频繁触发 TLS 重协商)。这些异常也可能由响应过大无法容纳于单个缓冲区引起,从而导致 HTTP 502 错误。理想情况下,该数值应保持为零,尽管若其相对于总请求数量极低,通常也可接受。这些数值通常不应视为警报信号(尤其是数值较小时),但突然上升可能表明存在异常。并非所有协议多路复用器都会测量此指标,若需获取事件的更多详情,唯一方法是启用追踪以捕获所有通信过程。

bc_http_major: integer 返回后端连接的 HTTP 主版本编码,可能为 1(表示 HTTP/0.9 至 HTTP/1.1)或 2(表示 HTTP/2)。请注意,此值基于网络传输编码,而非请求头中所含的版本。

bc_nb_streams: integer 返回后端连接上打开的流的数量。

bc_reused: boolean 如果通过复用的后端连接完成传输,则返回 true。

bc_rtt(<unit>): integer

bc_rtt(<unit>): integer

返回内核测量的后端连接往返时间(RTT)。<unit> 为可选,默认单位为毫秒。<unit> 可设置为 “ms” 表示毫秒,或 “us” 表示微秒。若服务器连接未建立,或连接非 TCP,或操作系统不支持 TCP_INFO(例如 2.4 版本之前的 Linux 内核),则样本提取失败。

bc_rttvar(<unit>): integer

bc_rttvar(<unit>): integer

返回内核测量的后端连接往返时间(RTT)方差。<unit> 为可选,默认单位为毫秒。<unit> 可设置为 “ms” 表示毫秒,或 “us” 表示微秒。若服务器连接未建立,或连接非 TCP,或操作系统不支持 TCP_INFO(例如 Linux 内核版本低于 2.4),则样本提取失败。

bc_settings_streams_limit: 整数 返回后端连接上允许的最大流数。对于 TCP 和 HTTP/1.1 连接,该值始终为 1。对于其他协议,取决于与服务器协商的设置。

bc_src: ip 这是连接在服务器端的源 IP 地址,即 HAProxy 所连接的服务器地址。该字段类型为 IP,适用于 IPv4 和 IPv6 表。在 IPv6 表中,IPv4 地址根据 RFC 4291 映射为其对应的 IPv6 形式。

bc_src_port: integer 返回与连接在服务器端的 TCP 源端口对应的整数值,即 HAProxy 所连接的源端口。

bc_srv_queue: 整数,表示在等待目标服务器连接槽位时,从队列中取出的流数量。这等价于日志格式中的 %sq。

be_id: integer 返回一个整数,表示当前后端的 ID。可在前端的响应中使用,以检查是哪个后端处理了请求。若在前端中使用且未使用后端,则返回当前前端的 ID。该字段也可用于 tcp-check 或 http-check 规则集中。

be_connect_timeout: integer 返回当前后端的连接超时配置值,单位为毫秒。该超时可被“set-timeout”规则覆盖。详见 “cur_connect_timeout”。

be_name: string 返回一个包含当前后端名称的字符串。可在前端中用于响应,以检查是哪个后端处理了请求。若在前端中使用且未使用后端,则返回当前前端的名称。该函数也可用于 tcp-check 或 http-check 规则集中。

be_queue_timeout: integer 返回当前后端队列超时的配置值(单位:毫秒)。该超时可被“set-timeout”规则覆盖。详见 “cur_queue_timeout”。

be_server_timeout: integer 返回当前后端服务器超时的配置值(单位:毫秒)。该超时值可被“set-timeout”规则覆盖。详见 “cur_server_timeout”。

be_tarpit_timeout: integer 返回当前后端队列超时的配置值,单位为毫秒。该超时可被“set-timeout”规则覆盖。详见 “cur_tarpit_timeout”。

be_tunnel_timeout: integer 返回当前后端的隧道超时配置值(单位:毫秒)。该超时可被“set-timeout”规则覆盖。详见 “cur_tunnel_timeout”。

bytes_in: 整数 参见 “req.bytes_in”。

bytes_out: 整数 参见 “res.bytes_in”。

cur_connect_timeout: integer 返回当前流所应用的连接超时时间(单位:毫秒)。默认情况下,该值等于 be_connect_timeout,除非已应用“set-timeout”规则。参见 “be_connect_timeout”。

cur_client_timeout: integer 返回当前流所应用的客户端超时时间(单位:毫秒)。默认情况下,该值等于 fe_client_timeout,除非已应用“set-timeout”规则。参见 “fe_client_timeout”。

cur_queue_timeout: integer 返回当前流所应用的队列超时时间(单位:毫秒)。默认情况下,该值等于 be_queue_timeout,除非已应用“set-timeout”规则。参见 “be_queue_timeout”。

cur_server_timeout: integer 返回当前流所应用的服务器超时时间(单位:毫秒)。默认情况下,该值等于 be_server_timeout,除非已应用“set-timeout”规则。参见 “be_server_timeout”。

cur_tarpit_timeout: integer 返回当前流应用的 tarpit 超时时间(单位:毫秒)。默认情况下,该值等于 fe_tarpit_timeout 或 be_tarpit_timeout,除非已应用“set-timeout”规则。参见 “fe_tarpit_timeout” 和 “be_tarpit_timeout”。

cur_tunnel_timeout: integer 返回当前流所应用的隧道超时时间(单位:毫秒)。默认情况下,该值等于 be_tunnel_timeout,除非已应用“set-timeout”规则。参见 “be_tunnel_timeout”。

dst: ip 这是客户端侧连接的目标 IP 地址,即客户端所连接的地址。任何 tcp/http 规则均可修改此地址。在透明模式下运行时,该字段可能具有实用价值。其类型为 IP,适用于 IPv4 和 IPv6 表。在 IPv6 表中,IPv4 地址根据 RFC 4291 映射为对应的 IPv6 形式。当入站连接经过涉及连接跟踪的地址转换或重定向时,将报告重定向前的原始目标地址。在 Linux 系统上,若设置了 nf_conntrack_tcp_loose sysctl,源地址与目标地址偶尔可能出现颠倒,因为延迟响应可能重新打开已超时的连接,并导致源与目标角色被误判。

dst_conn: integer 返回一个整数值,表示当前在相同套接字上建立的连接数,包括正在评估的连接。该值通常用于 ACL,也可用于将信息传递至服务器的 HTTP 头或日志中。可用于在强制阻断前返回抱歉页面,或在套接字被认为已饱和时,使用特定后端处理新请求。此功能可为不同监听端口或地址分配不同的限制。参见 “fe_conn” 和 “be_conn” 获取。

dst_is_local:boolean 如果入站连接的目标地址是系统本地地址,则返回 true;如果该地址在系统上不存在,表示该连接在透明模式下被拦截,则返回 false。此判断可用于默认对转发流量应用某些规则,而对目标为机器真实地址的流量应用其他规则。例如,统计信息页面可仅在此地址上提供,或 SSH 访问可被本地重定向。请注意,该检查涉及若干系统调用,因此建议每个连接仅执行一次。

dst_port: integer 返回与客户端侧连接的目标 TCP 端口对应的整数值,即客户端所连接的端口。任何 TCP 或 HTTP 规则均可修改此端口。在透明模式下运行时,可用于为整个应用会话动态分配端口,将所有用户绑定至同一服务器,或通过 HTTP 头将目标端口信息传递给服务器。

fc.timer.handshake: 整数 接受 TCP 连接并完成低层协议握手的总时间。当前支持的协议包括 proxy-protocol 和 SSL。此指标等同于日志格式中的 %Th。单位为毫秒(ms)。更多信息请参见 Section 8.4 “Timing events”

fc.timer.total: 整数 代理从接收流到两端均关闭的总持续时间。这等同于日志格式中的 %Tt。单位为毫秒(ms)。更多信息请参见 第 8.4 节 “时间事件”

fc_dst: ip 这是客户端侧连接的原始目标 IP 地址。仅“tcp-request connection”规则可修改此地址。详情请参见“dst”。

fc_dst_is_local: 布尔类型 若入站连接的原始目标地址属于本机系统,则返回 true;若该地址在系统中不存在,则返回 false。详见 “dst_is_local”。

fc_dst_port: 整数 返回与客户端侧连接的原始目标 TCP 端口对应的整数值。仅“tcp-request connection”规则可修改此地址。详情参见“dst-port”。

fc_err: integer 返回当前连接上可能发生的错误的 ID。该获取值为严格正数时,表示连接未成功,并会导致输出错误日志(如 第 8.2.5 节 所述)。有关错误代码及其对应错误信息的完整列表,请参见 “fc_err_str” 获取项。

fc_err_name: string 返回描述前端发生问题的内部错误名称,导致连接失败。该字符串由单个单词组成,当无错误时为空。其对应于 “fc_err_str” 关键字所列表格中的“name”列。

fc_err_str: string 返回描述当前连接发生问题的错误消息,导致连接失败。该字符串对应错误日志格式中的“message”部分(参见 第 8.2.5 节 )。以下是完整的错误码及其对应错误消息列表:

  +----+------------------+-------------------------------------------------------------------------+
  | ID | name             | message                                                                 |
  +----+------------------+-------------------------------------------------------------------------+
  | 0  | -                | "Success"                                                               |
  | 1  | CONF_FDLIM       | "Reached configured maxconn value"                                      |
  | 2  | PROC_FDLIM       | "Too many sockets on the process"                                       |
  | 3  | SYS_FDLIM        | "Too many sockets on the system"                                        |
  | 4  | SYS_MEMLIM       | "Out of system buffers"                                                 |
  | 5  | NOPROTO          | "Protocol or address family not supported"                              |
  | 6  | SOCK_ERR         | "General socket error"                                                  |
  | 7  | PORT_RANGE       | "Source port range exhausted"                                           |
  | 8  | CANT_BIND        | "Can't bind to source address"                                          |
  | 9  | FREE_PORTS       | "Out of local source ports on the system"                               |
  | 10 | ADDR_INUSE       | "Local source address already in use"                                   |
  | 11 | PRX_EMPTY        | "Connection closed while waiting for PROXY protocol header"             |
  | 12 | PRX_ABORT        | "Connection error while waiting for PROXY protocol header"              |
  | 13 | PRX_TIMEOUT      | "Timeout while waiting for PROXY protocol header"                       |
  | 14 | PRX_TRUNCATED    | "Truncated PROXY protocol header received"                              |
  | 15 | PRX_NOT_HDR      | "Received something which does not look like a PROXY protocol header"   |
  | 16 | PRX_BAD_HDR      | "Received an invalid PROXY protocol header"                             |
  | 17 | PRX_BAD_PROTO    | "Received an unhandled protocol in the PROXY protocol header"           |
  | 18 | CIP_EMPTY        | "Connection closed while waiting for NetScaler Client IP header"        |
  | 19 | CIP_ABORT        | "Connection error while waiting for NetScaler Client IP header"         |
  | 20 | CIP_TIMEOUT      | "Timeout while waiting for a NetScaler Client IP header"                |
  | 21 | CIP_TRUNCATED    | "Truncated NetScaler Client IP header received"                         |
  | 22 | CIP_BAD_MAGIC    | "Received an invalid NetScaler Client IP magic number"                  |
  | 23 | CIP_BAD_PROTO    | "Received an unhandled protocol in the NetScaler Client IP header"      |
  | 24 | SSL_EMPTY        | "Connection closed during SSL handshake"                                |
  | 25 | SSL_ABORT        | "Connection error during SSL handshake"                                 |
  | 26 | SSL_TIMEOUT      | "Timeout during SSL handshake"                                          |
  | 27 | SSL_TOO_MANY     | "Too many SSL connections"                                              |
  | 28 | SSL_NO_MEM       | "Out of memory when initializing an SSL connection"                     |
  | 29 | SSL_RENEG        | "Rejected a client-initiated SSL renegotiation attempt"                 |
  | 30 | SSL_CA_FAIL      | "SSL client CA chain cannot be verified"                                |
  | 31 | SSL_CRT_FAIL     | "SSL client certificate not trusted"                                    |
  | 32 | SSL_MISMATCH     | "Server presented an SSL certificate different from the configured one" |
  | 33 | SSL_MISMATCH_SNI | "Server presented an SSL certificate different from the expected one"   |
  | 34 | SSL_HANDSHAKE    | "SSL handshake failure"                                                 |
  | 35 | SSL_HANDSHAKE_HB | "SSL handshake failure after heartbeat"                                 |
  | 36 | SSL_KILLED_HB    | "Stopped a TLSv1 heartbeat attack (CVE-2014-0160)"                      |
  | 37 | SSL_NO_TARGET    | "Attempt to use SSL on an unknown target (internal error)"              |
  | 38 | SSL_EARLY_FAILED | "Server refused early data"                                             |
  | 39 | SOCKS4_SEND      | "SOCKS4 Proxy write error during handshake"                             |
  | 40 | SOCKS4_RECV      | "SOCKS4 Proxy read error during handshake"                              |
  | 41 | SOCKS4_DENY      | "SOCKS4 Proxy deny the request"                                         |
  | 42 | SOCKS4_ABORT     | "SOCKS4 Proxy handshake aborted by server"                              |
  | 43 | SSL_FATAL        | "SSL fatal error"                                                       |
  | 44 | REVERSE          | "Reverse connect failure"                                               |
  | 45 | POLLERR          | "Poller reported POLLERR"                                               |
  | 46 | EREFUSED         | "ECONNREFUSED returned by OS"                                           |
  | 47 | ERESET           | "ECONNRESET returned by OS"                                             |
  | 48 | EUNREACH         | "ENETUNREACH returned by OS"                                            |
  | 49 | ENOMEM           | "ENOMEM returned by OS"                                                 |
  | 50 | EBADF            | "EBADF returned by OS"                                                  |
  | 51 | EFAULT           | "EFAULT returned by OS"                                                 |
  | 52 | EINVAL           | "EINVAL returned by OS"                                                 |
  | 53 | ENCONN           | "ENCONN returned by OS"                                                 |
  | 54 | ENSOCK           | "ENSOCK returned by OS"                                                 |
  | 55 | ENOBUFS          | "ENOBUFS returned by OS"                                                |
  | 56 | EPIPE            | "EPIPE returned by OS"                                                  |
  +----+------------------+-------------------------------------------------------------------------+

fc_fackets: integer 返回内核为客户端连接测量的 fack 计数器值。如果服务器连接未建立、连接不是 TCP 类型,或操作系统不支持 TCP_INFO(例如 2.4 版本之前的 Linux 内核),则样本提取失败。

fc_glitches: integer 返回前端连接上计数的协议异常数量。 这些异常通常涵盖协议违规行为,以及可能表明存在伪造或行为异常的客户端的小型异常,例如日志中错误过多,或大量连接过早被中止,导致频繁的 TLS 重协商。这些异常也可能由过大无法容纳于单个缓冲区的请求引起,从而导致 HTTP 400 错误。 理想情况下,该数值应保持为零,尽管某些浏览器在试探协议边界时偶尔触发该计数也属可能。通常情况下,此类数值不应被视为警报(尤其是数值较小时),但突然的大幅增长可能表明存在异常。若数值较大(例如每连接数百至数千次,或与请求数量相当),则可能表明存在专门设计的客户端,正在尝试探测或攻击协议栈。并非所有协议多路复用器都测量此指标,若需获取事件的更多详情,应启用追踪以捕获所有交互。

fc_http_major: integer 报告前端连接的 HTTP 主版本编码,可能为 1(表示 HTTP/0.9 至 HTTP/1.1)或 2(表示 HTTP/2)。请注意,该值基于网络传输编码,而非请求头中所含的版本。

fc_lost: 整数 若连接不是 TCP 或 QUIC,样本提取失败。 对于 QUIC,返回客户端连接丢失的 QUIC 数据包数量。 对于 TCP,返回内核为客户端连接测量的丢失计数。 若服务器连接未建立,或操作系统不支持 TCP_INFO(例如 2.4 版本之前的 Linux 内核),样本提取失败。

fc_nb_streams: 整数 返回前端连接上打开的流的数量。

fc_pp_authority: 字符串 返回客户端在 PROXY 协议中发送的第一个 authority TLV,若存在。

fc_pp_tlv(<id>): string

fc_pp_tlv(<id>): string

返回指定 TLV ID 对应的 TLV 值。ID 必须为 0 到 255 之间的数值,或以下支持的符号名称之一,这些名称对应 PPv2 规范中的 TLV 常量后缀:“ALPN”: PP2_TYPE_ALPN, “AUTHORITY”: PP2_TYPE_AUTHORITY, “CRC32”: PP2_TYPE_CRC32C, “NETNS”: PP2_TYPE_NETNS, “NOOP”: PP2_TYPE_NOOP, “SSL”: PP2_TYPE_SSL, “SSL_CIPHER”: PP2_SUBTYPE_SSL_CIPHER, “SSL_CN”: PP2_SUBTYPE_SSL_CN, “SSL_KEY_ALG”: PP2_SUBTYPE_SSL_KEY_ALG, “SSL_SIG_ALG”: PP2_SUBTYPE_SSL_SIG_ALG, “SSL_VERSION”: PP2_SUBTYPE_SSL_VERSION, “UNIQUE_ID”: PP2_TYPE_UNIQUE_ID。

接收的值必须小于或等于 1024 字节。此举旨在防止潜在的拒绝服务(DoS)攻击。小于或等于 256 字节的值可被内存池化。因此,为获得最佳性能,建议将发送值的长度限制在 256 字节以内。

请注意,与 fc_pp_authority 和 fc_pp_unique_id 不同,fc_pp_tlv 可以在存在重复 TLV ID 的情况下遍历所有匹配的 TLV。遍历顺序与 PROXY 协议头中的位置一致。然而,应尽量避免依赖重复的 TLV,因为 TLV 通常被视为唯一。通常情况下,发现重复的 TLV ID 表明 PROXY 协议头的发送方存在错误。

fc_pp_unique_id: string 返回客户端在 PROXY 协议中发送的第一个唯一 ID TLV,若有。

fc_rcvd_proxy: boolean 若客户端通过 PROXY 协议发起连接,则返回 true。

fc_reordering: 整数 若连接不是 TCP 或 QUIC,样本提取失败。对于 QUIC,返回客户端连接的 QUIC 重排序数据包数量。对于 TCP,返回内核测量的客户端连接的重排序计数器。若服务器连接未建立,或操作系统不支持 TCP_INFO(例如 2.4 版本之前的 Linux 内核),样本提取失败。

fc_retrans: integer 返回内核为客户端连接测量的重传次数。如果服务器连接未建立、连接不是 TCP 类型,或操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。

fc_rtt(<unit>): integer

fc_rtt(<unit>): integer

如果连接不是 TCP 或 QUIC,则样本提取失败。对于 QUIC,返回客户端连接的平滑往返时间。对于 TCP,返回内核测量的客户端连接的往返时间(RTT)。<unit> 为可选项,默认单位为毫秒。<unit> 可设置为 “ms” 表示毫秒,或 “us” 表示微秒。如果服务器连接未建立,或操作系统不支持 TCP_INFO(例如 Linux 内核版本早于 2.4),则样本提取失败。

fc_rttvar(<unit>): integer

fc_rttvar(<unit>): integer

如果连接不是 TCP 或 QUIC,则样本提取失败。对于 QUIC,返回客户端连接的平滑往返时间方差。对于 TCP,返回内核测量的客户端连接的往返时间(RTT)方差。<unit> 为可选参数,默认单位为毫秒。<unit> 可设置为 “ms” 表示毫秒,或 “us” 表示微秒。如果服务器连接未建立,或操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。

fc_sacked: 整数 返回由内核测量的客户端连接的丢弃计数器值。如果服务器连接未建立、连接不是 TCP 类型,或操作系统不支持 TCP_INFO(例如,Linux 内核版本早于 2.4),则样本提取失败。

fc_saved_syn: binary 返回系统在建立入站连接过程中保存的 SYN 数据包副本。这要求“bind”行中包含“tcp-ss”选项,且运行的 Linux 内核版本不低于 4.3。当“tcp-ss”设置为 1 时,仅包含 IP 和 TCP 头。当“tcp-ss”设置为 2 时,IP 头之前还包含以太网头,可用于控制或记录源 MAC 地址或 VLAN 等信息。请注意,系统不保证一定会保存 SYN 数据包。例如,若使用 SYN Cookie 机制,SYN 数据包不会被保存,连接将在匹配的 ACK 数据包上建立。此外,系统不保证在首次读取后仍保留该副本。因此,强烈建议在“tcp-request connection”规则中将该样本复制到“sess”作用域的变量中,并仅使用该变量进行后续操作。值得注意的是,在环回接口上,系统会构造一个 14 字节的虚拟以太网头,其中源地址和目的地址均为零,仅协议字段被设置。在调试过程中,可方便地使用“hex”转换器将此类样本转换为十六进制格式。示例(字段手动分隔并注释如下):

frontend test
    mode http
    bind:::4445 tcp-ss 2
    tcp-request connection set-var(sess.syn) fc_saved_syn
    http-request return status 200 content-type text/plain \
                 lf-string "%[var(sess.syn),hex]\n"

$ curl '0:4445'
000000000000 000000000000 0800 \  # MAC_DST MAC_SRC PROTO=IPv4
4500003C0A65400040063255       \  # IPv4 header, proto=6 (TCP)
7F000001 7F000001              \  # IP_SRC=127.0.0.1 IP_DST=127.0.0.1
E1F2 115D 01AF4E3E 00000000    \  # TCP_SPORT=57842 TCP_DPORT=4445, SEQ
A0 02 FFD7 FE300000            \  # OPT_LEN=20 TCP_FLAGS=SYN WIN=65495
0204FFD70402080A01C2A71A0000000001030307 # MSS=65495, TS, SACK, WSCALE 7

$ curl '[::1]:4445'
000000000000 000000000000 86DD   \ # MAC_DST MAC_SRC PROTO=IPv6
6008018F00280640                 \ # IPv6 header, proto=6 (TCP)
00000000000000000000000000000001 \ # SRC=::1
00000000000000000000000000000001 \ # DST=::1
9758 115D B5511F5D 00000000      \ # TCP_SPORT=38744 TCP_DPORT=4445, SEQ
A0 02 FFC4 00300000              \  # OPT_LEN=20 TCP_FLAGS=SYN WIN=65476
0204FFC40402080A9C231D680000000001030307 # MSS=65476, TS, SACK, WSCALE 7

“bytes()” 转换器有助于从数据包中提取特定字段。be2dec() 也允许读取数据块并以整数形式输出。如需更精确的提取,请参阅 “eth.XXX” 转换器。

IPv4 输入示例:

frontend test
    mode http
    bind:4445 tcp-ss 2
    tcp-request connection set-var(sess.syn) fc_saved_syn
    http-request return status 200 content-type text/plain lf-string \
                 "mac_dst=%[var(sess.syn),eth.dst,hex] \
                  mac_src=%[var(sess.syn),eth.src,hex] \
                  proto=%[var(sess.syn),eth.proto,bytes(6),be2hex(,2)] \
                  ipv4h=%[var(sess.syn),eth.data,bytes(0,12),hex] \
                  ipv4_src=%[var(sess.syn),eth.data,ip.src] \
                  ipv4_dst=%[var(sess.syn),eth.data,ip.dst] \
                  tcp_spt=%[var(sess.syn),eth.data,ip.data,tcp.src] \
                  tcp_dpt=%[var(sess.syn),eth.data,ip.data,tcp.dst] \
                  tcp_win=%[var(sess.syn),eth.data,ip.data,tcp.win] \
                  tcp_opt=%[var(sess.syn),eth.data,ip.data,bytes(20),hex]\n"

$ curl '0:4445'
mac_dst=000000000000 mac_src=000000000000 proto=0800 \
ipv4h=4500003CC9B7400040067302 ipv4_src=127.0.0.1 ipv4_dst=127.0.0.1 \
tcp_spt=43970 tcp_dpt=4445 tcp_win=65495 \
tcp_opt=0204FFD70402080A01DC0D410000000001030307

另请参见 “set-var” 动作,以及 “be2dec”、“bytes”、“hex”、“eth.XXX”、“ip.XXX” 和 “tcp.XXX” 转换器。

fc_settings_streams_limit: 整数 返回前端连接上允许的最大流数。对于 TCP 和 HTTP/1.1 连接,该值始终为 1。对于其他协议,取决于与客户端协商的设置。

fc_src: ip 这是连接在客户端一侧的原始源 IP 地址。仅“tcp-request connection”规则可修改此地址。详情参见“src”。

fc_src_is_local: 布尔值 用于判断传入连接的源地址是否为系统本地地址,若源地址在系统中不存在则返回 false。详情请参见 “src_is_local”。

fc_src_port: integer 返回与客户端侧连接的 TCP 源端口相对应的整数值。仅“tcp-request connection”规则可修改此地址。详情参见“src-port”。

fc_unacked: 整数 返回由内核测量的客户端连接的未确认(unacked)计数器值。 若服务器连接未建立、连接非 TCP 协议,或操作系统不支持 TCP_INFO(例如 2.4 版本之前的 Linux 内核),则样本提取失败。

fe_client_timeout: integer 返回当前前端客户端超时的配置值,单位为毫秒。该超时值可被“set-timeout”规则覆盖。

fe_defbe: string 返回一个字符串,其中包含前端的默认后端名称。可在前端中使用,以检查请求默认将由哪个后端处理。

fe_id: integer 返回一个整数,其中包含当前前端的 ID。该值可在后端中使用,以检查请求源自哪个前端,或用于将通过同一前端访问的全部用户绑定到同一台服务器。

fe_name: string 返回一个包含当前前端名称的字符串。可在后端中使用,以检查其调用来源的前端,或确保通过同一前端访问的所有用户被绑定到同一台服务器。

fe_tarpit_timeout: integer 返回当前前端的 tarpit 超时配置值,单位为毫秒。该超时可被“set-timeout”规则覆盖。

req.bytes_in: integer 此值返回从客户端接收的字节数。该数值对应 HAProxy 实际接收到的数据量,包括部分头信息和内部编码开销。请求压缩不会影响此处报告的数值。

req.bytes_out: 整数 此值返回发送至服务器的字节数。该数值对应 HAProxy 实际发送的数据量,包括部分头信息和内部编码开销。请求压缩会影响此处报告的数值。

res.bytes_in: 整数 此值返回从服务器接收到的字节数。该数值对应 HAProxy 实际接收到的数据量,包括部分头信息和内部编码开销。响应压缩不会影响此处报告的数值。

res.bytes_out: integer 此值返回发送给客户端的字节数。该数值对应 HAProxy 发送的数据量,包括部分头信息和内部编码开销。响应压缩会影响此处报告的数值。

res.timer.data: integer,表示响应负载的总传输时间,直至最后一个字节发送至客户端。在 HTTP 中,该时间从最后一个响应头之后(即 Tr 之后)开始计算。此值等同于日志格式中的 %Td,单位为毫秒(ms)。更多信息请参见 第 8.4 节 “时间事件”

sc_bytes_in_rate(<ctr>[,<table>]): integer

sc_bytes_in_rate(<ctr>[,<table>]): integer
sc0_bytes_in_rate([<table>]): integer
sc1_bytes_in_rate([<table>]): integer
sc2_bytes_in_rate([<table>]): integer

返回当前跟踪计数器的客户端到服务器字节速率平均值,单位为字节/周期,周期长度由表中配置的值决定。参见 “table_bytes_in_rate”。

sc_bytes_out_rate(<ctr>[,<table>]): integer

sc_bytes_out_rate(<ctr>[,<table>]): integer
sc0_bytes_out_rate([<table>]): integer
sc1_bytes_out_rate([<table>]): integer
sc2_bytes_out_rate([<table>]): integer

返回当前跟踪计数器的平均服务器到客户端字节速率,单位为字节,按表中配置的周期计算。另请参见 “table_bytes_out_rate”。

sc_clr_gpc(<idx>,<ctr>[,<table>]): integer

sc_clr_gpc(<idx>,<ctr>[,<table>]): integer

清除当前代理的粘性表中指定 ID <ctr> 的跟踪计数器关联数组在索引 <idx> 处的通用计数器值,或从指定的粘性表 <table> 中清除,并返回其先前值。<idx> 为 0 至 99 之间的整数,<ctr> 为 0 至 2 之间的整数。首次调用前,存储值为零,因此首次调用将始终返回零。此获取操作仅适用于 ‘gpc’ 数组 data_type(不适用于旧版 ‘gpc0’ 或 ‘gpc1’ data_type)。

sc_clr_gpc0(<ctr>[,<table>]): integer

sc_clr_gpc0(<ctr>[,<table>]): integer
sc0_clr_gpc0([<table>]): integer
sc1_clr_gpc0([<table>]): integer
sc2_clr_gpc0([<table>]): integer

清除当前跟踪计数器关联的第一个通用计数器,并返回其先前的值。首次调用前,存储的值为零,因此首次调用将始终返回零。通常作为表达式中的第二个 ACL 使用,以便在第一个 ACL 验证通过时标记连接:

示例:

# block if 5 consecutive requests continue to come faster than 10 sess
# per second, and reset the counter as soon as the traffic slows down.
acl abuse sc0_http_req_rate gt 10
acl kill  sc0_inc_gpc0 gt 5
acl save  sc0_clr_gpc0 ge 0
tcp-request connection accept if !abuse save
tcp-request connection reject if abuse kill

sc_clr_gpc1(<ctr>[,<table>]): integer

sc_clr_gpc1(<ctr>[,<table>]): integer
sc0_clr_gpc1([<table>]): integer
sc1_clr_gpc1([<table>]): integer
sc2_clr_gpc1([<table>]): integer

清除与当前跟踪计数器关联的第二个通用计数器,并返回其先前的值。首次调用前,存储的值为零,因此首次调用将始终返回零。通常用作表达式中的第二个 ACL,以便在第一个 ACL 验证通过时标记连接。

sc_conn_cnt(<ctr>[,<table>]): integer

sc_conn_cnt(<ctr>[,<table>]): integer
sc0_conn_cnt([<table>]): integer
sc1_conn_cnt([<table>]): integer
sc2_conn_cnt([<table>]): integer

返回当前跟踪计数器中累计的入站连接数量。另请参见 “table_conn_cnt”。

sc_conn_cur(<ctr>[,<table>]): integer

sc_conn_cur(<ctr>[,<table>]): integer
sc0_conn_cur([<table>]): integer
sc1_conn_cur([<table>]): integer
sc2_conn_cur([<table>]): integer

返回当前正在跟踪相同计数器的并发连接数量。该数值在开始跟踪时自动递增,在停止跟踪时自动递减。另请参见 “table_conn_cur”。

sc_conn_rate(<ctr>[,<table>]): integer

sc_conn_rate(<ctr>[,<table>]): integer
sc0_conn_rate([<table>]): integer
sc1_conn_rate([<table>]): integer
sc2_conn_rate([<table>]): integer

返回当前跟踪计数器的平均连接速率,单位为表格中配置周期内的连接数量。参见 “table_conn_rate”。

sc_get_gpc(<idx>,<ctr>[,<table>]): integer

sc_get_gpc(<idx>,<ctr>[,<table>]): integer

返回代理中索引 <idx> 处的通用计数器(GPC)数组值,该值与当前代理的 stick-table 中 ID <ctr> 的跟踪计数器,或指定 stick-table <table> 关联。<idx> 为 0 至 99 之间的整数,<ctr> 为 0 至 2 之间的整数。若该索引处未存储 gpc 值,则返回零。此获取操作仅适用于 ‘gpc’ 数组数据类型(不适用于旧版 ‘gpc0’ 或 ‘gpc1’ 数据类型)。参见 “table_gpc” 和 “sc_inc_gpc”。

sc_get_gpc0(<ctr>[,<table>]): integer

sc_get_gpc0(<ctr>[,<table>]): integer
sc0_get_gpc0([<table>]): integer
sc1_get_gpc0([<table>]): integer
sc2_get_gpc0([<table>]): integer

返回当前跟踪计数器关联的第一个通用计数器的值。 另请参阅 “table_gpc0” 和 sc/sc0/sc1/sc2_inc_gpc0。

sc_get_gpc1(<ctr>[,<table>]): integer

sc_get_gpc1(<ctr>[,<table>]): integer
sc0_get_gpc1([<table>]): integer
sc1_get_gpc1([<table>]): integer
sc2_get_gpc1([<table>]): integer

返回当前跟踪计数器关联的第二个通用计数器的值。参见 “table_gpc1” 和 sc/sc0/sc1/sc2_inc_gpc1。

sc_get_gpt(<idx>,<ctr>[,<table>]): integer

sc_get_gpt(<idx>,<ctr>[,<table>]): integer

返回索引 <idx> 处与 ID <ctr> 关联的计数器跟踪数组中第一个通用标签(GPT)的值,该值来自当前代理的 stick-table 或指定的 stick-table <table>。<idx> 为 0 至 99 之间的整数,<ctr> 为 0 至 2 之间的整数。若该索引处未存储 GPT,则返回零。此获取操作仅适用于 ‘gpt’ 数组数据类型(不适用于旧版 ‘gpt0’ 数据类型)。参见 “table_gpt”。

sc_get_gpt0(<ctr>[,<table>]): integer

sc_get_gpt0(<ctr>[,<table>]): integer
sc0_get_gpt0([<table>]): integer
sc1_get_gpt0([<table>]): integer
sc2_get_gpt0([<table>]): integer

返回当前跟踪计数器关联的第一个通用标签的值。参见 “table_gpt0”。

sc_glitch_cnt(<ctr>[,<table>]): integer

sc_glitch_cnt(<ctr>[,<table>]): integer
sc0_glitch_cnt([<table>]): integer
sc1_glitch_cnt([<table>]): integer
sc2_glitch_cnt([<table>]): integer

返回当前跟踪计数器关联的前端连接中观察到的累积连接异常次数。通常,这些异常会导致请求或连接被中止,因此返回的数值通常对应于过去的连接。该值并无好坏之分,但质量较差的客户端可能每连接偶尔引发数次异常,而极不正常或恶意的客户端可能在短时间内导致单个连接上累计数千次事件。有关当前连接受影响的异常数量,请参见 fc_glitches;按源地址查询异常次数,请参见 src_glitch_cnt;有关事件发生率的度量,请参见 sc_glitch_rate。

sc_glitch_rate(<ctr>[,<table>]): integer

sc_glitch_rate(<ctr>[,<table>]): integer
sc0_glitch_rate([<table>]): integer
sc1_glitch_rate([<table>]): integer
sc2_glitch_rate([<table>]): integer

返回当前跟踪计数器期间,前端连接异常事件的平均发生速率,单位为配置表中设定周期内的事件数量。通常此类异常会导致请求或连接被中止,因此返回的值通常与历史连接相关。该值并无好坏之分,但质量较差的客户端可能每连接偶尔引发数次异常,故通常预期该速率为较低水平。然而,极不正常或恶意的客户端可能在每连接中迅速引发数千次事件,从而维持较高的速率。参见 “table_glitch_rate” 和 “sc_glitch_cnt”。

sc_gpc_rate(<idx>,<ctr>[,<table>]): integer

sc_gpc_rate(<idx>,<ctr>[,<table>]): integer

返回当前代理的表或指定 stick-table <table> 中,ID <ctr> 关联的跟踪计数器数组中索引 <idx> 处的通用计数器(General Purpose Counter)的平均增量速率。该值报告了在配置周期内 gpc 计数器被增量的频率。<idx> 为 0 至 99 之间的整数,<ctr> 为 0 至 2 之间的整数。请注意,‘gpc_rate’ 计数器数组必须存储在 stick-table 中才会有返回值,因为 ‘gpc’ 仅保存事件计数。此获取操作仅适用于 ‘gpc_rate’ 数组 data_type(不适用于旧版 ‘gpc0_rate’ 及 ‘gpc1_rate’ data_type)。另见 “table_gpc_rate”、“sc_get_gpc” 和 “sc_inc_gpc”。

sc_gpc0_rate(<ctr>[,<table>]): integer

sc_gpc0_rate(<ctr>[,<table>]): integer
sc0_gpc0_rate([<table>]): integer
sc1_gpc0_rate([<table>]): integer
sc2_gpc0_rate([<table>]): integer

返回与当前跟踪计数器关联的第一个通用计数器(General Purpose Counter)的平均增量速率。该值报告了在配置周期内 gpc0 计数器的增量频率。参见 src_gpc0_rate、sc/sc0/sc1/sc2_get_gpc0 以及 sc/sc0/sc1/sc2_inc_gpc0。

请注意,“gpc0_rate” 计数器必须存储在 stick-table 中,才会有返回值,因为 “gpc0” 仅保存事件计数。

sc_gpc1_rate(<ctr>[,<table>]): integer

sc_gpc1_rate(<ctr>[,<table>]): integer
sc0_gpc1_rate([<table>]): integer
sc1_gpc1_rate([<table>]): integer
sc2_gpc1_rate([<table>]): integer

返回与当前跟踪计数器关联的第二个通用计数器的平均增量速率。该指标报告在配置周期内 gpc1 计数器的增量频率。参见 src_gpcA_rate、sc/sc0/sc1/sc2_get_gpc1 和 sc/sc0/sc1/sc2_inc_gpc1。

请注意,“gpc1_rate” 计数器必须存储在 stick-table 中,才会有返回值,因为 “gpc1” 仅保存事件计数。

sc_http_err_cnt(<ctr>[,<table>]): integer

sc_http_err_cnt(<ctr>[,<table>]): integer
sc0_http_err_cnt([<table>]): integer
sc1_http_err_cnt([<table>]): integer
sc2_http_err_cnt([<table>]): integer

返回当前跟踪计数器的累计 HTTP 错误数量。该数值包含请求错误以及 4xx 错误响应。另请参见 “table_http_err_cnt”。

sc_http_err_rate(<ctr>[,<table>]): integer

sc_http_err_rate(<ctr>[,<table>]): integer
sc0_http_err_rate([<table>]): integer
sc1_http_err_rate([<table>]): integer
sc2_http_err_rate([<table>]): integer

返回当前跟踪计数器的 HTTP 错误平均速率,单位为配置表中设定周期内的错误数量。该指标包含请求错误和 4xx 错误响应。参见 src_http_err_rate。

sc_http_fail_cnt(<ctr>[,<table>]): integer

sc_http_fail_cnt(<ctr>[,<table>]): integer
sc0_http_fail_cnt([<table>]): integer
sc1_http_fail_cnt([<table>]): integer
sc2_http_fail_cnt([<table>]): integer

返回当前跟踪计数器累计的 HTTP 响应失败次数。这包括响应错误以及除 501 和 505 以外的所有 5xx 状态码。另请参阅 “table_http_fail_cnt”。

sc_http_fail_rate(<ctr>[,<table>]): integer

sc_http_fail_rate(<ctr>[,<table>]): integer
sc0_http_fail_rate([<table>]): integer
sc1_http_fail_rate([<table>]): integer
sc2_http_fail_rate([<table>]): integer

返回当前跟踪计数器的 HTTP 响应失败平均速率,单位为配置表中设定周期内的失败次数。该指标包含响应错误以及除 501 和 505 以外的所有 5xx 状态码。参见 “table_http_fail_rate”。

sc_http_req_cnt(<ctr>[,<table>]): integer

sc_http_req_cnt(<ctr>[,<table>]): integer
sc0_http_req_cnt([<table>]): integer
sc1_http_req_cnt([<table>]): integer
sc2_http_req_cnt([<table>]): integer

返回当前跟踪计数器累计的 HTTP 请求数。包括所有已启动的请求,无论是否有效。参见 src_http_req_cnt。

sc_http_req_rate(<ctr>[,<table>]): integer

sc_http_req_rate(<ctr>[,<table>]): integer
sc0_http_req_rate([<table>]): integer
sc1_http_req_rate([<table>]): integer
sc2_http_req_rate([<table>]): integer

返回当前跟踪计数器的 HTTP 请求平均速率,单位为每周期内的请求数量,该周期由表中配置的值决定。此值包含所有已启动的请求,无论其是否有效。 参见 src_http_req_rate。

sc_inc_gpc(<idx>,<ctr>[,<table>]): integer

sc_inc_gpc(<idx>,<ctr>[,<table>]): integer

将指定 ID <ctr> 的跟踪计数器关联的数组中索引 <idx> 处的通用计数器值递增,并返回其新值。该操作可从当前代理的粘性表或指定的粘性表 <table> 中执行。<idx> 为 0 至 99 之间的整数,<ctr> 为 0 至 2 之间的整数。首次调用前,存储值为零,因此首次调用将使其增至 1 并返回 1。此获取操作仅适用于 ‘gpc’ 数组 data_type(不适用于旧版 ‘gpc0’ 或 ‘gpc1’ data_type)。

sc_inc_gpc0(<ctr>[,<table>]): integer

sc_inc_gpc0(<ctr>[,<table>]): integer
sc0_inc_gpc0([<table>]): integer
sc1_inc_gpc0([<table>]): integer
sc2_inc_gpc0([<table>]): integer

递增与当前跟踪计数器关联的第一个通用计数器,并返回其新值。首次调用前,存储的值为零,因此首次调用将使其增至 1,并返回 1。通常作为表达式中的第二个 ACL 使用,以便在第一个 ACL 验证通过时标记连接:

示例:

acl abuse sc0_http_req_rate gt 10
acl kill  sc0_inc_gpc0 gt 0
tcp-request connection reject if abuse kill

sc_inc_gpc1(<ctr>[,<table>]): integer

sc_inc_gpc1(<ctr>[,<table>]): integer
sc0_inc_gpc1([<table>]): integer
sc1_inc_gpc1([<table>]): integer
sc2_inc_gpc1([<table>]): integer

递增与当前跟踪计数器关联的第二个通用计数器,并返回其新值。首次调用前,存储值为零,因此首次调用将使其增至 1,并返回 1。通常在表达式中作为第二个 ACL 使用,以便在第一个 ACL 验证通过时标记连接。

sc_kbytes_in(<ctr>[,<table>]): integer

sc_kbytes_in(<ctr>[,<table>]): integer
sc0_kbytes_in([<table>]): integer
sc1_kbytes_in([<table>]): integer
sc2_kbytes_in([<table>]): integer

返回当前跟踪计数器中客户端到服务器的数据总量,单位为千字节。测试当前基于 32 位整数执行,这将数值上限限制为 4 太字节。参见 “table_kbytes_in”。

sc_kbytes_out(<ctr>[,<table>]): integer

sc_kbytes_out(<ctr>[,<table>]): integer
sc0_kbytes_out([<table>]): integer
sc1_kbytes_out([<table>]): integer
sc2_kbytes_out([<table>]): integer

返回当前跟踪计数器中服务器到客户端的数据总量,单位为千字节。测试当前基于 32 位整数执行,因此数值上限为 4 太字节。参见 “table_kbytes_out”。

sc_key(<ctr>): any sc0_key: any sc1_key: any sc2_key: any 返回用于匹配当前跟踪计数器的键。

sc_sess_cnt(<ctr>[,<table>]): integer

sc_sess_cnt(<ctr>[,<table>]): integer
sc0_sess_cnt([<table>]): integer
sc1_sess_cnt([<table>]): integer
sc2_sess_cnt([<table>]): integer

返回从当前跟踪计数器中累计的已转换为会话的入站连接数量,即被“tcp-request connection”规则接受的连接。后端记录的会话数可能多于连接数,因为若客户端与后端之间通过 HTTP 持久连接进行通信,单个连接可能产生多个后端会话。参见 “table_sess_cnt”。

sc_sess_rate(<ctr>[,<table>]): integer

sc_sess_rate(<ctr>[,<table>]): integer
sc0_sess_rate([<table>]): integer
sc1_sess_rate([<table>]): integer
sc2_sess_rate([<table>]): integer

返回当前跟踪计数器的平均会话速率,单位为表格中配置周期内的会话数量。会话指成功通过早期“tcp-request connection”规则的连接。后端统计的会话数可能多于连接数,因为若客户端与后端之间通过连接执行了部分 HTTP 持久连接,单个连接可产生多个后端会话。参见 “table_sess_rate”。

sc_tracked(<ctr>[,<table>]): boolean

sc_tracked(<ctr>[,<table>]): boolean
sc0_tracked([<table>]): boolean
sc1_tracked([<table>]): boolean
sc2_tracked([<table>]): boolean

如果当前会话正在跟踪指定的会话计数器,则返回 true。 这在决定是否将某些值设置到传递给服务器的头中时可能有用。

sc_trackers(<ctr>[,<table>]): integer

sc_trackers(<ctr>[,<table>]): integer
sc0_trackers([<table>]): integer
sc1_trackers([<table>]): integer
sc2_trackers([<table>]): integer

返回当前正在跟踪相同计数器的并发连接数量。当开始跟踪时,该数值自动递增;当停止跟踪时,自动递减。与 sc0_conn_cur 不同,它不依赖任何存储信息,而是基于表的引用计数(即 CLI 中 “show table” 命令返回的“use”值)。在某些情况下,该值更适合用于七层跟踪。例如,可用于告知服务器来自特定地址的并发连接数量。

so_id: integer 返回一个整数,其中包含当前监听套接字的 ID。在涉及多个“bind”指令的前端中,或需将通过同一套接字连接的所有用户绑定到同一服务器时,该值非常有用。

so_name: string 返回一个字符串,其中包含当前监听套接字的名称,该名称由 “bind” 行上的 name 参数定义。其用途与 so_id 相同,但使用字符串而非整数。

src: ip 这是会话中客户端的源地址。任意 TCP 或 HTTP 规则均可修改此地址。该字段类型为 IP,适用于 IPv4 和 IPv6 表。在 IPv6 表中,IPv4 地址根据 RFC 4291 映射为对应的 IPv6 地址。请注意,使用的是 TCP 层的源地址,而非位于代理后的客户端地址。然而,若使用了 “accept-proxy” 或 “accept-netscaler-cip” 绑定指令,则对于除 “tcp-request connection” 以外的所有规则集,该地址可为位于另一兼容 PROXY 协议组件后的客户端地址。当入站连接经过涉及连接跟踪的地址转换或重定向时,将报告重定向前的原始目标地址。在 Linux 系统上,若设置了 nf_conntrack_tcp_loose sysctl,源地址与目标地址偶尔可能出现颠倒,因为延迟响应可能重新打开已超时的连接,并导致源与目标角色互换。

示例:

# add an HTTP header in requests with the originating address' country
http-request set-header X-Country %[src,map_ip(geoip.lst)]

src_bytes_in_rate([<table>]): integer

src_bytes_in_rate([<table>]): integer

与 “table_bytes_in_rate” 转换器相同,但键设置为传入连接的源地址。

等价于:src, table_bytes_in_rate([<table>])

src_bytes_out_rate([<table>]): integer

src_bytes_out_rate([<table>]): integer

与 “table_bytes_out_rate” 转换器相同,但键设置为传入连接的源地址。

等价于:src, table_bytes_out_rate([<table>])

src_clr_gpc(<idx>[,<table>]): integer

src_clr_gpc(<idx>[,<table>]): integer

与 “table_clr_gpc” 转换器相同,但键设置为传入连接的源地址。

等价于:src, table_clr_gpc(<idx>[,<table>])

src_clr_gpc0([<table>]): integer

src_clr_gpc0([<table>]): integer

与 “table_clr_gpc0” 转换器相同,但键设置为传入连接的源地址。

等价于:src, table_clr_gpc0([<table>])

src_clr_gpc1([<table>]): integer

src_clr_gpc1([<table>]): integer

与 “table_clr_gpc1” 转换器相同,但键设置为入站连接的源地址。

等价于:src, table_clr_gpc1([<table>])

src_conn_cnt([<table>]): integer

src_conn_cnt([<table>]): integer

与 “table_conn_cnt” 转换器相同,但键设置为传入连接的源地址。

等价于:src, table_conn_cnt([<table>])

src_conn_cur([<table>]): integer

src_conn_cur([<table>]): integer

与 “table_conn_cur” 转换器相同,但键设置为入站连接的源地址。

等价于:src, table_conn_cur([<table>])

src_conn_rate([<table>]): integer

src_conn_rate([<table>]): integer

与 “table_conn_rate” 转换器相同,但键设置为传入连接的源地址。

等价于:src, table_conn_rate([<table>])

src_get_gpc(<idx>[,<table>]): integer

src_get_gpc(<idx>[,<table>]): integer

与 “table_gpc” 转换器相同,但键设置为传入连接的源地址。

等价于:src, table_gpc(<idx>[,<table>])

src_get_gpc0([<table>]): integer

src_get_gpc0([<table>]): integer

与 “table_gpc0” 转换器相同,但键设置为传入连接的源地址。

等价于:src, table_gpc0([<table>])

src_get_gpc1([<table>]): integer

src_get_gpc1([<table>]): integer

与 “table_gpc1” 转换器相同,但键设置为传入连接的源地址。

等价于:src, table_gpc1([<table>])

src_get_gpt(<idx>[,<table>]): integer

src_get_gpt(<idx>[,<table>]): integer

与 “table_gpt” 转换器相同,但键设置为传入连接的源地址。

等价于:src, table_gpt(<idx>[,<table>])

src_get_gpt0([<table>]): integer

src_get_gpt0([<table>]): integer

与 “table_gpt0” 转换器相同,但键设置为传入连接的源地址。

等价于:src, table_gpt0([<table>])

src_glitch_cnt([<table>]): integer

src_glitch_cnt([<table>]): integer

与 “table_glitch_cnt” 转换器相同,但键设置为入站连接的源地址。

等价于:src, table_glitch_cnt([<table>])

src_glitch_rate([<table>]): integer

src_glitch_rate([<table>]): integer

与 “table_glitch_rate” 转换器相同,但键设置为传入连接的源地址。

等价于:src, table_glitch_rate([<table>])

src_gpc_rate(<idx>[,<table>]): integer

src_gpc_rate(<idx>[,<table>]): integer

与 “table_gpc_rate” 转换器相同,但键设置为入站连接的源地址。

等价于:src, table_gpc_rate(<idx>[,<table>])

src_gpc0_rate([<table>]): integer

src_gpc0_rate([<table>]): integer

与 “table_gpc0_rate” 转换器相同,但键设置为传入连接的源地址。

等价于:src, table_gpc0_rate([<table>])

src_gpc1_rate([<table>]): integer

src_gpc1_rate([<table>]): integer

与 “table_gpc1_rate” 转换器相同,但键设置为传入连接的源地址。

等价于:src, table_gpc1_rate([<table>])

src_http_err_cnt([<table>]): integer

src_http_err_cnt([<table>]): integer

与 “table_http_err_cnt” 转换器相同,但键设置为传入连接的源地址。

等价于:src, table_http_err_cnt([<table>])

src_http_err_rate([<table>]): integer

src_http_err_rate([<table>]): integer

与 “table_http_err_rate” 转换器相同,但键设置为入站连接的源地址。

等价于:src, table_http_err_rate([<table>])

src_http_fail_cnt([<table>]): integer

src_http_fail_cnt([<table>]): integer

与 “table_http_fail_cnt” 转换器相同,但键设置为入站连接的源地址。

等价于:src, table_http_fail_cnt([<table>])

src_http_fail_rate([<table>]): integer

src_http_fail_rate([<table>]): integer

与 “table_http_fail_rate” 转换器相同,但键设置为入站连接的源地址。

等价于:src, table_http_fail_rate([<table>])

src_http_req_cnt([<table>]): integer

src_http_req_cnt([<table>]): integer

与 “table_http_req_cnt” 转换器相同,但键设置为入站连接的源地址。

等价于:src, table_http_req_cnt([<table>])

src_http_req_rate([<table>]): integer

src_http_req_rate([<table>]): integer

与 “table_http_req_rate” 转换器相同,但键设置为入站连接的源地址。

等价于:src, table_http_req_rate([<table>])

src_inc_gpc(<idx>[,<table>]): integer

src_inc_gpc(<idx>[,<table>]): integer

与 “src_inc_gpc” 转换器相同,但键设置为传入连接的源地址。

等价于:src, table_inc_gpc(<idx>[,<table>])

src_inc_gpc0([<table>]): integer

src_inc_gpc0([<table>]): integer

与 “src_inc_gpc0” 转换器相同,但键设置为入站连接的源地址。

等价于:src, table_inc_gpc0([<table>])

src_inc_gpc1([<table>]): integer

src_inc_gpc1([<table>]): integer

与 “src_inc_gpc1” 转换器相同,但键设置为传入连接的源地址。

等价于:src, table_inc_gpc1([<table>])

src_is_local: boolean 如果传入连接的源地址是系统本地地址,则返回 true;如果该地址在系统中不存在,即来自远程机器,则返回 false。请注意,UNIX 地址被视为本地地址。可以根据客户端来源应用某些访问限制(例如,要求远程机器进行身份认证或使用 HTTPS)。请注意,该检查涉及若干系统调用,因此建议每连接仅执行一次。

src_kbytes_in([<table>]): integer

src_kbytes_in([<table>]): integer

与 “table_kbytes_in” 转换器相同,但键设置为传入连接的源地址。

等价于:src, table_kbytes_in([<table>])

src_kbytes_out([<table>]): integer

src_kbytes_out([<table>]): integer

与 “table_kbytes_out” 转换器相同,但键设置为入站连接的源地址。

等价于:src, table_kbytes_out([<table>])

src_port: integer 返回与客户端侧连接的 TCP 源端口对应的整数值,即客户端连接所使用的端口。任何 TCP 或 HTTP 规则均可修改此端口。由于现代协议对源端口的关注度已大幅降低,该函数的使用范围非常有限。

src_sess_cnt([<table>]): integer

src_sess_cnt([<table>]): integer

与 “table_sess_cnt” 转换器相同,但键设置为传入连接的源地址。

等价于:src, table_sess_cnt([<table>])

src_sess_rate([<table>]): integer

src_sess_rate([<table>]): integer

与 “table_sess_rate” 转换器相同,但键设置为传入连接的源地址。

等价于:src, table_sess_rate([<table>])

src_updt_conn_cnt([<table>]): integer

src_updt_conn_cnt([<table>]): integer

在当前代理的粘性表或指定的粘性表中,创建或更新与传入连接的源地址关联的条目。该表必须配置为存储 “conn_cnt” 数据类型,否则匹配将被忽略。当前计数加一,并刷新过期计时器。返回更新后的计数,因此该匹配不会返回零。此动作曾用于根据源地址拒绝服务滥用行为。请注意:建议在 “tcp-request” 规则中使用更完整的 “track-sc*” 动作替代。

示例:

# This frontend limits incoming SSH connections to 3 per 10 second for
# each source address, and rejects excess connections until a 10 second
# silence is observed. At most 20 addresses are tracked.
listen ssh
    bind:22
    mode tcp
    maxconn 100
    stick-table type ip size 20 expire 10s store conn_cnt
    tcp-request content reject if { src_updt_conn_cnt gt 3 }
    server local 127.0.0.1:22

srv_id: integer 返回一个整数,其中包含处理响应时服务器的 ID。虽然该字段几乎仅用于 ACL,但也可用于日志记录或调试。它同样可用于 tcp-check 或 http-check 规则集。

srv_name: string 返回一个字符串,其中包含处理响应时服务器的名称。虽然该字段几乎仅用于 ACL,但也可用于日志记录或调试。它同样可用于 tcp-check 或 http-check 规则集中。

txn.conn_retries: 整数 返回此流在尝试连接服务器时经历的连接重试次数。该值在连接未完全建立期间可能发生变化。对于 HTTP 连接,该值可能受 L7 重试影响。

txn.redispatched: boolean 若连接在重试过程中根据“option redispatch”配置发生重分派,则返回 true。该值在连接未完全建立前可能发生变化。对于 HTTP 连接,该值可能受 L7 重试影响。

7.3.4. 在第 5 层获取样本

第五层通常仅指会话层,而在 HAProxy 中,该层对应于所有连接握手完成后但尚未提供任何内容时的会话状态。此处描述的获取方法可应用于最低至 “tcp-request content” 规则集,除非其依赖未来信息。这类方法通常包括 SSL 协商的结果。

本节中各类样本提取方法及其对应类型的摘要:

  keyword                                          output type
-------------------------------------------------+-------------
51d.all(<prop>[,<prop>*])                          string
bs.aborted                                         boolean
bs.debug_str([<bitmap>])                           string
bs.id                                              integer
bs.rst_code                                        integer
fs.aborted                                         boolean
fs.debug_str([<bitmap>])                           string
fs.id                                              integer
fs.rst_code                                        integer
ssl_bc                                             boolean
ssl_bc_alg_keysize                                 integer
ssl_bc_alpn                                        string
ssl_bc_cipher                                      string
ssl_bc_client_early_traffic_secret                 string
ssl_bc_client_handshake_traffic_secret             string
ssl_bc_client_random                               binary
ssl_bc_client_traffic_secret_0                     string
ssl_bc_curve                                       string
ssl_bc_early_exporter_secret                       string
ssl_bc_err                                         integer
ssl_bc_err_str                                     string
ssl_bc_exporter_secret                             string
ssl_bc_is_resumed                                  boolean
ssl_bc_npn                                         string
ssl_bc_protocol                                    string
ssl_bc_server_handshake_traffic_secret             string
ssl_bc_server_random                               binary
ssl_bc_server_traffic_secret_0                     string
ssl_bc_session_id                                  binary
ssl_bc_session_key                                 binary
ssl_bc_sni                                         string
ssl_bc_unique_id                                   binary
ssl_bc_use_keysize                                 integer
ssl_c_ca_err                                       integer
ssl_c_ca_err_depth                                 integer
ssl_c_chain_der                                    binary
ssl_c_der                                          binary
ssl_c_err                                          integer
ssl_c_i_dn([<entry>[,<occ>[,<format>]]])           string
ssl_c_key_alg                                      string
ssl_c_notafter                                     string
ssl_c_notbefore                                    string
ssl_c_r_dn([<entry>[,<occ>[,<format>]]])           string
ssl_c_s_dn([<entry>[,<occ>[,<format>]]])           string
ssl_c_san                                          string
ssl_c_serial                                       binary
ssl_c_sha1                                         binary
ssl_c_sig_alg                                      string
ssl_c_used                                         boolean
ssl_c_verify                                       integer
ssl_c_version                                      integer
ssl_f_der                                          binary
ssl_f_i_dn([<entry>[,<occ>[,<format>]]])           string
ssl_f_key_alg                                      string
ssl_f_notafter                                     string
ssl_f_notbefore                                    string
ssl_f_s_dn([<entry>[,<occ>[,<format>]]])           string
ssl_f_serial                                       binary
ssl_f_sha1                                         binary
ssl_f_sig_alg                                      string
ssl_f_version                                      integer
ssl_fc                                             boolean
ssl_fc_alg_keysize                                 integer
ssl_fc_alpn                                        string
ssl_fc_cipher                                      string
ssl_fc_cipherlist_bin([<filter_option>])           binary
ssl_fc_cipherlist_hex([<filter_option>])           string
ssl_fc_cipherlist_str([<filter_option>])           string
ssl_fc_cipherlist_xxh                              integer
ssl_fc_client_early_traffic_secret                 string
ssl_fc_client_handshake_traffic_secret             string
ssl_fc_client_random                               binary
ssl_fc_client_traffic_secret_0                     string
ssl_fc_crtname                                     string
ssl_fc_curve                                       string
ssl_fc_early_exporter_secret                       string
ssl_fc_ecformats_bin                               binary
ssl_fc_eclist_bin([<filter_option>])               binary
ssl_fc_err                                         integer
ssl_fc_err_str                                     string
ssl_fc_exporter_secret                             string
ssl_fc_extlist_bin([<filter_option>])              binary
ssl_fc_has_crt                                     boolean
ssl_fc_has_early                                   boolean
ssl_fc_has_sni                                     boolean
ssl_fc_is_resumed                                  boolean
ssl_fc_npn                                         string
ssl_fc_protocol                                    string
ssl_fc_protocol_hello_id                           integer
ssl_fc_server_handshake_traffic_secret             string
ssl_fc_server_random                               binary
ssl_fc_server_traffic_secret_0                     string
ssl_fc_session_id                                  binary
ssl_fc_session_key                                 binary
ssl_fc_sigalgs_bin([<filter_option>])              binary
ssl_fc_sni                                         string
ssl_fc_supported_versions_bin([<filter_option>])   binary
ssl_fc_unique_id                                   binary
ssl_fc_use_keysize                                 integer
ssl_s_chain_der                                    binary
ssl_s_der                                          binary
ssl_s_i_dn([<entry>[,<occ>[,<format>]]])           string
ssl_s_key_alg                                      string
ssl_s_notafter                                     string
ssl_s_notbefore                                    string
ssl_s_s_dn([<entry>[,<occ>[,<format>]]])           string
ssl_s_serial                                       binary
ssl_s_sha1                                         binary
ssl_s_sig_alg                                      string
ssl_s_version                                      integer
txn.timer.user                                     integer
-------------------------------------------------+-------------

详细列表:

51d.all(<prop>[,<prop>*]): string

51d.all(<prop>[,<prop>*]): string

以字符串形式返回所请求属性的值,各值之间使用“51degrees-property-separator”指定的分隔符分隔。设备通过请求中的所有重要 HTTP 头进行识别。该函数最多可传入五个属性名,若某属性名无法找到,则返回值为“NoData”。

示例:

# Here the header "X-51D-DeviceTypeMobileTablet" is added to the request
# containing the three properties requested using all relevant headers from
# the request.
frontend http-in
  bind *:8081
  default_backend servers
  http-request set-header X-51D-DeviceTypeMobileTablet \
    %[51d.all(DeviceType,IsMobile,IsTablet)]

bs.aborted: 布尔值,若当前流从服务器接收到中止请求,则返回 true;否则返回 false。

bs.debug_str([<bitmap>]): string

bs.debug_str([<bitmap>]): string

此功能专用于开发人员在特定复杂故障排查会话期间使用。它从后端流和连接的底层提取部分内部状态,并将其整理为字符串,通常以一系列以空格分隔的“name=value”形式呈现。<bitmap> 可选参数用于指定要提取信息的层级,其值为以下各项的算术 OR(或求和)结果:- 套接字层:16 - 连接层:8 - 传输层(如 SSL):4 - 多路复用连接:2 - 多路复用流:1

这些值可能随版本变化。默认值 0 具有特殊含义,表示启用所有层。请勿依赖此函数的输出进行长期生产环境监控。该函数即使在稳定分支内也可能持续演进,以满足对更详细信息的需求。一个典型用例是将这些信息与 fs.debug_str() 一同拼接至日志格式的末尾。示例:

log-format "$HAPROXY_HTTP_LOG_FMT fs=<%[fs.debug_str]> bs=<%[bs.debug_str]>"

bs.id: integer 返回服务器端多路复用器的流 ID。由多路复用器负责返回相应信息。

bs.rst_code: integer 返回从服务器接收到的当前流的重置码。返回服务器发送的 H2 RST_STREAM 帧或 QUIC STOP_SENDING 帧的码值。若未接收到中止事件,或服务器流非 H2/QUIC 流,则样本提取失败。

fs.aborted: 布尔型 若当前流从客户端接收到中止请求,则返回 true;否则返回 false。

fs.debug_str([<bitmap>]): string

fs.debug_str([<bitmap>]): string

此功能专供开发人员在特定复杂故障排查会话期间使用。它从前端流和连接的底层提取部分内部状态,并将其整理为字符串,通常以一系列用空格分隔的“name=value”形式呈现。<bitmap> 可选参数用于指定要提取信息的层级,其值为以下各项的算术 OR(或求和)结果:- 套接字层:16 - 连接层:8 - 传输层(如 SSL):4 - 多路复用连接:2 - 多路复用流:1

这些值可能随版本变化。默认值 0 具有特殊含义,表示启用所有层。请勿依赖此函数的输出进行长期生产环境监控。该函数即使在稳定分支内也可能持续演进,以满足对更详细信息的需求。一个典型用例是将这些信息与 bs.debug_str() 一同拼接至日志格式的末尾。示例:

log-format "$HAPROXY_HTTP_LOG_FMT fs=<%[fs.debug_str]> bs=<%[bs.debug_str]>"

fs.id: integer 返回客户端侧多路复用器的流 ID。由多路复用器负责返回适当的信息。例如,在原始 TCP 上,始终返回 0,因为不存在流。

fs.rst_code: integer 返回客户端在当前流中接收到的重置码。返回客户端发送的 H2 RST_STREAM 帧或 QUIC STOP_SENDING 帧的重置码。若未接收到中止事件,或客户端流非 H2/QUIC 流,则样本提取失败。

ssl_bc: boolean 当后端连接通过 SSL/TLS 传输层建立并已在本地解密时返回 true。这意味着出站连接是向启用了“ssl”选项的服务器发起的。该字段可用于 tcp-check 或 http-check 规则集。

ssl_bc_alg_keysize: integer 返回在通过 SSL/TLS 传输层建立出站连接时所支持的对称加密算法密钥长度(单位:位)。该字段可在 tcp-check 或 http-check 规则集中使用。

ssl_bc_alpn: string 此字段用于从通过 TLS 传输层建立的出站连接中提取应用层协议协商(ALPN)字段。结果为一个字符串,包含与服务器协商确定的协议名称。SSL 库必须在编译时启用了对 TLS 扩展的支持(请检查 HAProxy -vv)。请注意,除非在 “server” 行上使用 “alpn” 关键字指定了协议列表,否则不会通告 TLS ALPN 扩展。此外,服务器并不强制必须从该列表中选择协议,也可能请求其他协议。TLS ALPN 扩展旨在取代 TLS NPN 扩展。参见 “ssl_bc_npn”。该字段可用于 tcp-check 或 http-check 规则集中。

ssl_bc_cipher: string 当出站连接通过 SSL/TLS 传输层建立时,返回所使用的加密套件名称。可在 tcp-check 或 http-check 规则集中使用。

ssl_bc_client_early_traffic_secret: 字符串 返回 CLIENT_EARLY_TRAFFIC_SECRET 作为十六进制字符串,用于后端连接,当出站连接通过 TLS 1.3 传输层建立时。 要求 OpenSSL >= 1.1.1。此为 OpenSSL 密钥日志回调导出的密钥之一,用于生成 SSLKEYLOGFILE。 必须通过在全局段中启用 “tune.ssl.keylog on” 激活 SSL 密钥日志记录。 参见 “tune.ssl.keylog”

ssl_bc_client_handshake_traffic_secret: string 返回 CLIENT_HANDSHAKE_TRAFFIC_SECRET 作为十六进制字符串,用于在出站连接通过 TLS 1.3 传输层建立时的后端连接。要求 OpenSSL ≥ 1.1.1。此值为 OpenSSL 密钥日志回调导出的密钥之一,用于生成 SSLKEYLOGFILE。必须在全局段中通过 “tune.ssl.keylog on” 激活 SSL 密钥日志功能。参见 “tune.ssl.keylog”

ssl_bc_client_random: 二进制格式返回后端连接的客户端随机数,当入站连接通过 SSL/TLS 传输层建立时有效。该功能可用于解密使用临时密码套件传输的流量。需使用 OpenSSL >= 1.1.0 或 BoringSSL。可在 tcp-check 或 http-check 规则集中使用。

ssl_bc_client_traffic_secret_0: string 返回 CLIENT_TRAFFIC_SECRET_0 作为十六进制字符串,用于后端连接。当出站连接通过 TLS 1.3 传输层建立时使用。 要求 OpenSSL ≥ 1.1.1。此为 OpenSSL 密钥日志回调导出的密钥之一,用于生成 SSLKEYLOGFILE。 必须在全局段中通过 “tune.ssl.keylog on” 激活 SSL 密钥日志功能。 参见 “tune.ssl.keylog”

ssl_bc_curve: 字符串 返回在通过 SSL/TLS 传输层建立出站连接时用于密钥协商的曲线名称。此功能需要 OpenSSL ≥ 3.0.0 或 AWS-LC ≥ 1.57.0。

ssl_bc_early_exporter_secret: string 当出站连接通过 TLS 1.3 传输层建立时,返回后端连接的 EARLY_EXPORTER_SECRET 作为十六进制字符串。要求 OpenSSL 版本 ≥ 1.1.1。此值为 OpenSSL 密钥日志回调导出的密钥之一,用于生成 SSLKEYLOGFILE。必须在全局段中通过 “tune.ssl.keylog on” 激活 SSL 密钥日志功能。参见 “tune.ssl.keylog”

ssl_bc_err: 整数 当出站连接通过 SSL/TLS 传输层建立时,返回后端侧第一个错误堆栈中最后一个错误的 ID。该值可能包含握手错误,以及其他在连接生命周期内发生的读取或写入错误。若需获取该错误码的文本描述,可使用 “ssl_bc_err_str” 样本提取,或使用 “openssl errstr” 命令(需以十六进制表示的错误码作为参数)。请查阅所用 SSL 库文档以获取完整的错误码列表。

ssl_bc_err_str: 字符串 当出站连接通过 SSL/TLS 传输层建立时,返回从后端视角出发,该连接上首个错误堆栈中最后一个错误的字符串表示形式。参见 “ssl_fc_err”。

ssl_bc_exporter_secret: string 当出站连接通过 TLS 1.3 传输层建立时,以十六进制字符串形式返回 EXPORTER_SECRET 作为后端连接的密钥。 要求 OpenSSL 版本 ≥ 1.1.1。 此值为 OpenSSL 密钥日志回调导出的密钥之一,用于生成 SSLKEYLOGFILE。 必须在全局段中通过 “tune.ssl.keylog on” 激活 SSL 密钥日志功能。 参见 “tune.ssl.keylog”

ssl_bc_is_resumed: 布尔型 当后端连接通过 SSL/TLS 传输层建立,且新创建的 SSL 会话是通过缓存的会话或 TLS 票据恢复时,返回 true。该字段可用于 tcp-check 或 http-check 规则集。

ssl_bc_npn: string 此字段用于从通过 TLS 传输层建立的出站连接中提取“下一协议协商”(Next Protocol Negotiation)字段。结果为一个字符串,包含与服务器协商确定的协议名称。SSL 库必须在编译时启用了对 TLS 扩展的支持(请检查 HAProxy -vv)。请注意,除非在 “server” 行中通过 “npn” 关键字指定了协议列表,否则不会通告 TLS NPN 扩展。此外,服务器并不强制必须从该列表中选择协议,也可能使用其他协议。请注意,TLS NPN 扩展已被 ALPN 取代。该字段可在 tcp-check 或 http-check 规则集中使用。

ssl_bc_protocol: 字符串 返回通过 SSL/TLS 传输层建立出站连接时所使用的协议名称。可在 tcp-check 或 http-check 规则集中使用。

ssl_bc_server_handshake_traffic_secret: string 返回 SERVER_HANDSHAKE_TRAFFIC_SECRET 作为十六进制字符串,用于后端连接,当出站连接通过 TLS 1.3 传输层建立时。要求 OpenSSL >= 1.1.1。此值为 OpenSSL 密钥日志回调导出的密钥之一,用于生成 SSLKEYLOGFILE。必须在全局段中通过 “tune.ssl.keylog on” 激活 SSL 密钥日志功能。参见 “tune.ssl.keylog”

ssl_bc_server_random: 二进制数据 返回通过 SSL/TLS 传输层建立的入站连接所对应的后端连接的服务器随机数。该字段可用于解密使用临时密码套件传输的流量。使用此功能需要 OpenSSL >= 1.1.0 或 BoringSSL。可在 tcp-check 或 http-check 规则集中使用。

ssl_bc_server_traffic_secret_0: string 以十六进制字符串形式返回 SERVER_TRAFFIC_SECRET_0,当出站连接通过 TLS 1.3 传输层建立时。要求 OpenSSL 版本 ≥ 1.1.1。此值为 OpenSSL keylog 回调导出的密钥之一,用于生成 SSLKEYLOGFILE。必须在全局段中通过 “tune.ssl.keylog on” 激活 SSL 密钥日志记录。参见 “tune.ssl.keylog”

ssl_bc_session_id: binary 返回在出站连接通过 SSL/TLS 传输层建立时的后端连接的 SSL ID。该字段可用于日志记录,以判断会话是否被复用。可在 tcp-check 或 http-check 规则集中使用。

ssl_bc_session_key: 二进制格式返回后端连接的 SSL 会话主密钥,当出站连接通过 SSL/TLS 传输层建立时。该字段可用于解密使用临时密码套件传输的流量。此功能需要 OpenSSL >= 1.1.0 或 BoringSSL。可在 tcp-check 或 http-check 规则集中使用。

ssl_bc_sni: string 此字段用于获取连接到服务器时所使用的 TLS 扩展字段 Server Name Indication(SNI)。当存在时,结果通常为一个字符串,其内容与 HTTPS 主机名匹配(长度不超过 253 个字符)。主要用途为日志记录和调试(例如,确定连接建立时实际使用的 SNI,以便与服务器端所见内容进行比对)。

ssl_bc_unique_id: binary 当出站连接通过 SSL/TLS 传输层建立时,返回 RFC5929 第 3 节 定义的 TLS 唯一 ID。可通过转换器 “ssl_bc_unique_id,base64” 将其编码为 Base64 格式。该值可用于 tcp-check 或 http-check 规则集。

ssl_bc_use_keysize: integer 返回在通过 SSL/TLS 传输层建立出站连接时所使用的对称加密算法密钥长度(单位:位)。该指标可在 tcp-check 或 http-check 规则集中使用。

ssl_c_ca_err: 整数。当客户端连接通过 SSL/TLS 传输层建立时,返回在深度 > 0 处验证客户端证书时检测到的第一个错误的 ID,若在此验证过程中未发现错误则返回 0。请参阅所用 SSL 库文档以获取完整的错误码列表。

ssl_c_ca_err_depth: 整数。当客户端通过 SSL/TLS 传输层建立连接时,返回在验证客户端证书过程中检测到的第一个错误在 CA 证书链中的深度。若未发现错误,则返回 0。

ssl_c_chain_der: 二进制 返回客户端在通过 SSL/TLS 传输层建立入站连接时提供的链式证书的 DER 格式内容。在用于 ACL 时,匹配值可传入十六进制形式。可使用任意支持 ASN.1 DER 数据的库解析该结果。当前不支持已恢复的会话。

ssl_c_der: 二进制 返回客户端在通过 SSL/TLS 传输层建立连接时提供的 DER 格式证书。在用于 ACL 时,用于匹配的值可按十六进制形式传递。

ssl_c_err: 整数 当入站连接通过 SSL/TLS 传输层建立时,返回在深度 0 验证过程中检测到的第一个错误的 ID,若在此验证过程中未发现错误则返回 0。请参阅所用 SSL 库文档以获取错误代码的完整列表。

ssl_c_i_dn([<entry>[,<occ>[,<format>]]]): string

ssl_c_i_dn([<entry>[,<occ>[,<format>]]]): string

当通过 SSL/TLS 传输层建立入站连接时,若未指定 <entry>,返回客户端所提交证书的颁发者完整可区分名称(DN);否则返回从 DN 开头起第一个匹配的条目值。若指定正/负数作为可选的第二个参数,则返回从 DN 开头/结尾起第 n 个指定条目的值。例如,“ssl_c_i_dn(OU,2)” 返回第二个组织单位,而 “ssl_c_i_dn(CN)” 返回通用名称。<format> 参数允许获取适用于不同协议处理的 DN 格式。当前支持的格式为 rfc2253(用于 LDAP v3)。若仅需修改格式,可将前两个参数设为空字符串和零。示例:ssl_c_i_dn(,0,rfc2253) 如果请求条目的 ASN.1 值(未指定 <entry> 时则为 DN 中任意条目)包含内嵌 NUL 字节且其后仍有其他数据,则将其视为格式错误,并且不返回任何数据。

ssl_c_key_alg: 字符串 返回在通过 SSL/TLS 传输层建立入站连接时,客户端所提交证书的密钥生成算法名称。

ssl_c_notafter: 字符串 返回客户端在建立 SSL/TLS 传输层连接时提供的到期日期,格式为格式化字符串 YYMMDDhhmmss[Z]。

ssl_c_notbefore: string 返回客户端在建立入站连接时通过 SSL/TLS 传输层提供的起始日期,格式为格式化字符串 YYMMDDhhmmss[Z]。

ssl_c_r_dn([<entry>[,<occ>[,<format>]]]): string

ssl_c_r_dn([<entry>[,<occ>[,<format>]]]): string

当通过 SSL/TLS 传输层建立的入站连接成功使用配置的 ca-file 验证时,若未指定 <entry>,返回客户端所提交证书的根 CA 的完整可区分名称;否则返回从 DN 开头起第一个匹配的条目值。若指定正数/负数作为可选的第二个参数,则返回从 DN 开头/结尾起第 n 个给定条目的值。例如,“ssl_c_r_dn(OU,2)” 返回第二个组织单位,而“ssl_c_r_dn(CN)” 返回通用名称。<format> 参数允许获取适用于不同协议消费的 DN 格式。当前支持 rfc2253(用于 LDAP v3)。若仅需修改格式,可将前两个参数设为空字符串和零。示例:ssl_c_r_dn(,0,rfc2253) 如果请求条目的 ASN.1 值(未指定 <entry> 时则为 DN 中任意条目)包含内嵌 NUL 字节且其后仍有其他数据,则将其视为格式错误,并且不返回任何数据。

ssl_c_s_dn([<entry>[,<occ>[,<format>]]]): string

ssl_c_s_dn([<entry>[,<occ>[,<format>]]]): string

当通过 SSL/TLS 传输层建立入站连接时,若未指定 <entry>,返回客户端所提交证书中主题的完整可分辨名称;否则返回从 DN 开头起第一个匹配的条目值。若指定正/负的出现次数作为可选的第二个参数,则返回从 DN 开头/结尾起第 n 个指定条目的值。例如,“ssl_c_s_dn(OU,2)” 返回第二个组织单位,而 “ssl_c_s_dn(CN)” 返回通用名称。<format> 参数允许获取适用于不同协议处理的 DN 格式。当前支持的格式为 rfc2253(用于 LDAP v3)。若仅需修改格式,可将前两个参数设为空字符串和零。示例:ssl_c_s_dn(,0,rfc2253) 如果请求条目的 ASN.1 值(未指定 <entry> 时则为 DN 中任意条目)包含内嵌 NUL 字节且其后仍有其他数据,则将其视为格式错误,并且不返回任何数据。

ssl_c_san: 字符串 当通过 SSL/TLS 传输层建立连接,并提供了客户端证书时,返回该证书中包含的以逗号分隔的 Subject Alt Name 字段字符串。

可用于检查客户端证书。

示例:

acl is_valid_client_cert ssl_c_used && ! ssl_c_verify
http-request set-header X-SSL-Client-SAN %[ssl_c_san] if is_valid_client_cert

将导致:

X-SSL-Client-SAN: IP Address:127.0.0.1, IP Address:127.0.0.2, IP Address:127.0.0.3, URI:http://docs.haproxy.org/2.7/, DNS:ca.tests.haproxy.com

ssl_c_serial: 二进制格式,返回客户端在通过 SSL/TLS 传输层建立连接时提供的证书序列号。在用于 ACL 时,用于匹配的值可采用十六进制形式传入。

ssl_c_sha1: binary 返回客户端在通过 SSL/TLS 传输层建立入站连接时提供的证书的 SHA-1 指纹。此值可用于将客户端绑定至服务器,或传递给服务器。请注意,输出为二进制格式,因此若需将该签名传递给服务器,必须先以十六进制或 Base64 编码,例如下例所示:

示例:

http-request set-header X-SSL-Client-SHA1 %[ssl_c_sha1,hex]

ssl_c_sig_alg: 字符串 返回在通过 SSL/TLS 传输层建立入站连接时,客户端所提交证书的签名算法名称。

ssl_c_used: 布尔值,若当前 SSL 会话使用了客户端证书,则返回 true,即使当前连接使用了 SSL 会话恢复也是如此。参见 “ssl_fc_has_crt”。

ssl_c_verify: integer 当入站连接通过 SSL/TLS 传输层建立时,返回验证结果的错误 ID;若未发生错误,则返回零。请参阅所使用的 SSL 库文档,以获取完整的错误代码列表。

ssl_c_version: 整数 返回客户端在通过 SSL/TLS 传输层建立入站连接时提供的证书版本。

ssl_f_der: 二进制 返回前端在通过 SSL/TLS 传输层建立入站连接时所呈现的 DER 格式证书。在用于 ACL 时,用于匹配的值可按十六进制形式传递。

ssl_f_i_dn([<entry>[,<occ>[,<format>]]]): string

ssl_f_i_dn([<entry>[,<occ>[,<format>]]]): string

当入站连接通过 SSL/TLS 传输层建立时,若未指定 <entry>,返回前端所呈现证书的完整颁发者区分名(DN);否则返回从 DN 开头起第一个匹配的条目值。若指定正/负的出现次数作为可选的第二个参数,则返回从 DN 开头/结尾起第 n 个指定条目的值。例如,“ssl_f_i_dn(OU,2)” 返回第二个组织单位,而 “ssl_f_i_dn(CN)” 返回通用名称。<format> 参数允许获取适用于不同协议消费的 DN 格式。当前支持的格式为 rfc2253(用于 LDAP v3)。若仅需修改格式,可将前两个参数设为空字符串和零。示例:ssl_f_i_dn(,0,rfc2253) 如果请求条目的 ASN.1 值(未指定 <entry> 时则为 DN 中任意条目)包含内嵌 NUL 字节且其后仍有其他数据,则将其视为格式错误,并且不返回任何数据。

ssl_f_key_alg: 字符串 返回前端在通过 SSL/TLS 传输层建立入站连接时所呈现证书的密钥生成算法名称。

ssl_f_notafter: 字符串 返回前端以格式化字符串形式呈现的证书有效期截止日期,格式为 YYMMDDhhmmss[Z],该日期对应于当前连接通过 SSL/TLS 传输层建立时的前端所呈现的证书有效期。

ssl_f_notbefore:字符串 返回前端以格式化字符串形式呈现的起始日期,格式为 YYMMDDhhmmss[Z],表示通过 SSL/TLS 传输层建立入站连接时的时间。

ssl_f_s_dn([<entry>[,<occ>[,<format>]]]): string

ssl_f_s_dn([<entry>[,<occ>[,<format>]]]): string

当入站连接通过 SSL/TLS 传输层建立时,若未指定 <entry>,返回前端所呈现证书主体的完整可区分名称;否则返回从 DN 开头起第一个匹配的条目值。若指定正/负的出现次数作为可选的第二个参数,则返回从 DN 开头/结尾起第 n 个指定条目的值。例如,“ssl_f_s_dn(OU,2)” 返回第二个组织单位,而 “ssl_f_s_dn(CN)” 返回通用名称。<format> 参数允许获取适用于不同协议处理的 DN 格式。当前支持 rfc2253(用于 LDAP v3)。若仅需修改格式,可将前两个参数设为空字符串和零。示例:ssl_f_s_dn(,0,rfc2253) 如果请求条目的 ASN.1 值(未指定 <entry> 时则为 DN 中任意条目)包含内嵌 NUL 字节且其后仍有其他数据,则将其视为格式错误,并且不返回任何数据。

ssl_f_serial: binary 返回前端在通过 SSL/TLS 传输层建立入站连接时所呈现的证书序列号。在用于 ACL 时,可传入十六进制形式的值进行匹配。

ssl_f_sha1: 二进制值 返回前端在通过 SSL/TLS 传输层建立入站连接时所呈现的证书的 SHA-1 指纹。此值可用于判断在使用 SNI 时选择了哪个证书。

ssl_f_sig_alg: string 返回在通过 SSL/TLS 传输层建立入站连接时,前端所呈现证书的签名算法名称。

ssl_f_version: integer 返回前端在通过 SSL/TLS 传输层建立入站连接时所出示证书的版本。

ssl_fc: boolean 当前端连接通过 SSL/TLS 传输层建立并已在本地解密时返回 true。这意味着该连接已匹配到使用带有 “ssl” 选项的 “bind” 指令声明的套接字。

示例:

# This passes "X-Proto: https" to servers when client connects over SSL
listen http-https
    bind:80
    bind:443 ssl crt /etc/haproxy.pem
    http-request add-header X-Proto https if { ssl_fc }

ssl_fc_alg_keysize: integer 返回在通过 SSL/TLS 传输层建立的入站连接中,所支持的对称加密算法密钥长度(以比特为单位)。

ssl_fc_alpn: string 此字段用于从通过 TLS 传输层建立且由 HAProxy 本地解密的入站连接中提取应用层协议协商(ALPN)字段。结果为一个字符串,包含客户端通告的协议名称。SSL 库必须在启用 TLS 扩展支持的情况下编译(请检查 HAProxy -vv)。请注意,除非“bind”行上的“alpn”关键字指定了协议列表,否则不会通告 TLS ALPN 扩展。此外,客户端并不强制必须从该列表中选择协议,也可能请求其他协议。TLS ALPN 扩展旨在取代 TLS NPN 扩展。参见 “ssl_fc_npn”。

ssl_fc_cipher: string 返回通过 SSL/TLS 传输层建立的入站连接所使用的加密套件名称。

ssl_fc_cipherlist_bin([<filter_option>]): binary

ssl_fc_cipherlist_bin([<filter_option>]): binary

返回客户端 Hello 消息中密码套件列表的二进制形式。返回值的最大长度受 “tune.ssl.capture-buffer-size” 设置所控制的共享捕获缓冲区大小限制。 设置 <filter_option> 可用于过滤返回数据。接受的值包括:

0: return the full list of ciphers (default)
1: exclude GREASE (RFC8701) values from the output

示例:

http-request set-header X-SSL-JA3 %[ssl_fc_protocol_hello_id],\
    %[ssl_fc_cipherlist_bin(1),be2dec(-,2)],\
    %[ssl_fc_extlist_bin(1),be2dec(-,2)],\
    %[ssl_fc_eclist_bin(1),be2dec(-,2)],\
    %[ssl_fc_ecformats_bin,be2dec(-,1)]
acl is_malware req.fhdr(x-ssl-ja3),digest(md5),hex \
    -f /path/to/file/with/malware-ja3.lst
http-request set-header X-Malware True if is_malware
http-request set-header X-Malware False if !is_malware

ssl_fc_cipherlist_hex([<filter_option>]): string

ssl_fc_cipherlist_hex([<filter_option>]): string

返回以十六进制编码的客户端 Hello 密码套件列表的二进制形式。返回值的最大长度受共享捕获缓冲区大小限制,该大小由 “tune.ssl.capture-buffer-size” 设置控制。设置 <filter_option> 可用于过滤返回数据。

接受的值:

0: return the full list of ciphers (default)
1: exclude GREASE (RFC8701) values from the output

ssl_fc_cipherlist_str([<filter_option>]): string

ssl_fc_cipherlist_str([<filter_option>]): string

返回客户端问候消息中密码套件列表的解码文本形式。返回值的最大长度受共享捕获缓冲区大小限制,该大小由 “tune.ssl.capture-buffer-size” 设置控制。 设置 <filter_option> 可用于过滤返回数据。接受的值如下:

0: return the full list of ciphers (default)
1: exclude GREASE (RFC8701) values from the output

请注意,此样本提取功能仅在 OpenSSL >= 1.0.2 时可用。若该功能未启用,则此样本提取返回的哈希值为 “ssl_fc_cipherlist_xxh”。

ssl_fc_cipherlist_xxh: integer 返回密码套件列表的 xxh64 哈希值。该哈希值仅在 “tune.ssl.capture-buffer-size” 的值大于 0 时才可返回,但哈希值会考虑密码套件列表中的全部数据。

ssl_fc_client_early_traffic_secret: 字符串 返回客户端在通过 TLS 1.3 传输层建立连接时,前端连接的 CLIENT_EARLY_TRAFFIC_SECRET,以十六进制字符串形式输出。 要求 OpenSSL 版本 ≥ 1.1.1。此值为 OpenSSL keylog 回调导出的密钥之一,用于生成 SSLKEYLOGFILE。 必须在全局段中通过 “tune.ssl.keylog on” 激活 SSL 密钥日志记录。 参见 “tune.ssl.keylog”

ssl_fc_client_handshake_traffic_secret: 字符串 返回前端连接在通过 TLS 1.3 传输层建立时的 CLIENT_HANDSHAKE_TRAFFIC_SECRET,以十六进制字符串形式输出。 要求 OpenSSL 版本 ≥ 1.1.1。 此值为 OpenSSL keylog 回调导出的密钥之一,用于生成 SSLKEYLOGFILE。 必须在全局段中通过 “tune.ssl.keylog on” 激活 SSL 密钥日志记录。 参见 “tune.ssl.keylog”

ssl_fc_client_random: binary 返回通过 SSL/TLS 传输层建立的前端连接的客户端随机数。在解密使用临时密码套件传输的流量时非常有用。此功能需要 OpenSSL >= 1.1.0 或 BoringSSL。

ssl_fc_client_traffic_secret_0: string 当前端连接通过 TLS 1.3 传输层建立时,返回 CLIENT_TRAFFIC_SECRET_0 的十六进制字符串形式。 要求 OpenSSL ≥ 1.1.1。此值为 OpenSSL 密钥日志回调导出的密钥之一,用于生成 SSLKEYLOGFILE。 必须在全局段中通过 “tune.ssl.keylog on” 激活 SSL 密钥日志功能。参见 “tune.ssl.keylog”

ssl_fc_crtname: string 返回用于入站 SSL/TLS 连接的证书名称。该名称与在 “show ssl cert” 中显示的一致:可能是带相对路径或绝对路径的文件名,也可能是别名,具体取决于证书在配置中声明的方式。

示例:

crt-store example
    load crt "example.com.pem"

frontend www
    bind *:443 ssl crt "@example/example.com.pem"
    acl match_certificate ssl_fc_crtname -m beg -i "@example/"
    http-request set-header X-Cert-Name %[ssl_fc_crtname] if match_certificate

ssl_fc_curve: string 返回在通过 SSL/TLS 传输层建立入站连接时用于密钥协商的曲线名称。此功能需要 OpenSSL 版本 ≥ 3.0.0。

ssl_fc_early_rcvd: boolean 若在该连接上检测到早期数据,无论握手是否已完成,均返回 true。该字段在流量处理中无实际用途,但却是唯一能“检测”客户端是否使用 0-RTT 发送早期数据的方式。在调试时偶尔有用,因为其他替代方案仅限于网络流量捕获,或在代码中记录前端连接标志并进行匹配。此外,该字段也可用于统计客户端能力。参见 “ssl_fc_has_early”。

ssl_fc_early_exporter_secret: string 当前端连接通过 TLS 1.3 传输层建立时,以十六进制字符串形式返回 EARLY_EXPORTER_SECRET。要求 OpenSSL 版本 ≥ 1.1.1。此值为 OpenSSL 密钥日志回调导出的密钥之一,用于生成 SSLKEYLOGFILE。必须在全局段中通过 “tune.ssl.keylog on” 激活 SSL 密钥日志功能。参见 “tune.ssl.keylog”

ssl_fc_ecformats_bin: binary 返回客户端 Hello 中支持的椭圆曲线点格式的二进制形式。返回值的最大长度受 “tune.ssl.capture-buffer-size” 设置所控制的共享捕获缓冲区大小限制。

示例:

http-request set-header X-SSL-JA3 %[ssl_fc_protocol_hello_id],\
    %[ssl_fc_cipherlist_bin(1),be2dec(-,2)],\
    %[ssl_fc_extlist_bin(1),be2dec(-,2)],\
    %[ssl_fc_eclist_bin(1),be2dec(-,2)],\
    %[ssl_fc_ecformats_bin,be2dec(-,1)]
acl is_malware req.fhdr(x-ssl-ja3),digest(md5),hex \
    -f /path/to/file/with/malware-ja3.lst
http-request set-header X-Malware True if is_malware
http-request set-header X-Malware False if !is_malware

ssl_fc_eclist_bin([<filter_option>]): binary

ssl_fc_eclist_bin([<filter_option>]): binary

返回客户端 Hello 消息中支持的椭圆曲线的二进制形式。返回值的最大长度受 “tune.ssl.capture-buffer-size” 设置所控制的共享捕获缓冲区大小限制。设置 <filter_option> 可用于过滤返回数据。接受的值:

0: return the full list of supported elliptic curves (default)
1: exclude GREASE (RFC8701) values from the output

示例:

http-request set-header X-SSL-JA3 %[ssl_fc_protocol_hello_id],\
    %[ssl_fc_cipherlist_bin(1),be2dec(-,2)],\
    %[ssl_fc_extlist_bin(1),be2dec(-,2)],\
    %[ssl_fc_eclist_bin(1),be2dec(-,2)],\
    %[ssl_fc_ecformats_bin,be2dec(-,1)]
acl is_malware req.fhdr(x-ssl-ja3),digest(md5),hex \
    -f /path/to/file/with/malware-ja3.lst
http-request set-header X-Malware True if is_malware
http-request set-header X-Malware False if !is_malware

ssl_fc_err: 整数 当客户端连接通过 SSL/TLS 传输层建立时,返回前端侧第一个错误堆栈中最后一个错误的 ID,若未发生错误则返回 0。该字段可用于识别除证书验证错误外的握手相关错误(如加密套件不匹配),以及连接生命周期中发生的其他读取或写入错误。客户端证书验证过程中发生的任何错误均不会通过此获取方式上报,而是通过现有的 “ssl_c_err”、“ssl_c_ca_err” 和 “ssl_c_ca_err_depth” 获取方式上报。如需获取该错误码的文本描述,可使用 “ssl_fc_err_str” 样本提取方式,或使用 “openssl errstr” 命令(需以十六进制形式提供错误码作为参数)。请查阅所用 SSL 库文档以获取完整的错误码列表。

ssl_fc_err_str:字符串 当客户端连接通过 SSL/TLS 传输层建立时,返回前端侧第一个错误堆栈中最后一个错误的字符串表示。客户端证书验证过程中发生的任何错误均不会通过此获取方式返回。参见 “ssl_fc_err”。

ssl_fc_exporter_secret: string 返回 EXPORTER_SECRET 作为十六进制字符串,用于前端连接,当入站连接通过 TLS 1.3 传输层建立时。要求 OpenSSL ≥ 1.1.1。此值为 OpenSSL 密钥日志回调导出的密钥之一,用于生成 SSLKEYLOGFILE。必须在全局段中通过 “tune.ssl.keylog on” 激活 SSL 密钥日志功能。参见 “tune.ssl.keylog”

ssl_fc_extlist_bin([<filter_option>]): binary

ssl_fc_extlist_bin([<filter_option>]): binary

返回客户端问候扩展列表的二进制形式。返回值的最大长度受 “tune.ssl.capture-buffer-size” 设置控制的共享捕获缓冲区大小限制。 设置 <filter_option> 可用于过滤返回的数据。接受的值:

0: return the full list of extensions (default)
1: exclude GREASE (RFC8701) values from the output

示例:

http-request set-header X-SSL-JA3 %[ssl_fc_protocol_hello_id],\
    %[ssl_fc_cipherlist_bin(1),be2dec(-,2)],\
    %[ssl_fc_extlist_bin(1),be2dec(-,2)],\
    %[ssl_fc_eclist_bin(1),be2dec(-,2)],\
    %[ssl_fc_ecformats_bin,be2dec(-,1)]
acl is_malware req.fhdr(x-ssl-ja3),digest(md5),hex \
    -f /path/to/file/with/malware-ja3.lst
http-request set-header X-Malware True if is_malware
http-request set-header X-Malware False if !is_malware

ssl_fc_has_crt: 布尔值,当通过 SSL/TLS 传输层的入站连接中存在客户端证书时返回 true。在设置 ‘verify’ 语句为 ‘optional’ 时尤为有用。请注意:在使用会话 ID 或 TLS 票据进行 SSL 会话恢复时,当前连接中可能不存在客户端证书,但可从缓存或票据中检索。因此,若要检查当前 SSL 会话是否使用了客户端证书,应优先使用 “ssl_c_used”。

ssl_fc_has_early: 布尔值,若已发送早期数据且握手尚未完成,则返回 true。由于存在安全风险,建议能够拒绝此类请求,或通过“wait-for-handshake”动作等待握手完成后再处理。参见 “ssl_fc_early_rcvd”。

ssl_fc_has_sni: 布尔值 此检查用于判断通过 SSL/TLS 传输层建立的入站连接中是否包含服务器名称指示 TLS 扩展(SNI)。当入站连接包含 TLS SNI 字段时,返回 true。此功能要求 SSL 库在编译时启用了对 TLS 扩展的支持(请检查 HAProxy -vv)。

ssl_fc_is_resumed: 布尔值 返回值为 true,表示通过 SSL 会话缓存或 TLS 票据,在基于 SSL/TLS 传输层的入站连接上成功恢复了 SSL/TLS 会话。

ssl_fc_npn: string 此字段从通过 TLS 传输层建立且由 HAProxy 本地解密的入站连接中提取“下一协议协商”(Next Protocol Negotiation)字段。结果为一个字符串,包含客户端通告的协议名称。SSL 库必须在启用 TLS 扩展支持的情况下编译(请检查 HAProxy -vv)。请注意,除非“bind”行上的“npn”关键字指定了协议列表,否则不会通告 TLS NPN 扩展。此外,客户端并不强制必须从该列表中选择协议,也可能请求其他协议。请注意,TLS NPN 扩展已被 ALPN 取代。

ssl_fc_protocol: string 返回通过 SSL/TLS 传输层建立的入站连接所使用的协议名称。

ssl_fc_protocol_hello_id: 整数 客户端在会话期间希望使用的 TLS 协议版本,由客户端 Hello 消息中的指示值决定。仅当 “tune.ssl.capture-buffer-size” 的值设置为大于 0 时,该值才可返回。

示例:

http-request set-header X-SSL-JA3 %[ssl_fc_protocol_hello_id],\
    %[ssl_fc_cipherlist_bin(1),be2dec(-,2)],\
    %[ssl_fc_extlist_bin(1),be2dec(-,2)],\
    %[ssl_fc_eclist_bin(1),be2dec(-,2)],\
    %[ssl_fc_ecformats_bin,be2dec(-,1)]
acl is_malware req.fhdr(x-ssl-ja3),digest(md5),hex \
    -f /path/to/file/with/malware-ja3.lst
http-request set-header X-Malware True if is_malware
http-request set-header X-Malware False if !is_malware

ssl_fc_server_handshake_traffic_secret: string 返回前端连接在通过 TLS 1.3 传输层建立时的 SERVER_HANDSHAKE_TRAFFIC_SECRET,以十六进制字符串形式输出。 要求 OpenSSL 版本 ≥ 1.1.1。 此值为 OpenSSL keylog 回调导出的密钥之一,用于生成 SSLKEYLOGFILE。 必须在全局段中通过 “tune.ssl.keylog on” 激活 SSL 密钥日志记录。 另请参见 “tune.ssl.keylog”

ssl_fc_server_random: binary 返回通过 SSL/TLS 传输层建立的前端连接的服务器随机数。在使用临时密码套件加密的流量解密时,该字段非常有用。此功能需要 OpenSSL >= 1.1.0 或 BoringSSL。

ssl_fc_server_traffic_secret_0: string 当前端连接通过 TLS 1.3 传输层建立时,返回 SERVER_TRAFFIC_SECRET_0 的十六进制字符串形式。 要求 OpenSSL 版本 ≥ 1.1.1。此值为 OpenSSL 密钥日志回调导出的密钥之一,用于生成 SSLKEYLOGFILE。 必须在全局段中通过 “tune.ssl.keylog on” 激活 SSL 密钥日志功能。参见 “tune.ssl.keylog”

ssl_fc_session_id: binary 返回通过 SSL/TLS 传输层建立的前端连接的 SSL 会话 ID。该值可用于将特定客户端固定到某台服务器。请注意,部分浏览器会每隔几分钟刷新一次会话 ID。

ssl_fc_session_key: binary 返回前端连接的 SSL 会话主密钥,当入站连接通过 SSL/TLS 传输层建立时有效。该字段可用于解密使用临时密码套件传输的流量。此功能要求 OpenSSL 版本 ≥ 1.1.0,或使用 BoringSSL。

ssl_fc_sigalgs_bin([<filter_option>]): binary

ssl_fc_sigalgs_bin([<filter_option>]): binary

返回在 Client Hello 阶段呈现的 signatures_algorithms (13) TLS 扩展的内容。该扩展提供一个二进制列表,其中包含 TLS RFC 定义的 2 字节算法: https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.3 。

该值仅在 “tune.ssl.capture-buffer-size” 的值大于 0 时才可返回。 设置 <filter_option> 可用于过滤返回的数据。可接受的值:0:返回完整的密码套件列表(默认);1:从输出中排除 GREASE(RFC8701)值。

ssl_fc_sni: string 此字段用于从通过 SSL/TLS 传输层建立且由 HAProxy 本地解密的入站连接中提取 Server Name Indication TLS 扩展(SNI)字段。当存在时,结果通常为一个匹配 HTTPS 主机名的字符串(长度不超过 253 个字符)。SSL 库必须在编译时启用 TLS 扩展支持(请检查 HAProxy -vv)。

此 fetch 与上方的 “req.ssl_sni” 不同之处在于,它作用于 HAProxy 正在解密的连接,而非仅盲目转发的 SSL 内容。另请参见下方的 “ssl_fc_sni_end” 和 “ssl_fc_sni_reg”。此功能要求 SSL 库在构建时启用了 TLS 扩展支持(请检查 HAProxy -vv)。

请注意!除非在非常特定的条件下,通常不应将此字段用作 HTTP “Host” 头字段的替代。例如,当将 HTTPS 连接转发至服务器时,SNI 字段必须使用 “req.hdr(host)” 从 HTTP Host 头字段获取,而非从前端 SNI 值获取。原因在于,SNI 仅用于选择服务器端将呈现的证书,客户端随后可发送与证书中名称匹配但 Host 值不同的请求。因此,“ssl_fc_sni” 通常不应作为 “sni” 服务器关键字的参数使用,除非后端以 TCP 模式运行。

ACL 衍生规则:

ssl_fc_sni_end: suffix match
ssl_fc_sni_reg: regex match

ssl_fc_supported_versions_bin([<filter_option>]): binary

ssl_fc_supported_versions_bin([<filter_option>]): binary

返回在 Client Hello 中呈现的 supported_versions (43) TLS 扩展的内容。 该内容为一个二进制列表,每个版本占 2 字节,包括 TLSv1.3 (0x0304) 和 TLSv1.2 (0x0303)。

该值仅在 “tune.ssl.capture-buffer-size” 的值大于 0 时才可返回。 设置 <filter_option> 可用于过滤返回的数据。可接受的值:0:返回完整的密码套件列表(默认);1:从输出中排除 GREASE(RFC8701)值。

ssl_fc_unique_id: binary 当通过 SSL/TLS 传输层建立入站连接时,返回 RFC5929 第 3 节 定义的 TLS 唯一 ID。可通过转换器 “ssl_fc_unique_id,base64” 将该唯一 ID 编码为 base64 格式。

ssl_fc_use_keysize: integer 返回在通过 SSL/TLS 传输层建立的入站连接中所使用的对称加密算法密钥长度(单位:位)。

ssl_s_chain_der: 二进制 返回在通过 SSL/TLS 传输层建立出站连接时,服务器提供的 DER 格式证书链。在用于 ACL 时,可传入十六进制形式的值进行匹配。可使用任意支持 ASN.1 DER 数据的库解析该结果。当前不支持已恢复的会话。

ssl_s_der: 二进制格式 返回在通过 SSL/TLS 传输层建立出站连接时,服务器提供的 DER 格式证书。在用于 ACL 时,用于匹配的值可以以十六进制形式传递。

ssl_s_i_dn([<entry>[,<occ>[,<format>]]]): string

ssl_s_i_dn([<entry>[,<occ>[,<format>]]]): string

当出站连接通过 SSL/TLS 传输层建立时,若未指定 <entry>,返回服务器所呈现证书的完整颁发者区分名(DN);否则返回从 DN 开头起第一个匹配的条目值。若指定正/负数作为可选的第二个参数,则返回从 DN 开头/末尾起第 n 个指定条目的值。例如,“ssl_s_i_dn(OU,2)” 返回第二个组织单位,而 “ssl_s_i_dn(CN)” 返回通用名称。<format> 参数允许获取适用于不同协议消费的 DN 格式。当前支持的格式为 rfc2253(用于 LDAP v3)。若仅需修改格式,可将前两个参数设为空字符串和零。示例:ssl_s_i_dn(,0,rfc2253) 如果请求条目的 ASN.1 值(未指定 <entry> 时则为 DN 中任意条目)包含内嵌 NUL 字节且其后仍有其他数据,则将其视为格式错误,并且不返回任何数据。

ssl_s_key_alg: 字符串 返回在通过 SSL/TLS 传输层建立出站连接时,服务器所出示证书的密钥生成算法名称。

ssl_s_notafter: 字符串 返回服务器在建立出站连接时通过 SSL/TLS 传输层提供的结束日期,格式为格式化字符串 YYMMDDhhmmss[Z]。

ssl_s_notbefore: string 返回服务器在建立出站连接时通过 SSL/TLS 传输层提供的起始日期,格式为格式化字符串 YYMMDDhhmmss[Z]。

ssl_s_s_dn([<entry>[,<occ>[,<format>]]]): string

ssl_s_s_dn([<entry>[,<occ>[,<format>]]]): string

当出站连接通过 SSL/TLS 传输层建立时,若未指定 <entry>,返回服务器所呈现证书的完整可区分名称(DN);否则返回从 DN 开头起第一个匹配的条目值。若指定正/负数作为可选的第二个参数,则返回从 DN 开头/结尾起第 n 个指定条目的值。例如,“ssl_s_s_dn(OU,2)” 返回第二个组织单位,而 “ssl_s_s_dn(CN)” 返回通用名称。<format> 参数允许获取适用于不同协议处理的 DN 格式。当前支持的格式为 rfc2253(用于 LDAP v3)。若仅需修改格式,可将前两个参数设为空字符串和零。示例:ssl_s_s_dn(,0,rfc2253) 如果请求条目的 ASN.1 值(未指定 <entry> 时则为 DN 中任意条目)包含内嵌 NUL 字节且其后仍有其他数据,则将其视为格式错误,并且不返回任何数据。

ssl_s_serial: binary 返回在通过 SSL/TLS 传输层建立出站连接时,服务器所呈现证书的序列号。在用于 ACL 时,用于匹配的值可以以十六进制形式传入。

ssl_s_sha1: 二进制值 返回在通过 SSL/TLS 传输层建立出站连接时,服务器所呈现证书的 SHA-1 指纹。此值可用于判断在使用 SNI 时选择了哪个证书。

ssl_s_sig_alg: string 返回在通过 SSL/TLS 传输层建立出站连接时,服务器所出示证书的签名算法名称。

ssl_s_version: 整数 返回在通过 SSL/TLS 传输层建立出站连接时,服务器所出示证书的版本。

txn.timer.user: integer 客户端视角下估算的总时间,指代理接收请求的时刻至两端连接关闭时刻之间的实际耗时,不包含空闲时间。该值等效于日志格式中的 %Tu,单位为毫秒(ms)。详细信息请参见 第 8.4 节 “时间事件”

7.3.5. 从缓冲区内容获取样本(层 6)

从缓冲区内容中提取样本的方式与上述其他样本提取方式略有不同,因为所采样的数据是瞬时的。这些数据仅在可用时才能使用,一旦转发便会丢失。因此,例如在请求过程中从缓冲区内容中提取的样本无法用于响应中。即使在数据提取过程中,其内容也可能发生变化。在某些情况下,有必要设置一定的延迟或结合多种样本提取方法,以确保所期望的数据完整且可用,例如通过 TCP 请求内容检查。有关该主题的更详细信息,请参阅“tcp-request content”关键字。

请注意:若在 HTTP 代理中使用以下样本提取方式,将被忽略。这些方式仅处理缓冲区中原始内容。而 HTTP 代理使用结构化内容,因此这些数据的原始表示毫无意义。若 ACL 依赖以下任一样本提取方式,将发出警告。但无法检测所有无效用法(例如在自定义日志格式或样本表达式中)。请务必小心。

本节中各类样本提取方法及其对应类型的摘要:

  keyword                                             output type
----------------------------------------------------+-------------
distcc_body(<token>[,<occ>])                          binary
distcc_param(<token>[,<occ>])                         integer
payload(<offset>,<length>)                            binary
payload_lv(<offset1>,<length>[,<offset2>])            binary
rdp_cookie([<name>])                                  string
rdp_cookie_cnt([name])                                integer
rep_ssl_hello_type                                    integer
req.len                                               integer
req.payload(<offset>,<length>)                        binary
req.payload_lv(<offset1>,<length>[,<offset2>])        binary
req.proto_http                                        boolean
req.rdp_cookie([<name>])                              string
req.rdp_cookie_cnt([name])                            integer
req.ssl_alpn                                          string
req.ssl_cipherlist                                    binary
req.ssl_ec_ext                                        boolean
req.ssl_hello_type                                    integer
req.ssl_keyshare_groups                               binary
req.ssl_sigalgs                                       binary
req.ssl_sni                                           string
req.ssl_st_ext                                        integer
req.ssl_supported_groups                              binary
req.ssl_ver                                           integer
req_len                                               integer
req_proto_http                                        boolean
req_ssl_hello_type                                    integer
req_ssl_sni                                           string
req_ssl_ver                                           integer
res.len                                               integer
res.payload(<offset>,<length>)                        binary
res.payload_lv(<offset1>,<length>[,<offset2>])        binary
res.ssl_hello_type                                    integer
----------------------------------------------------+-------------

详细列表:

distcc_body(<token>[,<occ>]): binary

distcc_body(<token>[,<occ>]): binary

解析一个 distcc 消息,并返回与令牌出现次数 <occ> 对应的正文 <token>。出现次数从 1 开始计算,若未指定,则任意出现次数均可匹配,但目前实际仅检查第一个出现。此功能可用于通过 HAProxy 提取使用 distcc 构建的文件中的文件名或参数。有关支持的令牌完整列表,请参阅 distcc 协议文档。

distcc_param(<token>[,<occ>]): integer

distcc_param(<token>[,<occ>]): integer

解析一个 distcc 消息,并返回与标记 <occ> 第 <token> 次出现关联的参数。出现次数从 1 开始计数,未指定时,任意出现均可匹配,但目前实际仅检查首个出现。此功能可用于提取特定信息,例如协议版本、文件大小或通过 HAProxy 构建的文件中的参数。另一使用场景是在连接服务器前等待预处理文件内容的开始,以避免保持空闲连接。有关支持标记的完整列表,请参阅 distcc 协议文档。

示例:

# wait up to 20s for the pre-processed file to be uploaded
tcp-request inspect-delay 20s
tcp-request content accept if { distcc_param(DOTI) -m found }
# send large files to the big farm
use_backend big_farm if { distcc_param(DOTI) gt 1000000 }

payload(<offset>,<length>): binary (deprecated)

payload(<offset>,<length>): binary (deprecated)

当用于请求上下文时(例如“stick on”、“stick match”),此为 “req.payload” 的别名;当用于响应上下文时(例如“stick store response”),此为 “res.payload” 的别名。

payload_lv(<offset1>,<length>[,<offset2>]): binary (deprecated)

payload_lv(<offset1>,<length>[,<offset2>]): binary (deprecated)

当在请求上下文中使用时(例如“stick on”、“stick match”),此为 “req.payload_lv” 的别名;当在响应上下文中使用时(例如“stick store response”),此为 “res.payload_lv” 的别名。

req.len: integer req_len: integer (已弃用) 返回请求缓冲区中字节数对应的整数值。该值主要用于 ACL。需要注意的是,只要缓冲区内容在变化,此测试就不会返回假值。这意味着,对零值的相等性检查几乎总会在会话开始时立即匹配,而对更多数据的检测则会等待数据到达,并仅在 HAProxy 确定不会再有更多数据到达时才返回假值。此测试设计用于与 TCP 请求内容检查配合使用。

req.payload(<offset>,<length>): binary

req.payload(<offset>,<length>): binary

提取请求缓冲区中从 <offset> 字节开始、长度为 <length> 字节的二进制数据块。特殊情况下,若 <length> 参数为零,则提取从 <offset> 字节到缓冲区末尾的全部内容。此功能可与 ACL 配合使用,以检查缓冲区任意位置是否存在特定内容。

ACL 衍生规则:

req.payload(<offset>,<length>): hex binary match

req.payload_lv(<offset1>,<length>[,<offset2>]): binary

req.payload_lv(<offset1>,<length>[,<offset2>]): binary

此操作提取一个二进制块,其大小由 <offset1> 指定,长度为 <length> 字节,起始位置为 <offset2>(若已指定)或位于请求缓冲区中长度字段之后。<offset2> 参数还支持相对偏移,若在前缀添加 ‘+’ 或 ‘-’ 符号。

ACL 衍生规则:

req.payload_lv(<offset1>,<length>[,<offset2>]): hex binary match

示例:请参阅“stick store-response”关键字中的示例。

req.proto_http: boolean req_proto_http: boolean(已弃用) 当请求缓冲区中的数据符合 HTTP 格式且能正确解析时返回 true。该检测使用与常规 HTTP 请求解析器相同的解析逻辑,因此不会产生意外结果。该测试仅在请求完成、失败或超时时才生效。此测试可用于在 TCP 日志中报告协议,但其主要用途是在缓冲区中存在完整的 HTTP 请求前,阻止对 TCP 请求的分析,例如用于追踪请求头。

示例:

# track request counts per "base" (concatenation of Host+URL)
tcp-request inspect-delay 10s
tcp-request content reject if !HTTP
tcp-request content track-sc0 base table req-rate

req.rdp_cookie([<name>]): string

req.rdp_cookie([<name>]): string
rdp_cookie([<name>]): string (deprecated)

当请求缓冲区内容看起来符合 RDP 协议时,提取 RDP Cookie <name>,或在未指定时提取任意 Cookie。解析器仅检查首个 Cookie,如 RDP 协议规范所示。Cookie 名称不区分大小写。通常使用“MSTS”作为 Cookie 名称,若客户端正确配置,该名称可包含连接到服务器的客户端用户名。“MSTSHASH” Cookie 也常用于实现服务器会话粘性。

与“balance rdp-cookie”不同之处在于,可使用任意负载均衡算法,因此客户端到后端服务器的分配与 RDP Cookie 的哈希值无关。预计使用“balance roundrobin”或“balance leastconn”等负载均衡算法,相较于“balance rdp-cookie”所采用的哈希方式,能够实现更均匀的客户端到后端服务器的分配。

ACL 衍生规则:

req.rdp_cookie([<name>]): exact string match

示例:

listen tse-farm
    bind 0.0.0.0:3389
    # wait up to 5s for an RDP cookie in the request
    tcp-request inspect-delay 5s
    tcp-request content accept if RDP_COOKIE
    # apply RDP cookie persistence
    persist rdp-cookie
    # Persist based on the mstshash cookie
    # This is only useful makes sense if
    # balance rdp-cookie is not used
    stick-table type string size 204800
    stick on req.rdp_cookie(mstshash)
    server srv1 1.1.1.1:3389
    server srv1 1.1.1.2:3389

另请参阅:“balance rdp-cookie”、“persist rdp-cookie”、“tcp-request”以及 “req.rdp_cookie” ACL。

req.rdp_cookie_cnt([name]): integer

req.rdp_cookie_cnt([name]): integer
rdp_cookie_cnt([name]): integer (deprecated)

尝试将请求缓冲区解析为 RDP 协议,然后返回找到的 RDP Cookie 数量对应的整数。若传入可选的 Cookie 名称,则仅考虑与该名称匹配的 Cookie。此功能主要用于 ACL。

ACL 衍生规则:

req.rdp_cookie_cnt([<name>]): integer match

req.ssl_alpn: string 返回一个字符串,其中包含客户端在 SSL ClientHello 消息中发送的 Application-Layer Protocol Negotiation(ALPN)TLS 扩展(RFC7301)的值。 请注意,此字段仅适用于请求缓冲区中原始获取的内容,不适用于通过 SSL 数据层解密后的内容,因此在使用 “ssl” 选项的 “bind” 语句中无法生效。 此字段可用于 ACL 中,根据 TLS 客户端的 ALPN 优先级做出路由决策,如以下示例所示。另见 “ssl_fc_alpn”。此 fetch 只分析请求缓冲区中找到的第一个 ClientHello 消息;有关 HelloRetryRequest、TLS 重新协商和 Encrypted Client Hello 所造成影响的详情,请参阅 req.ssl_sni 关键字文档。

示例:

# Wait for a client hello for at most 5 seconds
tcp-request inspect-delay 5s
tcp-request content accept if { req.ssl_hello_type 1 }
use_backend bk_acme if { req.ssl_alpn acme-tls/1 }
default_backend bk_default

req.ssl_cipherlist binary

req.ssl_cipherlist binary

返回客户端在 TLS ClientHello 内容中报告的支持的对称加密算法列表的二进制形式。请注意,此功能仅适用于请求缓冲区中原始内容,不适用于通过 SSL 数据层解密后的内容,因此在使用了 “ssl” 选项的 “bind” 语句中无法生效。请参考 “ssl_fc_cipherlist_bin”,该选项为 SSL 绑定的等效配置,可在指定 “ssl” 选项时使用。此 fetch 只分析请求缓冲区中找到的第一个 ClientHello 消息;有关 HelloRetryRequest、TLS 重新协商和 Encrypted Client Hello 所造成影响的详情,请参阅 req.ssl_sni 关键字文档。

示例:

# Wait for a client hello for at most 5 seconds
tcp-request inspect-delay 5s
tcp-request content accept if { req.ssl_hello_type 1 }
use-server fe3 if { req.ssl_cipherlist,be2hex(:,2),lower -m sub 1302:009f }
server fe3  ${htst_fe3_addr}:${htst_fe3_port}

req.ssl_ec_ext: boolean 返回一个布尔值,标识客户端是否在 SSL ClientHello 消息中发送了 RFC4492 第 5.1 节 定义的支持椭圆曲线扩展。该字段可用于在同一 IP 地址上,向支持 ECC 的客户端提供 EC 证书,而对其他客户端使用 RSA。请注意,此功能仅适用于请求缓冲区中的原始内容,不适用于通过 SSL 数据层解密后的内容,因此在使用了 “ssl” 选项的 “bind” 语句中无法生效。此 fetch 只分析请求缓冲区中找到的第一个 ClientHello 消息;有关 HelloRetryRequest、TLS 重新协商和 Encrypted Client Hello 所造成影响的详情,请参阅 req.ssl_sni 关键字文档。

req.ssl_hello_type: integer req.ssl_hello_type: integer(已弃用) 返回一个整数值,表示在请求缓冲区中找到的 SSL 握手消息的类型。若缓冲区包含可解析为完整 SSL(v3 或更高版本)客户端握手消息的数据,则返回该类型值。请注意,此功能仅适用于请求缓冲区中的原始内容,不适用于通过 SSL 数据层解密后的内容,因此在使用“ssl”选项的“bind”行中无法生效。该功能主要用于 ACL 中检测预期包含可用于会话粘性的 SSL 会话 ID 的 SSL 握手消息。此 fetch 只分析请求缓冲区中找到的第一个 ClientHello 消息;有关 HelloRetryRequest、TLS 重新协商和 Encrypted Client Hello 所造成影响的详情,请参阅 req.ssl_sni 关键字文档。

req.ssl_keyshare_groups binary

req.ssl_keyshare_groups binary

返回客户端在 TLS ClientHello 消息中报告的支持密钥交换的加密参数列表的二进制格式。在 TLS v1.3 中,keyshare 是 ClientHello 消息的一部分,也是客户端 Hello 消息的最后一个扩展。请注意,此功能仅适用于请求缓冲区中原始获取的内容,不适用于通过 SSL 数据层解密的内容,因此在使用带有 “ssl” 选项的 “bind” 语句时无法生效。此 fetch 只分析请求缓冲区中找到的第一个 ClientHello 消息;有关 HelloRetryRequest、TLS 重新协商和 Encrypted Client Hello 所造成影响的详情,请参阅 req.ssl_sni 关键字文档。

示例:

# Wait for a client hello for at most 5 seconds
tcp-request inspect-delay 5s
tcp-request content accept if { req.ssl_hello_type 1 }
use-server fe3 if { req.ssl_keyshare_groups,be2hex(:,2),lower -m sub 001d  }
server fe3  ${htst_fe3_addr}:${htst_fe3_port}

req.ssl_sigalgs binary

req.ssl_sigalgs binary

返回客户端在 TLS ClientHello 中报告的支持的签名算法列表的二进制形式。此信息作为客户端问候扩展可用。请注意,此功能仅适用于请求缓冲区中原始内容,不适用于通过 SSL 数据层解密的内容,因此在使用带有 “ssl” 选项的 “bind” 语句时无法生效。请参考 “ssl_fc_sigalgs_bin”,该配置项是当指定 “ssl” 选项时可使用的 SSL 绑定等效项。此 fetch 只分析请求缓冲区中找到的第一个 ClientHello 消息;有关 HelloRetryRequest、TLS 重新协商和 Encrypted Client Hello 所造成影响的详情,请参阅 req.ssl_sni 关键字文档。

示例:

# Wait for a client hello for at most 5 seconds
tcp-request inspect-delay 5s
tcp-request content accept if { req.ssl_hello_type 1 }
use-server fe4 if { req.ssl_sigalgs,be2hex(:,2),lower -m sub 0403:0805 }
server fe4  ${htst_fe4_addr}:${htst_fe4_port}

req.ssl_sni: string req_ssl_sni: string (已弃用) 返回一个字符串,其中包含客户端在通过请求缓冲区的 TLS 流中发送的 Server Name TLS 扩展值。该值仅在缓冲区包含可解析为完整 SSL(v3 或更高版本)客户端 Hello 消息的数据时有效。请注意,此功能仅适用于请求缓冲区中的原始内容,不适用于通过 SSL 数据层解密后的内容,因此在使用了 “ssl” 选项的 “bind” 语句中无法生效。该功能仅适用于 HTTPS(443)、IMAPS(993)、SMTPS(465)等实际基于隐式 TLS 的协议,不适用于 SMTP(25/587)或 IMAP(143)等显式 TLS 协议。SNI 通常包含客户端尝试连接的主机名称(针对较新浏览器)。该测试专为 TCP 请求内容检查设计。若需内容切换,建议首先等待完整的客户端 Hello 消息(类型 1),如以下示例所示。另见 “ssl_fc_sni”。请注意,由于下述 HelloRetryRequest、TLS 重新协商和 Encrypted Client Hello 等因素,这个 fetch 返回的值不够可靠,不能单独用于允许或拒绝对特定主机的访问。

此 fetch 只解析请求缓冲区中找到的第一个 ClientHello 消息。如果客户端在同一 TCP 流中发送多个 ClientHello,例如服务器在 TLS 1.3 中请求了 HelloRetryRequest(HRR),或客户端发起 TLS 重新协商(稍后在同一 TCP 流中发送新的 ClientHello,且其中可能包含不同的 SNI),则只返回第一个 ClientHello 中携带的 SNI,后续 ClientHello 的内容都会被忽略。

使用 Encrypted Client Hello(ECH)时,网络上可见的 ClientHello 只是“外层”ClientHello,其中嵌入了真实且加密的“内层”ClientHello。此时,该 fetch 提取的是外层 ClientHello 中作为诱饵的 SNI,而不是客户端实际要访问的主机。当前该 fetch 无法解密或分析内层 ClientHello,因此使用 ECH 时不得依赖它做出路由或访问控制决策。

ACL 衍生规则:

req.ssl_sni: exact string match

示例:

# Wait for a client hello for at most 5 seconds
tcp-request inspect-delay 5s
tcp-request content accept if { req.ssl_hello_type 1 }
use_backend bk_allow if { req.ssl_sni -f allowed_sites }
default_backend bk_sorry_page

req.ssl_st_ext: integer 返回 0 表示客户端未发送 SessionTicket TLS 扩展(RFC5077) 返回 1 表示客户端发送了 SessionTicket TLS 扩展 返回 2 表示客户端还发送了非零长度的 TLS SessionTicket

请注意,此字段仅适用于请求缓冲区中原始内容的检测,不适用于通过 SSL 数据层解密后的内容,因此在使用了 “ssl” 选项的 “bind” 配置行中无法生效。 例如,可利用此字段检测客户端是否发送了 SessionTicket,并据此进行粘性会话处理:若未发送 SessionTicket,则使用 SessionID 进行粘性会话,或不进行粘性会话,因为使用 SessionTicket 时服务器端无状态。此 fetch 只分析请求缓冲区中找到的第一个 ClientHello 消息;有关 HelloRetryRequest、TLS 重新协商和 Encrypted Client Hello 所造成影响的详情,请参阅 req.ssl_sni 关键字文档。

req.ssl_supported_groups binary

req.ssl_supported_groups binary

返回客户端在 TLS ClientHello 中报告并用于密钥交换的支持组列表的二进制形式,该列表可包含椭圆曲线和非椭圆曲线密钥交换。请注意,此功能仅适用于请求缓冲区中原始内容,不适用于通过 SSL 数据层解密的内容,因此在使用了 “ssl” 选项的 “bind” 语句中无法生效。请参考 “ssl_fc_eclist_bin”,其为指定 “ssl” 选项时可用的 SSL 绑定等效项。此 fetch 只分析请求缓冲区中找到的第一个 ClientHello 消息;有关 HelloRetryRequest、TLS 重新协商和 Encrypted Client Hello 所造成影响的详情,请参阅 req.ssl_sni 关键字文档。

示例:

# Wait for a client hello for at most 5 seconds
tcp-request inspect-delay 5s
tcp-request content accept if { req.ssl_hello_type 1 }
use-server fe3 if { req.ssl_supported_groups, be2hex(:,2),lower -m sub 0017 }
server fe3  ${htst_fe3_addr}:${htst_fe3_port}

req.ssl_ver: integer req.ssl_ver: integer(已弃用) 返回一个整数值,表示请求缓冲区中流的 SSL/TLS 协议版本。支持 SSLv2 Hello 消息和 SSLv3 消息。TLSv1 被标识为 SSL 版本 3.1。该值由主版本号乘以 65536 后加上次版本号构成。请注意,此功能仅适用于请求缓冲区中的原始内容,不适用于通过 SSL 数据层解密后的内容,因此在使用 “ssl” 选项的 “bind” 行中无法生效。ACL 版本的测试匹配格式为十进制表示的 MAJOR.MINOR(例如 3.1)。该获取器主要用于 ACL。此 fetch 只分析请求缓冲区中找到的第一个 ClientHello 消息;有关 HelloRetryRequest、TLS 重新协商和 Encrypted Client Hello 所造成影响的详情,请参阅 req.ssl_sni 关键字文档。

ACL 衍生规则:

req.ssl_ver: decimal match

res.len: integer 返回响应缓冲区中当前存在的字节数。该值主要用于 ACL。需要注意的是,只要缓冲区内容在变化,此测试就不会返回假值。这意味着,对零值的相等性检查几乎总会在流开始时立即匹配,而对更多数据的检测则会等待数据到达,并仅在 HAProxy 确定不会再有更多数据到达时才返回假值。此测试设计用于 TCP 响应内容检查。也可用于基于 tcp-check 的 expect 规则。

res.payload(<offset>,<length>): binary

res.payload(<offset>,<length>): binary

从响应缓冲区中提取 <length> 字节,起始位置为 <offset> 字节。作为特例,若 <length> 参数为零,则从 <offset> 字节开始提取至缓冲区末尾的全部内容。此功能可与 ACL 配合使用,以检查任意位置的缓冲区中是否存在特定内容,也可用于基于 tcp-check 的 expect 规则中。

res.payload_lv(<offset1>,<length>[,<offset2>]): binary

res.payload_lv(<offset1>,<length>[,<offset2>]): binary

此规则提取一个二进制块,其大小由 <offset1> 指定,长度为 <length> 字节,起始位置为 <offset2>(若已指定)或位于响应缓冲区中长度字段之后。<offset2> 参数还支持相对偏移,若在前缀加上 ‘+’ 或 ‘-’ 符号。该参数也可用于基于 tcp-check 的 expect 规则。

示例:请参阅“stick store-response”关键字中的示例。

res.ssl_hello_type: 整数 rep_ssl_hello_type: 整数(已弃用) 返回一个整数值,表示响应缓冲区中包含的 SSL 握手消息的类型。若缓冲区中包含可解析为完整 SSL(v3 或更高版本)握手消息的数据,则返回该消息的类型。请注意,此功能仅适用于响应缓冲区中的原始内容,不适用于通过 SSL 数据层解密后的内容,因此在使用 “ssl” 选项的 “server” 配置行中无法生效。该功能主要用于 ACL 中检测预期包含可用于会话粘性的 SSL 会话 ID 的 SSL 握手消息。

7.3.6. 获取 HTTP 样本(第 7 层)

可以在 HTTP 内容、请求和响应中获取样本。此应用层也称为第 7 层。只有在已从相应的请求或响应缓冲区完整解析出 HTTP 请求或响应后,才能在此段中获取数据。所有 HTTP 特定规则以及以 “mode http” 运行的段均始终满足此条件。在使用 TCP 内容检查时,可能需要支持检查延迟,以确保请求或响应先到达。此类获取操作所需的 CPU 资源可能略多于第 4 层操作,但差异不大,因为请求和响应已建立索引。

请注意:关于 tcp-request 内容规则中的 HTTP 处理,从 HTTP 代理角度看,所有功能均可按预期工作。但从 TCP 代理角度看,若未进行 HTTP 升级,则仅支持 HTTP/1 内容。对于 HTTP/2 内容,仅能访问前缀部分。因此,仅可依赖 “req.proto_http”、“req.ver” 以及可选的 “method” 样本提取。其他所有 L7 样本提取将失败。HTTP 升级完成后,其行为将与从 HTTP 代理中获取时相同。

本节中各类样本提取方法及其对应类型的摘要:

  keyword                                          output type
-------------------------------------------------+-------------
base                                               string
base32                                             integer
base32+src                                         binary
baseq                                              string
capture.req.hdr(<idx>)                             string
capture.req.method                                 string
capture.req.uri                                    string
capture.req.ver                                    string
capture.res.hdr(<idx>)                             string
capture.res.ver                                    string
cook([<name>])                                     string
cook_cnt([<name>])                                 integer
cook_val([<name>])                                 integer
cookie([<name>])                                   string
hdr([<name>[,<occ>]])                              string
hdr_cnt([<header>])                                integer
hdr_ip([<name>[,<occ>]])                           ip
hdr_val([<name>[,<occ>]])                          integer
http_auth(<userlist>)                              boolean
http_auth_bearer([<header>])                       string
http_auth_group(<userlist>)                        string
http_auth_pass                                     string
http_auth_type                                     string
http_auth_user                                     string
http_first_req                                     boolean
method                                             integer
path                                               string
pathq                                              string
query([<options>])                                 string
req.body                                           binary
req.body_len                                       integer
req.body_param([<name>[,i]])                       string
req.body_size                                      integer
req.cook([<name>])                                 string
req.cook_cnt([<name>])                             integer
req.cook_names([<delim>])                          string
req.cook_val([<name>])                             integer
req.fhdr(<name>[,<occ>])                           string
req.fhdr_cnt([<name>])                             integer
req.hdr([<name>[,<occ>]])                          string
req.hdr_cnt([<name>])                              integer
req.hdr_ip([<name>[,<occ>]])                       ip
req.hdr_names([<delim>])                           string
req.hdr_val([<name>[,<occ>]])                      integer
req.hdrs                                           string
req.hdrs_bin                                       binary
req.timer.hdr                                      integer
req.timer.idle                                     integer
req.timer.queue                                    integer
req.timer.tq                                       integer
req.ver                                            string
req_ver                                            string
request_date([<unit>])                             integer
res.body                                           binary
res.body_len                                       integer
res.body_size                                      integer
res.cache_hit                                      boolean
res.cache_name                                     string
res.comp                                           boolean
res.comp_algo                                      string
res.cook([<name>])                                 string
res.cook_cnt([<name>])                             integer
res.cook_names([<delim>])                          string
res.cook_val([<name>])                             integer
res.fhdr([<name>[,<occ>]])                         string
res.fhdr_cnt([<name>])                             integer
res.hdr([<name>[,<occ>]])                          string
res.hdr_cnt([<name>])                              integer
res.hdr_ip([<name>[,<occ>]])                       ip
res.hdr_names([<delim>])                           string
res.hdr_val([<name>[,<occ>]])                      integer
res.hdrs                                           string
res.hdrs_bin                                       binary
res.timer.hdr                                      integer
res.ver                                            string
resp_ver                                           string
scook([<name>])                                    string
scook_cnt([<name>])                                integer
scook_val([<name>])                                integer
server_status                                      integer
set-cookie([<name>])                               string
shdr([<name>[,<occ>]])                             string
shdr_cnt([<name>])                                 integer
shdr_ip([<name>[,<occ>]])                          ip
shdr_val([<name>[,<occ>]])                         integer
status                                             integer
txn.status                                         integer
txn.timer.total                                    integer
unique-id                                          string
url                                                string
url32                                              integer
url32+src                                          binary
url_ip                                             ip
url_param([<name>[,<delim>[,i]]])                  string
url_port                                           integer
urlp([<name>[,<delim>[,i]]])                       string
urlp_val([<name>[,<delim>[,i]]])                   integer
-------------------------------------------------+-------------

详细列表:

base: string 该选项返回请求的首个 Host 头与路径部分的拼接结果,路径部分从第一个斜杠开始,到问号前结束。在虚拟主机环境中,此选项可用于检测 URL 滥用,同时提升共享缓存的效率。结合有限大小的粘性表使用,还可统计按主机/路径划分的最常请求对象的访问情况。配合 ACL 可实现同时涉及主机和路径的简单内容切换规则,例如 “www.example.com/favicon.ico "。另请参见 “path” 和 “uri”。

ACL 衍生规则:

base    : exact string match
base_beg: prefix match
base_dir: subdir match
base_dom: domain match
base_end: suffix match
base_len: length match
base_reg: regex match
base_sub: substring match

请注意:ACL 衍生规则不得在后续使用转换器,或在采用“-m”模式匹配方法的 ACL 中使用。

base32: integer 此返回上述 “base” 获取方法所返回值的 32 位哈希值。 在高流量网站上追踪每个 URL 的活动时非常有用,无需存储所有 URL。 取而代之的是存储较短的哈希值,可大幅节省内存。 输出类型为无符号整数。 所使用的哈希函数为 SDBM,且输出结果具备完整的雪崩效应。 从技术上讲,base32 等同于 “base,sdbm(1)"。

base32+src: binary 该函数返回上述 base32 获取结果与下方 src 获取结果的拼接结果。 结果类型为 binary,长度为 8 字节或 20 字节,具体取决于源地址的地址族。 可用于跟踪每个 IP 地址或每个 URL 的计数器。

baseq:string 此返回请求的 Host 头与路径部分(包含查询字符串)的拼接结果,查询字符串从第一个斜杠开始。使用此选项替代 “base” 可以更准确地识别目标资源,适用于统计信息或缓存场景。另请参见 “path”、“pathq” 和 “base”。

capture.req.hdr(<idx>): string

capture.req.hdr(<idx>): string

此用于提取由 “capture request header” 捕获的头内容,idx 为配置中捕获关键字的位置,首个条目索引为 0。参见:“capture request header”。

capture.req.method: string 该选项用于捕获 HTTP 请求的方法。可在请求和响应中使用。与 “method” 不同,它可在请求和响应中均使用,因为其已分配内存。

capture.req.uri: string 该选项用于捕获请求的 URI,其范围从第一个斜杠开始,到请求中第一个空格之前结束(不包含主机部分)。与“path”和“url”不同,它可在请求和响应中使用,因为其内存已分配。

capture.req.ver: string 该选项用于提取请求的 HTTP 版本,并以 “HTTP/<major>.<minor>” 的格式返回。由于依赖持久化信息,该选项可在请求、响应及日志中使用。若请求版本无效,则该样本提取操作失败。

capture.res.hdr(<idx>): string

capture.res.hdr(<idx>): string

此用于提取由 “capture response header” 捕获的头内容,idx 为配置中捕获关键字的位置,首个条目索引为 0。参见:“capture response header”

capture.res.ver: string 该选项用于提取响应的 HTTP 版本,并以 “HTTP/<major>.<minor>” 的格式返回。由于依赖持久化信息,该选项可用于日志记录。若响应版本无效,则该样本提取操作失败。

cookie([<name>]): string (deprecated)

cookie([<name>]): string (deprecated)

提取请求中 “Cookie” 头字段或响应中 “Set-Cookie” 头字段里最后一个名为 <name> 的 Cookie 值,并以字符串形式返回。典型用途是让共享同一配置文件的多个客户端始终使用同一台服务器。这与使用 “request-learn” 语句时 “appsession” 的功能类似,但支持多对等节点同步以及重启后的状态保持。若未指定名称,则返回第一个 Cookie 值。此获取方式已不再推荐使用,应改用 req.cook() 或 res.cook(),因为该方式在不同使用上下文中会根据方向产生歧义。

hdr([<name>[,<occ>]]): string

hdr([<name>[,<occ>]]): string

这与在请求上使用时的 req.hdr() 等效,与在响应上使用时的 res.hdr() 等效。 请参考相应的样本提取方法以获取更多详细信息。 如对样本提取方向存在疑问,请使用明确的版本。 请注意,与 hdr() 样本提取方法不同,hdr_* ACL 关键字明确应用于请求头。

http_auth(<userlist>): boolean

http_auth(<userlist>): boolean

返回一个布尔值,指示从客户端接收到的认证数据是否与指定 userlist 中存储的用户名和密码匹配。此获取函数在 ACL 之外基本无用。当前仅支持 HTTP Basic 认证。

http_auth_bearer([<header>]): string

http_auth_bearer([<header>]): string

当使用 Bearer 方案时(例如发送 JSON Web Token),返回客户端在授权数据中提供的令牌。不会对客户端发送的数据进行校验。若提供了特定的 <header>,则会解析该头字段而非 Authorization 头。

http_auth_group(<userlist>): string

http_auth_group(<userlist>): string

返回与客户端发送的认证数据中匹配的用户名字符串,前提是该用户名和密码均符合指定 userlist 的验证规则。主要用途是在 ACL 中使用,以检查该用户是否属于列表中的任意组。此获取函数在 ACL 之外基本无实际用途。当前仅支持 HTTP Basic 认证。

ACL 衍生规则:

http_auth_group(<userlist>): group ...
Returns true when the user extracted from the request and whose password is
valid according to the specified userlist belongs to at least one of the
groups.

http_auth_pass: string 返回从客户端接收到的认证数据中的用户密码,该数据由 Authorization 头提供。本样本提取不执行任何校验。仅支持 Basic 认证。

http_auth_type: string 返回从客户端接收的认证数据中找到的认证方法,该数据由 Authorization 头提供。本样本不执行任何检查。仅支持 Basic 认证。

http_auth_user: string 返回从客户端接收的认证数据中提取的用户名,该数据由 Authorization 头提供。本样本提取不执行任何校验。仅支持 Basic 认证。

http_first_req:boolean 当正在处理的请求是该连接中的第一个请求时,返回 true。此字段可用于添加或移除某些请求中可能缺失的头,尤其是在请求非首个时;也可用于帮助在日志中对请求进行分组。

method: 整数 + 字符串 返回与 HTTP 请求中的方法对应的整数值。 例如,“GET” 对应值 1(请查阅源码以确认对应关系)。值 9 表示“其他方法”,可转换为从流中提取的字符串。此值不应直接作为样本使用,仅用于 ACL,ACL 会透明地将模式中的方法转换为整数 + 字符串值。部分预定义的 ACL 已经检查最常见的方法。

ACL 衍生规则:

method: case insensitive method match

示例:

# only accept GET and HEAD requests
acl valid_method method GET HEAD
http-request deny if ! valid_method

path: string 该选项提取请求的 URL 路径,路径从第一个斜杠开始,到问号前结束(不包含主机部分)。典型用途包括与支持预取的缓存配合使用,以及用于需要从多个数据库聚合信息并将其存入缓存的门户。请注意,对于出站缓存,使用 “url” 选项更为合适。在 ACL 中,通常用于匹配精确的文件名(例如 “/login.php”),或使用其衍生形式匹配目录部分。另请参阅 “url” 和 “base” 获取方法。请注意,URI 中的任何片段引用(路径后的 ‘#’)均严格违反 HTTP 标准,将被拒绝。然而,如果接收请求的前端配置了 “option accept-unsafe-violations-in-http-request”,则该片段部分将被接受,并同样出现在路径中。

ACL 衍生规则:

path    : exact string match
path_beg: prefix match
path_dir: subdir match
path_dom: domain match
path_end: suffix match
path_len: length match
path_reg: regex match
path_sub: substring match

请注意:ACL 衍生规则不得在后续使用转换器,或在采用“-m”模式匹配方法的 ACL 中使用。

pathq: string 该样本提取从第一个斜杠开始获取请求的 URL 路径及查询字符串。此样本提取方式非常实用,可始终获取相对 URI,排除协议和权威部分(如存在)。实际上,尽管 HTTP/1.1 请求目标通常采用此种形式,但在 HTTP/2 中常使用绝对 URI。此样本提取在两种情况下均返回相同结果。请注意,URI 中的片段引用(路径后的 ‘#’)严格违反 HTTP 标准,将被拒绝。然而,若接收请求的前端配置了 “option accept-unsafe-violations-in-http-request”,则该片段部分将被接受,并包含在路径中。

query([<options>]): string

query([<options>]): string

提取请求的查询字符串,该字符串从第一个问号之后开始。若不存在问号,则此获取操作返回空值。若存在问号但其后无内容,则返回空字符串。这意味着可借助“found”匹配方法轻松判断查询字符串是否存在。此获取操作与“path”互补,后者在问号前停止;也与 “query_string” 互补,后者包含问号。

可选参数可用于自定义返回值。支持以下选项:

- with_qm: Include the question mark at the beginning ot the query string,
            if not empty.

req.body: binary 此函数返回 HTTP 请求的可用请求体作为数据块。建议启用 “option http-buffer-request”,以确保尽可能等待请求体的完整接收。

req.body_len: integer 此字段返回 HTTP 请求可用正文的字节数。如果正文长度超过缓冲区大小,该值可能低于声明的长度。建议启用 “option http-buffer-request”,以尽可能等待请求正文的完整接收。

req.body_param([<name>[,i]]): string

req.body_param([<name>[,i]]): string

本文假设 POST 请求的请求体为 URL 编码格式。用户可检查 “content-type” 是否包含 “application/x-www-form-urlencoded” 值。该提取操作会获取请求体中第一个出现的参数 <name>,其值在遇到 ‘&’ 前结束。参数名区分大小写,除非额外添加 “i” 作为第二个参数。若未指定参数名,则匹配任意参数,返回第一个匹配项。结果为请求体中参数 <name> 对应的值字符串(不执行 URL 解码)。请注意,ACL 版本的此提取操作会遍历多个参数,若未指定参数名,则会依次报告所有参数的值。

req.body_size: integer 返回 HTTP 请求体的声明长度(以字节为单位)。该值表示声明的 Content-Length 头,或在使用分块编码时可用数据的大小。

req.cook([<name>]): string

req.cook([<name>]): string
cook([<name>]): string (deprecated)

提取请求中 “Cookie” 头字段行里最后一个名为 <name> 的 Cookie 值,并以字符串形式返回。若未指定名称,则返回第一个 Cookie 值。在与 ACL 配合使用时,将评估所有匹配的 Cookie。根据 Cookie 头规范(RFC6265)要求,名称和值周围的空格将被忽略。Cookie 名称区分大小写。空 Cookie 为有效值,因此若存在空 Cookie,其值可能为空。请使用 “found” 匹配来检测其存在性。对服务器发送的响应 Cookie,请使用 res.cook() 变体。

ACL 衍生规则:

req.cook([<name>])    : exact string match
req.cook_beg([<name>]): prefix match
req.cook_dir([<name>]): subdir match
req.cook_dom([<name>]): domain match
req.cook_end([<name>]): suffix match
req.cook_len([<name>]): length match
req.cook_reg([<name>]): regex match
req.cook_sub([<name>]): substring match

请注意:ACL 衍生规则不得在后续使用转换器,或在采用“-m”模式匹配方法的 ACL 中使用。

req.cook_cnt([<name>]): integer

req.cook_cnt([<name>]): integer
cook_cnt([<name>]): integer (deprecated)

返回一个整数值,表示请求中出现的 cookie <name> 的次数,若未指定 <name>,则表示所有 cookie 的数量。

req.cook_names([<delim>]): string

req.cook_names([<delim>]): string

此操作构建一个字符串,该字符串由规则评估时请求中出现的所有 Cookie 名称(来自 Cookie 头)连接而成。默认分隔符为逗号(’,’),但可作为可选参数 <delim> 覆盖。此时,仅考虑 <delim> 的第一个字符。

req.cook_val([<name>]): integer

req.cook_val([<name>]): integer
cook_val([<name>]): integer (deprecated)

从请求的 “Cookie” 头中提取名称为 <name> 的最后一个 Cookie 实例,并将其值转换为整数后返回。若未指定名称,则返回第一个 Cookie 值。在 ACL 中使用时,将遍历所有匹配的名称,直至找到一个值匹配为止。

req.fhdr(<name>[,<occ>]): string

req.fhdr(<name>[,<occ>]): string

返回 HTTP 请求中头 <name> 最后一次出现的完整值。与 req.hdr() 的区别在于,值中包含的任何逗号都会被原样返回,不会作为分隔符使用。在处理如 User-Agent 等头时,此功能有时很有用。

在 ACL 中使用时,将遍历所有出现的项,直到找到匹配项为止。

可选地,可指定特定出现位置为位置编号。正值表示从首次出现开始的位置,1 代表第一个。负值表示相对于最后一个位置,-1 代表最后一个。

req.fhdr_cnt([<name>]): integer

req.fhdr_cnt([<name>]): integer

返回一个整数值,表示请求头字段名 <name> 的出现次数,若未指定 <name>,则返回头字段的总数。与 res.hdr_cnt() 不同,它不会在逗号处拆分头字段,这一点与 req.fhdr() 一致。

req.hdr([<name>[,<occ>]]): string

req.hdr([<name>[,<occ>]]): string

返回 HTTP 请求中头 <name> 的最后一个以逗号分隔的值。该获取操作将任意逗号视为不同值的分隔符。当需要处理被定义为值列表的头时(例如 Accept 或 X-Forwarded-For),此功能非常有用。若需获取完整行的头,请使用 req.fhdr()。请仔细查阅 RFC 7231,以了解特定头的正确解析方式。此外,部分头不区分大小写(例如 Connection)。

在 ACL 中使用时,将遍历所有出现的项,直到找到匹配项为止。

可选地,可指定特定出现位置为位置编号。正值表示从首次出现开始的位置,1 代表第一个。负值表示相对于最后一个位置,-1 代表最后一个。

典型用法是在将 X-Forwarded-For 头转换为 IP 后,将其与 IP stick-table 关联。

ACL 衍生规则:

hdr([<name>[,<occ>]])    : exact string match
hdr_beg([<name>[,<occ>]]): prefix match
hdr_dir([<name>[,<occ>]]): subdir match
hdr_dom([<name>[,<occ>]]): domain match
hdr_end([<name>[,<occ>]]): suffix match
hdr_len([<name>[,<occ>]]): length match
hdr_reg([<name>[,<occ>]]): regex match
hdr_sub([<name>[,<occ>]]): substring match

请注意:ACL 衍生规则不得在后续使用转换器,或在采用“-m”模式匹配方法的 ACL 中使用。

req.hdr_cnt([<name>]): integer

req.hdr_cnt([<name>]): integer
hdr_cnt([<header>]): integer (deprecated)

返回一个整数值,表示请求头字段名 <name> 的出现次数,若未指定 <name>,则返回头字段值的总数量。与 req.hdr() 类似,它会统计头字段值中每个以逗号分隔的部分。若需统计完整行头的出现次数,则应改用 req.fhdr_cnt()。

通过 ACL,可用来检测特定头的存在、缺失或滥用情况,也可通过拒绝包含某些头字段多个实例的请求,阻止请求走私攻击。

有关头匹配的更多信息,请参见 req.hdr()。

req.hdr_ip([<name>[,<occ>]]): ip

req.hdr_ip([<name>[,<occ>]]): ip
hdr_ip([<name>[,<occ>]]): ip (deprecated)

提取 HTTP 请求中头 <name> 的最后一次出现,将其转换为 IPv4 或 IPv6 地址并返回该地址。与 ACL 配合使用时,将检查所有出现,若 <name> 被省略,则检查每个头的每个值。解析器严格遵循 RFC7239 中描述的格式,但允许 IPv4 地址可选地后跟冒号(’:’)和有效的十进制端口号(0 至 65535),该端口号将被静默丢弃。其他所有格式均不匹配,导致地址被忽略。

<occ> 参数的处理方式与 req.hdr() 相同。

典型用法是与 X-Forwarded-For 和 X-Client-IP 头配合使用。

req.hdr_names([<delim>]): string

req.hdr_names([<delim>]): string

此操作构建一个字符串,该字符串由请求中所有头字段名称按其出现顺序拼接而成。默认分隔符为逗号(’,’),但可作为可选参数 <delim> 覆盖。此时仅考虑 <delim> 的第一个字符。

req.hdr_val([<name>[,<occ>]]): integer

req.hdr_val([<name>[,<occ>]]): integer
hdr_val([<name>[,<occ>]]): integer (deprecated)

提取 HTTP 请求中头 <name> 的最后一次出现,并将其转换为整数值。与 ACL 配合使用时,将检查所有出现的头,若省略 <name>,则检查每个头的每个值。

<occ> 参数的处理方式与 req.hdr() 相同。

典型用法是与 X-Forwarded-For 头配合使用。

req.hdrs: string 返回当前请求头作为字符串,包含分隔头与请求体的最后一个空行。最后一个空行可用于检测头块是否被截断。该样本提取功能对某些 SPOE 头分析器及高级日志记录非常有用。

req.hdrs_bin:以预解析的二进制形式返回当前请求头。此功能适用于通过 SPOE 执行部分处理卸载。每个字符串由长度字段后接长度指定的字节数构成。长度采用 SPOE 文档中详述的可变整数编码方式表示。列表末尾通过一对空头名称和值(两者长度均为 0)标记。

*(<str:header-name>`` <str:header-value>)<empty string> ``<empty string>

int:请参阅 SPOE 文档以了解编码格式;str:<int:length>`` <bytes>

req.timer.hdr: integer 客户端请求的总耗时(仅限 HTTP 模式)。该值表示从接收到首个字节到代理收到标记 HTTP 头结束的空行之间的时间间隔。单位为毫秒(ms),等效于日志格式中的 %TR。详见 第 8.4 节 “定时事件”。

req.timer.idle: 整数 该值表示 HTTP 请求的空闲时间(仅限 HTTP 模式)。此计时器统计握手完成与首个 HTTP 请求字节到达之间的时长。单位为毫秒,等效于日志格式中的 %Ti。详见 第 8.4 节 “时间事件”。

req.timer.queue: 整数 用于等待连接槽位的队列中累计耗时。单位为毫秒,等同于日志格式中的 %Tw。详见 第 8.4 节 “时间事件” 获取更多详情。

req.timer.tq:整数,从接受连接时间或上一个响应最后一个字节发出后开始计算,获取客户端请求所花费的总时间。单位为毫秒,等同于日志格式中的 %Tq。详细信息请参见 第 8.4 节 “时间事件”。

req.ver: string req_ver: string(已弃用) 返回 HTTP 请求中的版本字符串,格式为 “<major>.<minor>"。该字段可用于 ACL。部分预定义的 ACL 已经针对常见版本进行检查。由于依赖持久化信息,该样本提取可在请求、响应及日志中使用。若请求版本无效,该样本提取将失败。

常用值为 “1.0”、“1.1”、“2.0” 或 “3.0”。

ACL 衍生规则:

req.ver: exact string match

request_date([<unit>]): integer

request_date([<unit>]): integer

这是 HAProxy 首次接收到 HTTP 请求第一个字节的精确时间(日志格式别名 %tr)。该时间由 accept_date + 握手时间 (%Th) + 空闲时间 (%Ti) 计算得出。

返回自纪元以来的秒数。

<unit> 为可选配置,可设置为 “s” 表示秒(默认行为)、“ms” 表示毫秒或 “us” 表示微秒。若指定单位,返回值为整数,表示自纪元以来的秒、毫秒或微秒数。当需要小于秒级的时间分辨率时,该配置非常有用。

res.body: binary 此指令返回 HTTP 响应中可用的正文内容作为数据块。与请求侧不同,此处没有指令用于等待响应正文的到达。该样本提取在健康检查上下文中尤为有用(且可直接使用)。

可在基于 tcp-check 的 expect 规则中使用。

res.body_len: integer 此指令返回当前可用 HTTP 响应体的字节数长度。与请求侧不同,此处没有指令用于等待响应体的完整到达。该样本提取在健康检查上下文中尤为实用(且可直接使用)。

可在基于 tcp-check 的 expect 规则中使用。

res.body_size: integer 该指令返回 HTTP 响应体的声明长度(以字节为单位)。 其值代表声明的 Content-Length 头,或在使用分块编码时代表可用数据的大小。 与请求侧不同,此处没有指令用于等待响应体。 该样本提取在健康检查上下文中非常有用(且可直接使用)。

可在基于 tcp-check 的 expect 规则中使用。

res.cache_hit: boolean 如果响应是基于 HTTP 缓存条目生成的,则返回布尔值 “true”,否则返回布尔值 “false”。

res.cache_name: string 返回一个字符串,其中包含用于构建 HTTP 响应的 HTTP 缓存名称;若 res.cache_hit 为 true,则返回该缓存名称,否则返回空字符串。

res.comp: boolean 如果响应被 HAProxy 压缩,则返回布尔值 “true”,否则返回布尔值 “false”。此值可用于在日志中添加信息。

res.comp_algo: string 返回一个字符串,其中包含 HAProxy 对响应进行压缩时所使用的算法名称,例如:“deflate”。此字段可用于在日志中添加相关信息。

res.cook([<name>]): string

res.cook([<name>]): string
scook([<name>]): string (deprecated)

从响应的 “Set-Cookie” 头中提取名称为 <name> 的 cookie 的最后一次出现值,并以字符串形式返回。若未指定名称,则返回第一个 cookie 值。

可在基于 tcp-check 的 expect 规则中使用。

ACL 衍生规则:

res.scook([<name>]: exact string match

res.cook_cnt([<name>]): integer

res.cook_cnt([<name>]): integer
scook_cnt([<name>]): integer (deprecated)

返回一个整数值,表示响应中出现的 cookie <name> 的次数,若未指定 <name>,则表示所有 cookie 的数量。此功能主要用于结合 ACL 使用,以检测可疑响应。

可在基于 tcp-check 的 expect 规则中使用。

res.cook_names([<delim>]): string

res.cook_names([<delim>]): string

此操作构建一个字符串,该字符串由规则被评估时响应中(Set-Cookie 头)出现的所有 Cookie 名称拼接而成。默认分隔符为逗号(’,’),但可作为可选参数 <delim> 覆盖。此时,仅考虑 <delim> 的第一个字符。

可在基于 tcp-check 的 expect 规则中使用。

res.cook_val([<name>]): integer

res.cook_val([<name>]): integer
scook_val([<name>]): integer (deprecated)

从响应的 “Set-Cookie” 头中提取 <name> 的最后一次出现,将其值转换为整数并返回。若未指定名称,则返回第一个 cookie 值。

可在基于 tcp-check 的 expect 规则中使用。

res.fhdr([<name>[,<occ>]]): string

res.fhdr([<name>[,<occ>]]): string

此获取方式的功能与 req.fhdr() 获取方式类似,区别在于它作用于 HTTP 响应中的头。

与 req.fhdr() 类似,res.fhdr() 返回完整的值。如果头被定义为列表,则应使用 res.hdr()。

此获取方式在处理 Date 或 Expires 等头时有时很有用。

可在基于 tcp-check 的 expect 规则中使用。

res.fhdr_cnt([<name>]): integer

res.fhdr_cnt([<name>]): integer

此获取方式的功能与 req.fhdr_cnt() 获取方式类似,区别在于它作用于 HTTP 响应中的头。

与 req.fhdr_cnt() 类似,res.fhdr_cnt() 获取操作的是完整值。如果头被定义为列表形式,应使用 res.hdr_cnt()。

可在基于 tcp-check 的 expect 规则中使用。

res.hdr([<name>[,<occ>]]): string

res.hdr([<name>[,<occ>]]): string
shdr([<name>[,<occ>]]): string (deprecated)

此获取方式与 req.hdr() 获取方式类似,区别在于它作用于 HTTP 响应中的头。

与 req.hdr() 类似,res.hdr() 获取器会将逗号视为分隔符。若不希望如此,应使用 res.fhdr()。

可在基于 tcp-check 的 expect 规则中使用。

ACL 衍生规则:

res.hdr([<name>[,<occ>]])    : exact string match
res.hdr_beg([<name>[,<occ>]]): prefix match
res.hdr_dir([<name>[,<occ>]]): subdir match
res.hdr_dom([<name>[,<occ>]]): domain match
res.hdr_end([<name>[,<occ>]]): suffix match
res.hdr_len([<name>[,<occ>]]): length match
res.hdr_reg([<name>[,<occ>]]): regex match
res.hdr_sub([<name>[,<occ>]]): substring match

请注意:ACL 衍生规则不得在后续使用转换器,或在采用“-m”模式匹配方法的 ACL 中使用。

res.hdr_cnt([<name>]): integer

res.hdr_cnt([<name>]): integer
shdr_cnt([<name>]): integer (deprecated)

此获取方式的功能与 req.hdr_cnt() 获取方式类似,区别在于它作用于 HTTP 响应中的头。

与 req.hdr_cnt() 类似,res.hdr_cnt() 也把逗号视为分隔符。若不希望如此,应使用 res.fhdr_cnt()。

可在基于 tcp-check 的 expect 规则中使用。

res.hdr_ip([<name>[,<occ>]]): ip

res.hdr_ip([<name>[,<occ>]]): ip
shdr_ip([<name>[,<occ>]]): ip (deprecated)

此获取方式的功能与 req.hdr_ip() 获取方式类似,区别在于它作用于 HTTP 响应中的头。

这可用于将部分数据载入粘性表。

可在基于 tcp-check 的 expect 规则中使用。

res.hdr_names([<delim>]): string

res.hdr_names([<delim>]): string

此操作构建一个字符串,该字符串由响应中规则被评估时出现的所有头名称拼接而成。默认分隔符为逗号(’,’),但可作为可选参数 <delim> 覆盖。此时,仅考虑 <delim> 的第一个字符。

可在基于 tcp-check 的 expect 规则中使用。

res.hdr_val([<name>[,<occ>]]): integer

res.hdr_val([<name>[,<occ>]]): integer
shdr_val([<name>[,<occ>]]): integer (deprecated)

此获取方式的功能与 req.hdr_val() 获取方式类似,区别在于它作用于 HTTP 响应中的头。

这可用于将部分数据载入粘性表。

可在基于 tcp-check 的 expect 规则中使用。

res.hdrs: string 返回当前响应头作为字符串,包含分隔头与请求体的最后一个空行。最后一个空行可用于检测头块是否被截断。该样本提取方法适用于某些 SPOE 头分析器及高级日志记录。

也可用于基于 tcp-check 的 expect 规则中。

res.hdrs_bin:以预解析的二进制形式返回当前响应头。此功能可用于将部分处理任务卸载至 SPOE。可在基于 tcp-check 的 expect 规则中使用。每个字符串由长度字段后接长度指定的字节数构成。长度采用 SPOE 文档中详述的可变整数编码方式表示。列表末尾以一对空头名称和值(两者长度均为 0)标记。

*(<str:header-name>`` <str:header-value>)<empty string> ``<empty string>

int:请参阅 SPOE 文档以了解编码格式;str:<int:length>`` <bytes>

res.timer.hdr: integer 表示从建立与服务器的 TCP 连接时刻到服务器发送完整响应头时刻之间所经过的时间。该值以毫秒为单位报告,等同于日志格式中的 %Tr。有关更多详细信息,请参见 第 8.4 节 “时间事件”。

res.ver: string resp_ver: string (已弃用) 返回 HTTP 响应中的版本字符串,格式为 “<major>.<minor>"。该字段可用于日志记录,但主要用于 ACL。若响应版本无效,此样本提取将失败。

可在基于 tcp-check 的 expect 规则中使用。

ACL 衍生规则:

resp.ver: exact string match

server_status: integer 返回一个整数,其中包含从服务器接收到的 HTTP 状态码。如果未从服务器接收到响应,样本提取将失败。

set-cookie([<name>]): string (deprecated)

set-cookie([<name>]): string (deprecated)

从响应的 “Set-Cookie” 头中提取 cookie 名称 <name> 的最后一次出现,并使用对应的值进行匹配。此功能可与 “appsession” 在默认选项下的行为相媲美,但支持多对等节点同步以及重启后的状态保持。

此获取函数已弃用,已被 “res.cook” 获取函数取代。该关键字将很快消失。

status: integer 返回一个整数,包含 HTTP 响应中的 HTTP 状态码,例如 302。该值主要用于 ACL 和整数范围中,例如在响应非 3xx 状态码时移除所有 Location 头。若未通过 set-status 动作等手段修改,该值即为客户端实际接收到的状态码。

可在基于 tcp-check 的 expect 规则中使用。

txn.status: integer 返回一个整数,包含事务的 HTTP 状态码,该状态码与日志中报告的一致。

txn.timer.total: integer HTTP 请求的总活动时间,即从代理接收到请求头的第一个字节开始,到响应体最后一个字节发出为止的时间。该指标等同于日志格式中的 %Ta,单位为毫秒(ms)。更多信息请参见 第 8.4 节 “时间事件”

unique-id: string 返回附加到请求的唯一 ID。必须设置指令 “unique-id-format”。若未设置,将导致 unique-id 样本提取失败。请注意,唯一 ID 通常用于 HTTP 请求,但此样本提取可与其他协议一同使用。显然,若用于非 HTTP 协议,“unique-id-format” 指令不得包含 HTTP 相关部分。参见:unique-id-format 和 unique-id-header

url: string 此字段提取请求中呈现的请求 URL。典型用途包括与支持预取的缓存配合使用,以及用于需要从多个数据库聚合信息并将其保留在缓存中的门户。在使用 ACL 时,应优先选择使用 “path” 而非 “url”,因为客户端可能像通常对代理那样发送完整 URL。唯一真正的用途是匹配 “*",该匹配在 “path” 中无法实现,且已有预定义的 ACL 可处理此情况。另请参见 “path” 和 “base”。请注意,URI 中的任何片段引用(路径后的 ‘#’)均严格违反 HTTP 标准,将被拒绝。然而,如果接收请求的前端配置了 “option accept-unsafe-violations-in-http-request”,则该片段部分将被接受,并且也会出现在 url 中。

ACL 衍生规则:

url    : exact string match
url_beg: prefix match
url_dir: subdir match
url_dom: domain match
url_end: suffix match
url_len: length match
url_reg: regex match
url_sub: substring match

请注意:ACL 衍生规则不得在后续使用转换器,或在采用“-m”模式匹配方法的 ACL 中使用。

32 位 URL 哈希:整数 该选项返回由首个 Host 头与完整 URL(包括参数)拼接后生成的 32 位哈希值(不同于“base32”获取方式中仅使用请求路径部分)。此方法适用于追踪每个 URL 的活动情况。由于存储的是较短的哈希值,可显著节省内存。输出类型为无符号整数。

url32+src:二进制 该指令返回 “url32” 获取项与 “src” 获取项的拼接结果。结果类型为二进制,长度为 8 字节或 20 字节,具体取决于源地址族。可用于跟踪每个 IP 地址、每个 URL 的计数器。

url_ip: ip 当请求的主机部分以 IP 地址形式呈现时,此选项用于从请求的 URL 中提取 IP 地址。其使用范围非常有限。例如,监控系统可使用此字段作为源 IP 的替代,以测试特定源地址将遵循的路径,或为特定源地址强制在表中添加条目。可与 http-request set-dst 配合使用,以模拟旧版的 option http_proxy。

url_port: integer 从请求的 URL 中提取端口部分。请注意,若请求中未指定端口,则默认使用端口 80。

urlp([<name>[,<delim>[,i]]]): string

urlp([<name>[,<delim>[,i]]]): string
url_param([<name>[,<delim>[,i]]]): string

提取查询字符串中首个出现的参数 <name>,该参数位于 ‘?’ 或 <delim> 之后,且在 ‘&’、’;’ 或 <delim> 之前。参数名称区分大小写,除非额外添加 “i” 作为第三个参数。若未指定参数名,则匹配任意参数,并返回首个匹配项。结果为对应请求中参数 <name> 的值(不执行 URL 解码)。此功能可用于基于客户端 ID 的会话粘性,提取作为 URL 参数传递的应用程序 Cookie,或在 ACL 中执行某些检查。请注意,ACL 版本的此获取操作会遍历多个参数,若未指定参数名,则会逐个报告所有参数值。

ACL 衍生规则:

urlp(<name>[,<delim>])    : exact string match
urlp_beg(<name>[,<delim>]): prefix match
urlp_dir(<name>[,<delim>]): subdir match
urlp_dom(<name>[,<delim>]): domain match
urlp_end(<name>[,<delim>]): suffix match
urlp_len(<name>[,<delim>]): length match
urlp_reg(<name>[,<delim>]): regex match
urlp_sub(<name>[,<delim>]): substring match

请注意:ACL 衍生规则不得在后续使用转换器,或在采用“-m”模式匹配方法的 ACL 中使用。

示例:

# match http://example.com/foo?PHPSESSIONID=some_id
stick on urlp(PHPSESSIONID)
# match http://example.com/foo;JSESSIONID=some_id
stick on urlp(JSESSIONID,;)

urlp_val([<name>[,<delim>[,i]]]): integer

urlp_val([<name>[,<delim>[,i]]]): integer

参见上方的 “urlp”。此选项从请求中提取 URL 参数 <name> 并将其转换为整数值。可用于基于用户 ID 的会话粘性,或与 ACL 配合匹配页码或价格。

7.3.7. 获取开发者样本

本组样本提取方法专为开发者保留,严禁在生产环境中使用,除非开发者明确要求,且仅用于调试目的。此外,不会对向后兼容性进行特别维护。无法保证以下样本提取方法不会发生变更、重命名或被直接移除。因此,若必须使用其中任一方法,请务必谨慎。为避免任何歧义,这些样本提取方法均置于专用作用域 “internal” 中,例如 “internal.strm.is_htx”。

本节中各类样本提取方法及其对应类型的摘要:

  keyword                                          output type
-------------------------------------------------+-------------
internal.htx.data                                  integer
internal.htx.free                                  integer
internal.htx.free_data                             integer
internal.htx.has_eom                               boolean
internal.htx.nbblks                                integer
internal.htx.size                                  integer
internal.htx.used                                  integer
internal.htx_blk.size(<idx>)                       integer
internal.htx_blk.type(<idx>)                       string
internal.htx_blk.data(<idx>)                       binary
internal.htx_blk.hdrname(<idx>)                    string
internal.htx_blk.hdrval(<idx>)                     string
internal.htx_blk.start_line(<idx>)                 string
internal.strm.is_htx                               boolean
-------------------------------------------------+-------------

详细列表:

internal.htx.data: integer 返回与通道关联的 HTX 消息中数据所占用的字节数。通道的选择取决于样本方向。

internal.htx.free: 整数 返回与通道关联的 HTX 消息中空闲空间(大小 - 已用)的字节数。通道的选择取决于样本方向。

internal.htx.free_data: integer 返回与通道关联的 HTX 消息中数据部分的可用字节数。通道的选择取决于样本方向。

internal.htx.has_eom: boolean 如果与通道关联的 HTX 消息包含消息结束标志(EOM),则返回 true;否则返回 false。通道的选择取决于样本方向。

internal.htx.nbblks: integer 返回与通道关联的 HTX 消息中包含的块数量。通道的选择取决于样本方向。

internal.htx.size: integer 返回与通道关联的 HTX 消息的总字节数。通道的选择取决于样本方向。

internal.htx.used: integer 返回与通道关联的 HTX 消息中已使用的总字节数(数据 + 元数据)。通道的选择取决于样本方向。

internal.htx_blk.size(<idx>): integer

internal.htx_blk.size(<idx>): integer

返回与通道关联的 HTX 消息中位置 <idx> 处块的大小,若该块不存在则返回 0。通道的选择取决于样本方向。<idx> 可以是任意正整数,或以下特殊值之一: - head:最旧插入的块 - tail:最新插入的块 - first:分析(重新)开始的第一个块

internal.htx_blk.type(<idx>): string

internal.htx_blk.type(<idx>): string

返回与通道关联的 HTX 消息中位置 <idx> 处块的类型,若该块不存在则返回 “HTX_BLK_UNUSED”。通道的选择取决于样本方向。<idx> 可为任意正整数,或以下特殊值之一: * head:最旧插入的块 * tail:最新插入的块 * first:分析(重新)开始的第一个块

internal.htx_blk.data(<idx>): binary

internal.htx_blk.data(<idx>): binary

返回与通道关联的 HTX 消息中位置 <idx> 处的 DATA 块的值,若该位置不存在或其非 DATA 块,则返回空字符串。通道的选择取决于样本方向。<idx> 可为任意正整数,或以下特殊值之一:

* head : The oldest inserted block
* tail : The newest inserted block
* first: The first block where to (re)start the analysis

internal.htx_blk.hdrname(<idx>): string

internal.htx_blk.hdrname(<idx>): string

返回与通道关联的 HTX 消息中位置 <idx> 处的 HEADER 块的头名称,若该块不存在或不是 HEADER 块,则返回空字符串。通道的选择取决于样本方向。<idx> 可以是任意正整数,或以下特殊值之一:

* head : The oldest inserted block
* tail : The newest inserted block
* first: The first block where to (re)start the analysis

internal.htx_blk.hdrval(<idx>): string

internal.htx_blk.hdrval(<idx>): string

返回与通道关联的 HTX 消息中位置 <idx> 处的 HEADER 块的头值,若该块不存在或不是 HEADER 块,则返回空字符串。通道的选择取决于样本方向。<idx> 可以是任意正整数,或以下特殊值之一:

* head : The oldest inserted block
* tail : The newest inserted block
* first: The first block where to (re)start the analysis

internal.htx_blk.start_line(<idx>): string

internal.htx_blk.start_line(<idx>): string

返回通道关联的 HTX 消息中位置 <idx> 处的 REQ_SL 或 RES_SL 块的值,若该块不存在或不是 SL 块,则返回空字符串。通道的选择取决于样本方向。<idx> 可以是任意正整数,或以下特殊值之一:

* head : The oldest inserted block
* tail : The newest inserted block
* first: The first block where to (re)start the analysis

internal.strm.is_htx: boolean 如果当前流为 HTX 流,则返回 true。这意味着通道缓冲区中的数据采用内部 HTX 表示形式存储。否则,返回 false。

7.4. 预定义访问控制列表

部分预定义的 ACL 已被硬编码,因此无需在每个需要它们的前端中声明。它们的名称均采用大写形式,以避免混淆。其等效性如下所示。

ACL name          Equivalent to                Usage
---------------+----------------------------------+------------------------------------------------------
FALSE            always_false                       never match
HTTP             req.proto_http                     match if request protocol is valid HTTP
HTTP_1.0         req.ver 1.0                        match if HTTP request version is 1.0
HTTP_1.1         req.ver 1.1                        match if HTTP request version is 1.1
HTTP_2.0         req.ver 2.0                        match if HTTP request version is 2.0
HTTP_3.0         req.ver 3.0                        match if HTTP request version is 3.0
HTTP_CONTENT     req.hdr_val(content-length) gt 0   match an existing content-length in the HTTP request
HTTP_URL_ABS     url_reg ^[^/:]*://                 match absolute URL with scheme
HTTP_URL_SLASH   url_beg /                          match URL beginning with "/"
HTTP_URL_STAR    url     *                          match URL equal to "*"
LOCALHOST        src 127.0.0.1/8::1                match connection from local host
METH_CONNECT     method  CONNECT                    match HTTP CONNECT method
METH_DELETE      method  DELETE                     match HTTP DELETE method
METH_GET         method  GET HEAD                   match HTTP GET or HEAD method
METH_HEAD        method  HEAD                       match HTTP HEAD method
METH_OPTIONS     method  OPTIONS                    match HTTP OPTIONS method
METH_POST        method  POST                       match HTTP POST method
METH_PUT         method  PUT                        match HTTP PUT method
METH_TRACE       method  TRACE                      match HTTP TRACE method
RDP_COOKIE       req.rdp_cookie_cnt gt 0            match presence of an RDP cookie in the request buffer
REQ_CONTENT      req.len gt 0                       match data in the request buffer
TRUE             always_true                        always match
WAIT_END         wait_end                           wait for end of content analysis
---------------+----------------------------------+------------------------------------------------------

17 - 8. 日志记录

日志级别、格式、配置文件、时间戳、捕获、状态及示例

本文的强项之一无疑是其精确的日志记录。它可能为这类产品提供了最详尽的信息级别,这对排查复杂环境中的问题至关重要。日志中提供的标准信息包括客户端端口、TCP/HTTP 状态定时器、流在终止时的精确状态以及精确的终止原因,关于将流量导向服务器的决策信息,当然还包括捕获任意头字段的能力。

为提升系统管理能力的响应速度,该功能可清晰呈现所遇到的内部与外部问题,且可同时将日志发送至多个目标,并针对不同级别设置过滤器:

  • 全局进程级日志(系统错误、启动/停止等)
  • 每个实例的系统和内部错误(资源不足、缺陷等)
  • 每个实例的外部问题(服务器上下线、连接数上限)
  • 每个实例的活动日志(客户端连接),无论是在建立阶段还是终止阶段
  • 按请求控制日志级别,例如:http-request set-log-level silent if sensitive_request

将不同级别的日志分发至不同的日志服务器,可使多个生产团队协同工作,并尽快解决各自的问题。例如,系统团队可监控系统级错误,应用团队可实时监控其服务器的启停状态,安全团队则可延迟一小时分析活动日志。

8.1. 日志级别

TCP 和 HTTP 连接可记录包括日期、时间、源 IP 地址、目标地址、连接持续时间、响应时间、HTTP 请求、HTTP 返回码、传输字节数、流结束条件,甚至交换的 Cookie 值等信息。例如,用于追踪特定用户的问题。所有消息可发送至最多两个 syslog 服务器。有关日志设施的更多信息,请参阅 “log” 关键字在 第 4.2 节 中的说明。

8.2. 日志格式

HAProxy 支持 5 种日志格式。这些格式之间存在若干共用字段,将在后续段落中详细说明。部分字段可能因配置中特定选项的指示而略有差异。支持的格式如下:

  • 默认格式,极为简单,极少使用。该格式仅在连接被接受的瞬间提供关于入站连接的极简信息:源 IP:端口、目标 IP:端口和前端名称。此模式最终将被移除,因此不会进行详细描述。

  • TCP 格式,功能更强大。当在前端配置了 “option tcplog” 时,该格式被启用。HAProxy 通常会在连接终止后才进行日志记录。该格式提供更丰富的信息,例如计时器、连接数、队列大小等……推荐用于纯 TCP 代理。

  • HTTP 格式,适用于 HTTP 代理的最先进格式。当在前端启用 “option httplog” 时,该格式被激活。它提供与 TCP 格式相同的信息,并增加了一些 HTTP 特有的字段,例如请求、状态码,以及头和 Cookie 的捕获。建议对 HTTP 代理使用此格式。

  • CLF HTTP 格式,与 HTTP 格式等效,但字段排列顺序与 CLF 格式一致。在此模式下,所有计时器、捕获、标志等均在通用字段结束后按字段逐一出现,顺序与标准 HTTP 格式中一致。

  • 自定义日志格式,可定义自有日志行。

后续段落将深入探讨每种格式的详细信息。格式规范将按 “field” 进行。除非另有说明,字段是指由任意数量空格分隔的文本片段。由于 syslog 服务器可能在行首插入字段,因此始终假设首个字段为包含进程名称和标识符的字段。

请注意:由于日志行可能非常长,下述各段中的日志示例可能会被拆分为多行。示例日志行将以三个右尖括号(’»>’)开头,每当一条日志被拆分为多行时,非末尾行将以反斜杠(\)结尾,下一行将缩进两个字符。

8.2.1. 默认日志格式

此格式在未设置特定选项时使用。连接一旦被接受,日志即被发出。请注意,当前此格式是唯一记录请求目标 IP 和端口的格式。

示例:

    listen www
        mode http
        log global
        server srv1 127.0.0.1:8000

>>> Feb  6 12:12:09 localhost \
      haproxy[14385]: Connect from 10.0.1.2:33312 to 10.0.3.31:8012 \
      (www/HTTP)

字段格式 从上例提取 1 process_name ‘[’ pid ‘]:’ HAProxy[14385]: 2 ‘Connect from’ Connect from 3 source_ip ‘:’ source_port 10.0.1.2:33312 4 ’to’ to 5 destination_ip ‘:’ destination_port 10.0.3.31:8012 6 ‘(’ frontend_name ‘/’ mode ‘)’ (www/HTTP)

详细字段说明:

  • “source_ip” 是发起连接的客户端的 IP 地址。
  • “source_port” 是发起连接的客户端的 TCP 端口。
  • “destination_ip” 是客户端连接的目标 IP 地址。
  • “destination_port” 是客户端连接的目标 TCP 端口。
  • “frontend_name” 是接收并处理该连接的前端(或监听器)的名称。
  • “mode 是前端当前运行的模式(TCP 或 HTTP)。

若为 Unix 套接字,源地址和目标地址将标记为“unix:”,端口反映接受连接的套接字的内部 ID(与统计信息中报告的 ID 相同)。

建议新安装时不要使用此已弃用的格式,因为它最终将被移除。

8.2.2. TCP 日志格式

当在前端中指定 “option tcplog” 时,使用 TCP 格式。该格式是纯 TCP 代理的推荐格式,可提供大量用于故障排查的宝贵信息。由于此格式包含计时器和字节数统计,日志通常在会话结束时输出。若指定 “option logasap”,则可在会话早期输出日志,这在远程终端等具有长会话的环境中尤为合理。匹配 “monitor” 规则的会话将永不记录日志。也可在前端中指定 “option dontlognull”,以避免在客户端与服务器之间未交换任何数据的会话中输出日志。若在前端中指定 “option dontlog-normal”,则正常连接将不会被记录。

TCP 日志格式在内部被声明为基于以下确切字符串的自定义日志格式,该字符串也可用作扩展格式的基础(如需)。此外,可使用 HAPROXY_TCP_LOG_FMT 变量替代。请参阅 第 8.2.6 节 “自定义日志格式”,了解如何使用。

# strict equivalent of "option tcplog"
log-format "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts \
            %ac/%fc/%bc/%sc/%rc %sq/%bq"
# or using the HAPROXY_TCP_LOG_FMT variable
log-format "${HAPROXY_TCP_LOG_FMT}"

且 CLF 日志格式在内部被声明为基于此确切字符串的自定义日志格式:

# strict equivalent of "option tcplog clf"
log-format "%{Q}o %{-Q}ci - - [%T] \"TCP \" 000 %B \"\" \"\" %cp \
            %ms %ft %b %s %Th %Tw %Tc %Tt %U %ts-- %ac %fc %bc \
            %sc %rc %sq %bq \"\" \"\" "

部分字段可能因某些配置选项的不同而略有差异,这些字段在下方字段名后以星号(*)标记。

示例:

    frontend fnt
        mode tcp
        option tcplog
        log global
        default_backend bck

    backend bck
        server srv1 127.0.0.1:8000

>>> Feb  6 12:12:56 localhost \
      haproxy[14387]: 10.0.1.2:33313 [06/Feb/2009:12:12:51.443] fnt \
      bck/srv1 0/0/5007 212 -- 0/0/0/0/3 0/0

字段格式 从上例中提取 1 process_name ‘[’ pid ‘]:’ HAProxy[14387]: 2 client_ip ‘:’ client_port 10.0.1.2:33313 3 ‘[’ accept_date ‘]’ [06/Feb/2009:12:12:51.443] 4 frontend_name fnt 5 backend_name ‘/’ server_name bck/srv1 6 Tw ‘/’ Tc ‘/’ Tt* 0/0/5007 7 bytes_read* 212 8 termination_state – 9 actconn ‘/’ feconn ‘/’ beconn ‘/’ srv_conn ‘/’ retries* 0/0/0/0/3 10 srv_queue ‘/’ backend_queue 0/0

详细字段说明:

  • “client_ip” 是发起 TCP 连接至 HAProxy 的客户端 IP 地址。如果连接是在 Unix 套接字上接受的,则 IP 地址将被替换为单词 “unix”。请注意,当连接在配置了 “accept-proxy” 的套接字上接受,且正确使用了 PROXY 协议,或在配置了 “accept-netscaler-cip” 的套接字上接受,且正确使用了 NetScaler 客户端 IP 插入协议时,日志将反映转发连接的信息。

  • “client_port” 是发起连接的客户端的 TCP 端口。如果连接是在 Unix 套接字上接受的,则端口将被接受该连接的套接字 ID 替代,该 ID 同样会在统计信息接口中报告。

  • “accept_date” 是 HAProxy 接收到连接的确切日期(若系统队列中存在延迟,该日期可能与网络上观察到的日期略有差异)。该日期通常与上游防火墙日志中出现的日期一致。在 HTTP 模式下,accept_date 字段将在连接准备好接收新请求的时刻重置(HTTP/1 为上一个响应结束时,HTTP/2 为上一个请求结束后立即)。

  • “frontend_name” 是接收并处理该连接的前端(或监听器)的名称。

  • “backend_name” 是用于管理与服务器连接的后端(或监听器)的名称。若未应用切换规则,其值将与前端相同,这对 TCP 应用程序而言较为常见。

  • “server_name” 是连接最后被发送至的服务器名称,若发生连接错误并触发重分派,该名称可能与首个服务器不同。请注意,该服务器属于处理请求的后端。若连接在到达服务器前被中止,则显示为 “<NOSRV>” 而非服务器名称。

  • “Tw” 是连接在各个队列中等待的总时间,单位为毫秒。如果连接在进入队列前被中止,则该值可能为 “-1”。更多详情请参见下方 “Timers”。

  • “Tc” 是连接至最终服务器期间花费的总时间(单位:毫秒),包含重试时间。若在建立连接前连接被中止,则该值可能为 “-1”。更多详情请参见下方 “Timers”。

  • “Tt” 是从 accept 到最后一次关闭之间经过的总时间,单位为毫秒,涵盖所有可能的处理过程。有一个例外情况:若指定了 “option logasap”,则时间计数会在日志发出时停止。此时,数值前会附加一个 “+” 号,表示最终值将更大。有关更多详情,请参见下方 “Timers”。

  • “bytes_read” 是在记录日志时,从服务器传输到客户端的总字节数。若指定了 “option logasap”,该值前会加上 “+” 号,表示最终值可能更大。请注意,该值为 64 位计数器,因此日志分析工具必须能够处理该值而不会溢出。

  • “termination_state” 是会话结束时所处的条件。这表示会话状态、导致会话终止的一方以及终止原因(超时、错误等)。正常标志应为 “–",表示会话由任一端关闭,且缓冲区中无剩余数据。详见下文“断开连接时的流状态”。

  • “actconn” 是会话记录时进程的并发连接总数。该值可用于检测是否达到每进程的系统限制。例如,当多个连接错误发生时,若 actconn 接近 512,很可能系统将进程的文件描述符使用上限设为 1024,且所有文件描述符均已耗尽。请参阅 第 3 节 “全局段”以了解如何调整系统设置。

  • “feconn” 是会话记录时前端的并发连接总数。该值可用于估算维持高负载所需的资源量,并检测前端的 “maxconn” 是否已达到。当该值出现大幅跃升时,通常是因为后端服务器发生拥塞,但有时也可能由拒绝服务攻击引起。

  • “beconn” 是会话记录时后端处理的并发连接总数。该数值包括后端服务器上当前活跃的并发连接总数,以及队列中等待的连接数量。可用于估算支持特定应用高负载所需的额外服务器数量。当该数值出现大幅跃升时,通常表明后端服务器存在拥塞,但有时也可能由拒绝服务攻击引起。

  • “srv_conn” 是会话记录时服务器上仍处于活跃状态的并发连接总数。该值绝不会超过服务器配置的 “maxconn” 参数。若该值经常接近或等于服务器的 “maxconn”,说明流量控制参与程度较高,表明服务器的 maxconn 值可能过低,或用于处理负载的服务器数量不足,无法实现最优响应时间。当仅有一个服务器的 “srv_conn” 值较高时,通常意味着该服务器存在某些问题,导致连接处理时间长于其他服务器。

  • “retries” 是该会话在尝试连接服务器时经历的连接重试次数。通常情况下应为零,除非服务器在连接尝试的瞬间正在停止。频繁重试通常表明 HAProxy 与服务器之间存在网络问题,或服务器端系统队列配置不当,导致无法将新连接加入队列。该字段可选择性地以加号 ‘+’ 作为前缀,表示在初始服务器达到最大重试次数后,会话已发生重分派。此时日志中显示的服务器名称为重分派目标服务器,而非首次尝试的服务器,尽管在使用哈希算法等情况下两者可能相同。因此,一般规则是:当重试次数前出现 ‘+’ 符号时,该次数不应归因于日志中记录的服务器。

  • “srv_queue” 是在当前请求之前,服务器队列中已处理的请求数量。当请求未经过服务器队列时,该值为 0。通过将请求在队列中等待的时间除以队列中的请求数量,可估算服务器响应时间的近似值。请注意,若会话发生重分派并经过两个服务器队列,其位置将累加。除非发生重分派,否则请求不应同时经过服务器队列和后端队列。

  • “backend_queue” 是在当前请求之前,后端全局队列中已处理的请求数量。当请求未经过全局队列时,该值为 0。该值可用于估算平均队列长度,除以服务器的 “maxconn” 参数后,即可得出缺失服务器的数量。请注意,若会话发生重分派,请求可能两次经过后端队列,此时两个位置将累加。除非发生重分派,否则请求不应同时经过服务器队列和后端队列。

8.2.3. HTTP 日志格式

本文档中的 HTTP 格式最为完整,且最适用于 HTTP 代理。当在前端中指定 “option httplog” 时启用该格式。它提供的信息级别与 TCP 格式相同,同时具备 HTTP 协议特有的附加功能。与 TCP 格式类似,日志通常在流结束时发出,除非指定了 “option logasap”,这通常仅对下载站点有意义。匹配 “monitor” 规则的流将永远不会被记录。还可以通过在前端中指定 “option dontlognull”,避免记录客户端未发送任何数据的流。若在前端中指定 “option dontlog-normal”,则成功连接将不会被记录。

HTTP 日志格式在内部被声明为基于以下确切字符串的自定义日志格式,该字符串也可用作扩展格式的基础(如需)。此外,可使用 HAPROXY_HTTP_LOG_FMT 变量替代。请参阅 第 8.2.6 节 “自定义日志格式”,了解如何使用。

# strict equivalent of "option httplog"
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"
# or using the HAPROXY_HTTP_LOG_FMT variable
log-format "${HAPROXY_HTTP_LOG_FMT}"

且 CLF 日志格式在内部被声明为基于此确切字符串的自定义日志格式:

# strict equivalent of "option httplog clf"
log-format "%{+Q}o %{-Q}ci - - [%trg] %r %ST %B \"\" \"\" %cp \
            %ms %ft %b %s %TR %Tw %Tc %Tr %Ta %tsc %ac %fc \
            %bc %sc %rc %sq %bq %CC %CS %hrl %hsl"

大多数字段与 TCP 日志共享,部分字段有所不同。某些字段的值可能因配置选项的不同而略有差异。这些字段在下方字段名后以星号(’*’)标记。

示例:

    frontend http-in
        mode http
        option httplog
        log global
        default_backend bck

    backend static
        server srv1 127.0.0.1:8000

>>> Feb  6 12:14:14 localhost \
      haproxy[14389]: 10.0.1.2:33317 [06/Feb/2009:12:14:14.655] http-in \
      static/srv1 10/0/30/69/109 200 2750 - - ---- 1/1/1/1/0 0/0 {1wt.eu} \
      {} "GET /index.html HTTP/1.1"

字段格式 从上例中提取 1 process_name ‘[’ pid ‘]:’ HAProxy[14389]: 2 client_ip ‘:’ client_port 10.0.1.2:33317 3 ‘[’ request_date ‘]’ [06/Feb/2009:12:14:14.655] 4 frontend_name http-in 5 backend_name ‘/’ server_name static/srv1 6 TR ‘/’ Tw ‘/’ Tc ‘/’ Tr ‘/’ Ta* 10/0/30/69/109 7 status_code 200 8 bytes_read* 2750 9 captured_request_cookie - 10 captured_response_cookie - 11 termination_state —- 12 actconn ‘/’ feconn ‘/’ beconn ‘/’ srv_conn ‘/’ retries* 1/1/1/1/0 13 srv_queue ‘/’ backend_queue 0/0 14 ‘{’ captured_request_headers* ‘}’ {HAProxy.1wt.eu} 15 ‘{’ captured_response_headers* ‘}’ {} 16 ‘”’ http_request ‘”’ “GET /index.html HTTP/1.1”

详细字段说明:

  • “client_ip” 是发起 TCP 连接至 HAProxy 的客户端 IP 地址。如果连接是在 Unix 套接字上接受的,则 IP 地址将被替换为单词 “unix”。请注意,当连接在配置了 “accept-proxy” 的套接字上接受,且正确使用了 PROXY 协议,或在配置了 “accept-netscaler-cip” 的套接字上接受,且正确使用了 NetScaler 客户端 IP 插入协议时,日志将反映转发连接的信息。

  • “client_port” 是发起连接的客户端的 TCP 端口。如果连接是在 Unix 套接字上接受的,则端口将被接受该连接的套接字 ID 替代,该 ID 同样会在统计信息接口中报告。

  • “request_date” 是 HAProxy 收到 HTTP 请求第一个字节的确切时间(日志字段 %tr)。

  • “frontend_name” 是接收并处理该连接的前端(或监听器)的名称。

  • “backend_name” 是用于管理与服务器连接的后端(或监听器)的名称。若未应用切换规则,该名称将与前端相同。

  • “server_name” 是连接最后被发送至的服务器名称,若发生连接错误并触发重分派,该名称可能与首个服务器不同。请注意,该服务器属于处理请求的后端。若请求在到达服务器前被中止,则显示为 “<NOSRV>” 而非服务器名称。若请求被统计信息子系统拦截,则显示为 “<STATS>"。

  • “TR” 是在接收到首个字节后,等待客户端发送完整 HTTP 请求(不包含正文)所花费的总时间,单位为毫秒。若连接在完整请求接收完成前被中止,或接收到无效请求,则该值可能为 “-1”。该值通常应非常小,因为请求通常可容纳于单个数据包中。此处时间过长通常表明客户端与 HAProxy 之间存在网络问题,或请求为手动输入。详见 第 8.4 节 “时间事件” 获取更多详情。

  • “Tw” 是连接在各个队列中等待的总时间,单位为毫秒。如果连接在进入队列前被中止,则该值可能为 “-1”。有关更多详细信息,请参见 第 8.4 节 “时间事件”。

  • “Tc” 是连接至最终服务器期间花费的总时间(单位:毫秒),包含重试时间。若请求在建立连接前被中止,则该值可能为 “-1”。更多详情请参见 第 8.4 节 “时间事件”。

  • “Tr” 是客户端等待服务器发送完整 HTTP 响应所花费的总时间(单位:毫秒),不包含数据传输时间。若请求在完整响应接收前被中止,则该值可能为 “-1”。该时间通常与服务器处理请求的时间一致,但可能受客户端向服务器发送的数据量影响。在 “GET” 请求中,若该值过大,通常表明服务器过载。更多详情请参见 第 8.4 节 “时间事件”。

  • “Ta” 是请求在 HAProxy 中保持活跃的时间,单位为毫秒,表示从接收到请求的第一个字节到发送响应的最后一个字节所经过的总时间。该时间涵盖所有可能的处理过程,但不包括握手时间(参见 Th)和空闲时间(参见 Ti)。有一个例外情况:若指定了 “option logasap”,则时间计数将在日志发出时停止。此时,数值前会附加一个 “+” 号,表示最终结果将更大。详情请参见 第 8.4 节 “时间事件”。

  • “status_code” 是 HAProxy 返回给客户端的 HTTP 状态码。该状态码通常由服务器设置,但在服务器无法访问或其响应被 HAProxy 阻断时,也可能由 HAProxy 设置。

  • “bytes_read” 是在记录日志时向客户端传输的总字节数。该数值包含 HTTP 头。若指定 “option logasap”,此值前会附加 “+” 号,表示最终值可能更大。请注意,该数值为 64 位计数器,因此日志分析工具必须能够处理该数值而不会溢出。

  • “captured_request_cookie” 是一个可选的“name=value”条目,表示客户端在请求中携带了该 Cookie。Cookie 名称及其最大长度由前端配置中的“capture cookie”语句定义。当该选项未设置时,该字段为单个连字符(’-’)。仅可捕获一个 Cookie,通常用于跟踪客户端与服务器之间的会话 ID 交换,以检测因应用程序缺陷导致的客户端会话交叉问题。详情请参阅下文“捕获 HTTP 头和 Cookie”段。

  • “captured_response_cookie” 是一个可选的“name=value”条目,表示服务器在其响应中返回了 Cookie。Cookie 名称及其最大长度由前端配置中的“capture cookie”语句定义。当该选项未设置时,该字段为单个连字符(’-’)。仅可捕获一个 Cookie,通常用于跟踪客户端与服务器之间的会话 ID 交换,以检测因应用程序缺陷导致的客户端会话交叉问题。详情请参阅下方“捕获 HTTP 头和 Cookie”段。

  • “termination_state” 是流结束时所处的条件。这表示流状态,哪一端导致流结束,以及原因(超时、错误等),类似于 TCP 日志,并包含最后两个字符中关于 Cookie 持久化操作的信息。正常标志应以 “–” 开头,表示流由任一端关闭,且缓冲区中无剩余数据。详见下文“断开连接时的流状态”获取更多详情。

  • “actconn” 是流被记录时进程的并发连接总数。 该值可用于检测是否达到每进程的系统限制。例如,当多个连接错误发生时,若 actconn 接近 512 或 1024,很可能表明系统将进程的文件描述符使用上限设为 1024,且所有文件描述符均已耗尽。 请参阅 第 3 节 “全局段”以了解如何调整系统配置。

  • “feconn” 是流记录时前端的并发连接总数。 该值有助于估算维持高负载所需的资源量,并检测前端的 “maxconn” 是否已达到。 该值通常出现大幅跃升时,往往是因为后端服务器发生拥塞,但有时也可能由拒绝服务攻击引起。

  • “beconn” 是在日志记录时后端处理的并发连接总数。该数值包括后端服务器上当前活跃的并发连接数以及队列中等待的连接数。可用于估算支持特定应用高负载所需的额外服务器数量。当该值出现大幅跃升时,通常表明后端服务器存在拥塞,但有时也可能由拒绝服务攻击引起。

  • “srv_conn” 是流记录时服务器上仍处于活跃状态的并发连接总数。该值绝不会超过服务器配置的 “maxconn” 参数。若该值经常接近或等于服务器的 “maxconn”,表明流量控制参与程度较高,即服务器的 maxconn 值可能过低,或用于处理负载的服务器数量不足,无法实现最优响应时间。当仅有一个服务器的 “srv_conn” 值较高时,通常意味着该服务器存在某些问题,导致请求处理时间长于其他服务器。

  • “retries” 是此流在尝试连接服务器时经历的连接重试次数。正常情况下应为零,除非服务器在连接尝试的同一时刻被停止。频繁重试通常表明 HAProxy 与服务器之间存在网络问题,或服务器端系统队列配置不当,导致无法将新连接排队。该字段可选择性地以加号 ‘+’ 开头,表示在初始服务器达到最大重试次数后,连接已被重分派。此时日志中显示的服务器名称是连接被重分派至的目标服务器,而非首个服务器,尽管在某些情况下(例如使用哈希时)两者可能相同。因此,一般规则是:当重试次数前出现 ‘+’ 符号时,该次数不应归因于日志中记录的服务器。

  • “srv_queue” 是在当前请求之前,服务器队列中已处理的请求数量。当请求未经过服务器队列时,该值为 0。通过将请求在队列中等待的时间除以队列中的请求数量,可估算服务器响应时间的近似值。请注意,若流经历重分派并经过两个服务器队列,其位置将累加。除非发生重分派,否则请求不应同时经过服务器队列和后端队列。

  • “backend_queue” 是在当前请求之前,后端全局队列中已处理的请求数量。当请求未经过全局队列时,该值为 0。该值可用于估算平均队列长度,除以服务器的 “maxconn” 参数后,即可得出缺失服务器的数量。请注意,若流经历重分派,可能两次经过后端队列,此时两个位置将累加。除非发生重分派,否则请求不应同时经过服务器队列和后端队列。

  • “captured_request_headers” 是由于前端中存在 “capture request header” 语句而捕获的请求头列表。可捕获多个头,它们之间以竖线字符(’|’)分隔。当未启用捕获时,不显示花括号,导致后续字段位置偏移。请注意,此字段可能包含空格,使用时需要比未使用时更智能的日志解析器。有关更多详细信息,请参阅下方“捕获 HTTP 头和 Cookie”段。

  • “captured_response_headers” 是由于前端中存在 “capture response header” 语句而在响应中捕获的头列表。可捕获多个头,它们将使用竖线字符(’|’)分隔。当未启用捕获时,大括号不会出现,导致后续字段位置偏移。请注意,此字段可能包含空格,使用时需要比未使用时更智能的日志解析器。有关更多详细信息,请参阅下方“捕获 HTTP 头和 Cookie”段。

  • “http_request” 是完整的 HTTP 请求行,包含方法、请求路径和 HTTP 版本字符串。不可打印字符会被编码(详见下文“不可打印字符”段)。此字段始终位于最后,始终用引号包围,且是唯一可包含引号的字段。若向日志格式中添加新字段,将插入此字段之前。当请求过大且超出标准 syslog 缓冲区(1024 字符)容量时,该字段可能被截断。因此,此字段必须始终位于最后。

8.2.4. HTTPS 日志格式

HTTPS 格式最适合用于 SSL 连接上的 HTTP。它是 HTTP 格式(参见 第 8.2.3 节 )的扩展,在其中添加了与 SSL 相关的信息。当在前端中指定 “option httpslog” 时,该格式被启用。与 TCP 和 HTTP 格式类似,日志通常在流结束时发出,除非指定了 “option logasap”。若流匹配 “monitor” 规则,则该流将不会被记录。也可通过在前端中指定 “option dontlognull” 来避免记录客户端未发送任何数据的流。若在前端中指定 “option dontlog-normal”,则正常连接将不会被记录。

HTTPS 日志格式在内部被定义为基于以下精确字符串的自定义日志格式,该字符串也可用作扩展格式的基础(如需)。此外,可使用 HAPROXY_HTTPS_LOG_FMT 变量替代。请参阅 第 8.2.6 节 “自定义日志格式”,了解如何使用。

# strict equivalent of "option httpslog"
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 \
           %[fc_err]/%[ssl_fc_err,hex]/%[ssl_c_err]/\
           %[ssl_c_ca_err]/%[ssl_fc_is_resumed] %[ssl_fc_sni]/%sslv/%sslc"
# or using the HAPROXY_HTTPS_LOG_FMT variable
log-format "${HAPROXY_HTTPS_LOG_FMT}"

该格式本质上是 HTTP 格式(参见 第 8.2.3 节 ),并在其基础上附加了新字段。新增字段(第 17 行和第 18 行)将在下文详述。关于 HTTP 字段的说明,请参见 HTTP 段。

示例:

    frontend https-in
        mode http
        option httpslog
        log global
        bind *:443 ssl crt mycerts/srv.pem ...
        default_backend bck

    backend static
        server srv1 127.0.0.1:8000 ssl crt mycerts/clt.pem ...

>>> Feb  6 12:14:14 localhost \
      haproxy[14389]: 10.0.1.2:33317 [06/Feb/2009:12:14:14.655] https-in \
      static/srv1 10/0/30/69/109 200 2750 - - ---- 1/1/1/1/0 0/0 {1wt.eu} \
      {} "GET /index.html HTTP/1.1" 0/0/0/0/0 \
      1wt.eu/TLSv1.3/TLS_AES_256_GCM_SHA384

字段格式 从上例中提取 1 process_name ‘[’ pid ‘]:’ HAProxy[14389]: 2 client_ip ‘:’ client_port 10.0.1.2:33317 3 ‘[’ request_date ‘]’ [06/Feb/2009:12:14:14.655] 4 frontend_name https-in 5 backend_name ‘/’ server_name static/srv1 6 TR ‘/’ Tw ‘/’ Tc ‘/’ Tr ‘/’ Ta* 10/0/30/69/109 7 status_code 200 8 bytes_read* 2750 9 captured_request_cookie - 10 captured_response_cookie - 11 termination_state —- 12 actconn ‘/’ feconn ‘/’ beconn ‘/’ srv_conn ‘/’ retries* 1/1/1/1/0 13 srv_queue ‘/’ backend_queue 0/0 14 ‘{’ captured_request_headers* ‘}’ {HAProxy.1wt.eu} 15 ‘{’ captured_response_headers* ‘}’ {} 16 ‘”’ http_request ‘"’ “GET /index.html HTTP/1.1” 17 fc_err ‘/’ ssl_fc_err ‘/’ ssl_c_err ‘/’ ssl_c_ca_err ‘/’ ssl_fc_is_resumed 0/0/0/0/0 18 ssl_fc_sni ‘/’ ssl_version ‘/’ ssl_ciphers 1wt.eu/TLSv1.3/TLS_AES_256_GCM_SHA384

详细字段说明:

  • “fc_err” 是前端一侧连接的状态。它对应于 “fc_err” 样本提取。有关更多信息,请参阅 “fc_err” 和 “fc_err_str” 样本提取函数。

  • “ssl_fc_err” 是从前端视角看,该连接上首次 SSL 错误栈中的最后一个错误。可用于检测 SSL 握手错误等情形。若一切正常,则其值为 0。有关更多信息,请参见 “ssl_fc_err” 样本提取的说明。

  • “ssl_c_err” 表示客户端证书验证过程的状态。即使验证错误码非空,握手仍可能成功,若该错误码属于被忽略的类型。请参见 “ssl_c_err” 样本提取和 “crt-ignore-err” 选项。

  • “ssl_c_ca_err” 表示客户端证书链验证过程的状态。握手过程可能成功,但若验证错误码非空,且该错误码属于被忽略的类型,则仍可能出现这种情况。请参见 “ssl_c_ca_err” 样本提取和 “ca-ignore-err” 选项。

  • “ssl_fc_is_resumed” 在传入的 TLS 会话通过有状态缓存或无状态票据恢复时为真。请注意,一个 TLS 会话可被多个请求共享。

  • “ssl_fc_sni” 是客户端用于选择要使用的证书的 SNI(服务器名称指示)。通常与连接的第一个请求的主机名匹配。若该字段缺失,可能表示客户端未发送 SNI,此时 HAProxy 将使用默认证书,或在启用 strict-sni 时拒绝连接。

  • “ssl_version” 是前端的 SSL 版本。

  • “ssl_ciphers” 是连接所使用的 SSL 密码。

8.2.5. 错误日志格式

当入站连接因 SSL 握手失败或无效的 PROXY 协议头而中断时,HAProxy 将使用较短的固定行格式记录该事件,除非通过 “error-log-format” 行定义了专用错误日志格式。默认情况下,日志级别为 LOG_INFO,除非在后端中设置了选项 “log-separate-errors”,此时将使用 LOG_ERR 级别。若设置了 “dontlognull” 选项,则不会记录未交换任何数据的连接(例如探测连接)。

默认格式如下所示:

  >>> Dec  3 18:27:14 localhost \
        haproxy[6103]: 127.0.0.1:56059 [03/Dec/2012:17:35:10.380] frt/f1: \
        Connection error during SSL handshake

Field   Format                                Extract from the example above
    1   process_name '[' pid ']:'                             haproxy[6103]:
    2   client_ip ':' client_port                            127.0.0.1:56059
    3   '[' accept_date ']'                       [03/Dec/2012:17:35:10.380]
    4   frontend_name "/" bind_name ":"                              frt/f1:
    5   message                        Connection error during SSL handshake

这些字段仅提供最少的信息,以帮助排查连接失败问题。

通过使用 “error-log-format” 指令,将不再使用上述传统日志格式,所有错误日志行将遵循已定义的格式。

一个较为完整的 error-log-format 示例,将报告源地址和端口、连接 accept() 日期、前端名称、进程上和该前端的活跃连接数、HAProxy 内部错误标识符(前端连接)、十六进制 OpenSSL 错误编号(可复制粘贴至 “openssl errstr” 以获取完整解码)、客户端证书提取状态(0 表示无错误)、使用 CA 验证客户端证书的状态(0 表示无错误)、连接是否为新建或已恢复的布尔值、客户端提供的可选服务器名称指示(SNI)、SSL 版本名称以及连接上使用的 SSL 密码套件(如有)。请注意,后端连接错误不会在此处报告,因为后端连接失败的前提是其已成功通过流,因此将作为常规流量日志记录(参见 option httplog 或 option httpslog)。

# detailed frontend connection error log
error-log-format "%ci:%cp [%tr] %ft %ac/%fc %[fc_err]/\
      %[ssl_fc_err,hex]/%[ssl_c_err]/%[ssl_c_ca_err]/%[ssl_fc_is_resumed] \
      %[ssl_fc_sni]/%sslv/%sslc"

8.2.6. 自定义日志格式

历史上,自定义日志格式仅用于生成日志。但当其被用于通过组合多个复杂表达式来生成字符串时,其便捷性使得许多原本仅接受字符串作为参数的指令开始采用自定义日志格式定义。如今,这些指令可接受的参数类型已扩展为支持此类自定义日志格式定义。本文档中通常以“<fmt>”表示的此类参数,其定义方式与本节所述的 “log-format” 指令的参数完全相同。

当涉及日志且默认日志格式无法满足需求时,可极为细致地定义新的日志格式。由于从零开始创建日志格式并非总是简单任务,强烈建议首先查看现有格式(“option tcplog”、“option httplog”、“option httpslog”),选择最接近预期的格式,复制其 “log-format” 对应字符串,并进行调整。

自定义日志格式定义从配置角度而言是一个单一参数。这意味着其内容不得包含空格(空格或制表符),除非这些空格通过反斜杠字符(’\’)进行转义,或整个定义被引号包围(这是推荐的使用方式)。由于历史经验表明,未加引号的格式字符串极易出错,单个遗漏的反斜杠字符就可能导致格式被静默截断,因此不再建议使用未加引号的格式字符串。尽管由于 1.5-dev9 版本发布后日志格式的广泛采用,此类配置至今仍普遍存在(该版本发布三年前引号尚不可用),但建议现在将其转换为带引号的字符串,并移除反斜杠。

日志格式定义由任意数量的日志格式项组成,各项之间用文本和空格分隔。日志格式项以字符 ‘%’ 开头。若需原样输出 ‘%’,必须在其前添加另一个 ‘%’,形成 ‘%%’。

日志格式项可以是别名或样本表达式:

如果某项名称用方括号(’[’ .. ‘]’)括起,则将其用作样本表达式规则(参见 第 7.3 节 )。这可用于添加一些较少见的信息,例如客户端 SSL 证书的 DN,或记录将用于向粘性表中存储条目时所使用的键。该用法也常用于非日志类动作(如头操作、变量处理等)。

否则,如果该项使用字母数字名称命名,则为别名。(有关可用别名的列表,请参见下表)

项目可使用花括号(’{}’)传递参数,多个参数在花括号内以逗号分隔。可通过在标志前加 ‘+’ 或 ‘-’ 符号来添加或移除标志(详见下文可用标志列表)。

特殊别名 “%o” 可用于将其标志传播到同一格式字符串中的所有其他 logformat 项。在使用带引号的(“Q”)和转义的(“E”)字符串格式时,此功能尤为便捷。

特殊别名 “%OG” 可用于以人类可读格式检索日志来源(日志生成位置)。在使用 “option logasap” 时尤为有用,因为某些日志变量或样本提取可能在日志格式表达式被评估的时间或位置不同而报告不完整值,或表现出不同行为。可能的取值包括:

  • “sess_error”:在会话错误处理期间生成日志
  • “sess_killed”:在会话中止期间生成日志(已终止的初始会话)
  • “txn_accept”:在前端连接被接受后立即生成日志
  • “txn_request”:在客户端请求接收后生成日志
  • “txn_connect”:在后端连接建立后生成日志
  • “txn_response”:在服务器响应处理期间生成日志
  • “txn_close”:在最终事务步骤生成日志,关闭前
  • “unspec”:未知或未指定 “%OG” 仅在日志记录上下文中相关

项目可选择性地通过 (’()’) 命名。名称必须紧跟在 ‘%’ 之后(位于参数之前)。当设置编码标志如 “json” 或 “cbor” 时,该名称将自动作为键名使用。若未指定编码标志(默认情况),则忽略项目名称。也可通过在名称后附加 ‘:type’ 强制指定项目的输出类型,格式如下:%(itemname:itemtype)aliasname 或 %(itemname:itemtype)[expr],其中 itemtype 可为 ‘str’、‘sint’ 或 ‘bool’。指定类型仅在使用编码方法时有意义。此外,支持为匿名项目提供空名称以强制输出类型:%(:itemtype),即在未全局设置编码时使用,详见下方标志定义。

由于自定义日志格式最初仅用于日志记录,因此在不同使用场景下对不可打印字符和不安全字符(ASCII 码 32 至 126 以外的字符,以及少数其他字符)的处理存在特殊规则。第 8.6 节 详细说明了日志中具体采取的措施,以确保不会发送可能影响终端输出可读性的不安全编码。当用于构造 HTTP 头、健康检查或响应负载时,规则较为宽松,仅对 HTTP 头字段中禁止出现的字符使用百分号 % 前缀的十六进制编码进行替换。通常这不会造成问题,但在某些情况下可能影响输出,例如在构建错误页面或完整响应负载时,期望原样重现的换行符可能显示为 “%0A”。

请注意:在配置指令 “log-format”、“log-format-sd” 和 “unique-id-format” 中,空格被视为分隔符并被合并。

请注意:使用 RFC5424 syslog 消息格式时,PARAM-VALUE 内部的字符 ‘"’、\ 和 ‘]’ 应使用 \ 作为前缀进行转义(详见 https://tools.ietf.org/html/rfc5424#section-6.3.3 以获取更多详情)。在此类情况下,应考虑使用标志 “E”。

支持的项目标志包括(可从项目的参数中启用或禁用):

  • Q: 对字符串进行转义
  • X: 十六进制表示(IP 地址、端口、%Ts、%rt、%pid)
  • E: 使用 ‘\’ 作为前缀,对字符串中的引号 ‘"’、’\’ 和 ‘]’ 进行转义(用于 RFC5424 结构化数据日志格式)
  • bin: 尝试保留二进制数据,这在处理输出二进制数据的样本表达式时可能有用,以保留原始数据。但需注意,这显然可能生成不可打印字符,包括空字节(NULL-byte),而大多数 syslog 接收端不期望此类数据。因此,该选项主要适用于 set-var-fmt、环形缓冲区和具备二进制能力的日志接收端。此选项只能全局设置(使用 %o),若在单个项的选项中设置将被忽略。
  • json: 自动将值以 JSON 格式编码(全局设置时,仅考虑命名的日志格式项)。未完成的数值(例如:使用 logasap 时的 ‘%B’),通常以 ‘+’ 前缀但不进行编码,将原样编码。同时,’+E’ 选项将被忽略。
  • cbor: 自动将值以 CBOR 格式编码(全局设置时,仅考虑命名的日志格式项)。默认情况下,CBOR 编码数据以十六进制形式表示,以确保其在 stdout 上可打印,并可与常规 syslog 接收端配合使用。与 json 编码类似,未完成的数值将原样编码,’+E’ 选项将被忽略。当与 ‘+bin’ 选项结合使用时,将直接生成原始二进制 CBOR 负载。请注意,这显然可能生成不可打印字符,因此主要适用于 set-var-fmt、环形缓冲区和具备二进制能力的日志接收端。

示例:

log-format %T\ %t\ Some\ Text
log-format %{+Q}o\ %t\ %s\ %{-Q}r

log-format-sd %{+Q,+E}o\ [exampleSDID@1234\ header=%[capture.req.hdr(0)]]

log-format "%{+json}o %(request)r %(custom_expr)[str(custom)]"
log-format "%{+cbor}o %(request)r %(custom_expr)[str(custom)]"

请参阅下表以了解当前定义的别名:

  +---+------+------------------------------------------------------+---------+
  | R | alias| field name (8.2.2 and 8.2.3 for description)         | type    |
  |   |      | sample fetch alternative                             |         |
  +===+======+======================================================+=========+
  |   | %o   | special, apply flags on all following items          |         |
  +---+------+------------------------------------------------------+---------+
  |                          date formats                                     |
  +---+------+------------------------------------------------------+---------+
  |   | %T   | Accept date UTC + timezone                           |         |
  |   |      | %[accept_date,utime("%d/%b/%Y:%H:%M:%S %z")]         | date    |
  +---+------+------------------------------------------------------+---------+
  |   | %Tl  | Accept date local + timezone                         |         |
  |   |      | %[accept_date,ltime("%d/%b/%Y:%H:%M:%S %z")]         | date    |
  +---+------+------------------------------------------------------+---------+
  |   | %Ts  | Accept date as a UNIX timestamp                      | numeric |
  |   |      | %[accept_date]                                       |         |
  +---+------+------------------------------------------------------+---------+
  |   | %t   | Accept date local (with millisecond resolution)      |         |
  |   |      | %[accept_date(ms),ms_ltime("%d/%b/%Y:%H:%M:%S.%3N")] | date    |
  +---+------+------------------------------------------------------+---------+
  |   | %ms  | Accept date milliseconds                             |         |
  |   |      | %[accept_date(ms),ms_utime("%3N")]                   | numeric |
  +---+------+------------------------------------------------------+---------+
  | H | %tr  | Request date local (with millisecond resolution)     |         |
  |   |      | %[request_date(ms),ms_ltime("%d/%b/%Y:%H:%M:%S.%3N")]| date    |
  +---+------+------------------------------------------------------+---------+
  | H | %trg | Request date UTC + timezone                          |         |
  |   |      | %[request_date,utime("%d/%b/%Y:%H:%M:%S %z")]        | date    |
  +---+------+------------------------------------------------------+---------+
  | H | %trl | Request date local + timezone                        |         |
  |   |      | %[request_date,ltime("%d/%b/%Y:%H:%M:%S %z")]        | date    |
  +---+------+------------------------------------------------------+---------+
  |                          Timing events                                    |
  +---+------+------------------------------------------------------+---------+
  | H | %Ta  | Active time of the request (from TR to end)          |         |
  |   |      | %[txn.timer.total]                                   | numeric |
  +---+------+------------------------------------------------------+---------+
  |   | %Tc  | Tc                                                   |         |
  |   |      | %[bc.timer.connect]                                  | numeric |
  +---+------+------------------------------------------------------+---------+
  |   | %Td  | Td = Tt - (Tq + Tw + Tc + Tr)                        |         |
  |   |      | %[res.timer.data]                                    | numeric |
  +---+------+------------------------------------------------------+---------+
  |   | %Th  | connection handshake time (SSL, PROXY proto)         |         |
  |   |      | %[fc.timer.handshake]                                | numeric |
  +---+------+------------------------------------------------------+---------+
  | H | %Ti  | idle time before the HTTP request                    |         |
  |   |      | %[req.timer.idle]                                    | numeric |
  +---+------+------------------------------------------------------+---------+
  | H | %Tq  | Th + Ti + TR                                         |         |
  |   |      | %[req.timer.tq]                                      | numeric |
  +---+------+------------------------------------------------------+---------+
  | H | %TR  | time to receive the full request from 1st byte       |         |
  |   |      | %[req.timer.hdr]                                     | numeric |
  +---+------+------------------------------------------------------+---------+
  | H | %Tr  | Tr (response time)                                   |         |
  |   |      | %[res.timer.hdr]                                     | numeric |
  +---+------+------------------------------------------------------+---------+
  |   | %Tt  | Tt                                                   |         |
  |   |      | %[fc.timer.total]                                    | numeric |
  +---+------+------------------------------------------------------+---------+
  |   | %Tu  | Tu                                                   |         |
  |   |      | %[txn.timer.user]                                    | numeric |
  +---+------+------------------------------------------------------+---------+
  |   | %Tw  | Tw                                                   |         |
  |   |      | %[req.timer.queue]                                   | numeric |
  +---+------+------------------------------------------------------+---------+
  |                          Others                                           |
  +---+------+------------------------------------------------------+---------+
  |   | %B   | bytes_read           (from server to client)         | numeric |
  |   |      | %[res.bytes_in]                                      |         |
  +---+------+------------------------------------------------------+---------+
  | H | %CC  | captured_request_cookie                              | string  |
  +---+------+------------------------------------------------------+---------+
  | H | %CS  | captured_response_cookie                             | string  |
  +---+------+------------------------------------------------------+---------+
  |   | %H   | hostname                                             | string  |
  |   |      | %[hostname]                                          |         |
  +---+------+------------------------------------------------------+---------+
  | H | %HM  | HTTP method (ex: POST)                               | string  |
  |   |      | %[method]
  +---+------+------------------------------------------------------+---------+
  | H | %HP  | HTTP request URI without query string                | string  |
  +---+------+------------------------------------------------------+---------+
  | H | %HPO | HTTP path only (without host nor query string)       | string  |
  +---+------+------------------------------------------------------+---------+
  | H | %HQ  | HTTP request URI query string (ex: ?bar=baz)         | string  |
  |   |      | ?%[query]                                            |         |
  +---+------+------------------------------------------------------+---------+
  | H | %HU  | HTTP request URI (ex: /foo?bar=baz)                  | string  |
  +---+------+------------------------------------------------------+---------+
  | H | %HV  | HTTP version (ex: HTTP/1.0)                          | string  |
  |   |      | HTTP/%[req.ver]                                      |         |
  +---+------+------------------------------------------------------+---------+
  |   | %ID  | unique-id                                            | string  |
  |   |      | %[unique-id]                                         |         |
  +---+------+------------------------------------------------------+---------+
  |   | %ST  | status_code                                          | numeric |
  |   |      | %[txn.status]                                        |         |
  +---+------+------------------------------------------------------+---------+
  |   | %U   | bytes_uploaded       (from client to server)         | numeric |
  |   |      | %[req.bytes_in]                                      |         |
  +---+------+------------------------------------------------------+---------+
  |   | %ac  | actconn                                              |         |
  |   |      | %[act_conn]                                          | numeric |
  +---+------+------------------------------------------------------+---------+
  |   | %b   | backend_name                                         |         |
  |   |      | %[be_name]                                           | string  |
  +---+------+------------------------------------------------------+---------+
  |   | %bc  | beconn      (backend concurrent connections)         | numeric |
  |   |      | %[be_conn]                                           |         |
  +---+------+------------------------------------------------------+---------+
  |   | %bi  | backend_source_ip       (connecting address)         |         |
  |   |      | %[bc_src]                                            | IP      |
  +---+------+------------------------------------------------------+---------+
  |   | %bp  | backend_source_port     (connecting address)         |         |
  |   |      | %[bc_src_port]                                       | numeric |
  +---+------+------------------------------------------------------+---------+
  |   | %bq  | backend_queue                                        | numeric |
  |   |      | %[bc_be_queue]                                       |         |
  +---+------+------------------------------------------------------+---------+
  |   | %ci  | client_ip                 (accepted address)         |         |
  |   |      | %[src]                                               | IP      |
  +---+------+------------------------------------------------------+---------+
  |   | %cp  | client_port               (accepted address)         |         |
  |   |      | %[src_port]                                          | numeric |
  +---+------+------------------------------------------------------+---------+
  |   | %f   | frontend_name                                        | string  |
  |   |      | %[fe_name]                                           |         |
  +---+------+------------------------------------------------------+---------+
  |   | %fc  | feconn     (frontend concurrent connections)         | numeric |
  |   |      | %[fe_conn]                                           |         |
  +---+------+------------------------------------------------------+---------+
  |   | %fi  | frontend_ip              (accepting address)         |         |
  |   |      | %[dst]                                               | IP      |
  +---+------+------------------------------------------------------+---------+
  |   | %fp  | frontend_port            (accepting address)         |         |
  |   |      | %[dst_port]                                          | numeric |
  +---+------+------------------------------------------------------+---------+
  |   | %ft  | frontend_name_transport ('~' suffix for SSL)         | string  |
  +---+------+------------------------------------------------------+---------+
  |   | %lc  | frontend_log_counter                                 | numeric |
  +---+------+------------------------------------------------------+---------+
  |   | %hr  | captured_request_headers default style               | string  |
  +---+------+------------------------------------------------------+---------+
  |   | %hrl | captured_request_headers CLF style                   | string  |
  |   |      |                                                      | list    |
  +---+------+------------------------------------------------------+---------+
  |   | %hs  | captured_response_headers default style              | string  |
  +---+------+------------------------------------------------------+---------+
  |   | %hsl | captured_response_headers CLF style                  | string  |
  |   |      |                                                      | list    |
  +---+------+------------------------------------------------------+---------+
  | L | %OG  | human readable log origin                            | string  |
  +---+------+------------------------------------------------------+---------+
  |   | %pid | PID                                                  |         |
  |   |      | %[pid]                                               | numeric |
  +---+------+------------------------------------------------------+---------+
  | H | %r   | http_request                                         | string  |
  +---+------+------------------------------------------------------+---------+
  |   | %rc  | retries                                              | numeric |
  |   |      | %[txn.redispatched,iif(+,)]%[txn.conn_retries]       |         |
  +---+------+------------------------------------------------------+---------+
  |   | %rt  | request_counter (HTTP req or TCP session)            | numeric |
  |   |      | %[txn.id32]                                          |         |
  +---+------+------------------------------------------------------+---------+
  |   | %s   | server_name                                          | string  |
  |   |      | %[srv_name]                                          |         |
  +---+------+------------------------------------------------------+---------+
  |   | %sc  | srv_conn     (server concurrent connections)         | numeric |
  +---+------+------------------------------------------------------+---------+
  |   | %si  | server_IP                   (target address)         |         |
  |   |      | %[bc_dst]                                            | IP      |
  +---+------+------------------------------------------------------+---------+
  |   | %sp  | server_port                 (target address)         |         |
  |   |      | %[bc_dst_port]                                       | numeric |
  +---+------+------------------------------------------------------+---------+
  |   | %sq  | srv_queue                                            | numeric |
  |   |      | %[bc_srv_queue]                                      |         |
  +---+------+------------------------------------------------------+---------+
  | S | %sslc| ssl_ciphers (ex: AES-SHA)                            |         |
  |   |      | %[ssl_fc_cipher]                                     | string  |
  +---+------+------------------------------------------------------+---------+
  | S | %sslv| ssl_version (ex: TLSv1)                              |         |
  |   |      | %[ssl_fc_protocol]                                   | string  |
  +---+------+------------------------------------------------------+---------+
  |   | %ts  | termination_state                                    | string  |
  |   |      | %[txn.sess_term_state]                               |         |
  +---+------+------------------------------------------------------+---------+
  | H | %tsc | termination_state with cookie status                 | string  |
  +---+------+------------------------------------------------------+---------+
R = Restrictions: H = mode http only; S = SSL only; L = log only

8.3. 高级日志记录选项

一些高级日志选项常被寻找,但仅通过查看各项配置选项往往难以发现。以下是少数可启用更优日志功能的选项入口。有关其用法的更多信息,请参阅关键字参考。

8.3.1. 禁用外部测试日志记录

对 HAProxy 执行健康检查的情况十分常见。有时是第 3 层负载均衡器,例如 LVS 或任何商用负载均衡器,有时则可能是更完整的监控系统,例如 Nagios。当检查频率非常高时,用户常会询问如何禁用这些检查的日志记录。有三种可能的解决方案:

  • 若连接来自任意位置且仅为 TCP 探测,通常建议在前端通过设置 “option dontlognull” 来禁用无数据交换连接的日志记录。该设置同时也会禁用端口扫描日志记录,是否需要此功能应根据实际需求决定。

  • 可以在多种条件下(如源网络、路径、User-Agent 等)使用 “http-request set-log-level silent” 动作。

  • 若测试在已知的 URI 上执行,请使用 “monitor-uri” 将该 URI 声明为专用监控地址。任何发送此请求的主机仅会收到健康检查结果,且该请求不会被记录。

8.3.2. 在日志记录之前等待流终止

在连接结束时记录日志的问题在于,对于长时间的流(如远程终端会话或大文件下载),你无法了解其间发生了什么。此问题可通过在前端配置中指定“option logasap”来规避。HAProxy 将在数据传输开始前尽可能早地记录日志。这意味着在 TCP 情况下,仍会记录与服务器的连接状态;在 HTTP 情况下,则在处理完服务器头后立即记录。此时报告的字节数为发送给客户端的头字节数。为避免与正常日志混淆,总时间字段和字节数前会加上“+”号,表示实际数值肯定更大。

8.3.3. 提高错误日志级别

有时将正常流量日志与错误日志分离更为方便,例如便于从日志文件中监控错误。当使用选项 “log-separate-errors” 时,发生错误、超时、重试、重分派或 HTTP 状态码 5xx 的连接,其 syslog 级别将从 “info” 提升至 “err”。这有助于 syslog 守护进程将日志存储于独立文件中。请注意,必须同时保留在正常流量文件中的错误日志,以确保日志顺序不被破坏。如果已配置 syslog 守护进程将所有高于 “notice” 级别的日志存储于 “admin” 文件中,则需格外小心,因为 “err” 级别高于 “notice”。

8.3.4. 禁用成功连接的日志记录

尽管初听之下可能显得奇怪,但一些大型网站每秒需处理数千条日志,且在长期保存日志或从中检测错误方面面临困难。若在前端中设置选项 “dontlog-normal”,所有正常连接将不会被记录。此处定义的正常连接是指无任何错误、超时、重试或重分派的连接。在 HTTP 中,还会检查状态码,状态码为 5xx 的响应不被视为正常,也将被记录。当然,此举强烈不建议,因为它会移除日志中绝大部分有用信息。仅在别无选择时方可执行。

8.3.5. 日志配置文件

虽然某些指令如 “log-format”、“log-format-sd”、“error-log-format” 或 “log-tag” 可用于全局或在代理级别配置日志格式,但将此类设置尽可能靠近日志端点配置可能更为合适,即按每个 “log” 指令配置。

本文第 “log-profile” 段发挥作用之处在于:“log-profile” 可在配置文件中的任意位置定义。该段接受一组不同的关键字,用于描述针对特定 log 指令所生成日志的构建方式。

通过 “log” 指令,可选择通过名称指定特定的日志配置文件。同一配置文件可从多个 “log” 指令中使用。

log-profile <name> 创建一个标识为 <name> 的新日志配置文件

log-tag <string> 使用 “log-tag” 指令全局或按代理覆盖 syslog 日志标签。

在 <step> 上 [drop] [format <fmt>] [sd <sd_fmt>] 重写通常用于在 <step> 日志记录步骤构建日志行的格式字符串。<fmt> 用于重写 “log-format” 或 “error-log-format” 字符串(取决于 <step>),而 <sd_fmt> 用于重写 “log-format-sd” 字符串(两者可同时使用)。

“drop” 特殊关键字可用于指定对指定的 <step> 不发出日志。 若先前已定义,该关键字优先于 “format” 和 “sd”。

<step> 的可能取值如下:

  • “accept” :在前端连接被接受后立即生成日志时,覆盖 log-format
  • “request” :在接收到客户端请求后生成日志时,覆盖 log-format
  • “connect” :在后端连接建立后生成日志时,覆盖 log-format
  • “response” :在服务器响应处理过程中生成日志时,覆盖 log-format
  • “close” :在最终事务(txn)步骤生成日志时,覆盖 log-format
  • “error” :在事务错误导致日志生成时,覆盖 error-log-format
  • “any” :覆盖所有日志步骤的 log-format 和 error-log-format,除非声明了更精确的步骤覆盖

请参阅 “do-log” 动作以获取相关的额外 <step> 值。

此设置仅对在使用 “log-format” 指令有意义的上下文中的 “log” 指令有效(例如:http 和 tcp 代理)。否则将被忽略。

示例:

log-profile myprof

  log-tag "custom-tag"

  on error format "%ci: error"
  on connect drop
  on any sd "custom-sd"

listen myproxy
  mode http
  option httplog
  log-tag "normal"

  log stdout format rfc5424 local0
  # success:
  # <134>1 2024-06-12T10:09:11.823400+02:00 - normal 224482 - - 127.0.0.1:53594 [12/Jun/2024:10:09:11.814] myproxy myproxy/<NOSRV> 0/-1/-1/-1/0 200 49 - - LR-- 1/1/0/0/0 0/0 "GET / HTTP/1.1"
  #
  # error:
  # <134>1 2024-06-12T10:09:44.810929+02:00 - normal 224482 - - 127.0.0.1:59258 [12/Jun/2024:10:09:44.426] myproxy myproxy/<NOSRV> -1/-1/-1/-1/384 400 0 - - CR-- 1/1/0/0/0 0/0 "<BADREQ>"

  log 127.0.0.1:514 format rfc5424 profile myprof local0
  # success:
  # <134>1 2024-06-12T10:09:11.823428+02:00 - custom-tag 224482 - custom-sd 127.0.0.1:53594 [12/Jun/2024:10:09:11.814] myproxy myproxy/<NOSRV> 0/-1/-1/-1/0 200 49 - - LR-- 1/1/0/0/0 0/0 "GET / HTTP/1.1"
  #
  # error:
  # <134>1 2024-06-12T10:09:51.566524+02:00 - custom-tag 224482 - - 127.0.0.1: error

8.4. 事件计时

计时器在排查网络问题时提供极大帮助。所有值均以毫秒(ms)为单位报告。这些计时器应与流终止标志配合使用。在 TCP 模式下,若前端启用了 “option tcplog”,将报告 3 个控制点,格式为 “Tw/Tc/Tt”;在 HTTP 模式下,将报告 5 个控制点,格式为 “TR/Tw/Tc/Tr/Ta”。此外,还提供三个其他测量值,分别为 “Th”、“Ti” 和 “Tq”。

HTTP 模式下的时间事件:

                 first request               2nd request
      |<-------------------------------->|<-------------- ...
      t         tr                       t    tr ...
   ---|----|----|----|----|----|----|----|----|--
     : Th   Ti   TR   Tw   Tc   Tr   Td: Ti   ...
     :<---- Tq ---->:                  :
     :<-------------- Tt -------------->:
     :<--        -----Tu--------------->:
               :<--------- Ta --------->:

TCP 模式下的时间事件:

           TCP session
      |<----------------->|
      t                   t
   ---|----|----|----|----|---
      | Th   Tw   Tc   Td |
      |<------ Tt ------->|
  • Th:接受 TCP 连接并完成低层协议握手的总时间。目前,这些协议包括 proxy-protocol 和 SSL。在整个连接生命周期中,此操作可能仅发生一次。此处时间较长可能表明客户端仅预先建立了连接而未发送数据,或因网络问题导致无法在合理时间内完成握手(例如 MTU 问题),或 SSL 握手计算开销过大。请注意,此时间仅在首个请求前报告,因此可对所有请求的值取平均以计算摊销值。后续请求在此处始终报告为零。

该计时器在日志格式中命名为 %Th,作为样本提取时则命名为 fc.timer.handshake。

  • Ti:为 HTTP 请求的空闲时间(仅限 HTTP 模式)。该计时器在握手完成与 HTTP 请求首个字节之间计时。在持久连接模式下处理第二个请求时,计时器在前一个响应传输结束后开始计时。当使用 HTTP/2 等多路复用协议时,计时器在前一个请求结束后立即开始计时。部分浏览器会预先建立与服务器的连接,以降低未来请求的延迟,并将连接保持待命状态直至需要使用。此延迟将被报告为空闲时间。值 -1 表示连接上未收到任何数据。

该计时器在日志格式中命名为 %Ti,作为样本提取时则为 req.timer.idle。

  • TR:获取客户端请求的总时间(仅限 HTTP 模式)。该值表示从接收到首个字节到代理收到标记 HTTP 头结束的空行之间所经过的时间。值 “-1” 表示从未收到头结束标记。这种情况发生在客户端提前关闭或超时时。由于大多数请求可容纳于单个数据包中,该时间通常很短。若时间较长,可能表明在测试过程中手动输入了请求。

该计时器在日志格式中命名为 %TR,作为样本提取时则为 req.timer.hdr。

  • Tq:从接受客户端请求的时刻起,或从上一个响应的最后一个字节发出后开始计算的总时间(仅限 HTTP 模式)。其值严格等于 Th + Ti + TR,除非其中任一项为 -1,此时也返回 -1。在 HTTP 持久连接和浏览器预连接功能出现之前,该计时器曾非常有用。如今建议放弃使用,转而采用 TR,因为空闲时间会显著增加报告中的噪声。

该计时器在日志格式中命名为 %Tq,在样本提取中为 req.timer.tq。

  • Tw:在队列中等待连接槽位所花费的总时间。该值包含后端队列以及服务器队列,取决于队列大小以及服务器完成先前请求所需的时间。值 “-1” 表示请求在进入队列前已被终止,通常发生在无效或被拒绝的请求上。

该计时器在日志格式中命名为 %Tw,作为样本提取时则为 req.timer.queue。

  • Tc:建立与服务器的 TCP 连接所花费的总时间。该值表示代理发送连接请求的时刻,到服务器确认连接的时刻之间的时间间隔,或表示从 TCP SYN 数据包发出,到收到对应的 SYN/ACK 数据包的时间间隔。值 “-1” 表示连接从未建立成功。

该计时器在日志格式中命名为 %Tc,在样本提取中命名为 bc.timer.connect。

  • Tr:服务器响应时间(仅限 HTTP 模式)。该值表示从与服务器建立 TCP 连接的时刻,到服务器发送完整响应头的时刻之间所经过的时间。它仅反映请求处理时间,不包含因数据传输导致的网络开销。请注意,当客户端需向服务器发送数据时(例如在 POST 请求期间),该时间已开始计算,这可能导致观察到的响应时间出现偏差。因此,建议不要过于依赖此字段来评估来自不可信网络后端的客户端发起的 POST 请求。此处值为 “-1” 表示从未收到最后一个响应头(空行),极可能是服务器超时发生在服务器完成请求处理之前,或服务器返回了无效响应。

该计时器在日志格式中命名为 %Tr,作为样本提取时则为 res.timer.hdr。

  • Td:表示响应负载从开始传输到向客户端发送最后一个字节的总耗时。在 HTTP 中,该时间从最后一个响应头发送完成后开始计算(即 Tr 之后)。

发送的数据无法保证客户端能够收到,数据可能滞留在内核或网络中。

该计时器在日志格式中命名为 %Td,在样本提取中命名为 res.timer.data。

  • Ta:HTTP 请求的总活跃时间,指代理接收到请求头第一个字节的时刻,到发出响应体最后一个字节的时刻之间的时长。例外情况是当指定了 “logasap” 选项时,此时仅等于 (TR + Tw + Tc + Tr),并以加号“+”作为前缀。通过该字段,可减去其他有效计时器,推导出 “Td”,即数据传输时间:
Td = Ta - (TR + Tw + Tc + Tr)
Timers with "-1" values have to be excluded from this equation. Note that
"Ta" can never be negative.

This timer is named %Ta as a log-format alias, and txn.timer.total as a
sample fetch.
  • Tt:从代理接受连接到两端均关闭的总流持续时间。当指定 “logasap” 选项时例外。此时,其值仅等于 (Th+Ti+TR+Tw+Tc+Tr),并以 ‘+’ 号前缀。通过从该字段中减去其他有效计时器,可推导出 “Td”,即数据传输时间:
Td = Tt - (Th + Ti + TR + Tw + Tc + Tr)
Timers with "-1" values have to be excluded from this equation. In TCP
mode, "Ti", "Tq" and "Tr" have to be excluded too. Note that "Tt" can never
be negative and that for HTTP, Tt is simply equal to (Th+Ti+Ta).

This timer is named %Tt as a log-format alias, and fc.timer.total as a
sample fetch.
  • Tu:从代理接受请求的时刻到两端连接关闭的时刻,客户端所感知的总估算时间,不包含空闲时间。该指标有助于粗略衡量用户所感知的端到端延迟,避免因请求间持久连接(keep-alive)导致的空闲时间干扰。此计时仅为用户所见时间的估算值,因其假设网络延迟在两个方向上相同。例外情况是当指定 “logasap” 选项时,此时其值仅等于 (Th + TR + Tw + Tc + Tr),并以加号(+)作为前缀。

该计时器在日志格式中命名为 %Tu,在样本提取中命名为 txn.timer.user。

这些超时计时器可提供关于故障原因的宝贵线索。由于 TCP 协议定义的重传延迟为 3、6、12… 秒,因此可以确定,接近 3 秒倍数的超时计时器几乎总是与网络问题(如线路、协商或拥塞)导致的数据包丢失有关。此外,若 “Ta” 或 “Tt” 接近配置中指定的超时值,通常意味着某一流已因超时而被中止。

最常见的场景:

  • 若 “Th” 或 “Ti” 接近 3000,表示客户端与代理之间的数据包可能已丢失。在本地网络中这种情况极为罕见,但在客户端位于远端网络且发送大请求时可能发生。有时,即使没有网络原因,此处也可能出现高于正常值的情况。在攻击期间或资源耗尽状况结束后,HAProxy 可能在几毫秒内接受数千个连接。接受这些连接所花费的时间不可避免地会轻微延迟其他连接的处理,因此在一次性接受数千个新连接后,可能会测量到数十毫秒级别的请求耗时。使用任一持久连接模式时,可能会显示更大的空闲时间,因为 “Ti” 测量的是等待额外请求所花费的时间。

  • 若 “Tc” 接近 3000,表示在服务器连接阶段,服务器与代理之间可能丢失了数据包。该值应始终非常低,本地网络下约为 1 ms,远程网络下应小于几十毫秒。

  • 若 “Tr” 几乎始终低于 3000,仅个别值似乎以 3000 为平均值,代理与服务器之间可能有数据包丢失。

  • 若 “Ta” 即使在字节数较小时也较大,通常是因为 HAProxy 以隧道模式运行时,客户端和服务器均未决定关闭连接,且双方已协商使用持久连接模式。为解决此问题,需在前端或后端指定一种 HTTP 选项,以控制持久连接或关闭选项。当使用 “maxconn” 选项对服务器进行连接调控时,保持 ‘Ta’ 或 ‘Tt’ 尽可能小至关重要,因为除非已有连接释放,否则不会向服务器发送新的连接。

其他值得注意的 HTTP 日志情况(‘xx’ 表示任意需忽略的值):

TR/Tw/Tc/Tr/+Ta  The "option logasap" is present on the frontend and the log
                 was emitted before the data phase. All the timers are valid
                 except "Ta" which is shorter than reality.

-1/xx/xx/xx/Ta   The client was not able to send a complete request in time
                 or it aborted too early. Check the stream termination flags
                 then "timeout http-request" and "timeout client" settings.

TR/-1/xx/xx/Ta   It was not possible to process the request, maybe because
                 servers were out of order, because the request was invalid
                 or forbidden by ACL rules. Check the stream termination
                 flags.

TR/Tw/-1/xx/Ta   The connection could not establish on the server. Either it
                 actively refused it or it timed out after Ta-(TR+Tw) ms.
                 Check the stream termination flags, then check the
                 "timeout connect" setting. Note that the tarpit action might
                 return similar-looking patterns, with "Tw" equal to the time
                 the client connection was maintained open.

TR/Tw/Tc/-1/Ta   The server has accepted the connection but did not return
                 a complete response in time, or it closed its connection
                 unexpectedly after Ta-(TR+Tw+Tc) ms. Check the stream
                 termination flags, then check the "timeout server" setting.

8.5. 断开连接时的流状态

TCP 和 HTTP 日志在活跃连接数之前提供流终止指示符,位于 “termination_state” 字段中。在 TCP 模式下,该字段长度为 2 个字符;在 HTTP 模式下,长度扩展为 4 个字符,每个字符具有特殊含义:

  • 在第一个字符上,报告导致流终止的第一个事件的代码:
C: the TCP session was unexpectedly aborted by the client.

S: the TCP session was unexpectedly aborted by the server, or the
    server explicitly refused it.

P: the stream or session was prematurely aborted by the proxy, because
    of a connection limit enforcement, because a DENY filter was
    matched, because of a security check which detected and blocked a
    dangerous error in server response which might have caused
    information leak (e.g. cacheable cookie).

L: the stream was locally processed by HAProxy.

R: a resource on the proxy has been exhausted (memory, sockets, source
    ports, ...). Usually, this appears during the connection phase, and
    system logs should contain a copy of the precise error. If this
    happens, it must be considered as a very serious anomaly which
    should be fixed as soon as possible by any means.

I: an internal error was identified by the proxy during a self-check.
    This should NEVER happen, and you are encouraged to report any log
    containing this, because this would almost certainly be a bug. It
    would be wise to preventively restart the process after such an
    event too, in case it would be caused by memory corruption.

D: the stream was killed by HAProxy because the server was detected
    as down and was configured to kill all connections when going down.

U: the stream was killed by HAProxy on this backup server because an
    active server was detected as up and was configured to kill all
    backup connections when going up.

K: the stream was actively killed by an admin operating on HAProxy.

c: the client-side timeout expired while waiting for the client to
    send or receive data.

s: the server-side timeout expired while waiting for the server to
    send or receive data.

-: normal stream completion, both the client and the server closed
    with nothing left in the buffers.
  • 在第二个字符中,流关闭时的 TCP 或 HTTP 流状态:
R: the proxy was waiting for a complete, valid REQUEST from the client
    (HTTP mode only). Nothing was sent to any server.

Q: the proxy was waiting in the QUEUE for a connection slot. This can
    only happen when servers have a 'maxconn' parameter set. It can
    also happen in the global queue after a redispatch consecutive to
    a failed attempt to connect to a dying server. If no redispatch is
    reported, then no connection attempt was made to any server.

C: the proxy was waiting for the CONNECTION to establish on the
    server. The server might at most have noticed a connection attempt.

H: the proxy was waiting for complete, valid response HEADERS from the
    server (HTTP only).

D: the stream was in the DATA phase.

L: the proxy was still transmitting LAST data to the client while the
    server had already finished. This one is very rare as it can only
    happen when the client dies while receiving the last packets.

T: the request was tarpitted. It has been held open with the client
    during the whole "timeout tarpit" duration or until the client
    closed, both of which will be reported in the "Tw" timer.

-: normal stream completion after end of data transfer.
  • 第三个字符表示持久性 Cookie 是否由客户端提供(仅在 HTTP 模式下):
N: the client provided NO cookie. This is usually the case for new
    visitors, so counting the number of occurrences of this flag in the
    logs generally indicate a valid trend for the site frequentation.

I: the client provided an INVALID cookie matching no known server.
    This might be caused by a recent configuration change, mixed
    cookies between HTTP/HTTPS sites, persistence conditionally
    ignored, or an attack.

D: the client provided a cookie designating a server which was DOWN,
    so either "option persist" was used and the client was sent to
    this server, or it was not set and the client was redispatched to
    another server.

V: the client provided a VALID cookie, and was sent to the associated
    server.

E: the client provided a valid cookie, but with a last date which was
    older than what is allowed by the "maxidle" cookie parameter, so
    the cookie is consider EXPIRED and is ignored. The request will be
    redispatched just as if there was no cookie.

O: the client provided a valid cookie, but with a first date which was
    older than what is allowed by the "maxlife" cookie parameter, so
    the cookie is consider too OLD and is ignored. The request will be
    redispatched just as if there was no cookie.

U: a cookie was present but was not used to select the server because
    some other server selection mechanism was used instead (typically a
    "use-server" rule).

-: does not apply (no cookie set in configuration).
  • 最后一个字符报告了对服务器返回的持久性 Cookie 执行的操作(仅限 HTTP 模式):
N: NO cookie was provided by the server, and none was inserted either.

I: no cookie was provided by the server, and the proxy INSERTED one.
    Note that in "cookie insert" mode, if the server provides a cookie,
    it will still be overwritten and reported as "I" here.

U: the proxy UPDATED the last date in the cookie that was presented by
    the client. This can only happen in insert mode with "maxidle". It
    happens every time there is activity at a different date than the
    date indicated in the cookie. If any other change happens, such as
    a redispatch, then the cookie will be marked as inserted instead.

P: a cookie was PROVIDED by the server and transmitted as-is.

R: the cookie provided by the server was REWRITTEN by the proxy, which
    happens in "cookie rewrite" or "cookie prefix" modes.

D: the cookie provided by the server was DELETED by the proxy.

-: does not apply (no cookie set in configuration).

两个首个标志的组合可提供关于流或会话终止时发生的情况及其终止原因的大量信息。这有助于检测服务器过载、网络问题、本地系统资源耗尽、攻击等情况。

最常见的终止标志组合如下所示。组合按字母顺序排列,小写字母紧接在对应大写字母之后,以便于查找和理解。

标志 说明

 --   Normal termination.

 CC   The client aborted before the connection could be established to the
      server. This can happen when HAProxy tries to connect to a recently
      dead (or unchecked) server, and the client aborts while HAProxy is
      waiting for the server to respond or for "timeout connect" to expire.

 CD   The client unexpectedly aborted during data transfer. This can be
      caused by a browser crash, by an intermediate equipment between the
      client and HAProxy which decided to actively break the connection,
      by network routing issues between the client and HAProxy, or by a
      keep-alive stream between the server and the client terminated first
      by the client.

 cD   The client did not send nor acknowledge any data for as long as the
      "timeout client" delay. This is often caused by network failures on
      the client side, or the client simply leaving the net uncleanly.

 CH   The client aborted while waiting for the server to start responding.
      It might be the server taking too long to respond or the client
      clicking the 'Stop' button too fast.

 cH   The "timeout client" stroke while waiting for client data during a
      POST request. This is sometimes caused by too large TCP MSS values
      for PPPoE networks which cannot transport full-sized packets. It can
      also happen when client timeout is smaller than server timeout and
      the server takes too long to respond.

 CQ   The client aborted while its stream was queued, waiting for a server
      with enough empty slots to accept it. It might be that either all the
      servers were saturated or that the assigned server was taking too
      long a time to respond.

 CR   The client aborted before sending a full HTTP request. Most likely
      the request was typed by hand using a telnet client, and aborted
      too early. The HTTP status code is likely a 400 here. Sometimes this
      might also be caused by an IDS killing the connection between HAProxy
      and the client. "option http-ignore-probes" can be used to ignore
      connections without any data transfer.

 cR   The "timeout http-request" stroke before the client sent a full HTTP
      request. This is sometimes caused by too large TCP MSS values on the
      client side for PPPoE networks which cannot transport full-sized
      packets, or by clients sending requests by hand and not typing fast
      enough, or forgetting to enter the empty line at the end of the
      request. The HTTP status code is likely a 408 here. Note: recently,
      some browsers started to implement a "pre-connect" feature consisting
      in speculatively connecting to some recently visited web sites just
      in case the user would like to visit them. This results in many
      connections being established to web sites, which end up in 408
      Request Timeout if the timeout strikes first, or 400 Bad Request when
      the browser decides to close them first. These ones pollute the log
      and feed the error counters. Some versions of some browsers have even
      been reported to display the error code. It is possible to work
      around the undesirable effects of this behavior by adding "option
      http-ignore-probes" in the frontend, resulting in connections with
      zero data transfer to be totally ignored. This will definitely hide
      the errors of people experiencing connectivity issues though.

 CT   The client aborted while its stream was tarpitted. It is important to
      check if this happens on valid requests, in order to be sure that no
      wrong tarpit rules have been written. If a lot of them happen, it
      might make sense to lower the "timeout tarpit" value to something
      closer to the average reported "Tw" timer, in order not to consume
      resources for just a few attackers.

 LC   The request was intercepted and locally handled by HAProxy. The
      request was not sent to the server. It only happens with a redirect
      because of a "redir" parameter on the server line.

 LR   The request was intercepted and locally handled by HAProxy. The
      request was not sent to the server. Generally it means a redirect was
      returned, an HTTP return statement was processed or the request was
      handled by an applet (stats, cache, Prometheus exported, lua applet...).

 LH   The response was intercepted and locally handled by HAProxy. Generally
      it means a redirect was returned or an HTTP return statement was
      processed.

 SC   The server or an equipment between it and HAProxy explicitly refused
      the TCP connection (the proxy received a TCP RST or an ICMP message
      in return). Under some circumstances, it can also be the network
      stack telling the proxy that the server is unreachable (e.g. no route,
      or no ARP response on local network). When this happens in HTTP mode,
      the status code is likely a 502 or 503 here.

 sC   The "timeout connect" stroke before a connection to the server could
      complete. When this happens in HTTP mode, the status code is likely a
      503 or 504 here.

 SD   The connection to the server died with an error during the data
      transfer. This usually means that HAProxy has received an RST from
      the server or an ICMP message from an intermediate equipment while
      exchanging data with the server. This can be caused by a server crash
      or by a network issue on an intermediate equipment.

 sD   The server did not send nor acknowledge any data for as long as the
      "timeout server" setting during the data phase. This is often caused
      by too short timeouts on L4 equipment before the server (firewalls,
      load-balancers, ...), as well as keep-alive sessions maintained
      between the client and the server expiring first on HAProxy.

 SH   The server aborted before sending its full HTTP response headers, or
      it crashed while processing the request. Since a server aborting at
      this moment is very rare, it would be wise to inspect its logs to
      control whether it crashed and why. The logged request may indicate a
      small set of faulty requests, demonstrating bugs in the application.
      Sometimes this might also be caused by an IDS killing the connection
      between HAProxy and the server.

 sH   The "timeout server" stroke before the server could return its
      response headers. This is the most common anomaly, indicating too
      long transactions, probably caused by server or database saturation.
      The immediate workaround consists in increasing the "timeout server"
      setting, but it is important to keep in mind that the user experience
      will suffer from these long response times. The only long term
      solution is to fix the application.

 sQ   The stream spent too much time in queue and has been expired. See
      the "timeout queue" and "timeout connect" settings to find out how to
      fix this if it happens too often. If it often happens massively in
      short periods, it may indicate general problems on the affected
      servers due to I/O or database congestion, or saturation caused by
      external attacks.

 PC   The proxy refused to establish a connection to the server because the
      process's socket limit has been reached while attempting to connect.
      The global "maxconn" parameter may be increased in the configuration
      so that it does not happen anymore. This status is very rare and
      might happen when the global "ulimit-n" parameter is forced by hand.

 PD   The proxy blocked an incorrectly formatted chunked encoded message in
      a request or a response, after the server has emitted its headers. In
      most cases, this will indicate an invalid message from the server to
      the client. HAProxy supports chunk sizes of up to 2GB - 1 (2147483647
      bytes). Any larger size will be considered as an error.

 PH   The proxy blocked the server's response, because it was invalid,
      incomplete, dangerous (cache control), or matched a security filter.
      In any case, an HTTP 502 error is sent to the client. One possible
      cause for this error is an invalid syntax in an HTTP header name
      containing unauthorized characters. It is also possible but quite
      rare, that the proxy blocked a chunked-encoding request from the
      client due to an invalid syntax, before the server responded. In this
      case, an HTTP 400 error is sent to the client and reported in the
      logs. Finally, it may be due to an HTTP header rewrite failure on the
      response. In this case, an HTTP 500 error is sent (see
      "tune.maxrewrite" and "http-response strict-mode" for more
      inforomation).

 PR   The proxy blocked the client's HTTP request, either because of an
      invalid HTTP syntax, in which case it returned an HTTP 400 error to
      the client, or because a deny filter matched, in which case it
      returned an HTTP 403 error.  It may also be due to an HTTP header
      rewrite failure on the request. In this case, an HTTP 500 error is
      sent (see "tune.maxrewrite" and "http-request strict-mode" for more
      inforomation).

 PT   The proxy blocked the client's request and has tarpitted its
      connection before returning it a 500 server error. Nothing was sent
      to the server. The connection was maintained open for as long as
      reported by the "Tw" timer field.

 RC   A local resource has been exhausted (memory, sockets, source ports)
      preventing the connection to the server from establishing. The error
      logs will tell precisely what was missing. This is very rare and can
      only be solved by proper system tuning.

两个最后标志的组合可提供大量关于客户端、服务器及 HAProxy 如何处理持久性连接的信息。这对排查断连故障至关重要,尤其当用户抱怨需重新认证时。常见的标志包括:

--   Persistence cookie is not enabled.

NN   No cookie was provided by the client, none was inserted in the
     response. For instance, this can be in insert mode with "postonly"
     set on a GET request.

II   A cookie designating an invalid server was provided by the client,
     a valid one was inserted in the response. This typically happens when
     a "server" entry is removed from the configuration, since its cookie
     value can be presented by a client when no other server knows it.

NI   No cookie was provided by the client, one was inserted in the
     response. This typically happens for first requests from every user
     in "insert" mode, which makes it an easy way to count real users.

VN   A cookie was provided by the client, none was inserted in the
     response. This happens for most responses for which the client has
     already got a cookie.

VU   A cookie was provided by the client, with a last visit date which is
     not completely up-to-date, so an updated cookie was provided in
     response. This can also happen if there was no date at all, or if
     there was a date but the "maxidle" parameter was not set, so that the
     cookie can be switched to unlimited time.

EI   A cookie was provided by the client, with a last visit date which is
     too old for the "maxidle" parameter, so the cookie was ignored and a
     new cookie was inserted in the response.

OI   A cookie was provided by the client, with a first visit date which is
     too old for the "maxlife" parameter, so the cookie was ignored and a
     new cookie was inserted in the response.

DI   The server designated by the cookie was down, a new server was
     selected and a new cookie was emitted in the response.

VI   The server designated by the cookie was not marked dead but could not
     be reached. A redispatch happened and selected another one, which was
     then advertised in the response.

8.6. 不可打印字符

为避免在查阅日志时对日志分析工具或终端造成干扰,不可打印字符不会直接写入日志文件,而是转换为对应 ASCII 码的两位十六进制表示,并以字符 ‘#’ 作为前缀。仅 ASCII 码值在 32 至 126(含)之间的字符可直接记录,无需转义。显然,转义字符 ‘#’ 本身也需编码以避免歧义("#23")。同理,字符 ‘"’ 被编码为 “#22”,在记录头时,字符 ‘{’、’|’ 和 ‘}’ 也需进行相同处理。

请注意,空格字符(’ ‘)在头中未被编码,这可能导致依赖空格计数来定位字段的工具出现问题。一个包含空格的典型头为 “User-Agent”。

最后,观察到某些 syslog 守护进程(如 syslog-ng)会使用反斜杠(\)转义引号(’"’)。由于日志中其他位置不会出现引号,因此可安全地执行反向操作。

8.7. 捕获 HTTP cookies

Cookie 捕获可简化对完整用户会话的追踪。可通过在前端中使用 “capture cookie” 语句实现。详细信息请参见 第 4.2 节 。仅可捕获一个 Cookie,该 Cookie 会在请求(“Cookie:” 头)和响应(“Set-Cookie:” 头)中同时被检查。相应值将在 HTTP 日志的 “captured_request_cookie” 和 “captured_response_cookie” 位置报告(有关 HTTP 日志格式的详情请参见 第 8.2.3 节 )。若任一 Cookie 未被发现,将用连字符 ‘-’ 替代其值。通过此方式,可轻松检测用户是否切换至新会话,例如服务器为其重新分配了新的 Cookie。也可用于检测服务器是否意外向客户端设置了错误的 Cookie,从而导致会话交叉。

示例:

# capture the first cookie whose name starts with "ASPSESSION"
capture cookie ASPSESSION len 32

# capture the first cookie whose name is exactly "vgnvisitor"
capture cookie vgnvisitor= len 32

可以使用 “http-request” 和 “http-response” 规则,将 Cookie 分配至作用域 “txn” 的变量中。随后,可通过 “req.cook” 和 “res.cook” 样本提取函数从请求或响应中提取 Cookie 值(参见 section 7.3.6 ),并使用 “set-var” 或 “set-var-fmt” 动作将其赋值给变量(参见 section 4.3 )。自定义日志格式即可在指定位置输出这些变量(参见 section 8.2.6 )。

8.8. 捕获 HTTP 头(遗留)

头捕获可用于跟踪上游代理设置的唯一请求标识符、虚拟主机名称、用户代理、POST 内容长度、来源地址等信息。在响应中,可搜索关于响应长度、服务器要求缓存行为的信息,或重定向期间的对象位置。

有两种方式执行头捕获。现代方式涉及从待捕获的头中设置变量,或从 “req.hdr_names”、“req.hdrs”、“res.hdr_names”、“res.hdrs” 返回的复合样本中设置变量(详见 section 7.3.6 ),这些变量可使用 “txn” 作用域中的 “set-var” 和 “set-var-fmt” 动作,通过 “http-request” 和 “http-response” 规则集进行赋值(详见 section 4.3 ),随后可在自定义日志格式中引用(详见 section 8.2.6 )。这是捕获 HTTP 头的推荐方式。

此外,还存在一种较早的方法,该方法在引入 http-request 规则和变量之前即已存在,无需调整日志格式,且长期以来一直用于日志记录,同时作为在 HTTP 事务全程中传递请求信息的一种人工手段,使用较旧的 “capture” 规则集。本文所述即为此方法。

使用前端中的“capture request header”和“capture response header”语句执行旧版头捕获。请参阅 第 4.2 节 以获取更多详细信息。

可以同时包含请求头和响应头。不存在的头字段将记录为空字符串;若某个头字段出现多次,仅记录其最后一次出现的值。请求头按声明顺序用花括号 ‘{’ 和 ‘}’ 包裹,以竖线 ‘|’ 分隔,中间不加空格。响应头采用相同的表示方式,但显示在请求头块之后,以一个空格分隔。这些头字段块在日志中紧随 HTTP 请求之前显示。

作为特殊情况,可以在 TCP 前端中指定 HTTP 头捕获。其目的是在请求随后被切换至 HTTP 后端时,启用对将被解析的头信息的记录。

示例:

# This instance chains to the outgoing proxy
listen proxy-out
    mode http
    option httplog
    option logasap
    log global
    server cache1 192.168.1.1:3128

    # log the name of the virtual server
    capture request  header Host len 20

    # log the amount of data uploaded during a POST
    capture request  header Content-Length len 10

    # log the beginning of the referrer
    capture request  header Referer len 20

    # server name (useful for outgoing proxies only)
    capture response header Server len 20

    # logging the content-length is useful with "option logasap"
    capture response header Content-Length len 10

    # log the expected cache behavior on the response
    capture response header Cache-Control len 8

    # the Via header will report the next proxy's name
    capture response header Via len 20

    # log the URL location during a redirection
    capture response header Location len 20
    >>> Aug  9 20:26:09 localhost \
          haproxy[2022]: 127.0.0.1:34014 [09/Aug/2004:20:26:09] proxy-out \
          proxy-out/cache1 0/0/0/162/+162 200 +350 - - ---- 0/0/0/0/0 0/0 \
          {fr.adserver.yahoo.co||http://fr.f416.mail.} {|864|private||} \
          "GET http://fr.adserver.yahoo.com/"
    >>> Aug  9 20:30:46 localhost \
          haproxy[2022]: 127.0.0.1:34020 [09/Aug/2004:20:30:46] proxy-out \
          proxy-out/cache1 0/0/0/182/+182 200 +279 - - ---- 0/0/0/0/0 0/0 \
          {w.ods.org||} {Formilux/0.1.8|3495|||} \
          "GET http://trafic.1wt.eu/ HTTP/1.1"
    >>> Aug  9 20:30:46 localhost \
          haproxy[2022]: 127.0.0.1:34028 [09/Aug/2004:20:30:46] proxy-out \
          proxy-out/cache1 0/0/2/126/+128 301 +223 - - ---- 0/0/0/0/0 0/0 \
          {www.sytadin.equipement.gouv.fr||http://trafic.1wt.eu/} \
          {Apache|230|||http://www.sytadin.} \
          "GET http://www.sytadin.equipement.gouv.fr/ HTTP/1.1"

8.9. 日志示例

以下是真实场景中的日志示例,附有说明。部分日志由人工编造。为便于阅读,已移除 syslog 部分。其唯一目的是解释如何解读这些日志。

>>> haproxy[674]: 127.0.0.1:33318 [15/Oct/2003:08:31:57.130] px-http &#92;
      px-http/srv1 6559/0/7/147/6723 200 243 - - ---- 5/3/3/1/0 0/0 &#92;
      "HEAD / HTTP/1.0"

=> long request (6.5s) entered by hand through 'telnet'. The server replied
   in 147 ms, and the session ended normally ('----')

>>> haproxy[674]: 127.0.0.1:33319 [15/Oct/2003:08:31:57.149] px-http &#92;
      px-http/srv1 6559/1230/7/147/6870 200 243 - - ---- 324/239/239/99/0 &#92;
      0/9 "HEAD / HTTP/1.0"

=> Idem, but the request was queued in the global queue behind 9 other
   requests, and waited there for 1230 ms.
    >>> haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17.654] px-http \
          px-http/srv1 9/0/7/14/+30 200 +243 - - ---- 3/3/3/1/0 0/0 \
          "GET /image.iso HTTP/1.0"
=> request for a long data transfer. The "logasap" option was specified, so
   the log was produced just before transferring data. The server replied in
   14 ms, 243 bytes of headers were sent to the client, and total time from
   accept to first data byte is 30 ms.

>>> haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17.925] px-http &#92;
      px-http/srv1 9/0/7/14/30 502 243 - - PH-- 3/2/2/0/0 0/0 &#92;
      "GET /cgi-bin/bug.cgi? HTTP/1.0"

=> the proxy blocked a server response either because of an "http-response
   deny" rule, or because the response was improperly formatted and not
   HTTP-compliant, or because it blocked sensitive information which risked
   being cached. In this case, the response is replaced with a "502 bad
   gateway". The flags ("PH--") tell us that it was HAProxy who decided to
   return the 502 and not the server.

>>> haproxy[18113]: 127.0.0.1:34548 [15/Oct/2003:15:18:55.798] px-http &#92;
      px-http/`<NOSRV>` -1/-1/-1/-1/8490 -1 0 - - CR-- 2/2/2/0/0 0/0 ""

=> the client never completed its request and aborted itself ("C---") after
   8.5s, while the proxy was waiting for the request headers ("-R--").
   Nothing was sent to any server.

>>> haproxy[18113]: 127.0.0.1:34549 [15/Oct/2003:15:19:06.103] px-http &#92;
     px-http/`<NOSRV>` -1/-1/-1/-1/50001 408 0 - - cR-- 2/2/2/0/0 0/0 ""

=> The client never completed its request, which was aborted by the
   time-out ("c---") after 50s, while the proxy was waiting for the request
   headers ("-R--"). Nothing was sent to any server, but the proxy could
   send a 408 return code to the client.

>>> haproxy[18989]: 127.0.0.1:34550 [15/Oct/2003:15:24:28.312] px-tcp &#92;
      px-tcp/srv1 0/0/5007 0 cD 0/0/0/0/0 0/0

=> This log was produced with "option tcplog". The client timed out after
   5 seconds ("c----").

>>> haproxy[18989]: 10.0.0.1:34552 [15/Oct/2003:15:26:31.462] px-http &#92;
      px-http/srv1 3183/-1/-1/-1/11215 503 0 - - SC-- 205/202/202/115/3 &#92;
      0/0 "HEAD / HTTP/1.0"

=> The request took 3s to complete (probably a network problem), and the
   connection to the server failed ('SC--') after 4 attempts of 2 seconds
   (config says 'retries 3'), and no redispatch (otherwise we would have
   seen "/+3"). Status code 503 was returned to the client. There were 115
   connections on this server, 202 connections on this proxy, and 205 on
   the global process. It is possible that the server refused the
   connection because of too many already established.

18 - 9. 支持的过滤器

跟踪、压缩、SPOE、缓存、FastCGI、OpenTracing、以及带宽过滤器

以下是官方支持的过滤器及其所接受的参数列表。根据编译选项的不同,部分过滤器可能不可用。可用过滤器的列表将在 HAProxy -vv. 中报告。

另请参见:“过滤器”

9.1. 跟踪

过滤器 trace [name <name>] [random-forwarding] [max-fwd <max>] [hexdump]

参数:

<name>               is an arbitrary name that will be reported in
                     messages. If no name is provided, "TRACE" is used.

<quiet>              inhibits trace messages.

<random-forwarding>  enables the random forwarding of parsed data. By
                     default, this filter forwards all previously parsed
                     data. With this parameter, it only forwards a random
                     amount of the parsed data.

<max>                is the maximum amount of data that can be forwarded at
                     a time. "max-fwd" option can be combined with the
                     random forwarding. <max> must be an positive integer.
                     0 means there is no limit.

<hexdump>             dumps all forwarded data to the server and the client.

此过滤器可作为开发新过滤器的基础。它定义了所有回调函数,并在标准错误流(stderr)中输出有用信息,供所有回调函数参考。该过滤器可用于调试其他过滤器的活动,或简单地用于排查 HAProxy 的运行状态。

使用 <random-parsing> 和/或 <random-forwarding> 参数是测试过滤器行为的有效方法,该过滤器用于解析客户端与服务器之间交换的数据,并通过在处理过程中引入延迟来实现。

9.2. HTTP 压缩

过滤器 comp-req

启用根据“compression”设置显式尝试压缩 HTTP 请求的过滤器。 隐式设置“compression direction request”。

过滤器 comp-res

启用根据“compression”设置显式尝试压缩 HTTP 响应的过滤器。 隐式设置“compression direction response”

filter compression(已弃用)

用于向后兼容的别名,其功能等同于同时启用 “comp-req” 和 “comp-res” 过滤器。必须使用 “compression” 关键字来配置相应行为:

在 HAProxy 1.7 中,HTTP 压缩已移入过滤器模块。仍需使用 “compression” 关键字来启用和配置 HTTP 压缩。当未使用其他过滤器时,仅此一项已足够。当与缓存或 fcgi-app 启用时,同样仅此一项已足够。此时,压缩始终在响应存储至缓存后执行。但当同一监听器/前端/后端启用至少一个除缓存或 fcgi-app 以外的过滤器时,必须显式使用过滤器行来启用 HTTP 压缩。这一点需注意过滤器的评估顺序。

另请参阅:“压缩”,第 9.4 节 中关于缓存过滤器的内容,以及第 9.5 节 中关于 fcgi-app 过滤器的内容。

9.3. 流处理卸载引擎 (SPOE)

过滤器 spoe [引擎 <name>] 配置 <file>

参数:

<name>      is the engine name that will be used to find the right scope in
            the configuration file. If not provided, all the file will be
            parsed.

<file>      is the path of the engine configuration file. This file can
            contain configuration of several engines. In this case, each
            part must be placed in its own scope.

流处理卸载引擎(SPOE)是一种与外部组件通信的过滤器。它允许在分层应用中将部分流的特定处理任务卸载至外部组件。这些外部组件及其与之交换的信息主要通过专用配置文件进行配置。此外,还需在 HAProxy 配置中定义专用后端。

SPOE 通过自研的二进制协议——流处理卸载协议(Stream Processing Offload Protocol,SPOP),与外部组件通信。

当 SPOE 在流中使用时,会启动一个专用流来处理与外部组件的通信。主流是该“SPOE”流的父流。这意味着可以从“SPOE”流中获取主流的变量。有关变量的详细信息,请参见 第 2.8 节 。

有关 SPOE 配置和 SPOP 规范的全部信息,请参见“doc/SPOE.txt”。

9.4. 缓存

过滤器 缓存 <name>

参数:

<name>      is name of the cache section this filter will use.

缓存通过过滤器存储可缓存的响应。必须使用 HTTP 规则 cache-store 和 cache-use 来定义缓存的使用方式和时机。默认情况下,相应的过滤器会隐式定义。当仅使用 fcgi-app 或压缩过滤器时,无需额外配置即可满足需求。在此情况下,压缩过滤器始终在缓存过滤器之后执行。但当同一监听器/前端/后端使用了除压缩或 fcgi-app 以外的其他过滤器时,必须显式添加过滤器行以启用缓存。这一点需特别注意,因为过滤器的执行顺序至关重要。

有关更多信息,请参见:第 9.2 节 关于压缩过滤器,第 9.5 节 关于 FCGI 应用过滤器,以及第 6 节 关于缓存。

9.5. FastCGI 应用

过滤器 fcgi-app <name>

参数:

<name>      is name of the fcgi-app section this filter will use.

FastCGI 应用程序使用过滤器对请求路径上的所有自定义参数进行评估,并对响应路径上的头进行处理。<name> 必须引用一个已存在的 fcgi-app 段。应使用指令 “use-fcgi-app” 来定义所使用的应用程序。默认情况下,相应的过滤器会隐式定义。当仅使用缓存或压缩过滤器时,此方式已足够。但当同一后端使用至少一个除压缩或缓存以外的其他过滤器时,必须显式使用过滤器行指定 fcgi-app。这一点对于了解过滤器的评估顺序至关重要。

另请参阅:“use-fcgi-app”,第 9.2 节 关于压缩过滤器,第 9.4 节 关于缓存过滤器,以及第 10 节 关于 FastCGI 应用。

9.6. OpenTracing

本文档中的 OpenTracing 过滤器为 HAProxy 提供了对分布式追踪的原生支持。通过向受支持的追踪器(如 Datadog、Jaeger、Lightstep 和 Zipkin)之一发送符合 OpenTracing 规范的请求,即可启用该功能。请注意:所列追踪器不按优先级排序,而是按字母顺序排列。

此功能仅在 HAProxy 编译时启用 USE_OT=1 时才可用。

通过在 HAProxy 配置中显式指定,可激活 OpenTracing 过滤器。 若未执行此操作,OpenTracing 过滤器将完全不参与 HAProxy 的工作。

过滤器 opentracing [id <id>] 配置 <file>

参数:

<id>        is the OpenTracing filter id that will be used to find the
            right scope in the configuration file. If no filter id is
            specified, 'ot-filter' is used as default.  If scope is not
            specified in the configuration file, it applies to all defined
            OpenTracing filters.

<file>      is the path of the OpenTracing configuration file. The same
            file can contain configurations for multiple OpenTracing
            filters simultaneously. In that case we do not need to define
            scope so the same configuration applies to all filters or each
            filter must have its own scope defined.

有关过滤器操作、配置和使用的更详细文档,请参见 addons/ot 目录。

请注意:由于 OpenTracing 本身已不再由其作者维护或支持,因此不建议在新设计中使用 OpenTracing 过滤器。OpenTracing 将在 3.3 版本中弃用,并在 3.5 版本中移除。自 3.4 版本起,已提供基于 OpenTelemetry 的替代过滤器,完整的构建说明目前位于:

https://github.com/haproxytech/haproxy-opentelemetry/

9.7. 带宽限制

过滤器 bwlim-in <name> 默认限速 <size> 默认周期 <time> [最小大小 <sz>] 过滤器 过滤器 bwlim-out <name> 默认限速 <size> 默认周期 <time> [最小大小 <sz>] 过滤器 过滤器 bwlim-in <name> 限速 <size> 键 <pattern> [表 <table>] [最小大小 <sz>] 过滤器 过滤器 bwlim-out <name> 限速 <size> 键 <pattern> [表 <table>] [最小大小 <sz>]

参数:

<name>      is the filter name that will be used by 'set-bandwidth-limit'
            actions to reference a specific bandwidth limitation filter.

<size>      is max number of bytes that can be forwarded over the period.
            The value must be specified for per-stream and shared bandwidth
            limitation filters. It follows the HAProxy size format and is
            expressed in bytes.

<pattern>   is a sample expression rule as described in section 7.3. It
            describes what elements will be analyzed, extracted, combined,
            and used to select which table entry to update the counters. It
            must be specified for shared bandwidth limitation filters only.

<table>     is an optional table to be used instead of the default one,
            which is the stick-table declared in the current proxy. It can
            be specified for shared bandwidth limitation filters only.

<time>      is the default time period used to evaluate the bandwidth
            limitation rate. It can be specified for per-stream bandwidth
            limitation filters only. It follows the HAProxy time format and
            is expressed in milliseconds.

<min-size>  is the optional minimum number of bytes forwarded at a time by
            a stream excluding the last packet that may be smaller. This
            value can be specified for per-stream and shared bandwidth
            limitation filters. It follows the HAProxy size format and is
            expressed in bytes.

带宽限制过滤器应用于限制流级别的数据转发速度。由此延伸,此类过滤器可限制资源所消耗的网络带宽。可同时使用多个带宽限制过滤器。例如,可为每个源地址设置限制,以确保客户端不会占用全部网络带宽,从而影响其他客户端;同时,也可为每个流设置限制,以便对单个客户端的多个连接进行公平处理。

这些过滤器的定义顺序至关重要。如果在一个流上启用了多个带宽过滤器,过滤将按照其定义顺序依次应用。其他过滤器的定义顺序同样重要。例如,HTTP 压缩过滤器的定义顺序位于带宽限制过滤器之前或之后,将决定限制是作用于压缩后的有效载荷,还是不作用于压缩后的有效载荷。缓存过滤器的情况亦是如此。

有两种带宽限制过滤器。第一种强制执行默认限制,且按流应用。第二种使用会话粘性表,对共享表中同一项的所有流平均分配限制。

此外,对于特定过滤器,根据所使用的过滤器关键字,限制可应用于从客户端接收并转发至服务器的入站数据,或应用于从服务器接收并发送至客户端的出站数据。若需对入站数据施加限制,必须使用“bwlim-in”关键字。若需对出站数据施加限制,必须使用“bwlim-out”关键字。在两种情况下,带宽限制均在流级别上应用于转发的数据。

带宽限制在流级别应用,而非连接级别。对于多路复用协议(H2、H3 和 FastCGI),同一连接内的不同流可具有不同的限制。

对于基于流的带宽限制过滤器,必须定义默认周期和默认限制。如其名称所示,这些是用于设置流带宽限制速率的默认值。然而,对于此类过滤器(仅限此类),当使用 TCP/HTTP 的 “set-bandwidth-limit” 动作启用过滤器时,可通过样本表达式重新定义这些值。

对于共享带宽限制过滤器,根据其应用于入站或出站数据,所使用的会话粘性表必须存储相应的字节速率信息。 必须存储 “bytes_in_rate(<period>)” 计数器以限制入站数据, 必须使用 “bytes_out_rate(<period>)” 计数器以限制出站数据。

最后,可以为特定流设置带宽限制过滤器每次可转发的最小字节数。此举旨在避免转发过少的数据,以降低 CPU 使用率。该值必须谨慎设定。若设置过低,可能增加 CPU 使用率;若设置过高,则可能增加延迟。该值与所设定的带宽限制密切相关。若其值过于接近带宽限制,为避免超出限制,可能产生短暂停顿,因为单次消耗的字节数过多。该值高度依赖于过滤器配置。一个较好的做法是,从约 2 个 TCP MSS(通常为 2896 字节)开始,经若干次试验后进行调整。

示例:

frontend http
    bind *:80
    mode http

    # If this filter is enabled, the stream will share the download limit
    # of 10m/s with all other streams with the same source address.
    filter bwlim-out limit-by-src key src table limit-by-src limit 10m

    # If this filter is enabled, the stream will be limited to download at 1m/s,
    # independently of all other streams.
    filter bwlim-out limit-by-strm default-limit 1m default-period 1s

    # Limit all streams to 1m/s (the default limit) and those accessing the
    # internal API to 100k/s. Limit each source address to 10m/s. The shared
    # limit is applied first. Both are limiting the download rate.
    http-request set-bandwidth-limit limit-by-strm
    http-request set-bandwidth-limit limit-by-strm limit 100k if { path_beg /internal }
    http-request set-bandwidth-limit limit-by-src
    ...

backend limit-by-src
    # The stickiness table used by <limit-by-src> filter
    stick-table type ip size 1m expire 3600s store bytes_out_rate(1s)

另请参见:“tcp-request content set-bandwidth-limit”、“tcp-response content set-bandwidth-limit”、“http-request set-bandwidth-limit”和“http-response set-bandwidth-limit”。

19 - 10. FastCGI 应用程序

FastCGI 应用配置、参数、示例及限制

HAProxy 可以向 Responder FastCGI 应用发送 HTTP 请求。此功能自 HAProxy 2.1 版本起引入。为此,必须将服务器配置为使用 FastCGI 协议(在服务器行中使用关键字 “proto fcgi”),且后端管理这些服务器时,必须配置并使用一个 FastCGI 应用(在代理段中使用关键字 “use-fcgi-app”)。可以定义多个 FastCGI 应用,但每个后端在同一时间只能使用其中一个。

HAProxy 实现了 FastCGI 规范中针对 Responder 应用的所有功能。特别是,它能够在单一连接上复用多个请求。

10.1. 配置

10.1.1. FastCGI 应用段

fcgi-app <name>

fcgi-app <name>

声明一个名为 <name> 的 FastCGI 应用。要使配置有效,至少必须定义文档根目录。

acl <aclname> <criterion> [flags] [operator] <value> ...

acl <aclname> <criterion> [flags] [operator] <value> ...

声明或完成访问控制列表。

请参阅 “acl” 的 第 4.2 节 和 第 7 节 了解 ACL 使用详情。为 FastCGI 应用定义的 ACL 为私有,无法被任何其他应用或代理使用。同理,任何其他段中定义的 ACL 也无法被 FastCGI 应用使用。但预定义的 ACL 可用。

docroot <path>

docroot <path>

定义远程主机上的文档根目录。<path> 将用于构建 FastCGI 参数 SCRIPT_FILENAME 和 PATH_TRANSLATED 的默认值。此项为必选设置。

index <script-name>

index <script-name>

定义在以斜杠 ("/") 结尾的 URI 后附加的脚本名称,用于设置 FastCGI 参数 SCRIPT_NAME 的默认值。此项为可选设置。

示例:

index index.php

log-stderr global

log-stderr global
log-stderr <target> [len <length>] [format <format>]
    [sample <ranges>:<sample_size>] <facility> [<level> [<minlevel>]]

启用记录 FastCGI 应用程序报告的 STDERR 消息。

请参见 “log” 关键字在 第 4.2 节 中的说明。该设置为可选。默认情况下,忽略 STDERR 消息。

pass-header <name> [ { if | unless } <condition> ]

pass-header <name> [ { if | unless } <condition> ]

指定将传递给 FastCGI 应用程序的请求头名称。可选地,其后可跟一个基于 ACL 的条件,此时仅当该条件为真时才进行评估。

大多数请求头已可供 FastCGI 应用程序使用,且均以 “HTTP_” 为前缀。因此,该指令仅用于传递那些被有意省略的头。当前,头 “Authorization”、“Proxy-Authorization” 以及逐跳头被省略。

请注意,头 “Content-type” 和 “Content-length” 永远不会传递给 FastCGI 应用程序,因为它们已转换为参数。

path-info <regex>

path-info <regex>

定义一个正则表达式,用于从 URL 解码后的路径中提取脚本名和路径信息。 因此,<regex> 可能包含两个捕获:第一个用于捕获脚本名,第二个用于捕获路径信息。第一个捕获为必选,第二个为可选。通过这种方式,可以从路径中提取脚本名,同时忽略路径信息。此设置为可选。若未定义,则不对路径执行匹配,且 FastCGI 参数 PATH_INFO 和 PATH_TRANSLATED 不会被填充。

出于安全考虑,当定义了此正则表达式时,路径在经过 URL 解码后禁止包含换行符和空字符。此限制的原因在于,否则匹配将始终失败(由于 HAProxy 中正则表达式执行方式的限制)。因此,若在 URL 解码后的路径中发现这两个字符之一,将向客户端返回错误。此处遵循最小惊讶原则。

示例:

path-info ^(/.+\.php)(/.*)?$ # both script-name and path-info may be set
path-info ^(/.+\.php)        # the path-info is ignored

option get-values

option get-values
no option get-values

启用或禁用获取连接管理相关变量。

HAProxy 可在建立连接时发送记录 FCGI_GET_VALUES,以获取以下变量的值:

* FCGI_MAX_REQS     The maximum number of concurrent requests this
                    application will accept.

* FCGI_MPXS_CONNS   "0" if this application does not multiplex connections,
                    "1" otherwise.

部分 FastCGI 应用程序不支持此功能。部分应用程序在发送响应后立即关闭连接。因此,默认情况下,此选项处于禁用状态。

请注意,FastCGI 应用程序接受的最大并发请求数是一个连接级变量。它仅限制每个连接的流数量。若需对应用的全局负载进行限制,必须设置服务器参数 “maxconn” 和 “pool-max-conn”。此外,若应用不支持连接多路复用,则最大并发请求数将自动设为 1。

option keep-conn

option keep-conn
no option keep-conn

指示 FastCGI 应用程序在发送响应后是否保持连接打开。

若禁用,FastCGI 应用程序在响应此请求后关闭连接。默认情况下,此选项已启用。

option max-reqs <reqs>

option max-reqs <reqs>

定义该应用程序将接受的最大并发请求数。

该选项可在连接建立期间获取变量 FCGI_MAX_REQS 时被覆盖。此外,若应用程序不支持连接复用,该选项将被忽略。默认值为 1。

option mpxs-conns

option mpxs-conns
no option mpxs-conns

启用或禁用连接复用支持。

该选项可在连接建立期间获取变量 FCGI_MPXS_CONNS 时被覆盖。默认情况下已禁用。

set-param <name> <fmt> [ { if | unless } <condition> ]

set-param <name> <fmt> [ { if | unless } <condition> ]

设置应传递给该应用的 FastCGI 参数。其值由 <fmt> 定义,必须遵循自定义日志格式规则(参见 第 8.2.6 节 “自定义日志格式”)。可选地,其后可跟一个基于 ACL 的条件,此时仅当该条件为真时才进行评估。

使用该指令,可以覆盖默认 FastCGI 参数的值。若值被计算为空字符串,则忽略该规则。这些指令按声明顺序进行评估。

示例:

# PHP only, required if PHP was built with --enable-force-cgi-redirect
set-param REDIRECT_STATUS 200

set-param PHP_AUTH_DIGEST %[req.hdr(Authorization)]

10.1.2. 代理段

use-fcgi-app <name> 为后端指定要使用的 FastCGI 应用。

参数:

<name>    is the name of the FastCGI application to use.

该关键字仅适用于具备后端功能且至少包含一个 FastCGI 服务器的 HTTP 代理。尽管 FastCGI 服务器可与 HTTP 服务器混合使用,但除非有充分理由,否则不建议如此操作(详见 第 10.3 节 中关于限制的详细说明)。每个后端在同一时间只能定义一个应用程序。

请注意,一旦后端引用了 FastCGI 应用,根据配置情况,即使请求未发送至 FastCGI 服务器,也可能执行部分处理。用于设置参数或向应用传递头的规则将被评估。

10.1.3. 示例

frontend front-http mode http bind *:80 bind *:

  use_backend back-dynamic if { path_reg ^/.+&#92;.php(/.*)?$ }
  default_backend back-static

backend back-static mode http server www A.B.C.D:80

backend back-dynamic mode http use-fcgi-app php-fpm server php-fpm A.B.C.D:9000 proto fcgi

fcgi-app php-fpm log-stderr global option keep-conn

  docroot /var/www/my-app
  index index.php
  path-info ^(/.+&#92;.php)(/.*)?$

10.2. 默认参数

响应式 FastCGI 应用程序的目的与 CGI/1.1 程序相同。在 CGI/1.1 规范(RFC3875)中,必须向脚本传递若干变量。因此,HAProxy 会设置这些变量以及 FastCGI 应用程序中常用的其他变量。所有这些变量均可被覆盖,但需谨慎操作。

  +-------------------+-----------------------------------------------------+
  | AUTH_TYPE         | Identifies the mechanism, if any, used by HAProxy   |
  |                   | to authenticate the user. Concretely, only the      |
  |                   | BASIC authentication mechanism is supported.        |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | CONTENT_LENGTH    | Contains the size of the message-body attached to   |
  |                   | the request. It means only requests with a known    |
  |                   | size are considered as valid and sent to the        |
  |                   | application.                                        |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | CONTENT_TYPE      | Contains the type of the message-body attached to   |
  |                   | the request. It may not be set.                     |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | DOCUMENT_ROOT     | Contains the document root on the remote host under |
  |                   | which the script should be executed, as defined in  |
  |                   | the application's configuration.                    |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | GATEWAY_INTERFACE | Contains the dialect of CGI being used by HAProxy   |
  |                   | to communicate with the FastCGI application.        |
  |                   | Concretely, it is set to "CGI/1.1".                 |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | PATH_INFO         | Contains the portion of the URI path hierarchy      |
  |                   | following the part that identifies the script       |
  |                   | itself. To be set, the directive "path-info" must   |
  |                   | be defined.                                         |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | PATH_TRANSLATED   | If PATH_INFO is set, it is its translated version.  |
  |                   | It is the concatenation of DOCUMENT_ROOT and        |
  |                   | PATH_INFO. If PATH_INFO is not set, this parameters |
  |                   | is not set too.                                     |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | QUERY_STRING      | Contains the request's query string. It may not be  |
  |                   | set.                                                |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | REMOTE_ADDR       | Contains the network address of the client sending  |
  |                   | the request.                                        |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | REMOTE_USER       | Contains the user identification string supplied by |
  |                   | client as part of user authentication.              |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | REQUEST_METHOD    | Contains the method which should be used by the     |
  |                   | script to process the request.                      |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | REQUEST_URI       | Contains the request's URI.                         |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | SCRIPT_FILENAME   | Contains the absolute pathname of the script. it is |
  |                   | the concatenation of DOCUMENT_ROOT and SCRIPT_NAME. |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | SCRIPT_NAME       | Contains the name of the script. If the directive   |
  |                   | "path-info" is defined, it is the first part of the |
  |                   | URI path hierarchy, ending with the script name.    |
  |                   | Otherwise, it is the entire URI path.               |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | SERVER_NAME       | Contains the name of the server host to which the   |
  |                   | client request is directed. It is the value of the  |
  |                   | header "Host", if defined. Otherwise, the           |
  |                   | destination address of the connection on the client |
  |                   | side.                                               |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | SERVER_PORT       | Contains the destination TCP port of the connection |
  |                   | on the client side, which is the port the client    |
  |                   | connected to.                                       |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | SERVER_PROTOCOL   | Contains the request's protocol.                    |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | SERVER_SOFTWARE   | Contains the string "HAProxy" followed by the       |
  |                   | current HAProxy version.                            |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | HTTPS             | Set to a non-empty value ("on") if the script was   |
  |                   | queried through the HTTPS protocol.                 |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+

10.3. 限制

当前实现存在一些限制。第一个限制涉及某些请求头在传递给 FastCGI 应用程序时的隐藏方式。这一过程发生在后端侧的请求头分析阶段,即在连接建立之前。此时,HAProxy 知道后端使用的是 FastCGI 应用程序,但尚无法确定该请求是否将被路由至 FastCGI 服务器。为隐藏请求头,HAProxy 会直接从 HTX 消息中移除这些头。因此,若请求最终被路由至 HTTP 服务器,该服务器将无法看到这些头。出于此原因,不建议在同一后端中混合使用 FastCGI 服务器和 HTTP 服务器。

同样地,规则 “set-param” 和 “pass-header” 在请求头分析阶段进行评估。因此,即使请求最终被转发至 HTTP 服务器,评估操作也始终执行。

关于规则 “set-param”,当应用规则时,会向 HTX 消息中添加一个伪头。 因此,与 HTTP 头重写类似,若缓冲区已满,操作可能失败。 规则 “set-param” 将与规则 “http-request” 竞争资源。

最后,所有 FastCGI 参数和 HTTP 头均被发送至一个独立记录 FCGI_PARAM。该记录的编码必须一次性完成,否则将返回处理错误。这意味着记录 FCGI_PARAM 在编码后,其大小不得超过缓冲区容量。但此处无需预留空间。

20 - 11. 粘性表与对等节点

粘性表存储与对等节点复制声明

在 HAProxy 中,stick-table 是一种机制,允许将一定数量的信息和指标与特定类型的键关联,并在最后一次更新后持续一定时间。这可视为表格中的一行多列数据,其中行号由键值决定,各列代表不同的衡量标准。

会话粘性表最初设计用于存储客户端-服务器会话粘性信息,以维持两者之间的持久会话。客户端连接或发送请求时,将通过一个标识符(源地址、Cookie 或 URL 参数)进行识别,并将选定的服务器与该标识符关联存储在粘性表中,持续时间为可配置时长,以便来自同一客户端的后续访问可自动路由至同一服务器,从而确保客户端在其创建的应用会话中保持连接。

如今,stick-table 可存储的信息已不仅限于服务器编号,还可存储与特定客户端相关的活动指标(如请求次数/速率、连接次数/速率、字节数/速率等),以及一些任意事件计数器(“gpc” 用于“通用计数器”)和用于标记客户端特性的标签(“gpt” 用于“通用标签”)。

会话粘性表可被 “stick” 指令引用,用于实现客户端-服务器会话粘性;可被 “track-sc” 规则引用,用于定义需在哪个表中追踪何种键以收集指标;还可被多种样本提取函数和转换器引用,这些函数和转换器可对指定键执行即时查找,以获取特定指标或数据。基本原则是:对表(gpt/gpc/指标)的更新以及对会话粘性信息的查找会刷新访问条目并推迟其过期时间;而仅通过样本提取函数和转换器执行的查找仅提取数据,不会推迟条目的过期时间。

为使该机制具备可扩展性并抵御 HAProxy 重载和故障切换的影响,可通过 “Peers” 机制在其他节点(称为 “peers”)之间共享 stick-table 更新,该机制详见 第 11.2 节 。为精细调整与对等节点的通信,还可选择指定某些表仅接收来自对等节点的信息,或指定对等节点的更新应转发至其他表。

最后,粘性表可声明于代理段(前端或后端)中,使用 “stick-table” 关键字,每个段中仅允许一个粘性表,且其名称将自动采用该段的名称;也可声明于对等节点段中,使用 “table” 关键字后跟表名,该方式允许在同一个 “peers” 段中声明多个粘性表。若需多个粘性表,通常推荐方案为:若表需共享,应声明于对等节点段中;或为每个表创建独立的后端段,每个段中仅包含 “stick-table” 定义。

11.1. 粘性表声明

在代理段(“frontend”、“backend”、“listen”)和 “peers” 段中声明粘性表的语法非常相似,区别在于对等节点段中的声明必须指定一个名称,且不支持 “peers” 选项。

在 “frontend”、“backend” 或 “listen” 段中:

stick-table type <type> size <size> [expire <expire>] [nopurge] [recv-only] [write-to <wtable>] [srvkey <srvkey>] [store <data_type>]* [brates-factor <factor>] [peers <peersect>]

在 “peers” 段中:

table <name> type <type> size <size> [expire <expire>] [nopurge] [recv-only] [write-to <wtable>] [srvkey <srvkey>] [store <data_type>]* [brates-factor <factor>]

参数:(先列出必选参数,后按字母顺序排序)

  • type <type> 此必选参数用于设置键类型为 <type>,通常为单个单词,但也可能包含其自身的参数:

    • ip 此类型应避免使用,建议改用更明确的类型,例如 “ipv4” 或 “ipv6”。在 3.2 版本之前,它是配置 IPv4 的唯一方式。从 3.2 版本起,“ip” 是 “ipv4” 的别名,而 “ipv4” 为首选。在未来的版本中,“ip” 将改为对应 “ipv6”。该类型仅用于帮助从 3.2 之前版本向 3.2 之后版本平稳过渡。

    • ipv4 以此类型声明的表,仅存储 IPv4 地址。该形式非常紧凑(每个条目约 50 字节),支持极快的条目查找与存储,几乎无额外开销。主要用于存储客户端源 IP 地址。

    • ipv6 使用 “type ipv6” 声明的表仅存储 IPv6 地址。该形式非常紧凑(每个条目约 60 字节),支持极快的条目查找与存储,几乎无额外开销。主要用于存储客户端源 IP 地址。

    • integer 使用 “type integer” 声明的表将存储 32 位整数,例如可用于存储请求中的客户端标识符。

    • string [len <len>] 声明为 “type string” 的表将存储最多 <len> 个字符的子字符串。如果模式提取器提供的字符串长度超过 <len>,在存储前将被截断。匹配时,表中字符串与提取的模式之间最多比较 <len> 个字符。未指定时,字符串默认限制为 32 个字符。增加长度可能带来不可忽略的内存使用影响。

    • binary [len <len>] 声明为 “type binary” 的表将存储长度为 <len> 字节的二进制块。若模式提取器提供的块大于 <len>,将在存储前被截断。若样本表达式提供的块短于 <len>,将用 0 填充至指定长度。未指定时,块长度默认自动限制为 32 字节。增大长度可能导致不可忽略的内存使用影响。

  • size <size> 此必选参数用于设置表中可容纳的最大条目数 <size>。该值直接影响内存使用量。每个条目需额外估算 50 字节,加上上述键的大小、可选存储的指标大小,以及如有字符串则还需加上字符串大小。size 支持后缀 “k”、“m”、“g”,分别表示 2^10、2^20 和 2^30 的倍数。

  • expire <delay> 定义表中条目自创建以来、或通过 ’track-sc’ 更新、或通过 ‘stick match’ 或 ‘stick on’ 规则匹配后的最大持续时间。过期延迟 <delay> 使用标准时间格式定义,与各类超时设置类似,默认单位为毫秒。最大持续时间略高于 24 天。详见 第 2.5 节 获取更多信息。若未指定此延迟,会话将不会自动过期,但表满时将移除最旧的条目。请注意,若未指定过期延迟,切勿使用 “nopurge” 参数。注意:’table_*’ 转换器执行查找操作,但不会更新触碰过期时间,因为它们不需要 ’track-sc’。

  • brates-factor <factor> 指定应用于入/出字节速率的系数。不逐字节计数,而是按字节块进行计数。内部速率基于 32 位计数器定义,每周期上限约为 40 亿字节。通过使用此参数,可在指定周期内实现超过 4G 字节的速率。系数必须大于 0 且小于或等于 1024。

  • nopurge 表示当表已满时拒绝清除较旧的条目。若未指定此选项,当 HAProxy 试图向已满的表中存储条目时,将清除部分最旧的条目以释放空间供新条目使用。这通常是期望的行为。在某些特定情况下,更希望拒绝新条目而非清除较旧的条目。例如,当需存储的数据量远超硬件限制时,宁愿拒绝新客户端的接入,也不愿中断已连接的客户端。使用此参数时,请务必正确设置 “expire” 参数(参见上文)。

  • recv-only 表示我们不打算使用该表执行更新操作,而仅计划通过该表从感兴趣的远程对等节点获取数据。实际上,使用此关键字可检索本地独有的值,例如 “conn_cur”,这些值默认不会被学习,因为它们可能与本地对等节点对该表执行的本地更新产生冲突。此选项仅适用于不参与跟踪规则或执行表更新操作的方法的表,或更简单地说:仅用于获取信息的远程表。

  • peers <peersect> 在段 <peersect> 中配置的对等节点将接收已创建、更新或刷新的条目以实现同步,同时从该段中配置的对等节点学习到的键也将插入或更新至表中。此外,在启动时,可尝试从指定为“本地对等节点”的旧进程实例中学习条目,该实例通过本段指定。

  • srvkey <srvkey> 指定服务器在粘性表中的标识方式。有效值为 “name” 和 “addr”。若指定 “name”,则服务器的标识由其 <name> 参数决定(可由模板生成)。若指定 “addr”,则服务器通过当前网络地址(含端口)进行标识。“addr” 在使用服务发现为对等节点的粘性表生成服务器地址时尤为有用,可确保对等节点间对同一会话粘性令牌始终使用相同的主机。

  • store <data_type> 用于在粘性表中存储附加信息。该信息可被 ACL 用于控制与匹配粘性表的客户端活动相关的各种条件。针对此处指定的每一项,每个条目的大小将被扩大,以容纳附加数据。一个条目中可存储多种数据类型。可在 “store” 关键字后以逗号分隔的列表形式指定多个数据类型。或者,也可重复使用 “store” 关键字并随后指定一个或多个数据类型。除 “server_id” 类型会自动检测并启用外,所有其他数据类型必须显式声明以进行存储。若 ACL 引用了未存储的数据类型,该 ACL 将不会匹配。部分数据类型需要参数,该参数必须紧跟在类型名后的括号内提供。详见下文支持的数据类型及其参数。

  • write-to <wtable> 指定另一个粘性表的名称,对等节点的更新将被写入该表,同时也会写入源表。<wtable> 的类型必须与所定义的表类型相同,且键长度必须一致,源表自身不能作为目标表。每当通过一个对等节点接收到源表的条目更新时,HAProxy 将尝试刷新相关的 <wtable> 条目。如果该条目尚不存在,将被创建;否则其值以及计时器将被更新。请注意,仅那些不参与算术运算的类型(如 server_id、server_key 和 gpt)才会被写入 <wtable>,以防止远程表的处理结果干扰本地目标表上的算术运算(例如:防止共享累计计数器无限增长)。此选项的一个常见用途是在对等节点集群环境中使用粘性规则(用于服务器持久性),因为匹配的键将从远程表中学习到。

可通过 “store” 指令关联的数据显示类型如下。请注意,存储大量数据类型时,内存需求可能成为关键因素。事实上,若在每个条目中同时存储以下所有指标,每个条目可能需要数百字节,百万条目表则可能占用数百 MB。因此,每种类型的近似存储大小已在下方各参数后以括号形式注明。

参数:

  • bytes_in_cnt [4 字节] 这是客户端到服务器的字节数。它是一个 64 位正整数,用于统计与该条目匹配的客户端所接收的累计字节数。头信息包含在计数中。此指标可用于限制对照片或视频服务器上传功能的滥用。请注意,该值在数据进入 HAProxy 时进行测量,因此计数不受压缩影响。

  • bytes_in_rate(<period>) [12 字节] 这是一个从客户端到服务器的字节速率计数器。它接受一个整数参数 <period>,表示以毫秒为单位的平均值测量周期长度。该指标报告在该周期内平均的入站字节速率,单位为每周期字节数。可用于检测上传量过大且过快的用户。 请注意:在大文件上传场景下,上传数据量可能在连接终止时仅被统计一次,从而导致平均传输速率出现峰值,而非平滑变化。尽管启用“option contstats”可部分缓解此问题,但并非完全解决。建议使用 byte_in_cnt 以获得更公平的统计效果。

  • bytes_out_cnt [4 字节] 这是服务器到客户端的字节数。它是一个正的 64 位整数,用于统计发送给匹配此条目的客户端的累计字节数。头信息包含在计数中。可用于限制机器人大量消耗整个站点资源的行为。请注意,该值在数据进入 HAProxy 时进行测量,因此计数不受压缩影响。

  • bytes_out_rate(<period>) [12 字节] 这是一个从服务器到客户端的字节速率计数器。它接受一个整数参数 <period>,表示以毫秒为单位的平均值测量周期长度。该指标报告该周期内平均的出站字节速率,单位为每周期字节数。可用于检测下载量过大且过快的用户。 请注意:在大文件传输过程中,传输数据量可能在连接终止时被重复计数一次,从而导致平均传输速率出现峰值,而非平滑变化。尽管启用“option contstats”可部分缓解此问题,但目前尚不完善。建议使用 byte_out_cnt 以获得更公平的统计结果。

  • conn_cnt [4 字节] 这是连接计数。它是一个正的 32 位整数,用于统计从客户端接收并匹配此条目的连接的绝对数量。该数值不代表连接已被接受,仅表示连接已被接收。

  • conn_cur [4 字节] 当前连接数。这是一个正的 32 位整数,用于存储该条目当前的并发连接数。每当一个入站连接匹配该条目时,计数加 1;当连接断开时,计数减 1。通过这种方式,可以随时准确获知该条目当前的并发连接数量。默认情况下,该类型不会从对等节点学习,因为其会忽略本地计数,无法反映真实情况。然而,与 recv-only 配合使用时,可用于学习对等节点所观测到的并发连接数量。

  • conn_rate(<period>) [12 字节] 这是一个连接频率计数器。它接受一个整数参数 <period>,表示测量平均值的时间周期长度,单位为毫秒。该计数器报告在该周期内平均的入站连接速率,单位为每周期连接数。结果为整数,可使用 ACL 进行匹配。连接是否被接受或拒绝,均不影响其测量。

  • glitch_cnt [4 字节] 这是前端连接的异常事件计数。它是一个正的 32 位整数,用于累计记录前端连接上报的异常事件数量。异常事件指客户端在协议层面发生的异常或意外行为,可能表明客户端存在严重缺陷,或可能是攻击行为。因此,该计数器可用于判断在发生此类情况时应采取何种动作。

  • glitch_rate(<period>) [12 字节] 这是一个用于统计异常事件频率的计数器。它接受一个整数参数 <period>,表示以毫秒为单位的平均值测量周期长度。该指标报告在该周期内平均的前端异常事件发生率。可用于检测存在缺陷的客户端或可能的攻击者,这些客户端在协议层面执行了不常见或出乎意料的行为,前提是 HAProxy 已将其标记为此类行为。

  • gpc(<nb>) [4 * <nb> 字节] 这是一个包含 <nb> 个通用计数器元素的数组。 该数组由正 32 位整数构成,可用于计数任意内容。通常情况下,它们将作为某些条目的增量计数器使用,例如记录某项限制已达到并触发相应动作。该数组最多限制为 100 个元素:gpc0 至 gpc99,以确保对等节点更新消息的构建可容纳于缓冲区中。请注意,大量计数器会增加数据量及对等协议的流量负载,因为每次任一计数器更新时,所有数据/计数器都会被推送。 此数据类型将排除在同一表中使用旧版数据类型 ‘gpc0’ 和 ‘gpc1’。使用 ‘gpc’ 数组数据类型时,所有与 ‘gpc0’ 和 ‘gpc1’ 相关的样本提取函数及动作均适用于该数组的前两个元素。

  • gpc_rate(<nb>,<period>) [12 * <nb> 字节] 这是一个在一段时间内通用计数器增量速率的数组。这些元素为正的 32 位整数,可用于任意用途。与 <gpc> 类似,但不同于累积计数,它们维护的是计数器的增量速率。通常用于测量特定事件的发生频率(例如,对某个特定 URL 的请求)。该数组最多可包含 100 个元素:gpt(100),以确保 gpc0 至 gpc99 的存储,并保证对等节点更新消息的构建可容纳于缓冲区。该数组不能少于 1 个元素:若仅需存储 gpc0,应使用 gpc(1)。请注意,大量计数器会增加数据量及使用对等节点协议时的流量负载,因为每次任一计数器更新时,所有数据/计数器均会被推送。此 data_type 将排除在同一表中使用旧版 data_type ‘gpc0_rate’ 和 ‘gpc1_rate’。使用 ‘gpc_rate’ 数组 data_type 时,所有 ‘gpc0’ 和 ‘gpc1’ 相关的获取和动作将作用于该数组的前两个元素。

  • gpc0 [4 字节] 这是第一个通用计数器。它是一个无符号 32 位整数,可用于任何用途。通常情况下,它将用于为某些条目打上特殊标签,例如标记已检测到特定行为,以便在后续匹配中识别。

  • gpc0_rate(<period>) [12 字节] 这是第一个通用计数器在一段时间内的增量速率。它是一个正 32 位整数,可用于任何用途。与 <gpc0> 类似,它统计事件,但不保留累计数值,而是维持计数器的增量速率。通常用于测量特定事件的发生频率(例如,对特定 URL 的请求)。

  • gpc1 [4 字节] 这是第二个通用计数器。它是一个正 32 位整数,可用于任何用途。通常情况下,它将用于为某些条目打上特殊标签,例如标记已检测到特定行为,以便在后续匹配中识别。

  • gpc1_rate(<period>) [12 字节] 这是第二个通用计数器在一段时间内的增量速率。它是一个正 32 位整数,可用于任何用途。与 <gpc1> 类似,它用于统计事件,但不保留累计数值,而是维护计数器的增量速率。通常用于测量特定事件的发生频率(例如,对特定 URL 的请求)。

  • gpt(<nb>) [4 * <nb> 字节] 这是一个包含 <nb> 个通用标签元素的数组。该数组由正 32 位整数构成,可用于任意用途。通常情况下,这些元素用于为某些条目添加特殊标签,例如标记已检测到特定行为,以便后续匹配时识别。该数组最多可包含 100 个元素:gpt(100),支持存储 gpt0 至 gpt99,以确保对等节点更新消息可适配缓冲区。数组至少需包含 1 个元素:若仅需存储标签 gpt0,请使用 gpt(1)。请注意,大量计数器将增加数据量并提升对等协议的流量负载,因为每次任一计数器更新时,所有数据/计数器均会被推送。该 data_type 将排除在同一表中使用旧版 data_type ‘gpt0’。使用 ‘gpt’ 数组 data_type 时,所有与 ‘gpt0’ 相关的获取操作和动作均作用于该数组的第一个元素。

  • gpt0 [4 字节] 这是第一个通用标签。它是一个正 32 位整数,可用于任何用途。通常情况下,它将用于为某些条目打上特殊标签,例如标记已检测到特定行为,以便在后续匹配中识别。

  • http_req_cnt [4 字节] 这是 HTTP 请求计数。它是一个正 32 位整数,用于统计从客户端接收的、与该条目匹配的 HTTP 请求数量。无论请求是否有效,均计入总数。请注意,当客户端启用持久连接时,该计数与会话数存在差异。

  • http_req_rate(<period>) [12 字节] 这是一个请求频率计数器。它接受一个整数参数 <period>,表示以毫秒为单位的统计平均值的时间周期长度。该指标报告该周期内的平均 HTTP 请求速率,单位为每周期请求数。结果为整数,可使用 ACL 进行匹配。是否为有效请求无关紧要。请注意,当客户端启用持久连接时,此指标与会话数不同。

  • http_err_cnt [4 字节] 这是 HTTP 请求错误计数。它是一个正 32 位整数,用于统计由匹配此条目的客户端引发的 HTTP 请求错误的绝对数量。错误包括无效或截断的请求、被拒绝或被限速的请求,以及认证失败的请求。若服务器返回 4xx 状态码,则该请求也计入错误,因为这是由客户端触发的错误(例如,漏洞扫描)。

  • http_err_rate(<period>) [12 字节] 这是一个 HTTP 请求频率计数器。它接受一个整数参数 <period>,表示以毫秒为单位的统计周期长度,用于计算平均值。该指标报告该周期内的平均 HTTP 请求错误率,单位为每周期请求数(关于错误的定义,请参见上方的 http_err_cnt)。结果为一个整数,可使用 ACL 进行匹配。

  • http_fail_cnt [4 字节] 这是 HTTP 响应失败计数。它是一个正的 32 位整数,用于统计由匹配此条目的服务器引起的 HTTP 响应失败的绝对数量。无效或截断的响应,以及除 501 或 505 以外的所有 5xx 响应均被计入错误。该指标旨在与 path 或 URI 结合使用,以检测服务故障。

  • http_fail_rate(<period>) [12 字节] 这是一个 HTTP 响应失败频率计数器。它接受一个整数参数 <period>,表示以毫秒为单位的统计平均值的时间周期长度。该指标报告在该周期内每周期的平均 HTTP 响应失败率,单位为每周期请求数(关于失败的定义,请参见上述 http_fail_cnt)。结果为一个整数,可使用 ACL 进行匹配。

  • server_id [4 字节] 该值为整数,用于存储请求被分配到的服务器的数值 ID。此字段由“stick match”、“stick store”和“stick on”规则使用。当被引用时,该字段会自动启用。请注意,基于学习信息的会话粘性存在一些限制,例如所有学习到的关联关系在重启后将丢失,除非对等节点已正确配置为在重启时传输此类信息(建议配置)。通常情况下,会话粘性可作为其他会话粘性机制的补充,但不应始终作为唯一机制。

  • sess_cnt [4 字节] 会话计数。这是一个正的 32 位整数,用于统计匹配此条目的客户端所发起的会话绝对数量。会话指由第 4 层规则(“tcp-request connection”)接受的连接。

  • sess_rate(<period>) [12 字节] 这是一个会话频率计数器。它接受一个整数参数 <period>,表示以毫秒为单位的统计周期长度。该计数器报告在该周期内平均的入站会话速率,单位为每周期会话数。结果为整数,可使用 ACL 进行匹配。

示例:

# Keep track of counters of up to 1 million IP addresses over 5 minutes
# and store a general purpose counter and the average connection rate
# computed over a sliding window of 30 seconds.
stick-table type ip size 1m expire 5m store gpc0,conn_rate(30s)

另请参阅:“stick match”、“stick on”、“stick store-request”、“track-sc”、第 2.5 节 关于时间格式、第 11.2 节 关于对等节点、第 9.7 节 关于带宽限制,以及 第 7 节 关于 ACL。

11.2. 对等节点声明

可以在多个 HAProxy 实例之间通过 TCP 连接以多主模式传播粘性表中的任意数据类型条目。每个实例会将其本地的更新和插入操作推送至远程对等节点。推送的值会直接覆盖远程值,不会进行聚合。

一个例外是数据类型 “conn_cur”,默认情况下不会从对等节点学习该值,因为它应反映本地状态。早期版本默认会同步该值,这已知会导致主动-主动配置中出现负值,以及在重载或主动-被动切换时出现持续增长的值,因为本地值会反映比实际存在的连接数更多的连接。然而,在某些场景下,从对等节点学习该值可能是有意义的,例如当该表为仅用于学习/监控数据的被动远程表,而不依赖其进行写操作或更新时。为实现此目的,可在表声明中添加 “recv-only” 关键字。无论如何,“conn_cur” 信息始终会被推送,以便监控系统能够对其进行观察。

中断的交换会自动检测并从已知的最新点恢复。此外,在执行平滑重启时,旧进程会通过此类 TCP 连接与新进程建立连接,将所有条目推送至新进程,然后再由新进程尝试连接其他对等节点。这确保了重载过程中的快速复制,即使对于大型表,通常也只需不到一秒的时间。

请注意,服务器 ID 用于远程识别服务器,因此配置必须相似,或至少在所有参与方的服务器上强制使用相同的 ID。

peers <peersect>

peers <peersect>

创建一个名为 <peersect> 的新对等节点列表。该列表为独立段,可被一个或多个粘性表引用。

bind [<address>]:port [param*]

bind [<address>]:port [param*]
bind /<path> [param*]

定义本 “peers” 段中本地对等节点的绑定参数。此类行在同属一个 “peers” 段时,不支持与 “peer” 行共存。

disabled

disabled

禁用一个对等节点段。该操作将同时禁用监听功能以及与此段相关的任何同步。此功能用于在不注释掉所有 “peers” 引用的情况下,禁用粘性表的同步。

default-bind [param*]

default-bind [param*]

定义本地对等节点的绑定参数,不包括其地址。

default-server [param*]

default-server [param*]

更改 “peers” 段中服务器的默认选项。

参数:

<param*>  is a list of parameters for this server. The "default-server"
          keyword accepts an important number of options and has a complete
          section dedicated to it. In a peers section, the transport
          parameters of a "default-server" line are supported. Please refer
          to section 5 for more details, and the "server" keyword below in
          this section for some of the restrictions.

另请参阅:“server” 和 第 5 节 关于服务器选项

enabled

enabled

此操作重新启用此前通过 “disabled” 关键字禁用的对等节点段。

log <target> [len <length>] [format <format>] [sample <ranges>:<sample_size>]

log <target> [len <length>] [format <format>] [sample <ranges>:<sample_size>]
    <facility> [<level> [<minlevel>]]

“peers” 段支持与代理相同的 “log” 关键字,用于记录关于 “peers” 监听器的信息。有关详细信息,请参阅代理的 “log” 选项。

peer <peername> [<address>]:port [param*]

peer <peername> [<address>]:port [param*]
peer <peername> /<path> [param*]

定义 peers 段内的对等节点。若 <peername> 设置为本地对等节点名称(默认为主机名,或通过 “-L” 命令行选项或 “localpeer” 全局配置项强制指定),HAProxy 将在指定地址上监听来自远程对等节点的连接。否则,该地址定义了用于连接以加入远程对等节点的目标地址,且 <peername> 在协议层面用于在服务器端识别和验证远程对等节点。

在平滑重启期间,旧实例使用本地对等节点地址连接新实例,并启动完整的复制(教学过程)。

强烈建议在所有对等节点上使用完全相同的 peers 声明,并仅通过 “-L” 命令行参数或 “localpeer” 全局配置项来更改本地对等节点名称。这有助于在所有对等节点间保持配置文件的一致性。

地址参数可以引用环境变量,详见 第 2.3 节 的环境变量说明。

请注意:“peer” 关键字可透明地被 “server” 关键字替换(详见下文 “server” 关键字说明)。

server <peername> [<address>:<port>] [param*]

server <peername> [<address>:<port>] [param*]
server <peername> [/<path>] [param*]

如前所述,“peer” 关键字可被 “server” 关键字替代,后者支持 5.2 段中与传输设置相关的全部 “server” 参数。若底层对等节点为本地节点,则地址参数不得出现;必须在 “bind” 行上提供,参见本 “peers” 段中的 “bind” 关键字。

若干 “server” 参数对 “peers” 段无效。对等节点本质上不支持动态主机名解析或健康检查,因此 “init_addr”、“resolvers”、“check”、“agent-check” 或 “track” 等参数不受支持。同理,不存在负载均衡或会话粘性,因此 “weight” 或 “cookie” 等参数无任何作用。

示例:

 # The old way.
 peers mypeers
     peer haproxy1 192.168.0.1:1024
     peer haproxy2 192.168.0.2:1024
     peer haproxy3 10.2.0.1:1024

 backend mybackend
     mode tcp
     balance roundrobin
     stick-table type ip size 20k peers mypeers
     stick on src

     server srv1 192.168.0.30:80
     server srv2 192.168.0.31:80

Example:
  peers mypeers
     bind 192.168.0.1:1024 ssl crt mycerts/pem
     default-server ssl verify none
     server haproxy1 #local peer
     server haproxy2 192.168.0.2:1024
     server haproxy3 10.2.0.1:1024

shards <shards>

在某些配置中,用户希望将粘性表内容分发至部分对等节点,而非将全部粘性表内容发送给 “peers” 段中声明的每个对等节点。在此类情况下,“shards” 指定参与此粘性表内容分发的对等节点数量。另请参见 “shard” 服务器参数。

table <tablename> type {ip | integer | string [len <length>] | binary [len <length>]}

table <tablename> type {ip | integer | string [len <length>] | binary [len <length>]}
  size `<size>` [expire `<expire>`] [write-to `<wtable>`] [nopurge] [store `<data_type>`]*
  [recv-only]

为当前段配置会话粘性表。该行的解析方式与其它段中的 “stick-table” 关键字完全相同,但此处的 “peers” 参数非必需,并需额外指定一个必填的首个参数以标识粘性表。与其它段不同,“peers” 段中可存在多个 “table” 行(另请参见 第 11.1 节 中对 “table” 和 “stick-table” 关键字的完整定义)。

请注意,“peers” 段具有独立的 stick-table 命名空间,以避免不同 “peers” 段中名称相同的 stick-table 发生冲突。此机制在内部通过在 “peers” 段名称后添加斜杠(/)字符来实现,从而为 stick-table 名称添加前缀。若在配置文件的其他位置需引用 “peers” 段中声明的 stick-table,请务必使用带前缀的 stick-table 名称,格式如下:

peers mypeers
    peer A ...
    peer B ...
    table t1 ...

frontend fe1
    tcp-request content track-sc0 src table mypeers/t1

这也必须是粘性表名称的前缀版本,通过 CLI 引用粘性表时需使用该格式。

关于 “peers” 协议,由于仅属于同一段的 “peers” 才能相互通信,因此无需进行此类区分。多个 “peers” 段可声明名称相同的 stick-table。这是通过网络传输的 stick-table 名称的简写形式。仅以斜杠字符 ‘/’ 作为前缀,以避免在以后端形式声明的 stick-table 与在 “peers” 段中声明的 stick-table 之间发生名称冲突,如下所示的奇特但受支持的配置:

peers mypeers
    peer A ...
    peer B ...
    table t1 type string size 10m store gpc0

backend t1
    stick-table type string size 10m store gpc0 peers mypeers

此处 “t1” 表在 “mypeers” 段中声明,其全局名称为 “mypeers/t1”。“t1” 表作为后端声明,其全局名称为 “t1”。但在对等节点协议层面,前者表名为 “/t1”,后者再次命名为 “t1”。

21 - 12. 其他配置段

跟踪、用户、邮件发送器、错误、环形缓冲区、证书、ACME、全局健康检查

以下所述段落使用频率较低,通常仅支持少量参数。它们之间不存在隐式关联。所有段均通过单一关键字启动。在 “global” 段之前禁止出现任何此类段。部分段的支持可能受构建选项限制(例如与 SSL 相关的任何功能)。

12.1. 跟踪

为调试目的,可激活 HAProxy 子系统上的追踪功能。该功能将输出特定子系统的调试消息,是诊断问题的强力工具。可通过 CLI 动态配置追踪。也可在配置文件中通过专用 “traces” 段预先定义部分设置。有关追踪的更多详情,请参阅管理指南。该功能属于开发者工具,适用于复杂调试会话。其输出信息极为详尽,且存在性能开销,使用时应谨慎。由于其为开发者工具,本段配置不保证向后兼容性。

traces

traces

开始一个新的 traces 段。可使用一个或多个 “traces” 段。所有指令按声明顺序求值,后声明的指令会覆盖先前的指令。

trace <source> <args...>

trace <source> <args...>

配置在 “trace” 子系统中。每个配置项均可在管理手册中找到,并遵循完全相同的语法。“trace” 命令所产生的任何输出,均会在本段的解析阶段发出。大多数情况下,这些输出为错误和警告信息,但某些不完整的命令可能会列出允许的选择项。该命令并非用于常规使用,通常仅在复杂调试会话中由开发者建议使用。请注意,根据追踪级别和详细程度,启用追踪可能会严重降低整体性能。有关语句语法的详细信息,请参阅管理手册。

示例:

ring buf1
  size 10485760 # 10MB
  format timed
  backing-file /tmp/h1.traces

ring buf2
  size 10485760 # 10MB
  format timed
  backing-file /tmp/h2.traces

traces
  trace h1 sink buf1 level developer verbosity complete start now
  trace h2 sink buf1 level developer verbosity complete start now

12.2. 用户列表

可以控制对前端、后端或监听段以及 HTTP 统计信息的访问,仅允许经过身份认证和授权的用户访问。为此,必须至少创建一个用户列表,并定义用户。

userlist <listname>

userlist <listname>

创建名为 <listname> 的新用户列表。可使用多个独立的用户列表,以分别存储不同客户的认证与授权数据。

group <groupname> [users <user>,<user>,(...)]

group <groupname> [users <user>,<user>,(...)]

将组 <groupname> 添加到当前用户列表中。也可通过在 “users” 关键字后使用以逗号分隔的用户名列表,将用户附加到该组。

user <username> [password|insecure-password <password>]

user <username> [password|insecure-password <password>]
                [groups <group>,<group>,(...)]

将用户 <username> 添加至当前用户列表。可使用加密(安全)或非加密(不安全)密码。加密密码通过 crypt(3) 函数进行评估,具体支持的算法取决于系统的功能,例如基于现代 Glibc 的 Linux 系统支持 MD5、SHA-256、SHA-512,以及经典的基于 DES 的密码加密方法。

请注意:使用加密密码可能导致显著增加的 CPU 使用率,具体取决于请求数量以及所使用的算法。对于任何哈希变体,每个请求的密码都必须在与配置文件中指定的值进行比较之前,通过所选算法进行处理。当前大多数算法均故意设计为计算成本较高,以抵御暴力破解攻击。它们并非仅对明文密码进行一次加盐哈希,而是重复数千次。这可能迅速成为 HAProxy 整体 CPU 消耗的主要因素,甚至可能导致应用程序崩溃!

为降低哈希函数的高 CPU 使用率,一种方法是减少哈希函数(SHA 系列算法)的迭代轮数,或在算法支持的情况下降低 “cost” 值。

需要注意,使用 musl(例如 Alpine Linux)实现时,计算哈希值的性能通常低于其 glibc 对应实现,因此也建议考虑此因素。

所有密码均被视为普通参数,因此受 section 2.2 引用与转义规则约束。建议对密码使用单引号。

示例:

userlist L1
  group G1 users tiger,scott
  group G2 users xdb,scott

  user tiger password $6$k6y3o.eP$JlKBx9za9667qe4(...)xHSwRv6J.C0/D7cV91
  user scott insecure-password 'elgato'
  user xdb insecure-password 'hello'

userlist L2
  group G1
  group G2

  user tiger password $6$k6y3o.eP$JlKBx(...)xHSwRv6J.C0/D7cV91 groups G1
  user scott insecure-password 'elgato' groups G1,G2
  user xdb insecure-password 'hello' groups G2

请注意,两个列表在功能上完全相同。

12.3. 邮件发送器

当服务器状态发生变化时,可发送电子邮件警报。若已配置邮件警报,将向 mailers 段中配置的每个邮件发送器发送邮件。邮件通过 Lua 发送(参见 examples/lua/mailers.lua)。

mailers <mailersect>

mailers <mailersect>

创建一个名为 <mailersect> 的邮件列表。该邮件列表为独立段,可被一个或多个代理引用。

mailer <mailername> <ip>:<port>

mailer <mailername> <ip>:<port>

在 mailers 段中定义一个邮件发送器。

示例:

global
    # mailers.lua file as provided in the git repository
    # adjust path as needed
    lua-load examples/lua/mailers.lua

mailers mymailers
    mailer smtp1 192.168.0.1:587
    mailer smtp2 192.168.0.2:587

backend mybackend
    mode tcp
    balance roundrobin

    email-alert mailers mymailers
    email-alert from test1@horms.org
    email-alert to test2@horms.org

    server srv1 192.168.0.30:80
    server srv2 192.168.0.31:80

timeout mail <time>

timeout mail <time>

定义用于建立邮件/连接并发送至邮件服务器的时间。若未定义,默认值为 10 秒。为确保初始 TCP 握手期间至少可发送两个 SYN-ACK 数据包,建议将此值保持在 4 秒以上。

示例:

mailers mymailers
    timeout mail 20s
    mailer smtp1 192.168.0.1:587

12.4. HTTP 错误

可以全局声明多个 HTTP 错误组,后续可在任意代理段中导入。同一组可被多次引用,且可完全或部分导入。

http-errors <name>

http-errors <name>

创建一个名为 <name> 的新 http-errors 组。该组为独立段,可被一个或多个代理通过名称引用。

errorfile <code> <file>

errorfile <code> <file>

将文件内容与 HTTP 错误码关联

参数:

<code>    is the HTTP status code. Currently, HAProxy is capable of
          generating codes 200, 400, 401, 403, 404, 405, 407, 408, 410,
          425, 429, 500, 501, 502, 503, and 504.

<file>    designates a file containing the full HTTP response. It is
          recommended to follow the common practice of appending ".http" to
          the filename so that people do not confuse the response with HTML
          error pages, and to use absolute paths, since files are read
          before any chroot is performed.

请参阅 “errorfile” 关键字在 第 4 节 中的说明以获取详细信息。

示例:

http-errors website-1
    errorfile 400 /etc/haproxy/errorfiles/site1/400.http
    errorfile 404 /etc/haproxy/errorfiles/site1/404.http
    errorfile 408 /dev/null  # work around Chrome pre-connect bug

http-errors website-2
    errorfile 400 /etc/haproxy/errorfiles/site2/400.http
    errorfile 404 /etc/haproxy/errorfiles/site2/404.http
    errorfile 408 /dev/null  # work around Chrome pre-connect bug

12.5. 环形缓冲区

可以全局声明环形缓冲区,用作日志服务器或追踪目标。

ring <ringname>

ring <ringname>

创建一个名为 <ringname> 的环形缓冲区。

backing-file <path>

backing-file <path>

使用内存映射文件替代常规内存分配来存储环形缓冲区。这在无需通过慢速客户端连接 CLI 的情况下,可用于收集用于事后分析的追踪数据或日志。新写入的内容将自动覆盖旧内容,确保始终可获取最新数据。进程停止后,写入环形缓冲区的内容将立即在该文件中可见(通常会在进程停止后很快显现,但无此保证,因为写入操作并非同步)。

当使用此选项时,总存储区域将减少“struct ring”所占的大小,该结构从区域起始位置开始,用于恢复区域内容。文件将以起始用户的所有权创建,权限模式为 0600,并且大小由 “size” 指令配置。在指令解析时(即使在配置检查期间),任何已存在的非空文件将首先被重命名为附加后缀 “.bak”,任何先前存在的带有后缀 “.bak” 的文件将被删除。这确保了进程的即时重载或重启不会清除宝贵的调试信息,并为管理员留出时间发现此新生成的 “.bak” 文件,必要时可将其归档。因此,在崩溃后,由 <path> 指定的文件将包含最新信息;若服务重启,则“<path>.bak”文件将包含该信息。这意味着所需的总存储容量将是环形缓冲区大小的两倍。文件轮转失败将被静默忽略,因此将文件置于无写权限的目录中即可避免生成备份文件(如无需该功能)。

请注意:使用此功能存在稳定性与安全风险。首先,将环形缓冲区(ring)备份到慢速设备(例如物理硬盘)可能导致访问时出现明显延迟,若过多线程竞争访问,甚至可能引发系统崩溃。其次,外部进程修改该区域可能导致 HAProxy 进程崩溃,或导致其自身内存被覆盖。第三,若文件系统在环形缓冲区之前已满,向环形缓冲区写入数据可能引发进程崩溃。

环形缓冲区中的信息采用结构化格式,无法直接通过文本编辑器读取(尽管其中大部分内容看起来几乎无法阅读)。该文件的输出仅适用于开发者。

description <text>

description <text>

描述为环形缓冲区的可选描述字符串,将在 CLI 中显示。默认情况下,<name> 被复用以填充此字段。

format <format>

format <format>

用于将事件存储到环形缓冲区的格式。

参数:

<format> is the log format used when generating syslog messages. It may be
         one of the following:

  iso     A message containing only the ISO date, followed by the text.
          The PID, process name and system name are omitted. This is
          designed to be used with a local log server.

  local   Analog to rfc3164 syslog message format except that hostname
          field is stripped. This is the default.
          Note: option "log-send-hostname" switches the default to
          rfc3164.

  raw     A message containing only the text. The level, PID, date, time,
          process name and system name are omitted. This is designed to be
          used in containers or during development, where the severity
          only depends on the file descriptor used (stdout/stderr). This
          is the default.

  rfc3164 The RFC3164 syslog message format.
          (https://tools.ietf.org/html/rfc3164)

  rfc5424 The RFC5424 syslog message format.
          (https://tools.ietf.org/html/rfc5424)

  short   A message containing only a level between angle brackets such as
          '<3>', followed by the text. The PID, date, time, process name
          and system name are omitted. This is designed to be used with a
          local log server. This format is compatible with what the systemd
          logger consumes.

 priority A message containing only a level plus syslog facility between angle
          brackets such as '<63>', followed by the text. The PID, date, time,
          process name and system name are omitted. This is designed to be used
          with a local log server.

  timed   A message containing only a level between angle brackets such as
          '<3>', followed by ISO date and by the text. The PID, process
          name and system name are omitted. This is designed to be
          used with a local log server.

maxlen <length>

maxlen <length>

存储于环形缓冲区中的事件消息的最大长度,包括格式化头。若事件消息长度超过 <length>,将被截断至该长度。

server <name> <address> [param*]

server <name> <address> [param*]

用于配置一个 syslog TCP 服务器,以将环形缓冲区中的消息转发出去。此功能支持 5.2 段中列出的所有 “server” 参数。其中部分参数对 “ring” 段不适用。重要提示:向环形缓冲区添加多个服务器并无实际意义,因为所有服务器将收到环形缓冲区内容的完全相同副本,环形缓冲区的推进速度将受限于最慢的服务器。若某一服务器无响应,将导致旧消息无法被清除,甚至可能阻塞新消息插入环形缓冲区。向多个服务器发送消息的正确方式是为每个日志服务器配置独立的环形缓冲区,而非将多个服务器绑定至同一环形缓冲区。请注意,特定的服务器指令 “log-proto” 用于设置消息发送所使用的协议。

size <size>

size <size>

这是可选的环形缓冲区大小,单位为字节。默认值设为 BUFSIZE。

timeout connect <timeout>

timeout connect <timeout>

设置连接尝试连接服务器时等待成功的最长时间。

参数:

<timeout> is the timeout value specified in milliseconds by default, but
          can be in any other unit if the number is suffixed by the unit,
          as explained at the top of this document.

timeout server <timeout>

timeout server <timeout>

设置输出缓冲区中待处理数据的最大停留时间。

参数:

<timeout> is the timeout value specified in milliseconds by default, but
          can be in any other unit if the number is suffixed by the unit,
          as explained at the top of this document.

示例:

global
    log ring@myring local7

ring myring
    description "My local buffer"
    format rfc5424
    maxlen 1200
    size 32764
    timeout connect 5s
    timeout server 10s
    server mysyslogsrv 127.0.0.1:6514 log-proto octet-count

12.6. 日志转发

可以声明一个或多个日志转发段,HAProxy 会将所有接收到的日志消息转发至日志服务器列表。

log-forward <name>

log-forward <name>

创建一个标识为 <name> 的新日志转发代理。

backlog <conns>

backlog <conns>

向系统提供关于连接接收时期望的监听队列大小的提示。

bind <addr> [param*]

bind <addr> [param*]

用于配置流日志监听器以接收待转发的消息。此功能支持 5.1 小节中列出的 “bind” 参数,包括与 ssl 相关的参数,但某些语句如 “alpn” 对于通过 TCP 传输的 syslog 协议可能不适用。这些监听器支持 RFC-6587 中定义的“八位组计数”和 “Non-Transparent-Framing” 模式。

dgram-bind <addr> [param*]

dgram-bind <addr> [param*]

用于配置一个数据报日志监听器,以接收需转发的消息。地址必须采用 IPv4 或 IPv6 格式,后接端口。此配置支持 5.1 小节中部分 “bind” 参数,其中 “interface”、“namespace” 或 “transparent” 有效,其余参数在 UDP/syslog 场景下被视为无关,将被静默忽略。

log global

log global
log <target> [len <length>] [format <format>] [sample <ranges>:<sample_size>]
    <facility> [<level> [<minlevel>]]

用于配置目标日志服务器。有关代理的更多详细信息,请参见代理文档。若未指定日志格式,HAProxy 将尝试保留传入日志的格式。配置的设施(facility)会被忽略,除非传入消息中未包含设施,但输出格式中该字段为必填项。若输入格式中无时间戳,但输出格式中存在该字段,HAProxy 将使用本地日期。

示例:

global
   log stderr format iso local7

ring myring
    description "My local buffer"
    format rfc5424
    maxlen 1200
    size 32764
    timeout connect 5s
    timeout server 10s
    # syslog tcp server
    server mysyslogsrv 127.0.0.1:514 log-proto octet-count

log-forward sylog-loadb
    dgram-bind 127.0.0.1:1514
    bind 127.0.0.1:1514
    # all messages on stderr
    log global
    # all messages on local tcp syslog server
    log ring@myring local0
    # load balance messages on 4 udp syslog servers
    log 127.0.0.1:10001 sample 1:4 local0
    log 127.0.0.1:10002 sample 2:4 local0
    log 127.0.0.1:10003 sample 3:4 local0
    log 127.0.0.1:10004 sample 4:4 local0

maxconn <conns>

maxconn <conns>

修复日志转发器的最大并发连接数。默认值为 10。

timeout client <timeout>

timeout client <timeout>

设置客户端的最大不活动时间。

option assume-rfc6587-ntf

option assume-rfc6587-ntf

强制 HAProxy 始终将传入的 TCP 日志流视为使用非透明帧格式。此选项简化了帧格式逻辑,并确保消息处理的一致性,尤其在处理格式不正确的起始字符时尤为有用。

option dont-parse-log

option dont-parse-log

启用 HAProxy 以中继 syslog 消息,而不尝试解析和重构消息内容,适用于转发可能不符合传统格式的消息。此选项应与目标日志目标上的 format raw 设置配合使用,以确保原始消息内容得以保留。

option host { replace | fill | keep | append }

option host { replace | fill | keep | append }

设置在日志转发段中针对出站 RFC3164 或 RFC5424 消息的 syslog 主机字段所应采用的主机策略。

  replace If input message already contains a value for the hostname field,
          we replace it by the source IP address from the sender.
          If input message doesn't contain a value for the hostname field
          (ie: '-' as input rfc5424 message or non compliant rfc3164 or
          rfc5424 message), we use the source IP address from the sender as
          hostname field.

  fill    If input message already contains a value for the hostname field,
          we keep it.
          If input message doesn't contain a value for the hostname field
          (ie: '-' as input rfc5424 message or non compliant rfc3164 or
          rfc5424 message), we use the source IP address from the sender as
          hostname field.
          (This is the default)

  keep    If input message already contains a value for the hostname field,
          we keep it.
          If input message doesn't contain a value for the hostname field,
          we set it to 'localhost' (rfc3164) or '-' (rfc5424).

  append  If input message already contains a value for the hostname field,
          we append a comma followed by the IP address from the sender.
          If input message doesn't contain a value for the hostname field,
          we use the source IP address from the sender.

对于上述所有选项,若发送方的源 IP 地址不可用(例如:UNIX/ABNS 套接字),则结果策略为 “keep”。

请注意,此选项仅对 rfc3164 或 rfc5424 目标日志格式有效。其他日志格式下设置该选项将无明显效果。

12.7. 证书存储

HAProxy 使用内部存储机制来加载和存储配置中使用的证书。 该存储可通过使用 “crt-store” 段进行配置。它允许配置证书定义以及应加载到其中的文件。证书定义必须在配置中其他位置使用之前先声明。

crt-store [<name>]

“crt-store” 在参数中可选地指定名称。若指定名称,则该存储中的每个证书必须使用 “@<name>/<crt>” 或 “@<name>/<alias>” 进行引用。

证书存储中的文件也可通过 CLI 动态更新。参见管理指南中 第 9.3 节 的 “set ssl cert”。

以下关键字在 “crt-store” 段中受支持:

  • crt-base
  • key-base
  • load

crt-base <dir>

crt-base <dir>

为在使用 “crt” 指令时指定相对路径的默认证书目录。若指定绝对路径,则优先生效并忽略 “crt-base”。在 crt-store 中使用时,全局段的 crt-base 将被忽略。

key-base <dir>

key-base <dir>

为在使用 “key” 指令时指定相对路径获取 SSL 私钥的默认目录。若指定绝对路径,则优先生效,并忽略 “key-base”。在 crt-store 中使用时,全局段的 key-base 将被忽略。

load [crt <filename>] [param*]

load [crt <filename>] [param*]

在证书存储中加载 SSL 文件。参数列表请参见段 “12.7.1. Load options”

示例:

crt-store
    load crt "site1.crt" key "site1.key" ocsp "site1.ocsp" alias "site1"
    load crt "site2.crt" key "site2.key"

frontend in2
    bind *:443 ssl crt "@/site1" crt "site2.crt"

crt-store web
    crt-base /etc/ssl/certs/
    key-base /etc/ssl/private/
    load crt "site3.crt" alias "site3"
    load crt "site4.crt" key "site4.key"

frontend in2
    bind *:443 ssl crt "@/site1" crt "site2.crt"  crt "@web/site3" crt "@web/site4.crt"

12.7.1. 负载选项

在证书存储中加载 SSL 文件。load 关键字可接受多个参数,具体如下所示。这些关键字也可在 crt-list 中使用。

crt <filename>

crt <filename>

此参数为必填项,用于加载一个 PEM 格式文件,其中必须包含公钥证书,也可包含中间证书和私钥。若该文件中未提供私钥,则可使用 “key” 关键字指定私钥。

acme <string>

acme <string>

此选项用于为指定证书配置 ACME 协议。此功能为实验性特性,需在全局段中包含 “expose-experimental-directives” 关键字。

在 crt-store 中使用 “acme” 关键字时,可无需磁盘上已存在的证书即启动。此时将使用临时密钥对,直至 ACME 证书生成。此行为仅适用于 crt-store,若未先声明 crt-store,仅通过 crt-list 行或 ssl-f-use 行无法实现相同效果。

另请参见 第 12.8 节 (“ACME”)以及本段中的 “domains”。

alias <string>

alias <string>

可选参数。允许使用别名命名证书,以便在配置中通过该别名引用。在配置的其他位置调用别名时,必须以 @/ 为前缀。

domains <string>

domains <string>

配置用于 ACME 证书的域名列表。列表中的第一个域名将用作 CN。域名之间以逗号分隔。

另请参见 第 12.8 节 (“ACME”)以及本段中的 “acme”。

示例:

load crt "example.com.pem" acme LE domains "bar.example.com,foo.example.com"

ips <string>

ips <string>

配置将作为 IP SAN 包含在 ACME 证书中的 IP 地址列表。IP 地址以逗号分隔。

使用 “shortlived” 配置文件可能需要生成包含 IP 地址的证书。

另请参见本节中的 第 12.8 节 (“ACME”)、“acme” 及 “domains”。

示例:

load crt "server.pem" acme LE ips "192.0.2.1,2001:db8::1"

key <filename>

key <filename>

该参数为可选。加载以 PEM 格式编码的私钥。如果已通过 “crt” 定义了私钥,则将覆盖原有设置。

ocsp <filename>

ocsp <filename>

该参数为可选参数,用于加载以 DER 格式编码的 OCSP 响应。可通过 CLI 更新。

issuer <filename>

issuer <filename>

此参数为可选。以 PEM 格式加载 OCSP 发行者证书。为确定 OCSP 响应适用于哪个证书,必须提供发行者证书。如果在 “crt” 文件中未找到发行者证书,可使用此参数从文件加载。

sctl <filename>

sctl <filename>

此参数为可选。已启用对证书透明度(RFC6962)TLS 扩展的支持。 文件必须包含符合 RFC 描述的有效签名证书时间戳列表。文件将被解析以检查基本语法,但不会验证签名。

ocsp-update [ off | on ]

ocsp-update [ off | on ]

当设置为 ‘on’ 时,启用自动 OCSP 响应更新;否则,禁用该功能。其默认值为 ‘off’。可在 bind 语句中通过 crt-store 配置或使用全局选项 “tune.ocsp-update.mode” 来启用 OCSP 自动更新。若某个证书在多个 crt-list 中使用,且这些列表中 ‘ocsp-update’ 的设置值不同,则会引发错误。同理,若证书在 bind 语句中继承全局选项,但在 crt-list 中显式设置了不兼容的 ‘ocsp-update’ 选项,同样会引发错误。

示例:

以下是使用 crt-list 启用该功能的配置示例:

HAProxy.cfg:

frontend fe
    bind:443 ssl crt-list haproxy.list

HAProxy.list:

server_cert.pem [ocsp-update on] foo.bar

以下是使用 crt-store 启用该功能的配置示例:

HAProxy.cfg:

crt-store
  load crt foobar.pem ocsp-update on

frontend fe
    bind:443 ssl crt foobar.pem

当该选项设置为 ‘on’ 时,若在前端证书中发现 OCSP URI,系统将尝试获取 OCSP 响应。此模式的唯一限制是,必须已知证书颁发者信息,才能构建 OCSP certid。每个 OCSP 响应至少每小时更新一次,若某 OCSP 响应的过期时间早于该一小时限制,则更新频率将更高。为避免对过期时间极短或根本无“Next Update”字段的响应进行过于频繁的更新,仍会保留最少 5 分钟的更新间隔。由于存在此硬性限制,请注意,当自动更新设置为 ‘on’ 时,初始化期间加载的任何 OCSP 响应将在至少 5 分钟内不会被更新,即使其过期时间早于 now+5m。这通常不会造成太大困扰,因为 OCSP 响应在初始化加载时必须处于有效状态(其过期时间必须在将来),因此该响应在初始化后极短时间内过期的可能性极低。另一方面,若某证书指定了 OCSP URI 但未提供 OCSP 响应,将该证书的此选项设置为 ‘on’,可确保在初始化后立即自动获取 OCSP 响应。默认的最小和最大延迟(分别为 5 分钟和 1 小时)可通过 “ocsp-update.maxdelay” 和 “ocsp-update.mindelay” 全局选项进行配置。

每当 OCSP 响应由自动更新任务更新,或在调用 “update ssl ocsp-response” CLI 命令后,都会生成一条专用日志行。该日志行遵循专用格式,包含以下头信息 “<OCSP-UPDATE>",后接特定的 OCSP 相关信息:- 对应前端证书的路径 - 数值型更新状态 - 文本型更新状态 - 该响应的更新失败次数 - 该响应的更新成功次数。有关完整的错误码和错误消息列表,请参见 “show ssl ocsp-updates” CLI 命令。无论相关 OCSP 响应更新成功或失败,均会发出此日志行。OCSP 请求/响应通过一个设置了 dontlog-normal 选项的 http_client 实例发送和接收,若发生错误(例如无法访问 OCSP 响应方),则使用常规 HTTP 日志格式。若发生此类错误,将伴随 “regular” OCSP 日志行,发出另一条包含 HTTP 相关信息的日志行(该日志行的文本状态很可能为 “HTTP error”)。但若发生纯粹的 HTTP 错误(例如无法访问 OCSP 响应方),则会额外发出一条遵循常规 HTTP 日志格式的日志行。以下是两条此类日志行的示例,首先为成功的 OCSP 更新日志行,随后为 HTTP 错误的示例,包含两条不同的日志行(为便于阅读,行已拆分,URL 已缩短):

<133>Mar  6 11:16:53 haproxy[14872]: <OCSP-UPDATE> /path_to_cert/foo.pem 1 \
        "Update successful" 0 1

<133>Mar  6 11:18:55 haproxy[14872]: <OCSP-UPDATE> /path_to_cert/bar.pem 2 \
        "HTTP error" 1 0
<133>Mar  6 11:18:55 haproxy[14872]: -:- [06/Mar/2023:11:18:52.200] \
        <OCSP-UPDATE> -/- 2/0/-1/-1/3009 503 217 - - SC-- 0/0/0/0/3 0/0 {} \
        "GET http://127.0.0.1:12345/MEMwQT HTTP/1.1"

故障排查:使用 Let’s Encrypt 证书时常见的错误之一是,若 DNS 解析返回 IPv6 地址,而系统未配置有效的出站 IPv6 路由。在此情况下,可以选择创建相应的路由,或在全局段中设置 “httpclient.resolvers.prefer ipv4” 选项。若出现 “OCSP 响应检查失败” 错误,应检查所提供的颁发者证书是否有效。在 “generic” 错误消息之后,括号内可能显示更精确的错误信息。该情况可能出现在 “OCSP 响应检查失败” 或 “插入过程中发生错误” 错误中。

jwt [ off | on ]

jwt [ off | on ]

允许通过 “jwt_verify_cert”、“jwt_decrypt_cert” 或 “jwt_decrypt” 转换器在设置为 ‘on’ 时,使用该证书进行 JWT 验证或解密。其默认值为 ‘off’。

当为某个证书设置 ‘on’ 时,CLI 命令 “del ssl cert” 将无法执行。要删除证书,该证书必须未被使用,无论是用于 SSL 握手还是 JWT 验证。

此选项可通过 CLI 命令 “add ssl jwt” 和 “del ssl jwt” 在运行时更改。另请参见 “show ssl jwt” CLI 命令。

generate-dummy [ off | on ]

generate-dummy [ off | on ]

在设置为 ‘on’ 时,允许在解析时生成私钥及其自签名证书。这在测试阶段未持有证书时可能有用。此时,可使用 “keytype”、“bits” 和 “curves” 自定义私钥。未使用时,默认值为 ‘off’。(另见 “keytype”、“bits” 和 “curves”)。

keytype [ RSA | ECDSA ]

keytype [ RSA | ECDSA ]

允许在解析时选择用于生成自签名证书的私钥类型。当此证书的 “generate-dummy” 设置为 ‘on’ 时,即为这种情况。未使用时,默认值为 ‘RSA’。(另请参见 “generate-dummy”)。

bits <number>

bits <number>

配置当 “generate-dummy” 设置为 ‘on’ 且 “keytype” 设置为 ‘RSA’ 时生成 RSA 自签名证书的位数。未使用时,默认值为 2048。(另请参见 “generate-dummy”)。

curves <string>

curves <string>

当 “generate-dummy” 设置为 ‘on’ 且 “keytype” 设置为 ‘ECDSA’ 时,配置此自签名证书的曲线。默认值为 ‘P-384’。

12.8. ACME

acme <name>

ACME 协议可通过 “acme” 段进行配置。该段需指定一个 “<name>” 参数,用于将证书与该段关联。

本节允许将 HAProxy 配置为 ACMEv2 客户端。此功能为实验性,因此 “expose-experimental-directives” 必须位于 global 段中,方可使用。

本文档在 HAProxy 官方维基上提供 https://github.com/haproxy/wiki/wiki/ACME:--native-haproxy

当前限制:

- The feature is limited to the http-01, dns-01 or dns-persist-01 challenges

- The feature is limited to the http-01, dns-01 or dns-persist-01 challenges

目前,http-01 完全由 HAProxy 处理,但 dns-01 和 dns-persist-01 需要通过 dataplaneAPI 或其他第三方工具与 DNS 提供商 API 通信。dns-persist-01 仅需设置一次 TXT 记录,因此可手动设置而无需使用工具。

- It is possible to start without an existing certificate on the disk. To do

- It is possible to start without an existing certificate on the disk. To do

因此,证书必须配置在 crt-store 中。在 crt-store 中使用 “acme” 关键字时,将在 ACME 证书生成前临时使用一对密钥。

- The current HAProxy architecture is a non-blocking model, access to the disk

- The current HAProxy architecture is a non-blocking model, access to the disk

在配置加载后不应执行此操作,因为这可能导致事件循环被阻塞,从而阻塞同一线程上的流量。这意味着由 HAProxy 生成的证书和密钥需通过统计信息套接字上的 “dump ssl cert” 命令从 HAProxy 外部转储。可以使用 dataplaneAPI 或 admin/cli/ 目录中提供的 HAProxy-dump-certs 脚本自动化证书转储。

ACME 调度器在 HAProxy 启动时启动,它将遍历所有证书,并在 notAfter 时间超过当前时间加上 (notAfter - notBefore) / 12 或 7 天(若 notBefore 未定义)时,启动 ACME 证书续期任务。调度器随后将休眠,并在 12 小时后唤醒。可以使用命令 “acme renew” 手动启动续期任务。详见管理指南中的 “acme status”。

以下关键字可在 ACME 段中使用:

account-key <filename>

account-key <filename>

配置账户密钥的路径。在启动 HAProxy 之前,必须先生成密钥。若未使用 account 关键字,acme 段将尝试使用文件名 “<name>.account.key” 加载文件。如果该文件不存在,HAProxy 将根据 acme 段中的参数生成一个密钥。

也可以使用 OpenSSL 手动生成 RSA 私钥:

openssl genrsa -out account.key 2048

或一个 ecdsa 类型的:

openssl ecparam -name secp384r1 -genkey -noout -out account.key

acme-vars <string>

acme-vars <string>

通过 “dpapi” 汇集点向外部 DNS 配置工具(例如 dataplaneAPI)传递任意变量。语义由工具具体决定;请参阅所用 DNS 配置工具文档。

该关键字仅在挑战类型为 “dns-01” 或 “dns-persist-01” 时才有意义。

另请参阅:“challenge”、“provider-name”

bits <number>

bits <number>

配置生成 RSA 证书时使用的位数。默认值为 2048。若机器性能不足,设置过高的值可能触发警告。(此值可通过 “warn-blocked-traffic-after” 配置,但过长的阻断时间可能触发看门狗机制。)

challenge <string>

challenge <string>

指定一个挑战类型作为参数,必须为 http-01、dns-01 或 dns-persist-01。若未使用,则默认为 http-01。

dns-persist-01 实现了 draft-ietf-acme-dns-persist。与 dns-01 不同,它在 “_validation-persist.<domain>” 处使用一个静态 TXT 记录,该记录仅设置一次,后续续订过程中不会更改。该记录必须包含账户 URI,以及一个可选的策略。此挑战类型在每次续订时无需对 DNS 提供商 API 进行写入访问。

challenge-ready <value>[,<value>]*

challenge-ready <value>[,<value>]*

配置在通知 ACME 服务器 DNS-01 挑战已准备就绪之前必须满足的条件。接受的取值如下:

cli  - wait for an operator to signal readiness via the CLI command
       "acme challenge_ready <crt> domain <domain>" on the master CLI or
       the stats socket. This allows an external DNS provisioning tool to
       confirm that the TXT record has been set before HAProxy proceeds.

dns  - perform a DNS pre-check by resolving the TXT record for
       "_acme-challenge.<domain>" using the configured "default" resolvers
       section, not the authoritative name servers. The challenge is not
       submitted until the TXT record matches the expected token. Results
       may therefore be affected by DNS caching at the resolver level. The
       delay between resolution attempts is controlled by "dns-delay". This
       option is independent of the CLI command, so no human intervention
       is required.

       For dns-01, the TXT record at "_acme-challenge.<domain>" is
       resolved and must match the expected token. For dns-persist-01,
       the TXT record at "_validation-persist.<domain>" is resolved and
       only its presence is checked.

delay - apply an initial wait of "dns-delay" before proceeding. Without
        "dns", the challenge is submitted after the delay expires. When
        combined with "dns", the initial wait is applied before starting
        the DNS pre-checks.

none - no readiness condition; the challenge is submitted to the ACME
       server immediately without waiting for any external confirmation.
       This option cannot be combined with others.

多个值可使用逗号组合。当指定多个条件时,HAProxy 按以下顺序处理:首先等待 CLI 确认(“cli”),然后应用初始延迟(“delay”),最后执行 DNS 预检查(“dns”)。

此选项仅与 dns-01 和 dns-persist-01 挑战类型兼容。

当 “challenge” 设置为 “dns-01” 且未配置此选项时,默认值为 “cli”。

当 “challenge” 设置为 “dns-persist-01” 且未配置此选项时,默认值为 “dns,delay”。

当 “challenge” 设置为 “dns-persist-01” 时,将在评估验证就绪条件之前始终执行一次初始的主动式 DNS 检查。由于 “_validation-persist.<domain>” TXT 记录在续订期间仅设置一次且不会更改,HAProxy 会在续订时检查该记录是否已存在。如果所有域名的检查均成功,验证请求将立即提交,跳过验证就绪流程(cli、delay、dns)。如果检查失败,HAProxy 将回退到正常的验证就绪流程。

示例:

# Wait for CLI confirmation, then verify DNS propagation
challenge-ready cli,dns

contact <string>

contact <string>

与证书颁发机构(CA)中的账户密钥相关联的联系邮箱。

curves <string>

curves <string>

使用 ECDSA 密钥类型时,请配置椭圆曲线。默认值为 P-384。

directory <string>

directory <string>

该关键字用于配置本段中 ACME 使用的 CA 目录 URL。由于不存在默认 URL,此关键字为必须项。

示例:

directory https://acme-staging-v02.api.letsencrypt.org/directory

dns-delay <time>

dns-delay <time>

配置 “challenge-ready” 条件 “delay” 和 “dns” 所使用的延迟时间。该值为以 HAProxy 时间格式表示的时间(例如 “5m”、“300s”)。默认值为 30 秒。

其作用取决于所使用的 “challenge-ready” 条件:

delay     - the challenge is submitted after this delay expires, without
            any DNS pre-check.

dns       - the delay between two consecutive DNS resolution attempts.
            The first probe fires immediately without any initial wait.

dns+delay - the initial wait before the first DNS resolution attempt, and
            the delay between subsequent retries.

请注意,解析过程通过配置的 “default” 解析器段进行,而非权威域名服务器。因此,结果仍可能受解析器层级 DNS 缓存的影响。

dns-timeout <time>

dns-timeout <time>

当 “challenge-ready” 包含 “dns” 时,配置在中止挑战前允许成功解析 TXT 记录的最大时间。该值为以 HAProxy 时间格式表示的时间(例如 “10m”、“600s”)。默认值为 600 秒。

超时从首次 DNS 解析尝试触发时开始计算(在初始 “dns-delay” 之后)。若下一次解析尝试将在超时结束后才触发,则挑战将因错误而中止。此机制可防止 DNS 传播失败时出现无限重试循环。

参见:“dns-delay”

keytype <string>

keytype <string>

配置将生成的密钥类型。值可以是 “RSA” 或 “ECDSA”。还可以为 ECDSA 配置 “curves”,并为 RSA 配置 “bits”。默认情况下生成 EC384 密钥。

map <map>

map <map>

配置用于存储令牌(键)和指纹(值)的映射,该映射在使用多个账户时有助于响应挑战。ACME 任务将在验证挑战前添加条目,并在任务结束时移除这些条目。

profile <string>

profile <string>

通过在 newOrder 请求中包含 “profile” 字段,向证书颁发机构(CA)请求特定的证书配置文件。此功能实现 draft-ietf-acme-profiles 规范。

证书颁发机构(CA)特定的配置文件名称为短标识符(例如 “classic”、“shortlived”)。设置后,配置文件名称将原样发送至 newOrder JSON 负载中。若该配置文件不受支持,CA 可选择忽略请求或返回错误。未设置时,不包含配置文件字段,CA 将使用其默认颁发策略。

请参阅 https://letsencrypt.org/docs/profiles/ 了解 Let’s Encrypt 配置文件。

示例:

# Request short-lived certificates
profile shortlived

provider-name <string>

provider-name <string>

通过 “dpapi” 汇流点向外部 DNS 配置工具(例如 dataplaneAPI)传递 DNS 服务商名称。可接受的值因工具而异;请参阅所用 DNS 配置工具文档。

该关键字仅在挑战类型为 “dns-01” 或 “dns-persist-01” 时才有意义。

另请参阅:“challenge”、“acme-vars”

reuse-key { on | off }

reuse-key { on | off }

若设置为 “on”,HAProxy 将不会生成新的私钥,而是保留之前的私钥。启用此选项时,建议定期手动重新生成密钥,以实现私钥轮换。

当使用大于 2048 位的 RSA 密钥时,该选项可能有用,因为生成这些密钥可能耗时较长,且可能拖慢执行该操作的单个线程。

使用相同的密钥在使用 ACME 服务器的缓存时可能很有用,有助于获取与当前密钥对应的有效证书。

默认设置为 “off”。

示例:

global
    expose-experimental-directives
    httpclient.resolvers.prefer ipv4

frontend in
    bind *:80
    bind *:443 ssl
    http-request return status 200 content-type text/plain lf-string "%[path,field(-1,/)].%[path,field(-1,/),map(virt@acme)]\n" if { path_beg '/.well-known/acme-challenge/' }
    ssl-f-use crt "foo.example.com.pem.rsa"   acme LE1 domains "foo.example.com.pem,bar.example.com"
    ssl-f-use crt "foo.example.com.pem.ecdsa" acme LE2 domains "foo.example.com.pem,bar.example.com"

acme LE1
    directory https://acme-staging-v02.api.letsencrypt.org/directory
    account-key /etc/haproxy/letsencrypt.account.key
    contact john.doe@example.com
    challenge http-01
    keytype RSA
    bits 2048
    map virt@acme

acme LE2
    directory https://acme-staging-v02.api.letsencrypt.org/directory
    account-key /etc/haproxy/letsencrypt.account.key
    contact john.doe@example.com
    challenge http-01
    keytype ECDSA
    curves P-384
    map virt@acme

eab-key-id <filename>

eab-key-id <filename>

配置 EAB 密钥 ID 文件的路径。凭据由证书颁发机构(CA)提供,必须在启动 HAProxy 之前放置于指定路径。该凭据仅在账户创建时使用。

该文件必须包含一个纯 ASCII 字符串。

EAB 凭据仅在初始 ACME 账户创建期间需要,之后可从配置中移除,或通过清空文件移除。空文件将被静默忽略。空白字符不被忽略,除非是末尾的换行符。

相关文档:“eab-mac-key”、“eab-mac-alg”

eab-mac-key <filename>

eab-mac-key <filename>

配置 EAB MAC 密钥文件的路径。凭据由 CA 提供,必须在启动 HAProxy 之前放置于指定路径。该凭据仅在账户创建时使用。

文件必须包含一个经过 base64url 编码的 MAC 密钥。

EAB 凭据仅在初始 ACME 账户创建期间需要,之后可从配置中移除,或通过清空文件移除。空文件将被静默忽略。空白字符不被忽略,除非是末尾的换行符。

相关文档:“eab-key-id”、“eab-mac-alg”

eab-mac-alg { HS256 | HS384 | HS512 }

eab-mac-alg { HS256 | HS384 | HS512 }

配置用于 EAB 签名的 MAC 算法。默认值为 HS256。EAB MAC 密钥必须足够大以支持指定的 MAC 算法。并非所有 CA 均支持 HS256 以外的算法。

相关文档:“eab-key-id”、“eab-mac-key”

12.9. 健康检查

可以全局声明多个健康检查,这些健康检查可在整个配置中由所有服务器使用,从而覆盖本地代理配置。

healthcheck <name>

healthcheck <name>

创建了一个名为 <name> 的新健康检查。该名称必须唯一。应在服务器行中使用此名称来引用特定的健康检查段。

type <type>

type <type>

定义健康检查类型。此参数为必填项。支持以下类型的健康检查:

* tcp-check
* httpchk
* ssl-hello-chk
* smtpchk
* pgsql-check
* redis-check
* mysql-check
* ldap-check
* spop-check

每种类型使用的参数(如有)与对应代理的选项相同。例如,可为 “httpchk” 类型指定方法、URI 等:

示例:

   healthcheck my-http-check
type httpchk GET /health HTTP/1.1 %[srv_name]

另请参阅:option tcp-check、option httpchk、option ssl-hello-chk、option smtpchk、option mysql-check、option pgsql-check、option redis-check、option ldap-check 和 option spop-check

http-check comment <string>

http-check comment <string>
http-check connect [default] [port <expr>] [addr <ip>] [send-proxy]
                   [via-socks4] [ssl] [sni <sni>] [alpn <alpn>] [linger]
                   [proto <name>] [comment <msg>]
http-check disable-on-404
http-check expect [min-recv <int>] [comment <msg>]
                  [ok-status <st>] [error-status <st>] [tout-status <st>]
                  [on-success <fmt>] [on-error <fmt>] [status-code <expr>]
                  [!] <match> <pattern>
http-check send [meth <method>] [{ uri <uri> | uri-lf <fmt> }>] [ver <version>]
                [hdr <name> <fmt>]* [{ body <string> | body-lf <fmt> }]
                [comment <msg>]
http-check send-state
http-check set-var(<var-name>[,<cond>...]) <expr>
http-check set-var-fmt(<var-name>[,<cond>...]) <fmt>
http-check unset-var(<var-name>)

为 “httpchk” 健康检查添加特定的 http-check 规则。使用与对应代理指令相同的语法。详情请参阅相应代理的文档。

tcp-check comment <string>

tcp-check comment <string>
tcp-check connect [default] [port <expr>] [addr <ip>] [send-proxy] [via-socks4]
                  [ssl] [sni <sni>] [alpn <alpn>] [linger]
                  [proto <name>] [comment <msg>]
tcp-check expect [min-recv <int>] [comment <msg>]
                 [ok-status <st>] [error-status <st>] [tout-status <st>]
                 [on-success <fmt>] [on-error <fmt>] [status-code <expr>]
                 [!] <match> <pattern>
tcp-check send <data> [comment <msg>]
tcp-check send-lf <fmt> [comment <msg>]
tcp-check send-binary <hexstring> [comment <msg>]
tcp-check send-binary-lf <hexfmt> [comment <msg>]
tcp-check set-var(<var-name>[,<cond>...]) <expr>
tcp-check set-var-fmt(<var-name>[,<cond>...]) <fmt>
tcp-check unset-var(<var-name>)

为 “tcp-check” 健康检查添加特定的 tcp-check 规则。使用与对应代理指令相同的语法。详情请参阅对应代理的文档。

22 - 1. 先决条件

读者应具备 Unix 系统管理与故障排查知识

本文介绍如何启动、停止、管理 HAProxy 及排查其故障,也会说明一些已知限制和应避免的陷阱。本文不涉及 HAProxy 的配置方法;相关内容请参阅 configuration.txt 。

本文假定读者具备类 Unix 操作系统的管理能力,日常使用 shell,并熟悉 strace、tcpdump 等故障排查工具。

23 - 2. HAProxy 架构

进程、线程、事件循环、chroot、日志、时钟与 TCP 代理模型

HAProxy 是一个多线程、事件驱动、非阻塞的守护进程。它使用事件多路复用机制调度所有活动,而不依赖系统在多项活动之间切换调度。大多数情况下,HAProxy 只运行一个进程,因此在系统上执行 “ps aux” 时通常只会看到一个 “haproxy” 进程;平滑重载期间是例外,此时旧进程会与新进程并行完成剩余工作。因此,使用 strace 始终可以轻松跟踪其活动。为利用多个处理器,HAProxy 默认会为每个允许使用的处理器启动一个工作线程。除非另有明确配置,传入流量会均匀分配给所有线程,每个线程运行相同的事件循环。HAProxy 将线程间依赖严格控制在最低水平,以实现近乎线性的扩展能力。这也意味着每条连接只由一个线程处理。因此,要充分利用全部处理能力,连接数至少应与线程数相当;实际环境几乎总能满足这一条件。

HAProxy 在启动时设计为将自身隔离到 chroot 环境中,此后将完全无法访问任何文件系统。其依赖的库(如 libc、libssl 等)同样受此限制。直接后果是,运行中的进程无法重新加载配置文件以应用更改,必须使用更新后的配置文件启动新进程。此外,还存在一些不太明显的后果:某些由 libc 在运行时尝试访问的时区文件或解析器文件可能无法找到,不过这种情况通常不会发生,因为这些文件在启动后一般不再需要。这一原则带来的一个良好结果是,HAProxy 进程完全无状态,终止后无需任何清理操作,因此任何有效的终止方法均可正确执行。

HAProxy 不会写入日志文件,但依赖标准的 syslog 协议将日志发送至远程服务器(该服务器通常位于同一系统上)。

HAProxy 使用内部时钟执行超时控制。该时钟以系统时间为基础,并会纠正意外漂移:HAProxy 限制 poll() 等待事件的时间,再测量实际经过的时长。实际等待时间从不超过一秒。因此,对完全空闲的进程运行 strace 时,可以看到周期性的 poll()(或其变体)调用,前后夹着两次 gettimeofday() 调用。这完全正常且无害,开销低到在系统整体负载中无法察觉。示例:

16:35:40.002320 gettimeofday({1442759740, 2605}, NULL) = 0
16:35:40.002942 epoll_wait(0, {}, 200, 1000) = 0
16:35:41.007542 gettimeofday({1442759741, 7641}, NULL) = 0
16:35:41.007998 gettimeofday({1442759741, 8114}, NULL) = 0
16:35:41.008391 epoll_wait(0, {}, 200, 1000) = 0
16:35:42.011313 gettimeofday({1442759742, 11411}, NULL) = 0

HAProxy 是 TCP 代理,而非路由器。它只处理已经过内核验证并建立的连接,不处理任何形式的数据包,也不处理其他状态的套接字(例如 SYN_RECV 或 TIME_WAIT),不过这些套接字的存在可能妨碍端口绑定。HAProxy 依赖系统接受传入连接并发起传出连接。因此,在一条转发连接两端观察到的数据包没有对应关系,其大小、数量甚至协议族都可能不同。连接只能从 LISTEN 状态的套接字接受,所以使用 “netstat” 查看监听套接字时,必然能看到 HAProxy 的全部监听端点。示例:

# netstat -ltnp

Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1629/sshd tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 2847/haproxy tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 2847/haproxy

24 - 3. 启动 HAProxy

命令行语法、选项、配置加载及启动行为

HAProxy 通过在命令行中传入若干参数来调用 “haproxy” 程序启动。实际语法如下:

$ haproxy [<options>]*

其中 [<options>]* 为任意数量的选项。每个选项均以 ‘-’ 开头,后接一个或多个字母,可选地跟随一个或多个额外参数。若未指定任何选项,HAProxy 将显示帮助页面,并提示支持的选项。可用选项可能因操作系统略有差异。其中相当一部分选项与 “global” 段中的等效选项重叠。在此情况下,命令行选项始终优先于配置文件,以便可通过命令行快速强制设置,而无需修改配置文件。当前选项列表如下:

-- <cfgfile>*

-- <cfgfile>*

所有紧跟 “–” 之后的参数均为需按声明顺序加载和处理的配置文件/目录路径。该选项在依赖 shell 加载按数字顺序排列的多个文件时尤为有用。参见 “-f”。"–" 与 “-f” 的区别在于,"-f" 必须置于每个文件名之前,而 “–” 仅需置于所有文件名之前一次即可。两个选项可同时使用,命令行顺序仍适用。当指定多个文件时,每个文件必须从段边界开始,因此每个文件的第一个关键字必须为 “global”、“defaults”、“peers”、“listen”、“frontend”、“backend” 等之一。文件不能仅包含服务器列表。

-f <cfgfile|cfgdir>

-f <cfgfile|cfgdir>

将 <cfgfile> 添加到要加载的配置文件列表中。若 <cfgdir> 为目录,则其包含的所有文件(仅文件)按字典序(使用 LC_COLLATE=C)添加到要加载的配置文件列表中;仅扩展名为 “.cfg” 的文件会被添加,且不包含以 “.” 开头的隐藏文件。配置文件按声明顺序加载并处理。此选项可多次指定,以加载多个文件。另见 “–"。”–" 与 “-f” 的区别在于,前者需在每个文件名前放置一个 “-f”,而后者仅需在所有文件名前放置一个 “–"。两者可同时使用,命令行顺序仍适用。当指定多个文件时,每个文件必须从段边界开始,因此每个文件的第一个关键字必须为 “global”、“defaults”、“peers”、“listen”、“frontend”、“backend” 等之一。例如,文件不能仅包含服务器列表。

-C <dir>

-C <dir>

在加载配置文件前更改目录 <dir>。这在使用相对路径时很有用。请注意,使用通配符时需谨慎,尤其是在 “–” 之后,因为这些通配符实际上会在启动 HAProxy 前由 shell 替换。

-D

-D

以守护进程模式启动。进程在 fork 后与当前终端分离,错误信息将不再在终端中输出。这等价于配置文件中 “global” 段的 “daemon” 关键字。建议在任何初始化脚本中始终强制启用此项,以确保配置错误不会阻止系统启动。

-L <name>

-L <name>

将本地对等节点名称更改为 <name>,默认值为本地主机名。此设置仅在对等节点复制时使用。可在配置文件中使用变量 $HAPROXY_LOCALPEER 来引用对等节点名称。

-N <limit>

-N <limit>

将每个代理的默认 maxconn 设置为 <limit>,而非内置默认值(通常为 2000)。 仅用于调试。

-V

-V

启用详细模式(禁用安静模式)。恢复 “-q” 或 “quiet” 的效果。

-W

-W

主进程/工作进程模式。该模式等效于配置文件中 “global” 段的 “master-worker” 关键字。此模式将启动一个 “master”,用于监控 “workers”。使用该模式时,可通过向主进程发送 SIGUSR2 信号直接重载 HAProxy。主进程/工作进程模式与前台运行或守护进程模式均兼容。建议在多进程模式下配合 systemd 使用此模式。

-Ws

-Ws

主进程/工作进程模式,支持 notify 类型的 systemd 服务。

-4

-4

强制 DNS 解析器仅查询并接受 IPv4 地址(“A” 记录)。当在缺乏端到端双栈连接能力的环境中遇到困难时,可使用此选项。该设置会覆盖全局 “dns-accept-family” 指令,并强制其设置为 “ipv4”。

-c

-c

仅检查配置文件并退出,不会尝试绑定。若一切正常,退出状态码为零;若遇到错误,则为非零值。若存在警告,将予以报告。默认情况下,此选项不会输出成功消息。与 “-V” 联用时,成功将输出消息“配置文件有效”。

脚本必须使用退出状态来判断命令执行是否成功。

-cc

-cc

在配置的条件块中评估一个条件。若条件为真,退出状态为 0;若条件为假,退出状态为 1;若遇到错误,退出状态为 2。

-d

-d

启用调试模式。此模式会禁用守护进程模式,强制进程在前台运行,并显示进出事件。此模式在初始化脚本中绝不可使用。

-dA[file]

-dA[file]

在配置加载完成后,立即将启动时检测到的所有依赖项归档为 tar 格式的指定文件, 此操作等同于 “set-dumpable libs”,但不同于将库保留在内存中,而是将其转储到文件中。 此功能可在生成核心转储后使用,以便向开发者提供所有必要库,从而允许其利用核心转储进行分析。 并非所有操作系统均支持此功能。强烈建议与常规配置文件配合使用,当手动执行时可选择性地配合 “-c”, 以确保 HAProxy 在完成转储后立即退出,而不启动服务。示例:

$ haproxy -dA/tmp/libs.tar -c -f /etc/haproxy/haproxy.cfg

-dC[key]

-dC[key]

转储配置文件。该操作在行被分词后执行,因此注释将被移除,缩进将被强制处理。若指定了非零密钥,则在敏感/机密字段前截断行,并使用与 CLI 匿名模式相同的算法,以该密钥对标识符和地址进行哈希处理后输出。这意味着输出可安全地与需要分析使用相同密钥匿名化转储内容的开发者共享。请参阅 CLI 的“set anon”命令。

-dD

-dD

启用诊断模式。此模式将输出关于可疑配置语句的额外警告。即使在 “zero-warning” 模式下,也不会阻止启动,也不会更改退出状态码。

-dF

-dF

禁用数据快速转发。该机制通过直接在侧边之间传递数据而不唤醒流来优化数据转发。通过此指令,可禁用此优化。请注意,该指令同时也会禁用任何内核 TCP 拼接功能。此命令并非用于常规使用,通常仅在复杂调试会话中由开发人员建议使用。

-dG

-dG

禁用使用 getaddrinfo() 将主机名解析为地址。当怀疑 getaddrinfo() 未能按预期工作时,可以使用此选项。该选项的提供是因为多种系统上存在大量错误实现的 getaddrinfo(),导致难以排查的异常情况。

-dI

-dI

启用不安全的 fork。这等效于全局段中的 “insecure-fork-wanted”。在使用 ASAN 运行所有回归测试时,可能需要 fork addr2line 以解析地址,此时该选项较为有用。

-dK<class[,class]*>

-dK<class[,class]*>

输出每个类别中注册的关键词列表。类别列表可通过 “-dKhelp” 获取。可使用 “-dKall” 输出所有类别,否则可指定帮助信息中列出的类别,以逗号分隔。输出格式会因所导出的关键词类别不同而异(例如 “cfg” 将以类似配置文件格式显示已知的配置关键词,而 “smp” 将显示以每个规则集的兼容性矩阵为前缀的样本提取函数)。这些输出通常不会由人工直接使用,但对尝试检测特定位置新关键词出现的外部工具而言,可极大协助自动更新文档、语法高亮文件、配置解析器、API 等。输出格式可能随时间略有变化,因此强烈建议主要将此输出用于与先前存档进行差异检测。请注意,并非所有关键词均被列出,因为许多关键词在不同关键词注册子系统创建之前就已存在,因此不会出现在其中。然而,由于新关键词仅通过现代机制添加,因此可以合理地认为该输出可用于高精度检测语言扩展。关键词仅在配置完全解析后才被导出,因此即使动态创建的关键词也可被导出。一种有效的导出并退出方式是针对现有配置运行静默配置检查:

./haproxy -dKall -q -c -f foo.cfg

若无配置文件可用,使用 “-f /dev/null” 也可输出所有默认关键字,但返回状态将不为零,因为此时不存在监听器,该状态必须被忽略。

-dL

-dL

输出已加载的动态共享库列表,该列表在配置处理结束时生成。通常,该列表还会包含深层依赖项,例如从 Lua 代码加载的任何内容,以及可执行文件本身。输出格式应便于直接清理并生成所有依赖项的归档包。由于该操作不会阻止程序启动,建议仅与 “-c” 和 “-q” 一同使用,此时仅显示已加载对象的列表(或在出错时无输出)。此外请注意,当提供此类包以协助核心转储分析时,大多数库实际上是符号链接,创建归档包时需解引用这些链接。

./haproxy -W -q -c -dL -f foo.cfg | tar -T - -hzcf archive.tgz

以详细模式启动时(-V),除非处于静默模式(-q),否则还会枚举共享库的地址范围。

-dM[<byte>[,]][help|options,...]

-dM[<byte>[,]][help|options,...]

强制内存填充,或更改其他调试选项。内存填充指使用 malloc() 或 pool_alloc() 分配的每个内存区域在传递给调用方之前均会被填充为 <byte>。当未指定 <byte> 时,其默认值为 0x50(‘P’)。尽管这会略微降低操作性能,但有助于可靠地触发因代码中遗漏初始化而导致的随机崩溃问题。请注意,-dM0 的作用是将任何 malloc() 调用变为 calloc()。无论何种情况,若启用此选项后出现或消失的缺陷,均表明 HAProxy 存在缺陷,请务必报告。其他若干选项可单独使用,或在字节值后以逗号分隔使用。特殊选项 “help” 将列出当前支持的选项及其当前值。每个调试选项均可强制开启或关闭。通常情况下,最优化选项会在构建时根据操作系统自动选择,无需调整,除非开发者建议。支持的调试选项包括(设置/清除):

  • fail / no-fail:
This enables randomly failing memory allocations, in conjunction with
the global "tune.fail-alloc" setting. This is used to detect missing
error checks in the code. Setting the option presets the ratio to 1%
failure rate.
  • no-merge / merge:
By default, pools of very similar sizes are merged, resulting in more
efficiency, but this complicates the analysis of certain memory dumps.
This option allows to disable this mechanism, and may slightly increase
the memory usage.
  • 冷优先 / 热优先:
In order to optimize the CPU cache hit ratio, by default the most
recently released objects ("hot") are recycled for new allocations.
But doing so also complicates analysis of memory dumps and may hide
use-after-free bugs. This option allows to instead pick the coldest
objects first, which may result in a slight increase of CPU usage.
  • integrity / no-integrity:
When this option is enabled, memory integrity checks are enabled on
the allocated area to verify that it hasn't been modified since it was
last released. This works best with "no-merge", "cold-first" and "tag".
Enabling this option will slightly increase the CPU usage.
  • backup / no-backup:
This option performs a copy of each released object at release time,
allowing developers to inspect them. It also performs a comparison at
allocation time to detect if anything changed in between, indicating a
use-after-free condition. This doubles the memory usage and slightly
increases the CPU usage (similar to "integrity"). If combined with
"integrity", it still duplicates the contents but doesn't perform the
comparison (which is performed by "integrity"). Just like "integrity",
it works best with "no-merge", "cold-first" and "tag".
  • no-global / global:
Depending on the operating system, a process-wide global memory cache
may be enabled if it is estimated that the standard allocator is too
slow or inefficient with threads. This option allows to forcefully
disable it or enable it. Disabling it may result in a CPU usage
increase with inefficient allocators. Enabling it may result in a
higher memory usage with efficient allocators.
  • no-cache / cache:
Each thread uses a very fast local object cache for allocations, which
is always enabled by default. This option allows to disable it. Since
the global cache also passes via the local caches, this will
effectively result in disabling all caches and allocating directly from
the default allocator. This may result in a significant increase of CPU
usage, but may also result in small memory savings on tiny systems.
  • caller / no-caller:
Enabling this option reserves some extra space in each allocated object
to store the address of the last caller that allocated or released it.
This helps developers go back in time when analysing memory dumps and
to guess how something unexpected happened.
  • 标签 / 无标签:
Enabling this option reserves some extra space in each allocated object
to store a tag that allows to detect bugs such as double-free, freeing
an invalid object, and buffer overflows. It offers much stronger
reliability guarantees at the expense of 4 or 8 extra bytes per
allocation. It usually is the first step to detect memory corruption.
  • poison / no-poison:
Enabling this option will fill allocated objects with a fixed pattern
that will make sure that some accidental values such as 0 will not be
present if a newly added field was mistakenly forgotten in an
initialization routine. Such bugs tend to rarely reproduce, especially
when pools are not merged. This is normally enabled by directly passing
the byte's value to -dM but using this option allows to disable/enable
use of a previously set value.

-dR

-dR

在监听端口上禁用 SO_REUSEPORT 套接字选项。这等价于 “global” 段中的 “noreuseport” 关键字。在多线程场景下,当观察到 HAProxy 线程间负载分配不均时,可应用此配置(可通过 top 监控)。

-dS

-dS

禁用 splice() 系统调用。其效果等同于 “global” 段中的 “nosplice” 关键字。当怀疑 splice() 行为异常或导致性能问题,或使用 strace 查看转发数据(使用 splice() 时数据不会出现)时,可以使用此选项。

-dT

-dT

禁用 kTLS 的使用。其效果等同于 “global” 段中的关键字 “noktls”。当怀疑存在与 kTLS 相关的缺陷时,此选项尤为有用。

-dV

-dV

在服务器端禁用 SSL 验证。这等效于在 “global” 段中设置 “ssl-server-verify none”。当需要在生产环境之外复现生产环境问题时,此选项非常有用。切勿在初始化脚本中使用,因为它会降低服务器的 SSL 安全性。

-dW

-dW

若设置,HAProxy 在处理配置时若发出任何警告,将拒绝启动。 这有助于发现细微错误,并保持配置在不同版本间的一致性与可移植性。 建议在由人工管理配置的服务脚本中设置此选项,但不建议在生成的配置中使用,因为生成的配置通常会发出更多警告。 可与 “-c” 结合使用,使检查配置中的警告导致失败。这等效于全局选项 “zero-warning”。

-dZ

-dZ

在 “zero-copy” 模式下禁用数据转发。这等效于 “global” 段中的 “tune.disable-zero-copy-forwarding” 关键字。当出现数据丢失或数据完整性问题,或使用 strace 查看转发数据时,此选项可能有所帮助,因为它同时禁用了内核 TCP 拼接功能。

-db

-db

禁用后台模式和多进程模式。进程将保持在前台运行。该模式主要用于开发或小型测试,仅需按 Ctrl-C 即可停止进程。切勿在初始化脚本中使用。

-dc

-dc

启用 CPU 亲和性调试。在启动前,将报告所选 CPU 和被驱逐 CPU 的列表及其拓扑信息。

-de

-de

禁用 “epoll” 检查器的使用。这等同于 “global” 段中的关键字 “noepoll”。 当怀疑与此检查器相关的缺陷时,该选项尤为有用。在支持 epoll 的系统上,回退通常为 “poll” 检查器。

-dk

-dk

禁用 “kqueue” 检查器的使用。这等价于 “global” 段中的关键字 “nokqueue”。当怀疑与此检查器相关的缺陷时,该选项尤为有用。在支持 kqueue 的系统上,回退机制通常为 “poll” 检查器。

-dp

-dp

禁用 “poll” 监听器的使用。这等效于 “global” 段中的关键字 “nopoll”。 当怀疑与此监听器相关的缺陷时,该选项尤为有用。在支持 poll 的系统上,回退机制通常为 “select” 监听器,该监听器无法禁用,且最多支持 1024 个文件描述符。

-dr

-dr

忽略服务器地址解析失败。在非生产环境中验证配置时,通常无法访问相同的解析器,导致服务器地址解析失败,从而难以测试配置。此选项将 “none” 方法添加至所有服务器的地址解析方法列表中,确保即使 libc 无法解析地址,启动流程也不会中断。

-dt [<trace_desc>,...]

-dt [<trace_desc>,...]

在标准错误输出中激活追踪功能。若不带参数,将在错误级别启用所有追踪源。此功能特别有助于检测客户端或服务器的协议违规行为。可选参数用于指定使用逗号分隔的多种追踪配置列表。每个元素可激活一个或全部追踪源。此外,可在每个元素中使用冒号作为内部分隔符,可选地指定级别和详细程度。若输入无效的详细程度或级别名称,将显示可用关键字列表。例如,可对每个字段传入 ‘help’ 以先查阅列表。

-dv

-dv

禁用 “evports” 轮询器的使用。这等同于 “global” 段中的关键字 “noevports”。当怀疑与此轮询器相关的缺陷时,该选项尤为有用。在支持事件端口的系统上(如 Solaris 10 及更高版本的 SunOS),回退机制通常为 “poll” 轮询器。

-m <limit>

-m <limit>

限制可分配内存(用于保存进程数据)为 <limit> 兆字节。这可能导致部分连接被拒绝或出现性能下降,具体取决于正常操作所需的内存数量。该设置主要用于强制 HAProxy 进程在资源受限的环境中运行。请注意,HAProxy 进程之间不共享内存,通过 fork() 系统调用创建的子进程会继承父进程的资源限制。因此,在主进程/工作进程模式下,该内存限制会分别应用于主进程及其 fork 出的工作进程。

-n <limit>

-n <limit>

将每个进程的连接数限制为 <limit>。这等效于全局段中的关键字 “maxconn”。该设置优先于该关键字。可在资源限制过低的系统上快速强制降低限制,以避免服务中断。

-p <file>

-p <file>

启动时将所有进程的 PID 写入 <file>。这等价于 “global” 段中的关键字 “pidfile”。该文件在进入 chroot 监狱前打开,并在执行 “-C” 所隐含的 chdir() 之后打开。每个 PID 单独占一行。

-q

-q

设置 “quiet” 模式。此操作将禁用输出消息。可与 “-c” 联用,仅用于检查配置文件是否有效。

-S <bind>[,bind_options...]

-S <bind>[,bind_options...]

在主进程/工作进程模式下,绑定一个主 CLI,该 CLI 可访问所有运行中或已退出的进程。出于安全考虑,建议将主 CLI 绑定到本地 Unix 套接字。绑定选项与配置文件中的关键字 “bind” 相同,但各选项之间使用英文逗号分隔,而非空格。

请注意,此套接字无法用于在无缝重载期间从旧进程获取监听套接字。

-sf <pid>*

-sf <pid>*

在启动完成后,向旧进程发送 “finish” 信号(SIGUSR1),以请求它们完成当前操作并退出。<pid> 是要发送信号的进程 ID 列表(每个参数对应一个进程 ID)。列表在任意以 “-” 开头的选项处结束。如果进程 ID 列表为空也无妨,因此可基于 “pidof” 或 “pgrep” 等命令的执行结果动态构建该列表。

-st <pid>*

-st <pid>*

在启动完成后,向旧进程发送 “terminate” 信号(SIGTERM)以立即终止它们,而不完成其当前操作。<pid> 是要发送信号的进程 ID 列表(每个参数一个)。列表在任意以 “-” 开头的选项处结束。如果进程 ID 列表为空也无妨,因此可基于 “pidof” 或 “pgrep” 等命令的执行结果动态构建。

-v

-v

报告版本和构建日期。

-vv

-vv

显示版本、构建选项、库版本和可用的轮询器。此输出在提交错误报告时会自动请求。

-x <unix_socket>

-x <unix_socket>

连接到指定的套接字,并尝试从旧进程获取任何监听套接字,然后使用这些套接字,而非尝试绑定新的套接字。这在 Linux 上重载配置时避免遗漏任何新连接时非常有用。

在未启用主进程/工作进程模式时,必须在配置中使用“expose-fd listeners”在统计信息套接字上启用该功能。

在主进程/工作进程模式下,无需使用“expose-fd listeners”,主进程在使用“sockpair@”语法进行重载时会自动启用此选项,从而允许主进程直接连接到工作进程,而无需依赖配置中声明的任何统计信息套接字。如需禁用此功能,可传递 -x /dev/null.

从初始化文件启动 HAProxy 的安全方式是强制启用守护进程模式,将现有进程 ID 存储到 PID 文件,并使用该 PID 文件通知旧进程终止后再退出:

haproxy -f /etc/haproxy.cfg \
        -D -p /var/run/haproxy.pid -sf $(cat /var/run/haproxy.pid)

当配置被拆分为若干特定文件(例如:TCP 与 HTTP)时,建议使用 “-f” 选项:

haproxy -f /etc/haproxy/global.cfg -f /etc/haproxy/stats.cfg \
        -f /etc/haproxy/default-tcp.cfg -f /etc/haproxy/tcp.cfg \
        -f /etc/haproxy/default-http.cfg -f /etc/haproxy/http.cfg \
        -D -p /var/run/haproxy.pid -sf $(cat /var/run/haproxy.pid)

当预期的文件数量未知时,例如特定客户使用的文件,建议将文件名以固定长度的序列号开头,并使用 “–” 加载这些文件,可在加载部分默认配置之后进行。

haproxy -f /etc/haproxy/global.cfg -f /etc/haproxy/stats.cfg \
        -f /etc/haproxy/default-tcp.cfg -f /etc/haproxy/tcp.cfg \
        -f /etc/haproxy/default-http.cfg -f /etc/haproxy/http.cfg \
        -D -p /var/run/haproxy.pid -sf $(cat /var/run/haproxy.pid) \
        -f /etc/haproxy/default-customers.cfg -- /etc/haproxy/customers/*

有时,由于各种原因可能导致启动失败。此时,务必验证所调用的 HAProxy 版本是否为预期版本,并确认其是否支持预期的功能(例如:SSL、PCRE、压缩、Lua 等)。可通过运行 “haproxy -vv” 来验证。该命令会报告一些重要信息,如特定构建选项、目标系统以及所使用库的版本。提交错误报告时,应系统性提供这些信息:

$ haproxy -vv

HAProxy version 1.6-dev7-a088d3-4 2015/10/08 Copyright 2000-2015 Willy Tarreau willy@haproxy.org

Build options:

TARGET  = linux2628
CPU     = generic
CC      = gcc
CFLAGS  = -pg -O0 -g -fno-strict-aliasing -Wdeclaration-after-statement \
          -DBUFSIZE=8030 -DMAXREWRITE=1030 -DSO_MARK=36 -DTCP_REPAIR=19
OPTIONS = USE_ZLIB=1 USE_DLMALLOC=1 USE_OPENSSL=1 USE_LUA=1 USE_PCRE=1

Default settings:

maxconn = 2000, bufsize = 8030, maxrewrite = 1030, maxpollevents = 200

Encrypted password support via crypt(3): yes Built with zlib version: 1.2.6 Compression algorithms supported: identity(“identity”), deflate(“deflate”), \ raw-deflate(“deflate”), gzip(“gzip”) Built with OpenSSL version: OpenSSL 1.0.1o 12 Jun 2015 Running on OpenSSL version: OpenSSL 1.0.1o 12 Jun 2015 OpenSSL library supports TLS extensions: yes OpenSSL library supports SNI: yes OpenSSL library supports prefer-server-ciphers: yes Built with PCRE version: 8.12 2011-01-15 PCRE library supports JIT: no (USE_PCRE_JIT not set) Built with Lua version: Lua 5.3.1 Built with transparent proxy support using: IP_TRANSPARENT IP_FREEBIND

Available polling systems:

 epoll: pref=300,  test result OK
  poll: pref=200,  test result OK
select: pref=150,  test result OK

Total: 3 (3 usable), will use epoll.

许多非开发人员用户可在此验证的相关信息包括:

- the version

- the version

1.6-dev7-a088d3-4 表示当前代码位于提交 ID “a088d3”,该提交位于正式版本 “1.6-dev7” 之后的第 4 个提交。版本 1.6-dev7 将显示为 “1.6-dev7-8c1ad7”。真正重要的是 “1.6-dev7”。这是未来将演变为 1.6 版本的第 7 个开发版本。该版本不适合在生产环境中使用(除非完全了解其风险)。稳定版本将显示为三位数字版本,例如 “1.5.14-16f863”,表示在 1.5 版本基础上的第 14 个修复级别。该版本为生产就绪版本。

- the release date

- the release date

2015/10/08。采用通用的年/月/日格式表示。此处指 2015 年 8 月 8 日。由于稳定版本通常每隔数月发布一次(初期为 1 至 2 个月,产品趋于稳定后可能长达 6 个月),若此处显示的日期较旧,说明可能正受多个已修复的缺陷或安全问题影响,建议访问官方站点进行确认。

- build options

- build options

它们适用于自行构建软件包的人员,能够解释为何某些行为不符合预期。例如,上述开发版本是为 Linux 2.6.28 或更高版本构建的,针对通用 CPU(无 CPU 特定优化),且缺乏任何代码优化(-O0),因此在性能方面表现不佳。

- libraries versions

- libraries versions

zlib 版本号由库本身报告。通常情况下,zlib 被认为是非常稳定的产品,几乎无需升级。OpenSSL 报告两个版本号,分别为构建时使用的版本和当前系统中实际使用的版本。这两个版本号在末尾字母上可能不同,但数字部分绝不会不同。同时报告构建日期,因为大多数 OpenSSL 的问题均为安全漏洞,必须高度重视,因此该库必须始终保持最新。若此处显示的版本为 4 个月前的版本,则高度可疑,实际上确实遗漏了一次更新。PCRE 提供极快的正则表达式支持,强烈推荐使用。其部分扩展功能(如 JIT)并非所有版本均支持,且仍处于较早期阶段,因此部分用户选择不启用这些功能,这也是为何会报告构建状态。关于 Lua 脚本语言,HAProxy 期望使用 5.3 版本,该版本相对较新,因其发布于 HAProxy 1.6 之前不久。请务必访问 Lua 官方网站,确认该分支是否发布了相关修复。

- Available polling systems will affect the process's scalability when

- Available polling systems will affect the process's scalability when

处理超过一千个并发连接时。这些机制仅在构建时于 TARGET 变量中指定了正确系统的情况下才可用。在 Linux 上强烈建议使用 “epoll” 机制,在 BSD 上强烈建议使用 kqueue 机制。若缺少这些机制,将导致使用 poll() 或甚至 select(),在处理大量连接时会造成较高的 CPU 使用率。

25 - 4. 停止与重启 HAProxy

信号、软停止、重载和主从重启

HAProxy 支持优雅停止和强制停止。强制停止操作简单:当向 HAProxy 进程发送 SIGTERM 信号时,进程立即退出,所有已建立的连接将被关闭。优雅停止通过向 HAProxy 进程发送 SIGUSR1 信号触发,其操作仅包括解除对监听端口的绑定,但会继续处理现有连接,直至所有连接关闭。当最后一个连接关闭后,进程退出。

硬停止方法用于服务管理脚本的“stop”或“restart”动作。 优雅停止用于“reload”动作,该动作尝试在新进程中无缝重载新配置。

在重载或重启过程中,新的 HAProxy 进程自身可发送这两个信号,以确保信号在最晚可能时刻发出,且仅在绝对必要时才发送。这分别由“-st”(强制)和“-sf”(优雅)选项实现。

在主进程/工作进程模式下,无需启动新的 HAProxy 进程即可重载配置。主进程收到 SIGUSR2 信号后,会以 -sf 参数及工作进程的 PID 列表重新执行自身。随后,主进程将解析配置文件并创建新的工作进程。

为更好地理解这些信号的使用方式,有必要了解完整的重启机制。

首先,一个现有的 HAProxy 进程正在运行。管理员使用特定于系统的命令,例如 “/etc/init.d/haproxy reload”,以表明希望使新的配置文件生效。随后发生以下过程:首先,服务脚本(/etc/init.d/haproxy 或等效脚本)将使用 “HAProxy -c” 验证配置文件是否能正确解析。之后,将尝试使用该配置文件启动 HAProxy,命令为 “-st” 或 “-sf”。

然后 HAProxy 会尝试绑定所有监听端口。如果发生严重错误(例如:地址在系统中不存在、权限被拒绝),进程将报错退出。如果因端口已被占用而导致套接字绑定失败,则进程会先向“-st”或“-sf”中指定的所有 PID 发送 SIGTTOU 信号。此信号被称为“暂停”信号,它指示所有现有的 HAProxy 进程暂时停止监听其端口,以便新进程重新尝试绑定。在此期间,旧进程仍继续处理现有连接。如果绑定仍然失败(例如端口被其他守护进程共享),则新进程会向旧进程发送 SIGTTIN 信号,指示其恢复操作,如同什么都没发生过一样。旧进程随后将重新开始监听端口并继续接受连接。请注意,该机制依赖于系统,某些操作系统在多进程模式下可能不支持此功能。

如果新进程成功绑定到所有端口,则向所有进程发送 SIGTERM(在 “-st” 情况下为强制停止)或 SIGUSR1(在 “-sf” 情况下为优雅停止),以通知它们新进程现已接管操作,旧进程须立即退出,或在完成当前任务后退出。

请注意,在此时间段内,存在两个持续时间仅为几毫秒的小窗口,在高负载情况下可能观察到少量连接失败。通常情况下,每秒新增 10000 个连接时,重载操作期间的失败率约为 1 次。这意味着,每秒新增 30000 个连接的高负载站点在每次重载时可能约有 3 次连接失败。这种情况发生在以下两种情形中:

  • 若新进程因旧进程的存在而无法绑定,它必须首先经历 SIGTTOU + SIGTTIN 序列,该过程通常持续约一毫秒,涉及数十个前端,期间部分端口将未被旧进程绑定,也尚未被新进程绑定。HAProxy 在支持 SO_REUSEPORT 套接字选项的系统上可规避此问题,因为这允许新进程直接绑定,无需先请求旧进程解除绑定。大多数 BSD 系统几乎自始便支持此功能。Linux 从 2.0 版本开始支持,但在 2.2 版本左右被移除,不过当时已有相关补丁流传。该功能在内核 3.9 中重新引入,因此若观察到连接失败率高于上述情况,应确保内核版本为 3.9 或更高,或相关补丁已回迁至所用内核(可能性较低)。

  • 当旧进程关闭监听端口时,内核可能无法始终将仍处于套接字接收队列中的待处理连接重新分配。在高负载情况下,可能在套接字关闭前瞬间收到一个 SYN 数据包,导致向客户端发送 RST 数据包。在某些对丢包零容忍的关键环境中,有时会通过防火墙规则在重载期间阻止 SYN 数据包,强制客户端重传。此方法完全依赖系统特性,因为某些系统可能能够访问其他监听队列,从而避免发送 RST。第二种情况涉及客户端在本地套接字处于 SYN_RECV 状态时刚发送的 ACK。在 HAProxy 进程尚未感知到该连接关闭前,该 ACK 将导致发送 RST 数据包。这种情况更难消除,尽管上述防火墙过滤规则若在重启进程前约一秒钟应用,仍可有效应对。

对绝大多数用户而言,此类丢包根本不会发生,因为他们所承受的负载不足以触发竞态条件。对于大多数高流量用户,只要其系统中至少正确支持 SO_REUSEPORT,故障率仍处于可接受的噪声范围内。

26 - 5. 文件描述符限制

描述限制、sizing、系统约束及故障排查

为确保所有传入连接均能成功处理,HAProxy 在加载时会计算进程生命周期内所需的文件描述符总数。常规 Unix 进程默认被授予 1024 个文件描述符,特权进程可自行提升该限制。这是以 root 身份启动 HAProxy 并由其自行调整限制的原因之一。默认的 1024 个文件描述符大致可支持约 500 个并发连接的处理。该计算基于全局 maxconn 参数,该参数限制每个进程的总连接数,同时考虑监听器数量、启用健康检查的服务器数量、代理检查、对等节点、日志记录器以及可能的其他技术需求。对该数值的粗略估算方法为:将 maxconn 值翻倍,并额外增加数十个,即可得到所需的文件描述符近似数量。

最初,HAProxy 无法自动计算此值,必须通过全局段中的 “ulimit-n” 设置手动指定。这解释了为何至今仍有许多配置中保留该设置。不幸的是,该值常被错误计算,导致在接近 maxconn 限制时出现连接失败,而非在等待所需资源时对新连接进行限流。因此,务必移除任何可能源自极旧版本的残留 “ulimit-n” 设置。

提高文件描述符数量以应对中等负载是必须的,但需进行一些操作系统特定的调整。首先,select() 轮询机制最多只能处理 1024 个文件描述符。实际上,在 Linux 上曾支持更多,但由于某些操作系统附带过于严格的 SELinux 策略,禁止使用 select() 处理超过 1024 个文件描述符,HAProxy 现在在这种情况下拒绝启动,以避免运行时出现任何问题。在所有支持的操作系统上,poll() 均可用,且不受此限制影响。HAProxy 会自动选择该机制,因此无需额外操作即可获得正常配置。但当文件描述符数量增加时,poll() 的性能会显著下降。尽管 HAProxy 尽力降低此性能影响(例如通过内部文件描述符缓存和批量处理),但一个通用的经验是:使用 poll() 处理超过一千个并发连接时,将消耗大量 CPU 资源。

对于基于 2.6 及以上内核的 Linux 系统,将使用 epoll() 系统调用。该机制具有更高的可扩展性,依赖于内核中的回调机制,可保证无论注册监控的文件描述符数量多少,唤醒时间始终恒定。只要检测到该功能,且 HAProxy 已针对某一类 Linux 发行版编译构建,便会自动启用。可通过命令 “HAProxy -vv” 验证其存在与支持情况。

对于支持该功能的 BSD 系统,可使用 kqueue() 作为替代方案。由于其支持批量处理变更,性能远超 poll(),甚至略胜于 epoll()。目前至少 FreeBSD 和 OpenBSD 支持该功能。与 Linux 的 epoll() 类似,其支持情况和可用性会在运行 “HAProxy -vv” 时的输出中报告。

拥有一个优秀的轮询器是一回事,但进程必须能够达到限制才是必须的。HAProxy 启动时,会立即设置新进程的文件描述符限制,并验证设置是否成功。若设置失败,将在进程分叉前报告该问题,以便管理员能够发现。只要进程以 root 身份启动,该设置就应不会失败。然而,若进程由非特权用户启动,则可能失败。如果存在必须不以 root 身份启动 HAProxy 的充分理由(例如:由终端用户或特定应用程序账户启动),则系统管理员可为该特定用户提升文件描述符限制。可通过在用户命令行中执行 “ulimit -n” 验证该设置的有效性。输出结果应反映新的限制值。

请注意:当在用户账户中更改非特权用户的限制时,这些值通常仅在用户登录时被考虑,而在系统启动时运行的某些脚本或 crontab 中则完全不被考虑。这完全取决于操作系统,因此在以这种方式运行 HAProxy 之前,请务必检查 “ulimit -n”。一般建议不要在生产环境中以非特权用户身份启动 HAProxy。另一个重要原因在于,这会阻止 HAProxy 启用某些安全防护功能。

一旦确认系统允许 HAProxy 进程使用请求的文件描述符数量,可能会遇到两个新的系统特定限制。第一个是系统级文件描述符限制,即系统上所有进程打开的文件描述符总数。当达到此限制时,accept() 或 socket() 通常会返回 ENFILE。第二个是每个进程的文件描述符硬限制,它阻止 setrlimit() 设置更高的值。这两项限制均高度依赖于操作系统。在 Linux 上,系统级限制在启动时根据内存总量设定,可通过 “fs.file-max” sysctl 修改。每个进程的默认硬限制为 1048576,但可使用 “fs.nr_open” sysctl 进行更改。

当进程的文件描述符限制设置过低时,可能会在运行过程中观察到文件描述符限制问题。使用 strace 工具时,会报告 accept() 和 socket() 返回 “-1 EMFILE”,表明进程的限制已达到。此时,只需提高 “ulimit-n” 值(或将其移除)即可解决问题。若这些系统调用返回 “-1 ENFILE”,则表示内核的限制已达到,必须调整系统级参数。此类问题必须立即解决,否则会导致高 CPU 使用率(当 accept() 失败时)以及用户可见的连接失败。一种解决方案是降低全局 maxconn 值以强制序列化处理,或禁用 HTTP 持久连接,以促使连接更快释放并重用。

27 - 6. 内存管理

内存分配、限制、内存池、缓冲区与进程容量规划

HAProxy 采用简单、快速的池式内存管理。由于 HAProxy 只使用少量不同的对象类型,从已经包含适当大小对象的内存池中获取新对象,远比针对每种大小分别调用 malloc() 高效。内存池按栈或 LIFO 方式组织,新分配的对象会优先取自刚刚释放、仍在 CPU 缓存中的对象。大小相近的内存池会合并,以减少内存碎片。

默认配置以性能为先:每个释放的对象都会放回原来的内存池;已分配对象不会归还给系统,因为预计很快便会再次使用。

可以在 CLI 中使用 “show pools” 命令检查各内存池的使用情况:

> show pools
Dumping pools usage. Use SIGQUIT to flush them.
  - Pool cache_st (16 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 1 users, @0x9ccc40=03 [SHARED]
  - Pool pipe (32 bytes): 5 allocated (160 bytes), 5 used, 0 failures, 2 users, @0x9ccac0=00 [SHARED]
  - Pool comp_state (48 bytes): 3 allocated (144 bytes), 3 used, 0 failures, 5 users, @0x9cccc0=04 [SHARED]
  - Pool filter (64 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 3 users, @0x9ccbc0=02 [SHARED]
  - Pool vars (80 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 2 users, @0x9ccb40=01 [SHARED]
  - Pool uniqueid (128 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 2 users, @0x9cd240=15 [SHARED]
  - Pool task (144 bytes): 55 allocated (7920 bytes), 55 used, 0 failures, 1 users, @0x9cd040=11 [SHARED]
  - Pool session (160 bytes): 1 allocated (160 bytes), 1 used, 0 failures, 1 users, @0x9cd140=13 [SHARED]
  - Pool h2s (208 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 2 users, @0x9ccec0=08 [SHARED]
  - Pool h2c (288 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 1 users, @0x9cce40=07 [SHARED]
  - Pool spoe_ctx (304 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 2 users, @0x9ccf40=09 [SHARED]
  - Pool connection (400 bytes): 2 allocated (800 bytes), 2 used, 0 failures, 1 users, @0x9cd1c0=14 [SHARED]
  - Pool hdr_idx (416 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 1 users, @0x9cd340=17 [SHARED]
  - Pool dns_resolut (480 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 1 users, @0x9ccdc0=06 [SHARED]
  - Pool dns_answer_ (576 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 1 users, @0x9ccd40=05 [SHARED]
  - Pool stream (960 bytes): 1 allocated (960 bytes), 1 used, 0 failures, 1 users, @0x9cd0c0=12 [SHARED]
  - Pool requri (1024 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 1 users, @0x9cd2c0=16 [SHARED]
  - Pool buffer (8030 bytes): 3 allocated (24090 bytes), 2 used, 0 failures, 1 users, @0x9cd3c0=18 [SHARED]
  - Pool trash (8062 bytes): 1 allocated (8062 bytes), 1 used, 0 failures, 1 users, @0x9cd440=19
Total: 19 pools, 42296 bytes allocated, 34266 used.

内存池名称仅供识别,取自最先使用该内存池的对象类型。括号中的大小是池内对象的大小;对象大小总是向上取整为最接近的 16 字节倍数。输出会同时报告当前已分配的对象数及其对应字节数,便于判断哪个内存池占用最多。“used” 字段还会报告当前正在使用的对象数;“allocated” 与 “used” 之差,就是已经释放、可立即复用的对象数。每行末尾的地址是内存池地址,后面的数字是内存池索引;没有分配索引时报告为 -1。

可以使用 “-m” 命令行选项限制每个进程分配的内存量,后接以 MB 为单位的数值。该限制覆盖进程的全部可寻址空间,包括部分库和栈使用的内存,因此在构建资源受限系统时可以作为可靠上限。其作用与支持 “ulimit -v” 的系统相同,其他系统则相当于 “ulimit -d”。

如果因为达到内存上限或系统可用内存不足而分配失败,HAProxy 会先释放所有内存池中的全部可用对象,再次尝试分配。向 HAProxy 进程发送 SIGQUIT 信号,也可以主动触发这一未使用内存释放机制。

执行重载时,进入优雅停止状态的进程还会在释放连接后自动执行若干清理操作,尽可能释放内存供新进程使用。

28 - 7. CPU 使用率

线程、CPU 亲和性、饱和度、profiling 及性能行为

HAProxy 通常大部分时间运行在系统空间,仅小部分时间运行在用户空间。经过精细调优的 3.5 GHz CPU 在单核满载 100% 时,每秒可维持约 80000 次端到端连接的建立与关闭。当单核达到饱和时,典型数值为:

  • 长 TCP 连接或大 HTTP 对象:系统占用 95%,用户占用 5%
  • 短 TCP 连接或关闭模式下的小 HTTP 对象:系统占用 85%,用户占用 15%
  • 持久连接模式下的小 HTTP 对象:系统占用 70%,用户占用 30%

规则处理和正则表达式的数量会增加用户空间部分的开销。防火墙规则、连接跟踪以及系统中复杂的路由表则会增加系统空间部分的开销。

在大多数系统上,网络传输期间观察到的 CPU 时间可被分为 4 个部分:

  • 中断部分,涉及在目标进程尚未确定之前执行的所有 I/O 接收处理。通常,接收的数据包(Rx packets)会在中断中进行统计。在某些系统(如 Linux)中,中断处理可能被推迟到专用线程执行,此时表现为软中断(softirq),该线程被称为 ksoftirqd/0(对应 CPU 0)。负责处理此负载的 CPU 通常由硬件设置决定,但在软中断情况下,通常可以将处理重新映射到其他 CPU。该中断部分通常被视为寄生性负载,因为它不与任何进程直接关联,但实际上是在为进程准备工作的过程中执行的处理。

  • 系统部分,涉及所有通过用户空间调用的内核代码执行的处理。 例如,系统调用被计入系统时间。所有同步交付的 Tx 数据包均计入系统时间。若因队列已满需延迟处理某些数据包,则这些数据包后续可能在中断上下文中被处理(例如:在收到 ACK 以打开 TCP 窗口时)。

  • 用户部分,仅在用户空间运行应用程序代码。HAProxy 仅在此部分运行,尽管其大量使用系统调用。规则处理、正则表达式、压缩和加密均会增加用户空间的 CPU 消耗。

  • 空闲部分,即 CPU 在无事可做时的运行状态。例如,HAProxy 会等待传入连接,或等待数据发出,这意味着系统正在等待客户端的 ACK 以推送这些数据。

在实际分析 HAProxy 的活动时,通常可以合理地认为:中断/软中断由内核驱动中的接收(Rx)处理引起,用户空间时间由 HAProxy 中的第 7 层处理引起,系统时间则由发送(Tx)路径上的网络处理引起。

由于 HAProxy 在事件循环中运行,它通过 poll()(或任何替代方法)等待新事件,并在返回 poll() 以等待新事件之前尽可能快速地处理所有事件。它会测量在 poll() 中等待的时间与处理事件所花费时间的比值。轮询时间与总时间的比值称为“空闲”时间,即等待某些事件发生所花费的时间。该比值在统计页面的“idle”行或 CLI 中的“Idle_pct”字段中报告。当该值接近 100% 时,表示负载极低;当该值接近 0% 时,表示系统始终存在活动。尽管在系统过载时,由于其他进程可能抢占 HAProxy 进程的 CPU,该指标的准确性会降低,但它仍能较好地反映 HAProxy 对自身工作负载的判断:若负载较低但空闲比值也较低,可能表明 HAProxy 有大量工作需要处理,可能是由于需要处理非常耗时的规则。反之,若 HAProxy 显示空闲接近 100% 但处理速度仍然缓慢,说明它已处于等待传入数据的状态,无法采取任何措施加快处理速度。在以下示例中,HAProxy 完全处于空闲状态:

$ echo "show info" | socat - /var/run/haproxy.sock | grep ^Idle
Idle_pct: 100

当空闲比率开始变得非常低时,必须调整系统并正确配置进程和中断,以尽可能为所有任务节省 CPU 资源。如果存在防火墙,应尝试禁用它或进行调优,以确保其不会成为性能瓶颈的主要原因。请注意,卸载有状态防火墙通常会同时降低中断/软中断数量和系统使用率,因为此类防火墙同时作用于接收(Rx)和发送(Tx)路径。在 Linux 上,卸载 nf_conntrack 和 ip_conntrack 模块可判断是否存在优化空间。若存在优化空间,则模块以默认设置运行,需自行研究如何调优以获得更高性能。通常这涉及显著增大哈希表大小。在 FreeBSD 上,执行 “pfctl -d” 可同时禁用 “pf” 防火墙及其有状态引擎。

如果观察到大量时间消耗在中断(interrupt)或软中断(softirq)上,必须确保它们不运行在同一个 CPU 上。大多数系统倾向于将任务绑定到接收网络流量的 CPU,因为对于某些工作负载,这能提升性能。但面对高度依赖网络的工作负载时,情况恰恰相反,因为 HAProxy 进程将不得不与其内核对应部分竞争 CPU 资源。将 HAProxy 绑定到一个 CPU 核心,而将中断绑定到另一个核心,且两者共享相同的 L3 缓存,通常能显著提升网络性能。实践中,HAProxy 与网络栈的处理工作量非常接近,因此它们几乎可以各自填满一个完整的 CPU。在 Linux 上,可通过 taskset(用于 HAProxy)或使用 HAProxy 配置中的 cpu-map 实现此绑定,而中断的分配则在 /proc/irq. 中进行。许多网络接口支持多个队列和多个中断。通常,将它们分散到少量共享相同 L3 缓存的 CPU 核心上会有帮助。请务必停止 irq_balance,因为它在这些工作负载下总是执行最糟糕的调度策略。

对于涉及大量 SSL 流量或大量压缩的 CPU 密集型工作负载,使用多个进程专门处理特定任务可能是值得的,尽管此处并无通用规则,需通过实验进行验证。

为提升 CPU 处理能力,可将 HAProxy 配置为以多个进程运行,方法是在全局段中使用 “nbproc” 指令。但存在一些限制:

  • 健康检查按进程运行,因此目标服务器将收到与运行进程数量相同的检查次数;
  • maxconn 值和队列大小为进程级配置,必须正确设置以避免对服务器造成过载;
  • 外部连接应避免使用端口范围,以防止端口冲突;
  • stick-tables 为进程级配置,各进程之间不共享;
  • 每个 peers 段在同一时间只能在一个进程中运行;
  • CLI 操作在同一时间仅作用于单个进程。

基于此,通常最简单的配置方式是设置一个由多个进程运行的第一层,负责执行繁重的处理任务,并将流量转发至由单个进程运行的第二层。该机制适用于 SSL 和压缩,这两项功能均属于 CPU 密集型操作。实例可通过 Unix 套接字轻松串联(Unix 套接字比 TCP 套接字更高效,且不会占用端口),并利用 PROXY 协议向下一阶段传递客户端信息。采用此方式时,建议将所有单进程任务绑定至进程编号 1,其余任务绑定至后续进程,以便更方便地为不同机器生成相似的配置。

在 Linux 版本 3.9 及以上中,当每个进程在相同 IP:端口上绑定独立的监听套接字时,HAProxy 以多进程模式运行的效率会显著提高;这将使内核均匀地在所有进程间分发负载,而非唤醒所有进程。有关详细信息,请参阅配置手册中“bind”关键字行的“process”选项。

29 - 8. 日志记录

Syslog 集成、启动日志、运行时日志及日志故障排查

对于日志记录,HAProxy 始终依赖 syslog 服务器,因为它不执行任何文件系统访问。标准用法是通过 UDP 将日志发送至日志服务器(默认端口为 514)。通常情况下,该配置会指向 127.0.0.1,即本地 syslog 守护进程运行的位置,但也常通过网络将日志发送至集中式服务器。在主动-主动场景中,集中式服务器尤其具有优势,可确保日志按到达顺序合并。HAProxy 也可使用 Unix 套接字将日志发送至本地 syslog 守护进程,但强烈不建议使用,因为当 syslog 服务器重启而 haproxy 仍在运行时,套接字将被替换,新日志将丢失。由于 HAProxy 将被隔离在 chroot 环境中,它将无法重新连接至新的套接字。现场观察表明,Unix 套接字使用的日志缓冲区非常小,即使在极轻负载下也可能导致消息丢失。不过,这在测试环境中可以接受。

建议将以下指令添加至 “global” 段,以使 HAProxy 使用 “local0” 设施将日志输出至本地守护进程:

log 127.0.0.1:514 local0

然后在每个“defaults”段或每个前端和后端段中添加以下配置:

log global

通过这种方式,所有日志将通过全局定义日志服务器位置的方式实现集中化。

某些 syslog 守护进程默认不监听 UDP 流量,因此具体启用方式取决于所使用的守护进程:

  • 在 sysklogd 上,需在守护进程的命令行中传递参数 “-r”,使其监听用于接收“远程”日志的 UDP 套接字;请注意,无法将其限制为仅接收来自 127.0.0.1 的日志,因此也会接收来自远程系统的日志;

  • 在 rsyslogd 中,必须将以下行添加到配置文件中:

$ModLoad imudp
$UDPServerAddress *
$UDPServerRun 514
  • 在 syslog-ng 上,可通过以下方式创建新的源,随后需将其添加至某个 “log” 指令的有效源列表中:
source s_udp {
  udp(ip(127.0.0.1) port(514));
};

请参阅系统日志守护进程手册以获取更多信息。如果系统日志文件中未见日志,请考虑执行以下测试:

  • 重启 HAProxy。每个前端和后端都会记录一行日志,表明其正在启动。如果收到这些日志,说明日志功能正常。

  • 执行命令 strace -tt -s100 -etrace=sendmsg -p \<haproxy's pid\>,并执行你期望产生日志的活动。你应该能在 sendmsg() 调用处看到日志消息的发送。若未出现,请使用 strace 重新启动 HAProxy。若仍无日志输出,说明配置中肯定存在错误。

  • 使用 tcpdump 监听端口 514,例如在环回接口上监听本地发送的流量:“tcpdump -As0 -ni lo port 514”。如果在此处看到数据包,说明数据已发送,此时应排查 syslogd 守护进程。

流量日志由前端(接收传入连接的位置)发送, 后端也必须能够发送日志,以便在健康检查后报告服务器状态变更。 有关所有可能的日志设置的更多信息,请参阅 HAProxy 配置手册。

选择一个未被其他守护进程使用的 facility 会更加方便。HAProxy 的示例通常建议将流量日志使用 “local0”,管理日志使用 “local1”,因为它们在实际环境中几乎不会出现。使用单一 facility 也同样足够。分别记录日志便于日志分析,但同样需要注意,日志有时可能包含机密信息,因此必须避免与其他日志混合,以防意外泄露给未经授权的人员。

对于在生产环境中进行故障排查且对服务器容量影响较小的情况,建议使用 HAProxy 自带的 “halog” 工具。该工具类似于 grep,专为以极高的数据速率处理 HAProxy 日志文件而设计。典型处理速度可达每秒 1 至 2 GB 日志。它能够仅提取特定日志(例如:搜索某类 HTTP 状态码、连接终止状态、按响应时间范围搜索、仅查找错误等),统计行数,限制输出行数,还可执行一些更高级的统计分析,如按响应时间或错误计数对服务器排序、按时间或访问次数对 URL 排序、按访问次数对客户端地址排序等。该工具可快速发现异常情况,例如机器人在网站上循环访问,便于及时阻断。

30 - 9. 统计信息与监控

CSV 和类型化统计信息、运行时 CLI 命令、主 CLI 和统计文件

可以查询 HAProxy 的运行状态。最常用的机制是 HTTP 统计信息页面。该页面还提供了一种用于监控工具的替代 CSV 输出格式。相同的格式也通过 Unix 套接字提供。

统计信息按类别分组,类别以域(domain)命名,对应 HAProxy 的多个组件。当前提供两个域:proxy 和 resolvers。若未指定,将选择 proxy 域。请注意,仅代理的统计信息会显示在 HTTP 页面上。

9.1. CSV 格式

可通过 Unix 套接字或 HTTP 页面查阅统计信息。两种方式均提供 CSV 格式,其字段定义如下。第一行以井号(’#’)开头,每个逗号分隔的字段对应一列标题。从第二行开始的其余行采用标准 CSV 格式,以逗号作为分隔符,双引号(’"’)作为可选的文本分隔符,仅当被包围的文本存在歧义时(如包含引号或逗号)才使用。文本中的双引号字符需以两个双引号(’""’)表示,这是大多数工具所识别的格式。请勿在这些字段前插入任何列,以免破坏依赖硬编码列位置的工具。

对于代理的统计信息,每个字段名后方括号内会列出该字段可能具有值的类型。类型包括 L(监听器)、F(前端)、B(后端)和 S(服务器)。存在一组固定的静态字段,其始终以相同顺序可用。包含字符“-”的列表示静态字段的结束,此后字段的存在性或顺序无法保证。

以下是使用代理统计信息域的静态字段列表:

 0. pxname [LFBS]: proxy name
 1. svname [LFBS]: service name (FRONTEND for frontend, BACKEND for backend,
    any name for server/listener)
 2. qcur [..BS]: current queued requests. For the backend this reports the
    number queued without a server assigned.
 3. qmax [..BS]: max value of qcur
 4. scur [LFBS]: current sessions
 5. smax [LFBS]: max sessions
 6. slim [LFBS]: configured session limit
 7. stot [LFBS]: cumulative number of sessions
 8. bin [LFBS]: bytes in
 9. bout [LFBS]: bytes out
10. dreq [LFB.]: requests denied because of security concerns.
    - For tcp this is because of a matched tcp-request content rule.
    - For http this is because of a matched http-request or tarpit rule.
11. dresp [LFBS]: responses denied because of security concerns.
    - For http this is because of a matched http-request rule, or
      "option checkcache".
12. ereq [LF..]: request errors. Some of the possible causes are:
    - early termination from the client, before the request has been sent.
    - read error from the client
    - client timeout
    - client closed connection
    - various bad requests from the client.
    - request was tarpitted.
13. econ [..BS]: number of requests that encountered an error trying to
    connect to a backend server. The backend stat is the sum of the stat
    for all servers of that backend, plus any connection errors not
    associated with a particular server (such as the backend having no
    active servers).
14. eresp [..BS]: response errors. srv_abrt will be counted here also.
    Some other errors are:
    - write error on the client socket (won't be counted for the server stat)
    - failure applying filters to the response.
15. wretr [..BS]: number of times a connection to a server was retried.
16. wredis [..BS]: number of times a request was redispatched to another
    server. The server value counts the number of times that server was
    switched away from.
17. status [LFBS]: status (UP/DOWN/NOLB/MAINT/MAINT(via)/MAINT(resolution)...)
18. weight [..BS]: total effective weight (backend), effective weight (server)
19. act [..BS]: number of active servers (backend), server is active (server)
20. bck [..BS]: number of backup servers (backend), server is backup (server)
21. chkfail [...S]: number of failed checks. (Only counts checks failed when
    the server is up.)
22. chkdown [..BS]: number of UP->DOWN transitions. The backend counter counts
    transitions to the whole backend being down, rather than the sum of the
    counters for each server.
23. lastchg [..BS]: number of seconds since the last UP<->DOWN transition
24. downtime [..BS]: total downtime (in seconds). The value for the backend
    is the downtime for the whole backend, not the sum of the server downtime.
25. qlimit [...S]: configured maxqueue for the server, or nothing in the
    value is 0 (default, meaning no limit)
26. pid [LFBS]: process id (0 for first instance, 1 for second, ...)
27. iid [LFBS]: unique proxy id
28. sid [L..S]: server id (unique inside a proxy)
29. throttle [...S]: current throttle percentage for the server, when
    slowstart is active, or no value if not in slowstart.
30. lbtot [..BS]: total number of times a server was selected, either for new
    sessions, or when re-dispatching. The server counter is the number
    of times that server was selected.
31. tracked [...S]: id of proxy/server if tracking is enabled.
32. type [LFBS]: (0=frontend, 1=backend, 2=server, 3=socket/listener)
33. rate [.FBS]: number of sessions per second over last elapsed second
34. rate_lim [.F..]: configured limit on new sessions per second
35. rate_max [.FBS]: max number of new sessions per second
36. check_status [...S]: status of last health check, one of:
       UNK     -> unknown
       INI     -> initializing
       SOCKERR -> socket error
       L4OK    -> check passed on layer 4, no upper layers testing enabled
       L4TOUT  -> layer 1-4 timeout
       L4CON   -> layer 1-4 connection problem, for example
                  "Connection refused" (tcp rst) or "No route to host" (icmp)
       L6OK    -> check passed on layer 6
       L6TOUT  -> layer 6 (SSL) timeout
       L6RSP   -> layer 6 invalid response - protocol error
       L7OK    -> check passed on layer 7
       L7OKC   -> check conditionally passed on layer 7, for example 404 with
                  disable-on-404
       L7TOUT  -> layer 7 (HTTP/SMTP) timeout
       L7RSP   -> layer 7 invalid response - protocol error
       L7STS   -> layer 7 response error, for example HTTP 5xx
    Notice: If a check is currently running, the last known status will be
    reported, prefixed with "* ". e. g. "* L7OK".
37. check_code [...S]: layer5-7 code, if available
38. check_duration [...S]: time in ms took to finish last health check
39. hrsp_1xx [.FBS]: http responses with 1xx code
40. hrsp_2xx [.FBS]: http responses with 2xx code
41. hrsp_3xx [.FBS]: http responses with 3xx code
42. hrsp_4xx [.FBS]: http responses with 4xx code
43. hrsp_5xx [.FBS]: http responses with 5xx code
44. hrsp_other [.FBS]: http responses with other codes (protocol error)
45. hanafail [...S]: failed health checks details
46. req_rate [.F..]: HTTP requests per second over last elapsed second
47. req_rate_max [.F..]: max number of HTTP requests per second observed
48. req_tot [.FB.]: total number of HTTP requests received
49. cli_abrt [..BS]: number of data transfers aborted by the client
50. srv_abrt [..BS]: number of data transfers aborted by the server
    (inc. in eresp)
51. comp_in [.FB.]: number of HTTP response bytes fed to the compressor
52. comp_out [.FB.]: number of HTTP response bytes emitted by the compressor
53. comp_byp [.FB.]: number of bytes that bypassed the HTTP compressor
    (CPU/BW limit)
54. comp_rsp [.FB.]: number of HTTP responses that were compressed
55. lastsess [..BS]: number of seconds since last session assigned to
    server/backend
56. last_chk [...S]: last health check contents or textual error
57. last_agt [...S]: last agent check contents or textual error
58. qtime [..BS]: the average queue time in ms over the 1024 last requests
59. ctime [..BS]: the average connect time in ms over the 1024 last requests
60. rtime [..BS]: the average response time in ms over the 1024 last requests
    (0 for TCP)
61. ttime [..BS]: the average total session time in ms over the 1024 last
    requests
62. agent_status [...S]: status of last agent check, one of:
       UNK     -> unknown
       INI     -> initializing
       SOCKERR -> socket error
       L4OK    -> check passed on layer 4, no upper layers testing enabled
       L4TOUT  -> layer 1-4 timeout
       L4CON   -> layer 1-4 connection problem, for example
                  "Connection refused" (tcp rst) or "No route to host" (icmp)
       L7OK    -> agent reported "up"
       L7STS   -> agent reported "fail", "stop", or "down"
63. agent_code [...S]: numeric code reported by agent if any (unused for now)
64. agent_duration [...S]: time in ms taken to finish last check
65. check_desc [...S]: short human-readable description of check_status
66. agent_desc [...S]: short human-readable description of agent_status
67. check_rise [...S]: server's "rise" parameter used by checks
68. check_fall [...S]: server's "fall" parameter used by checks
69. check_health [...S]: server's health check value between 0 and rise+fall-1
70. agent_rise [...S]: agent's "rise" parameter, normally 1
71. agent_fall [...S]: agent's "fall" parameter, normally 1
72. agent_health [...S]: agent's health parameter, between 0 and rise+fall-1
73. addr [L..S]: address:port or "unix". IPv6 has brackets around the address.
74: cookie [..BS]: server's cookie value or backend's cookie name
75: mode [LFBS]: proxy mode (tcp, http, health, unknown)
76: algo [..B.]: load balancing algorithm
77: conn_rate [.F..]: number of connections over the last elapsed second
78: conn_rate_max [.F..]: highest known conn_rate
79: conn_tot [.F..]: cumulative number of connections
80: intercepted [.FB.]: cum. number of intercepted requests (monitor, stats)
81: dcon [LF..]: requests denied by "tcp-request connection" rules
82: dses [LF..]: requests denied by "tcp-request session" rules
83: wrew [LFBS]: cumulative number of failed header rewriting warnings
84: connect [..BS]: cumulative number of connection establishment attempts
85: reuse [..BS]: cumulative number of connection reuses
86: cache_lookups [.FB.]: cumulative number of cache lookups
87: cache_hits [.FB.]: cumulative number of cache hits
88: srv_icur [...S]: current number of idle connections available for reuse
89: src_ilim [...S]: limit on the number of available idle connections
90. qtime_max [..BS]: the maximum observed queue time in ms
91. ctime_max [..BS]: the maximum observed connect time in ms
92. rtime_max [..BS]: the maximum observed response time in ms (0 for TCP)
93. ttime_max [..BS]: the maximum observed total session time in ms
94. eint [LFBS]: cumulative number of internal errors
95. idle_conn_cur [...S]: current number of unsafe idle connections
96. safe_conn_cur [...S]: current number of safe idle connections
97. used_conn_cur [...S]: current number of connections in use
98. need_conn_est [...S]: estimated needed number of connections
99. uweight [..BS]: total user weight (backend), server user weight (server)
100. agg_server_status [..B.]: backend aggregated gauge of server's status
101. agg_server_status_check [..B.]: (deprecated)
102. agg_check_status [..B.]: backend aggregated gauge of server's state check
     status
103. srid [...S]: server id revision
104. sess_other [.F..]: total number of sessions other than HTTP since process
     started
105. h1_sess [.F..]: total number of HTTP/1 sessions since process started
106. h2_sess [.F..]: total number of HTTP/2 sessions since process started
107. h3_sess [.F..]: total number of HTTP/3 sessions since process started
108. req_other [.F..]: total number of sessions other than HTTP processed by
     this object since the worker process started
109. h1req [.F..]: total number of HTTP/1 sessions processed by this object
     since the worker process started
110. h2req [.F..]: total number of hTTP/2 sessions processed by this object
     since the worker process started
111. h3req [.F..]: total number of HTTP/3 sessions processed by this object
     since the worker process started
112. proto [L...]: protocol
113. priv_idle_cur [...S]: current number of private idle connections
114. reqbin [LFBS]: total number of request bytes received since the worker
     process started
115. reqbout [LFBS]: total number of request bytes sent since the worker
     process started
116. resbin [LFBS]: total number of response bytes received since the worker
     process started
117. resbout [LFBS]: total number of response bytes sent since the worker
     process started

对于所有其他统计信息域,字段的存在与否或顺序均无法保证。此时,应始终使用头行来解析 CSV 数据。

9.2. 类型化输出格式

“show info” 和 “show stat” 均支持一种模式,其中每个输出值均附带其类型,以及足够信息以明确该值在进程间应如何聚合,以及其如何演变。

在所有情况下,输出格式为每行仅包含一个值,所有信息均以冒号(’:’)分隔的字段形式呈现。

第一列指定被转储的对象或指标。其格式由生成此输出的命令决定,本节不作说明。通常由一系列标识符和字段名组成。

第二列包含四个字符,分别表示所报告值的来源、性质、作用域和持久性状态。第一个字符(来源)表示该值的提取位置。可能的字符如下:

M   The value is a metric. It is valid at one instant any may change depending
    on its nature .

S   The value is a status. It represents a discrete value which by definition
    cannot be aggregated. It may be the status of a server ("UP" or "DOWN"),
    the PID of the process, etc.

K   The value is a sorting key. It represents an identifier which may be used
    to group some values together because it is unique among its class. All
    internal identifiers are keys. Some names can be listed as keys if they
    are unique (eg: a frontend name is unique). In general keys come from the
    configuration, even though some of them may automatically be assigned. For
    most purposes keys may be considered as equivalent to configuration.

C   The value comes from the configuration. Certain configuration values make
    sense on the output, for example a concurrent connection limit or a cookie
    name. By definition these values are the same in all processes started
    from the same configuration file.

P   The value comes from the product itself. There are very few such values,
    most common use is to report the product name, version and release date.
    These elements are also the same between all processes.

第二个字符(即类型)用于表示字段所携带信息的性质,以便聚合器决定对多个值进行聚合时应采用的操作。可能的字符包括:

A   The value represents an age since a last event. This is a bit different
    from the duration in that an age is automatically computed based on the
    current date. A typical example is how long ago did the last session
    happen on a server. Ages are generally aggregated by taking the minimum
    value and do not need to be stored.

a   The value represents an already averaged value. The average response times
    and server weights are of this nature. Averages can typically be averaged
    between processes.

C   The value represents a cumulative counter. Such measures perpetually
    increase until they wrap around. Some monitoring protocols need to tell
    the difference between a counter and a gauge to report a different type.
    In general counters may simply be summed since they represent events or
    volumes. Examples of metrics of this nature are connection counts or byte
    counts.

D   The value represents a duration for a status. There are a few usages of
    this, most of them include the time taken by the last health check and
    the time a server has spent down. Durations are generally not summed,
    most of the time the maximum will be retained to compute an SLA.

G   The value represents a gauge. It's a measure at one instant. The memory
    usage or the current number of active connections are of this nature.
    Metrics of this type are typically summed during aggregation.

L   The value represents a limit (generally a configured one). By nature,
    limits are harder to aggregate since they are specific to the point where
    they were retrieved. In certain situations they may be summed or be kept
    separate.

M   The value represents a maximum. In general it will apply to a gauge and
    keep the highest known value. An example of such a metric could be the
    maximum amount of concurrent connections that was encountered in the
    product's life time. To correctly aggregate maxima, you are supposed to
    output a range going from the maximum of all maxima and the sum of all
    of them. There is indeed no way to know if they were encountered
    simultaneously or not.

m   The value represents a minimum. In general it will apply to a gauge and
    keep the lowest known value. An example of such a metric could be the
    minimum amount of free memory pools that was encountered in the product's
    life time. To correctly aggregate minima, you are supposed to output a
    range going from the minimum of all minima and the sum of all of them.
    There is indeed no way to know if they were encountered simultaneously
    or not.

N   The value represents a name, so it is a string. It is used to report
    proxy names, server names and cookie names. Names have configuration or
    keys as their origin and are supposed to be the same among all processes.

O   The value represents a free text output. Outputs from various commands,
    returns from health checks, node descriptions are of such nature.

R   The value represents an event rate. It's a measure at one instant. It is
    quite similar to a gauge except that the recipient knows that this measure
    moves slowly and may decide not to keep all values. An example of such a
    metric is the measured amount of connections per second. Metrics of this
    type are typically summed during aggregation.

T   The value represents a date or time. A field emitting the current date
    would be of this type. The method to aggregate such information is left
    as an implementation choice. For now no field uses this type.

第三个字符(作用域)表示该值所反映的范围。某些元素可能与进程相关,而其他元素可能与配置或系统相关。明确这一区别至关重要,以判断在聚合过程中是否应保留单一值,还是必须对多个值进行聚合。当前支持的字符如下:

C   The value is valid for a whole cluster of nodes, which is the set of nodes
    communicating over the peers protocol. An example could be the amount of
    entries present in a stick table that is replicated with other peers. At
    the moment no metric use this scope.

P   The value is valid only for the process reporting it. Most metrics use
    this scope.

S   The value is valid for the whole service, which is the set of processes
    started together from the same configuration file. All metrics originating
    from the configuration use this scope. Some other metrics may use it as
    well for some shared resources (eg: shared SSL cache statistics).

s   The value is valid for the whole system, such as the system's hostname,
    current date or resource usage. At the moment this scope is not used by
    any metric.

第四个字符(持久性状态)表示该值(指标)在重载后是否保持持久。后续字符的含义如下:

V   The metric is volatile because it is local to the current process so
    the value will be lost when reloading.

P   The metric is persistent because it may be shared with other co-processes
    so that the value is preserved across reloads.

消费这些信息的用户通常只需具备这 4 个字符即可准确报告跨多个进程的聚合信息。

在该列之后,第三列指示字段类型,包括 “s32”(有符号 32 位整数)、“s64”(有符号 64 位整数)、“u32”(无符号 32 位整数)、“u64”(无符号 64 位整数)和 “str”(字符串)。在解析值之前,必须了解其类型,以确保正确读取。例如,仅包含数字的字符串仍然是字符串,而非整数(如通过检查获取的错误码)。

第四列是值本身,其编码方式根据类型而定。字符串在冒号后直接输出,不加任何前导空格。若字符串中包含冒号,将正常显示。这意味着输出不应仅通过冒号进行分割,否则某些检查输出或服务器地址可能被截断。

9.3. Unix 套接字命令

统计信息套接字默认未启用。如需启用,必须在 HAProxy 配置的 global 段中添加一行配置。建议添加第二行以设置更大的超时值,手动执行命令时此设置始终有益:

global
    stats socket /var/run/haproxy.sock mode 600 level admin
    stats timeout 2m

也可以通过重复该行来添加多个统计信息套接字实例,并使其监听 TCP 端口而非 Unix 套接字。默认情况下从不这样做,因为存在安全隐患,但在某些情况下可能较为方便:

global
    stats socket /var/run/haproxy.sock mode 600 level admin
    stats socket ipv4@192.168.0.1:9999 level admin
    stats timeout 2m

要访问套接字,需要使用外部工具,例如“socat”。Socat 是一款功能强大的工具,可用于连接任意两个端点。我们使用它将终端连接到套接字,或将其与若干 stdin/stdout 管道连接,以供脚本使用。我们将主要使用以下两种语法:

# socat /var/run/haproxy.sock stdio
# socat /var/run/haproxy.sock readline

第一个用于脚本。可以将脚本的输出发送给 HAProxy,并将 HAProxy 的输出传递给另一个脚本。例如,这在获取计数器或攻击追踪信息时非常有用。

第二个仅适用于手动执行命令。其优势在于终端由 readline 库处理,支持行编辑和历史记录,当重复执行命令时(例如:监视计数器)非常方便。

套接字支持三种操作模式:

  • 非交互式,静默模式
  • 交互式,静默模式
  • 交互式,带提示

非交互模式是 socat 与套接字连接时的默认模式。在此模式下,可发送单行内容。该行将作为整体被处理,响应会返回,并在响应结束时关闭连接。此模式通常由脚本和监控工具使用。在此模式下也可以发送多个命令,但需以分号(;)分隔。例如:

# echo "show info;show stat;show table" | socat /var/run/haproxy stdio

如果命令需要使用分号或反斜杠(例如在值中),则必须用反斜杠(’\’)进行转义。

交互模式允许在前一行命令执行完毕后发送新命令。 该模式存在两种变体:一种为静默模式,其行为与非交互模式类似,但套接字会等待新命令而非关闭;另一种在行首显示提示符(\>)。 对于高级工具,推荐使用交互模式;对于人类用户,推荐使用带提示符的模式。

可以使用 “prompt” 命令更改模式。默认情况下,该命令在交互模式与提示模式之间切换。在交互模式下输入 “prompt” 将切换至提示模式。该命令可选择性地指定以下特定模式之一:

  • “n”:非交互模式(执行单个命令后退出)
  • “i”:交互模式(执行多个命令,无提示符)
  • “p”:提示符模式(执行多个命令,带有提示符)

由于默认模式为非交互式,必须首先使用“prompt”命令切换模式,否则前一条命令将导致连接关闭。切换至非交互式模式后,同一行的所有命令执行完毕,连接将被关闭。

因此,在手动调试时,通常会从执行“prompt”命令开始:

# socat /var/run/haproxy readline
prompt

show info …

交互式工具可能更倾向于使用“prompt i”来切换至交互模式,而无需显示提示符。

可选地,提示符中可显示进程的运行时间。为启用此功能,使用命令 prompt timed 可启用提示符并切换时间显示状态。运行时间以格式 “d:hh:mm:ss” 显示,其中 “d” 表示天数,“hh”、“mm”、“ss” 分别表示以两位数字表示的小时、分钟和秒:

# socat /var/run/haproxy readline
prompt timed

[23:03:34:39]> show version 2.8-dev9-e5e622-18

[23:03:34:41]> quit

当在主 CLI 上设置定时提示时,提示符将显示当前选定进程的运行时间,因此该功能适用于主进程、当前工作进程或较早的工作进程:

master> prompt timed
[0:00:00:50] master> show proc
(...)
[0:00:00:58] master> @!11955     <-- master, switch to current worker
[0:00:01:03] 11955> @!11942      <-- current worker, switch to older worker
[0:00:02:17] 11942> @            <-- older worker, switch back to master
[0:00:01:10] master>

由于可同时发出多个命令,HAProxy 使用空行作为分隔符,以标记每个命令输出的结束,并确保没有任何命令会在输出中产生空行。因此,脚本可以轻松解析输出,即使多个命令在单行中通过管道传递。

部分命令可接受可选负载。若需为命令添加负载,首行必须以 “<<\n” 模式结尾。后续行将被视为负载内容,可包含任意行数。验证带负载的命令时,需以空行结尾。

负载内容的结束模式可自定义,以改变负载的结束方式。若需以非空行的方式结束负载,可在 << 与 &#92;n 之间设置自定义模式。除 << 外,最多可使用 64 个字符,否则将不被视为有效负载。使用随机负载模式通常已足够。例如,使用包含空行和注释的 PEM 文件时:

# echo -e "set ssl cert common.pem <<%EOF%\n$(cat common.pem)\n%EOF%\n" | \
socat /var/run/haproxy.stat -

存在限制:模式 “<<” 不能紧接在行末最后一个单词之后。命令行长度不得超过 tune.bufsize,包括启动负载的模式,但不包含负载本身。负载大小默认限制为 128KB。可通过设置 “tune.cli.max-payload-size” 全局参数进行修改,但需注意相关注意事项。请注意,标记负载结束的模式也包含在此限制范围内。

在交互模式下输入负载时,提示符将从“> ”变为“+ ”。

当多个 HAProxy 进程在相同套接字上启动时,任意一个进程都可能接收请求,并输出其自身的统计信息。

当前支持的统计套接字命令列表如下。若发送了未知命令,HAProxy 将显示使用说明,提醒所有支持的命令。部分命令支持更复杂的语法,通常在出现错误时会说明命令中哪一部分无效。

部分命令需要更高权限才能执行。若权限不足,将收到错误提示“权限被拒绝”。请参阅配置手册中“bind”关键字行的“level”选项以获取更多信息。

abort ssl ca-file <cafile>

abort ssl ca-file <cafile>

中止并销毁临时 CA 文件更新事务。

另请参见“set ssl ca-file”和“commit ssl ca-file”。

abort ssl cert <filename>

abort ssl cert <filename>

中止并销毁临时 SSL 证书更新事务。

另请参见“set ssl cert”和“commit ssl cert”。

abort ssl crl-file <crlfile>

abort ssl crl-file <crlfile>

中止并销毁临时 CRL 文件更新事务。

另请参见“set ssl crl-file”和“commit ssl crl-file”。

acme renew <certificate>

acme renew <certificate>

启动一个使用指定证书名称的 ACME 证书生成任务。该证书必须关联至一个 acme 段,参见配置手册第 12.8 段“ACME”。另请参阅“acme status”。

acme status

acme status

显示所有使用 ACME 配置的证书的状态。

该命令以制表符分隔输出:

  • HAProxy 中配置的证书名称
  • 配置中使用的 acme 段
  • acme 任务的状态,取值为 “Running”、“Scheduled” 或 “Stopped”
  • 证书的 UTC 过期日期,格式为 ISO8601
  • 相对过期时间(已过期则为 0d)
  • 证书的 UTC 预定日期,格式为 ISO8601
  • 相对预定时间(若处于 Running 状态则为 0d)

示例:

$ echo "@1; acme status" | socat /tmp/master.sock - | column -t -s $'\t'
# certificate   section  state      expiration date (UTC)  expires in        scheduled date (UTC)  scheduled in
ecdsa.pem       LE       Running    2020-01-18T09:31:12Z   0d 0h00m00s       2020-01-15T21:31:12Z  0d 0h00m00s
foobar.pem.rsa  LE       Scheduled  2025-08-04T11:50:54Z   89d 23h01m13s     2025-07-27T23:50:55Z  82d 11h01m14s

add acl [@<ver>] <acl> <pattern>

add acl [@<ver>] <acl> <pattern>

向 ACL <acl> 中添加一项。<acl> 为 #<id> 或由 “show acl” 返回的 <name>。 该命令不会验证该项是否已存在。除非使用 “@<ver>” 指定特定版本,否则条目将添加至当前 ACL 版本。该版本号必须事先通过 “prepare acl” 分配,且其值须位于 “show acl” 输出中报告的 “curr_ver” 与 “next_ver” 之间。使用特定版本号添加的条目,需在执行 “commit acl” 操作后方可生效匹配。但可使用 “show acl @<ver>” 命令查阅,或通过 “clear acl @<ver>” 命令清除。 若参考 <acl> 为与映射(map)同名的名称,则禁止使用此命令。此时应改用 “add map” 命令。

add backend <name> from <defproxy> [mode <mode>] [guid <guid>]

add backend <name> from <defproxy> [mode <mode>] [guid <guid>]

使用名称 <name> 实例化一个新的后端代理。

仅可创建 TCP 或 HTTP 代理。所有设置均继承自 <defproxy> 默认代理实例。默认情况下,除非 <defproxy> 显式定义了后端模式,否则必须通过同名参数指定后端模式。如需,也可选择性地使用 GUID 参数。

可通过命令 add server 添加服务器。后端将以未发布状态初始化。确认已就绪可接收流量后,请使用 publish backend 命令发布新创建的实例。

所有命名的默认代理均可使用,前提是它们符合配置解析过程中应用的相同继承规则。不过存在一些例外情况,例如当模式既非 TCP 也非 HTTP 时。

此命令受限制,仅可在配置为“admin”级别的套接字上执行。

add map [@<ver>] <map> <key> <value>

add map [@<ver>] <map> <key> <value>
add map [@<ver>] <map> <payload>

向映射 <map> 中添加一项,将值 <value> 关联至键 <key>。该命令不会验证该项是否已存在。主要用于在执行“clear”或“prepare”操作后填充映射。除非使用 “@<ver>” 指定特定版本,否则条目将添加至当前 ACL 版本。该版本号必须事先通过“prepare acl”分配,并且其数值范围应位于“show acl”输出中报告的 “curr_ver” 与 “next_ver” 之间。使用特定版本号添加的条目,需在执行“commit map”操作后方可匹配。但可通过“show map @<ver>”命令查阅,或通过“clear acl @<ver>”命令清除。若指定的映射同时用作 ACL,则 ACL 仅匹配 <key> 部分,忽略 <value> 部分。使用载荷语法时,可通过在不同行中输入多个键/值对来添加多组键值对。每行中首个词为键,其余部分视为值,值中可包含空格。

示例:

# socat /tmp/sock1 -
prompt

> add map #-1 <<
+ key1 value1
+ key2 value2 with spaces
+ key3 value3 also with spaces
+ key4 value4

>

add server <backend>/<server> [args]*

add server <backend>/<server> [args]*

为后端 <backend> 创建一个新的服务器。

<server> 名称在后端中不得已存在。后端必须使用动态负载均衡算法,对此有特殊限制。可从服务器配置文件语句中选取部分关键字来配置服务器行为(参见“add server help”以获取可用关键字列表)。请注意,同一后端中若存在虚构的 ‘default-server’ 语句,其设置将不会被复用。

当前,动态服务器使用“none” init-addr 方法进行静态初始化。这意味着,即使服务器创建将被验证,若指定的地址为完全限定域名(FQDN),也不会执行解析。

为支持重载操作,通过 CLI 创建的服务器也应手动插入相应的 HAProxy 配置文件中。未在配置文件中出现的动态服务器在重载操作后将无法恢复。

动态服务器可使用“track”关键字来跟踪配置中另一台服务器的检查状态。然而,无法跟踪另一台动态服务器。此举旨在确保即使在删除动态服务器的情况下,跟踪链仍保持一致。

使用 “check” 关键字启用健康检查支持。请注意,健康检查默认处于禁用状态,必须通过 “enable health” 命令独立启用服务器的健康检查功能。对于代理检查,使用 “agent-check” 关键字和 “enable agent” 命令。请注意,在此情况下,服务器可能根据代理报告的状态自动激活,无需显式执行 “enable server” 命令。这也意味着在移除具有代理检查的动态服务器时需格外谨慎。应首先通过 “disable agent” 命令停用代理,再将服务器置于所需的维护模式,方可执行移除操作。

在使用大量动态服务器时,可能会达到文件描述符限制。请参考本文中“u-limit”全局关键字的文档。

add server help

add server help

列出当前 HAProxy 版本支持的动态服务器关键字。关键字语法与配置文件中的服务器行类似,请参阅各自文档以获取详细信息。

add ssl ca-file <cafile> <payload>

add ssl ca-file <cafile> <payload>

向 ca-file 添加新证书。当 CLI 的缓冲区大小达到上限且需要添加多个证书时,此命令非常有用。无需通过“set”命令一次性设置所有证书,可逐个添加证书。执行“set ssl ca-file”将重置 ca-file。

示例:

echo -e "set ssl ca-file cafile.pem <<\n$(cat rootCA.crt)\n" | \
socat /var/run/haproxy.stat -
echo -e "add ssl ca-file cafile.pem <<\n$(cat intermediate1.crt)\n" | \
socat /var/run/haproxy.stat -
echo -e "add ssl ca-file cafile.pem <<\n$(cat intermediate2.crt)\n" | \
socat /var/run/haproxy.stat -
echo "commit ssl ca-file cafile.pem" | socat /var/run/haproxy.stat -

add ssl crt-list <crtlist> <certificate>

add ssl crt-list <crtlist> <certificate>
add ssl crt-list <crtlist> <payload>

在 crt-list 中添加证书。该命令也可用于目录,因为目录现在与 crt-list 的加载方式相同。若需在参数中使用证书名称,允许使用 SSL 选项或过滤器,此时 crt-list 行必须作为负载发送。负载中仅支持一条 crt-list 行。该命令将为所有使用 crt-list 的 bind 行加载证书。若要向 HAProxy 推送新证书,必须使用命令 “new ssl cert” 或 “set ssl cert”。

示例:

$ echo "new ssl cert foobar.pem" | socat /tmp/sock1 -
$ echo -e "set ssl cert foobar.pem <<\n$(cat foobar.pem)\n" | socat
/tmp/sock1 -
$ echo "commit ssl cert foobar.pem" | socat /tmp/sock1 -
$ echo "add ssl crt-list certlist1 foobar.pem" | socat /tmp/sock1 -

$ echo -e 'add ssl crt-list certlist1 <<\nfoobar.pem [allow-0rtt] foo.bar.com
!test1.com\n' | socat /tmp/sock1 -

add ssl ech <bind> <payload>

add ssl ech <bind> <payload>

向 <bind> 行添加 ECH 密钥。有效载荷必须采用 ECH 格式的 PEM 格式。 (https://datatracker.ietf.org/doc/html/draft-farrell-tls-pemesni )

绑定行格式为 <frontend>/@<filename>:<linenum>(例如:frontend1/@HAProxy.conf:19),或 <frontend>/<name>(若绑定行使用了 “name” 关键字命名)。

必须使用支持 ECH 的 OpenSSL 版本,且 HAProxy 必须以 USE_ECH=1 编译。 该命令仅在以实验模式运行的 CLI 连接中受支持(参见“experimental-mode on”)。

另请参见配置手册 第 5.1 节 中的 “show ssl ech” 和 “ech”。

示例:

$ openssl ech -public_name foobar.com -out foobar3.com.ech
$ echo -e "experimental-mode on; add ssl ech frontend1/@haproxy.conf:19 <<%EOF%\n$(cat foobar3.com.ech)\n%EOF%\n" | \
  socat /tmp/haproxy.sock -
added a new ECH config to frontend1

add ssl jwt <filename>

add ssl jwt <filename>

将已加载的证书添加到可用于 JWT 验证的证书列表中(参见 “jwt_verify_cert” 转换器)。该命令在正在进行的事务中无效。另请参见“del ssl jwt”和“show ssl jwt”命令。有关更多信息,请参见“jwt”证书选项。

clear counters

clear counters

清除每个代理(前端和后端)及每个服务器的统计信息计数器的最大值。累积计数器不受影响。“show activity” 命令报告的内部活动计数器也会被重置。此命令可用于在事件发生后获取干净的计数器,而无需重启或清除流量计数器。该命令受限制,仅可在配置为“operator”或“admin”级别的套接字上执行。

clear counters all

clear counters all

清除每个代理(前端与后端)及每个服务器的统计信息计数器。此操作效果等同于重启。该命令受限制,仅可在配置为“admin”级别的套接字上执行。

clear acl [@<ver>] <acl>

clear acl [@<ver>] <acl>

从 acl <acl> 中移除所有条目。<acl> 为 “show acl” 返回的 #<id> 或 <name>。请注意,若引用 <acl> 为名称且与映射共享,则该映射也将被清空。默认情况下仅清除当前版本的 ACL(即正在匹配的版本)。但也可通过在版本号前加 ‘@’ 来指定清除其他版本。

clear map [@<ver>] <map>

clear map [@<ver>] <map>

清除映射 <map> 中的所有条目。<map> 为 “show map” 返回的 #<id> 或 <name>。请注意,如果引用 <map> 为名称且与某个 acl 共享,则该 acl 也将被清除。默认情况下仅清除当前版本的映射(即正在匹配的版本)。但可以使用 ‘@’ 加上指定版本的方式,清除其他版本。

clear table <table> [ data.<type> <operator> <value> ] | [ key <key> ] |

clear table <table> [ data.<type> <operator> <value> ] | [ key <key> ] |
                    [ ptr <ptr> ]

从粘性表 <table> 中移除条目。

这通常用于解除某些用户因被不当拒绝访问服务而产生的问题,也可用于清除将要被替换的服务器所匹配的会话粘性条目(详见下文“show table”部分)。请注意,有时删除条目会被拒绝,因为该条目当前正被某个会话跟踪。会话结束后等待几秒再重试是常见做法。

若未提供任何选项参数,将删除所有条目。

当使用 “data.” 形式时,将移除与通过存储数据应用的过滤器匹配的条目(参见第 4.2 段中的 “stick-table”)。必须在 <type> 中指定存储数据类型,且该数据类型必须已存储在表中,否则将报告错误。数据将根据 <operator> 与 64 位整数 <value> 进行比较。操作符与 ACL 中的相同:

- eq: match entries whose data is equal to this value
- ne: match entries whose data is not equal to this value
- le: match entries whose data is less than or equal to this value
- ge: match entries whose data is greater than or equal to this value
- lt: match entries whose data is less than this value
- gt: match entries whose data is greater than this value

使用键形式时,条目 <key> 将被移除。键的类型必须与表类型相同,当前仅限于 IPv4、IPv6、整数和字符串。

使用 ptr 形式时,条目 <ptr> 将被移除。<ptr> 以 0xffff 格式写入,必须与之前执行“show table”命令返回的地址对应。当因键为空或 CLI 上存在不兼容字符而无法通过键匹配条目时,使用指针匹配条目可能具有实际意义。

如果 data.<type> 为数组类型,可以使用 “[]” 访问数组中的特定索引,例如:data.gpt[1]

示例:

    $ echo "show table http_proxy" | socat stdio /tmp/sock1
>>> # table: http_proxy, type: ip, size:204800, used:2
>>> 0x80e6a4c: key=127.0.0.1 use=0 exp=3594729 gpc0=0 conn_rate(30000)=1 \
      bytes_out_rate(60000)=187
>>> 0x80e6a80: key=127.0.0.2 use=0 exp=3594740 gpc0=1 conn_rate(30000)=10 \
      bytes_out_rate(60000)=191
>>> 0x80e6b40: key=127.0.0.3 use=0 exp=3594743 gpc0=2 conn_rate(30000)=10 \
      bytes_out_rate(60000)=200

    $ echo "clear table http_proxy key 127.0.0.1" | socat stdio /tmp/sock1

    $ echo "show table http_proxy" | socat stdio /tmp/sock1
>>> # table: http_proxy, type: ip, size:204800, used:1
>>> 0x80e6a80: key=127.0.0.2 use=0 exp=3594740 gpc0=1 conn_rate(30000)=10 \
>>> 0x80e6b40: key=127.0.0.3 use=0 exp=3594743 gpc0=2 conn_rate(30000)=10 \
      bytes_out_rate(60000)=200
      bytes_out_rate(60000)=191
    $ echo "clear table http_proxy data.gpc0 eq 1" | socat stdio /tmp/sock1
    $ echo "show table http_proxy" | socat stdio /tmp/sock1
>>> # table: http_proxy, type: ip, size:204800, used:1
>>> 0x80e6b40: key=127.0.0.3 use=0 exp=3594743 gpc0=2 conn_rate(30000)=10 \
      bytes_out_rate(60000)=200

    $ echo "clear table http_proxy ptr 0x80e6b40" | socat stdio /tmp/sock1
    $ echo "show table http_proxy" | socat stdio /tmp/sock1
>>> # table: http_proxy, type: ip, size:204800, used:0

commit acl @<ver> <acl>

commit acl @<ver> <acl>

提交对 ACL <acl> 版本 <ver> 所做的全部更改,并删除所有历史版本。<acl> 为“show acl”返回的 #<id> 或 <name>。版本号必须介于 “show acl” 报告的 “curr_ver”+1 与 “next_ver” 之间。如需查看将提交至 ACL 的内容,可使用 “show acl @<ver> <acl>” 查询。指定的版本号通常由 “prepare acl” 命令创建。该替换操作为原子操作,其过程为将当前版本原子性地更新为指定版本,这将立即使其他版本中的所有条目不可见,同时使新版本中的所有条目变为可见。也可通过先执行 “prepare acl”,再不添加任何条目即进行提交的方式,使用本命令实现对 ACL 中所有可见条目的原子性删除。若引用 <acl> 为同时用作映射的名称,则不得使用本命令,此时应改用 “commit map” 命令。

commit map @<ver> <map>

commit map @<ver> <map>

提交对映射 <map> 版本 <ver> 所做的全部更改,并删除所有历史版本。<map> 为 “show map” 返回的 #<id> 或 <name>。版本号必须介于 “curr_ver” + 1 与 “next_ver” 之间,该范围由 “show map” 命令报告。如需查看将提交至映射的内容,可使用 “show map @<ver> <map>” 命令查询。指定的版本号通常通过 “prepare map” 命令创建。该替换操作为原子操作,其过程为将当前版本原子性地更新为指定版本,这将立即使其他版本中的所有条目不可见,同时使新版本中的所有条目变为可见。也可通过先执行 “prepare map”,再不添加任何条目即执行提交,来实现对映射中所有可见条目的原子性删除。

commit ssl ca-file <cafile>

commit ssl ca-file <cafile>

提交临时 SSL CA 文件更新事务。

若存在已有的 CA 文件(在“show ssl ca-file”中显示为“Used”状态),则将新的 CA 文件树条目插入 CA 文件树中,并重建所有使用该 CA 文件条目的实例及其所需的 SSL 上下文。所有先前由已重建实例使用的上下文将被移除。成功后,从树中移除原有的 CA 文件条目。失败时,不进行任何删除或移除操作,所有原始 SSL 上下文均保留并继续使用。临时事务提交后,即被销毁。

在新 CA 文件(经“new ssl ca-file”操作后,且处于“show ssl ca-file”中“未使用”状态)的情况下,该 CA 文件将被插入 CA 文件树中,但 HAProxy 不会在任何地方使用它。如需使用该文件并生成使用它的 SSL 上下文,需通过“add ssl crt-list”将其添加至证书列表中。

另请参阅 “new ssl ca-file”、“set ssl ca-file”、“add ssl ca-file”、“abort ssl ca-file” 和 “add ssl crt-list”。

commit ssl cert <filename>

commit ssl cert <filename>

提交临时 SSL 证书更新事务。

若存在现有证书(在 “show ssl cert” 中显示为 “Used” 状态),则生成其所需的全部 SSL 上下文和 SNIs,插入新证书,并移除旧证书。在配置中所有使用 <filename> 的位置,将其在内存中替换为新证书。若操作失败,则不执行任何删除或插入操作。临时事务提交后,立即销毁。

在新证书(经“new ssl cert”操作后,且在“show ssl cert”中处于“Unused”状态)的情况下,该证书将被提交至证书存储,但 HAProxy 中不会在任何地方使用它。若要使用该证书并生成其 SNI,需将其添加至 crt-list 或通过“add ssl crt-list”添加至目录。

另请参阅 “new ssl cert”、“set ssl cert”、“abort ssl cert” 和 “add ssl crt-list”。

commit ssl crl-file <crlfile>

commit ssl crl-file <crlfile>

提交临时 SSL CRL 文件更新事务。

在存在现有 CRL 文件(在“show ssl crl-file”中显示为“Used”状态)的情况下,新的 CRL 文件条目将被插入 CA 文件树中(该树同时存储 CA 文件和 CRL 文件),所有使用该 CRL 文件条目的实例都将被重建,以及其所需的 SSL 上下文也将被重建。所有先前由重建后的实例使用的上下文将被移除。成功后,先前的 CRL 文件条目将从树中移除。失败时,不会移除或删除任何内容,所有原始 SSL 上下文将被保留并继续使用。临时事务提交后,将被销毁。

在新 CRL 文件(经“new ssl crl-file”创建且处于“show ssl crl-file”中“未使用”状态)的情况下,该 CRL 文件将被插入 CRL 文件树中,但 HAProxy 任何地方都不会使用它。要使用该文件并生成使用它的 SSL 上下文,需通过“add ssl crt-list”将其添加至 crt-list。

另请参见 “new ssl crl-file”、“set ssl crl-file”、“abort ssl crl-file” 和 “add ssl crt-list”。

debug counters [reset|show|on|off|all|bug|chk|cnt|glt|?]*

debug counters [reset|show|on|off|all|bug|chk|cnt|glt|?]*

列出代码中内置的计数器,其具体数量可能因构建选项而异。部分计数器依赖于 DEBUG_STRICT,另一些则依赖于 DEBUG_COUNTERS。该命令接受多个参数的组合,其中部分参数定义动作,另一些定义过滤器:- bug 用于列出 BUG_ON() 语句的计数器 - cnt 用于列出 COUNT_IF() 语句的计数器 - chk 用于列出 CHECK_IF() 语句的计数器 - glt 用于列出 COUNT_GLITCH() 语句的计数器 - all 用于显示从未触发过的计数器(值为 0) - off 动作:禁用 COUNT_IF() 计数器的更新 - on 动作:启用 COUNT_IF() 计数器的更新 - reset 动作:重置所有指定的计数器 - show 动作:显示所有指定的计数器

默认情况下,动作为“show”,用于显示计数器,列出的计数器均为非零值的类型。当未指定其他动作时,“show”命令为隐式执行,仅用于便于从脚本中生成命令。

输出以一个整数计数器开头,后接大写的计数器类型,接着是其在代码中的位置(文件:行号)、函数名称,以及可选的“: ”和描述。请注意,输出格式可能在主版本之间发生变化,且为提升调试能力,新类型和条目可能会被回溯应用到稳定版本中。对这些输出的监控应仅以极为宽松和宽松的方式进行,最好避免。

通常情况下,终端用户不会使用此命令,但开发者在排查问题、查找 CNT 或 GLT 条目时,可能会邀请用户执行该命令。需要注意的是,非零的“CHK”条目不应出现,若发现此类情况,应报告给开发者,因为这可能表明代码中存在错误的假设。

debug dev <command> [args]*

debug dev <command> [args]*

调用开发者专用命令。仅在以专家模式运行的 CLI 连接中受支持(参见“expert-mode on”)。此类命令极为危险且不容出错,误用可能导致进程崩溃。它们仅限专家使用,除非明确指示,否则务必不可使用。部分命令仅在编译 HAProxy 时定义了 DEBUG_DEV 时才可用,因其可能带来安全风险。所有这些命令均需管理员权限,且故意未被文档化,以避免促使不熟悉源代码的人员使用。

del acl <acl> [<key>|#<ref>]

del acl <acl> [<key>|#<ref>]

从映射 <acl> 中删除与键 <key> 对应的所有 ACL 条目。<acl> 为 “show acl” 返回的 #<id> 或 <name>。若使用 <ref>,则仅删除列出的引用。引用可通过列出映射内容获取。请注意,若引用 <acl> 为名称且与映射共享,则该条目在映射中也将被删除。

del backend <name>

del backend <name>

删除名为 <name> 的后端代理。

此操作仅适用于 TCP 或 HTTP 代理。要成功执行,后端实例必须已先取消发布。此外,其所有服务器必须先移除(通过 “del server” 命令行工具)。最后,后端实例上不得仍存在任何关联的流。

存在额外限制,阻止后端的移除。首先,若后端被配置元素显式引用,则无法移除,例如通过 use_backend 规则或在样本表达式中引用。部分代理选项与运行时删除不兼容。目前,当使用已弃用的 dispatch 或 option transparent 时即属此类情况。此外,若后端中声明了 stick-table,则无法移除该后端。最后,若后端中曾存在 QUIC 服务器,则目前无法移除该后端。

在执行此命令前,使用“wait be-removable”检查上述要求可能很有用。这还提供了一种等待与目标后端关联的流最终关闭的方法。

此命令受限制,仅可在配置为“admin”级别的套接字上执行。

del map <map> [<key>|#<ref>]

del map <map> [<key>|#<ref>]

从映射 <map> 中删除对应键 <key> 的所有条目。<map> 为“show map”命令返回的 #<id> 或 <name>。若使用 <ref>,则仅删除列出的引用。引用可通过列出映射内容来查找。请注意,若引用 <map> 为名称且与某个 acl 共享,则该条目在映射中也将被删除。

del ssl ca-file <cafile>

del ssl ca-file <cafile>

从 HAProxy 中删除 CA 文件树条目。CA 文件必须未被使用,并且已从任何 crt-list 中移除。

使用 “show ssl ca-file” 可查看 CA 文件的状态。若证书通过配置中的 “ca-file” 或 “ca-verify-file” 指令直接引用,则无法执行删除操作。

del ssl cert <certfile>

del ssl cert <certfile>

从 HAProxy 中删除证书存储。证书必须未被使用(例如用于 JWT 验证),且已从任意 crt-list 或目录中移除。“show ssl cert” 命令可显示证书状态。若证书通过配置中的 “crt” 指令直接引用,则无法执行删除操作。

del ssl crl-file <crlfile>

del ssl crl-file <crlfile>

从 HAProxy 中删除 CRL 文件树条目。CRL 文件必须未被使用,并且已从任何 crt-list 中移除。“show ssl crl-file” 命令显示 CRL 文件的状态。若证书通过配置中的 “crl-file” 指令直接引用,则无法执行删除操作。

del ssl crt-list <filename> <certfile[:line]>

del ssl crt-list <filename> <certfile[:line]>

从 crt-list 中删除条目。此操作将删除该条目在前端中使用的所有 SNI。若证书在 crt-list 中多次使用,需指定要删除的行号。如需显示行号,请使用命令 “show ssl crt-list -n <crtlist>"。

del ssl ech <bind>

del ssl ech <bind>

删除绑定行中的 ECH 密钥。

绑定行格式为 <frontend>/@<filename>:<linenum>(例如:frontend1/@HAProxy.conf:19),或 <frontend>/<name>(若绑定行使用了 “name” 关键字命名)。

必须使用支持 ECH 的 OpenSSL 版本,且 HAProxy 必须以 USE_ECH=1 编译。 该命令仅在以实验模式运行的 CLI 连接中受支持(参见“experimental-mode on”)。

另请参见配置手册 第 5.1 节 中的 “show ssl ech”、“add ssl ech” 和 “ech”。

示例:

$ echo "experimental-mode on; del ssl ech frontend1/@haproxy.conf:19" | socat /tmp/haproxy.sock -
deleted all ECH configs from frontend1/@haproxy.conf:19

del ssl jwt <filename>

del ssl jwt <filename>

从可用于 JWT 验证的证书列表中移除已加载的证书 (参见 “jwt_verify_cert” 转换器)。该命令在正在进行的事务中无效。另请参见 “add ssl jwt” 和 “show ssl jwt” 命令。有关更多信息,请参见 “jwt” 证书选项。

del server <backend>/<server>

del server <backend>/<server>

从后端 <backend> 中删除一个可移除的服务器。可移除的服务器是指同时满足以下所有条件的服务器:

  • 未被其他配置元素引用
  • 必须已进入维护模式(参见“disable server”)
  • 不得有任何活动或空闲连接

如果满足以下任一条件,则该命令将执行失败。

活跃连接是指至少有一个正在进行的请求的连接。可以使用“shutdown sessions server”命令加速其终止。建议在执行“del server”前使用“wait srv-removable”,以确保所有活跃或空闲连接均已关闭,从而保证命令执行成功。

disable agent <backend>/<server>

disable agent <backend>/<server>

将辅助代理检查标记为临时停止。

当代理检查作为辅助检查运行时(由于服务器指令中的 agent-check 参数),仅当代理处于启用状态时才会初始化新的检查。因此,禁用代理将阻止任何新的代理检查启动,直至通过 enable agent 重新启用代理。

当代理被禁用时,若在代理处于启用状态期间已启动辅助代理检查,则处理流程如下:所有可能改变权重的结果,特别是“drain”或代理返回的权重,均被忽略。代理检查的处理过程其余部分保持不变。

此功能的动机在于,允许暂停代理检查对权重的影响,以便在使用 set weight 配置服务器权重时,不会被代理检查所覆盖。

此命令受限制,仅可在配置为“admin”级别的套接字上执行。

disable dynamic-cookie backend <backend>

disable dynamic-cookie backend <backend>

禁用为后端 <backend> 生成动态 Cookie

disable frontend <frontend>

disable frontend <frontend>

将前端标记为临时停止。这对应于软重启期间所使用的模式:前端会释放端口,但在需要时可重新启用。使用时应谨慎,因为某些非 Linux 操作系统无法重新启用该前端。此功能适用于那些无法想象停止代理的环境,但又必须修复配置错误的代理时。通过这种方式,可以释放端口,并将其绑定到另一个进程以恢复操作。在统计信息页面上,该前端将显示状态为“STOP”。

前端可通过其名称或其数字 ID 指定,数字 ID 前需加井号(’#’)。

此命令受限制,仅可在配置为“admin”级别的套接字上执行。

disable health <backend>/<server>

disable health <backend>/<server>

将主健康检查标记为临时停止。这将停止发送健康检查,且忽略最后一次健康检查结果。服务器将处于未检查状态,并被视为 UP,除非辅助代理检查强制其变为 DOWN。

此命令受限制,仅可在配置为“admin”级别的套接字上执行。

disable server <backend>/<server>

disable server <backend>/<server>

将服务器标记为维护状态。在此模式下,直到服务器退出维护状态前,将不再对该服务器执行任何检查。如果其他服务器跟踪此服务器,这些服务器将在维护期间被设置为不可用。

在统计信息页面中,因维护而处于 DOWN 状态的服务器将显示为“MAINT”状态,其关联的追踪服务器则显示为“MAINT(via)”状态。

后端和服务器均可通过其名称或编号指定,编号前需加井号(’#’)。

此命令受限制,仅可在配置为“admin”级别的套接字上执行。

dump ssl cert <certfile>

dump ssl cert <certfile>

将 HAProxy 内存中加载的证书转储。转储内容按 PEM 格式输出证书,随后是私钥,接着是叶证书,最后是证书链。可通过在文件名前加上星号来转储事务。此操作在通过 CLI 更新证书但未同步到文件系统时,用于将证书保存至文件系统,十分有用。

此命令受限制,仅可在配置为“admin”级别的套接字上执行。

示例:

$ echo "dump ssl cert cert1.pem" | socat /tmp/sock1 -

$ echo "dump ssl cert cert1.pem" | socat /tmp/sock1 - | openssl storeutl -noout -text /dev/stdin

dump stats-file

dump stats-file

生成一个统计文件,该文件可用于在启动时预加载 HAProxy 计数器的值。详见“统计文件”段获取更多详情。

echo <text>

echo <text>

通过 CLI 输出一些文本。在导出多个命令结果时,可在命令之间添加注释,此功能可能有用。

示例:

echo "expert-mode on; echo FDs from fdtab; show fd; echo wild FDs; debug dev fd" | socat /var/run/haproxy.sock -

enable agent <backend>/<server>

enable agent <backend>/<server>

恢复被临时停止的辅助代理检查。

有关临时启动和停止辅助代理的影响详情,请参见“disable agent”部分。

此命令受限制,仅可在配置为“admin”级别的套接字上执行。

enable dynamic-cookie backend <backend>

enable dynamic-cookie backend <backend>

为后端 <backend> 启用动态 Cookie 生成。必须同时提供密钥。

enable frontend <frontend>

enable frontend <frontend>

恢复一个曾被临时停止的前端。某些监听端口可能无法重新绑定(例如:在执行“disable frontend”操作后,有其他进程占用了这些端口)。若发生此情况,将显示错误信息。部分操作系统可能无法恢复已被禁用的前端。

前端可通过其名称或其数字 ID 指定,数字 ID 前需加井号(’#’)。

此命令受限制,仅可在配置为“admin”级别的套接字上执行。

enable health <backend>/<server>

enable health <backend>/<server>

恢复被临时停止的主健康检查。这将重新启用健康检查的发送。请参见“disable health”获取详细信息。

此命令受限制,仅可在配置为“admin”级别的套接字上执行。

enable server <backend>/<server>

enable server <backend>/<server>

如果服务器之前因维护被标记为 DOWN,则此操作将服务器标记为 UP 并重新启用检查。

后端和服务器均可通过其名称或编号指定,编号前需加井号(’#’)。

此命令受限制,仅可在配置为“admin”级别的套接字上执行。

experimental-mode [on|off]

experimental-mode [on|off]

不带选项时,表示当前连接上是否启用了实验模式。传入 “on” 时,仅对当前 CLI 连接启用实验模式。传入 “off” 时,将其关闭。

实验模式用于访问仍在开发中的额外功能。这些功能当前尚不稳定,应谨慎使用。它们可能在不同版本间发生破坏性变更。

在主 CLI 中使用此命令时,不应添加前缀,因为该命令将在任何工作进程连接到其 CLI 时设置其模式。

示例:

echo "@1; experimental-mode on; <experimental_cmd>..." | socat /var/run/haproxy.master -
echo "experimental-mode on; @1 <experimental_cmd>..." | socat /var/run/haproxy.master -

expert-mode [on|off]

expert-mode [on|off]

该命令与 experimental-mode 类似,但用于切换专家模式。

专家模式可显示可能对进程造成极大危害的高级命令,这些命令偶尔可帮助开发者收集复杂错误的关键信息。误用这些功能极可能导致进程崩溃。请勿在未被邀请的情况下使用此选项。请注意,该命令故意未列在帮助消息中,仅在管理员级别下可用。切换至其他级别将自动重置专家模式。

在主 CLI 中使用此命令时,不应添加前缀,因为该命令将在任何工作进程连接到其 CLI 时设置其模式。

示例:

echo "@1; expert-mode on; debug dev exit 1" | socat /var/run/haproxy.master -
echo "expert-mode on; @1 debug dev exit 1" | socat /var/run/haproxy.master -

get map <map> <value>

get map <map> <value>
get acl <acl> <value>

在映射 <map> 或 ACL <acl> 中查找值 <value>。<map> 或 <acl> 为 “show map” 或 “show acl” 命令返回的 <id> 或 <name>。该命令返回与该映射关联的所有匹配模式。此功能适用于调试映射和 ACL。输出格式由每种匹配类型一行组成。每行由空格分隔的词序列构成。

前两个词是:

<match method>:   The match method applied. It can be "found", "bool",
                  "int", "ip", "bin", "len", "str", "beg", "sub", "dir",
                  "dom", "end" or "reg".

<match result>:   The result. Can be "match" or "no-match".

以下词语仅在模式与条目匹配时返回。

 `<index type>`:     "tree" or "list". The internal lookup algorithm.

 `<case>`:           "case-insensitive" or "case-sensitive". The
                   interpretation of the case.

 `<entry matched>`:  match="`<entry>`". Return the matched pattern. It is
                   useful with regular expressions.

最后两个词用于显示返回值及其类型。在 “acl” 情况下,该模式不存在。

 return=nothing:        No return because there are no "map".
 return="`<value>`":      The value returned in the string format.
 return=cannot-display: The value cannot be converted as string.

 type="`<type>`":         The type of the returned sample.

get var <name>

get var <name>

显示进程级变量 ’name’ 的存在性、类型和内容。仅可读取进程级变量,因此变量名必须以 ‘proc.’ 开头,否则将无法找到该变量。此命令需要具备 “operator” 或 “admin” 权限级别。

get weight <backend>/<server>

get weight <backend>/<server>

报告后端 <backend> 中服务器 <server> 的当前权重和初始权重,若任一不存在则返回错误。初始权重指配置文件中显示的权重。通常两者相等,除非当前权重已被修改。后端和服务器均可通过名称或编号 ID 指定,编号 ID 前需加井号(’#’)。

help [<command>]

help [<command>]

显示已知关键字及其基本用法列表,或与请求命令匹配的命令列表。未知命令也会显示相同的帮助屏幕。

httpclient [--htx] <method> <URI>

httpclient [--htx] <method> <URI>

通过 CLI 发起 HTTP 客户端请求,并在 CLI 上打印响应。仅在以专家模式运行的 CLI 连接中受支持(参见“expert-mode on”)。此功能仅用于调试。httpclient 可通过“default”解析器段解析 URL 中的服务器名称,该段默认包含 /etc/resolv.conf 的 DNS 服务器。但若未使用可解析 /etc/hosts 中主机的本地 DNS 守护进程,则无法解析这些主机。

–htx 选项允许使用 HAProxy 内部的 htx 表示形式,通过 htx_dump() 函数实现,主要用于调试。

new ssl ca-file <cafile>

new ssl ca-file <cafile>

创建一个全新的空 CA 文件树条目,用于填充一组 CA 证书,并添加至 crt-list。该命令应与 “set ssl ca-file”、“add ssl ca-file” 和 “add ssl crt-list” 一同使用。

new ssl cert <filename>

new ssl cert <filename>

创建一个全新的空 SSL 证书存储,用于填充证书并添加至目录或 crt-list。此命令应与 “set ssl cert” 和 “add ssl crt-list” 一同使用。

new ssl crl-file <crlfile>

new ssl crl-file <crlfile>

创建一个全新的空 CRL 文件树条目,用于填充一组 CRL 并添加至 crt-list。此命令应与 “set ssl crl-file” 和 “add ssl crt-list” 一同使用。

prepare acl <acl>

prepare acl <acl>

在 ACL <acl> 中分配一个新的版本号,以实现原子替换。<acl> 为 “#<id>” 或 “show acl” 返回的 <name>。新版本号将在 “New version created:” 之后的响应中显示。该编号随后可用于准备向 ACL 添加新条目,待提交后将原子式替换当前条目。该版本号在 “show acl” 中报告为 “next_ver”。分配新版本号不会产生任何影响,因为未使用的版本号在提交更近期版本后将自动移除。版本号为无符号 32 位值,达到上限后会回绕,因此在外部程序中比较时需格外小心。若引用 <acl> 为也用作映射的名称,则不得使用此命令。此时应改用 “prepare map” 命令。

prepare map <map>

prepare map <map>

在映射 <map> 中分配一个新的版本号,以实现原子替换。<map> 为 “show map” 返回的 #<id> 或 <name>。新版本号将在 “New version created:” 之后的响应中显示。该编号随后可用于准备向映射中添加新条目,待提交后将原子性地替换当前条目。在 “show map” 中,该编号报告为 “next_ver”。分配新版本号不会产生任何影响,因为未使用的版本号在提交更近期版本后将自动被移除。版本号为无符号 32 位值,达到上限后会回绕,因此在外部程序中比较时必须格外小心。

prompt [help | n | i | p | timed]*

prompt [help | n | i | p | timed]*

更改交互模式的行为以及在交互模式下行首显示的提示符: - “help” :显示命令的用法 - “n” :切换至非交互模式 - “i” :切换至交互模式 - “p” :切换至交互模式 + 提示符模式 - “timed” :切换在提示符中显示时间

不带任何选项时,将依次切换至提示模式,然后进入非交互模式。 在非交互模式下,当前行的最后一个命令执行完成后,连接即被关闭。 在交互模式下,命令执行完成后不会关闭连接,以便用户输入新命令。 在提示模式下,仍使用交互模式,行首会显示一个提示符,指示解释器正在等待用户输入新命令。 提示符由一个右角括号后跟一个空格组成,即 “> “。

提示模式更适合人类用户,交互模式适合高级脚本,而非交互模式(默认)适合基础脚本。请注意,主套接字不支持非交互模式。

publish backend <backend>

publish backend <backend>

激活内容切换至后端实例。此操作为“unpublish backend”命令的逆操作。该命令受限制,仅可在配置为“operator”或“admin”级别的套接字上执行。

quit

quit

在交互模式下关闭连接。

set anon [on|off] [<key>]

set anon [on|off] [<key>]

本文命令用于启用或禁用当前 CLI 会话的“匿名模式”,该模式会将命令输出中被视为敏感或机密的某些字段替换为哈希值。这些哈希值保留了元素间足够的 一致性,有助于开发者在排查 bug 时识别元素之间的关联,但其位数较低(24 位),由于可能匹配项数量极高,因此无法逆向还原。启用该模式后,若未指定密钥,则将使用全局密钥(在配置文件中通过 “anonkey” 指定,或通过 CLI 命令 “set anon global-key” 设置)。若未设置任何密钥,则将生成一个随机密钥。否则,可指定用于当前会话的 32 位密钥,例如复用之前转储所用的密钥,以帮助对比输出结果。开发者无需此密钥,且建议永不共享,因为该密钥可能被用于确认或否定关于某些哈希值所隐藏内容的猜测。

set dynamic-cookie-key backend <backend> <value>

set dynamic-cookie-key backend <backend> <value>

修改用于生成动态持久化 Cookie 的密钥。这将中断现有会话。

set anon global-key <key>

set anon global-key <key>

设置全局匿名化密钥为 <key>,该值必须为 0 到 4294967295 之间的 32 位整数(0 表示禁用全局密钥)。此命令需要管理员权限。

set map <map> [<key>|#<ref>] <value>

set map <map> [<key>|#<ref>] <value>

修改映射 <map> 中每个键 <key> 对应的值。<map> 为 “show map” 返回的 #<id> 或 <name>。若使用 <ref> 代替 <key>,则仅修改 <ref> 指向的条目。新值为 <value>。

set maxconn frontend <frontend> <value>

set maxconn frontend <frontend> <value>

动态更改指定前端的 maxconn 设置。允许任意正值,包括零,但设置值超过全局 maxconn 限制并无实际意义。若限制值提高且存在待处理连接,这些连接将立即被接受。若限制值降低至当前连接数以下,新连接的接受将延迟,直至达到阈值。前端可通过其名称或以井号(#)前缀的数字 ID 指定。

set maxconn server <backend/server> <value>

set maxconn server <backend/server> <value>

动态更改指定服务器的 maxconn 设置。允许任意正值,包括零,但设置值超过全局 maxconn 的情况并无实际意义。

set maxconn global <maxconn>

set maxconn global <maxconn>

动态调整全局 maxconn 设置,取值范围受限于初始全局 maxconn 设置。若增大该值,正在等待的连接将立即被接受。若减小至低于当前连接数,新连接的接受将延迟,直至达到阈值。值为零时恢复初始设置。

set profiling memory { on | off }

set profiling memory { on | off }
set profiling tasks { auto | on | off | lock | no-lock | memory | no-memory }

启用或禁用指定子系统的 CPU 或内存剖析功能。这等效于在配置文件的“global”段中设置或清除“profiling”选项。 请参阅“show profiling”。请注意,手动将任务剖析设置为“on”会自动重置调度器统计信息,从而可检查指定时间段内的活动情况。 内存剖析仅限于特定操作系统(已知在 linux-glibc 目标上可用),且需要在编译时设置 USE_MEMORY_PROFILING。

. 对于任务性能分析,可以在运行时启用或禁用任务级锁和内存计时的收集,但该更改仅在性能分析器从关闭/自动模式切换至开启模式时(无论是自动还是手动)才会生效。因此,当使用 “no-lock” 禁用任务级锁性能分析以节省 CPU 周期时,建议先关闭再开启任务性能分析,以确保更改生效。

set rate-limit connections global <value>

set rate-limit connections global <value>

更改进程级别的连接速率限制,该限制由全局配置项 maxconnrate 设置。值为零时表示禁用限制。此限制适用于所有前端,更改立即生效。数值以每秒连接数为单位。

set rate-limit http-compression global <value>

set rate-limit http-compression global <value>

更改最大输入压缩速率,该值由全局配置项 ‘maxcomprate’ 设置。值为零时表示禁用限制。该值以每秒千字节为单位传递。该值可在 “show info” 输出中通过 “CompressBpsRateLim” 行查看,单位为字节。

set rate-limit sessions global <value>

set rate-limit sessions global <value>

更改进程级会话速率限制,该限制由全局配置项 maxsessrate 设置。值为零时表示禁用限制。此限制适用于所有前端,更改立即生效。值以每秒会话数为单位。

set rate-limit ssl-sessions global <value>

set rate-limit ssl-sessions global <value>

更改进程级 SSL 会话速率限制,该限制由全局配置项 maxsslrate 设置。值为 0 时表示禁用限制。此限制适用于所有前端,更改立即生效。该值以每秒发送至 SSL 栈的会话数为单位,应用于握手之前,以防止对握手机制的滥用。

set server <backend>/<server> addr <ip4 or ip6 address> [port <port>]

set server <backend>/<server> addr <ip4 or ip6 address> [port <port>]

将服务器的当前 IP 地址替换为所提供的地址。可选地,使用 ‘port’ 参数更改端口。请注意,更改端口还支持端口映射的切换(使用 +X 或 -Y 表示),但前提是已为健康检查配置了端口。

set server <backend>/<server> agent [ up | down ]

set server <backend>/<server> agent [ up | down ]

强制将服务器的代理状态切换至新状态。此操作可用于立即更改服务器状态,例如在某些代理检查响应较慢时。请注意,若存在跟踪服务器,该变更将被传播至跟踪服务器。

set server <backend>/<server> agent-addr <addr> [port <port>]

set server <backend>/<server> agent-addr <addr> [port <port>]

更改服务器代理检查的地址。允许在运行时将代理检查迁移到另一个地址。

可同时指定 IP 地址和主机名,将自动解析。可选地,更改代理检查的端口。

set server <backend>/<server> agent-port <port>

set server <backend>/<server> agent-port <port>

更改用于代理检查的端口。

set server <backend>/<server> agent-send <value>

set server <backend>/<server> agent-send <value>

更改发送至代理检查目标的代理字符串。可在更改服务器地址时更新字符串,以保持两者一致。

set server <backend>/<server> health [ up | stopping | down ]

set server <backend>/<server> health [ up | stopping | down ]

强制将服务器的健康状态更改为新状态。此操作可用于立即切换服务器状态,例如在某些健康检查响应较慢时。请注意,若存在跟踪服务器,该变更将被传播至跟踪服务器。

set server <backend>/<server> check-addr <ip4 | ip6> [port <port>]

set server <backend>/<server> check-addr <ip4 | ip6> [port <port>]

更改用于服务器健康检查的 IP 地址。可选地,更改用于服务器健康检查的端口。

set server <backend>/<server> check-port <port>

set server <backend>/<server> check-port <port>

将健康检查使用的端口更改为 <port>

set server <backend>/<server> state [ ready | drain | maint ]

set server <backend>/<server> state [ ready | drain | maint ]

强制将服务器的管理状态更改为新状态。此操作可用于禁用负载均衡和/或向服务器发送任何流量。将状态设为“ready”可使服务器进入正常模式,该命令等同于“enable server”命令。将状态设为“maint”不仅会阻止向服务器发送任何流量,还会禁用所有健康检查。此操作等同于“disable server”命令。将模式设为“drain”仅会将服务器从负载均衡中移除,但仍允许对其进行健康检查,并接受新的持久连接。若存在跟踪服务器,更改将传播至这些服务器。

set server <backend>/<server> weight <weight>[%]

set server <backend>/<server> weight <weight>[%]

将服务器的权重更改为参数中传入的值。这与下方的“set weight”命令完全等效。

set server <backend>/<server> fqdn <FQDN>

set server <backend>/<server> fqdn <FQDN>

更改服务器的完全限定域名(FQDN)为参数中传入的值。这要求为该服务器配置并启用了内部运行时 DNS 解析器。

set server <backend>/<server> ssl [ on | off ] (deprecated)

set server <backend>/<server> ssl [ on | off ]  (deprecated)

此选项用于配置向服务器发起连接时的 SSL 加密。关闭时,所有流量将变为明文传输;健康检查路径保持不变。

此命令已弃用,请改用“add server”命令动态创建服务器,支持启用或不启用 SSL。

set severity-output [ none | number | string ]

set severity-output [ none | number | string ]

更改当前会话期间统计套接字输出的严重性格式。

set ssl ca-file <cafile> <payload>

set ssl ca-file <cafile> <payload>

本命令属于事务系统的一部分,可能需要使用“commit ssl ca-file”和“abort ssl ca-file”命令。若当前无正在进行的事务,该命令将创建一个 CA 文件树条目,用于存储负载中包含的证书。该 CA 文件条目不会被保存至 CA 文件树,仅在临时事务中保留。若已存在同名事务,先前的 CA 文件条目将被删除,并由新条目替换。完成修改后,必须通过“commit ssl ca-file”调用提交事务。若需分别添加多个证书,可使用“add ssl ca-file”命令。

示例:

echo -e "set ssl ca-file cafile.pem <<\n$(cat rootCA.crt)\n" | \
socat /var/run/haproxy.stat -
echo "commit ssl ca-file cafile.pem" | socat /var/run/haproxy.stat -

set ssl cert <filename> <payload>

set ssl cert <filename> <payload>

此命令属于事务系统的一部分,“commit ssl cert” 和 “abort ssl cert” 命令可能需要使用。该事务系统适用于 “show ssl cert” 命令所显示的任意证书,即适用于任意前端或后端证书。若当前无进行中的事务,系统将把证书 <filename> 在内存中复制一份至临时事务,随后使用载荷中的 PEM 文件更新该事务。若存在同名文件的事务,系统将更新该事务。也可对与证书关联的文件(如 .issuer、.sctl、.oscp 等)进行更新。完成修改后,必须执行 “commit ssl cert” 以提交事务。

通过 CLI 注入文件时必须谨慎,因为空行用于通知负载的结束。建议注入已清理过的 PEM 文件。一种简单的方法是删除所有空行,仅保留 PEM 段中的内容。可使用 sed 命令实现。

示例:

# With some simple sanitizing
 echo -e "set ssl cert localhost.pem <<\n$(sed -n '/^$/d;/-BEGIN/,/-END/p' 127.0.0.1.pem)\n" | \
 socat /var/run/haproxy.stat -

 # Complete example with commit
 echo -e "set ssl cert localhost.pem <<\n$(cat 127.0.0.1.pem)\n" | \
 socat /var/run/haproxy.stat -
 echo -e \
 "set ssl cert localhost.pem.issuer <<\n $(cat 127.0.0.1.pem.issuer)\n" | \
 socat /var/run/haproxy.stat -
 echo -e \
 "set ssl cert localhost.pem.ocsp <<\n$(base64 -w 1000 127.0.0.1.pem.ocsp)\n" | \
 socat /var/run/haproxy.stat -
 echo "commit ssl cert localhost.pem" | socat /var/run/haproxy.stat -

set ssl crl-file <crlfile> <payload>

set ssl crl-file <crlfile> <payload>

本命令属于事务系统的一部分,可能需要使用“commit ssl crl-file”和“abort ssl crl-file”命令。若当前无正在进行的事务,该命令将创建一个 CRL 文件树条目,用于存储载荷中的吊销列表。该 CRL 文件条目不会被保存至 CRL 文件树,而仅保留在临时事务中。若已存在同名的事务,先前的 CRL 文件条目将被删除,并由新条目替换。完成修改后,必须通过调用“commit ssl crl-file”提交事务。

示例:

echo -e "set ssl crl-file crlfile.pem <<\n$(cat rootCRL.pem)\n" | \
socat /var/run/haproxy.stat -
echo "commit ssl crl-file crlfile.pem" | socat /var/run/haproxy.stat -

set ssl ech <bind> <payload>

set ssl ech <bind> <payload>

使用此密钥替换绑定行中的 ECH 密钥。负载必须以 ECH 格式的 PEM 格式提供。 (https://datatracker.ietf.org/doc/html/draft-farrell-tls-pemesni )

绑定行格式为 <frontend>/@<filename>:<linenum>(例如:frontend1/@HAProxy.conf:19),或 <frontend>/<name>(若绑定行使用了 “name” 关键字命名)。

必须使用支持 ECH 的 OpenSSL 版本,且 HAProxy 必须以 USE_ECH=1 编译。 该命令仅在以实验模式运行的 CLI 连接中受支持(参见“experimental-mode on”)。

另请参见配置手册 第 5.1 节 中的 “show ssl ech”、“add ssl ech” 和 “ech”。

$ openssl ech -public_name foobar.com -out foobar3.com.ech
$ echo -e "experimental-mode on;
           set ssl ech frontend1/@haproxy.conf:19 <<%EOF%&#92;n$(cat foobar3.com.ech)&#92;n%EOF%&#92;n" | &#92;
  socat /tmp/haproxy.sock -
set new ECH configs for frontend1/@haproxy.conf:19

set ssl ocsp-response <response | payload>

set ssl ocsp-response <response | payload>

此命令用于更新证书的 OCSP 响应(参见 “bind” 行中的 “crt”)。执行的控制操作与初始加载响应时相同。<response> 必须以 Base64 编码的 DER 格式响应字符串形式传递,该响应来自 OCSP 服务器。此命令不支持 BoringSSL。

示例:

openssl ocsp -issuer issuer.pem -cert server.pem \
             -host ocsp.issuer.com:80 -respout resp.der
echo "set ssl ocsp-response $(base64 -w 10000 resp.der)" | \
             socat stdio /var/run/haproxy.stat

using the payload syntax:
echo -e "set ssl ocsp-response <<\n$(base64 resp.der)\n" | \
             socat stdio /var/run/haproxy.stat

set ssl tls-key <id> <tlskey>

set ssl tls-key <id> <tlskey>

为 <id> 监听器设置下一个 TLS 密钥为 <tlskey>。该密钥将成为最终密钥,倒数第二密钥用于加密(其余密钥仅用于解密)。最旧的 TLS 密钥将被覆盖。<id> 为数值 #<id> 或由 “show tls-keys” 返回的 <file>。<tlskey> 为经过 base64 编码的 48 位或 80 位 TLS 会话票据密钥(例如:OpenSSL rand 80 | OpenSSL base64 -A)。

set table <table> key <key> [data.<data_type> <value>]*

set table <table> key <key> [data.<data_type> <value>]*
set table <table> ptr <ptr> [data.<data_type> <value>]*

在表中创建或更新一个粘性表条目。若键不存在,则插入一条新条目。

请参阅第 4.2 段中的 stick-table 以获取 <data_type> 的所有可能取值。最常见用法是动态添加源 IP 地址条目,并在 gpc0 中设置标志,以动态屏蔽 IP 地址或影响其服务质量。单次调用中可传递多个 data_type。

可选地,对于现有条目,可使用指针查找代替键查找:<ptr> 的格式为 0xffff,且必须与先前执行“show table”命令所返回的地址对应。当因键为空或 CLI 上存在不兼容字符而无法通过键匹配条目时,使用指针匹配条目可能具有实际意义。

如果 data.<data_type> 为数组类型,可以使用 “[]” 访问数组中的特定索引,例如:data.gpt[1]

set timeout cli <delay>

set timeout cli <delay>

更改当前连接的 CLI 接口超时时间。在需要长时间调试会话且用户需持续检查某些指标而不被断开连接时,此功能非常有用。延迟时间以秒为单位指定。

set var <name> <expression>

set var <name> <expression>
set var <name> expr <expression>
set var <name> fmt <format>

允许使用表达式 <expression> 或格式字符串 <format> 的结果来设置或覆盖进程级变量 ’name’。仅可使用进程级变量,因此名称必须以 ‘proc.’ 开头,否则不会设置任何变量。<expression> 和 <format> 仅可包含“内部”样本提取关键字和转换器,尽管最可能有用的通常是 str(‘something’)、int()、简单字符串或对其他变量的引用。请注意,命令行解析器不识别引号,因此表达式中的任何空格必须以反斜杠转义。该命令需要“operator”或“admin”级别权限。该命令仅在以实验模式运行的 CLI 连接上受支持(参见“experimental-mode on”)。

set weight <backend>/<server> <weight>[%]

set weight <backend>/<server> <weight>[%]

将服务器的权重更改为参数中传入的值。若该值以百分号(%)结尾,则新权重将相对于初始配置的权重计算。绝对权重允许的范围为 0 至 256。相对权重必须为正数,且最终计算出的绝对权重上限为 256。属于运行静态负载均衡算法的服务器组的服务器具有更严格的限制,因为权重一旦设定便不可更改。因此,对于此类服务器,仅接受的值为 0 和 100%(或 0 和初始权重)。更改立即生效,但某些负载均衡算法需要一定数量的请求后才会考虑权重变化。该命令的典型用法是在更新期间将服务器权重设为 0 以禁用它,更新完成后将其权重恢复为 100% 以重新启用。此命令受限制,仅可在配置为“admin”级别的套接字上执行。后端和服务器均可通过名称或其数值 ID 指定,数值 ID 前需加井号(#)。

show acl [[@<ver>] <acl>]

show acl [[@<ver>] <acl>]

显示关于 ACL 转换器的信息。若未指定参数,将返回所有可用 ACL 的列表。若指定 <acl>,则输出其内容。<acl> 为 #<id> 或 <name>。默认情况下显示 ACL 的当前版本(即当前用于匹配并作为 ‘curr_ver’ 在 ACL 列表中报告的版本)。可通过在 ACL 标识符前添加 @<ver> 来选择输出其他版本。版本号作为过滤器使用,不存在的版本将不返回任何结果。输出格式与映射(map)相同,即使对于样本值(sample value)也是如此。返回的数据并非可用 ACL 的列表,而是构成任意 ACL 的所有模式(pattern)的列表。其中许多模式可与映射(map)共享。’entry_cnt’ 值表示 ACL 条目总数,不仅包括激活的条目,还包含当前正在添加的条目。

show anon

show anon

显示匿名模式的当前状态(启用或禁用)以及当前会话的密钥。

show backend

show backend

转储运行进程中的可用后端列表

show cli level

show cli level

显示当前 CLI 会话的 CLI 级别。结果可能是 ‘admin’、‘operator’ 或 ‘user’。 参见 ‘operator’ 和 ‘user’ 命令。

示例:

$ socat /tmp/sock1 readline
prompt
> operator
> show cli level
operator
> user
> show cli level
user
> operator
Permission denied

operator

operator

将当前 CLI 会话的 CLI 级别降低至 operator。该级别无法提升。同时会退出 expert 和 experimental 模式。参见“show cli level”。

unpublish backend <backend>

unpublish backend <backend>

将后端标记为未来流量选择中不可用。实际上,引用该后端的 use_backend / default_backend 规则将被忽略,继续评估后续的内容切换规则。与禁用的后端不同,服务器的健康检查仍保持激活状态。该命令受限制,仅可在配置为“operator”或“admin”级别的套接字上执行。

user

user

将当前 CLI 会话的级别降低至 user。该级别无法提升。同时会退出 expert 和 experimental 模式。参见“show cli level”。

show activity [-1 | 0 | thread_num]

show activity [-1 | 0 | thread_num]

报告有关内部事件的一些计数器,有助于开发者以及对 HAProxy 有足够了解、能够缩小异常行为报告原因的人员。典型示例为一个正常运行的进程从未休眠且持续占用 100% 的 CPU。输出字段将按每项指标一行组织,同一行内包含各线程的计数器。这些计数器为 32 位,将在进程生命周期内发生溢出,但由于该命令的调用通常会执行两次,因此不会造成问题。字段未被正式文档化,以确保其确切含义在计数器被更新的代码中得到验证。这些值也会被 “clear counters” 命令重置。在多线程部署中,第一列将显示所有线程的总和(或平均值,视指标性质而定),所有线程的值将以方括号形式按线程顺序列出。可选地,可在参数中指定要转储的线程编号。特殊值 “0” 将报告聚合值(第一列),而 “-1”(默认值)将显示所有列。请注意,与单线程模式一样,当仅请求单列时,将不显示方括号。

show cli sockets

show cli sockets

列出 CLI 套接字。输出格式由三个以空格分隔的字段组成。第一个字段为套接字地址,可以是 Unix 套接字、IPv4 地址:端口对或 IPv6 地址。其他类型的套接字不会被输出。第二个字段描述套接字的级别:‘admin’、‘user’ 或 ‘operator’。第三个字段列出套接字绑定的进程,字段间以逗号分隔,可以是进程编号或 ‘all’。

示例:

$ echo 'show cli sockets' | socat stdio /tmp/sock1
# socket lvl processes
/tmp/sock1 admin all
127.0.0.1:9999 user 2,3,4
127.0.0.2:9969 user 2
[::1]:9999 operator 2

show cache

show cache

列出已配置的缓存及其各自缓存树中存储的对象。

$ echo ‘show cache’ | socat stdio /tmp/sock1 0x7f6ac6c5b03a: foobar (shctx:0x7f6ac6c5b000, available blocks:3918) 1 2 3 4

  1. 指向缓存结构的指针
  2. 缓存名称
  3. 指向 mmap 区域的指针(shctx)
  4. shctx 中可用于重用的块数量

0x7f6ac6c5b4cc 哈希值:286881868 变化值:0x0011223344556677 大小:39114(39 个块),引用计数:9,过期时间:237 1 2 3 4 5 6 7

  1. 缓存条目的指针
  2. 哈希值的前 32 位
  3. 在使用 vary 时,条目的二级哈希值
  4. 对象大小,单位为字节
  5. 用于该对象的块数量
  6. 正在使用该条目的事务数量
  7. 过期时间,若已过期则可能为负值

show dev

show dev

本命令旨在集中提供 HAProxy 开发者可能需要的部分信息,以便更深入理解特定问题的成因。该命令通常对用户无实际帮助,但这些信息有助于开发者排除某些假设。输出格式大致为一系列段,每段包含缩进的多行内容,每行一个元素,例如操作系统类型与版本、CPU 类型或启动时的文件描述符限制等。为避免重复或输出污染,某些无实际价值的字段(如“无限制”值)将被省略。未来可能新增更多字段,部分字段也可能发生变化。此输出不适用于脚本解析,不应被视为高度可靠,其主要目的是为可读者节省时间。

从技术上讲,此类信息直接从启动时存储的内部结构中获取,以便在崩溃后也能在核心转储文件中找到。因此,开发者可能会要求在进程正常运行时提前输出相关信息,以便与核心转储中的内容进行对比,或在多次重载之间进行对比(例如,某些限制值可能发生变化)。若启用了匿名化功能,任何可能敏感的值也将被匿名化(例如,节点名称)。

输出示例:

$ socat stdio /tmp/sock1 <<< "show dev"
Platform info
  machine vendor: To be filled by O.E.M
  machine family: Altra
  cpu model: Impl 0x41 Arch 8 Part 0xd0c r3p1
  virtual machine: no
  container: no
  OS name: Linux
  OS release: 6.2.0-36-generic
  OS version: #37~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Mon Oct  9 18:01:07 UTC 2
  OS architecture: aarch64
  node name: 489aaf
Process info
  pid: 1735846
  boot uid: 509
  boot gid: 1002
  fd limit (soft): 1024
  fd limit (hard): 1048576

show env [<name>]

show env [<name>]

转储进程已知的一个或全部环境变量。不带参数时,转储所有变量。带参数时,若该变量存在,则仅转储指定变量;否则输出“变量未找到”。变量以与“env”工具存储或返回相同的格式转储,即“<name>=<value>”。此功能在调试大量使用环境变量的配置文件时尤为有用,可确保其包含预期值。该命令受限制,仅可在配置为“operator”或“admin”级别的套接字上执行。

show errors [<iid>|<proxy>] [request|response]

show errors [<iid>|<proxy>] [request|response]

dump last known HTTP/1.x 请求和响应错误,这些错误由前端和后端收集。若指定 <iid>,则将转储范围限制为 ID 为 <iid> 的前端或后端相关的错误。代理 ID “-1” 将导致所有实例被转储。若指定代理名称,则使用其 ID 作为过滤器。若在代理名称或 ID 后添加 “request” 或 “response”,则仅转储请求或响应错误。此命令受限制,仅可在配置为 “operator” 或 “admin” 级别的套接字上执行。

可能收集的错误包括由协议违规引起的最后一个请求和响应错误,通常源于头字段名称中的无效字符。报告会精确指出具体违反协议的字符。其他重要信息,如错误检测的确切日期、前端和后端名称、服务器名称(如已知)、内部事务 ID 以及发起会话的源地址,也会一并报告。

所有字符均被返回,不可打印字符会被编码。最常见的字符(\t = 9,\n = 10,\r = 13 以及 \e = 27)以反斜杠后接一个字母的形式进行编码。反斜杠本身编码为 ‘\\’,以避免混淆。其他不可打印字符则编码为 ‘\xNN’,其中 NN 为字符 ASCII 码的两位十六进制表示。

每行前缀为该行首个字符在缓冲区中的位置,起始位置为 0。每行最多输出一条输入行,过长的行将被拆分为多个连续的输出行,确保输出宽度不超过 79 个字符。若某行被拆分,可通过其不以 ‘\n’ 结尾,且下一行偏移量前带有 ‘+’ 符号来判断,该符号表示当前行是前一行的续行。

示例:

    $ echo "show errors -1 response" | socat stdio /tmp/sock1
>>> [04/Mar/2009:15:46:56.081] backend http-in (#2): invalid response
      src 127.0.0.1, session #54, frontend fe-eth0 (#1), server s2 (#1)
      response length 213 bytes, error at position 23:

      00000  HTTP/1.0 200 OK\r\n
      00017  header/bizarre:blah\r\n
      00038  Location: blah\r\n
      00054  Long-line: this is a very long line which should b
      00104+ e broken into multiple lines on the output buffer,
      00154+  otherwise it would be too large to print in a ter
      00204+ minal\r\n
      00211  \r\n

In the example above, we see that the backend "http-in" which has internal
ID 2 has blocked an invalid response from its server s2 which has internal
ID 1. The request was on transaction 54 (called "session" here) initiated
by source 127.0.0.1 and received by frontend fe-eth0 whose ID is 1. The
total response length was 213 bytes when the error was detected, and the
error was at byte 23. This is the slash ('/') in header name
"header/bizarre", which is not a valid HTTP character for a header name.

show events [<sink>] [-w] [-n] [-0]

show events [<sink>] [-w] [-n] [-0]

不带选项时,列出所有已知事件接收端及其类型。带选项时,若接收端类型为缓冲区,则会转储该接收端中所有可用事件。若在接收端名称后传递选项 “-w”,则在到达缓冲区末尾后,命令将等待新事件并显示它们。可通过输入任意内容(该内容将被丢弃)或关闭会话来终止操作。选项 “-n” 用于直接定位到缓冲区末尾,通常与 “-w” 配合使用,以仅报告新事件。为方便起见,可使用 “-wn” 或 “-nw” 一次性启用上述两个选项。默认情况下,所有事件以换行符(’\n’ 或 10 或 0x0A)分隔。可通过传递 “-0” 参数将其更改为 NUL 字符(’\0’ 或 0)。

show fd [-!plcfbsd]* [[<tgid>]/[<fd>] | <fd>]

show fd [-!plcfbsd]* [[<tgid>]/[<fd>] | <fd>]

dump 所有打开的文件描述符列表,或仅输出指定编号 <fd> 的文件描述符。格式 “<tgid>/<fd>” 也允许使用,任一侧可为空以作为通配符(例如 “/<fd>” 表示跨线程组的 fd <fd>,"<tgid>/” 表示 <tgid> 的所有文件描述符)。目前 <tgid> 会被解析但被忽略,待未来支持按线程组的文件描述符表时再启用。可选择性地传入一组标志,以限制仅输出特定类型的文件描述符,或排除特定类型。当遇到 ‘-’ 或 ‘!’ 时,后续字符的选择将被反转,且每次以空格分隔的参数词前都会重置反转状态。可选的文件描述符类型包括:‘p’ 表示管道,’l’ 表示监听器,‘c’ 表示连接(任意类型),‘f’ 表示前端连接,‘b’ 表示后端连接(任意类型),’s’ 表示到服务器的连接,’d’ 表示到“分发”地址或后端透明地址的连接。通过此方式,‘b’ 是 ‘sd’ 的快捷方式,‘c’ 是 ‘fb’ 或 ‘fsd’ 的快捷方式。‘c!f’ 等价于 ‘b’(即“除前端连接外的所有连接”确实为后端连接)。该功能仅面向需要观察内部状态以排查复杂问题(如异常 CPU 使用率)的开发者。每行报告一个文件描述符,每行中其在多路复用器中的状态以大写字母表示启用的标志,小写字母表示禁用的标志,使用 “P” 表示“已轮询”,“R” 表示“就绪”,“A” 表示“活跃”,事件状态使用 “H” 表示“挂起”,“E” 表示“错误”,“O” 表示“输出”,“P” 表示“优先级”,“I” 表示“输入”,其他若干标志如 “N” 表示“新”(刚加入文件描述符缓存),“U” 表示“已更新”(在文件描述符缓存中收到更新),“L” 表示 “linger_risk”,“C” 表示“克隆”,随后是缓存条目位置、内部所有者指针、I/O 回调指针及其名称(如已知)。当所有者为连接时,报告连接标志及目标(前端、代理或服务器)。当所有者为监听器时,报告监听器状态及其前端。使用此命令前必须对内部结构有充分了解。请注意,输出格式可能随时间变化,因此不应由设计为长期稳定的工具解析该输出。某些内部结构状态可能对列出它们的函数而言显得可疑,此时输出行将附加感叹号(’!’)。这有助于在诊断事件时找到切入点。

show info [typed|json] [desc] [float]

show info [typed|json] [desc] [float]

在当前进程上转储 HAProxy 状态相关信息。若传入可选参数 “typed”,还将输出字段编号、名称和类型,以便外部监控产品能够轻松检索、可能聚合后报告其未知字段中的信息。每个字段单独占一行。若传入可选参数 “json”,则 “typed” 输出的信息将以 JSON 格式提供,作为 JSON 对象列表。默认格式仅包含由冒号(’:’)分隔的两列,左侧为字段名,右侧为值。请注意,在类型化输出格式中,单个对象的转储是连续的,因此消费者无需一次性存储全部内容。若传入可选参数 “float”,部分通常以整数形式输出的字段可能切换为浮点数以提高精度。具体哪些字段受影响未明确指定,因为这可能随时间变化。使用此选项意味着消费者能够处理浮点数。输出格式使用 sprintf("%f”)。

使用类型化输出格式时,每行由四个以冒号(’:’)分隔的列组成。第一列是一个由点号(.)分隔的三元素序列。第一个元素是字段在列表中的数值位置(从零开始)。该位置不应随时间变化,但根据构建选项或未来字段被删除的情况,可能出现空缺。第二个元素是字段名称,其形式与默认的 “show info” 输出中显示的一致。第三个元素是相对进程编号,从 1 开始。

该行中第一个冒号之后的内容遵循上方段落所述的“类型化输出格式”。简而言之,第二个字段(第一个冒号之后)表示变量的来源、性质和作用域。第三个字段表示字段类型,包括 “s32”、“s64”、“u32”、“u64” 和 “str”。第四个字段为值本身,消费者可根据第三列的类型信息进行解析,并根据第二列的信息进行处理。

因此,类型化模式下的整体行格式为:

<field_pos>.<field_name>.<process_num>:<tags>:<type>:<value>

当命令后附加 “desc” 时,会在指标后附加一个额外的冒号及一个被引号括起的字符串,用于描述该指标。截至本文撰写时,此功能仅支持 “typed” 和默认输出格式。

示例:

> show info
Name: HAProxy
Version: 1.7-dev1-de52ea-146
Release_date: 2016/03/11
Nbproc: 1
Process_num: 1
Pid: 28105
Uptime: 0d 0h00m04s
Uptime_sec: 4
Memmax_MB: 0
PoolAlloc_MB: 0
PoolUsed_MB: 0
PoolFailed: 0
(...)

> show info typed
0.Name.1:POSV:str:HAProxy
1.Version.1:POSV:str:3.1-dev0-7c653d-2466
2.Release_date.1:POSV:str:2025/07/01
3.Nbthread.1:CGSV:u32:1
4.Nbproc.1:CGSV:u32:1
5.Process_num.1:KGPV:u32:1
6.Pid.1:SGPV:u32:638069
7.Uptime.1:MDPV:str:0d 0h00m07s
8.Uptime_sec.1:MDPV:u32:7
9.Memmax_MB.1:CLPV:u32:0
10.PoolAlloc_MB.1:MGPV:u32:0
11.PoolUsed_MB.1:MGPV:u32:0
12.PoolFailed.1:MCPV:u32:0
(...)

在类型化格式中,第一列末尾的进程 ID 使得从多个进程获取的输出能够非常方便地进行视觉聚合。示例:

$ ( echo show info typed | socat /var/run/haproxy.sock1;    \
    echo show info typed | socat /var/run/haproxy.sock2 ) |  \
  sort -t . -k 1,1n -k 2,2 -k 3,3n
0.Name.1:POS:str:HAProxy
0.Name.2:POS:str:HAProxy
1.Version.1:POS:str:1.7-dev1-868ab3-148
1.Version.2:POS:str:1.7-dev1-868ab3-148
2.Release_date.1:POS:str:2016/03/11
2.Release_date.2:POS:str:2016/03/11
3.Nbproc.1:CGS:u32:2
3.Nbproc.2:CGS:u32:2
4.Process_num.1:KGP:u32:1
4.Process_num.2:KGP:u32:2
5.Pid.1:SGP:u32:30120
5.Pid.2:SGP:u32:30121
6.Uptime.1:MDP:str:0d 0h01m28s
6.Uptime.2:MDP:str:0d 0h01m28s
(...)

JSON 输出格式的定义详见其模式,可使用命令 “show schema json” 输出该模式。

JSON 输出中不包含额外的空白字符,以减少输出体积。如需人工阅读,可通过格式化工具处理输出以提高可读性。示例:

$ echo “show info json” | socat /var/run/haproxy.sock stdio | \ python -m json.tool

JSON 输出中不包含额外的空白字符,以减少输出体积。如需人工阅读,可通过格式化工具处理输出以提高可读性。示例:

$ echo “show info json” | socat /var/run/haproxy.sock stdio | \ python -m json.tool

show libs

show libs

输出已加载的共享动态库和目标文件列表,仅在支持该功能的系统上可用。当可用时,每个共享对象将显示其虚拟地址范围、大小以及路径。例如,可用于尝试估算某函数由哪个库提供。请注意,在许多系统上,每次重启后地址会发生变化(地址空间随机化),因此若需用于分析核心转储文件,该列表应在启动时获取。此命令仅可在配置为“operator”或“admin”级别的套接字上执行。请注意,输出格式可能因操作系统、架构甚至 HAProxy 版本而异,不应在脚本中依赖该格式。

show map [[@<ver>] <map>]

show map [[@<ver>] <map>]

显示关于映射转换器的信息。若未指定参数,将返回所有可用映射的列表。若指定 <map>,则输出其内容。<map> 为 #<id> 或 <name>。默认情况下显示映射的当前版本(即当前用于匹配并作为 ‘curr_ver’ 在映射列表中报告的版本)。可通过在映射标识符前添加 @<ver> 来选择输出其他版本。版本号作为过滤器使用,不存在的版本将仅返回无结果。’entry_cnt’ 值表示映射中所有条目的总数,而不仅限于激活状态的条目,因此也包含当前正在添加的条目。

输出中,第一列为唯一条目标识符,可用于“del map”和“set map”操作的引用。第二列为模式,第三列为样本(如可用)。返回的数据并非直接列出所有可用映射,而是列出构成任意映射的所有模式。其中许多模式可与 ACL 共享。

show peers [dict|-] [<peers section>]

show peers [dict|-] [<peers section>]

dump 有关“peers”段中配置的对等节点的信息。若未指定参数,将列出所有“peers”段中的对等节点。若指定 <peers section>,则仅输出属于该“peers”段的对等节点信息。若在对等节点段名称前指定“dict”,还将 dump 整个 Tx/Rx 字典缓存(数据量极大)。若对等节点段名为“dict”,可能需要传入“-”以正确输出。

以下是两个输出示例,其中 hostA、hostB 和 hostC 对等节点属于 “sharedlb” 对等节点段。仅 hostA 和 hostB 已建立连接。仅 hostA 向 hostB 发送了数据。

$ echo “show peers” | socat - /tmp/hostA 0x55deb0224320: [15/Apr/2019:11:28:01] id=sharedlb state=0 flags=0x3 \ resync_timeout=<PAST> task_calls=45122 0x55deb022b540: id=hostC(remote) addr=127.0.0.12:10002 status=CONN \ reconnect=4s confirm=0 flags=0x0 0x55deb022a440: id=hostA(local) addr=127.0.0.10:10000 status=NONE \ reconnect=<NEVER> confirm=0 flags=0x0 0x55deb0227d70: id=hostB(remote) addr=127.0.0.11:10001 status=ESTA reconnect=2s confirm=0 flags=0x20000200 appctx:0x55deb028fba0 st0=7 st1=0 task_calls=14456 \ state=EST xprt=RAW src=127.0.0.1:37257 addr=127.0.0.10:10000 remote_table:0x55deb0224a10 id=stkt local_id=1 remote_id=1 last_local_table:0x55deb0224a10 id=stkt local_id=1 remote_id=1 shared tables:

0x55deb0224a10 local_id=1 remote_id=1 flags=0x0 remote_data=0x65
  last_acked=0 last_pushed=3 last_get=0 teaching_origin=0 update=3
  table:0x55deb022d6a0 id=stkt update=3 localupdate=3 \
    commitupdate=3 syncing=0

$ echo “show peers” | socat - /tmp/hostB 0x55871b5ab320: [15/Apr/2019:11:28:03] id=sharedlb state=0 flags=0x3 \ resync_timeout=<PAST> task_calls=3 0x55871b5b2540: id=hostC(remote) addr=127.0.0.12:10002 status=CONN \ reconnect=3s confirm=0 flags=0x0 0x55871b5b1440: id=hostB(local) addr=127.0.0.11:10001 status=NONE \ reconnect=<NEVER> confirm=0 flags=0x0 0x55871b5aed70: id=hostA(remote) addr=127.0.0.10:10000 status=ESTA \ reconnect=2s confirm=0 flags=0x20000200 appctx:0x7fa46800ee00 st0=7 st1=0 task_calls=62356 \ state=EST remote_table:0x55871b5ab960 id=stkt local_id=1 remote_id=1 last_local_table:0x55871b5ab960 id=stkt local_id=1 remote_id=1 shared tables:

0x55871b5ab960 local_id=1 remote_id=1 flags=0x0 remote_data=0x65
  last_acked=3 last_pushed=0 last_get=3 teaching_origin=0 update=0
  table:0x55871b5b46a0 id=stkt update=1 localupdate=0 \
    commitupdate=0 syncing=0

show pools [byname|bysize|byusage] [detailed] [match <pfx>] [<nb>]

show pools [byname|bysize|byusage] [detailed] [match <pfx>] [<nb>]

dump 内部内存池状态。当怀疑存在内存泄漏时,此功能有助于追踪内存使用情况。其行为与在前台运行时发送 SIGQUIT 信号完全相同,但不会刷新内存池。输出默认不排序。若指定 “byname”,则按池名称排序;若指定 “bysize”,则按项目大小降序排序;若指定 “byusage”,则按总使用量降序排序,且仅显示已使用的条目。也可通过指定 <nb> 限制输出仅显示前若干条目(例如按使用量排序时)。还可通过指定 “detailed” 输出更多内部详情,包括所有已合并池的列表。最后,若指定 “match” 并后接前缀,则仅显示名称以该前缀开头的池。报告的总和仅针对符合筛选条件的池。示例:

$ socat - /tmp/haproxy.sock <<< "show pools match quic byusage"
Dumping pools usage. Use SIGQUIT to flush them.
  - Pool quic_conn_r (65560 bytes): 1337 allocated (87653720 bytes), ...
  - Pool quic_crypto (1048 bytes): 6685 allocated (7005880 bytes), ...
  - Pool quic_conn (4056 bytes): 1337 allocated (5422872 bytes), ...
  - Pool quic_rxbuf (262168 bytes): 8 allocated (2097344 bytes), ...
  - Pool quic_conne (184 bytes): 9359 allocated (1722056 bytes), ...
  - Pool quic_frame (184 bytes): 7938 allocated (1460592 bytes), ...
  - Pool quic_tx_pac (152 bytes): 6454 allocated (981008 bytes), ...
  - Pool quic_tls_ke (56 bytes): 12033 allocated (673848 bytes), ...
  - Pool quic_rx_pac (408 bytes): 1596 allocated (651168 bytes), ...
  - Pool quic_tls_se (88 bytes): 6685 allocated (588280 bytes), ...
  - Pool quic_cstrea (88 bytes): 4011 allocated (352968 bytes), ...
  - Pool quic_tls_iv (24 bytes): 12033 allocated (288792 bytes), ...
  - Pool quic_dgram (344 bytes): 732 allocated (251808 bytes), ...
  - Pool quic_arng (56 bytes): 4011 allocated (224616 bytes), ...
  - Pool quic_conn_c (152 bytes): 1337 allocated (203224 bytes), ...
Total: 15 pools, 109578176 bytes allocated, 109578176 used ...

show profiling [{all | status | tasks | memory}] [byaddr|bytime|byctx|aggr|<max_lines>]*

show profiling [{all | status | tasks | memory}] [byaddr|bytime|byctx|aggr|<max_lines>]*

以每行一个的方式输出当前的性能分析设置,以及用于修改这些设置的命令。 当启用任务性能分析时,调度器收集的部分函数级统计信息也将被输出,包括调用次数、总 CPU 时间/平均 CPU 时间以及总延迟/平均延迟的汇总信息。 当启用内存性能分析时,将报告诸如分配/释放次数及其大小等信息。 可通过指定相应关键字,将输出限制为仅性能分析状态、任务信息或内存性能分析信息;默认情况下,所有性能分析信息均会被输出。 还可通过指定数值限制,控制每个类别输出的行数。 可请求按地址、总执行时间或调用上下文而非使用频率对输出进行排序,例如便于比较后续调用结果或识别需优化的部分,并可按被调用函数聚合任务活动,而非查看详细信息。 请注意,性能分析本质上面向开发者,用于提示代码中 CPU 周期或内存浪费的位置。该信息对监控无实际用途。

show resolvers [<resolvers section id>]

show resolvers [<resolvers section id>]

转储指定解析器段的统计信息,若未提供段,则转储所有解析器段的统计信息。

针对每个名称服务器,报告以下计数器:

sent: number of DNS requests sent to this server
valid: number of DNS valid responses received from this server
update: number of DNS responses used to update the server's IP address
cname: number of CNAME responses
cname_error: CNAME errors encountered with this server
any_err: number of empty response (IE: server does not support ANY type)
nx: non existent domain response received from this server
timeout: how many time this server did not answer in time
refused: number of requests refused by this server
other: any other DNS errors
invalid: invalid DNS response (from a protocol point of view)
too_big: too big response
outdated: number of response arrived too late (after another name server)

show quic [<format>] [<filter>]

show quic [<format>] [<filter>]

dump info on all active QUIC frontend connections。此命令受限制,仅可在配置为“operator”或“admin”级别的套接字上执行。

可选参数可用于控制输出的详细程度。其值可按不同方式解释。第一种方式是使用预定义值:使用 “oneline” 表示默认格式,使用 “stream” 列出所有活动流,使用 “full” 显示全部信息。另一种方式是指定以逗号分隔的字段列表,以限制输出内容。当前支持的值包括 “tp”、“sock”、“pktns”、“cc” 和 “mux”。最后,若格式中使用 “help”,则会显示更详细的帮助信息。

最后一个参数用于限制或扩展连接列表。默认情况下,仅显示活跃的前端连接。使用额外参数 “clo” 可列出正在关闭的前端连接,使用 “be” 可列出后端连接,使用 “all” 可列出所有类别。也可以通过指定其十六进制地址来限制为单个连接。

show servers conn [<backend>]

show servers conn [<backend>]

转储指定后端(或所有后端,若未指定)中服务器的当前连接和空闲连接状态。可使用后端名称或标识符。

输出包含一行标题,显示字段名称,随后每行对应一个服务器,依次包含后端名称和 ID、服务器名称和 ID、地址、端口以及一系列数值。字段数量随线程数量变化而变化。输出格式在不同版本间及线程数量不同时可能略有差异。提取输出值时,需注意标题行以正确对应列,并留意线程数量,因为最后一列数据为每线程独立值:

bkname/svname         Backend name '/' server name
bkid/svid             Backend ID '/' server ID
addr                  Server's IP address
port                  Server's port (or zero if none)
-                     Unused field, serves as a visual delimiter
purge_delay           Interval between connection purges, in milliseconds
served                Number of connections currently in use
used_cur              Number of connections currently in use
                      note that this excludes conns attached to a session
used_max              Highest value of used_cur since the process started
need_est              Floating estimate of total needed connections
idle_sess             Number of idle connections flagged as private
unsafe_nb             Number of idle connections considered as "unsafe"
safe_nb               Number of idle connections considered as "safe"
idle_lim              Configured maximum number of idle connections
idle_cur              Total of the per-thread currently idle connections
idle_per_thr[NB]      Idle conns per thread for each one of the NB threads

当 <idle_cur> 与 <used_cur> 的总和超过估算值 <need_est> 时,HAProxy 将每隔 <purge_delay> 杀死一部分 <idle_cur>。该估算值会随连接活动情况变化。

由于空闲连接具有线程特性,必须理解的是,某些值在读取后可能发生改变,因此单行内的数据一致性无法保证。此输出主要用于调试,不应常规监控或绘图。

show servers state [<backend>]

show servers state [<backend>]

转储运行配置中发现的服务器状态。可提供后端名称或标识符,以将输出限制为该后端。

转储文件的格式如下:

  • 第一行包含格式版本(本规范中为 1);
  • 第二行包含列标题,以井号(’#’)开头;
  • 第三行及后续行包含数据;
  • 以井号(’#’)开头的每一行均被视为注释。

由于同一输出可能存在多个版本,以下是各文件格式版本对应的字段及其顺序列表:

1:
  be_id:                       Backend unique id.
  be_name:                     Backend label.
  srv_id:                      Server unique id (in the backend).
  srv_name:                    Server label.
  srv_addr:                    Server IP address.
  srv_op_state:                Server operational state (UP/DOWN/...).
                                 0 = SRV_ST_STOPPED
                                   The server is down.
                                 1 = SRV_ST_STARTING
                                   The server is warming up (up but
                                   throttled).
                                 2 = SRV_ST_RUNNING
                                   The server is fully up.
                                 3 = SRV_ST_STOPPING
                                   The server is up but soft-stopping
                                   (eg: 404).
  srv_admin_state:             Server administrative state (MAINT/DRAIN/...).
                               The state is actually a mask of values:
                                 0x01 = SRV_ADMF_FMAINT
                                   The server was explicitly forced into
                                   maintenance.
                                 0x02 = SRV_ADMF_IMAINT
                                   The server has inherited the maintenance
                                   status from a tracked server.
                                 0x04 = SRV_ADMF_CMAINT
                                   The server is in maintenance because of
                                   the configuration.
                                 0x08 = SRV_ADMF_FDRAIN
                                   The server was explicitly forced into
                                   drain state.
                                 0x10 = SRV_ADMF_IDRAIN
                                   The server has inherited the drain status
                                   from a tracked server.
                                 0x20 = SRV_ADMF_RMAINT
                                   The server is in maintenance because of an
                                   IP address resolution failure.
                                 0x40 = SRV_ADMF_HMAINT
                                   The server FQDN was set from stats socket.

  srv_uweight:                 User visible server's weight.
  srv_iweight:                 Server's initial weight.
  srv_time_since_last_change:  Time since last operational change.
  srv_check_status:            Last health check status.
  srv_check_result:            Last check result (FAILED/PASSED/...).
                                 0 = CHK_RES_UNKNOWN
                                   Initialized to this by default.
                                 1 = CHK_RES_NEUTRAL
                                   Valid check but no status information.
                                 2 = CHK_RES_FAILED
                                   Check failed.
                                 3 = CHK_RES_PASSED
                                   Check succeeded and server is fully up
                                   again.
                                 4 = CHK_RES_CONDPASS
                                   Check reports the server doesn't want new
                                   sessions.
  srv_check_health:            Checks rise / fall current counter.
  srv_check_state:             State of the check (ENABLED/PAUSED/...).
                               The state is actually a mask of values:
                                 0x01 = CHK_ST_INPROGRESS
                                   A check is currently running.
                                 0x02 = CHK_ST_CONFIGURED
                                   This check is configured and may be
                                   enabled.
                                 0x04 = CHK_ST_ENABLED
                                   This check is currently administratively
                                   enabled.
                                 0x08 = CHK_ST_PAUSED
                                   Checks are paused because of maintenance
                                   (health only).
  srv_agent_state:             State of the agent check (ENABLED/PAUSED/...).
                               This state uses the same mask values as
                               "srv_check_state", adding this specific one:
                                 0x10 = CHK_ST_AGENT
                                   Check is an agent check (otherwise it's a
                                   health check).
  bk_f_forced_id:              Flag to know if the backend ID is forced by
                               configuration.
  srv_f_forced_id:             Flag to know if the server's ID is forced by
                               configuration.
  srv_fqdn:                    Server FQDN.
  srv_port:                    Server port.
  srvrecord:                   DNS SRV record associated to this SRV.
  srv_use_ssl:                 use ssl for server connections.
  srv_check_port:              Server health check port.
  srv_check_addr:              Server health check address.
  srv_agent_addr:              Server health agent address.
  srv_agent_port:              Server health agent port.

show sess [<options>*]

show sess [<options>*]

转储所有已知的活动流(以前称为“会话”)。在慢速连接上应避免执行此操作,因为输出可能非常庞大。此命令受限制,仅可在配置为“operator”或“admin”级别的套接字上执行。请注意,在连接快速回收的机器上,输出的条目数可能少于实际存在的数量,因为该命令仅转储在输入命令前创建的最后一个流之前的所有现有流;在此期间终止的流将不会显示。有关支持的选项,请参见下文。

show sess [<id> | all | help] [<options>*]

show sess [<id> | all | help] [<options>*]

显示关于匹配流的大量内部信息。该命令支持两种输出格式:一种为简短格式,当未指定特定流标识符时,默认采用此格式;另一种为扩展格式,用于列出指定流时使用。简短格式由默认的 “show sess” 命令使用,每行仅输出一个流,包含少量信息,且流标识符位于行首,以十六进制表示(对应流的指针)。

在扩展形式中,由 “show sess <id>” 或 “show sess all” 使用时,流会以大量调试细节的形式在多行上输出(每流约 20 行),且仍以标识符开头。此处流之间的分隔符为行首的标识符;属于同一流的额外行以一个或多个空格开头(流内容缩进输出)。输出大量流可能导致输出内容极为庞大,耗时较长且对 CPU 消耗较高,因此始终建议仅输出所需最少信息。这些信息对大多数用户无用,但 HAProxy 开发者可将其用于排查复杂问题。确切的输出格式故意未予文档化,以便根据需求自由演进,包括在稳定分支中亦可调整。该输出旨在结合 src/stream.c 中的 strm_dump_to_buffer() 函数的实现进行解读,以明确特定字段的含义。

“help” 参数将显示命令的详细用法,而非转储流。

可以设置某些选项以自定义转储内容或应用过滤器。以下是支持的选项: - backend <b>:仅显示与该后端关联的流 - frontend <f>:仅显示与该前端关联的流 - older <age>:仅显示超过 <age> 秒的流 - server <b/s>:仅显示与该后端+服务器关联的流 - show-uri:转储请求分析过程中捕获的事务 URI。仅在已捕获时显示 - susp:仅显示开发人员根据可能随时间或版本变化的标准判定为可疑的流

show stat [domain <resolvers|proxy>] [{<iid>|<proxy>} <type> <sid>] \

show stat [domain <resolvers|proxy>] [{<iid>|<proxy>} <type> <sid>] \
          [typed|json] [desc] [up|no-maint]

转储统计信息。域用于选择要打印的统计信息;当前可用的有解析器和代理。默认使用 CSV 格式;若在其他参数后传递 “typed”,可启用上文所述的扩展类型化输出格式;若传递 “json”,则使用 JSON 格式。通过传递 <id>、<type> 和 <sid>,可仅转储选定项目:- <iid> 为代理 ID,-1 表示转储全部内容。也可指定代理名称 <proxy>,此时将使用该代理的 ID 作为选择器。- <type> 用于选择可转储对象的类型:1 表示前端,2 表示后端,4 表示服务器,-1 表示全部。这些值可进行按位或操作,例如:

1 + 2     = 3   -> frontend + backend.
1 + 2 + 4 = 7   -> frontend + backend + server.
- `<sid>` is a server ID, -1 to dump everything from the selected proxy.

示例:

    $ echo "show info;show stat" | socat stdio unix-connect:/tmp/sock1
>>> Name: HAProxy
    Version: 1.4-dev2-49
    Release_date: 2009/09/23
    Nbproc: 1
    Process_num: 1
    (...)

    # pxname,svname,qcur,qmax,scur,smax,slim,stot,bin,bout,dreq,  (...)
    stats,FRONTEND,,,0,0,1000,0,0,0,0,0,0,,,,,OPEN,,,,,,,,,1,1,0, (...)
    stats,BACKEND,0,0,0,0,1000,0,0,0,0,0,,0,0,0,0,UP,0,0,0,,0,250,(...)
    (...)
    www1,BACKEND,0,0,0,0,1000,0,0,0,0,0,,0,0,0,0,UP,1,1,0,,0,250, (...)

    $

在此示例中,同时发出了两条命令。这种方式便于在多进程模式下识别统计信息所对应的进程。在类型化输出格式中,无需如此操作,因为每个输出行都会报告进程编号。请注意,信息输出后有一行空行,用于标记第一个数据块的结束。第二个数据块(统计信息)末尾也出现类似的空行,以便读者确认输出未被截断。

当指定 “typed” 时,输出格式更适用于监控工具,因为其提供了数值位置,并标明了每个输出字段的类型。每个值单独占一行,包含进程编号、元素编号、性质、来源和作用域。该格式也可通过在 HTTP 统计信息 URI 后添加 “;typed” 获得。请注意,在 typed 输出格式中,单个对象的转储是连续的,因此消费者无需一次性存储全部数据。

“up” 修饰符将仅列出报告为正常或未检查的服务器。处于关闭、未解析或维护状态的服务器将不会被列出。这与 HTTP 统计信息中的 “;up” 选项类似。类似地,“no-maint” 修饰符将如同 HTTP 中的 “;no-maint” 修饰符,使处于禁用状态的服务器不被列出。区别在于,处于启用状态但已关闭的服务器不会被排除。

使用类型化输出格式时,每行由 4 个以冒号(’:’)分隔的列组成。第一列是由 5 个以点号(’.’)分隔的元素构成的序列。第一个元素是表示所描述对象类型的字母。当前已知的对象类型包括:‘F’ 表示前端,‘B’ 表示后端,‘L’ 表示监听器,‘S’ 表示服务器。第二个元素是表示该对象所属代理的唯一标识符的正整数。该值等同于 CSV 输出中的 “iid” 列,并与前端或后端段中可选的 “id” 指令前的值匹配。第三个元素是表示代理内部唯一对象标识符的正整数,对应于 CSV 输出中的 “sid” 列。在导出前端或后端时,该值报告为 0。对于监听器或服务器,该值对应其在代理内的相应 ID。第四个元素是字段在列表中的数值位置(从零开始)。该位置不应随时间变化,但根据构建选项或未来字段被删除的情况,可能出现空缺。第五个元素是字段名称,其形式与 CSV 输出中的名称一致。第六个元素是正整数,表示从 1 开始的相对进程编号。

该行中第一个冒号之后的内容遵循上方段落所述的“类型化输出格式”。简而言之,第二个字段(第一个冒号之后)表示变量的来源、性质、作用域及持久化状态。第三个字段表示字段类型,包括 “s32”、“s64”、“u32”、“u64”、“flt” 和 “str”。第四个字段为值本身,消费者可根据第三字段的类型信息进行解析,并依据第二字段的信息进行处理。

当命令后附加 “desc” 时,会在指标后附加一个额外的冒号及一个被引号括起的字符串,用于描述该指标。截至本文撰写时,此功能仅支持 “typed” 输出格式。

因此,类型化模式下的整体行格式为:

<obj>.<px_id>.<id>.<fpos>.<fname>.<process_num>:<tags>:<type>:<value>

以下是类型化输出格式的示例:

$ echo "show stat typed" | socat stdio unix-connect:/tmp/sock1
F.2.0.0.pxname.1:KNSV:str:dummy
F.2.0.1.svname.1:KNSV:str:FRONTEND
F.2.0.4.scur.1:MGPV:u32:0
F.2.0.5.smax.1:MMPV:u32:0
F.2.0.6.slim.1:CLPV:u32:524269
F.2.0.7.stot.1:MCPP:u64:0
F.2.0.8.bin.1:MCPP:u64:0
F.2.0.9.bout.1:MCPP:u64:0
F.2.0.10.dreq.1:MCPP:u64:0
F.2.0.11.dresp.1:MCPP:u64:0
F.2.0.12.ereq.1:MCPP:u64:0
F.2.0.17.status.1:SGPV:str:OPEN
F.2.0.26.pid.1:KGPV:u32:1
F.2.0.27.iid.1:KGSV:u32:2
F.2.0.28.sid.1:KGSV:u32:0
F.2.0.32.type.1:CGSV:u32:0
F.2.0.33.rate.1:MRPP:u32:0
F.2.0.34.rate_lim.1:CLPV:u32:0
F.2.0.35.rate_max.1:MMPV:u32:0
F.2.0.46.req_rate.1:MRPP:u32:0
F.2.0.47.req_rate_max.1:MMPV:u32:0
F.2.0.48.req_tot.1:MCPP:u64:0
F.2.0.51.comp_in.1:MCPP:u64:0
F.2.0.52.comp_out.1:MCPP:u64:0
F.2.0.53.comp_byp.1:MCPP:u64:0
F.2.0.54.comp_rsp.1:MCPP:u64:0
(...)

在类型化格式中,第一列末尾的进程 ID 使得从多个进程获取的输出能够非常方便地进行视觉聚合,如下例所示,每行均对应一个进程:

$ ( echo show stat typed | socat /var/run/haproxy.sock1 -; \
    echo show stat typed | socat /var/run/haproxy.sock2 - ) | \
  sort -t . -k 1,1 -k 2,2n -k 3,3n -k 4,4n -k 5,5 -k 6,6n
B.3.0.0.pxname.1:KNSV:str:private-backend
B.3.0.0.pxname.2:KNSV:str:private-backend
B.3.0.1.svname.1:KNSV:str:BACKEND
B.3.0.1.svname.2:KNSV:str:BACKEND
B.3.0.2.qcur.1:MGPV:u32:0
B.3.0.2.qcur.2:MGPV:u32:0
B.3.0.3.qmax.1:MMPV:u32:0
B.3.0.3.qmax.2:MMPV:u32:0
B.3.0.4.scur.1:MGPV:u32:0
B.3.0.4.scur.2:MGPV:u32:0
B.3.0.5.smax.1:MMPV:u32:0
B.3.0.5.smax.2:MMPV:u32:0
B.3.0.6.slim.1:CLPV:u32:1000
B.3.0.6.slim.2:CLPV:u32:1000
(...)

JSON 输出格式的定义详见其模式,可使用命令 “show schema json” 输出该模式。

JSON 输出中不包含额外的空白字符,以减少输出体积。如需人工阅读,可通过格式化工具处理输出以提高可读性。示例:

$ echo “show stat json” | socat /var/run/haproxy.sock stdio | \ python -m json.tool

JSON 输出中不包含额外的空白字符,以减少输出体积。如需人工阅读,可通过格式化工具处理输出以提高可读性。示例:

$ echo “show stat json” | socat /var/run/haproxy.sock stdio | \ python -m json.tool

show ssl ca-file [[*][\]<cafile>[:<index>]]

show ssl ca-file [[*][\]<cafile>[:<index>]]

显示进程加载的 CA 文件列表及其各自的证书数量。证书在状态为“已使用”前不会被任何前端或后端使用。列表中可能出现 “@system-ca” 条目,该条目由 httpclient 默认加载,包含 OpenSSL 返回的系统信任 CA 列表。若文件名前缀为星号,则表示该操作尚未提交。若指定 <cafile> 而未指定 <index>,将显示 CA 文件的状态(“已使用”/“未使用”),随后列出该 CA 文件中包含的所有证书的详细信息。每个证书显示的详细信息与 “show ssl cert” 命令输出一致。若指定 <cafile> 后跟 <index>,则仅显示指定索引的证书详情。索引从 1 开始。若索引无效(例如过大),则不显示任何内容。该命令可用于检查 CA 文件是否已正确更新。也可通过在文件名前加 ‘’ 来查看正在进行中的事务详情。若文件名首字符为 ‘’,可使用 ‘\*’ 进行转义。

示例:

$ echo "show ssl ca-file" | socat /var/run/haproxy.master -
# transaction
*cafile.crt - 2 certificate(s)
# filename
cafile.crt - 1 certificate(s)

$ echo "show ssl ca-file cafile.crt" | socat /var/run/haproxy.master -
Filename: /home/tricot/work/haproxy/reg-tests/ssl/set_cafile_ca2.crt
Status: Used

Certificate #1:
Serial: 11A4D2200DC84376E7D233CAFF39DF44BF8D1211
notBefore: Apr  1 07:40:53 2021 GMT
notAfter: Aug 17 07:40:53 2048 GMT
Subject Alternative Name:
Algorithm: RSA4096
SHA1 FingerPrint: A111EF0FEFCDE11D47FE3F33ADCA8435EBEA4864
Subject: /C=FR/ST=Some-State/O=HAProxy Technologies/CN=HAProxy Technologies CA
Issuer: /C=FR/ST=Some-State/O=HAProxy Technologies/CN=HAProxy Technologies CA

$ echo "show ssl ca-file *cafile.crt:2" | socat /var/run/haproxy.master -
Filename: */home/tricot/work/haproxy/reg-tests/ssl/set_cafile_ca2.crt
Status: Unused

Certificate #2:
Serial: 587A1CE5ED855040A0C82BF255FF300ADB7C8136
[...]

show ssl cert [[*][\]<filename>]

show ssl cert [[*][\]<filename>]

显示已加载到进程中的证书列表。这些证书在状态为“已使用”之前,不会被任何前端或后端使用。若文件名前缀为星号,则表示该证书为尚未提交的事务。若指定文件名,将显示该证书的详细信息。此命令可用于检查证书是否已正确更新。也可通过在文件名前加 ‘’ 来显示事务的详细信息。若文件名首字符为 ‘’,可使用 \* 进行转义。此命令还可通过在文件名后缀 “.ocsp” 扩展名来显示证书的 OCSP 响应详情。该功能对已提交的证书及正在进行的事务均有效。对于已提交的证书,此命令等效于使用证书对应的 OCSP 响应 ID 调用 “show ssl ocsp-response”。

示例:

$ echo "@1 show ssl cert" | socat /var/run/haproxy.master -
# transaction
*test.local.pem
# filename
test.local.pem

$ echo "@1 show ssl cert test.local.pem" | socat /var/run/haproxy.master -
Filename: test.local.pem
Status: Used
Serial: 03ECC19BA54B25E85ABA46EE561B9A10D26F
notBefore: Sep 13 21:20:24 2019 GMT
notAfter: Dec 12 21:20:24 2019 GMT
Issuer: /C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
Subject: /CN=test.local
Subject Alternative Name: DNS:test.local, DNS:imap.test.local
Algorithm: RSA2048
SHA1 FingerPrint: 417A11CAE25F607B24F638B4A8AEE51D1E211477

$ echo "@1 show ssl cert *test.local.pem" | socat /var/run/haproxy.master -
Filename: *test.local.pem
Status: Unused
[...]

$ echo "@1 show ssl cert \*.local.pem" | socat /var/run/haproxy.master -
Filename: *.local.pem
Status: Used
[...]

show ssl crl-file [[*][\]<crlfile>[:<index>]]

show ssl crl-file [[*][\]<crlfile>[:<index>]]

显示已加载到进程中的 CRL 文件列表。这些文件在状态为“已使用”之前,不会被任何前端或后端使用。若文件名前缀为星号,表示该操作尚未提交。若指定 <crlfile> 而未指定 <index>,将显示 CRL 文件的状态(“已使用”/“未使用”),并列出该 CRL 文件中包含的所有吊销列表的详细信息。每个列表的详细信息基于命令 “openssl crl -text -noout -in <file>” 的输出。若指定 <crlfile> 后跟 <index>,则仅显示指定索引的列表详情。索引从 1 开始。若索引无效(例如过大),则不显示任何内容。该命令可用于检查 CRL 文件是否已正确更新。也可以通过在文件名前加 ‘’ 来查看正在进行中的事务的详情。若文件名首字符为 ‘’,可使用 ‘\*’ 进行转义。

示例:

$ echo "show ssl crl-file" | socat /var/run/haproxy.master -
# transaction
*crlfile.pem
# filename
crlfile.pem

$ echo "show ssl crl-file crlfile.pem" | socat /var/run/haproxy.master -
Filename: /home/tricot/work/haproxy/reg-tests/ssl/crlfile.pem
Status: Used

Certificate Revocation List #1:
Version 1
Signature Algorithm: sha256WithRSAEncryption
Issuer: /C=FR/O=HAProxy Technologies/CN=Intermediate CA2
Last Update: Apr 23 14:45:39 2021 GMT
Next Update: Sep  8 14:45:39 2048 GMT
Revoked Certificates:
    Serial Number: 1008
        Revocation Date: Apr 23 14:45:36 2021 GMT

Certificate Revocation List #2:
Version 1
Signature Algorithm: sha256WithRSAEncryption
Issuer: /C=FR/O=HAProxy Technologies/CN=Root CA
Last Update: Apr 23 14:30:44 2021 GMT
Next Update: Sep  8 14:30:44 2048 GMT
No Revoked Certificates.

show ssl crt-list [-n] [<filename>]

show ssl crt-list [-n] [<filename>]

显示 HAProxy 配置中使用的 crt-list 列表和目录列表。若指定文件名,则转储 crt-list 或目录的内容。转储后的输出可作为 crt-list 文件使用。使用 ‘-n’ 选项可显示行号,当与 ‘del ssl crt-list’ 选项配合使用且存在重复条目时尤为有用。使用 ‘-n’ 选项输出的内容不兼容 crt-list 格式,且无法被 HAProxy 加载。

示例:

echo "show ssl crt-list -n localhost.crt-list" | socat /tmp/sock1 -
# localhost.crt-list
common.pem:1 !not.test1.com *.test1.com !localhost
common.pem:2
ecdsa.pem:3 [verify none allow-0rtt ssl-min-ver TLSv1.0 ssl-max-ver TLSv1.3] localhost !www.test1.com
ecdsa.pem:4 [verify none allow-0rtt ssl-min-ver TLSv1.0 ssl-max-ver TLSv1.3]

show ssl ech [<name>]

show ssl ech [<name>]

显示 HAProxy 进程中加载的 ECH 密钥列表。

当指定 <name> 时,显示特定绑定行的键。绑定行格式为 <frontend>/@<filename>:<linenum>(例如:frontend1/@HAProxy.conf:19),或 <frontend>/<name>(若绑定行使用了 “name” 关键字命名)。

‘age’ 条目表示键在绑定行中加载以来经过的时间(单位:秒)。当 HAProxy 启动、重载或重启时,该值将被重置。

必须使用支持 ECH 的 OpenSSL 版本,且 HAProxy 必须以 USE_ECH=1 编译。 该命令仅在以实验模式运行的 CLI 连接中受支持(参见“experimental-mode on”)。

另请参见配置手册中 第 5.1 节 的 “ech”。

示例:

$ echo "experimental-mode on; show ssl ech" | socat /tmp/haproxy.sock -
 ***
 frontend: frontend1

 bind: frontend1/@haproxy.conf:19

 ECH entry: 0 public_name: example.com age: 557 (has private key)
      [fe0d,94,example.com,[0020,0001,0001],c39285b774bf61c071864181c5292a012b30adaf767e39369a566af05573ef2b,00,00]

 ECH entry: 1 public_name: example.com age: 557 (has private key)
      [fe0d,ee,example.com,[0020,0001,0001],6572191131b5cabba819f8cacf2d2e06fa0b87b30d9b793644daba7b8866d511,00,00]

 bind: frontend1/@haproxy.conf:20

 ECH entry: 0 public_name: example.com age: 557 (has private key)
      [fe0d,94,example.com,[0020,0001,0001],c39285b774bf61c071864181c5292a012b30adaf767e39369a566af05573ef2b,00,00]

 ECH entry: 1 public_name: example.com age: 557 (has private key)
      [fe0d,ee,example.com,[0020,0001,0001],6572191131b5cabba819f8cacf2d2e06fa0b87b30d9b793644daba7b8866d511,00,00]

$ echo "experimental-mode on; show ssl ech frontend1/@haproxy.conf:19" | socat /tmp/haproxy.sock -
***
ECH for frontend1/@haproxy.conf:19
ECH entry: 0 public_name: example.com age: 786 (has private key)
      [fe0d,94,example.com,[0020,0001,0001],c39285b774bf61c071864181c5292a012b30adaf767e39369a566af05573ef2b,00,00]

ECH entry: 1 public_name: example.com age: 786 (has private key)
      [fe0d,ee,example.com,[0020,0001,0001],6572191131b5cabba819f8cacf2d2e06fa0b87b30d9b793644daba7b8866d511,00,00]

show ssl jwt

show ssl jwt

显示可用于 JWT 验证的证书列表。参见“add ssl jwt”和“del ssl jwt”命令。有关更多信息,请参见“jwt”证书选项。

示例:

echo "show ssl jwt"  | socat /tmp/sock1 -
#filename
jwt.pem

show ssl ocsp-response [[text|base64] <id|path>]

show ssl ocsp-response [[text|base64] <id|path>]

显示 HAProxy 中所用所有 OCSP 响应对应的 OCSP 树条目 ID,以及对应前端证书的路径、颁发者名称与密钥哈希,以及该 OCSP 响应所针对证书的序列号。若提供有效的 <id> 或有效前端证书的 <path>,则显示对应 OCSP 响应的内容。当提供 <id> 时,可定义数据转储的格式。’text’ 为默认选项,可显示与执行 “openssl ocsp -respin <ocsp-response> -text” 命令时相同的 OCSP 响应详细信息。‘base64’ 格式可将 OCSP 响应内容以 base64 形式转储。

示例:

$ echo "show ssl ocsp-response" | socat /var/run/haproxy.master -
# Certificate IDs
  Certificate ID key: 303b300906052b0e03021a050004148a83e0060faff709ca7e9b95522a2e81635fda0a0414f652b0e435d5ea923851508f0adbe92d85de007a0202100a
  Certificate path: /path_to_cert/foo.pem
    Certificate ID:
      Issuer Name Hash: 8A83E0060FAFF709CA7E9B95522A2E81635FDA0A
      Issuer Key Hash: F652B0E435D5EA923851508F0ADBE92D85DE007A
      Serial Number: 100A

$ echo "show ssl ocsp-response 303b300906052b0e03021a050004148a83e0060faff709ca7e9b95522a2e81635fda0a0414f652b0e435d5ea923851508f0adbe92d85de007a0202100a" | socat /var/run/haproxy.master -
OCSP Response Data:
  OCSP Response Status: successful (0x0)
  Response Type: Basic OCSP Response
  Version: 1 (0x0)
  Responder Id: C = FR, O = HAProxy Technologies, CN = ocsp.haproxy.com
  Produced At: May 27 15:43:38 2021 GMT
  Responses:
  Certificate ID:
    Hash Algorithm: sha1
    Issuer Name Hash: 8A83E0060FAFF709CA7E9B95522A2E81635FDA0A
    Issuer Key Hash: F652B0E435D5EA923851508F0ADBE92D85DE007A
    Serial Number: 100A
  Cert Status: good
  This Update: May 27 15:43:38 2021 GMT
  Next Update: Oct 12 15:43:38 2048 GMT
  [...]

$ echo "show ssl ocsp-response base64 /path_to_cert/foo.pem" | socat /var/run/haproxy.sock -
  MIIB8woBAKCCAewwggHoBgkrBgEFBQcwAQEEggHZMIIB1TCBvqE[...]

show ssl ocsp-updates

show ssl ocsp-updates

显示由 OCSP 更新机制所涉及条目的信息。该命令将为每个 OCSP 响应输出一行,包含响应的预期更新时间、上次成功更新的时间,以及成功和失败更新的计数器。同时,将以数值形式和文本形式提供上次更新的状态(成功或失败)。有关可能错误的完整列表,请参见下文。输出行将按“Next Update”时间升序排列。每行还将包含指向使用该 OCSP 响应的第一个前端证书的路径。有关 OCSP 自动更新的更多信息,请参见“show ssl ocsp-response”命令和“ocsp-update”选项。

更新的错误码和错误字符串可能如下:

  +----+-------------------------------------+
  | ID | message                             |
  +----+-------------------------------------+
  |  0 | "Unknown"                           |
  |  1 | "Update successful"                 |
  |  2 | "HTTP error"                        |
  |  3 | "Missing \"ocsp-response\" header"  |
  |  4 | "OCSP response check failure"       |
  |  5 | "Error during insertion"            |
  +----+-------------------------------------+

示例:

$ echo "show ssl ocsp-updates" | socat /tmp/haproxy.sock -
  OCSP Certid | Path | Next Update | Last Update | Successes | Failures | Last Update Status | Last Update Status (str)
      303b300906052b0e03021a050004148a83e0060faff709ca7e9b95522a2e81635fda0a0414f652b0e435d5ea923851508f0adbe92d85de007a02021015 | /path_to_cert/cert.pem | 30/Jan/2023:00:08:09 +0000 | - | 0 | 1 | 2 | HTTP error
      304b300906052b0e03021a0500041448dac9a0fb2bd32d4ff0de68d2f567b735f9b3c40414142eb317b75856cbae500940e61faf9d8b14c2c6021203e16a7aa01542f291237b454a627fdea9c1 | /path_to_cert/other_cert.pem | 30/Jan/2023:01:07:09 +0000 | 30/Jan/2023:00:07:09 +0000 | 1 | 0 | 1 | Update successful

show ssl providers

show ssl providers

显示 OpenSSL 初始化期间加载的提供者名称。提供者加载确实可通过 OpenSSL 配置文件进行配置,此选项可用于检查是否加载了正确的提供者。该命令仅在 OpenSSL v3 中可用。

示例:

$ echo "show ssl providers" | socat /var/run/haproxy.master -
Loaded providers:
    - fips
    - base

show ssl sni [-f <frontend>] [-A] [-t <offset>]

show ssl sni [-f <frontend>] [-A] [-t <offset>]

dump 指定前端配置的全部 SNI,若未指定前端则 dump 所有前端。该功能可用于查看前端提供的 SNI 列表,并识别同一前端是否因多个证书而重复定义了某个 SNI。

-A 选项可用于过滤列表,仅显示已过 notAfter 日期的证书,从而仅展示已过期的证书。

-t 选项接受以秒为单位的偏移量,或带时间单位(s、m、h、d)的偏移量,该偏移量将加到当前时间上,结合 -A. 使用时,可用于检查在偏移时间之后到期的证书。例如,若要检查 30 天后将过期的证书,只需执行命令 “show ssl sni -A -t 30d”。

列之间以单个 \t 分隔,便于简单解析。

“前端/绑定”列显示前端名称,后跟配置中的绑定行位置(前端/文件:行号)。

‘SNI’ 列显示 SNI,其内容可以是 CN、SAN 或来自 crt-list 的过滤器。绑定行的默认证书(即通过 ‘default-crt’ 显式声明的证书,或在未使用 ‘strict-sni’ 时隐式取绑定行中第一个证书)在 SNI 列中显示为 ‘*’ 字符。

“负向过滤器”列列出与通配符关联的负向过滤器,该列将显示位于同一 crt-list 行上的所有负向过滤器。若无负向过滤器,则显示连字符。

“类型”列显示加密算法类型,可以是 “rsa”、“ecdsa” 或 “dsa”。

‘文件名’ 列可以是配置中的文件名,也可以是 crt-store 中声明的别名。

‘NotAfter’ 和 ‘NotBefore’ 列直接从 X509 叶证书中提取。

示例:

$ echo "@1 show ssl sni -A -t 30d" | socat /var/run/haproxy-master.sock - | column -t -s $'\t'
# Frontend/Bind        SNI        Negative Filter  Type   Filename             NotAfter                  NotBefore
li1/haproxy.cfg:10021  *.ex.lan   !m1.ex.lan       rsa    example.lan.pem      Jun 13 13:37:21 2024 GMT  May 14 13:37:21 2024 GMT
li1/haproxy.cfg:10021  machine10  -                ecdsa  machine10.pem.ecdsa  Jun 13 13:37:21 2024 GMT  May 14 13:37:21 2024 GMT
li1/haproxy.cfg:10021  machine10  -                rsa    machine10.pem.rsa    Jun 13 13:37:21 2024 GMT  May 14 13:37:21 2024 GMT
li1/haproxy.cfg:10021  machine10  -                ecdsa  machine10.pem.ecdsa  Jun 13 13:37:21 2024 GMT  May 14 13:37:21 2024 GMT
li1/haproxy.cfg:10021  localhost  -                rsa    localhost.pem.rsa    Jun 13 13:37:11 2024 GMT  May 14 13:37:11 2024 GMT
li1/haproxy.cfg:10021  localhost  -                ecdsa  localhost.pem.ecdsa  Jun 13 13:37:10 2024 GMT  May 14 13:37:10 2024 GMT
li1/haproxy.cfg:10021  *          -                rsa    localhost.pem.rsa    Jun 13 13:37:11 2024 GMT  May 14 13:37:11 2024 GMT

show startup-logs

show startup-logs

输出当前 HAProxy 进程启动期间发出的所有消息,每个 startup-logs 缓冲区均与其 HAProxy 工作进程唯一对应。

该关键字也存在于主 CLI 中,用于显示最新的启动或重载尝试状态。

show table

show table

转储所有已知 stick-table 的通用信息。返回其名称(持有该 stick-table 的代理名称)、类型(当前始终为 0,表示 IP)、最大可能条目数以及当前已使用的条目数。

示例:

    $ echo "show table" | socat stdio /tmp/sock1
>>> # table: front_pub, type: ip, size:204800, used:171454
>>> # table: back_rdp, type: ip, size:204800, used:0

show table <name> [ data.<type> <operator> <value> [data.<type> ...]] |

show table <name> [ data.<type> <operator> <value> [data.<type> ...]] |
                  [ key <key> ] | [ ptr <ptr> ]

转储 stick-table <name> 的内容。在此模式下,首先会报告与“show table”相同的关于该表的通用信息,随后转储所有条目。由于该操作可能产生大量数据,可以指定一个过滤器,以明确显示哪些条目。

当使用 “data.” 形式时,过滤器作用于存储的数据(参见第 4.2 段中的 “stick-table”)。必须在 <type> 中指定存储的数据类型,且该数据类型必须已存储于表中,否则将报告错误。数据将根据 <operator> 与 64 位整数 <value> 进行比较。操作符与 ACL 中相同:

- eq: match entries whose data is equal to this value
- ne: match entries whose data is not equal to this value
- le: match entries whose data is less than or equal to this value
- ge: match entries whose data is greater than or equal to this value
- lt: match entries whose data is less than this value
- gt: match entries whose data is greater than this value

在此形式中,可使用多个数据过滤器条目,最多可达构建时定义的上限(默认为 4 个)。

使用键值形式时,将显示条目 <key>。键的类型必须与表的类型相同,当前仅限于 IPv4、IPv6、整数和字符串。

当使用 ptr 形式时,将显示条目 <ptr>。<ptr> 以 0xffff 格式书写,必须与先前执行“show table”命令返回的地址对应。若因键为空或 CLI 中存在不兼容字符而无法通过键匹配条目时,使用指针匹配条目可能具有实际意义。

如果 data.<type> 为数组类型,可以使用 “[]” 访问数组中的特定索引,例如:data.gpt[1]

示例:

    $ echo "show table http_proxy" | socat stdio /tmp/sock1
>>> # table: http_proxy, type: ip, size:204800, used:2
>>> 0x80e6a4c: key=127.0.0.1 use=0 exp=3594729 gpc0=0 conn_rate(30000)=1  \
      bytes_out_rate(60000)=187
>>> 0x80e6a80: key=127.0.0.2 use=0 exp=3594740 gpc0=1 conn_rate(30000)=10 \
      bytes_out_rate(60000)=191

    $ echo "show table http_proxy data.gpc0 gt 0" | socat stdio /tmp/sock1
>>> # table: http_proxy, type: ip, size:204800, used:2
>>> 0x80e6a80: key=127.0.0.2 use=0 exp=3594740 gpc0=1 conn_rate(30000)=10 \
      bytes_out_rate(60000)=191

    $ echo "show table http_proxy data.conn_rate gt 5" | \
        socat stdio /tmp/sock1
>>> # table: http_proxy, type: ip, size:204800, used:2
>>> 0x80e6a80: key=127.0.0.2 use=0 exp=3594740 gpc0=1 conn_rate(30000)=10 \
      bytes_out_rate(60000)=191

    $ echo "show table http_proxy key 127.0.0.2" | \
        socat stdio /tmp/sock1
>>> # table: http_proxy, type: ip, size:204800, used:2
>>> 0x80e6a80: key=127.0.0.2 use=0 exp=3594740 gpc0=1 conn_rate(30000)=10 \
      bytes_out_rate(60000)=191

    $ echo "show table http_proxy ptr 0x80e6a80" | \
        socat stdio /tmp/sock1
>>> # table: http_proxy, type: ip, size:204800, used:2
>>> 0x80e6a80: key=127.0.0.2 use=0 exp=3594740 gpc0=1 conn_rate(30000)=10 \
      bytes_out_rate(60000)=191

当数据准则应用于依赖时间的动态值(如字节速率)时,该值会在评估条目期间动态计算,以决定是否需要转储。这意味着此类过滤器可能在一段时间内匹配,随后不再匹配,因为随着时间推移,平均事件速率下降。

可以利用此功能提取滥用服务的 IP 地址列表,以便进行监控,甚至在防火墙中将其列入黑名单。示例:

$ echo "show table http_proxy data.gpc0 gt 0" \
  | socat stdio /tmp/sock1 \
  | fgrep 'key=' | cut -d' ' -f2 | cut -d= -f2 > abusers-ip.txt
  ( or | awk '/key/{ print a[split($2,a,"=")]; }' )

当粘性表同步至支持分片的对等节点段时,每个键将显示其分片编号(否则报告为“0”)。这有助于确定哪些对等节点将接收该键。示例:

$ echo "show table http_proxy" | socat stdio /tmp/sock1 | fgrep shard=
  0x7f23b0c822a8: key=10.0.0.2 use=0 exp=296398 shard=9 gpc0=0
  0x7f23a063f948: key=10.0.0.6 use=0 exp=296075 shard=12 gpc0=0
  0x7f23b03920b8: key=10.0.0.8 use=0 exp=296766 shard=1 gpc0=0
  0x7f23a43c09e8: key=10.0.0.12 use=0 exp=295368 shard=8 gpc0=0

show tasks

show tasks

显示当前运行队列中任务的数量,以及每个函数的任务数量及其平均延迟(当已知时,仅适用于启用了任务剖析的纯任务)。该输出为执行瞬间的快照,结果可能因执行时队列中剩余的任务而有所差异,尤其是在单线程模式下,此时 I/O 操作重新填充队列的可能性较低(除非队列已满)。该命令会独占访问进程,在高负载进程上执行时可能导致轻微但可测量的延迟,因此必须避免被监控机器人滥用。

show threads

show threads

为每个线程转储一些内部状态和结构,有助于开发者理解问题。输出格式力求可读,每个线程显示一个独立区块。当 HAProxy 以 USE_THREAD_DUMP=1 编译时,会使用涉及线程信号的高级转储机制,使每个线程依次转储自身状态。若未启用此选项,执行命令的线程将显示全部详细信息,其余线程则信息较少。处理命令的线程前会显示星号(’*’)。若某线程前显示右角括号(’>’),表示自上次调用此命令以来该线程未取得任何进展,表明代码中存在必须立即报告的缺陷。若两个线程均出现此情况,通常指示存在死锁。若仅有一个线程出现此情况,则为其他类型缺陷,例如链表损坏。在所有情况下,进程已无法正常运行,必须重启。

输出格式未予文档化,以便在识别新需求时可轻松演进,无需维护任何形式的向后兼容性。与“show activity”类似,若无代码在手,这些值毫无意义。

show tls-keys [id|*]

show tls-keys [id|*]

dump 所有已加载的 TLS 会话票证密钥引用。显示 TLS 会话票证密钥引用 ID 以及密钥加载来源文件。可使用这两个信息通过命令 “set ssl tls-key” 更新 TLS 密钥。若指定 ID 作为参数,将仅转储该引用的会话票证;使用 * 则转储所有引用中的全部密钥。

show schema json

show schema json

输出 “show info json” 和 “show stat json” 时所使用的模式的转储。

输出中不包含额外的空白字符,以减少输出体积。对于人工阅读,将输出通过格式化打印机处理可能更有帮助。示例:

$ echo “show schema json” | socat /var/run/haproxy.sock stdio | \ python -m json.tool

该模式遵循“JSON Schema”(json-schema.org)规范,因此可使用验证器对 “show info json” 和 “show stat json” 的输出结果依据该模式进行验证。

show trace [<source>]

show trace [<source>]

显示当前追踪状态。对于每个源,将显示一行,其中单个字符的状态指示追踪是否已停止、等待或运行。输出接收端(或“none”表示未设置)以及该接收端中丢弃的事件数量,随后是源的简要描述。若指定了源名称,则会列出该源支持的所有事件的详细列表,以及每个动作(报告、启动、暂停、停止)的状态,启用时以“+”表示,否则以“-”表示。所有这些事件相互独立,一个事件可能触发启动但未被报告,反之亦然。

show version

show version

显示当前 HAProxy 进程的版本。此命令可从主进程和工作进程的 CLI 中调用。

示例:

$ echo "show version" | socat /var/run/haproxy.sock stdio
2.4.9

$ echo "show version" | socat /var/run/haproxy-master.sock stdio
2.5.0

shutdown frontend <frontend>

shutdown frontend <frontend>

完全删除指定的前端。该前端绑定的所有端口将被释放。执行此操作后,前端将无法再启用。此操作旨在用于无法想象停止代理的环境,但又必须修复配置错误的代理时使用。通过这种方式,可以释放端口,并将其绑定到其他进程以恢复服务。前端一旦终止,将完全不会出现在统计信息页面上。

前端可通过其名称或其数字 ID 指定,数字 ID 前需加井号(’#’)。

此命令受限制,仅可在配置为“admin”级别的套接字上执行。

shutdown session <id>

shutdown session <id>

立即终止与指定流标识符匹配的流。该标识符是 “show sess” 转储输出中每行开头的第一个字段(对应流指针)。此操作可用于在不等待超时的情况下终止长时间运行的流,或在持续传输进行时终止该流。被终止的流将在日志中以 ‘K’ 标志报告。

shutdown sessions server <backend>/<server>

shutdown sessions server <backend>/<server>

立即终止与指定服务器关联的所有流。例如,可在将服务器置于维护模式后,使用此操作终止长时间运行的流。被终止的流将在日志中以 ‘K’ 标志报告。

后端连接在空闲状态下保留,除非服务器已进入维护模式,此时连接将立即被安排删除。

trace

trace

trace 命令单独使用时,会列出追踪源、其当前状态及简要描述。该命令仅作为进入下一级操作的菜单,详见下方其他 trace 命令。

trace 0

trace 0

立即停止所有追踪。此操作用于快速终止调试会话,或在多个源上启用了复杂追踪且影响服务时作为紧急处理动作。

trace <source> [<args...>]

trace <source> [<args...>]

为源 <source> 配置追踪。不带参数时,将列出该源支持的所有子命令。可串联多个子命令。支持的子命令如下:

event [ [+|-|!]<name> ] 不带参数时,将列出指定源支持的所有事件。已启用的事件前缀为 “+",未启用的事件前缀为 “-"。请注意,单个追踪可能被标记为多个事件,只要任一已启用的事件与追踪中标记的事件匹配,该事件就会传递至追踪子系统。例如,接收一个类型为 HEADERS 的 HTTP/2 帧可能触发帧事件和流事件,因为该帧会创建一个新流。若该源已启用帧事件或流事件中的任意一个,该帧将被传递至追踪框架。

With an argument, it is possible to toggle the state of each event and
individually enable or disable them. Two special keywords are supported,
"none", which matches no event, and is used to disable all events at once,
and "any" which matches all events, and is used to enable all events at
once. Other events are specific to the event source. It is possible to
enable one event by specifying its name, optionally prefixed with '+' for
better readability. It is possible to disable one event by specifying its
name prefixed by a '-' or a '!'.

One way to completely disable a trace source is to pass "event none", and
this source will instantly be totally ignored.

跟随 <other_source>。当另一源 <other_source> 锁定于某一条件,且当前源也匹配相同条件时,此操作允许源 <source> 同时发出追踪信息。例如,若某一源锁定于会话,从另一源跟随该源将导致后者为与该会话相关的所有事件发出追踪信息。此功能可在一定程度上用于追踪后端请求及其关联的前端连接。“session” 源通过提供 “new” 和 “end” 事件,使此类锁定处理更加简便。请注意,此时源 <source> 无需启用追踪,其追踪状态也不会受到影响。然而,若某些事件不包含可用于关联到被追踪元素的信息,则可能遗漏部分事件。该命令也可与元源 “all” 一同使用:此时所有源将跟随 <other_source>。

示例:

trace h1 lock session start sess_new pause sess_end follow session

level [<level>] 不带参数时,将列出此源的所有跟踪级别,当前级别前会以星号(’*’)作为标记。带参数时,将跟踪级别更改为指定级别。详细级别是一种在事件上报前应用的过滤器。此类过滤器用于根据事件的重要程度选择性地包含或排除事件。例如,开发者可能需要精确了解 HTTP 头在代码中的哪个位置被判定为无效,而终端用户可能根本不在意该头的有效性。目前,跟踪级别共有 5 个不同等级:

user       this will report information that are suitable for use by a
           regular haproxy user who wants to observe his traffic.
           Typically some HTTP requests and responses will be reported
           without much detail. Most sources will set this as the
           default level to ease operations.

proto      in addition to what is reported at the "user" level, it also
           displays protocol-level updates. This can for example be the
           frame types or HTTP headers after decoding.

state      in addition to what is reported at the "proto" level, it
           will also display state transitions (or failed transitions)
           which happen in parsers, so this will show attempts to
           perform an operation while the "proto" level only shows
           the final operation.

data       in addition to what is reported at the "state" level, it
           will also include data transfers between the various layers.

developer  it reports everything available, which can include advanced
           information such as "breaking out of this loop" that are
           only relevant to a developer trying to understand a bug that
           only happens once in a while in field. Function names are
           only reported at this level.
It is highly recommended to always use the "user" level only and switch to
other levels only if instructed to do so by a developer. Also it is a good
idea to first configure the events before switching to higher levels, as it
may save from dumping many lines if no filter is applied. The meta-source
"all" may also be used with this command: in this case, the level will be
applied to all existing sources at once.

lock [criterion] 若不带参数,将列出此源支持的所有锁住条件,并在当前选择的条件前用星号(’*’)标注。锁住(lock-on)表示该源将聚焦于首个匹配的事件,并仅持续关注触发该事件的条件,直到追踪结束前忽略所有其他条件。例如,这可用于对单个连接或单个流进行追踪。以下条件由部分追踪支持,但并非所有追踪均支持,因为某些条件可能对特定源不可用:

backend      lock on the backend that started the trace
connection   lock on the connection that started the trace
frontend     lock on the frontend that started the trace
listener     lock on the listener that started the trace
nothing      do not lock on anything
server       lock on the server that started the trace
session      lock on the session that started the trace
thread       lock on the thread that started the trace
In addition to this, each source may provide up to 4 specific criteria such
as internal states or connection IDs. For example in HTTP/2 it is possible
to lock on the H2 stream and ignore other streams once a strace starts.

When a criterion is passed in argument, this one is used instead of the
other ones and any existing tracking is immediately terminated so that it
can restart with the new criterion. The special keyword "nothing" is
supported by all sources to permanently disable tracking.

{ pause | start | stop } [ [+|-|!]event] 不带参数时,将列出为该追踪源自动暂停、启动或停止追踪所启用的事件。这些事件因每个追踪源而异。带参数时,将为指定动作启用事件(若可选地以 ‘+’ 前缀)或禁用事件(若以 ‘-’ 或 ‘!’ 前缀)。特殊关键字 “now” 并非事件,而是请求立即执行动作。关键字 “none” 和 “any” 的用法与 “trace event” 中一致。

The 3 supported actions are respectively "pause", "start" and "stop". The
"pause" action enumerates events which will cause a running trace to stop
and wait for a new start event to restart it. The "start" action enumerates
the events which switch the trace into the waiting mode until one of the
start events appears. And the "stop" action enumerates the events which
definitely stop the trace until it is manually enabled again. In practice it
makes sense to manually start a trace using "start now" without caring about
events, and to stop it using "stop now". In order to capture more subtle
event sequences, setting "start" to a normal event (like receiving an HTTP
request) and "stop" to a very rare event like emitting a certain error, will
ensure that the last captured events will match the desired criteria. And
the pause event is useful to detect the end of a sequence, disable the
lock-on and wait for another opportunity to take a capture. In this case it
can make sense to enable lock-on to spot only one specific criterion (e.g. a
stream), and have "start" set to anything that starts this criterion
(e.g. all events which create a stream), "stop" set to the expected anomaly,
and "pause" to anything that ends that criterion (e.g. any end of stream
event). In this case the trace log will contain complete sequences of
perfectly clean series affecting a single object, until the last sequence
containing everything from the beginning to the anomaly.

sink [<sink>] 若不带参数,将列出此源可用的所有事件接收端,当前配置的接收端前会附加星号(’*’)。接收端 “none” 始终可用,表示所有事件将被直接丢弃,尽管其处理不会被忽略(例如,锁机制仍会生效)。其他接收端是否可用取决于配置和构建选项,但通常在调试模式下 “stdout” 和 “stderr” 可用,内存环形缓冲区也应可用。指定名称后,接收端将立即切换至指定源。接收端切换期间事件不会被更改。最坏情况下,若使用无效接收端(或 “none”)可能导致部分事件丢失,但操作仍会继续发送至其他目标。该命令也可与元源 “all” 一同使用:此时接收端将同时应用于所有现有源。

verbosity [<level>] 不带参数时,将列出此源的所有详细级别,当前级别前会以星号(’*’)标记。带参数时,将详细级别更改为指定值。

Verbosity levels indicate how far the trace decoder should go to provide
detailed information. It depends on the trace source, since some sources
will not even provide a specific decoder. Level "quiet" is always available
and disables any decoding. It can be useful when trying to figure what's
happening before trying to understand the details, since it will have a very
low impact on performance and trace size. When no verbosity levels are
declared by a source, level "default" is available and will cause a decoder
to be called when specified in the traces. It is an opportunistic decoding.
When the source declares some verbosity levels, these ones are listed with a
description of what they correspond to. In this case the trace decoder
provided by the source will be as accurate as possible based on the
information available at the trace point. The first level above "quiet" is
set by default.

update ssl ocsp-response <certfile>

update ssl ocsp-response <certfile>

为指定的 <certfile> 创建 OCSP 请求,并将其发送至 OCSP 响应器。OCSP 响应器的 URI 应在证书的“权威信息访问”段中指定。仅第一个 URI 会被考虑。随后将检查所接收的 OCSP 响应,并将其插入本地 OCSP 响应树中。该命令仅对已存储 OCSP 响应的证书有效,这些证书的 OCSP 响应可能在初始化时提供,或此前通过 “set ssl cert” 或 “set ssl ocsp-response” 命令设置。若接收到的 OCSP 响应有效且已正确插入本地树中,其内容将显示在标准输出上。格式与 “show ssl ocsp-response” 中描述的相同。

wait { -h | <delay> } [<condition> [<args>...]]

wait { -h | <delay> } [<condition> [<args>...]]

在最简单的形式下,不带任何条件时,该操作会等待指定的延迟时间后再继续执行。此功能可用于收集特定时间间隔内的指标数据。

在指定条件和可选参数下,该命令将等待指定条件得到满足、不可恢复地失败,或在 <delay> 时长内始终不满足。支持的条件如下:

  • be-removable <proxy>:等待指定的代理后端可由“del backend”命令移除。某些条件将始终不被接受(例如后端尚未发布或其中包含服务器),并导致返回特定错误消息,指出未满足的条件。若在延迟时间内一切正常,则返回成功,并终止操作。

  • srv-removable <proxy>/<server>:此选项将等待指定服务器被 “del server” 命令移除,即处于维护状态且不再有任何连接(无论是活动连接还是空闲连接)。某些条件将始终不被接受(例如未处于维护状态),并导致返回特定错误消息,指出未满足的条件。服务器甚至可能已被并行移除,不再存在。若在超时前所有条件均满足,则返回成功,并终止操作。

默认情况下,延迟单位为毫秒,但也可接受其他单位,只要其后缀为常规计时单位(us、ms、s、m、h、d)。使用 socat 工具时,请勿忘记将 socat 的关闭超时时间延长至覆盖等待时间。将 “-h” 作为第一个或第二个参数传入可显示命令的用法。示例:

$ socat -t20 /path/to/socket - <<< "show activity; wait 10s; show activity"

$ socat -t5 /path/to/socket - <<< "
    disable server px/srv1
    shutdown sessions server px/srv1
    wait 2s srv-removable px/srv1
    del server px/srv1"

9.4. 主命令行界面

主进程 CLI 是主进程/工作进程模式下绑定至主进程的套接字。该 CLI 可访问所有运行中或即将退出的进程中的 Unix 套接字命令,并允许对这些进程进行基本监控。

主 CLI 仅可通过 HAProxy 程序参数中的 -S 选项进行配置。该选项还接受以逗号分隔的绑定选项。

示例:

# haproxy -W -S 127.0.0.1:1234 -f test1.cfg
# haproxy -Ws -S /tmp/master-socket,uid,1000,gid,1000,mode,600 -f test1.cfg
# haproxy -W -S /tmp/master-socket,level,user -f test1.cfg

9.4.1. 主命令行命令

@<[!]pid>

@<[!]pid>

主 CLI 使用特殊的前缀表示法来访问多个进程。该表示法易于识别,因其以 @ 开头。

以 @ 开头可后接相对进程号,或后接感叹号和 PID(例如 @1 或 @!1271)。单独使用 @ 可用于指定主进程。仅通过 PID 作为相对进程号才能访问的进程,仅在当前进程上下文中可用。

此前缀可用作命令前的包装符,表示仅将该命令及其本身发送至指定进程。此时,完整命令的结束位置与常规命令相同,即行尾或分号处。

缺陷:用于在主进程与工作进程之间实现通信的 sockpair@ 协议在 macOS 上已知不可靠,这是由于 macOS 的 sendmsg(2) 实现存在缺陷所致。因此,命令可能因该问题而无响应。

示例:

$ socat /var/run/haproxy-master.sock readline
prompt
master> @1 show info; @2 show info
[...]
Process_num: 1
Pid: 1271
[...]
Process_num: 2
Pid: 1272
[...]
master>

$ echo '@!1271 show info; @!1272 show info' | socat /var/run/haproxy-master.sock -
[...]

前缀也可作为独立命令使用,用于将默认执行上下文切换至指定进程,表示所有后续命令均将在该进程内执行,直至新的 ‘@’ 命令再次更改执行上下文。

示例:

$ socat /var/run/haproxy-master.sock readline
prompt
master> @1
1271> show info
[...]
1271> show stat
[...]
1271> @
master>

$ echo '@1; show info; show stat; @2; show info; show stat' | socat /var/run/haproxy-master.sock -
[...]

关于限制的说明:少数罕见命令会更改 CLI 会话的状态(例如 “set anon”、“set timeout”),在从主 CLI 执行时可能无法完全保持一致的行为,因为这些命令是逐个发送到各自的 CLI 会话中执行的。类似地,少数罕见命令(“show events”、“wait”)会主动监控 CLI 的输入或关闭状态,一旦 CLI 关闭便会立即中断。通过主 CLI 执行时,这些命令无法按预期工作,因为每个命令执行后其输入流即被关闭。对于此类罕见情况,下方的 “@@” 变体可能更为合适。

@@<[!]pid> [command...]

@@<[!]pid> [command...]

此前缀或命令与上述文档中记录的 “@” 前缀非常相似,不同之处在于它会进入工作进程,将整个命令行原样传递给该进程,并在命令执行完毕前保持连接。分号也会被传递,从而允许在工作进程中执行完整的命令流水线。与工作进程的连接将持续开放,直至命令列表执行完毕。在命令执行完成后发送的任何数据将被转发至工作进程的 CLI,可能被正在执行的命令所消耗,而对主进程 CLI 来说将丢失,从而实现与工作进程的真正双向连接。因此,使用此类命令的用户必须格外小心,在发送新命令至主 CLI 之前,务必等待当前命令执行完成。

无需执行单个命令,也可以通过不在单独一行上指定任何命令(即仅输入 “@@1”)的方式,在工作进程上打开一个完全交互式的会话。该会话可通过关闭连接或通过退出工作进程(使用 “quit” 命令)来终止。此时,主控套接字的提示模式(交互式、提示式、定时式)将传播至工作进程。

缺陷:用于在主进程与工作进程之间实现通信的 sockpair@ 协议在 macOS 上已知不可靠,这是由于 macOS 的 sendmsg(2) 实现存在缺陷所致。因此,命令可能因该问题而无响应。

示例:

# gracefully close connections and delete a server once idle (wait max 10s)
$ socat -t 11 /var/run/haproxy-master.sock - <<< \
   "@@1 disable server app2/srv36; \
   wait 10000 srv-removable app2/srv36; \
   del server app2/srv36"

# forcefully close connections and quickly delete a server
$ socat /var/run/haproxy-master.sock - <<< \
   "@@1 disable server app2/srv36; \
   shutdown sessions server app2/srv36; \
   wait 100 srv-removable app2/srv36; \
   del server app2/srv36"

# show messages arriving to this ring in real time ("tail -f" equivalent)
$ (echo "show events buf0 -w"; read) | socat /var/run/haproxy-master.sock -

expert-mode [on|off]

expert-mode [on|off]

此命令为通过主控 CLI 访问的每个工作进程激活“专家模式”。与“mcli-debug-mode”结合使用时,还会在主控端激活该命令。在主控 CLI 提示符中显示标志“e”。

参见 第 9.3 节 中的 “expert-mode” 以及 9.4.1 中的 “mcli-debug-mode”。

experimental-mode [on|off]

experimental-mode [on|off]

此命令为通过主控 CLI 访问的每个工作进程激活“experimental-mode”。 与“mcli-debug-mode”结合使用时,还会在主控 CLI 上激活该命令。 在主控 CLI 提示符中显示标志“x”。

另请参阅 第 9.3 节 中的 “experimental-mode” 以及 9.4.1 中的 “mcli-debug-mode”。

hard-reload

hard-reload

此命令与通过主 CLI 执行的“reload”命令功能相同,区别在于它会对前一个进程执行硬停止(-st),而非停止-停止(-sf)。这意味着前一个进程在退出前不会等待任何操作完成,因此所有连接将被立即关闭。

另请参见“reload”命令。

mcli-debug-mode [on|off]

mcli-debug-mode [on|off]

此关键字可在主进程 CLI 中启用特殊模式,使主 CLI 可使用原本仅限工作进程 CLI 使用的命令,从而支持对主进程进行调试。启用后,可通过输入“help”查看新增可用命令。结合使用“experimental-mode”或“expert-mode”时,可启用更多命令。在主 CLI 提示符中显示标志“d”。

prompt

prompt

当通过 “prompt” 命令启用提示符时,CLI 所处的上下文将在提示符中显示。主进程以 “master” 字符串标识,其他进程则以其 PID 标识。若上次重载失败,主进程的提示符将变为 “master[ReloadFailed]>",以便明确显示当前进程仍在使用旧配置运行,且新配置尚未生效。

主 CLI 提示符可显示多个标志,表示启用的模式。“d” 表示 mcli-debug-mode,“e” 表示 expert-mode,“x” 表示 experimental-mode。

示例:

$ socat /var/run/haproxy-master.sock -
prompt
master> expert-mode on
master(e)> experimental-mode on
master(xe)> mcli-debug-mode on
master(xed)> @1
95191(xed)>

reload

reload

也可以使用“reload”命令重载 HAProxy 主进程,其效果与对主进程执行 kill -USR2 相同,前提是用户至少具备“operator”或“admin”权限。

此命令允许执行同步重载,命令将在重载完成后返回重载状态。若使用工具解析该状态,请注意超时设置,状态仅在配置解析完成且新工作进程创建后才会返回。默认情况下,“socat” 命令的超时时间为 0.5s,若重载耗时过长,该工具将在消息显示前退出。“ncat” 默认无超时设置。当使用 USE_SHM_OPEN=1 编译时,重载命令还可输出主进程的启动日志。

示例:

$ echo "reload" | socat -t300 /var/run/haproxy-master.sock stdin
Success=1
--
[NOTICE]   (482713): haproxy version is 2.7-dev7-4827fb-69
[NOTICE]   (482713): path to executable is ./haproxy
[WARNING]  (482713): config: 'http-request' rules ignored for proxy 'frt1' as they require HTTP mode.
[NOTICE]   (482713): New worker (482720) forked
[NOTICE]   (482713): Loading success.

$ echo "reload" | socat -t300 /var/run/haproxy-master.sock stdin
Success=0
--
[NOTICE]   (482886): haproxy version is 2.7-dev7-4827fb-69
[NOTICE]   (482886): path to executable is ./haproxy
[ALERT]    (482886): config: parsing [test3.cfg:1]: unknown keyword 'Aglobal' out of section.
[ALERT]    (482886): config: Fatal errors found in configuration.
[WARNING]  (482886): Loading failure!

$

重载命令是主 CLI 上最后执行的命令,此后所有命令均被忽略。 重载命令返回状态后,将关闭与 CLI 的连接。

请注意,重载将关闭与主 CLI 的所有连接。另请参见“hard-reload”命令。

show proc [debug]

show proc [debug]

主 CLI 引入了 show proc 命令,用于监视进程。

示例:

$ echo 'show proc' | socat /var/run/haproxy-master.sock -
#<PID>          <type>          <reloads>       <uptime>        <version>
1162            master          5 [failed: 0]   0d00h02m07s     2.5-dev13
# workers
1271            worker          1               0d00h00m00s     2.5-dev13
# old workers
1233            worker          3               0d00h00m43s     2.0-dev3-6019f6-289

在此示例中,主进程已重载 5 次,但其中一个旧的工作进程仍在运行,并成功存活了 3 次重载。可以访问该工作进程的 CLI 以了解当前情况。

‘debug’ 参数有助于显示调试详情,当前用于展示 IPC 通信的文件描述符(FDs)。请注意,调试输出在 HAProxy 不同版本之间无法保证稳定。

show startup-logs

show startup-logs

HAProxy 必须使用 USE_SHM_OPEN=1 编译,才能在主 CLI 上正确使用,否则所有消息将不可见。

与统计套接字上的对应命令类似,该命令可用于显示 HAProxy 的启动消息。但该命令不会输出当前工作进程的启动消息,而是输出最近一次启动或重载的启动消息,这意味着它能够输出失败重载时的解析消息。

这些消息也会通过 “reload” 命令输出。

9.5. 统计文件

所谓统计文件可用于在进程启动时,以非零值预加载 HAProxy 内部计数器。其主要用途是在重载期间保留工作进程的统计信息。统计文件中仅包含所有暴露的 HAProxy 统计信息的片段,因为仅对指标类数值进行预加载才有意义。

目前,统计文件中仅支持代理计数器。这允许预先加载前端、后端、服务器和监听器的值。然而,仅存储具有非空 GUID 的对象实例。这确保了即使其他参数不同,也能为类型和 GUID 匹配的对象预先加载值。

CLI 命令 dump stats-file 的用途是生成统计信息文件。统计信息文件的格式由内部定义,未来可能随时更改或扩展。该格式至少保证在相邻的 HAProxy 稳定分支版本间兼容,但在将统计信息文件加载到较旧版本的进程时,可能需要额外的可选配置。

31 - 10. 简化配置管理

让大型 HAProxy 配置更易维护的方法

组成集群的两个 HAProxy 节点通常使用完全相同的配置,只有少数地址不同。与其为每个节点分别维护一份最终必然产生差异的重复配置,不如在配置中引用环境变量。这样,多个配置实例便可共用同一个文件,只需在系统级环境变量中保留少量差异。此功能始于 1.5 版,当时只有地址可以包含环境变量;1.6 版进一步支持在所有位置使用环境变量。其语法与 UNIX shell 相同:变量以美元符号(’$’)开头,后接左花括号(’{’)、变量名和右花括号(’}’)。除地址外,环境变量只在双引号包围的参数中解析;这是为了避免破坏使用含美元符号正则表达式的现有配置。

环境变量也便于编写可在多个站点使用、仅地址不同的通用配置,还可以把密码从部分配置文件中移出。以下示例中的 “site1.env” 文件会在启动时由 init 脚本加载:

$ cat site1.env
LISTEN=192.168.1.1
CACHE_PFX=192.168.11
SERVER_PFX=192.168.22
LOGGER=192.168.33.1
STATSLP=admin:pa$$w0rd
ABUSERS=/etc/haproxy/abuse.lst
TIMEOUT=10s

$ cat haproxy.cfg
global
    log "${LOGGER}:514" local0

defaults
    mode http
    timeout client "${TIMEOUT}"
    timeout server "${TIMEOUT}"
    timeout connect 5s

frontend public
    bind "${LISTEN}:80"
    http-request reject if { src -f "${ABUSERS}" }
    stats uri /stats
    stats auth "${STATSLP}"
    use_backend cache if { path_end .jpg .css .ico }
    default_backend server

backend cache
    server cache1 "${CACHE_PFX}.1:18080" check
    server cache2 "${CACHE_PFX}.2:18080" check

backend server
    server cache1 "${SERVER_PFX}.1:8080" check
    server cache2 "${SERVER_PFX}.2:8080" check

32 - 11. 应避免的常见陷阱

应避免的运维失误与反直觉行为

有时会有人报告:系统重启后 HAProxy 服务没有启动,但手动启动又能正常工作。这通常出现在使用 keepalived 等集群 IP 地址机制、只把服务 IP 分配给主节点的环境中。HAProxy 绑定 0.0.0.0 时一切正常,改为绑定虚拟 IP 后却无法启动。原因是服务启动时,本地节点尚未持有该虚拟 IP;HAProxy 尝试绑定时,系统会因其不是本地 IP 地址而拒绝操作。正确的解决办法不是推迟 HAProxy 服务启动——这无法应对服务重启——而是把系统配置为允许绑定非本地地址。在 Linux 上,将 net.ipv4.ip_nonlocal_bind sysctl 设为 1 即可。如果需要透明截获经 HAProxy 转发到特定目标地址的 IP 流量,也必须启用此设置。

多进程配置若使用源端口范围,表面上可能运行正常,却会在高负载下随机失败:多个进程可能同时尝试使用同一源端口连接同一服务器,而这是不允许的。系统会报告错误并使用其他端口重试。增大 “retries” 参数可以在一定程度上掩盖问题,但也会增加 CPU 开销和处理时间,日志中仍会出现一定数量的重试记录。因此,多进程配置应避免使用端口范围。

HAProxy 使用 SO_REUSEPORT,并允许多个独立进程绑定同一个 IP:port。故障排查时,可能出现旧进程尚未停止、新进程便已启动的情况。这会产生荒谬的测试结果,看起来仿佛配置变更完全没有生效。实际上,即使新进程已经使用新配置重启,旧进程仍会接收并处理部分传入连接,从而返回意外结果。如有疑问,只需停止新进程后再次测试;如果服务仍然可用,很可能是旧进程依然存活,必须将其停止。Linux 的 “netstat -lntp” 命令在此很有帮助。

通过命令行向 ACL 添加条目时(例如将某个源地址加入黑名单),务必注意:这些条目不会同步写入文件,一旦有人重载配置,更新便会丢失。对于临时黑名单,这往往正是期望的效果;但如果所做变更是某个问题的正式修复,就可能不符合预期。详见 CLI 接口的 “add acl” 动作。

33 - 12. 调试与性能问题

排查崩溃、卡顿、延迟和吞吐量问题的方法

当 HAProxy 以 “-d” 选项启动时,它将以前台模式运行,并为每个事件打印一行输出,例如接收到的连接、连接结束,以及每个请求或响应头行。此调试输出在内容被处理前发出,因此不会考虑本地修改。主要用途是无需运行网络嗅探器即可查看请求和响应。当多个连接并行处理时,输出可读性会降低,但位于 examples/ 目录中的 “debug2ansi” 和 “debug2html” 脚本可显著改善此问题,通过为输出着色提升可读性。

如果 HAProxy 发现 HTTP/1.x 请求或响应格式错误而将其拒绝,最佳做法是连接到 CLI 并执行 “show errors” 命令。该命令将报告每个前端和后端最后捕获的故障 HTTP/1.x 请求和响应,包含所有必要信息,以精确定位被拒绝的输入流中的首个字符。此信息有时用于向客户或开发人员证明其代码中存在缺陷。在此情况下,可以使用 “option accept-unsafe-violations-in-http-request” 来放宽请求检查(但仍保留捕获功能),或使用其对应选项 “option accept-unsafe-violations-in-http-response” 来放宽来自服务器的响应检查。具体详情请参见配置手册。

示例:

> show errors
Total events captured on [13/Oct/2015:13:43:47.169]: 1

[13/Oct/2015:13:43:40.918] frontend HAProxyLocalStats (#2): invalid request
  backend <NONE> (#-1), server <NONE> (#-1), event #0
  src 127.0.0.1:51981, session #0, session flags 0x00000080
  HTTP msg state 26, msg flags 0x00000000, tx flags 0x00000000
  HTTP chunk len 0 bytes, HTTP body len 0 bytes
  buffer flags 0x00808002, out 0 bytes, total 31 bytes
  pending 31 bytes, wrapping at 8040, error at position 13:

  00000  GET /invalid request HTTP/1.1\r\n

CLI 中的 “show info” 命令输出提供了多项有用信息,包括历史上达到的最高连接速率、最高 SSL 密钥速率,以及一般情况下有助于解释 CPU 或内存使用异常的各类信息。示例:

> show info
Name: HAProxy
Version: 1.6-dev7-e32d18-17
Release_date: 2015/10/12
Nbproc: 1
Process_num: 1
Pid: 7949
Uptime: 0d 0h02m39s
Uptime_sec: 159
Memmax_MB: 0
Ulimit-n: 120032
Maxsock: 120032
Maxconn: 60000
Hard_maxconn: 60000
CurrConns: 0
CumConns: 3
CumReq: 3
MaxSslConns: 0
CurrSslConns: 0
CumSslConns: 0
Maxpipes: 0
PipesUsed: 0
PipesFree: 0
ConnRate: 0
ConnRateLimit: 0
MaxConnRate: 1
SessRate: 0
SessRateLimit: 0
MaxSessRate: 1
SslRate: 0
SslRateLimit: 0
MaxSslRate: 0
SslFrontendKeyRate: 0
SslFrontendMaxKeyRate: 0
SslFrontendSessionReuse_pct: 0
SslBackendKeyRate: 0
SslBackendMaxKeyRate: 0
SslCacheLookups: 0
SslCacheMisses: 0
CompressBpsIn: 0
CompressBpsOut: 0
CompressBpsRateLim: 0
ZlibMemUsage: 0
MaxZlibMemUsage: 0
Tasks: 5
Run_queue: 1
Idle_pct: 100
node: wtap
description:

当 HAProxy 新版本中出现看似随机的问题(例如:每第二个请求被中止、偶发崩溃等)时,建议尝试启用内存污染功能。该功能可使每次调用 malloc() 后立即用可配置字节填充内存区域。默认情况下,该字节为 0x50(ASCII 码中的 ‘P’),但也可使用任意其他字节,包括零(其效果等同于 calloc(),可能使问题消失)。通过命令行选项 “-dM” 启用内存污染。该功能会轻微影响性能,不建议在生产环境中使用。若问题在启用该功能后始终存在,或在使用字节零进行污染时完全不出现,则明确表明已发现缺陷,务必报告。否则,若无明显变化,则问题与此无关。

在排查延迟问题时,必须在本地机器上同时使用 strace 和 tcpdump,并在远程系统上另启一个 tcpdump。原因在于处理链中的每个环节都可能存在延迟,必须明确是哪一个环节导致了延迟,才能确定应对方向。实际操作中,本地 tcpdump 会显示输入数据到达的时间点;strace 会显示 HAProxy 接收这些数据的时间点(通过 recv/recvfrom 系统调用)。请注意,OpenSSL 使用 read()/write() 系统调用而非 recv()/send()。strace 还会显示 HAProxy 发送数据的时间点,而 tcpdump 会显示系统将数据发送至网卡的时间点。随后,外部 tcpdump 会显示数据实际被接收的时间点(因为本地 tcpdump 仅显示数据入队时间)。在本地系统上进行嗅探的优势在于,strace 和 tcpdump 使用相同的参考时钟。strace 应配合 “-tts200” 使用,以获取完整的时间戳,并报告足够大的数据块以便读取。tcpdump 应配合 “-nvvttSs0” 使用,以报告完整数据包、真实序列号和完整时间戳。

在实际应用中,HAProxy 几乎总是立即接收到数据(除非机器的 CPU 已饱和,或这些数据无效且未被传递)。如果数据已接收但未发送,通常是因为输出缓冲区已饱和(即接收方消耗数据的速度不够快)。可通过观察轮询机制在一段时间内未通知输出文件描述符可写状态来确认这一点(在 strace 输出中,通常更容易发现数据最终发出的时间点,然后回溯查看写事件何时被通知)。这通常与接收方返回的 ACK 匹配,可通过 tcpdump 检测到。数据发送后,可能在系统中停留一段时间而无任何操作。此时,TCP 拥塞窗口可能受限,无法允许这些数据离开,需等待 ACK 以打开窗口。若流量空闲,数据耗时 40 ms 或 200 ms 才能发出,属于不同问题(并非问题),这是 Nagle 算法阻止空包立即发出,以期后续数据能与其合并。HAProxy 在纯 TCP 模式和隧道中会自动禁用 Nagle。但在转发 HTTP 正文时,Nagle 仍明确启用,这有助于提升性能,通过减少数据包数量。部分不符合 HTTP 规范的应用程序可能对不完整 HTTP 响应消息的延迟敏感。此时需启用 “option http-no-delay” 以禁用 Nagle,从而绕过其设计缺陷,但需注意链路中的其他代理也可能受到类似影响。若 tcpdump 显示数据立即发出,但对端未及时收到,可能表示存在拥塞的广域网链路,或启用了流量控制的局域网导致数据无法发出,更常见的情况是 HAProxy 实际运行在虚拟机中,由于某种原因,虚拟机管理器决定数据无需立即发送。在虚拟化环境中,延迟问题几乎总是由虚拟化层引起,因此为节省时间,建议首先对比虚拟机内部与外部组件的 tcpdump 输出。任何差异均应归因于虚拟机管理器及其配套驱动。

当在 tcpdump 追踪中观察到某些 TCP SACK 段(使用 -vv)时,始终意味着发送方已获得数据包丢失的证据。虽然未观察到 SACK 段并不表示不存在丢包,但若观察到 SACK 段,则明确表明网络存在丢包。网络中出现丢包是正常现象,但丢包率低到肉眼难以察觉的程度。若在追踪中频繁出现 SACK 段,则应深入调查具体发生了什么以及数据包在何处丢失。HTTP 对 TCP 丢包的适应能力较差,会导致延迟显著增加。

“netstat -i” 命令将报告每个接口的统计信息。若某个接口的 Rx-Ovr 计数器持续增长,表明系统资源不足以接收所有传入数据包,导致数据包在被网络驱动程序处理前丢失。Rx-Drp 表示部分接收的数据包因应用程序处理速度不足而在网络协议栈中丢失。在某些攻击期间也可能发生此类情况。Tx-Drp 表示输出队列已满,数据包不得不被丢弃。使用 TCP 时这种情况应极为罕见,但可能表明出站链路已饱和。

34 - 13. 安全注意事项

特权隔离、攻击面、Linux 能力及安全运行

HAProxy 旨在以极低的权限运行。使用它的标准方式是将其隔离到 chroot 环境中,并将其权限降级为非 root 用户,且该用户在该环境内没有任何权限,从而确保未来若发现任何漏洞,其被攻破也不会影响系统其余部分。

为执行 chroot 操作,进程必须首先以 root 用户身份启动。手动构建 chroot 环境并在其中启动进程毫无意义,这类 chroot 环境难以构建,通常无法得到妥善维护,且包含的缺陷远多于主文件系统。一旦发生入侵,攻击者可利用特意构建的文件系统。不幸的是,许多系统管理员混淆了“以 root 身份启动”与“以 root 身份运行”的区别,导致在启动 HAProxy 之前就更改了用户 ID,从而削弱了实际的安全限制。

HAProxy 必须以 root 身份启动,以实现以下目的:

  • 调整文件描述符限制
  • 绑定到特权端口编号
  • 绑定到特定网络接口
  • 透明地监听外部地址
  • 在 chroot 沙箱内隔离自身
  • 降权至另一个非特权 UID

HAProxy 可能需要以 root 身份运行,以实现以下目的:

  • 绑定到接口以发起出站连接
  • 绑定到特权源端口以发起出站连接
  • 透明地绑定到外部地址以发起出站连接

大多数用户无需使用“以 root 身份运行”的情况。但“以 root 身份启动”涵盖了大多数使用场景。

安全的配置应满足以下要求:

  • 一个指向空位置且无任何访问权限的 chroot 语句。可通过 UNIX 命令行按如下方式准备:
# mkdir /var/empty && chmod 0 /var/empty || echo "Failed"

并在 HAProxy 配置的 global 段中以如下方式引用:

chroot /var/empty
  • 在 global 段中同时使用 uid/user 和 gid/group 语句:
user haproxy
group haproxy
  • 设置统计信息套接字的模式、所有者用户 ID 和所有者组 ID,使其与允许访问 CLI 的用户和/或组匹配,以确保无人可访问:
stats socket /var/run/haproxy.stat uid hatop gid hatop mode 600

13.1. Linux 能力支持

自 v2.9 版本起,HAProxy 支持 Linux 能力。若二进制文件编译时 USE_LINUX_CAP=1,则在从 root 用户切换至非 root 用户时,能够保留通过 ‘setcap’ 关键字赋予的能力。

自 v3.1 版本起,HAProxy 也会检查通过 ‘setcap’ 关键字指定的权限是否已在二进制文件中由管理员设置为允许集(通过 capget 系统调用)。若存在此情况,HAProxy 在以非 root 用户运行时,将通过 capset 系统调用将其权限从允许集转移到进程的有效集。

此举旨在避免 HAProxy 以 root 用户启动并运行时可能出现的所有使用场景:透明代理模式、绑定到特权端口。

‘setcap’ 关键字支持以下网络能力:

  • cap_net_admin:透明代理、将套接字绑定到特定网络接口、使用 set-mark 动作;
  • cap_net_raw(cap_net_admin 的子集):透明代理;
  • cap_net_bind_service:将套接字绑定到特定网络接口;
  • cap_sys_admin:在特定网络命名空间中创建套接字。

HAProxy 不会在未将这些能力列为 ‘setcap’ 参数的情况下,将其从允许集(Permitted set)转移到有效集(Effective)。有关 ‘setcap’ 关键字及支持能力的更多信息,请参见配置指南第 3.1 节“进程管理与安全”。

系统管理员可在 HAProxy 二进制文件中添加所需功能,允许集可通过以下命令设置:

示例:

# setcap cap_net_admin,cap_net_bind_service=p /usr/local/sbin/haproxy

新增的功能将在进程启动后于其允许集(Permitted set)中体现。若相同的功能作为 ‘setcap’ 关键字的参数,也可在进程有效集(Effective set)中观察到。可通过以下命令进行验证:

示例:

# grep Cap /proc/<haproxy PID>/status

CapInh: 0000000000000000 CapPrm: 0000000000001400 CapEff: 0000000000001400 CapBnd: 000001ffffffffff CapAmb: 0000000000000000

有关 setcap 和能力集的更多详细信息,请参阅 Linux 手册页(capabilities(7))。

在某些使用场景中,例如透明代理或在特定网络命名空间中创建套接字时,配置文件解析器会检测到需要 cap_net_raw、cap_sys_admin 或其他受支持的能力。随后,在初始化阶段,HAProxy 进程会检查这些能力是否可被添加到其有效能力集(Effective set)中。若因 capget 或 capset 系统调用失败(某些安全模块如 SELinux、Seccomp 等对系统调用施加了限制)而导致无法完成,进程将发出诊断警告(以 -dD 开头)。

由于支持多种不同平台及其各异的系统设置,解析器无法从配置文件中推断出是否将绑定到特权端口。因此,在权限不足(以非 root 用户运行)的情况下,进程仅会以如下告警信息终止。用户需自行检查配置文件及 HAProxy 二进制文件的权限能力设置。

示例:

$ haproxy -dD -f haproxy.cfg
...
[ALERT]    (96797): Binding [haproxy.cfg:36] for frontend fe: cannot bind socket (Permission denied) for [0.0.0.0:80]
[ALERT]    (96797): [haproxy.main()] Some protocols failed to start their listeners! Exiting.