配置手册

版本 3.3.0

2025/11/26

本文档涵盖了上述版本中实现的配置语言。它不提供任何提示、示例或建议。有关此类文档,请参阅参考手册或架构手册。以下摘要旨在帮助您按名称查找章节并在文档中导航。文档贡献者须知:本文档每行格式化为80列,使用偶数个空格进行缩进,不使用制表符。请严格遵守这些规则,以便在任何地方都能轻松打印。如果某行需要逐字打印且不适合,请在每行末尾加上反斜杠('\'),并在下一行继续,缩进两个字符。有时,为了强调输入和输出之间的差异,当它们可能模糊不清时,用三个闭合尖括号('>>>')作为所有输出行(日志、控制台输出)的前缀也很有用。如果添加新章节,请更新下面的摘要以便于搜索。
1. 关于 HTTP 的快速提醒
1.1.
1.2.
1.3.
1.3.1.
1.3.2.
1.4.
1.4.1.
1.4.2.

2.

配置 HAProxy
2.1.
2.2.
2.3.
2.4.
2.5.
2.6.
2.7.
2.8.
2.9.
2.9.1.
2.9.2.
2.9.3.
2.10.

3.

全局部分
3.1.
3.2.
3.3.
3.4.

4.

代理
4.1.
4.2.
4.3.
4.4.

5.

绑定和服务​​器选项
5.1.
5.2.
5.3.
5.3.1.
5.3.2.

6.

缓存
6.1.
6.2.
6.2.1.
6.2.2.

7.

使用 ACL 和获取样本
7.1.
7.1.1.
7.1.2.
7.1.3.
7.1.4.
7.1.5.
7.1.6.
7.2.
7.3.
7.3.1.
7.3.2.
7.3.3.
7.3.4.
7.3.5.
7.3.6.
7.3.7.
7.4.

8.

日志
8.1.
8.2.
8.2.1.
8.2.2.
8.2.3.
8.2.4.
8.2.5.
8.2.6.
8.3.
8.3.1.
8.3.2.
8.3.3.
8.3.4.
8.3.5.
8.4.
8.5.
8.6.
8.7.
8.8.
8.9.

9.

支持的过滤器
9.1.
9.2.
9.3.
9.4.
9.5.
9.6.
9.7.

10.

FastCGI 应用程序
10.1.
10.1.1.
10.1.2.
10.1.3.
10.2.
10.3.

11.

粘滞表和对等节点
11.1.
11.2.

12.

其他部分
12.1.
12.2.
12.3.
12.4.
12.5.
12.6.
12.7.
12.7.1.
12.8.
当 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 close”模式),连接建立的次数与 HTTP 事务的次数相同。由于连接在响应后由服务器关闭,客户端无需知道内容长度,它认为当连接关闭时响应即告完成。这也意味着如果某些响应由于网络错误而被截断,客户端可能会错误地认为响应已完成,这曾导致有时屏幕上渲染出被截断的图像。由于协议的事务性质,可以对其进行改进,以避免在两个后续事务之间关闭连接。然而,在这种模式下,服务器必须为每个响应指示内容长度,以便客户端不会无限期地等待。为此,使用了特殊的标头:“Content-length”。此模式称为“keep-alive”模式,随 HTTP/1.1 一起出现(一些 HTTP/1.0 代理支持它),在请求之间重用的连接称为“持久连接”:[CON] [REQ1] ... [RESP1] [REQ2] ... [RESP2] [CLO] ... 它的优点是事务之间的延迟减少,服务器端所需的处理能力降低,并且能够检测到被截断的响应。它通常比关闭模式更快,但并非总是如此,因为一些客户端通常将其并发连接限制为一个较小的值,这在网络连接较差时补偿较少。此外,一些服务器必须长时间保持连接活动,等待可能的新请求,并且由于连接数量过多,可能会经历高内存使用率,而关闭过快可能会破坏在连接关闭时到达的一些请求。在此模式下,响应大小需要提前知道,因此对于动态生成或压缩的内容并不总是可行。出于这个原因,实现了另一种模式,即“分块模式”(chunked mode),发送方不是一次性宣布整个大小,而是只宣布其缓冲区中已有的下一个“块”的大小,并且可以随时以零大小的块结束。在此模式下,不使用 Content-Length 标头。通信中的另一个改进是流水线模式(pipelining mode)。它仍然使用 keep-alive,但客户端不等第一个响应就发送第二个请求。这对于获取构成页面的大量图像非常有用:[CON] [REQ1] [REQ2] ... [RESP1] [RESP2] [CLO] ... 这显然对性能有巨大的好处,因为后续请求之间的网络延迟被消除了。许多 HTTP 代理不支持正确的流水线,因为在 HTTP 中无法将响应与相应的请求相关联。因此,服务器必须按照接收请求的完全相同的顺序回复。实际上,在各种客户端尝试部署后,由于在某些服务器上缺乏可靠性,它已被完全放弃。但服务器必须支持它。下一个改进是多路复用模式,如 HTTP/2 和 HTTP/3 中所实现。在此模式下,多个事务(即请求-响应对)通过单个连接并行传输,并且它们都以自己的速度进行,相互独立。对于多路复用协议,引入了“流”(stream)的新概念,以表示发生在同一连接上的这些并行通信。每个流通常被分配一个给定连接的唯一标识符,两端都使用该标识符来知道将数据传送到何处。客户端在同一连接上并行启动多个流(多达 100 个,有时更多)是很常见的,并让服务器对它们进行分类,并根据可用的响应以任何顺序响应。多路复用模式的主要好处是它显着减少了往返次数,并加快了高延迟网络上的页面加载时间。这在许多使用图像的网站上很明显,所有图像似乎都在并行加载。这些协议还通过采用一些机制来压缩标头字段以减少线路上的字节数来提高效率,因此如果没有适当的工具,它们不像 HTTP/1 那样可以通过手动操作或肉眼可读。出于这个原因,HTTP 消息的各种示例在文献中(包括本文档)继续使用 HTTP/1 语法表示,即使是较新版本的协议。HTTP/2 存在一些设计限制,例如数据包丢失会同时影响所有流,如果客户端花费太多时间来检索对象(例如需要将其存储在磁盘上),它可能会减慢检索速度,并使得在此期间无法访问在其后面等待的数据。这称为“队头阻塞”(head of line blocking)或“HoL blocking”或有时简称“HoL”。HTTP/3 是在 QUIC 上实现的,QUIC 本身是在 UDP 上实现的。QUIC 通过独立处理的流在传输层解决了队头阻塞问题。实际上,当遇到丢失时,受影响的流不会影响其他流,并且所有流都可以并行访问。QUIC 还提供连接迁移支持,但目前 haproxy 不支持它。默认情况下,HAProxy 在处理持久连接时以 keep-alive 模式运行:对于它处理的每个连接,它处理每个请求和响应,并在响应结束和新请求开始之间将连接在两端保持空闲状态。当它从客户端接收到 HTTP/2 连接时,它会并行处理所有请求并使连接空闲,等待新请求,就像它是一个 keep-alive HTTP 连接一样。HAProxy 主要支持 3 种连接模式:- keep alive:所有请求和响应都经过处理,面向客户端和面向服务器的连接保持活动状态以等待新请求。这是默认设置,适用于现代 Web 和现代协议(HTTP/2 和 HTTP/3)。- server close:面向服务器的连接在响应后关闭。- close:连接在两端响应结束后主动关闭。除此之外,默认情况下,面向服务器的连接可以被来自任何客户端的任何请求重用,正如 HTTP 协议规范所要求的那样,因此如果需要(例如客户端的源地址等),任何特定于特定客户端的信息都必须随每个请求一起传递。当 HTTP/2 与服务器一起使用时,默认情况下 HAProxy 会将此连接专用于同一客户端,以避免客户端之间出现队头阻塞的风险。

1.2. 术语

在 HAProxy 内部,术语随着 HTTP 协议及其用法的演变而有所发展。虽然最初连接、会话、流或事务之间没有显着差异,但随着时间的推移,这些术语变得更加清晰,以密切匹配现代 HTTP 协议版本中存在的内容,尽管出于历史兼容性的目的,某些术语在配置或命令行界面中仍然可见。以下是适用于当前版本 HAProxy 的一些定义:- 连接(connection):连接是在远程代理(客户端或服务器)和 HAProxy 之间以最低级别可能的单个双向通信通道。通常它对应于在一对 IP 和端口之间建立的 TCP 套接字。在面向客户端的一侧,连接是客户端连接到 HAProxy 时实例化的第一个实体,并且在连接级别应用的规则是最早应用的规则。- 会话(session):会话添加了一些与连接关联的上下文信息。这包括特定于传输层的信息(例如 TLS 密钥等)或变量。这个术语长期以来在 HAProxy 内部用于表示两端之间的端到端 HTTP/1.0 通信,因此尽管现在它代表流,但在某些 CLI 命令或统计信息的名称中仍然可见,但帮助消息和描述试图使其明确。它在网络级别术语(例如操作系统内部的 TCP 会话或跨防火墙的 TCP 会话)或非 HTTP 用户级应用程序(例如 telnet 会话或 SSH 会话)方面仍然有效。它不得与用于在 cookie 中存储完整用户上下文并要求发送到同一服务器的“应用程序会话”混淆。- 流(stream):流完全对应于应用程序级别的端到端双向通信,可以在其中应用分析和转换。在 HTTP 中,它包含单个请求及其关联的响应,并由请求的到达实例化,并随着响应交付的结束而完成。在这种情况下,这种流与多路复用协议的流之间存在 1:1 的关系。在 TCP 通信中,每个连接只有一个流。- 事务(transaction):事务仅是一对请求和关联的响应。在流出现之前,该术语与会话结合使用,但现在事务与流之间存在 1:1 的关系。它主要在变量的范围“txn”中可见,该范围在整个事务期间有效,因此在流中有效。- 请求(request):它表示从客户端流向服务器的流量。它主要用于 HTTP 以指示执行操作的位置。此术语也存在于 TCP 操作中,用于指示处理数据的位置。请求通常作为流量或活动单位出现在计数器中。它们并不总是意味着响应(例如,由于错误),但由于没有自发响应而没有请求,请求仍然是衡量整体活动的相关指标。在 TCP 中,请求的数量与连接数量相同。- 响应(response):这表示从服务器流向客户端的流量,或者有时是 HAProxy 自己生成响应时(例如 HTTP 重定向)从 HAProxy 流向客户端的流量。- 服务(service):这通常表示 HAProxy 中的一些内部处理,不需要服务器,例如 stats 页面、缓存或一些 Lua 代码来实现小型应用程序。服务通常读取请求,执行一些操作并生成响应。

1.3. HTTP 请求

首先,让我们考虑这个 HTTP 请求: 行号 内容 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 个字段组成:- 方法(METHOD):GET- URI(统一资源标识符):/serv/login.php?lang=en&profile=2- 版本标签(version tag):HTTP/1.1所有这些都由标准所称的 LWS(线性空白字符)分隔,通常是空格,但也可能是制表符或换行符/回车符后跟空格/制表符。方法本身不能包含任何冒号(':'),并且仅限于字母。所有这些各种组合使得 HAProxy 最好自己执行拆分,而不是让用户编写复杂或不准确的正则表达式。URI 本身可以有几种形式:- “相对 URI”:/serv/login.php?lang=en&profile=2它是没有主机部分的完整 URL。这通常是服务器、反向代理和透明代理接收到的内容。- “绝对 URI”,也称为“URL”:http://192.168.0.12:8080/serv/login.php?lang=en&profile=2它由一个“方案”(protocol name,后跟 '://')、一个主机名或地址、可选的冒号(':')后跟端口号,然后是从地址部分后的第一个斜杠('/')开始的相对 URI 组成。这通常是代理接收到的内容,但支持 HTTP/1.1 的服务器也必须接受这种形式。- 星号('*'):这种形式仅在与 OPTIONS 方法结合使用时接受,不可中继。它用于查询下一跳的功能。- 地址:端口组合:192.168.0.12:80这与 CONNECT 方法一起使用,CONNECT 方法用于通过 HTTP 代理建立 TCP 隧道,通常用于 HTTPS,但有时也用于其他协议。在相对 URI 中,识别出两个子部分。问号之前的部分称为“路径”。它通常是服务器上静态对象的相对路径。问号之后的部分称为“查询字符串”。它主要用于发送给动态脚本的 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 在索引标头、检查值和计算它们时会处理所有这些复杂的组合,因此无需担心它们的写入方式,但重要的是不要指责应用程序如果它做了不寻常、有效的事情是错误的。重要提示:正如 RFC7231 所建议的那样,HAProxy 通过用 LWS 替换标头中间的换行符来规范化标头,以便连接多行标头。这对于正确的分析是必需的,并有助于功能较弱的 HTTP 解析器正常工作,并且不会被此类复杂结构所欺骗。

1.4. HTTP 响应

HTTP 响应看起来与 HTTP 请求非常相似。两者都称为 HTTP 消息。让我们考虑这个 HTTP 响应:行号 内容1 HTTP/1.1 200 OK2 Content-length: 3503 Content-Type: text/html作为一个特例,HTTP 支持所谓的“信息性响应”,状态码为 1xx。这些消息很特别,因为它们不传达响应的任何部分,它们只用作一种信号消息,例如要求客户端继续发送其请求。在状态 100 响应的情况下,请求的信息将由紧随信息性响应之后的下一个非 100 响应消息携带。这意味着可以向单个请求发送多个响应,并且这仅在启用 keep-alive 时有效(1xx 消息出现在 HTTP/1.1 中)。HAProxy 处理这些消息,并能够正确转发和跳过它们,只处理下一个非 100 响应。因此,除非另有明确说明,否则这些消息既不记录也不转换。状态 101 消息表示协议正在同一连接上更改,HAProxy 必须切换到隧道模式,就像发生了 CONNECT 一样。然后 Upgrade 标头将包含有关连接正在切换到的协议类型的附加信息。

1.4.1. 响应行

第 1 行是“响应行”。它始终由 3 个字段组成:- 版本标签(version tag):HTTP/1.1- 状态码(status code):200- 原因短语(reason phrase):OK状态码始终是 3 位数字。第一位数字表示一般状态:- 1xx = 要跳过的信息性消息(例如 100、101)- 2xx = OK,内容正在发送中(例如 200、206)- 3xx = OK,没有内容发送中(例如 302、304)- 4xx = 由客户端引起的错误(例如 401、403、404)- 5xx = 由服务器引起的错误(例如 500、502、503)状态码大于 599 不得在通信中发出,尽管某些代理可能会在日志中生成它们以报告其内部状态。有关所有此类代码的详细含义,请参阅 RFC9110。HTTP/2 及更高版本没有版本标签,并使用“:status”伪标头来报告状态码。“原因”字段只是一个提示,但客户端不解析它。那里可以找到任何东西,但尊重公认的消息是一种常见的做法。它可以由一个或多个单词组成,例如“OK”、“Found”或“Authentication Required”。它在 HTTP/2 及更高版本中不存在,并且不会在那里发出。当来自 HTTP/2 或更高版本的响应传输到 HTTP/1 客户端时,HAProxy 将生成与状态码匹配的常见原因字段。HAProxy 可能会自行发出以下状态码:代码 何时/原因200 访问统计信息页面,以及回复监控请求时301 执行重定向时,具体取决于配置的代码302 执行重定向时,具体取决于配置的代码303 执行重定向时,具体取决于配置的代码307 执行重定向时,具体取决于配置的代码308 执行重定向时,具体取决于配置的代码400 对于无效或过大的请求401 执行操作需要身份验证时(访问统计信息页面时)403 当“http-request deny”规则禁止请求时404 当找不到请求的资源时408 在请求完成之前请求超时发生时410 当请求的资源不再可用且以后也不会再次可用时413 当 HTTP/1.0 GET/HEAD/DELETE 请求带有有效负载时,另请参阅“h1-accept-payload-with-any-method”选项500 当 HAProxy 遇到无法恢复的内部错误时,例如内存分配失败,这不应该发生501 当 HAProxy 因不支持的功能而无法满足客户端请求时502 当服务器返回空、无效或不完整的响应时,或者当“http-response deny”规则阻止响应时。503 当没有可用的服务器来处理请求时,或者响应与“monitor fail”条件匹配的监控请求时504 在服务器响应之前响应超时发生时上面的 4xx 和 5xx 错误代码可以自定义(请参阅第 4.2 节中的“errorloc”)。其他状态码可以通过特定操作有意发出(例如,请参阅第 4.3 节中的“deny”、“return”和“redirect”操作)。

1.4.2. 响应头

响应头的工作方式与请求头完全相同,因此,HAProxy 对两者使用相同的解析函数。有关更多详细信息,请参阅第 1.3.2 段。

2.1. 配置文件格式

HAProxy 的配置过程涉及 3 个主要参数来源:- 命令行参数,始终优先- 配置文件,此处描述其格式- 运行进程的环境,以防某些环境变量被明确引用配置文件遵循一个相当简单的层次结构格式,它遵循一些基本规则:1. 配置文件是语句的有序序列2. 语句是在任何未受保护的“#”(哈希)之前的一行非空行3. 一行是由未受保护的空格或制表符分隔的一系列令牌或“词”4. 一行的第一个词或词序列是本文档中列出的关键字或关键字序列之一5. 所有其他词都是第一个词的参数,其中一些是本文档中列出的众所周知的关键字,其他是值、对配置其他部分的引用或表达式6. 某些关键字分隔一个节,在该节中仅支持关键字的子集7. 一个节在文件末尾或在新节开始的特殊关键字处结束要编写简单但可靠的配置生成器,只需要了解以上所有内容,但这不足以可靠地解析任何配置或找出如何处理某些特殊情况。首先,上述规则有一些后果。规则 6 和 7 意味着用于定义新节的关键字在任何地方都有效,并且不能在特定节中具有不同的含义。这些关键字始终是单个词(与词序列相反),传统上,紧随其后的节使用相同的名称来表示。例如,当谈论“全局节”时,它指的是紧随“global”关键字之后的配置节。这种用法在错误消息中经常使用,以帮助定位需要解决的部分。许多节创建内部对象或配置空间,需要将其与其他节区分开来。在这种情况下,它们将使用一个额外的词来设置这个特定节的名称。对于其中一些,节名称是强制性的。例如,“frontend foo”将创建一个名为“foo”的“frontend”类型的新节。通常,名称特定于其节,不同类型的两个节可以使用相同的名称,但不推荐这样做,因为它往往会使配置管理复杂化。规则 7 的直接后果是,当同时读取多个文件时,每个文件必须以新节开头,并且每个文件的结尾将结束一个节。一个文件不能包含子节,也不能结束现有节并开始新节。规则 1 提到顺序很重要。确实,有些关键字创建的指令可以重复多次,以创建要按特定顺序应用的有序列规则。例如,“tcp-request”可用于在不同标准上交替使用“accept”和“reject”规则。因此,配置文件处理器在编辑文件时必须始终保留节的顺序。节的顺序通常无关紧要,除非全局节必须放置在其他节之前,但如果需要可以重复。此外,一些自动标识符可能会自动分配给一些创建的对象(例如代理),并且通过重新排序节,它们的标识符将发生变化。这些出现在统计信息中。因此,下面的配置将为“foo”分配 ID 号 1,为“bar”分配 ID 号 2,如果两个节颠倒,则会交换:listen foo bind :80 listen bar bind :81另一个重要点是,根据上述规则 2 和 3,空行、空格、制表符以及紧随未受保护的“#”字符之后的注释不属于配置的一部分,因为它们仅用作分隔符。这意味着以下配置严格等效:global#这是全局节 daemon#守护进程 frontend foo mode http # 或者 tcp and: global daemon # 这是公共 web 前端 frontend foo mode http 常见的做法是只将启动新节的关键字左对齐,并缩进(即在前面添加制表符或几个空格)所有其他关键字,以便立即看出它们属于同一节(如上例二所示)。在新节之前放置注释有助于读者确定它是否是所需的节。在节末尾留一个空行也有助于在编辑时直观地发现末尾。制表符非常方便用于缩进,但它们复制粘贴效果不佳。如果使用空格代替,建议不要放置太多(2 到 4 个),这样在有限的编辑器中编辑时不会成为负担,因为这些编辑器不支持自动缩进。早期,由于大多数关键字不会占用两个以上的参数,因此将参数在固定制表符位置拆分是很常见的。随着现代版本具有复杂表达式,这种做法不再适用,也不推荐。

2.2. 引号和转义

在现代配置中,一些参数要求使用以前被认为是纯分隔符的字符。为了使这成为可能,HAProxy 支持通过在要转义的字符前面添加反斜杠('\')进行字符转义,使用双引号("")对一段文本进行弱引用,以及使用单引号('')对一段文本进行强引用。这与许多编程语言中所做的工作非常相似,并且非常接近 Bourne shell 中常见的做法。原理如下:当配置解析器将行剪切成单词时,它还会处理引号和反斜杠,以确定字符是分隔符还是当前单词中的该字符的原始表示形式。然后删除转义字符,删除引号,剩余的单词按原样用作关键字或参数。如果单词中需要反斜杠,则必须使用自身进行转义(即双反斜杠)或进行强引用。引号外的转义是通过在特殊字符前加上反斜杠('\')来实现的:\ 将空格标记为与分隔符不同\# 将哈希标记为与注释开头不同\\ 使用反斜杠\' 使用单引号并将其与强引用分隔\" 使用双引号并将其与弱引用分隔此外,一些不可打印字符可以使用其通常的 C 语言表示形式发出:\n 插入换行符(LF,字符 \x0a 或 ASCII 10 十进制)\r 插入回车符(CR,字符 \x0d 或 ASCII 13 十进制)\t 插入制表符(字符 \x09 或 ASCII 9 十进制)\xNN 插入 ASCII 代码为十六进制 NN 的字符(例如 \x0a 代表 LF)。弱引用是通过在要保护的字符或字符序列周围加上双引号("")来实现的。弱引用可防止对以下内容的解释:空格或制表符作为单词分隔符' 单引号作为强引用分隔符# 哈希作为注释开头弱引用允许解释环境变量(在引号之外不进行评估),方法是在其前面加上美元符号('$')。如果双引号内需要美元字符,则必须使用反斜杠进行转义。强引用是通过在要保护的字符或字符序列周围加上单引号('')来实现的。在单引号内,不解释任何内容,这是引用正则表达式的有效方式。因此,下表显示了特殊字符在不同上下文中如何输入(不可打印字符替换为其名称,并用尖括号括起来)。请注意,某些只能以转义形式表示的字符在单引号内没有可能的表示形式,因此表中缺少它们
字符无引号弱引用强引用
<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"'\'
示例
# 以下这些都是完全等效的: 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
There is one particular case where a second level of quoting or escaping may be necessary. Some keywords take arguments within parenthesis, sometimes delimited by commas. These arguments are commonly integers or predefined words, but when they are arbitrary strings, it may be required to perform a separate level of escaping to disambiguate the characters that belong to the argument from the characters that are used to delimit the arguments themselves. A pretty common case is the "regsub" converter. It takes a regular expression in argument, and if a closing parenthesis is needed inside, this one will require to have its own quotes. The keyword argument parser is exactly the same as the top-level one regarding quotes, except that the \#, \$, and \xNN escapes are not processed. But what is not always obvious is that the delimiters used inside must first be escaped or quoted so that they are not resolved at the top level. Let's take this example making use of the "regsub" converter which takes 3 arguments, one regular expression, one replacement string and one set of flags: # replace all occurrences of "foo" with "blah" in the path: http-request set-path %[path,regsub(foo,blah,g)] Here no special quoting was necessary. But if now we want to replace either "foo" or "bar" with "blah", we'll need the regular expression "(foo|bar)". We cannot write: http-request set-path %[path,regsub((foo|bar),blah,g)] because we would like the string to cut like this: http-request set-path %[path,regsub((foo|bar),blah,g)] |---------|----|-| arg1 _/ / / arg2 __________/ / arg3 ______________/ but actually what is passed is a string between the opening and closing parenthesis then garbage: http-request set-path %[path,regsub((foo|bar),blah,g)] |--------|--------| arg1=(foo|bar _/ / trailing garbage _________/ The obvious solution here seems to be that the closing parenthesis needs to be quoted, but alone this will not work, because as mentioned above, quotes are processed by the top-level parser which will resolve them before processing this word: http-request set-path %[path,regsub("(foo|bar)",blah,g)] ------------ -------- ---------------------------------- word1 word2 word3=%[path,regsub((foo|bar),blah,g)] So we didn't change anything for the argument parser at the second level which still sees a truncated regular expression as the only argument, and garbage at the end of the string. By escaping the quotes they will be passed unmodified to the second level: 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 _______________/ Another approach consists in using single quotes outside the whole string and double quotes inside (so that the double quotes are not stripped again): http-request set-path '%[path,regsub("(foo|bar)",blah,g)]' ------------ -------- ---------------------------------- word1 word2 word3=%[path,regsub("(foo|bar)",blah,g)] |---------||----|-| arg1=(foo|bar) _/ / / arg2 ___________/ / arg3 _______________/ But in this case it's important to note that delimiters embedded into the higher level string remain pure characters and are not delimiters anymore. It particularly means that spaces and tabs around commas are part of the string. The example below is wrong on multiple points: 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" ______________/ The single fact of surrounding commas with spaces resulted in the spaces being part of the field itself, hence the converter " regsub" (starting with a space), which won't be found and will trigger an error, but more subtly, the replacement string " blah" will insert a space in the output. A good rule of thumb is to never insert unneeded spaces inside expressions. When using regular expressions, it can happen that the dollar ('$') character appears in the expression or that a backslash ('\') is used in the replacement string. In this case these ones will also be processed inside the double quotes thus single quotes are preferred (or double escaping). Example: 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 ______________________/ Remember that backslashes are not escape characters within single quotes and that the whole word above is already protected against them using the single quotes. Conversely, if double quotes had been used around the whole expression, single the dollar character and the backslashes would have been resolved at top level, breaking the argument contents at the second level. Unfortunately, since single quotes can't be escaped inside of strong quoting, if you need to include single quotes in your argument, you will need to escape or quote them twice. There are a few ways to do this: http-request set-var(txn.foo) str("\\'foo\\'") http-request set-var(txn.foo) str(\"\'foo\'\") http-request set-var(txn.foo) str(\\\'foo\\\') When in doubt, simply do not use quotes anywhere, and start to place single or double quotes around arguments that require a comma or a closing parenthesis, and think about escaping these quotes using a backslash if the string contains a dollar or a backslash. Again, this is pretty similar to what is used under a Bourne shell when double-escaping a command passed to "eval". For API writers the best is probably to place escaped quotes around each and every argument, regardless of their contents. Users will probably find that using single quotes around the whole expression and double quotes around each argument provides more readable configurations.

2.3. 环境变量

HAProxy 的配置支持环境变量。这些变量仅在双引号内被解释。变量在配置解析期间被展开。变量名前必须有美元符号 ("$"),并且可以选择性地用大括号 ("{}") 括起来,类似于 Bourne shell 中的做法。变量名可以包含字母数字字符或下划线 ("_"),但不应以数字开头。如果变量包含由空格分隔的多个值列表,可以通过用大括号将变量括起来并在右大括号前附加后缀 '[*]' 来将其展开为单个参数。当变量未设置时,也可以通过在变量名旁边的破折号 '-' 后面附加该值来指定一个默认值。请注意,默认值只替换不存在的变量,而不是空变量。
示例
bind "fd@${FD_APP1}" log "${LOCAL_SYLOG-127.0.0.1}:514" local0 notice # 发送到本地服务器 user "$HAPROXY_USER"
HAProxy 定义了一些变量,这些变量可以在配置文件中使用。这些变量列在下面的矩阵中,它们被分为四类: * usable:变量可以在配置中访问,可以按原样解析,也可以在条件块或谓词中使用,以启用或禁用某些配置片段,如第 2.4 节“条件块”所述。 * modifiable:变量可以在配置中通过 "setenv" / "unsetenv" 关键字重新定义或取消设置。 * listed:变量列在 CLI 的 "show env" 命令输出中,如管理指南第 9.3 节“Unix 套接字命令”所述。还有两个子类别“master”和“worker”,在下表中分别标记为“M”和“W”,显示了 HAProxy 以 master-worker 模式启动时两个进程之间的差异。 * master:变量在 master 进程中设置并可访问。因此,它将出现在 master CLI 的 "show env" 输出中,并且可以在条件块或指令中使用,以启用 master 的一些特殊设置(参见第 2.4 节“条件块”中的示例)。 * worker:变量在 worker 进程中设置并可访问。它将出现在 worker CLI 的 "show env"(或 master CLI 的 "@1 show env")中,并且也可以限制某些 worker 进程参数(参见第 2.4 节“条件块”中的示例)。 在独立模式下(没有 "-W" 选项或 "master-worker" 关键字),进程的行为类似于 worker,除了变量 "HAPROXY_MASTER_CLI" 和 "HAPROXY_MWORKER" 未定义。 有些变量被标记为不可用且不可修改: * HAPROXY_CFGFILES * HAPROXY_MWORKER * HAPROXY_CLI * HAPROXY_MASTER_CLI * HAPROXY_LOCALPEER 它们的值在配置解析期间未定义,而是在初始化期间设置的。因此,建议不要在条件块中使用这些变量,也不要在 global 部分的 "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_LOCALPEER:在进程启动时定义,包含本地对等体的名称。(请参阅管理指南中的 "-L"。) * HAPROXY_CFGFILES:HAProxy 加载的配置文件的列表,以分号分隔。如果您指定了一个目录,这可能很有用。 * HAPROXY_HTTP_LOG_FMT:包含第 8.2.3 节“HTTP 日志格式”中定义的默认 HTTP 日志格式的值。它可用于覆盖默认日志格式,而无需复制整个原始定义。 * HAPROXY_HTTP_CLF_LOG_FMT:包含第 8.2.3 节“HTTP 日志格式”中定义的默认 HTTP CLF 日志格式的值。它可用于覆盖默认日志格式,而无需复制整个原始定义。
示例
# 将给出最终判决的规则添加到日志中 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 日志格式”中定义的 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_MWORKER:在 master-worker 模式下,此变量设置为 1。 * HAPROXY_CLI:每个进程的 stats socket 配置的监听地址,这些地址以分号分隔。 * HAPROXY_MASTER_CLI:在 master-worker 模式下,master CLI 的监听地址,以分号分隔。 * HAPROXY_STARTUP_VERSION:包含用于启动的版本,在 master-worker 模式下,这是用于启动 master 的版本,即使在更新二进制文件和重新加载之后也是如此。 * HAPROXY_BRANCH:包含 HAProxy 分支版本(例如 "2.8")。它不包含完整的版本号。如果资源(如 maps 或证书)位于包含分支号的路径中,这在迁移情况下很有用。 此外,一些伪变量在内部解析,可以用作常规变量。伪变量总是以点号('.')开头,并且是唯一允许使用点号的变量。当前的伪变量列表是: * .FILE:当前正在解析的配置文件的名称。 * .LINE:当前正在解析的配置文件的行号,从一开始。 * .SECTION:当前正在解析的节的名称,如果该节没有名称(例如 "global"),则为其类型,或者在第一个节之前为空字符串。 这些变量在它们被解析的位置解析。例如,如果 ".LINE" 变量用于位于 defaults 节中的 "log-format" 指令中,它的行号将在解析和编译 "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"。 - 一个谓词,可选地后跟括号中的参数。 - 放置在一对括号 '(' 和 ')' 之间的条件 - 一个感叹号 ('!'),放在上述任何非空元素之前,它将否定其状态。 - 使用逻辑 AND ('&&') 组合的表达式,将从左到右评估,直到一个返回 false - 使用逻辑 OR ('||') 组合的表达式,将从右到左评估,直到一个返回 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>) : 如果功能 <name> 列在 "haproxy -vv" 报告的功能列表中(这意味着 <name> 出现在 '+' 之后),则返回 true - 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(<版本>):如果当前的 openssl 版本严格早于 <版本>,则返回 true,否则返回 false。像 LibreSSL、AWS-LC 和 WolfSSL 这样的库也提供一个伪 OpenSSL 版本。
示例
openssl_version_before(3.5.0)
- ssllib_name_startswith(<名称>):如果 HAProxy 链接的 SSL 库名称以 <名称> 开头,则返回 true。
示例
ssllib_name_startswith(wolfSSL)
- streq(<字符串1>,<字符串2>):仅当两个字符串相等时返回 true - strneq(<字符串1>,<字符串2>):仅当两个字符串不同时返回 true - strstr(<字符串1>,<字符串2>):仅当第二个字符串在第一个字符串中找到时返回 true。 - version_atleast(<版本>):如果当前的 haproxy 版本至少与 <版本> 一样新,则返回 true,否则返回 false。版本语法与 "haproxy -v" 显示的相同,缺失的组件被假定为零。 - version_before(<版本>):如果当前的 haproxy 版本严格早于 <版本>,则返回 true,否则返回 false。版本语法与 "haproxy -v" 显示的相同,缺失的组件被假定为零。 - enabled(<选项>):如果选项 <选项> 在运行时启用,则返回 true。仅支持一部分选项:POLL、EPOLL、KQUEUE、EVPORTS、SPLICE、GETADDRINFO、REUSEPORT、FAST-FORWARD、SERVER-SSL-VERIFY-NONE
示例
# 1. HAPROXY_MWORKER 变量由 HAProxy 在 master 和 worker 进程环境中自动设置 # (参见 2.3. 环境变量中的 HAProxy 变量矩阵)。它的存在会启用一个额外的侦听器。 global master-worker .if defined(HAPROXY_MWORKER) listen mwcli_px bind :1111 ... .endif # 2. HAPROXY_BRANCH 由 HAProxy 在 master 和 worker 进程环境中自动设置 # (参见 2.3. 环境变量中的 HAProxy 变量矩阵)。我们检查 HAPROXY_BRANCH 值并有条件地启用 # mworker-max-reloads 参数。 global master-worker .if streq("$HAPROXY_BRANCH",3.1) mworker-max-reloads 5 .endif # 3. 一些任意环境变量由用户在 global 部分设置。如果 HAProxy 以 master-worker 模式启动, # 它们将呈现在 master 和 worker 进程环境中。我们检查这些变量的值并有条件地启用端口 80 和 443。 # 环境变量检查可以与功能和版本检查混合使用。 global setenv WITH_SSL yes unsetenv SSL_ONLY .if strneq("$SSL_ONLY",yes) bind :80 .endif .if streq("$WITH_SSL",yes) .if feature(OPENSSL) bind :443 ssl crt ... .endif .endif .if feature(OPENSSL) && (streq("$WITH_SSL",yes) || streq("$SSL_ONLY",yes)) bind :443 ssl crt ... .endif .if version_atleast(2.4-dev19) profiling.memory on .endif .if !feature(OPENSSL) .alert "SSL support is mandatory" .endif
还提供了另外四个指令来报告某些状态: - .diag "message" : 仅在诊断模式(-dD)下发出此消息 - .notice "message" : 以 NOTICE 级别发出此消息 - .warning "message" : 以 WARNING 级别发出此消息 - .alert "message" : 以 ALERT 级别发出此消息 如果启用了 "zero-warning",以 WARNING 级别发出的消息可能导致进程启动失败。以 ALERT 级别发出的消息将始终导致致命错误。这些可以用来检测一些不适当的条件并向用户提供建议。
示例
.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: 切换到 2.4 后将 'redirect' 替换为 'return'" 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 配置中,变量可以在示例获取函数、转换器、log-format 字符串或 TCP/HTTP 操作中使用。可以定义进程范围的变量,在进程的整个生命周期内全局可访问。其他一些变量的生命周期较短。变量类似于 shell 脚本中找到的变量。它是内存块的符号名称。变量大小不受限制且动态分配。因此必须谨慎使用,特别是对于密集使用。但是,可以通过设置 "tune.vars" 全局参数来限制变量使用的最大内存量。 变量必须使用 "<scope>.<name>" 格式指定。<scope> 是一个单词,表示变量的生命周期。<name> 部分在范围内可能只包含字符 'a-z'、'A-Z'、'0-9' 和 '_'。它在此范围内是唯一的,但不同范围中的相同名称可以用于指代不同的变量。 支持的范围是: * proc:用于在整个进程生命周期内已知且全局可访问的变量。可以使用 "get var" 和 "set var" 命令从 CLI 操作 "proc" 变量。它们也可以通过 "set-var" 和 "set-var-fmt" 指令从 "global" 部分设置。 * 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>。fd 必须已绑定且可能已在侦听。 'ip@<address>[:port1[-port2]]' 紧跟 <address> 的被视为 IPv4 或 IPv6 地址,具体取决于语法。根据使用此地址的语句,可以或必须指定端口或端口范围。 'ipv4@<address>[:port1[-port2]]' 紧跟 <address> 的始终被视为 IPv4 地址。根据使用此地址的语句,可以或必须指定端口或端口范围。 'ipv6@<address>[:port1[-port2]]' 紧跟 <address> 的始终被视为 IPv6 地址。根据使用此地址的语句,可以或必须指定端口或端口范围。 'sockpair@<n>' 紧跟地址的是已连接的 unix socket 或 socketpair 的文件描述符。在连接期间,发起者创建一对已连接的套接字,并将其中一个通过 FD 传递给另一端。侦听器等待从 unix socket 接收 FD,并将其用作 accept() 的 FD。应谨慎使用。 错误:由于 macOS sendmsg(2) 实现中的问题,此协议在 macOS 上已知不可靠。连接可能无法正确接受。 'unix@<path>' 紧跟字符串的被视为 UNIX socket <path>。此前缀对于声明不以斜杠 '/' 开头的 UNIX socket 路径很有用。

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 socket <path>,但传输方法强制为 "datagram"。它被视为 'dgram+unix@' 的别名。 'uxst@<path>' 紧跟字符串的被视为 unix socket <path>,但传输方法强制为 "stream"。它被视为 'stream+unix@' 的别名。 在未来的版本中,可以使用其他前缀来指定 QUIC 等协议,这些协议基于 "datagram" 类型的套接字提供流传输。

2.10. 示例

# 一个简单的 HTTP 代理配置,在所有接口的 80 端口上监听,# 并将请求转发到名为 "servers" 的单个后端,该后端有一个名为 "server1" 的服务器,# 监听于 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 # 使用单个 listen 块定义的相同配置。更短但表达力较差,尤其是在 HTTP 模式下。 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
“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-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 - key-base - limited-quic - localpeer - log - log-send-hostname - log-tag - lua-load - lua-load-per-thread - lua-prepend-path - 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.small - tune.comp.maxlevel - 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.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.rxbuf - tune.h2.fe.glitches-threshold - tune.h2.fe.initial-window-size - tune.h2.fe.max-concurrent-streams - 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.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 (deprecated) - tune.quic.cc-hystart (deprecated) - tune.quic.disable-tx-pacing (deprecated) - tune.quic.disable-udp-gso (deprecated) - 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.rxbuf - tune.quic.fe.tx.pacing - tune.quic.fe.tx.udp-gso - tune.quic.frontend.max-data-size (deprecated) - tune.quic.frontend.max-idle-timeout (deprecated) - tune.quic.frontend.max-streams-bidi (deprecated) - tune.quic.frontend.max-tx-mem (deprecated) - tune.quic.frontend.stream-data-ratio (deprecated) - tune.quic.frontend.default-max-window-size (deprecated) - tune.quic.listen - tune.quic.max-frame-loss (deprecated) - tune.quic.mem.tx-max - tune.quic.reorder-ratio (deprecated) - tune.quic.retry-threshold (deprecated) - tune.quic.socket-owner (deprecated) - 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.stick-counters - tune.ssl.cachesize - tune.ssl.capture-buffer-size - tune.ssl.capture-cipherlist-size (deprecated) - tune.ssl.default-dh-param - tune.ssl.force-private-cache - tune.ssl.hard-maxrecord - tune.ssl.keylog - tune.ssl.lifetime - tune.ssl.maxrecord - tune.ssl.ssl-ctx-cache-size - tune.ssl.ocsp-update.maxdelay (deprecated) - tune.ssl.ocsp-update.mindelay (deprecated) - 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 * HTTP客户端 - httpclient.resolvers.disabled - httpclient.resolvers.id - httpclient.resolvers.prefer - httpclient.retries - httpclient.ssl.ca-file - httpclient.ssl.verify - httpclient.timeout.connect

3.1. 进程管理与安全

用于提供设备检测服务的 51Degrees 数据文件的路径。该文件应该是解压缩的,并且 HAProxy 具有相关权限可以访问。请注意,此选项仅在 HAProxy 编译时启用了 USE_51DEGREES 的情况下可用。
要从数据集中加载的 51Degrees 属性名称列表。完整的名称列表可在 51Degrees 网站上找到:https://51degrees.com/resources/property-dictionary 请注意,此选项仅在 HAProxy 编译时启用了 USE_51DEGREES 的情况下可用。
一个字符,将附加到包含 51Degrees 结果的响应头中每个属性值的末尾。如果未设置,则默认为 ','。请注意,此选项仅在 HAProxy 编译时启用了 USE_51DEGREES 的情况下可用。
将 51Degrees 转换器缓存的大小设置为 <数字> 个条目。这是一个 LRU 缓存,用于记录以前的设备检测及其结果。默认情况下,此缓存是禁用的。请注意,此选项仅在 HAProxy 编译时启用了 USE_51DEGREES 的情况下可用。
启用('on')或禁用('off')在检测过程中使用性能图。默认值取决于 51Degrees 库。请注意,此选项仅在 HAProxy 编译时启用了 USE_51DEGREES 和 51DEGREES_VER=4 的情况下可用。
启用('on')或禁用('off')在检测过程中使用预测图。默认值取决于 51Degrees 库。请注意,此选项仅在 HAProxy 编译时启用了 USE_51DEGREES 和 51DEGREES_VER=4 的情况下可用。
设置检测可以允许的漂移值。请注意,此选项仅在 HAProxy 编译时启用了 USE_51DEGREES 和 51DEGREES_VER=4 的情况下可用。
设置检测可以允许的差异值。请注意,此选项仅在 HAProxy 编译时启用了 USE_51DEGREES 和 51DEGREES_VER=4 的情况下可用。
启用('on')或禁用('off')在检测过程中使用不匹配的节点。默认值取决于 51Degrees 库。请注意,此选项仅在 HAProxy 编译时启用了 USE_51DEGREES 和 51DEGREES_VER=4 的情况下可用。
acme.scheduler { auto | off }
启用或禁用 ACME 调度器。ACME 调度器在 HAProxy 启动时启动,它将遍历证书并在 notAfter 值超过 curtime + (notAfter - notBefore) / 12 时,或者如果 notBefore 未定义则在 7 天时启动 ACME 续订任务。然后调度器将休眠并在 12 小时后唤醒。默认值为 "auto"。
ca-base <dir>
当相对路径与 "ca-file"、"ca-verify-file" 或 "crl-file" 指令一起使用时,分配一个默认目录来获取 SSL CA 证书和 CRL。在 "ca-file"、"ca-verify-file" 和 "crl-file" 中指定的绝对位置优先并忽略 "ca-base"。
chroot <jail dir>
在降低权限之前,将当前目录更改为 <jail dir> 并在那里执行 chroot()。这提高了安全级别,以防未知漏洞被利用,因为它会使攻击者很难利用系统。这仅在进程以超级用户权限启动时有效。确保 <jail_dir> 既为空又对任何人不可写非常重要。
定义一个时间窗口,在此期间,在软停止的情况下,空闲连接和活动连接的关闭将被分散进行。收到 SIGUSR1 并且宽限期结束后(如果有的话),如果没有设置此选项,空闲连接将立即全部关闭,而活动的 HTTP 或 HTTP2 连接将在收到下一个请求后结束,方法是在 HTTP 响应中附加“Connection: close”行,或者在 HTTP2 的情况下发送 GOAWAY 帧。当设置此选项时,连接关闭将在此设定的 <time> 内分散进行。如果 close-spread-time 设置为“infinite”,则在软停止期间将禁用活动连接的关闭。“Connection: close”头将不再添加到 HTTP 响应中(或 HTTP2 的 GOAWAY),空闲连接只有在其超时到达时(基于配置中设置的各种超时)才会被关闭。
参数
<time> 是一个时间窗口(默认为毫秒),在此期间,连接关闭将在软停止操作期间分散进行,或者如果应禁用活动连接关闭,则为“infinite”。
如果使用了“hard-stop-after”选项,建议将此设置的值设置为低于该选项中使用的值,以便所有连接都有机会在进程停止前正常关闭。
定义一个由属于同一集群的多个节点共享的 ASCII 字符串密钥。它可以用于不同的用途。它至少用于为该进程实例化的所有 QUIC 连接派生无状态重置令牌。这也用于派生用于加密重试令牌的密钥。如果未设置此参数,则在进程启动时将选择一个随机值。这允许使用依赖于它的功能,尽管有一些限制。
cpu-map [auto:]<线程组>[/<线程集>] <cpu集>[,...] [...]
在某些操作系统上,可以将线程组或线程绑定到特定的 CPU 集。这意味着指定的线程永远不会在其他 CPU 上运行。 "cpu-map" 指令指定单个线程或线程组的 CPU 集。第一个参数是线程组范围,可选地后跟一个线程集。这些范围具有以下格式: all | odd | even | number[-[number]] <number> 必须是 1 到 32 或 64 之间的数字,具体取决于机器的字大小。任何大于 'thread-groups' 的组 ID 和大于机器字大小的线程 ID 都将被忽略。所有线程编号都相对于它们所属的组。可以使用由短划线 ('-') 分隔的两个此类数字指定范围。还可以使用 "all" 一次指定所有线程,使用 "odd" 指定奇数编号,或使用 "even" 指定偶数编号,就像使用 "thread" 绑定指令一样。 第二个和后续参数是 CPU 集。每个 CPU 集要么是一个唯一的数字(从第一个 CPU 的 0 开始),要么是由短划线 ('-') 分隔的两个此类数字的范围。这些 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 # 将第一个组的所有线程绑定到 # 前 4 个 CPU cpu-map 1/1- 0- # 将被 "cpu-map 1/1-64 0-63" 或 "cpu-map 1/1-32 0-31" 替换, # 具体取决于机器的字大小。 # 所有这些行都将线程 1 绑定到 cpu 0,线程 2 绑定到 cpu 1,依此类推。 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 # 使用 all/odd/even 关键字将每个线程绑定到恰好一个 CPU cpu-map auto:1/all 0-63 cpu-map auto:1/even 0-31 cpu-map auto:1/odd 32-63 # 无效的 cpu-map,因为线程集和 CPU 集大小不同。 cpu-map auto:1/1-4 0 # 无效 cpu-map auto:1/1 0-3 # 无效 # 将这 4 个组的 40 个线程映射到单个 CPU 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 # 将 80 个线程映射到一个物理套接字,将另外 80 个映射到另一个套接字, # 不强制分配。这些被分成 4 个组,因为没有一个组可以有超过 64 个线程。 cpu-map 1/1-40 0-39,80-119 # node0,兄弟 0 和 1 cpu-map 2/1-40 0-39,80-119 cpu-map 3/1-40 40-79,120-159 # node1,兄弟 0 和 1 cpu-map 4/1-40 40-79,120-159
cpu-policy <policy>
选择要使用的 CPU 分配策略。在多 CPU 系统上,有很多原因不使用所有可用的 CPU 内核,和/或将它们分组到不同的线程组中,以实现性能、延迟、成本或系统范围的资源管理。 "cpu-set" 指令已经允许驱逐其中一些,但完成后,需要决定如何将剩余的 CPU 分配给线程和线程组。这种映射通常是使用 "cpu-map" 指令执行的,尽管在异构系统上维护它可能特别困难。 "cpu-policy" 指令在不使用 "cpu-map" 时选择要使用的少数分配策略之一。目前支持以下策略,其中 "performance" 是默认策略: - none 不执行特定的后选择。所有启用的 CPU 都将可用,并且如果未设置线程数,它将设置为可用 CPU 的数量,但每个线程组不超过 32 个(对于 32 位系统)或 64 个(对于 64 位系统)。如果未设置线程组数,它将设置为 1。 - efficiency 与下面的 "group-by-ccx" 完全相同,不同之处在于,性能比下一个性能较低的内核高出 25% 以上的由内核组成的 CPU 集群将被驱逐。这些通常是“大”或“性能”内核。这意味着如果检测到多种类型的 CPU 内核,将只使用高效的内核。这对于适度的负载可能是有意义的,此时最强大的内核需要可用于应用程序或安全组件。一些现代 CPU 拥有大量此类高效 CPU 内核,它们可以集体提供可观的性能水平,同时使用更少的电量。 - first-usable-node 如果 CPU 以前未在启动时受限(例如使用 "taskset" 实用程序),并且如果未设置 "nbthread" 指令,则将使用第一个具有启用 CPU 的 NUMA 节点,并且此数量的 CPU 将用作线程数。将启用一个线程组,其中包含所有这些线程,限制为 32 或 64,具体取决于系统。 - group-by-2-ccx 与下面的 "group-by-ccx" 相同,但每两个 CCX 创建一个组。这对于具有许多 CCX 且每个 CCX 具有少量内核的 CPU 可能有意义,以避免创建许多组,或者在并非所有内核都在使用时稍微平滑分布。请注意,当 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 创建一个组。这对于具有许多 CCX 且每个 CCX 具有少量内核的 CPU 可能有意义,以避免创建许多组,或者在并非所有内核都在使用时稍微平滑分布。请注意,当 CCX 之间的通信缓慢时,这可能会产生非常糟糕的性能影响。通常不建议这样做。 - group-by-4-clusters 与 "group-by-cluster" 相同,但每四个集群创建一个组。这对于具有许多集群且每个集群具有少量内核的 CPU 可能有意义,以避免创建许多组,或者在并非所有内核都在使用时稍微平滑分布。请注意,当集群之间的通信缓慢时,这可能会产生非常糟糕的性能影响。通常不建议这样做。 - group-by-ccx 如果既没有设置 "nbthread" 也没有设置 "nbtgroups",则为每个具有可用 CPU 的 CPU 核心复合体 ("CCX") 创建一个线程组,每个组的线程数与 CPU 数相同。CCX 将具有相似快速访问最后一级缓存 ("LLC") 的 CPU 分组在一起,通常是 L3 缓存。在大多数现代机器上,为了性能,将来自不同 CCX 的 CPU 混合在同一个线程组中至关重要。然后,组中的所有线程都绑定到 CCX 的所有 CPU,以便组内通信保持在 CCX 内部,而不会强制执行过强的绑定。尊重每组线程限制和线程组限制。建议在多插槽和 NUMA 系统以及具有不良 CCX 间延迟的 CPU 上使用此功能。 - group-by-cluster 如果既没有设置 "nbthread" 也没有设置 "nbtgroups",则为每个具有可用 CPU 的 CPU 集群创建一个线程组,每个组的线程数与 CPU 数相同。组中的所有线程都绑定到集群的所有 CPU,以便组内通信保持在集群内部,而不会强制执行过强的绑定。尊重每组线程限制和线程组限制。建议在多插槽和 NUMA 系统以及具有不良 CCX 间延迟的 CPU 上使用此功能。在大多数服务器机器上,集群和 CCX 是相同的,但在异构机器上(“性能”与“效率”或“大”与“小”),集群通常由 CCX 的一部分组成,仅由非常相似的 CPU 组成(相同类型,频率差异最大 +/-5%)。这种差异在开发人员和管理员用于验证设置的现代笔记本电脑和台式机上可见。 - performance 与上面的 "group-by-ccx" 完全相同,不同之处在于,性能低于下一个性能更高的内核 80% 的由内核组成的 CPU 集群将被驱逐。这些通常是“小”或“高效”内核,它们的添加通常不会带来显著的收益,并且很容易适得其反(例如 TLS 握手)。通常,将此类内核保留用于其他任务(例如网络处理)会更有效。在开发系统上,这些内核也可以用于运行辅助工具,例如负载生成器和监控工具。这是默认策略。 - resource 这与上面的 "group-by-cluster" 类似,不同之处在于只使用最小且最有效的 CPU 集群,而所有其他集群将被忽略。这可用于将资源使用限制在仍能提供可观性能的最低限度,例如尝试进一步降低功耗或最小化某些租赁系统上用于 sidecar 设置所需的内核数量,以便更容易地缩减系统规模。请注意,如果只有一个集群存在,它仍将完全使用。
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
crt-base <dir>
当相对路径与 "crtfile" 或 "crt" 指令一起使用时,分配一个默认目录来获取 SSL 证书。指定的绝对位置优先并忽略 "crt-base"。
使进程 fork 到后台运行。这是推荐的操作模式。它等同于命令行参数 "-D"。它可以通过命令行参数 "-db" 禁用。此选项在 systemd 模式下被忽略。
default-path { current | config | parent | origin <path> }
默认情况下,HAProxy 从进程启动位置加载由相对路径指定的所有文件。在某些情况下,可能需要强制所有相对路径从不同位置开始,就像进程是从这些位置启动的一样。这就是此指令的目的。从技术上讲,它将在处理每个配置文件时执行对指定位置的临时 chdir(),并在处理每个文件后返回原始目录。 它需要一个参数,指示加载路径不以斜杠 ('/') 开头的文件时使用的策略: - "current" 指示所有相对文件都从进程启动的目录加载;这是默认设置。 - "config" 指示所有相对文件都应从包含配置文件的目录加载。更具体地说,如果配置文件包含斜杠 ('/'),则使用到最后一个斜杠的最长部分作为要更改的目录,否则使用当前目录。此模式便于将 maps、errorfiles、证书和 Lua 脚本捆绑在一起作为可重定位包。当加载多个配置文件时,目录会为每个文件更新。 - "parent" 指示所有相对文件都应从包含配置文件的目录的父目录加载。更具体地说,如果配置文件包含斜杠 ('/'),则将 ".." 附加到到最后一个斜杠的最长部分作为要更改的目录,否则目录为 ".."。此模式便于将 maps、errorfiles、证书和 Lua 脚本捆绑在一起作为可重定位包,但每个部分位于不同的子目录中(例如 "config/"、"certs/"、"maps/" 等)。 - "origin" 指示所有相对文件都应从指定的(必需的)路径加载。这可用于简化在系统上并行运行的不同 HAProxy 实例的管理,其中每个实例使用不同的前缀,但其余部分易于重定位。 每个 "default-path" 指令会立即替换任何前一个指令,并可能导致切换到不同的目录。虽然这应该始终导致所需的行为,但使用多个 default-path 指令确实不是一个好的做法,如果使用,策略应在所有配置文件中保持一致。 警告:某些配置元素(例如 maps 或证书)由其配置的路径唯一标识。通过使用可重定位布局,它们中的几个可能最终具有相同的唯一名称,使其难以在运行时更新,尤其是在从不同目录加载多个配置文件时。在采用相对路径之前,必须遵守严格的无冲突文件命名方案。一种健壮的方法可以包括将所有文件名前缀为其各自的站点名称,或者在目录级别执行此操作。
添加描述实例的文本。请注意,需要转义某些字符(例如 #),并且此文本将插入 HTML 页面中,因此您应避免使用“<”和“>”字符。
设置要由 API 加载的 DeviceAtlas JSON 数据文件的路径。该路径必须是一个有效的 JSON 数据文件,并且 HAProxy 进程可以访问。
设置 API 返回的信息级别。此指令是可选的,如果未设置,则默认为 0。
设置用于检测请求期间是否使用了 DeviceAtlas 客户端组件的客户端 cookie 名称。此指令是可选的,如果未设置,则默认为 DAPROPS。
设置 API 属性结果的字符分隔符。此指令是可选的,如果未设置,则默认为 |。
dns-accept-family <family>[,...]
By default, DNS resolvers accept both IPv4 and IPv6 addresses. This can be influenced by the "resolve-prefer" keywords on server lines as well as the family argument to the "do-resolve" action, but that is only a preference, which does not block the other family from being used when it's alone. In some environments where dual-stack is not usable, stumbling on an unreachable IPv6-only DNS record can cause significant trouble as it will replace a previous IPv4 one which would possibly have continued to work till next request. The "dns-accept-family" global option permits to enforce usage of only one (or both) address families. The argument is a comma-delimited list of the following words: - "ipv4": query and accept IPv4 addresses ("A" records) - "ipv6": query and accept IPv6 addresses ("AAAA" records) - "auto": use IPv4, and IPv6 if the system has a default gateway for it. The result of the last check is cached for 30 seconds. When a single family is used, no request will be sent to resolvers for the other family, and any response for the other family will be ignored. The default value since 3.3 is "auto", which effectively enables both families only once IPv6 has been proven to be routable, otherwise sticks to IPv4.
此声明必须在使用一些标记为已弃用的指令之前出现,以消除警告并确保配置文件不会被拒绝。并非所有已弃用的指令都受此影响,只有那些没有任何替代解决方案的指令。
此语句必须出现在使用标记为实验性的指令之前,否则配置文件将被拒绝。请注意,此选项涵盖的功能不保证能正常工作,并且在维护周期中可能会中断。开发人员将在开发下一版本期间尽最大努力维护它们,并将尽一切合理的努力避免破坏它们,但不能保证。由于这些原因,这些功能预计在下一个 LTS 版本发布后将不再受支持。希望试用实验性功能的用户应迅速升级以受益于对该功能的改进。为了知道是否仍需要此指令,方法很简单:如果在未使用任何此类功能的情况下启用它,将发出警告,建议将其关闭。因此,如果没有警告,则表示仍然需要它。
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>
设置进程将使用的最大文件描述符数的上限,无论系统限制如何。虽然 "ulimit-n" 和 "maxconn" 可用于强制执行某个值,但当未设置时,进程将受限于 "ulimit -n -H" 报告的 RLIMIT_NOFILE 设置的硬限制。但一些现代操作系统现在允许在这里设置极大的值(数量级为 10 亿),这对于常规使用会消耗过多的内存。提供 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
gid <number>
将进程的组 ID 更改为 <number>。建议将组 ID 专用于 HAProxy 或一小部分类似的守护程序。HAProxy 必须以属于此组的用户或具有超级用户权限启动。请注意,如果 HAProxy 是从具有补充组的用户启动的,则只有在具有超级用户权限的情况下才能放弃这些组。另请参阅 "group" 和 "uid"。
grace <time>
定义 SIGUSR1 和实际软停止之间的延迟。
参数
<time> 是在接收到 SIGUSR1 信号后,在继续执行软停止操作之前将等待的额外延迟(默认为毫秒)。
这用于与需要停止 haproxy 进程但某些外部组件需要在解绑监听器之前检测状态的旧环境兼容。其原理是内部的 "stopping" 变量(由 "stopping" 样本获取函数报告)将被设置为 true,但监听器将继续无干扰地接受连接,直到延迟到期,之后将进行常规的软停止。这不能与重新加载的进程一起使用,否则会阻止旧进程解绑,并可能阻止新进程启动,或者只是引起麻烦。
示例
global grace 10s # 在通过 SIGUSR1 设置 stopping 之前,返回 200 OK frontend ext-check bind :9999 monitor-uri /ext-check monitor fail if { stopping }
请注意,一个更灵活、更持久的方法是让编排系统从 CLI 设置一个全局变量,使用该变量来响应外部检查,然后在延迟后发送 SIGUSR1 信号。
示例
# 在 proc.stopping 设置为非零之前返回 200 OK。可以通过 # HTTP 使用 set-var(proc.stopping) 或从 CLI 使用: # > 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 }
group <group name>
与 "gid" 类似,但使用 /etc/group 中组名 <group name> 的 GID。另请参阅 "gid" 和 "user"。
不拒绝带有负载的 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 请求。然而,这对于一些旧客户端可能是一个问题。在这种情况下,可以设置此全局选项。
根据 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>
定义在将标头名称 <from> 发送给 HTTP/1 客户端或服务器之前,将其更改为 <to> 时应用的大小写调整(如果启用)。<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"。
定义一个文件,其中包含键/值对列表,用于在将某些标头名称发送给 HTTP/1 客户端或服务器之前调整其大小写。文件 <hdrs-file> 每行必须包含 2 个标头名称。第一个必须是小写,两者除了大小写之外不得不同。以 '#' 开头的行将被忽略,空行也是如此。前导和尾随的制表符和空格将被删除。不允许重复条目。请注意,除非在代理中指定了 "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 websockets。这可用于克服在实现相对较新的 RFC8441 时遇到问题的客户端,例如 Firefox 88。要允许客户端自动降级到 http/1.1 进行 websocket 隧道,请在绑定行上使用 "alpn" 指定 h2 支持,而无需显式使用 "proto" 关键字。如果此语句先前已激活,则可以通过在关键字前加上 "no" 来禁用。
定义执行干净的软停止所允许的最长时间。
参数
<time> 是实例在通过 SIGUSR1 信号接收到软停止时将保持活动的最长时间(默认为毫秒)。
这可用于确保即使在软停止期间连接保持打开(例如,在 tcp 模式下为代理设置了长超时),实例也会退出。它适用于 TCP 和 HTTP 模式。
示例
global hard-stop-after 30s
切换每个协议的保护,禁止与使用特权端口作为其源端口的客户端进行通信。此端口范围根据 RFC 6335 定义。默认情况下,对 QUIC 协议启用保护,因为这种行为是可疑的,并可能被用作欺骗或 DNS/NTP 放大攻击。
http-err-codes [+-]<range>[,...] [...]
替换、减少或扩展定义错误的状态码列表,这些错误被终止码和粘性表中的 "http_err_cnt" 计数器所考虑。错误的默认范围是 400 到 499,但在某些情况下,一些用户更喜欢排除特定的代码,特别是在跟踪客户端错误时(例如,在动态生成内容的系统上出现 404)。另请参阅 "http-fail-codes" 和 "http_err_cnt"。不带 '+' 或 '-' 的范围会将现有范围重新定义为新范围。以 '+' 开头的范围会将现有范围扩展以包含指定的范围,该范围可能与现有范围重叠,也可能不重叠。以 '-' 开头的范围会从现有范围中删除指定的范围。范围由一个 100 到 599 之间的数字组成,可选地后跟一个 "-" 和另一个大于或等于第一个数字的数字,以指示范围的上界。多个范围可以用逗号分隔,用于同一个添加/删除/替换操作。
示例
http-err-codes 400,402-444,446-480,490 # 精确设置这些代码 http-err-codes 400-499 -450 +500 # 设置 400 到 500,除了 450 http-err-codes -450-459 # 从范围中移除 450 到 459 http-err-codes +501,505 # 将 501 和 505 添加到范围中
http-fail-codes [+-]<range>[,...] [...]
替换、减少或扩展定义失败的状态码列表,这些失败被终止码和粘性表中的 "http_fail_cnt" 计数器所考虑。失败的默认范围是 500 到 599,除了 501 和 505,它们可以由客户端触发,通常表示服务器处理请求失败。一些用户更喜欢在某些情况下排除某些代码,当已知它们不相关时,例如在某些 SOAP 环境中的 500,因为它在那里不表示服务器故障。语法与上面的 http-err-codes 完全相同。另请参阅 "http-err-codes" 和 "http_fail_cnt"。
默认情况下,HAProxy 会努力阻止在启动后创建任何线程和进程。在使用来源不确定的 Lua 文件以及试验可能仍包含漏洞(其可利用性不确定)的开发版本时,这样做尤为重要。一般来说,确保不会因流量触发任何意外的后台活动是一种良好的卫生习惯。但这会阻止外部检查工作,并可能破坏一些严重依赖 fork 能力的特定 Lua 脚本。此选项用于禁用此保护。请注意,禁用它是一个坏主意,因为一旦禁用,库中或 HAProxy 本身中的漏洞将更容易被利用。此外,从 Lua 或其他地方 fork 不可靠,因为 forked 进程可能会随机嵌入另一个线程设置的锁,并且永远无法完成操作。因此,强烈建议永远不要使用此选项,并且任何需要此类 fork 的工作负载都应重新考虑并转移到更安全的解决方案(例如,使用代理而不是外部检查)。此选项支持 "no" 前缀来禁用它。也可以通过 haproxy 命令行上的 "-dI" 激活它。
HAProxy 在运行时不需要调用可执行文件(除了使用强烈不推荐的外部检查时),甚至预计会隔离到空的 chroot 中。因此,基本上没有充分的理由允许调用 setuid 可执行文件,除非用户完全了解风险。在 HAProxy 需要调用外部检查和/或禁用 chroot 的情况下,利用库中或 HAProxy 本身中的漏洞可能导致执行外部程序。在 Linux 上,可以锁定进程,以便忽略此类可执行文件上存在的任何 setuid 位。这大大降低了在这种情况下权限升级的风险。这是 HAProxy 默认执行的操作。如果这导致外部检查出现问题(例如,需要 "ping" 命令的检查),则可以通过在全局部分明确添加此指令来禁用此保护。如果启用,可以通过在关键字前加上 "no" 来将其关闭。
分配一个目录以加载用于签发者完成的证书链。所有文件必须采用 PEM 格式。对于使用 "crt" 或 "crt-list" 加载的证书,如果证书链未包含在 PEM 中(也通常称为中间证书),HAProxy 将完成证书链,前提是证书的签发者对应于使用 "issuers-chain-path" 加载的证书链中的第一个证书。包含 PrivateKey+Certificate+IntermediateCA2+IntermediateCA1 的 "crt" 文件可以用 PrivateKey+Certificate 替换。如果 "issuers-chain-path" 目录中存在包含 IntermediateCA2+IntermediateCA1 的文件,HAProxy 将完成链。具有相同签发者的所有其他证书将共享内存中的链。当未使用 .issuer 或 PEM 中未提供链时,OCSP 功能能够使用已完成的链。
key-base <dir>
当使用 "key" 指令并使用相对路径时,指定一个用于获取 SSL 私钥的默认目录。指定的绝对路径优先,并忽略 "key-base"。此选项仅在使用 crt-store 加载行时有效。
当 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>
设置本地实例的对等名称。如果指定了 "-L" 命令行参数或在 "peers" 部分定义之后使用,它将被忽略。在这种情况下,在配置解析期间将发出警告消息。此选项还将设置 HAPROXY_LOCALPEER 环境变量。另请参阅管理指南中的 "-L" 和下面的 "peers" 部分。
log <target> [len <length>] [format <format>] [sample <ranges>:<sample_size>] [profile <prof>] <facility> [max level [min level]]
添加一个全局 syslog 服务器。可以定义多个全局服务器。它们将接收启动和退出日志,以及配置有 "log global" 的代理的所有日志。有关代理的更多详细信息,请参阅 "log" 选项。
设置 syslog 报头中的 hostname 字段。如果设置了可选的 "string" 参数,则报头将设置为该字符串内容,否则使用系统的主机名。通常在不通过中间 syslog 服务器中继日志或仅为自定义日志中打印的主机名时使用。
log-tag <string>
将 syslog 头中的标签字段设置为此字符串。它默认为从命令行启动的程序名称,通常是 "haproxy"。有时,区分在同一主机上运行的多个进程可能很有用。另请参阅每个代理的 "log-tag" 指令。
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 文件加载并执行到每个启动的线程中。任何全局变量都具有线程本地可见性,因此每个线程可以看到不同的值。因此,强烈建议不要在以这种方式加载的程序中使用全局变量。对于每个线程,都会加载并初始化一个独立的副本,一切都按线程的数字顺序从 1 到 nbthread 顺序完成。如果某些操作只需要执行一次,程序应该检查 "core.thread" 变量以找出正在初始化的线程。以这种方式加载的程序将在所有线程上并发运行,并且具有高度可扩展性。这是加载注册样本获取器、转换器、操作或服务的简单函数的推荐方法,前提是确定程序不依赖于全局变量。为了简单起见,即使只使用一个线程,甚至禁用线程(在这种情况下,它将等同于 lua-load),此指令也可用。此指令可以多次使用。有关 args 的用法,请参阅 lua-load。
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"` 时,Lua 将首先尝试加载 /usr/share/haproxy-lua/example.lua 脚本,如果不存在,则将尝试加载 /usr/share/haproxy-lua/example/init.lua,如果仍不存在,则尝试加载默认路径。有关详细信息,请参阅 Lua 文档中的 https://lua.ac.cn/pil/8.1.html。
master-worker (deprecated)
主-工作模式。它等同于命令行 "-W" 参数。此关键字已弃用,请使用 "-W" 或 "-Ws" 启动主-工作模式。此模式将启动一个 "master",它将在读取配置后 fork 一个 "worker" 来处理流量。master 用作进程管理器,将监视 "worker"。使用此模式,您可以通过向 master 发送 SIGUSR2 信号来直接重新加载 HAProxy。重新加载将要求 master 再次读取配置并 fork 一个新的 worker。前一个 worker 将保留直到其作业结束。主-工作模式与前台或守护程序模式兼容。默认情况下,如果 worker 以错误的返回码退出(例如发生段错误),所有 worker 都将被终止,并且 master 将退出。将此行为与 systemd 单元文件中的 Restart=on-failure 结合使用很方便,以便重新启动整个进程。如果您不希望这种行为,则必须使用关键字 "no-exit-on-failure"。另请参阅管理指南中的 "-W"。
在主-工作模式下,默认情况下,如果 worker 以错误的返回码退出(例如发生段错误),所有 worker 都将被终止,并且 master 将退出。将此行为与 systemd 单元文件中的 Restart=on-failure 结合使用很方便,以便重新启动整个进程。此关键字允许在 worker 崩溃时保持其余进程活动,而不是终止所有进程。使用时需要谨慎,因为它仅用于调试,并可能使 master 进程处于异常状态。
在主-工作模式下,此选项限制了 worker 在重新加载后可以存活的次数。如果 worker 在重新加载后没有退出,一旦其重新加载次数大于此数字,worker 将收到 SIGTERM。此选项有助于控制 worker 的数量。另请参阅管理指南中的 "show proc"。默认情况下,此值设置为 50。
nbthread <number>
此设置仅在内置线程支持时可用。它使 HAProxy 在 <number> 个线程上运行。“nbthread” 在 HAProxy 在前台启动时也有效。在某些支持 CPU 亲和性的平台上,默认的 “nbthread” 值会自动设置为启动时进程绑定的 CPU 数量。这意味着线程数可以轻松地从调用进程中使用 "taskset" 或 "cpuset" 等命令进行调整。否则,此值默认为 1。默认值在 "haproxy -vv" 的输出中报告。请注意,此处设置或自动检测的值受 “thread-hard-limit”(如果设置)设置的限制。
当在支持 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 ]
完全禁用 HAProxy 中的 ocsp-update。任何 ocsp-update 配置都将被忽略。默认为 "off"。有关自动更新机制的更多信息,请参阅选项 "ocsp-update"。
ocsp-update.httpproxy <address>[:port]
允许为 OCSP 更新使用 HTTP 代理。这仅适用于 HTTP,不支持 HTTPS。此选项将允许 OCSP 更新器在请求中向代理发送绝对 URI。
tune.ssl.ocsp-update.maxdelay <number> (已弃用)
设置同一 OCSP 响应两次自动更新之间的最大间隔。此时间以秒表示,默认为 3600(1 小时)。它必须设置为高于 “ocsp-update.mindelay” 的值。有关自动更新机制的更多信息,请参阅选项 “ocsp-update”。
tune.ssl.ocsp-update.mindelay <number> (已弃用)
设置同一 OCSP 响应两次自动更新之间的最小间隔。此时间以秒表示,默认为 300(5 分钟)。它对于没有明确过期时间的 OCSP 响应特别有用。它必须设置为低于 “ocsp-update.maxdelay” 的值。有关自动更新机制的更多信息,请参阅选项 “ocsp-update”。
ocsp-update.mode [ on | off ]
为配置中使用的所有证书设置默认的 ocsp-update 模式。此全局选项可以被 crt-list 的 “ocsp-update” 选项覆盖。此选项默认设置为 "off"。有关自动更新机制的更多信息,请参阅选项 “ocsp-update”。
pidfile <pidfile>
在守护进程模式下,将所有守护进程的 PID 写入文件 <pidfile>;在主-工作者模式下,将主进程的 PID 写入文件 <pidfile>。此选项等同于 "-p" 命令行参数。该文件必须对启动进程的用户可访问。另请参阅 "daemon" 和 "master-worker"。
PROXY 协议 v2 实现中的一个错误存在于 HAProxy 2.1 之前的版本中,导致它为健康检查发出 PROXY 命令而不是 LOCAL 命令。这问题特别微小,但会混淆一些服务器的日志。遗憾的是,这个错误发现得很晚,并揭示出一些可能只针对 HAProxy 测试其 PROXY 协议实现的服务器无法正确处理 LOCAL 命令,并在 HAProxy 检查它们时永久保持在 "down" 状态。当这种情况发生时,可以启用此全局选项以恢复到旧的(错误的)行为,直到联系受影响组件的供应商并修复它们。此选项默认禁用,并作用于所有具有 "send-proxy-v2" 语句的服务器。
presetenv <name> <value>
将环境变量 <name> 设置为值 <value>。如果该变量已存在,则不会被覆盖。更改会立即生效,以便配置文件中的下一行可以看到新值。另请参阅 "setenv"、"resetenv" 和 "unsetenv"。
执行一次性打开最大文件描述符的操作,从而预分配内核的数据结构。这可以防止当 nbthread>1 且 HAProxy 打开一个需要内核扩展其数据结构的文件描述符时出现的短暂暂停。
resetenv [<name> ...]
删除除参数中指定的环境变量之外的所有环境变量。它允许在使用 setenv 或 unsetenv 设置新值之前,使用一个干净受控的环境。请注意,一些内部函数可能会使用某些环境变量,例如时间操作函数,以及 OpenSSL 甚至外部检查。此命令必须极其小心使用,并且只能在完全验证后使用。更改会立即生效,因此配置文件中的下一行将看到新的环境。另请参阅 “setenv”、“presetenv” 和 “unsetenv”。
server-state-base <directory>
指定目录前缀,该前缀将附加在所有不以“/”开头的服务器状态文件名前面。另请参阅 "server-state-file"、"load-server-state-from-file" 和 "server-state-file-name"。
指定包含服务器状态的文件路径。如果路径以斜杠('/')开头,则视为绝对路径,否则视为相对于使用 "server-state-base" 指定的目录(如果已设置)或当前目录。在重新加载 HAProxy 之前,可以使用统计命令 "show servers state" 保存服务器的当前状态。该命令的输出必须写入 <file> 指向的文件中。启动时,在处理流量之前,HAProxy 将读取、加载并应用文件中找到且在其当前运行配置中可用的每个服务器的状态。另请参阅 "server-state-base" 和 "show servers state"、"load-server-state-from-file" 和 "server-state-file-name"。
此选项最好默认禁用,仅在开发人员要求时才启用。如果已启用,仍可以通过在其前加上 "no" 关键字来强制禁用。它对性能或稳定性没有影响,但会努力重新启用可能因文件大小限制 (ulimit -f)、核心大小限制 (ulimit -c) 或更改其 UID/GID 后进程的 "可转储性"(例如 Linux 上的 /proc/sys/fs/suid_dumpable)而禁用的核心转储。核心转储可能仍然受当前目录权限(检查启动文件的目录)、chroot 目录权限(可能需要暂时禁用 chroot 指令或将其移动到专用的可写位置)或任何其他系统特定约束的限制。例如,一些 Linux 发行版以将默认核心文件替换为系统上甚至未安装的可执行文件路径而闻名(检查 /proc/sys/kernel/core_pattern)。通常,只需写入 "core"、"core.%p" 或 "/var/log/core/core.%p" 即可解决问题。当尝试启用此选项以等待罕见问题重新出现时,通常最好先尝试通过向 "haproxy" 进程发出 "kill -11" 等命令来获取此类转储,并验证它在死亡时是否在预期位置留下核心文件。
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>
将进程范围变量“<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>...]
设置在以非 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>
将环境变量 <name> 设置为值 <value>。如果该变量存在,则会被覆盖。更改会立即生效,因此配置文件中的下一行将看到新的值。另请参阅 “presetenv”、“resetenv” 和 “unsetenv”。
shm-stats-file <name> [ EXPERIMENTAL ]
设置此指令后,它将启用使用共享内存来存储统计计数器。<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> [ EXPERIMENTAL ]
此设置定义了用于共享计数器的共享内存能够存储的每个线程组的最大对象数。它与 shm 的最大内存大小直接相关,用于将 shm "预映射"到给定大小,以避免运行时重新映射。它默认为 2k,这应该适用于大多数设置,而不会有不合适的内存使用风险,但如果需要,可以轻松更改。如果此值太低而无法注册预期存储在共享内存中的对象,haproxy 将在启动期间发出警告。它仅在定义了 "shm-stats-file" 时才相关。另请参阅 "thread-groups"
此设置仅在内置 OpenSSL 支持时可用。它设置了默认字符串,描述了在 SSL/TLS 握手期间协商的密码算法列表("cipher suite"),直到 TLSv1.2,适用于所有未显式定义其密码算法列表的 "bind" 行。字符串格式在 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" 关键字以获取更多信息。
此设置仅在内置 OpenSSL 支持且使用 OpenSSL 1.1.1 或更高版本构建 HAProxy 时可用。它设置了默认字符串,描述了在 TLSv1.3 握手期间协商的密码算法列表("cipher suite"),适用于所有未显式定义其密码算法列表的 "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
此设置仅在内置 OpenSSL 支持时可用。它设置了默认字符串,描述了与客户端身份验证相关的签名算法列表,适用于所有未显式定义其签名算法列表的 "bind" 行。字符串格式是以冒号分隔的签名算法列表。每个签名算法可以使用两种形式之一:TLS1.3 签名方案名称 ("rsa_pss_rsae_sha256") 或公钥算法 + 摘要形式 ("ECDSA+SHA256")。列表可以包含两种形式。有关格式的更多信息,请参阅 SSL_CTX_set1_client_sigalgs(3)。签名算法列表也可在 RFC8446 section 4.2.3 和 OpenSSL 的 ssl/t1_lib.c 文件中找到。此设置不适用于 TLSv1.1 及更早版本的协议,因为这些版本中不会单独协商签名算法。除非需要与中间盒兼容,否则不建议更改此设置。
此设置仅在内置 OpenSSL 支持时可用。它设置了在使用 ECDHE 进行 SSL/TLS 握手期间协商的椭圆曲线算法列表(“曲线套件”)的默认字符串。该字符串的格式是一个以冒号分隔的曲线名称列表。请检查 “bind” 关键字以获取更多信息。
此设置仅在内置 OpenSSL 支持时可用。它设置了默认的 ssl 选项,以强制应用于所有 "bind" 行。请检查 "bind" 关键字以查看可用选项。
示例
global ssl-default-bind-options ssl-min-ver TLSv1.0 no-tls-tickets
此设置仅在内置 OpenSSL 支持时可用。它设置了默认字符串,描述了在 TLSv1.2 和 TLSv1.3 握手期间协商的签名算法列表,适用于所有未显式定义其签名算法列表的 "bind" 行。字符串格式是以冒号分隔的签名算法列表。每个签名算法可以使用两种形式之一:TLS1.3 签名方案名称 ("rsa_pss_rsae_sha256") 或公钥算法 + 摘要形式 ("ECDSA+SHA256")。列表可以包含两种形式。有关格式的更多信息,请参阅 SSL_CTX_set1_sigalgs(3)。签名算法列表也可在 RFC8446 section 4.2.3 和 OpenSSL 的 ssl/t1_lib.c 文件中找到。此设置不适用于 TLSv1.1 及更早版本的协议,因为这些版本中不会单独协商签名算法。除非需要与中间盒兼容,否则不建议更改此设置。
此设置仅在内置 OpenSSL 支持时可用。它设置了默认字符串,描述了在 SSL/TLS 握手期间与服务器协商的密码算法列表,直到 TLSv1.2,适用于所有未显式定义其密码算法列表的 "server" 行。字符串格式在 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" 关键字以获取更多信息。
此设置仅在内置 OpenSSL 支持且使用 OpenSSL 1.1.1 或更高版本构建 HAProxy 时可用。它设置了默认字符串,描述了在 TLSv1.3 握手期间与服务器协商的密码算法列表,适用于所有未显式定义其密码算法列表的 "server" 行。字符串格式在 OpenSSL 手册页中的 "man 1 ciphers" 中 "ciphersuites" 部分定义。对于 TLSv1.2 及更早版本的密码配置,请检查 "ssl-default-server-ciphers" 关键字。请检查 "server" 关键字以获取更多信息。
此设置仅在内置 OpenSSL 支持时可用。它设置了默认字符串,描述了与客户端身份验证相关的签名算法列表,适用于所有未显式定义其签名算法列表的 "server" 行。字符串格式是以冒号分隔的签名算法列表。每个签名算法可以使用两种形式之一:TLS1.3 签名方案名称 ("rsa_pss_rsae_sha256") 或公钥算法 + 摘要形式 ("ECDSA+SHA256")。列表可以包含两种形式。有关格式的更多信息,请参阅 SSL_CTX_set1_client_sigalgs(3)。签名算法列表也可在 RFC8446 section 4.2.3 和 OpenSSL 的 ssl/t1_lib.c 文件中找到。此设置不适用于 TLSv1.1 及更早版本的协议,因为这些版本中不会单独协商签名算法。除非需要与中间盒兼容,否则不建议更改此设置。
此设置仅在内置 OpenSSL 支持时可用。它设置了在使用 ECDHE 进行 SSL/TLS 握手期间协商的椭圆曲线算法列表(“曲线套件”)的默认字符串。该字符串的格式是一个以冒号分隔的曲线名称列表。请检查 “server” 关键字以获取更多信息。
此设置仅在内置 OpenSSL 支持时可用。它设置了默认的 ssl 选项,以强制应用于所有 "server" 行。请检查 "server" 关键字以查看可用选项。
此设置仅在内置 OpenSSL 支持时可用。它设置了默认字符串,描述了在 TLSv1.2 和 TLSv1.3 握手期间协商的签名算法列表,适用于所有未显式定义其签名算法列表的 "server" 行。字符串格式是以冒号分隔的签名算法列表。每个签名算法可以使用两种形式之一:TLS1.3 签名方案名称 ("rsa_pss_rsae_sha256") 或公钥算法 + 摘要形式 ("ECDSA+SHA256")。列表可以包含两种形式。有关格式的更多信息,请参阅 SSL_CTX_set1_sigalgs(3)。签名算法列表也可在 RFC8446 section 4.2.3 和 OpenSSL 的 ssl/t1_lib.c 文件中找到。此设置不适用于 TLSv1.1 及更早版本的协议,因为这些版本中不会单独协商签名算法。除非需要与中间盒兼容,否则不建议更改此设置。
此设置仅在内置 OpenSSL 支持时可用。它设置了默认 DH 参数,用于在 SSL/TLS 握手期间使用短暂 Diffie-Hellman (DHE) 密钥交换时,适用于所有未显式定义其参数的 "bind" 行。如果绑定证书文件中包含自定义 DH 参数,则此设置将被覆盖。如果未使用 ssl-dh-param-file 或未直接在证书文件中设置自定义 DH 参数,则不会使用 DHE 密码,除非设置了 tune.ssl.default-dh-param。在后一种情况下,将使用指定大小的预定义 DH 参数。自定义参数已知更安全,因此建议使用。可以通过使用 OpenSSL 命令 "openssl dhparam <size>" 生成自定义 DH 参数,其中 size 应至少为 2048,因为 1024 位 DH 参数不应再被视为安全。
ssl-passphrase-cmd <cmd> <args> ...
此设置仅在内置 OpenSSL 支持时可用。它允许定义一个完整的命令行,该命令行将在初始化期间加载加密证书时调用。该命令可以是脚本或任何其他程序。它将提供加密私钥路径作为第一个参数,然后是用户定义的 "args" 参数,并且应该将允许解码加密私钥的密码短语转储到标准输出。对于在初始化期间加载的每个新的加密私钥,HAProxy 将首先尝试所有其他已知的密码短语来解码私钥,如果都不起作用,则最终会再次调用密码短语命令。
此设置仅在内置 OpenSSL 支持且 OpenSSL 版本至少为 3.0 时可用。它允许定义在提供程序中获取算法时使用的默认属性字符串。它的行为方式与 openssl propquery 选项相同,并遵循相同的语法(在 https://www.openssl.org/docs/man3.0/man7/property.html 中描述)。例如,如果您加载了两个提供程序,foo 和默认提供程序,则 propquery “?provider=foo” 允许默认选择由 foo 提供程序提供的算法实现,如果找不到,则回退到默认提供程序的实现。
此设置仅在内置 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"。
此设置仅在内置 OpenSSL 支持且 OpenSSL 版本至少为 3.0 时可用。它允许指定 OpenSSL 用于查找提供程序的搜索路径。它的行为方式与 OPENSSL_MODULES 环境变量相同。它将用于任何后续的 “ssl-provider” 选项,直到定义新的 “ssl-provider-path”。另请参阅 “ssl-provider”。
此设置允许配置 HAProxy 查找额外 SSL 文件的方式。默认情况下,HAProxy 会在文件名后添加一个新的扩展名。(例如:对于 “foobar.crt”,加载 “foobar.crt.key”)。启用此选项后,HAProxy 会在添加新扩展名之前删除原扩展名(例如:对于 “foobar.crt”,加载 “foobar.key”)。您的 crt 文件必须具有 “.crt” 扩展名才能使此选项生效。此选项与捆绑扩展名(.ecdsa、.rsa、.dsa)不兼容,并且不会尝试删除它们。此选项默认禁用。另请参阅 “ssl-load-extra-files”。
ssl-load-extra-files <none|all|bundle|sctl|ocsp|issuer|key>*
此设置更改了 HAProxy 在加载 SSL 证书期间查找未指定文件的方式。此选项适用于与 "bind" 行以及 "server" 行关联的证书,但某些额外文件对 "server" 行证书没有任何功能影响。默认情况下,HAProxy 会自动发现配置中未指定的许多文件,如果需要优化启动时间,您可能希望禁用此行为。"none":仅加载配置中指定的文件。如果文件不存在,请勿尝试加载证书包。如果是目录,则不会尝试捆绑具有相同基本名称的证书。"all":这是默认行为,它将尝试加载所有内容,包括包、sctl、ocsp、issuer、key。"bundle":当配置中指定的文件不存在时,HAProxy 将尝试加载 "cert bundle"。证书包仅在前端管理,不适用于后端证书。从 HAProxy 2.3 开始,包不再加载到相同的 OpenSSL 证书存储中,而是将每个证书加载到单独的存储中,这等同于声明多个 "crt"。需要 OpenSSL 1.1.1 才能实现此目的。这意味着包现在仅用于向后兼容,并且不再是执行混合 RSA/ECC 绑定配置所必需的。要将这些 PEM 文件关联到 HAProxy 识别的 "cert bundle" 中,必须按以下方式命名它们:所有要捆绑的 PEM 文件必须具有相同的基本名称,并带有指示密钥类型的后缀。目前支持三个后缀:rsa、dsa 和 ecdsa。例如,如果 www.example.com 有两个 PEM 文件,一个 RSA 文件和一个 ECDSA 文件,则必须命名为:"example.pem.rsa" 和 "example.pem.ecdsa"。文件名中的第一部分是任意的;只有后缀才重要。要将此包加载到 HAProxy 中,只需指定基本名称
Example
bind :8443 ssl crt example.pem
请注意,后缀未提供给 HAProxy;这告诉 HAProxy 查找证书包。HAProxy 将加载包中的所有 PEM 文件,就像它们是单独配置在多个 "crt" 中一样。包加载不再对目录加载产生影响,因为文件是单独加载的。在 CLI 上,包被视为单独的文件,并且需要包扩展名才能提交它们。OCSP 文件 (.ocsp)、签发者文件 (.issuer)、证书透明度 (.sctl) 以及私钥 (.key) 支持多证书捆绑。"sctl":尝试为每个 crt 关键字加载 "<basename>.sctl"。如果为后端证书提供,它将被加载但不会产生任何功能影响。"ocsp":尝试为每个 crt 关键字加载 "<basename>.ocsp"。如果为后端证书提供,它将被加载但不会产生任何功能影响。"issuer":如果 PEM 文件中未提供 OCSP 文件的签发者,请尝试加载 "<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
此指令允许选择 OpenSSL 安全级别,如 https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_security_level.html 中所述。该安全级别将应用于 HAProxy 中的每个 SSL 上下文。仅支持 0 到 5 之间的值。默认值取决于您的 OpenSSL 版本、发行版以及库的编译方式。此指令至少需要 OpenSSL 1.1.1。
ssl-server-verify [none|required]
服务器端 SSL 验证的默认行为。如果指定为 'none',则不验证服务器证书。默认值为 'required',除非使用命令行选项 '-dV' 强制指定。
自签发 CA,即 x509 根 CA,是证书链验证的锚点:作为服务器发送它是无用的,客户端必须拥有它。标准配置需要不在 PEM 文件中包含此类 CA。此选项允许您在 PEM 文件中保留此类 CA 而不将其发送给客户端。用例是为 ocsp 提供颁发者,而无需“.issuer”文件,并能够与“issuers-chain-path”共享它。这涉及所有没有中间证书的证书。对于 BoringSSL 来说是无用的,.issuer 被忽略,因为 ocsp 位不需要它。至少需要 OpenSSL 1.0.2。
stats maxconn <connections>
默认情况下,统计套接字限制为 10 个并发连接。可以使用 "stats maxconn" 更改此值。
stats socket [<address:port>|<path>] [param*]
将 UNIX 套接字绑定到 <path> 或将 TCPv4/v6 地址绑定到 <address:port>。对此套接字的连接将返回各种统计信息输出,甚至允许发出一些命令来更改某些运行时设置。有关更多详细信息,请参阅管理指南的第 9.3 节“Unix 套接字命令”。支持“bind”行支持的所有参数,例如限制某些用户或其访问权限的访问。有关更多信息,请参阅第 5.1 节
stats timeout <timeout, in milliseconds>
统计套接字的默认超时时间设置为 10 秒。可以使用 "stats timeout" 更改此值。该值必须以毫秒为单位传递,或者带有时间单位后缀,如 { us, ms, s, m, h, d }。
stats-file <path>
生成的 haproxy stats-file 的路径。启动时,haproxy 会将值预加载到其内部计数器中。使用 CLI 命令 “dump stats-file” 生成此类 stats-file。有关更多详细信息,请参阅管理手册。
stress-level <level>
激活备用代码以对 haproxy 二进制文件进行压力测试。级别是从 0 到 9 的整数。默认值 0 禁用任何压力执行。级别从 1 到 9 将增加对 haproxy 二进制文件的压力。请注意,使用任何正数级别都可能显著损害性能。因此,除非用于调试目的并在开发人员请求时,否则绝不应激活它。
当 setrlimit 失败时,使进程在启动时失败。HAProxy 会根据计算结果尝试设置最佳的 setrlimit。如果失败,它将发出警告。此选项旨在保证当这些限制失败时 HAProxy 明确失败。它默认启用。仍可通过在其前添加“no”关键字来强制禁用它。
thread-group <group> [<thread-range>...]
此设置仅在内置线程支持时可用。它枚举了将组成线程组 <group> 的线程列表。线程号和组号从 1 开始。线程范围可以一次使用单个线程号定义,也可以通过指定由破折号“-”分隔的下限和上限来定义(例如 “1-16”)。未分配的线程将自动分配给未分配的线程组,而使用此指令定义的线程组将永远不会接收超过定义的线程数。多次定义同一组会用新的定义覆盖以前的定义。另请参阅 “nbthread” 和 “thread-groups”。
thread-groups <number>
此设置仅在内置线程支持时可用。它使 HAProxy 将其线程分成 <number> 个独立的组。目前,默认值为 1。线程组可以减少线程之间的共享以限制争用,但需要一些额外的配置工作。这也是使用超过 64 个线程的唯一方法,因为每个组最多可以配置 64 个线程。最大组数在编译时配置,默认为 16。另请参阅 “nbthread”。
此设置用于强制限制线程数,无论是检测到的还是配置的。这在线程数是自动检测的操作系统上特别有用,其中在通用和可移植的配置中希望线程数低于 CPU 数。实际上,虽然 “nbthread” 强制的线程数如果高于可用 CPU 数将导致警告和性能不佳,但 thread-hard-limit 只会限制最大值,并自动将线程数限制为不高于此值,但不会提高较低的值。如果 “nbthread” 被强制设置为更高的值,则 thread-hard-limit 生效,并发出警告,以便可以修复配置异常。默认情况下没有限制。另请参阅 “nbthread”。
uid <number>
将进程的用户 ID 更改为 <number>。建议将用户 ID 专用于 HAProxy 或一小部分类似的守护程序。HAProxy 必须以超级用户权限启动才能切换到另一个用户。另请参阅 "gid" 和 "user"。
ulimit-n <number>
将每个进程的文件描述符最大数量设置为 <number>。默认情况下,它是自动计算的,因此建议不要使用此选项。如果目的只是限制文件描述符的数量,最好改用 “fd-hard-limit”。请注意,在此自动资源计算中未考虑动态服务器。如果使用大量动态服务器,可能需要手动指定此值。
unix-bind [ 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> ...]
删除参数中指定的环境变量。这对于隐藏某些操作期间偶尔从用户环境中继承的一些敏感信息很有用。不存在的变量会被静默忽略,因此操作后可以确定这些变量都不再存在。更改会立即生效,因此配置文件中的下一行将看不到这些变量。另请参阅 “setenv”、“presetenv” 和 “resetenv”。
user <user name>
与 "uid" 类似,但使用 /etc/passwd 中用户名 <user name> 的 UID。另请参阅 "uid" 和 "group"。
node <name>
只允许字母、数字、连字符和下划线,与 DNS 名称类似。此语句在 HA 配置中很有用,其中两个或多个进程或服务器共享相同的 IP 地址。通过在所有节点上设置不同的节点名称,可以轻松地立即发现哪个服务器正在处理流量。
设置 WURFL User-Agent 缓存大小。为了更快地查找,已处理的用户代理会保存在 LRU 缓存中:- “0”:不使用缓存。- <size>:lru 缓存的大小(以元素为单位)。请注意,此选项仅在 HAProxy 编译时带有 USE_WURFL=1 时可用。
wurfl-data-file <file path>
WURFL 数据文件的路径,用于提供设备检测服务。HAProxy 应具有相关权限才能访问该文件。请注意,此选项仅在 HAProxy 编译时带有 USE_WURFL=1 时可用。
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 请求而来的原始 useragent。 - wurfl_api_version 包含表示当前使用的 Libwurfl API 版本的字符串。 - wurfl_info 包含有关已解析的 wurfl.xml 及其完整路径的字符串。 - wurfl_last_load_time 包含上次成功加载 WURFL 的 UNIX 时间戳。 - wurfl_normalized_useragent 规范化的 useragent。请注意,此选项仅在 HAProxy 使用 USE_WURFL=1 编译时才可用。
一个将用于在包含 WURFL 结果的响应头中分隔值的字符。如果未设置,则默认使用逗号(‘,’)。请注意,此选项仅在 HAProxy 编译时带有 USE_WURFL=1 时可用。
wurfl-patch-file [<file path>]
WURFL 补丁文件路径列表。请注意,补丁在启动期间加载,因此在 chroot 之前。请注意,此选项仅在 HAProxy 编译时带有 USE_WURFL=1 时可用。

3.2. 性能调优

在某些情况下,尤其是在处理支持可变频率的处理器上的低延迟时,或者在虚拟机中运行时,每次进程使用轮询器等待 I/O 时,处理器都会重新进入睡眠状态或长时间提供给另一个 VM,这会导致延迟过高。此选项提供了一种解决方案,通过始终在轮询器上使用空超时来防止处理器休眠。这会导致延迟显著降低(观察到 30 到 100 微秒),代价是处理器过热的风险。它甚至可以与线程一起使用,在这种情况下,绑定不正确的线程可能会严重冲突,导致性能更差,并且 "show info" 输出中的 CPU stolen 字段值很高,表明哪些线程配置错误。使用此选项时,重要的是不要让进程与网络中断在同一处理器上运行。最好避免在共享同一核心的多个 CPU 线程上使用它。此选项默认禁用。如果已启用,仍可以通过在其前加上 "no" 关键字来强制禁用。它被 "select" 和 "poll" 轮询器忽略。此选项在无缝重新加载的上下文中会自动在旧进程上禁用;它避免了当多个进程停留一段时间等待当前连接结束时过多的 cpu 冲突。
max-spread-checks <delay in milliseconds>
默认情况下,HAProxy 会尝试将健康检查的开始时间分散在服务器场中所有服务器的最小健康检查间隔内。其原则是避免对在同一台服务器上运行的服务进行密集冲击。但是当使用大的检查间隔(10 秒或更长)时,服务器场中的最后一个服务器需要一些时间才能开始被测试,这可能是一个问题。此参数用于强制规定第一次和最后一次检查之间的延迟上限,即使服务器的检查间隔较大。当服务器以较短的间隔运行时,它们的间隔仍将得到尊重。
设置 HAProxy 在停止新请求的压缩或降低当前请求的压缩级别之前可以达到的最大 CPU 使用率。它的工作方式类似于“maxcomprate”,但测量的是 CPU 使用率而不是传入数据带宽。该值以 HAProxy 使用的 CPU 百分比表示。值 100 表示禁用限制。默认值为 100。设置较低的值将防止压缩工作减慢整个进程的速度并引入高延迟。
maxcomprate <number>
将每个进程的最大输入压缩速率设置为 <number> 千字节/秒。对于每个流,如果达到最大值,压缩级别将在流期间降低。如果在流开始时达到最大值,则该流将完全不压缩。如果未达到最大值,压缩级别将增加到 tune.comp.maxlevel。值为零表示没有限制,这是默认值。
maxconn <number>
设置每个进程的最大并发连接数上限为 <number>。它等同于命令行参数 "-n"。通过 "-n" 在命令行参数中提供的值优先于在全局部分设置的 maxconn 值。Haproxy 进程也可以使用 SYSTEM_MAXCONN 编译时变量编译,在这种情况下,它用作系统 maxconn 最大值。同样,如果设置了 SYSTEM_MAXCONN 限制,命令行 "-n" 参数允许在运行时绕过它。当达到 maxconn 时,代理将停止接受连接。进程软文件描述符限制(可以使用 "ulimit -n" 命令获取)会根据提供的 maxconn 自动调整。另请参阅 "ulimit-n"。注意:"select" 轮询器在某些平台上无法可靠地使用超过 1024 个文件描述符。如果您的平台仅支持 select 并在启动时报告 "select FAILED",则需要减少 maxconn 直到它起作用(通常略低于 500)。如果未设置 maxconn 值,它将根据当前文件描述符限制自动计算,由 "ulimit -nH" 命令报告(我们取硬限制和软限制之间的最大值),然后自动值可能会被 "fd-hard-limit" 和内存限制(如果后者是通过 "-m" 命令行选项强制执行的)减少。自动值还取决于缓冲区大小、分配给压缩的内存、SSL 缓存大小以及是否使用 SSL 和相关的 maxsslconn(也可以是自动的)。
maxconnrate <number>
将每个进程每秒的最大连接数设置为 <number>。当达到此限制时,代理将停止接受连接。它可以用来限制全局容量,而不考虑每个前端的容量。需要注意的是,这只能用作服务保护措施,因为当达到限制时,前端之间不一定会公平分配,所以最好也为每个前端限制一个接近其预期份额的值。此外,降低 tune.maxaccept 可以提高公平性。
maxpipes <number>
将每个进程的最大管道数设置为 <number>。目前,管道仅由基于内核的 tcp 拼接使用。由于一个管道包含两个文件描述符,"ulimit-n" 值将相应增加。默认值为 maxconn/4,这对于大多数重度使用情况来说似乎已经足够了。拼接代码动态分配和释放管道,并且可以回退到标准复制,因此将此值设置得太低可能只会影响性能。
maxsessrate <number>
将每个进程每秒的最大会话数设置为 <number>。当达到此限制时,代理将停止接受连接。它可以用来限制全局容量,而不考虑每个前端的容量。需要注意的是,这只能用作服务保护措施,因为当达到限制时,前端之间不一定会公平分配,所以最好也为每个前端限制一个接近其预期份额的值。此外,降低 tune.maxaccept 可以提高公平性。
maxsslconn <number>
设置每个进程的最大并发 SSL 连接数上限为 <number>。默认情况下没有特定于 SSL 的限制,这意味着全局 maxconn 设置将应用于所有连接。设置此限制可避免 openssl 使用过多内存并在 malloc 返回 NULL 时崩溃(因为它不幸地无法可靠地检查此类情况)。请注意,此限制适用于传入和传出连接,因此一个被解密然后加密的连接计为 2 个 SSL 连接。如果未设置此值,但强制执行了内存限制,则将根据内存限制、maxconn、缓冲区大小、分配给压缩的内存、SSL 缓存大小以及在前端、后端或两者中是否使用 SSL 自动计算此值。如果在有内存限制的情况下既未指定 maxconn 也未指定 maxsslconn,HAProxy 将自动调整这些值,以便 100% 的连接可以在 SSL 上进行而没有风险,并会考虑启用 SSL 的侧面(前端、后端、两者)。
maxsslrate <number>
将每个进程每秒的最大 SSL 会话数设置为 <number>。当达到此限制时,SSL 侦听器将停止接受连接。它可以用来限制全局 SSL CPU 使用率,而不考虑每个前端的容量。需要注意的是,这只能用作服务保护措施,因为当达到限制时,前端之间不一定会公平分配,所以最好也为每个前端限制一个接近其预期份额的值。同样重要的是要注意,会话是在进入 SSL 堆栈之前而不是之后计算的,这也保护了堆栈免受不良握手的影响。此外,降低 tune.maxaccept 可以提高公平性。
maxzlibmem <number>
设置 zlib 每个进程可用的最大 RAM 量(以兆字节为单位)。当达到最大量时,只要 RAM 不可用,未来的数据流将不会被压缩。当设置为 0 时,没有限制。默认值为 0。该值可以通过 UNIX 套接字上的“show info”命令在“MaxZlibMemUsage”行中以字节为单位获取,zlib 使用的内存是“ZlibMemUsage”(以字节为单位)。
在某些尝试回收大量内存的时刻(内存不足或重载时)禁用内存修剪(“malloc_trim”)。修剪内存会强制系统的分配器扫描所有未使用的区域并释放它们。这通常被视为一种好的做法,可以为新进程留出更多可用内存,而旧进程不太可能大量使用它。但某些处理成千上万并发连接的系统可能会经历大量的内存碎片,这可能导致此释放操作极其漫长。在此期间,没有更多的流量通过该进程,不再接受新的连接,一些健康检查甚至可能失败,看门狗(watchdog)甚至可能触发并杀死无响应的进程,留下一个巨大的核心转储文件。如果发生这种情况,建议使用此选项来禁用修剪,停止尝试对新进程友好。请注意,先进的内存分配器通常不会遇到此类问题。
禁用在 Linux 上使用 "epoll" 事件轮询系统。它等同于命令行参数 "-de"。下一个使用的轮询系统通常是 "poll"。另请参阅 "nopoll"。
在源自 Solaris 10 及更高版本的 SunOS 系统上禁用事件端口(event ports)事件轮询系统的使用。它等同于命令行参数“-dv”。下一个使用的轮询系统通常是“poll”。另请参阅“nopoll”。
禁用使用 getaddrinfo(3) 进行名称解析。它等同于命令行参数 "-dG"。将使用已弃用的 gethostbyname(3)。
禁用在 BSD 上使用 "kqueue" 事件轮询系统。它等同于命令行参数 "-dk"。下一个使用的轮询系统通常是 "poll"。另请参阅 "nopoll"。
禁用 ktls 的使用。它等同于命令行参数 "-dT"。
禁用“poll”事件轮询系统的使用。它等同于命令行参数“-dp”。下一个使用的轮询系统将是“select”。通常不需要禁用“poll”,因为它在 HAProxy 支持的所有平台上都可用。另请参阅“nokqueue”、“noepoll”和“noevports”。
禁用 SO_REUSEPORT 的使用 - 请参阅 socket(7)。它等同于命令行参数 "-dR"。
禁用在 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 }
启用('on')或禁用('off')按函数的内存分析。这将保留进程中任何地方(包括库)的 malloc/calloc/realloc/free 调用的使用统计信息,这些信息将通过 CLI 上的“show profiling”命令报告。这主要用于当观察到无法通过池信息解释的异常内存使用,并且需要其他信息时。性能损失通常在 1% 左右,在高度线程化的机器上可能会更高一些,因此通常适合在生产环境中使用。同样的功能也可以在运行时通过 CLI 上的“set profiling memory”命令实现,请查阅管理手册。
profiling.tasks { auto | on | off }
启用 ('on') 或禁用 ('off') 每任务 CPU 分析。当设置为 'auto' 时,分析会在线程开始遭受平均延迟 1000 微秒或更高(如 "avg_loop_us" 活动字段中所报告)时自动打开,并在延迟返回到 990 微秒以下时自动关闭(此值是过去 1024 个循环的平均值,因此变化不快,并且倾向于显著平滑短时峰值)。它也可能在过载系统、容器或虚拟机上自发触发,或者在系统交换时(这在负载均衡器上绝对不应该发生)。每任务 CPU 分析对于报告时间花费在哪里以及哪些请求对哪些其他请求产生什么影响非常方便。启用它通常会对整体性能产生不到 1% 的影响,因此建议将其保留为默认的 'auto' 值,以便仅在发现问题时才运行。此功能需要支持 clock_gettime(2) 系统调用以及 clock 标识符 CLOCK_MONOTONIC 和 CLOCK_THREAD_CPUTIME_ID 的系统,否则报告的时间将为零。此选项可以在运行时使用 CLI 上的 "set profiling" 进行更改。
spread-checks <0..50, in percent>
有时,希望避免以精确的间隔向服务器发送代理和健康检查,例如当许多逻辑服务器位于同一物理服务器上时。借助此参数,可以在检查间隔中添加 0 到 +/- 50% 之间的随机性。2 到 5 之间的值似乎效果很好。默认值仍为 0。
ssl-engine <name> [algo <comma-separated list of algorithms>]
将 OpenSSL 引擎设置为 <name>。<name> 的有效值列表可以使用命令 "openssl engine" 获取。此语句可以多次使用,它只会启用多个加密引擎。引用不支持的引擎将阻止 HAProxy 启动。请注意,对于最近的处理器,许多引擎的 HTTPS 性能低于纯软件。可选命令 "algo" 设置 ENGINE 将使用 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,可以重建 HAProxy 时使用 USE_ENGINE=1 标志。
向 SSL 上下文添加 SSL_MODE_ASYNC 模式。如果使用支持异步的 SSL 引擎,这将启用异步 TLS I/O 操作。当前实现最多支持 32 个引擎。Openssl ASYNC API 不支持移动读/写缓冲区,并且与 HAProxy 的缓冲区管理不兼容。因此,在读/写操作上禁用了异步模式(它仅在初始和重新协商握手期间启用)。
启用('on')或禁用('off')小程序(applet)的数据零拷贝转发。默认启用。
为每个进程可分配的缓冲区数量设置一个硬限制。默认值为零,表示无限制。该限制将自动重新调整以满足紧急情况下的保留缓冲区,这样用户就不必进行复杂的计算。强制设置此值对于限制进程可能占用的内存量,同时保持正常的行为特别有用。当达到此限制时,请求缓冲区的任务会等待另一个缓冲区被释放。只要限制合理,大多数情况下等待时间非常短且不易察觉。然而,一些历史上的限制在不同版本中削弱了这一机制,已知在某些持续短缺的情况下,一些任务可能会冻结直到超时,因此在非严格必要时,最好避免使用此选项。
设置每个线程预分配并保留的缓冲区数量,这些缓冲区仅在内存分配失败导致的内存短缺情况下使用。最小值为 0,默认值为 4。除非核心开发人员出于非常具体的原因建议更改,否则用户没有理由更改此值。
设置缓冲区大小(以字节为单位)。较低的值允许在相同数量的 RAM 中共存更多流,而较高的值允许某些具有非常大 cookie 的应用程序工作。默认值是 16384,可以在构建时更改。强烈建议不要更改此默认值,因为非常低的值会破坏某些服务(例如统计信息),而大于默认值的值会增加内存使用量,可能会导致系统内存不足。至少全局 maxconn 参数应按此参数增加的相同因子减小。此外,HTTP/2 的使用要求此值必须为 16384 或更大。如果 HTTP 请求大于 (tune.bufsize - tune.maxrewrite),HAProxy 将返回 HTTP 400(Bad Request)错误。同样,如果 HTTP 响应大于此大小,HAProxy 将返回 HTTP 502(Bad Gateway)。请注意,使用此参数设置的值将在 32 位机器上自动向上舍入为 8 的下一个倍数,在 64 位机器上自动向上舍入为 16 的下一个倍数。
设置小缓冲区的字节大小。默认值为 1024。这些缓冲区设计用于一些内存消耗受限但似乎不必分配完整缓冲区的特定上下文中。然而,如果小缓冲区不足,会自动进行重新分配以切换到标准大小的缓冲区。目前,它仅由 HTTP/3 协议用于发出响应头。
设置最大压缩级别。压缩级别影响压缩过程中的 CPU 使用率。此值影响压缩过程中的 CPU 使用率。每个使用压缩的数据流都使用此值初始化压缩算法。默认值为 1。
禁用数据快速转发。它是一种通过将数据直接从一侧传递到另一侧而不唤醒流来优化数据转发的机制。通过此指令,可以禁用此优化。请注意,它还禁用了任何内核 tcp 拼接,以及零拷贝转发。此命令不适用于常规使用,通常只有开发人员在复杂的调试会话中才会建议使用。
全局禁用数据的零拷贝转发。这是一种通过避免使用通道缓冲区来优化数据快速转发的机制。通过此指令,可以禁用此优化。注意,它还禁用了任何内核 TCP 拼接。
在 HAProxy 的历史中,遇到了一些由 Linux 内核中 epoll 机制的错误引起的复杂问题。这些问题通常非常罕见,并且无法在报告者的环境之外重现,并且只能通过禁用 epoll 并切换到 poll 来解决,这对于高性能环境来说并不令人满意。每次,问题都只影响非常特定(且罕见)的事件类型,提供屏蔽它们的能力可以构成一种更可接受的解决方案。此选项提供了这种可能性,允许默默地忽略一些不常见的事件,并用输入(报告未指定的传入事件)替换它们。效果是避免在某些地方使用快速错误处理路径,而只使用常见路径。除非专家邀请您这样做以诊断或解决内核错误,否则不应使用此选项。该选项接受一个参数,该参数是以逗号分隔的单词列表,每个单词指定要屏蔽的事件。目前支持的事件列表是:- "err":屏蔽 EPOLLERR 事件 - "hup":屏蔽 EPOLLHUP 事件 - "rdhup":屏蔽 EPOLLRDHUP 事件
示例
# 屏蔽所有非流量的 epoll 事件: tune.epoll.mask-events err,hup,rdhup
设置异步任务处理程序(来自 event_hdl API)一次可以处理的事件数量。<number> 应在 1 到 10000 之间。较大的数字可能导致线程争用,因为任务在不中断的情况下进行繁重的工作;另一方面,较小的数字可能导致任务不断被重新调度,因为它每次运行无法消耗足够多的事件,也无法跟上事件生成者的速度。默认值可以在构建时强制设置,否则默认为 100。
如果使用 DEBUG_FAIL_ALLOC 编译或使用 "-dMfail" 启动,则给出分配尝试失败的百分比机会。必须在 0(无失败)和 100(无成功)之间。这对于调试并确保内存故障得到妥善处理非常有用。未设置时,比率为 0。但是,命令行 "-dMfail" 选项会自动将其设置为 1% 的失败率,因此无需更改配置进行测试。
tune.fd.edge-triggered { on | off } [ 实验性 ]
为支持它的文件描述符(FD)启用('on')或禁用('off')边缘触发轮询模式。目前仅在 epoll 下支持。在某些情况下,它可能会显著减少 epoll_ctl() 调用的数量并略微提高性能。这仍然是实验性的,如果仍然存在错误,可能会导致连接冻结,并且默认禁用。
设置 CPU 最小使用率(介于 0 和 100 之间),当连接显示过多故障时,将终止这些连接。这适用于已达到其故障阈值限制的连接。在非常长的连接经常表现不佳但不会造成任何性能影响的环境中,只要它们没有造成损害,就可能希望保留它们,并且只在 CPU 变得繁忙时才开始终止此类连接。此参数允许指定当 CPU 使用率达到或超过此级别时,将主动终止达到其故障阈值的连接,但在低于此级别时永远不会终止。请注意,CPU 使用率是按线程测量的,因此单个行为不当的连接可能会被终止。默认值为零,这意味着达到其故障阈值的连接将自动被终止。经验法则是将此值设置为通常观察到的 CPU 使用率的两倍,或者通常观察到的 CPU 使用率加上一半的空闲时间(例如,如果 CPU 通常达到 60%,则在此处设置 80 可能有意义)。如果没有 tune.h2.fe.glitches-threshold 或 tune.quic.fe.sec.glitches-threshold,此参数无效。另请参阅全局参数 "tune.h2.fe.glitches-threshold" 和 "tune.quic.fe.sec.glitches-threshold"。
启用('on')或禁用('off')H1 多路复用器的数据零拷贝接收。默认启用。
启用('on')或禁用('off')H1 多路复用器的数据零拷贝发送。默认启用。
设置后端连接上故障(glitches)数量的阈值,超过该阈值连接将自动被终止。这允许自动终止行为不佳的连接,而无需为其编写明确的规则。默认值为零,表示未设置阈值,因此任何事件都不会导致连接关闭。请注意,一些 H2 服务器可能会在长时间连接上偶尔引起一些故障,因此这里的任何非零值可能应该在数百或数千的量级,以便在不影响轻微有问题的服务器的情况下有效。也可以通过使用“tune.glitches.kill.cpu-usage”来仅在 CPU 使用率超过某个水平时终止连接。
设置传出连接的 HTTP/2 初始窗口大小,即服务器在等待 HAProxy 确认之前可以响应的字节数。此设置仅影响有效负载内容,不影响头部。如果未设置,则应用由 tune.h2.initial-window-size 设置的通用默认值。稍微增加此值可以加快下载速度或减少服务器上的 CPU 使用率,但代价是在客户端之间造成不公平。最好使用 tune.h2.be.rxbuf,它不会引起任何不公平。它不影响资源使用。
设置每个传出连接的 HTTP/2 最大并发流数(即单个到服务器连接上的未完成请求数)。如果未设置,则应用由 tune.h2.max-concurrent-streams 设置的默认值。小于默认值 100 的值可能会提高站点的响应能力,但代价是需要维护更多到服务器的已建立连接。当“http-reuse”设置为“always”时,建议减小此值,以免在同一连接上混合过多不同的客户端,因为如果一个客户端比其他客户端慢,一种称为“队头阻塞”的机制往往会对共享连接的所有客户端的下载速度产生级联效应(在这种情况下,保持 tune.h2.be.initial-window-size 较低)。强烈建议不要增加此值;有些人可能会发现在较低的值(通常为 1..5)下运行是最佳的。
设置传出连接的 HTTP/2 接收缓冲区大小(以字节为单位)。此大小将向上取整到 tune.bufsize 的下一个倍数,并将在所有上传数据(HEADERS 和 DATA 帧)的流之间共享。在任何情况下,每个流都将始终被授予一个缓冲区,并且 7/8 的未使用缓冲区将在下载有效负载的流之间共享,从而在 http-reuse 设置为 "always" 时,显著提高上传性能并避免在多个客户端之间共享的后端连接上出现队头阻塞(HoL)。通告的每个流的窗口会自动调整以反映可用空间,因此实际上应该不需要调整 tune.h2.be.initial-window-size。如果设置的大小小于处理所有流所需的大小,则将使用此最小值。默认值约为 1600k(100 个流,每个流有 16kB 的缓冲区)。
设置前端连接上故障(glitches)数量的阈值,超过该阈值连接将自动被终止。这允许自动终止行为不佳的连接,而无需为其编写明确的规则。默认值为零,表示未设置阈值,因此任何事件都不会导致连接关闭。请注意,一些 H2 客户端可能会在长时间连接上偶尔引起一些故障,因此这里的任何非零值可能应该在数百或数千的量级,以便在不影响轻微有问题的客户端的情况下有效。也可以通过使用“tune.glitches.kill.cpu-usage”来仅在 CPU 使用率超过某个水平时终止连接。
设置传入连接的 HTTP/2 初始窗口大小,即客户端在等待 HAProxy 确认之前可以上传的字节数。此设置仅影响有效负载内容(即 POST 请求的主体),不影响头部。如果未设置,则应用由 tune.h2.initial-window-size 设置的通用默认值。增加此值可以加快上传速度。默认值等于 tune.bufsize (16384),允许每个流在 100 毫秒 ping 时间下至少有 1.25 Mbps 的带宽,在 1 毫秒 ping 时间下有 125 Mbps 的带宽。它不影响资源使用。使用过大的值可能会导致客户端在并行访问页面与大文件上传时体验到响应性不足。最好使用 tune.h2.fe.rxbuf,它不会引起任何不公平。
设置每个传入连接的 HTTP/2 最大并发流数(即单个客户端连接上的未完成请求数)。如果未设置,则应用由 tune.h2.max-concurrent-streams 设置的默认值。对于具有大量小对象的复杂站点,在高延迟网络上,大于默认值 100 的值有时可能会略微改善页面加载时间,但也可能因允许客户端一次性分配更多资源而导致使用更多内存。默认值 100 通常很好,建议不要更改此值。
设置每个传入连接处理的 HTTP/2 总流的最大数量。一旦达到此限制,HAProxy 将发送一个优雅的 GOAWAY 帧,通知客户端它将在所有挂起的流关闭后关闭连接。实际上,客户端在收到此消息时倾向于尽快关闭,并为下一个请求建立新连接。在客户端连接时间很长并在场内造成一些不平衡的情况下,这样做有时很有用且合乎需要。例如,在某些高度动态的环境中,可能会在负载增加时即时实例化新的负载均衡器,并且一旦负载下降,应停止它们而不断开已建立的连接。通过在此处设置限制,连接将具有有限的生命周期,并且会经常更新,其中一些可能会建立到其他节点,从而快速释放现有资源。重要的是要理解此限制与上面的 "tune.h2.fe.max-concurrent-streams" 之间存在隐式关系。实际上,HAProxy 将始终接受处理客户端和前端之间可能在传输中的任何可能挂起的流,因此所宣传的限制将始终自动提高由 max-concurrent-streams 中配置的值,并且此值将作为硬限制,非兼容客户端违反此限制将导致连接关闭。因此,当从日志中计算每个连接的请求数时,可能会观察到介于 max-total-streams 和 (max-total-streams + max-concurrent-streams) 之间的任何数字,具体取决于客户端创建流的速度。默认值为零,它不施加超出协议隐含限制(2^30 ~= 1.07 十亿)的任何限制。值在 1000 左右可能已经会导致频繁的连接更新,而不会对大多数客户端造成任何明显延迟。设置得太低可能会导致由于频繁的 TLS 重新连接而增加 CPU 使用率,此外还会增加页面加载时间。请注意,某些负载测试工具不支持重新连接,并且可能会报告此设置的错误;因此,在运行性能基准测试时可能需要禁用它。另请参阅 "tune.h2.fe.max-concurrent-streams"。
设置传入连接的 HTTP/2 接收缓冲区大小(以字节为单位)。此大小将向上取整到 tune.bufsize 的下一个倍数,并将在所有上传数据(HEADERS 和 DATA 帧)的流之间共享。在任何情况下,每个流都将始终被授予一个缓冲区,并且 7/8 的未使用缓冲区将在上传有效负载的流之间共享,从而显著提高上传性能。通告的每个流的窗口会自动调整以反映可用空间,因此实际上应该不需要调整 tune.h2.fe.initial-window-size。如果设置的大小小于处理所有流所需的大小,则将使用此最小值。默认值 1600k(100 个流,每个流有 16kB 的缓冲区)允许具有 100ms RTT 的客户端大约有 130 Mbps 的上传速度。
设置 HTTP/2 动态头表大小。默认为 4096 字节,不能大于 65536 字节。较大的值可能有助于某些客户端发送更紧凑的请求,具体取决于它们的能力。每个 HTTP/2 连接都会消耗此数量的内存。建议不要更改它。
设置 HTTP/2 初始窗口大小的默认值,适用于传入和传出连接。当未设置 tune.h2.fe.initial-window-size 时,此值用于传入连接;当未设置 tune.h2.be.initial-window-size 时,此值用于传出连接。此设置既用作初始值,也用作每流的最小值。默认值等于 16384 (tune.bufsize),对于上传而言,在显示 100 毫秒 ping 时间的网络上,每流大致允许至少 1.25 Mbps 的带宽,或者在 1 毫秒本地网络上允许 125 Mbps 的带宽。当使用的接收缓冲区少于最大值时,在 tune.h2.be.rxbuf 和 tune.h2.fe.rxbuf 定义的限制内,未使用的缓冲区将在接收流之间共享。因此,通常没有必要更改此默认设置。鉴于更改此默认值会同时提高上传速度并导致客户端在下载方面更加不公平,建议改用特定于端点的设置 tune.h2.fe.initial-window-size 和 tune.h2.be.initial-window-size。
设置每个连接的默认 HTTP/2 最大并发流数(即单个连接上的未完成请求数)。当未设置 tune.h2.fe.max-concurrent-streams 时,此值用于传入连接;当未设置 tune.h2.be.max-concurrent-streams 时,此值用于传出连接。默认值为 100。影响因方向而异,因此请参阅上述两个设置以获取更多详细信息。建议不要使用此设置,而是切换到按方向的设置。值为零将禁用限制,因此单个客户端可以创建 HAProxy 可分配的任意数量的流。强烈建议不要更改此值。
设置 HAProxy 向其对等方宣告愿意接收的 HTTP/2 最大帧大小。默认值是 16384 和缓冲区大小 (tune.bufsize) 之间的较大者。在任何情况下,HAProxy 都不会宣告支持大于缓冲区的帧大小。此设置的主要目的是允许在使用大缓冲区时限制最大帧大小设置。过大的帧大小可能会影响性能或导致某些对等方行为不当。强烈建议不要更改此值。
启用('on')或禁用('off')H2 多路复用器的数据零拷贝发送。默认启用。
设置捕获的 cookie 的最大长度。"capture cookie xxx len yyy" 允许的最大值将是此值,任何更高的值都将自动截断为此值。重要的是不要设置太高的值,因为所有 cookie 捕获无论其配置值如何都会分配此大小(它们共享一个池)。此值是每个请求每个响应的,因此每个连接分配的内存是此值的两倍。如果未指定,限制设置为 63 个字符。建议不要更改此值。
设置日志中请求 URI 的最大长度。这可以防止在日志行中截断带有有价值查询字符串的长请求 URI。这与 syslog 的限制无关。如果增加此限制,您可能还需要增加 'log ... len yyy' 参数。您的 syslog 守护进程可能也需要特定的配置指令。默认值为 1024。
设置接收到的 HTTP 消息中允许的最大标头数。当消息中的标头数大于此值(包括第一行)时,它将被拒绝,对于请求,状态码为 "400 Bad Request",对于响应,状态码为 "502 Bad Gateway"。默认值是 101,这对于所有用法都足够了,考虑到广泛部署的 Apache 服务器使用相同的限制。将此限制推得更远可能很有用,以便在应用程序得到修复之前暂时允许有错误的应用程序工作。接受范围是 1..32767。请记住,每个新标头会为每个流消耗 32 位内存,因此不要将此限制推得太高。请注意,HTTP/1.1 是一个文本协议,因此在发送消息时没有特殊限制。消息解析期间的限制就足够了。HTTP/2 和 HTTP/3 是二进制协议,需要编码步骤。当编码标头以符合协议施加的限制时,也会设置限制。此限制足够大,但出于目的未记录。出于相同的原因,在解码的第一步中应用了相同的限制。
启用('on')或禁用('off')同一服务器的空闲连接池在线程间的共享。默认是共享它们,以最小化到服务器的持久连接数,并优化连接重用率。但为了帮助调试或当怀疑 HAProxy 在连接重用方面存在错误时,强制禁用多线程间的空闲池共享,并将此选项设置为 "off" 可能很方便。默认是 on。强烈建议在禁用此选项时,不要为所有依赖连接重用以实现高性能的服务器设置一个保守的“pool-low-conn”值,否则随着线程数的增加,连接可能会被频繁关闭。
tune.idletimer <timeout>
设置一个持续时间,在此之后 HAProxy 将认为一个空缓冲区可能与一个空闲流相关联。这用于在交替转发大数据和小数据时优化调整某些数据包的大小。使用 splice() 或在 SSL 中发送大缓冲区的决定受此参数调节。该值以毫秒为单位,介于 0 和 65535 之间。值为零表示 HAProxy 不会尝试检测空闲流。默认值为 1000,这似乎能正确检测最终用户的暂停(例如,在点击前阅读页面)。应该没有理由更改此值。请检查下面的 tune.ssl.maxrecord。
tune.listener.default-shards { by-process | by-thread | by-group }
通常,所有 "bind" 行将创建一个单独的分片,即所有进程线程都将侦听的单个套接字。对于许多线程,这不是很高效,甚至可能在内核中引起一些重要的开销来更新轮询状态甚至向各个线程分发事件。现代操作系统支持传入连接的平衡,这种机制将包括允许多个套接字绑定到同一地址和端口,并均匀地将所有传入连接分发到这些套接字,以便每个线程只看到在其绑定的套接字中等待的连接。这显著减少了内核端的开销,并提高了传入连接路径的性能。这通常在 HAProxy 中使用 "shards" 设置在 "bind" 行上启用,默认值为 1,这意味着每个侦听器在进程中都是唯一的。在具有许多处理器的系统上,将默认设置更改为 "by-thread" 以始终为每个线程创建一个侦听套接字,或更改为 "by-group" 以始终为每个线程组创建一个侦听套接字可能更方便。请注意 "by-thread" 的文件描述符使用情况,因为每个侦听器将需要与线程数一样多的套接字。此外,某些操作系统(例如 FreeBSD)在同一地址上最多限制为 256 个套接字。请注意,对于涉及单个线程组的默认配置,"by-group" 将保持与 "by-process" 等效,并且在不支持此机制的系统上将回退到共享同一套接字。默认值是 "by-group",对于不支持多个绑定的系统或套接字族,将回退到 "by-process"。
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 }
明确告诉 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 脚本正确将 bool haproxy 样本作为布尔值处理后,将此选项设置为 "normal"。此设置必须在任何 "lua-load" 或 "lua-load-per-thread" 指令之前设置才能被考虑,否则将被忽略。
"burst" 执行超时适用于任何 Lua 处理器。如果处理器未能在超时之前完成或让出,它将被中止,以防止线程争用、防止流量长时间得不到服务,并最终防止进程因看门狗介入而崩溃。与其他是让出累积的 Lua 超时不同,burst-timeout 将确保单个 Lua 执行窗口中花费的时间不超过配置的超时。此处让出意味着 Lua 执行被有效中断,要么是通过对 Lua 让出函数的显式调用(例如 core.(m)sleep() 或 core.yield()),要么是跟随自动强制让出(参见 tune.lua.forced-yield),并且将在相关任务设置为重新调度时稍后恢复。并非所有 Lua 处理器都可以让出:我们必须区分可让出处理器和不可让出处理器。对于可让出处理器(任务、操作等),达到超时意味着 "tune.lua.forced-yield" 对于系统来说可能太高了,降低它可能会改善情况,但检查在 Lua 函数中的某些关键点添加手动让出是否有帮助也是一个好主意。它也可能表明处理器在无法中断的特定 Lua 库函数中花费了太多时间。对于不可让出处理器(Lua 转换器、样本获取),它可能仅仅表明处理器正在进行过多的计算,这可能是由于设计不当造成的,因为此类处理器(通常会阻塞请求执行流)预计会快速终止以允许请求处理通过。这里常见的解决方案是尝试更好地优化 Lua 函数以提高速度,因为减少 "tune.lua.forced-yield" 无济于事。此超时仅计算纯 Lua 运行时。如果 Lua 执行 core.sleep,则不计算睡眠时间。默认超时为 1000 毫秒。注意:如果从处理器发起 Lua GC 周期(无论是显式请求还是 Lua 在一段时间后自动触发),GC 周期时间也将被计算在内。确实,无法推断 GC 周期时间,因此这可能会在饱和系统上导致一些误报(GC 难以赶上并消耗大部分可用执行运行时)。如果发生这种情况,这里有一些解决方案线索:- 检查脚本是否可以优化以减少 Lua 内存占用 - 微调 Lua GC 参数和/或请求手动 GC 周期(参见:https://lua.ac.cn/manual/5.4/manual.html#pdf-collectgarbage)- 增加 tune.lua.burst-timeout 将值设置为 0 会完全禁用此保护。
此指令强制 Lua 引擎每执行 <number> 条指令就执行一次让出(yield)。这允许中断一个长脚本,并让 HAProxy 调度器处理其他任务,如接受连接或转发流量。对于使用“lua-load-per-thread”加载的脚本,默认值为 10000 条指令;对于使用“lua-load”加载的脚本,默认值为 MAX(500, 10000 / nbthread) 条指令(这被认为是性能的最佳值,同时注意不要因多个线程竞争全局 Lua 锁而造成线程争用)。如果 HAProxy 经常执行一些 Lua 代码但需要更高的响应性,可以降低此值。如果 Lua 代码相当长且其结果对于处理数据是绝对必需的,可以增加 <number>,但应明智地设置该值,因为在多线程环境中它可能会增加争用。
启用('on')或禁用('off')通过适用于当前代理的日志记录器(如果有)记录 LUA 脚本的输出。默认为 'on'。
tune.lua.log.stderr { on | auto | off }
启用('on')或禁用('off')通过 stderr 记录 LUA 脚本的输出。当设置为 'auto' 时,如果满足以下任一条件,则通过 stderr 进行日志记录为 'on': - tune.lua.log.loggers 设置为 'off' - 脚本在没有全局日志记录器的非代理上下文中执行 - 脚本在没有附加日志记录器的代理上下文中执行。请注意,启用时,此日志记录是 tune.lua.log.loggers 配置的日志记录之外的补充。默认为 'auto'。
设置 Lua 每个进程可用的最大 RAM 量(以兆字节为单位)。默认情况下为零,表示无限制。设置限制很重要,以确保脚本中的错误不会导致系统内存耗尽。
这是 Lua 服务的执行超时。这对于防止无限循环或在 Lua 中花费太多时间很有用。此超时仅计算纯 Lua 运行时。如果 Lua 执行了休眠,休眠时间不计入。默认超时为 4 秒。
这是 Lua 会话的执行超时。这对于防止无限循环或在 Lua 中花费太多时间很有用。此超时仅计算纯 Lua 运行时。如果 Lua 执行了休眠,休眠时间不计入。默认超时为 4 秒。
目的与 "tune.lua.session-timeout" 相同,但此超时专用于任务。默认情况下,此超时未设置,因为任务可能在 HAProxy 的整个生命周期内保持活动状态。例如,用于检查服务器的任务。
设置每个线程的活动检查数,超过此数,线程将主动尝试寻找负载较轻的线程来运行健康检查,或者将其排队,直到其上运行的活动检查数量减少。默认值为零,表示没有设置此类限制。在某些运行大量昂贵检查且线程数众多的环境中,当负载出现不均并可能导致健康检查在启动时随机超时时,可能需要此设置,尤其是在使用 OpenSSL 3.0 时,其在健康检查上的 CPU 密集度比旧版本高约 20 倍。这将导致尝试在所有线程之间平均分配健康检查工作。绝大多数配置不需要调整此参数。请注意,如果检查执行缓慢,过低的值可能会显著减慢健康检查的速度。
设置一个进程在切换到其他工作之前可以连续接受的最大连接数。在单进程模式下,较高的数字曾经在高连接率下提供更好的性能,但现在有了多队列后,情况已非如此。此值单独应用于每个监听器,因此会考虑监听器绑定的进程数。此值默认为 4,表现出最佳结果。如果从旧配置中继承了一个明显更高的值,可能值得将其移除,因为这既能提高性能又能降低响应时间。在多进程模式下,它会被监听器绑定的进程数的两倍所除。将此值设置为 -1 会完全禁用该限制。通常不需要调整此值。
设置在一次调用轮询系统时可以处理的最大事件量。默认值根据操作系统进行调整。已经注意到,将其减少到 200 以下会以网络带宽为代价略微降低延迟,而将其增加到 200 以上则会以延迟为代价略微增加带宽。配置的值必须小于或等于 1000000。
将保留的缓冲区空间设置为此大小(以字节为单位)。保留空间用于报头重写或追加。套接字上的第一次读取永远不会超过 bufsize-maxrewrite。历史上,它默认为 bufsize 的一半,但这没有太大意义,因为很少有大量的报头需要添加。设置得太高会妨碍处理大的请求或响应。设置得太低会妨碍向已有的较大请求或 POST 请求添加新报头。通常明智的做法是将其设置为大约 1024。如果大于 bufsize 的一半,它会自动调整为 bufsize 的一半。这意味着您在更改 bufsize 时不必担心它。
设置在支持让出的规则集评估函数中可以一次评估的最大规则数。确实,看到具有大量 "tcp-request content" 或 "http-request" 规则的配置并不罕见。大量的规则与耗费 CPU 的操作(例如:处理内容的动作)相结合可能会产生线程争用,因为如果评估没有中断,给定规则集中的所有规则都会在同一个轮询循环中进行评估。此选项确保对于面向内容的规则集(由于内容检查而已经支持让出),在同一轮询循环中执行的规则数不超过 。它的作用是强制评估函数让出,以便它在下一个轮询循环中返回以继续评估。受影响的规则集是:- "tcp-request content" - "tcp-response content" - "http-request" - "http-response" 默认值为 50。
设置将保留在本地缓存中并永远不会被其他线程恢复的每线程内存量。对该内存的访问非常快(无锁),并且拥有足够的内存对于在极端线程争用下保持良好的性能水平至关重要。该值以字节表示,默认值在构建时通过 CONFIG_HAP_POOL_CACHE_SIZE 配置,默认值为 524288 (512 kB)。在某些使用场景中,较大的值可能会提高性能,尤其是当性能配置文件显示内存分配压力很大时。经验表明,一个好的值是每 CPU 核心 L2 缓存大小的一到两倍。过大的值会对性能产生负面影响,因为会对 CPU 中的 L3 缓存造成低效使用,并且会消耗更大的内存量。建议不要更改此值,或者以小幅度增量进行更改。为了完全禁用每线程 CPU 缓存,使用一个非常小的值可能会起作用,但最好在命令行上使用 "-dMno-cache"。
调整内核的每个套接字缓冲,以便在缓冲的数据量等于此值加上测量的窗口大小时,报告套接字的发送端已满。其原理是在套接字缓冲区中保留严格需要的最小字节量,再加上一个小余量,对应于 haproxy 再次尝试发送时将要发送的内容。将其设置为一个较低的值(通常在 tune.bufsize 左右)可以显著减少系统缓冲区中的内存消耗,并减少因刷新缓冲数据而引起的应用程序级延迟。对于支持它的系统,这通常比 tune.sndbuf.client 和 tune.sndbuf.server 是更有效、更准确的设置。这适用于每个连接(取决于设置,是来自客户端的连接还是到服务器的连接),并且仅用于 TCP 连接。默认值为零,表示无限制。这仅在 Linux 上可用。
设置模式查找缓存的大小为  个条目。这是一个 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 来禁用缓存。
设置 haproxy 在发送消息时一次将尝试处理的粘性表更新的最大数量。检索这些更新的数据需要一些锁定操作,这在高度线程化的机器上如果无限制可能会消耗大量 CPU,并且在旧进程和新进程之间的初始批量传输期间也可能增加流量延迟。相反,低值也可能导致更高的 CPU 开销,并需要更长的时间来完成。默认值为 200,建议不要更改它。
tune.pipesize <大小>
将内核管道缓冲区大小设置为此大小(以字节为单位)。默认情况下,管道是系统的默认大小。但有时在使用 TCP 拼接时,增加管道大小可以提高性能,特别是在怀疑管道未被填满且执行了许多 splice() 调用时。这对内核的内存占用有影响,因此如果影响不明确,则不应更改此值。
此设置设置 HAProxy 全局使用的文件描述符最大数量(百分比),相对于 HAProxy 在我们无法重用连接并且必须创建新连接时开始终止空闲连接之前可以使用的最大文件描述符数量。默认值为 25(四分之一的文件描述符将意味着大约一半的最大前端连接可以保留一个空闲的后端连接,任何超出此范围的在针对连接重用的通用情况下可能没有多大意义)。
此设置设置 HAProxy 全局使用的文件描述符最大数量(百分比),相对于 HAProxy 在我们停止将连接放入空闲池以供重用之前可以使用的最大文件描述符数量。默认值为 20。
启用('on')或禁用('off')直通(pass-through)多路复用器的数据零拷贝转发。要使用此功能,还必须配置内核拼接。默认启用。
定义 Cubic 拥塞控制算法真正考虑丢失事件所需的丢失数据包数。通常,任何丢失事件都被认为是拥塞的结果,足以让 Cubic 从较小的窗口重新开始。但实验表明,丢失的原因多种多样,根本不是由拥塞引起的,可以简单地称为虚假丢失,对于这些丢失,调整窗口没有效果,只会减慢通信速度。无线电信号差、乱序交付、客户端 CPU 使用率高导致随机延迟以及系统计时器不精确都可能是常见原因。此设置允许 Cubic 对虚假丢失更加容忍,通过更改两次 ACK 之间累积丢失的最小数量以被视为丢失事件,默认值为 1。实验中观察到了一些显著的增益,但总是伴随着重传浪费的带宽增加以及拥塞链路饱和的风险增加。值 2 可用于短时间比较某些指标。未经专家事先分析情况,切勿超过 2。默认值和最小值是 1。始终使用 1。
tune.quic.cc.cubic.min-losses <number> (deprecated)
此关键字在 3.3 中已弃用,并将在 3.5 中删除。它是 QUIC 配置应用精简流程的一部分。如果使用,此设置将仅应用于前端连接。
启用('on')或禁用('off')用于 QUIC 连接的 HyStart++ (RFC 9406) 算法,作为拥塞控制算法慢启动阶段的替代方案,该阶段可能导致高丢包率。默认禁用。
tune.quic.cc-hystart { on | off } (deprecated)
此关键字在 3.3 中已弃用,并将在 3.5 中删除。它是 QUIC 配置应用精简流程的一部分。如果使用,此设置将仅应用于前端连接。
设置单个 QUIC 帧可以被标记为丢失的限制。如果超过此限制,连接将被视为失败并立即关闭。默认值为 10。
tune.quic.max-frame-loss <number> (deprecated)
此关键字在 3.3 中已弃用,并将在 3.5 中删除。它是 QUIC 配置应用精简流程的一部分。如果使用,此设置将仅应用于前端连接。
设置单个 QUIC 连接的拥塞控制器在前端或后端侧的默认最大窗口大小。该值必须写为整数,带有可选后缀 'k'、'm' 或 'g'。它必须介于 10k 和 4g 之间。QUIC 多路复用器还使用当前的拥塞窗口大小来确定是否可以在数据发射时分配新的流缓冲区。因此,最大拥塞窗口大小也用作此分配器的限制。默认值为 480k。另请参阅 "quic-cc-algo" 绑定选项。
此关键字在 3.3 中已弃用,并将在 3.5 中删除。它是 QUIC 配置应用精简流程的一部分。如果使用,此设置将仅应用于前端连接。
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)
此关键字在 3.3 中已弃用,并将在 3.5 中删除。它是 QUIC 配置应用精简流程的一部分。如果使用,此设置将仅应用于前端连接。
设置前端或后端侧的 QUIC max_idle_timeout 传输参数。它遵循 HAProxy 时间格式,以毫秒表示。这决定了连接在有效时间段内保持不活动后静默关闭的时间段。两个端点都依赖于相同的协商值:- 如果两个参数都不为空,则取两个参数中的最小值,- 如果只有一个参数不为空,则取最大值,- 如果两个参数都为空,则禁用此功能。默认值为 30 秒。
此关键字在 3.3 中已弃用,并将在 3.5 中删除。它是 QUIC 配置应用精简流程的一部分。如果使用,此设置将仅应用于前端连接。
设置前端或后端侧每个连接的故障阈值,达到该阈值时连接将自动终止。这允许自动终止行为不当的连接,而无需为它们编写显式规则。默认值为零,表示未设置阈值,因此不会有任何事件导致连接关闭。请注意,一些 QUIC 客户端在长时间连接中可能会偶尔导致一些故障,因此这里的任何非零值可能都应在数百或数千范围内才能有效,而不会影响稍微有问题的客户端。也可以通过使用 "tune.glitches.kill.cpu-usage" 仅在 CPU 使用率超过某个级别时终止连接。
此关键字在 3.3 中已弃用,并将在 3.5 中删除。它是 QUIC 配置应用精简流程的一部分。如果使用,此设置将仅应用于前端连接。
一旦半开连接数达到此数值,将为所有已配置的 QUIC 侦听器动态启用重试(Retry)功能。半开连接是指其握手尚未成功完成或失败的连接。要使此设置生效,需要设置集群密钥(cluster secret),否则它将被静默忽略(参见“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)
此关键字在 3.3 中已弃用,并将在 3.5 中删除。它是 QUIC 配置应用精简流程的一部分。如果使用,此设置将仅应用于前端连接。
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)
此关键字在 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.fe.stream.data-ratio <0..100, in percent>
此设置允许配置每个流中传输中数据字节数的硬限制。它以 QUIC 流 rxbuf 连接设置的百分比表示,结果向上舍入到 bufsize。默认值是 90。这适用于最常见的 Web 场景,其中上传仅针对一个或几个流执行,而其余流仅用于下载。如果流 rxbuf 连接限制保持在合理水平,则确保只有一部分打开的流可以分配到其最大容量。在应用程序并行使用许多上传流并遭受这些流之间不公平性的情况下,降低此比率可能是有意义的,以增加公平性并减少每流带宽。
tune.quic.frontend.stream-data-ratio <0..100, in percent> (deprecated)
此关键字在 3.3 中已弃用,并将在 3.5 中删除。它是 QUIC 配置应用精简流程的一部分。如果使用,此设置将仅应用于前端连接。
设置前端或后端侧的 QUIC initial_max_streams_bidi 传输参数。这是远程对等方在连接生命周期内将被授权同时打开的双向流的最大数量。在前端侧,这限制了并发 HTTP/3 客户端请求的数量。默认值是 100。请注意,如果您减少它,它可能会限制流在接收时的缓冲能力,这会导致上传吞吐量差。可以通过增加 QUIC 流 rxbuf 连接设置来纠正。
此关键字在 3.3 中已弃用,并将在 3.5 中删除。它是 QUIC 配置应用精简流程的一部分。如果使用,此设置将仅应用于前端连接。
此设置是 QUIC 前端连接中传输中数据字节数的硬限制。它被重用作为 initial_max_data 传输参数的值。它直接影响对等方的上传带宽,具体取决于延迟和 haproxy 中每个连接的内存消耗。默认情况下,该值设置为 0,表示它必须自动生成为 max-concurrent 和 bufsize 的乘积。例如,如果后端应用程序依赖于高延迟网络上的大量上传,则可以增加此值。
此关键字在 3.3 中已弃用,并将在 3.5 中删除。它是 QUIC 配置应用精简流程的一部分。如果使用,此设置将仅应用于前端连接。
启用('on')或禁用('off')QUIC 发射的分组支持。默认情况下,它是活动的。分组的目的是平滑数据发射以减少网络丢失。在大多数情况下,它将通过避免重传来显著提高网络吞吐量。但是,对于具有非常高带宽/低延迟特性的网络,禁用它可能很有用,以防止不必要的延迟并减少 CPU 消耗。另请参阅 "quic-cc-algo" 绑定选项。
此关键字在 3.3 中已弃用,并将在 3.5 中删除。它是 QUIC 配置应用精简流程的一部分。如果使用,此设置将仅应用于前端连接。
启用('on')或禁用('off')QUIC 发射的 UDP GSO 支持。默认情况下,它是活动的。此内核功能允许通过单个系统调用发射多个数据报,这对于大型传输更高效。当怀疑发射有问题时,根据开发人员的建议禁用它可能很有用。
此关键字在 3.3 中已弃用,并将在 3.5 中删除。它是 QUIC 配置应用精简流程的一部分。如果使用,此设置将仅应用于前端连接。
tune.quic.listen { on | off }
禁用前端侧的 QUIC 传输协议。所有 QUIC 侦听器仍将创建,但它们不会侦听传入数据报。因此,haproxy 将不会处理前端侧的任何 QUIC 流量。默认值是 "on"。如果怀疑 QUIC 流量有问题,可以使用此选项轻松切换 QUIC 侦听器,而无需修改每个单独的配置行。另请参阅 "quic_enabled" 样本获取。
设置 QUIC 协议栈在传输层用于发送的最大可用内存量。这既是飞行中字节的限制,也是多路复用器输出缓冲区的限制。请注意,为防止线程竞争,此限制并非严格执行,因此在某些情况下可能会超过。此外,每个连接将始终能够使用至少 2 个数据报的窗口,因此应与适当的 maxconn 结合使用。
tune.quic.frontend.max-tx-mem <size> (deprecated)
此关键字在 3.3 中已弃用,并将在 3.5 中删除。它是 QUIC 配置应用精简流程的一部分。如果使用,此设置将仅应用于前端连接。
启用('on')或禁用('off')QUIC 多路复用器的零拷贝数据发送。默认情况下启用。
此配置选项接受一个介于 -20 和 19 之间的值。它应用了 man 2 setpriority 中记录的调度优先级。此优先级在配置解析之后应用,这意味着只有工作进程或独立进程会应用它。通常配置它以设置比执行配置解析的进程(tune.renice.startup)更高的优先级。
此配置选项接受一个介于 -20 和 19 之间的值。它应用了 man 2 setpriority 中记录的调度优先级。此优先级在应用其余配置之前应用,如果您想降低配置解析的优先级,这可能很有用。这应用于独立进程或工作进程在配置解析之前。一旦配置被解析,除非使用 tune.renice.runtime,否则将恢复先前的优先级。
将非连接套接字上的内核套接字接收缓冲区大小设置为此大小。这可用于侦听器模式下的 QUIC 和前端上的日志转发。默认系统缓冲区有时可能太小,无法接收大量聚合流量的套接字,导致一些丢失和可能的重传(在 QUIC 的情况下),可能会在高流量下减慢连接建立速度。该值以字节表示,应用于每个套接字。在侦听器模式下,套接字在所有连接之间共享,套接字总数取决于 "bind" 行的 "shards" 值。没有一个好的值,一个好的值对应于预期大小乘以预期连接数。内核可能会修剪大值。另请参阅 "tune.rcvbuf.client" 和 "tune.rcvbuf.server" 以了解其连接套接字对应项,以及 "tune.sndbuf.backend" 和 "tune.sndbuf.frontend" 以了解发送设置。
强制将客户端或服务器端的内核套接字接收缓冲区大小设置为指定的字节值。此值适用于所有 TCP/HTTP 前端和后端。通常不应设置此值,默认大小(0)让内核根据可用内存量自动调整此值。但是,有时将其设置为非常低的值(例如 4096)有助于节省内核内存,因为它阻止内核缓冲过多的接收数据。不过,较低的值会显著增加 CPU 使用率。
HAProxy 使用一些提示来检测短读是否表示套接字缓冲区的末尾。其中之一是读取返回的字节数超过 <recv_enough>,默认为 10136(7 个 1448 字节的段)。此默认值可以通过此设置更改,以更好地处理涉及大量短消息的工作负载,例如 telnet 或 SSH 会话。
设置环形缓冲区前面的写队列数量。这可能会影响调试会话期间跟踪的 CPU 使用率,过低或过高的值都可能产生重要影响。合适的值是由开发人员通过实验确定的,除非被指示这样做以尝试解决特定问题,否则不应尝试更改它。在版本升级时不应将此类设置保留在配置中,因为其最佳值可能会随时间变化。
设置运行任务时一次可以处理的最大任务量。默认值取决于线程数,但在 35 到 280 之间,这往往显示出最高的请求率和最低的延迟。增加它可能会在处理 I/O 时产生延迟,使其太小可能会产生额外的开销。较高的线程数受益于较低的值。当尝试使用更大的值时,启用 tune.sched.low-latency 和可能启用 tune.fd.edge-triggered 以将最大延迟限制在最低可能值可能会很有用。
启用('on')或禁用('off')低延迟任务调度器。默认情况下,HAProxy 一次处理一个类别的多个类别的任务,因为这是最有效的。但是当使用较大的 tune.runqueue-depth 值运行时,这可能对请求或连接延迟产生可测量的影响。启用此低延迟设置后,如果存在较低优先级类别的任务,它们将始终在其他任务之前执行。这将允许在大量流量中降低新请求或连接所经历的最大延迟,但代价是对这种大流量产生更大的影响。对于常规使用,最好保持关闭。默认值为 off。
将非连接套接字上的内核套接字发送缓冲区大小设置为此大小。这可用于后端侧的 UNIX 套接字和 UDP 日志记录,以及前端上侦听器模式下的 QUIC。默认系统缓冲区有时可能太小,无法在许多连接(或日志发送者)之间共享套接字,导致一些丢失和可能的重传,从而在高流量下减慢新连接建立速度。该值以字节表示,应用于每个套接字。在侦听器模式下,套接字在所有连接之间共享,套接字总数取决于 "bind" 行的 "shards" 值。没有一个好的值,一个好的值对应于预期大小乘以预期连接数。内核可能会修剪大值。另请参阅 "tune.sndbuf.client" 和 "tune.sndbuf.server" 以了解其连接套接字对应项,以及 "tune.rcvbuf.backend" 和 "tune.rcvbuf.frontend" 以了解接收设置。
强制将客户端或服务器端的内核套接字发送缓冲区大小设置为指定的字节值。此值适用于所有 TCP/HTTP 前端和后端。通常不应设置此值,默认大小(0)让内核根据可用内存量自动调整此值。但是,有时将其设置为非常低的值(例如 4096)有助于节省内核内存,因为它阻止内核缓冲过多的接收数据。不过,较低的值会显著增加 CPU 使用率。另一个用例是防止与极慢的客户端发生写超时,因为内核会等待缓冲区的大部分被读取后才再次通知 HAProxy。另请参阅 tune.notsent-lowat.client 和 tune.notsent-lowat.server,以获取更有效设置,以更精细地控制 Linux 上的内存使用和响应性,而不会损害性能。
设置全局 SSL 会话缓存的大小,以块为单位。一个块足够大,可以包含一个不带对等证书的编码会话。一个带对等证书的编码会话根据对等证书的大小存储在多个块中。一个块大约使用 200 字节的内存(基于用于 `shctx_init` 函数的 `sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE` 计算)。默认值可在构建时强制指定,否则默认为 20000。当缓存满时,最空闲的条目将被清除并重新分配。较高的值会减少这种清除的发生,从而通过确保所有用户尽可能长时间地保留其会话来减少 CPU 密集型的 SSL 握手次数。所有条目在启动时预先分配。将此值设置为 0 会禁用 SSL 会话缓存。
设置用于捕获客户端 hello 密码列表、扩展列表、椭圆曲线列表和椭圆曲线点格式的缓冲区的最大大小。如果值为 0(默认值),则禁用捕获,否则将为每个 SSL/TLS 连接分配一个缓冲区。
在 DHE 密钥交换的情况下,设置用于生成临时/临时 Diffie-Hellman 密钥的 Diffie-Hellman 参数的最大大小。最终大小将尝试匹配服务器的 RSA(或 DSA)密钥的大小(例如,对于 2048 位 RSA 密钥,使用 2048 位临时 DH 密钥),但不会超过此最大值。只允许 1024 或更高的值。较高的值会增加 CPU 负载,而大于 1024 位的值不受 Java 7 及更早版本的客户端支持。如果直接在证书文件中或通过使用 ssl-dh-param-file 参数提供了静态 Diffie-Hellman 参数,则不使用此值。如果既没有定义 default-dh-param 也没有定义 ssl-dh-param-file,并且给定前端的服务器 PEM 文件没有指定其自己的 DH 参数,则 DHE 密码将对此前端不可用。
此选项禁用所有进程之间的 SSL 会话缓存共享。通常不应使用它,因为它会由于客户端命中随机进程而强制进行许多重新协商。但在某些操作系统上可能需要它,因为这些操作系统上可能无法使用任何 SSL 缓存同步方法。在这种情况下,在 SSL 层之前添加第一层基于哈希的负载均衡可能会限制缺少会话共享的影响。
设置在任何时候传递给 SSL_write() 的最大字节数。默认值 0 表示没有限制。与 tune.ssl.maxrecord 相反,此设置不会动态调整。较小的记录可能会降低吞吐量,但在处理低占用客户端时可能是必需的。
tune.ssl.keylog { on | off }
此选项激活 TLS 密钥的日志记录。应谨慎使用它,因为它会为每个 SSL 会话消耗更多内存并可能降低性能。默认情况下禁用此功能。这些样本获取应用于生成解密 Wireshark 流量所需的 SSLKEYLOGFILE。https://mdn.org.cn/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format SSLKEYLOG 的格式如下:
设置缓存的 SSL 会话可以保持有效的时长。此时间以秒为单位表示,默认为 300(5 分钟)。重要的是要理解,这并不保证会话会持续那么长时间,因为如果缓存已满,最长时间空闲的会话将被清除,尽管它们配置了生命周期。此设置的真正用处是防止会话被使用太长时间。
设置在数据传输开始时传递给 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。
将用于存储生成证书的缓存大小设置为 <number> 个条目。这是一个 LRU 缓存。因为动态生成 SSL 证书的开销很大,所以它们被缓存起来。默认缓存大小设置为 1000 个条目。
设置可通过 "tcp-request" 或 "http-request" 规则中的 "track-sc*" 操作由连接或请求同时跟踪的 stick-counters 数量。默认值在构建时由宏 MAX_SESS_STK_CTR 设置,默认为 3。使用此设置可以更改值并忽略构建时传递的值,但不能将其设置为大于 100 的值。在将复杂配置移植到 haproxy 时可能需要增加此值,但警告用户注意成本:每个条目每个连接占用 16 字节,每个请求占用 16 字节,所有这些都需要为所有请求分配和清零,即使未使用。因此,值 10 会使每个请求的内存消耗增加 320 字节,并会导致此内存在每个请求中被擦除,这确实具有可测量的 CPU 影响。相反,当不使用 "track-sc" 规则时,可以降低该值(0 有效地完全禁用 stick-counters)。
默认情况下,我们不会尝试使用其他线程组的空闲连接。但是,这可以更改。<值> 的有效值为:“none”,默认值,如果使用,将不会尝试使用其他线程组的空闲连接;“restricted”,其中我们只有在使用无法创建新连接的协议(例如反向 http)以及使用 strict-maxconn 时才会尝试从另一个线程获取空闲连接;以及“full”,其中我们将始终在其他线程组中查找空闲连接。请注意,使用其他线程组的连接可能会产生性能损失,因此除非确实需要,否则不应使用。
这五个调优有助于管理变量系统使用的最大内存量。"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",则所有可用空间都被消耗。请注意,运行时超出限制不会导致错误消息,但值可能会被截断或损坏。因此,请确保准确规划存储所有变量所需的空间量。
为每个流设置 zlib 初始化中的 memLevel 参数。它定义了应为内部压缩状态分配多少内存。值为 1 使用最少的内存,但速度慢并降低压缩率;值为 9 使用最大的内存以获得最佳速度。可以是 1 到 9 之间的值。默认值为 8。
为每个流设置窗口大小(历史缓冲区的大小)作为 zlib 初始化的参数。此参数的较大值会导致更好的压缩,但代价是内存使用量增加。可以是 8 到 15 之间的值。默认值为 15。

3.3. 调试

anonkey <密钥>
这将全局匿名化密钥设置为 <密钥>,它必须是一个介于 0 和 4294967295 之间的 32 位数字。这是启用匿名模式时 CLI 命令默认使用的密钥。此密钥也可以在运行时通过 CLI 命令“set anon global-key”设置。另请参阅管理手册中的命令行参数“-dC”。
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 命令更改此状态。请查阅管理手册。
此命令将配置解析器暂停 <timeout> 毫秒。这对于开发或测试 init 脚本的超时非常有用,特别是用于模拟非常长的重载。它需要设置 expose-experimental-directives。<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后跟单位后缀,也可以是任何其他单位,如本文档开头所述。
示例
global expose-experimental-directives force-cfg-parser-pause 10s
这通过跳过释放内存对象和侦听器来加快重载时旧进程的退出,因为所有这些都将在进程死亡时由操作系统回收。收益只是微不足道的(对于巨大的配置,最多也就几百毫秒)。实际上,主要目标用途是当在 deinit() 代码中发现错误时,因为它允许绕过它。除非开发人员指示,否则最好不要使用此选项。
启动期间不显示任何消息。它等同于命令行参数 "-q"。
这允许调整卡住任务阻塞流量后触发在标准错误输出上发出警告的延迟。延迟以毫秒表示,默认为 100 毫秒。允许的值必须在 1 毫秒到 1000 毫秒之间(包括 1 毫秒和 1000 毫秒)。较低的值会频繁触发警告,较高的值会很少触发警告。看门狗无论如何都会在 1 秒内对未能响应两次的失控任务进行终止,因此 1000 毫秒的警告延迟通常不会触发任何警告。建议将值保持在 10 到 100 毫秒之间,以检测可能降低用户体验、导致响应时间过长或交互式会话卡顿的配置异常。例如,设计不当的 Lua 样本获取函数进行繁重计算,或者具有非常高评估成本的非常大的 map_reg 或 map_regm map 文件可能会导致此类问题。相比之下,TLS 握手可能需要一到两毫秒,压缩 16kB HTTP 响应缓冲区大约需要一毫秒。输出包含违规任务的线程转储以及回溯和一些上下文,有助于找出时间花在哪里。
设置此选项后,如果在处理和应用配置时发出任何警告,HAProxy 将拒绝启动。这意味着有关参数组合不佳的警告、有关无法设置的非常高限制的警告等等,都会使进程在启动期间因错误而退出。此选项无法捕获一些较晚的启动警告,例如在“daemon”或“master-worker”模式下更改组 ID 时未能丢弃补充组,或者在 fork() 后未能将进程标记为可转储。此选项不捕获运行时发出的警告。强烈建议在不经常更改的配置上设置此选项,因为它有助于检测细微的错误并保持配置的整洁和向前兼容。请注意,“haproxy -c”在这种情况下也会报告错误。此选项等同于命令行参数“-dW”。

3.4. HTTPClient 调优

HTTPClient 是一个内部 HTTP 库,可供各种子系统使用,例如在 LUA 脚本中。HTTPClient 不用于数据路径,换句话说,它与通过 HAProxy 的 HTTP 流量无关。
禁用 httpclient 的 DNS 解析。阻止创建“default”解析器部分。默认值为 off。
此选项定义了 httpclient 将尝试解析时使用的解析器部分。默认选项是“default”解析器 ID。默认情况下,如果不使用此选项,如果找不到该部分,它将简单地禁用解析。但是,当明确启用此选项时,如果加载失败,它将触发配置错误。
此选项允许您在解析时选择您想要的 IP 族,当您的网络上 IPv6 不可用时,这很方便。默认选项是“ipv6”。
此选项允许配置 httpclient 在请求失败时的重试次数。这与后端中的“retries”关键字的作用相同。默认值为 3。
此选项定义了应用于验证服务器证书的 ca-file。它接受与服务器行上的“ca-file”选项相同的参数。默认情况下以及不使用此选项时,值为“@system-ca”,它会尝试加载系统的 CA。如果失败,httpclient 的 SSL 将被禁用。但是,当明确启用此选项时,如果失败,它将触发配置错误。
httpclient.ssl.verify [none|required]
其工作方式与服务器行上的 verify 选项相同。如果指定为 'none',则不验证服务器证书。默认选项是“required”。默认情况下以及不使用此选项时,值为“required”。如果失败,httpclient 的 SSL 将被禁用。但是,当明确启用此选项时,如果失败,它将触发配置错误。
为 httpclient 默认设置连接尝试的最大等待时间。
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
默认值为 5000ms。
代理配置可以位于一组部分中:- defaults [<name>] [ from <defaults_name> ] - frontend <name> [ from <defaults_name> ] - backend <name> [ from <defaults_name> ] - listen <name> [ from <defaults_name> ] "frontend" 部分描述了一组接受客户端连接的侦听套接字。"backend" 部分描述了一组代理将连接到以转发传入连接的服务器。"listen" 部分定义了一个完整的代理,其前端和后端部分组合在一个部分中。它通常对仅 TCP 流量有用。"defaults" 部分将所有设置重置为已记录的设置,并为后续部分预设新设置。所有 "frontend"、"backend" 和 "listen" 部分始终从 defaults 部分获取其初始设置,默认情况下是新创建部分之前出现的最新一个。可以通过在部分行上指示其名称以及可选关键字 "from" 来显式指定从中加载初始设置的特定 "defaults" 部分。虽然 "defaults" 部分不要求名称,但为了更好的可读性,鼓励使用此用法。这也是指定要使用的特定部分而不是默认上一个部分的唯一方法。由于 "defaults" 部分名称是可选的,因此默认情况下对其名称应用非常宽松的检查,甚至允许它们重叠。但是,如果 "defaults" 部分被任何其他部分引用,则其名称必须符合对所有代理名称施加的语法,并且此名称在 defaults 部分中必须是唯一的。请注意,无论当前允许什么,建议通常避免重复的部分名称,并遵守与代理名称相同的语法。此规则可能会在未来版本中强制执行。此外,如果 defaults 部分被代理显式使用,而又被另一个代理隐式使用(因为它是定义的最后一个),则会发出警告。强烈建议不要混合使用这两种用法,方法是始终使用显式引用或添加一个保留用于所有隐式使用的最后一个公共 defaults 部分。请注意,defaults 部分甚至可以从另一个 defaults 部分获取其初始设置,因此可以在多级 defaults 部分中继承设置。这对于建立某些配置配置文件以携带默认设置组(例如 TCP 与 HTTP 或短超时与长超时)可能很方便,但很快就会变得难以理解。所有代理名称必须由大小写字母、数字、'-'(破折号)、'_'(下划线)、'.'(点)和 ':'(冒号)组成。ACL 名称区分大小写,这意味着 "www" 和 "WWW" 是两个不同的代理。历史上,当满足某些条件时(例如,当没有相同的前端/后端功能时),所有代理名称可以重叠,但这过去常常在日志中造成太多问题,以及 CLI 操作、stick-tables 命名和统计信息检索方面的混淆。现在强制要求两个代理具有不同的名称,无论其各自的功能如何。目前,支持两种主要的代理模式:"tcp",也称为第 4 层,以及 "http",也称为第 7 层。在第 4 层模式下,HAProxy 只是转发两侧之间的双向流量。在第 7 层模式下,HAProxy 分析协议,并可以通过允许、阻止、切换、添加、修改或删除请求或响应中的任意内容来与之交互,基于任意标准。在 HTTP 模式下,应用于流经连接的请求和响应的处理取决于前端的 HTTP 选项和后端的组合。HAProxy 支持 3 种连接模式:- KAL:保持活动("option http-keep-alive"),这是默认模式:处理所有请求和响应,连接保持打开状态,但在响应和新请求之间空闲。- SCL:服务器关闭("option http-server-close"):在接收到响应结束时关闭面向服务器的连接,但面向客户端的连接保持打开状态。- CLO:关闭("option httpclose"):在响应结束时关闭连接,并在两个方向上附加 "Connection: close"。应用于流经前端和后端的连接的有效模式可以由两种代理模式根据以下矩阵确定,但简而言之,模式是对称的,保持活动是最弱的选项,关闭是最强的选项。后端模式 | KAL | SCL | CLO ----+-----+-----+---- KAL | KAL | SCL | CLO ----+-----+-----+---- SCL | SCL | SCL | CLO ----+-----+-----+---- CLO | CLO | CLO | CLO 可以将 TCP 前端连接到 HTTP 后端。如果只处理 HTTP 流量,则没有意义。但它可用于在同一前端内处理多种协议。在这种情况下,客户端的连接首先作为原始 tcp 连接处理,然后升级到 HTTP。在升级之前,内容处理是在原始数据上执行的。升级后,数据将使用称为 HTX 的内部表示形式进行解析和存储,并且不再可能依赖原始表示形式。无法回溯。有两种升级方式,就地升级和破坏性升级。第一个涉及 TCP 到 HTTP/1 升级。在 HTTP/1 中,请求处理是序列化的,因此可以保留应用程序流。第二个涉及 TCP 到 HTTP/2 升级。因为它是多路复用协议,所以应用程序流不能与任何 HTTP/2 流相关联,并且被销毁。当 HAProxy 在较低级别(在 H2 多路复用器中)接收到新的 HTTP/2 流时,将创建新的应用程序流。理解这种差异很重要,因为它会彻底改变处理数据的方式。执行 HTTP/1 升级时,已经在原始数据上执行的内容处理既不会丢失也不会重新执行,而对于 HTTP/2 升级,应用程序流是不同的,并且所有前端规则都会在每个流上系统地评估。如前所述,第一个流(TCP 流)被销毁,但仅在评估前端规则之后。从 TCP 代理执行 HTTP 处理时,还有另一个要理解的重要点。虽然 HAProxy 能够从 tcp-request content 规则中即时解析 HTTP/1,但对于 HTTP/2 则不可能。只能解析 HTTP/2 序言。这是 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. 代理关键字矩阵

支持以下关键字列表。它们中的大多数可能只能在有限的一组部分类型中使用。其中一些被标记为 "deprecated"(已弃用),因为它们继承自可能令人困惑或功能受限的旧语法,并且有新的推荐关键字来替换它们。标有 "(*)" 的关键字可以使用 "no" 前缀可选地反转,例如 "no option contstats"。当选项默认启用并且必须针对特定实例禁用时,这很有意义。此类选项也可以使用 "default" 前缀,以便无论在以前的 "defaults" 部分中指定了什么,都恢复默认设置。在标有 "(!)" 的 defaults 部分中支持的关键字仅在命名 defaults 部分中支持,在匿名 defaults 部分中不支持。注意:一些危险且不推荐的指令故意未在以下矩阵中列出。这是故意的。这些指令已记录。但不在下面列出是另一种劝阻任何人使用它的方式。
关键字defaultsfrontendlistenbackend
aclX (!)XXX
backlogXXX 
balanceX XX
bind XX 
capture cookie XX 
capture request header XX 
capture response header XX 
clitcpka-cntXXX 
clitcpka-idleXXX 
clitcpka-intvlXXX 
compressionXXXX
cookieX XX
crt XX 
declare capture XX 
default-serverX XX
default_backendXXX 
description XXX
disabledXXXX
(deprecated)dispatch  XX
email-alert fromXXXX
关键字defaultsfrontendlistenbackend
email-alert levelXXXX
email-alert mailersXXXX
email-alert myhostnameXXXX
email-alert toXXXX
enabledXXXX
errorfileXXXX
errorfilesXXXX
errorlocXXXX
errorloc302XXXX
errorloc303XXXX
error-log-formatXXX 
force-persist  XX
filter XXX
fullconnX XX
guid XXX
hash-balance-factorX XX
hash-preserve-affinityX XX
hash-typeX XX
http-after-responseX (!)XXX
http-check commentX XX
关键字defaultsfrontendlistenbackend
http-check connectX XX
http-check disable-on-404X XX
http-check expectX XX
http-check sendX XX
http-check send-stateX XX
http-check set-varX XX
http-check unset-varX XX
http-errorXXXX
http-requestX (!)XXX
http-responseX (!)XXX
http-reuseX XX
http-send-name-headerX XX
id XXX
ignore-persist  XX
load-server-state-from-fileX XX
(*)logXXXX
log-formatXXX 
log-format-sdXXX 
log-tagXXXX
log-stepsXXX 
关键字defaultsfrontendlistenbackend
max-keep-alive-queueX XX
max-session-srv-connsXXX 
maxconnXXX 
modeXXXX
monitor fail XX 
monitor-uriXXX 
(*)option abortoncloseXXXX
(*)option allbackupsX XX
(*)option checkcacheX XX
(*)option clitcpkaXXX 
(*)option contstatsXXX 
(*)option disable-h2-upgradeXXX 
(*)option dontlog-normalXXX 
(*)option dontlognullXXX 
option forwardforXXXX
(*)option forwardedX XX
(*)option h1-case-adjust-bogus-clientXXX 
(*)option h1-case-adjust-bogus-serverX XX
(*)option http-buffer-requestXXXX
(*)option http-drop-request-trailersX  X
关键字defaultsfrontendlistenbackend
(*)option http-drop-response-trailersX X 
(*)option http-ignore-probesXXX 
(*)option http-keep-aliveXXXX
(*)option http-no-delayXXXX
(*)option http-pretend-keepaliveX XX
option http-restrict-req-hdr-namesXXXX
(*)option http-server-closeXXXX
(*)option http-use-proxy-headerXXX 
option httpchkX XX
(*)option httpcloseXXXX
option httplogXXX 
option httpslogXXX 
(*)option independent-streamsXXXX
option ldap-checkX XX
option external-checkX XX
(*)option log-health-checksX XX
(*)option log-separate-errorsXXX 
(*)option logasapXXX 
option mysql-checkX XX
(*)option nolingerXXXX
关键字defaultsfrontendlistenbackend
option originaltoXXXX
(*)option persistX XX
option pgsql-checkX XX
(*)option prefer-last-serverX XX
(*)option redispatchX XX
option redis-checkX XX
option smtpchkX XX
(*)option socket-statsXXX 
(*)option splice-autoXXXX
(*)option splice-requestXXXX
(*)option splice-responseXXXX
option spop-checkX XX
(*)option srvtcpkaX XX
option ssl-hello-chkX XX
option tcp-checkX XX
(*)option tcp-smart-acceptXXX 
(*)option tcp-smart-connectX XX
option tcpkaXXXX
option tcplogXXX 
(deprecated)(*)option transparentX XX
关键字defaultsfrontendlistenbackend
(*)option idle-close-on-responseXXX 
external-check commandX XX
external-check pathX XX
persist rdp-cookieX XX
quic-initialX (!)XX 
rate-limit sessionsXXX 
redirect XXX
retriesX XX
retry-onX XX
server  XX
server-state-file-nameX XX
server-template  XX
sourceX XX
srvtcpka-cntX XX
srvtcpka-idleX XX
srvtcpka-intvlX XX
stats admin XXX
stats authXXXX
stats enableXXXX
stats hide-versionXXXX
关键字defaultsfrontendlistenbackend
stats http-request XXX
stats realmXXXX
stats refreshXXXX
stats scopeXXXX
stats show-descXXXX
stats show-legendsXXXX
stats show-nodeXXXX
stats uriXXXX
stick match  XX
stick on  XX
stick store-request  XX
stick store-response  XX
stick-table XXX
tcp-check commentX XX
tcp-check connectX XX
tcp-check expectX XX
tcp-check sendX XX
tcp-check send-lfX XX
tcp-check send-binaryX XX
tcp-check send-binary-lfX XX
关键字defaultsfrontendlistenbackend
tcp-check set-varX XX
tcp-check unset-varX XX
tcp-request connectionX (!)XX 
tcp-request contentX (!)XXX
tcp-request inspect-delayX (!)XXX
tcp-request sessionX (!)XX 
tcp-response contentX (!) XX
tcp-response inspect-delayX (!) XX
timeout checkX XX
timeout clientXXX 
timeout client-finXXX 
timeout client-hsXXX 
timeout connectX XX
timeout http-keep-aliveXXXX
timeout http-requestXXXX
timeout queueX XX
timeout serverX XX
timeout server-finX XX
timeout tarpitXXXX
timeout tunnelX XX
关键字defaultsfrontendlistenbackend
(已弃用)transparentX XX
unique-id-formatXXX 
unique-id-headerXXX 
use_backend XX 
use-fcgi-app  XX
use-server  XX

4.2. 按字母排序的关键字参考

本节提供了每个关键字及其用法的描述。
acl <aclname> <criterion> [flags] [operator] <value> ...
声明或完成一个访问列表。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend
是(!)
yes(!)

yes

yes

yes
此指令仅在命名的 defaults 部分可用,而不能在匿名的 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
有关 ACL 的用法,请参见第 7 节
backlog <conns>
向系统提供关于期望的侦听积压队列大致大小的提示。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<conns> 是待处理连接的数量。根据操作系统的不同,它可能表示已确认的连接数、未确认的连接数或两者之和。
此选项仅对流侦听器有意义,包括 QUIC 侦听器。但是,它的行为与 QUIC 实例不同。对于所有侦听器(QUIC 除外),为了防止 SYN 洪水攻击,一种解决方案是增加系统的 SYN 积压大小。根据系统,有时它只是通过系统参数可调,有时根本不可调,有时系统依赖于应用程序在 listen() 系统调用时给出的提示。默认情况下,HAProxy 将前端的 maxconn 值传递给 listen() 系统调用。在可以利用此值的系统上,能够指定不同的值有时很有用,因此有了此 backlog 参数。在 Linux 2.4 上,系统会忽略该参数。在 Linux 2.6 上,它被用作提示,系统接受高达最小的更大二次幂,并且永远不会超过某些限制(通常为 32768)。对于 QUIC 侦听器,积压为活动握手和等待接受的连接的最大计数设置了共享限制。握手阶段主要依赖于与远程对等方的网络延迟,而第二阶段完全取决于 haproxy 负载。当达到其中一个限制时,haproxy 开始丢弃对 INITIAL 数据包的接收,阻止任何新连接分配,直到连接超额开始减少。这种情况可能导致浏览器静默降级 HTTP 版本并切换到 TCP。
balance <algorithm> [ <arguments> ]
balance url_param <param> [check_post]
定义在后端中使用的负载均衡算法。可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<algorithm> 是用于在进行负载均衡时选择服务器的算法。这仅适用于没有可用持久性信息,或连接被重新调度到另一台服务器时。<algorithm> 可以是以下之一: roundrobin 每个服务器根据其权重轮流使用。当服务器的处理时间均匀分布时,这是最平滑和最公平的算法。此算法是动态的,这意味着服务器权重可以即时调整,例如用于慢启动。它在设计上限制为每个后端最多 4095 个活动服务器。请注意,在某些大型集群中,当服务器在非常短的时间内停机后恢复运行时,有时可能需要数百个请求才能重新集成到集群中并开始接收流量。这是正常的,尽管非常罕见。在此指出是为了以防您有机会观察到它,这样您就不会担心。注意:对于处于 LOG 模式的后端,权重会被忽略。 static-rr 每个服务器根据其权重轮流使用。此算法与 roundrobin 类似,只是它是静态的,这意味着即时更改服务器的权重无效。另一方面,它对服务器数量没有设计限制,并且当服务器启动时,一旦重新计算完整映射,它总是立即重新引入集群。它运行所需的 CPU 也略少(大约 -1%)。此算法在 LOG 模式下不可用。 leastconn 具有最低连接数的服务器接收连接。在具有相同负载的服务器组内执行轮询,以确保所有服务器都将被使用。建议在预期非常长的会话(例如 LDAP、SQL、TSE 等)时使用此算法,但不太适合使用短会话的协议(例如 HTTP)。此算法是动态的,这意味着服务器权重可以即时调整,例如用于慢启动。它还会考虑排队连接的数量以及已建立的连接,以最大程度地减少排队。此算法在 LOG 模式下不可用。 first 具有可用连接槽的第一个服务器接收连接。服务器按照从最低数字标识符到最高数字标识符的顺序选择(请参阅服务器参数 "id"),该标识符默认为服务器在集群中的位置。一旦服务器达到其 maxconn 值,将使用下一个服务器。如果不设置 maxconn,使用此算法没有意义。此算法的目的是始终使用最少数量的服务器,以便在非高峰时段可以关闭多余的服务器电源。此算法忽略服务器权重,对 RDP 或 IMAP 等长会话的益处大于 HTTP,尽管它在 HTTP 中也可能有用。为了有效地使用此算法,建议云控制器定期检查服务器使用情况以在未使用时将其关闭,并定期检查后端队列以在队列膨胀时打开新服务器。或者,使用 "http-check send-state" 可以告知服务器负载情况。此算法在 LOG 模式下不可用。 hash 以常规样本表达式作为参数。表达式针对每个请求进行评估,并根据配置的 hash-type 进行哈希处理。哈希结果除以正在运行的服务器的总权重,以指定哪个服务器将接收请求。这可以用于代替 "source"、"uri"、"hdr()"、"url_param()"、"rdp-cookie",以便使用转换器、完善评估,或者例如用于从本地变量中提取数据。当数据不可用时,将应用 round robin。此算法默认为静态的,这意味着即时更改服务器的权重无效,但这可以通过使用 "hash-type" 进行更改。此算法在 LOG 模式下不可用于后端,请改用 "log-hash"。 source 源 IP 地址被哈希并除以正在运行的服务器的总权重,以指定哪个服务器将接收请求。这确保了只要没有服务器停机或启动,相同的客户端 IP 地址将始终到达同一服务器。如果由于正在运行的服务器数量变化而导致哈希结果发生变化,许多客户端将被定向到不同的服务器。此算法通常用于无法插入 cookie 的 TCP 模式。它也可以在 Internet 上用于为拒绝会话 cookie 的客户端提供尽力而为的粘性。此算法默认为静态的,这意味着即时更改服务器的权重无效,但这可以通过使用 "hash-type" 进行更改。另请参阅上面的 "hash" 选项。此算法在 LOG 模式下不可用于后端。 uri 此算法对 URI 的左侧部分(问号之前)或整个 URI(如果存在 "whole" 参数)进行哈希处理,并将哈希值除以正在运行的服务器的总权重。结果指定哪个服务器将接收请求。这确保了只要没有服务器启动或停机,相同的 URI 将始终定向到同一服务器。这与代理缓存和防病毒代理一起使用,以最大程度地提高缓存命中率。请注意,此算法只能在 HTTP 后端中使用。此算法默认为静态的,这意味着即时更改服务器的权重无效,但这可以通过使用 "hash-type" 进行更改。此算法支持两个可选参数 "len" 和 "depth",两者都后跟一个正整数。当需要仅基于 URI 的开头来平衡服务器时,这些选项可能会有所帮助。"len" 参数指示算法应仅考虑 URI 开头的那么多字符来计算哈希。请注意,将 "len" 设置为 1 很少有意义,因为大多数 URI 都以开头的 "/" 开头。"depth" 参数指示用于计算哈希的最大目录深度。请求中的每个斜杠算作一个级别。如果同时指定这两个参数,则当达到任一参数时,评估停止。参数 "path-only" 指示哈希键从路径的第一个 '/' 开始。这可用于忽略绝对 URI 的 authority 部分,并确保 HTTP/1 和 HTTP/2 URI 将提供相同的哈希。另请参阅上面的 "hash" 选项。 url_param 将在每个 HTTP GET 请求的查询字符串中查找参数中指定的 URL 参数。如果使用修饰符 "check_post",则在 URL 中问号 ('?') 之后的查询字符串中未找到参数时,将在 HTTP POST 请求实体中搜索参数参数。消息正文将仅在收到 advertised 数据量或请求缓冲区已满时才开始分析。在极少数情况下使用分块编码时,仅扫描第一个分块。由分块边界分隔的参数值可能会随机平衡(如果根本没有平衡)。此关键字过去支持一个可选的 <max_wait> 参数,该参数现在已被忽略。如果找到参数后跟等号 ('=') 和一个值,则对该值进行哈希处理并除以正在运行的服务器的总权重。结果指定哪个服务器将接收请求。这用于跟踪请求中的用户标识符,并确保只要没有服务器启动或停机,相同的用户 ID 将始终发送到同一服务器。如果未找到值或未找到参数,则应用 round robin 算法。请注意,此算法只能在 HTTP 后端中使用。此算法默认为静态的,这意味着即时更改服务器的权重无效,但这可以通过使用 "hash-type" 进行更改。另请参阅上面的 "hash" 选项。 hdr(<name>) 将在每个 HTTP 请求中查找 HTTP 标头 <name>。与等效的 ACL 'hdr()' 函数一样,括号中的标头名称不区分大小写。如果标头不存在或不包含任何值,则应用 roundrobin 算法。一个可选的 'use_domain_only' 参数可用,用于将哈希算法减少到主域部分,并带有一些特定的标头,例如 'Host'。例如,在 Host 值 "haproxy.1wt.eu" 中,只会考虑 "1wt"。此算法默认为静态的,这意味着即时更改服务器的权重无效,但这可以通过使用 "hash-type" 进行更改。另请参阅上面的 "hash" 选项。 random random(<draws>) 一个随机数将用作一致性哈希函数的键。这意味着服务器的权重得到尊重,动态权重更改会立即生效,新服务器的添加也是如此。随机负载均衡对于大型集群或服务器频繁添加或移除的情况很有用,因为它可以避免在这种情况下 roundrobin 或 leastconn 可能导致的锤击效应。 hash-balance-factor 指令可用于进一步提高负载均衡的公平性,尤其是在服务器响应时间高度可变的情况下。当存在参数 <draws> 时,它必须是一个大于或等于一的整数值,表示在选择这些服务器中负载最低的服务器之前抽取的次数。事实上,已经证明选择两个服务器中负载最低的一个足以显着提高算法的公平性,始终避免选择集群中负载最高的服务器,并消除可能由一致列表的不公平分布引起的任何偏差。较高的值 N 将以性能为代价带走 N-1 个负载最高的服务器。值非常高时,算法将收敛到 leastconn 的结果,但速度慢得多。默认值为 2,通常显示出非常好的分布和性能。此算法也称为“两个随机选择的力量”(Power of Two Random Choices),在此处描述:http://www.eecs.harvard.edu/~michaelm/postscripts/handbook2001.pdf 对于处于 LOG 模式的后端,draws 的数量将被忽略,并且会选择一个单一的随机数,因为没有服务器负载的概念。随机日志均衡对于大型集群或服务器频繁添加或从可用服务器池中移除的情况很有用,因为它可以避免在这种情况下 roundrobin 可能导致的锤击效应。 rdp-cookie rdp-cookie(<name>) 将为每个传入的 TCP 请求查找 RDP cookie <name>(如果省略,则为 "mstshash")并对其进行哈希处理。与等效的 ACL 'req.rdp_cookie()' 函数一样,名称不区分大小写。此机制可用作降级的持久性模式,因为它使得始终将同一用户(或同一会话 ID)发送到同一服务器成为可能。如果未找到 cookie,则使用正常的 roundrobin 算法。请注意,为了使其工作,前端必须确保请求缓冲区中已存在 RDP cookie。为此,您必须使用 'tcp-request content accept' 规则结合 'req.rdp_cookie_cnt' ACL。此算法默认为静态的,这意味着即时更改服务器的权重无效,但这可以通过使用 "hash-type" 进行更改。另请参阅上面的 "hash" 选项。 log-hash 以逗号分隔的转换器列表作为参数。这些转换器按顺序应用于输入日志消息,结果将转换为字符串,然后根据配置的 hash-type 进行哈希处理。生成的哈希将用于在日志后端中声明的服务器中选择目标服务器。此算法的目标是能够使用字符串转换器在最终日志消息中提取键,然后通过哈希粘性到同一服务器。目前仅支持 "map-based" 哈希。此算法仅适用于 LOG 模式下的后端,对于其他后端,请改用 "hash"。 sticky 尽可能地粘性到同一服务器。可用服务器列表中的第一个服务器接收所有日志消息。当服务器停机时,列表中的下一个服务器取代其位置。当先前停机的服务器恢复运行时,它被添加到列表的末尾,以便粘性服务器不会更改,直到它停机。<arguments> 是一个可选参数列表,某些算法可能需要这些参数。目前,只有 "url_param"、"uri" 和 "log-hash" 支持可选参数。
当没有设置其他算法、模式或选项时,后端的负载均衡算法设置为 "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) LOG 后端示例: 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 #... Note: the following caveats and limitations on using the "check_post" extension with "url_param" must be considered : - 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.
bind [<address>]:<port_range> [, ...] [param*]
bind /<path> [, ...] [param*]
在前端中定义一个或多个监听地址和/或端口。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

no

yes

yes

no
参数
<address> 是可选的,可以是主机名、IPv4 地址、IPv6 地址或 '*'。它指定前端将侦听的地址。如果未设置,将侦听系统的所有 IPv4 地址。对于 '*' 或系统的特殊地址 "0.0.0.0" 也是如此。IPv6 等效项是 '::'。请注意,对于 UDP,绑定到多个地址时需要特定的操作系统功能,以确保在响应时使用正确的网络接口和源地址。换句话说,对于 QUIC 侦听器,仅在运行足够现代的系统时才绑定到多个地址。或者,可以在地址前使用地址族前缀来强制使用该族,无论地址格式如何,这对于指定没有斜杠 ('/') 的 unix 套接字路径很有用。目前支持的前缀有: - 'ipv4@' -> 地址始终为 IPv4 - 'ipv6@' -> 地址始终为 IPv6 - 'udp@' -> 地址解析为 IPv4 或 IPv6,并使用协议 UDP。目前这些侦听器仅在 log-forward 部分支持。 - 'udp4@' -> 地址始终为 IPv4,并使用协议 UDP。目前这些侦听器仅在 log-forward 部分支持。 - 'udp6@' -> 地址始终为 IPv6,并使用协议 UDP。目前这些侦听器仅在 log-forward 部分支持。 - 'unix@' -> 地址是本地 unix 套接字的路径 - 'abns@' -> 地址位于抽象命名空间中(仅限 Linux)。 - 'abnsz@' -> 地址位于抽象命名空间中(仅限 Linux),但它被显式地以零终止。这意味着不使用 \0 填充来完成 sun_path。这对于与不实现 haproxy 使用的默认 abns 命名逻辑的程序进行互连很有用。 - 'fd@<n>' -> 使用从父级继承的文件描述符 <n>。fd 必须已绑定,并且可能已在侦听或未在侦听。 - 'sockpair@<n>'-> 类似于 fd@,但您必须使用已连接的 unix 套接字或 socketpair 的 fd。绑定等待通过 unix 套接字接收 FD,并将其用作 accept() 的 FD。应谨慎使用。 - 'quic4@' -> 地址解析为 IPv4,并使用协议 UDP。请注意,为了在大流量下获得最佳性能,您应该保持 "tune.quic.fe.sock-per-conn default-on"。否则,QUIC 连接将通过侦听器套接字进行多路复用。另一种替代方法是将 QUIC 侦听器实例复制到多个线程上,例如使用 "shards" 关键字来至少减少线程争用。 - 'quic6@' -> 地址解析为 IPv6,并使用协议 UDP。关于 IPv4 的 QUIC 性能说明同样适用。 - 'rhttp@' [ EXPERIMENTAL ] -> 用于反向 HTTP。地址必须是具有格式 '<backend>/<server>' 的服务器。服务器将用于实例化与远程地址的连接。侦听器将尝试维护 "nbconn" 连接。这是一个实验性功能,需要在此绑定之前的一行上使用 "expose-experimental-directives"。您可能想在 address 参数中引用一些环境变量,请参阅关于环境变量的 section 2.3。<port_range> 是一个唯一的 TCP 端口,或者是代理将接受连接的端口范围,用于上面指定的 IP 地址。对于 TCP 侦听器,端口是强制性的。请注意,在 IPv6 地址的情况下,端口始终是最后一个冒号 (':') 之后的数字。范围可以是: - 单个数字端口(例如:'80') - 以短划线分隔的端口范围,明确说明下限和上限(例如:'2000-2100'),包括在范围内。必须特别注意端口范围,因为每个 <address:port> 对都会消耗一个套接字(= 一个文件描述符),因此很容易通过简单的范围消耗大量描述符,并耗尽套接字。此外,每个 <address:port> 对必须在同一系统上运行的所有实例中仅使用一次。请注意,绑定到低于 1024 的端口通常需要特定的权限才能启动程序,这与 'uid' 参数无关。<path> 是以斜杠 ('/') 开头的 UNIX 套接字路径。这是 TCP 侦听端口的替代方案。HAProxy 将在此位置的套接字上接收 UNIX 连接。路径必须以斜杠开头,并且默认情况下是绝对路径。它可以是相对于全局部分中由 "unix-bind" 定义的前缀。请注意,前缀后跟套接字路径的总长度不能超过 UNIX 套接字的一些系统限制,这些限制通常设置为 107 个字符。<param*> 是同一行上声明的所有套接字共有的参数列表。这些众多参数取决于操作系统和构建选项,并有专门的部分进行介绍。请参阅 section 5 以获取更多详细信息。
可以指定一个由逗号分隔的地址:端口组合列表。然后前端将在所有这些地址上进行监听。前端可以监听的地址和端口数量没有固定限制,同样,前端中的 "bind" 语句数量也没有限制。
Example
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 中向任何抽象套接字定义传递选项 “,unix-tightsocklen=0” 以使其与 HAProxy 兼容,或者改用 “abnsz” HAProxy 套接字族。
capture cookie <name> len <length>
捕获并记录请求和响应中的 cookie。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

no

yes

yes

no
参数
<name> 是要捕获的 cookie 名称的开头。为了精确匹配名称,只需在名称后加上一个等号('=')。完整的名称将出现在日志中,这对于会同时调整 cookie 名称和值的应用服务器(例如 ASPSESSIONXXX)很有用。<length> 是日志中报告的最大字符数,包括 cookie 名称、等号和值,全部采用标准的 "name=value" 格式。如果字符串超过 <length>,它将被从右侧截断。
仅捕获第一个 cookie。监视 "cookie" 请求标头和 "set-cookie" 响应标头。这对于检查导致用户之间会话交叉或窃取的应用程序错误特别有用,因为通常用户的 cookie 只能在登录页面上更改。当客户端未提供 cookie 时,关联的日志列将报告 "-"。当请求未导致服务器分配 cookie 时,响应列中会报告 "-"。捕获仅在前端执行,因为对于给定的前端,日志格式必须不因后端而异。将来可能会改变。请注意,一个前端中只能有一个 "capture cookie" 语句。最大捕获长度由全局 "tune.http.cookielen" 设置,默认为 63 个字符。无法在 "defaults" 部分中指定捕获。
示例
capture cookie ASPSESSION len 32
capture request header <name> len <length>
捕获并记录指定请求头的最后一次出现。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

no

yes

yes

no
参数
<name> 是要捕获的头的名称。头名称不区分大小写,但通常的做法是按照它们在请求中出现的样子来写,每个单词的首字母大写。头名称不会出现在日志中,只报告其值,但其在日志中的位置会得到尊重。<length> 是从值中提取并报告在日志中的最大字符数。如果字符串超过 <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
capture response header <name> len <length>
捕获并记录指定响应头的最后一次出现。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

no

yes

yes

no
参数
<name> 是要捕获的头的名称。头名称不区分大小写,但通常的做法是按照它们在响应中出现的样子来写,每个单词的首字母大写。头名称不会出现在日志中,只报告其值,但其在日志中的位置会得到尊重。<length> 是从值中提取并报告在日志中的最大字符数。如果字符串超过 <length>,它将被从右侧截断。
捕获该头最后一次出现的完整值。结果将添加到日志中,位于捕获的请求头之后,并用大括号('{}')括起来。如果捕获了多个头,它们将用竖线('|')分隔,并按照在配置中声明的相同顺序出现。不存在的头将被记录为空字符串。响应头捕获的常见用途包括指示预期返回字节数的 "Content-length" 头,以及跟踪重定向的 "Location" 头。捕获的响应头数量及其长度没有限制,但明智的做法是保持较低的值以限制每个流的内存使用。为了保持同一前端的日志格式一致,头捕获只能在前端中声明。不能在 "defaults" 部分中指定捕获。
示例
capture response header Content-length len 9 capture response header Location len 15
clitcpka-cnt <计数>
设置 TCP 在客户端侧断开连接之前应发送的最大 keepalive 探测次数。可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<count> 是 keepalive 探测的最大次数。
此关键字对应于套接字选项 TCP_KEEPCNT。如果未指定此关键字,则使用系统范围的 TCP 参数 (tcp_keepalive_probes)。此设置的可用性取决于操作系统。已知在 Linux 上可以工作。
clitcpka-idle <超时>
设置连接需要保持空闲多长时间后,TCP 开始发送 keepalive 探测,如果启用了在客户端侧发送 TCP keepalive 数据包。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<timeout> 是连接需要保持空闲的时间,之后 TCP 开始发送 keepalive 探测。默认以秒为单位指定,但如果数字后跟单位后缀,也可以是任何其他单位,如本文档开头所述。
此关键字对应于套接字选项 TCP_KEEPIDLE。如果未指定此关键字,则使用系统范围的 TCP 参数 (tcp_keepalive_time)。此设置的可用性取决于操作系统。已知在 Linux 上可以工作。
设置客户端侧各个 keepalive 探测之间的时间。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<timeout> 是各个 keepalive 探测之间的时间。默认以秒为单位指定,但如果数字后跟单位后缀,也可以是任何其他单位,如本文档开头所述。
此关键字对应于套接字选项 TCP_KEEPINTVL。如果未指定此关键字,则使用系统范围的 TCP 参数 (tcp_keepalive_intvl)。此设置的可用性取决于操作系统。已知在 Linux 上可以工作。
compression algo <algorithm> ...
compression type <mime type> ...
启用 HTTP 压缩。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
algo 后面是响应支持的压缩算法列表(旧关键字)。algo-req 后面是请求的压缩算法(只提供一种)。algo-res 后面是响应支持的压缩算法列表。type 后面是将为响应压缩的 MIME 类型列表(旧关键字)。type-req 后面是将为请求压缩的 MIME 类型列表。type-res 后面是将为响应压缩的 MIME 类型列表。
目前支持的算法有: identity 这主要用于调试,对于开发压缩功能很有用。Identity 不对数据应用任何更改。 gzip 应用 gzip 压缩。此设置仅在内置支持 zlib 或 libslz 时可用。 deflate 与 "gzip" 相同,但使用 deflate 算法和 zlib 格式。请注意,此算法在许多浏览器上支持模糊,并且最近的浏览器根本不支持。强烈建议不要将其用于除实验之外的任何目的。此设置仅在内置支持 zlib 或 libslz 时可用。 raw-deflate 与 "deflate" 相同,没有 zlib 包装器,用作浏览器需要 "deflate" 时的替代方案。所有主要浏览器都理解它,尽管违反了标准,但已知它比 "deflate" 效果更好,至少在 MSIE 和某些版本的 Safari 上。不要与 "deflate" 结合使用,因为两者都对相同的 Accept-Encoding 令牌做出反应。此设置仅在内置支持 zlib 或 libslz 时可用。压缩将根据 Accept-Encoding 请求标头激活。使用 identity 时,它不关心该标头。如果后端服务器支持 HTTP 压缩,这些指令将不执行任何操作:HAProxy 将看到压缩的响应,并且不会再次压缩。如果后端服务器不支持 HTTP 压缩且请求中存在 Accept-Encoding 标头,HAProxy 将压缩匹配的响应。在以下情况下禁用压缩: * 请求未在 "Accept-Encoding" 标头中宣传支持的压缩算法 * 响应消息不是 HTTP/1.1 或更高版本 * HTTP 状态代码不是 200、201、202 或 203 之一 * 响应既不包含 "Content-Length" 标头,也不包含最后一个值为 "chunked" 的 "Transfer-Encoding" * 响应包含 "Content-Type" 标头,其第一个值以 "multipart" 开头 * 响应在 "Cache-control" 标头中包含 "no-transform" 值 * User-Agent 匹配 "Mozilla/4",除非它是带 XP SP2 的 MSIE 6,或者是 MSIE 7 及更高版本 * 响应包含 "Content-Encoding" 标头,表明响应已压缩(请参阅 compression offload) * 响应包含无效的 "ETag" 标头或多个 ETag 标头 * 有效负载大小小于最小大小(请参阅 compression minsize-res) 注意:压缩不发出 Warning 标头。
示例
compression algo gzip compression type text/html text/plain
设置应用压缩的最小负载大小(以字节为单位)。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
小于此大小的负载将不会被压缩,从而避免了对不会从压缩中显著受益的数据产生不必要的 CPU 开销。"minsize-req" 适用于请求,"minsize-res" 适用于响应。默认值为 0。
使 HAProxy 仅作为压缩卸载器工作。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

no

yes

yes

yes
"offload" 设置使 HAProxy 删除 Accept-Encoding 头,以防止后端服务器压缩响应。强烈建议不要这样做,因为这意味着所有的压缩工作都将在 HAProxy 所在的单点上完成。然而,在某些部署场景中,HAProxy 可能安装在一个有缺陷的网关前面,该网关的 HTTP 压缩实现有问题且无法关闭。在这种情况下,可以使用 HAProxy 来防止该网关发出无效的负载。在这种情况下,仅仅在配置中删除该头是行不通的,因为它在头被解析之前应用,这会阻止 HAProxy 进行压缩。因此,"offload" 设置应用于此类场景。如果在 defaults 部分中使用此设置,则会发出警告并忽略该选项。
使 haproxy 能够同时压缩请求和响应。有效值为 "request",仅压缩请求;"response",仅压缩响应;或 "both",当您想同时压缩两者时。默认值为 "response"。可在以下上下文中使用:http
cookie <名称> [ rewrite | insert | prefix ] [ indirect ] [ nocache ] [ postonly ] [ preserve ] [ httponly ] [ secure ] [ domain <域名> ]* [ maxidle <空闲时间> ] [ maxlife <生命周期> ] [ dynamic ] [ attr <值> ]*
在后端启用基于 cookie 的持久性。可在以下上下文中使用: http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<name> 是将要监视、修改或插入以实现持久性的 cookie 的名称。此 cookie 通过响应中的 "Set-Cookie" 标头发送给客户端,并在所有请求中由客户端通过 "Cookie" 标头带回。应特别注意选择一个名称,该名称不会与任何可能的应用程序 cookie 冲突。此外,如果同一后端可能被同一客户端使用(例如 HTTP/HTTPS),如果不需要它们之间的持久性,则应注意在所有后端之间使用不同的 cookie 名称。 rewrite 此关键字指示 cookie 将由服务器提供,并且 HAProxy 必须修改其值以在其中设置服务器的标识符。当将 "Set-cookie" 和 "Cache-control" 标头的复杂组合管理留给应用程序时,此模式很方便。然后,应用程序可以决定是否适合发出持久性 cookie。由于必须监视所有响应,因此此模式在 HTTP 隧道模式下不起作用。除非应用程序行为非常复杂和/或损坏,否则不建议在新的部署中从这种模式开始。此关键字与 "insert" 和 "prefix" 不兼容。 insert 此关键字指示如果客户端尚未拥有允许其访问此服务器的 cookie,则 HAProxy 必须在服务器响应中插入持久性 cookie。当不使用 "preserve" 选项时,如果服务器发出具有相同名称的 cookie,它将在处理之前被删除。因此,此模式可用于升级在 "rewrite" 模式下运行的现有配置。cookie 将只是一个会话 cookie,不会存储在客户端的磁盘上。默认情况下,除非添加 "indirect" 选项,否则服务器将看到客户端发出的 cookie。由于缓存效应,通常明智的做法是添加 "nocache" 或 "postonly" 关键字(见下文)。"insert" 关键字与 "rewrite" 和 "prefix" 不兼容。 prefix 此关键字指示不依赖专用的持久性 cookie,而是完成现有的 cookie。在某些特定环境中可能需要这样做,其中客户端不支持多个 cookie,并且应用程序已经需要它。在这种情况下,每当服务器设置名为 <name> 的 cookie 时,它将以服务器的标识符和分隔符作为前缀。前缀将从所有客户端请求中删除,以便服务器仍然找到它发出的 cookie。由于所有请求和响应都可能被修改,因此此模式不适用于隧道模式。"prefix" 关键字与 "rewrite" 和 "insert" 不兼容。注意:强烈建议不要将 "indirect" 与 "prefix" 一起使用,否则服务器 cookie 更新将不会发送给客户端。 indirect 指定此选项时,不会向已拥有针对已处理请求的服务器的有效 cookie 的客户端发出 cookie。如果服务器本身设置了此类 cookie,则会将其删除,除非还设置了 "preserve" 选项。在 "insert" 模式下,这还将从传输到服务器的请求中删除 cookie,从而使持久性机制从应用程序的角度来看完全透明。注意:强烈建议不要将 "indirect" 与 "prefix" 一起使用,否则服务器 cookie 更新将不会发送给客户端。 nocache 建议将此选项与 insert 模式结合使用,当客户端和 HAProxy 之间存在缓存时,因为它确保如果需要插入 cookie,可缓存的响应将被标记为不可缓存。这很重要,因为如果所有持久性 cookie 都添加在可缓存的主页上,例如,所有客户都将从外部缓存中获取该页面,并且都将共享相同的持久性 cookie,导致一个服务器接收的流量比其他服务器多得多。另请参阅 "insert" 和 "postonly" 选项。 postonly 此选项确保 cookie 插入将仅在对 POST 请求的响应上执行。它是 "nocache" 选项的替代方案,因为 POST 响应不可缓存,因此这确保了持久性 cookie 永远不会被缓存。由于大多数站点在第一次 POST(通常是登录请求)之前不需要任何形式的持久性,因此这是一种在不冒缓存中存在持久性 cookie 风险的情况下优化缓存的非常有效的方法。另请参阅 "insert" 和 "nocache" 选项。 preserve 此选项只能与 "insert" 和/或 "indirect" 一起使用。它允许服务器自己发出持久性 cookie。在这种情况下,如果在响应中找到 cookie,HAProxy 将保持不变。这对于例如在注销请求后结束持久性很有用。为此,服务器只需发出一个具有无效值(例如空)或过去日期的 cookie。通过将此机制与 "disable-on-404" 检查选项结合使用,可以执行完全优雅的关机,因为用户在注销后肯定会离开服务器。 httponly 此选项告诉 HAProxy 在插入 cookie 时添加 "HttpOnly" cookie 属性。此属性用于使用户代理不与非 HTTP 组件共享 cookie。请查看 RFC6265 以获取有关此属性的更多信息。 secure 此选项告诉 HAProxy 在插入 cookie 时添加 "Secure" cookie 属性。此属性用于使用户代理永远不会通过非安全通道发出此 cookie,这意味着使用此标志学到的 cookie 将仅通过 SSL/TLS 连接提供。请查看 RFC6265 以获取有关此属性的更多信息。 domain 此选项允许指定插入 cookie 的域。它需要恰好一个参数:一个有效的域名。如果域以点开头,则允许浏览器将其用于以该名称结尾的任何主机。也可以通过多次调用此选项来指定多个域名。某些浏览器可能对域的数量有小的限制,因此在执行此操作时要小心。记录显示,向 MSIE 6 或 Firefox 2 发送 10 个域可以按预期工作。 maxidle 此选项允许插入的 cookie 在闲置一段时间后被忽略。它仅适用于 insert-mode cookie。当 cookie 发送给客户端时,也会发送发出此 cookie 的日期。在后续提供此 cookie 时,如果日期早于参数指示的延迟(以秒为单位),则将忽略它。否则,如果需要,它将在发送响应给客户端时刷新。这对于防止从不关闭浏览器的用户在同一服务器上停留太长时间(例如,在集群大小更改后)特别有用。当设置此选项且 cookie 没有日期时,它始终被接受,但在响应中会刷新。这保持了管理员访问其站点的能力。日期比未来 24 小时更远的 cookie 将被忽略。这样做可以让管理员修复时区问题,而不会冒将用户踢出站点的风险。 maxlife 此选项允许插入的 cookie 在某些生命周期后被忽略,无论它们是否在使用中。它仅适用于 insert mode cookie。当 cookie 第一次发送给客户端时,也会发送发出此 cookie 的日期。在后续提供此 cookie 时,如果日期早于参数指示的延迟(以秒为单位),则将忽略它。如果请求中的 cookie 没有日期,它将被接受并设置日期。日期比未来 24 小时更远的 cookie 将被忽略。这样做可以让管理员修复时区问题,而不会冒将用户踢出站点的风险。与 maxidle 相反,此值不会刷新,只有第一次访问日期计算在内。maxidle 和 maxlife 都可以同时使用。这对于防止从不关闭浏览器的用户在同一服务器上停留太长时间(例如,在集群大小更改后)特别有用。这比 maxidle 方法更强,因为它在某些绝对延迟后强制重新调度。 dynamic 激活动态 cookie。使用时,将为每个服务器动态创建一个会话 cookie,基于服务器的 IP 和端口,以及在 "dynamic-cookie-key" 后端指令中指定的密钥。每次 IP 地址更改时都会重新生成 cookie,并且仅为 IPv4/IPv6 生成。 attr 此选项告诉 HAProxy 在插入 cookie 时添加额外的属性。属性值可以包含除控制字符或 ";" 之外的任何字符。此选项可以重复。
每个 HTTP 后端只能有一个持久性 cookie,并且可以在 defaults 部分中声明。cookie 的值将是 "server" 语句中 "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
declare capture [ request | response ] len <length>
声明一个捕获槽。可在以下上下文中使用: tcp, http

可用于部分

defaultsfrontendlistenbackend

no

yes

yes

no
参数
<length> 是允许捕获的长度。
此声明仅在 frontend 或 listen 配置段中可用,但保留的槽可以在 backend 中使用。“request”关键字分配一个用于请求中的捕获槽,“response”分配一个用于响应中的捕获槽。
更改后端中服务器的默认选项。可在以下上下文中使用: tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<param*> 是此服务器的参数列表。“default-server” 关键字接受大量选项,并有一个专门介绍它的完整部分。更多详情请参阅第 5 节
Example
default-server inter 1000 weight 13
default_backend <backend>
指定当没有匹配的 “use_backend” 规则时使用的后端。可在以下上下文中使用: tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<backend> 是要使用的后端的名称。
在使用“use_backend”关键字在前端和后端之间进行内容切换时,指明在没有规则匹配时将使用哪个后端通常很有用。这通常是动态后端,它将捕获所有未确定的请求。
Example
use_backend dynamic if url_dyn use_backend static if url_css url_img extension_img default_backend dynamic
description <string>
描述一个 listen、frontend 或 backend。可在以下上下文中使用: tcp, http, log

可用于部分

defaultsfrontendlistenbackend

no

yes

yes

yes
参数: string
允许添加一句话来在 HAProxy HTML 统计页面中描述相关对象。该描述将打印在其所描述对象名称的右侧。<string> 参数中的空格无需使用反斜杠转义。
禁用一个代理、前端或后端。可在以下上下文中使用: tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
"disabled" 关键字用于禁用实例,主要用于释放侦听端口或暂时禁用服务。实例仍将创建并检查其配置,但它将以 "stopped" 状态创建,并在统计信息中显示为该状态。它不会接收任何流量,也不会发送任何健康检查或日志。通过在 "defaults" 部分中添加 "disabled" 关键字,可以一次禁用多个实例。
dispatch <address>:<port> (deprecated)
设置一个默认服务器地址。可在以下上下文中使用: tcp, http

可用于部分

defaultsfrontendlistenbackend

no

no

yes

yes
参数
<address> 是默认服务器的 IPv4 地址。或者,也支持可解析的主机名,但此名称将在启动期间解析。<ports> 是一个强制性的端口规范。所有连接都将发送到此端口,并且不允许像普通服务器那样使用端口偏移量。
"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 <字符串>
为后端设置动态 cookie 的密钥。可在以下上下文中使用: http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数: 要使用的密钥。
当启用动态 cookie 时(请参阅 cookie 的 “dynamic” 指令),会为每个服务器创建一个动态 cookie(除非在 “server” 行上明确指定),使用服务器 IP 地址、TCP 端口和密钥的哈希值。这样,我们可以确保在多个负载均衡器之间实现会话持久性,即使服务器是动态添加或删除的。
启用一个代理、前端或后端。可在以下上下文中使用: tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
当默认值设置为 "disabled" 时,"enabled" 关键字用于显式启用实例。这很少使用。
errorfile <code> <file>
返回文件内容,而不是由 HAProxy 生成的错误。可在以下上下文中使用: http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<code> 是 HTTP 状态码。目前,HAProxy 能够生成的状态码有 200, 400, 401, 403, 404, 405, 407, 408, 410, 413, 414, 425, 429, 431, 500, 501, 502, 503 和 504。<file> 指定一个包含完整 HTTP 响应的文件。建议遵循通用做法,在文件名后附加 ".http",这样人们就不会将响应与 HTML 错误页面混淆,并建议使用绝对路径,因为文件在执行任何 chroot 之前被读取。
重要的是要理解此关键字并非旨在重写服务器返回的错误,而是 HAProxy 检测并返回的错误。这就是为什么支持的错误列表仅限于一小部分。代码 200 是为了响应匹配 "monitor-uri" 规则的请求而发出的。文件在 HAProxy 启动时解析,并且必须根据 HTTP 规范有效。它们不应超过配置的缓冲区大小(BUFSIZE),通常为 16 kB,否则将返回内部错误。明智的做法是不要在其中包含对本地内容(例如图像)的任何引用,以避免在所有服务器都停机时,客户端和 HAProxy 之间发生循环,导致返回错误而不是图像。最后,响应不能超过 (tune.bufsize - tune.maxrewrite),以便 "http-after-response" 规则仍有空间运行(请参阅 "tune.maxrewrite")。文件在配置时读取并保存在内存中。因此,即使进程被 chrooted,错误也会继续返回,并且在进程运行时不会考虑任何文件更改。开发这些文件的一种简单方法是将其与 403 状态代码关联,并查询被阻止的 URL。
Example
errorfile 400 /etc/haproxy/errorfiles/400badreq.http errorfile 408 /dev/null # 解决 Chrome 预连接的 bug errorfile 403 /etc/haproxy/errorfiles/403forbid.http errorfile 503 /etc/haproxy/errorfiles/503sorry.http
errorfiles <名称> [<状态码> ...]
全部或部分地导入在 <name> http-errors 部分中定义的错误文件。可在以下上下文中使用: http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<name> 是一个现有 http-errors 部分的名称。<code> 是一个 HTTP 状态码。可以列出多个状态码。目前,HAProxy 能够生成的状态码有 200, 400, 401, 403, 404, 405, 407, 408, 410, 413, 414, 425, 429, 431, 500, 501, 502, 503 和 504。
在 http-errors 部分中以名称 <name> 定义的错误将被导入到当前代理中。如果未指定状态码,则 http-errors 部分的所有错误文件都将被导入。否则,只有与所列状态码关联的错误文件才会被导入。这些错误文件会覆盖代理已定义的自定义错误。并且它们可能会被后续的错误文件覆盖。从功能上讲,这与使用 “errorfile” 指令手动声明所有错误文件完全相同。
Example
errorfiles generic errorfiles site-1 403 404
errorloc <code> <url>
errorloc302 <code> <url>
返回一个到 URL 的 HTTP 重定向,而不是由 HAProxy 生成的错误。可在以下上下文中使用: http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<code> 是 HTTP 状态码。目前,HAProxy 能够生成的状态码有 200, 400, 401, 403, 404, 405, 407, 408, 410, 413, 414, 425, 429, 431, 500, 501, 502, 503 和 504。<url> 是 "Location" 标头的确切内容。它可以包含一个指向同一站点上错误页面的相对 URI,或者一个指向另一个站点上错误页面的绝对 URI。应特别注意相对 URI,以避免如果 URI 本身可能生成相同的错误(例如 500)时出现重定向循环。
重要的是要理解,此关键字并非用于重写服务器返回的错误,而是用于重写 HAProxy 检测并返回的错误。这就是为什么支持的错误列表仅限于一小部分。状态码 200 是为响应匹配“monitor-uri”规则的请求而发出的。请注意,这两个关键字都返回 HTTP 302 状态码,它告诉客户端使用相同的 HTTP 方法获取指定的 URL。对于非 GET 方法(如 POST),这可能会很有问题,因为发送给客户端的 URL 可能不允许 GET 以外的方法。要解决此问题,请使用“errorloc303”,它会发送 HTTP 303 状态码,指示客户端必须使用 GET 请求获取该 URL。
errorloc303 <code> <url>
返回一个到 URL 的 HTTP 重定向,而不是由 HAProxy 生成的错误。可在以下上下文中使用: http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<code> 是 HTTP 状态码。目前,HAProxy 能够生成的状态码有 200, 400, 401, 403, 404, 405, 407, 408, 410, 413, 414, 425, 429, 431, 500, 501, 502, 503 和 504。<url> 是 "Location" 标头的确切内容。它可以包含一个指向同一站点上错误页面的相对 URI,或者一个指向另一个站点上错误页面的绝对 URI。应特别注意相对 URI,以避免如果 URI 本身可能生成相同的错误(例如 500)时出现重定向循环。
重要的是要理解,此关键字并非用于重写服务器返回的错误,而是用于重写 HAProxy 检测并返回的错误。这就是为什么支持的错误列表仅限于一小部分。状态码 200 是为响应匹配“monitor-uri”规则的请求而发出的。请注意,这两个关键字都返回 HTTP 303 状态码,它告诉客户端使用相同的 HTTP GET 方法获取指定的 URL。这解决了与“errorloc”和 302 状态码相关的常见问题。一些在 HTTP/1.1 之前设计的非常旧的浏览器可能不支持它,但到目前为止还没有报告过此类问题。
email-alert from <emailaddr>
声明在电子邮件警报的信封和标头中使用的发件人电子邮件地址。这是发送电子邮件警报的地址。可在以下上下文中使用: tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<emailaddr> 是发送电子邮件警报时使用的发件人电子邮件地址
还需要设置“email-alert mailers”和“email-alert to”,如果设置了,则为该代理启用电子邮件警报发送功能。
声明将发送电子邮件警报的消息的最大日志级别。这充当发送电子邮件警报的过滤器。可在以下上下文中使用: tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<level> 8 个 syslog 级别之一:emerg alert crit err warning notice info debug 以上 syslog 级别从低到高排序。
默认级别是 alert。还需要设置“email-alert from”、“email-alert mailers”和“email-alert to”,如果设置了,则为该代理启用电子邮件警报发送功能。在以下情况下会发送警报: * 一个未暂停的服务器被标记为 down 且 <level> 是 alert 或更低 * 一个已暂停的服务器被标记为 down 且 <level> 是 notice 或更低 * 一个服务器被标记为 up 或进入 drain 状态且 <level> 是 notice 或更低 * 启用了“option log-health-checks”,<level> 是 info 或更低,并且发生了健康检查状态更新
email-alert mailers <mailersect>
声明发送电子邮件警报时要使用的邮件发送器。可在以下上下文中使用: tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<mailersect> 是用于发送电子邮件警报的邮件程序部分的名称。
还需要设置“email-alert from”和“email-alert to”,如果设置了,则为该代理启用电子邮件警报发送功能。
声明与邮件发送器通信时使用的目标主机名地址。可在以下上下文中使用: tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<hostname> 是与邮件程序通信时使用的主机名
默认使用系统的主机名。还需要设置“email-alert from”、“email-alert mailers”和“email-alert to”,如果设置了,则为该代理启用电子邮件警报发送功能。
email-alert to <emailaddr>
声明电子邮件警报的信封中的收件人地址和标头中的收件人地址。这是发送电子邮件警报的目标地址。可在以下上下文中使用: tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<emailaddr> 是发送电子邮件警报时使用的收件人电子邮件地址
还需要设置“email-alert mailers”和“email-alert to”,如果设置了,则为该代理启用电子邮件警报发送功能。
指定在前端发生连接错误时要使用的日志格式字符串。可在以下上下文中使用: tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
该指令指定了用于包含与错误、超时、重试、重新分派或 HTTP 状态码 5xx 相关信息的日志的格式字符串。简而言之,此格式将用于所有会受 “log-separate-errors” 选项影响的日志行,包括在第 8.2.5 节中描述的连接错误。如果在 defaults 部分中使用该指令,所有后续的前端都将使用相同的日志格式。请参阅深入介绍自定义日志格式字符串的第 8.2.6 节。“error-log-format” 指令会覆盖之前的 “error-log-format” 指令。
force-persist { if | unless } <condition>
声明一个条件,以在服务器宕机时强制持久性。可在以下上下文中使用: tcp, http

可用于部分

defaultsfrontendlistenbackend

no

no

yes

yes
默认情况下,请求不会调度到停机的服务器。可以使用 "option persist" 强制执行此操作,但它是无条件的,并且如果设置了 "option redispatch",则会重新调度到有效服务器。这使得强制某些请求到达因维护操作而被人工标记为停机的服务器的可能性很小。"force-persist" 语句允许声明各种基于 ACL 的条件,当满足这些条件时,将导致请求忽略服务器的停机状态并仍尝试连接到它。这使得启动服务器成为可能,该服务器仍回复健康检查的错误,并运行专门配置的浏览器来测试服务。在方便的方法中,可以使用特定的源 IP 地址或特定的 cookie。cookie 还有一个优点,即可以轻松地从测试页面添加到/从浏览器中删除。一旦服务通过验证,就可以通过返回对健康检查的有效响应来向世界开放服务。当满足 "if" 条件时,或除非满足 "unless" 条件时,强制持久性才会启用。当使用此功能时,最终的重新调度始终被禁用。
filter <名称> [参数*]
将过滤器 <name> 添加到附加到代理的过滤器列表中。可在以下上下文中使用: tcp, http

可用于部分

defaultsfrontendlistenbackend

no

yes

yes

yes
参数
<name> 是过滤器的名称。官方支持的过滤器在第 9 节中引用。<param*> 是过滤器 <name> 接受的参数列表。这些参数的解析是过滤器的责任。有关支持的参数的所有详细信息,请参阅相应过滤器(第 9 节)的文档。
对于同一个代理,可以多次使用 filter 行。如果需要,可以多次引用同一个过滤器。
示例
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
fullconn <conns>
指定后端负载达到何种程度时,服务器将达到其 maxconn。可在以下上下文中使用: tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<conns> 是后端上的连接数,该连接数将使服务器使用最大连接数。
当服务器指定了 "maxconn" 参数时,这意味着其并发连接数永远不会更高。此外,如果它有 "minconn" 参数,它表示一个遵循后端负载的动态限制。然后,服务器将始终接受至少 <minconn> 个连接,绝不超过 <maxconn> 个连接,并且当后端并发连接数少于 <conns> 时,限制将在两个值之间平稳过渡。这使得在正常负载期间限制服务器上的负载成为可能,但在重要负载期间进一步推进,而在特殊负载期间不会使服务器过载。由于很难正确设置此值,HAProxy 会自动将其设置为所有可能分支到此后端的 frontend 的 maxconn 总和的 10%(基于 "use_backend" 和 "default_backend" 规则)。这样,将其留空是安全的。但是,涉及动态名称的 "use_backend" 不会被计数,因为无法知道它们是否可能匹配。
Example
# 服务器将接受 100 到 1000 个并发连接 # 当后端达到 10000 个连接时,将达到 1000 的最大值。 backend dynamic fullconn 10000 server srv1 dyn1:80 minconn 100 maxconn 1000 server srv2 dyn2:80 minconn 100 maxconn 1000
guid <字符串>
为此代理指定一个区分大小写的全局唯一 ID。可在以下上下文中使用: tcp, http, log

可用于部分

defaultsfrontendlistenbackend

no

yes

yes

yes
<string> 在所有对象类型的所有 haproxy 配置中必须是唯一的。格式未指定,允许用户选择其命名策略。唯一的限制是其长度不能大于 127 个字符。所有字母数字值和 '.'、':'、'-' 和 '_' 字符都有效。另请参阅 "shm-stats-file"。
为有界负载一致性哈希指定平衡因子。可在以下上下文中使用: tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

no

no

yes
参数
<factor> 是控制发送到服务器的最大并发请求数的参数,表示为所有活动服务器上平均并发请求数的百分比。
为具有 "hash-type consistent" 的服务器指定 "hash-balance-factor" 可启用一种算法,该算法可防止任何一台服务器同时获取过多请求,即使某些哈希桶接收的请求比其他哈希桶多得多。将 <factor> 设置为 0(默认值)会禁用此功能。否则,<factor> 是一个大于 100 的百分比。例如,如果 <factor> 为 150,则不允许任何服务器的负载超过平均负载的 1.5 倍。如果使用服务器权重,它们将得到尊重。如果第一选择服务器不合格,算法将根据请求哈希选择另一台服务器,直到找到具有额外容量的服务器。较高的 <factor> 允许服务器之间存在更大的不平衡,而较低的 <factor> 意味着平均将检查更多服务器,从而影响性能。合理的值范围是 125 到 200。此设置也用于 "balance random",它在内部依赖于一致性哈希机制。
hash-preserve-affinity { always | maxconn | maxqueue }
指定一种方法,用于在服务器饱和或队列已满时,通过哈希负载均衡将流分配给服务器。可在以下上下文中使用: http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
可以指定以下值: - "always":这是默认策略。根据哈希将流分配给服务器,无论服务器当前是否饱和。 - "maxconn":选择此选项后,设置了 "maxconn" 且当前饱和的服务器将被跳过。将通过跟随哈希环来选择另一台服务器。这对未设置 "maxconn" 的服务器没有影响。如果所有服务器都饱和,则请求将排队到哈希环中最初选择的服务器之前的最后一个服务器。 - "maxqueue":选择此选项后,设置了 "maxconn"、将 "maxqueue" 设置为非零值(有限队列大小)且当前队列已满的服务器将被跳过。将通过跟随哈希环来选择另一台服务器。这对未同时设置 "maxconn" 和 "maxqueue" 的服务器没有影响。
hash-type <method> <function> <modifier>
指定一种用于将哈希映射到服务器的方法。可在以下上下文中使用: tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<method> 是用于从 <function> 计算的哈希中选择服务器的方法: map-based 哈希表是一个包含所有活动服务器的静态数组。哈希将非常平滑,会考虑权重,但将是静态的,即服务器启动时权重的更改将被忽略。这意味着不会有慢启动。此外,由于服务器是根据其在数组中的位置选择的,因此当服务器计数更改时,大多数映射都会更改。这意味着当服务器启动或停机,或将服务器添加到集群时,大多数连接将重新分配给不同的服务器。这对于缓存来说可能不方便。 consistent 哈希表是一个树,其中填充了每个服务器的许多出现。哈希键在树中查找,并选择最近的服务器。此哈希是动态的,它支持在服务器启动时更改权重,因此与慢启动功能兼容。它的优点是当服务器启动或停机时,只会移动其关联。当将服务器添加到集群时,只有一小部分映射被重新分配,使其成为缓存的理想方法。然而,由于其原理,分布永远不会非常平滑,有时可能需要调整服务器的权重或 ID 以获得更平衡的分布。为了在多个负载均衡器上获得相同的分布,重要的是所有服务器都具有完全相同的 ID。注意:如果未指定哈希函数,一致性哈希使用 sdbm 和 avalanche。 <function> 是要使用的哈希函数: sdbm 此函数最初是为 sdbm(ndbm 的公共领域重新实现)数据库库创建的。发现在打乱位方面表现良好,导致键的分布更好,分裂更少。它碰巧也是一个具有良好分布的良好通用哈希函数,除非总服务器权重是 64 的倍数,在这种情况下应用 avalanche 修饰符可能会有所帮助。 djb2 此函数由 Dan Bernstein 在 comp.lang.c 上多年前首次提出。研究表明,对于某些工作负载,此函数提供的分布优于 sdbm。它通常适用于基于文本的输入,但对于仅数字输入或总服务器权重是 33 的倍数时,性能可能会极差,除非也使用 avalanche 修饰符。 wt6 此函数是在过去测试其他函数时为 HAProxy 设计的。它不像其他函数那样平滑,但对输入数据集或服务器数量的敏感性要低得多。它可以作为 sdbm+avalanche 或 djb2+avalanche 的替代方案,用于一致性哈希,或用于对数字数据(例如源 IP 地址或 URL 参数中的访问者标识符)进行哈希处理时。 crc32 这是最常见的 CRC32 实现,用于以太网、gzip、PNG 等。它比其他函数慢,但可能提供更好的分布或更不可预测的结果,尤其是在用于字符串时。 none 不对键进行哈希处理,键将用作哈希,这对于使用转换器手动对键进行哈希处理并让 haproxy 直接使用结果很有用。 <modifier> 指示在对键进行哈希处理后应用的可选方法: avalanche 此指令指示不应按其原始形式使用上面哈希函数的结果,而必须首先应用 4 字节的完整雪崩哈希。此步骤的目的是混合前一个哈希的结果位,以避免当输入包含一些有限值或服务器数量是哈希组件之一(SDBM 为 64,DJB2 为 33)的倍数时,避免任何不希望的效果。启用 avalanche 倾向于使结果更不可预测,但也不如使用原始函数平滑。可能需要对某些工作负载进行一些测试。此哈希是 Bob Jenkins 提出的众多哈希之一。
默认的哈希类型是“map-based”,建议在大多数情况下使用。默认的函数是“sdbm”,函数的选择应基于被哈希值的范围。
http-after-response <动作> <选项...> [ { if | unless } <条件> ]
对所有第 7 层响应(服务器、小程序/服务和内部响应)进行访问控制。可在以下上下文中使用: http

可用于部分

defaultsfrontendlistenbackend
是(!)
yes(!)

yes

yes

yes
http-after-response 语句定义了一组应用于第 7 层处理的规则。这些规则在前端、listen 或后端部分中遇到时按其声明顺序进行评估。由于这些规则适用于响应,因此首先应用后端规则,然后应用前端规则。任何规则后都可以选择跟着一个基于 ACL 的条件,在这种情况下,只有当条件评估为真时才会评估该规则。与 http-response 规则不同,这些规则适用于所有响应,即服务器响应,也适用于 HAProxy 生成的所有响应。这些规则在响应分析结束时、数据转发阶段之前进行评估。条件在执行操作之前立即进行评估,并且操作仅执行一次。因此,如果某个操作更改了作为条件的一部分进行检查的元素,则没有问题。这也意味着多个操作可以依赖于相同的条件,因此更改条件评估的第一个操作足以隐式禁用其余操作。例如,当尝试在变量为空时从各种来源为其分配值时,可以使用此方法。每个实例的 "http-after-response" 语句数量没有限制。语法中 "http-after-response" 之后的第一个关键字是规则的操作,可选地后跟操作的各种参数。支持的操作及其各自的语法在第 4.3 节 "Actions" 中列举(查找标记为 "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 <字符串>
为接下来的 http-check 规则定义一个注释,如果失败,将在日志中报告。可在以下上下文中使用: tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<string> 是如果以下 http-check 规则失败时要在日志中添加的注释消息。
它仅适用于 connect、send 和 expect 规则。这对于进行用户友好的错误报告很有用。
http-check connect [default] [port <表达式>] [addr <ip>] [send-proxy] [via-socks4] [ssl] [sni <sni>] [alpn <alpn>] [linger] [proto <名称>] [comment <消息>]
打开一个新连接以执行 HTTP 健康检查。可在以下上下文中使用: tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
comment <msg> 定义如果规则评估失败时要报告的消息。 default 使用服务器行的默认选项执行健康检查。仅当未重新定义时才使用服务器选项。 port <expr> 如果未设置,则使用检查端口或服务器端口。它告诉 HAProxy 连接到哪里。<port> 必须是有效的 TCP 端口整数,从 1 到 65535,或一个 sample-fetch 表达式。 addr <ip> 定义执行健康检查的 IP 地址。 send-proxy 发送 PROXY 协议字符串 via-socks4 使用上游 socks4 代理启用传出健康检查。 ssl 打开加密连接 sni <sni> 指定用于在 SSL 上执行健康检查的 SNI。 alpn <alpn> 定义要使用 ALPN 宣传的协议。协议列表由逗号分隔的协议名称列表组成,例如:"h2,http/1.1"。如果未设置,则使用服务器 ALPN。 proto <name> 强制用于此连接的多路复用器协议。它必须是 HTTP mux 协议,并且必须在后端可用。可用协议列表在 haproxy -vv 中报告。 linger 干净地关闭连接,而不是使用单个 RST。
就像 tcp-check 健康检查一样,可以配置用于执行 HTTP 健康检查的连接。此指令也应用于描述涉及多个请求/响应交换的场景,可能在不同的端口上或与不同的服务器。当服务器行上既没有配置 TCP 端口,也没有服务器端口指令时,http-check 序列的第一步必须是使用 “http-check connect” 指定端口。在一个 http-check 规则集中,'connect' 是必需的,并且也必须以 'connect' 规则开始规则集。目的是确保管理员知道他们在做什么。当一个 connect 必须开始规则集时,它前面仍然可以有 set-var、unset-var 或 comment 规则。
示例
# 检查服务器上的 HTTP 和 HTTPs 服务。 # 首先通过服务器行端口指令打开端口 80,然后 # tcp-check 打开端口 443,加密并在其上运行请求: 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
在健康检查响应为 HTTP/404 时启用维护模式。可在以下上下文中使用: tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
当设置此选项时,返回 HTTP 404 状态码的服务器将从后续的负载均衡中排除,但仍会接收持久连接。这为 Web 管理员提供了一种非常方便的方法来对其服务器进行平滑关闭。同样重要的是要注意,在此模式下被检测为失败的服务器不会生成警报,只会生成一个通知。如果服务器再次响应 2xx 或 3xx,它将立即重新插入到服务器场中。统计页面上的状态为此模式下的服务器报告为 "NOLB"。重要的是要注意,此选项仅与 “httpchk” 选项一起使用。如果此选项与 “http-check expect” 一起使用,则它优先于后者,因此 404 响应仍将被视为软停止。还要注意,已停止的服务器即使响应 404s 也会保持停止状态。此选项仅对正在运行的服务器进行评估。
http-check expect [min-recv <整数>] [comment <消息>] [ok-status <状态>] [error-status <状态>] [tout-status <状态>] [on-success <格式>] [on-error <格式>] [status-code <表达式>] [!] <匹配> <模式>
使 HTTP 健康检查考虑响应内容或特定状态码。可在以下上下文中使用: tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
comment <msg> 定义如果规则评估失败时要报告的消息。 min-recv 是可选的,可以定义评估当前 expect 规则所需的最小数据量。如果接收到的字节数低于此限制,则检查将等待更多数据。此选项可用于解决一些模糊的匹配规则,或避免对已知仍不完整的内容执行代价高昂的正则表达式匹配。如果使用精确字符串,则使用字符串长度和此参数之间的最小值。如果此参数设置为 -1,则忽略它。如果 expect 规则不匹配,则检查将等待更多数据。如果设置为 0,则评估结果始终是结论性的。 ok-status <st> 是可选的,可用于设置检查状态,如果 expect 规则成功评估并且它是 tcp-check 规则集中的最后一条规则。"L7OK"、"L7OKC"、"L6OK" 和 "L4OK" 受支持: - L7OK:检查通过第 7 层 - L7OKC:检查有条件地通过第 7 层,将服务器设置为 NOLB 状态。 - L6OK:检查通过第 6 层 - L4OK:检查通过第 4 层 默认情况下使用 "L7OK"。 error-status <st> 是可选的,可用于设置检查状态,如果在 expect 规则评估期间发生错误。"L7OKC"、"L7RSP"、"L7STS"、"L6RSP" 和 "L4CON" 受支持: - L7OKC:检查有条件地通过第 7 层,将服务器设置为 NOLB 状态。 - L7RSP:第 7 层响应无效 - 协议错误 - L7STS:第 7 层响应错误,例如 HTTP 5xx - L6RSP:第 6 层响应无效 - 协议错误 - L4CON:第 1-4 层连接问题 默认情况下使用 "L7RSP" 使用。 tout-status <st> 是可选的,可用于设置检查状态,如果在 expect 规则评估期间发生超时。"L7TOUT"、"L6TOUT" 和 "L4TOUT" 受支持: - L7TOUT:第 7 层(HTTP/SMTP)超时 - L6TOUT:第 6 层(SSL)超时 - L4TOUT:第 1-4 层超时 默认情况下使用 "L7TOUT"。 on-success <fmt> 是可选的,可用于自定义日志中报告的信息消息,如果 expect 规则成功评估并且它是 tcp-check 规则集中的最后一条规则。<fmt> 是自定义日志格式字符串(请参阅 section 8.2.6)。 on-error <fmt> 是可选的,可用于自定义日志中报告的信息消息,如果在 expect 规则评估期间发生错误。<fmt> 是自定义日志格式字符串(请参阅 section 8.2.6)。 <match> 是一个关键字,指示如何在响应中查找特定模式。关键字可以是 "status"、"rstatus"、"hdr"、"fhdr"、"string" 或 "rstring" 之一。关键字前面可以有感叹号 ("!") 来否定匹配。感叹号和关键字之间允许有空格。有关支持的关键字的更多详细信息,请参见下文。 <pattern> 是要查找的模式。它可以是字符串、正则表达式或具有多个参数的更复杂模式。如果字符串模式包含空格,则必须使用通常的反斜杠 ('\') 进行转义。
By default, "option httpchk" considers that response statuses 2xx and 3xx are valid, and that others are invalid. When "http-check expect" is used, it defines what is considered valid or invalid. Only one "http-check" statement is supported in a backend. If a server fails to respond or times out, the check obviously fails. The available matches are : 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. It is important to note that the responses will be limited to a certain size defined by the global "tune.bufsize" option, which defaults to 16384 bytes. Thus, too large responses may not contain the mandatory pattern when using "string" or "rstring". If a large response is absolutely required, it is possible to change the default max size by setting the global variable. However, it is worth keeping in mind that parsing very large responses can waste some CPU cycles, especially when regular expressions are used, and that it is always better to focus the checks on smaller resources. In an http-check ruleset, the last expect rule may be implicit. If no expect rule is specified after the last "http-check send", an implicit expect rule is defined to match on 2xx or 3xx status codes. It means this rule is also defined if there is no "http-check" rule at all, when only "option httpchk" is set. Last, if "http-check expect" is combined with "http-check disable-on-404", then this last one has precedence when the server responds with 404.
示例
# 只接受状态码 200 为有效 http-check expect status 200,201,300-310 # 确保设置了 sessid cookie http-check expect header name "set-cookie" value -m beg "sessid=" # 将 SQL 错误视为错误 http-check expect ! string SQL\ Error # 仅将 5xx 状态码视为错误 http-check expect ! rstatus ^5 # 检查在 /html 之前是否有正确的十六进制标签 http-check expect rstring <!--tag:[0-9a-f]*--></html>
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

可用于部分

defaultsfrontendlistenbackend

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.
In addition to the request line defined by the "option httpchk" directive, this one is the valid way to add some headers and optionally a body to the request sent during HTTP health checks. If a body is defined, the associate "Content-Length" header is automatically added. Thus, this header or "Transfer-encoding" header should not be present in the request provided by "http-check send". If so, it will be ignored. The old trick consisting to add headers after the version string on the "option httpchk" line is now deprecated. Also "http-check send" doesn't support HTTP keep-alive. Keep in mind that it will automatically append a "Connection: close" header, unless a Connection header has already already been configured via a hdr entry. Note that the Host header and the request authority, when both defined, are automatically synchronized. It means when the HTTP request is sent, when a Host is inserted in the request, the request authority is accordingly updated. Thus, don't be surprised if the Host header value overwrites the configured request authority. Note also for now, no Host header is automatically added in HTTP/1.1 or above requests. You should add it explicitly.
在 HTTP 健康检查中启用状态头的发送。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
When this option is set, HAProxy will systematically send a special header "X-Haproxy-Server-State" with a list of parameters indicating to each server how they are seen by HAProxy. This can be used for instance when a server is manipulated without access to HAProxy and the operator needs to know whether HAProxy still sees it up or not, or if the server is the last one in a farm. The header is composed of fields delimited by semi-colons, the first of which is a word ("UP", "DOWN", "NOLB"), possibly followed by a number of valid checks on the total number before transition, just as appears in the stats interface. Next headers are in the form "<variable>=<value>", indicating in no specific order some values available in the stats interface : - a variable "address", containing the address of the backend server. This corresponds to the <address> field in the server declaration. For unix domain sockets, it will read "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. Example of a header received by the application server : >>> X-Haproxy-Server-State: UP 2/3; name=bck/srv2; node=lb1; weight=1/2; \ scur=13/22; qcur=0
http-check set-var(<var-name>[,<cond>...]) <expr>
http-check set-var-fmt(<var-name>[,<cond>...]) <fmt>
此操作设置变量的内容。变量是内联声明的。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<var-name> 变量的名称。只能使用 "proc"、"sess" 和 "check" 作用域。有关变量的详细信息,请参见第 2.8 节。<cond> 一组必须全部为真才能实际设置变量的条件(例如 "ifnotempty"、"ifgt" ...)。有关可能条件的完整列表,请参见 set-var 转换器的描述。<expr> 是一个样本获取表达式,可能后跟转换器。<fmt> 这是使用自定义日志格式表示的值(请参见第 8.2.6 节中的自定义日志格式)。
示例
http-check set-var(check.port) int(1234) http-check set-var-fmt(check.port) "name=%H"
在其作用域内释放对变量的引用。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<var-name> 变量的名称。只能使用 "proc"、"sess" 和 "check" 作用域。有关变量的详细信息,请参见第 2.8 节
示例
http-check unset-var(check.port)
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

可用于部分

defaultsfrontendlistenbackend

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.
This directive may be used instead of "errorfile", to define a custom error message. As "errorfile" directive, it is used for errors detected and returned by HAProxy. If an errorfile is defined, it is parsed when HAProxy starts and must be valid according to the HTTP standards. The generated response must not exceed the configured buffer size (BUFFSIZE), otherwise an internal error will be returned. Finally, if you consider to use some http-after-response rules to rewrite these errors, the reserved buffer space should be available (see "tune.maxrewrite"). The files are read at the same time as the configuration and kept in memory. For this reason, the errors continue to be returned even when the process is chrooted, and no file change is considered while the process is running. Note: 400/408/500 errors emitted in early stage of the request parsing are handled by the multiplexer at a lower level. No custom formatting is supported at this level. Thus only static error messages, defined with "errorfile" directive, are supported. However, this limitation only exists during the request headers parsing or between two transactions.
http-request <action> [options...] [ { if | unless } <condition> ]
第 7 层请求的访问控制 可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend
是(!)
yes(!)

yes

yes

yes
The http-request statement defines a set of rules which apply to layer 7 processing. The rules are evaluated in their declaration order when they are met in a frontend, listen or backend section. Any rule may optionally be followed by an ACL-based condition, in which case it will only be evaluated if the condition evaluates to true. The condition is evaluated just before the action is executed, and the action is performed exactly once. As such, there is no problem if an action changes an element which is checked as part of the condition. This also means that multiple actions may rely on the same condition so that the first action that changes the condition's evaluation is sufficient to implicitly disable the remaining actions. This is used for example when trying to assign a value to a variable from various sources when it's empty. There is no limit to the number of "http-request" statements per instance. The first keyword after "http-request" in the syntax is the rule's action, optionally followed by a varying number of arguments for the action. The supported actions and their respective syntaxes are enumerated in section 4.3 "Actions" (look for actions which tick "HTTP Req"). This directive is only available from named defaults sections, not anonymous ones. Rules defined in the defaults section are evaluated before ones in the associated proxy section. To avoid ambiguities, in this case the same defaults section cannot be used by proxies with the frontend capability and by proxies with the backend capability. It means a listen section cannot use a defaults section defining such rules.
示例
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
http-response <action> <options...> [ { if | unless } <condition> ]
第 7 层响应的访问控制 可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend
是(!)
yes(!)

yes

yes

yes
The http-response statement defines a set of rules which apply to layer 7 processing. The rules are evaluated in their declaration order when they are met in a frontend, listen or backend section. Since these rules apply on responses, the backend rules are applied first, followed by the frontend's rules. Any rule may optionally be followed by an ACL-based condition, in which case it will only be evaluated if the condition evaluates to true. The condition is evaluated just before the action is executed, and the action is performed exactly once. As such, there is no problem if an action changes an element which is checked as part of the condition. This also means that multiple actions may rely on the same condition so that the first action that changes the condition's evaluation is sufficient to implicitly disable the remaining actions. This is used for example when trying to assign a value to a variable from various sources when it's empty. There is no limit to the number of "http-response" statements per instance. The first keyword after "http-response" in the syntax is the rule's action, optionally followed by a varying number of arguments for the action. The supported actions and their respective syntaxes are enumerated in section 4.3 "Actions" (look for actions which tick "HTTP Res"). This directive is only available from named defaults sections, not anonymous ones. Rules defined in the defaults section are evaluated before ones in the associated proxy section. To avoid ambiguities, in this case the same defaults section cannot be used by proxies with the frontend capability and by proxies with the backend capability. It means a listen section cannot use a defaults section defining such rules.
示例
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-reuse { never | safe | aggressive | always }
声明如何在请求之间共享空闲的 HTTP 连接 可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
In order to avoid the cost of setting up new connections to backend servers for each HTTP request, HAProxy tries to keep such idle connections opened after being used. These connections are specific to a server and are stored in a list called a pool, and are grouped together by a set of common key properties. Subsequent HTTP requests will cause a lookup of a compatible connection sharing identical properties in the associated pool and result in this connection being reused instead of establishing a new one. A limit on the number of idle connections to keep on a server can be specified via the "pool-max-conn" server keyword. Unused connections are periodically purged according to the "pool-purge-delay" interval. The following connection properties are used to determine if an idle connection is eligible for reuse on a given request: - source and destination addresses - proxy protocol - TOS and mark socket options - connection name, determined either by the result of the evaluation of the "pool-conn-name" expression if present, otherwise by the "sni" expression In some occasions, connection lookup or reuse is not performed due to extra restrictions. This is determined by the reuse strategy specified via the keyword argument: - "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". Also note that connections with certain bogus authentication schemes (relying on the connection) like NTLM are marked private if possible and never shared. This won't be the case however when using a protocol with multiplexing abilities and using reuse mode level value greater than the default "safe" strategy as in this case nothing prevents the connection from being already shared. The rules to decide to keep an idle connection opened or to close it after processing are also governed by the "tune.pool-low-fd-ratio" (default: 20%) and "tune.pool-high-fd-ratio" (default: 25%). These correspond to the percentage of total file descriptors spent in idle connections above which haproxy will respectively refrain from keeping a connection opened after a response, and actively kill idle connections. Some setups using a very high ratio of idle connections, either because of too low a global "maxconn", or due to a lot of HTTP/2 or HTTP/3 traffic on the frontend (few connections) but HTTP/1 connections on the backend, may observe a lower reuse rate because too few connections are kept open. It may be desirable in this case to adjust such thresholds or simply to increase the global "maxconn" value. When thread groups are explicitly enabled, it is important to understand that idle connections are only usable between threads from a same group. As such it may happen that unfair load between groups leads to more idle connections being needed, causing a lower reuse rate. The same solution may then be applied (increase global "maxconn" or increase pool ratios).
向请求添加服务器名称。使用由 <header> 给出的头字符串。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<header> 用于发送服务器名称的头字符串。
The "http-send-name-header" statement causes the header field named <header> to be set to the name of the target server at the moment the request is about to be sent on the wire. Any existing occurrences of this header are removed. Upon retries and redispatches, the header field is updated to always reflect the server being attempted to connect to. Given that this header is modified very late in the connection setup, it may have unexpected effects on already modified headers. For example using it with transport-level header such as connection, content-length, transfer-encoding and so on will likely result in invalid requests being sent to the server. This is why following header names are forbidden: host, content-length, transfer-encoding and connection.
id <value>
为代理设置一个持久 ID。可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

no

yes

yes

yes
参数:
为代理设置一个持久 ID。此 ID 必须是唯一的正数。如果未设置,将自动分配一个未使用的 ID。第一个分配的值将是 1。此 ID 当前仅在统计信息中返回。
ignore-persist { if | unless } <condition>
声明一个忽略持久性的条件。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

no

no

yes

yes
默认情况下,当启用 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
load-server-state-from-file { global | local | none }
允许 HAProxy 的无缝重载。可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
此指令将 HAProxy 指向一个文件,该文件中保存了先前运行进程的服务器状态。这样,在启动时,在处理流量之前,新进程可以像没有发生重载一样将旧状态应用于服务器。"load-server-state-from-file" 指令的目的是告诉 HAProxy 使用哪个文件。目前,只有 2 个参数,要么阻止加载状态,要么从包含所有后端和服务器的文件中加载状态。状态文件可以通过在 stats 套接字上运行 "show servers state" 命令并重定向输出来生成。该文件的格式是版本化的,并且非常具体。要理解它,请阅读 "show servers state" 命令的文档(管理指南第 9.3 章)。
参数
global 加载由名为 "server-state-file" 的全局指令指向的文件的内容。 local 如果设置了 "server-state-file-name" 指令,则加载其指向的文件的内容。如果未设置,则使用后端名称作为文件名。 none 不为此后端加载任何状态
注意:- 默认情况下,服务器的 IP 地址在重载时会保留,但顺序可以通过服务器的“init-addr”设置来更改。这意味着在运行时通过 CLI 执行的 IP 地址更改将被保留,并且对本地解析器(例如 /etc/hosts)的任何更改可能不会有任何效果(如果正在使用状态文件)。- 除非在前一个和新的配置文件之间发生了变化,否则将应用前一个运行进程的服务器权重。
示例
最小配置
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 # <文档示例中省略了字段名称> 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 # <文档示例中省略了字段名称> 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
log <target> [len <length>] [format <format>] [sample <ranges>:<sample_size>] [profile <prof>] <facility> [<level> [<minlevel>]]
启用每个实例的事件和流量日志记录。可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
前缀:当必须清除记录器列表时,应使用 no。例如,如果您不想从默认记录器列表继承。此前缀不允许有参数。
参数
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 字节。
Example
log global log stdout format short daemon # 发送日志到 systemd log stdout format raw daemon # 发送所有内容到 stdout log stderr format raw daemon notice # 发送重要事件到 stderr log 127.0.0.1:514 local0 notice # 仅发送重要事件 log tcp@127.0.0.1:514 local0 notice notice # 相同但限制输出 # 级别并以 tcp 发送 log "${LOCAL_SYSLOG}:514" local0 notice # 发送到本地服务器
指定用于流量日志的自定义日志格式字符串。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
此指令指定了将用于所有通过使用此行的前端的流量所产生的日志的日志格式字符串。如果该指令在 defaults 部分中使用,所有后续的前端将使用相同的日志格式。请参阅第 8.2.6 节,该节深入介绍了自定义日志格式字符串。也可以定义仅在连接错误情况下使用的特定日志格式,请参见 "error-log-format" 选项。"log-format" 指令会覆盖之前的 "option tcplog"、"log-format"、"option httplog" 和 "option httpslog" 指令。
指定用于生成 RFC5424 结构化数据的自定义日志格式字符串。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
该指令指定了 RFC5424 结构化数据日志格式字符串,该字符串将用于所有通过使用此行的前端的流量产生的日志。如果该指令在 defaults 部分中使用,所有后续的前端将使用相同的日志格式。请参阅第 8.2.6 节,该节深入介绍了日志格式字符串。有关 RFC5424 结构化数据部分的更多信息,请参阅 https://tools.ietf.org/html/rfc5424#section-6.3。注意:此日志格式字符串仅用于将日志格式设置为“rfc5424”的记录器。
Example
log-format-sd [exampleSDID@1234\ bytes=\"%B\"\ status=\"%ST\"]
log-steps <steps>
指定在事务处理的哪些步骤应生成日志。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
在 tcp/http 事务处理期间,haproxy 可能会在处理的不同步骤(即:接受、连接、请求、响应、关闭)产生日志。默认情况下,HAProxy 每个事务只发出一个日志,一旦 logformat 表达式中使用的所有项目都能被满足,这意味着实际上日志通常在事务结束时发出(对于 HTTP 是在响应结束后,对于 TCP 是在连接结束后),除非使用了 "option logasap"。" log-steps " 指令允许精确地定义日志发出的时刻,甚至允许为同一事务发出多个日志。可以使用特殊值 'all' 来启用所有可用的日志源,从而可以从接受到关闭跟踪一个事务。也可以使用它们的名称(用空格分隔)来指定单个日志源,以选择性地启用何时应生成日志。常见的日志源有:accept, connect, request, response, close。
示例
frontend myfront option httplog log-steps accept,close #仅记录事务的接受和关闭
Log origins specified as "logging steps" (such as accept, close) can be used as-is in log-profiles (after 'on' directive). Combining "log-steps" with log-profiles is really interesting to have fine-grained control over logs automatically generated by haproxy during transaction processing. This setting is only relevant on frontends, it is ignored on backends.
log-tag <string>
指定用于所有传出日志的日志标签。可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
Sets the tag field in the syslog header to this string. It defaults to the log-tag set in the global section, otherwise the program name as launched from the command line, which usually is "HAProxy". Sometimes it can be useful to differentiate between multiple processes running on the same host, or to differentiate customer instances running in the same process. In the backend, logs about servers up/down will use this tag. As a hint, it can be convenient to set a log-tag related to a hosted customer in a defaults section then put all the frontends and backends for that customer, then start another customer in a new defaults section. See also the global "log-tag" directive.
设置用于维护 keep-alive 连接的最大服务器队列大小。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
HTTP keep-alive tries to reuse the same server connection whenever possible, but sometimes it can be counter-productive, for example if a server has a lot of connections while other ones are idle. This is especially true for static servers. The purpose of this setting is to set a threshold on the number of queued connections at which HAProxy stops trying to reuse the same server and prefers to find another one. The default value, -1, means there is no limit. A value of zero means that keep-alive requests will never be queued. For very close servers which can be reached with a low latency and which are not sensible to breaking keep-alive, a low value is recommended (e.g. local static server can use a value of 10 or less). For remote servers suffering from a high latency, higher values might be needed to cover for the latency and/or the cost of picking a different server. Note that this has no impact on responses which are maintained to the same server consecutively to a 401 response. They will still go to the same server even if they have to be queued.
设置我们可以为给定客户端会话保持空闲的最大传出连接数。默认值为 5(精确等于在构建时定义的 MAX_SRV_LIST)。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
maxconn <conns>
设置前端的最大并发连接数。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<conns> 是前端将接受服务的最大并发连接数。超出的连接将由系统在套接字的侦听队列中排队,并在一个连接关闭后得到服务。
If the system supports it, it can be useful on big sites to raise this limit very high so that HAProxy manages connection queues, instead of leaving the clients with unanswered connection attempts. This value should not exceed the global maxconn. Also, keep in mind that a connection contains two buffers of tune.bufsize (16kB by default) each, as well as some other data resulting in about 33 kB of RAM being consumed per established connection. That means that a medium system equipped with 1GB of RAM can withstand around 20000-25000 concurrent connections if properly tuned. Also, when <conns> is set to large values, it is possible that the servers are not sized to accept such loads, and for this reason it is generally wise to assign them some reasonable connection limits. When this value is set to zero, which is the default, the global "maxconn" value is used.
mode { tcp|http|log|spop }
设置实例的运行模式或协议

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
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. 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 log backend. This mode is mandatory and automatically set, if necessary, for backends referenced by SPOE engines.
在进行内容切换时,前端和后端必须处于相同的模式(通常是 HTTP),否则配置将被拒绝。
Example
defaults http_instances mode http
monitor fail { if | unless } <condition>
添加一个条件,以便向监控 HTTP 请求报告失败。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

no

yes

yes

no
参数
if <cond> 如果条件满足,监控请求将失败,否则将成功。该条件应描述一个组合测试,如果所有条件都满足,则必须导致失败,例如后端及其备份中的服务器数量都很少。 unless <cond> 只有当条件满足时,监控请求才会成功,否则将失败。这样的条件可以基于对后端列表中最小活动服务器数量的存在的测试。
This statement adds a condition which can force the response to a monitor request to report a failure. By default, when an external component queries the URI dedicated to monitoring, a 200 response is returned. When one of the conditions above is met, HAProxy will return 503 instead of 200. This is very useful to report a site failure to an external component which may base routing advertisements between multiple sites on the availability reported by HAProxy. In this case, one would rely on an ACL involving the "nbsrv" criterion. Note that "monitor fail" only works in HTTP mode. Both status messages may be tweaked using "errorfile" or "errorloc" if needed.
示例
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
拦截外部组件监控请求使用的 URI。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<uri> 是我们想要拦截以返回 HAProxy 健康状态而不是转发请求的确切 URI。
When an HTTP request referencing <uri> will be received on a frontend, HAProxy will not forward it nor log it, but instead will return either "HTTP/1.0 200 OK" or "HTTP/1.0 503 Service unavailable", depending on failure conditions defined with "monitor fail". This is normally enough for any front-end HTTP probe to detect that the service is UP and running without forwarding the request to a backend server. Note that the HTTP method, the version and all headers are ignored, but the request must at least be valid at the HTTP level. This keyword may only be used with an HTTP-mode frontend. Monitor requests are processed very early, just after the request is parsed and even before any "http-request". The only rulesets applied before are the tcp-request ones. They cannot be logged either, and it is the intended purpose. Only one URI may be configured for monitoring; when multiple "monitor-uri" statements are present, the last one will define the URI to be used. They are only used to report HAProxy's health to an upper component, nothing more. However, it is possible to add any number of conditions using "monitor fail" and ACLs so that the result can be adjusted to whatever check can be imagined (most often the number of available servers in a backend). Note: if <uri> starts by a slash ('/'), the matching is performed against the request's path instead of the request's uri. It is a workaround to let the HTTP/2 requests match the monitor-uri. Indeed, in HTTP/2, clients are encouraged to send absolute URIs only.
Example
# 使用 /haproxy_test 报告 HAProxy 的状态 frontend www mode http monitor-uri /haproxy_test
Enable or disable early abortion of not started processing when client closes May be used in the following contexts: tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
TCP connections support being closed independently in each direction, and a connection with only one direction closed is often said to be "half-closed". Originally when the HTTP ecosystem was mostly made of the "close mode", with only one request and one response per connection before closing, it was pretty frequent to see scripted clients send their request, close the sending side, wait for the response, receive the close indication and be done with this. But with the arrival of keep-alive and more advanced protocols, this practice has practically disappeared and the only cases where a client closes before receiving its response is essentially when the user wants to abort a transfer, or when a timeout strikes and the connection is closed. These two situations (half-closed vs abort) are undistinguishable from the server side (here the HAProxy listener). This is a problem because leaving the connection alive and continuing to process a request when clients abort can cost a lot of resources, particularly if the closure is the result of a user hitting the "reload" button, as it means new requests are queued without the previous ones being aborted. And conversely, systematically aborting when facing such a half-close situation would break a number of TCP applications and even some HTTP ones on internal networks interacting with legacy agents. The "abortonclose" option permits to choose the desired behavior: - when present in a frontend, it will avoid processing TLS handshakes which are pending on a half-closed connection. This can be the result of a user hitting "reload" during an HTTPS request under high load such as a VRRP fail-over between an active HAProxy node and the backup one: all clients reconnect at the same time to the new node, and all have to perform a costly, full TLS handshake. If it takes more than a few seconds, it's likely that some users will give up, and it's pointless to waste CPU cycles on their handshakes. Given the CPU cost of TLS handshakes, it is recommended to leave this option enabled on internet-facing frontends. This is the default for incoming TLS connections. - 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. The recommendation is to enable this option on internet-facing TLS endpoints and HTTP services, and to disable it for pure TCP ones as well as unexposed legacy environments. It is enabled by default in HTTP backends, and may be forcefully disabled by prepending the "no" keyword before it, either in the backend section itself, or in the "defaults" section it inherits from. It is also enabled by default for TLS listeners and may be forcefully disabled as well by specifying "no option abortonclose" in the frontend or in the "defaults" section it inherits from. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
启用或禁用放宽 HTTP 请求解析。“accept-invalid-http-request”关键字已弃用,请改用 "option accept-unsafe-violations-in-http-request"。
启用或禁用放宽 HTTP 响应解析。“accept-invalid-http-response”关键字已弃用,请改用 "option accept-unsafe-violations-in-http-response"。
启用或禁用放宽 HTTP 请求解析。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
By default, HAProxy complies with the different HTTP RFCs in terms of message parsing. This means the message parsing is quite strict and causes an error to be returned to the client for malformed messages. This is the desired behavior as such malformed messages are essentially used to build attacks exploiting server weaknesses, and bypass security filtering. Sometimes, a buggy browser will not respect these RCFs for whatever reason (configuration, implementation...) and the issue will not be immediately fixed. In such case, it is possible to relax HAProxy's parser to accept some invalid requests by specifying this option. Most of rules concern the H1 parsing for historical reason. Newer HTTP versions tends to be cleaner and applications follow more stickly these protocols. When this option is set, the following rules are observed: * In H1 only, invalid characters, including NULL character, in header name will be accepted; * 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 ('\'), 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. This option should never be enabled by default as it hides application bugs and open security breaches. It should only be deployed after a problem has been confirmed. When this option is enabled, invalid but accepted H1 requests will be captured in order to permit later analysis using the "show errors" request on the UNIX stats socket.Doing this also helps confirming that the issue has been solved. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
启用或禁用放宽 HTTP 响应解析。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
Similarly to "option accept-unsafe-violations-in-http-request", this option may be used to relax parsing rules of HTTP responses. It should only be enabled for trusted legacy servers to accept some invalid responses. Most of rules concern the H1 parsing for historical reason. Newer HTTP versions tends to be cleaner and applications follow more stickly these protocols. When this option is set, the following rules are observed: * In H1 only, invalid characters, including NULL character, in header name will be accepted; * 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. This option should never be enabled by default as it hides application bugs and open security breaches. It should only be deployed after a problem has been confirmed. When this option is enabled, erroneous header names will still be accepted in responses, but the complete response will be captured in order to permit later analysis using the "show errors" request on the UNIX stats socket. Doing this also helps confirming that the issue has been solved. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
选择一次性使用所有备份服务器,还是只使用第一个。可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
默认情况下,当所有正常服务器都宕机时,第一个可用的备用服务器将获得所有流量。有时,可能希望一次使用多个备用服务器,因为一个可能不够用。当启用 "option allbackups" 时,当所有正常服务器都不可用时,将在所有备用服务器之间执行负载均衡。将使用相同的负载均衡算法,并遵守服务器的权重。因此,备用服务器之间将不再有任何优先级顺序。此选项主要用于专用于在应用程序完全离线时返回“抱歉”页面的静态服务器群。 如果此选项已在 "defaults" 部分中启用,可以通过在其前面添加 "no" 关键字来在特定实例中禁用它。
分析所有服务器响应并阻止带有可缓存 cookie 的响应。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
Some high-level frameworks set application cookies everywhere and do not always let enough control to the developer to manage how the responses should be cached. When a session cookie is returned on a cacheable object, there is a high risk of session crossing or stealing between users traversing the same caches. In some situations, it is better to block the response than to let some sensitive session information go in the wild. The option "checkcache" enables deep inspection of all server responses for strict compliance with HTTP specification in terms of cacheability. It carefully checks "Cache-control", "Pragma" and "Set-cookie" headers in server response to check if there's a risk of caching a cookie on a client-side proxy. When this option is enabled, the only responses which can be delivered to the client are : - all those without "Set-Cookie" header; - all those with a return code other than 200, 203, 204, 206, 300, 301, 404, 405, 410, 414, 501, provided that the server has not set a "Cache-control: public" header field; - all those that result from a request using a method other than GET, HEAD, OPTIONS, TRACE, provided that the server has not set a 'Cache-Control: public' header field; - those with a 'Pragma: no-cache' header - those with a 'Cache-control: private' header - those with a 'Cache-control: no-store' header - those with a 'Cache-control: max-age=0' header - those with a 'Cache-control: s-maxage=0' header - those with a 'Cache-control: no-cache' header - those with a 'Cache-control: no-cache="set-cookie"' header - those with a 'Cache-control: no-cache="set-cookie,' header (allowing other fields after set-cookie) If a response doesn't respect these requirements, then it will be blocked just as if it was from an "http-response deny" rule, with an "HTTP 502 bad gateway". The session state shows "PH--" meaning that the proxy blocked the response during headers processing. Additionally, an alert will be sent in the logs so that admins are informed that there's something to be fixed. Due to the high impact on the application, the application should be tested in depth with the option enabled before going to production. It is also a good practice to always activate it during tests, even if it is not used in production, as it will report potentially dangerous application behaviors. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
启用或禁用在客户端发送 TCP keepalive 数据包。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
When there is a firewall or any session-aware component between a client and a server, and when the protocol involves very long sessions with long idle periods (e.g. remote desktops), there is a risk that one of the intermediate components decides to expire a session which has remained idle for too long. Enabling socket-level TCP keep-alives makes the system regularly send packets to the other end of the connection, leaving it active. The delay between keep-alive probes is controlled by the system only and depends both on the operating system and its tuning parameters. It is important to understand that keep-alive packets are neither emitted nor received at the application level. It is only the network stacks which sees them. For this reason, even if one side of the proxy already uses keep-alives to maintain its connection alive, those keep-alive packets will not be forwarded to the other side of the proxy. Please note that this has nothing to do with HTTP keep-alive. Using option "clitcpka" enables the emission of TCP keep-alive probes on the client side of a connection, which should help when session expirations are noticed between HAProxy and a client. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
启用持续的流量统计更新。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
默认情况下,用于统计计算的计数器仅在流结束时递增。这在处理小对象时效果很好,但对于大对象(例如大图片或存档)或音视频流,从 HAProxy 计数器生成的图表看起来像一只刺猬。启用此选项后,计数器会随着流的进行而频繁递增,通常每 5 秒一次,这通常足以生成清晰的图表。重新计数直接触及热路径,因此默认情况下未启用,因为它可能导致大量会话计数的唤醒,并导致轻微的性能下降。
启用或禁用从 HTTP/1.x 客户端连接的隐式 HTTP/2 升级。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
默认情况下,如果 HAProxy 从给定的 HTTP 连接收到的第一个请求与 HTTP/2 连接前言(即字符串 "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n")匹配,HAProxy 能够将 HTTP/1.x 客户端连接隐式升级为 HTTP/2 连接。这样,就可以在非 SSL 连接上支持 HTTP/1.x 和 HTTP/2 客户端。必须使用此选项来禁用隐式升级。请注意,此隐式升级仅支持 HTTP 代理,因此此选项也一样。另请注意,可以通过在绑定行上指定 "proto h2" 来强制在明文连接上使用 HTTP/2。最后,此选项适用于所有绑定行。要为特定的绑定行禁用隐式 HTTP/2 升级,可以使用 "proto h1"。如果此选项已在“defaults”部分启用,则可以通过在其前面加上“no”关键字来在特定实例中禁用它。
启用或禁用对正常、成功的连接的日志记录。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
有些大型网站每秒处理数千个连接,日志记录对它们来说是一个主要的痛点。其中一些甚至被迫关闭日志,无法调试生产问题。设置此选项可确保正常的连接,即那些没有经历错误、超时、重试或重新分派的连接,将不会被记录。这为异常情况留下了磁盘空间。在 HTTP 模式下,会检查响应状态码,返回码为 5xx 的仍将被记录。 强烈建议不要使用此选项,因为大多数情况下,复杂问题的关键在于正常的日志中,而这些日志在这里不会被记录。如果您需要分离日志,请改用 "log-separate-errors" 选项。
启用或禁用对空连接的日志记录。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
在某些环境中,有些组件会定期连接到各种系统,以确保它们仍然存活。这可能是来自另一个负载均衡器以及监控系统的情况。默认情况下,即使是简单的端口探测或扫描也会产生一条日志。如果这些连接过多地污染了日志,可以启用选项“dontlognull”,以指示没有传输任何数据的连接将不会被记录,这通常对应于那些探测。请注意,错误仍将返回给客户端并在统计信息中计算。如果这不是期望的,可以使用 http-ignore-probes 选项。通常建议不要在不受控制的环境(例如互联网)中使用此选项,否则扫描和其他恶意活动将不会被记录。如果此选项已在“defaults”部分启用,则可以通过在其前面加上“no”关键字来在特定实例中禁用它。
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>]
启用在发送到服务器的请求中插入 rfc 7239 forwarded 头部。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<host_expr> 可选参数,用于指定一个自定义样本表达式,其结果将用作 'host' 参数值 <by_expr> 可选参数,用于指定一个自定义样本表达式,其结果将用作 'by' 参数的 nodename 值 <for_expr> 可选参数,用于指定一个自定义样本表达式,其结果将用作 'for' 参数的 nodename 值 <by_port_expr> 可选参数,用于指定一个自定义样本表达式,其结果将用作 'by' 参数的 nodeport 值 <for_port_expr> 可选参数,用于指定一个自定义样本表达式,其结果将用作 'for' 参数的 nodeport 值
Since HAProxy works in reverse-proxy mode, servers are losing some request context (request origin: client ip address, protocol used...) A common way to address this limitation is to use the well known x-forward-for and x-forward-* friends to expose some of this context to the underlying servers/applications. While this use to work and is widely deployed, it is not officially supported by the IETF and can be the root of some interoperability as well as security issues. To solve this, a new HTTP extension has been described by the IETF: forwarded header (RFC7239). More information here: https://www.rfc-editor.org/rfc/rfc7239.html The use of this single header allow to convey numerous details within the same header, and most importantly, fixes the proxy chaining issue. (the rfc allows for multiple chained proxies to append their own values to an already existing header). This option may be specified in defaults, listen or backend section, but it will be ignored for frontend sections. Setting option forwarded without arguments results in using default implicit behavior. Default behavior enables proto parameter and injects original client ip. The equivalent explicit/manual configuration would be: option forwarded proto for The keyword 'by' is used to enable 'by' parameter ("nodename") in forwarded header. It allows to embed request proxy information. 'by' value will be set to proxy ip (destination address) If not available (ie: UNIX listener), 'by' will be set to "unknown". The keyword 'by-expr' is used to enable 'by' parameter ("nodename") in forwarded header. It allows to embed request proxy information. 'by' value will be set to the result of the sample expression <by_expr>, if valid, otherwise it will be set to "unknown". The keyword 'for' is used to enable 'for' parameter ("nodename") in forwarded header. It allows to embed request client information. 'for' value will be set to client ip (source address) If not available (ie: UNIX listener), 'for' will be set to "unknown". The keyword 'for-expr' is used to enable 'for' parameter ("nodename") in forwarded header. It allows to embed request client information. 'for' value will be set to the result of the sample expression <for_expr>, if valid, otherwise it will be set to "unknown". The keyword 'by_port' is used to provide "nodeport" info to 'by' parameter. 'by_port' requires 'by' or 'by-expr' to be set or it will be ignored. "nodeport" will be set to proxy (destination) port if available, otherwise it will be ignored. The keyword 'by_port-expr' is used to provide "nodeport" info to 'by' parameter. 'by_port-expr' requires 'by' or 'by-expr' to be set or it will be ignored. "nodeport" will be set to the result of the sample expression <by_port_expr>, if valid, otherwise it will be ignored. The keyword 'for_port' is used to provide "nodeport" info to 'for' parameter. 'for_port' requires 'for' or 'for-expr' to be set or it will be ignored. "nodeport" will be set to client (source) port if available, otherwise it will be ignored. The keyword 'for_port-expr' is used to provide "nodeport" info to 'for' parameter. 'for_port-expr' requires 'for' or 'for-expr' to be set or it will be ignored. "nodeport" will be set to the result of the sample expression <for_port_expr>, if valid, otherwise it will be ignored.
示例
# 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 [ except <network> ] [ header <name> ] [ if-none ]
启用向发送到服务器的请求中插入 X-Forwarded-For 头部。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<network> 是一个可选参数,用于对匹配 <network> 的源禁用此选项。<name> 是一个可选参数,用于指定一个不同的 "X-Forwarded-For" 头部名称。
Since HAProxy works in reverse-proxy mode, the servers see its IP address as their client address. This is sometimes annoying when the client's IP address is expected in server logs. To solve this problem, the well-known HTTP header "X-Forwarded-For" may be added by HAProxy to all requests sent to the server. This header contains a value representing the client's IP address. Since this header is always appended at the end of the existing header list, the server must be configured to always use the last occurrence of this header only. See the server's manual to find how to enable use of this standard header. Note that only the last occurrence of the header must be used, since it is really possible that the client has already brought one. The keyword "header" may be used to supply a different header name to replace the default "X-Forwarded-For". This can be useful where you might already have a "X-Forwarded-For" header from a different application (e.g. stunnel), and you need preserve it. Also if your backend server doesn't use the "X-Forwarded-For" header and requires different one (e.g. Zeus Web Servers require "X-Cluster-Client-IP"). Sometimes, a same HAProxy instance may be shared between a direct client access and a reverse-proxy access (for instance when an SSL reverse-proxy is used to decrypt HTTPS traffic). It is possible to disable the addition of the header for a known source address or network by adding the "except" keyword followed by the network address. In this case, any source IP matching the network will not cause an addition of this header. Most common uses are with private networks or 127.0.0.1. IPv4 and IPv6 are both supported. Alternatively, the keyword "if-none" states that the header will only be added if it is not present. This should only be used in perfectly trusted environment, as this might cause a security issue if headers reaching HAProxy are under the control of the end-user. This option may be specified either in the frontend or in the backend. If at least one of them uses it, the header will be added. Note that the backend's setting of the header subargument takes precedence over the frontend's if both are defined. In the case of the "if-none" argument, if at least one of the frontend or the backend does not specify it, it wants the addition to be mandatory, so it wins.
Example
# 公共 HTTP 地址,也由同一台机器上的 stunnel 使用 frontend www mode http option forwardfor except 127.0.0.1 # stunnel 已经添加了该标头 # 这些服务器希望在 X-Client 中获取 IP 地址 backend www mode http option forwardfor header X-Client
启用或禁用发送给有问题的客户端的 HTTP/1 头部的大小写调整。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
There is no standard case for header names because, as stated in RFC7230, they are case-insensitive. So applications must handle them in a case- insensitive manner. But some bogus applications violate the standards and erroneously rely on the cases most commonly used by browsers. This problem becomes critical with HTTP/2 because all header names must be exchanged in lower case, and HAProxy follows the same convention. All header names are sent in lower case to clients and servers, regardless of the HTTP version. When HAProxy receives an HTTP/1 response, its header names are converted to lower case and manipulated and sent this way to the clients. If a client is known to violate the HTTP standards and to fail to process a response coming from HAProxy, it is possible to transform the lower case header names to a different format when the response is formatted and sent to the client, by enabling this option and specifying the list of headers to be reformatted using the global directives "h1-case-adjust" or "h1-case-adjust-file". This must only be a temporary workaround for the time it takes the client to be fixed, because clients which require such workarounds might be vulnerable to content smuggling attacks and must absolutely be fixed. Please note that this option will not affect standards-compliant clients. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
启用或禁用发送给有问题的服务器的 HTTP/1 头部的大小写调整。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
There is no standard case for header names because, as stated in RFC7230, they are case-insensitive. So applications must handle them in a case- insensitive manner. But some bogus applications violate the standards and erroneously rely on the cases most commonly used by browsers. This problem becomes critical with HTTP/2 because all header names must be exchanged in lower case, and HAProxy follows the same convention. All header names are sent in lower case to clients and servers, regardless of the HTTP version. When HAProxy receives an HTTP/1 request, its header names are converted to lower case and manipulated and sent this way to the servers. If a server is known to violate the HTTP standards and to fail to process a request coming from HAProxy, it is possible to transform the lower case header names to a different format when the request is formatted and sent to the server, by enabling this option and specifying the list of headers to be reformatted using the global directives "h1-case-adjust" or "h1-case-adjust-file". This must only be a temporary workaround for the time it takes the server to be fixed, because servers which require such workarounds might be vulnerable to content smuggling attacks and must absolutely be fixed. Please note that this option will not affect standards-compliant servers. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
启用或禁用在处理前等待整个 HTTP 请求体。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
有时,在做出决定之前等待 HTTP 请求的主体是可取的。例如,“balance url_param”就是这样做的。第一个用例是在连接到服务器之前缓冲来自慢速客户端的请求。另一个用例是基于请求主体的内容做出路由决策。此选项放置在前端或后端中,强制 HTTP 处理等待直到接收到整个主体或请求缓冲区已满。它可能与一些滥用 HTTP 的应用程序产生不希望的副作用,这些应用程序期望前端和后端之间有无缓冲的传输,因此绝对不应默认使用。
在发送到服务器时从请求中删除 HTTP trailers。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

no

no

yes
参数:
When this option is enabled, any HTTP trailers found in a request will be dropped before sending it to the server. RFC9110#section-6.5.1 stated that trailer fields could be merged into the header fields. It should be done on purpose, but it may be a problem for some applications, especially if malicious clients hide sensitive header fields in the trailers part and some intermediaries merge them with headers with no specific checks. In that case, this option can be enabled on the backend to drop any trailer fields found in requests before sending them to the server. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
在发送到客户端时从响应中删除 HTTP trailers。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
此选项与“option http-drop-request-trailers”类似,但必须用于在将响应发送给客户端之前从响应中删除 trailer 字段。如果此选项已在“defaults”部分启用,则可以通过在其前面加上“no”关键字来在特定实例中禁用它。
启用或禁用对空连接和请求超时的日志记录。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
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. There was already "option dontlognull" but it's insufficient in this case. Instead, this option does the following things : - prevent any 400/408 message from being sent to the client if nothing was received over a connection before it was closed; - prevent any log from being emitted in this situation; - prevent any error counter from being incremented That way the empty connection is silently ignored. Note that it is better not to use this unless it is clear that it is needed, because it will hide real problems. The most common reason for not receiving a request and seeing a 408 is due to an MTU inconsistency between the client and an intermediary element such as a VPN, which blocks too large packets. These issues are generally seen with POST requests as well as GET with large cookies. The logs are often the only way to detect them. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
为 HTTP/1.x 连接启用或禁用从客户端到服务器的 HTTP keep-alive。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
By default HAProxy operates in keep-alive mode with regards to persistent HTTP/1.x connections: for each connection it processes each request and response, and leaves the connection idle on both sides. This mode may be changed by several options such as "option http-server-close" or "option httpclose". This option allows to set back the keep-alive mode, which can be useful when another mode was used in a defaults section. Setting "option http-keep-alive" enables HTTP keep-alive mode on the client- and server- sides. This provides the lowest latency on the client side (slow network) and the fastest session reuse on the server side at the expense of maintaining idle connections to the servers. In general, it is possible with this option to achieve approximately twice the request rate that the "http-server-close" option achieves on small objects. There are mainly two situations where this option may be useful : - 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. This last case can happen when the server is a fast static server of cache. At the moment, logs will not indicate whether requests came from the same session or not. The accept date reported in the logs corresponds to the end of the previous request, and the request time corresponds to the time spent waiting for a new request. The keep-alive request time is still bound to the timeout defined by "timeout http-keep-alive" or "timeout http-request" if not set. This option disables and replaces any previous "option httpclose" or "option http-server-close".
指示系统在 HTTP 中优先考虑低交互延迟而不是性能。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
In HTTP, each payload is unidirectional and has no notion of interactivity. Any agent is expected to queue data somewhat for a reasonably low delay. There are some very rare server-to-server applications that abuse the HTTP protocol and expect the payload phase to be highly interactive, with many interleaved data chunks in both directions within a single request. This is absolutely not supported by the HTTP specification and will not work across most proxies or servers. When such applications attempt to do this through HAProxy, it works but they will experience high delays due to the network optimizations which favor performance by instructing the system to wait for enough data to be available in order to only send full packets. Typical delays are around 200 ms per round trip. Note that this only happens with abnormal uses. Normal uses such as CONNECT requests nor WebSockets are not affected. When "option http-no-delay" is present in either the frontend or the backend used by a connection, all such optimizations will be disabled in order to make the exchanges as fast as possible. Of course this offers no guarantee on the functionality, as it may break at any other place. But if it works via HAProxy, it will work as fast as possible. This option should never be used by default, and should never be used at all unless such a buggy application is discovered. The impact of using this option is an increase of bandwidth usage and CPU usage, which may significantly lower performance in high latency environments.
定义 HAProxy 是否会向服务器宣告 HTTP/1.x 连接的 keepalive。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
When running with "option http-server-close" or "option httpclose", HAProxy adds a "Connection: close" header to the HTTP/1.x request forwarded to the server. Unfortunately, when some servers see this header, they automatically refrain from using the chunked encoding for responses of unknown length, while this is totally unrelated. The effect is that a client or a cache could receive an incomplete response without being aware of it, and consider the response complete. By setting "option http-pretend-keepalive", HAProxy will make the server believe it will keep the connection alive. The server will then not fall back to the abnormal undesired above. When HAProxy gets the whole response, it will close the connection with the server just as it would do with the "option httpclose". That way the client gets a normal response and the connection is correctly closed on the server side. It is recommended not to enable this option by default, because most servers will more efficiently close the connection themselves after the last packet, and release its buffers slightly earlier. Also, the added packet on the network could slightly reduce the overall peak performance. However it is worth noting that when this option is enabled, HAProxy will have slightly less work to do. So if HAProxy is the bottleneck on the whole architecture, enabling this option might save a few CPU cycles. This option may be set in backend and listen sections. Using it in a frontend section will be ignored and a warning will be reported during startup. It is a backend related option, so there is no real reason to set it on a frontend. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
option http-restrict-req-hdr-names { preserve | delete | reject }
设置 HAProxy 关于包含 "[a-zA-Z0-9-]" 字符集之外字符的 HTTP 请求头部名称的策略。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
preserve 禁用过滤。这是没有配置 FastCGI 应用程序的 HTTP 代理的默认模式。 delete 删除名称中包含 "[a-zA-Z0-9-]" 字符集之外字符的请求头部。这是配置了 FastCGI 应用程序的 HTTP 后端的默认模式。 reject 如果请求包含名称中含有 "[a-zA-Z0-9-]" 字符集之外字符的头部,则以 403-Forbidden 响应拒绝该请求。
此选项可用于将请求头部名称限制为字母数字和连字符字符 ([A-Za-z0-9-])。这对于与无法处理头部名称中某些字符的非 HTTP 兼容服务器互操作可能是必需的。对于 FastCGI 应用程序也可能是必需的,因为头部名称中的所有非字母数字字符都会被下划线 ('_') 替换。因此,很容易混淆头部名称并绕过一些规则。例如,"X-Forwarded-For" 和 "X_Forwarded-For" 头部在 FastCGI 中都被转换为 "HTTP_X_FORWARDED_FOR"。请注意,此选项是按代理评估的,并且在 http-request 规则评估之后。
启用或禁用服务器端的 HTTP/1.x 连接关闭。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
By default HAProxy operates in keep-alive mode with regards to persistent HTTP/1.x connections: for each connection it processes each request and response, and leaves the connection idle on both sides. This mode may be changed by several options such as "option http-server-close" or "option httpclose". Setting "option http-server-close" enables HTTP connection-close mode on the server side while keeping the ability to support HTTP keep-alive and pipelining on the client side. This provides the lowest latency on the client side (slow network) and the fastest session reuse on the server side to save server resources, similarly to "option httpclose". It also permits non-keepalive capable servers to be served in keep-alive mode to the clients if they conform to the requirements of RFC7230. Please note that some servers do not always conform to those requirements when they see "Connection: close" in the request. The effect will be that keep-alive will never be used. A workaround consists in enabling "option http-pretend-keepalive". At the moment, logs will not indicate whether requests came from the same session or not. The accept date reported in the logs corresponds to the end of the previous request, and the request time corresponds to the time spent waiting for a new request. The keep-alive request time is still bound to the timeout defined by "timeout http-keep-alive" or "timeout http-request" if not set. This option may be set both in a frontend and in a backend. It is enabled if at least one of the frontend or backend holding a connection has it enabled. It disables and replaces any previous "option httpclose" or "option http-keep-alive". Please check section 4 ("Proxies") to see how this option combines with others when frontend and backend options differ. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
使用非标准的 Proxy-Connection 头代替 Connection 可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
While RFC7230 explicitly states that HTTP/1.1 agents must use the Connection header to indicate their wish of persistent or non-persistent connections, both browsers and proxies ignore this header for proxied connections and make use of the undocumented, non-standard Proxy-Connection header instead. The issue begins when trying to put a load balancer between browsers and such proxies, because there will be a difference between what HAProxy understands and what the client and the proxy agree on. By setting this option in a frontend, HAProxy can automatically switch to use that non-standard header if it sees proxied requests. A proxied request is defined here as one where the URI begins with neither a '/' nor a '*'. This is incompatible with the HTTP tunnel mode. Note that this option can only be specified in a frontend and will affect the request along its whole life. Also, when this option is set, a request which requires authentication will automatically switch to use proxy authentication headers if it is itself a proxied request. That makes it possible to check or enforce authentication in front of an existing proxy. This option should normally never be used, except in front of a proxy.
option httpchk <method> <uri>
option httpchk <method> <uri> <version>
option httpchk <method> <uri> <version> <host>
启用 HTTP 协议来检查服务器健康状况 可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<method> 是与请求一起使用的可选 HTTP 方法。如果未设置,则使用“OPTIONS”方法,因为它通常需要较低的服务器处理能力,并且易于从日志中过滤掉。可以使用任何方法,但不建议发明非标准方法。<uri> 是 HTTP 请求中引用的 URI。它默认为“/”,这在几乎所有服务器上都是默认可访问的,但可以更改为任何其他 URI。允许使用查询字符串。<version> 是可选的 HTTP 版本字符串。它默认为“HTTP/1.0”,但有些服务器在 HTTP 1.0 中可能会行为不正确,因此将其更改为 HTTP/1.1 有时会有所帮助。请注意,Host 字段在 HTTP/1.1 中是强制性的。<host> 是可选的 HTTP Host 头的值。默认情况下不设置。它是一个日志格式字符串。
By default, server health checks only consist in trying to establish a TCP connection. When "option httpchk" is specified, a complete HTTP request is sent once the TCP connection is established, and responses 2xx and 3xx are considered valid, while all other ones indicate a server failure, including the lack of any response. Combined with "http-check" directives, it is possible to customize the request sent during the HTTP health checks or the matching rules on the response. It is also possible to configure a send/expect sequence, just like with the directive "tcp-check" for TCP health checks. The server configuration is used by default to open connections to perform HTTP health checks. By it is also possible to overwrite server parameters using "http-check connect" rules. "httpchk" option does not necessarily require an HTTP backend, it also works with plain TCP backends. This is particularly useful to check simple scripts bound to some dedicated ports using the inetd daemon. However, it will always internally relies on an HTX multiplexer. Thus, it means the request formatting and the response parsing will be strict.
示例
# 将 HTTPS 流量中继到 Apache 实例,并使用 HTTP 请求 "OPTIONS * HTTP/1.1" # 在端口 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
启用或禁用 HTTP/1.x 连接关闭 可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
By default HAProxy operates in keep-alive mode with regards to persistent HTTP/1.x connections: for each connection it processes each request and response, and leaves the connection idle on both sides. This mode may be changed by several options such as "option http-server-close" or "option httpclose". If "option httpclose" is set, HAProxy will close the client or the server connection, depending where the option is set. The frontend is considered for client connections while the backend is considered for server ones. If the option is set on a listener, it is applied both on client and server connections. It will check if a "Connection: close" header is already set in each direction, and will add one if missing. This option may also be combined with "option http-pretend-keepalive", which will disable sending of the "Connection: close" request header, but will still cause the connection to be closed once the whole response is received. It disables and replaces any previous "option http-server-close" or "option http-keep-alive". If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
启用 HTTP 请求、流状态和计时器的日志记录 可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
clf 如果添加了“clf”参数,则输出格式将是 CLF 格式,而不是 HAProxy 的默认 HTTP 格式。当您需要将 HAProxy 的日志输入到只支持 CLF 格式且不可扩展的特定日志分析器时,可以使用此选项。
默认情况下,日志输出格式非常简单,只包含源地址、目标地址和实例名称。通过指定“option httplog”,每条日志行都会变成更丰富的格式,包括但不限于 HTTP 请求、连接计时器、流状态、连接数、捕获的头和 cookie、前端、后端和服务器名称,当然还有源地址和端口。仅指定“option httplog”将自动清除默认设置的“clf”模式。“option httplog”会覆盖任何先前的“log-format”指令。
启用 HTTPS 请求、流状态和计时器的日志记录 可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
默认情况下,日志输出格式非常简单,只包含源地址、目标地址和实例名称。通过指定“option httpslog”,每条日志行都会变成更丰富的格式,包括但不限于 HTTP 请求、连接计时器、流状态、连接数、捕获的头和 cookie、前端、后端和服务器名称、SSL 证书验证和 SSL 握手状态,当然还有源地址和端口。“option httpslog”会覆盖任何先前的“log-format”指令。
启用或禁用双向独立的超时处理 可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
By default, when data is sent over a socket, both the write timeout and the read timeout for that socket are refreshed, because we consider that there is activity on that socket, and we have no other means of guessing if we should receive data or not. While this default behavior is desirable for almost all applications, there exists a situation where it is desirable to disable it, and only refresh the read timeout if there are incoming data. This happens on streams with large timeouts and low amounts of exchanged data such as telnet session. If the server suddenly disappears, the output data accumulates in the system's socket buffers, both timeouts are correctly refreshed, and there is no way to know the server does not receive them, so we don't timeout. However, when the underlying protocol always echoes sent data, it would be enough by itself to detect the issue using the read timeout. Note that this problem does not happen with more verbose protocols because data won't accumulate long in the socket buffers. When this option is set on the frontend, it will disable read timeout updates on data sent to the client. There probably is little use of this case. When the option is set on the backend, it will disable read timeout updates on data sent to the server. Doing so will typically break large HTTP posts from slow lines, so use it with caution.
使用 LDAPv3 健康检查来测试服务器 可在以下上下文中使用:tcp

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
可以测试服务器是否正确地使用 LDAPv3 通信,而不仅仅是测试它是否接受 TCP 连接。设置此选项后,会向服务器发送一个 LDAPv3 匿名简单绑定消息,并分析响应以查找 LDAPv3 绑定响应消息。只有当 LDAP 响应包含成功 resultCode (http://tools.ietf.org/html/rfc4511#section-4.1.9) 时,服务器才被认为是有效的。绑定请求的日志记录取决于服务器,请参阅您的文档如何配置它。
Example
option ldap-check
使用外部进程进行服务器健康检查 可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
可以使用外部命令测试服务器的健康状况。这是通过运行使用 "external-check command" 设置的可执行文件来实现的。需要设置全局的 "external-check"。
避免在软停止期间关闭空闲的前端连接 可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
By default, idle connections will be closed during a soft stop. In some environments, a client talking to the proxy may have prepared some idle connections in order to send requests later. If there is no proper retry on write errors, this can result in errors while haproxy is reloading. Even though a proper implementation should retry on connection/write errors, this option was introduced to support backwards compatibility with haproxy prior to version 2.4. Indeed before v2.4, haproxy used to wait for a last request and response to add a "connection: close" header before closing, thus notifying the client that the connection would not be reusable. In a real life example, this behavior was seen in AWS using the ALB in front of a haproxy. The end result was ALB sending 502 during haproxy reloads. Users are warned that using this option may increase the number of old processes if connections remain idle for too long. Adjusting the client timeouts and/or the "hard-stop-after" parameter accordingly might be needed in case of frequent reloads.
启用或禁用健康检查状态更新的日志记录 可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
默认情况下,如果服务器处于 UP 状态,则记录失败的健康检查;如果服务器处于 DOWN 状态,则记录成功的健康检查,因此额外的信息量是有限的。启用此选项后,健康检查状态或服务器健康状况的任何变化都将被记录,这样就可以知道服务器在崩溃前偶尔会检查失败,或者确切知道它何时未能响应有效的 HTTP 状态,然后端口何时开始拒绝连接,以及服务器何时完全停止响应。请注意,此选项有意不记录非健康检查引起的状态变化(例如,在 CLI 上启用/禁用)。
更改非完全成功连接的日志级别 可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
有时在日志中查找错误并不容易。此选项使 HAProxy 提高包含潜在有用信息的日志级别,例如错误、超时、重试、重新分派或 HTTP 状态码 5xx。级别从“info”变为“err”。这使得大多数 syslog 守护进程可以将它们单独记录到不同的文件中。请注意不要从原始文件中删除它们,否则会丢失提供非常重要信息的顺序。使用此选项,处理每秒数千个连接的大型站点可以将正常流量记录到循环缓冲区中,并仅归档较小的错误日志。
启用或禁用早期日志记录。 可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
By default, logs are emitted when all the log format aliases and sample fetches used in the definition of the log-format string return a value, or when the stream is terminated. This allows the built in log-format strings to account for the transfer time, or the number of bytes in log messages. When handling long lived connections such as large file transfers or RDP, it may take a while for the request or connection to appear in the logs. Using "option logasap", the log message is created as soon as the server connection is established in mode tcp, or as soon as the server sends the complete headers in mode http. Missing information in the logs will be the total number of bytes which will only indicate the amount of data transferred before the message was created and the total time which will not take the remainder of the connection life or transfer time into account. For the case of HTTP, it is good practice to capture the Content-Length response header so that the logs at least indicate how many bytes are expected to be transferred.
示例
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 mysql-check [ user <username> [ { post-41 | pre-41 } ] ]
使用 MySQL 健康检查来测试服务器 可在以下上下文中使用:tcp

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<username> 这是连接到 MySQL 服务器时将使用的用户名。 post-41 发送与 v4.1 后客户端兼容的检查(默认) pre-41 发送与 v4.1 前客户端兼容的检查
If you specify a username, the check consists of sending two MySQL packet, one Client Authentication packet, and one QUIT packet, to correctly close MySQL session. We then parse the MySQL Handshake Initialization packet and/or Error packet. It is a basic but useful test which does not produce error nor aborted connect on the server. However, it requires an unlocked authorised user without a password. To create a basic limited user in MySQL with optional resource limits: 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 */; If you don't specify a username (it is deprecated and not recommended), the check only consists in parsing the Mysql Handshake Initialization packet or Error packet, we don't send anything in this mode. It was reported that it can generate lockout if check is too frequent and/or if there is not enough traffic. In fact, you need in this case to check MySQL "max_connect_errors" value as if a connection is established successfully within fewer than MySQL "max_connect_errors" attempts after a previous connection was interrupted, the error count for the host is cleared to zero. If HAProxy's server get blocked, the "FLUSH HOSTS" statement is the only way to unblock it. Remember that this does not check database presence nor database consistency. To do this, you can use an external check with xinetd for example. The check requires MySQL >=3.22, for older version, please use TCP check. Most often, an incoming MySQL server needs to see the client's IP address for various purposes, including IP privilege matching and connection logging. When possible, it is often wise to masquerade the client's IP address when connecting to the server using the "usesrc" argument of the "source" keyword, which requires the transparent proxy feature to be compiled in, and the MySQL server to route the client via the machine hosting HAProxy.
启用或禁用关闭后立即清理会话资源 可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
When clients or servers abort connections in a dirty way (e.g. they are physically disconnected), the session timeouts triggers and the session is closed. But it will remain in FIN_WAIT1 state for some time in the system, using some resources and possibly limiting the ability to establish newer connections. When this happens, it is possible to activate "option nolinger" which forces the system to immediately remove any socket's pending data on close. Thus, a TCP RST is emitted, any pending data are truncated, and the session is instantly purged from the system's tables. The generally visible effect for a client is that responses are truncated if the close happens with a last block of data (e.g. on a redirect or error response). On the server side, it may help release the source ports immediately when forwarding a client aborts in tunnels. In both cases, TCP resets are emitted and given that the session is instantly destroyed, there will be no retransmit. On a lossy network this can increase problems, especially when there is a firewall on the lossy side, because the firewall might see and process the reset (hence purge its session) and block any further traffic for this session,, including retransmits from the other side. So if the other side doesn't receive it, it will never receive any RST again, and the firewall might log many blocked packets. For all these reasons, it is strongly recommended NOT to use this option, unless absolutely needed as a last resort. In most situations, using the "client-fin" or "server-fin" timeouts achieves similar results with a more reliable behavior. On Linux it's also possible to use the "tcp-ut" bind or server setting. This option may be used both on frontends and backends, depending on the side where it is required. Use it on the frontend for clients, and on the backend for servers. While this option is technically supported in "defaults" sections, it must really not be used there as it risks to accidentally propagate to sections that must no use it and to cause problems there. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
option originalto [ except <network> ] [ header <name> ]
启用向服务器发送的请求中插入 X-Original-To 头 可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<network> 是一个可选参数,用于为匹配 <network> 的源禁用此选项。<name> 是一个可选参数,用于指定一个不同的 "X-Original-To" 标头名称。
Since HAProxy can work in transparent mode, every request from a client can be redirected to the proxy and HAProxy itself can proxy every request to a complex SQUID environment and the destination host from SO_ORIGINAL_DST will be lost. This is annoying when you want access rules based on destination ip addresses. To solve this problem, a new HTTP header "X-Original-To" may be added by HAProxy to all requests sent to the server. This header contains a value representing the original destination IP address. Since this must be configured to always use the last occurrence of this header only. Note that only the last occurrence of the header must be used, since it is really possible that the client has already brought one. The keyword "header" may be used to supply a different header name to replace the default "X-Original-To". This can be useful where you might already have a "X-Original-To" header from a different application, and you need preserve it. Also if your backend server doesn't use the "X-Original-To" header and requires different one. Sometimes, a same HAProxy instance may be shared between a direct client access and a reverse-proxy access (for instance when an SSL reverse-proxy is used to decrypt HTTPS traffic). It is possible to disable the addition of the header for a known destination address or network by adding the "except" keyword followed by the network address. In this case, any destination IP matching the network will not cause an addition of this header. Most common uses are with private networks or 127.0.0.1. IPv4 and IPv6 are both supported. This option may be specified either in the frontend or in the backend. If at least one of them uses it, the header will be added. Note that the backend's setting of the header subargument takes precedence over the frontend's if both are defined.
示例
# 原始目标地址 frontend www mode http option originalto except 127.0.0.1 # 这些服务器希望在 X-Client-Dst 中获取 IP 地址 backend www mode http option originalto header X-Client-Dst
启用或禁用对故障服务器的强制持久性 可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
当 HTTP 请求到达一个带有引用故障服务器的 cookie 的后端时,默认情况下它会被重新分派到另一台服务器。如果绝对需要,可以使用 "option persist" 强制将请求首先发送到故障服务器。一个常见的用例是当服务器处于极端负载下并不断地出现状态切换时。在这种情况下,用户仍将被导向到他们打开会话的服务器,希望他们能得到正确的服务。建议将 "option redispatch" 与此选项结合使用,以便在无法连接到服务器的情况下(服务器确定故障),客户端最终将被重定向到另一台有效的服务器。如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
使用 PostgreSQL 健康检查来测试服务器 可在以下上下文中使用:tcp

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<username> 这是连接到 PostgreSQL 服务器时将使用的用户名。
此检查发送一个 PostgreSQL StartupMessage 并等待认证请求或 ErrorResponse 消息。这是一个基本但有用的测试,不会在服务器上产生错误或中止连接。此检查与 "mysql-check" 相同。
允许多个负载均衡的请求保留在同一台服务器上 可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
When the load balancing algorithm in use is not deterministic, and a previous request was sent to a server to which HAProxy still holds a connection, it is sometimes desirable that subsequent requests on a same session go to the same server as much as possible. Note that this is different from persistence, as we only indicate a preference which HAProxy tries to apply without any form of warranty. The real use is for keep-alive connections sent to servers. When this option is used, HAProxy will try to reuse the same connection that is attached to the server instead of rebalancing to another server, causing a close of the connection. This can make sense for static file servers. It does not make much sense to use this in combination with hashing algorithms. Note, HAProxy already automatically tries to stick to a server which sends a 401 or to a proxy which sends a 407 (authentication required), when the load balancing algorithm is not deterministic. This is mandatory for use with the broken NTLM authentication challenge, and significantly helps in troubleshooting some faulty applications. Option prefer-last-server might be desirable in these environments as well, to avoid redistributing the traffic after every other response. It may be useful to precise here, which load balancing algorithms are considered deterministic. Deterministic algorithms will always select the same server for a given client data, assuming the set of available servers has not changed. In general, deterministic algorithms involve hashing or lookups on the incoming requests to choose the target server. However, this is not always the case; "static-rr", for example, can be also considered as deterministic because the server choice is based on the server's static weight, making the selection predictable. "sticky" algorithm provides deterministic routing for the returning clients. As for non-deterministic algorithms, these algorithms select a server based on dynamic server state or simple rotation, so two consecutive requests are not guaranteed to land on the same server. option prefer-last-server is designed specifically for these. roundrobin, leastconn are examples of such algorithms. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
启用或禁用在连接失败时会话重新分发 可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<interval> 可选的整数值,用于控制重试连接时重新分发的频率。正值 P 表示希望在每第 P 次重试时进行重新分发,负值 N 表示希望在最后一次重试前的第 N 次重试时进行重新分发。例如,默认值 -1 保留了在最后一次重试时重新分发的历史行为,正值 1 表示每次重试都重新分发,正值 3 表示每三次重试重新分发一次。您可以使用值 0 禁用重新分发。
In HTTP mode, if a server designated by a cookie is down, clients may definitely stick to it, for example when using "option persist" or "force-persist", because they cannot flush the cookie, so they will not be able to access the service anymore. Specifying "option redispatch" will allow the proxy to break cookie or consistent hash based persistence and redistribute them to a working server. Active servers are selected from a subset of the list of available servers. Active servers that are not down or in maintenance (i.e., whose health is not checked or that have been checked as "up"), are selected in the following order: 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. When a retry occurs, HAProxy tries to select another server than the last one. The new server is selected from the current list of servers. Sometimes, if the list is updated between retries (e.g., if numerous retries occur and last longer than the time needed to check that a server is down, remove it from the list and fall back on the list of backup servers), connections may be redirected to a backup server, though. It also allows to retry connections to another server in case of multiple connection failures. Of course, it requires having "retries" set to a nonzero value. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
使用 redis 健康检查来测试服务器 可在以下上下文中使用:tcp

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
可以测试服务器是否正确地使用 REDIS 协议通信,而不仅仅是测试它是否接受 TCP 连接。设置此选项后,会向服务器发送一个 PING redis 命令,并分析响应以查找 "+PONG" 响应消息。
Example
option redis-check
option smtpchk <hello> <domain>
使用 SMTP 健康检查来测试服务器 可在以下上下文中使用:tcp

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<hello> 是一个可选参数。它是要使用的“hello”命令。它可以是“HELO”(用于 SMTP)或“EHLO”(用于 ESMTP)。所有其他值都将转换为默认命令(“HELO”)。<domain> 是要呈现给服务器的域名。只有在指定了 hello 命令时才能指定(并且是强制性的)。默认情况下,使用“localhost”。
When "option smtpchk" is set, the health checks will consist in TCP connections followed by an SMTP command. By default, this command is "HELO localhost". The server's return code is analyzed and only return codes starting with a "2" will be considered as valid. All other responses, including a lack of response will constitute an error and will indicate a dead server. This test is meant to be used with SMTP servers or relays. Depending on the request, it is possible that some servers do not log each connection attempt, so you may want to experiment to improve the behavior. Using telnet on port 25 is often easier than adjusting the configuration. Most often, an incoming SMTP server needs to see the client's IP address for various purposes, including spam filtering, anti-spoofing and logging. When possible, it is often wise to masquerade the client's IP address when connecting to the server using the "usesrc" argument of the "source" keyword, which requires the transparent proxy feature to be compiled in.
Example
option smtpchk HELO mydomain.org
启用或禁用为每个套接字收集并提供单独的统计信息。 可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
启用或禁用双向套接字上的自动内核加速 可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
When this option is enabled either on a frontend or on a backend, HAProxy will automatically evaluate the opportunity to use kernel tcp splicing to forward data between the client and the server, in either direction. HAProxy uses heuristics to estimate if kernel splicing might improve performance or not. Both directions are handled independently. Note that the heuristics used are not much aggressive in order to limit excessive use of splicing. This option requires splicing to be enabled at compile time, and may be globally disabled with the global option "nosplice". Since splice uses pipes, using it requires that there are enough spare pipes. Important note: kernel-based TCP splicing is a Linux-specific feature which first appeared in kernel 2.6.25. It offers kernel-based acceleration to transfer data between sockets without copying these data to user-space, thus providing noticeable performance gains and CPU cycles savings. Since many early implementations are buggy, corrupt data and/or are inefficient, this feature is not enabled by default, and it should be used with extreme care. While it is not possible to detect the correctness of an implementation, 2.6.29 is the first version offering a properly working implementation. In case of doubt, splicing may be globally disabled using the global "nosplice" keyword.
Example
option splice-auto
如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
启用或禁用请求套接字上的自动内核加速 可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
当此选项在前端或后端启用时,HAProxy 将尽可能使用内核 TCP 拼接来转发从客户端到服务器的数据。如果备用管道不足,它可能仍会使用 recv/send 方案。此选项需要在编译时启用拼接,并且可以通过全局选项“nosplice”全局禁用。由于 splice 使用管道,因此使用它需要有足够的备用管道。重要说明:有关使用限制,请参阅“option splice-auto”。
Example
option splice-request
如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
启用或禁用响应套接字上的自动内核加速 可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
当此选项在前端或后端启用时,HAProxy 将尽可能使用内核 TCP 拼接来转发从服务器到客户端的数据。如果备用管道不足,它可能仍会使用 recv/send 方案。此选项需要在编译时启用拼接,并且可以通过全局选项“nosplice”全局禁用。由于 splice 使用管道,因此使用它需要有足够的备用管道。重要说明:有关使用限制,请参阅“option splice-auto”。
Example
option splice-response
如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
使用 SPOP 健康检查来测试服务器 可在以下上下文中使用:tcp

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
可以测试服务器是否正确地使用 SPOP 协议进行通信,而不仅仅是测试它是否接受 TCP 连接。设置此选项后,HAProxy 和服务器之间会执行 HELLO 握手,并分析响应以检查是否报告了错误。
Example
option spop-check
启用或禁用在服务器端发送 TCP keepalive 数据包 可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
When there is a firewall or any session-aware component between a client and a server, and when the protocol involves very long sessions with long idle periods (e.g. remote desktops), there is a risk that one of the intermediate components decides to expire a session which has remained idle for too long. Enabling socket-level TCP keep-alives makes the system regularly send packets to the other end of the connection, leaving it active. The delay between keep-alive probes is controlled by the system only and depends both on the operating system and its tuning parameters. It is important to understand that keep-alive packets are neither emitted nor received at the application level. It is only the network stacks which sees them. For this reason, even if one side of the proxy already uses keep-alives to maintain its connection alive, those keep-alive packets will not be forwarded to the other side of the proxy. Please note that this has nothing to do with HTTP keep-alive. Using option "srvtcpka" enables the emission of TCP keep-alive probes on the server side of a connection, which should help when session expirations are noticed between HAProxy and a server. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
使用 SSLv3 客户端 hello 健康检查来测试服务器 可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
当某些基于 SSL 的协议在 TCP 模式下通过 HAProxy 中继时,可以测试服务器是否正确地使用 SSL 协议,而不仅仅是测试它是否接受 TCP 连接。当设置了“option ssl-hello-chk”时,一旦与服务器建立连接,就会发送纯 SSLv3 客户端 hello 消息,并分析响应以查找 SSL 服务器 hello 消息。只有当响应包含此服务器 hello 消息时,服务器才被认为是有效的。所有测试过的服务器都正确地回复了 SSLv3 客户端 hello 消息,并且大多数测试过的服务器甚至不记录仅包含 hello 消息的请求,这是值得赞赏的。请注意,即使 HAProxy 中没有内置 SSL 支持,此检查也能工作,因为它会伪造 SSL 消息。当 SSL 支持可用时,最好使用原生的 SSL 健康检查而不是这个。
使用 tcp-check 发送/期望序列执行健康检查 可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
This health check method is intended to be combined with "tcp-check" command lists in order to support send/expect types of health check sequences. TCP checks currently support 4 modes of operations : - no "tcp-check" directive : the health check only consists in a connection attempt, which remains the default mode. - "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. A fifth mode can be used to insert comments in different steps of the script. For each tcp-check rule you create, you can add a "comment" directive, followed by a string. This string will be reported in the log and stderr in debug mode. It is useful to make user-friendly error reporting. The "comment" is of course optional. During the execution of a health check, a variable scope is made available to store data samples, using the "tcp-check set-var" operation. Freeing those variable is possible using "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
启用或禁用在接受序列中节省一个 ACK 数据包 可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
When an HTTP connection request comes in, the system acknowledges it on behalf of HAProxy, then the client immediately sends its request, and the system acknowledges it too while it is notifying HAProxy about the new connection. HAProxy then reads the request and responds. This means that we have one TCP ACK sent by the system for nothing, because the request could very well be acknowledged by HAProxy when it sends its response. For this reason, in HTTP mode, HAProxy automatically asks the system to avoid sending this useless ACK on platforms which support it (currently at least Linux). It must not cause any problem, because the system will send it anyway after 40 ms if the response takes more time than expected to come. During complex network debugging sessions, it may be desirable to disable this optimization because delayed ACKs can make troubleshooting more complex when trying to identify where packets are delayed. It is then possible to fall back to normal behavior by specifying "no option tcp-smart-accept". It is also possible to force it for non-HTTP proxies by simply specifying "option tcp-smart-accept". For instance, it can make sense with some services such as SMTP where the server speaks first. It is recommended to avoid forcing this option in a defaults section. In case of doubt, consider setting it back to automatic values by prepending the "default" keyword before it, or disabling it using the "no" keyword.
启用或禁用在连接序列中节省一个 ACK 数据包 可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
在某些系统(至少是 Linux)上,HAProxy 可以请求内核在收到连接请求时不立即发送一个空的 ACK,而是直接发送带有数据的请求。这可以在网络上节省一个数据包,从而提高性能。这对某些服务器也很有用,因为它们可以立即随传入连接一起获取请求。当在后端设置了 "option tcp-smart-connect" 时,此功能被启用。默认情况下不启用,因为它会使网络故障排除变得更加复杂。只在客户端先说话的协议(如 HTTP)中启用它才有意义。在其他情况下,如果没有数据可以代替 ACK 发送,则会发送一个正常的 ACK。如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字来在特定实例中禁用它。
启用或禁用在两端发送 TCP keepalive 数据包 可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
When there is a firewall or any session-aware component between a client and a server, and when the protocol involves very long sessions with long idle periods (e.g. remote desktops), there is a risk that one of the intermediate components decides to expire a session which has remained idle for too long. Enabling socket-level TCP keep-alives makes the system regularly send packets to the other end of the connection, leaving it active. The delay between keep-alive probes is controlled by the system only and depends both on the operating system and its tuning parameters. It is important to understand that keep-alive packets are neither emitted nor received at the application level. It is only the network stacks which sees them. For this reason, even if one side of the proxy already uses keep-alives to maintain its connection alive, those keep-alive packets will not be forwarded to the other side of the proxy. Please note that this has nothing to do with HTTP keep-alive. Using option "tcpka" enables the emission of TCP keep-alive probes on both the client and server sides of a connection. Note that this is meaningful only in "defaults" or "listen" sections. If this option is used in a frontend, only the client side will get keep-alives, and if this option is used in a backend, only the server side will get keep-alives. For this reason, it is strongly recommended to explicitly use "option clitcpka" and "option srvtcpka" when the configuration is split between frontends and backends.
启用 TCP 连接的高级日志记录,包含流状态和计时器 可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
clf 如果添加了 "clf" 参数,那么输出格式将是 CLF 格式,而不是 HAProxy 的默认 TCP 格式。当您需要将 HAProxy 的日志输入到仅支持 CLF 格式且不可扩展的特定日志分析器时,可以使用此选项。由于这需要 HTTP 格式,因此某些值已被预设。HTTP 请求将显示为 TCP,响应代码将显示为 000。
默认情况下,日志输出格式非常简单,只包含源地址和目标地址以及实例名称。通过指定 "option tcplog",每条日志行都会变成一种更丰富的格式,包括但不限于连接计时器、流状态、连接数、前端、后端和服务器名称,当然还有源地址和端口。此选项对于纯 TCP 代理非常有用,可以找出客户端或服务器是哪一方断开连接或超时。对于普通的 HTTP 代理,最好使用 "option httplog",它甚至更完整。 "option tcplog" 会覆盖任何先前的 "log-format" 指令。
option transparent (deprecated)
启用客户端透明代理 可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
This option was introduced in order to provide layer 7 persistence to layer 3 load balancers. The idea is to use the OS's ability to redirect an incoming connection for a remote address to a local process (here HAProxy), and let this process know what address was initially requested. When this option is used, sessions without cookies will be forwarded to the original destination IP address of the incoming request (which should match that of another equipment), while requests with cookies will still be forwarded to the appropriate server. Note that contrary to a common belief, this option does NOT make HAProxy present the client's IP to the server when establishing the connection. As of 3.3, this option is now deprecated because it used to suffer from a number of internal technical limitations. Using it will emit a warning, which can be avoided if really needed via the "expose-deprecated-directives" global keyword. The correct approach is to declare a server on address 0.0.0.0, which will take care of connecting to the expected destination address. A server will also properly handle idle connections to the target servers.
示例
# option transparent ## before 3.3 server transparent 0.0.0.0
执行外部检查时要运行的可执行文件 可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<command> 是要运行的外部命令
The arguments passed to the to the command are: <proxy_address> <proxy_port> <server_address> <server_port> The <proxy_address> and <proxy_port> are derived from the first listener that is either IPv4, IPv6 or a UNIX socket. In the case of a UNIX socket listener the proxy_address will be the path of the socket and the <proxy_port> will be the string "NOT_USED". In a backend section, it's not possible to determine a listener, and both <proxy_address> and <proxy_port> will have the string value "NOT_USED". Some values are also provided through environment variables. Environment variables : 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". If the command executed and exits with a zero status then the check is considered to have passed, otherwise the check is considered to have failed.
Example
external-check command /bin/true
运行外部检查时使用的 PATH 环境变量的值 可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<path> 是执行外部命令时使用的路径
默认路径为 ""。
Example
external-check path "/usr/bin:/bin"
启用基于 RDP cookie 的持久性 可在以下上下文中使用:tcp

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<name> 是要检查的可选 RDP cookie 的名称。如果省略,将使用默认的 cookie 名称 "msts"。目前没有更改此名称的有效理由。
此语句启用基于 RDP cookie 的持久性。RDP cookie 包含在已知服务器列表中找到服务器所需的所有信息。因此,当在后端中设置此选项时,将分析请求,如果找到 RDP cookie,则会对其进行解码。如果它与仍然 UP 的已知服务器匹配(或者如果设置了 "option persist"),则连接将被转发到此服务器。请注意,这仅在 TCP 后端中有意义,但要使其工作,前端必须等待足够长的时间以确保 RDP cookie 存在于请求缓冲区中。这与 "rdp-cookie" 负载均衡方法的要求相同。因此,强烈建议将所有语句放在一个 "listen" 部分中。此外,重要的是要理解,终端服务器只有在配置为 "令牌重定向模式" 时才会发出此 RDP cookie,这意味着 "IP 地址重定向" 选项被禁用。
Example
listen tse-farm bind :3389 # 在请求中等待 RDP cookie 最多 5 秒 tcp-request inspect-delay 5s tcp-request content accept if RDP_COOKIE # 应用 RDP cookie 持久性 persist rdp-cookie # 如果服务器未知,让我们在相同的 cookie 上进行负载均衡。 # 或者,"balance leastconn" 也可能有用。 balance rdp-cookie server srv1 1.1.1.1:3389 server srv2 1.1.1.2:3389
quic-initial <action> [ { if | unless } <condition> ]
对传入的 QUIC 初始数据包执行操作。与 "tcp-request connection" 不同,此操作在任何连接元素实例化、SSL 握手开始和完成之前执行,这在希望拒绝连接尝试时更有效。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend
是(!)
yes(!)

yes

yes

no
参数
<action> 定义了在条件适用时要执行的操作。见下文。<condition> 是一个标准的仅限第 4 层的基于 ACL 的条件(见第 7 节)。然而,QUIC 初始规则执行得太早,即使对于某些第 4 层的样本提取方法也是如此,尽管没有配置警告,但可能会导致未指定的运行时行为,虽然它们不会崩溃。请考虑目前仅支持内部样本和第 4 层的 "src*" 和 "dst*"。
此操作在 QUIC 数据包解析的早期执行。因此,只支持最少的操作列表: - accept - dgram-drop - reject - send-retry
设置前端每秒接受的新会话数限制 可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<rate> <rate> 参数是一个整数,指定前端每秒接受的最大新会话数。
When the frontend reaches the specified number of new sessions per second, it stops accepting new connections until the rate drops below the limit again. During this time, the pending sessions will be kept in the socket's backlog (in system buffers) and HAProxy will not even be aware that sessions are pending. When applying very low limit on a highly loaded service, it may make sense to increase the socket's backlog using the "backlog" keyword. This feature is particularly efficient at blocking connection-based attacks or service abuse on fragile servers. Since the session rate is measured every millisecond, it is extremely accurate. Also, the limit applies immediately, no delay is needed at all to detect the threshold.
Example
将 SMTP 的连接速率限制为最大每秒 10 个
listen smtp mode tcp bind :25 rate-limit sessions 10 server smtp1 127.0.0.1:1025
注意:当达到最大速率时,前端的状态不会改变,但如果启用了 "socket-stats" 选项,其套接字在统计信息中将显示为 "WAITING"。
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

可用于部分

defaultsfrontendlistenbackend

no

yes

yes

yes
如果/除非条件匹配,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 }
示例
仅将旧 URL 永久重定向到新 URL
http-request redirect code 301 location \ %[path,map_str(old-blog-articles.map)] ignore-empty
有关 ACL 的用法,请参见第 7 节
retries <value>
设置在服务器失败后对其执行的重试次数 可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<value> 是在服务器失败后,请求或连接尝试应重试的次数。
By default, retries apply only to new connection attempts. However, when the "retry-on" directive is used, other conditions might trigger a retry (e.g. empty response, undesired status code), and each of them will count one attempt, and when the total number attempts reaches the value here, an error will be returned. In order to avoid immediate reconnections to a server which is restarting, a turn-around timer of min("timeout connect", one second) is applied before a retry occurs on the same server. When "option redispatch" is set, some retries may be performed on another server even if a cookie references a different server. By default this will only be the last retry unless an argument is passed to "option redispatch".
retry-on [以空格分隔的关键字列表]
指定何时尝试自动重试失败的请求。此设置仅在 "mode" 设置为 http 时有效,否则将被静默忽略。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

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".
Using this directive replaces any previous settings with the new ones; it is not cumulative. Please note that using anything other than "none" and "conn-failure" requires to allocate a buffer and copy the whole request into it, so it has memory and performance impacts. Requests not fitting in a single buffer will never be retried (see the global tune.bufsize setting). You have to make sure the application has a replay protection mechanism built in such as a unique transaction IDs passed in requests, or that replaying the same request has no consequence, or it is very dangerous to use any retry-on value beside "conn-failure" and "none". Static file servers and caches are generally considered safe against any type of retry. Using a status code can be useful to quickly leave a server showing an abnormal behavior (out of memory, file system issues, etc), but in this case it may be a good idea to immediately redispatch the connection to another server (please see "option redispatch" for this). Last, it is important to understand that most causes of failures are the requests themselves and that retrying a request causing a server to misbehave will often make the situation even worse for this server, or for the whole service in case of redispatch. Unless you know exactly how the application deals with replayed requests, you should not use this directive. The default is "conn-failure".
示例
retry-on 503 504
server <name> <address>[:[port]] [param*]
在后端声明一个服务器 可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

no

no

yes

yes
参数
<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. - '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 中向任何抽象套接字定义传递选项 “,unix-tightsocklen=0” 以使其与 HAProxy 兼容,或者改用 “abnsz” HAProxy 套接字族。
server-state-file-name [ { use-backend-name | <file> } ]
设置要读取、加载并应用于此后端中可用服务器的服务器状态文件。可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

no

no

yes

yes
它仅在指令 "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-template <prefix> <num | range> <fqdn>[:<port>] [params*]
设置一个模板来初始化具有共享参数的服务器。这些服务器的名称由 <prefix> 和 <num | range> 参数构建。可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

no

no

yes

yes
参数
<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.
示例
# 初始化 3 个服务器,名称分别为 srv1、srv2 和 srv3, # FQDN 为 google.com,并启用了健康检查。 server-template srv 1-3 google.com:80 check # 或 server-template srv 3 google.com:80 check # 将等同于: 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>] | hdr_ip(<hdr>[,<occ>]) } ]
source <addr>[:<port>] [interface <name>]
设置出站连接的源地址 可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<addr> 是 HAProxy 在连接到服务器之前将绑定的 IPv4 地址。此地址也用作健康检查的源地址。默认值 0.0.0.0 意味着系统将选择最合适的地址来到达目的地。可以选择在地址之前使用地址族前缀来强制指定地址族,而不管地址格式如何,这对于指定没有斜杠 ('/') 的 unix socket 路径非常有用。目前支持的前缀有: - 'ipv4@' -> 地址始终为 IPv4 - 'ipv6@' -> 地址始终为 IPv6 - 'unix@' -> 地址是本地 unix socket 的路径 - 'abns@' -> 地址位于抽象命名空间中(仅限 Linux) - 'abnsz@' -> 地址位于零终止抽象命名空间中(仅限 Linux) 您可能希望在 address 参数中引用一些环境变量,请参阅关于环境变量的第 2.3 节。 <port> 是一个可选端口。通常不需要,但在某些非常特定的上下文中可能有用。默认值零表示系统将选择一个空闲端口。请注意,后端不支持端口范围。如果您想强制使用端口范围,则必须在每行 "server" 中指定它们。 <addr2> 是在全透明代理模式下转发连接时向服务器显示的 IP 地址。目前仅在某些打了补丁的 Linux 内核上支持此功能。当指定此地址时,连接到服务器的客户端将显示此地址,而健康检查仍将使用 <addr> 地址。 <port2> 是在全透明代理模式下转发连接时向服务器显示的可选端口(请参见上面的 <addr2>)。默认值零表示系统将选择一个空闲端口。 <hdr> 是用于获取要绑定的 IP 地址的 HTTP 标头名称。这是一个逗号分隔的标头列表的名称,其中可以包含多个 IP 地址。默认情况下,使用最后一次出现的值。这旨在与 X-Forwarded-For 标头配合使用,并自动绑定到上一个代理(通常是 Stunnel)看到的客户端 IP 地址。要使用最后一次出现以外的其他值,请参阅下面的 <occ> 参数。当未找到标头(或出现次数)时,不执行绑定,因此使用代理的默认 IP 地址。另请记住,与任何 HTTP 标头一样,标头名称不区分大小写。 <occ> 是用于多值标头中要使用的值的出现次数。这与 "hdr_ip(<hdr>)" 结合使用,用于指定源 IP 地址使用哪个出现次数。正值表示从第一次出现开始的位置,1 为第一次。负值表示相对于最后一次出现的位置,-1 为最后一次。这对于 X-Forwarded-For 标头在基础架构入口点设置且必须在多个代理层之外使用的情况很有帮助。如果未指定此值,则假定为 -1。在此处传递零会禁用此功能。 <name> 是用于出站流量绑定的可选接口名称。在支持此功能的系统上(目前仅限 Linux),即使系统根据路由表不会选择此接口,它也允许将所有流量绑定到此服务器。应极其谨慎地使用此功能。请注意,使用此选项需要 root 权限。
在复杂的环境中,"source" 关键字非常有用,其中只允许特定地址连接到服务器。例如,当必须通过公共网关使用私有地址,并且已知系统无法自行确定适当的源地址时,可能需要此功能。可以使用 "usesrc" 可选关键字使用在某些打了补丁的 Linux 内核上可用的扩展。它使得可以使用不属于系统本身的 IP 地址连接到服务器。这称为“全透明代理模式”。为此,目标服务器必须通过运行 HAProxy 的机器将流量路由回此地址,并且通常必须在此机器上启用 IP 转发。在此“全透明代理”模式下,可以强制向服务器显示特定 IP 地址。实际上,这并不常用。更常见的用途是告诉 HAProxy 显示客户端的 IP 地址。为此,有两种方法: - 显示客户端的 IP 和端口地址。这是最透明的模式,但当机器上启用了 IP 连接跟踪时,可能会导致问题,因为同一个连接可能会以不同的状态看到两次。然而,此解决方案的巨大优势在于不限制系统使用 64k 个出站地址+端口对,因为可以使用所有客户端范围。 - 仅显示客户端的 IP 地址并选择一个空闲端口。此解决方案仍然相当优雅,但透明度稍低(下游防火墙日志将与上游不匹配)。它的缺点是将并发连接数限制为通常的 64k 端口。然而,由于上游和下游端口不同,机器上的本地 IP 连接跟踪不会因重用同一会话而受到干扰。此选项设置后端中所有服务器的默认源地址。它也可以在 "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)
srvtcpka-cnt <count>
设置 TCP 在服务器端断开连接之前应发送的最大 keepalive 探测次数。可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<count> 是 keepalive 探测的最大次数。
此关键字对应于套接字选项 TCP_KEEPCNT。如果未指定此关键字,则使用系统范围的 TCP 参数 (tcp_keepalive_probes)。此设置的可用性取决于操作系统。已知在 Linux 上可以工作。
srvtcpka-idle <timeout>
设置连接需要保持空闲多长时间后,TCP 开始发送 keepalive 探测(如果在服务器端启用了 TCP keepalive 数据包的发送)。可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<timeout> 是连接需要保持空闲的时间,之后 TCP 开始发送 keepalive 探测。默认以秒为单位指定,但如果数字后跟单位后缀,也可以是任何其他单位,如本文档开头所述。
此关键字对应于套接字选项 TCP_KEEPIDLE。如果未指定此关键字,则使用系统范围的 TCP 参数 (tcp_keepalive_time)。此设置的可用性取决于操作系统。已知在 Linux 上可以工作。
srvtcpka-intvl <timeout>
设置服务器端各个 keepalive 探测之间的时间。可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<timeout> 是各个 keepalive 探测之间的时间。默认以秒为单位指定,但如果数字后跟单位后缀,也可以是任何其他单位,如本文档开头所述。
此关键字对应于套接字选项 TCP_KEEPINTVL。如果未指定此关键字,则使用系统范围的 TCP 参数 (tcp_keepalive_intvl)。此设置的可用性取决于操作系统。已知在 Linux 上可以工作。
stats admin { if | unless } <cond>
如果/除非条件匹配,则启用统计信息管理级别 可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

no

yes

yes

yes
此语句如果/除非条件匹配,则启用统计信息管理级别。管理级别允许从 Web 界面启用/禁用服务器。出于安全原因,默认情况下统计信息页面是只读的。目前,POST 请求受限于缓冲区大小减去保留的缓冲区空间,这意味着如果服务器列表太长,请求将不会被处理。建议一次只更改少量服务器。
Example
# 仅对 localhost 启用统计信息管理级别 backend stats_localhost stats enable stats admin if LOCALHOST
Example
# 由于身份验证,统计信息管理级别始终启用 backend stats_auth stats enable stats auth admin:AdMiN123 stats admin if TRUE
Example
# 统计信息管理级别取决于经过身份验证的用户 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
ssl-f-use [<sslbindconf> ...]*
将证书分配给当前前端。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

no

yes

yes

no
参数
<sslbindconf> 支持来自 bind 行的以下关键字(请参阅第 5.1 节。绑定选项): - 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 还支持来自 crt-store load 关键字的以下关键字(请参阅第 12.7.1 节。加载选项): - crt - key - ocsp - issuer - sctl - ocsp-update
将证书 <crtname> 分配给一个自动创建的 crt-list,该列表以前端名称并以 @ 为前缀(例如:'@frontend1')。这个隐式的 crt-list 将被分配给当前前端中所有 "ssl" 绑定行。来自 stats 套接字的 crt-list 命令对这个 crt-list 有效,因此可以替换、删除或向其添加证书和 SSL 选项。
Example
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
stats auth <user>:<passwd>
启用带身份验证的统计信息并授予帐户访问权限 可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<user> 是要授予访问权限的用户名 <passwd> 是与此用户关联的明文密码
此语句启用具有默认设置的统计信息,并仅限制对声明用户的访问。可以根据需要重复多次以允许尽可能多的用户。当用户尝试访问统计信息而没有有效帐户时,将返回“401 Forbidden”响应,以便浏览器要求用户提供有效的用户和密码。返回给浏览器的 realm 可使用 "stats realm" 进行配置。由于身份验证方法是 HTTP Basic Authentication,密码在网络上以明文形式传输。因此,决定配置中也使用明文密码,以提醒用户这些密码不应是敏感的,也不应与其他帐户共享。还可以使用 "stats scope" 缩小报告中显示的代理范围。尽管此语句本身足以启用统计信息报告,但建议设置所有其他设置,以避免依赖默认的、不明显的参数。
Example
# 公共访问(仅限于此后端) 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 # 内部监控访问(无限制) backend private_monitoring stats enable stats uri /admin?stats stats refresh 5s
使用默认设置启用统计信息报告 可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
此语句使用构建时定义的默认设置启用统计报告。除非另有说明,否则将使用以下设置:- stats uri : /haproxy?stats - stats realm : "HAProxy Statistics" - stats auth : 无身份验证 - stats scope : 无限制 尽管此语句本身足以启用统计报告,但建议设置所有其他设置,以避免依赖默认的不明显参数。
Example
# 公共访问(仅限于此后端) 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 # 内部监控访问(无限制) backend private_monitoring stats enable stats uri /admin?stats stats refresh 5s
启用统计信息并隐藏 HAProxy 版本报告 可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
默认情况下,统计页面会报告一些有用的状态信息以及统计数据。其中包括 HAProxy 的版本。但是,通常认为向任何人报告精确的版本是危险的,因为它可能帮助他们利用已知弱点进行特定攻击。“stats hide-version”语句从统计报告中移除版本信息。建议对公共站点或任何具有弱登录名/密码的站点使用此功能。尽管此语句本身足以启用统计报告,但建议设置所有其他设置,以避免依赖默认的不明显参数。
Example
# 公共访问(仅限于此后端) 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 # 内部监控访问(无限制) backend private_monitoring stats enable stats uri /admin?stats stats refresh 5s
stats http-request { allow | deny | auth [realm <realm>] } [ { if | unless } <condition> ]
统计信息访问控制 可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

no

no

yes

yes
与 "http-request" 类似,这组选项允许精细控制对统计信息的访问。每个选项后面都可以跟 if/unless 和 acl。第一个匹配条件的选项(或没有条件的选项)是最终的。对于 "deny",将返回 403 错误;对于 "allow",将执行正常处理;对于 "auth",将返回 401/407 错误代码,以便要求客户端输入用户名和密码。每个实例的 http-request 语句数量没有固定限制。
stats realm <realm>
启用统计信息并设置身份验证领域 可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<realm> 是报告给浏览器的 HTTP 基本认证领域的名称。浏览器用它在弹出窗口中显示,邀请用户输入有效的用户名和密码。
领域被读取为单个词,因此其中的任何空格都应使用反斜杠('\')进行转义。此语句仅在与“stats auth”结合使用时才有用,因为它只与身份验证相关。尽管此语句本身足以启用统计报告,但建议设置所有其他设置,以避免依赖默认的不明显参数。
Example
# 公共访问(仅限于此后端) 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 # 内部监控访问(无限制) backend private_monitoring stats enable stats uri /admin?stats stats refresh 5s
启用带自动刷新的统计信息 可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<delay> 是建议的刷新延迟,以秒为单位指定,它将返回给查看报告页面的浏览器。虽然浏览器可以自由应用任何延迟,但通常会遵守它并每隔这么多秒刷新一次页面。刷新间隔可以用任何其他非默认的时间单位指定,方法是在值后面加上单位后缀,如本文档开头所述。
此语句在具有永久报告负载均衡器活动的监控显示器上很有用。设置后,HTML 报告页面将包含一个“刷新”/“停止刷新”链接,以便用户可以选择是否希望页面自动刷新。尽管仅此语句就足以启用统计信息报告,但建议设置所有其他设置,以避免依赖默认的不明显参数。
Example
# 公共访问(仅限于此后端) 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 # 内部监控访问(无限制) backend private_monitoring stats enable stats uri /admin?stats stats refresh 5s
stats scope { <name> | "." }
启用统计信息并限制访问范围 可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<name> 是要报告的 listen、frontend 或 backend 部分的名称。特殊名称“.”(一个点)表示该语句所在的节。
指定此语句后,只有使用此语句枚举的部分才会出现在报告中。所有其他部分都将被隐藏。如果需要报告多个部分,此语句可以根据需要出现多次。请注意,名称检查是作为简单的字符串比较执行的,并且从不检查给定的部分名称是否真的存在。尽管此语句本身足以启用统计报告,但建议设置所有其他设置,以避免依赖默认的不明显参数。
Example
# 公共访问(仅限于此后端) 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 # 内部监控访问(无限制) backend private_monitoring stats enable stats uri /admin?stats stats refresh 5s
stats show-desc [ <desc> ]
在统计信息页面上启用描述报告。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
<desc> 是一个可选的要报告的描述。如果未指定,则自动使用全局部分的描述。此语句对于向客户提供共享服务的用户非常有用,其中每个客户的节点或描述应该不同。尽管此语句本身足以启用统计报告,但建议设置所有其他设置,以避免依赖默认的不明显参数。默认情况下不显示描述。
Example
# 内部监控访问(无限制) backend private_monitoring stats enable stats show-desc Master node for Europe, Asia, Africa stats uri /admin?stats stats refresh 5s
在统计信息页面上启用报告附加信息 可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
在统计信息页面上启用报告附加信息: - cap: 功能(代理) - mode: tcp, http 或 health 之一(代理) - id: SNMP ID(代理、套接字、服务器) - IP(套接字、服务器) - cookie(后端、服务器) 尽管仅此语句就足以启用统计信息报告,但建议设置所有其他设置,以避免依赖默认的不明显参数。默认行为是不显示此信息。
启用在统计页面上显示额外的统计模块。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
新的列会以工具提示的形式添加到包含额外统计值行的末尾。虽然仅此语句就足以启用统计报告,但建议设置所有其他设置,以避免依赖于默认的不明显参数。默认行为是不显示此信息。
stats show-node [ <name> ]
在统计页面上启用主机名报告。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<name> 是一个可选的要报告的名称。如果未指定,则自动使用全局部分的节点名称。
此语句对于向其客户提供共享服务的用户非常有用,在为每个客户提供的统计页面上,节点或描述可能会有所不同。默认行为是不显示主机名。虽然仅此语句就足以启用统计报告,但建议设置所有其他设置,以避免依赖于默认的不明显参数。
示例
# 内部监控访问(无限制) backend private_monitoring stats enable stats show-node Europe-1 stats uri /admin?stats stats refresh 5s
stats uri <prefix>
启用统计并定义用于访问它们的 URI 前缀。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<prefix> 是任何将被重定向到统计信息的 URI 的前缀。此前缀可能包含一个问号('?')以指示查询字符串的一部分。
统计信息 URI 在中继流量上被拦截,因此它在正常应用程序中显示为一个页面。强烈建议确保所选 URI 永远不会出现在应用程序中,否则将永远无法在应用程序中访问它。HAProxy 中编译的默认 URI 是 "/haproxy?stats",但这可以在构建时更改,因此最好始终在此处显式指定它。通常最好在 URI 中包含问号,以便中间代理避免缓存结果。此外,由于任何以该前缀开头的字符串都将被接受为统计信息请求,因此问号有助于确保没有有效的 URI 以相同的词开头。有时使用 "/" 作为 URI 前缀非常方便,并将其放在自己的 "listen" 实例中。这使得将地址或端口专用于统计信息变得容易。尽管此语句本身足以启用统计信息报告,但建议设置所有其他设置,以避免依赖默认的、不明显的参数。
Example
# 公共访问(仅限于此后端) 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 # 内部监控访问(无限制) backend private_monitoring stats enable stats uri /admin?stats stats refresh 5s
stick match <pattern> [table <table>] [{if | unless} <cond>]
定义一个请求模式匹配条件,以将用户粘滞(stick)到一台服务器。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

no

no

yes

yes
参数
<pattern> 是如第 7.3 节所述的采样表达式规则。它描述了将分析传入请求或连接的哪些元素,以期在粘性表中找到匹配的条目。此规则是强制性的。 <table> 是可选的粘性表名称。如果未指定,则使用同一后端的表。粘性表使用 "stick-table" 语句声明。 <cond> 是可选的匹配条件。它使得仅在满足(或不满足)其他条件时才匹配特定条件。例如,它可以用于匹配源 IP 地址,除非请求通过已知的代理,在这种情况下,我们将匹配包含该 IP 地址的标头。
某些协议或应用程序需要复杂的粘性规则,并且不能总是简单地依赖 cookie 或哈希。"stick match" 语句描述了一个规则,用于从传入请求或连接中提取粘性标准。有关可能的模式和转换规则的完整列表,请参阅第 7 节。该表必须使用 "stick-table" 语句声明。它的类型必须与模式兼容。默认情况下,它是在同一后端中存在的表。可以通过使用 "table" 关键字引用它来与其他后端共享表。如果引用了另一个表,则使用后端内部的服务器 ID。默认情况下,所有服务器 ID 在每个后端都从 1 开始,因此服务器顺序就足够了。但如有疑问,强烈建议使用其 "id" 设置强制指定服务器 ID。可以使用 "if" 或 "unless" 后跟条件来限制 "stick match" 语句适用的条件。有关基于 ACL 的条件,请参阅第 7 节。对 "stick match" 语句的数量没有限制。第一个匹配并匹配的请求将导致请求被定向到与创建条目的请求所使用的服务器相同的服务器。这样,可以使用多个匹配作为回退。粘性规则在持久性 cookie 之后检查,因此如果已使用 cookie 选择服务器,它们将不会影响粘性。这样,插入 cookie 和匹配 IP 地址以维护 HTTP 和 HTTPS 之间的粘性变得非常容易。
Example
# 将 SMTP 用户转发到他们在过去 30 分钟内 # 刚刚用于 POP 的同一台服务器 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 on <pattern> [table <table>] [{if | unless} <condition>]
定义一个请求模式,将用户与服务器关联。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

no

no

yes

yes
注意:此形式完全等同于后跟 "stick store-request" 的 "stick match",所有参数都相同。请参考这两个关键字以获取详细信息。它仅作为编写更易维护的配置的便利方式提供。
示例
# 以下形式... stick on src table pop if !localhost # ...与此形式完全等价: stick match src table pop if !localhost stick store-request src table pop if !localhost # 对 HTTP 使用 cookie 持久性,对 HTTPS 以及 # 没有 cookie 的 HTTP 使用源地址粘滞。在两种访问之间共享同一个表。 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 store-request <pattern> [table <table>] [{if | unless} <condition>]
定义一个请求模式,用于在粘滞表中创建一个条目。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

no

no

yes

yes
参数
<pattern> 是如第 7.3 节所述的采样表达式规则。它描述了选择服务器后将分析、提取并存储到表中的传入请求或连接的哪些元素。 <table> 是可选的粘性表名称。如果未指定,则使用同一后端的表。粘性表使用 "stick-table" 语句声明。 <cond> 是可选的存储条件。它使得仅在满足(或不满足)某些条件时才存储特定标准。例如,它可以用于存储源 IP 地址,除非请求通过已知的代理,在这种情况下,我们将存储包含该 IP 地址的标头的转换形式。
某些协议或应用程序需要复杂的粘性规则,并且不能总是简单地依赖 cookie 或哈希。"stick store-request" 语句描述了一个规则,用于决定从请求中提取什么以及何时提取,以便将其存储到粘性表中,供后续请求使用 "stick match" 语句进行匹配。显然,提取的部分必须有意义,并且有机会在后续请求中匹配。例如,存储客户端的 IP 地址通常有意义。存储在 URL 参数中找到的 ID 也有意义。存储源端口几乎永远没有意义,因为它会被随机匹配。有关可能的模式和转换规则的完整列表,请参阅第 7 节。该表必须使用 "stick-table" 语句声明。它的类型必须与模式兼容。默认情况下,它是在同一后端中存在的表。可以通过使用 "table" 关键字引用它来与其他后端共享表。如果引用了另一个表,则使用后端内部的服务器 ID。默认情况下,所有服务器 ID 在每个后端都从 1 开始,因此服务器顺序就足够了。但如有疑问,强烈建议使用其 "id" 设置强制指定服务器 ID。可以使用 "if" 或 "unless" 后跟条件来限制 "stick store-request" 语句适用的条件。此条件将在解析请求时进行评估,因此可以使用任何标准。有关基于 ACL 的条件,请参阅第 7 节。对 "stick store-request" 语句的数量没有限制,但每个请求或响应同时存储的限制为 8 个。这使得可以存储多达 8 个标准,所有这些标准都从请求或响应中提取,而不管规则的数量如何。只保留前 8 个匹配的标准。使用此功能,可以一次性填充多个表,以期增加在另一种协议或访问方法上识别用户的机会。使用多个具有相同表的 store-request 规则是可能的,并且可以通过按偏好降序排列规则来用于找到要依赖的最佳标准。对于给定的表,只会存储第一个提取的标准。所有后续引用同一表的 store-request 规则将被跳过,并且其 ACL 将不会被评估。一旦建立了服务器连接,就会评估 "store-request" 规则,以便表将包含处理请求的实际服务器。
Example
# 将 SMTP 用户转发到他们在过去 30 分钟内 # 刚刚用于 POP 的同一台服务器 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 store-response <pattern> [table <table>] [{if | unless} <condition>]
定义一个响应模式,用于在粘滞表中创建一个条目。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

no

no

yes

yes
参数
<pattern> 是如第 7.3 节所述的采样表达式规则。它描述了选择服务器后将分析、提取并存储到表中的响应或连接的哪些元素。 <table> 是可选的粘性表名称。如果未指定,则使用同一后端的表。粘性表使用 "stick-table" 语句声明。 <cond> 是可选的存储条件。它使得仅在满足(或不满足)某些条件时才存储特定标准。例如,它可以用于仅在响应是 SSL server hello 时才存储 SSL 会话 ID。
某些协议或应用程序需要复杂的粘性规则,并且不能总是简单地依赖 cookie 或哈希。"stick store-response" 语句描述了一个规则,用于决定从响应中提取什么以及何时提取,以便将其存储到粘性表中,供后续请求使用 "stick match" 语句进行匹配。显然,提取的部分必须有意义,并且有机会在后续请求中匹配。存储响应标头中找到的 ID 有意义。有关可能的模式和转换规则的完整列表,请参阅第 7 节。该表必须使用 "stick-table" 语句声明。它的类型必须与模式兼容。默认情况下,它是在同一后端中存在的表。可以通过使用 "table" 关键字引用它来与其他后端共享表。如果引用了另一个表,则使用后端内部的服务器 ID。默认情况下,所有服务器 ID 在每个后端都从 1 开始,因此服务器顺序就足够了。但如有疑问,强烈建议使用其 "id" 设置强制指定服务器 ID。可以使用 "if" 或 "unless" 后跟条件来限制 "stick store-response" 语句适用的条件。此条件将在解析响应时进行评估,因此可以使用任何标准。有关基于 ACL 的条件,请参阅第 7 节。对 "stick store-response" 语句的数量没有限制,但每个请求或响应同时存储的限制为 8 个。这使得可以存储多达 8 个标准,所有这些标准都从请求或响应中提取,而不管规则的数量如何。只保留前 8 个匹配的标准。使用此功能,可以一次性填充多个表,以期增加在另一种协议或访问方法上识别用户的机会。使用多个具有相同表的 store-response 规则是可能的,并且可以通过按偏好降序排列规则来用于找到要依赖的最佳标准。对于给定的表,只会存储第一个提取的标准。所有后续引用同一表的 store-response 规则将被跳过,并且其 ACL 将不会被评估。然而,即使 store-request 规则引用一个表,store-response 规则也可以使用同一个表。这意味着每个表可以一次性从请求中学习一个元素,从响应中学习一个元素。表将包含处理请求的实际服务器。
Example
# 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 type <类型> size <大小> [expire <过期时间>] [参数...]
为当前部分配置粘滞表。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

no

yes

yes

yes
这用于声明和配置一个 stick-table。有关完整的详细信息和支持的参数列表,请参阅第 11.1 节。只有类型和大小是强制性的。
tcp-check comment <字符串>
为以下 tcp-check 规则定义一个注释,如果失败,将在日志中报告。可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<字符串> 是如果以下 tcp-check 规则失败时要在日志中添加的注释消息。
它仅适用于 connect、send 和 expect 规则。这对于进行用户友好的错误报告很有用。
tcp-check connect [default] [port <表达式>] [addr <ip>] [send-proxy] [via-socks4] [ssl] [sni <sni>] [alpn <alpn>] [linger] [proto <名称>] [comment <消息>]
打开一个新连接。可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
comment <msg> 定义如果规则评估失败要报告的消息。 default 使用服务器行的默认选项进行健康检查。仅当未重新定义时才使用服务器选项。 port <expr> 如果未设置,则使用检查端口或服务器端口。它告诉 HAProxy 连接到哪里。<port> 必须是有效的 TCP 端口整数,从 1 到 65535,或者是采样获取表达式。 addr <ip> 定义进行健康检查的 IP 地址。 send-proxy 通过 PROXY 协议发送字符串 via-socks4 启用使用上游 socks4 代理的出站健康检查。 ssl 打开加密连接 sni <sni> 指定用于 SSL 健康检查的 SNI。 alpn <alpn> 定义要使用 ALPN 宣传的协议。协议列表由逗号分隔的协议名称列表组成,例如:"http/1.1,http/1.0"(不带引号)。如果未设置,则使用服务器 ALPN。 proto <name> 强制使用此连接的多路复用器协议。它必须是 TCP mux 协议,并且必须可以在后端使用。可用协议列表在 haproxy -vv 中报告。 linger 干净地关闭连接,而不是使用单个 RST。
当一个应用程序依赖于多个 TCP 端口,或者当 HAProxy 在一个后端中对许多服务进行负载均衡时,有必要在将服务器视为可运行之前单独探测所有服务。当服务器行上既没有配置 TCP 端口也没有 server port 指令时,那么 'tcp-check connect port <端口>' 必须是序列的第一步。在 tcp-check 规则集中,'connect' 是必需的,并且也必须用 'connect' 规则来开始规则集。目的是确保管理员知道他们在做什么。当一个 connect 必须开始规则集时,它前面仍然可以有 set-var、unset-var 或 comment 规则。
示例
# 检查服务器上的 HTTP 和 HTTPs 服务。 # 首先由于服务器行端口指令打开端口 80,然后 # tcp-check 打开端口 443,加密并在其上运行请求: 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 # 从单个服务器检查 POP 和 IMAP: 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
tcp-check expect [min-recv <整数>] [comment <消息>] [ok-status <状态>] [error-status <状态>] [tout-status <状态>] [on-success <格式>] [on-error <格式>] [status-code <表达式>] [!] <匹配> <模式>
指定在通用健康检查期间要收集和分析的数据。可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
comment <msg> 定义如果规则评估失败要报告的消息。 min-recv 是可选的,可以定义评估当前 expect 规则所需的最小数据量。如果接收到的字节数低于此限制,则检查将等待更多数据。此选项可用于解决一些模糊的匹配规则,或避免对已知仍不完整的内容执行代价高昂的 regex 匹配。如果使用精确字符串(string 或 binary),则使用字符串长度与此参数之间的最小值。如果此参数设置为 -1,则忽略此参数。如果 expect 规则不匹配,则检查将等待更多数据。如果设置为 0,则评估结果始终是结论性的。 <match> 是一个关键字,指示如何在响应中查找特定模式。关键字可以是 "string"、"rstring"、"binary" 或 "rbinary" 之一。关键字前面可以有感叹号 ("!") 来否定匹配。感叹号和关键字之间允许有空格。有关支持的关键字的更多详细信息,请参见下文。 ok-status <st> 是可选的,可用于设置检查状态,如果 expect 规则成功评估并且它是 tcp-check 规则集中的最后一条规则。支持 "L7OK"、"L7OKC"、"L6OK" 和 "L4OK": - L7OK:检查通过第 7 层 - L7OKC:检查有条件地通过第 7 层,将服务器设置为 NOLB 状态。 - L6OK:检查通过第 6 层 - L4OK:检查通过第 4 层 默认使用 "L7OK"。 error-status <st> 是可选的,可用于设置检查状态,如果 expect 规则评估期间发生错误。支持 "L7OKC"、"L7RSP"、"L7STS"、"L6RSP" 和 "L4CON": - L7OKC:检查有条件地通过第 7 层,将服务器设置为 NOLB 状态。 - L7RSP:第 7 层无效响应 - 协议错误 - L7STS:第 7 层响应错误,例如 HTTP 5xx - L6RSP:第 6 层无效响应 - 协议错误 - L4CON:第 1-4 层连接问题 默认使用 "L7RSP"。 tout-status <st> 是可选的,可用于设置检查状态,如果在 expect 规则评估期间发生超时。支持 "L7TOUT"、"L6TOUT" 和 "L4TOUT": - L7TOUT:第 7 层(HTTP/SMTP)超时 - L6TOUT:第 6 层(SSL)超时 - L4TOUT:第 1-4 层超时 默认使用 "L7TOUT"。 on-success <fmt> 是可选的,可用于自定义日志中报告的信息消息,如果 expect 规则成功评估并且它是 tcp-check 规则集中的最后一条规则。<fmt> 是自定义日志格式(请参阅第 8.2.6 节)。 on-error <fmt> 是可选的,可用于自定义日志中报告的信息消息,如果在 expect 规则评估期间发生错误。<fmt> 是自定义日志格式(请参阅第 8.2.6 节)。 status-code <expr> 是可选的,可用于设置在成功或错误时日志中报告的检查状态代码。<expr> 是一个标准 HAProxy 表达式,由采样获取后跟一些转换器组成。 <pattern> 是要查找的模式。它可以是字符串或正则表达式。如果模式包含空格,则必须使用通常的反斜杠 ('\') 进行转义。如果 match 设置为 binary,则模式必须以偶数个十六进制数字序列传递。每两个数字序列将代表一个字节。十六进制数字可以使用大写或小写。
可用的匹配项有意与其 http-check 对应项相似: string <string>:测试响应缓冲区中的精确字符串匹配。如果响应缓冲区包含此精确字符串,则健康检查响应将被视为有效。如果 "string" 关键字前面有 "!",则如果正文包含此字符串,则响应将被视为无效。这可用于在协议响应中查找强制模式,或在协议横幅中出现特定错误时检测失败。 rstring <regex>:测试响应缓冲区上的正则表达式。如果响应缓冲区匹配此表达式,则健康检查响应将被视为有效。如果 "rstring" 关键字前面有 "!",则如果正文匹配此表达式,则响应将被视为无效。 string-lf <fmt>:测试响应缓冲区中的自定义日志格式匹配。如果响应缓冲区包含评估 <fmt> 所产生的字符串(遵循第 8.2.6 节中描述的自定义日志格式规则),则健康检查响应将被视为有效。如果前面有 "!",则如果缓冲区包含该字符串,则响应将被视为无效。 binary <hexstring>:测试响应缓冲区中十六进制形式的精确字符串匹配。如果响应缓冲区包含此精确十六进制字符串,则健康检查响应将被视为有效。目的是匹配二进制协议上的数据。 rbinary <regex>:测试响应缓冲区上的正则表达式,如 "rstring"。但是,响应缓冲区将转换为其十六进制形式,包括 NUL 字节。这允许使用所有 regex 引擎来匹配任何二进制内容。十六进制转换的大小是原始响应的两倍。因此,预期的模式应该在最多一半的响应缓冲区大小上工作。 binary-lf <hexfmt>:测试响应缓冲区中十六进制形式的自定义日志格式匹配。如果响应缓冲区包含评估 <fmt> 所产生的十六进制字符串(遵循自定义日志格式规则(请参阅第 8.2.6 节)),则健康检查响应将被视为有效。如果前面有 "!",则如果缓冲区包含该十六进制字符串,则响应将被视为无效。十六进制字符串在匹配响应缓冲区之前转换为二进制字符串。重要的是要注意,响应将限制为由全局 "tune.bufsize" 选项定义的特定大小,该选项默认为 16384 字节。因此,当使用 "string"、"rstring" 或 binary 时,太大的响应可能不包含强制模式。如果绝对需要大响应,则可以通过设置全局变量来更改默认最大大小。然而,值得记住的是,解析非常大的响应会浪费一些 CPU 周期,尤其是使用正则表达式时,并且最好始终将检查集中在较小的资源上。此外,在当前状态下,检查将找不到响应中空字符之后的任何字符串或正则表达式。同样,不可能请求匹配空字符。
示例
# 执行 POP 检查 option tcp-check tcp-check expect string +OK\ POP3\ ready # 执行 IMAP 检查 option tcp-check tcp-check expect string *\ OK\ IMAP4\ ready # 查找 redis 主服务器 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
tcp-check send <数据> [comment <消息>]
tcp-check send-lf <格式> [comment <消息>]
指定一个字符串或自定义日志格式,作为通用健康检查期间的问题发送。可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
comment <消息> 定义了如果规则评估失败时要报告的消息。 <数据> 是在通用健康检查会话期间将发送的字符串。 <格式> 是在通用健康检查会话期间(请参见第 8.2.6 节)评估后将发送的自定义日志格式。
示例
# 查找 redis 主服务器 option tcp-check tcp-check send info\ replication\r\n tcp-check expect string role:master
tcp-check send-binary <十六进制字符串> [comment <消息>]
tcp-check send-binary-lf <十六进制格式> [comment <消息>]
指定一个十六进制数字字符串或十六进制数字自定义日志格式,作为原始 tcp 健康检查期间的二进制问题发送。可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
comment <消息> 定义了如果规则评估失败时要报告的消息。 <十六进制字符串> 是在通用健康检查会话期间,转换为二进制后将发送的十六进制字符串。 <十六进制格式> 是在通用健康检查会话期间(请参见第 8.2.6 节),评估并转换为二进制后将发送的十六进制自定义日志格式。
示例
# 二进制 redis 检查 option tcp-check tcp-check send-binary 50494e470d0a # PING\r\n tcp-check expect binary 2b504F4e47 # +PONG
tcp-check set-var(<变量名>[,<条件>...]) <表达式>
tcp-check set-var-fmt(<变量名>[,<条件>...]) <格式>
此操作设置变量的内容。变量是内联声明的。可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<变量名> 变量的名称。只能使用 "proc"、"sess" 和 "check" 范围。有关变量的详细信息,请参见第 2.8 节。 <条件> 一组必须全部为真才能实际设置变量的条件(例如 "ifnotempty"、"ifgt" ...)。有关可能的条件的完整列表,请参见 set-var 转换器的描述。 <表达式> 是一个样本提取表达式,后面可能跟着转换器。 <格式> 这是使用自定义日志格式规则表示的值(请参见第 8.2.6 节中的自定义日志格式)。
示例
tcp-check set-var(check.port) int(1234) tcp-check set-var-fmt(check.name) "%H"
tcp-check unset-var(<变量名>)
在其作用域内释放对变量的引用。可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<var-name> 变量的名称。只能使用 "proc"、"sess" 和 "check" 作用域。有关变量的详细信息,请参见第 2.8 节
示例
tcp-check unset-var(check.port)
tcp-request connection <动作> <选项...> [ { if | unless } <条件> ]
根据第 4 层条件对传入连接执行一个动作。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend
是(!)
yes(!)

yes

yes

no
参数
<action> 定义了如果条件适用要执行的操作。见下文。<condition> 是一个标准的仅第 4 层的基于 ACL 的条件(见第 7 节)。
在新传入连接被接受后,可以立即评估一些条件来决定是否必须接受或丢弃此连接,或者跟踪其计数器。这些条件不能使用任何数据内容,因为连接尚未读取,并且尚未分配缓冲区。这用于以非常低的开销选择性地快速接受或丢弃来自各种来源的连接。如果需要检查某些内容才能做出决定,则必须使用 "tcp-request content" 语句。"tcp-request connection" 规则按照其确切的声明顺序进行评估。如果没有规则匹配或没有规则,则默认操作是接受传入连接。对可插入的规则数量没有特定的限制。任何规则都可以选择后跟基于 ACL 的条件,在这种情况下,只有当条件评估为真时才会被评估。条件在执行操作之前进行评估,并且操作仅执行一次。因此,如果操作更改了作为条件一部分检查的元素,则没有问题。这也意味着多个操作可以依赖相同的条件,因此更改条件评估的第一个操作足以隐式禁用其余操作。例如,当尝试在变量为空时从各种来源为其分配值时,就会使用此功能。语法中 "tcp-request connection" 之后的第一个关键字是规则的操作,可选择后跟可变数量的操作参数。支持的操作及其各自的语法在第 4.3 节“操作”中列举(查找勾选“TCP RqCon”的操作)。此指令仅在命名的 defaults 部分中可用,而不是匿名部分中。defaults 部分中定义的规则在关联的代理部分中的规则之前进行评估。为避免歧义,在这种情况下,具有 frontend 能力的代理和具有 backend 能力的代理不能使用相同的 defaults 部分。这意味着 listen 部分不能使用定义此类规则的 defaults 部分。请注意,"if/unless" 条件是可选的。如果未对操作设置条件,则简单地无条件执行操作。这对于 "track-sc*" 操作以及将默认操作更改为 reject 非常有用。
示例
接受所有来自白名单主机的连接,拒绝过快的连接而不计数,并跟踪已接受的连接。这导致来自滥用来源的连接速率受到限制。
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 }
有关 ACL 的用法,请参见第 7 节
tcp-request content <action> [{if | unless} <condition>]
根据第 4-7 层条件对新会话执行一个动作。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend
是(!)
yes(!)

yes

yes

yes
参数
<action> 定义了如果条件适用要执行的操作。见下文。<condition> 是一个标准的第 4-7 层基于 ACL 的条件(见第 7 节)。
请求的内容可以在请求处理的早期阶段进行分析,称为“TCP 内容检查”。在此阶段,每次更新请求内容时都会评估基于 ACL 的规则,直到 "accept"、"reject" 或 "switch-mode" 规则匹配,或者 TCP 请求检查延迟过期而没有匹配规则。这些规则与 "tcp-request connection" 规则的第一个区别是 "tcp-request content" 规则可以使用内容来做出决定。通常,这些决定会考虑协议识别或有效性。第二个区别是基于内容的规则可以在 frontend 和 backend 中使用。在客户端 HTTP keep-alive 的情况下,所有 tcp-request content 规则都会再次评估,因此 HAProxy 会记录由 "tcp-request connection" 与 "tcp-request content" 规则分配了哪些粘性计数器,并在处理 HTTP 请求后刷新所有与内容相关的计数器,以便它们可以再次被评估用于下一个请求。当规则跟踪某些 L7 信息或以基于 L7 的 ACL 为条件时,这一点尤为重要,因为跟踪可能会在请求之间发生变化。基于内容的规则按照其确切的声明顺序进行评估。如果没有规则匹配或没有规则,则默认操作是接受内容。对可插入的规则数量没有特定的限制。虽然这不是强制性的,但建议在 "tcp-request connection" 规则中使用 track-sc0,在 frontend 的 "tcp-request content" 规则中使用 track-sc1,在 backend 的 "tcp-request content" 规则中使用 track-sc2,因为这使得配置更具可读性且易于故障排除,但这只是一个指导方针,所有计数器都可以在任何地方使用。语法中 "tcp-request content" 之后的第一个关键字是规则的操作,可选择后跟可变数量的操作参数。支持的操作及其各自的语法在第 4.3 节“操作”中列举(查找勾选“TCP RqCnt”的操作)。此指令仅在命名的 defaults 部分中可用,而不是匿名部分中。defaults 部分中定义的规则在关联的代理部分中的规则之前进行评估。为避免歧义,在这种情况下,具有 frontend 能力的代理和具有 backend 能力的代理不能使用相同的 defaults 部分。这意味着 listen 部分不能使用定义此类规则的 defaults 部分。请注意,"if/unless" 条件是可选的。如果未对操作设置条件,则简单地无条件执行操作。这对于 "track-sc*" 操作以及将默认操作更改为 reject 非常有用。另请注意,建议使用 "tcp-request session" 规则来跟踪 *不* 依赖第 7 层内容的信息,尤其是对于 HTTP frontends。某些 HTTP 处理是在会话级别执行的,可能会导致请求提前被拒绝。因此,在这种情况下,内容级别的跟踪可能会受到干扰。启动期间会发出警告,以尽可能防止此类不可靠的使用。从 TCP 代理使用 "tcp-request content" 规则匹配第 7 层内容是完全可能的,因为 HTTP 特定的 ACL 匹配能够在提取所需数据之前初步解析缓冲区的内容。如果缓冲的内容未解析为有效的 HTTP 消息,则 ACL 不匹配。此处涉及的解析器与所有其他 HTTP 处理的解析器完全相同,因此不存在以不同方式解析的风险。在 HTTP frontend 或 HTTP backend 中,保证在首次评估规则时 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)
示例
# 接受 Host 头部为 "example.com" 的 HTTP 请求 # 并拒绝其他所有请求。(仅适用于 HTTP/1 连接) 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 # 接受 Host 头部为 "example.com" 的 HTTP 请求 # 并拒绝其他所有请求。(适用于 HTTP/1 和 HTTP/2 连接) 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 # 此处隐式处理非 HTTP 流量 ... http-request reject unless is_host_com
示例
# 如果客户端先说话,则拒绝 SMTP 连接 tcp-request inspect-delay 30s acl content_present req.len gt 0 tcp-request content reject if content_present # 仅当客户端说话时才转发 HTTPS 连接 tcp-request inspect-delay 30s acl content_present req.len gt 0 tcp-request content accept if content_present tcp-request content reject
示例
# 跟踪 X-Forwarded-For 中的最后一个 IP(粘滞表类型为 string) tcp-request inspect-delay 10s tcp-request content track-sc0 hdr(x-forwarded-for,-1) # 或者跟踪 X-Forwarded-For 中的最后一个 IP(粘滞表类型为 ip|ipv6) tcp-request content track-sc0 req.hdr_ip(x-forwarded-for,-1)
示例
# 按“base”(Host+URL 的串联)跟踪请求计数 tcp-request inspect-delay 10s tcp-request content track-sc0 base table req-rate
示例
跟踪每个前端和每个后端的计数器,当后端检测到滥用(并标记 gpc0)时,在前端阻止滥用者。
frontend http # 在 SC0 中使用通用计数器 0 作为全局滥用计数器 # 保护我们所有的站点 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 # 如果某个来源对此动态站点发出的请求过快(由 # SC1 跟踪),则在前端全局阻止它。 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
有关 ACL 的用法,请参见第 7 节
设置在内容检查期间等待数据的最大允许时间。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend
是(!)
yes(!)

yes

yes

yes
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
主要使用 HAProxy 作为 TCP 中继的人通常担心在不进行任何分析的情况下将任何类型的协议传递给服务器的风险。为了能够分析请求内容,我们必须首先保留数据,然后分析它们。此语句只是启用数据保留,最长为指定的时间量。当连接到达 frontend 时,TCP 内容检查会非常早地应用,然后当连接转发到 backend 时,也会非常早地应用。这意味着如果 frontend 和 backend 都有 tcp-request 规则,连接可能会在 frontend 中经历第一次延迟,在 backend 中经历第二次延迟。请注意,在执行内容检查时,HAProxy 会在每一块新数据进入时评估整个规则,同时考虑到这些数据是部分的。如果在上述延迟之前没有规则匹配,则会在过期时执行最后一次检查,此时认为内容是最终的。如果未设置延迟,HAProxy 将根本不等待,并根据可用信息立即应用裁决。显然,这不太可能非常有用,甚至可能存在竞态条件,因此不建议使用此类设置。请注意,如果发生连接错误或关闭,或者请求缓冲区看起来已满,则检查延迟会缩短。一旦规则匹配,请求就会被释放并照常继续。如果达到超时且没有规则匹配,则默认策略是让它不受影响地通过。对于大多数协议,将其设置为几秒钟就足够了,因为大多数客户端在连接后会立即发送完整的请求。添加 3 秒或更多秒以涵盖 TCP 重传,仅此而已。对于某些协议,使用较大的值可能是有意义的,例如确保客户端在服务器之前永远不会说话(例如 SMTP),或等待客户端说话,然后再将数据传递给服务器(例如 SSL)。请注意,客户端超时必须至少覆盖检查延迟,否则它将首先过期。如果客户端关闭连接或缓冲区已满,则延迟会立即过期,因为内容将无法再更改。此指令仅在命名的 defaults 部分中可用,而不是匿名部分中。代理从其 defaults 部分继承此值。
tcp-request session <动作> [{if | unless} <条件>]
根据第 5 层条件对已验证的会话执行一个动作。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend
是(!)
yes(!)

yes

yes

no
参数
<动作> 定义了如果条件适用时要执行的动作。见下文。 <条件> 是一个标准的仅第 5 层的基于 ACL 的条件(见第 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 部分中定义的规则在关联的代理部分中的规则之前进行评估。为避免歧义,在这种情况下,具有 frontend 能力的代理和具有 backend 能力的代理不能使用相同的 defaults 部分。这意味着 listen 部分不能使用定义此类规则的 defaults 部分。请注意,"if/unless" 条件是可选的。如果未对操作设置条件,则简单地无条件执行操作。这对于 "track-sc*" 操作以及将默认操作更改为 reject 非常有用。
示例
默认跟踪原始源地址,或者对于来自本地代理的连接,跟踪 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 }
有关 ACL 的用法,请参见第 7 节
tcp-response content <action> [{if | unless} <condition>]
根据第 4-7 层的条件对会话响应执行操作。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend
是(!)
yes(!)

no

yes

yes
参数
<action> 定义了如果条件适用要执行的操作。见下文。<condition> 是一个标准的第 4-7 层基于 ACL 的条件(见第 7 节)。
响应内容可以在响应处理的早期阶段进行分析,称为“TCP 内容检查”。在此阶段,每次更新响应内容时都会评估基于 ACL 的规则,直到最终规则匹配,或者设置的 TCP 响应检查延迟过期而没有匹配规则。通常,这些决定会考虑协议识别或有效性。基于内容的规则按照其确切的声明顺序进行评估。如果没有规则匹配或没有规则,则默认操作是接受内容。对可插入的规则数量没有特定的限制。语法中 "tcp-response content" 之后的第一个关键字是规则的操作,可选择后跟可变数量的操作参数。支持的操作及其各自的语法在第 4.3 节“操作”中列举(查找勾选“TCP RsCnt”的操作)。此指令仅在命名的 defaults 部分中可用,而不是匿名部分中。defaults 部分中定义的规则在关联的代理部分中的规则之前进行评估。为避免歧义,在这种情况下,具有 frontend 能力的代理和具有 backend 能力的代理不能使用相同的 defaults 部分。这意味着 listen 部分不能使用定义此类规则的 defaults 部分。请注意,"if/unless" 条件是可选的。如果未对操作设置条件,则简单地无条件执行操作。这对于将默认操作更改为 reject 非常有用。支持几种类型的操作:使用 "tcp-response content" 规则匹配第 7 层内容是完全可能的,但在这种情况下,确保已缓冲完整响应非常重要,否则不会匹配任何内容。为了实现这一点,最好的解决方案是在检查期间检测 HTTP 协议。有关 ACL 使用,请参阅第 7 节
设置在内容检查期间等待响应的最长允许时间。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend
是(!)
yes(!)

no

yes

yes
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
此指令仅在命名的 defaults 部分中可用,不能在匿名部分中使用。代理从其 defaults 部分继承此值。
timeout check <timeout>
设置额外的检查超时,但仅在连接已经建立之后。可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
如果设置,HAProxy 使用 min("timeout connect", "inter") 作为检查的连接超时,使用 "timeout check" 作为额外的读取超时。“min”用于使运行 *非常* 长 "timeout connect" 的人(例如,那些由于队列或 tarpit 而需要此功能的人)不会减慢检查速度。(另请注意,没有有效的理由设置如此长的连接超时,因为始终可以使用 "timeout queue" 和 "timeout tarpit" 来避免这种情况)。如果未设置 "timeout check",则 HAProxy 使用 "inter" 作为完整的检查超时(连接 + 读取),就像所有 <1.3.15 版本一样。在大多数情况下,检查请求比正常请求简单得多且处理速度更快,人们可能希望踢出滞后的服务器,因此此超时应小于 "timeout server"。此参数特定于 backend,但可以在 "defaults" 部分中一次性指定。这实际上是确保不会忘记它的最简单解决方案之一。
timeout client <timeout>
设置客户端侧的最大不活动时间。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
当客户端期望确认或发送数据时,会应用不活动超时。在 HTTP 模式下,此超时在客户端发送请求的第一阶段以及在客户端读取服务器发送的数据的响应期间尤其重要。也就是说,对于第一阶段,最好设置 "timeout http-request" 以更好地保护 HAProxy 免受类似 Slowloris 的攻击。默认情况下,该值以毫秒为单位指定,但如果数字带有单位后缀,则可以以任何其他单位指定,如本文档开头所述。在 TCP 模式下(以及在较小程度上在 HTTP 模式下),强烈建议客户端超时等于服务器超时,以避免复杂的调试情况。一个好的做法是指定略高于 3 秒倍数(例如 4 或 5 秒)的超时时间,以涵盖一次或多次 TCP 数据包丢失。如果长寿命流与短寿命流混合在一起(例如 WebSocket 和 HTTP),则值得考虑 "timeout tunnel",它会覆盖 "timeout client" 和 "timeout server" 用于隧道,以及 "timeout client-fin" 用于半关闭连接。此参数特定于 frontend,但可以在 "defaults" 部分中一次性指定。这实际上是确保不会忘记它的最简单解决方案之一。未指定的超时会导致无限超时,不建议这样做。接受并使用此类用法,但在启动期间会报告警告,因为它可能导致如果系统超时也未配置,则系统中会积累过期的会话。
为半关闭连接设置客户端侧的不活动超时。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
当客户端期望确认或发送数据而一个方向已关闭时,会应用不活动超时。此超时与 "timeout client" 的不同之处在于它仅适用于在一个方向上关闭的连接。这对于避免在客户端未干净断开连接时将连接保持在 FIN_WAIT 状态太久特别有用。此问题在 RDP 或 WebSocket 等长连接上特别常见。请注意,当连接在一个方向关闭时,此超时可以覆盖 "timeout tunnel"。一旦发送了 GOAWAY 帧,它就会应用于空闲的 HTTP/2 连接,通常表示期望连接快速结束。此参数特定于 frontend,但可以在 "defaults" 部分中一次性指定。默认情况下未设置,因此半关闭连接将使用其他超时(timeout.client 或 timeout.tunnel)。
设置等待客户端 TLS 握手完成的最长时间。这可用于 TCP 和 QUIC 连接。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
如果未设置此握手超时,则将使用客户端超时来替代。
timeout connect <timeout>
设置等待到服务器的连接尝试成功的最大时间。可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
如果服务器与 HAProxy 位于同一局域网内,连接应该是即时的(少于几毫秒)。无论如何,指定略高于 3 秒倍数的超时(例如 4 或 5 秒)以覆盖一个或多个 TCP 数据包丢失是一个好习惯。默认情况下,如果未指定队列和 tarpit 超时,连接超时也会将它们预设为相同的值。此参数特定于后端,但可以在 "defaults" 部分中为所有后端一次性指定。这实际上是避免忘记它的最简单解决方案之一。未指定的超时会导致无限超时,这是不推荐的。这种用法被接受并且可以工作,但在启动时会报告警告,因为如果系统超时也未配置,可能会导致系统中失败会话的累积。
设置等待新 HTTP 请求出现的最长允许时间。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
默认情况下,在 keep-alive 情况下等待新请求的时间由 "timeout http-request" 设置。然而,这并不总是方便,因为有些人希望非常短的 keep-alive 超时以更快地释放连接,而另一些人则希望有更长的超时,但在请求开始呈现自身时仍有短超时。"http-keep-alive" 超时涵盖了这些需求。它将定义在发送响应后等待新 HTTP 请求开始到来的时间。一旦看到请求的第一个字节,"http-request" 超时用于等待完整的请求到来。请注意,新请求之前的空行不会刷新超时,也不会计为新请求。这两个超时之间还有另一个区别:当连接在 timeout http-keep-alive 期间过期时,不返回错误,连接只是关闭。如果连接在 "http-request" 中过期,同时等待请求完成,则在关闭连接之前向客户端返回 HTTP 408 错误,除非在 frontend 中设置了 "option http-ignore-probes"。通常,"timeout http-keep-alive" 最适合用于防止客户端在短连接数量较多的站点上保持空闲连接打开太久。这可以通过在 HTTP/1.1 中将值设置为几十到几百毫秒来实现。这将在客户端请求页面后关闭连接,而无需保持该连接打开以等待来自客户端的更多活动。在这种情况下,来自浏览器的新活动将导致 TCP 和/或 SSL 层的重新握手。一个常见的用例是仅提供重定向到 HTTPS 页面的 HTTP 站点。此类连接最好不要保持空闲太久,因为它们不会被重用,除非可能用于获取 favicon。另一个用例恰恰相反:有些站点希望允许客户端重用空闲连接很长时间(例如 30 秒到一分钟),但不希望等待这么长时间才能进行第一个请求,以避免非常廉价的攻击媒介。在这种情况下,http-keep-alive 超时将设置为较大值,但 http-request 将保持较低值(几秒钟)。当设置为非常小的值时,除非请求真正是流水线式的,否则未流水线化的其他请求很可能通过另一个连接处理,这在 HTTP/1.1 中非常罕见(请求背靠背发送而无需等待响应)。大多数 HTTP/1.1 实现发送一个请求,等待响应,然后发送另一个请求。对于 HTTP/1.1 来说,此处的小值可能有利于为拥有数十万客户端的站点使用更少的内存和套接字,代价是增加握手计算成本。使用小值处理 HTTP/2 时应特别小心。HTTP/2 的本质是在连接上多路复用请求,以节省重新连接 TCP 和/或 SSL 层的开销。该协议还使用控制帧,这些帧在 TCP 连接过早关闭时处理不佳,在极少数情况下,这可能会导致数据离开 HAProxy 后被破坏时响应被截断(此时甚至无法记录错误)。对于 HTTP/2 连接,建议的较低起始值约为 4 秒。这将防止大多数现代 keep-alive 实现不必要地保持陈旧连接打开,同时允许后续请求重用连接。然而,这应根据需要进行调整,只是一个起点。如果未设置此参数,则应用 "http-request" 超时,如果两者都未设置,则 "timeout client" 仍应用于较低级别。它应该在 frontend 中设置才能生效,除非 frontend 处于 TCP 模式,在这种情况下将使用 HTTP backend 的超时。
设置等待一个完整的 HTTP 请求的最长允许时间。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
为了提供 DoS 保护,可能需要降低接收完整 HTTP 请求的最大可接受时间,而不会影响客户端超时。这有助于防止在建立连接上未发送任何内容时受到保护。客户端超时无法针对此滥用提供良好的保护,因为它是不活动超时,这意味着如果攻击者偶尔发送一个字符,则超时不会触发。使用 HTTP 请求超时,无论客户端输入速度如何,如果请求未及时完成,请求都将被中止。当超时过期时,会向客户端发送 HTTP 408 响应以告知问题,并关闭连接。日志将报告终止代码 "cR"。一些最近的浏览器对此标准、有据可查的行为存在问题,因此可能需要使用 "option http-ignore-probes" 或 "errorfile 408 /dev/null" 来隐藏 408 代码。有关 "cR" 终止代码的更多详细信息,请参见第 8.5 节中的解释。默认情况下,此超时仅适用于请求的标头部分,而不适用于任何数据。一旦收到空行,就不再使用此超时。当与 "option http-buffer-request" 结合使用时,此超时也适用于请求正文。如果未设置 "timeout http-keep-alive",则在 keep-alive 连接上再次使用它来等待第二个请求。通常,将其设置为几秒钟就足够了,因为大多数客户端在连接后会立即发送完整的请求。添加 3 秒或更多秒以涵盖 TCP 重传,仅此而已。将其设置为非常低的值(例如 50 毫秒)通常在本地网络上有效,只要没有数据包丢失。这将防止人们使用 telnet 发送裸 HTTP 请求。如果未设置此参数,则客户端超时仍适用于传入请求的每个块之间。它应该在 frontend 中设置才能生效,除非 frontend 处于 TCP 模式,在这种情况下将使用 HTTP backend 的超时。
timeout queue <timeout>
设置在队列中等待一个可用连接槽的最长时间。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
当服务器的 maxconn 达到时,连接会保留在队列中等待,这个队列可以是特定于服务器的,也可以是后端全局的。为了避免无限期等待,对队列中等待的请求应用了超时。如果达到超时,则认为请求几乎永远不会被服务,因此它会被丢弃并向客户端返回 503 错误。"timeout queue" 语句允许设置请求在队列中等待的最长时间。如果未指定,则使用与后端连接超时 ("timeout connect") 相同的值,以实现与没有 "timeout queue" 参数的旧版本的向后兼容性。
timeout server <timeout>
设置服务器侧的最大不活动时间。可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
不活动超时适用于服务器预期应答或发送数据时。在 HTTP 模式下,此超时在服务器响应的第一阶段尤其重要,此时它必须发送标头,因为它直接代表了服务器处理请求的时间。要确定放置什么值,通常最好从被认为是不可接受的响应时间开始,然后检查日志以观察响应时间分布,并相应地调整值。默认情况下,该值以毫秒为单位指定,但如果数字后带有单位后缀,则可以采用任何其他单位,如本文档顶部所述。在 TCP 模式下(以及在较小程度上,在 HTTP 模式下),强烈建议客户端超时保持等于服务器超时,以避免复杂的调试情况。无论预期的服务器响应时间如何,一个好的做法是至少覆盖一次或多次 TCP 数据包丢失,方法是指定略高于 3 秒倍数的超时(例如,至少 4 或 5 秒)。如果一些长期存在的流与短期存在的流混合在一起(例如 WebSocket 和 HTTP),则值得考虑 "timeout tunnel",它会覆盖 "timeout client" 和 "timeout server" 用于隧道。此参数特定于后端,但可以在 "defaults" 部分中一次性指定。这实际上是确保不会忘记它的一种最简单方法。未指定的超时会导致无限超时,这是不推荐的。这种用法被接受并且有效,但在启动期间会报告警告,因为它可能导致系统中累积过期的会话,如果系统的超时也没有配置。
为半关闭连接设置服务器侧的不活动超时。可在以下上下文中使用:tcp, http, log

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
不活动超时适用于当服务器预期应答或发送数据,而一个方向已经关闭时。此超时与 "timeout server" 的不同之处在于,它仅适用于在一个方向上关闭的连接。这对于避免当远程服务器没有干净地断开连接时,连接长时间处于 FIN_WAIT 状态特别有用。这个问题在 RDP 或 WebSocket 等长时间连接中特别常见。请注意,当连接在一个方向上关闭时,此超时可以覆盖 "timeout tunnel"。提供此设置是为了完整性,但在大多数情况下,应该不需要它。此参数特定于后端,但可以在 "defaults" 部分中一次性指定。默认情况下不设置,因此半关闭连接将使用其他超时(timeout.server 或 timeout.tunnel)。
timeout tarpit <timeout>
设置被置于 tarpit 状态的连接将维持的时长。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<timeout> 是 tarpit 的持续时间,默认以毫秒为单位指定,但如果数字后跟单位后缀,也可以是任何其他单位,如本文档开头所述。
当使用 "http-request tarpit" 将一个连接置于 tarpit 状态时,它会在没有任何活动的情况下保持打开一段时间,然后关闭。“timeout tarpit”定义了它将保持打开的时间长度。默认情况下,该值以毫秒为单位指定,但如果数字后跟有单位后缀,则可以是任何其他单位,如本文档开头所述。如果未指定,将使用与后端连接超时(“timeout connect”)相同的值,以向后兼容没有“timeout tarpit”参数的旧版本。
timeout tunnel <timeout>
为隧道设置客户端和服务器侧的最大不活动时间。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
隧道超时适用于客户端和服务器之间建立双向连接,并且连接在两个方向上都保持不活动状态。一旦连接成为隧道,此超时将取代客户端和服务器超时。在 TCP 中,只要没有分析器连接到任一连接(例如,tcp 内容规则被接受),就会使用此超时。在 HTTP 中,当连接升级时(例如,切换到 WebSocket 协议,或将 CONNECT 请求转发到代理),或者在第一个响应之后未指定 keepalive/close 选项时,会使用此超时。由于此超时通常与长期存在的连接结合使用,因此最好也设置 "timeout client-fin" 以处理客户端突然从网络中消失且不确认关闭,或发送关闭且不再确认挂起数据的情况。这可能发生在存在防火墙的有损网络中,并通过存在大量处于 FIN_WAIT 状态的会话来检测。默认情况下,该值以毫秒为单位指定,但如果数字后带有单位后缀,则可以采用任何其他单位,如本文档顶部所述。无论预期的正常空闲时间如何,一个好的做法是至少覆盖一次或多次 TCP 数据包丢失,方法是指定略高于 3 秒倍数的超时(例如,至少 4 或 5 秒)。此参数特定于后端,但可以在 "defaults" 部分中一次性指定。这实际上是确保不会忘记它的一种最简单方法。
Example
defaults http option http-server-close timeout connect 5s timeout client 30s timeout client-fin 30s timeout server 30s timeout tunnel 1h # 用于 WebSocket 和 CONNECT 的超时
transparent (已弃用)
启用客户端透明代理 可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
引入此关键字是为了向第 3 层负载均衡器提供第 7 层持久性。其思想是利用操作系统的能力将远程地址的传入连接重定向到本地进程(此处为 HAProxy),并让该进程知道最初请求的地址。使用此选项时,没有 cookie 的会话将被转发到传入请求的原始目标 IP 地址(该地址应与另一设备的地址匹配),而带有 cookie 的请求仍将被转发到适当的服务器。" transparent" 关键字已弃用,请改用 "option transparent"。请注意,与普遍看法相反,此选项在建立连接时并不会使 HAProxy 向服务器呈现客户端的 IP。
为每个请求生成一个唯一 ID。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<fmt> 是一个自定义日志格式字符串(参见第 8.2.6 节)。
此关键字使用自定义日志格式为每个请求创建一个 ID。唯一 ID 对于跟踪通过复杂基础设施中多个组件的请求非常有用。新创建的 ID 也可以使用自定义日志格式字符串中的 %ID 别名进行记录。该格式应由组合在一起时保证唯一的元素组成。例如,如果涉及多个 HAProxy 实例,包含节点名称可能很重要。通常需要记录传入连接的源和目标地址及端口。请注意,由于可以在同一连接上执行多个请求,包含请求计数器可能有助于区分它们。同样,时间戳可以防止计数器回滚。记录进程 ID 将避免服务重启后发生冲突。建议对许多字段使用十六进制表示法,因为它使它们更紧凑并节省日志空间。
示例
unique-id-format %{+X}o\ %ci:%cp_%fi:%fp_%Ts_%rt:%pid 将生成: 7F000001:8296_7F00001E:1F90_4F7B0A69_0003:790A
在 HTTP 请求中添加一个唯一 ID 标头。可在以下上下文中使用:http

可用于部分

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<name> 是头部的名称。
使用 unique-id-format 在发送到服务器的 HTTP 请求中添加一个 unique-id 头部。如果 unique-id-format 不存在,则无法工作。
示例
unique-id-format %{+X}o\ %ci:%cp_%fi:%fp_%Ts_%rt:%pid unique-id-header X-Unique-ID 将生成: X-Unique-ID: 7F000001:8296_7F00001E:1F90_4F7B0A69_0003:790A 另请参阅: "unique-id-format"
use_backend <backend> [{if | unless} <condition>]
如果/除非满足基于 ACL 的条件,则切换到特定的后端。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

no

yes

yes

no
参数
<backend> 是一个有效的后端或 "listen" 部分的名称,或一个解析为后端名称的自定义日志格式(参见第 8.2.6 节中的自定义日志格式)。<condition> 是一个由 ACL 组成的条件,如第 7 节所述。如果省略,则无条件应用该规则。
在进行内容切换时,连接到达前端,然后根据许多条件分派到各种后端。条件和后端之间的关系由 "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" 设置。动态名称无法做到这一点。
定义用于后端的 FastCGI 应用程序。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

no

no

yes

yes
参数
<name> 是要使用的 FastCGI 应用程序的名称。
有关 FastCGI 应用程序设置的详细信息,请参见第 10.1 节
use-server <server> if <condition>
use-server <server> unless <condition>
仅在/除非满足基于 ACL 的条件时才使用特定服务器。可在以下上下文中使用:tcp, http

可用于部分

defaultsfrontendlistenbackend

no

no

yes

yes
参数
<server> 是同一后端部分中有效服务器的名称,或解析为服务器名称的自定义日志格式字符串(参见第 8.2.6 节)。<condition> 是由 ACL 组成的条件,如第 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")。如果这些服务器的权重设置为零,则它们将不用于其他流量。
Example
# 基于 SNI 字段拦截传入的 TLS 请求 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 # 所有其余请求都转发到此服务器 server default 192.168.0.2:443 check
当 <server> 是一个简单名称时,它会与配置中现有的服务器进行核对,如果指定的服务器不存在,则会报告错误。如果它是一个自定义日志格式,则在解析配置时不会执行检查,如果我们在运行时无法解析有效的服务器名称,但 use-server 规则的条件是由一个返回 true 的 ACL 决定的,那么将不会应用其他 use-server 规则,而是回退到负载均衡。

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 节 使用相同的缩写。
关键字QUIC: IniTCP: RqConRqSesRqCntRsCntHTTP: ReqResAft
acceptXXXXX   
add-acl     XX 
add-header     XXX
allow     XXX
attach-srv  X     
auth     X  
cache-store      X 
cache-use     X  
capture   X XXX
close    X   
del-acl     XX 
del-header     XXX
del-map     XXX
deny     XX 
dgram-dropX       
disable-l7-retry     X  
do-logXXXXXXXX
do-resolve   X X  
early-hint     X  
expect-netscaler-cip X      
关键字QUIC: IniTCP: RqConRqSesRqCntRsCntHTTP: ReqResAft
expect-proxy layer4 X      
normalize-uri     X  
pause     XX 
redirect     XX 
rejectXXXXXX  
replace-header     XXX
replace-path     X  
replace-pathq     X  
replace-uri     X  
replace-value     XXX
return     XX 
sc-add-gpc XXXXXXX
sc-inc-gpc XXXXXXX
sc-inc-gpc0 XXXXXXX
sc-inc-gpc1 XXXXXXX
sc-set-gpt XXXXXXX
sc-set-gpt0 XXXXXXX
send-retryX       
send-spoe-group   XXXX 
set-bandwidth-limit   XXXX 
关键字QUIC: IniTCP: RqConRqSesRqCntRsCntHTTP: ReqResAft
set-bc-mark   X X  
set-bc-tos   X X  
set-dst XXX X  
set-dst-port XXX X  
set-fc-mark XXXXXX 
set-fc-tos XXXXXX 
set-header     XXX
set-log-level   XXXXX
set-map     XXX
(已弃用)set-mark XXXXXX 
set-method     X  
set-nice   XXXX 
set-path     X  
set-pathq     X  
set-priority-class   X X  
set-priority-offset   X X  
set-query     X  
set-retries   X X  
set-src XXX X  
set-src-port XXX X  
关键字QUIC: IniTCP: RqConRqSesRqCntRsCntHTTP: ReqResAft
set-status      XX
set-timeout     XX 
(已弃用)set-tos XXXXXX 
set-uri     X  
set-var XXXXXXX
set-var-fmt XXXXXXX
silent-drop XXXXXX 
strict-mode     XXX
switch-mode   X    
tarpit     X  
track-sc0 XXX XX 
track-sc1 XXX XX 
track-sc2 XXX XX 
unset-var XXXXXXX
use-service   X X  
wait-for-body     XX 
wait-for-handshake     X  

4.4. 按字母顺序排序的操作参考

本节使用与上述第 4.3 节中描述的相同的规则集术语标记,提供了每个操作及其用法的详细描述。

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
XXXXX   
此操作停止规则的评估,并让请求或响应通过检查。此操作是最终的,即对于当前部分,不会评估同一规则集中的任何后续规则。此操作与“allow”操作没有区别,只是为了历史兼容性,“accept”用于 TCP 和 QUIC 规则,而“allow”用于 HTTP 规则。另请参见下面的“allow”操作。
add-acl(<file-name>) <key fmt>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     XX 
这用于向 ACL 中添加一个新条目。ACL 必须从文件中加载(即使是虚拟的空文件)。要更新的 ACL 的文件名在括号中传递。它接受一个参数:<key fmt>,该参数遵循第 8.2.6 节中描述的自定义日志格式规则,以收集新条目的内容。它在插入前会先在 ACL 中进行查找,以避免重复(或更多)的值。它等同于 stats 套接字中的 "add acl" 命令,但可以由 HTTP 请求触发。
add-header <name> <fmt>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     XXX
此操作附加一个 HTTP 标头字段,其名称由 <name> 指定,其值由 <fmt> 定义,<fmt> 遵循自定义日志格式规则(参见第 8.2.6 节中的自定义日志格式)。这对于向服务器传递特定于连接的信息(例如客户端的 SSL 证书)或将多个标头合并为一个特别有用。此规则不是最终的,因此可以添加其他类似的规则。请注意,标头添加是立即执行的,因此一个规则可能会重用前一个规则产生的结果标头。

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     XXX
此操作停止规则的评估,并让请求通过检查。此操作是最终的,即对于当前部分,不会评估同一规则集中的任何后续规则。此操作与“accept”操作没有区别,只是为了历史兼容性,“accept”用于 TCP 规则,而“allow”用于 HTTP 规则。另请参见上面的“accept”操作。
attach-srv <srv> [name <expr>] [ 实验性 ]

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
  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>]

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     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

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
      X 
在缓存中存储一个 http-response。响应头的存储在此步骤完成,这意味着您可以使用其他 http-response 操作在存储响应之前或之后修改头。此操作负责设置缓存存储过滤器。有关缓存设置,请参见第 6.2 节
cache-use <name>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     X  
尝试从缓存 <name> 中提供一个缓存对象。此指令对于存储缓存也是必需的,因为它计算缓存哈希值。如果您想对存储和提供都使用一个条件,最好将其放在此指令之后。有关缓存设置,请参见第 6.2 节
capture <sample> [ len <length> | id <id> ]

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
   X XXX
这会从请求或响应缓冲区捕获样本表达式 <sample>,并将其转换为最多 <len> 个字符的字符串。生成的字符串存储在下一个 "capture" 槽中(请求或响应),因此它可能会出现在某些捕获的 HTTP 标头旁边。然后它将自动出现在日志中,并且可以使用样本获取方法提取它以将其填充到标头或任何其他内容中。长度应受到限制,因为此大小将在整个流生命周期内为每次捕获分配。请注意,长度仅适用于 "http-request" 规则。请查看 第 7.3 节(获取样本)、"capture request header" 和 "capture response header" 以获取更多信息。如果使用关键字 "id" 代替 "len",则该动作尝试将捕获的字符串存储在先前声明的捕获槽中。这对于在后端运行捕获很有用。槽 ID 可以由先前的指令 "http-request capture" 或使用 "declare capture" 关键字声明。在后端使用此动作时,请仔细检查相关前端是否具有所需的捕获槽,否则此规则将在运行时被忽略。由于 HAProxy 能够在运行时动态解析后端名称,因此在配置解析时无法检测到这一点。

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
    X   
此操作用于立即关闭与服务器的连接。后续的“tcp-response content”规则将不再被评估。此操作的主要目的是,在应用程序协议期望先经过一段较长的超时时间的情况下,强制结束客户端与服务器之间的交换后的连接。其目标是消除那些在某些协议下会占用大量服务器资源的空闲连接。
del-acl(<file-name>) <key fmt>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     XX 
此操作用于从 ACL 中删除一个条目。该 ACL 必须是从文件中加载的(即使是一个虚拟的空文件)。要更新的 ACL 的文件名在括号中传递。它接受一个参数:<key fmt>,该参数遵循第 8.2.6 节中的自定义日志格式规则,用于收集要删除条目的内容。它等效于 stats socket 中的 "del acl" 命令,但可以由 HTTP 请求或响应触发。
del-header <name> [ -m <meth> ]

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     XXX
此操作移除所有名称在 <name> 中指定的 HTTP 标头字段。<meth> 是应用于标头名称的匹配方法。支持的匹配方法有“str”(精确匹配)、“beg”(前缀匹配)、“end”(后缀匹配)、“sub”(子串匹配)和“reg”(正则表达式匹配)。如果未指定,则使用精确匹配方法。
del-map(<map-name>) <key fmt>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     XXX
此操作用于从 MAP 中删除一个条目。<map-name> 必须遵循 2.7 节中关于 maps 和 ACLs 名称格式的描述。要更新的 MAP 名称在括号中传递。它接受一个参数:<key fmt>,该参数遵循第 8.2.6 节中的自定义日志格式规则,用于收集要删除条目的内容。它等效于 stats socket 中的 "del map" 命令,但可以由 HTTP 请求或响应触发。
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 IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     XX 
此操作停止规则评估并立即拒绝请求或响应。默认情况下,对请求返回 HTTP 403 错误,对响应返回 502 错误,但返回的响应可以使用与“return”操作相同的语法进行自定义。因此,详情请参见下文的“return”。为了兼容性,当没有定义参数,或仅定义了 "deny_status" 时,会隐含 "default-errorfiles" 参数。这意味着 "deny [deny_status <status>]" 是 "deny [status <status>] default-errorfiles" 的别名。此操作是最终的,即同一规则集中的后续规则将不会对当前部分进行评估。另请参阅“return”操作以了解高级语法。

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
X       
此操作会静默忽略收到的 QUIC 初始数据包,否则该数据包将导致新的 QUIC 连接实例化并执行其 SSL 握手。

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     X  
此操作会禁止任何因连接失败以外的原因而重试请求的尝试。例如,这对于确保 POST 请求在失败时不会被重试非常有用。

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
XXXXXXXX
此操作手动触发代理上的日志发送。这意味着代理上的日志选项将被考虑(包括诸如“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" 日志格式别名时,它们将被正确报告。
示例
log-profile myprof on tcp-req-conn format "Connect: %ci" frontend myfront log stdout format rfc5424 profile myprof local0 log-format "log generated using proxy logformat, from '%OG'" tcp-request connection do-log #使用特殊的 log-profile 格式 tcp-request content do-log #使用代理的 logformat
do-resolve(<var>,<resolvers>[,ipv4|ipv6]) <expr>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
   X X  
此动作执行 <expr> 输出的 DNS 解析,并将结果存储在变量 <var> 中。它使用由 <resolvers> 指向的 DNS 解析器部分。可以使用可选参数 'ipv4' 或 'ipv6' 选择解析首选项。另请参阅全局 "dns-accept-family" 关键字以强制严格使用特定系列。执行 DNS 解析时,客户端连接暂停,等待解析结束。如果找到 IP 地址,它将存储在 <var> 中。如果发生任何类型的错误,则不设置 <var>。可以使用此动作在运行时发现服务器 IP 地址,并基于请求中找到的信息(即 Host 标头)。如果此动作用于查找服务器的 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>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     X  
此操作用于在任何其他响应之前构建一个 HTTP 103 Early Hints 响应。它会向此响应中追加一个 HTTP 标头字段,其名称由 <name> 指定,其值由 <fmt> 定义,该 <fmt> 遵循自定义日志格式规则(参见第 8.2.6 节中的自定义日志格式)。这对于向客户端传递一些 Link 标头以预加载渲染 HTML 文档所需的资源特别有用。更多信息请参阅 RFC 8297。

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
 X      
此操作配置面向客户端的连接,以便在从套接字读取任何字节之前接收 NetScaler 客户端 IP 插入协议头。这相当于在“bind”行上使用“accept-netscaler-cip”关键字,不同之处在于,使用 TCP 规则允许仅对使用 ACL 的特定 IP 地址范围接受 PROXY 协议。当来自公共主机的流量通过多层负载均衡器时,这非常方便。

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
 X      
此操作配置面向客户端的连接,以便在从套接字读取任何字节之前接收 PROXY 协议头。这相当于在“bind”行上使用“accept-proxy”关键字,不同之处在于,使用 TCP 规则允许仅对使用 ACL 的特定 IP 地址范围接受 PROXY 协议。当来自公共主机的流量通过多层负载均衡器时,这非常方便。
normalize-uri <normalizer>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     X  
执行请求 URI 的规范化。HAProxy 2.4 中的 URI 规范化目前作为实验性技术预览提供。因此,它首先需要全局指令 'expose-experimental-directives' 才能调用它。您应该做好准备,规范化器的行为可能会更改以修复可能的问题,可能会破坏您基础结构中的正确请求处理。每个规范化器处理一种类型的规范化,以允许对支持的后端选择适当的规范化级别。例如,"path-strip-dotdot" 规范化器可能对将请求 URI 直接映射到本地文件系统中的路径的静态文件服务器有用。但是,它可能会破坏需要路径中特定数量段的 API 路由。重要的是要注意,一些规范化器可能会对损坏的 URI 导致不安全的转换。也可能发生的是,本身安全的规范化器组合在不正确组合时会导致不安全的转换。例如,当损坏的 URI 包含裸百分比字符时,"percent-decode-unreserved" 规范化器可能会导致意外结果。一个这样的损坏 URI 是 "/%%36%36",它将被解码为 "/%66",而 "/%66" 又等同于 "/f"。通过指定 "strict" 选项,对此类损坏 URI 的请求将被安全地拒绝。提供以下规范化器: - fragment-encode: 将 "#" 编码为 "%23"。应首选 "fragment-strip" 规范化器,除非已知损坏的客户端未在路径组件中正确编码 '#'。
示例
- /#foo -> /%23foo
- fragment-strip: 移除 URI 的“fragment”组件。根据 RFC 3986#3.5,URI 的“fragment”组件不应被发送,而应由用户代理在检索资源后处理。应首先应用此规范化器,以确保片段不被解释为请求路径组件的一部分。
示例
- /#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/ (无变化)
- 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 (无变化) - /%%36%36 -> /%66 (不安全) - /%ZZ -> /%ZZ
如果指定了“strict”选项,则无效序列将导致返回 HTTP 400 Bad Request。
示例
- /%%36%36 -> HTTP 400 - /%ZZ -> HTTP 400
- percent-to-uppercase: 将百分比编码序列中的字母大写(RFC 3986#6.2.2.1)。
示例
- /%6f -> /%6F - /%zz -> /%zz
如果指定了“strict”选项,则无效序列将导致返回 HTTP 400 Bad Request。
示例
- /%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> }

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     XX 
这将暂停消息分析指定的毫秒数。超时可以以毫秒为单位指定,如果数字后带有单位后缀,则可以采用任何其他单位,如本文档顶部所述。也可以编写一个表达式,该表达式必须返回一个解释为毫秒超时的数字。如果表达式评估失败或返回无效值,则忽略该动作并继续评估。此动作可用于调试目的。但它也可以用于根据特定标准减缓某些客户端。例如,可以通过 "track-sc" 规则跟踪客户端来减缓请求率过高的客户端。
redirect <rule>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     XX 
这会根据重定向规则执行 HTTP 重定向。这与 "redirect" 语句完全相同,不同之处在于它插入的重定向规则在其他 "http-request" 或 "http-response" 规则中间处理,并且这些规则使用自定义日志格式。对于响应,只允许 "location" 类型的重定向。此外,当在响应期间执行重定向时,从服务器到 HAProxy 的传输会中断,以便不会将有效载荷转发给客户端。这可能会导致 HTTP/1 上的一些连接关闭。此动作是最终的,即对于当前部分,不会评估同一规则集中的其他规则。有关规则的语法,请参阅 "redirect" 关键字。

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
XXXXXX  
这会停止规则评估并立即关闭连接而不发送任何响应。对于 HTTP 规则,它的作用类似于 "tcp-request content reject" 规则。强制立即关闭 HTTP/2 连接可能很有用。在 "tcp-request connection" 规则中,被拒绝的连接甚至不会成为会话,这就是为什么它们在统计信息中单独计算为 "denied connections"。它们不被视为会话速率限制,也不会被记录。原因是这些规则只应用于过滤极高的连接速率,例如在大规模 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>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     XXX
此操作将标头字段 <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 # 应用于: Cookie: foo=foobar; expires=Tue, 14-Jun-2016 01:40:45 GMT; # 输出: Cookie: foo=foobar;ip=192.168.1.20; expires=Tue, 14-Jun-2016 01:40:45 GMT; # 假设后端 IP 是 192.168.1.20 http-request replace-header User-Agent curl foo # 应用于: User-Agent: curl/7.47.0 # 输出: User-Agent: foo
示例
http-response replace-header Set-Cookie (C=[^;]*);(.*) \1;ip=%bi;\2 # 应用于: Set-Cookie: C=1; expires=Tue, 14-Jun-2016 01:40:45 GMT # 输出: Set-Cookie: C=1;ip=192.168.1.20; expires=Tue, 14-Jun-2016 01:40:45 GMT # 假设后端 IP 是 192.168.1.20。
replace-path <match-regex> <replace-fmt>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     X  
此操作的工作方式类似于“replace-header”,但它作用于请求的路径部分,而不是标头。路径部分从可选的 scheme+authority 之后的第一个“/”开始,到问号之前结束。因此,替换不会修改 scheme、authority 和查询字符串。值得注意的是,正则表达式的评估可能比某些 ACL 更昂贵,因此对于罕见的替换,如果不匹配,使用条件来避免执行评估可能会更有利。
示例
# 在 /foo 前加上前缀:将 /bar?q=1 变为 /foo/bar?q=1: http-request replace-path (.*) /foo\1 # 去除 /foo:将 /foo/bar?q=1 变为 /bar?q=1 http-request replace-path /foo/(.*) /\1 # 或者如果只有部分请求匹配,这样更高效: http-request replace-path /foo/(.*) /\1 if { url_beg /foo/ }
replace-pathq <match-regex> <replace-fmt>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     X  
此操作与 "http-request replace-path" 相同,不同之处在于路径包含了查询字符串(如果存在)。因此,路径和查询字符串都会被替换。
示例
# 在路径后添加后缀 /foo:将 /bar?q=1 变为 /bar/foo?q=1: http-request replace-pathq ([^?]*)(\?(.*))? \1/foo\2
replace-uri <match-regex> <replace-fmt>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     X  
这类似于 "replace-header",但它作用于请求的 URI 部分而不是标头。URI 部分可能包含可选的方案、权威或查询字符串。这些被视为与匹配的值的一部分。值得注意的是,正则表达式的评估成本可能高于某些 ACL,因此罕见的替换可能受益于条件,以避免在不匹配时完全执行评估。重要说明:历史上在 HTTP/1.x 中,绝大多数浏览器发送的请求使用“origin form”,这与“absolute form”不同,因为它们在 URI 部分不包含方案或权威。大多数情况下,只有发送给代理的请求、手动伪造的请求以及某些应用程序发出的请求使用绝对形式。因此,"replace-uri" 通常在 HTTP/1.x 中使用以 "/" 开头的规则时工作正常。但是对于 HTTP/2,鼓励客户端仅发送绝对 URI,这些 URI 看起来像 HTTP/1 客户端用于与代理通信的 URI。因此,这些部分 replace-uri 规则在 HTTP/2 中可能会失败,而在 HTTP/1 中工作。要么需要调整规则以可选地匹配方案和权威,要么应使用 replace-path。
示例
# 将所有 "http" 绝对请求重写为 "https": http-request replace-uri ^http://(.*) https://\1 # 添加前缀 /foo:将 /bar?q=1 变为 /foo/bar?q=1: http-request replace-uri ([^/:]*://[^/]*)?(.*) \1/foo\2
replace-value <name> <match-regex> <replace-fmt>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     XXX
此操作的工作方式类似于“replace-header”,但它将正则表达式与标头字段 <name> 的每个逗号分隔的值进行匹配,而不是整个标头。这适用于所有允许携带多个值的标头。例如 Accept 请求标头,或者请求或响应的 Cache-Control。
示例
http-request replace-value X-Forwarded-For ^192\.168\.(.*)$ 172.16.\1 # 应用于: X-Forwarded-For: 192.168.10.1, 192.168.13.24, 10.0.0.37 # 输出: X-Forwarded-For: 172.16.10.1, 172.16.13.24, 10.0.0.37
示例
http-after-response replace-value Cache-control ^public$ private # 应用于: Cache-Control: max-age=3600, public # 输出: Cache-Control: max-age=3600, private
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 IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     XX 
这会停止规则评估并立即返回响应。用于响应的默认状态码是 200。它可以作为 "status" 的参数可选指定。响应内容类型也可以作为 "content-type" 的参数指定。最后,可以定义响应本身。它可以是指定要使用的 errorfile 的完整 HTTP 响应,也可以是指定要使用的文件或字符串的响应有效载荷。创建响应时遵循以下规则: * 如果未定义 errorfile 和要使用的有效载荷,则返回一个虚拟响应。仅考虑 "status" 参数。它可以是范围 [200, 599] 中的任何代码。如果存在 "content-type" 参数,则忽略它。 * 如果设置了 "default-errorfiles" 参数,则考虑代理的 errorfiles。如果定义了 "status" 参数,它必须是 HAProxy 处理的状态码之一(200、400、403、404、405、408、410、413、414、425、429、431、500、501、502、503 和 504)。如果存在 "content-type" 参数,则忽略它。 * 如果定义了特定的 errorfile,带有 "errorfile" 参数,则返回包含完整 HTTP 响应的相应文件。仅考虑 "status" 参数。它必须是 HAProxy 处理的状态码之一(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" 的参数。使用 "lf-string" 参数,字符串被评估为自定义日志格式(请参阅 第 8.2.6 节)。使用 "string" 参数,它被视为原始字符串。当响应不基于 errorfile 时,可以使用 "hdr" 参数将 HTTP 标头字段附加到响应。否则,忽略所有 "hdr" 参数。对于每个参数,标头名称在 <name> 中指定,其值由 <fmt> 定义,该 <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> }

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
 XXXXXXX
此动作将与由 <sc-id> 指定的粘性计数器关联的数组中索引 <idx> 处的通用计数器增加 <int> 整数值或表达式 <expr> 的整数评估值。整数和表达式限制为无符号 32 位值。如果发生错误,此动作将静默失败,并继续执行动作评估。<idx> 是 0 到 99 之间的整数,<sc-id> 是 0 到 2 之间的整数。如果在此索引处没有存储 GPC,它也会静默失败。即使值为零,表中的条目也会刷新。'gpc_rate' 会自动调整以反映 gpc 值的平均增长率。此动作仅适用于 'gpc' 和 'gpc_rate' 数组 data_types(而不适用于旧版 'gpc0'、'gpc1'、'gpc0_rate' 也不适用于 'gpc1_rate' data_types)。旧版数据类型没有等效函数,但如果值始终为 1,请参阅 'sc-inc-gpc()'、'sc-inc-gpc0()' 和 'sc-inc-gpc1()'。也无法递减该值,但可以使用 'sc-set-gpt()' 代替将精确值存储在通用标记中。此动作的主要用途是计算分数或总卷(例如,服务器或 WAF 报告的每个源 IP 的估计危险、上传的总字节数等)。
sc-inc-gpc(<idx>,<sc-id>)

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
 XXXXXXX
此操作将与由 <sc-id> 指定的粘性计数器关联的数组中,索引为 <idx> 的通用目的计数器(GPC)递增 1。如果发生错误,此操作将静默失败,并且操作评估继续。<idx> 是 0 到 99 之间的整数,<sc-id> 是 0 到 2 之间的整数。如果在此索引处没有存储 GPC,它也会静默失败。此操作仅适用于 'gpc' 和 'gpc_rate' 数组数据类型(不适用于旧的 'gpc0'、'gpc1'、'gpc0_rate' 或 'gpc1_rate' 数据类型)。
sc-inc-gpc0(<sc-id>)
sc-inc-gpc1(<sc-id>)

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
 XXXXXXX
此操作根据由 <sc-id> 指定的粘性计数器来递增 GPC0 或 GPC1 计数器。如果发生错误,此操作将静默失败,并且操作评估继续。
sc-set-gpt(<idx>,<sc-id>) { <int> | <expr> }

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
 XXXXXXX
此操作将与由 <sc-id> 指定的粘性计数器关联的数组中,索引为 <idx> 的 32 位无符号 GPT 设置为 <int>/<expr> 的值。预期结果是一个布尔值。如果发生错误,此操作将静默失败,并且操作评估继续。<idx> 是 0 到 99 之间的整数,<sc-id> 是 0 到 2 之间的整数。如果在此索引处没有存储 GPT,它也会静默失败。此操作仅适用于 'gpt' 数组数据类型(不适用于旧的 'gpt0' 数据类型)。
sc-set-gpt0(<sc-id>) { <int> | <expr> }

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
 XXXXXXX
此操作根据由 <sc-id> 指定的粘性计数器和 <int>/<expr> 的值来设置 32 位无符号 GPT0 标签。预期结果是一个布尔值。如果发生错误,此操作将静默失败,并且操作评估继续。此操作是 "sc-set-gpt(0,<sc-id>)" 的别名。另请参阅“sc-set-gpt”操作。

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
X       
此操作强制发送一个 Retry 数据包以响应没有 token 的客户端 Initial 数据包。这对于在实例化任何连接元素和开始握手之前确保客户端地址得到验证非常有用。
send-spoe-group <engine-name> <group-name>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
   XXXX 
此操作用于触发发送一组 SPOE 消息。为此,必须定义用于发送消息的 SPOE 引擎,以及要发送的 SPOE 组。当然,SPOE 引擎必须引用一个现有的 SPOE 过滤器。如果在 SPOE 过滤器行上未提供引擎名称,则必须使用 SPOE 代理名称。
参数
<engine-name> SPOE 引擎名称。 <group-name> 在引擎配置中指定的 SPOE 组名称。
set-bandwidth-limit <name> [limit {<expr> | <size>}] [period {<expr> | <time>}]

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
   XXXX 
此操作用于启用带宽限制过滤器 <name>,根据过滤器类型,可以在上传或下载方向上启用。如果且仅当 <name> 引用一个每流带宽限制过滤器时,可以定义自定义的限制和周期。当执行 set-bandwidth-limit 规则时,它首先将过滤器的所有设置重置为其默认值,然后再启用它。因此,如果对同一过滤器执行多个“set-bandwidth-limit”操作,则只有最后一个生效。可以在同一个流上启用多个带宽限制过滤器。请注意,此操作不能在 defaults 部分中使用,因为带宽限制过滤器不能在 defaults 部分中定义。此外,只限制 HTTP 负载传输。HTTP 标头不被考虑。
参数
<expr> 是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成。结果被转换为一个整数。对于 "limit" 参数,它被解释为以字节为单位的大小;对于 "period" 参数,它被解释为以毫秒为单位的持续时间。 <size> 是一个数字。它遵循 HAProxy 的大小格式,并以字节表示。 <time> 是一个数字。它遵循 HAProxy 的时间格式,并以毫秒表示。
示例
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> }

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
   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> }

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
   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>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
 XXX X  
此操作用于将目标 IP 地址设置为指定表达式的值。当 HAProxy 前面的代理重写了目标 IP,但在 HTTP 标头中提供了正确的 IP 时,或者您想为隐私目的屏蔽 IP 时,这很有用。如果要连接到新的地址/端口,请在后端中使用 '0.0.0.0:0' 作为服务器地址。
参数
<expr> 是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成。
示例
http-request set-dst hdr(x-dst) http-request set-dst dst,ipmask(24)
在可能的情况下,只要地址族允许,set-dst 会保留原始目标端口,否则目标端口将被设置为 0。

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
 XXX X  
此操作用于将目标端口地址设置为指定表达式的值。如果要连接到新的地址/端口,请在后端中使用 '0.0.0.0:0' 作为服务器地址。
参数
<expr> 是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成。
示例
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> }

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
 XXXXXX 
在支持此功能的平台上,此操作用于将所有发送到客户端的数据包上的 Netfilter/IPFW MARK 设置为 <mark> 或 <expr> 中传递的值。该值为一个无符号 32 位值,可以被 netfilter/ipfw 和路由表匹配,或通过 DTrace 监控数据包。<mark> 可以用十进制或十六进制格式(以 "0x" 为前缀)表示。或者,可以使用 <expr>:它是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成,必须解析为整数类型。此操作可用于强制某些数据包采用不同的路由(例如,对于大批量下载使用更便宜的网络路径)。此功能在 Linux 内核 2.6.32 及以上版本以及 FreeBSD 和 OpenBSD 上可用,并需要管理员权限。
set-fc-tos { <tos | <expr> }

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
 XXXXXX 
在支持此功能的平台上,此操作用于将发送到客户端的数据包的 TOS 或 DSCP 字段值设置为 <tos> 或 <expr> 中传递的值。该值表示 IP TOS 字段的整个 8 位。请注意,在 DSCP 或 TOS 中只使用较高的 6 位,较低的 2 位始终为 0。或者,可以使用 <expr>:它是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成,必须解析为整数类型。此操作可用于根据请求中的某些信息调整边界路由器的某些路由行为。有关更多信息,请参阅 RFC 2474、2597、3260 和 4594。
set-header <name> <fmt>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     XXX
此操作与“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]

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
   XXXXX
当满足某个条件时,此操作用于更改当前请求的日志级别。有效级别是 8 个 syslog 级别(参见“log”关键字)加上特殊级别 "silent",它会禁用此请求的日志记录。此规则不是最终的,因此最后一个匹配的规则获胜。此规则可用于禁用来自其他设备的健康检查。
set-map(<map-name>) <key fmt> <value fmt>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     XXX
此操作用于向 map 中添加一个新条目。<map-name> 必须遵循 2.7 节中关于 maps 和 ACLs 名称格式的描述。要更新的 MAP 名称在括号中传递。它接受 2 个参数:<key fmt>,遵循第 8.2.6 节中描述的自定义日志格式规则,用于收集 map 键;以及 <value fmt>,遵循自定义日志格式规则,用于收集新条目的内容。它在插入前会先在 map 中进行查找,以避免重复(或更多)的值。它等效于 stats socket 中的 "set map" 命令,但可以由 HTTP 请求触发。
set-mark <mark> (已弃用)
这是“set-fc-mark”的别名(应改用后者)。

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     X  
此操作使用格式化字符串 <fmt> 的求值结果来重写请求方法。这样做应该有极少数的正当理由,因为它更有可能破坏某些东西而不是修复它。
set-nice <nice>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
   XXXX 
这会设置当前正在处理的请求/响应的 "nice" 因子。它仅对同时处理的其他请求产生影响。默认值为 0,除非通过 "bind" 行上的 "nice" 设置进行更改。接受的范围是 -1024..1024。值越高,请求就越“nice”。较低的值将使请求比其他请求更重要。这对于提高某些请求的速度或降低不重要请求的优先级很有用。在没有事先试验的情况下使用此设置可能会导致严重的减速。
set-path <fmt>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     X  
此操作使用格式化字符串 <fmt> 的求值结果来重写请求路径。查询字符串(如果有)保持不变。如果在路径之前找到了 scheme 和 authority,它们也保持不变。如果请求没有路径("*"),则该路径将被格式替换。例如,这可以用于在路径前添加一个目录组件。另请参阅 "http-request set-query" 和 "http-request set-uri"。
Example
# 在路径前添加主机名 http-request set-path /%[hdr(host)]%[path]
set-pathq <fmt>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     X  
此操作与 "http-request set-path" 相同,不同之处在于查询字符串也被重写。它可用于移除查询字符串,包括问号(使用 "http-request set-query" 是不可能的)。

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
   X X  
此操作用于设置当前请求的队列优先级类别。该值必须是一个样本表达式,其转换结果为 -2047 到 2047 范围内的整数。超出此范围的结果将被截断。优先级类别决定了排队请求的处理顺序。值越低,优先级越高。

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
   X X  
此操作用于设置当前请求的队列优先级时间戳偏移量。该值必须是一个样本表达式,其转换结果为 -524287 到 524287 范围内的整数。超出此范围的结果将被截断。当一个请求进入队列时,它首先按优先级类别排序,然后按当前时间戳加上给定的偏移量(以毫秒为单位)进行排序。值越低,优先级越高。请注意,结果时间戳的跟踪精度仅足以表示 524,287 毫秒(8 分 44 秒 287 毫秒)。如果请求排队时间足够长,以至于调整后的时间戳超过此值,它将被错误地识别为最高优先级。因此,将“timeout queue”设置为一个值,使其与偏移量相加后不超过此限制,这一点很重要。
set-query <fmt>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     X  
此操作使用格式化字符串 <fmt> 的求值结果来重写请求中出现在第一个问号("?")之后的查询字符串。问号之前的部分保持不变。如果请求不包含问号且新值不为空,则会在 URI 的末尾添加一个问号,后跟新值。如果问号已存在,即使新值为空,它也永远不会被移除。这可以用于从查询字符串中添加或删除参数。另请参阅 "http-request set-path" 和 "http-request set-uri"。
示例
# 在查询字符串中将“%3D”替换为“=” http-request set-query %[query,regsub(%3D,=,g)]
set-retries <int> | <epxr>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
   X X  
此操作仅对当前流覆盖指定的“retries”值。它可以是一个整数值,范围在 [0, 100] 之间,也可以是一个表达式,其必须返回一个在 [0, 100] 范围内的整数。请注意,此操作仅在后端侧相关,因此该规则仅适用于具有后端能力的代理。它也不允许在 "defaults" 部分中使用。
示例
tcp-request content set-retries 3 http-request set-retries var(txn.retries)
set-src <expr>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
 XXX X  
此操作用于将源 IP 地址设置为指定表达式的值。当 HAProxy 前面的代理重写了源 IP,但在 HTTP 标头中提供了正确的 IP 时,或者您想为隐私目的屏蔽源 IP 时,这很有用。所有后续对“src”的提取调用都将返回此值(见示例)。
参数
<expr> 是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成。
另请参阅“option forwardfor”。
示例
http-request set-src hdr(x-forwarded-for) http-request set-src src,ipmask(24) # 经过掩码处理后,这将根据最后字节为零的 IP 地址来跟踪连接。 http-request track-sc0 src
在可能的情况下,只要地址族允许,set-src 会保留原始源端口,否则源端口将被设置为 0。

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
 XXX X  
此操作用于将源端口地址设置为指定表达式的值。
参数
<expr> 是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成。
示例
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>]

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
      XX
此操作将响应状态码替换为 <status>,该值必须是 100 到 999 之间的整数。可选地,可以提供由 <str> 定义的自定义原因文本,否则将使用指定代码的默认原因作为备选。请注意,原因字符串仅存在于 HTTP/1.x 中,并被其他协议版本忽略。
示例
# 返回“431 Request Header Fields Too Large” http-response set-status 431 # 返回“503 Slow Down”,自定义原因 http-response set-status 503 reason "Slow Down".
set-timeout { client | server | tunnel } { <timeout> | <expr> }

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     XX 
此动作仅为当前流覆盖指定的 "client"、"server" 或 "tunnel" 超时。超时可以以毫秒为单位指定,如果数字后带有单位后缀,则可以采用任何其他单位,如本文档顶部所述。也可以编写一个表达式,该表达式必须返回一个解释为毫秒超时的数字。请注意,服务器/隧道超时仅与后端相关,因此此规则仅适用于具有后端功能的代理。同样,客户端超时仅与前端相关。此外,超时值必须为非空才能获得预期结果。
示例
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)
set-tos <tos> (已弃用)
这是“set-fc-tos”的别名(应改用后者)。
set-uri <fmt>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     X  
此操作使用格式化字符串 <fmt> 的求值结果来重写请求 URI。scheme、authority、path 和查询字符串都会被一次性替换。这可以用于在代理前重写主机,或对 URI 进行复杂的修改,例如在路径和查询字符串之间移动部分。如果设置了绝对 URI,它将按原样发送到 HTTP/1.1 服务器。如果这不是期望的行为,则应分别设置主机、路径和/或查询字符串。另请参阅 "http-request set-path" 和 "http-request set-query"。
set-var(<var-name>[,<cond>...]) <expr>
set-var-fmt(<var-name>[,<cond>...]) <fmt>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
 XXXXXXX
此操作用于设置变量的内容。变量是内联声明的。
参数
<var-name> 变量的名称。不能设置父流的变量。有关变量的详细信息,请参见第 2.8 节。 <cond> 一组必须全部为真才能实际设置变量的条件(例如 "ifnotempty"、"ifgt" ...)。有关可能的条件的完整列表,请参阅 set-var 转换器的描述。 <expr> 是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成。 <fmt> 这是使用自定义日志格式规则表示的值(参见第 8.2.6 节中的自定义日志格式)。
所有作用域都可用于 HTTP 规则,但作用域“proc”和“sess”是唯一可在无法访问内容的规则集(如“tcp-request connection”和“tcp-request session”)中使用的作用域。
示例
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> ]

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
 XXXXXX 
这会停止规则评估,并使用一种依赖于系统的方式使面向客户端的连接突然消失,该方式试图防止客户端被通知。当调用时不带 rst-ttl 参数时,我们尝试使用 TCP_REPAIR 防止向客户端发送任何 FIN 或 RST 数据包。如果这失败(主要是因为缺少权限),我们会回退到发送一个 TTL 为 1 的 RST 数据包。效果是客户端仍然看到已建立的连接,而 HAProxy 上没有连接,从而节省了资源。然而,放置在 HAProxy 和客户端之间的有状态设备(防火墙、代理、负载均衡器)也会在其会话表中保留已建立的连接。可选的 rst-ttl 更改了此行为:不使用 TCP_REPAIR,而是发送具有可配置 TTL 的 RST 数据包。当设置为合理值时,RST 数据包会穿过本地基础架构,删除防火墙和其他系统中的连接,但在到达客户端之前消失。来自客户端的未来数据包将被前端设备丢弃。这些本地 RST 保护本地资源,但不保护客户端资源。除非完全理解这样做的后果,否则不得使用。
strict-mode { on | off }

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     XXX
此操作为后续规则启用或禁用严格重写模式。它不影响在其之前声明的规则,并且仅适用于对请求执行重写的规则。当启用严格模式时,任何重写失败都会触发内部错误。否则,此类错误将被静默忽略。严格重写模式的目的是使某些重写是可选的,而其他重写必须执行才能继续请求处理。默认情况下,严格重写模式是启用的。当规则集评估结束时,其值也会被重置。因此,例如,如果您在前端更改模式,当 HAProxy 开始后端规则评估时,默认模式将被恢复。
switch-mode http [ proto <name> ]

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
   X    
此操作用于执行连接升级。目前仅支持 HTTP 升级。协议可以可选地指定。此操作仅适用于具有前端能力的代理。连接升级会立即执行,后续的“tcp-request content”规则不会被评估。应优先使用此升级方法,而不是依赖后端模式的隐式方法。使用此方法时,可以在前端设置 HTTP 指令而不会有任何警告。如果执行了 HTTP 升级,这些指令将被有条件地评估。但是,仍然必须选择一个 HTTP 后端。将 HTTP 连接(无论是否升级)路由到 TCP 服务器仍然不受支持。有关 HTTP 升级的更多详细信息,请参见第 4 节关于代理的部分。
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 IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     X  
这会停止规则评估,并立即阻止请求,而不响应一段由 "timeout tarpit" 或 "timeout connect" 指定的延迟(如果未设置前者)。在此延迟之后,如果客户端仍处于连接状态,则返回响应,以便客户端不会怀疑它已被诱捕。日志将报告标志 "PT"。tarpit 规则的目标是在攻击期间减缓并发请求数量有限的机器人。它对非常笨拙的机器人非常有效,并且与 "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-sc1 <key> [table <table>]
track-sc2 <key> [table <table>]

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
 XXX XX 
这会启用从当前请求跟踪粘性计数器。这些规则不会停止评估,也不会更改默认动作。同一连接可以同时跟踪的计数器数量由全局 "tune.stick-counters" 设置设置,该设置默认为 MAX_SESS_STKCTR(如果在构建时设置,则在 haproxy -vv 中报告),默认值为 3,因此 track-sc 数字在 0 和 (tune.stick-counters-1) 之间。执行的第一个 "track-sc0" 规则将指定表的计数器作为第一组启用跟踪。执行的第一个 "track-sc1" 规则将指定表的计数器作为第二组启用跟踪。执行的第一个 "track-sc2" 规则将指定表的计数器作为第三组启用跟踪。建议的做法是使用第一组计数器用于每个前端计数器,使用第二组计数器用于每个后端计数器。但这只是一个指导方针,所有这些都可以在任何地方使用。
参数
<key> 是必需的,它是一个如 第 7.3 节 所述的样本表达式规则。它描述了传入连接、请求或响应的哪些元素将被分析、提取、组合,并用于选择更新哪个表条目的计数器。<table> 是一个可选的表,用于替代默认表,默认表是在当前代理中声明的 stick-table。所有匹配和更新该键的计数器都将在此表中进行,直到会话结束。
一旦执行了“track-sc*”规则,将在表中查找该键,如果未找到,则会为其分配一个条目。然后,在整个会话生命周期内都会保留一个指向该条目的指针,并且该条目的计数器会尽可能频繁地更新,即每当会话的计数器更新时,以及在会话结束时系统性地更新。计数器只为跟踪开始后发生的事件更新。作为一个例外,连接计数器和请求计数器会系统性地更新,以反映有用的信息。如果该条目跟踪并发连接计数器,只要该条目被跟踪,就会计为一个连接,并且在此期间该条目不会过期。跟踪计数器相比仅检查键值还提供了性能优势,因为对于所有使用它的 ACL 检查,都只执行一次表查找。
unset-var(<var-name>)

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
 XXXXXXX
这用于取消设置一个变量。有关 <var-name> 的详细信息,请参阅“set-var”操作。
示例
http-request unset-var(req.my_var)
use-service <service-name>

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
   X X  
此操作会执行配置的 TCP 或 HTTP 服务来响应请求,具体取决于它所在的规则集。该规则是最终的,即在同一规则集中不会再评估其他规则。服务可以选择发送任何有效响应来回复,也可以选择立即关闭连接而不发送任何响应。对于 HTTP 服务,有效响应需要是一个有效的 HTTP 响应。除了原生服务(例如用于 HTTP 服务的 Prometheus 导出器),还可以用 Lua 编写自定义的 TCP 和 HTTP 服务。
参数
<service-name> 是必需的。它是要调用的服务。
示例
http-request use-service prometheus-exporter if { path /metrics }
wait-for-body time <time> [ at-least <bytes> ]

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     XX 
这会延迟请求或响应的处理,直到发生以下条件之一:- 收到完整的请求体,此时处理正常进行。- 当给出 "at-least" 参数且 <bytes> 不为零时,已收到 <bytes> 字节的数据,此时处理正常进行。- 请求缓冲区已满,此时处理正常进行。此缓冲区的大小由“tune.bufsize”选项决定。- 请求等待时间超过 <time> 毫秒。在这种情况下,HAProxy 将向客户端响应 408 "Request Timeout" 错误并停止处理请求。请注意,如果其他任何条件先发生,即使尚未收到完整的请求体,此超时也不会发生。此操作可用作“option http-buffer-request”的替代品。
参数
<time> 是必需的。它是等待请求体的最长时间。它遵循 HAProxy 的时间格式,单位为毫秒。<bytes> 是可选的。它是停止等待所需的最小有效负载大小。它遵循 HAProxy 的大小格式,单位为字节。值为 0(默认值)表示没有限制。
示例
如果 METH_POST,则 http-request wait-for-body time 1s at-least 1k

可用范围

QUIC IniTCP RqConRqSesRqCntRsCntHTTP ReqResAft
     X  
这会延迟请求的处理,直到 SSL 握手完成。这主要用于延迟处理早期数据,直到我们确定它们是有效的。
关键字 "bind"、"server" 和 "default-server" 支持许多设置,具体取决于某些构建选项和构建 HAProxy 的系统。这些设置通常每个都包含一个单词,有时后跟一个值,写在与 "bind" 或 "server" 行相同的行上。所有这些选项都在本节中描述。

5.1. Bind 选项

bind”关键字支持许多设置,这些设置都作为参数在同一行上传递。这些参数出现的顺序无关紧要,只要它们出现在绑定地址之后即可。所有这些参数都是可选的。其中一些由单个单词组成(布尔值),而另一些则需要一个值。在这种情况下,值必须紧跟在设置名称之后。当前支持的设置如下。
accept-netscaler-cip <magic number>
强制在同一行上声明的任何 TCP 套接字接受的所有连接上使用 NetScaler 客户端 IP 插入协议。NetScaler 客户端 IP 插入协议规定了传入连接的第 3/4 层地址,这些地址将在任何使用地址的地方使用,唯一的例外是“tcp-request connection”规则,它只会看到真实的连接地址。日志将反映协议中指定的地址,除非协议被违反,在这种情况下仍将使用真实地址。此关键字与外部组件的支持相结合,可用作 X-Forwarded-For 机制的高效可靠的替代方案,后者并非总是可靠,甚至并非总是可用。另请参阅“tcp-request connection expect-netscaler-cip”,以更精细地设置允许使用该协议的客户端。
强制在由同一行上声明的任何套接字接受的任何连接上使用 PROXY 协议。PROXY 协议的版本 1 和 2 都受支持并能正确检测。PROXY 协议规定了传入连接的第 3/4 层地址,这些地址将在任何使用地址的地方使用,唯一的例外是 "tcp-request connection" 规则,它只会看到真实的连接地址。日志将反映协议中指示的地址,除非协议被违反,在这种情况下仍将使用真实地址。此关键字与外部组件的支持相结合,可以作为 X-Forwarded-For 机制的一种高效可靠的替代方案,该机制并非总是可靠,甚至并非总是可用。另请参阅 "tcp-request connection expect-proxy" 以更精细地设置允许哪些客户端使用该协议。
允许在使用 TLSv1.3 时接收早期数据。由于安全考虑,默认禁用此功能。因为它容易受到重放攻击,所以您应该只允许它用于可以安全重放的请求,即幂等请求。您可以使用 "wait-for-handshake" 动作处理任何使用早期数据不安全的请求。对于 QUIC,QuicTLS、OpenSSL >= 3.5.2 和 AWS-LC 支持 0rtt。对于 TCP/TLS,仅 OpenSSL 支持 0rtt,并且要求客户端发送 ALPN,否则在握手发生之前不会考虑早期数据。
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 扩展。在撰写本文时,大多数浏览器仍然支持 HTTP/2 的 ALPN 和 NPN,因此回退到 NPN 可能仍然有效一段时间。但应尽可能使用 ALPN。未宣传的协议不会被协商。例如,可以使用以下方式仅接受 HTTP/2 连接: bind :443 ssl crt pub.pem alpn h2 # 显式禁用 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/1.1" 或 "no-alpn" 来显式禁用 HTTP/2,或者全局启用 "h2-workaround-bogus-websocket-clients"。
backlog <backlog>
将套接字的 backlog 设置为此值。如果未指定或为 0,则使用前端的 backlog,通常默认为 maxconn 值。
ca-file <cafile>
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载验证客户端证书的 CA 证书。可以加载包含多个 CA 的目录,在这种情况下,HAProxy 将尝试加载目录中所有可用的“.pem”、“.crt”、“.cer”和“.crl”文件,以点开头的文件将被忽略。警告:可以使用“@system-ca”参数代替 cafile,以使用您系统的受信任 CA,就像 server 指令一样。但除非您知道自己在做什么,否则不应使用它。这样配置基本上意味着 bind 将接受由您系统上存在的任何 CA 生成的任何客户端证书,这是极其不安全的。
ca-ignore-err [all|<errorID>,...]
此设置仅在内置 OpenSSL 支持时可用。设置在深度 > 0 的验证期间要忽略的以逗号分隔的 errorID 列表。它可以是数字 ID,也可以是常量名称 (X509_V_ERR),可在 OpenSSL 文档中找到:https://www.openssl.org/docs/manmaster/man3/X509_STORE_CTX_get_error.html#ERROR-CODES 建议使用常量名称,因为数值在新版本的 OpenSSL 中可能会改变。如果设置为 'all',则忽略所有错误。如果忽略了某个错误,SSL 握手不会中止。
ca-sign-file <cafile>
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,其中包含用于创建和签署服务器证书的 CA 证书和 CA 私钥。当启用证书动态生成时,这是一个强制性设置。有关详细信息,请参见 'generate-certificates'。
ca-sign-pass <passphrase>
此设置仅在内置 OpenSSL 支持时可用。它是 CA 私钥的密码。此设置是可选的,仅在启用证书动态生成时使用。有关详细信息,请参见 'generate-certificates'。
此设置指定一个 PEM 文件,用于加载验证客户端证书的 CA 证书。它指定的 CA 证书不应包含在服务器 hello 消息中发送的 CA 名称中。通常,“ca-file”必须用中间证书定义,而“ca-verify-file”则用终止证书链的证书(如根 CA)定义。
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")。如果配置特定拥塞控制算法失败,默认算法将保持不变,并发出警告报告问题。
frontend public bind :443 cc bbr # 对高带宽使用 BBR 算法
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>
此设置仅在内置 OpenSSL 支持且使用 OpenSSL 1.1.1 或更高版本构建 HAProxy 时可用。它设置描述在 TLSv1.3 握手期间协商的密码算法("cipher suite")列表的字符串。字符串的格式在 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>
此设置仅在内置 OpenSSL 支持时可用。它设置描述与客户端身份验证相关的协商签名算法列表的字符串。该字符串的格式在 OpenSSL 手册页的“man 3 SSL_CTX_set1_client_sigalgs”中定义。如果没有确定特定的用例,不建议使用此设置。
crl-file <crlfile>
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载验证客户端证书的证书吊销列表。您需要为您证书颁发机构链中的每个证书提供一个证书吊销列表。
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 服务器名称指示字段(与其 CN 或 alt 主题之一匹配)的客户端。支持通配符,其中使用通配符字符 '*' 代替第一个主机名组件(例如 *.example.org 匹配 www.example.org,但不匹配 www.sub.example.org)。如果使用空目录,除非使用 "strict-sni" 关键字,否则 HAProxy 将不会启动。如果客户端未提供 SNI,或者 SSL 库不支持 TLS 扩展,或者客户端提供了与任何证书不匹配的 SNI 主机名,则将呈现第一个加载的证书。这意味着当从目录加载证书时,强烈建议首先将默认证书作为文件加载,或者确保它始终是目录中的第一个证书。为了选择多个默认证书(1 个 rsa 和 1 个 ecdsa),有 3 个选项: - 可以将多证书捆绑包配置为第一个证书(在配置中 `crt foobar.pem`,其中现有文件是 `foobar.pem.ecdsa` 和 `foobar.pem.rsa`。 - 或者 crt-list 行中每个证书的 '*' 过滤器。 - 可以使用 'default-crt' 关键字。请注意,同一证书可以多次加载而没有副作用。一些 CA(例如 GoDaddy)在获取证书时提供一个下拉列表,其中不包括 HAProxy 作为服务器类型。如果发生这种情况,请务必选择 CA 认为需要中间 CA 的 Web 服务器(对于 GoDaddy,选择 Apache Tomcat 将获得正确的捆绑包,但许多其他(例如 nginx)会导致错误的捆绑包,可能对某些客户端不起作用)。对于每个 PEM 文件,HAProxy 检查同一路径下是否存在后缀为 ".ocsp" 的文件。如果找到此类文件,则会自动启用对 TLS 证书状态请求扩展(也称为 "OCSP stapling")的支持。此文件的内容是可选的。如果非空,它必须包含 DER 格式的有效 OCSP 响应。为了有效,OCSP 响应必须符合以下规则:它必须指示良好状态,它必须是 PEM 文件证书的单个响应,并且它在添加时必须有效。如果不遵守这些规则,则忽略 OCSP 响应并发出警告。为了识别 OCSP 响应适用于哪个证书,需要颁发者的证书。如果在 PEM 文件中找不到颁发者的证书,如果存在,它将从与 PEM 文件后缀为 ".issuer" 的同一路径中的文件加载,否则将失败并显示错误。对于每个 PEM 文件,HAProxy 还会检查同一路径下是否存在后缀为 ".sctl" 的文件。如果找到此类文件,则启用证书透明度 (RFC6962) TLS 扩展的支持。解析文件以检查基本语法,但不验证任何签名。在某些情况下,需要支持多种密钥类型,例如 RSA 和 ECDSA,以用于提供给客户端的密码套件。这允许支持 EC 证书的客户端能够使用 EC 密码,同时支持较旧的仅 RSA 客户端。为了实现这一点,需要 OpenSSL 1.1.1,您可以通过为每种证书类型提供一个 crt 条目来配置此行为,或者像 HAProxy 1.8 之前要求的那样配置“证书捆绑包”。请参阅 "ssl-load-extra-files"。.
此设置仅在内置 OpenSSL 支持时可用。设置在深度 == 0 的验证期间要忽略的以逗号分隔的 errorID 列表。它可以是数字 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>
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件列表,其中包含可选的 ssl 配置和每个证书的 SNI 过滤器,每行的格式如下: <crtfile> [\[<sslbindconf> ...\]] [[!]<snifilter> ...] 空行以及以哈希 ('#') 开头的行将被忽略。crt-list 可以通过 stats socket 动态操作。(请参阅管理指南中的 "add ssl crt-list"、"del ssl crt-list"、"show ssl crt-list")。crt-list 通常是专用文件,但是使用 "crt" 指令加载的目录在内部表示为 crt-list。前端中的 "ssl-f-use" 指令也声明了一个链接到此前端的 crt-list。crtfile: 这是证书的文件名,或者如果它在其他地方声明(例如通过 CLI 或在 crt-store 中使用别名),则为标识符。可以在多行上使用相同的 <crtfile>,但使用不同的选项和过滤器。crt-list 中支持多证书捆绑包(请参阅 "ssl-load-extra-files"),只要在 <crtfile> 中给出基本名称即可。HAProxy 将在内部复制 crt-list 行,在加载文件时添加算法扩展名 (.rsa, .ecdsa, .dsa)。sslbindconf: <sslbindconf> 支持来自 bind 行的以下关键字(请参阅第 5.1 节。绑定选项): - 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> 还支持来自 crt-store load 关键字的以下关键字(请参阅第 12.7.1 节。加载选项): - crt - key - ocsp - issuer - sctl - ocsp-update bind 行中的参数在 <sslbindconf> 中继承,如果未指定任何参数,则继承默认选项,<sslbindconf> 中指定的参数会覆盖那些继承的设置。snifilter: 当在 crt-list 行上使用 <snifilter> 参数时,在握手期间不再使用 CN 和 SAN 来选择此行上的证书,而是使用 <snifilter>。<snifilter> 是由空格分隔的条目列表。此列表可以包含域或通配符。通配符采用通配符 DNS 格式,使用单个星号作为条目的第一个字符。可以通过指定单个域前的 '!' 来从通配符中排除域。在 '*' 前面有 '!' 将被忽略。在同一行上没有通配符的负面过滤器也不受支持。特殊条目 '*' 用于指定默认证书,当没有域匹配时,它用作回退。证书将呈现给提供有效 TLS 服务器名称指示字段(与 SNI 过滤器之一匹配)的客户端,或 <crtfile> 的 CN 和 SAN。匹配算法首先在列表中查找正向域条目,如果未找到,它将尝试在列表中查找通配符。如果通配符匹配,haproxy 会检查同一行中的负面过滤器,并在必要时取消匹配。在有多个密钥算法(RSA、ECDSA、DSA)的情况下,HAProxy 将尝试匹配每种类型的一个证书,并根据客户端支持的内容选择正确的证书。如果客户端未提供 SNI,或者没有证书匹配,这将回退到默认证书之一。要禁用默认证书回退,可以使用 'strict-sni' 选项。当定义了多个默认证书时,HAProxy 能够根据客户端支持的内容选择正确的 ECDSA 或 RSA 证书。bind 行上声明的第一个证书(无论是来自 crt 还是 crt-list 选项)都用作默认证书。也可以声明 '*' 过滤器,它将此证书添加到默认证书列表中。为了澄清配置,默认证书可以在列表开头显式(带有 '*' 过滤器),因此不会在前面添加隐式默认证书。由于多证书捆绑包在 crt-list 中为每种算法重复,因此只有一个算法会占据 crt-list 中的第一行并被视为默认值。要么通过声明 '*' 作为过滤器或在 bind 行上设置它来将整个捆绑包指定为默认值。stats socket 上的 "show ssl sni" 命令可用于调试您的配置。(请参阅管理指南中的 "show ssl sni")。
示例
# 注释 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
此选项与 "crt" 选项相同,不同之处在于此证书也将用作默认证书。可以添加多个默认证书以拥有一个 ECDSA 和一个 RSA 证书,拥有更多证书并不是很有用。此选项不会禁用隐式默认证书,如果首先声明 'crt' 证书,在任何 'default-crt' 或其他 'crt' 之前,它仍将用作默认证书。当 bind 行上未使用 "strict-sni" 选项时,将使用默认证书。当客户端未使用 servername 扩展名,或者 servername 与任何配置的证书不匹配时,将提供默认证书。
示例
# 此 bind 行有 2 个默认证书 bind *:443 default-crt foobar.pem.rsa default-crt foobar.pem.ecdsa crt website.pem.rsa # 此 bind 行有 3 个默认证书 bind *:443 crt website.pem.rsa default-crt foobar.pem.rsa default-crt foobar.pem.ecdsa
另请参阅“crt”关键字。
curves <curves>
此设置仅在内置 OpenSSL 支持时可用。它设置描述在与 ECDHE 的 SSL/TLS 握手期间协商的椭圆曲线算法列表(“曲线套件”)的字符串。该字符串的格式是以冒号分隔的曲线名称列表。
示例
"X25519:P-256" (不带引号)
当设置了“curves”时,会忽略“ecdhe”参数。
是一个可选关键字,仅在某些 Linux 内核上受支持。它规定只有在连接上有数据到达时,或者最坏情况下在第一次重传后,才会接受连接。这只应在客户端首先发言的协议(例如 HTTP)上使用。它可以通过确保在接受连接时大部分请求已经可用,从而略微提高性能。另一方面,它将无法检测到不发言的连接。重要的是要注意,此选项在所有 2.6.31 之前的内核中都是有问题的,因为在客户端发言之前连接永远不会被接受。这可能会导致前端防火墙出现问题,前端防火墙会看到一个已建立的连接,而代理只会看到它处于 SYN_RECV 状态。此选项仅在 TCPv4/TCPv6 套接字上受支持,其他套接字会忽略它。
ecdhe <named curve>
此设置仅在内置 OpenSSL 支持时可用。它设置用于生成 ECDH 临时密钥的命名曲线(RFC 4492)。默认情况下,使用的命名曲线是 prime256v1。
ech <dir> [ EXPERIMENTAL ]
将 <dir> 中的所有 ECH 密钥应用于 bind 行。文件必须具有 .ech 扩展名,并且必须使用 PEM 文件格式用于 ECH。(https://datatracker.ietf.org/doc/draft-farrell-tls-pemesni/)此关键字以共享模式启用 ECH,HAProxy 既充当 TLS 端点又充当 ECH 端点。请参阅 https://datatracker.ietf.org/doc/draft-ietf-tls-esni/ 这是一个实验性功能,需要全局部分中的 "expose-experimental-directives" 选项。它还需要支持 ECH 的 OpenSSL 版本,并且 HAProxy 必须使用 USE_ECH=1 编译。
示例
$ 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
此选项仅可与 stats 套接字一起使用。它使您的 stats 套接字能够将侦听器 FD 传递给另一个 HAProxy 进程。在 master-worker 模式下,不再需要此功能,侦听器将通过 master 和 worker 之间的内部套接字对进行传递。另请参阅管理指南中的“-x”。
此选项强制此监听器实例化的 SSL 连接仅使用 SSLv3。对于高连接速率,SSLv3 通常比 TLS 对应项开销更低。此选项也可用于全局语句“ssl-default-bind-options”。另请参阅“ssl-min-ver”和“ssl-max-ver”。
此选项强制此监听器实例化的 SSL 连接仅使用 TLSv1.0。此选项也可用于全局语句“ssl-default-bind-options”。另请参阅“ssl-min-ver”和“ssl-max-ver”。
此选项强制此监听器实例化的 SSL 连接仅使用 TLSv1.1。此选项也可用于全局语句“ssl-default-bind-options”。另请参阅“ssl-min-ver”和“ssl-max-ver”。
此选项强制此监听器实例化的 SSL 连接仅使用 TLSv1.2。此选项也可用于全局语句“ssl-default-bind-options”。另请参阅“ssl-min-ver”和“ssl-max-ver”。
此选项强制此监听器实例化的 SSL 连接仅使用 TLSv1.3。此选项也可用于全局语句“ssl-default-bind-options”。另请参阅“ssl-min-ver”和“ssl-max-ver”。
此设置仅在内置 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>
将 UNIX 套接字的组设置为指定的系统 gid。它也可以在全局部分的“unix-bind”语句中默认设置。请注意,某些平台会直接忽略此设置。此设置与“group”设置等效,不同之处在于使用的是组 ID 而不是其名称。非 UNIX 套接字会忽略此设置。
group <group>
将 UNIX 套接字的组设置为指定的系统组。也可以在全局部分的 "unix-bind" 语句中默认设置。请注意,某些平台会直接忽略此设置。此设置与 "gid" 设置等效,不同之处在于它使用组名而不是组 ID。此设置对非 UNIX 套接字无效。
guid-prefix <string>
为此绑定行上分配的每个监听套接字生成区分大小写的全局唯一 ID。前缀将与当前绑定行上的监听器位置索引连接起来,并以字符“-”作为分隔符。有关其格式的更多信息,请参阅“guid”代理关键字描述。另请参阅“shm-stats-file”。
id <id>
固定套接字 ID。默认情况下,套接字 ID 是自动分配的,但有时为了方便监控而固定它们会更方便。此值必须是严格正数,并且在侦听器/前端内是唯一的。此选项只能在定义单个套接字时使用。
idle-ping <delay>
可在以下上下文中使用:tcp、http、log。定义对空闲前端连接进行定期活动性检查的间隔。如果对等方无法在下一次计划的测试前响应,则连接将关闭。否则,客户端超时将刷新,并保持连接。请注意,http-request/http-keep-alive 计时器并行运行,不会被 idle-ping 刷新。此功能依赖于特定的底层协议支持。目前,只有 H2 多路复用实现了它。idle-ping 被其他协议直接忽略。此选项在使用反向 HTTP 时特别有用。在 bind 行上设置它对于负责主动发起连接并随后通过这些连接接收传入流量的对等方很有用。
interface <interface>
将套接字限制到特定接口。指定后,只有从该特定接口接收的数据包才会由套接字处理。目前仅在 Linux 上受支持。该接口必须是主系统接口,而不是别名接口。如果多个前端绑定到不同的接口,也可以将它们绑定到同一地址。请注意,绑定到网络接口需要 root 权限。此参数仅与 TCPv4/TCPv6 套接字兼容。指定后,返回流量将使用与入站流量相同的接口及其关联的路由表,即使配置了通过不同接口的显式路由也是如此。当同一客户端 IP 地址需要能够访问托管在不同接口上的前端时,这对于解决非对称路由问题非常有用。
ktls <on|off> [ 实验性 ]
为此类套接字启用或禁用 ktls。如果启用,如果内核支持且密码兼容,将使用 kTLS。这仅在 Linux 内核 4.17 及更高版本上可用。
label <label>
为这些套接字设置一个可选标签。它可以用于按标签对套接字进行分组,而与 bind 行的声明位置无关。
level <level>
此设置仅用于 stats 套接字,用于限制可在套接字上发出的命令的性质。其他套接字会忽略此设置。<level> 可以是以下之一: - “user”是权限最低的级别;只能读取非敏感统计数据,不允许更改。在不容易限制对套接字访问的系统上,这很有意义。 - “operator”是默认级别,适用于大多数常见用途。可以读取所有数据,并且只允许进行非敏感更改(例如清除最大计数器)。 - “admin”应谨慎使用,因为它允许执行所有操作(例如清除所有计数器)。
maxconn <maxconn>
将套接字限制为此数量的并发连接。多余的连接将保留在系统的 backlog 中,直到释放一个连接。如果未指定,限制将与前端的 maxconn 相同。请注意,在端口范围或多个地址的情况下,相同的值将应用于每个套接字。此设置允许对昂贵的套接字进行不同的限制,例如 SSL 条目,它们很容易耗尽所有内存。
mode <mode>
设置用于定义 UNIX 套接字访问权限的八进制模式。也可以在全局部分的 "unix-bind" 语句中默认设置。请注意,某些平台会直接忽略此设置。此设置对非 UNIX 套接字无效。
mss <maxseg>
设置要在传入连接上通告的 TCP 最大段大小(MSS)值。这可用于为某些特定端口强制使用较低的 MSS,例如用于通过 VPN 的连接。请注意,这依赖于一个内核功能,理论上在 Linux 下受支持,但在 2.6.28 之前的所有版本中都有错误。它可能在其他操作系统上工作,也可能不工作。它也可能不改变通告的值,而是改变传出段的有效大小。在以太网网络上,TCPv4 的通常通告值为 1460 = 1500(MTU) - 40(IP+TCP)。如果此值为正,它将用作通告的 MSS。如果为负,它将指示传出段应比传入连接的通告 MSS 减少多少。此参数仅与 TCP v4/v6 套接字兼容。
name <name>
为这些套接字设置一个可选名称,该名称将在统计页面上报告。
namespace <name>
在 Linux 上,可以指定套接字将属于哪个网络命名空间。此指令使得可以显式地将侦听器绑定到不同于默认命名空间的命名空间。请参考您的操作系统文档以了解有关网络命名空间的更多详细信息。
nbconn <nbconn> [ 实验性 ]
此设置仅对使用反向 HTTP 的侦听器实例有效。这将定义将并行建立的连接数。如果未指定,则使用默认值 1。反向 HTTP 目前仍在积极开发中。配置机制将来可能会改变。因此,它在内部被标记为实验性,这意味着在使用此指令之前必须在一行上出现“expose-experimental-directives”。
nice <nice>
设置从套接字发起的连接的“友好度”(niceness)。值必须在 -1024 到 1024(含)之间,默认为零。正值意味着此类连接对其他连接更友好,并且容易在调度器中让出位置。相反,负值意味着连接希望以比其他连接更高的优先级运行。这种差异仅在高负载下,当系统接近饱和时才会发生。负值适用于低延迟或管理服务,而高值通常推荐用于 CPU 密集型任务,如 SSL 处理或对延迟不那么敏感的批量传输。例如,为 SMTP 套接字使用正值,为 RDP 套接字使用负值可能是有意义的。
禁用 ALPN 处理(从技术上讲,此操作将 ALPN 字符串设置为空字符串,该字符串将不会被通告)。它允许取消先前出现的“alpn”设置并禁用应用协议协商。它还可用于防止监听器在 HTTPS 或 QUIC 监听器上与客户端协商 ALPN;默认情况下,HTTPS 监听器将通告“h2,http/1.1”,QUIC 监听器将通告“h3”。另请参阅上面的“alpn”。请注意,使用“crt-list”时,证书可能会覆盖“alpn”设置并重新启用其处理。
此设置仅在内置 OpenSSL 支持时可用。它在使用 ca-file 时阻止在服务器 hello 消息中发送 CA 名称。请使用“ca-verify-file”代替带有“no-ca-names”的“ca-file”。
此设置仅在内置 OpenSSL 支持时可用。当支持 SSL 时,它会禁用从此监听器实例化的任何套接字上的 SSLv3 支持。请注意,SSLv2 在代码中被强制禁用,无法使用任何配置选项启用。此选项也可用于全局语句“ssl-default-bind-options”。请改用“ssl-min-ver”和“ssl-max-ver”。
此设置仅在内置 OpenSSL 支持时可用。它禁用先前“strict-sni”指令强制执行的 strict-sni。当通过“ssl-default-bind-options”全局强制执行时,可能需要在一个“bind”行上有选择地禁用 strict-sni 的使用。另请参阅“strict-sni” bind 选项。
此设置仅在内置 OpenSSL 支持时可用。它禁用无状态会话恢复(RFC 5077 TLS Ticket 扩展)并强制使用有状态会话恢复。无状态会话恢复在 CPU 使用方面成本更高。此选项在全局语句“ssl-default-bind-options”中也可用。TLS ticket 机制仅用于 TLS 1.2 及以下版本。除非定期轮换 ticket 密钥(通过 reload 或使用“tls-ticket-keys”),否则使用 TLS ticket 会损害前向保密性。
此设置仅在内置 OpenSSL 支持时可用。当支持 SSL 时,它会禁用从此监听器实例化的任何套接字上的 TLSv1.0 支持。请注意,SSLv2 在代码中被强制禁用,无法使用任何配置选项启用。此选项也可用于全局语句“ssl-default-bind-options”。请改用“ssl-min-ver”和“ssl-max-ver”。
此设置仅在内置 OpenSSL 支持时可用。当支持 SSL 时,它会禁用从此监听器实例化的任何套接字上的 TLSv1.1 支持。请注意,SSLv2 在代码中被强制禁用,无法使用任何配置选项启用。此选项也可用于全局语句“ssl-default-bind-options”。请改用“ssl-min-ver”和“ssl-max-ver”。
此设置仅在内置 OpenSSL 支持时可用。当支持 SSL 时,它会禁用从此监听器实例化的任何套接字上的 TLSv1.2 支持。请注意,SSLv2 在代码中被强制禁用,无法使用任何配置选项启用。此选项也可用于全局语句“ssl-default-bind-options”。请改用“ssl-min-ver”和“ssl-max-ver”。
此设置仅在内置 OpenSSL 支持时可用。当支持 SSL 时,它会禁用从此监听器实例化的任何套接字上的 TLSv1.3 支持。请注意,SSLv2 在代码中被强制禁用,无法使用任何配置选项启用。此选项也可用于全局语句“ssl-default-bind-options”。请改用“ssl-min-ver”和“ssl-max-ver”。
npn <protocols>
此选项启用 NPN TLS 扩展,并通告指定的协议列表支持 NPN。协议列表由逗号分隔的协议名称列表组成,例如:“http/1.1,http/1.0”(不带引号)。这需要构建 SSL 库时启用 TLS 扩展支持(使用 haproxy -vv 检查)。请注意,NPN 扩展已被 ALPN 扩展取代(请参阅“alpn”关键字),尽管此关键字仅从 OpenSSL 1.0.2 开始可用。如果希望在较旧版本的 OpenSSL 上使用 HTTP/2,NPN 仍可能被使用,因为在撰写本文时,大多数客户端仍支持它。可以同时启用 NPN 和 ALPN,尽管除了测试之外可能没有任何意义。
在选择密码套件时使用客户端的偏好,默认情况下强制使用服务器的偏好。此选项也适用于全局语句“ssl-default-bind-options”。请注意,对于 OpenSSL >= 1.1.1,如果 ChaCha20-Poly1305 密码套件位于客户端密码列表的顶部,ChaCha20-Poly1305 无论如何都会被重新优先排序(无需设置此选项)。当使用双算法设置(RSA + ECDSA)时,选择算法将在 RSA 和 ECDSA 之间进行选择,并始终优先选择 ECDSA。一旦选择了正确的证书,它将让 SSL 库优先选择密码套件、曲线等。这意味着此选项不能用于优先选择 RSA 证书而非 ECDSA 证书。
proto <name>
强制多路复用器的协议用于传入连接。它必须与前端模式(TCP 或 HTTP)兼容。它还必须可在前端使用。可用协议列表在 haproxy -vv 中报告。报告了协议属性:模式 (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 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”。
quic-cc-algo { cubic | newreno | bbr | nocc }[(<args,...>)]
这是一个 QUIC 特定设置,用于为尝试连接到配置的 QUIC 监听器的任何连接选择拥塞控制算法。它们类似于 TCP 使用的算法。在拥塞算法之上激活了Pacing,以减少损耗并提高吞吐量。它可以通过全局关键字“tune.quic.fe.tx.pacing”关闭。在大多数情况下,Pacing应保持激活状态,尤其是在使用 BBR 时,因为它依赖于 Pacing才能按预期工作。在没有 Pacing的情况下使用 BBR 可能会导致传输过程中速度变慢或高损耗率。默认值:cubic 对于进一步的自定义,可以在算法令牌后指定参数列表。它必须写在括号之间,并用逗号分隔。每个参数都是可选的,如果需要可以为空。以下是每个参数的强制顺序: - 最大窗口大小(以字节为单位)。它必须大于 10k 且小于 4g。默认情况下,使用“tune.quic.fe.cc.max-win-size”值。
示例
# newreno 拥塞控制算法 quic-cc-algo newreno # cubic 拥塞控制算法,窗口大小为 1MB quic-cc-algo cubic(1m)
可以使用一个特殊值“nocc”来强制使用一个始终设置为最大尺寸的固定拥塞窗口。这保留用于调试场景,以消除拥塞控制器引起的任何副作用。它绝不能在生产环境中使用,因为它可能很快导致网络问题,如高丢包率。
这是一个 QUIC 特定设置,强制对尝试连接到配置的 QUIC 监听器的所有连接使用 QUIC 重试功能。它包括验证对等方能够在其用于发起新连接的传输地址上接收数据包,向它们发送包含令牌的重试数据包。此令牌必须返回给重试数据包发送方,后者是唯一能够验证令牌的一方。请注意,即使设置了重试阈值(请参阅“tune.quic.fe.sec.retry-threshold”设置),QUIC 重试也将始终使用。此设置要求设置集群密钥,否则启动时将报告错误(请参阅“cluster-secret”)。有关 QUIC 重试的更多信息,请参阅 https://www.rfc-editor.org/rfc/rfc9000.html#section-8.1.2。
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”,则将忽略单个监听器配置。
此设置仅与 stats 套接字一起使用,用于配置附加到信息反馈消息前的严重性级别输出。消息的严重性级别范围可以在 0 到 7 之间,符合 syslog rfc5424。请求数据的有效且成功的套接字命令(例如“show map”、“get acl foo”等)绝不会附加严重性级别。其他套接字会忽略此设置。<format> 可以是以下之一:- “none”(默认)不向反馈消息前附加严重性级别。- “number” 严重性级别作为数字附加。- “string” 严重性级别作为遵循 rfc5424 约定的字符串附加。
shards { <number> | by-thread | by-group }
在多线程模式下,在支持同一 IP:port 上多个监听器的操作系统上,这将自动为此行创建此数量的多个相同监听器,所有这些监听器都绑定到附加到此监听器的线程数的公平份额。当使用非常大的线程数时,单个套接字上的内核内锁定开始导致显著开销时,这有时会很有用。在这种情况下,传入流量分布在多个套接字上,并且争用减少。请注意,这样做很容易通过使更多线程工作来增加 CPU 使用率。如果分片数量高于可用线程数,它将自动修剪为线程数(即每个线程一个分片)。特殊值“by-thread”也会在“bind”行上创建与线程数一样多的分片。由于系统将在所有这些分片之间平均分配传入流量,因此此数字是线程数的整数除数非常重要。或者,另一个特殊值“by-group”将为每个线程组创建一个分片。这在处理许多线程且不希望创建太多套接字时非常有用。负载分配会稍微不那么理想,但争用(尤其是在系统中)仍会低于单个套接字。在不支持绑定到同一地址的多个套接字的操作系统上,“by-thread”和“by-group”将自动回退到单个分片。对于“by-group”,这是在没有任何警告的情况下完成的,因为它不会改变单个组的任何内容,并且无论如何都会导致套接字为每个组重复。但是,对于“by-thread”,如果发生这种情况,将发出诊断警告,因为生成的监听器数量将不是预期的数量。
sigalgs <sigalgs>
此设置仅在内置 OpenSSL 支持时可用。它设置一个字符串,描述在 TLSv1.2 和 TLSv1.3 握手期间协商的签名算法列表。字符串的格式在 OpenSSL 手册页的“man 3 SSL_CTX_set1_sigalgs”中定义。不建议使用此设置,除非需要与中间件兼容。
此设置仅在内置 OpenSSL 支持时可用。它在此监听器实例化的连接上启用 SSL 解密。需要一个证书(参见上面的“crt”)。缓冲区中的所有内容都将以明文形式出现,因此 ACL 和 HTTP 处理将只能访问解密后的内容。SSLv3 默认被禁用,使用“ssl-min-ver SSLv3”来启用它。
ssl-max-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]
此选项强制此监听器实例化的 SSL 连接使用 <version> 或更低版本。在不使用“ssl-min-ver”的情况下使用此设置可能会产生歧义,因为默认 ssl-min-ver 值在未来的 HAProxy 版本中可能会更改。此选项也可用于全局语句“ssl-default-bind-options”。另请参阅“ssl-min-ver”。
ssl-min-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]
此选项强制在此监听器实例化的 SSL 连接上使用 <version> 或更高版本。默认值为“TLSv1.2”。此选项也适用于全局语句“ssl-default-bind-options”。另请参见“ssl-max-ver”。
此设置仅在内置 OpenSSL 支持时可用。仅当客户端提供的 SNI 与证书匹配时才允许 SSL/TLS 协商。不使用默认证书。此选项还允许在绑定行上不带任何证书启动,因此可以使用空目录,稍后从 stats 套接字填充。此选项也可用于全局语句“ssl-default-bind-options”,并可通过在“bind”行上使用“no-strict-sni”来选择性禁用。有关更多信息,请参阅“crt”选项。请参阅管理指南中的“add ssl crt-list”命令。
tcp-md5sig <password>
为从此监听套接字实例化的所有传入连接启用 TCP MD5 签名(RFC 2385 通过 TCP MD5 签名选项保护 BGP 会话)。此选项仅在 Linux 上可用。启用后,<password> 字符串用于使用 16 字节 MD5 摘要对每个 TCP 段进行签名。这将保护 TCP 连接免受欺骗。此选项的主要用例是允许 BGP 保护自身免受欺骗 TCP 段引入连接流的影响。但它对于任何非常长寿命的 TCP 连接都可能有用。
tcp-ut <delay>
为从此监听套接字实例化的所有传入连接设置 TCP 用户超时。此选项自 Linux 2.6.37 版本起可用。它允许 HAProxy 为包含未在配置的延迟内收到确认的数据的套接字配置超时。这对于经历长空闲期的长连接(例如远程终端或数据库连接池)特别有用,其中客户端和服务器超时必须保持较高以允许长时间的空闲,但同时检测客户端是否已消失以释放与其连接(及服务器会话)相关的所有资源又非常重要。参数是一个以毫秒为单位的延迟,默认情况下。这仅适用于常规 TCP 连接,对其他协议无效。
是一个可选关键字,仅在 Linux 内核版本 >= 3.7 上受支持。它在监听套接字上启用 TCP 快速打开(TCP Fast Open),这意味着支持此功能的客户端将能够在第二次连接开始的三次握手期间发送请求并接收响应,从而在第一次连接后节省一次往返时间。这仅对连接率高且每次往返都很重要的协议有意义。这可能会导致许多防火墙出现问题,因为它们不接受 SYN 数据包上的数据,因此只应在经过充分测试后才启用此选项。此选项仅在 TCPv4/TCPv6 套接字上受支持,并被其他套接字忽略。如果您的 libc 未定义 TCP_FASTOPEN,您可能需要使用 USE_TFO=1 来构建 HAProxy。
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”,它们甚至会有一个专用的 stats 条目。主要目的是让多个绑定行共享相同的 IP:port,但在监听器中不共享同一线程,以便系统可以将传入连接分配到多个队列中,从而绕过 haproxy 的内部队列负载平衡。目前已知 Linux 3.9 及更高版本支持此功能。另请参阅上面的“shards”关键字,该关键字可自动复制“bind”行并将其分配给多个线程组。此关键字与反向 HTTP 绑定兼容。但是,对于此类监听器,禁止指定跨越多个线程组的线程集,因为这可能导致“nbconn”无法按预期工作。
此设置仅在内置 OpenSSL 支持时可用。它启用无状态会话恢复(RFC 5077 TLS Ticket 扩展)。它是默认设置,但如果通过“no-tls-tickets”(在“ssl-default-bind-options”中提及)全局禁用此功能,则可能需要选择性地在“bind”行上重新启用此功能。另请参阅“no-tls-tickets”绑定关键字。
tls-ticket-keys <keyfile>
设置从中加载密钥的 TLS 票证密钥文件。根据使用 aes128 还是 aes256,密钥需要是 48 或 80 字节长,并使用 base64 编码,每行一个密钥(例如 openssl rand 80 | openssl base64 -A | xargs echo)。第一个密钥决定了后续密钥使用的密钥长度:您不能混合使用 aes128 和 aes256 密钥。密钥数量由 TLS_TICKETS_NO 构建选项指定(默认为 3),文件中至少需要存在同样数量的密钥。最后的 TLS_TICKETS_NO 个密钥将用于解密,倒数第二个密钥用于加密。这通过简单地将新密钥追加到文件并重新加载进程来实现轻松的密钥轮换。密钥必须定期轮换(例如每 12 小时),否则完美前向保密性会受到损害。将密钥远离任何永久性存储设备(如硬盘)也是一个好主意(提示:使用 tmpfs 并且不要交换这些文件)。生命周期提示可以使用 tune.ssl.timeout 进行更改。
是一个可选关键字,仅在某些 Linux 内核上受支持。它表示即使地址不属于本地机器,也会绑定这些地址,并且目标为这些地址的数据包将被截获,就好像这些地址是本地配置的一样。这通常需要启用 IP 转发。注意!不要将此与默认地址 '*' 一起使用,因为它会重定向指定端口的所有流量。此关键字仅在 HAProxy 使用 USE_LINUX_TPROXY=1 构建时可用。此参数仅与 TCPv4 和 TCPv6 套接字兼容,具体取决于内核版本。一些发行版的内核包含该功能的向后移植版本,因此请向您的供应商查询支持情况。
uid <uid>
将 UNIX 套接字的属主设置为指定的系统 uid。它也可以在全局部分的“unix-bind”语句中默认设置。请注意,某些平台会直接忽略此设置。此设置与“user”设置等效,不同之处在于使用的是用户数字 ID 而不是其名称。非 UNIX 套接字会忽略此设置。
user <user>
将 UNIX 套接字的所有者设置为指定的系统用户。它也可以在全局部分的“unix-bind”语句中默认设置。请注意,某些平台会直接忽略此设置。此设置与“uid”设置等效,不同之处在于使用的是用户名而不是其 uid。此设置被非 UNIX 套接字忽略。
是一个可选关键字,仅在包括 Linux 内核版本 >= 2.4.21 在内的大多数最新系统上受支持。它用于在使用默认地址时将套接字同时绑定到 IPv4 和 IPv6。在默认情况下仅绑定到 IPv6 的系统上,这样做有时是必要的。它对非 IPv6 套接字没有影响,并被“v6only”选项覆盖。
是一个可选关键字,仅在包括 Linux 内核版本 >= 2.4.21 在内的大多数最新系统上受支持。它用于在使用默认地址时将套接字仅绑定到 IPv6。这样做有时比系统范围的设置更受欢迎,因为它是针对每个监听器的。它对非 IPv6 套接字没有影响,并优先于“v4v6”选项。
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”关键字支持一定数量的设置,所有这些设置都作为参数在服务器行上传递。这些参数出现的顺序并不重要,并且它们都是可选的。其中一些设置是单个单词(布尔值),而另一些则需要其后跟一个或多个值。在这种情况下,这些值必须紧跟在设置名称之后:server <name> <address>[:port] [settings ...] default-server [settings ...] 请注意,所有这些设置都受“server”和“default-server”关键字支持,除了“id”仅受“server”支持。目前支持的设置如下。
addr <ipv4|ipv6>
可在以下上下文中使用:tcp, http, log 使用“addr”参数,可以为发送健康检查或探测 agent-check 使用不同的 IP 地址。在某些服务器上,可能需要为能够执行复杂测试的特定组件专用一个 IP 地址,这些测试比应用程序本身更适合健康检查。如果未设置“check”参数,则此参数将被忽略。另请参见“port”参数。
可用于以下上下文:tcp、http、log 启用独立于常规健康检查运行的辅助代理检查。代理健康检查是通过对由“agent-port”参数设置的端口进行 TCP 连接并读取以遇到的第一个 '\r' 或 '\n' 终止的 ASCII 字符串来执行的。该字符串由一系列单词组成,这些单词由空格、制表符或逗号分隔,顺序任意,每个单词都包含: - 正整数百分比的 ASCII 表示,例如“75%”。此格式的值将设置与 HAProxy 启动时配置的服务器初始权重成比例的权重。请注意,零权重在统计信息页面上报告为“DRAIN”,因为它对服务器具有相同的效果(它已从 LB 场中删除)。这是设置服务器权重的传统方式。最好使用“weight:”前缀设置它。 - 字符串“weight:”后跟一个正整数或正整数百分比,中间没有空格。如果值以“%”符号结尾,则新权重将与服务器的初始权重成比例。否则,该值被视为绝对权重,并且必须在 0 到 256 之间。作为运行静态负载平衡算法的场的一部分的服务器具有更严格的限制,因为权重一旦设置就无法更改。因此,对于这些服务器,唯一接受的值是 0 和 100%(或 0 和初始权重)。更改会立即生效,尽管某些 LB 算法需要一定数量的请求才能考虑更改。请注意,零权重在统计信息页面上报告为“DRAIN”,因为它对服务器具有相同的效果(它已从 LB 场中删除)。 - 字符串“maxconn:”后跟一个整数(中间没有空格)。此格式的值将设置服务器的 maxconn。通告的最大连接数需要乘以负载均衡器的数量以及使用此健康检查的不同后端,才能获得服务器可能接收的连接总数。示例:maxconn:30 - 单词“ready”。这将把服务器的管理状态转变为 READY 模式,从而取消任何 DRAIN 或 MAINT 状态。 - 单词“drain”。这将把服务器的管理状态转变为 DRAIN 模式,从而它不会接受任何新连接,除了通过持久性接受的连接。 - 单词“maint”。这将把服务器的管理状态转变为 MAINT 模式,从而它根本不会接受任何新连接,并且健康检查将被停止。 - 单词“down”、“fail”或“stopped”,可选后跟一个描述字符串(在 sharp ('#') 之后)。所有这些都将服务器的操作状态标记为 DOWN,但由于单词本身在统计信息页面上报告,因此差异允许管理员知道情况是预期的还是非预期的:服务可能有意停止,可能看起来已启动但未通过某些有效性测试,或者可能被视为已关闭(例如缺少进程,或者端口无响应)。 - 如果健康检查也报告服务可访问,则单词“up”会将服务器的操作状态设置回 UP。代理未通告的参数不会更改。例如,代理可能旨在监视 CPU 使用率,并且仅报告相对权重,从不与操作状态交互。同样,代理可以设计为具有 3 个单选按钮的最终用户界面,允许管理员仅更改管理状态。但是,重要的是要考虑只有代理才能恢复其自身的操作,因此如果使用代理将服务器设置为 DRAIN 模式或 DOWN 状态,则代理必须实现其他等效操作才能使服务再次投入运行。未能连接到代理不被视为错误,因为连接性由通过“check”参数启用的常规健康检查进行测试。请注意,在代理报告“down”后停止代理不是一个好主意,因为只有报告“up”的代理才能再次使服务器启动。请注意,Unix stats 套接字上的 CLI 也可以强制执行代理的结果,以便在需要时解决错误的代理。需要设置“agent-port”参数。另请参阅“agent-inter”和“no-agent-check”参数。
agent-send <string>
可在以下上下文中使用:tcp, http, log 如果指定了此选项,HAProxy 将在连接时将给定的字符串(逐字)发送到代理服务器。例如,您可以将后端名称编码到此字符串中,这将使您的代理能够根据后端发送不同的响应。如果您想用换行符终止请求,请确保包含一个 '\n'。
agent-inter <delay>
可用于以下上下文:tcp、http、log “agent-inter”参数将两次代理检查之间的时间间隔设置为 <delay> 毫秒。如果未指定,则延迟默认为 2000 毫秒。与所有其他基于时间的参数一样,它可以用 { us, ms, s, m, h, d } 中的任何其他显式单位输入。“agent-inter”参数也用作代理检查的超时,除非设置了“timeout check”。为了减少多个服务器托管在同一硬件上时的“共振”效应,所有服务器的代理和健康检查都以很小的时间偏移开始。还可以使用全局“spread-checks”关键字在代理和健康检查间隔中添加一些随机噪声。例如,当许多后端使用相同的服务器时,这很有意义。另请参阅“agent-check”和“agent-port”参数。
agent-addr <addr>
可在以下上下文中使用:tcp, http, log “agent-addr”参数设置代理检查的地址。您可以将代理检查卸载到另一个目标,这样如果您无法实现自感知和自管理的服务,就可以在一个地方管理 HAProxy 中定义的服务器的状态和权重。您可以同时指定 IP 或主机名,它将被解析。
agent-port <port>
可在以下上下文中使用:tcp, http, log “agent-port”参数设置用于代理检查的 TCP 端口。另请参见“agent-check”和“agent-inter”参数。
可用于以下上下文:tcp、http、log、peers、ring 允许在使用 TLS 1.3 时向服务器发送早期数据。请注意,仅当客户端使用早期数据时,或者如果后端使用带有“0rtt-rejected”关键字的“retry-on”时,才会发送早期数据。对于 QUIC,QuicTLS、OpenSSL >= 3.5.2 和 AWS-LC 支持 0rtt。对于 TCP/TLS,仅 OpenSSL 支持 0rtt。
alpn <protocols>
可用于以下上下文:tcp、http 这启用 TLS ALPN 扩展并通告指定的协议列表支持 ALPN。协议列表由逗号分隔的协议名称列表组成,例如:“http/1.1,http/1.0”(不带引号)。这需要构建 SSL 库时启用 TLS 扩展支持(使用 haproxy -vv 检查)。ALPN 扩展取代了最初的 NPN 扩展。ALPN 是连接到 HTTP/2 服务器所必需的。它也是能够通过 QUIC 服务器使用 HTTP/3 所必需的,“h3”用作没有“alpn”设置的 QUIC 服务器的默认值。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。
可在以下上下文中使用:tcp, http, log 当服务器行上存在“backup”时,该服务器仅在所有其他非备份服务器都不可用时才用于负载均衡。但是,带有引用该服务器的持久性 cookie 的请求将始终被处理。默认情况下,只使用第一个可操作的备份服务器,除非在后端设置了“allbackups”选项。另请参见“no-backup”和“allbackups”选项。
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>
可用于以下上下文: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”)。如果无法配置特定的拥塞控制算法,则保留默认算法
可用于以下上下文:tcp、http、log 此选项启用对服务器的健康检查: - 未设置时,不执行健康检查,并且服务器始终被视为可用。 - 设置且未配置其他检查方法时,当可以在最高配置的传输层建立连接时,服务器被视为可用。这意味着默认情况下是 TCP,或者当设置了“ssl”或“check-ssl”时是 SSL/TLS,两者都可能与连接前缀结合使用,例如当设置了“send-proxy”或“check-send-proxy”时是 PROXY 协议标头。此行为对于动态服务器略有不同,请阅读以下段落了解更多详细信息。 - 设置且定义了应用程序级健康检查时,应用程序级交换在配置的传输层之上执行,如果所有交换都成功,则服务器被视为可用。默认情况下,健康检查在与服务器配置的相同地址和端口上执行,使用相同的封装参数(SSL/TLS、代理协议标头等)。可以使用“addr”更改目标地址,使用“port”更改端口。完成后,假定服务器未在服务端口上检查,并且不会重新使用配置的封装参数。必须显式设置“check-send-proxy”以发送连接标头,设置“check-ssl”以使用 SSL/TLS。请注意,不会为动态服务器执行 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”配置可选的应用程序级健康检查。
示例
# 简单的 tcp 检查 backend foo server s1 192.168.0.1:80 check # 这会执行 tcp 连接 + tls 握手 backend foo server s1 192.168.0.1:443 ssl check # 简单的 tcp 检查足以使检查成功 backend foo option tcp-check tcp-check connect server s1 192.168.0.1:443 ssl check
可用于以下上下文:tcp、http 此选项允许检查重用空闲连接(如果可用),而不是打开专用连接。检查完成后,连接将重新插入池中。主要目标是限制特定服务器上的连接打开和关闭次数。此功能仅与 http-check 规则集兼容。对于其他检查类型,它会被静默忽略。此外,应在后端上将重用策略设置为 aggressive,因为每次检查尝试都是通过专用会话执行的。为了配置简单起见,如果定义了任何特定的检查连接选项(无论是在服务器行上还是通过自定义 tcp-check 连接规则),则此选项会被静默忽略。对于充当被动反向 HTTP 网关的服务器,此选项会自动启用,因为对于这些服务器,仅通过重用支持连接。
可在以下上下文中使用:tcp, http 此选项强制在传出的健康检查中发送 PROXY 协议行,无论服务器是否为正常流量使用 send-proxy。默认情况下,如果 PROXY 协议已为正常流量启用,并且没有“port”或“addr”指令存在,则为健康检查启用 PROXY 协议。但是,如果存在这样的指令,则需要使用“check-send-proxy”选项来强制使用该协议。有关更多信息,请参见“send-proxy”选项。
check-alpn <protocols>
可在以下上下文中使用:tcp, http 定义要通过 ALPN 通告的协议。协议列表由一个以逗号分隔的协议名称列表组成,例如:"http/1.1,http/1.0"(不含引号)。如果未设置,则使用服务器的 ALPN。
可在以下上下文中使用:tcp, http 当为检查执行连接重用时,如果设置了 <name>,则使用它作为连接标识符来匹配池中相应的连接。这相当于“pool-conn-name”服务器关键字。如果未使用当前选项,“check-sni”也将用作备用。
可用于以下上下文:tcp、http 强制多路复用器的协议用于服务器的健康检查连接。它必须与健康检查类型(TCP 或 HTTP)兼容。它还必须可在后端使用。可用协议列表在 haproxy -vv 中报告。报告了协议属性:模式 (TCP/HTTP)、边 (FE/BE)、mux 名称及其标志。某些协议在服务器端容易出现行首阻塞(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 使用。
可用于以下上下文: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>
可在以下上下文中使用:tcp, http, log 此选项允许您指定在通过 SSL 进行健康检查时使用的 SNI。只能使用字符串来设置 <sni>。如果您想为代理流量设置 SNI,请参见“sni”。
可用于以下上下文:tcp、http、log 此选项强制通过 SSL 对所有健康检查进行加密,无论服务器是否将 SSL 用于正常流量。这通常在指定显式“port”或“addr”指令且未继承 SSL 健康检查时使用。重要的是要了解此选项在检查下方插入 SSL 传输层,以便简单的 TCP 连接检查变为 SSL 连接,从而取代旧的 ssl-hello-chk。最常见的用法是通过将“httpchk”与 SSL 检查结合来发送 HTTPS 检查。所有 SSL 设置对健康检查和流量都是通用的(例如密码)。有关详细信息,请参阅“ssl”选项,并参阅“no-check-ssl”禁用此选项。
可在以下上下文中使用:tcp, http, log 此选项启用通过上游 socks4 代理进行的传出健康检查。默认情况下,即使为正常流量启用了 socks 隧道,健康检查也不会通过它。
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>
可用于以下上下文:tcp、http、log、peers、ring 此设置仅在内置 OpenSSL 支持且使用 OpenSSL 1.1.1 或更高版本构建 HAProxy 时可用。此选项设置描述在与服务器进行 TLS 1.3 握手期间协商的密码算法列表的字符串。字符串的格式在 OpenSSL 手册页中“man 1 ciphers”的“ciphersuites”部分中定义。有关 TLSv1.2 及更早版本的密码配置,请检查“ciphers”关键字。
client-sigalgs <sigalgs>
可在以下上下文中使用:tcp、http、log、peers、ring 此设置仅在内置 OpenSSL 支持时可用。它设置一个描述协商的与客户端身份验证相关的签名算法列表的字符串。该字符串的格式在 OpenSSL 手册页的 "man 3 SSL_CTX_set1_client_sigalgs" 中定义。如果没有确定特定的用例,不建议使用此设置。
cookie <value>
可用于以下上下文:http “cookie”参数将分配给服务器的 cookie 值设置为 <value>。将在传入请求中检查此值,并选择具有相同值的第一个操作服务器。反过来,在 cookie 插入或重写模式下,此值将分配给发送到客户端的 cookie。多个服务器共享相同的 cookie 值没有问题,这在正常服务器和备份服务器之间实际上很常见。另请参阅后端部分中的“cookie”关键字。
crl-file <crlfile>
可在以下上下文中使用:tcp、http、log、peers、ring 此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载证书吊销列表以验证服务器的证书。
crt <cert>
可在以下上下文中使用:tcp、http、log、peers、ring 此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载证书及其关联的私钥。此文件可以通过将两个 PEM 文件连接成一个来构建。如果服务器发送客户端证书请求,则将发送此证书。如果该文件不包含私钥,HAProxy 将尝试在同一路径下加载带有“.key”后缀的密钥(前提是相应地设置了“ssl-load-extra-files”选项)。
curves <curves>
可在以下上下文中使用:tcp、http、log、peers、ring 此设置仅在内置 OpenSSL 支持时可用。它设置一个字符串,描述在 SSL/TLS 握手期间与 ECDHE 协商的椭圆曲线算法列表(“曲线套件”)。该字符串的格式是一个以冒号分隔的曲线名称列表。
示例
"X25519:P-256" (不带引号)
可用于以下上下文:tcp、http、log “disabled”关键字在“disabled”状态下启动服务器。这意味着它在维护模式下被标记为down,并且除了持久模式允许的连接之外,没有其他连接会到达它。它非常适合设置新服务器,因为正常流量永远不会到达它们,同时仍然可以通过使用 force-persist 机制来测试服务。另请参阅“enabled”设置。
可在以下上下文中使用:tcp、http、log 此选项可用作'server'设置,以重置任何从'default-server'指令继承为默认值的'disabled'设置。它也可用作'default-server'设置,以重置任何先前的'default-server' 'disabled'设置。
error-limit <count>
可在以下上下文中使用:tcp、http、log 如果启用了健康状况观察,"error-limit"参数指定触发由"on-error"选项选择的事件的连续错误数。默认设置为 10 个连续错误。另请参见"check"、"error-limit"和"on-error"。
fall <count>
可在以下上下文中使用:tcp、http、log "fall"参数规定,在连续 <count> 次不成功的健康检查后,服务器将被视为死亡。如果未指定,此值默认为 3。另请参见"check"、"inter"和"rise"参数。
可在以下上下文中使用:tcp、http、log、peers、ring 此选项在与服务器通信时强制仅使用 SSLv3。对于高连接率,SSLv3 通常比 TLS 对应版本成本更低。此选项在全局语句"ssl-default-server-options"中也可用。另请参见"ssl-min-ver"和 ssl-max-ver"。
可在以下上下文中使用:tcp、http、log、peers、ring 此选项在与服务器通信时强制仅使用 TLSv1.0。此选项在全局语句"ssl-default-server-options"中也可用。另请参见"ssl-min-ver"和 ssl-max-ver"。
可在以下上下文中使用:tcp、http、log、peers、ring 此选项在与服务器通信时强制仅使用 TLSv1.1。此选项在全局语句"ssl-default-server-options"中也可用。另请参见"ssl-min-ver"和 ssl-max-ver"。
可在以下上下文中使用:tcp、http、log、peers、ring 此选项在与服务器通信时强制仅使用 TLSv1.2。此选项在全局语句"ssl-default-server-options"中也可用。另请参见"ssl-min-ver"和 ssl-max-ver"。
可在以下上下文中使用:tcp、http、log、peers、ring 此选项在与服务器通信时强制仅使用 TLSv1.3。此选项在全局语句"ssl-default-server-options"中也可用。另请参见"ssl-min-ver"和 ssl-max-ver"。
guid <string>
可用于以下上下文:tcp、http、log 为此服务器指定区分大小写的全局唯一 ID。这在所有 haproxy 配置中的所有对象类型中必须是唯一的。有关其格式的更多信息,请参阅“guid”代理关键字描述。另请参阅“shm-stats-file”。
hash-key <key>
可在以下上下文中使用:tcp、http、log 指定“hash-type consistent”节点密钥的计算方式
参数
<key> <key> 可以是以下之一: id 节点密钥将派生自服务器的数字标识符,如从“id”设置的,或默认为其在服务器列表中的位置。 addr 节点密钥将派生自服务器的地址(如果可用),否则回退到“id”。 addr-port 节点密钥将派生自服务器的地址和端口(如果可用),否则回退到“id”。
"addr" 和 "addr-port" 选项在多个 HAProxy 进程对同一组服务器进行负载均衡的场景中可能很有用。如果每个进程的服务器顺序不同(例如,因为 DNS 记录以不同顺序解析),这将允许每个独立的 HAProxy 进程就路由决策达成一致。
id <value>
可在以下上下文中使用:tcp、http、log 为服务器设置一个持久 ID。此 ID 必须为正数且对于该代理是唯一的。如果未设置,将自动分配一个未使用的 ID。第一个分配的值将是 1。此 ID 当前仅在统计信息中返回。
idle-ping <delay>
可在以下上下文中使用:tcp、http、log 定义在空闲后端连接上进行定期活动性检查的时间间隔。如果对端在下一次计划的测试之前无法响应,则连接将关闭。此关键字指的是后端侧,因此它对于检查空闲连接是否仍然可用很有用。请注意,这不会阻止连接在空闲池清理时被销毁。此功能依赖于特定的底层协议支持。目前,只有 H2 多路复用实现了它。Idle-ping 被其他协议简单地忽略。当使用反向 HTTP 时,此选项特别有用。在服务器行上设置它对于监听传入连接并将其附加到相应服务器以便稍后在流量转发中重用的对端很有用。
init-addr {last | libc | none | <ip>},[...]*
可用于以下上下文:tcp、http、log 指示如果服务器使用 FQDN,则在启动时应按什么顺序解析服务器的地址。尝试通过依次应用逗号分隔列表中的每种方法来解析地址。使用第一个成功的方法。如果到达列表末尾仍未找到可用的方法,则会引发错误。方法“last”建议选择出现在状态文件中的地址(请参阅“server-state-file”)。方法“libc”使用 libc 的内部解析器(gethostbyname() 或 getaddrinfo(),具体取决于操作系统和构建选项)。方法“none”专门指示服务器应在 down 状态下启动,不带任何有效的 IP 地址。这对于忽略启动时的一些 DNS 问题很有用,等待稍后修复情况。最后,可以提供 IP 地址(IPv4 或 IPv6)。它可以是服务器当前已知的地址(例如由配置生成器填充),也可以是用于捕获旧会话并向其显示适当错误消息的虚拟服务器的地址。当使用“first”负载平衡算法时,此 IP 地址可以指向用于触发即时创建新实例的虚假服务器。此选项默认为“last,libc”,表示首先使用状态文件中找到的上一个地址(如果有),否则使用 libc 的解析器。这确保了与历史行为的持续兼容性。使用内部解析器时,通常建议要么禁用基于 libc 的解析,要么使其显式化(有关更多详细信息,请参阅第 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>
fastinter <delay>
downinter <delay>
可用于以下上下文:tcp, http, log "inter" 参数设置两次连续健康检查之间的时间间隔为 <delay> 毫秒。如果未指定,延迟默认为 2000 毫秒。也可以使用 "fastinter" 和 "downinter" 根据服务器状态优化检查之间的延迟。
服务器状态使用的间隔
UP 100% (非过渡状态)inter
过渡性 UP (正在变为 down "fall"),
过渡性 DOWN (正在变为 up "rise"),
或尚未检查。
如果设置了“fastinter”,则使用它,
否则使用“inter”。
DOWN 100% (非过渡状态)
如果设置了“downinter”,则使用它,
否则使用“inter”。
与所有其他基于时间的参数一样,它们可以以任何其他显式单位 { 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 }
可在以下上下文中使用:tcp、http

可用于部分

defaultsfrontendlistenbackend

no

no

yes

yes
"init-state" 选项设置服务器的初始状态: - 当设置为 'fully-up' 时,服务器被视为立即可用,并且当所有健康检查失败时可以转为 DOWN 状态。 - 当设置为 'up'(默认值)时,服务器被视为立即可用,并将启动一次健康检查,如果失败,可立即将其转为 DOWN 状态。 - 当设置为 'down' 时,服务器最初被视为不可用,并将启动一次健康检查,如果成功,可立即将其转为 UP 状态。 - 当设置为 'fully-down' 时,服务器最初被视为不可用,并且当所有健康检查成功时可以转为 UP 状态。 当 HAProxy 实例(重新)启动、检测到新服务器(例如通过服务发现/DNS 解析)、动态服务器上线、服务器退出维护等时,会考虑服务器的初始状态。
示例
# 仅将客户端流量传递给 Redis "master" 节点 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 # 仅在 3 次成功健康检查后才将流量传递给服务器 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
ktls <on|off> [ EXPERIMENTAL ]
可用于以下上下文:tcp, http, log, peers, ring 为这些套接字启用或禁用 ktls。如果启用,如果内核支持且密码兼容,将使用 kTLS。这仅在 Linux 上可用。
log-bufsize <bufsize>
可在以下上下文中使用:log “log-bufsize”指定用于与日志后端中的日志服务器关联的隐式环形缓冲区的 bufsize。如果未指定,则默认为 BUFSIZE。使用更大的值会增加内存使用量,但可以帮助防止在服务器慢速时丢失日志消息,因为缓冲区将能够容纳更多待处理的消息。此关键字只能在日志后端部分(使用“mode log”)中使用
log-proto <logproto>
可在以下上下文中使用:log、ring “log-proto”指定用于将事件消息转发到在日志或环形部分中配置的服务器的协议。可能的值为“legacy”和“octet-count”,分别对应 rfc6587 中的“非透明成帧”和“八位字节计数”。“legacy”是默认值。
maxconn <maxconn>
可用于以下上下文:tcp, http "maxconn" 参数指定将发送到此服务器的最大并发连接数。如果传入并发连接数高于此值,它们将被排队,等待释放一个槽位。此参数非常重要,因为它可以防止脆弱的服务器在极端负载下崩溃。如果指定了 "minconn" 参数,则限制变为动态的。默认值为“0”,表示无限制。另请参阅 "minconn" 和 "maxqueue" 参数,以及后端的 "fullconn" 关键字。在 HTTP 模式下,此参数限制并发请求数而不是连接数。多个请求可能会通过单个 TCP 连接多路复用到服务器。例如,如果您指定 maxconn 为 50,您可能会看到 1 到 50 个实际服务器连接,但并发请求不超过 50 个。
maxqueue <maxqueue>
可用于以下上下文:tcp, http "maxqueue" 参数指定将在此服务器的队列中等待的最大连接数。如果达到此限制,后续请求将被重新分派到其他服务器,而不是无限期地等待服务。这会破坏持久性,但可以在用户尝试连接的服务器即将崩溃时,允许他们快速重新登录。某些负载平衡算法(如 leastconn)会考虑这一点,如果明确设置为大于零的值,则接受将请求添加到服务器队列中,直到达到此值,这在处理个位数 maxconn 值时通常可以更好地平滑负载。默认值为“0”,表示队列是无限的。另请参阅 "maxconn" 和 "minconn" 参数以及 "balance leastconn"。
max-reuse <count>
可用于以下上下文:http, ring 在 http 上下文中使用时:"max-reuse" 参数指示 HTTP 连接处理器,它们不应将服务器连接重用于发送新请求的次数超过此数字。允许的值是 -1(默认值),它禁用此限制,或任何正值。值零将有效地禁用保持活动。这仅用于解决某些服务器错误,这些错误会导致它们随时间泄漏资源。较低层不一定会遵守此参数,因为可能存在使其无法强制执行的技术限制。至少到服务器的 HTTP/2 连接会遵守它。在 ring 上下文中使用时:"max-reuse" 参数指示接收器 TCP 连接处理器,它们不应将服务器连接重用于发送消息的次数超过此数字。这意味着一旦在同一连接上处理了至少 "max-reuse + 1" 条消息,到服务器的连接将被强制销毁。然后,到服务器的连接将自动重新创建。在多线程上下文中处理大量消息时,这有助于更好地将环的负载分散到多个线程上。实际上,每个连接在其整个持续时间内都绑定到同一个 CPU 线程:与 HTTP 不同,没有像 syslog 事务这样的东西,所以只要服务器不关闭连接或没有发生网络错误,服务器连接就可以无限期地存在。通过不时销毁连接,我们为其他线程提供了依次处理某些消息的机会。它也有助于在 haproxy 和日志服务器之间存在额外的负载平衡层的情况下,优雅地轮换日志服务器。然而,请记住,每次连接回收都会在现代操作系统上留下处于 TIME_WAIT 状态的出站端口,该端口在大约一分钟内不可重用,因此,必须小心不要使用太低的值,以防止快速耗尽源端口。根据经验法则,确保每秒关闭次数不超过几次,最好是少得多。允许的值是 -1(默认值),它禁用此限制,或任何正值。与 HTTP 上下文不同,与接收器服务器一起使用时,"max-reuse" 是尽力而为的:环消息是分批处理的,因此在每批之间检查限制。
minconn <minconn>
可用于以下上下文:tcp, http 设置 "minconn" 参数时,maxconn 限制将成为遵循后端负载的动态限制。服务器将始终接受至少 <minconn> 个连接,永不超过 <maxconn>,并且当后端具有少于 <fullconn> 个并发连接时,限制将在两个值之间平稳过渡。这使得在正常负载期间限制服务器上的负载成为可能,但在重要负载期间进一步推动它,而不会在特殊负载期间使服务器过载。另请参阅 "maxconn" 和 "maxqueue" 参数,以及 "fullconn" 后端关键字。
namespace <name>
可在以下上下文中使用:tcp、http、log、peers、ring 在 Linux 上,可以指定一个套接字将属于哪个网络命名空间。此指令使得可以明确地将服务器绑定到不同于默认命名空间的命名空间。请参考您的操作系统文档以获取有关网络命名空间的更多详细信息。
可用于以下上下文:tcp, http, log 此选项可用作 "server" 设置,以重置任何从 "default-server" 指令继承的 "agent-check" 设置作为默认值。它也可用作 "default-server" 设置,以重置任何先前的 "default-server" "agent-check" 设置。
可用于以下上下文:tcp, http, log 此选项可用作 "server" 设置,以重置任何从 "default-server" 指令继承的 "backup" 设置作为默认值。它也可用作 "default-server" 设置,以重置任何先前的 "default-server" "backup" 设置。
可用于以下上下文:tcp, http, log 此选项可用作 "server" 设置,以重置任何从 "default-server" 指令继承的 "check" 设置作为默认值。它也可用作 "default-server" 设置,以重置任何先前的 "default-server" "check" 设置。
可在以下上下文中使用:tcp、http 此选项会恢复任何可能从“default-server”继承的先前的“check-reuse-pool”。任何检查都将在其专用的连接上进行。
可用于以下上下文:tcp, http, log 此选项可用作 "server" 设置,以禁用默认启用的 SSL 健康检查的自动 SNI 选择。请参阅 "no-sni-auto" 选项以禁用代理流量的自动 SNI 选择。
可用于以下上下文:tcp, http, log 此选项可用作 "server" 设置,以重置任何从 "default-server" 指令继承的 "check-ssl" 设置作为默认值。它也可用作 "default-server" 设置,以重置任何先前的 "default-server" "check-ssl" 设置。
可用于以下上下文:tcp, http, log 仅当内置 OpenSSL 支持时,此设置才可用。它禁用给定 SSL 后端的重新协商机制,无论是传统的非安全机制还是最近的“安全重新协商”机制(RFC 5746 TLS Renegotiation Indication Extension)。此选项也可用于全局语句 "ssl-default-server-options"。TLS 1.3 中不再可能进行重新协商。如果既未指定 "renegotiate" 也未指定 "no-renegotiate",则保留 SSL 库的默认行为。请注意,例如 OpenSSL 库默认启用安全重新协商,而 AWS-LC 禁用它。另请参阅 "renegotiate"。
可用于以下上下文:tcp, http 此选项可用作 "server" 设置,以重置任何从 "default-server" 指令继承的 "send-proxy" 设置作为默认值。它也可用作 "default-server" 设置,以重置任何先前的 "default-server" "send-proxy" 设置。
可用于以下上下文:tcp, http 此选项可用作 "server" 设置,以重置任何从 "default-server" 指令继承的 "send-proxy-v2" 设置作为默认值。它也可用作 "default-server" 设置,以重置任何先前的 "default-server" "send-proxy-v2" 设置。
可用于以下上下文:tcp, http 此选项可用作 "server" 设置,以重置任何从 "default-server" 指令继承的 "send-proxy-v2-ssl" 设置作为默认值。它也可用作 "default-server" 设置,以重置任何先前的 "default-server" "send-proxy-v2-ssl" 设置。
可用于以下上下文:tcp, http 此选项可用作 "server" 设置,以重置任何从 "default-server" 指令继承的 "send-proxy-v2-ssl-cn" 设置作为默认值。它也可用作 "default-server" 设置,以重置任何先前的 "default-server" "send-proxy-v2-ssl-cn" 设置。
可用于以下上下文:tcp, http, log, peers, ring 此选项可用作 "server" 设置,以禁用默认启用的自动 SNI 选择。请参阅 "no-check-sni-auto" 选项以禁用 SSL 健康检查的自动 SNI 选择。
可用于以下上下文:tcp, http, log, peers, ring 此选项可用作 "server" 设置,以重置任何从 "default-server" 指令继承的 "ssl" 设置作为默认值。它也可用作 "default-server" 设置,以重置任何先前的 "default-server" "ssl" 设置。请注意,使用 `default-server ssl` 设置和 `no-ssl` 在服务器上仍然会初始化 SSL 连接,因此稍后可以通过运行时 API 启用:请参阅管理文档中的 `set server` 命令。
可在以下上下文中使用:tcp、http、log、peers、ring 此选项在与服务器通信时禁用 SSL 会话重用。它将强制服务器为每个新连接执行完整的握手。这可能仅对基准测试、故障排除以及偏执的用户有用。
可用于以下上下文:tcp, http, log, peers, ring 此选项在使用 SSL 与服务器通信时禁用 SSLv3 支持。请注意,SSLv2 在代码中被禁用,不能使用任何配置选项启用。请改用 "ssl-min-ver" 和 "ssl-max-ver"。支持 default-server:否
可用于以下上下文:tcp, http, log, peers, ring 仅当内置 OpenSSL 支持时,此设置才可用。它禁用无状态会话恢复(RFC 5077 TLS Ticket 扩展)并强制使用有状态会话恢复。无状态会话恢复对服务器的 CPU 使用率更高。此选项也可用于全局语句 "ssl-default-server-options"。TLS 票据机制仅用于 TLS 1.2。前向保密性会受到 TLS 票据的损害,除非定期轮换票据密钥(通过重新加载或使用 "tls-ticket-keys")。另请参阅 "tls-tickets"。
可用于以下上下文:tcp, http, log, peers, ring 此选项在使用 SSL 与服务器通信时禁用 TLSv1.0 支持。请注意,SSLv2 在代码中被禁用,不能使用任何配置选项启用。TLSv1 比 SSLv3 更耗资源,因此在与本地服务器通信时禁用它通常有意义。此选项也可用于全局语句 "ssl-default-server-options"。请改用 "ssl-min-ver" 和 "ssl-max-ver"。支持 default-server:否
可用于以下上下文:tcp, http, log, peers, ring 此选项在使用 SSL 与服务器通信时禁用 TLSv1.1 支持。请注意,SSLv2 在代码中被禁用,不能使用任何配置选项启用。TLSv1 比 SSLv3 更耗资源,因此在与本地服务器通信时禁用它通常有意义。此选项也可用于全局语句 "ssl-default-server-options"。请改用 "ssl-min-ver" 和 "ssl-max-ver"。支持 default-server:否
可用于以下上下文:tcp, http, log, peers, ring 此选项在使用 SSL 与服务器通信时禁用 TLSv1.2 支持。请注意,SSLv2 在代码中被禁用,不能使用任何配置选项启用。TLSv1 比 SSLv3 更耗资源,因此在与本地服务器通信时禁用它通常有意义。此选项也可用于全局语句 "ssl-default-server-options"。请改用 "ssl-min-ver" 和 "ssl-max-ver"。支持 default-server:否
可用于以下上下文:tcp, http, log, peers, ring 此选项在使用 SSL 与服务器通信时禁用 TLSv1.3 支持。请注意,SSLv2 在代码中被禁用,不能使用任何配置选项启用。TLSv1 比 SSLv3 更耗资源,因此在与本地服务器通信时禁用它通常有意义。此选项也可用于全局语句 "ssl-default-server-options"。请改用 "ssl-min-ver" 和 "ssl-max-ver"。支持 default-server:否
可用于以下上下文:tcp, http, log, peers, ring 此选项可用作 "server" 设置,以重置任何从 "default-server" 指令继承的 "verifyhost" 设置作为默认值。它也可用作 "default-server" 设置,以重置任何先前的 "default-server" "verifyhost" 设置。
可用于以下上下文:tcp, http, log, peers, ring 此选项可用作 "server" 设置,以重置任何从 "default-server" 指令继承的 "tfo" 设置作为默认值。它也可用作 "default-server" 设置,以重置任何先前的 "default-server" "tfo" 设置。
可在以下上下文中使用:tcp、http 从不将分配给此服务器的连接添加到粘性表中。这可以与备份结合使用,以确保对备份服务器禁用粘性表持久性。
npn <protocols>
可在以下上下文中使用:tcp、http 这将启用 NPN TLS 扩展,并通告指定的协议列表作为 NPN 之上支持的协议。协议列表由一个逗号分隔的协议名称列表组成,例如:“http/1.1,http/1.0”(不带引号)。这要求 SSL 库在构建时启用了对 TLS 扩展的支持(请使用 haproxy -vv 进行检查)。请注意,NPN 扩展已被 ALPN 扩展取代(参见“alpn”关键字),但后者仅从 OpenSSL 1.0.2 开始可用。
observe <mode>
可在以下上下文中使用:tcp, http。此选项启用基于观察与服务器通信的健康状况调整。默认情况下此功能是禁用的,启用它也需要启用健康检查。支持两种模式:“layer4” 和 “layer7”。在 layer4 模式下,只有成功/不成功的 TCP 连接是重要的。在 layer7 模式下(仅允许用于 http 代理),将验证从服务器收到的响应,例如有效/错误的 http 状态码、无法解析的标头、超时等。有效的状态码包括 100 到 499、501 和 505。另请参阅 “check”、“on-error” 和 “error-limit”。
on-error <mode>
可在以下上下文中使用:tcp, http, log。选择当检测到足够多的连续错误时应该发生什么。目前,有四种模式可用: - fastinter:强制 fastinter - fail-check:模拟一次失败的检查,也强制 fastinter(默认) - sudden-death:模拟一次致命前失败的健康检查,再有一次失败的检查将标记服务器为 down,强制 fastinter - mark-down:立即将服务器标记为 down 并强制 fastinter。另请参阅 “check”、“observe” 和 “error-limit”。
可在以下上下文中使用:tcp, http, log。修改当服务器被标记为 down 时发生的操作。目前有一个可用动作:- shutdown-sessions:关闭对端流。启用此设置后,当服务器宕机时,所有到该服务器的连接将立即终止。如果健康检查检测到比简单连接状态更复杂的情况,并且长超时会导致服务在太长时间内无响应,则可以使用此设置。例如,健康检查可能会检测到数据库卡住,并且无法再重用现有连接。以这种方式终止的连接将以 'D' 终止代码(表示“Down”)记录。动作默认是禁用的。
on-marked-up <action>
可在以下上下文中使用:tcp, http, log。修改当服务器被标记为 up 时发生的操作。目前有一个可用动作: - shutdown-backup-sessions:关闭所有备份服务器上的流。仅当服务器不处于备份状态且未被禁用(其有效权重 > 0)时才会执行此操作。在处理长会话(例如 LDAP、SQL 等)时,有时可以使用此功能强制活动服务器在恢复后重新接管所有流量。这样做可能比它试图解决的问题带来更多麻烦(例如,不完整的事务),因此请极其谨慎地使用此功能。因服务器恢复而终止的流将以 'U' 终止代码(表示“Up”)记录。动作默认是禁用的。
pool-conn-name <表达式>
可在以下上下文中使用:http。当建立后端连接时,会评估此表达式以生成连接名称。此名称是空闲服务器池中连接的关键属性之一。请参阅 “http-reuse” 关键字。当请求查找现有空闲连接时,会评估此表达式以匹配相同的连接。在后端连接使用 SSL SNI 的上下文中,连接名称会自动分配给 “sni” 表达式的结果。这适用于最常见的用法。对于更高级的设置,可以使用 “pool-conn-name” 来覆盖此设置。
pool-low-conn <最大值>
可用于以下上下文:http 设置服务器空闲连接数的低阈值,低于该阈值,线程将不会尝试从另一个线程窃取连接。这对于涉及许多非常快的服务器的场景中提高 CPU 使用模式非常有用,以确保所有线程始终保持少量空闲连接,而不是让它们在单个线程上累积并从线程迁移到线程。两倍于线程数的典型值似乎已经显示出非常好的性能,响应时间低于毫秒。默认值为零,表示可以随时使用任何空闲连接。这是正常使用的推荐设置。这仅适用于根据与 "http-reuse" 相同的原则可以共享的连接。如果通过 "tune.idle-pool.shared" 禁用线程之间的连接共享,则使用此设置以确保每个线程始终拥有少量连接可能变得非常重要,否则连接重用率会随着线程数的增加而降低。
pool-max-conn <最大值>
可在以下上下文中使用:http。设置服务器的空闲连接最大数量。-1 表示无限连接,0 表示没有空闲连接。默认值为 -1。当启用空闲连接时,不再属于任何客户端会话的孤立空闲连接将被移动到一个专用池中,以便未来的客户端可以使用它们。这仅适用于可以根据与 “http-reuse” 相同的原则共享的连接。
可在以下上下文中使用:http。设置开始清除空闲连接的延迟。每个 <delay> 间隔,一半的空闲连接将被关闭。0 表示我们不保留任何空闲连接。默认值为 5 秒。
port <port>
可在以下上下文中使用:tcp, http, log。使用 “port” 参数,可以使用不同的端口来发送健康检查或探测代理检查(agent-check)。在某些服务器上,可能希望将一个端口专用于能够执行比应用程序更适合健康检查的复杂测试的特定组件。例如,在 inetd 中运行一个简单的脚本是很常见的。如果未设置 “check” 参数,则此参数将被忽略。另请参阅 “addr” 参数。
proto <名称>
可用于以下上下文:tcp, http 强制为此服务器的传出连接使用多路复用器的协议。它必须与后端的模式(TCP 或 HTTP)兼容。它也必须在后端可用。可用协议列表在 haproxy -vv 中报告。报告了协议属性:模式(TCP/HTTP)、侧(FE/BE)、mux 名称及其标志。有些协议容易受到服务器端队头阻塞的影响(flag=HOL_RISK)。最后,有些协议不支持升级(flag=NO_UPG)。HTX 兼容性也已报告(flag=HTX)。以下是可用作服务器行上的 "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 spop:mode=SPOP side=BE mux=SPOP flags=HOL_RISK|NO_UPG 此选项背后的想法是绕过为此服务器建立的所有连接选择最佳多路复用器协议。如果配置了 ALPN 或 NPN 设置,则指定的协议应与多路复用器协议兼容,以避免任何问题。例如,如果设置了 "proto h1",则不应将 ALPN 设置为 "h2"。另请参阅 "ws" 以使用 websocket 流的替代协议。
redir <prefix>
可用于以下上下文:http "redir" 参数为此服务器的所有 GET 和 HEAD 请求启用重定向模式。这意味着 HAProxy 不会转发请求到服务器,而是发送一个“HTTP 302”响应,其“Location”标头由此前缀紧跟请求的 URI(从路径组件的开头 '/' 开始)组成。这意味着在 <prefix> 之后不应使用尾部斜杠。所有无效请求都将被拒绝,所有非 GET 或 HEAD 请求将由服务器正常服务。请注意,由于响应是完全伪造的,因此响应中不可能进行标头篡改或 cookie 插入。然而,请求中的 cookie 仍然会被分析,这使得此解决方案在本地发生灾难时将用户导向远程位置完全可用。主要用途是通过让客户端直接连接到静态服务器来提高带宽。注意:切勿在此处使用相对位置,否则会导致客户端和 HAProxy 之间出现循环!
Example
server srv1 192.168.1.1:80 redir http://image1.mydomain.com check
可用于以下上下文:tcp, http, log 此选项为给定的 SSL 后端启用安全重新协商机制(RFC 5746 TLS Renegotiation Indication Extension)。这并不意味着 SSL 客户端将发送重新协商请求,它只允许后端在服务器请求时进行重新协商。它仍然需要底层 SSL 库实际支持重新协商。此选项也可用于全局语句 "ssl-default-server-options"。TLS 1.3 中不再可能进行重新协商。如果既未指定 "renegotiate" 也未指定 "no-renegotiate",则保留 SSL 库的默认行为。请注意,例如 OpenSSL 库默认启用安全重新协商,而 AWS-LC 禁用它。
rise <count>
可在以下上下文中使用:tcp, http, log。“rise” 参数指出,一个服务器在连续 <count> 次成功的健康检查后将被视为可操作。如果未指定,此值默认为 2。另请参阅 “check”、“inter” 和 “fall” 参数。
resolve-opts <选项>,<选项>,...
可在以下上下文中使用: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 的默认行为:防止重用已设置到同一后端中且共享相同 FQDN 的服务器的 IP 地址。这与 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 地址,则两个服务器都将使用它 * 如果域名服务器返回 2 个 IP 地址,则每个服务器将选择一个不同的地址 默认值:未设置
可在以下上下文中使用: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 <网络>[,<网络[,...]]
可在以下上下文中使用:tcp, http, log。此选项优先选择与网络匹配的 IP 地址。这对于云环境优先选择本地 IP 很有用。在某些情况下,云高可用性服务可以在许多不同的数据中心上通过许多 IP 地址进行通告。数据中心之间的延迟不可忽略,因此此补丁允许优先选择本地数据中心。如果没有地址与配置的网络匹配,则会选择另一个地址。
示例
server s1 app1.domain.com:80 resolvers mydns resolve-net 10.0.0.0/8
可在以下上下文中使用:tcp, http, log。指向一个现有的 “resolvers” 部分,以解析当前服务器的主机名。在使用解析器时,通常建议禁用基于 libc 的解析,尽管存在例外情况(参见 第 5.3.1 节)。在任何情况下,使用解析器时明确指定 “init-addr” 是一个好习惯,以免忽略此元素。
示例
server s1 app1.domain.com:80 init-addr last,none check resolvers mydns
另请参阅 第 5.3 节 了解实现细节和需要注意的陷阱。
可用于以下上下文: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" 选项。
可用于以下上下文:tcp, http "send-proxy-v2" 参数强制对建立到此服务器的任何连接使用 PROXY 协议版本 2。PROXY 协议通知另一端传入连接的第 3/4 层地址,以便它可以知道客户端的地址或它访问的公共地址,无论上层协议如何。如果协商了 alpn,它也会发送 ALPN 信息。如果服务器不知道此版本的协议,则不得使用此设置。另请参阅本节的 "no-send-proxy-v2" 选项和 "bind" 关键字的 send-proxy" 选项。
可在以下上下文中使用:tcp, http。“set-proxy-v2-tlv-fmt” 参数用于发送任意 PROXY 协议版本 2 TLV。关于已定义 TLV 类型的类型(<id>)范围,请参考代理协议规范的 第 2.2.8 节。但是,只要值不超过 65,535 字节的最大长度,就可以自由选择。它也可以通过使用 fetch “fc_pp_tlv” 从前端检索接收到的 TLV 来转发 TLV。它可以用作服务器或默认服务器选项。它必须与 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,并将其设置为新创建的 TLV 的值,该 TLV 的类型也为 0x20。
proxy-v2-options <选项>[,<选项>]*
可用于以下上下文: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 请求。
可用于以下上下文:tcp, http "send-proxy-v2-ssl" 参数强制对建立到此服务器的任何连接使用 PROXY 协议版本 2。PROXY 协议通知另一端传入连接的第 3/4 层地址,以便它可以知道客户端的地址或它访问的公共地址,无论上层协议如何。此外,PROXY 协议的 SSL 信息扩展被添加到 PROXY 协议标头中。如果服务器不知道此版本的协议,则不得使用此设置。另请参阅本节的 "no-send-proxy-v2-ssl" 选项以及 "bind" 关键字的 "send-proxy-v2" 选项。
可用于以下上下文:tcp, http "send-proxy-v2-ssl" 参数强制对建立到此服务器的任何连接使用 PROXY 协议版本 2。PROXY 协议通知另一端传入连接的第 3/4 层地址,以便它可以知道客户端的地址或它访问的公共地址,无论上层协议如何。此外,PROXY 协议的 SSL 信息扩展以及客户端证书(如果有)主题中的 Common Name 被添加到 PROXY 协议标头中。如果服务器不知道此版本的协议,则不得使用此设置。另请参阅本节的 "no-send-proxy-v2-ssl-cn" 选项以及 "bind" 关键字的 "send-proxy-v2" 选项。
shard <shard>
可用于以下上下文:peers 此参数仅用于 stick-tables 与对等协议同步的上下文。"shard" 参数标识将接收具有此分片作为分发哈希的密钥的所有 stick-table 更新的对等体。接受的值是从 0 到 "peers" 部分中指定的 "shards" 参数值。0 值是默认值,表示对等体将接收所有密钥更新。大于 "shards" 的值将被忽略。对于提供给本地对等体的任何值也是如此。
Example
peers mypeers shards 3 peer A 127.0.0.1:40001 # 没有分片值的本地对等体 (内部为0) 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>
可在以下上下文中使用:tcp, http, log, peers, ring。此设置仅在构建时包含 OpenSSL 支持时可用。它设置了描述在 TLSv1.2 和 TLSv1.3 握手期间协商的签名算法列表的字符串。字符串的格式在 OpenSSL 手册页的 “man 3 SSL_CTX_set1_sigalgs” 中定义。除非需要与中间设备兼容,否则不建议使用此设置。
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",以最大化步数。slowstart 永远不会在 HAProxy 启动时应用,否则会对正在运行的服务器造成麻烦。它仅在服务器先前被视为失败时应用。
sni <expression>
可用于以下上下文:tcp, http, log, peers, ring "sni" 参数评估样本获取表达式,将其转换为字符串,并使用结果作为发送到服务器的 SNI TLS 扩展中的主机名。一个典型的用例是在桥接 TCP/SSL 场景中发送从客户端接收到的 SNI,使用 "ssl_fc_sni" 样本获取表达式。这绝不能用于 HTTPS,因为在 HTTPS 中 SNI 必须始终与 Host 字段匹配,并且允许客户端通过同一连接使用不同的主机名。如果设置了 "verify required"(这是推荐设置),则结果名称也将与服务器证书的名称匹配。有关更多详细信息,请参阅 "verify" 指令。如果您想为健康检查设置 SNI,请参阅 "check-sni" 指令以获取更多详细信息。默认情况下,SNI 分配给 "http-reuse" 的连接名称,除非被 "pool-conn-name" 服务器关键字覆盖。
可用于以下上下文:tcp, http, log, peers, ring "sni-auto" 参数启用自动 SNI 选择,如果尚未设置任何值。默认情况下启用此参数,但此参数可用作 "server" 设置,以重置任何从 "default-server" 指令继承的 "no-sni-auto" 设置作为默认值。它也可用作 "default-server" 设置,以重置任何先前的 "default-server" "no-sni-auto" 设置。对于 HTTPS 连接,如果找到请求主机标头值,则基于该值选择 SNI。否则保持未设置状态。对于其他协议,此选项将被忽略。如果使用 SNI 的自动选择,则该值将分配给 "http-reuse" 的连接名称,除非被 "pool-conn-name" 服务器关键字覆盖。请参阅 "check-sni-auto" 选项以启用 SSL 健康检查的自动 SNI 选择。
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。
可用于以下上下文: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 ]
可在以下上下文中使用: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 ]
可在以下上下文中使用:tcp, http, log, peers, ring。当使用 SSL 与服务器通信时,此选项强制使用 <version> 或更高版本。此选项也可在全局语句 “ssl-default-server-options” 中使用。另请参阅 “ssl-max-ver”。
可用于以下上下文:tcp, http, log, peers, ring 此选项可用作 "server" 设置,以重置任何从 "default-server" 指令继承的 "no-ssl-reuse" 设置作为默认值。它也可用作 "default-server" 设置,以重置任何先前的 "default-server" "no-ssl-reuse" 设置。
可用于以下上下文:tcp, http 此选项可用作 "server" 设置,用于重置任何从 "default-server" 指令作为默认值继承而来的 "non-stick" 设置。它也可以用作 "default-server" 设置,用于重置任何先前的 "default-server" "non-stick" 设置。
可在以下上下文中使用:tcp, http。对服务器的 maxconn 有点用词不当,它实际上配置了我们发送到服务器的最大请求数,但由于有空闲连接,我们可能与服务器的总连接数更多。如果需要对服务器的连接进行严格限制,则可以使用 strict-maxconn。然后我们将永远不会与服务器建立超过 maxconn 的连接,并在需要时尝试重用或终止连接。但请注意,如果无法建立新连接且没有可用的空闲连接,这可能会导致请求失败。当建立“私有”连接时,即仅与会话绑定的连接(因为发生了身份验证),可能会发生这种情况。
socks4 <地址>:<端口>
可在以下上下文中使用:tcp, http, log, peers, ring。此选项为与服务器的传出连接启用上游 socks4 隧道。默认情况下,使用此选项不会强制健康检查通过 socks4。您必须使用关键字 “check-via-socks4” 来启用它。
tcp-md5sig <password>
可用于以下上下文:tcp, http, log, peers, ring 为到此服务器的所有传出连接启用 TCP MD5 签名(RFC 2385 通过 TCP MD5 签名选项保护 BGP 会话)。此选项仅在 Linux 上可用。启用后,<password> 字符串用于使用 16 字节 MD5 摘要对每个 TCP 段进行签名。这将保护 TCP 连接免受欺骗。此选项的主要用例是允许 BGP 保护自身免受欺骗性 TCP 段引入连接流的影响。但它对于任何非常长寿命的 TCP 连接都可能有用。
tcp-ut <delay>
可在以下上下文中使用:tcp, http, log, peers, ring。为所有到此服务器的传出连接设置 TCP 用户超时。此选项自 Linux 2.6.37 版本起可用。它允许 HAProxy 为包含数据但在配置的延迟内未收到确认的套接字配置超时。这对于经历长时间空闲的长期连接(如远程终端或数据库连接池)特别有用,其中客户端和服务器超时必须保持较高以允许长时间的空闲,但检测服务器已消失以释放与其连接(以及客户端会话)相关的所有资源又很重要。一个典型的用例也是在健康检查太慢或软重载期间强制终止死掉的服务器连接,因为此时健康检查被禁用。参数是一个默认以毫秒表示的延迟。这仅适用于常规 TCP 连接,对其他协议无效。
可在以下上下文中使用:tcp, http, log, peers, ring。此选项在支持的系统(目前仅 Linux 内核 >= 4.11)上,在连接到服务器时启用 TCP 快速打开。有关 TCP 快速打开的更多信息,请参阅 “tfo” 绑定选项。请注意,使用 tfo 时,您还应该为 “retry-on” 使用 “conn-failure”、“empty-response” 和 “response-timeout” 关键字,否则 HAProxy 将无法在失败时重试连接。另请参阅 “no-tfo”。
track [<后端>/]<服务器>
可在以下上下文中使用:tcp, http, log。此选项启用通过跟踪另一个服务器来设置当前服务器状态的能力。可以跟踪一个本身跟踪另一个服务器的服务器,只要链的末端有一个启用了健康检查的服务器。如果省略 <backend>,则使用当前后端。如果使用 disable-on-404,则必须在两个代理上都启用它。
Example
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
可用于以下上下文:tcp, http, log, peers, ring 此选项可用作 "server" 设置,用于重置任何从 "default-server" 指令作为默认值继承而来的 "no-tls-tickets" 设置。TLS ticket 机制仅用于 TLS 1.2 及以下版本。除非定期轮换 ticket 密钥(通过重新加载或使用 "tls-ticket-keys"),否则前向保密性会受到 TLS tickets 的影响。它也可以用作 "default-server" 设置,用于重置任何先前的 "default-server" "no-tls-tickets" 设置。
verify [none|required]
可用于以下上下文:tcp, http, log, peers, ring 此设置仅在内置 OpenSSL 支持时可用。如果设置为 'none',则不验证服务器证书。在其他情况下,将使用 'ca-file' 中的 CA 和可选的 'crl-file' 中的 CRL 来验证服务器提供的证书,前提是已检查证书主题和 subjectAlternateNames 属性中提供的名称是否与使用 "sni" 指令传递的名称匹配,或者如果未提供,则与使用 "verifyhost" 指令传递的静态主机名匹配。如果找不到名称,则忽略证书的名称。因此,如果没有 SNI,使用 "verifyhost" 非常重要。如果验证失败,握手将中止。在使用 SSL 连接到服务器时验证服务器证书至关重要,否则通信容易受到微不足道的中间人攻击,使 SSL 完全失效。除非 "ssl_server_verify" 出现在全局部分中,否则 "verify" 默认设置为 "required"。
verifyhost <hostname>
可用于以下上下文:tcp, http, log, peers, ring 此设置仅在内置 OpenSSL 支持时可用,并且仅在同时指定了 'verify required' 时生效。当未使用 SNI 连接到服务器时,此指令设置一个默认的静态主机名来检查服务器的证书。如果未使用 SNI,这是启用主机名验证的唯一方法。设置此静态主机名后,它也将用于健康检查(健康检查无法提供 SNI 值)。如果证书中的主机名与指定的主机名不匹配,则握手将中止。服务器提供的证书中的主机名可能包含通配符。另请参阅 "verify"、"sni" 和 "no-verifyhost" 选项。
weight <weight>
可在以下上下文中使用:tcp, http。“weight” 参数用于调整服务器相对于其他服务器的权重。所有服务器将接收与其权重相对于所有权重总和成比例的负载,因此权重越高,负载越高。默认权重为 1,最大值为 256。值为 0 表示服务器不参与负载均衡,但仍接受持久连接。如果使用此参数根据服务器容量分配负载,建议从既可以增长也可以缩小的值开始,例如在 10 到 100 之间,以便为以后的调整留出足够的空间。
ws { auto | h1 | h2 }
可用于以下上下文:http 此选项允许配置中继 websocket 流时使用的协议。当使用 HTTP/2 后端但不支持 RFC8441 中的 H2 websockets 时,此选项最有用。默认模式为 "auto"。这将重用与主协议相同的协议。唯一的区别是使用 ALPN 时。在这种情况下,如果配置的服务器 ALPN 包含 "http/1.1",它可以尝试将 ALPN 降级为 "http/1.1" 仅用于 websocket 流。值 "h1" 用于通过 ALPN(如果为服务器激活了 SSL ALPN)强制对 websockets 流使用 HTTP/1.1。同样,"h2" 可用于强制使用 HTTP/2.0 websockets。使用此值时请谨慎:服务器必须支持 RFC8441,否则 haproxy 在中继 websockets 时将报告错误。请注意,NPN 不予考虑,因为它的使用已被弃用,取而代之的是 ALPN 扩展。另请参阅 "alpn" 和 "proto"。

5.3. 使用 DNS 进行服务器 IP 地址解析

HAProxy 允许在服务器行上使用主机名,通过域名服务器检索其 IP 地址。默认情况下,HAProxy 在解析配置文件时、启动时解析名称,并为进程的生命周期缓存结果。在某些情况下,这并不足够,例如在亚马逊中,服务器的 IP 可能会在重启后更改,或者 ELB 虚拟 IP 可能会根据当前工作负载而更改。本章描述了如何配置 HAProxy 以在运行时处理服务器的名称解析。无论是否启用了运行时服务器名称解析,默认情况下 HAProxy 将在启动时通过 libc 在配置解析期间进行第一次解析,除非被 “init-addr” 参数禁用。

5.3.1. 总体概述

正如我们在引言中所见,HAProxy 中的名称解析发生在进程生命周期的两个不同步骤:1. 在启动时,HAProxy 解析服务器行定义并匹配主机名。它使用 libc 函数来解析主机名。此解析依赖于 /etc/resolv.conf 文件。2. 在运行时,HAProxy 会对需要 DNS 解析的服务器进行定期名称解析。其他一些事件可以在运行时触发名称解析:- 当服务器的健康检查以连接超时结束时:这可能是因为服务器有了新的 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. resolvers 部分

此部分专门介绍与 HAProxy 中名称解析相关的主机信息。可以根据需要有任意数量的解析器部分。每个部分可以包含许多名称服务器。在启动时,如果没有在配置中命名此方式的部分,HAProxy 会尝试生成一个名为 "default" 的解析器部分。此部分默认由 httpclient 使用,并使用 parse-resolv-conf 关键字。如果 HAProxy 自动生成此部分失败,则不会发出错误或警告。当解析器部分中配置了多个名称服务器时,HAProxy 会使用第一个有效的响应。在响应无效的情况下,只处理最后一个响应。目的是给较慢的服务器一个机会,在快速故障或过时的服务器之后提供有效的答案。当每个服务器返回不同的错误类型时,HAProxy 只使用最后一个错误。以下处理应用于此错误:1. HAProxy 使用新的查询类型重试相同的 DNS 查询。A 查询切换到 AAAA 或相反。SRV 查询不在此处涉及。超时错误也排除在外。2. 完成(或不适用)查询类型的回退后,HAProxy 使用首选查询类型重试原始 DNS 查询。3. HAProxy 重试前述步骤 <resolve_retries> 次。如果在此之后未收到有效的响应,它将停止 DNS 解析并报告错误。例如,在解析器部分中配置了 2 个名称服务器时,可能出现以下场景:- 第一个响应有效并直接应用,第二个响应被忽略 - 第一个响应无效,第二个响应有效,则应用第二个响应 - 第一个响应是 NX 域,第二个响应是截断响应,则 HAProxy 使用新类型重试查询 - 第一个响应是 NX 域,第二个响应是超时,则 HAProxy 使用新类型重试查询 - 两个名称服务器都查询超时,则 HAProxy 使用相同的查询类型重试查询 由于 DNS 服务器可能无法在一个 DNS 请求中回答所有 IP,HAProxy 会保留以前答案的缓存,如果 <hold obsolete> 秒内未返回 IP,答案将被视为过时。
resolvers <resolvers id>
创建一个新的名为 <resolvers id> 的域名服务器列表。resolvers 部分接受以下参数:
定义 HAProxy 接受并向此 resolvers 部分中配置的所有域名服务器通告的最大有效负载大小。<nb> 以字节为单位。如果未设置,HAProxy 通告 512。(RFC 6891 定义的最小值)注意:允许的最大值为 65535。UDP 的推荐值为 4096,不建议超过 8192,除非您确定您的系统和网络可以处理此大小(超过 65507 没有意义,因为这是 UDP 的最大有效负载大小)。如果您只使用 TCP 域名服务器来处理巨大的 DNS 响应,您应该将此值设置为最大值:65535。
nameserver <名称> <地址>[:端口] [参数*]
用于配置名称服务器。名称服务器的 <name> 应是唯一的。默认情况下,<address> 被视为数据报类型。这意味着如果配置了 IPv4 或 IPv6 而没有特殊的地址前缀(第 11 段),将使用 UDP 协议。如果使用了流协议地址前缀,名称服务器将被视为流服务器(例如 TCP),并且将考虑在第 5.2 段中找到的与 DNS 解析相关的 "server" 参数。注意:目前在 TCP 模式下,4 个查询在同一连接上进行流水线处理。每 5 秒移除一批空闲连接。可以配置 "maxconn" 来限制这些并发连接的数量,如果服务器支持,TLS 也应该可用。
将 /etc/resolv.conf 中找到的所有域名服务器添加到此 resolvers 域名服务器列表中。顺序如同 /etc/resolv.conf 中的每个域名服务器被单独放置在此指令的位置。
hold <status> <period>
在接收到 DNS 响应 <status> 后,确定服务器的状态是否应从 UP 更改为 DOWN。为了做出这个决定,它会检查在过去 <period> 期间是否收到了任何有效的状态,以抵消刚刚收到的无效状态。<status>:上次名称解析状态。nx 在收到 NXDOMAIN 状态后,检查在结束期间是否有任何有效的状态。refused 在收到 REFUSED 状态后,检查在结束期间是否有任何有效的状态。timeout 在 "timeout retry" 发生后,检查在结束期间是否有任何有效的状态。other 在收到任何其他无效状态后,检查在结束期间是否有任何有效的状态。valid 仅适用于 "http-request do-resolve" 和 "tcp-request content do-resolve" 操作。它定义了服务器在触发另一次解析之前将保持有效响应的期限。它不影响服务器的动态解析。obsolete 定义在收到更新的答案记录后等待多长时间才移除过时的 DNS 记录。它适用于 SRV 记录。<period>:在过去的一段时间内必须收到有效响应的时长。它遵循 HAProxy 时间格式,默认单位为毫秒。对于依赖动态 DNS 解析来确定其 IP 地址的服务器,接收无效的 DNS 响应(例如 NXDOMAIN)将导致服务器的状态从 UP 更改为 DOWN。hold 指令定义了向过去看多远以查找有效响应。如果 <period> 内收到了有效的响应,则刚刚收到的无效状态将被忽略。除非在结束期间收到了有效的响应,否则服务器将被标记为 DOWN。例如,如果设置了 "hold nx 30s",并且最后收到的 DNS 响应是 NXDOMAIN,则除非在过去 30 秒内收到了有效的响应,否则服务器将被标记为 DOWN。处于 DOWN 状态的服务器在收到 DNS 服务器的有效状态后将立即标记为 UP。"hold valid" 和 "hold obsolete" 存在单独的行为。"valid" 的默认值是 10 秒,"obsolete" 的默认值是 0 秒,其他情况的默认值是 30 秒。
定义在放弃之前为解析服务器名称而发送的查询次数 <nb>。默认值:3。当名称服务器超时或完整的 DNS 查询类型故障转移序列结束并且我们需要从默认的 ANY 查询类型重新开始时,会发生重试。
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
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. 设置

要设置缓存,您必须定义一个 cache 部分,并在代理中使用相应的 http-request 和 http-response 动作来使用它。

6.2.1. 缓存部分

cache <名称>
声明一个缓存部分,分配一个名为 <name> 的共享缓存内存,缓存大小是强制性的。
total-max-size <兆字节>
以兆字节为单位定义缓存的 RAM 大小。此大小被分成 1kB 的块,供缓存条目使用。其最大值为 4095。
定义要缓存的对象最大大小。不得大于 “total-max-size” 的一半。如果未设置,则等于缓存大小的 256 分之一。所有大小大于 “max-object-size” 的对象将不会被缓存。
max-age <秒>
定义最大过期持续时间。过期时间设置为 Cache-Control 响应标头中的 s-maxage 或 max-age(按此顺序)指令与此值之间的最小值。默认值为 60 秒,这意味着默认情况下您不能缓存超过 60 秒的对象。
process-vary <on/off>
启用或禁用对 Vary 标头的处理。禁用时,包含此类标头的响应将永远不会被缓存。启用时,我们需要对所有传入请求的请求标头子集计算一个初步哈希(这可能会带来 cpu 成本),该哈希将用于为给定请求构建一个二级键(参见 RFC 7234#4.1)。目前,二级键是根据 'accept-encoding'、'referer' 和 'origin' 标头的内容构建的。默认值为 off(禁用)。
定义缓存中具有相同主键的同时二级条目的最大数量。这需要启用 vary 支持。其默认值为 10,应传递一个严格的正整数。

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
HAProxy 能够从请求或响应流、客户端或服务器信息、表、环境信息等中提取数据……提取此类数据的操作称为获取样本。一旦检索到,这些样本可用于各种目的,例如作为粘滞表的键,但最常见的用法是将其与称为模式的预定义常量数据进行匹配。

7.1. 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 变体可以描述同一样本获取方法的替代匹配方法。样本获取方法是唯一支持转换的方法。样本获取方法返回的数据可以是以下类型之一:- boolean - integer (signed or unsigned) - IPv4 or IPv6 address - string - data block 转换器将任何这些数据转换为任何其他类型。例如,一些转换器可能将字符串转换为小写字符串,而其他转换器可能将字符串转换为 IPv4 地址,或将网络掩码应用于 IP 地址。结果样本的类型是应用于列表的最后一个转换器的类型,默认为样本获取方法的类型。每个样本或转换器返回特定类型的数据,在本文档中使用其关键字指定。当使用标准样本获取方法声明 ACL 时,某些类型会自动涉及一个默认匹配方法,如下表所示:+---------------------+-----------------+ | Sample or converter | Default | | output type | matching method | +---------------------+-----------------+ | boolean | bool | +---------------------+-----------------+ | integer | int | +---------------------+-----------------+ | ip | ip | +---------------------+-----------------+ | string | str | +---------------------+-----------------+ | binary | none, use "-m" | +---------------------+-----------------+ 请注意,为了匹配二进制样本,必须指定匹配方法,请参见下文。ACL 引擎可以将这些类型与以下类型的模式进行匹配:- boolean - integer or integer range - IP address / network - string (exact, substring, suffix, prefix, subdir, domain) - regular expression - hex block 目前支持以下 ACL 标志:-i:在匹配所有后续模式期间忽略大小写。-f:从列表中加载模式。-m:使用特定的模式匹配方法。-n:禁止 DNS 解析。-M:将 -f 指向的文件加载为 map。-u:强制 ACL 的唯一 ID。--:强制标志结束。当字符串看起来像其中一个标志时很有用。"-f" 标志后跟的名称必须遵循 2.7 中描述的 map 和 ACL 名称格式。甚至可以传递多个 "-f" 参数,如果模式要从多个列表中加载。如果引用了现有文件,所有行都将作为单独的值读取。空行以及以井号 ('#') 开头的行将被忽略。所有前导空格和制表符都将被去除。如果绝对有必要插入以井号开头的有效模式,只需在它前面加上一个空格,以免被当作注释。根据数据类型和匹配方法,HAProxy 可能会将行加载到二叉树中,从而实现非常快速的查找。这对于 IPv4 和精确字符串匹配是正确的。在这种情况下,重复项将自动删除。"-M" 标志允许 ACL 使用 map。如果设置了此标志,则列表将解析为两列条目。第一列包含 ACL 使用的模式,第二列包含样本。样本以后可以被 map 使用。在某些罕见情况下,这可能很有用,其中 ACL 仅用于在应用映射之前检查 map 中是否存在模式。"-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" 结合使用,它必须放在首位。模式匹配方法必须是以下之一:- "found":只检查是否可以在流中找到请求的样本,但不将其与任何模式进行比较。建议不要传递任何模式以避免混淆。此匹配方法特别适用于检测某些内容(例如标头、cookie 等)的存在,即使它们为空,也不需要将它们与任何内容进行比较或计数。- "bool":将值作为布尔值检查。它只能应用于返回布尔值或整数值的获取,并且不带模式。值为零或 false 不匹配,所有其他值都匹配。- "int":将值作为整数匹配。它可以与整数和布尔样本一起使用。布尔 false 是整数 0,true 是整数 1。- "ip":将值作为 IPv4 或 IPv6 地址匹配。它仅与 IP 地址样本兼容,因此它被暗示且从不需要。- "bin":将内容与表示二进制序列的十六进制字符串进行匹配。这可以与二进制或字符串样本一起使用。- "len":将样本的长度作为整数匹配。这可以与二进制或字符串样本一起使用。- "str":精确匹配:将内容与字符串进行匹配。这可以与二进制或字符串样本一起使用。- "sub":子字符串匹配:检查内容是否包含至少一个提供的字符串模式。这可以与二进制或字符串样本一起使用。- "reg":正则表达式匹配:将内容与正则表达式列表进行匹配。这可以与二进制或字符串样本一起使用。- "beg":前缀匹配:将模式与提取字符串的开头进行比较,如果其中任何一个匹配,则 ACL 匹配。这可以与二进制或字符串样本一起使用。- "end":后缀匹配:将模式与提取字符串的末尾进行比较,如果其中任何一个匹配,则 ACL 匹配。这可以与二进制或字符串样本一起使用。- "dir":子目录匹配:检查内容的斜杠分隔部分是否与提供的字符串模式之一精确匹配。这可以与二进制或字符串样本一起使用。因此,字符串 "/images/png/logo/32x32.png" 将匹配 "/images"、"/images/png"、"images/png"、"/png/logo"、"logo/32x32.png" 或 "32x32.png",但不匹配 "png" 或 "32x32"。- "dom":域匹配:检查内容的点分隔部分是否与提供的字符串模式之一精确匹配,分隔符为点 ("."), 冒号 (":"), 斜杠 ("/"), 问号 ("?"), 字符串的开头或结尾。这用于 URL。模式中的前导和尾随分隔符被忽略。如果其中任何一个匹配,则 ACL 匹配。因此,在示例字符串 "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",要么将其设置为第二个,要么在第一个字符串之前传递 "--" 标志。当然,匹配字符串 "--" 也是如此。不要对可能包含 null 字节 (0x00) 的二进制获取使用字符串匹配,因为比较会在遇到第一个 null 字节时停止。相反,首先使用 hex 转换器将二进制获取转换为十六进制字符串。所有 ACL 特定条件都暗示一个默认匹配方法。通常,这些条件是通过连接原始样本获取方法的名称和匹配方法组成的。例如,"hdr_beg" 将 "beg" 匹配应用于使用 "hdr" 获取方法检索的样本。此匹配方法仅在关键字单独使用时可用,不带任何转换器。如果在此类 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”的获取方法。当使用布尔匹配时,获取的值会按原样返回,这意味着布尔值“true”将始终匹配,而布尔值“false”将永远不匹配。布尔匹配也可以通过在返回整数值的获取方法上使用“-m bool”来强制执行。然后,整数值 0 会被转换为布尔值“false”,所有其他值都会被转换为“true”。

7.1.2. 匹配整数

整数匹配默认应用于整数获取方法。也可以使用 "-m int" 在布尔获取上强制执行。在这种情况下,"false" 转换为整数 0,"true" 转换为整数 1。整数匹配还支持整数范围和运算符。请注意,整数匹配仅适用于正值。范围是用冒号分隔的下限和上限表示的值,两者都可以省略。例如,"1024:65535" 是表示非特权端口范围的有效范围,"1024:" 也可以使用。"0:1023" 是特权端口的有效表示,":1023" 也可以使用。作为特例,一些 ACL 函数支持十进制数,它们实际上是用点分隔的两个整数。这用于某些版本检查。所有整数属性都适用于这些十进制数,包括范围和运算符。为了更方便使用,还支持比较运算符。请注意,将运算符与范围一起使用意义不大,强烈不鼓励。同样,对一组值执行顺序比较意义不大。整数匹配可用的运算符有:eq:如果测试值等于至少一个值,则为 truege:如果测试值大于或等于至少一个值,则为 truegt:如果测试值大于至少一个值,则为 truele:如果测试值小于或等于至少一个值,则为 truele:如果测试值小于至少一个值,则为 true 例如,以下 ACL 匹配任何负的 Content-Length 标头:acl negative-length req.hdr_val(content-length) lt 0 此 ACL 匹配 SSL 版本在 3.0 和 3.1 之间(包括):acl sslv3 req.ssl_ver 3:3.1

7.1.3. 匹配字符串

字符串匹配适用于字符串或二进制获取方法,并存在 6 种不同的形式:- 精确匹配(-m str):提取的字符串必须与模式精确匹配;- 子字符串匹配(-m sub):在提取的字符串内部查找模式,如果找到其中任何一个,则 ACL 匹配;- 前缀匹配(-m beg):将模式与提取字符串的开头进行比较,如果其中任何一个匹配,则 ACL 匹配。- 后缀匹配(-m end):将模式与提取字符串的末尾进行比较,如果其中任何一个匹配,则 ACL 匹配。- 子目录匹配(-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。模式中的前导和尾随分隔符被忽略。如果其中任何一个匹配,则 ACL 匹配。因此,在示例字符串 "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",要么将其设置为第二个,要么在第一个字符串之前传递 "--" 标志。当然,匹配字符串 "--" 也是如此。不要对可能包含 null 字节 (0x00) 的二进制获取使用字符串匹配,因为比较会在遇到第一个 null 字节时停止。相反,首先使用 hex 转换器将二进制获取转换为十六进制字符串。
示例
# 如果字符串 <tag> 存在于二进制样本中,则匹配 acl tag_found req.payload(0,0),hex -m sub 3C7461673E

7.1.4. 匹配正则表达式 (regexes)

与字符串匹配一样,正则表达式匹配也适用于按字面传递的字符串,但反斜杠("\")除外,它使得可以转义某些字符,如空格。如果在第一个正则表达式之前传递了“-i”标志,则匹配将忽略大小写。为了匹配字符串“-i”,要么将其放在第二个位置,要么在第一个正则表达式之前传递“--”标志。当然,匹配字符串“--”也适用相同的原则。

7.1.5. 匹配任意数据块

可以将一些提取的样本与一个可能无法安全地表示为字符串的二进制块进行匹配。为此,当匹配方法设置为二进制时,模式必须以偶数个十六进制数字的形式传递。每两个数字的序列将代表一个字节。十六进制数字可以使用大写或小写。
Example
# 在输入流中匹配 "Hello\n" (\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 八位字节的缩写形式:+------------------+------------------+------------------+ | 示例 1 | 示例 2 | 示例 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,如果 IPv6 地址与 2002:IPV4::、::IPV4 或 ::ffff:IPV4 匹配,则匹配在 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 表达式,即时构建,无需声明。它们必须用大括号括起来,每个大括号前后有一个空格(因为大括号必须被视为独立的单词)。示例:以下规则:acl missing_cl req.hdr_cnt(Content-length) eq 0 http-request deny if METH_POST missing_cl 也可以这样写:http-request deny if METH_POST { req.hdr_cnt(Content-length) eq 0 } 通常不建议使用此构造,因为以这种方式编写时更容易在配置中留下错误。但是,对于仅匹配一个源 IP 地址的非常简单的规则,使用它们可能比声明具有随机名称的 ACL 更有意义。另一个很好的用例是:使用命名 ACL:acl site_dead nbsrv(dynamic) lt 2 acl site_dead nbsrv(static) lt 2 monitor fail if site_dead 使用匿名 ACL:monitor fail if { nbsrv(dynamic) lt 2 } || { nbsrv(static) lt 2 } 有关 "http-request deny" 和 "use_backend" 关键字的详细帮助,请参阅第 4.2 节

7.3. 获取样本

从历史上看,样本获取方法仅用于检索数据以使用 ACL 与模式进行匹配。随着 stick-tables 的出现,创建了一类新的样本获取方法,它们通常与 ACL 对应物共享相同的语法。这些样本获取方法也称为" fetches"。截至目前,ACL 和 fetches 已经融合。所有 ACL 获取方法都已作为获取方法提供,ACL 也可以使用任何样本获取方法。本节详细介绍了所有可用的样本获取方法及其输出类型。一些样本获取方法具有已弃用的别名,用于保持与现有配置的兼容性。它们被明确标记为已弃用,不应在新设置中使用。还指出了可用的 ACL 派生词及其各自的匹配方法。这些都具有明确定义的默认模式匹配方法,因此无需(尽管允许)传递 "-m" 选项来指示如何使用 ACL 匹配样本。如上文样本类型与匹配兼容性矩阵所示,当在 ACL 中使用通用样本获取方法时,"-m" 选项是强制性的,除非样本类型是 boolean、integer、IPv4 或 IPv6 之一。当相同的关键字作为 ACL 关键字和标准获取方法存在时,ACL 引擎将默认自动选择仅限 ACL 的关键字。其中一些关键字支持一个或多个必需参数,以及一个或多个可选参数。这些参数是强类型的,在解析配置时会进行检查,以确保不会使用不正确的参数(例如,未解析的后端名称)。获取函数参数放在括号之间,并用逗号分隔。当参数是可选的时,将在下面用方括号 ('[ ]') 指示。当所有参数都是可选时,可以省略括号。因此,标准样本获取方法的语法是以下之一:- name - name(arg1) - name(arg1,arg2)

7.3.1. 转换器

样本获取方法可以与应用于获取样本的转换相结合(也称为"转换器")。这些组合形成了所谓的"样本表达式",结果是一个"样本"。最初这仅受 "stick on" 和 "stick store-request" 指令支持,但现在已扩展到可以使用样本的所有地方(ACL、log-format、unique-id-format、add-header 等)。这些转换作为一系列特定关键字在样本获取方法之后枚举。这些关键字也可以紧跟在获取关键字的参数之后附加,用逗号分隔。这些关键字也可以支持一些参数(例如网络掩码),这些参数必须在括号中传递。一类转换器是位运算符和算术运算符,支持对整数执行基本操作。支持一些位操作(and、or、xor、cpl),支持一些算术操作(add、sub、mul、div、mod、neg)。提供了一些比较器(odd、even、not、bool),使得无需编写 ACL 即可报告匹配。支持以下关键字
关键字输入类型输出类型
51d.single(prop[,prop*])字符串字符串
add(value)整数整数
add_item(delim[,var[,suff]])字符串字符串
aes_gcm_dec(bits,nonce,key,aead_tag[,aad])二进制二进制
aes_gcm_enc(bits,nonce,key,aead_tag[,aad])二进制二进制
and(value)整数整数
b64dec字符串二进制
base2二进制字符串
base64二进制字符串
be2dec(separator,chunk_size[,truncate])二进制字符串
le2dec(separator,chunk_size[,truncate])二进制字符串
be2hex([separator[,chunk_size[,truncate]]])二进制字符串
bool整数布尔
bytes(offset[,length])二进制二进制
capture-req(id)字符串字符串
capture-res(id)字符串字符串
concat([start[,var[,end]]])字符串字符串
cpl整数整数
crc32([avalanche])二进制整数
crc32c([avalanche])二进制整数
关键字输入类型输出类型
cut_crlf字符串字符串
da-csv-conv(prop[,prop*])字符串字符串
date字符串整数
debug([prefix][,destination])任意相同
digest(algorithm)二进制二进制
div(value)整数整数
djb2([avalanche])二进制整数
even整数布尔
field(index,delimiters[,count])字符串字符串
fix_is_valid二进制布尔
fix_tag_value(tag)二进制二进制
hex二进制字符串
hex2i二进制整数
hmac(algorithm,key)二进制二进制
host_only字符串字符串
htonl整数整数
http_date([offset[,unit]])整数字符串
iif(true,false)布尔字符串
in_table([table])任意布尔
ipmask(mask4[,mask6])地址地址
关键字输入类型输出类型
json([input-code])字符串字符串
json_query(json_path[,output_type])字符串_outtype_
jwt_header_query([json_path[,output_type]])字符串字符串
jwt_payload_query([json_path[,output_type]])字符串字符串
jwt_verify(alg,key)字符串整数
jwt_verify_cert(alg,cert)字符串整数
language(value[,default])字符串字符串
length字符串整数
lower字符串字符串
ltime(format[,offset])整数字符串
ltrim(chars)字符串字符串
map(map_name[,default_value])字符串字符串
map_match(map_name[,default_value])_match_字符串
map_match_output(map_name[,default_value])_match__output_
mod(value)整数整数
mqtt_field_value(pkt_type,fieldname_or_prop_ID)二进制二进制
mqtt_is_valid二进制布尔
ms_ltime(format[,offset])整数字符串
ms_utime(format[,offset])整数字符串
mul(value)整数整数
关键字输入类型输出类型
nbsrv字符串整数
neg整数整数
not整数布尔
odd整数布尔
or(value)整数整数
param(name[,delim])字符串字符串
port_only字符串整数
protobuf(field_number[,field_type])二进制二进制
regsub(regex,subst[,flags])字符串字符串
rfc7239_field(field)字符串字符串
rfc7239_is_valid字符串布尔
rfc7239_n2nn字符串地址 / str
rfc7239_n2np字符串整数 / str
rfc7239_nn地址/str字符串
rfc7239_np整数/str字符串
rtrim(chars)字符串字符串
sdbm([avalanche])二进制整数
secure_memcmp(var)字符串布尔
set-var(var[,cond...])任意相同
sha1二进制二进制
关键字输入类型输出类型
sha2([bits])二进制二进制
srv_is_up字符串布尔
srv_queue字符串整数
strcmp(var)字符串布尔
sub(value)整数整数
table_bytes_in_rate([table])任意整数
table_bytes_out_rate([table])任意整数
table_clr_gpc(idx[,table])任意整数
table_clr_gpc0([table])任意整数
table_clr_gpc1([table])任意整数
table_conn_cnt([table])任意整数
table_conn_cur([table])任意整数
table_conn_rate([table])任意整数
table_expire([table[,default_value]])任意整数
table_glitch_cnt([table])任意整数
table_glitch_rate([table])任意整数
table_gpc(idx[,table])任意整数
table_gpc0([table])任意整数
table_gpc0_rate([table])任意整数
table_gpc1([table])任意整数
关键字输入类型输出类型
table_gpc1_rate([table])任意整数
table_gpc_rate(idx[,table])任意整数
table_gpt(idx[,table])任意整数
table_gpt0([table])任意整数
table_http_err_cnt([table])任意整数
table_http_err_rate([table])任意整数
table_http_fail_cnt([table])任意整数
table_http_fail_rate([table])任意整数
table_http_req_cnt([table])任意整数
table_http_req_rate([table])任意整数
table_idle([table[,default_value]])任意整数
table_inc_gpc(idx[,table])任意整数
table_inc_gpc0([table])任意整数
table_inc_gpc1([table])任意整数
table_kbytes_in([table])任意整数
table_kbytes_out([table])任意整数
table_server_id([table])任意整数
table_sess_cnt([table])任意整数
table_sess_rate([table])任意整数
table_trackers([table])任意整数
关键字输入类型输出类型
ub64dec字符串字符串
ub64enc字符串字符串
ungrpc(field_number[,field_type])二进制二进制 / 整数
unset-var(var)任意相同
upper字符串字符串
url_dec([in_form])字符串字符串
url_enc([enc_type])字符串字符串
us_ltime(format[,offset])整数字符串
us_utime(format[,offset])整数字符串
utime(format[,offset])整数字符串
when(condition)任意相同
word(index,delimiters[,count])字符串字符串
wt6([avalanche])二进制整数
x509_v_err_str整数字符串
xor(value)整数整数
xxh3([seed])二进制整数
xxh32([seed])二进制整数
以下是转换器关键字的详细列表
51d.single(<prop>[,<prop>*])
以字符串形式返回所请求属性的值,值之间由“51degrees-property-separator”指定的分隔符分隔。设备通过传递给转换器的 User-Agent 标头来识别。该函数最多可以传递五个属性名称,如果找不到属性名称,则返回“NoData”值。
Example
# 此处,标头 "X-51D-DeviceTypeMobileTablet" 被添加到请求中, # 它包含了通过传递给转换器的 User-Agent 所请求的三个属性的值。 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>)
将 <value> 添加到类型为有符号整数的输入值中,并以有符号整数形式返回结果。<value> 可以是数值或变量名。有关变量的详细信息,请参见第 2.8 节
add_item(<delim>[,<var>[,<suff>]])
在当前样本之后连接最少 2 个最多 3 个字段,然后将其转换为字符串。第一个 <delim> 是一个常量字符串,如果现有样本不为空且 <var> 或 <suff> 不为空,则将紧跟在现有样本之后附加。第二个 <var> 是一个变量名。将查找该变量,将其内容转换为字符串,并将其紧跟在 <delim> 部分之后附加。如果找不到变量,则不附加任何内容。它是可选的,并且可以选择后跟一个常量字符串 <suff>,但是如果省略 <var>,则 <suff> 是强制性的。此转换器类似于 concat 转换器,可用于构建由一系列其他变量组成的新变量,但主要区别在于它会检查添加分隔符是否合理,例如当前样本为空时就不合理。这种情况需要使用 concat 转换器分隔的 2 个单独规则,其中第一个规则必须在添加分隔符之前检查当前样本字符串是否为空。如果逗号或右括号需要用作分隔符,则必须用引号或反斜杠保护它们,反斜杠本身也需要保护,以免被第一级解析器剥离(有关引用和转义,请参阅第 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_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>])
使用 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>)
对类型为有符号整数的输入值与 <value> 执行按位“与”操作,并以有符号整数形式返回结果。<value> 可以是数值或变量名。有关变量的详细信息,请参见第 2.8 节
将 base64 编码的输入字符串转换(解码)为其二进制表示。它执行 base64() 的反向操作。对于 base64url(“URL 和文件名安全字母表”(RFC 4648))变体,请参见“ub64dec”。
将二进制输入样本转换为每个输入字节包含八个二进制数字的二进制字符串。它用于在原生表示不允许前缀匹配的类型上执行最长前缀匹配,例如 IP 前缀。
将二进制输入样本转换为 base64 字符串。它用于以可靠传输的方式记录或传输二进制内容(例如,SSL ID 可以复制到标头中)。对于 base64url(“URL 和文件名安全字母表”(RFC 4648))变体,请参见“ub64enc”。
be2dec(<separator>,<chunk_size>[,<truncate>])
将大端二进制输入样本转换为一个字符串,其中每个 <chunk_size> 输入字节对应一个无符号整数。如果指定,<separator> 会每 <chunk_size> 个二进制输入字节插入一次。<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>])
将小端二进制输入样本转换为一个字符串,每个 <chunk_size> 输入字节对应一个无符号整数。如果指定,<separator> 会每 <chunk_size> 个二进制输入字节插入一次。<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>]]])
将大端二进制输入样本转换为一个十六进制字符串,其中每个输入字节对应两个十六进制数字。它用于以可靠的方式记录或传输某些二进制输入数据的十六进制转储(例如,可以将 SSL ID 复制到标头中)。如果指定,<separator> 会每 <chunk_size> 个二进制输入字节插入一次。<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
如果类型为有符号整数的输入值非空,则返回布尔值 TRUE,否则返回 FALSE。与 and() 结合使用,可用于报告输入值的位测试的真/假(例如,验证标志的存在)。
bytes(<offset>[,<length>])
从输入二进制样本中提取一些字节。结果是一个二进制样本,从原始样本的偏移量(以字节为单位)开始,并可选地在给定的长度处截断。<offset> 和 <length> 可以是数值或变量名。如果 <offset> 或 <length> 无效,转换器将返回一个空样本。无效的 <offset> 意味着负值或大于等于输入样本长度的值。无效的 <length> 意味着负值,或者在某些情况下,大于输入样本长度的值。
示例
http-request set-var(txn.input) req.hdr(input) # 假设输入是 "012345" http-response set-header bytes_0 "%[var(txn.input),bytes(0)]" # 输出 "012345" http-response set-header bytes_1_3 "%[var(txn.input),bytes(1,3)]" # 输出 "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)]" # 输出 "123"
捕获请求槽 <id> 中的字符串条目,并按原样返回该条目。如果槽不存在,捕获将静默失败。
捕获响应槽 <id> 中的字符串条目,并按原样返回该条目。如果槽不存在,捕获将静默失败。
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])" ## 功能相同 http-request set-header x-hap-sig %[var(txn.sig)]
获取类型为有符号整数的输入值,应用取反(翻转所有位)并以有符号整数的形式返回结果。
crc32([<avalanche>])
使用 CRC32 哈希函数将二进制输入样本哈希成一个无符号 32 位量。可选地,如果可选的 <avalanche> 参数等于 1,则可以对输出应用完整的雪崩哈希函数。此转换器使用与各种基于哈希的负载均衡算法相同的函数,因此它将提供完全相同的结果。它旨在与其他需要对某些输入键计算 CRC32 的软件兼容,因此它遵循在以太网、Gzip、PNG 等中最常见的实现。它比其他算法慢,但可能提供更好或至少更不可预测的分布。它不得用于安全目的,因为 32 位哈希很容易被破解。另请参见“djb2”、“sdbm”、“wt6”、“crc32c”和“hash-type”指令。
crc32c([<avalanche>])
使用 CRC32C 哈希函数将二进制输入样本哈希成一个无符号 32 位量。可选地,如果可选的 <avalanche> 参数等于 1,则可以对输出应用完整的雪崩哈希函数。此转换器使用 RFC4960 附录 B [8] 中描述的相同函数。它旨在与其他需要对某些输入键计算 CRC32C 的软件兼容。它比其他算法慢,并且不得用于安全目的,因为 32 位哈希很容易被破解。另请参见“djb2”、“sdbm”、“wt6”、“crc32”和“hash-type”指令。
在找到的第一个回车符('\r')或换行符('\n')处截断输入样本的字符串表示。仅更新字符串长度。
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)]
此转换器用于转换 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>])
此转换器用作调试工具。它捕获输入样本并将其发送到事件接收器 <destination>,该接收器可以指定一个环形缓冲区,如“buf0”,以及“stdout”或“stderr”。可用的接收器可以在运行时通过在 CLI 上发出“show events”来检查。如果未指定,输出将是“buf0”,可以通过 CLI 的“show events”命令进行查询。可以传递一个可选的前缀 <prefix> 来帮助区分来自多个表达式的输出。然后它将出现在输出消息的冒号之前。输入样本按原样传递到输出,因此将调试转换器插入链中的任何位置都是安全的,即使对于不可打印的样本类型也是如此。
示例
tcp-request connection track-sc0 src,debug(track-sc)
digest(<algorithm>)
将二进制输入样本转换为消息摘要。结果是一个二进制样本。<algorithm> 必须是一个 OpenSSL 消息摘要名称(例如 sha256)。请注意,此转换器仅在 HAProxy 使用 USE_OPENSSL 编译时可用。
div(<value>)
将类型为有符号整数的输入值除以 <value>,并以有符号整数形式返回结果。如果 <value> 为空,则返回最大的无符号整数(通常为 2^63-1)。<value> 可以是数值或变量名。有关变量的详细信息,请参见第 2.8 节
djb2([<avalanche>])
使用 DJB2 哈希函数将二进制输入样本哈希成一个无符号 32 位量。可选地,如果可选的 <avalanche> 参数等于 1,则可以对输出应用完整的雪崩哈希函数。此转换器使用与各种基于哈希的负载均衡算法相同的函数,因此它将提供完全相同的结果。它主要用于调试,但可以用作粘性表条目来收集粗略统计。它不得用于安全目的,因为 32 位哈希很容易被破解。另请参见“crc32”、“sdbm”、“wt6”、“crc32c”和“hash-type”指令。
如果类型为有符号整数的输入值为偶数,则返回布尔值 TRUE,否则返回 FALSE。它在功能上等同于 "not,and(1),bool"。
field(<index>,<delimiters>[,<count>])
从输入字符串中,根据给定的分隔符,从开头(正索引)或结尾(负索引)提取给定索引处的子字符串。索引从 1 或 -1 开始,分隔符是格式化为字符串的字符列表。您可以选择指定要提取的字段数量 <count>(默认为 1)。值为 0 表示提取所有剩余字段。
Example
str(f1_f2_f3__f5),field(4,_) # <空> 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
解析二进制有效载荷并执行关于 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> 中提取值。<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 标签 ID 是 35,所以下面两行将返回相同的内容 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)
将二进制输入样本转换为十六进制字符串,其中每个输入字节对应两个十六进制数字。它用于以可靠的方式记录或传输某些二进制输入数据的十六进制转储(例如,可以将 SSL ID 复制到标头中)。
将每个输入字节包含两个十六进制数字的十六进制字符串转换为整数。如果输入值无法转换,则返回零。
hmac(<algorithm>,<key>)
使用给定的密钥将二进制输入样本转换为消息认证码。结果是一个二进制样本。<algorithm> 必须是已注册的 OpenSSL 消息摘要名称之一(例如 sha256)。<key> 参数必须是 base64 编码的,并且可以是字符串或变量。请注意,此转换器仅在 HAProxy 使用 USE_OPENSSL 编译时可用。
转换包含 Host 标头值的字符串并移除其端口。输入必须遵守 Host 标头值的格式 (rfc9110#section-7.2)。它将支持以下类型的输入:hostname, hostname:80, 127.0.0.1, 127.0.0.1:80, [::1], [::1]:80。此转换器还会将字符串设置为小写。
将输入整数值转换为其网络字节序的 32 位二进制表示。因为样本获取拥有有符号 64 位整数,当使用此转换器时,输入整数值首先被转换为无符号 32 位整数。
http_date([<offset[,<unit>]])
将一个假定包含自纪元以来日期的整数转换为适合在 HTTP 标头字段中使用的字符串表示形式。如果指定了偏移值,则在进行转换之前将其添加到日期中。这对于发出 Date 标头字段、响应中与正偏移量结合使用的 Expires 值,或者当偏移量为负时使用的 Last-Modified 值特别有用。如果指定了单位值,则将时间戳视为“s”(秒,默认行为)、“ms”(毫秒)或“us”(微秒)自纪元以来。偏移量假定与输入时间戳具有相同的单位。
iif(<true>,<false>)
如果输入值为 true,则返回 <true> 字符串。否则返回 <false> 字符串。
示例
http-request set-header x-forwarded-proto %[ssl_fc,iif(https,http)]
in_table([<table>])
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,则返回布尔值 false。否则返回布尔值 true。这可用于验证某个键是否存在于跟踪某些元素的表中(例如,源 IP 地址或 Authorization 标头是否已被看到)。
ipmask(<mask4>[,<mask6>])
将掩码应用于 IP 地址,并使用结果进行查找和存储。这可用于使某个掩码内的所有主机共享相同的表条目,从而使用相同的服务器。mask4 可以以点分十进制形式(例如 255.255.255.0)或 CIDR 形式(例如 24)传递。mask6 可以以四元组形式(例如 ffff:ffff::)或 CIDR 形式(例如 64)传递。如果未提供 mask6,出于向后兼容的原因,IPv6 地址将转换失败。
json([<input-code>])
转义输入字符串并生成一个可用于 JSON 字符串的 ASCII 输出字符串。转换器尝试根据 <input-code> 参数解码输入字符串。它可以是 "ascii"、"utf8"、"utf8s"、"utf8p" 或 "utf8ps"。"ascii" 解码器永远不会失败。"utf8" 解码器检测 3 种类型的错误:- 错误的 UTF-8 序列(单独的 continuation 字节、错误的 continuation 字节数等) - 无效范围(解码值在 UTF-8 禁止范围内) - 代码过长(值使用比必要更多的字节编码)。UTF-8 JSON 编码在 UTF-8 字符大于 0xffff 时可能产生 "too long value" 错误,因为 JSON 字符串转义规范只授权 4 个十六进制数字用于值编码。UTF-8 解码器有 4 种变体,由两个后缀字母组合指定:"p" 表示 "permissive","s" 表示 "silently ignore"。解码器的行为是:- "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 类型 string、boolean、number 和 array。浮点数将作为字符串返回。通过指定 output_type 'int',值将转换为整数。数组将作为字符串返回,以方括号开头和结尾。内容是 CSV。根据数据类型,数组值可能带引号。如果数组值是复杂类型,则字符串包含每个值的完整 json 表示,并用逗号分隔。例如,对 JWT 进行角色查询的结果:["manage-account","manage-account-links","view-profile"] 如果无法转换,json_query 转换器将失败。<json_path> 必须是 https://datatracker.ietf.org/doc/draft-ietf-jsonpath-base/ 中定义的有效 JSON Path 字符串。注意:根据上下文和底层实现,重复 JSON 键的提取是未定义的,并且可能返回输入内容中相同键的第一个、最后一个或任何其他出现次数,并且如果键名以编码形式传递,它们可能并不总是匹配。简而言之,此转换器不适合用于内容清理。
示例
# 从请求体中获取一个整数值 # "{"integer":4}" => 5 http-request set-var(txn.pay_int) req.body,json_query('$.integer','int'),add(1) # 获取名称中带'.'的键 # {"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') # 从JWT Bearer令牌中获取'iss'键的值 http-request set-var(txn.token_payload) req.hdr(Authorization),word(2,.),ub64dec,json_query('$.iss')
jwt_header_query([<json_path>[,<output_type>]])
当输入为 JSON Web Token (JWT) 时,如果没有提供参数,则返回令牌的已解码头部部分(JWT 的第一个 base64-url 编码部分);否则,对令牌的已解码头部部分执行 json_query 操作。有关接受的 json_path 和 output_type 参数的详细信息,请参见“json_query”转换器。请注意,此转换器仅在 HAProxy 编译时使用了 USE_OPENSSL 时才可用。
jwt_payload_query([<json_path>[,<output_type>]])
当输入为 JSON Web Token (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) 执行签名验证。目前,只能处理使用 Compact Serialization 格式的 JWS 令牌(三个由点分隔的 base64-url 编码字符串)。此转换器仅验证令牌的签名,不执行 RFC7519 第 7.2 节中指定的完整 JWT 验证。例如,我们不确保标头和负载内容在解码后是完全有效的 JSON,并且不执行有关其各自内容的任何检查。- <alg> 可以是字符串或变量名(另请参阅 "set-var"),其中包含用于验证的算法名称。RFC7518 第 3.1 节中提及的算法得到管理:+--------------+---------------------------------------------------------+ | "alg" 参数 | 数字签名或 MAC 算法 | | 值 | | +--------------+---------------------------------------------------------+ | HS256 | 使用 SHA-256 的 HMAC | | HS384 | 使用 SHA-384 的 HMAC | | HS512 | 使用 SHA-512 的 HMAC | | RS256 | 使用 SHA-256 的 RSASSA-PKCS1-v1_5 | | RS384 | 使用 SHA-384 的 RSASSA-PKCS1-v1_5 | | RS512 | 使用 SHA-512 的 RSASSA-PKCS1-v1_5 | | ES256 | 使用 P-256 和 SHA-256 的 ECDSA | | ES384 | 使用 P-384 和 SHA-384 的 ECDSA | | ES512 | 使用 P-521 和 SHA-512 的 ECDSA | | PS256 | 使用 SHA-256 和 MGF1 (SHA-256) 的 RSASSA-PSS | | PS384 | 使用 SHA-384 和 MGF1 (SHA-384) 的 RSASSA-PSS | | PS512 | 使用 SHA-512 和 MGF1 (SHA-512) 的 RSASSA-PSS | | none | 未执行数字签名或 MAC | +--------------+---------------------------------------------------------+ - <key> 可以是字符串或变量名(另请参阅 "set-var"),其中包含密钥或公钥路径。密钥仅适用于使用 HMAC 算法时。公钥必须是 PKCS#1 格式(用于 RSA 密钥,以 BEGIN RSA PUBLIC KEY 开头)或 SPKI 格式(Subject Public Key Info,以 BEGIN PUBLIC KEY 开头)。公钥必须在配置解析期间可用,并且无法在运行时更新或加载。有关基于完整 PEM 证书的 JWT 令牌验证,请参阅 "jwt_verify_cert" 转换器。所有可能用于验证 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 编译时可用。
示例
# 从授权标头获取 JWT,提取其 JOSE 标头的 "alg" 字段,并使用公钥验证签名 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) 执行签名验证。目前,只能处理使用 Compact Serialization 格式的 JWS 令牌(三个由点分隔的 base64-url 编码字符串)。此转换器仅验证令牌的签名,不执行 RFC7519 第 7.2 节中指定的完整 JWT 验证。例如,我们不确保标头和负载内容在解码后是完全有效的 JSON,并且不执行有关其各自内容的任何检查。- <alg> 可以是字符串或变量名(另请参阅 "set-var"),其中包含用于验证的算法名称。与 "jwt_verify" 转换器不同,此转换器仅期望证书作为第二个参数,因此不应用于使用 HMAC 算法的令牌。RFC7518 第 3.1 节中提及的算法得到管理(除了 HMAC 算法):+--------------+---------------------------------------------------------+ | "alg" 参数 | 数字签名或 MAC 算法 | | 值 | | +--------------+---------------------------------------------------------+ | RS256 | 使用 SHA-256 的 RSASSA-PKCS1-v1_5 | | RS384 | 使用 SHA-384 的 RSASSA-PKCS1-v1_5 | | RS512 | 使用 SHA-512 的 RSASSA-PKCS1-v1_5 | | ES256 | 使用 P-256 和 SHA-256 的 ECDSA | | ES384 | 使用 P-384 和 SHA-384 的 ECDSA | | ES512 | 使用 P-521 和 SHA-512 的 ECDSA | | PS256 | 使用 SHA-256 和 MGF1 (SHA-256) 的 RSASSA-PSS | | PS384 | 使用 SHA-384 和 MGF1 (SHA-384) 的 RSASSA-PSS | | PS512 | 使用 SHA-512 和 MGF1 (SHA-512) 的 RSASSA-PSS | | none | 未执行数字签名或 MAC | +--------------+---------------------------------------------------------+ - <key> 可以是字符串或变量名(另请参阅 "set-var"),其中包含证书路径。证书必须是标准 PEM 证书(以 BEGIN CERTIFICATE 开头)。它们的路径可以直接传递给转换器,也可以通过变量引用。如果使用变量,相应的证书可以声明在 crt-store 中,也可以通过 stats socket 动态加载。如果直接给出路径,如果相应的证书尚未加载到内部证书存储中,它将在配置解析期间加载,因此它必须已经存在,否则将引发错误。只有明确定义为可用于 JWT 验证的证书才能使用。请参阅 "jwt" crt-store 选项。可以使用 stats socket 动态更新证书并添加新证书。另请参阅管理指南中的 "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 编译时可用。
示例
# 从授权标头获取 JWT,提取其 JOSE 标头的 "alg" 字段,并使用公共证书验证签名 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>])
从 "accept-language" 标头中使用 "req.fhdr" 提取的列表中返回具有最高 q-factor 的值。没有 q-factor 的值其 q-factor 为 1。q-factor 为 0 的值被丢弃。只有属于分号分隔的 <values> 列表中的值才会被考虑。<value> 参数的语法是 "lang[;lang[;lang[;...]]]"。如果没有值与给定列表匹配,并且提供了默认值,则返回默认值。请注意,语言名称在破折号('-')后可能有变体。如果此变体存在于列表中,它将被匹配,但如果不存在,则只检查基础语言。匹配是区分大小写的,输出字符串始终是参数中提供的字符串之一。参数的顺序没有意义,只有请求中值的顺序有意义,因为在共享相同 q-factor 的多个值中,第一个值被使用。
Example
# 此配置根据请求切换到匹配 # 给定语言的后端: 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
获取字符串的长度。这只能放在字符串样本提取函数或返回字符串类型的转换关键字之后。结果是整数类型。
将字符串样本转换为小写。这只能放在字符串样本获取函数之后或返回字符串类型的转换关键字之后。结果类型为字符串。
ltime(<format>[,<offset>])
将一个应包含自纪元以来日期的整数转换为表示该日期的本地时间的字符串,使用 strftime(3) 定义的 <format> 字符串。目的是允许在日志中使用任何日期格式。可以对输入日期应用一个可选的 <offset>(正或负,以秒为单位)。有关操作系统支持的格式,请参阅 strftime() 手册页。另请参阅 utime 转换器。
Example
# 输出两列,一列是本地时间,另一列是 ip:port # 例如 20140710162350 127.0.0.1:57325 log-format %[date,ltime(%Y%m%d%H%M%S)]\ %ci:%cp
ltrim(<chars>)
从输入样本的字符串表示的开头跳过任何属于 <chars> 的字符。
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 中描述的 map 和 ACL 名称格式。避免键重叠非常重要:IP 地址和字符串存储在树中,因此将使用第一个最精细的匹配。其他键存储在列表中,因此将使用第一个匹配的出现。下表包含按输入类型、匹配类型和输出类型排序的所有可用 map 函数列表。
输入类型匹配方法输出类型 str输出类型 int输出类型 ip输出类型 key
strstrmap_strmap_str_intmap_str_ipmap_str_key
strbegmap_begmap_beg_intmap_end_ipmap_end_key
strsubmap_submap_sub_intmap_sub_ipmap_sub_key
strdirmap_dirmap_dir_intmap_dir_ipmap_dir_key
strdommap_dommap_dom_intmap_dom_ipmap_dom_key
strendmap_endmap_end_intmap_end_ipmap_end_key
strregmap_regmap_reg_intmap_reg_ipmap_reg_key
strregmap_regmmap_reg_intmap_reg_ipmap_reg_key
intintmap_intmap_int_intmap_int_ipmap_int_key
ipipmap_ipmap_ip_intmap_ip_ipmap_ip_key
名为“map_regm”的特殊 map 期望正则表达式中有匹配区域,并通过用相应的匹配文本替换反向引用(如“\1”)来修改输出。输出类型“key”表示将返回匹配条目的键(如在 map 文件中找到的)作为字符串,而不是值。请注意,当使用“key”输出类型时,不支持可选的 <default_value> 参数。<map_name> 引用的文件每行包含一个键 + 值。以'#'开头的行和空行都将被忽略。前导的制表符和空格会被去除。然后,键是第一个“word”(一系列非空格/制表符字符),值是这一系列空格/制表符之后直到行尾的内容,不包括尾随的空格/制表符。
Example
# 这是一条注释,会被忽略 2.22.246.0/23 United Kingdom \n <-><-----------><--><------------><----> | | | | `- 尾随空格被忽略 | | | `---------- 值 | | `-------------------- 中间空格被忽略 | `----------------------------  `------------------------------------ 前导空格被忽略
mod(<value>)
将有符号整数类型的输入值除以 <value>,并返回余数作为有符号整数。如果 <value> 为 null,则返回零。<value> 可以是数值或变量名。有关变量的详细信息,请参见 第 2.8 节
mqtt_field_value(<packettype>,<fieldname_or_property_ID>)
返回在类型为 <packettype> 的输入 MQTT 有效负载中找到的 <fieldname> 的值。<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 (or 1): flags, protocol_name, protocol_version, client_identifier, will_topic, will_payload, username, password, keepalive OR any property ID as a numeric value (for MQTT v5.0 packets only): 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 Not supported yet: 38: User Property - CONNACK (or 2): flags, protocol_version, reason_code OR any property ID as a numeric value (for MQTT v5.0 packets only): 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 Not supported yet: 38: User Property 由于当前 HAProxy 设计,只能解析客户端和服务器发送的第一条消息。因此,此转换器只能从 CONNECT 和 CONNACK 数据包类型中提取数据。CONNECT 是客户端发送的第一条消息,CONNACK 是服务器发送的第一个响应。
示例
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 # 与上面相同 tcp-request content set-var(txn.username) \ req.payload(0,0),mqtt_field_value(1,protocol_name) \ if data_in_buffer
检查二进制输入是否为有效的 MQTT 报文。它返回一个布尔值。由于当前 HAProxy 的设计,只能解析客户端和服务器发送的第一个消息。因此,此转换器只能从 CONNECT 和 CONNACK 报文类型中提取数据。CONNECT 是客户端发送的第一个消息,CONNACK 是服务器发送的第一个响应。仅支持 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>])
此转换器功能类似“ltime”,但输入单位是毫秒。它还支持受 date(1) 启发的 %N 转换说明符。将一个假定包含自纪元以来日期的整数,使用由 <format> 字符串定义的格式,通过 strftime(3) 转换为表示本地时间的字符串。目的是允许在日志中使用任何日期格式。可以对输入日期应用一个可选的以毫秒为单位的 <offset>(正或负)。有关您的操作系统支持的格式,请参见 strftime() 手册页。%N 转换说明符允许您输出日期的纳秒部分,但由于输入是毫秒,精度有限 (000000000..999000000)。%N 可以在 % 和 N 之间接受一个宽度参数。这对于显示毫秒 (%3N) 或微秒 (%6N) 很有用。默认和最大宽度为 9 (%N = %9N)。另请参见用于 UTC 的 utime 转换器,以及“ltime”和“us_ltime”转换器。
Example
# 输出 3 列,本地时间、时区和另一列 ip:port # 例如 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>])
此转换器功能类似“utime”,但输入单位是毫秒。它还支持受 date(1) 启发的 %N 转换说明符。将一个假定包含自纪元以来日期的整数,使用由 <format> 字符串定义的格式,通过 strftime(3) 转换为表示 UTC 时间的字符串。目的是允许在日志中使用任何日期格式。可以对输入日期应用一个可选的以毫秒为单位的 <offset>(正或负)。有关您的操作系统支持的格式,请参见 strftime() 手册页。%N 转换说明符允许您输出日期的纳秒部分,但由于输入是毫秒,精度有限 (000000000..999000000)。%N 可以在 % 和 N 之间接受一个宽度参数。这对于显示毫秒 (%3N) 或微秒 (%6N) 很有用。默认和最大宽度为 9 (%N = %9N)。另请参见用于本地时间的 ltime 转换器,以及“utime”和“us_utime”转换器。
Example
# 输出 3 列,UTC 时间、时区和另一列 ip:port # 例如 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>)
将有符号整数类型的输入值乘以 <value>,并返回乘积作为有符号整数。如果发生溢出,将返回该符号的最大可能值,以防止运算环绕。<value> 可以是数值或变量名。有关变量的详细信息,请参见 第 2.8 节
接受一个字符串类型的输入值,将其解释为后端名称,并返回该后端中可用服务器的数量。可用于需要从动态名称(如 map 查找的结果)查找后端的地方。
获取类型为有符号整数的输入值,计算其相反值,并以有符号整数的形式返回余数。0 是单位元。此运算符用于反向减法:为了从一个常量中减去输入值,只需执行 "neg,add(value)"。
如果输入的有符号整数值非零,则返回布尔值 FALSE,否则返回 TRUE。与 and() 结合使用,可用于报告输入值的位测试结果是真还是假(例如,验证某个标志是否存在)。
如果类型为有符号整数的输入值为奇数,则返回布尔值 TRUE,否则返回 FALSE。它在功能上等同于 "and(1),bool"。
or(<value>)
对 <value> 和输入的有符号整数值执行按位“或”运算,并返回结果作为有符号整数。<value> 可以是数值或变量名。有关变量的详细信息,请参见 第 2.8 节
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 选项。
Example
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()
将包含 Host 标头值的字符串转换为一个整数,方法是返回其端口。输入必须遵循 Host 标头值的格式 (rfc9110#section-7.2)。它将支持以下类型的输入:hostname, hostname:80, 127.0.0.1, 127.0.0.1:80, [::1], [::1]:80。如果输入中未提供端口,它将返回 0。
protobuf(<field_number>[,<field_type>])
此函数提取输入二进制样本表示的协议缓冲区消息的原始模式下的协议缓冲区消息字段,其中 <field_number> 作为字段编号(点分表示法),如果 <field_type> 不存在,则作为整数样本(如果此字段存在)(另请参阅下面的 "ungrpc")。授权类型的列表如下:"int32", "int64", "uint32", "uint64", "sint32", "sint64", "bool", "enum" for the "varint" wire type 0 "fixed64", "sfixed64", "double" for the 64bit wire type 1, "fixed32", "sfixed32", "float" for the wire type 5。请注意,"string" 被视为长度分隔类型,因此不需要任何 <field_type> 参数即可提取。有关协议缓冲区消息字段类型的更多信息,请参阅此处:https://developers.google.com/protocol-buffers/docs/encoding
regsub(<regex>,<subst>[,<flags>])
对输入字符串应用基于正则表达式的替换。它执行与众所周知的 "sed" 实用程序相同的操作,使用 "s/<regex>/<subst>/"。默认情况下,它将用替换字符串 <subst> 替换输入字符串中与正则表达式 <regex> 匹配的最大部分的第一次出现。可以通过在第三个参数 <flags> 中添加标志 "g" 来替换所有出现次数。也可以通过在 <flags> 中添加标志 "i" 使正则表达式不区分大小写。由于 <flags> 是一个字符串,它由所有所需标志的串联组成。因此,如果需要 "i" 和 "g",使用 "gi" 或 "ig" 将具有相同的效果。此转换器的主要用途是替换某些字符或字符序列。强烈建议使用受保护的引号将正则表达式部分括起来,以提高清晰度,并避免正则表达式中的右括号与函数中的括号混淆。就像在 Bourne shell 中一样,第一级引号在行上定界单词组时进行处理,第二级可用于参数。建议在外部使用单引号,因为它们不会尝试解析反斜杠或美元符号。
示例
# 去除 "x-path" 标头中的重复 "/"。 # 输入: x-path: /////a///b/c/xzxyz/ # 输出: x-path: /a/b/c/xzxyz/ http-request set-header x-path "%[hdr(x-path),regsub('/+','/','g')]" # 将查询字符串复制到 x-query 并删除所有前导的 '?', ';' 和 '&' http-request set-header x-query "%[query,regsub([?;&]*,'')]" # 捕获组和反向引用 # 两行代码作用相同。 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)]
rfc7239_field(<field>)
从符合 RFC 7239 的标头值输入中提取单个字段/参数。支持的字段有: - proto: 'http' 或 'https' - host: http 兼容的主机 - for: RFC7239 节点 - by: RFC7239 节点 更多信息请见:https://www.rfc-editor.org/rfc/rfc7239.html#section-6
示例
# 从 forwarded 标头中提取 host 字段并将其存储在 req.fhost 变量中 http-request set-var(req.fhost) req.hdr(forwarded),rfc7239_field(host) #输入: "proto=https;host=\"haproxy.org:80\"" # 输出: "haproxy.org:80" # 从 forwarded 标头中提取 for 字段并将其存储在 req.ffor 变量中 http-request set-var(req.ffor) req.hdr(forwarded),rfc7239_field(for) #输入: "proto=https;host=\"haproxy.org:80\";for=\"127.0.0.1:9999\"" # 输出: "127.0.0.1:9999"
如果输入标头是符合 RFC 7239 的标头值,则返回 true,否则返回 false。
示例
acl valid req.hdr(forwarded),rfc7239_is_valid #输入: "for=127.0.0.1;proto=http" # 输出: TRUE #输入: "proto=custom" # 输出: FALSE
将 RFC7239 节点(由 'for' 或 'by' 7239 标头字段提供)转换为其对应的最终节点名称形式: - ipv4 地址 - ipv6 地址 - 'unknown' - '_obfs' 标识符
示例
# 从 forwarded 标头中提取 'for' 字段,从 # 结果节点标识符中提取节点名,并将结果存储在 req.fnn 中 http-request set-var(req.fnn) req.hdr(forwarded),rfc7239_field(for),rfc7239_n2nn #输入: "127.0.0.1:9999" # 输出: 127.0.0.1 (ipv4) #输入: "[ab:cd:ff:ff:ff:ff:ff:ff]:9998" # 输出: ab:cd:ff:ff:ff:ff:ff:ff (ipv6) #输入: "_name:_port" # 输出: "_name" (string)
将 RFC7239 节点(由 'for' 或 'by' 7239 标头字段提供)转换为其对应的最终节点端口形式: - 无符号整数 - '_obfs' 标识符
示例
# 从 forwarded 标头中提取 'by' 字段,从 # 结果节点标识符中提取节点端口,并将结果存储在 req.fnp 中 http-request set-var(req.fnp) req.hdr(forwarded),rfc7239_field(by),rfc7239_n2np #输入: "127.0.0.1:9999" # 输出: 9999 (integer) #输入: "[ab:cd:ff:ff:ff:ff:ff:ff]:9998" # 输出: 9998 (integer) #输入: "_name:_port" # 输出: "_port" (string)
将提供的地址/字符串输入转换为符合 RFC7239 的节点名称。它可用于手动构建 'for' 或 'by' 7239 标头字段。当提供的输入是字符串时,它将自动加上 '_' 前缀以表示混淆的标识符。字符串必须符合 RFC7239 字符集。如果字符串为空,它将被转换为 "unknown" 标识符。
示例
#输入: ipv6(ab:cd:ff:ff:ff:ff:ff:ff) # 输出: "[ab:cd:ff:ff:ff:ff:ff:ff]" #输入: str(test) # 输出: "_test" #输入: str() # 输出: "unknown"
将提供的无符号整数/字符串输入转换为符合 RFC7239 的节点端口。它可用于手动构建 'for' 或 'by' 7239 标头字段。当提供的输入是字符串时,它将自动加上 '_' 前缀以表示混淆的标识符。字符串必须符合 RFC7239 字符集且不能为空。
示例
#输入: int(12) # 输出: "12" #输入: str(test) # 输出: "_test" # 构建 'for' forwarded 标头字段 http-request set-var-fmt(txn.test) "for=\"%[ipv6(::1),rfc7239_nn]:%[int(8080),rfc7239_np]\";" # 输出: "for=\"[::1]:8080\";" # 构建符合 RFC-7239 的标头: http-request set-var-fmt(txn.forwarded) "for=\"%[ipv6(::1),rfc7239_nn]:%[str(8888),rfc7239_np]\";host=\"haproxy.org\";proto=http" # 检查 RFC-合规性: http-request set-var(txn.test) "var(txn.forwarded),debug(test,stderr),rfc7239_is_valid,debug(test,stderr)" # stderr 输出: # [debug] test: type=str <for="[::1]:_8888";host="haproxy.org";proto=http> # [debug] test: type=bool <1>
rtrim(<chars>)
从输入样本的字符串表示的末尾跳过任何属于 <chars> 的字符。
sdbm([<avalanche>])
使用 SDBM 哈希函数将二进制输入样本哈希成一个无符号 32 位整数。可选地,如果可选的 <avalanche> 参数等于 1,可以对输出应用一个完整的雪崩哈希函数。此转换器使用与各种基于哈希的负载均衡算法相同的函数,因此它将提供完全相同的结果。它主要用于调试,但可以用作粘滞表条目来收集粗略的统计数据。它不应用于安全目的,因为 32 位哈希很容易被破解。另请参见“crc32”、“djb2”、“wt6”、“crc32c”和“hash-type”指令。
将 <var> 的内容与输入值进行比较。两个值都被视为二进制字符串。返回一个布尔值,指示两个二进制字符串是否匹配。如果两个二进制字符串长度相同,则比较将在恒定时间内执行。请注意,此转换器仅在 HAProxy 编译时使用了 USE_OPENSSL 时才可用。
Example
http-request set-var(txn.token) hdr(token) # 检查客户端发送的令牌是否与密钥令牌 # 的值匹配,而不会通过时间攻击泄露内容。 acl token_given str(my_secret_token),secure_memcmp(txn.token)
set-var(<var>[,<cond>...])
设置一个变量,变量内容为输入内容。如果所有指定的条件都为真(可能条件的列表见下文),则原样返回输出内容。该变量将保留该值和关联的输入类型。有关变量的详细信息,请参阅第2.8节。您可以向转换器传递最多四个条件,条件列表如下: - "ifexists"/"ifnotexists": 检查变量在当前 set-var 调用之前是否已存在。变量通常是通过成功的 set-var 调用创建的。请注意,"proc" 作用域的变量是在配置解析期间创建的,因此 "ifexists" 条件对于它们始终为真。 - "ifempty"/"ifnotempty": 检查输入是否为空。标量类型永远不为空,因此无论输入内容如何(整数、布尔值、IP 等),ifempty 条件都将为假。 - "ifset"/"ifnotset": 检查变量是否先前已设置,或者是否对变量调用了 unset-var。尚未存在的变量被认为是未设置的。"proc" 变量可以存在但未设置,因为它们是在配置解析期间创建的。 - "ifgt"/"iflt": 检查变量的内容是否"大于"或"小于"输入。此检查只能在输入和变量都为整数类型时执行。否则,检查默认被视为真。
将二进制输入样本转换为 SHA-1 摘要。结果是一个长度为 20 字节的二进制样本。
sha2([<bits>])
将二进制输入样本转换为 SHA-2 家族的摘要。结果是一个长度为 <bits>/8 字节的二进制样本。<bits> 的有效值为 224、256、384、512,分别对应 SHA-<bits>。默认值为 256。请注意,此转换器仅在 HAProxy 编译时使用了 USE_OPENSSL 时才可用。
接受一个字符串类型的输入值,可以是服务器名称或 <backend>/<server> 格式,并在指定服务器当前为 UP 状态时返回 true。可用于需要从动态名称(如 cookie 值,例如 req.cook(SRVID),srv_is_up)查询服务器状态的地方,然后决定将请求定向到别处。在使用此功能之前,请记住,在不受控制的数据上使用此转换器可能会允许外部观察者查询整个配置中任何服务器的状态,这在某些环境中可能是不可接受的。
接受一个字符串类型的输入值,可以是服务器名称或 <backend>/<server> 格式,并返回该服务器上排队的流数量。可用于需要从动态名称(如 cookie 值,例如 req.cook(SRVID),srv_queue)查询排队流的地方,然后决定中断持久性或将请求定向到别处。在使用此功能之前,请记住,在不受控制的数据上使用此转换器可能会允许外部观察者查询整个配置中任何服务器的状态,这在某些环境中可能是不可接受的。
strcmp(<var>)
将 <var> 的内容与字符串类型的输入值进行比较。返回一个与 strcmp(3) 兼容的有符号整数结果:如果两个字符串相同,则为 0。如果左侧字符串在字典序上小于右侧字符串或左侧字符串更短,则返回小于 0 的值。否则返回大于 0 的值(右侧字符串大于左侧字符串或右侧字符串更短)。如果您需要以恒定时间比较两个二进制字符串,另请参见 secure_memcmp 转换器。
Example
http-request set-var(txn.host) hdr(host) # 检查客户端是否正在尝试域前置(domain fronting)。 acl ssl_sni_http_host_match ssl_fc_sni,strcmp(txn.host) eq 0
sub(<value>)
从有符号整数类型的输入值中减去 <value>,并返回结果作为有符号整数。注意:为了从一个常量中减去输入值,只需执行 "neg,add(value)"。<value> 可以是数值或变量名。有关变量的详细信息,请参见 第 2.8 节
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的平均客户端到服务器字节速率,该速率是在表中配置的周期内测量的字节量。另请参见 sc_bytes_in_rate 样本提取关键字。
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的平均服务器到客户端字节速率,该速率是在表中配置的周期内测量的字节量。另请参见 sc_bytes_out_rate 样本提取关键字。
table_clr_gpc(<idx>[,<table>])
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。清除 gpc 数组中索引 <idx> 处的通用计数器,并返回其先前的值。<idx> 是一个 0 到 99 之间的整数。如果未找到条目,则会创建一个条目并返回 0。此转换器仅适用于 'gpc' 数组 data_type(而不适用于旧版的 'gpc0' 或 'gpc1' data_types)。另请参见 sc_clr_gpc 样本提取关键字。
table_clr_gpc0([<table>])
使用输入样本在当前代理的 stick-table 或指定的 stick-table 中执行查找。清除第一个通用计数器 '0' 并返回其先前的值。如果未找到条目,则创建一个条目并返回 0。这通常用作表达式中的第二个ACL,以便在第一个ACL验证时标记连接。
示例
# 如果连续 5 个请求的速率持续超过每秒 10 个会话,则阻止, # 并在流量减慢时立即重置计数器。 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>])
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。清除第一个通用计数器 '1' 并返回其先前的值。如果未找到条目,则会创建一个条目并返回 0。这通常在表达式中用作第二个 ACL,以便在第一个 ACL 被验证时标记一个连接。另请参见 sc_clr_gpc1 样本提取关键字。
table_conn_cnt([<table>])
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的累计传入连接数。另请参见 sc_conn_cnt 样本提取关键字。
table_conn_cur([<table>])
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的当前并发跟踪连接数。另请参见 sc_conn_cur 样本提取关键字。
table_conn_rate([<table>])
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的平均传入连接速率。另请参见 sc_conn_rate 样本提取关键字。
table_expire([<table>[,<default_value>]])
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,转换器将失败,除非设置了 <default_value>:这会使转换器成功并返回 <default_value>。如果找到了键,转换器将返回与指定表中输入样本关联的键过期延迟。另请参见 table_idle 样本提取关键字。
table_glitch_cnt([<table>])
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的前端连接故障的累计数量。另请参见 sc_glitch_cnt 样本提取关键字和 fc_glitches,后者用于测量当前前端连接上的值。
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的平均前端连接故障率。另请参见 sc_glitch_rate 样本提取关键字。
table_gpc(<idx>[,<table>])
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,则返回整数值零。否则,转换器返回与指定 <table> 中输入样本关联的数组中索引 <idx> 处的通用计数器的当前值。<idx> 是一个 0 到 99 之间的整数。如果在此索引处没有存储 GPC,它也返回整数值 0。这仅适用于 'gpc' 数组 data_type(而不适用于旧版的 'gpc0' 或 'gpc1' data_types)。另请参见 sc_get_gpc 样本提取关键字。
table_gpc0([<table>])
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的第一个通用计数器的当前值。另请参见 sc_get_gpc0 样本提取关键字。
table_gpc0_rate([<table>])
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,则返回整数值零。否则,转换器返回在表中配置的周期内,与指定表中输入样本关联的 gpc0 计数器被递增的频率。另请参见 sc_get_gpc0_rate 样本提取关键字。
table_gpc1([<table>])
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的第二个通用计数器的当前值。另请参见 sc_get_gpc1 样本提取关键字。
table_gpc1_rate([<table>])
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,则返回整数值零。否则,转换器返回在表中配置的周期内,与指定表中输入样本关联的 gpc1 计数器被递增的频率。另请参见 sc_get_gpc1_rate 样本提取关键字。
table_gpc_rate(<idx>[,<table>])
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,则返回整数值零。否则,转换器返回在配置的周期内,数组(与指定粘滞表 <table> 中的输入样本关联)中索引 <idx> 处的全局计数器被递增的频率。<idx> 是一个 0 到 99 之间的整数。如果在此索引处没有存储 gpc_rate,它也返回整数值 0。这仅适用于 'gpc_rate' 数组 data_type(而不适用于旧版的 'gpc0_rate' 或 'gpc1_rate' data_types)。另请参见 sc_gpc_rate 样本提取关键字。
table_gpt(<idx>[,<table>])
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,则返回整数值零。否则,转换器返回与指定 <table> 中输入样本关联的数组中索引 <idx> 处的通用标签的当前值。<idx> 是一个 0 到 99 之间的整数。如果在此索引处没有存储 GPT,它也返回整数值 0。这仅适用于 'gpt' 数组 data_type(而不适用于旧版的 'gpt0' data-type)。另请参见 sc_get_gpt 样本提取关键字。
table_gpt0([<table>])
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的第一个通用标签的当前值。另请参见 sc_get_gpt0 样本提取关键字。
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的 HTTP 错误的累计数量。另请参见 sc_http_err_cnt 样本提取关键字。
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,则返回整数值零。否则,返回与指定表中输入样本关联的 HTTP 错误的平均速率,该速率是在表中配置的周期内测量的错误数量。另请参见 sc_http_err_rate 样本提取关键字。
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的 HTTP 失败的累计数量。另请参见 sc_http_fail_cnt 样本提取关键字。
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,则返回整数值零。否则,返回与指定表中输入样本关联的 HTTP 失败的平均速率,该速率是在表中配置的周期内测量的失败数量。另请参见 sc_http_fail_rate 样本提取关键字。
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的 HTTP 请求的累计数量。另请参见 sc_http_req_cnt 样本提取关键字。
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,则返回整数值零。否则,返回与指定表中输入样本关联的 HTTP 请求的平均速率,该速率是在表中配置的周期内测量的请求数量。另请参见 sc_http_req_rate 样本提取关键字。
table_idle([<table>[,<default_value>]])
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,转换器将失败,除非设置了 <default_value>:这会使转换器成功并返回 <default_value>。如果找到了键,转换器将返回与指定表中输入样本关联的键条目自上次更新以来保持空闲的时间。另请参见 table_expire 样本提取关键字。
table_inc_gpc(<idx>[,<table>])
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。递增数组中索引 <idx> 处的通用计数器并返回其新值。<idx> 是一个 0 到 99 之间的整数。如果未找到条目,则会创建一个条目并返回 1。此转换器仅适用于 'gpc' 数组 data_type(而不适用于旧版的 'gpc0' 或 'gpc1' data_types)。另请参见 sc_inc_gpc。
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>])
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。递增通用计数器 '1' 并返回其新值。如果未找到条目,则会创建一个条目并返回 1。另请参见 sc0/sc2/sc2_inc_gpc1。这通常在表达式中用作第二个 ACL,以便在第一个 ACL 被验证时标记一个连接。
table_kbytes_in([<table>])
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的客户端到服务器数据的累计数量,以千字节为单位。该测试目前在 32 位整数上执行,这限制了值的大小为 4 TB。另请参见 sc_kbytes_in 样本提取关键字。
table_kbytes_out([<table>])
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中未找到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的服务器到客户端数据的累计数量,以千字节为单位。该测试目前在 32 位整数上执行,这限制了值的大小为 4 TB。另请参见 sc_kbytes_out 样本提取关键字。
table_server_id([<table>])
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回与指定表中的输入样本关联的服务器 ID。当与服务器的连接成功时,服务器 ID 通过“stick”规则与样本关联。服务器 ID 为零表示没有服务器与此键关联。
table_sess_cnt([<table>])
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回与指定表中的输入样本关联的累计传入会话数。请注意,此处的会话指的是被“tcp-request connection”规则集接受的传入连接。另请参见 sc_sess_cnt 样本提取关键字。
table_sess_rate([<table>])
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回与指定表中的输入样本关联的平均传入会话率。请注意,此处的会话指的是被“tcp-request connection”规则集接受的传入连接。另请参见 sc_sess_rate 样本提取关键字。
table_trackers([<table>])
使用输入样本在当前代理的粘滞表或指定的粘滞表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回在指定表中跟踪与输入样本相同键的当前并发连接数。它与 table_conn_cur 的不同之处在于它不依赖任何存储的信息,而是依赖于表的引用计数(即在 CLI 上通过“show table”返回的“use”值)。这有时可能更适合于第 7 层跟踪。例如,它可用于告知服务器来自给定地址的并发连接数。另请参见 sc_trackers 样本提取关键字。
此转换器是 b64dec 转换器的 base64url 变体。base64url 编码是 base64 编码的“URL 和文件名安全字母表”变体。它也是 JWT (JSON Web Token) 标准中使用的编码。
示例
# 解码 JWT 负载: http-request set-var(txn.token_payload) req.hdr(Authorization),word(2,.),ub64dec
此转换器是 base64 转换器的 base64url 变体。
ungrpc(<field_number>[,<field_type>])
这会以原始模式从 gRPC 消息的输入二进制样本表示中提取协议缓冲区消息字段,如果不存在 <field_type>,则使用 <field_number> 作为字段编号(点式表示法),如果存在该字段,则将其作为整数样本提取。授权类型的列表如下:"int32", "int64", "uint32", "uint64", "sint32", "sint64", "bool", "enum" (for the "varint" wire type 0) "fixed64", "sfixed64", "double" (for the 64bit wire type 1), "fixed32", "sfixed32", "float" (for the wire type 5)。请注意,"string" 被视为长度分隔类型,因此提取时不需要任何 <field_type> 参数。有关协议缓冲区消息字段类型的更多信息,请参阅此处:https://developers.google.com/protocol-buffers/docs/encoding
示例
// 这是一个根据 // https://github.com/grpc/grpc/blob/master/examples/protos/route_guide.proto 改编的 protocol buffer .proto 文件内容 message Point { int32 latitude = 1; int32 longitude = 2; } message PPoint { Point point = 59; } message Rectangle { // 矩形的一个角。 PPoint lo = 48; // 矩形的另一个角。 PPoint hi = 49; }
假设一个请求正文由一个 "Rectangle" 对象值(两个 PPoint 协议缓冲区消息)组成,可以使用这些 "ungrpc" 指令提取这四个协议缓冲区字段:req.body,ungrpc(48.59.1,int32) # 第一个 PPoint 的 "lo" 的 "latitude" req.body,ungrpc(48.59.2,int32) # 第一个 PPoint 的 "lo" 的 "longitude" req.body,ungrpc(49.59.1,int32) # 第二个 PPoint 的 "hi" 的 "latitude" req.body,ungrpc(49.59.2,int32) # 第二个 PPoint 的 "hi" 的 "longitude" 我们还可以如下提取中间的 48.59 字段作为二进制样本:req.body,ungrpc(48.59) 由于 gRPC 消息始终由 gRPC 标头后跟协议缓冲区消息组成,在前面的示例中,第一个 PPoint 的 "lo" 的 "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>)
如果输入内容已定义,则取消设置变量。变量的名称以其作用域的指示开头。有关变量的详细信息,请参阅第 2.8 节
将字符串样本转换为大写。这只能放在字符串样本提取函数之后或返回字符串类型的转换关键字之后。结果为字符串类型。
url_dec([<in_form>])
接受一个经过 URL 编码的字符串作为输入,并返回其解码后的版本作为输出。输入和输出的类型都是字符串。如果将 <in_form> 参数设置为非零整数值,则假定输入字符串是表单或查询字符串的一部分,并且“+”字符将被转换为空格(' ')。否则,只有在表示查询字符串的问号(“?”)之后才会发生这种情况。
url_enc([<enc_type>])
接受一个字符串作为输入,并返回其编码后的版本作为输出。输入和输出的类型都是字符串。默认情况下,编码类型用于`query`类型。目前不支持其他类型,但可选参数是为了将来的更改而保留的。
us_ltime(<format>[,<offset>])
此功能类似于 "ltime",但输入以微秒为单位。它还支持受 date(1) 启发的 %N 转换说明符。将一个假定包含自纪元以来的日期的整数转换为一个字符串,该字符串使用 strftime(3) 定义的 <format> 字符串以本地时间表示该日期。目的是允许在日志中使用任何日期格式。可以对输入日期应用一个可选的 <offset>(正值或负值),以微秒为单位。请参阅 strftime() 手册页以了解您的操作系统支持的格式。%N 转换说明符允许您输出日期的纳秒部分,由于输入是微秒,精度有限 (000000000..999999000)。%N 可以在 % 和 N 之间使用宽度参数。它对于显示毫秒 (%3N) 或微秒 (%6N) 非常有用。默认和最大宽度为 9 (%N = %9N)。另请参阅用于 UTC 的 "utime" 转换器以及 "ltime" 和 "ms_ltime" 转换器。
Example
# 输出 3 个部分:本地时间、时区和另一个包含 ip:port 的部分 # 例如 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>])
此功能类似于 "utime",但输入以微秒为单位。它还支持受 date(1) 启发的 %N 转换说明符。将一个假定包含自纪元以来的日期的整数转换为一个字符串,该字符串使用 strftime(3) 定义的 <format> 字符串以 UTC 时间表示该日期。目的是允许在日志中使用任何日期格式。可以对输入日期应用一个可选的 <offset>(正值或负值),以微秒为单位。请参阅 strftime() 手册页以了解您的操作系统支持的格式。%N 转换说明符允许您输出日期的纳秒部分,由于输入是微秒,精度有限 (000000000..999999000)。%N 可以在 % 和 N 之间使用宽度参数。它对于显示毫秒 (%3N) 或微秒 (%6N) 非常有用。默认和最大宽度为 9 (%N = %9N)。另请参阅用于本地时间的 "ltime" 转换器以及 "utime" 和 "ms_utime" 转换器。
Example
# 输出 3 个部分:UTC 时间、时区和另一个包含 ip:port 的部分 # 例如 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>])
将一个应包含自纪元以来日期的整数,使用由 <format> 字符串定义的格式,通过 strftime(3) 转换为表示 UTC 时间的字符串。目的是允许在日志中使用任何日期格式。可以对输入日期应用一个可选的 <offset>(单位为秒,可正可负)。有关您的操作系统支持的格式,请参阅 strftime() 手册页。另请参阅“ltime”转换器以及“ms_utime”和“us_utime”。
Example
# 输出两个部分,一个包含 UTC 时间,另一个包含 ip:port # 例如 20140710162350 127.0.0.1:57325 log-format %[date,utime(%Y%m%d%H%M%S)]\ %ci:%cp
when(<condition>[,<args>...])
评估条件,如果条件为真,则将输入样本原样传递给输出,否则返回空值。这专门用于生成一些很少需要的数据,这些数据只应在特定条件下发出,例如在遇到错误时发出调试信息。条件由下面列表中的关键字组成,前面可选地加上一个感叹号 ('!') 来否定它,后面可选地加上一些特定于该条件的参数: - "error" 在处理请求或流期间遇到错误时返回 true。它使用与 "dontlog-normal" 相同的规则(例如,成功的重新分发算作错误)。 - "forwarded" 在请求被转发到后端服务器时返回 true。 - "normal" 在没有发生错误时返回 true(这等同于 "!error")。 - "processed" 在请求被转发到后端服务器或被 applet 处理时返回 true。 - "stopping" 如果在评估规则时进程当前正在停止,则返回 true。 - "toapplet" 在请求被 applet 处理时返回 true。 - "acl" 在下一个参数指定的 ACL 评估为 true 时返回 true。请注意,ACL 由转换器内联评估,因此它引用的内容在该上下文中必须有效。一个特定的用例是评估总传输时间是否过长,然后决定是否记录异常长传输的详细信息。请注意,无论如何都会评估内容,因此这样做并不能避免生成该信息。它仅用于避免生成该信息。一个例子是在日志中仅在处理过程中遇到错误时添加后端流调试信息,或者在停止时记录额外信息等。
示例
# 正常时记录 "dbg={-}",错误时记录 "dbg={... 调试信息 ...}": log-format "$HAPROXY_HTTP_LOG_FMT dbg={%[bs.debug_str,when(!normal)]}" 在这里,当规则未验证时,日志中的“dbg”字段将只包含一个破折号('-')以表示内容缺失,而验证通过时将发出整个调试块。
示例 # 正常时记录 "dbg={-}",传输缓慢时记录 "dbg={... 调试信息 ...}" 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)]}" 示例 # 仅在发出真实连接时才发出后端源 IP/端口: log-format "$HAPROXY_HTTP_LOG_FMT \ src=[%[bc_src,when(forwarded)]:%[bc_src_port,when(forwarded)]]" 由于当条件不为真时它会终止表达式的评估,因此也可以用它来阻止后续转换器的调用。例如,这可以用于仅在出错时调用 debug() 转换器,以便仅在绝对必要时记录元素。
示例
# 仅在出错且输出为连接时,才将整个响应头列表输出到 stderr。 # 这里我们滥用了一个虚拟变量。 http-after-response set-var(res.test) \ res.hdrs,when(error),when(forwarded),debug(hdrs,stderr)
word(<index>,<delimiters>[,<count>])
根据给定的分隔符,从输入字符串中提取从头开始(正索引)或从尾开始(负索引)计数的第 n 个单词。索引从 1 或 -1 开始,分隔符是格式化为字符串的字符列表。空单词会被跳过。这意味着输入字符串开头或结尾的分隔符会被忽略,输入字符串内的连续分隔符被视为单个分隔符。您可以选择性地指定要提取的单词数 <count>(默认为 1)。值为 0 表示提取所有剩余的单词。
Example
str(f1_f2_f3__f5),word(4,_) # f5 str(f1_f2_f3__f5),word(5,_) # <未找到> 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 哈希函数将二进制输入样本哈希为一个无符号 32 位整数。可选地,如果可选的 <avalanche> 参数等于 1,则可以对输出应用全雪崩哈希函数。此转换器使用与各种基于哈希的负载均衡算法相同的函数,因此它将提供完全相同的结果。它主要用于调试,但可以用作粘滞表条目以收集粗略的统计数据。它不得用于安全目的,因为 32 位哈希很容易被破解。另请参阅“crc32”、“djb2”、“sdbm”、“crc32c”和“hash-type”指令。
将数值转换为其对应的 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>)
在 <value> 和有符号整数类型的输入值之间执行按位“XOR”(异或)操作,并返回结果作为有符号整数。<value> 可以是数值或变量名。有关变量的详细信息,请参阅第 2.8 节
xxh3([<seed>])
使用 XXhash 哈希函数的 XXH3 64 位变体将二进制输入样本哈希为一个有符号 64 位整数。此哈希支持一个种子,默认为零,但可以通过 <seed> 参数传递不同的值。此哈希以其优异性能和极快速度而闻名,因此可用于哈希 URL 和/或 URL 参数,作为粘滞表键来收集具有低碰撞率的统计数据,但必须注意,该算法不被认为是密码学安全的。
xxh32([<seed>])
使用 XXHash 哈希函数的 32 位变体将二进制输入样本哈希为一个无符号 32 位整数。此哈希支持一个种子,默认为零,但可以通过 <seed> 参数传递不同的值。此哈希以其优异性能和极快速度而闻名,因此可用于哈希 URL 和/或 URL 参数,作为粘滞表键来收集具有低碰撞率的统计数据,但必须注意,该算法不被认为是密码学安全的。
xxh64([<seed>])
使用 XXHash 哈希函数的 64 位变体将二进制输入样本哈希为一个有符号 64 位整数。此哈希支持一个种子,默认为零,但可以通过 <seed> 参数传递不同的值。此哈希以其优异性能和极快速度而闻名,因此可用于哈希 URL 和/或 URL 参数,作为粘滞表键来收集具有低碰撞率的统计数据,但必须注意,该算法不被认为是密码学安全的。

7.3.2. 从内部状态提取样本

第一组样本提取方法适用于甚至与任何客户端信息都无关的内部信息。这些有时与“monitor fail”指令一起使用,以向外部观察者报告内部状态。本节中描述的样本提取方法可在任何地方使用。本节中样本提取方法及其各自类型的摘要
关键字输出类型
acl([!]<name>[,...])布尔
act_conn整数
always_false布尔
always_true布尔
avg_queue([<backend>])整数
be_conn([<backend>])整数
be_conn_free([<backend>])整数
be_sess_rate([<backend>])整数
bin(<hex>)bin
bool(<bool>)bool
connslots([<backend>])整数
cpu_calls整数
cpu_ns_avg整数
cpu_ns_tot整数
date([<offset>[,<unit>]])整数
date_us整数
env(<name>)字符串
fe_conn([<frontend>])整数
fe_req_rate([<frontend>])整数
fe_sess_rate([<frontend>])整数
关键字输出类型
hostname字符串
int(<integer>)signed
ipv4(<ipv4>)ipv4
ipv6(<ipv6>)ipv6
last_entity字符串
last_rule_file字符串
last_rule_line整数
lat_ns_avg整数
lat_ns_tot整数
meth(<method>)method
nbsrv([<backend>])整数
pid整数
prio_class整数
prio_offset整数
proc整数
queue([<backend>])整数
quic_enabled布尔
rand([<range>])整数
srv_conn([<backend>/]<server>)整数
srv_conn_free([<backend>/]<server>)整数
关键字输出类型
srv_is_up([<backend>/]<server>)布尔
srv_iweight([<backend>/]<server>)整数
srv_queue([<backend>/]<server>)整数
srv_sess_rate([<backend>/]<server>)整数
srv_uweight([<backend>/]<server>)整数
srv_weight([<backend>/]<server>)整数
stopping布尔
str(<string>)字符串
table_avl([<table>])整数
table_cnt([<table>])整数
term_events字符串
thread整数
txn.id32整数
txn.sess_term_state字符串
uptime整数
uuid([<version>])字符串
var(<var-name>[,<default>])undefined
wait_end布尔
waiting_entity字符串
详细列表
acl([!]<name>[,...]) : boolean
如果所有指定 ACL 的评估结果都为 true,则返回 true,否则返回 false。最多可以提供 12 个 ACL,每个 ACL 用逗号分隔。每个指定的 ACL 都可以以“!”为前缀来反转结果。如果任何评估产生错误,则样本也返回错误。请注意,HAProxy 不会对引用的 ACL 执行任何验证检查,例如在响应上下文中使用使用 http 请求样本的 ACL。此行为将来可能会更改。
act_conn : integer
返回进程上的活动并发连接总数。
always_false : 布尔值
始终返回布尔值“false”。在调整配置时,它可以与 ACL 一起用作另一个 ACL 的临时替代品。
always_true : 布尔值
始终返回布尔值“true”。在调整配置时,它可以与 ACL 一起用作另一个 ACL 的临时替代品。
avg_queue([<backend>]) : 整数
返回指定后端排队连接总数除以活动服务器数量的结果。如果未指定后端,则使用当前后端。这与 "queue" 非常相似,不同之处在于它考虑了服务器集群的大小,以便更准确地衡量新连接可能需要处理的时间。主要用途是与 ACL 结合使用,当确定新用户将获得降级服务时向其返回抱歉页面,或者将其传递给后端服务器作为标头,以便它们决定在降级模式下工作或禁用某些功能以加快处理速度。请注意,如果不再有任何活动的服务器,排队连接数的两倍将被视为测量值。这是一个公平的估计,因为我们期望一台服务器很快就能恢复,但我们仍然更喜欢将新流量发送到状态更好的其他后端。另请参阅 "queue"、"be_conn" 和 "be_sess_rate" 样本获取。
be_conn([<backend>]) : 整数
适用于后端上当前已建立的连接数,可能包括正在评估的连接。如果未指定后端名称,则使用当前后端。但也可以检查另一个后端。当标称服务器组已满时,它可用于使用特定的服务器组。另请参见“fe_conn”、“queue”、“be_conn_free”和“be_sess_rate”标准。
be_conn_free([<backend>]) : integer
返回一个整数值,对应于后端中可用服务器上的可用连接数。不包括队列槽位。也不包括备份服务器,除非所有其他服务器都已关闭。如果未指定后端名称,则使用当前后端。但也可以检查另一个后端。当标称服务器组已满时,它可用于使用特定的服务器组。另请参见“be_conn”、“connslots”和“srv_conn_free”标准。其他注意事项和说明:如果任何服务器的 maxconn 或 maxqueue 为 0(表示无限制),则此提取显然没有意义,在这种情况下返回的值将为 -1。
be_sess_rate([<backend>]) : 整数
返回一个整数值,对应于后端上的会话创建速率,以每秒新会话数表示。这与 ACL 一起使用,以便在昂贵或脆弱的后端达到过高的会话速率时切换到备用后端,或限制服务滥用(例如防止在线词典被爬取)。使用 log-format 指令将此元素添加到日志中也很有用。
Example
# 如果字典请求过于频繁,则重定向到错误页面 backend dynamic mode http acl being_scanned be_sess_rate gt 100 redirect location /denied.html if being_scanned
bin(<hex>) : bin
返回一个二进制链。输入是字符串的十六进制表示。
bool(<bool>) : 布尔值
返回一个布尔值。<bool> 可以是 'true'、'false'、'1' 或 '0'。'false' 和 '0' 相同。'true' 和 '1' 相同。
connslots([<backend>]) : 整数
通过将所有服务器的最大连接数和最大队列大小相加,返回后端中仍然可用的连接槽数量对应的整数值。这可能只用于 ACL。这里的基本思想是能够测量仍然可用的连接"槽"的数量(连接+队列),以便超出此数量的任何内容(预期用法;请参阅 "use_backend" 关键字)可以重定向到不同的后端。'connslots' = 可用服务器连接槽数量 + 可用服务器队列槽数量。请注意,虽然可以使用 "fe_conn",但当您有流量流向单个 IP,然后根据 ACL(可能使用基于名称的负载平衡)拆分成多个后端时,"connslots" 特别有用,并且您希望能够区分不同的后端及其可用的 "connslots"。此外,虽然 "nbsrv" 只测量实际*宕机*的服务器,但此获取更细粒度,还会查看可用连接槽的数量。另请参阅 "queue" 和 "avg_queue"。其他注意事项和说明:在目前这个时间点,代码不处理动态连接。此外,如果任何服务器 maxconn 或 maxqueue 为 0,则此获取显然没有意义,在这种情况下返回的值将为 -1。
cpu_calls : integer
返回自处理流或当前请求的任务分配以来对其的调用次数。在 HTTP keep-alive 的情况下,每次新请求都会在同一连接上重置此数字。此值通常应较低且稳定(对于典型的简单请求约为 2 次调用),但如果执行了某些处理(压缩、缓存或分析),则可能会变高。这纯粹是为了性能监控。
cpu_ns_avg : integer
返回处理流或当前请求的每个任务调用的平均纳秒数。在 HTTP keep-alive 的情况下,每次新请求都会在同一连接上重置此数字。此值表示每次调用处理请求或连接的总体成本。没有好坏之分,但调用中花费的时间会自动导致其他处理的延迟(参见下面的 lat_ns_avg),并可能影响其他连接的表观响应时间。某些操作(如压缩、复杂正则表达式匹配或繁重的 Lua 操作)可能会直接影响此值,将其记录在日志中将更容易发现需要修复以恢复良好性能的错误处理。注意:此值正好是 cpu_ns_tot 除以 cpu_calls。
cpu_ns_tot : integer
返回处理流或当前请求的每个任务调用的总纳秒数。在 HTTP keep-alive 的情况下,每次新请求都会在同一连接上重置此数字。此值表示每次调用处理请求或连接的总体成本。没有好坏之分,但调用中花费的时间会自动导致其他处理的延迟(参见下面的 lat_ns_avg),导致机器上的 CPU 成本,并可能影响其他连接的表观响应时间。某些操作(如压缩、复杂正则表达式匹配或繁重的 Lua 操作)可能会直接影响此值,将其记录在日志中将更容易发现需要修复以恢复良好性能的错误处理。由于 cpu_calls 计数较高(例如,在处理许多 HTTP 块时),该值可能会人为地偏高,因此通常首选记录 cpu_ns_avg。
date([<offset>[,<unit>]]) : integer
以纪元(自 1970 年 1 月 1 日以来的秒数)形式返回当前日期。如果指定了偏移值,则在返回值之前将其添加到当前日期。这对于计算相对日期特别有用,因为允许正负偏移。与 http_date 转换器结合使用时很有用。<unit> 是可选的,可以设置为“s”表示秒(默认行为)、“ms”表示毫秒或“us”表示微秒。如果设置了 unit,则返回值是一个整数,反映自纪元以来的秒数、毫秒数或微秒数,再加上偏移量。当需要不到一秒的时间分辨率时,这很有用。
Example
# 在每个响应中设置一个到期头,时间为现在+1小时 http-response set-header Expires %[date(3600),http_date] # 在每个响应中设置一个到期头,时间为现在+1小时, # 具有毫秒级粒度 http-response set-header Expires %[date(3600000,ms),http_date(0,ms)]
date_us : integer
返回日期的微秒部分(“秒”部分由 date 样本返回)。此样本与 date 样本一致,因为它来自相同的 timeval 结构。
env(<name>) : 字符串
返回一个包含环境变量 <name> 值的字符串。提醒一下,环境变量是每个进程的,并在进程启动时采样。这对于将一些信息传递给下一跳服务器,或者与 ACL 结合使用以在进程以特定方式启动时采取特定操作很有用。
示例
# 将 Via 头传递给下一跳,其中包含本地主机名 http-request add-header Via 1.1\ %[env(HOSTNAME)] # 当设置了 STOP 环境变量时,拒绝无 cookie 的请求 http-request deny if !{ req.cook(SESSIONID) -m found } { env(STOP) -m found }
fe_conn([<frontend>]) : 整数
返回前端上当前已建立的连接数,可能包括正在评估的连接。如果未指定前端名称,则使用当前前端。但也可以检查另一个前端。它可用于在硬阻塞之前返回一个“抱歉”页面,或者在服务器场被认为已满时使用特定的后端来处理新请求。这主要与 ACL 一起使用,但也可以用于在 HTTP 头中将一些统计信息传递给服务器。另请参阅“dst_conn”、“be_conn”、“fe_sess_rate”提取。
fe_req_rate([<frontend>]) : 整数
返回一个整数值,对应于每秒发送到前端的 HTTP 请求数。在启用客户端保持连接(keep-alive)的情况下,此数字可能与“fe_sess_rate”不同。
fe_sess_rate([<frontend>]) : 整数
返回一个整数值,对应于前端上的会话创建速率,单位为每秒新会话数。这与 ACL 一起使用,将传入会话速率限制在可接受的范围内,以便尽早防止服务滥用,例如,当与其他第 4 层 ACL 结合使用时,以强制客户端等待一段时间,直到速率下降到限制以下。使用 log-format 指令将此元素添加到日志中也很有用。另请参阅前端中使用的“rate-limit sessions”指令。
Example
# 此前端将传入邮件限制为 10/s,最多 100 个 # 并发连接。我们接受低于 10/s 的任何连接,并 # 强制超出的客户端等待 100 毫秒。由于客户端限制为 # 最多 100 个,因此每秒传入的邮件不能超过 10 封。 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>) : 有符号整数
返回一个有符号整数。
ipv4(<ipv4>) : ipv4
返回一个 IPv4 地址。
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-format "$HAPROXY_HTTP_LOG_FMT %{Q}[last_entity,when(error)]
这返回包含在流分析期间匹配的最后一个最终规则的配置文件的名称。最终规则是终止规则集评估的规则(例如 "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 : integer
返回处理流的任务被唤醒和实际调用之间花费的平均纳秒数。对于 HTTP keep-alive 的同一连接上的每个新请求,此数字会重置。该值表示由并行处理的所有其他请求对当前请求造成的总体延迟,是由于“嘈杂邻居”引起的感知性能的直接指标。为了保持较低的值,可以通过使用 "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 keep-alive 的同一连接上的每个新请求,此数字会重置。该值表示由并行处理的所有其他请求对当前请求造成的总体延迟,是由于“嘈杂邻居”引起的感知性能的直接指标。为了保持较低的值,可以通过使用 "tune.runqueue-depth" 减少调度程序的运行队列深度,通过使用 "tune.maxpollevents" 减少一次处理的并发事件数,通过使用 "bind" 行或前端中的 "nice" 选项降低流的 nice 值,通过使用 "tune.sched.low-latency" 启用低延迟调度,或者通过在日志中查找其他重型请求(显示出大的 "cpu_ns_avg" 值)来调整或修复其处理。大缓冲区压缩可能是一个罪魁祸首,例如重型正则表达式或长正则表达式列表。注意:虽然直观上总延迟似乎会增加传输时间,但这几乎从不正确,因为当任务等待 CPU 时,网络缓冲区会继续填充,下一次调用将一次处理更多内容。由于 cpu_calls 计数很高,该值可能会被人为地提高,例如在处理许多 HTTP 块时,因此通常更倾向于记录 lat_ns_avg,它是一个更相关的性能指标。
meth(<method>) : 方法
返回一个方法。
nbsrv([<backend>]) : 整数
返回一个整数值,对应于当前后端或指定后端的可用服务器数量。这主要与 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 : 整数
始终返回值 1(历史上它会返回调用进程号)。
queue([<backend>]) : 整数
返回指定后端的排队连接总数,包括服务器队列中的所有连接。如果未指定后端名称,则使用当前后端,但也可以检查另一个后端。这对于 ACL 或将统计信息传递给后端服务器很有用。这可用于在排队超过已知水平时采取行动,这通常表示流量激增或服务器大规模减速。一个可能的操作是拒绝新用户但仍然接受老用户。另请参阅“avg_queue”、“be_conn”和“be_sess_rate”提取。
quic_enabled : boolean
当编译了 QUIC 传输协议支持并且没有通过 "tune.quic.listen" 全局选项禁用 QUIC 侦听器时返回 true。另请参阅 "tune.quic.listen" 全局选项。
rand([<range>]) : 整数
返回一个在 <range> 个可能值范围内的随机整数值,从零开始。如果未指定范围,则默认为 2^32,即数字介于 0 和 4294967295 之间。例如,传递一些需要用于做出某些路由决策的值可能很有用,或者仅仅用于调试目的。此随机数不得用于安全目的。
srv_conn([<backend>/]<server>) : 整数
返回一个整数值,对应于指定服务器上当前已建立的连接数,可能包括正在评估的连接。如果省略 <backend>,则在当前后端中查找服务器。当一台服务器已满时,它可用于使用特定的服务器组,或告知服务器我们对其活动连接数的看法。另请参见“fe_conn”、“be_conn”、“queue”和“srv_conn_free”提取方法。
srv_conn_free([<backend>/]<server>) : integer
返回一个整数值,对应于指定服务器上的可用连接数,可能包括正在评估的连接。该值不包括队列槽位。如果省略 <backend>,则在当前后端中查找服务器。当一台服务器已满时,它可用于使用特定的服务器组,或告知服务器我们对其活动连接数的看法。另请参见“be_conn_free”和“srv_conn”提取方法。其他注意事项和说明:如果服务器的 maxconn 为 0,则此提取显然没有意义,在这种情况下返回的值将为 -1。
srv_is_up([<backend>/]<server>) : 布尔值
当指定服务器处于 UP 状态时返回 true,当其处于 DOWN 或维护模式时返回 false。如果省略 <backend>,则在当前后端中查找服务器。它主要用于根据通过健康检查报告的外部状态采取行动(例如,地理站点的可用性)。另一种可能的用途,更像是一种技巧,是使用虚拟服务器作为布尔变量,可以从 CLI 启用或禁用,以便可以实时调整依赖于这些 ACL 的规则。
srv_iweight([<backend>/]<server>) : integer
返回一个对应于服务器初始权重的整数。如果省略 <backend>,则在当前后端中查找服务器。另请参见“srv_weight”和“srv_uweight”。
srv_queue([<backend>/]<server>) : integer
返回一个整数值,对应于当前在指定服务器队列中等待的连接数。如果省略 <backend>,则在当前后端中查找服务器。有时可以与“use-server”指令一起使用,以在已知更快的服务器负载不大时强制使用它。另请参见“srv_conn”、“avg_queue”和“queue”样本提取方法。
srv_sess_rate([<backend>/]<server>) : 整数
返回一个对应于指定服务器上的会话创建速率的整数,以每秒新会话数表示。如果省略 <backend>,则在当前后端中查找服务器。这主要与 ACL 一起使用,但在日志中也可能有意义。这用于在昂贵或脆弱的服务器达到过高的会话速率时切换到备用后端,或限制服务滥用(例如防止潜在请求使服务器过载)。
Example
# 重定向到单独的后端 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
返回一个对应于用户可见服务器权重的整数。如果省略 <backend>,则在当前后端中查找服务器。另请参见“srv_weight”和“srv_iweight”。
srv_weight([<backend>/]<server>) : integer
返回一个对应于当前(或有效)服务器权重的整数。如果省略 <backend>,则在当前后端中查找服务器。另请参见“srv_iweight”和“srv_uweight”。
stopping : 布尔值
如果调用该函数的进程当前正在停止,则返回 TRUE。这对于日志记录,或在优雅关闭时放宽某些检查或帮助关闭某些连接很有用。
str(<string>) : 字符串
返回一个字符串。
table_avl([<table>]) : 整数
返回当前代理的粘滞表或指定粘滞表中的可用条目总数。另请参见“table_cnt”。
table_cnt([<table>]) : 整数
返回当前代理的粘滞表或指定粘滞表中当前正在使用的条目总数。另请参见“table_conn_cnt”和 table_avl 以了解其他条目计数方法。
term_events : string
返回附加到流的客户端和服务器端所有实体的所有已知终止事件。返回一个包含七个元素的元组,信息如下: - 前端连接的终止事件 - 前端多路复用连接的终止事件 - 前端流端点描述符(多路复用流或 applet)的终止事件 - 流的终止事件 - 后端流端点描述符(多路复用流或 applet)的终止事件 - 后端多路复用连接的终止事件 - 后端连接的终止事件 在每个级别,都会报告前四个事件。如果特定级别尚未报告任何事件,则返回空字符串。如果不支持终止事件,则返回“-”。它只能用于调试目的。确切的格式未被记录,因为它可能会根据开发人员的要求而演变。
thread : integer
返回一个整数值,对应于调用该函数的线程的位置,介于 0 和 (global.nbthread-1) 之间。这对于日志记录和调试目的很有用。
txn.id32 : integer
返回内部事务 ID。它是一个 32 位整数。因此,从绝对值来看,它的值不是唯一的,事务 ID 可能会回绕。回绕周期取决于请求速率。在实践中,这应该不是问题。对于真正的唯一 ID,请参见“unique-id-format”指令。
返回日志中报告的 TCP 或 HTTP 流终止状态。它是一个 2 个字符的字符串,即最终流状态后跟导致其终止的事件。有关可能事件的列表,请参见第 8.5 节中关于断开连接时的流状态。返回的是评估样本提取时的当前值。它可能会发生变化。除非在“http-after-response”规则集或日志消息中与 ACL 一起使用,否则它将始终为“--”。
示例
# 如果流在队列中超时,则返回 429-Too-Many-Requests http-after-response set-status 429 if { txn.sess_term_state "sQ" }
uptime : integer
返回当前 HAProxy 工作进程的正常运行时间(以秒为单位)。
uuid([<version>]) : string
根据 RFC 9562 标准返回一个 UUID。如果未指定版本,则返回 UUID 版本 4(完全随机)。支持版本 4 和 7。
var(<var-name>[,<default>]) : undefined
返回一个具有存储类型的变量。如果未设置变量,则样本提取失败,除非提供了默认值,在这种情况下,它将以字符串形式返回该默认值。允许空字符串。有关变量的详细信息,请参见第 2.8 节
wait_end : boolean
此获取在检查周期结束时返回 true,否则不获取任何内容。它仅用于 ACL 中,与内容分析结合使用,以避免过早返回错误的判断。它也可用于延迟某些操作,例如对某些特殊地址进行延迟拒绝。由于它要么停止规则评估,要么立即返回 true,因此建议将此 acl 用作规则中的最后一个。请注意,默认的 ACL "WAIT_END" 始终可用,无需事先声明。此测试旨在与 TCP 请求内容检查一起使用。
示例
# 将每个传入请求延迟 2 秒 tcp-request inspect-delay 2s tcp-request content accept if WAIT_END # 不要立即告诉坏家伙他们被拒绝了 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
这返回在遇到错误或超时时等待继续处理的实体的标识。例如,它可能是规则或过滤器。但是,此列表并不详尽,并且所有可能实体的格式也未强制记录。当实体是规则时,将返回其位置。它是包含规则的配置文件,后跟在该文件中定义规则的行,用冒号分隔。对于过滤器,将返回其开发人员定义的标识符。如果未定义此标识符,则返回一个对应于唯一内部标识符的十六进制值。此函数的主要目的是能够在遇到错误或超时中断此处理时,在日志中报告阻塞流分析的实体,以帮助调试问题。实体上返回的信息可能会随时间变化,不得用于调试以外的其他目的。
示例
# 如果报告了错误,则记录等待的实体(如果有),并且仅在报告了错误时记录 log-format "$HAPROXY_HTTP_LOG_FMT %{Q}[waiting_entity,when(error)]"

7.3.3. 在第 4 层提取样本

第 4 层通常只描述传输层,在 HAProxy 中,它最接近连接,此时还没有内容可用。除非需要一些未来的信息,否则此处描述的获取方法可以在低至 "tcp-request connection" 规则集上使用。这些通常包括 TCP/IP 地址和端口,以及与传入连接相关的 stick-tables 中的元素。对于从粘性计数器中检索值,可以使用预定义的 "sc0_"、"sc1_" 或 "sc2_" 前缀将计数器编号明确设置为 0、1 或 2。只有当全局 "tune.stick-counters" 值不超过 3 时,才能使用这三个预定义的前缀,否则在使用 "sc_" 前缀时,计数器编号可以指定为第一个整数参数,从 "sc_0" 到 "sc_N",其中 N 是 (tune.stick-counters-1)。可以使用 "sc*" 形式指定一个可选的表,在这种情况下,当前跟踪的键将在该备用表中查找,而不是在当前跟踪的表中查找。本节中的样本获取方法及其相应类型摘要
关键字输出类型
accept_date([<unit>])整数
bc.timer.connect整数
bc_be_queue整数
bc_dstip
bc_dst_port整数
bc_err整数
bc_err_name字符串
bc_err_str字符串
bc_glitches整数
bc_http_major整数
bc_nb_streams整数
bc_reused布尔
bc_rtt(<unit>)整数
bc_rttvar(<unit>)整数
bc_settings_streams_limit整数
bc_srcip
bc_src_port整数
bc_srv_queue整数
be_id整数
be_name字符串
关键字输出类型
be_server_timeout整数
be_tunnel_timeout整数
bytes_in整数
bytes_out整数
cur_client_timeout整数
cur_server_timeout整数
cur_tunnel_timeout整数
dstip
dst_conn整数
dst_is_local布尔
dst_port整数
fc.timer.handshake整数
fc.timer.total整数
fc_dstip
fc_dst_is_local布尔
fc_dst_port整数
fc_err整数
fc_err_name字符串
fc_err_str字符串
fc_fackets整数
关键字输出类型
fc_glitches整数
fc_http_major整数
fc_lost整数
fc_nb_streams整数
fc_pp_authority字符串
fc_pp_tlv(<id>)字符串
fc_pp_unique_id字符串
fc_rcvd_proxy布尔
fc_reordering整数
fc_retrans整数
fc_rtt(<unit>)整数
fc_rttvar(<unit>)整数
fc_sacked整数
fc_settings_streams_limit整数
fc_srcip
fc_src_is_local布尔
fc_src_port整数
fc_unacked整数
fe_client_timeout整数
fe_defbe字符串
关键字输出类型
fe_id整数
fe_name字符串
req.bytes_in整数
req.bytes_out整数
res.bytes_in整数
res.bytes_out整数
res.timer.data整数
sc0_bytes_in_rate([<table>])整数
sc0_bytes_out_rate([<table>])整数
sc0_clr_gpc0([<table>])整数
sc0_clr_gpc1([<table>])整数
sc0_conn_cnt([<table>])整数
sc0_conn_cur([<table>])整数
sc0_conn_rate([<table>])整数
sc0_get_gpc0([<table>])整数
sc0_get_gpc1([<table>])整数
sc0_get_gpt0([<table>])整数
sc0_glitch_cnt([<table>])整数
sc0_glitch_rate([<table>])整数
sc0_gpc0_rate([<table>])整数
关键字输出类型
sc0_gpc1_rate([<table>])整数
sc0_http_err_cnt([<table>])整数
sc0_http_err_rate([<table>])整数
sc0_http_fail_cnt([<table>])整数
sc0_http_fail_rate([<table>])整数
sc0_http_req_cnt([<table>])整数
sc0_http_req_rate([<table>])整数
sc0_inc_gpc0([<table>])整数
sc0_inc_gpc1([<table>])整数
sc0_kbytes_in([<table>])整数
sc0_kbytes_out([<table>])整数
sc0_key任意
sc0_sess_cnt([<table>])整数
sc0_sess_rate([<table>])整数
sc0_tracked([<table>])布尔
sc0_trackers([<table>])整数
sc1_bytes_in_rate([<table>])整数
sc1_bytes_out_rate([<table>])整数
sc1_clr_gpc0([<table>])整数
sc1_clr_gpc1([<table>])整数
关键字输出类型
sc1_conn_cnt([<table>])整数
sc1_conn_cur([<table>])整数
sc1_conn_rate([<table>])整数
sc1_get_gpc0([<table>])整数
sc1_get_gpc1([<table>])整数
sc1_get_gpt0([<table>])整数
sc1_glitch_cnt([<table>])整数
sc1_glitch_rate([<table>])整数
sc1_gpc0_rate([<table>])整数
sc1_gpc1_rate([<table>])整数
sc1_http_err_cnt([<table>])整数
sc1_http_err_rate([<table>])整数
sc1_http_fail_cnt([<table>])整数
sc1_http_fail_rate([<table>])整数
sc1_http_req_cnt([<table>])整数
sc1_http_req_rate([<table>])整数
sc1_inc_gpc0([<table>])整数
sc1_inc_gpc1([<table>])整数
sc1_kbytes_in([<table>])整数
sc1_kbytes_out([<table>])整数
关键字输出类型
sc1_key任意
sc1_sess_cnt([<table>])整数
sc1_sess_rate([<table>])整数
sc1_tracked([<table>])布尔
sc1_trackers([<table>])整数
sc2_bytes_in_rate([<table>])整数
sc2_bytes_out_rate([<table>])整数
sc2_clr_gpc0([<table>])整数
sc2_clr_gpc1([<table>])整数
sc2_conn_cnt([<table>])整数
sc2_conn_cur([<table>])整数
sc2_conn_rate([<table>])整数
sc2_get_gpc0([<table>])整数
sc2_get_gpc1([<table>])整数
sc2_get_gpt0([<table>])整数
sc2_glitch_cnt([<table>])整数
sc2_glitch_rate([<table>])整数
sc2_gpc0_rate([<table>])整数
sc2_gpc1_rate([<table>])整数
sc2_http_err_cnt([<table>])整数
关键字输出类型
sc2_http_err_rate([<table>])整数
sc2_http_fail_cnt([<table>])整数
sc2_http_fail_rate([<table>])整数
sc2_http_req_cnt([<table>])整数
sc2_http_req_rate([<table>])整数
sc2_inc_gpc0([<table>])整数
sc2_inc_gpc1([<table>])整数
sc2_kbytes_in([<table>])整数
sc2_kbytes_out([<table>])整数
sc2_key任意
sc2_sess_cnt([<table>])整数
sc2_sess_rate([<table>])整数
sc2_tracked([<table>])布尔
sc2_trackers([<table>])整数
sc_bytes_in_rate(<ctr>[,<table>])整数
sc_bytes_out_rate(<ctr>[,<table>])整数
sc_clr_gpc(<idx>,<ctr>[,<table>])整数
sc_clr_gpc0(<ctr>[,<table>])整数
sc_clr_gpc1(<ctr>[,<table>])整数
sc_conn_cnt(<ctr>[,<table>])整数
关键字输出类型
sc_conn_cur(<ctr>[,<table>])整数
sc_conn_rate(<ctr>[,<table>])整数
sc_get_gpc(<idx>,<ctr>[,<table>])整数
sc_get_gpc0(<ctr>[,<table>])整数
sc_get_gpc1(<ctr>[,<table>])整数
sc_get_gpt(<idx>,<ctr>[,<table>])整数
sc_get_gpt0(<ctr>[,<table>])整数
sc_glitch_cnt(<ctr>[,<table>])整数
sc_glitch_rate(<ctr>[,<table>])整数
sc_gpc0_rate(<ctr>[,<table>])整数
sc_gpc1_rate(<ctr>[,<table>])整数
sc_gpc_rate(<idx>,<ctr>[,<table>])整数
sc_http_err_cnt(<ctr>[,<table>])整数
sc_http_err_rate(<ctr>[,<table>])整数
sc_http_fail_cnt(<ctr>[,<table>])整数
sc_http_fail_rate(<ctr>[,<table>])整数
sc_http_req_cnt(<ctr>[,<table>])整数
sc_http_req_rate(<ctr>[,<table>])整数
sc_inc_gpc(<idx>,<ctr>[,<table>])整数
sc_inc_gpc0(<ctr>[,<table>])整数
关键字输出类型
sc_inc_gpc1(<ctr>[,<table>])整数
sc_kbytes_in(<ctr>[,<table>])整数
sc_kbytes_out(<ctr>[,<table>])整数
sc_key(<ctr>)任意
sc_sess_cnt(<ctr>[,<table>])整数
sc_sess_rate(<ctr>[,<table>])整数
sc_tracked(<ctr>[,<table>])布尔
sc_trackers(<ctr>[,<table>])整数
so_id整数
so_name字符串
srcip
src_bytes_in_rate([<table>])整数
src_bytes_out_rate([<table>])整数
src_clr_gpc(<idx>[,<table>])整数
src_clr_gpc0([<table>])整数
src_clr_gpc1([<table>])整数
src_conn_cnt([<table>])整数
src_conn_cur([<table>])整数
src_conn_rate([<table>])整数
src_get_gpc(<idx>[,<table>])整数
关键字输出类型
src_get_gpc0([<table>])整数
src_get_gpc1([<table>])整数
src_get_gpt(<idx>[,<table>])整数
src_get_gpt0([<table>])整数
src_glitch_cnt([<table>])整数
src_glitch_rate([<table>])整数
src_gpc0_rate([<table>])整数
src_gpc1_rate([<table>])整数
src_gpc_rate(<idx>[,<table>])整数
src_http_err_cnt([<table>])整数
src_http_err_rate([<table>])整数
src_http_fail_cnt([<table>])整数
src_http_fail_rate([<table>])整数
src_http_req_cnt([<table>])整数
src_http_req_rate([<table>])整数
src_inc_gpc(<idx>[,<table>])整数
src_inc_gpc0([<table>])整数
src_inc_gpc1([<table>])整数
src_is_local布尔
src_kbytes_in([<table>])整数
关键字输出类型
src_kbytes_out([<table>])整数
src_port整数
src_sess_cnt([<table>])整数
src_sess_rate([<table>])整数
src_updt_conn_cnt([<table>])整数
srv_id整数
srv_name字符串
txn.conn_retries整数
txn.redispatched布尔
详细列表
accept_date([<unit>]) : integer
这是 HAProxy 接收到连接的确切日期(如果系统中存在一些排队,可能与网络上观察到的日期略有不同)。这通常是任何上游防火墙日志中可能出现的日期。当在 HTTP 模式下使用时,accept_date 字段将被重置为连接准备好接收新请求的第一个时刻(HTTP/1 的前一个响应结束,HTTP/2 的前一个请求之后立即)。返回自纪元以来的秒数。 <unit> 是可选的,可以设置为“s”表示秒(默认行为)、“ms”表示毫秒或“us”表示微秒。如果设置了 unit,返回值将是一个整数,表示自纪元以来的秒、毫秒或微秒。当需要小于一秒的时间分辨率时,它很有用。
建立到服务器的 TCP 连接的总时间。这是日志格式中 %Tc 的等效项。以毫秒 (ms) 为单位报告。有关更多信息,请参阅第 8.4 节“计时事件”。
bc_be_queue : integer
在等待目标后端连接槽时出列的流的数量。这是日志格式中 %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”提取。
bc_err_name : string
返回描述后端连接上发生的问题并导致连接失败的内部错误名称。此字符串由一个单词组成,在没有错误时为空。它对应于“fc_err_str”关键字中表格的“name”列。
bc_err_str : string
返回描述当前后端连接上发生的问题并导致连接失败的错误消息。有关错误代码及其对应错误消息的完整列表,请参阅“fc_err_str”提取。
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
返回内核为后端连接测量的往返时间 (RTT)。<unit> 是可选的,默认单位是毫秒。<unit> 可以设置为“ms”表示毫秒或“us”表示微秒。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
bc_rttvar(<unit>) : integer
返回内核为后端连接测量的往返时间 (RTT) 方差。<unit> 是可选的,默认单位是毫秒。<unit> 可以设置为“ms”表示毫秒或“us”表示微秒。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
返回后端连接上允许的最大流数。对于 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 : integer
在等待目标服务器连接槽时出列的流的数量。这是日志格式中 %sq 的等效项。
be_id : 整数
返回一个整数,包含当前后端的 ID。它可以在前端使用响应来检查哪个后端处理了请求。如果在前端使用并且没有使用后端,它将返回当前前端的 ID。它也可以在 tcp-check 或 http-check 规则集中使用。
be_name : string
返回一个字符串,包含当前后端的名称。它可以在前端使用响应来检查哪个后端处理了请求。如果在前端使用并且没有使用后端,它将返回当前前端的名称。它也可以在 tcp-check 或 http-check 规则集中使用。
返回当前后端服务器超时配置值(以毫秒为单位)。此超时可以通过“set-timeout”规则覆盖。另请参阅“cur_server_timeout”。
返回当前后端隧道超时配置值(以毫秒为单位)。此超时可以通过“set-timeout”规则覆盖。另请参阅“cur_tunnel_timeout”。
bytes_in : integer
参见 "req.bytes_in"。
bytes_out : integer
参见 "res.bytes_in"。
返回流当前应用的客户端超时(以毫秒为单位)。在默认情况下,这将等于 fe_client_timeout,除非应用了“set-timeout”规则。另请参阅“fe_client_timeout”。
返回流当前应用的服务器超时(以毫秒为单位)。在默认情况下,这将等于 be_server_timeout,除非应用了“set-timeout”规则。另请参阅“be_server_timeout”。
返回流当前应用的隧道超时(以毫秒为单位)。在默认情况下,这将等于 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 : 整数
返回一个整数值,对应于同一套接字上当前建立的连接数,包括正在评估的连接。它通常与 ACL 一起使用,但也可以用于在 HTTP 头中或日志中将信息传递给服务器。它可以用于在硬阻塞之前返回一个“抱歉”页面,或者在套接字被认为饱和时使用特定的后端来处理新请求。这提供了为不同的侦听端口或地址分配不同限制的能力。另请参阅“fe_conn”和“be_conn”提取。
dst_is_local : boolean
如果传入连接的目标地址是本地系统地址,则返回 true;如果地址不存在于系统中(意味着它在透明模式下被拦截),则返回 false。这对于默认情况下对转发流量应用某些规则,而对定向到机器实际地址的流量应用其他规则可能很有用。例如,统计页面可能仅在该地址上提供,或者 SSH 访问可能被本地重定向。请注意,该检查涉及一些系统调用,因此最好每个连接只执行一次。
dst_port : 整数
返回客户端上的连接目标 TCP 端口的整数值,即客户端连接到的端口。任何 tcp/http 规则都可能更改此地址。在透明模式下运行时,为某个应用程序会话为某些客户端分配动态端口,将所有用户粘性到同一服务器,或通过 HTTP 标头将目标端口信息传递给服务器时,可以使用此端口。
接受 TCP 连接并执行低级协议握手(当前包括 proxy-protocol 和 SSL)的总时间。这是日志格式中 %Th 的等效项。以毫秒 (ms) 为单位报告。有关更多信息,请参阅第 8.4 节“计时事件”。
fc.timer.total : integer
流的总持续时间,从代理接受它到两端都关闭。这是日志格式中 %Tt 的等效项。以毫秒 (ms) 为单位报告。有关更多信息,请参阅第 8.4 节“计时事件”。
fc_dst : ip
这是客户端上的连接的原始目标 IP 地址。只有“tcp-request connection”规则可能更改此地址。有关详细信息,请参阅“dst”。
fc_dst_is_local : boolean
如果传入连接的原始目标地址是本地系统地址,则返回 true;如果地址不存在于系统中,则返回 false。有关详细信息,请参阅“dst_is_local”。
fc_dst_port : integer
返回客户端上的连接的原始目标 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 : integer
如果连接不是 TCP 或 QUIC,则样本提取失败。对于 QUIC,返回客户端连接丢失的 QUIC 数据包数量。对于 TCP,返回内核为客户端连接测量的丢失计数器。如果服务器连接未建立,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
fc_nb_streams : integer
返回前端连接上打开的流的数量。
返回客户端在 PROXY 协议头中发送的第一个 authority TLV(如果存在)。
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 的所有出现次数,以防存在重复的 TLV ID。迭代顺序与 PROXY 协议标头中的位置匹配。然而,应尽量避免依赖重复项,因为 TLV 通常被假定为唯一。通常,发现重复的 TLV ID 表示 PROXY 协议标头发送方存在错误。
返回客户端在 PROXY 协议头中发送的第一个 unique ID TLV(如果存在)。
fc_rcvd_proxy : boolean
如果客户端使用 PROXY 协议头启动连接,则返回 true。
fc_reordering : integer
如果连接不是 TCP 或 QUIC,则样本提取失败。对于 QUIC,返回客户端连接的 QUIC 重排序数据包数量。对于 TCP,返回内核为客户端连接测量的重排序计数器。如果服务器连接未建立,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
fc_retrans : integer
返回内核为客户端连接测量的重传计数器。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
fc_rtt(<unit>) : integer
如果连接不是 TCP 或 QUIC,则样本提取失败。对于 QUIC,返回客户端连接的平滑往返时间。对于 TCP,返回内核为客户端连接测量的往返时间 (RTT)。<unit> 是可选的,默认单位是毫秒。<unit> 可以设置为“ms”表示毫秒或“us”表示微秒。如果服务器连接未建立,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
fc_rttvar(<unit>) : integer
如果连接不是 TCP 或 QUIC,则样本提取失败。对于 QUIC,返回客户端连接的平滑往返时间方差。对于 TCP,返回内核为客户端连接测量的往返时间 (RTT) 方差。<unit> 是可选的,默认单位是毫秒。<unit> 可以设置为“ms”表示毫秒或“us”表示微秒。如果服务器连接未建立,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
fc_sacked : integer
返回内核为客户端连接测量的 sacked 计数器。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
返回前端连接上允许的最大流数。对于 TCP 和 HTTP/1.1 连接,始终为 1。对于其他协议,它取决于与客户端协商的设置。
fc_src : ip
这是客户端上的连接的原始源 IP 地址。只有“tcp-request connection”规则可能更改此地址。有关详细信息,请参阅“src”。
fc_src_is_local : boolean
如果传入连接的源地址是本地系统地址,则返回 true;如果地址不存在于系统中,则返回 false。有关详细信息,请参阅“src_is_local”。
fc_src_port : integer
返回客户端上的连接的 TCP 源端口的整数值。只有“tcp-request connection”规则可能更改此地址。有关详细信息,请参阅“src-port”。
fc_unacked : integer
返回内核为客户端连接测量的未确认计数器。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
返回当前前端的客户端超时配置值(以毫秒为单位)。此超时可以通过“set-timeout”规则覆盖。
fe_defbe : string
返回前端的默认后端名称的字符串。它可以在前端用于检查哪个后端将默认处理请求。
fe_id : 整数
返回一个包含当前前端 ID 的整数。它可以在后端使用,以检查它是从哪个前端调用的,或将通过同一前端进入的所有用户粘滞到同一台服务器。
fe_name : string
返回当前前端名称的字符串。它可以在后端用于检查它是由哪个前端调用的,或者将来自同一前端的所有用户粘性到同一服务器。
req.bytes_in : integer
这返回从客户端接收到的字节数。该值对应于 HAProxy 接收到的内容,包括一些标头和一些内部编码开销。请求压缩不会影响此处报告的值。
req.bytes_out : integer
这返回发送到服务器的字节数。该值对应于 HAProxy 发送的内容,包括一些标头和一些内部编码开销。请求压缩会影响此处报告的值。
res.bytes_in : integer
这返回从服务器接收到的字节数。该值对应于 HAProxy 接收到的内容,包括一些标头和一些内部编码开销。响应压缩不会影响此处报告的值。
res.bytes_out : integer
这返回发送到客户端的字节数。该值对应于 HAProxy 发送的内容,包括一些标头和一些内部编码开销。响应压缩会影响此处报告的值。
res.timer.data : integer
这是响应负载直到发送到客户端的最后一个字节的总传输时间。在 HTTP 中,它发生在最后一个响应头(Tr)之后。这相当于日志格式中的 %Td,以毫秒(ms)为单位报告。有关更多信息,请参见第 8.4 节“计时事件”。
sc_bytes_in_rate(<ctr>[,<table>]) : 整数
sc0_bytes_in_rate([<table>]) : 整数
sc1_bytes_in_rate([<table>]) : 整数
sc2_bytes_in_rate([<table>]) : 整数
返回当前跟踪计数器的平均客户端到服务器字节速率,以表格中配置的时间段内的字节量衡量。另请参阅“table_bytes_in_rate”。
sc_bytes_out_rate(<ctr>[,<table>]) : 整数
sc0_bytes_out_rate([<table>]) : 整数
sc1_bytes_out_rate([<table>]) : 整数
sc2_bytes_out_rate([<table>]) : 整数
返回当前跟踪计数器的平均服务器到客户端字节速率,以表格中配置的时间段内的字节量衡量。另请参阅“table_bytes_out_rate”。
sc_clr_gpc(<idx>,<ctr>[,<table>]) : integer
清除当前代理的粘滞表(stick table)中与指定跟踪计数器 ID <ctr> 关联的数组中索引为 <idx> 的通用计数器(General Purpose Counter),并返回其先前的值。<idx> 是一个介于 0 到 99 之间的整数,<ctr> 是一个介于 0 到 2 之间的整数。在第一次调用之前,存储的值为零,因此第一次调用将始终返回零。此获取仅适用于 'gpc' 数组的数据类型(而不适用于旧的 'gpc0' 或 'gpc1' 数据类型)。
sc_clr_gpc0(<ctr>[,<table>]) : 整数
sc0_clr_gpc0([<table>]) : 整数
sc1_clr_gpc0([<table>]) : 整数
sc2_clr_gpc0([<table>]) : 整数
清除与当前跟踪的计数器相关联的第一个通用计数器,并返回其先前的值。在第一次调用之前,存储的值为零,因此第一次调用将始终返回零。这通常用作表达式中的第二个ACL,以便在第一个ACL验证时标记连接。
示例
# 如果连续 5 个请求的速率持续高于每秒 10 个会话,则阻止, # 并在流量减慢时立即重置计数器。 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
sc0_clr_gpc1([<table>]) : integer
sc1_clr_gpc1([<table>]) : integer
sc2_clr_gpc1([<table>]) : integer
清除与当前跟踪计数器关联的第二个通用计数器,并返回其先前的值。在第一次调用之前,存储的值为零,因此第一次调用将始终返回零。这通常用作表达式中的第二个 ACL,以便在第一个 ACL 被验证后标记连接。
sc_conn_cnt(<ctr>[,<table>]) : 整数
sc0_conn_cnt([<table>]) : 整数
sc1_conn_cnt([<table>]) : 整数
sc2_conn_cnt([<table>]) : 整数
返回当前跟踪计数器的累计入站连接数。另请参阅“table_conn_cnt”。
sc_conn_cur(<ctr>[,<table>]) : 整数
sc0_conn_cur([<table>]) : 整数
sc1_conn_cur([<table>]) : 整数
sc2_conn_cur([<table>]) : 整数
返回当前跟踪相同跟踪计数器的并发连接数。当开始跟踪时,此数字会自动增加,在停止跟踪时自动减少。另请参阅“table_conn_cur”。
sc_conn_rate(<ctr>[,<table>]) : 整数
sc0_conn_rate([<table>]) : 整数
sc1_conn_rate([<table>]) : 整数
sc2_conn_rate([<table>]) : 整数
返回当前跟踪计数器的平均连接速率,以表格中配置的时间段内的连接数衡量。另请参阅“table_conn_rate”。
sc_get_gpc(<idx>,<ctr>[,<table>]) : integer
从当前代理的粘滞表或指定的粘滞表 <table> 中,返回与当前跟踪计数器 ID <ctr> 关联的 GPC 数组中索引为 <idx> 的通用计数器的值。<idx> 是一个介于 0 到 99 之间的整数,<ctr> 是一个介于 0 到 2 之间的整数。如果在此索引处没有存储 gpc,则返回零。此获取仅适用于 'gpc' 数组的数据类型(而不适用于旧的 'gpc0' 或 'gpc1' 数据类型)。另请参阅“table_gpc”和“sc_inc_gpc”。
sc_get_gpc0(<ctr>[,<table>]) : 整数
sc0_get_gpc0([<table>]) : 整数
sc1_get_gpc0([<table>]) : 整数
sc2_get_gpc0([<table>]) : 整数
返回与当前跟踪计数器关联的第一个通用计数器的值。另请参阅“table_gpc0”和 sc/sc0/sc1/sc2_inc_gpc0。
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
从当前代理的粘滞表或指定的粘滞表 <table> 中,返回与跟踪计数器 ID <ctr> 关联的数组中索引为 <idx> 的第一个通用标记(General Purpose Tag)的值。<idx> 是一个介于 0 到 99 之间的整数,<ctr> 是一个介于 0 到 2 之间的整数。如果在此索引处没有存储 GPT,则返回零。此获取仅适用于 'gpt' 数组的数据类型(而不适用于旧的 'gpt0' 数据类型)。另请参阅“table_gpt”。
sc_get_gpt0(<ctr>[,<table>]) : 整数
sc0_get_gpt0([<table>]) : 整数
sc1_get_gpt0([<table>]) : 整数
sc2_get_gpt0([<table>]) : 整数
返回与当前跟踪计数器关联的第一个通用标记的值。另请参阅“table_gpt0”。
sc_glitch_cnt(<ctr>[,<table>]) : integer
sc0_glitch_cnt([<table>]) : integer
sc1_glitch_cnt([<table>]) : integer
sc2_glitch_cnt([<table>]) : integer
返回与当前跟踪计数器关联的入站连接发生的正面连接故障(front connection glitches)的累计数量。通常,这些故障会导致请求或连接被中止,因此返回的值通常对应于过去的连接。没有“好”或“坏”的值,但质量差的客户端每连接可能会偶尔导致几次故障,而非常糟糕或恶意的客户端可能会快速导致每连接数千个事件被添加。另请参阅 fc_glitches(影响当前连接的数量)、src_glitch_cnt(按源查找)以及 sc_glitch_rate(事件速率测量)。
sc_glitch_rate(<ctr>[,<table>]) : integer
sc0_glitch_rate([<table>]) : integer
sc1_glitch_rate([<table>]) : integer
sc2_glitch_rate([<table>]) : integer
返回当前跟踪计数器中正面连接故障(front connection glitches)的平均速率,以表格中配置的时间段内的事件数量衡量。通常,这些故障会导致请求或连接被中止,因此返回的值通常与过去的连接相关。没有“好”或“坏”的值,但质量差的客户端每连接可能会偶尔导致几次故障,因此通常预期速率较低。然而,非常糟糕或恶意的客户端可能会快速导致每连接数千个事件被添加,并在此处维持高速率。另请参阅“table_glitch_rate”和“sc_glitch_cnt”。
sc_gpc_rate(<idx>,<ctr>[,<table>]) : integer
返回当前代理的表或指定的粘滞表 <table> 中,与跟踪计数器 ID <ctr> 关联的数组中索引为 <idx> 的通用计数器的平均增量速率。它报告了在配置的时间段内 gpc 计数器被增量的频率。<idx> 是一个介于 0 到 99 之间的整数,<ctr> 是一个介于 0 到 2 之间的整数。请注意,'gpc_rate' 计数器数组必须存储在粘滞表中才能返回一个值,因为 'gpc' 只保存事件计数。此获取仅适用于 'gpc_rate' 数组的数据类型(而不适用于旧的 'gpc0_rate' 或 'gpc1_rate' 数据类型)。另请参阅“table_gpc_rate”、“sc_get_gpc”和“sc_inc_gpc”。
sc_gpc0_rate(<ctr>[,<table>]) : 整数
sc0_gpc0_rate([<table>]) : 整数
sc1_gpc0_rate([<table>]) : 整数
sc2_gpc0_rate([<table>]) : 整数
返回与当前跟踪的计数器关联的第一个通用计数器的平均增量速率。它报告在配置的时间段内 gpc0 计数器递增的频率。另请参阅 src_gpc0_rate、sc/sc0/sc1/sc2_get_gpc0 和 sc/sc0/sc1/sc2_inc_gpc0。请注意,必须在粘性表中存储“gpc0_rate”计数器才能返回值,因为“gpc0”仅保存事件计数。
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”计数器必须存储在粘滞表中才能返回一个值,因为“gpc1”只保存事件计数。
sc_http_err_cnt(<ctr>[,<table>]) : 整数
sc0_http_err_cnt([<table>]) : 整数
sc1_http_err_cnt([<table>]) : 整数
sc2_http_err_cnt([<table>]) : 整数
返回当前跟踪计数器的累计 HTTP 错误数。这包括请求错误和 4xx 错误响应。另请参阅“table_http_err_cnt”。
sc_http_err_rate(<ctr>[,<table>]) : 整数
sc0_http_err_rate([<table>]) : 整数
sc1_http_err_rate([<table>]) : 整数
sc2_http_err_rate([<table>]) : 整数
返回当前跟踪的计数器中 HTTP 错误的平均速率,以表中配置的时间段内的错误数量来衡量。这包括请求错误和 4xx 错误响应。另请参阅 src_http_err_rate。
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
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>]) : 整数
sc0_http_req_cnt([<table>]) : 整数
sc1_http_req_cnt([<table>]) : 整数
sc2_http_req_cnt([<table>]) : 整数
返回当前跟踪计数器的累计 HTTP 请求数。这包括所有开始的请求,无论有效与否。另请参阅 src_http_req_cnt。
sc_http_req_rate(<ctr>[,<table>]) : 整数
sc0_http_req_rate([<table>]) : 整数
sc1_http_req_rate([<table>]) : 整数
sc2_http_req_rate([<table>]) : 整数
返回当前跟踪的计数器中 HTTP 请求的平均速率,以表中配置的时间段内的请求数量来衡量。这包括每个已启动的请求,无论其有效与否。另请参阅 src_http_req_rate。
sc_inc_gpc(<idx>,<ctr>[,<table>]) : integer
递增当前代理的粘滞表或指定的粘滞表 <table> 中与指定跟踪计数器 ID <ctr> 关联的数组中索引为 <idx> 的通用计数器,并返回其新值。<idx> 是一个介于 0 到 99 之间的整数,<ctr> 是一个介于 0 到 2 之间的整数。在第一次调用之前,存储的值为零,因此第一次调用会将其增加到 1 并返回 1。此获取仅适用于 'gpc' 数组的数据类型(而不适用于旧的 'gpc0' 或 'gpc1' 数据类型)。
sc_inc_gpc0(<ctr>[,<table>]) : 整数
sc0_inc_gpc0([<table>]) : 整数
sc1_inc_gpc0([<table>]) : 整数
sc2_inc_gpc0([<table>]) : 整数
递增与当前跟踪的计数器相关联的第一个通用计数器,并返回其新值。在第一次调用之前,存储的值为零,因此第一次调用会将其增加到 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
sc0_inc_gpc1([<table>]) : integer
sc1_inc_gpc1([<table>]) : integer
sc2_inc_gpc1([<table>]) : integer
递增与当前跟踪计数器关联的第二个通用计数器,并返回其新值。在第一次调用之前,存储的值为零,因此第一次调用会将其增加到 1 并返回 1。这通常用作表达式中的第二个 ACL,以便在第一个 ACL 被验证后标记连接。
sc_kbytes_in(<ctr>[,<table>]) : 整数
sc0_kbytes_in([<table>]) : 整数
sc1_kbytes_in([<table>]) : 整数
sc2_kbytes_in([<table>]) : 整数
返回当前跟踪计数器的客户端到服务器数据的总量,以千字节(kilobytes)为单位衡量。当前测试在 32 位整数上进行,这限制了值最大为 4 TB。另请参阅“table_kbytes_in”。
sc_kbytes_out(<ctr>[,<table>]) : 整数
sc0_kbytes_out([<table>]) : 整数
sc1_kbytes_out([<table>]) : 整数
sc2_kbytes_out([<table>]) : 整数
返回当前跟踪计数器的服务器到客户端数据的总量,以千字节(kilobytes)为单位衡量。当前测试在 32 位整数上进行,这限制了值最大为 4 TB。另请参阅“table_kbytes_out”。
sc_key(<ctr>) : any
sc0_key : any
sc1_key : any
sc2_key : any
返回用于匹配当前跟踪计数器的键。
sc_sess_cnt(<ctr>[,<table>]) : 整数
sc0_sess_cnt([<table>]) : 整数
sc1_sess_cnt([<table>]) : 整数
sc2_sess_cnt([<table>]) : 整数
返回当前跟踪计数器的、被转换为会话的入站连接的累计数量。这意味着它们已被“tcp-request connection”规则接受。一个后端可能计算出比连接更多的会话,因为每个连接都可能导致许多后端会话,如果执行了一些 HTTP 持久连接(keep-alive)。另请参阅“table_sess_cnt”。
sc_sess_rate(<ctr>[,<table>]) : 整数
sc0_sess_rate([<table>]) : 整数
sc1_sess_rate([<table>]) : 整数
sc2_sess_rate([<table>]) : 整数
返回当前跟踪计数器的平均会话速率,以表格中配置的时间段内的会话数量衡量。会话是指通过早期“tcp-request connection”规则的连接。一个后端可能计算出比连接更多的会话,因为每个连接都可能导致许多后端会话,如果执行了一些 HTTP 持久连接(keep-alive)。另请参阅“table_sess_rate”。
sc_tracked(<ctr>[,<table>]) : 布尔值
sc0_tracked([<table>]) : 布尔值
sc1_tracked([<table>]) : 布尔值
sc2_tracked([<table>]) : 布尔值
如果指定的会话计数器当前正被当前会话跟踪,则返回 true。这在决定是否要在传递给服务器的头中设置某些值时很有用。
sc_trackers(<ctr>[,<table>]) : 整数
sc0_trackers([<table>]) : 整数
sc1_trackers([<table>]) : 整数
sc2_trackers([<table>]) : 整数
返回跟踪相同跟踪计数器的当前并发连接数。此数字在跟踪开始时自动递增,在跟踪停止时自动递减。它与 sc0_conn_cur 的不同之处在于,它不依赖于任何存储的信息,而是依赖于表的引用计数(即在 CLI 上通过“show table”返回的“use”值)。这有时可能更适合于第 7 层跟踪。例如,它可以用来告诉服务器来自给定地址的并发连接数。
so_id : 整数
返回一个整数,包含当前监听套接字(listening socket)的 ID。这在涉及多个“bind”行的前端中非常有用,或者可以将所有来自同一套接字的用户粘滞到同一个服务器。
so_name : string
返回一个字符串,包含当前监听套接字(listening socket)的名称,该名称在“bind”行中通过 name 定义。它可以实现与 so_id 相同的功能,但使用字符串而不是整数。
src : ip
这是会话客户端的源 IP 地址。任何 tcp/http 规则都可能更改此地址。它是 IP 类型,适用于 IPv4 和 IPv6 表。在 IPv6 表上,IPv4 地址根据 RFC 4291 映射到其 IPv6 等效项。请注意,使用的是 TCP 级别的源地址,而不是代理后面的客户端地址。但是,如果使用了 "accept-proxy" 或 "accept-netscaler-cip" bind 指令,则对于所有规则集(除了看到真实地址的 "tcp-request connection")之外,它可能是另一个 PROXY 协议兼容组件后面的客户端地址。当传入连接经过涉及连接跟踪的地址转换或重定向时,将报告重定向之前的原始目标地址。在 Linux 系统上,如果设置了 nf_conntrack_tcp_loose sysctl,源地址和目标地址可能很少出现反转,因为延迟响应可能会重新打开超时连接并切换被认为是源和目标的内容。
示例
# 在请求中添加一个带有源地址国家的 HTTP 头 http-request set-header X-Country %[src,map_ip(geoip.lst)]
src_bytes_in_rate([<table>]) : 整数
与“table_bytes_in_rate”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_bytes_in_rate([<table>])
src_bytes_out_rate([<table>]) : 整数
与“table_bytes_out_rate”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_bytes_out_rate([<table>])
src_clr_gpc(<idx>[,<table>]) : integer
与“table_clr_gpc”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_clr_gpc(<idx>[,<table>])
src_clr_gpc0([<table>]) : 整数
与“table_clr_gpc0”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_clr_gpc0([<table>])
src_clr_gpc1([<table>]) : integer
与“table_clr_gpc1”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_clr_gpc1([<table>])
src_conn_cnt([<table>]) : 整数
与“table_conn_cnt”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_conn_cnt([<table>])
src_conn_cur([<table>]) : 整数
与“table_conn_cur”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_conn_cur([<table>])
src_conn_rate([<table>]) : 整数
与“table_conn_rate”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_conn_rate([<table>])
src_get_gpc(<idx>[,<table>]) : integer
与“table_gpc”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_gpc(<idx>[,<table>])
src_get_gpc0([<table>]) : 整数
与“table_gpc0”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_gpc0([<table>])
src_get_gpc1([<table>]) : integer
与“table_gpc1”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_gpc1([<table>])
src_get_gpt(<idx>[,<table>]) : integer
与“table_gpt”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_gpt(<idx>[,<table>])
src_get_gpt0([<table>]) : 整数
与“table_gpt0”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_gpt0([<table>])
src_glitch_cnt([<table>]) : integer
与“table_glitch_cnt”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_glitch_cnt([<table>])
src_glitch_rate([<table>]) : integer
与“table_glitch_rate”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_glitch_rate([<table>])
src_gpc_rate(<idx>[,<table>]) : integer
与“table_gpc_rate”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_gpc_rate(<idx>[,<table>])
src_gpc0_rate([<table>]) : 整数
与“table_gpc0_rate”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_gpc0_rate([<table>])
src_gpc1_rate([<table>]) : integer
与“table_gpc1_rate”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_gpc1_rate([<table>])
src_http_err_cnt([<table>]) : 整数
与“table_http_err_cnt”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_http_err_cnt([<table>])
src_http_err_rate([<table>]) : 整数
与“table_http_err_rate”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_http_err_rate([<table>])
src_http_fail_cnt([<table>]) : integer
与“table_http_fail_cnt”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_http_fail_cnt([<table>])
src_http_fail_rate([<table>]) : integer
与“table_http_fail_rate”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_http_fail_rate([<table>])
src_http_req_cnt([<table>]) : 整数
与“table_http_req_cnt”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_http_req_cnt([<table>])
src_http_req_rate([<table>]) : 整数
与“table_http_req_rate”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_http_req_rate([<table>])
src_inc_gpc(<idx>[,<table>]) : integer
与“src_inc_gpc”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_inc_gpc(<idx>[,<table>])
src_inc_gpc0([<table>]) : 整数
与“src_inc_gpc0”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_inc_gpc0([<table>])
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>]) : 整数
与“table_kbytes_in”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_kbytes_in([<table>])
src_kbytes_out([<table>]) : 整数
与“table_kbytes_out”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_kbytes_out([<table>])
src_port : 整数
返回一个整数值,对应于客户端侧连接的 TCP 源端口,这是客户端连接的端口。任何 tcp/http 规则都可能更改此地址。此函数的使用非常有限,因为现代协议如今对源端口不太关心。
src_sess_cnt([<table>]) : 整数
与“table_sess_cnt”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_sess_cnt([<table>])
src_sess_rate([<table>]) : 整数
与“table_sess_rate”转换器相同,但密钥设置为入站连接的源地址。等同于:src,table_sess_rate([<table>])
src_updt_conn_cnt([<table>]) : 整数
在当前代理的粘滞表或指定的粘滞表中,为传入连接的源地址创建或更新关联的条目。此表必须配置为存储 "conn_cnt" 数据类型,否则匹配将被忽略。当前计数会加一,并且到期计时器会刷新。更新后的计数将被返回,因此此匹配不会返回零。这曾被用来根据源地址拒绝滥用服务的用户。注意:建议改用 "tcp-request" 规则中功能更完整的 "track-sc*" 操作。
Example
# 此前端限制每个源地址的传入 SSH 连接为每 10 秒 3 次, # 并拒绝超出的连接,直到观察到 10 秒的静默期。最多跟踪 20 个地址。 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 规则集中使用。
返回此流在尝试连接到服务器时经历的连接重试次数。在连接完全建立之前,此值可能会发生变化。对于 HTTP 连接,L7 重试可能会影响该值。
根据“option redispatch”配置,如果在重试时发生重新调度,则返回 true。在连接完全建立之前,此值可能会发生变化。对于 HTTP 连接,L7 重试可能会影响该值。

7.3.4. 在第 5 层获取样本

第 5 层通常只描述会话层,在 HAProxy 中,一旦所有连接握手完成,并且在内容可用之前,它最接近会话层。此处描述的获取方法可用于低至“tcp-request content”的规则集,除非它们需要一些未来的信息。这些通常包括 SSL 协商的结果。本节中示例获取方法及其相应类型的摘要。
关键字输出类型
51d.all(<prop>[,<prop>*])字符串
bs.aborted布尔
bs.debug_str([<bitmap>])字符串
bs.id整数
bs.rst_code整数
fs.aborted布尔
fs.debug_str([<bitmap>])字符串
fs.id整数
fs.rst_code整数
ssl_bc布尔
ssl_bc_alg_keysize整数
ssl_bc_alpn字符串
ssl_bc_cipher字符串
ssl_bc_client_early_traffic_secret字符串
ssl_bc_client_handshake_traffic_secret字符串
ssl_bc_client_random二进制
ssl_bc_client_traffic_secret_0字符串
ssl_bc_curve字符串
ssl_bc_early_exporter_secret字符串
ssl_bc_err整数
关键字输出类型
ssl_bc_err_str字符串
ssl_bc_exporter_secret字符串
ssl_bc_is_resumed布尔
ssl_bc_npn字符串
ssl_bc_protocol字符串
ssl_bc_server_handshake_traffic_secret字符串
ssl_bc_server_random二进制
ssl_bc_server_traffic_secret_0字符串
ssl_bc_session_id二进制
ssl_bc_session_key二进制
ssl_bc_sni字符串
ssl_bc_unique_id二进制
ssl_bc_use_keysize整数
ssl_c_ca_err整数
ssl_c_ca_err_depth整数
ssl_c_chain_der二进制
ssl_c_der二进制
ssl_c_err整数
ssl_c_i_dn([<entry>[,<occ>[,<format>]]])字符串
ssl_c_key_alg字符串
关键字输出类型
ssl_c_notafter字符串
ssl_c_notbefore字符串
ssl_c_r_dn([<entry>[,<occ>[,<format>]]])字符串
ssl_c_s_dn([<entry>[,<occ>[,<format>]]])字符串
ssl_c_san字符串
ssl_c_serial二进制
ssl_c_sha1二进制
ssl_c_sig_alg字符串
ssl_c_used布尔
ssl_c_verify整数
ssl_c_version整数
ssl_f_der二进制
ssl_f_i_dn([<entry>[,<occ>[,<format>]]])字符串
ssl_f_key_alg字符串
ssl_f_notafter字符串
ssl_f_notbefore字符串
ssl_f_s_dn([<entry>[,<occ>[,<format>]]])字符串
ssl_f_serial二进制
ssl_f_sha1二进制
ssl_f_sig_alg字符串
关键字输出类型
ssl_f_version整数
ssl_fc布尔
ssl_fc_alg_keysize整数
ssl_fc_alpn字符串
ssl_fc_cipher字符串
ssl_fc_cipherlist_bin([<filter_option>])二进制
ssl_fc_cipherlist_hex([<filter_option>])字符串
ssl_fc_cipherlist_str([<filter_option>])字符串
ssl_fc_cipherlist_xxh整数
ssl_fc_client_early_traffic_secret字符串
ssl_fc_client_handshake_traffic_secret字符串
ssl_fc_client_random二进制
ssl_fc_client_traffic_secret_0字符串
ssl_fc_curve字符串
ssl_fc_early_exporter_secret字符串
ssl_fc_ecformats_bin二进制
ssl_fc_eclist_bin([<filter_option>])二进制
ssl_fc_err整数
ssl_fc_err_str字符串
ssl_fc_exporter_secret字符串
关键字输出类型
ssl_fc_extlist_bin([<filter_option>])二进制
ssl_fc_has_crt布尔
ssl_fc_has_early布尔
ssl_fc_has_sni布尔
ssl_fc_is_resumed布尔
ssl_fc_npn字符串
ssl_fc_protocol字符串
ssl_fc_protocol_hello_id整数
ssl_fc_server_handshake_traffic_secret字符串
ssl_fc_server_random二进制
ssl_fc_server_traffic_secret_0字符串
ssl_fc_session_id二进制
ssl_fc_session_key二进制
ssl_fc_sigalgs_bin([<filter_option>])二进制
ssl_fc_sni字符串
ssl_fc_supported_versions_bin([<filter_option>])二进制
ssl_fc_unique_id二进制
ssl_fc_use_keysize整数
ssl_s_chain_der二进制
ssl_s_der二进制
关键字输出类型
ssl_s_i_dn([<entry>[,<occ>[,<format>]]])字符串
ssl_s_key_alg字符串
ssl_s_notafter字符串
ssl_s_notbefore字符串
ssl_s_s_dn([<entry>[,<occ>[,<format>]]])字符串
ssl_s_serial二进制
ssl_s_sha1二进制
ssl_s_sig_alg字符串
ssl_s_version整数
txn.timer.user整数
详细列表
51d.all(<prop>[,<prop>*]) : string
以字符串形式返回请求的属性值,值之间用“51degrees-property-separator”指定的定界符分隔。设备通过请求中的所有重要 HTTP 头部来识别。该函数最多可以传递五个属性名称,如果找不到属性名称,则返回“NoData”。
Example
# 此处将头部 "X-51D-DeviceTypeMobileTablet" 添加到请求中 # 包含使用请求中的所有相关头部请求的三个属性。 frontend http-in bind *:8081 default_backend servers http-request set-header X-51D-DeviceTypeMobileTablet \ %[51d.all(DeviceType,IsMobile,IsTablet)]
bs.aborted : boolean
如果从服务器收到当前流的中止(abort)信号,则返回 true。否则返回 false。
bs.debug_str([<bitmap>]) : string
此函数旨在供开发人员在某些复杂的故障排除会话中使用。它从后端流和连接的较低层中提取一些内部状态,并将其排列成一个字符串,通常采用以空格分隔的一系列 "name=value" 形式。可选参数 <bitmap> 指示要从哪些层提取信息,并且是以下值的算术 OR(或总和): - 套接字层:16 - 连接层:8 - 传输层(例如 SSL):4 - 复用连接:2 - 复用流:1 这些值可能会在不同版本之间发生变化。默认值零很特殊,它会启用所有层。请不要依赖此函数的输出来进行长期生产监控。它旨在在稳定分支内发展,以满足对增加细节的需求。一个典型的用例是在 log-format 的末尾连接这些信息,以及 fs.debug_str()。示例:log-format "$HAPROXY_HTTP_LOG_FMT fs=<%[fs.debug_str]> bs=<%[bs.debug_str]>"
bs.id : integer
返回服务器端的复用器(multiplexer)流 ID。由复用器负责返回适当的信息。
bs.rst_code : integer
返回从服务器收到的当前流的重置代码。返回从服务器接收到的 H2 RST_STREAM 帧或 QUIC STOP_SENDING 帧的代码。如果未收到中止信号或服务器流不是 H2/QUIC 流,则此示例获取失败。
fs.aborted : boolean
如果从客户端收到当前流的中止(abort)信号,则返回 true。否则返回 false。
fs.debug_str([<bitmap>]) : string
此函数旨在供开发人员在某些复杂的故障排除会话中使用。它从前端流和连接的较低层中提取一些内部状态,并将其排列成一个字符串,通常采用以空格分隔的一系列 "name=value" 形式。可选参数 <bitmap> 指示要从哪些层提取信息,并且是以下值的算术 OR(或总和): - 套接字层:16 - 连接层:8 - 传输层(例如 SSL):4 - 复用连接:2 - 复用流:1 这些值可能会在不同版本之间发生变化。默认值零很特殊,它会启用所有层。请不要依赖此函数的输出来进行长期生产监控。它旨在在稳定分支内发展,以满足对增加细节的需求。一个典型的用例是在 log-format 的末尾连接这些信息,以及 bs.debug_str()。示例:log-format "$HAPROXY_HTTP_LOG_FMT fs=<%[fs.debug_str]> bs=<%[bs.debug_str]>"
fs.id : integer
返回客户端的复用器(multiplexer)流 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/TLS 传输层建立时支持的对称密码(cipher)密钥大小(以位为单位)。它可以用于 tcp-check 或 http-check 规则集。
ssl_bc_alpn : string
这从通过 TLS 传输层建立的传出连接中提取应用层协议协商字段。结果是包含与服务器协商的协议名称的字符串。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 传输层建立的出站连接所使用的密码(cipher)的名称。它可以用于 tcp-check 或 http-check 规则集。
当通过 TLS 1.3 传输层建立出站连接时,返回 CLIENT_EARLY_TRAFFIC_SECRET 作为十六进制字符串,用于后端连接。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调用于生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志记录必须通过全局部分的“tune.ssl.keylog on”进行激活。另请参阅“tune.ssl.keylog”。
当通过 TLS 1.3 传输层建立出站连接时,返回 CLIENT_HANDSHAKE_TRAFFIC_SECRET 作为十六进制字符串,用于后端连接。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调用于生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志记录必须通过全局部分的“tune.ssl.keylog on”进行激活。另请参阅“tune.ssl.keylog”。
当入站连接通过 SSL/TLS 传输层建立时,返回后端连接的客户端随机数(client random)。它对于解密使用临时密码(ephemeral ciphers)发送的流量很有用。这需要 OpenSSL >= 1.1.0,或 BoringSSL。它可以用于 tcp-check 或 http-check 规则集。
当通过 TLS 1.3 传输层建立出站连接时,返回 CLIENT_TRAFFIC_SECRET_0 作为十六进制字符串,用于后端连接。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调用于生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志记录必须通过全局部分的“tune.ssl.keylog on”进行激活。另请参阅“tune.ssl.keylog”。
ssl_bc_curve : string
当出站连接通过 SSL/TLS 传输层建立时,返回密钥协议(key agreement)中使用的曲线的名称。这需要 OpenSSL >= 3.0.0 或 AWS-LC >= 1.57.0。
当通过 TLS 1.3 传输层建立出站连接时,返回 EARLY_EXPORTER_SECRET 作为十六进制字符串,用于后端连接。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调用于生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志记录必须通过全局部分的“tune.ssl.keylog on”进行激活。另请参阅“tune.ssl.keylog”。
ssl_bc_err : integer
当出站连接通过 SSL/TLS 传输层建立时,返回后端端最后一个错误堆栈的第一个错误的 ID。它可能引发握手错误以及连接生命周期中发生的其他读写错误。为了获得此错误代码的文本描述,您可以使用“ssl_bc_err_str”示例获取,或使用“openssl errstr”命令(该命令以十六进制表示形式的错误代码作为参数)。请参考您的 SSL 库文档以查找错误代码的完整列表。
当出站连接通过 SSL/TLS 传输层建立时,返回后端角度的连接上发生的最后一个错误堆栈的第一个错误的字符串表示。另请参阅“ssl_fc_err”。
当通过 TLS 1.3 传输层建立出站连接时,返回 EXPORTER_SECRET 作为十六进制字符串,用于后端连接。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调用于生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志记录必须通过全局部分的“tune.ssl.keylog on”进行激活。另请参阅“tune.ssl.keylog”。
当后端连接通过 SSL/TLS 传输层建立,并且新创建的 SSL 会话是通过缓存会话或 TLS 票据恢复的,则返回 true。它可以用于 tcp-check 或 http-check 规则集。
ssl_bc_npn : string
这从通过 TLS 传输层建立的传出连接中提取下一个协议协商字段。结果是包含与服务器协商的协议名称的字符串。SSL 库必须在构建时启用 TLS 扩展支持(检查 haproxy -vv)。请注意,除非 "server" 行上的 "npn" 关键字指定了协议列表,否则不会通告 TLS NPN 扩展。此外,没有任何东西强制服务器从该列表中选择一个协议,可能会使用任何其他协议。请注意,TLS NPN 扩展已被 ALPN 取代。它可以在 tcp-check 或 http-check 规则集中使用。
返回通过 SSL/TLS 传输层建立的出站连接所使用的协议的名称。它可以用于 tcp-check 或 http-check 规则集。
当通过 TLS 1.3 传输层建立出站连接时,返回 SERVER_HANDSHAKE_TRAFFIC_SECRET 作为十六进制字符串,用于后端连接。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调用于生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志记录必须通过全局部分的“tune.ssl.keylog on”进行激活。另请参阅“tune.ssl.keylog”。
当入站连接通过 SSL/TLS 传输层建立时,返回后端连接的服务器随机数(server random)。它对于解密使用临时密码(ephemeral ciphers)发送的流量很有用。这需要 OpenSSL >= 1.1.0,或 BoringSSL。它可以用于 tcp-check 或 http-check 规则集。
当通过 TLS 1.3 传输层建立出站连接时,返回 SERVER_TRAFFIC_SECRET_0 作为十六进制字符串,用于后端连接。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调用于生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志记录必须通过全局部分的“tune.ssl.keylog on”进行激活。另请参阅“tune.ssl.keylog”。
当出站连接通过 SSL/TLS 传输层建立时,返回后端连接的 SSL ID。如果想要知道会话是否被重用,它对于日志记录很有用。它可以用于 tcp-check 或 http-check 规则集。
当出站连接通过 SSL/TLS 传输层建立时,返回后端连接的 SSL 会话主密钥。它对于解密使用临时密码(ephemeral ciphers)发送的流量很有用。这需要 OpenSSL >= 1.1.0,或 BoringSSL。它可以用于 tcp-check 或 http-check 规则集。
ssl_bc_sni : string
此项检索连接到服务器时使用的服务器名称指示(Server Name Indication, SNI)TLS 扩展字段。返回的结果(如果存在)通常是一个字符串,匹配 HTTPS 主机名(最多 253 个字符)。主要用例是用于日志记录和调试目的(例如,在建立连接时找出使用的 SNI,并将其与服务器看到的进行匹配)。
当出站连接通过 SSL/TLS 传输层建立时,返回 RFC 5929 第 3 节定义的 TLS 唯一 ID。可以使用转换器将唯一 ID 编码为 base64:“ssl_bc_unique_id,base64”。它可以用于 tcp-check 或 http-check 规则集。
返回出站连接通过 SSL/TLS 传输层建立时使用的对称密码(cipher)密钥大小(以位为单位)。它可以用于 tcp-check 或 http-check 规则集。
ssl_c_ca_err : integer
当传入连接通过 SSL/TLS 传输层建立时,如果在验证深度 > 0 的客户端证书期间检测到第一个错误,则返回该错误的 ID;如果在此验证过程中未遇到错误,则返回 0。请参考您的 SSL 库文档以查找完整的错误代码列表。
当传入连接通过 SSL/TLS 传输层建立时,如果在验证客户端证书期间检测到第一个错误,则返回该错误在 CA 链中的深度。如果未遇到错误,则返回 0。
当入站连接通过 SSL/TLS 传输层建立时,返回客户端提供的 DER 格式的链证书。当用于 ACL 时,可以以十六进制形式传递要匹配的值。可以使用任何接受 ASN.1 DER 数据的库来解析结果。它目前不支持恢复的会话。
ssl_c_der : binary
当传入连接通过 SSL/TLS 传输层建立时,返回由客户端提供的 DER 格式证书。当用于 ACL 时,用于匹配的值可以以十六进制形式传递。
ssl_c_err : integer
当传入连接通过 SSL/TLS 传输层建立时,如果在深度为 0 的验证期间检测到第一个错误,则返回该错误的 ID;如果在此验证过程中未遇到错误,则返回 0。请参考您的 SSL 库文档以查找完整的错误代码列表。
ssl_c_i_dn([<entry>[,<occ>[,<format>]]]) : string
当入站连接通过 SSL/TLS 传输层建立时,在未指定 <entry> 时,返回客户端提供的证书颁发者的完整区分名(Distinguished Name, DN),或者返回从 DN 开始的第一个给定条目的值。如果指定了正数/负数的出现次数作为可选的第二个参数,则返回从 DN 的开头/结尾开始的第 n 个给定条目的值。例如,“ssl_c_i_dn(OU,2)”表示第二个组织单位,而“ssl_c_i_dn(CN)”则检索通用名称。<format> 参数允许您获取适合不同协议使用的 DN。目前支持 LDAP v3 的 rfc2253。如果您只想修改格式,可以指定一个空字符串和零作为前两个参数。例如:ssl_c_i_dn(,0,rfc2253)
ssl_c_key_alg : string
当传入连接通过 SSL/TLS 传输层建立时,返回用于生成客户端证书密钥的算法名称。
当传入连接通过 SSL/TLS 传输层建立时,返回客户端证书中显示的结束日期,格式为 YYMMDDhhmmss[Z] 字符串。
当传入连接通过 SSL/TLS 传输层建立时,返回客户端证书中显示的开始日期,格式为 YYMMDDhhmmss[Z] 字符串。
ssl_c_r_dn([<entry>[,<occ>[,<format>]]]) : string
当入站连接通过 SSL/TLS 传输层建立,并且使用配置的 ca-file 成功验证时,在未指定 <entry> 时,返回客户端提供的证书的根 CA 的完整区分名(Distinguished Name, DN),或者返回从 DN 开始的第一个给定条目的值。如果指定了正数/负数的出现次数作为可选的第二个参数,则返回从 DN 的开头/结尾开始的第 n 个给定条目的值。例如,“ssl_c_r_dn(OU,2)”表示第二个组织单位,而“ssl_c_r_dn(CN)”则检索通用名称。<format> 参数允许您获取适合不同协议使用的 DN。目前支持 LDAP v3 的 rfc2253。如果您只想修改格式,可以指定一个空字符串和零作为前两个参数。例如:ssl_c_r_dn(,0,rfc2253)
ssl_c_s_dn([<entry>[,<occ>[,<format>]]]) : string
当入站连接通过 SSL/TLS 传输层建立时,在未指定 <entry> 时,返回客户端提供的证书主题的完整区分名(Distinguished Name, DN),或者返回从 DN 开始的第一个给定条目的值。如果指定了正数/负数的出现次数作为可选的第二个参数,则返回从 DN 的开头/结尾开始的第 n 个给定条目的值。例如,“ssl_c_s_dn(OU,2)”表示第二个组织单位,而“ssl_c_s_dn(CN)”则检索通用名称。<format> 参数允许您获取适合不同协议使用的 DN。目前支持 LDAP v3 的 rfc2253。如果您只想修改格式,可以指定一个空字符串和零作为前两个参数。例如:ssl_c_s_dn(,0,rfc2253)
ssl_c_san : string
当入站连接通过 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:https://docs.haproxy.cn/2.7/, DNS:ca.tests.haproxy.com
ssl_c_serial : binary
当传入连接通过 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 : string
当传入连接通过 SSL/TLS 传输层建立时,返回用于签署客户端证书的算法名称。
ssl_c_used : boolean
如果当前 SSL 会话使用了客户端证书,则返回 true,即使当前连接使用的是 SSL 会话恢复。另请参阅 "ssl_fc_has_crt"。
ssl_c_verify : integer
当传入连接通过 SSL/TLS 传输层建立时,返回验证结果的错误 ID;如果未遇到错误,则返回零。有关完整的错误代码列表,请参考您的 SSL 库文档。
ssl_c_version : integer
当传入连接通过 SSL/TLS 传输层建立时,返回客户端证书的版本。
ssl_f_der : binary
当传入连接通过 SSL/TLS 传输层建立时,返回前端提供的 DER 格式证书。当用于 ACL 时,用于匹配的值可以以十六进制形式传递。
ssl_f_i_dn([<entry>[,<occ>[,<format>]]]) : string
当入站连接通过 SSL/TLS 传输层建立时,在未指定 <entry> 时,返回前端提供的证书颁发者的完整区分名(Distinguished Name, DN),或者返回从 DN 开始的第一个给定条目的值。如果指定了正数/负数的出现次数作为可选的第二个参数,则返回从 DN 的开头/结尾开始的第 n 个给定条目的值。例如,“ssl_f_i_dn(OU,2)”表示第二个组织单位,而“ssl_f_i_dn(CN)”则检索通用名称。<format> 参数允许您获取适合不同协议使用的 DN。目前支持 LDAP v3 的 rfc2253。如果您只想修改格式,可以指定一个空字符串和零作为前两个参数。例如:ssl_f_i_dn(,0,rfc2253)
ssl_f_key_alg : string
当传入连接通过 SSL/TLS 传输层建立时,返回用于生成前端证书密钥的算法名称。
当传入连接通过 SSL/TLS 传输层建立时,返回前端证书中显示的结束日期,格式为 YYMMDDhhmmss[Z] 字符串。
当传入连接通过 SSL/TLS 传输层建立时,返回前端证书中显示的开始日期,格式为 YYMMDDhhmmss[Z] 字符串。
ssl_f_s_dn([<entry>[,<occ>[,<format>]]]) : string
当入站连接通过 SSL/TLS 传输层建立时,在未指定 <entry> 时,返回前端提供的证书主题的完整区分名(Distinguished Name, DN),或者返回从 DN 开始的第一个给定条目的值。如果指定了正数/负数的出现次数作为可选的第二个参数,则返回从 DN 的开头/结尾开始的第 n 个给定条目的值。例如,“ssl_f_s_dn(OU,2)”表示第二个组织单位,而“ssl_f_s_dn(CN)”则检索通用名称。<format> 参数允许您获取适合不同协议使用的 DN。目前支持 LDAP v3 的 rfc2253。如果您只想修改格式,可以指定一个空字符串和零作为前两个参数。例如:ssl_f_s_dn(,0,rfc2253)
ssl_f_serial : binary
当传入连接通过 SSL/TLS 传输层建立时,返回前端证书的序列号。当用于 ACL 时,用于匹配的值可以以十六进制形式传递。
ssl_f_sha1 : binary
当传入连接通过 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" 行的套接字。
Example
# 当客户端通过 SSL 连接时,向服务器传递 "X-Proto: https" listen http-https bind :80 bind :443 ssl crt /etc/haproxy.pem http-request add-header X-Proto https if { ssl_fc }
当传入连接通过 SSL/TLS 传输层建立时,返回支持的对称加密密钥大小(以位为单位)。
ssl_fc_alpn : string
这从通过 TLS 传输层建立并由 HAProxy 在本地解密的传入连接中提取应用层协议协商字段。结果是包含客户端通告的协议名称的字符串。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
返回客户端 hello 密码列表的二进制形式。最大返回值的长度受由“tune.ssl.capture-buffer-size”设置控制的共享捕获缓冲区大小的限制。设置 <filter_option> 允许过滤返回的数据。可接受的值:0:返回完整的密码列表(默认)1:从输出中排除 GREASE(RFC8701)值
示例
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
以十六进制编码的形式返回客户端 hello 密码列表的二进制形式。最大返回值的长度受由“tune.ssl.capture-buffer-size”设置控制的共享捕获缓冲区大小的限制。设置 <filter_option> 允许过滤返回的数据。可接受的值:0:返回完整的密码列表(默认)1:从输出中排除 GREASE(RFC8701)值
ssl_fc_cipherlist_str([<filter_option>]) : string
返回客户端 hello 密码列表的已解码文本形式。最大返回值的长度受由“tune.ssl.capture-buffer-size”设置控制的共享捕获缓冲区大小的限制。设置 <filter_option> 允许过滤返回的数据。可接受的值:0:返回完整的密码列表(默认)1:从输出中排除 GREASE(RFC8701)值请注意,此示例获取仅适用于 OpenSSL >= 1.0.2。如果未启用该函数,此示例获取将返回哈希值,如“ssl_fc_cipherlist_xxh”。
返回密码列表的 xxh64 哈希值。此哈希值仅在“tune.ssl.capture-buffer-size”的值大于 0 时才有效,但哈希值考虑了密码列表的所有数据。
当通过 TLS 1.3 传输层建立入站连接时,返回 CLIENT_EARLY_TRAFFIC_SECRET 作为十六进制字符串,用于前端连接。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调用于生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志记录必须通过全局部分的“tune.ssl.keylog on”进行激活。另请参阅“tune.ssl.keylog”。
当通过 TLS 1.3 传输层建立入站连接时,返回 CLIENT_HANDSHAKE_TRAFFIC_SECRET 作为十六进制字符串,用于前端连接。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调用于生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志记录必须通过全局部分的“tune.ssl.keylog on”进行激活。另请参阅“tune.ssl.keylog”。
当入站连接通过 SSL/TLS 传输层建立时,返回前端连接的客户端随机数(client random)。它对于解密使用临时密码(ephemeral ciphers)发送的流量很有用。这需要 OpenSSL >= 1.1.0,或 BoringSSL。
当通过 TLS 1.3 传输层建立入站连接时,返回 CLIENT_TRAFFIC_SECRET_0 作为十六进制字符串,用于前端连接。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调用于生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志记录必须通过全局部分的“tune.ssl.keylog on”进行激活。另请参阅“tune.ssl.keylog”。
ssl_fc_curve : string
当入站连接通过 SSL/TLS 传输层建立时,返回密钥协议(key agreement)中使用的曲线的名称。这需要 OpenSSL >= 3.0.0。
如果通过该连接看到了早期数据(early data),无论握手此后是否完成,都返回 true。它对流量处理没有实际用途,但是它是“看到”客户端使用 0-RTT 发送早期数据的方法之一,有时在调试时很有用,因为另外的唯一方法是网络流量捕获或记录前端连接的标志并在代码中匹配它们。它也可能有助于获取客户端功能统计信息。另请参阅“ssl_fc_has_early”。
当通过 TLS 1.3 传输层建立入站连接时,返回 EARLY_EXPORTER_SECRET 作为十六进制字符串,用于前端连接。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调用于生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志记录必须通过全局部分的“tune.ssl.keylog on”进行激活。另请参阅“tune.ssl.keylog”。
返回客户端 hello 支持的椭圆曲线点格式(elliptic curve point formats)的二进制形式。最大返回值的长度受由“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
返回客户端 hello 支持的椭圆曲线(elliptic curves)的二进制形式。最大返回值的长度受由“tune.ssl.capture-buffer-size”设置控制的共享捕获缓冲区大小的限制。设置 <filter_option> 允许过滤返回的数据。可接受的值:0:返回支持的椭圆曲线的完整列表(默认)1:从输出中排除 GREASE(RFC8701)值
示例
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 : integer
当入站连接通过 SSL/TLS 传输层建立时,返回前端端最后一个错误堆栈的第一个错误的 ID,如果没有遇到错误则返回 0。它可用于识别与握手相关的错误(除了验证错误,例如密码不匹配),以及连接生命周期中发生的其他读写错误。客户端证书验证过程中发生的任何错误都不会通过此获取返回,而是通过现有的“ssl_c_err”、“ssl_c_ca_err”和“ssl_c_ca_err_depth”获取返回。为了获得此错误代码的文本描述,您可以使用“ssl_fc_err_str”示例获取,或使用“openssl errstr”命令(该命令以十六进制表示形式的错误代码作为参数)。请参考您的 SSL 库文档以查找错误代码的完整列表。
当入站连接通过 SSL/TLS 传输层建立时,返回前端端发生的最后一个错误堆栈的第一个错误的字符串表示。在客户端证书验证过程中发生的任何错误都不会通过此获取返回。另请参阅“ssl_fc_err”。
当通过 TLS 1.3 传输层建立入站连接时,返回 EXPORTER_SECRET 作为十六进制字符串,用于前端连接。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调用于生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志记录必须通过全局部分的“tune.ssl.keylog on”进行激活。另请参阅“tune.ssl.keylog”。
ssl_fc_extlist_bin([<filter_option>]) : binary
返回客户端 hello 扩展列表(extension list)的二进制形式。最大返回值的长度受由“tune.ssl.capture-buffer-size”设置控制的共享捕获缓冲区大小的限制。设置 <filter_option> 允许过滤返回的数据。可接受的值:0:返回完整的扩展列表(默认)1:从输出中排除 GREASE(RFC8701)值
示例
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 : boolean
如果传入的 SSL/TLS 传输层连接中存在客户端证书,则返回 true。在 'verify' 语句设置为 'optional' 时很有用。注意:在使用会话 ID 或 TLS 票据进行 SSL 会话恢复时,当前连接中不存在客户端证书,但可以从缓存或票据中检索。因此,如果您想检查当前 SSL 会话是否使用了客户端证书,请优先使用 "ssl_c_used"。
如果发送了早期数据(early data),并且握手尚未完成,则返回 true。由于它具有安全隐患,因此能够拒绝这些数据或等待握手完成(通过“wait-for-handshake”操作)非常有用。另请参阅“ssl_fc_early_rcvd”。
ssl_fc_has_sni : boolean
这会检查入站连接是否通过 SSL/TLS 传输层建立,以及是否包含服务器名称指示(Server Name Indication, SNI)TLS 扩展。当入站连接提供 TLS SNI 字段时,返回 true。这需要 SSL 库已构建为支持 TLS 扩展(请检查 haproxy -vv)。
如果通过 SSL/TLS 传输层传入的连接上,SSL/TLS 会话已通过使用 SSL 会话缓存或 TLS 票据得到恢复,则返回 true。
ssl_fc_npn : string
这从通过 TLS 传输层建立并由 HAProxy 在本地解密的传入连接中提取下一个协议协商字段。结果是包含客户端通告的协议名称的字符串。SSL 库必须在构建时启用 TLS 扩展支持(检查 haproxy -vv)。请注意,除非 "bind" 行上的 "npn" 关键字指定了协议列表,否则不会通告 TLS NPN 扩展。此外,没有任何东西强制客户端从该列表中选择一个协议,可能会请求任何其他协议。请注意,TLS NPN 扩展已被 ALPN 取代。
当传入连接通过 SSL/TLS 传输层建立时,返回所使用的协议的名称。
客户端在会话期间希望通过 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
当传入连接通过 TLS 1.3 传输层建立时,以十六进制字符串形式返回前端连接的 SERVER_HANDSHAKE_TRAFFIC_SECRET。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调函数转储以生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志必须在全局部分使用 "tune.ssl.keylog on" 激活。另请参阅 "tune.ssl.keylog"
在连接通过 SSL/TLS 传输层建立时,返回前端连接的服务器随机数。这对于解密使用临时密码发送的流量非常有用。这需要 OpenSSL >= 1.1.0 或 BoringSSL。
当传入连接通过 TLS 1.3 传输层建立时,以十六进制字符串形式返回前端连接的 SERVER_TRAFFIC_SECRET_0。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调函数转储以生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志必须在全局部分使用 "tune.ssl.keylog on" 激活。另请参阅 "tune.ssl.keylog"
当传入连接通过 SSL/TLS 传输层建立时,返回前端连接的 SSL ID。这对于将给定客户端粘滞到某个服务器很有用。需要注意的是,某些浏览器每隔几分钟就会刷新其会话 ID。
在连接通过 SSL/TLS 传输层建立时,返回前端连接的 SSL 会话主密钥。这对于解密使用临时密码发送的流量非常有用。这需要 OpenSSL >= 1.1.0 或 BoringSSL。
ssl_fc_sigalgs_bin([<filter_option>]) : binary
返回客户端 hello 期间提供的 signatures_algorithms (13) TLS 扩展的内容。它提供了一个 2 字节算法的二进制列表,这些算法在 TLS RFC 中定义: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 在本地解密的传入连接中提取服务器名称指示 TLS 扩展 (SNI) 字段。结果(如果存在)通常是匹配 HTTPS 主机名(253 个字符或更少)的字符串。SSL 库必须在构建时启用 TLS 扩展支持(检查 haproxy -vv)。此获取与上面的 "req.ssl_sni" 不同,因为它适用于 HAProxy 正在解密的连接,而不是盲目转发的 SSL 内容。另请参阅下面的 "ssl_fc_sni_end" 和 "ssl_fc_sni_reg"。这要求 SSL 库在构建时启用 TLS 扩展支持(检查 haproxy -vv)。注意!除非在非常特定的条件下,否则通常不应将此字段用作 HTTP "Host" 标头字段的替代品。例如,将 HTTPS 连接转发到服务器时,必须使用 "req.hdr(host)" 而不是前端 SNI 值设置 SNI 字段。原因是 SNI 仅用于选择服务器端将呈现的证书,并且允许客户端发送具有不同 Host 值(只要它们匹配证书中的名称)的请求。因此,"ssl_fc_sni" 通常不应作为 "sni" 服务器关键字的参数使用,除非后端在 TCP 模式下工作。ACL 派生:ssl_fc_sni_end:后缀匹配 ssl_fc_sni_reg:正则表达式匹配
ssl_fc_supported_versions_bin([<filter_option>]) : binary
返回客户端 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/TLS 传输层建立时,返回 RFC5929 第 3 节中定义的 TLS 唯一 ID。可以使用转换器 "ssl_fc_unique_id,base64" 将唯一 ID 编码为 base64。
当传入连接通过 SSL/TLS 传输层建立时,返回实际使用的对称加密密钥大小(以位为单位)。
当出站连接通过 SSL/TLS 传输层建立时,返回服务器呈现的 DER 格式的链证书。当用于 ACL 时,用于匹配的值可以以十六进制形式传递。可以使用任何接受 ASN.1 DER 数据的库来解析结果。它目前不支持恢复的会话。
ssl_s_der : binary
当出站连接通过 SSL/TLS 传输层建立时,返回服务器呈现的 DER 格式的证书。当用于 ACL 时,用于匹配的值可以以十六进制形式传递。
ssl_s_i_dn([<entry>[,<occ>[,<format>]]]) : string
当出站连接通过 SSL/TLS 传输层建立时,返回服务器呈现的证书颁发者的完整专有名称,如果没有指定 <entry>,或者返回从 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)
ssl_s_key_alg : string
当出站连接通过 SSL/TLS 传输层建立时,返回用于生成服务器呈现的证书密钥的算法名称。
当出站连接通过 SSL/TLS 传输层建立时,以 YYMMDDhhmmss[Z] 格式的字符串返回服务器呈现的到期日期。
当出站连接通过 SSL/TLS 传输层建立时,以 YYMMDDhhmmss[Z] 格式的字符串返回服务器呈现的开始日期。
ssl_s_s_dn([<entry>[,<occ>[,<format>]]]) : string
当出站连接通过 SSL/TLS 传输层建立时,返回服务器呈现的证书主体的完整专有名称,如果没有指定 <entry>,或者返回从 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)
ssl_s_serial : binary
当出站连接通过 SSL/TLS 传输层建立时,返回服务器呈现的证书序列号。当用于 ACL 时,用于匹配的值可以以十六进制形式传递。
ssl_s_sha1 : binary
当出站连接通过 SSL/TLS 传输层建立时,返回服务器呈现的证书的 SHA-1 指纹。这可以用来知道使用 SNI 选择的证书。
ssl_s_sig_alg : string
当出站连接通过 SSL/TLS 传输层建立时,返回用于签名服务器呈现的证书的算法名称。
ssl_s_version : integer
当出站连接通过 SSL/TLS 传输层建立时,返回服务器呈现的证书的版本。
txn.timer.user : integer
从客户端看到的总估计时间,从代理接受它到双方都关闭,不包括空闲时间。这相当于日志格式中的 %Tu,并以毫秒 (ms) 为单位报告。有关更多详细信息,请参阅第 8.4 节“计时事件”。

7.3.5. 从缓冲区内容(第 6 层)获取样本

从缓冲区内容中获取样本与上面以前的样本获取有点不同,因为采样的数据是短暂的。这些数据只能在可用时使用,转发后就会丢失。因此,例如,在请求期间从缓冲区内容中获取的样本不能用于响应中。即使在获取数据时,它们也可能发生变化。有时需要设置一些延迟或组合多个样本获取方法,以确保预期数据完整且可用,例如通过 TCP 请求内容检查。有关该主题的更多详细信息,请参阅 "tcp-request content" 关键字。警告:如果从 HTTP 代理中使用,则忽略以下样本获取。它们只处理缓冲区中的原始内容。就其本身而言,HTTP 代理使用结构化内容。因此,这些数据的原始表示毫无意义。如果 ACL 依赖于以下样本获取之一,则会发出警告。但无法检测所有无效用法(例如在自定义日志格式或样本表达式内部)。所以要小心。本节中的样本获取方法及其相应类型摘要
关键字输出类型
distcc_body(<token>[,<occ>])二进制
distcc_param(<token>[,<occ>])整数
payload(<offset>,<length>)二进制
payload_lv(<offset1>,<length>[,<offset2>])二进制
rdp_cookie([<name>])字符串
rdp_cookie_cnt([name])整数
rep_ssl_hello_type整数
req.len整数
req.payload(<offset>,<length>)二进制
req.payload_lv(<offset1>,<length>[,<offset2>])二进制
req.proto_http布尔
req.rdp_cookie([<name>])字符串
req.rdp_cookie_cnt([name])整数
req.ssl_alpn字符串
req.ssl_cipherlist二进制
req.ssl_ec_ext布尔
req.ssl_hello_type整数
req.ssl_keyshare_groups二进制
req.ssl_sigalgs二进制
req.ssl_sni字符串
req.ssl_st_ext整数
req.ssl_supported_groups二进制
req.ssl_ver整数
req_len整数
req_proto_http布尔
req_ssl_hello_type整数
req_ssl_sni字符串
req_ssl_ver整数
res.len整数
res.payload(<offset>,<length>)二进制
res.payload_lv(<offset1>,<length>[,<offset2>])二进制
res.ssl_hello_type整数
详细列表
distcc_body(<token>[,<occ>]) : binary
解析 distcc 消息并返回与 token <token> 的 occurrence #<occ> 关联的正文。Occurrence 从 1 开始,如果未指定,则任何 occurrence 都可能匹配,但实际上目前只检查第一个。这可以用于提取通过 HAProxy 构建的文件中的文件名或参数。有关支持的 token 的完整列表,请参阅 distcc 的协议文档。
distcc_param(<token>[,<occ>]) : integer
解析 distcc 消息并返回与 token <token> 的 occurrence #<occ> 关联的参数。Occurrence 从 1 开始,如果未指定,则任何 occurrence 都可能匹配,但实际上目前只检查第一个。这可以用于提取某些信息,例如协议版本、文件大小或通过 HAProxy 构建的文件中的参数。另一个用例是在连接到服务器之前等待预处理文件内容,以避免保持空闲连接。有关支持的 token 的完整列表,请参阅 distcc 的协议文档。
Example
# 等待预处理文件上传最多 20 秒 tcp-request inspect-delay 20s tcp-request content accept if { distcc_param(DOTI) -m found } # 将大文件发送到大型服务器场 use_backend big_farm if { distcc_param(DOTI) gt 1000000 }
payload(<offset>,<length>) : binary (已弃用)
这是 "req.payload" 在请求上下文(例如,“stick on”、“stick match”)中的别名,在响应上下文(例如“stick store response”)中是 "res.payload" 的别名。
payload_lv(<offset1>,<length>[,<offset2>]) : binary (已弃用)
这是 "req.payload_lv" 在请求上下文(例如,“stick on”、“stick match”)中的别名,在响应上下文(例如“stick store response”)中是 "res.payload_lv" 的别名。
req.len : integer
req_len : integer (已弃用)
返回请求缓冲区中存在的字节数。这主要用于 ACL。重要的是要理解,只要缓冲区在变化,此测试就不会返回 false。这意味着等于零的检查几乎总是在会话开始时立即匹配,而对更多数据的测试将等待数据进入,直到 HAProxy 确定不再有数据进来时才返回 false。此测试旨在与 TCP 请求内容检查一起使用。
req.payload(<offset>,<length>) : binary
这会从请求缓冲区中提取 <length> 字节的二进制块,从字节 <offset> 开始。作为特殊情况,如果 <length> 参数为零,则提取从 <offset> 到末尾的整个缓冲区。这可以与 ACL 一起使用,以检查缓冲区中任何位置是否存在某些内容。ACL 派生:req.payload(<offset>,<length>):十六进制二进制匹配
req.payload_lv(<offset1>,<length>[,<offset2>]) : binary
这会提取一个二进制块,其大小由 <offset1> 指定 <length> 字节,如果指定了 <offset2>,则从该位置开始,否则紧跟在请求缓冲区中的长度之后。<offset2> 参数如果以 '+' 或 '-' 符号开头,也支持相对偏移。ACL 派生:req.payload_lv(<offset1>,<length>[,<offset2>]):十六进制二进制匹配
Example
请参考 "stick store-response" 关键字中的示例。
req.proto_http : boolean
req_proto_http : boolean (已弃用)
当请求缓冲区中的数据看起来像 HTTP 并且能被正确解析时,返回 true。它与通用的 HTTP 请求解析器相同,因此应该不会有意外。在请求完成、失败或超时之前,此测试不会匹配。此测试可用于在 TCP 日志中报告协议,但最大的用途是阻止 TCP 请求分析,直到缓冲区中出现完整的 HTTP 请求,例如为了跟踪某个头部。
示例
# 按 "base"(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
rdp_cookie([<name>]) : string (已弃用)
当请求缓冲区看起来像 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>]):精确字符串匹配
Example
listen tse-farm bind 0.0.0.0:3389 # 在请求中等待 RDP cookie 最多 5 秒 tcp-request inspect-delay 5s tcp-request content accept if RDP_COOKIE # 应用 RDP cookie 持久性 persist rdp-cookie # 基于 mstshash cookie 进行持久化 # 仅在不使用 balance rdp-cookie 时 # 才有意义 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
req.rdp_cookie_cnt([name]) : integer
rdp_cookie_cnt([name]) : integer (已弃用)
尝试将请求缓冲区解析为 RDP 协议,然后返回一个整数,表示找到的 RDP cookie 的数量。如果提供了可选的 cookie 名称,则只考虑匹配该名称的 cookie。这主要用于 ACL。ACL 派生:req.rdp_cookie_cnt([<name>]):整数匹配
req.ssl_alpn : string
返回一个字符串,其中包含客户端在 SSL ClientHello 消息中发送的应用层协议协商 (ALPN) TLS 扩展 (RFC7301) 的值。请注意,这仅适用于请求缓冲区中的原始内容,不适用于通过 SSL 数据层解密的内容,因此这不适用于带有 "ssl" 选项的 "bind" 行。这对于 ACL 非常有用,可以根据 TLS 客户端的 ALPN 首选项做出路由决策,如下面的示例所示。另请参阅 "ssl_fc_alpn"。
示例
# 等待客户端 hello 最多 5 秒 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
返回客户端在 TLS ClientHello 内容中报告的受支持的对称密码选项列表的二进制形式。请注意,这仅适用于请求缓冲区中的原始内容,不适用于通过 SSL 数据层解密的内容,因此这不适用于带有 "ssl" 选项的 "bind" 行。请参阅 "ssl_fc_cipherlist_bin",它是指定 "ssl" 选项时可以使用的 SSL bind 等效项。
示例
# 等待客户端 hello 最多 5 秒 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节中定义的“Supported Elliptic Curves Extension”。这可用于向 ECC 兼容客户端呈现 EC 证书,并对所有其他客户端使用 RSA,在同一 IP 地址上。请注意,这仅适用于请求缓冲区中的原始内容,不适用于通过 SSL 数据层解密的内容,因此这不适用于带有 "ssl" 选项的 "bind" 行。
req_ssl_hello_type : integer (已弃用)
如果缓冲区包含解析为完整 SSL(v3 或更高版本)客户端 Hello 消息的数据,则返回包含在请求缓冲区中找到的 SSL Hello 消息类型的整数值。请注意,这仅适用于请求缓冲区中的原始内容,不适用于通过 SSL 数据层解密的内容,因此这不适用于带有 "ssl" 选项的 "bind" 行。这主要用于 ACL 中以检测是否存在 SSL Hello 消息,该消息应包含可用于粘性的 SSL 会话 ID。
返回客户端在 TLS ClientHello 中报告的用于密钥交换的加密参数列表的二进制格式。在 TLS v1.3 中,keyshare 是 ClientHello 消息的一部分,并且是最终的客户端 hello 扩展。请注意,这仅适用于请求缓冲区中的原始内容,不适用于通过 SSL 数据层解密的内容,因此这不适用于带有 "ssl" 选项的 "bind" 行。
示例
# 等待客户端 hello 最多 5 秒 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}
返回客户端在 TLS ClientHello 中报告的受支持签名算法列表的二进制形式。这可作为客户端 hello 扩展使用。请注意,这仅适用于请求缓冲区中的原始内容,不适用于通过 SSL 数据层解密的内容,因此这不适用于带有 "ssl" 选项的 "bind" 行。请参阅 "ssl_fc_sigalgs_bin",它是指定 "ssl" 选项时可以使用的 SSL bind 等效项。
示例
# 等待客户端 hello 最多 5 秒 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 (已弃用)
如果缓冲区包含解析为完整 SSL(v3 或更高版本)客户端 Hello 消息的数据,则返回包含客户端在通过请求缓冲区传递的 TLS 流中发送的服务器名称 TLS 扩展的值的字符串。结果(如果存在)通常是匹配 HTTPS 主机名(253 个字符或更少)的字符串。SSL 库必须在构建时启用 TLS 扩展支持(检查 haproxy -vv)。请注意,这仅适用于请求缓冲区中的原始内容,不适用于通过 SSL 数据层解密的内容,因此这不适用于带有 "ssl" 选项的 "bind" 行。这仅适用于实际的隐式 TLS 协议,如 HTTPS (443)、IMAPS (993)、SMTPS (465),但不适用于显式 TLS 协议,如 SMTP (25/587) 或 IMAP (143)。SNI 通常包含客户端尝试连接的主机名(对于最近的浏览器)。当客户端使用 SSL/TLS 时,SNI 对于允许或拒绝访问某些主机非常有用。此测试旨在与 TCP 请求内容检查一起使用。如果需要内容切换,建议首先等待完整的客户端 hello(类型 1),如下面的示例所示。另请参阅 "ssl_fc_sni"。ACL 派生:req.ssl_sni:精确字符串匹配
示例
# 等待客户端 hello 最多 5 秒 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
如果客户端未发送 SessionTicket TLS 扩展 (RFC5077),则返回 0。如果客户端发送了 SessionTicket TLS 扩展,则返回 1。如果客户端还发送了非零长度的 TLS SessionTicket,则返回 2。请注意,这仅适用于请求缓冲区中的原始内容,不适用于通过 SSL 数据层解密的内容,因此这不适用于带有 "ssl" 选项的 "bind" 行。例如,这可用于检测客户端是否发送了 SessionTicket 并相应地进行粘性处理,如果没有 SessionTicket,则根据 SessionID 进行粘性处理或不进行粘性处理,因为在使用 SessionTickets 时没有服务器端状态。
返回客户端在 TLS ClientHello 中报告的受支持组列表的二进制形式,用于密钥交换,可包括椭圆曲线和非 EC 密钥交换。请注意,这仅适用于请求缓冲区中的原始内容,不适用于通过 SSL 数据层解密的内容,因此这不适用于带有 "ssl" 选项的 "bind" 行。请参阅 "ssl_fc_eclist_bin",它是指定 "ssl" 选项时可以使用的 SSL bind 等效项。
示例
# 等待客户端 hello 最多 5 秒 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。ACL 派生:req.ssl_ver:十进制匹配
res.len : integer
返回响应缓冲区中存在的字节数的整数值。这主要用于 ACL。重要的是要理解,只要缓冲区在变化,此测试就不会返回 false。这意味着等于零的检查几乎总是在流开始时立即匹配,而对更多数据的测试将等待数据进入,直到 HAProxy 确定不再有数据进来时才返回 false。此测试旨在与 TCP 响应内容检查一起使用。但也可用于基于 tcp-check 的 expect 规则。
res.payload(<offset>,<length>) : binary
这会从响应缓冲区中提取 <length> 字节的二进制块,从字节 <offset> 开始。作为特殊情况,如果 <length> 参数为零,则提取从 <offset> 到末尾的整个缓冲区。这可以与 ACL 一起使用,以检查缓冲区中任何位置是否存在某些内容。它也可用于基于 tcp-check 的 expect 规则。
res.payload_lv(<offset1>,<length>[,<offset2>]) : binary
这会提取一个二进制块,其大小由 <offset1> 指定 <length> 字节,如果指定了 <offset2>,则从该位置开始,否则紧跟在响应缓冲区中的长度之后。<offset2> 参数如果以 '+' 或 '-' 符号开头,也支持相对偏移。它也可用于基于 tcp-check 的 expect 规则。
Example
请参考 "stick store-response" 关键字中的示例。
rep_ssl_hello_type : integer (已弃用)
如果缓冲区包含解析为完整 SSL(v3 或更高版本)hello 消息的数据,则返回包含响应缓冲区中找到的 SSL hello 消息类型的整数值。请注意,这仅适用于响应缓冲区中的原始内容,不适用于通过 SSL 数据层解密的内容,因此这不适用于带有 "ssl" 选项的 "server" 行。这主要用于 ACL 中以检测是否存在 SSL Hello 消息,该消息应包含可用于粘性的 SSL 会话 ID。

7.3.6. 获取 HTTP 样本 (第 7 层)

可以从 HTTP 内容、请求和响应中获取样本。此应用层也称为第 7 层。只有当从其各自的请求或响应缓冲区解析出完整的 HTTP 请求或响应时,才能获取本节中的数据。对于所有 HTTP 特定规则和运行 "mode http" 的部分来说,情况总是如此。使用 TCP 内容检查时,可能需要支持检查延迟以首先让请求或响应进来。这些获取可能比第 4 层的获取需要更多的 CPU 资源,但不多,因为请求和响应已编制索引。注意:对于来自 tcp-request content 规则的 HTTP 处理,一切都将像 HTTP 代理一样按预期工作。但是,对于 TCP 代理,如果没有 HTTP 升级,它只适用于 HTTP/1 内容。对于 HTTP/2 内容,只有序言可见。因此,只能依赖 "req.proto_http"、"req.ver" 以及最终的 "method" 样本获取。所有其他 L7 样本获取都将失败。在 HTTP 升级之后,它们将以与 HTTP 代理相同的方式工作。本节中的样本获取方法及其相应类型摘要
关键字输出类型
base字符串
base32整数
base32+src二进制
baseq字符串
capture.req.hdr(<idx>)字符串
capture.req.method字符串
capture.req.uri字符串
capture.req.ver字符串
capture.res.hdr(<idx>)字符串
capture.res.ver字符串
cook([<name>])字符串
cook_cnt([<name>])整数
cook_val([<name>])整数
cookie([<name>])字符串
hdr([<name>[,<occ>]])字符串
hdr_cnt([<header>])整数
hdr_ip([<name>[,<occ>]])ip
hdr_val([<name>[,<occ>]])整数
http_auth(<userlist>)布尔
http_auth_bearer([<header>])字符串
关键字输出类型
http_auth_group(<userlist>)字符串
http_auth_pass字符串
http_auth_type字符串
http_auth_user字符串
http_first_req布尔
method整数
path字符串
pathq字符串
query([<options>])字符串
req.body二进制
req.body_len整数
req.body_param([<name>[,i]])字符串
req.body_size整数
req.cook([<name>])字符串
req.cook_cnt([<name>])整数
req.cook_names([<delim>])字符串
req.cook_val([<name>])整数
req.fhdr(<name>[,<occ>])字符串
req.fhdr_cnt([<name>])整数
req.hdr([<name>[,<occ>]])字符串
关键字输出类型
req.hdr_cnt([<name>])整数
req.hdr_ip([<name>[,<occ>]])ip
req.hdr_names([<delim>])字符串
req.hdr_val([<name>[,<occ>]])整数
req.hdrs字符串
req.hdrs_bin二进制
req.timer.hdr整数
req.timer.idle整数
req.timer.queue整数
req.timer.tq整数
req.ver字符串
req_ver字符串
request_date([<unit>])整数
res.body二进制
res.body_len整数
res.body_size整数
res.cache_hit布尔
res.cache_name字符串
res.comp布尔
res.comp_algo字符串
关键字输出类型
res.cook([<name>])字符串
res.cook_cnt([<name>])整数
res.cook_names([<delim>])字符串
res.cook_val([<name>])整数
res.fhdr([<name>[,<occ>]])字符串
res.fhdr_cnt([<name>])整数
res.hdr([<name>[,<occ>]])字符串
res.hdr_cnt([<name>])整数
res.hdr_ip([<name>[,<occ>]])ip
res.hdr_names([<delim>])字符串
res.hdr_val([<name>[,<occ>]])整数
res.hdrs字符串
res.hdrs_bin二进制
res.timer.hdr整数
res.ver字符串
resp_ver字符串
scook([<name>])字符串
scook_cnt([<name>])整数
scook_val([<name>])整数
server_status整数
关键字输出类型
set-cookie([<name>])字符串
shdr([<name>[,<occ>]])字符串
shdr_cnt([<name>])整数
shdr_ip([<name>[,<occ>]])ip
shdr_val([<name>[,<occ>]])整数
status整数
txn.status整数
txn.timer.total整数
unique-id字符串
url字符串
url32整数
url32+src二进制
url_ipip
url_param([<name>[,<delim>[,i]]])字符串
url_port整数
urlp([<name>[,<delim>[,i]]])字符串
urlp_val([<name>[,<delim>[,i]]])整数
详细列表
base : string
这返回第一个 Host 标头和请求路径部分的串联,路径部分从第一个斜杠开始,到问号之前结束。在虚拟托管环境中,它可用于检测 URL 滥用以及提高共享缓存效率。将其与有限大小的 stick table 一起使用,还可以收集有关按主机/路径请求最多的对象的统计信息。对于 ACL,它允许涉及主机和路径的简单内容切换规则,例如 "www.example.com/favicon.ico"。另请参阅 "path" 和 "uri"。ACL 派生:base:精确字符串匹配 base_beg:前缀匹配 base_dir:子目录匹配 base_dom:域匹配 base_end:后缀匹配 base_len:长度匹配 base_reg:正则表达式匹配 base_sub:子字符串匹配 注意: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 request header" 捕获的头部内容,idx 是 capture 关键字在配置中的位置。
此函数提取 HTTP 请求的 METHOD。它可以在请求和响应中使用。与 "method" 不同,因为它被分配了内存,所以可以在请求和响应中使用。
capture.req.uri : string
此函数提取请求的 HTTP 版本,并返回 "HTTP/1.0" 或 "HTTP/1.1"。与 "req.ver" 不同,因为它依赖于一个持久性标志,所以可以在请求、响应和日志中使用。
capture.res.hdr(<idx>) : string
此函数提取由 "capture response header" 捕获的头部内容,idx 是 capture 关键字在配置中的位置。第一个条目的索引为 0。
此函数提取响应的 HTTP 版本,并返回 "HTTP/1.0" 或 "HTTP/1.1"。与 "res.ver" 不同,因为它依赖于一个持久性标志,所以可以在日志中使用。
cookie([<name>]) : string (已弃用)
从请求的“Cookie”标头行中提取 cookie 名称 <name> 的最后一次出现,或从响应的“Set-Cookie”标头中提取,并返回其值作为字符串。典型的用途是让共享相同配置文件的多个客户端使用相同的服务器。这可以与“appsession”通过“request-learn”语句所做的类似,但支持多对同步和跨重启的状态保持。如果未指定名称,则返回第一个 cookie 值。此获取不应再使用,应替换为 req.cook() 或 res.cook(),因为它根据使用它的上下文含糊地使用方向。
hdr([<name>[,<occ>]]) : string
在请求上使用时,此函数等同于 req.hdr();在响应上使用时,等同于 res.hdr()。有关更多详细信息,请参考这些各自的获取。如果不确定获取方向,请使用明确的函数。请注意,与 hdr() 样本获取方法相反,hdr_* ACL 关键字明确地应用于请求头部。
http_auth(<userlist>) : boolean
返回一个布尔值,指示从客户端收到的身份验证数据是否与指定用户列表中存储的用户名和密码匹配。此获取函数在 ACL 之外并不真正有用。目前仅支持 http 基本身份验证。
http_auth_bearer([<header>]) : string
返回客户端在使用 Bearer 方案(例如,发送 JSON Web Tokens)的授权数据中找到的客户端提供的 token。不对客户端发送的数据执行任何检查。如果提供了特定的 <header>,它将解析该标头而不是 Authorization 标头。
http_auth_group(<userlist>) : string
如果从客户端收到的身份验证数据中的用户名和密码根据指定用户列表均有效,则返回一个对应于该用户名的字符串。其主要目的是在 ACL 中使用,然后检查该用户是否属于列表中的任何组。此获取函数在 ACL 之外并不真正有用。目前仅支持 http 基本身份验证。ACL 派生词:http_auth_group(<userlist>) : group ... 当从请求中提取的用户(其密码根据指定用户列表有效)属于至少一个组时返回 true。
返回用户在从客户端接收到的身份验证数据中找到的密码,该数据在 Authorization 标头中提供。此样本获取不执行任何检查。仅支持 Basic 身份验证。
返回用户在从客户端接收到的身份验证数据中找到的身份验证方法,该数据在 Authorization 标头中提供。此样本获取不执行任何检查。仅支持 Basic 身份验证。
返回用户在从客户端接收到的身份验证数据中找到的用户名,该数据在 Authorization 标头中提供。此样本获取不执行任何检查。仅支持 Basic 身份验证。
http_first_req : boolean
当正在处理的请求是连接的第一个请求时返回 true。这可用于添加或删除在请求不是第一个时某些请求中可能缺少的头部,或帮助在日志中对请求进行分组。
method : integer + string
返回一个对应于 HTTP 请求中方法的整数值。例如,"GET" 等于 1(检查源代码以确定匹配关系)。值 9 表示“其他方法”,并可能转换为从流中提取的字符串。这不应直接用作样本,它仅用于 ACL,ACL 会透明地将方法从模式转换为这些整数 + 字符串值。一些预定义的 ACL 已经检查了最常见的方法。ACL 派生词:method:不区分大小写的方法匹配
Example
# 只接受 GET 和 HEAD 请求 acl valid_method method GET HEAD http-request deny if ! valid_method
path : string
这提取请求的 URL 路径,该路径从第一个斜杠开始,到问号之前结束(不带主机部分)。典型用途是与具有预取功能的缓存一起使用,以及与需要从数据库聚合多个信息并将其保存在缓存中的门户网站一起使用。请注意,对于传出缓存,使用 "url" 而不是 "path" 会更明智。对于 ACL,它通常用于匹配精确的文件名(例如 "/login.php"),或使用派生形式匹配目录部分。另请参阅 "url" 和 "base" 获取方法。请注意,HTTP 标准严格禁止 URI 中的任何片段引用(路径后面的 '#'),并且将被拒绝。但是,如果接收请求的前端具有 "option accept-unsafe-violations-in-http-request",则此片段部分将被接受,并且也会出现在路径中。ACL 派生:path:精确字符串匹配 path_beg:前缀匹配 path_dir:子目录匹配 path_dom:域匹配 path_end:后缀匹配 path_len:长度匹配 path_reg:正则表达式匹配 path_sub:子字符串匹配 注意:ACL 派生后面不能跟转换器,也不能在带有 "-m" 模式匹配方法的 ACL 中使用。
pathq : string
这会提取请求的 URL 路径(包含查询字符串),路径从第一个斜杠开始。这个样本获取非常方便,可以始终检索相对 URI,不包括 scheme 和 authority 部分(如果有)。事实上,虽然这是 HTTP/1.1 请求目标的一种常见表示,但在 HTTP/2 中,通常使用绝对 URI。这个样本获取在这两种情况下都会返回相同的结果。请注意,URI 中的任何片段引用(路径后的“#”)都严格禁止由 HTTP 标准,并将被拒绝。但是,如果接收请求的前端具有“option accept-unsafe-violations-in-http-request”,则将接受此片段部分,并且它也会出现在路径中。
query([<options>]) : string
这会提取请求的查询字符串,该字符串从第一个问号开始。如果不存在问号,则此获取返回空。如果存在问号但后面没有内容,则返回空字符串。这意味着可以使用“found”匹配方法轻松知道是否存在查询字符串。此获取是“path”(在问号之前停止)和“query_string”(包含问号)的补充。可以使用可选参数来自定义返回值。支持以下选项:- with_qm:如果查询字符串不为空,则在其开头包含问号。
req.body : binary
这会返回 HTTP 请求的可用正文作为数据块。建议使用 "option http-buffer-request" 来确保尽可能等待请求的正文。
req.body_len : integer
这会返回 HTTP 请求可用正文的长度(以字节为单位)。如果正文大于缓冲区,则其长度可能小于广告长度。建议使用 "option http-buffer-request" 来确保尽可能等待请求的正文。
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
cook([<name>]) : string (已弃用)
这从请求中的 "Cookie" 标头行中提取 cookie 名称 <name> 的最后一次出现,并将其值作为字符串返回。如果未指定名称,则返回第一个 cookie 值。与 ACL 一起使用时,会评估所有匹配的 cookie。根据 Cookie 标头规范 (RFC6265) 的要求,名称和值周围的空格将被忽略。cookie 名称区分大小写。空 cookie 是有效的,因此如果存在空 cookie,它很可能会返回空值。使用 "found" 匹配来检测存在性。使用 res.cook() 变体用于服务器发送的响应 cookie。ACL 派生:req.cook([<name>]):精确字符串匹配 req.cook_beg([<name>]):前缀匹配 req.cook_dir([<name>]):子目录匹配 req.cook_dom([<name>]):域匹配 req.cook_end([<name>]):后缀匹配 req.cook_len([<name>]):长度匹配 req.cook_reg([<name>]):正则表达式匹配 req.cook_sub([<name>]):子字符串匹配 注意:ACL 派生后面不能跟转换器,也不能在带有 "-m" 模式匹配方法的 ACL 中使用。
req.cook_cnt([<name>]) : integer
cook_cnt([<name>]) : integer (已弃用)
返回一个整数值,表示名为 <name> 的 cookie 在请求中出现的次数;如果未指定 <name>,则表示所有 cookie 的数量。
req.cook_names([<delim>]) : string
在规则求值时,此函数会创建一个字符串,该字符串由请求(Cookie 标头)中出现的所有 cookie 名称连接而成。默认分隔符是逗号 (','),但可以作为可选参数 <delim> 覆盖。在这种情况下,只考虑 <delim> 的第一个字符。
req.cook_val([<name>]) : integer
cook_val([<name>]) : integer (已弃用)
此函数从请求的 "Cookie" 头部行中提取名为 <name> 的 cookie 的最后一次出现,并将其值转换为整数返回。如果未指定名称,则返回第一个 cookie 的值。在 ACL 中使用时,将遍历所有匹配的名称,直到找到一个匹配的值。
req.fhdr(<name>[,<occ>]) : string
返回 HTTP 请求中标头 <name> 的最后一次出现的完整值。它与 req.hdr() 的区别在于,它会返回值中存在的任何逗号,而不会将它们用作分隔符。这有时对 User-Agent 等标头很有用。从 ACL 使用时,会迭代所有出现直到找到匹配。可选地,可以通过位置编号指定特定的出现次数。正数表示从第一次出现开始的位置,1 是第一个。负数表示相对于最后一个的位置,-1 是最后一个。一个典型的用途是与 X-Forwarded-For 标头(在转换为 IP 后)相关联。
req.fhdr_cnt([<name>]) : integer
返回请求标头字段名称 <name> 的出现次数的整数值,如果未指定 <name>,则返回总标头字段数。与 req.fhdr() 不同,它不会在逗号处分割标头。ACL 中,它可以用于检测特定标头的存在、不存在或滥用,以及通过拒绝包含多个特定标头的请求来阻止请求伪装攻击。有关标头匹配的更多信息,请参阅 req.hdr()。
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>]]):精确字符串匹配 hdr_beg([<name>[,<occ>]]):前缀匹配 hdr_dir([<name>[,<occ>]]):子目录匹配 hdr_dom([<name>[,<occ>]]):域匹配 hdr_end([<name>[,<occ>]]):后缀匹配 hdr_len([<name>[,<occ>]]):长度匹配 hdr_reg([<name>[,<occ>]]):正则表达式匹配 hdr_sub([<name>[,<occ>]]):子字符串匹配 注意:ACL 派生后面不能跟转换器,也不能在带有 "-m" 模式匹配方法的 ACL 中使用。
req.hdr_cnt([<name>]) : integer
hdr_cnt([<header>]) : integer (已弃用)
返回请求标头字段名称 <name> 的出现次数的整数值,如果未指定 <name>,则返回所有标头字段值。与 req.hdr() 一样,它计算标头值中每个逗号分隔的部分。如果需要计算完整的行标头,则应改用 req.fhdr_cnt()。使用 ACL,它可以用于检测特定标头的存在、不存在或滥用,以及通过拒绝包含多个特定标头的请求来阻止请求伪装攻击。有关更多信息,请参阅 req.hdr()。
req.hdr_ip([<name>[,<occ>]]) : ip
hdr_ip([<name>[,<occ>]]) : ip (已弃用)
提取 HTTP 请求中最后一个标头 <name> 的值,将其转换为 IPv4 或 IPv6 地址,并返回该地址。与 ACL 一起使用时,会检查所有出现;如果省略 <name>,则检查每个标头的所有值。解析器严格遵循 RFC7239 中描述的格式,并扩展支持 IPv4 地址后面可选地跟着一个冒号 (':') 和一个有效的十进制端口号(0 到 65535),该端口号将被静默删除。所有其他格式将不匹配并导致地址被忽略。<occ> 参数的处理方式与 req.hdr() 相同。典型的用法是 X-Forwarded-For 和 X-Client-IP 标头。
req.hdr_names([<delim>]) : string
此函数构建一个字符串,该字符串由规则评估时请求中出现的所有头部名称拼接而成。默认分隔符是逗号 (','),但可以通过可选参数 <delim> 进行覆盖。在这种情况下,只考虑 <delim> 的第一个字符。
req.hdr_val([<name>[,<occ>]]) : integer
hdr_val([<name>[,<occ>]]) : integer (已弃用)
提取 HTTP 请求中最后一个标头 <name> 的值,并将其转换为整数值。与 ACL 一起使用时,会检查所有出现;如果省略 <name>,则检查每个标头的所有值。<occ> 参数的处理方式与 req.hdr() 相同。典型的用法是 X-Forwarded-For 标头。
req.hdrs : string
以字符串形式返回当前请求标头,包括分隔标头和请求正文的最后空行。最后空行可用于检测截断的标头块。此样本获取对于某些 SPOE 标头分析器和高级日志记录非常有用。
req.hdrs_bin : binary
以预解析的二进制形式返回当前请求标头。这对于使用 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 : integer
这是 HTTP 请求之前的空闲时间(仅限 HTTP 模式)。此计时器在握手结束和 HTTP 请求的第一个字节之间进行计数。以毫秒为单位报告,相当于日志格式中的 %Ti。有关更多详细信息,请参阅第 8.4 节“计时事件”。
req.timer.queue : integer
在队列中等待连接槽的总时间。以毫秒为单位报告,相当于日志格式中的 %Tw。有关更多详细信息,请参阅第 8.4 节“计时事件”。
req.timer.tq : integer
从接受日期或自上一个响应的最后一个字节发出以来,获取客户端请求的总时间。以毫秒为单位报告,相当于日志格式中的 %Tq。有关更多详细信息,请参阅第 8.4 节“计时事件”。
req.ver : string
req_ver : string (已弃用)
返回 HTTP 请求的版本字符串,例如“1.1”。这在 ACL 中很有用。对于日志,请使用“%HV”日志格式别名。一些预定义的 ACL 已经检查了版本 1.0 和 1.1。常见值为“1.0”、“1.1”、“2.0”或“3.0”。对于 http/2 和 http/3,该值不是从请求行中的 HTTP 版本中提取的,而是由协商的协议版本确定的。ACL 派生:req.ver:精确字符串匹配
request_date([<unit>]) : integer
这是 HAProxy 接收到 HTTP 请求的第一个字节的确切日期(日志格式别名 %tr)。这是从 accept_date + handshake time (%Th) + idle time (%Ti) 计算得出的。返回自 epoch 以来的秒数。<unit> 是可选的,可以设置为“s”表示秒(默认行为),“ms”表示毫秒或“us”表示微秒。如果设置了 unit,则返回值是一个整数,表示自 epoch 以来的秒、毫秒或微秒。当需要小于一秒的时间分辨率时,它很有用。
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”。
返回用于构建 HTTP 响应的 HTTP 缓存名称的字符串(如果 res.cache_hit 为 true),否则返回空字符串。
res.comp : boolean
如果响应已被 HAProxy 压缩,则返回布尔值 "true",否则返回布尔值 "false"。这可用于在日志中添加信息。
res.comp_algo : string
如果响应被 HAProxy 压缩,则返回一个包含所用算法名称的字符串,例如:“deflate”。这可用于在日志中添加一些信息。
res.cook([<name>]) : string
scook([<name>]) : string (已弃用)
从响应的“Set-Cookie”标头行中提取 cookie 名称 <name> 的最后一次出现,并返回其值。如果未指定名称,则返回第一个 cookie 值。它可用于基于 tcp-check 的 expect 规则。ACL 派生:res.scook([<name>]:精确字符串匹配
res.cook_cnt([<name>]) : integer
scook_cnt([<name>]) : integer (已弃用)
返回响应中 cookie <name> 的出现次数的整数值,如果未指定 <name>,则返回所有 cookie。这在与 ACL 结合以检测可疑响应时非常有用。它可用于基于 tcp-check 的 expect 规则。
res.cook_names([<delim>]) : string
在规则求值时,此函数会创建一个字符串,该字符串由响应(Set-Cookie 标头)中出现的所有 cookie 名称连接而成。默认分隔符是逗号 (','),但可以作为可选参数 <delim> 覆盖。在这种情况下,只考虑 <delim> 的第一个字符。它可用于基于 tcp-check 的 expect 规则。
res.cook_val([<name>]) : integer
scook_val([<name>]) : integer (已弃用)
从响应的“Set-Cookie”标头行中提取 cookie 名称 <name> 的最后一次出现,并将其值转换为整数返回。如果未指定名称,则返回第一个 cookie 值。它可用于基于 tcp-check 的 expect 规则。
res.fhdr([<name>[,<occ>]]) : string
此获取器的工作方式类似于 req.fhdr() 获取器,区别在于它作用于 HTTP 响应中的标头。与 req.fhdr() 一样,res.fhdr() 获取器返回完整值。如果标头定义为列表,则应使用 res.hdr()。此获取器有时对 Date 或 Expires 等标头很有用。它可用于基于 tcp-check 的 expect 规则。
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
shdr([<name>[,<occ>]]) : string (已弃用)
此获取的工作方式与 req.hdr() 获取类似,不同之处在于它作用于 HTTP 响应中的标头。与 req.hdr() 一样,res.hdr() 获取将逗号视为分隔符。如果不需要,应使用 res.fhdr()。它可以在基于 tcp-check 的 expect 规则中使用。ACL 派生:res.hdr([<name>[,<occ>]]):精确字符串匹配 res.hdr_beg([<name>[,<occ>]]):前缀匹配 res.hdr_dir([<name>[,<occ>]]):子目录匹配 res.hdr_dom([<name>[,<occ>]]):域匹配 res.hdr_end([<name>[,<occ>]]):后缀匹配 res.hdr_len([<name>[,<occ>]]):长度匹配 res.hdr_reg([<name>[,<occ>]]):正则表达式匹配 res.hdr_sub([<name>[,<occ>]]):子字符串匹配 注意:ACL 派生后面不能跟转换器,也不能在带有 "-m" 模式匹配方法的 ACL 中使用。
res.hdr_cnt([<name>]) : integer
shdr_cnt([<name>]) : integer (已弃用)
此获取器的工作方式类似于 req.hdr_cnt() 获取器,区别在于它作用于 HTTP 响应中的标头。与 req.hdr_cnt() 一样,res.hdr_cnt() 获取器将逗号视为分隔符。如果不需要,应使用 res.fhdr_cnt()。它可用于基于 tcp-check 的 expect 规则。
res.hdr_ip([<name>[,<occ>]]) : ip
shdr_ip([<name>[,<occ>]]) : ip (已弃用)
此获取器的工作方式类似于 req.hdr_ip() 获取器,区别在于它作用于 HTTP 响应中的标头。这有助于将某些数据学习到粘滞表中。它可用于基于 tcp-check 的 expect 规则。
res.hdr_names([<delim>]) : string
在规则求值时,此函数会创建一个字符串,该字符串由响应中出现的名称相同的标头连接而成。默认分隔符是逗号 (','),但可以作为可选参数 <delim> 覆盖。在这种情况下,只考虑 <delim> 的第一个字符。它可用于基于 tcp-check 的 expect 规则。
res.hdr_val([<name>[,<occ>]]) : integer
shdr_val([<name>[,<occ>]]) : integer (已弃用)
此获取器的工作方式类似于 req.hdr_val() 获取器,区别在于它作用于 HTTP 响应中的标头。这有助于将某些数据学习到粘滞表中。它可用于基于 tcp-check 的 expect 规则。
res.hdrs : string
以字符串形式返回当前响应标头,包括分隔标头和请求正文的最后空行。最后空行可用于检测截断的标头块。此样本获取对于某些 SPOE 标头分析器和高级日志记录非常有用。它也可用于基于 tcp-check 的 expect 规则。
res.hdrs_bin : binary
以预解析的二进制形式返回当前响应标头。这对于使用 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 响应中的版本字符串,例如“1.1”。这在日志中很有用,但主要用于 ACL。它可用于基于 tcp-check 的 expect 规则。ACL 派生:resp.ver:精确字符串匹配
server_status : integer
返回一个整数,其中包含从服务器收到的 HTTP 状态代码。如果没有从服务器收到响应,则样本获取失败。
set-cookie([<name>]) : string (已弃用)
从响应的“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 样本获取将失败。请注意,unique-id 通常与 HTTP 请求一起使用,但是此样本获取也可以与其他协议一起使用。显然,如果它与 HTTP 以外的协议一起使用,unique-id-format 指令不应包含 HTTP 部分。另请参阅:unique-id-format 和 unique-id-header
url : string
这提取请求中呈现的 URL。典型用途是与具有预取功能的缓存一起使用,以及与需要从数据库聚合多个信息并将其保存在缓存中的门户网站一起使用。对于 ACL,使用 "path" 优于使用 "url",因为客户端可能会发送一个完整的 URL,就像代理通常所做的那样。唯一真正的用途是匹配 "path" 中不匹配的 "*",为此已经有一个预定义的 ACL。另请参阅 "path" 和 "base"。请注意,HTTP 标准严格禁止 URI 中的任何片段引用(路径后面的 '#'),并且将被拒绝。但是,如果接收请求的前端具有 "option accept-unsafe-violations-in-http-request",则此片段部分将被接受,并且也会出现在 url 中。ACL 派生:url:精确字符串匹配 url_beg:前缀匹配 url_dir:子目录匹配 url_dom:域匹配 url_end:后缀匹配 url_len:长度匹配 url_reg:正则表达式匹配 url_sub:子字符串匹配 注意:ACL 派生后面不能跟转换器,也不能在带有 "-m" 模式匹配方法的 ACL 中使用。
url32 : integer
此函数返回一个 32 位哈希值,该值由连接第一个 Host 标头和整个 URL(包括参数,而不仅仅是请求的路径部分,如上面的 "base32" 提取)得到。这对于跟踪每个 URL 的活动很有用。存储一个较短的哈希值可以节省大量内存。输出类型是无符号整数。
url32+src : binary
此函数返回 "url32" 提取和 "src" 提取的连接结果。结果类型为 binary,大小为 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
url_param([<name>[,<delim>[,i]]]) : string
This extracts the first occurrence of the parameter  in the query string, which begins after either '?' or , and which ends before '&', ';' or . The parameter name is case-sensitive, unless"i" is added as a third argument. If no name is given, any parameter will match, and the first one will be returned. The result is a string corresponding to the value of the parameter  as presented in the request (no URL decoding is performed). This can be used for session stickiness based on a client ID, to extract an application cookie passed as a URL parameter, or in ACLs to apply some checks. Note that the ACL version of this fetch iterates over multiple parameters and will iteratively report all parameters values if no name is given ACL derivatives : urlp([,]) : exact string match urlp_beg([,]) : prefix match urlp_dir([,]) : subdir match urlp_dom([,]) : domain match urlp_end([,]) : suffix match urlp_len([,]) : length match urlp_reg([,]) : regex match urlp_sub([,]) : substring match Note: ACL derivatives must not be used followed by a converter or in ACLs with a "-m" pattern matching method.
Example
# 匹配 http://example.com/foo?PHPSESSIONID=some_id stick on urlp(PHPSESSIONID) # 匹配 http://example.com/foo;JSESSIONID=some_id stick on urlp(JSESSIONID,;)
urlp_val([<name>[,<delim>[,i]]]) : integer
参见上面的 "urlp"。此函数提取请求中的 URL 参数 <name> 并将其转换为整数值。例如,这可用于基于用户 ID 的会话粘性,或与 ACL 一起匹配页码或价格。

7.3.7. 为开发人员提取样本

这组样本fetch方法保留给开发人员,除非在调试目的下按开发人员的要求,否则绝不能在生产环境中使用。此外,在向后兼容性方面不会采取任何特殊措施。无法保证以下样本fetch方法永远不会更改、重命名或删除。因此,如果您使用其中一个,请务必小心。为避免任何歧义,这些样本fetch方法被放置在专用的“internal”作用域中,例如“internal.strm.is_htx”。本节中的样本fetch方法及其各自类型的摘要。
关键字输出类型
internal.htx.data整数
internal.htx.free整数
internal.htx.free_data整数
internal.htx.has_eom布尔
internal.htx.nbblks整数
internal.htx.size整数
internal.htx.used整数
internal.htx_blk.size(<idx>)整数
internal.htx_blk.type(<idx>)字符串
internal.htx_blk.data(<idx>)二进制
internal.htx_blk.hdrname(<idx>)字符串
internal.htx_blk.hdrval(<idx>)字符串
internal.htx_blk.start_line(<idx>)字符串
internal.strm.is_htx布尔
详细列表
返回与通道关联的HTX消息中数据使用的字节数。通道的选择取决于样本方向。
返回与通道关联的HTX消息中的可用空间(大小-已用)的字节数。通道的选择取决于样本方向。
返回与通道关联的HTX消息中数据使用的可用空间的字节数。通道的选择取决于样本方向。
如果与通道关联的HTX消息包含消息结束标志(EOM),则返回true。否则,返回false。通道的选择取决于样本方向。
返回与通道关联的HTX消息中存在的块的数量。通道的选择取决于样本方向。
返回与通道关联的HTX消息的总字节大小。通道的选择取决于样本方向。
返回与通道关联的HTX消息中使用的总大小(数据+元数据)的字节数。通道的选择取决于样本方向。
internal.htx_blk.size(<idx>) : integer
返回与通道关联的HTX消息中位置<idx>处的块的大小,如果不存在则返回0。通道的选择取决于样本方向。<idx>可以是任何正整数或以下特殊值之一:* head:最先插入的块* tail:最新插入的块* first:进行(重新)分析的第一个块
internal.htx_blk.type(<idx>) : string
返回与通道关联的HTX消息中位置<idx>处的块的类型,如果不存在则返回“HTX_BLK_UNUSED”。通道的选择取决于样本方向。<idx>可以是任何正整数或以下特殊值之一:* head:最先插入的块* tail:最新插入的块* first:进行(重新)分析的第一个块
internal.htx_blk.data(<idx>) : binary
返回与通道关联的HTX消息中位置<idx>处的DATA块的值,如果不存在或不是DATA块,则返回空字符串。通道的选择取决于样本方向。<idx>可以是任何正整数或以下特殊值之一:* head:最先插入的块* tail:最新插入的块* first:进行(重新)分析的第一个块
internal.htx_blk.hdrname(<idx>) : string
返回与通道关联的HTX消息中位置<idx>处的HEADER块的头部名称,如果不存在或不是HEADER块,则返回空字符串。通道的选择取决于样本方向。<idx>可以是任何正整数或以下特殊值之一:* head:最先插入的块* tail:最新插入的块* first:进行(重新)分析的第一个块
internal.htx_blk.hdrval(<idx>) : string
返回与通道关联的HTX消息中位置<idx>处的HEADER块的头部值,如果不存在或不是HEADER块,则返回空字符串。通道的选择取决于样本方向。<idx>可以是任何正整数或以下特殊值之一:* head:最先插入的块* tail:最新插入的块* first:进行(重新)分析的第一个块
返回与通道关联的HTX消息中位置<idx>处的REQ_SL或RES_SL块的值,如果不存在或不是SL块,则返回空字符串。通道的选择取决于样本方向。<idx>可以是任何正整数或以下特殊值之一:* head:最先插入的块* tail:最新插入的块* first:进行(重新)分析的第一个块
如果当前流是HTX流,则返回true。这意味着通道缓冲区中的数据使用内部HTX表示法存储。否则,返回false。

7.4. 预定义的 ACL

一些预定义的 ACL 是硬编码的,因此不必在每个需要它们的前端中声明。它们的名称都使用大写字母,以避免混淆。下面提供了它们的等效项。
ACL 名称等同于Usage
FALSEalways_false从不匹配
HTTPreq.proto_http匹配如果协议是有效的HTTP
HTTP_1.0req.ver 1.0匹配如果HTTP请求版本是1.0
HTTP_1.1req.ver 1.1匹配如果HTTP请求版本是1.1
HTTP_2.0req.ver 2.0匹配如果HTTP请求版本是2.0
HTTP_3.0req.ver 3.0匹配如果HTTP请求版本是3.0
HTTP_CONTENTreq.hdr_val(content-length) gt 0匹配HTTP请求中存在的content-length
HTTP_URL_ABSurl_reg ^[^/:]*://匹配带协议方案的绝对 URL
HTTP_URL_SLASHurl_beg /匹配以 "/" 开头的 URL
HTTP_URL_STARurl *匹配等于 "*" 的 URL
LOCALHOSTsrc 127.0.0.1/8 ::1匹配来自本地主机的连接
METH_CONNECTmethod CONNECT匹配 HTTP CONNECT 方法
METH_DELETEmethod DELETE匹配HTTP DELETE方法
METH_GETmethod GET HEAD匹配 HTTP GET 或 HEAD 方法
METH_HEADmethod HEAD匹配 HTTP HEAD 方法
METH_OPTIONSmethod OPTIONS匹配 HTTP OPTIONS 方法
METH_POSTmethod POST匹配 HTTP POST 方法
METH_PUTmethod PUT匹配HTTP PUT方法
METH_TRACEmethod TRACE匹配 HTTP TRACE 方法
RDP_COOKIEreq.rdp_cookie_cnt gt 0匹配请求缓冲区中是否存在RDP cookie
REQ_CONTENTreq.len gt 0匹配请求缓冲区中的数据
TRUEalways_true总是匹配
WAIT_ENDwait_end等待内容分析结束
HAProxy's strong points certainly lies is its precise logs. It probably provides the finest level of information available for such a product, which is very important for troubleshooting complex environments. Standard information provided in logs include client ports, TCP/HTTP state timers, precise stream state at termination and precise termination cause, information about decisions to direct traffic to a server, and of course the ability to capture arbitrary headers. In order to improve administrators reactivity, it offers a great transparency about encountered problems, both internal and external, and it is possible to send logs to different sources at the same time with different level filters : - global process-level logs (system errors, start/stop, etc..) - per-instance system and internal errors (lack of resource, bugs, ...) - per-instance external troubles (servers up/down, max connections) - per-instance activity (client connections), either at the establishment or at the termination. - per-request control of log-level, e.g. http-request set-log-level silent if sensitive_request The ability to distribute different levels of logs to different log servers allow several production teams to interact and to fix their problems as soon as possible. For example, the system team might monitor system-wide errors, while the application team might be monitoring the up/down for their servers in real time, and the security team might analyze the activity logs with one hour delay.

8.1. 日志级别

TCP and HTTP connections can be logged with information such as the date, time, source IP address, destination address, connection duration, response times, HTTP request, HTTP return code, number of bytes transmitted, conditions in which the stream ended, and even exchanged cookies values. For example track a particular user's problems. All messages may be sent to up to two syslog servers. Check the "log" keyword in section 4.2 for more information about log facilities.

8.2. 日志格式

HAProxy supports 5 log formats. Several fields are common between these formats and will be detailed in the following sections. A few of them may vary slightly with the configuration, due to indicators specific to certain options. The supported formats are as follows : - the default format, which is very basic and very rarely used. It only provides very basic information about the incoming connection at the moment it is accepted : source IP:port, destination IP:port, and frontend-name. This mode will eventually disappear so it will not be described to great extents. - the TCP format, which is more advanced. This format is enabled when "option tcplog" is set on the frontend. HAProxy will then usually wait for the connection to terminate before logging. This format provides much richer information, such as timers, connection counts, queue size, etc... This format is recommended for pure TCP proxies. - the HTTP format, which is the most advanced for HTTP proxying. This format is enabled when "option httplog" is set on the frontend. It provides the same information as the TCP format with some HTTP-specific fields such as the request, the status code, and captures of headers and cookies. This format is recommended for HTTP proxies. - the CLF HTTP format, which is equivalent to the HTTP format, but with the fields arranged in the same order as the CLF format. In this mode, all timers, captures, flags, etc... appear one per field after the end of the common fields, in the same order they appear in the standard HTTP format. - the custom log format, allows you to make your own log line. Next sections will go deeper into details for each of these formats. Format specification will be performed on a "field" basis. Unless stated otherwise, a field is a portion of text delimited by any number of spaces. Since syslog servers are susceptible of inserting fields at the beginning of a line, it is always assumed that the first field is the one containing the process name and identifier. Note : Since log lines may be quite long, the log examples in sections below might be broken into multiple lines. The example log lines will be prefixed with 3 closing angle brackets ('>>>') and each time a log is broken into multiple lines, each non-final line will end with a backslash ('\') and the next line will start indented by two characters.

8.2.1. 默认日志格式

当没有设置特定选项时,使用此格式。日志在连接被接受后立即发出。需要注意的是,这目前是唯一记录请求目标 IP 和端口的格式。
Example
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)
Field Format Extract from the example above 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) Detailed fields description : - "source_ip" is the IP address of the client which initiated the connection. - "source_port" is the TCP port of the client which initiated the connection. - "destination_ip" is the IP address the client connected to. - "destination_port" is the TCP port the client connected to. - "frontend_name" is the name of the frontend (or listener) which received and processed the connection. - "mode is the mode the frontend is operating (TCP or HTTP). In case of a UNIX socket, the source and destination addresses are marked as "unix:" and the ports reflect the internal ID of the socket which accepted the connection (the same ID as reported in the stats). It is advised not to use this deprecated format for newer installations as it will eventually disappear.

8.2.2. TCP 日志格式

The TCP format is used when "option tcplog" is specified in the frontend, and is the recommended format for pure TCP proxies. It provides a lot of precious information for troubleshooting. Since this format includes timers and byte counts, the log is normally emitted at the end of the session. It can be emitted earlier if "option logasap" is specified, which makes sense in most environments with long sessions such as remote terminals. Sessions which match the "monitor" rules are never logged. It is also possible not to emit logs for sessions for which no data were exchanged between the client and the server, by specifying "option dontlognull" in the frontend. Successful connections will not be logged if "option dontlog-normal" is specified in the frontend. The TCP log format is internally declared as a custom log format based on the exact following string, which may also be used as a basis to extend the format if required. Additionally the HAPROXY_TCP_LOG_FMT variable can be used instead. Refer to section 8.2.6 "Custom log format" to see how to use this: # 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}" And the CLF log format is internally declared as a custom log format based on this exact string: # 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 \"\" \"\" " A few fields may slightly vary depending on some configuration options, those are marked with a star ('*') after the field name below.
Example
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
Field Format Extract from the example above 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 Detailed fields description : - "client_ip" is the IP address of the client which initiated the TCP connection to HAProxy. If the connection was accepted on a UNIX socket instead, the IP address would be replaced with the word "unix". Note that when the connection is accepted on a socket configured with "accept-proxy" and the PROXY protocol is correctly used, or with a "accept-netscaler-cip" and the NetScaler Client IP insertion protocol is correctly used, then the logs will reflect the forwarded connection's information. - "client_port" is the TCP port of the client which initiated the connection. If the connection was accepted on a UNIX socket instead, the port would be replaced with the ID of the accepting socket, which is also reported in the stats interface. - "accept_date" is the exact date when the connection was received by HAProxy (which might be very slightly different from the date observed on the network if there was some queuing in the system's backlog). This is usually the same date which may appear in any upstream firewall's log. When used in HTTP mode, the accept_date field will be reset to the first moment the connection is ready to receive a new request (end of previous response for HTTP/1, immediately after previous request for HTTP/2). - "frontend_name" is the name of the frontend (or listener) which received and processed the connection. - "backend_name" is the name of the backend (or listener) which was selected to manage the connection to the server. This will be the same as the frontend if no switching rule has been applied, which is common for TCP applications. - "server_name" is the name of the last server to which the connection was sent, which might differ from the first one if there were connection errors and a redispatch occurred. Note that this server belongs to the backend which processed the request. If the connection was aborted before reaching a server, "<NOSRV>" is indicated instead of a server name. - "Tw" is the total time in milliseconds spent waiting in the various queues. It can be "-1" if the connection was aborted before reaching the queue. See "Timers" below for more details. - "Tc" is the total time in milliseconds spent waiting for the connection to establish to the final server, including retries. It can be "-1" if the connection was aborted before a connection could be established. See "Timers" below for more details. - "Tt" is the total time in milliseconds elapsed between the accept and the last close. It covers all possible processing. There is one exception, if "option logasap" was specified, then the time counting stops at the moment the log is emitted. In this case, a '+' sign is prepended before the value, indicating that the final one will be larger. See "Timers" below for more details. - "bytes_read" is the total number of bytes transmitted from the server to the client when the log is emitted. If "option logasap" is specified, the this value will be prefixed with a '+' sign indicating that the final one may be larger. Please note that this value is a 64-bit counter, so log analysis tools must be able to handle it without overflowing. - "termination_state" is the condition the session was in when the session ended. This indicates the session state, which side caused the end of session to happen, and for what reason (timeout, error, ...). The normal flags should be "--", indicating the session was closed by either end with no data remaining in buffers. See below "Stream state at disconnection" for more details. - "actconn" is the total number of concurrent connections on the process when the session was logged. It is useful to detect when some per-process system limits have been reached. For instance, if actconn is close to 512 when multiple connection errors occur, chances are high that the system limits the process to use a maximum of 1024 file descriptors and that all of them are used. See section 3 "Global parameters" to find how to tune the system. - "feconn" is the total number of concurrent connections on the frontend when the session was logged. It is useful to estimate the amount of resource required to sustain high loads, and to detect when the frontend's "maxconn" has been reached. Most often when this value increases by huge jumps, it is because there is congestion on the backend servers, but sometimes it can be caused by a denial of service attack. - "beconn" is the total number of concurrent connections handled by the backend when the session was logged. It includes the total number of concurrent connections active on servers as well as the number of connections pending in queues. It is useful to estimate the amount of additional servers needed to support high loads for a given application. Most often when this value increases by huge jumps, it is because there is congestion on the backend servers, but sometimes it can be caused by a denial of service attack. - "srv_conn" is the total number of concurrent connections still active on the server when the session was logged. It can never exceed the server's configured "maxconn" parameter. If this value is very often close or equal to the server's "maxconn", it means that traffic regulation is involved a lot, meaning that either the server's maxconn value is too low, or that there aren't enough servers to process the load with an optimal response time. When only one of the server's "srv_conn" is high, it usually means that this server has some trouble causing the connections to take longer to be processed than on other servers. - "retries" is the number of connection retries experienced by this session when trying to connect to the server. It must normally be zero, unless a server is being stopped at the same moment the connection was attempted. Frequent retries generally indicate either a network problem between HAProxy and the server, or a misconfigured system backlog on the server preventing new connections from being queued. This field may optionally be prefixed with a '+' sign, indicating that the session has experienced a redispatch after the maximal retry count has been reached on the initial server. In this case, the server name appearing in the log is the one the connection was redispatched to, and not the first one, though both may sometimes be the same in case of hashing for instance. So as a general rule of thumb, when a '+' is present in front of the retry count, this count should not be attributed to the logged server. - "srv_queue" is the total number of requests which were processed before this one in the server queue. It is zero when the request has not gone through the server queue. It makes it possible to estimate the approximate server's response time by dividing the time spent in queue by the number of requests in the queue. It is worth noting that if a session experiences a redispatch and passes through two server queues, their positions will be cumulative. A request should not pass through both the server queue and the backend queue unless a redispatch occurs. - "backend_queue" is the total number of requests which were processed before this one in the backend's global queue. It is zero when the request has not gone through the global queue. It makes it possible to estimate the average queue length, which easily translates into a number of missing servers when divided by a server's "maxconn" parameter. It is worth noting that if a session experiences a redispatch, it may pass twice in the backend's queue, and then both positions will be cumulative. A request should not pass through both the server queue and the backend queue unless a redispatch occurs.

8.2.3. HTTP 日志格式

The HTTP format is the most complete and the best suited for HTTP proxies. It is enabled by when "option httplog" is specified in the frontend. It provides the same level of information as the TCP format with additional features which are specific to the HTTP protocol. Just like the TCP format, the log is usually emitted at the end of the stream, unless "option logasap" is specified, which generally only makes sense for download sites. A stream which matches the "monitor" rules will never logged. It is also possible not to log streams for which no data were sent by the client by specifying "option dontlognull" in the frontend. Successful connections will not be logged if "option dontlog-normal" is specified in the frontend. The HTTP log format is internally declared as a custom log format based on the exact following string, which may also be used as a basis to extend the format if required. Additionally the HAPROXY_HTTP_LOG_FMT variable can be used instead. Refer to section 8.2.6 "Custom log format" to see how to use this: # 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}" And the CLF log format is internally declared as a custom log format based on this exact string: # 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" Most fields are shared with the TCP log, some being different. A few fields may slightly vary depending on some configuration options. Those ones are marked with a star ('*') after the field name below.
Example
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"
Field Format Extract from the example above 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" Detailed fields description : - "client_ip" is the IP address of the client which initiated the TCP connection to HAProxy. If the connection was accepted on a UNIX socket instead, the IP address would be replaced with the word "unix". Note that when the connection is accepted on a socket configured with "accept-proxy" and the PROXY protocol is correctly used, or with a "accept-netscaler-cip" and the NetScaler Client IP insertion protocol is correctly used, then the logs will reflect the forwarded connection's information. - "client_port" is the TCP port of the client which initiated the connection. If the connection was accepted on a UNIX socket instead, the port would be replaced with the ID of the accepting socket, which is also reported in the stats interface. - "request_date" is the exact date when the first byte of the HTTP request was received by HAProxy (log field %tr). - "frontend_name" is the name of the frontend (or listener) which received and processed the connection. - "backend_name" is the name of the backend (or listener) which was selected to manage the connection to the server. This will be the same as the frontend if no switching rule has been applied. - "server_name" is the name of the last server to which the connection was sent, which might differ from the first one if there were connection errors and a redispatch occurred. Note that this server belongs to the backend which processed the request. If the request was aborted before reaching a server, "<NOSRV>" is indicated instead of a server name. If the request was intercepted by the stats subsystem, "<STATS>" is indicated instead. - "TR" is the total time in milliseconds spent waiting for a full HTTP request from the client (not counting body) after the first byte was received. It can be "-1" if the connection was aborted before a complete request could be received or a bad request was received. It should always be very small because a request generally fits in one single packet. Large times here generally indicate network issues between the client and HAProxy or requests being typed by hand. See section 8.4 "Timing Events" for more details. - "Tw" is the total time in milliseconds spent waiting in the various queues. It can be "-1" if the connection was aborted before reaching the queue. See section 8.4 "Timing Events" for more details. - "Tc" is the total time in milliseconds spent waiting for the connection to establish to the final server, including retries. It can be "-1" if the request was aborted before a connection could be established. See section 8.4 "Timing Events" for more details. - "Tr" is the total time in milliseconds spent waiting for the server to send a full HTTP response, not counting data. It can be "-1" if the request was aborted before a complete response could be received. It generally matches the server's processing time for the request, though it may be altered by the amount of data sent by the client to the server. Large times here on "GET" requests generally indicate an overloaded server. See section 8.4 "Timing Events" for more details. - "Ta" is the time the request remained active in HAProxy, which is the total time in milliseconds elapsed between the first byte of the request was received and the last byte of response was sent. It covers all possible processing except the handshake (see Th) and idle time (see Ti). There is one exception, if "option logasap" was specified, then the time counting stops at the moment the log is emitted. In this case, a '+' sign is prepended before the value, indicating that the final one will be larger. See section 8.4 "Timing Events" for more details. - "status_code" is the HTTP status code returned to the client. This status is generally set by the server, but it might also be set by HAProxy when the server cannot be reached or when its response is blocked by HAProxy. - "bytes_read" is the total number of bytes transmitted to the client when the log is emitted. This does include HTTP headers. If "option logasap" is specified, this value will be prefixed with a '+' sign indicating that the final one may be larger. Please note that this value is a 64-bit counter, so log analysis tools must be able to handle it without overflowing. - "captured_request_cookie" is an optional "name=value" entry indicating that the client had this cookie in the request. The cookie name and its maximum length are defined by the "capture cookie" statement in the frontend configuration. The field is a single dash ('-') when the option is not set. Only one cookie may be captured, it is generally used to track session ID exchanges between a client and a server to detect session crossing between clients due to application bugs. For more details, please consult the section "Capturing HTTP headers and cookies" below. - "captured_response_cookie" is an optional "name=value" entry indicating that the server has returned a cookie with its response. The cookie name and its maximum length are defined by the "capture cookie" statement in the frontend configuration. The field is a single dash ('-') when the option is not set. Only one cookie may be captured, it is generally used to track session ID exchanges between a client and a server to detect session crossing between clients due to application bugs. For more details, please consult the section "Capturing HTTP headers and cookies" below. - "termination_state" is the condition the stream was in when the stream ended. This indicates the stream state, which side caused the end of stream to happen, for what reason (timeout, error, ...), just like in TCP logs, and information about persistence operations on cookies in the last two characters. The normal flags should begin with "--", indicating the stream was closed by either end with no data remaining in buffers. See below "Stream state at disconnection" for more details. - "actconn" is the total number of concurrent connections on the process when the stream was logged. It is useful to detect when some per-process system limits have been reached. For instance, if actconn is close to 512 or 1024 when multiple connection errors occur, chances are high that the system limits the process to use a maximum of 1024 file descriptors and that all of them are used. See section 3 "Global parameters" to find how to tune the system. - "feconn" is the total number of concurrent connections on the frontend when the stream was logged. It is useful to estimate the amount of resource required to sustain high loads, and to detect when the frontend's "maxconn" has been reached. Most often when this value increases by huge jumps, it is because there is congestion on the backend servers, but sometimes it can be caused by a denial of service attack. - "beconn" is the total number of concurrent connections handled by the backend when the stream was logged. It includes the total number of concurrent connections active on servers as well as the number of connections pending in queues. It is useful to estimate the amount of additional servers needed to support high loads for a given application. Most often when this value increases by huge jumps, it is because there is congestion on the backend servers, but sometimes it can be caused by a denial of service attack. - "srv_conn" is the total number of concurrent connections still active on the server when the stream was logged. It can never exceed the server's configured "maxconn" parameter. If this value is very often close or equal to the server's "maxconn", it means that traffic regulation is involved a lot, meaning that either the server's maxconn value is too low, or that there aren't enough servers to process the load with an optimal response time. When only one of the server's "srv_conn" is high, it usually means that this server has some trouble causing the requests to take longer to be processed than on other servers. - "retries" is the number of connection retries experienced by this stream when trying to connect to the server. It must normally be zero, unless a server is being stopped at the same moment the connection was attempted. Frequent retries generally indicate either a network problem between HAProxy and the server, or a misconfigured system backlog on the server preventing new connections from being queued. This field may optionally be prefixed with a '+' sign, indicating that the stream has experienced a redispatch after the maximal retry count has been reached on the initial server. In this case, the server name appearing in the log is the one the connection was redispatched to, and not the first one, though both may sometimes be the same in case of hashing for instance. So as a general rule of thumb, when a '+' is present in front of the retry count, this count should not be attributed to the logged server. - "srv_queue" is the total number of requests which were processed before this one in the server queue. It is zero when the request has not gone through the server queue. It makes it possible to estimate the approximate server's response time by dividing the time spent in queue by the number of requests in the queue. It is worth noting that if a stream experiences a redispatch and passes through two server queues, their positions will be cumulative. A request should not pass through both the server queue and the backend queue unless a redispatch occurs. - "backend_queue" is the total number of requests which were processed before this one in the backend's global queue. It is zero when the request has not gone through the global queue. It makes it possible to estimate the average queue length, which easily translates into a number of missing servers when divided by a server's "maxconn" parameter. It is worth noting that if a stream experiences a redispatch, it may pass twice in the backend's queue, and then both positions will be cumulative. A request should not pass through both the server queue and the backend queue unless a redispatch occurs. - "captured_request_headers" is a list of headers captured in the request due to the presence of the "capture request header" statement in the frontend. Multiple headers can be captured, they will be delimited by a vertical bar ('|'). When no capture is enabled, the braces do not appear, causing a shift of remaining fields. It is important to note that this field may contain spaces, and that using it requires a smarter log parser than when it's not used. Please consult the section "Capturing HTTP headers and cookies" below for more details. - "captured_response_headers" is a list of headers captured in the response due to the presence of the "capture response header" statement in the frontend. Multiple headers can be captured, they will be delimited by a vertical bar ('|'). When no capture is enabled, the braces do not appear, causing a shift of remaining fields. It is important to note that this field may contain spaces, and that using it requires a smarter log parser than when it's not used. Please consult the section "Capturing HTTP headers and cookies" below for more details. - "http_request" is the complete HTTP request line, including the method, request and HTTP version string. Non-printable characters are encoded (see below the section "Non-printable characters"). This is always the last field, and it is always delimited by quotes and is the only one which can contain quotes. If new fields are added to the log format, they will be added before this field. This field might be truncated if the request is huge and does not fit in the standard syslog buffer (1024 characters). This is the reason why this field must always remain the last one.

8.2.4. HTTPS日志格式

The HTTPS format is the best suited for HTTP over SSL connections. It is an extension of the HTTP format (see section 8.2.3) to which SSL related information are added. It is enabled when "option httpslog" is specified in the frontend. Just like the TCP and HTTP formats, the log is usually emitted at the end of the stream, unless "option logasap" is specified. A stream which matches the "monitor" rules will never logged. It is also possible not to log streams for which no data were sent by the client by specifying "option dontlognull" in the frontend. Successful connections will not be logged if "option dontlog-normal" is specified in the frontend. The HTTPS log format is internally declared as a custom log format based on the exact following string, which may also be used as a basis to extend the format if required. Additionally the HAPROXY_HTTPS_LOG_FMT variable can be used instead. Refer to section 8.2.6 "Custom log format" to see how to use this: # 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}" This format is basically the HTTP one (see section 8.2.3) with new fields appended to it. The new fields (lines 17 and 18) will be detailed here. For the HTTP ones, refer to the HTTP section.
Example
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
Field Format Extract from the example above 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 Detailed fields description : - "fc_err" is the status of the connection on the frontend's side. It corresponds to the "fc_err" sample fetch. See the "fc_err" and "fc_err_str" sample fetch functions for more information. - "ssl_fc_err" is the last error of the first SSL error stack that was raised on the connection from the frontend's perspective. It might be used to detect SSL handshake errors for instance. It will be 0 if everything went well. See the "ssl_fc_err" sample fetch's description for more information. - "ssl_c_err" is the status of the client's certificate verification process. The handshake might be successful while having a non-null verification error code if it is an ignored one. See the "ssl_c_err" sample fetch and the "crt-ignore-err" option. - "ssl_c_ca_err" is the status of the client's certificate chain verification process. The handshake might be successful while having a non-null verification error code if it is an ignored one. See the "ssl_c_ca_err" sample fetch and the "ca-ignore-err" option. - "ssl_fc_is_resumed" is true if the incoming TLS session was resumed with the stateful cache or a stateless ticket. Don't forgot that a TLS session can be shared by multiple requests. - "ssl_fc_sni" is the SNI (Server Name Indication) presented by the client to select the certificate to be used. It usually matches the host name for the first request of a connection. An absence of this field may indicate that the SNI was not sent by the client, and will lead haproxy to use the default certificate, or to reject the connection in case of strict-sni. - "ssl_version" is the SSL version of the frontend. - "ssl_ciphers" is the SSL cipher used for the connection.

8.2.5. 错误日志格式

When an incoming connection fails due to an SSL handshake or an invalid PROXY protocol header, HAProxy will log the event using a shorter, fixed line format, unless a dedicated error log format is defined through an "error-log-format" line. By default, logs are emitted at the LOG_INFO level, unless the option "log-separate-errors" is set in the backend, in which case the LOG_ERR level will be used. Connections on which no data are exchanged (e.g. probes) are not logged if the "dontlognull" option is set. The default format looks like this : >>> 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 These fields just provide minimal information to help debugging connection failures. By using the "error-log-format" directive, the legacy log format described above will not be used anymore, and all error log lines will follow the defined format. An example of reasonably complete error-log-format follows, it will report the source address and port, the connection accept() date, the frontend name, the number of active connections on the process and on thit frontend, haproxy's internal error identifier on the front connection, the hexadecimal OpenSSL error number (that can be copy-pasted to "openssl errstr" for full decoding), the client certificate extraction status (0 indicates no error), the client certificate validation status using the CA (0 indicates no error), a boolean indicating if the connection is new or was resumed, the optional server name indication (SNI) provided by the client, the SSL version name and the SSL ciphers used on the connection, if any. Note that backend connection errors are never reported here since in order for a backend connection to fail, it would have passed through a successful stream, hence will be available as regular traffic log (see option httplog or 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. 自定义日志格式

Historically, custom log formats were only used to produce logs. But their convenience when used to produce a string by assembling multiple complex expressions has got them adopted by many directives which used to take only a string in argument and which may now also take an such a Custom log format definition. Such arguments, which are commonly designated by "<fmt>" in this document, are defined exactly the same way as the argument to the "log-format" directive, described here. When it comes to logs and when the default log formats are not sufficient, it is possible to define new ones in very fine details. As creating a log-format from scratch is not always a trivial task, it is strongly recommended to first have a look at the existing formats ("option tcplog", "option httplog", "option httpslog"), pick the one looking the closest to the expectation, copy its "log-format" equivalent string and adjust it. A Custom log format definition is a single argument from a configuration perspective. This means that it may not contain blanks (spaces or tabs), unless these blanks are escaped using the backslash character ('\'), or the whole definition is enclosed between quotes (which is the recommended way to use them). The use of unquoted format strings is not recommended anymore as history has shown that it was very error prone since a single missing backslash character could result in silent truncation of the format. Such configurations are still commonly encountered due to the massive adoption of log formats after version 1.5-dev9, 3 years before quotes were usable, but it is recommended to convert them to quoted strings and to drop the backslashes now. A log format definition is made of any number of log format items separated by text and spaces. A log format item starts with character '%'. In order to emit a verbatim '%', it must be preceded by another '%' resulting in '%%'. Logformat items may either be aliases or sample expressions: If an item is named between square brackets ('[' .. ']') then it is used as a sample expression rule (see section 7.3). This it useful to add some less common information such as the client's SSL certificate's DN, or to log the key that would be used to store an entry into a stick table. It is also commonly used with non-log actions (header manipulation, variables etc). Else if the item is named using an alpha-numerical name, it is an alias. (Refer to the table below for the list of available aliases) Items can take arguments using braces ('{}'), and multiple arguments are separated by commas within the braces. Flags may be added or removed by prefixing them with a '+' or '-' sign (see below for the list of available flags). Special alias "%o" may be used to propagate its flags to all other logformat items on the same format string. This is particularly handy with quoted ("Q") and escaped ("E") string formats. Special alias "%OG" may be used to retrieve the log origin (when / where the log was generated) in a human readable format. It is particularly useful with "option logasap" because some log variables or sample fetches could report incomplete values or behave differently depending on when / where the logformat expression was evaluated. Possible values are: - "sess_error": log was generated during session error handling - "sess_killed": log was generated during session abortion (killed embryonic session) - "txn_accept": log was generated right after frontend conn was accepted - "txn_request": log was generated after client request was received - "txn_connect": log was generated after backend connection establishment - "txn_response": log was generated during server response handling - "txn_close": log was generated at the final txn step, before closing - "unspec": unknown or not specified "%OG" is only relevant in logging context. Items can optionally be named using ('()'). The name must be provided right after '%' (before arguments). It will automatically be used as key name when encoding flag such as "json" or "cbor" is set. When no encoding flag is specified (default), item name will be ignored. It is also possible to force the item's output to a given type by appending ':type' after the name, like this: %(itemname:itemtype)aliasname or %(itemname:itemtype)[expr] where itemtype may be 'str', 'sint' or 'bool'. Specifying the type is only relevant when an encoding method is used. Also, it is supported to provide an empty name to force the output type on an anonymous item: %(:itemtype), ie: when encoding is not set globally, see flags definitions below for more information. Due to the original goal of custom log formats to be used for logging only, there is a special case made of non-printable and unsafe characters (those outside ASCII codes 32 to 126 plus a few other ones) depending where they are used. Section 8.6 describes what's done exactly for logs in order to make sure one will not send unsafe codes that alter the readability of the output in a terminal. When used to form header fields, health checks or payload responses, the rules are less strict and only characters forbidden in HTTP header fields are replaced by their hexadecimal encoding preceded by character '%'. This is normally not a problem, but it might affect the output when the character was expected to be reproduced verbatim (e.g. when building an error page or a full response payload, where line feeds could appear as "%0A"). Note: in configuration directives "log-format", "log-format-sd" and "unique-id-format", spaces are considered as delimiters and are merged. Note: when using the RFC5424 syslog message format, the characters '"', '\' and ']' inside PARAM-VALUE should be escaped with '\' as prefix (see https://tools.ietf.org/html/rfc5424#section-6.3.3 for more details). In such cases, the use of the flag "E" should be considered. Supported item flags are (may be enabled/disabled from item's arguments): * Q: quote a string * X: hexadecimal representation (IPs, Ports, %Ts, %rt, %pid) * E: escape characters '"', '\' and ']' in a string with '\' as prefix (intended purpose is for the RFC5424 structured-data log formats) * bin: try to preserve binary data, this can be useful with sample expressions that output binary data in order to preserve the original data. Be careful however, because it can obviously generate non- printable chars, including NULL-byte, which most syslog endpoints don't expect. Thus it is mainly intended for use with set-var-fmt, rings and binary-capable log endpoints. This option can only be set globally (with %o), it will be ignored if set on an individual item's options. * json: automatically encode value in JSON format (when set globally, only named logformat items are considered) Incomplete numerical values (e.g.: '%B' when logasap is used), which are normally prefixed with '+' without encoding, will be encoded as-is. Also, '+E' option will be ignored. * cbor: automatically encode value in CBOR format (when set globally, only named logformat items are considered) By default, cbor encoded data is represented in HEX form so that it remains printable on stdout an can be used with usual syslog endpoints. As with json encoding, incomplete numerical values will be encoded as-is and '+E' option will be ignored. When combined with '+bin' option, it will directly generate raw binary CBOR payload. Be careful, because it will obviously generate non-printable chars, thus it is mainly intended for use with set-var-fmt, rings and binary-capable log endpoints.
示例
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)]"
Please refer to the table below for currently defined aliases : +---+------+------------------------------------------------------+---------+ | 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 | | | | %[req.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. 禁用外部测试的日志记录

It is quite common to have some monitoring tools perform health checks on HAProxy. Sometimes it will be a layer 3 load-balancer such as LVS or any commercial load-balancer, and sometimes it will simply be a more complete monitoring system such as Nagios. When the tests are very frequent, users often ask how to disable logging for those checks. There are three possibilities : - if connections come from everywhere and are just TCP probes, it is often desired to simply disable logging of connections without data exchange, by setting "option dontlognull" in the frontend. It also disables logging of port scans, which may or may not be desired. - it is possible to use the "http-request set-log-level silent" action using a variety of conditions (source networks, paths, user-agents, etc). - if the tests are performed on a known URI, use "monitor-uri" to declare this URI as dedicated to monitoring. Any host sending this request will only get the result of a health-check, and the request will not be logged.

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. 日志配置文件

While some directives such as "log-format", "log-format-sd", "error-log-format" or "log-tag" make it possible to configure log formatting globally or at the proxy level, it may be relevant to configure such settings as close as possible to the log endpoints, that is, per "log" directive. This is where "log-profile" section comes into play: "log-profile" may be defined anywhere in the configuration. This section accepts a set of different keywords that are used to describe how the logs emitted for a given `log` directive should be built. From a "log" directive, one can choose to use a specific log-profile by its name. The same profile may be used from multiple "log" directives.
创建一个新的日志配置文件,标识为 <name>
log-tag <string>
覆盖全局或按代理设置的 syslog 日志标记,使用“log-tag”指令。
on <step> [drop] [format <fmt>] [sd <sd_fmt>]
在 <step> 日志步骤中,覆盖通常用于构建日志行的 log-format 字符串。<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,除非声明了更精确的步骤覆盖。有关相关的附加 <step> 值,请参阅 "do-log" 操作。此设置仅与在"log" 指令用于使用 "log-format" 指令有意义的上下文(例如:http 和 tcp 代理)时相关。否则它将被忽略。
Example
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",则以 "Tw/Tc/Tt" 的形式报告 3 个控制点;在 HTTP 模式下,则以 "TR/Tw/Tc/Tr/Ta" 的形式报告 5 个控制点。此外,还提供了另外三个测量值:"Th"、"Ti" 和 "Tq"。HTTP 模式下的计时事件:第一个请求 第二个请求 |<-------------------------------->|<-------------- ... t tr t tr ... ---|----|----|----|----|----|----|----|----|-- : Th Ti TR Tw Tc Tr Td : Ti ... :<---- Tq ---->: : :<-------------- Tt -------------->: :<-- -----Tu--------------->: :<--------- Ta --------->: TCP 模式下的计时事件:TCP 会话 |<----------------->| t t ---|----|----|----|----|--- | Th Tw Tc Td | |<------ Tt ------->| - Th:接受 tcp 连接并执行低级协议握手的总时间。目前,这些协议是 proxy-protocol 和 SSL。这在整个连接的生命周期中可能只发生一次。此处时间过长可能表明客户端仅预先建立了连接但未进行通信,或者它正在经历网络问题,使其无法在合理的时间内完成握手(例如 MTU 问题),或者 SSL 握手计算成本很高。请注意,此时间仅在第一个请求之前报告,因此将其平均到所有请求以计算摊销值是安全的。第二个和后续请求在此处始终报告零。此计时器在 log-format 别名中命名为 %Th,在 sample fetch 中命名为 fc.timer.handshake。 - Ti:HTTP 请求之前的空闲时间(仅限 HTTP 模式)。此计时器从握手结束到 HTTP 请求的第一个字节之间开始计数。在 keep-alive 模式下处理第二个请求时,它在传输上一个响应结束后开始计数。当使用 HTTP/2 等多路复用协议时,它在上一个请求之后立即开始计数。一些浏览器会预先建立与服务器的连接,以减少未来请求的延迟,并保持挂起直到需要时。此延迟将报告为空闲时间。值为 -1 表示连接上未收到任何内容。此计时器在 log-format 别名中命名为 %Ti,在 sample fetch 中命名为 req.timer.idle。 - TR:获取客户端请求的总时间(仅限 HTTP 模式)。这是从接收到第一个字节到代理接收到标记 HTTP 标头结束的空行之间经过的时间。值 "-1" 表示从未见过标头结束。当客户端过早关闭或超时时会发生这种情况。此时间通常很短,因为大多数请求都适合单个数据包。时间过长可能表明在测试期间手动输入了请求。此计时器在 log-format 别名中命名为 %TR,在 sample fetch 中命名为 req.timer.hdr。 - Tq:从接受日期或自上一个响应的最后一个字节发出以来获取客户端请求的总时间(仅限 HTTP 模式)。它严格等于 Th + Ti + TR,除非其中任何一个为 -1,在这种情况下它也返回 -1。在 HTTP keep-alive 和浏览器预连接功能出现之前,此计时器非常有用。建议现在放弃它而改用 TR,因为空闲时间会给报告增加很多干扰。此计时器在 log-format 别名中命名为 %Tq,在 sample fetch 中命名为 req.timer.tq。 - Tw:在队列中等待连接槽的总时间。它包括后端队列以及服务器队列,并取决于队列大小以及服务器完成先前请求所需的时间。值 "-1" 表示请求在到达队列之前被终止,这通常发生在无效或被拒绝的请求中。此计时器在 log-format 别名中命名为 %Tw,在 sample fetch 中命名为 req.timer.queue。 - Tc:建立与服务器的 TCP 连接的总时间。这是从代理发送连接请求到服务器确认它之间经过的时间,或者在 TCP SYN 数据包和返回的匹配 SYN/ACK 数据包之间经过的时间。值 "-1" 表示连接从未建立。此计时器在 log-format 别名中命名为 %Tc,在 sample fetch 中命名为 bc.timer.connect。 - Tr:服务器响应时间(仅限 HTTP 模式)。这是从与服务器建立 TCP 连接到服务器发送其完整响应标头之间经过的时间。它纯粹显示其请求处理时间,不包括由于数据传输引起的网络开销。值得注意的是,当客户端有数据要发送给服务器时(例如在 POST 请求期间),时间已经开始运行,这可能会扭曲表观响应时间。因此,对于来自不受信任网络后面的客户端发起的 POST 请求,通常不宜过分信任此字段。此处的值 "-1" 表示从未见过最后一个响应标头(空行),最可能是因为服务器在设法处理请求之前超时,或者因为服务器返回了无效响应。此计时器在 log-format 别名中命名为 %Tr,在 sample fetch 中命名为 res.timer.hdr。 - Td:这是响应有效负载的传输总时间,直到发送给客户端的最后一个字节。在 HTTP 中,它在最后一个响应标头之后开始(在 Tr 之后)。发送的数据不保证被客户端接收,它们可能会卡在内核或网络中。此计时器在 log-format 别名中命名为 %Td,在 sample fetch 中命名为 res.timer.data。 - Ta:HTTP 请求的总活动时间,从代理接收到请求标头的第一个字节到发送响应正文的最后一个字节之间。例外情况是指定了 "logasap" 选项。在这种情况下,它仅等于 (TR+Tw+Tc+Tr),并带有 '+' 符号前缀。从该字段中,我们可以通过减去其他有效计时器来推断 "Td"(数据传输时间):Td = Ta - (TR + Tw + Tc + Tr) 具有 "-1" 值的计时器必须从该等式中排除。请注意,"Ta" 永远不能为负数。此计时器在 log-format 别名中命名为 %Ta,在 sample fetch 中命名为 txn.timer.total。 - Tt:总流持续时间,从代理接受它到两端关闭之间。例外情况是指定了 "logasap" 选项。在这种情况下,它仅等于 (Th+Ti+TR+Tw+Tc+Tr),并带有 '+' 符号前缀。从该字段中,我们可以通过减去其他有效计时器来推断 "Td"(数据传输时间):Td = Tt - (Th + Ti + TR + Tw + Tc + Tr) 具有 "-1" 值的计时器必须从该等式中排除。在 TCP 模式下,"Ti"、"Tq" 和 "Tr" 也必须排除。请注意,"Tt" 永远不能为负数,并且对于 HTTP,Tt 简单地等于 (Th+Ti+Ta)。此计时器在 log-format 别名中命名为 %Tt,在 sample fetch 中命名为 fc.timer.total。 - Tu:从客户端看,从代理接受它到两端关闭之间的总估计时间,不包括空闲时间。这对于大致测量用户所见的端到端时间很有用,而不会受到请求之间 keep-alive 时间的空闲时间干扰。此计时器仅是用户所见时间的估计值,因为它假设两个方向的网络延迟相同。例外情况是指定了 "logasap" 选项。在这种情况下,它仅等于 (Th+TR+Tw+Tc+Tr),并带有 '+' 符号前缀。此计时器在 log-format 别名中命名为 %Tu,在 sample fetch 中命名为 txn.timer.user。这些计时器提供了有关故障原因的宝贵指示。由于 TCP 协议定义了 3、6、12... 秒的重传延迟,因此我们确切地知道接近 3s 倍数的计时器几乎总是与由于网络问题(线路、协商、拥塞)造成的数据包丢失有关。此外,如果 "Ta" 或 "Tt" 接近配置中指定的超时值,则通常意味着流已因超时而中止。最常见的情况: - 如果 "Th" 或 "Ti" 接近 3000,则客户端和代理之间可能丢失了一个数据包。这在本地网络上非常罕见,但当客户端位于遥远的远程网络并发送大请求时可能会发生。有时,此处会出现比平时更大的值,而没有任何网络原因。有时,在攻击期间或资源匮乏结束后,HAProxy 可能会在几毫秒内接受数千个连接。接受这些连接所花费的时间不可避免地会略微延迟其他连接的处理,并且可能会在一次接受数千个新连接后测量到几十毫秒的请求时间。使用其中一种 keep-alive 模式可能会显示更大的空闲时间,因为 "Ti" 测量的是等待额外请求所花费的时间。 - 如果 "Tc" 接近 3000,则在服务器连接阶段,服务器和代理之间可能丢失了一个数据包。此值应始终非常低,例如本地网络上的 1 毫秒,远程网络上的几十毫秒以内。 - 如果 "Tr" 几乎总是低于 3000,除了少数几个似乎平均值被 3000 支配的值之外,代理和服务器之间可能丢失了一些数据包。 - 如果 "Ta" 很大,即使字节数很小,通常是因为 HAProxy 在隧道模式下运行,并且客户端和服务器都同意 keep-alive 连接模式时,客户端和服务器都不决定关闭连接。为了解决此问题,需要指定其中一个 HTTP 选项来在前端或后端操纵 keep-alive 或 close 选项。当连接调节与服务器上的 "maxconn" 选项一起使用时,具有最小的 'Ta' 或 'Tt' 非常重要,因为在释放另一个连接之前,不会向服务器发送新连接。其他值得注意的 HTTP 日志案例('xx' 表示要忽略的任何值):TR/Tw/Tc/Tr/+Ta "option logasap" 存在于前端,并且日志是在数据阶段之前发出的。所有计时器都有效,除了 "Ta" 比实际短。 -1/xx/xx/xx/Ta 客户端无法及时发送完整的请求或过早中止。检查流终止标志,然后检查 "timeout http-request" 和 "timeout client" 设置。TR/-1/xx/xx/Ta 无法处理请求,可能是因为服务器已停止运行,或者请求无效或被 ACL 规则禁止。检查流终止标志。TR/Tw/-1/xx/Ta 连接无法在服务器上建立。要么它主动拒绝了它,要么它在 Ta-(TR+Tw) 毫秒后超时。检查流终止标志,然后检查 "timeout connect" 设置。请注意,tarpit 操作可能会返回看起来相似的模式,其中 "Tw" 等于客户端连接保持打开的时间。TR/Tw/Tc/-1/Ta 服务器已接受连接,但未及时返回完整响应,或者它在 Ta-(TR+Tw+Tc) 毫秒后意外关闭连接。检查流终止标志,然后检查 "timeout server" 设置。

8.5. 断开连接时的流状态

TCP 和 HTTP 日志在 "termination_state" 字段中提供流终止指示器,就在活动连接数之前。在 TCP 模式下是 2 个字符长,在 HTTP 模式下扩展到 4 个字符,每个字符都有特殊的含义: - 在第一个字符上,报告导致流终止的第一个事件的代码:C:TCP 会话被客户端意外中止。S:TCP 会话被服务器意外中止,或者服务器明确拒绝了它。P:流或会话被代理过早中止,因为强制执行连接限制,因为匹配了 DENY 过滤器,因为安全检查检测并阻止了服务器响应中可能导致信息泄露的危险错误(例如可缓存 cookie)。L:流由 HAProxy 本地处理。R:代理上的资源已耗尽(内存、套接字、源端口等)。通常,这发生在连接阶段,系统日志应包含精确错误的副本。如果发生这种情况,必须将其视为非常严重的异常,应尽快通过任何方式修复。I:代理在自检期间识别出内部错误。这绝对不应该发生,建议您报告包含此内容的任何日志,因为这几乎肯定是一个错误。在这种事件发生后,最好预防性地重新启动进程,以防它是由内存损坏引起的。D:流被 HAProxy 终止,因为服务器被检测为关闭,并且配置为在关闭时终止所有连接。U:流被 HAProxy 在此备份服务器上终止,因为检测到活动服务器已启动,并且配置为在启动时终止所有备份连接。K:流被操作 HAProxy 的管理员主动终止。c:客户端超时在等待客户端发送或接收数据时过期。s:服务器端超时在等待服务器发送或接收数据时过期。-:正常流完成,客户端和服务器都关闭,缓冲区中没有剩余数据。 - 在第二个字符上,关闭时的 TCP 或 HTTP 流状态:R:代理正在等待来自客户端的完整、有效请求(仅限 HTTP 模式)。未发送任何内容到任何服务器。Q:代理正在 QUEUE 中等待连接槽。这只有在服务器设置了 'maxconn' 参数时才会发生。在由于连接到即将关闭的服务器失败而导致重新调度之后,也可能发生在全局队列中。如果没有报告重新调度,则未尝试连接到任何服务器。C:代理正在等待服务器上的 CONNECTION 建立。服务器最多可能已注意到连接尝试。H:代理正在等待来自服务器的完整、有效响应HEADERS(仅限 HTTP)。D:流处于 DATA 阶段。L:代理仍在将 LAST 数据传输给客户端,而服务器已完成。这种情况非常罕见,因为它只会在客户端在接收最后一个数据包时死亡时发生。T:请求被 tarpitted。它与客户端保持打开状态,持续了整个 "timeout tarpit" 持续时间,或者直到客户端关闭,这两者都将在 "Tw" 计时器中报告。-:数据传输结束后的正常流完成。 - 第三个字符告诉是否由客户端提供了持久性 cookie(仅限 HTTP 模式):N:客户端没有提供 cookie。这通常是新访问者的情况,因此计算日志中此标志的出现次数通常表示网站访问频率的有效趋势。I:客户端提供了无效 cookie,与任何已知服务器都不匹配。这可能是由于最近的配置更改、HTTP/HTTPS 站点之间的 cookie 混合、有条件地忽略持久性或攻击引起的。D:客户端提供了指定 DOWN 服务器的 cookie,因此要么使用了 "option persist",客户端被发送到此服务器,要么未设置,客户端被重新调度到另一台服务器。V:客户端提供了 VALID cookie,并被发送到关联的服务器。E:客户端提供了有效 cookie,但其最后日期早于 "maxidle" cookie 参数允许的日期,因此 cookie 被视为 EXPIRED 并被忽略。请求将像没有 cookie 一样重新调度。O:客户端提供了有效 cookie,但其第一个日期早于 "maxlife" cookie 参数允许的日期,因此 cookie 被视为太 OLD 并被忽略。请求将像没有 cookie 一样重新调度。U:存在 cookie,但未用于选择服务器,因为使用了其他服务器选择机制(通常是 "use-server" 规则)。-:不适用(配置中未设置 cookie)。 - 最后一个字符报告对服务器返回的持久性 cookie 执行了哪些操作(仅限 HTTP 模式):N:服务器没有提供 cookie,也没有插入 cookie。I:服务器没有提供 cookie,代理 INSERTED 了一个。请注意,在 "cookie insert" 模式下,如果服务器提供了 cookie,它仍将被覆盖并在此处报告为 "I"。U:代理 UPDATED 了客户端提供的 cookie 中的最后日期。这只有在 "insert" 模式下使用 "maxidle" 时才会发生。每当活动日期与 cookie 中指示的日期不同时,就会发生这种情况。如果发生任何其他更改(例如重新调度),则 cookie 将被标记为插入。P:服务器 PROVIDED 了一个 cookie,并按原样传输。R:服务器提供的 cookie 被代理 REWRITTEN,这发生在 "cookie rewrite" 或 "cookie prefix" 模式下。D:服务器提供的 cookie 被代理 DELETED。-:不适用(配置中未设置 cookie)。 前两个标志的组合提供了有关流或会话终止时发生的情况以及终止原因的大量信息。它有助于检测服务器饱和、网络问题、本地系统资源匮乏、攻击等。下面列出了最常见的终止标志组合。它们按字母顺序排序,小写集紧跟在大写集之后,以便于查找和理解。标志 原因 -- 正常终止。CC 客户端在连接到服务器之前中止。当 HAProxy 尝试连接到最近关闭(或未检查)的服务器,并且 HAProxy 正在等待服务器响应或 "timeout connect" 过期时,可能会发生这种情况。CD 客户端在数据传输期间意外中止。这可能是由浏览器崩溃、客户端和 HAProxy 之间的中间设备决定主动断开连接、客户端和 HAProxy 之间的网络路由问题,或者服务器和客户端之间的 keep-alive 流首先由客户端终止引起的。cD 客户端在等待客户端发送或接收数据时,"timeout client" 延迟的时间过期了。这通常是由客户端的网络故障引起的,或者客户端只是不干净地离开了网络。CH 客户端在等待服务器开始响应时中止。可能是服务器响应时间过长,或者客户端点击“停止”按钮过快。cH 在 POST 请求期间等待客户端数据时,"timeout client" 触发了。这有时是由于 PPPoE 网络的 TCP MSS 值过大,无法传输完整大小的数据包引起的。当客户端超时小于服务器超时且服务器响应时间过长时也可能发生。CQ 客户端在其流排队等待具有足够空闲槽的服务器接受时中止。可能是所有服务器都已饱和,或者分配的服务器响应时间过长。CR 客户端在发送完整 HTTP 请求之前中止。最可能是使用 telnet 客户端手动输入请求,并且过早中止。HTTP 状态码在此处可能是 400。有时这也可能是由 IDS 终止 HAProxy 和客户端之间的连接引起的。"option http-ignore-probes" 可用于忽略没有任何数据传输的连接。cR "timeout http-request" 触发,客户端未发送完整 HTTP 请求。这有时是由于客户端的 TCP MSS 值过大,无法传输完整大小的数据包,或者由于客户端手动发送请求且输入不够快,或者忘记在请求末尾输入空行引起的。HTTP 状态码在此处可能是 408。注意:最近,一些浏览器开始实现“预连接”功能,即推测性地连接到一些最近访问过的网站,以防用户想要访问它们。这导致与网站建立了许多连接,如果超时先触发,则以 408 Request Timeout 结束,如果浏览器决定先关闭它们,则以 400 Bad Request 结束。这些会污染日志并增加错误计数器。据报道,某些版本的某些浏览器甚至会显示错误代码。可以通过在前端添加 "option http-ignore-probes" 来解决这种不良行为的影响,从而完全忽略零数据传输的连接。但这肯定会隐藏遇到连接问题的用户的错误。LC 请求被 HAProxy 拦截并本地处理。请求未发送到服务器。这仅在由于服务器行上的 "redir" 参数而导致重定向时发生。LR 请求被 HAProxy 拦截并本地处理。请求未发送到服务器。通常意味着返回了重定向,处理了 HTTP return 语句或请求由小程序(stats、cache、Prometheus export、lua applet...)处理。LH 响应被 HAProxy 拦截并本地处理。通常意味着返回了重定向或处理了 HTTP return 语句。SC 服务器或 HAProxy 和它之间的设备明确拒绝了 TCP 连接(代理收到了 TCP RST 或 ICMP 消息作为回报)。在某些情况下,这也可能是网络堆栈告诉代理服务器无法访问(例如,没有路由,或者本地网络上没有 ARP 响应)。当这在 HTTP 模式下发生时,状态码在此处可能是 502 或 503。sC "timeout connect" 触发,连接到服务器未完成。当这在 HTTP 模式下发生时,状态码在此处可能是 503 或 504。SD 在数据传输期间,与服务器的连接因错误而中断。这通常意味着 HAProxy 在与服务器交换数据时收到了来自服务器的 RST 或来自中间设备的 ICMP 消息。这可能是由服务器崩溃或中间设备上的网络问题引起的。sD 在数据阶段,服务器在 "timeout server" 设置的时间内没有发送或确认任何数据。这通常是由服务器之前的 L4 设备(防火墙、负载均衡器等)上的超时时间过短,以及 HAProxy 上 keep-alive 会话在客户端和服务器之间首先过期引起的。SH 服务器在发送完整 HTTP 响应标头之前中止,或者在处理请求时崩溃。由于服务器在此刻中止非常罕见,因此最好检查其日志以控制它是否崩溃以及原因。记录的请求可能表明一小部分有缺陷的请求,证明应用程序中的错误。有时这也可能是由 IDS 终止 HAProxy 和服务器之间的连接引起的。sH "timeout server" 触发,服务器未返回其响应标头。这是最常见的异常,表明事务时间过长,可能是由服务器或数据库饱和引起的。立即的解决方法是增加 "timeout server" 设置,但重要的是要记住用户体验会受到这些长响应时间的影响。唯一的长期解决方案是修复应用程序。sQ 流在队列中花费的时间过长并已过期。请参阅 "timeout queue" 和 "timeout connect" 设置以找出如果这种情况经常发生如何修复。如果它经常在短时间内大量发生,则可能表明受影响服务器上存在一般问题,原因是 I/O 或数据库拥塞,或外部攻击引起的饱和。PC 代理拒绝建立与服务器的连接,因为在尝试连接时达到了进程的套接字限制。可以增加配置中的全局 "maxconn" 参数,使其不再发生。此状态非常罕见,只有在手动强制执行全局 "ulimit-n" 参数时才可能发生。PD 代理在服务器发出标头后阻止了请求或响应中格式不正确的 chunked 编码消息。在大多数情况下,这将表明服务器发给客户端的消息无效。HAProxy 支持高达 2GB - 1 (2147483647 字节) 的块大小。任何更大的大小都将被视为错误。PH 代理阻止了服务器的响应,因为它是无效的、不完整的、危险的(缓存控制)或匹配了安全过滤器。在任何情况下,都会向客户端发送 HTTP 502 错误。此错误的一个可能原因是 HTTP 标头名称中的语法无效,包含未经授权的字符。在服务器响应之前,代理也可能阻止了来自客户端的 chunked-encoding 请求,但这种情况很少见,因为语法无效。在这种情况下,会向客户端发送 HTTP 400 错误并在日志中报告。最后,它可能是由于响应上的 HTTP 标头重写失败造成的。在这种情况下,会发送 HTTP 500 错误(有关更多信息,请参阅 "tune.maxrewrite" 和 "http-response strict-mode")。PR 代理阻止了客户端的 HTTP 请求,要么是因为 HTTP 语法无效,在这种情况下它向客户端返回了 HTTP 400 错误,要么是因为匹配了拒绝过滤器,在这种情况下它向客户端返回了 HTTP 403 错误。它也可能是由于请求上的 HTTP 标头重写失败造成的。在这种情况下,会发送 HTTP 500 错误(有关更多信息,请参阅 "tune.maxrewrite" 和 "http-request strict-mode")。PT 代理阻止了客户端的请求,并在返回 500 服务器错误之前对连接进行了 tarpitted 处理。未向服务器发送任何内容。连接保持打开的时间与 "Tw" 计时器字段报告的时间一样长。RC 本地资源已耗尽(内存、套接字、源端口),导致无法建立与服务器的连接。错误日志将精确说明缺少什么。这种情况非常罕见,只能通过适当的系统调优来解决。最后两个标志的组合提供了有关客户端、服务器和 HAProxy 如何处理持久性的大量信息。这对于解决断开连接非常重要,尤其是在用户抱怨必须重新进行身份验证时。常见的标志是:-- 未启用持久性 cookie。NN 客户端未提供 cookie,响应中未插入 cookie。例如,这可能是在 "postonly" 设置的 GET 请求的 "insert" 模式下。II 客户端提供了指定无效服务器的 cookie,响应中插入了一个有效 cookie。这通常发生在配置中删除了 "server" 条目之后,因为当没有其他服务器知道其 cookie 值时,客户端可能会提供它。NI 客户端未提供 cookie,响应中插入了一个 cookie。这通常发生在 "insert" 模式下每个用户的第一个请求中,这使得它成为计算真实用户的简单方法。VN 客户端提供了 cookie,响应中未插入 cookie。这发生在客户端已经获得 cookie 的大多数响应中。VU 客户端提供了 cookie,其上次访问日期不是完全最新的,因此在响应中提供了更新后的 cookie。如果没有日期,或者有日期但未设置 "maxidle" 参数,以便可以将 cookie 切换到无限时间,也可能发生这种情况。EI 客户端提供了 cookie,其上次访问日期对于 "maxidle" 参数来说太旧了,因此 cookie 被忽略并在响应中插入了一个新 cookie。OI 客户端提供了 cookie,其首次访问日期对于 "maxlife" 参数来说太旧了,因此 cookie 被忽略并在响应中插入了一个新 cookie。DI cookie 指定的服务器已关闭,选择了新服务器并在响应中发出了新 cookie。VI cookie 指定的服务器未标记为死亡,但无法访问。发生了重新调度并选择了另一个服务器,然后在响应中进行了通告。

8.6. 不可打印字符

为了在查阅日志时避免给日志分析工具或终端带来麻烦,不可打印的字符不会按原样发送到日志文件中,而是会转换为其 ASCII 码的两位十六进制表示,并以字符“#”为前缀。唯一可以不经转义直接记录的字符范围是 32 到 126(含)。显然,转义字符“#”本身也会被编码以避免任何歧义(“#23”)。字符“"”也是如此,它会变成“#22”,以及在记录头时,“{”、“|”和“}”也是如此。请注意,空格字符(' ')在头中不被编码,这可能会给依赖空格计数来定位字段的工具带来问题。一个包含空格的典型头是“User-Agent”。最后,据观察,一些 syslog 守护进程(如 syslog-ng)会用反斜杠('\')来转义引号('\"')。可以安全地执行反向操作,因为日志中其他任何地方都不会出现引号。

8.7. 捕获 HTTP cookie

Cookie 捕获简化了对完整用户会话的跟踪。这可以通过在前端使用“capture cookie”语句来实现。更多详情请参考第 4.2 节。只能捕获一个 cookie,并且同一个 cookie 将同时在请求(“Cookie:”头)和响应(“Set-Cookie:”头)中进行检查。相应的值将报告在 HTTP 日志的“captured_request_cookie”和“captured_response_cookie”位置(请参阅关于 HTTP 日志格式的第 8.2.3 节)。当任一 cookie 未被看到时,一个破折号('-')将取代该值。这样,就很容易检测到用户何时切换到新会话,例如,因为服务器将为其重新分配一个新的 cookie。也可以检测服务器是否意外地向客户端设置了错误的 cookie,从而导致会话交叉。
示例
# 捕获第一个名称以“ASPSESSION”开头的 cookie capture cookie ASPSESSION len 32 # 捕获第一个名称正好是“vgnvisitor”的 cookie capture cookie vgnvisitor= len 32
可以使用 "http-request" 和 "http-response" 规则执行更高级的捕获,将 cookie 分配给范围为 "txn" 的变量。然后可以使用 "req.cook" 和 "res.cook" 样本获取函数(请参阅 第 7.3.6 节)从请求或响应中提取 cookie 值,并使用 "set-var" 或 "set-var-fmt" 操作(请参阅 第 4.3 节)将其分配给变量。然后,自定义 log-format 将允许在需要的位置呈现这些变量(请参阅 第 8.2.6 节)。

8.8. 捕获 HTTP 标头(旧版)

标头捕获对于跟踪上层代理设置的唯一请求标识符、虚拟主机名、用户代理、POST 内容长度、引荐来源等非常有用。在响应中,可以搜索有关响应长度、服务器如何要求缓存行为或重定向期间的对象位置的信息。有两种执行标头捕获的方法。现代方法涉及将要捕获的标头中的变量设置为捕获,或者从 "req.hdr_names"、"req.hdrs"、"res.hdr_names"、"res.hdrs" 返回的复合样本中设置(有关所有可能性,请参阅 第 7.3.6 节)。可以使用 "set-var" 和 "set-var-fmt" 操作从 "http-request" 和 "http-response" 规则集(请参阅 第 4.3 节)将其分配给范围为 "txn" 的变量,然后可以从自定义日志格式(请参阅 第 8.2.6 节)中引用这些变量。这是捕获 HTTP 标头的推荐方法。还有一种传统方法,它早于 http-request 规则和变量,不涉及调整日志格式,并且长期以来一直用于日志记录和作为在整个 HTTP 事务中传达请求信息的人工方式,使用较旧的 "capture" 规则集。这是本节中描述的内容。传统标头捕获使用前端中的 "capture request header" 和 "capture response header" 语句执行。请查阅 第 4.2 节 中的定义以获取更多详细信息。可以同时包含请求标头和响应标头。不存在的标头记录为空字符串,如果一个标头出现多次,则只记录其最后一次出现。请求标头按声明的顺序分组在花括号 '{' 和 '}' 中,并用竖线 '|' 分隔,不带任何空格。响应标头遵循相同的表示形式,但在请求标头块后面的空格之后显示。这些块显示在日志中的 HTTP 请求之前。作为特例,可以在 TCP 前端中指定 HTTP 标头捕获。目的是启用标头日志记录,如果请求随后切换到此 HTTP 后端,则将在 HTTP 后端中解析这些标头。
Example
    # 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. 日志示例

这些是真实世界的日志示例,并附有解释。其中一些是手动编造的。为了更好的阅读,系统日志部分已被删除。它们唯一的目的是解释如何破译它们。 >>> haproxy[674]: 127.0.0.1:33318 [15/Oct/2003:08:31:57.130] px-http \ px-http/srv1 6559/0/7/147/6723 200 243 - - ---- 5/3/3/1/0 0/0 \ "HEAD / HTTP/1.0" => 通过 'telnet' 手动输入的长请求 (6.5s)。服务器在 147 毫秒内回复,会话正常结束 ('----') >>> haproxy[674]: 127.0.0.1:33319 [15/Oct/2003:08:31:57.149] px-http \ px-http/srv1 6559/1230/7/147/6870 200 243 - - ---- 324/239/239/99/0 \ 0/9 "HEAD / HTTP/1.0" => 同样,但请求在全球队列中排队在 9 个其他请求之后,并在那里等待了 1230 毫秒。 >>> 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" => 长数据传输请求。指定了 "logasap" 选项,因此日志是在传输数据之前生成的。服务器在 14 毫秒内回复,向客户端发送了 243 字节的标头,从接受到第一个数据字节的总时间为 30 毫秒。 >>> haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17.925] px-http \ px-http/srv1 9/0/7/14/30 502 243 - - PH-- 3/2/2/0/0 0/0 \ "GET /cgi-bin/bug.cgi? HTTP/1.0" => 代理阻止了服务器响应,要么是因为 "http-response deny" 规则,要么是因为响应格式不正确且不符合 HTTP 规范,要么是因为它阻止了可能被缓存的敏感信息。在这种情况下,响应被替换为 "502 bad gateway"。标志 ("PH--") 告诉我们是 HAProxy 决定返回 502,而不是服务器。 >>> haproxy[18113]: 127.0.0.1:34548 [15/Oct/2003:15:18:55.798] px-http \ px-http/<NOSRV> -1/-1/-1/-1/8490 -1 0 - - CR-- 2/2/2/0/0 0/0 "" => 客户端从未完成其请求并在 8.5 秒后自行中止 ("C---"),而代理正在等待请求标头 ("-R--")。未向任何服务器发送任何内容。 >>> haproxy[18113]: 127.0.0.1:34549 [15/Oct/2003:15:19:06.103] px-http \ px-http/<NOSRV> -1/-1/-1/-1/50001 408 0 - - cR-- 2/2/2/0/0 0/0 "" => 客户端从未完成其请求,该请求在 50 秒后因超时 ("c---") 而中止,而代理正在等待请求标头 ("-R--")。未向任何服务器发送任何内容,但代理可以向客户端发送 408 返回代码。 >>> haproxy[18989]: 127.0.0.1:34550 [15/Oct/2003:15:24:28.312] px-tcp \ px-tcp/srv1 0/0/5007 0 cD 0/0/0/0/0 0/0 => 此日志是使用 "option tcplog" 生成的。客户端在 5 秒后超时 ("c----")。 >>> haproxy[18989]: 10.0.0.1:34552 [15/Oct/2003:15:26:31.462] px-http \ px-http/srv1 3183/-1/-1/-1/11215 503 0 - - SC-- 205/202/202/115/3 \ 0/0 "HEAD / HTTP/1.0" => 请求花费了 3 秒才完成(可能存在网络问题),并且在 4 次尝试 2 秒后连接到服务器失败 ('SC--')(配置为 'retries 3'),并且没有重新调度(否则我们会看到 "/+3")。向客户端返回了状态码 503。此服务器上有 115 个连接,此代理上有 202 个连接,全局进程上有 205 个连接。服务器可能因为连接太多而拒绝了连接。
此处列出了官方支持的过滤器及其接受的参数。根据编译选项,其中一些过滤器可能不可用。可用过滤器的列表将在 haproxy -vv 中报告。

9.1. 跟踪

filter trace [name <name>] [random-forwarding] [hexdump]
参数
<name> 是一个任意名称,将在消息中报告。如果未提供名称,则使用“TRACE”。 <quiet> 会抑制跟踪消息。 <random-forwarding> 启用对解析数据的随机转发。默认情况下,此过滤器转发所有先前解析的数据。使用此参数,它仅转发解析数据的随机量。 <hexdump> 将所有转发的数据转储到服务器和客户端。
此过滤器可用作开发新过滤器的基础。它定义了所有回调,并在标准错误流(stderr)上打印一条包含所有回调有用信息的消息。调试其他过滤器活动或 HAProxy 本身活动时可能很有用。使用 <;random-parsing> 和/或 <;random-forwarding> 参数是通过在处理中增加延迟来测试解析客户端和服务器之间交换数据的过滤器行为的好方法。

9.2. HTTP 压缩

HTTP compression has been moved to a filter in HAProxy 1.7. "compression" keyword must still be used to enable and configure HTTP compression. And when no other filter is used, it is enough. When used with the cache or the fcgi-app enabled, it is also enough. In this case, the compression is always done after the response is stored in the cache. But it is mandatory to explicitly use a filter line to enable HTTP compression when at least one filter other than the cache or the fcgi-app is used for the same listener/frontend/backend. This is important to know the filters evaluation order.

9.3. Stream Processing Offload Engine (SPOE)

filter spoe [engine <name>] config <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 使用内部二进制协议流处理卸载协议 (SPOP) 与外部组件通信。当在流上使用 SPOE 时,会生成一个专用流来处理与外部组件的通信。主流是此“SPOE”流的父流。这意味着可以从“SPOE”流中检索主流的变量。有关变量的详细信息,请参阅 第 2.8 节。有关 SPOE 配置和 SPOP 规范的所有信息,请参阅“doc/SPOE.txt”。

9.4. Cache

参数
<name> is name of the cache section this filter will use.
The cache uses a filter to store cacheable responses. The HTTP rules "cache-store" and "cache-use" must be used to define how and when to use a cache. By default the corresponding filter is implicitly defined. And when no other filters than fcgi-app or compression are used, it is enough. In such case, the compression filter is always evaluated after the cache filter. But it is mandatory to explicitly use a filter line to use a cache when at least one filter other than the compression or the fcgi-app is used for the same listener/frontend/backend. This is important to know the filters evaluation order.

9.5. Fcgi-app

参数
<name> is name of the fcgi-app section this filter will use.
FastCGI 应用程序使用过滤器来评估请求路径上的所有自定义参数,并处理响应路径上的标头。<name> 必须引用现有的 fcgi-app 部分。应使用指令 "use-fcgi-app" 来定义要使用的应用程序。默认情况下,相应的过滤器是隐式定义的。当只使用缓存或压缩之外的过滤器时,这就足够了。但是,当同一后端使用了压缩或缓存之外的至少一个过滤器时,必须明确使用过滤器行到 fcgi-app。这对于了解过滤器评估顺序很重要。

9.6. OpenTracing

OpenTracing过滤器增加了对 HAProxy 中分布式跟踪的原生支持。通过向 Datadog、Jaeger、Lightstep 和 Zipkin 追踪器等受支持的追踪器发送符合 OpenTracing 标准的请求来启用此功能。请注意:追踪器列表不分先后,按字母顺序排列。此功能仅在 HAProxy 使用 USE_OT=1 构建时启用。OpenTracing 过滤器的激活通过在 HAProxy 配置中显式指定来实现。如果未这样做,OpenTracing 过滤器将不会参与 HAProxy 的任何工作。
filter opentracing [id <id>] config <file>
参数
<id> 是 OpenTracing 过滤器的 ID,用于在配置文件中查找正确的范围。如果未指定过滤器 ID,则默认使用 'ot-filter'。如果在配置文件中未指定范围,则适用于所有已定义的 OpenTracing 过滤器。<file> 是 OpenTracing 配置文件路径。同一文件可以同时包含多个 OpenTracing 过滤器的配置。在这种情况下,我们不需要定义范围,因此相同的配置适用于所有过滤器,或者每个过滤器必须定义自己的范围。
有关过滤器的操作、配置和使用的更详细文档可以在 addons/ot 目录中找到。注意:OpenTracing 过滤器不应在新设计中使用,因为 OpenTracing 本身不再由其作者维护或支持。基于 OpenTelemetry 的替代过滤器正在开发中,预计在 HAProxy 3.2 左右准备就绪。因此,OpenTracing 将在 3.3 中弃用,并在 3.5 中移除。

9.7. 带宽限制

filter bwlim-in <name> default-limit <size> default-period <time> [min-size <sz>]
filter bwlim-out <name> default-limit <size> default-period <time> [min-size <sz>]
filter bwlim-in <name> limit <size> key <pattern> [table <table>] [min-size <sz>]
filter bwlim-out <name> limit <size> key <pattern> [table <table>] [min-size <sz>]
参数
<name> 是过滤器名称,将由 'set-bandwidth-limit' 操作用于引用特定的带宽限制过滤器。<size> 是在此期间可以转发的最大字节数。必须为 per-stream 和 shared 带宽限制过滤器指定该值。它遵循 HAProxy 大小格式,以字节表示。<pattern> 是 第 7.3 节 中所述的样本表达式规则。它描述了将分析、提取、组合和用于选择要更新计数器的表条目的元素。它必须仅为 shared 带宽限制过滤器指定。<table> 是一个可选表,用于代替默认表,默认表是在当前代理中声明的 stick-table。它只能为 shared 带宽限制过滤器指定。<time> 是用于评估带宽限制速率的默认时间段。它只能为 per-stream 带宽限制过滤器指定。它遵循 HAProxy 时间格式,以毫秒表示。<min-size> 是流一次转发的最小字节数(不包括可能更小的最后一个数据包)的可选值。可以为 per-stream 和 shared 带宽限制过滤器指定此值。它遵循 HAProxy 大小格式,以字节表示。
带宽限制过滤器应用于限制流级别的数据转发速度。通过扩展,此类过滤器限制了资源消耗的网络带宽。可以使用多个带宽限制过滤器。例如,可以定义按源地址的限制,以确保客户端永远不会消耗所有网络带宽,从而惩罚其他客户端,并定义按流的限制,以便能够公平地处理给定客户端的多个连接。这些过滤器的定义顺序很重要。如果流上启用了多个带宽过滤器,则将按照其定义顺序应用过滤。了解其他过滤器的定义顺序也很重要。例如,根据 HTTP 压缩过滤器是在带宽限制过滤器之前还是之后定义,限制将应用于压缩有效负载或不应用。缓存过滤器也是如此。有两种带宽限制过滤器。第一个强制执行默认限制并按流应用。第二个使用 stickiness 表来强制执行在共享同一表条目的所有流之间平均分配的限制。此外,对于给定的过滤器,根据使用的过滤器关键字,限制可以应用于传入数据(从客户端接收并转发到服务器)或传出数据(从服务器接收并发送到客户端)。要对传入数据应用限制,必须使用 "bwlim-in" 关键字。要对传出数据应用限制,必须使用 "bwlim-out" 关键字。在这两种情况下,带宽限制都应用于流级别转发的数据。带宽限制应用于流级别而不是连接级别。对于多路复用协议(H2、H3 和 FastCGI),同一连接的流可能具有不同的限制。对于 per-stream 带宽限制过滤器,必须定义默认时间段和限制。顾名思义,它们是用于设置流带宽限制速率的默认值。但是,对于此类过滤器,并且仅限于此类过滤器,可以使用 TCP/HTTP "set-bandwidth-limit" 操作启用过滤器时,可以使用样本表达式重新定义这些值。对于 shared 带宽限制过滤器,根据它是应用于传入数据还是传出数据,使用的 stickiness 表必须存储相应的字节速率信息。必须存储 "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)
HAProxy 能够向 Responder FastCGI 应用程序发送 HTTP 请求。此功能是在 HAProxy 2.1 中添加的。为此,必须将服务器配置为使用 FastCGI 协议(在服务器行上使用关键字 "proto fcgi"),并且必须配置 FastCGI 应用程序并由管理这些服务器的后端使用(在代理部分中使用关键字 "use-fcgi-app")。可以定义多个 FastCGI 应用程序,但后端一次只能使用一个。HAProxy 为 Responder 应用程序实现了 FastCGI 规范的所有功能。特别是它能够在简单连接上多路复用多个请求。

10.1. 设置

10.1.1. Fcgi-app 部分

fcgi-app <name>
声明一个名为 <name> 的 FastCGI 应用程序。要使其有效,至少必须定义 document root。
acl <aclname> <criterion> [flags] [operator] <value> ...
声明或完成访问列表。有关 ACL 用法的详细信息,请参见 第 4.2 节第 7 节中的“acl”关键字。为 FastCGI 应用程序定义的 ACL 是私有的。其他任何应用程序或代理都无法使用它们。同样,任何其他部分中定义的 ACL 也不适用于 FastCGI 应用程序。但是,预定义的 ACL 是可用的。
docroot <path> 定义远程主机上的文档根目录。<path> 将用于构建 FastCGI 参数 SCRIPT_FILENAME 和 PATH_TRANSLATED 的默认值。这是一个强制性设置。
index <script-name>
定义将在以斜杠 ("/") 结尾的 URI 之后附加的脚本名称,用于设置 FastCGI 参数 SCRIPT_NAME 的默认值。这是一个可选设置。
Example
index index.php
log-stderr <target> [len <length>] [format <format>] [sample <ranges>:<sample_size>] <facility> [<level> [<minlevel>]]
启用 FastCGI 应用程序报告的 STDERR 消息的日志记录。有关详细信息,请参阅 第 4.2 节 中的 "log" 关键字。这是一个可选设置。默认情况下,STDERR 消息被忽略。
pass-header <name> [ { if | unless } <condition> ]
指定将传递到 FastCGI 应用程序的请求头名称。它可能可选地跟一个基于 ACL 的条件,在这种情况下,只有当条件为真时才会对其进行评估。大多数请求头已经可供 FastCGI 应用程序使用,并带有“HTTP_”前缀。因此,此指令仅用于传递故意省略的头。当前,“Authorization”、“Proxy-Authorization”以及 hop-by-hop 头都会被省略。请注意,“Content-type”和“Content-length”头永远不会传递给 FastCGI 应用程序,因为它们已经被转换为参数。
path-info <regex>
定义一个正则表达式,用于从 URL 解码的路径中提取脚本名称和 path-info。因此,<regex> 可能有两个捕获:第一个捕获脚本名称,第二个捕获 path-info。第一个是强制性的,第二个是可选的。这样,就可以从路径中提取脚本名称而忽略 path-info。这是一个可选设置。如果未定义,则不会对路径进行匹配。并且 FastCGI 参数 PATH_INFO 和 PATH_TRANSLATED 不会被填充。出于安全原因,当定义此正则表达式时,URL 解码后的路径中禁止使用换行符和空字符。限制的原因是,由于 HAProxy 中正则表达式的执行方式存在限制,否则匹配将始终失败。因此,如果 URL 解码的路径中找到这两个字符中的任何一个,将向客户端返回错误。此处应用了最小惊讶原则。
Example
path-info ^(/.+\.php)(/.*)?$ # both script-name and path-info may be set path-info ^(/.+\.php) # the path-info is ignored
启用或禁用检索有关连接管理的变量。HAProxy 能够在连接建立时发送记录 FCGI_GET_VALUES 以检索以下变量的值:* FCGI_MAX_REQS 此应用程序将接受的最大并发请求数。* FCGI_MPXS_CONNS 如果此应用程序不进行连接多路复用,则为 "0",否则为 "1"。一些 FastCGI 应用程序不支持此功能。其他一些在发送响应后立即关闭连接。因此,默认情况下,此选项处于禁用状态。请注意,FastCGI 应用程序接受的最大并发请求数是一个连接变量。它仅限制每个连接的流数。如果必须限制应用程序的全局负载,则必须设置服务器参数 "maxconn" 和 "pool-max-conn"。此外,如果应用程序不支持连接多路复用,则最大并发请求数会自动设置为 1。
指示 FastCGI 应用程序在发送响应后是否保持连接打开。如果禁用,FastCGI 应用程序将在响应此请求后关闭连接。默认情况下,此选项处于启用状态。
定义此应用程序将接受的最大并发请求数。如果连接建立期间检索到 FCGI_MAX_REQS 变量,此选项可能会被覆盖。此外,如果应用程序不支持连接多路复用,则将忽略此选项。默认设置为 1。
启用或禁用连接多路复用的支持。如果连接建立期间检索到 FCGI_MPXS_CONNS 变量,此选项可能会被覆盖。默认情况下禁用。
set-param <name> <fmt> [ { if | unless } <condition> ]
设置一个应传递给此应用程序的 FastCGI 参数。其值由 <fmt> 定义,必须遵循自定义日志格式规则(请参见第 8.2.6 节“自定义日志格式”)。它可能可选地跟一个基于 ACL 的条件,在这种情况下,只有当条件为真时才会对其进行评估。使用此指令,可以覆盖默认 FastCGI 参数的值。如果将值评估为空字符串,则忽略该规则。这些指令按声明顺序进行评估。
Example
# 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. 代理部分

定义要用于后端的 FastCGI 应用程序。
参数
<name> 是要使用的 FastCGI 应用程序的名称。
此关键字仅适用于具有后端功能且至少有一个 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 ^/.+\.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 ^(/.+\.php)(/.*)?$

10.2. 默认参数

Responder FastCGI 应用程序与 CGI/1.1 程序具有相同的用途。在 CGI/1.1 规范 (RFC3875) 中,必须向脚本传递多个变量。因此 HAProxy 设置了它们以及 FastCGI 应用程序常用的一些其他变量。所有这些变量都可以被覆盖,但需要谨慎操作。 +-------------------+-----------------------------------------------------+ | AUTH_TYPE | 标识 HAProxy 用于身份验证用户的机制(如果有)。 | | | 具体来说,仅支持 BASIC 身份验证机制。 | | | | +-------------------+-----------------------------------------------------+ | CONTENT_LENGTH | 包含附加到请求的消息体的大小。这意味着只有 | | | 大小已知的请求才被视为有效并发送到应用 | | | 程序。 | | | | +-------------------+-----------------------------------------------------+ | CONTENT_TYPE | 包含附加到请求的消息体的类型。可能未设置。 | | | | +-------------------+-----------------------------------------------------+ | DOCUMENT_ROOT | 包含远程主机上的文档根目录,脚本应在该目 | | | 录下执行,具体取决于应用程序的配置。 | | | | +-------------------+-----------------------------------------------------+ | GATEWAY_INTERFACE | 包含 HAProxy 用于与 FastCGI 应用程序通信的 CGI | | | 方言。具体来说,它设置为 "CGI/1.1"。 | | | | +-------------------+-----------------------------------------------------+ | PATH_INFO | 包含 URI 路径层次结构中标识脚本本身的部 | | | 分之后的路径信息。要设置此变量,必须定义 | | | "path-info" 指令。 | | | | +-------------------+-----------------------------------------------------+ | PATH_TRANSLATED | 如果设置了 PATH_INFO,则它是其转换后的版本。 | | | 它是 DOCUMENT_ROOT 和 PATH_INFO 的串联。如果 | | | PATH_INFO 未设置,则此参数也不设置。 | | | | +-------------------+-----------------------------------------------------+ | QUERY_STRING | 包含请求的查询字符串。可能未设置。 | | | | +-------------------+-----------------------------------------------------+ | REMOTE_ADDR | 包含发送请求的客户端的网络地址。 | | | | +-------------------+-----------------------------------------------------+ | REMOTE_USER | 包含客户端作为用户身份验证一部分提供的用户 | | | 标识字符串。 | | | | +-------------------+-----------------------------------------------------+ | REQUEST_METHOD | 包含脚本应用于处理请求的方法。 | | | | +-------------------+-----------------------------------------------------+ | REQUEST_URI | 包含请求的 URI。 | | | | +-------------------+-----------------------------------------------------+ | SCRIPT_FILENAME | 包含脚本的绝对路径名。它是 DOCUMENT_ROOT | | | 和 SCRIPT_NAME 的串联。 | | | | +-------------------+-----------------------------------------------------+ | SCRIPT_NAME | 包含脚本的名称。如果定义了指令 "path-info", | | | 它是 URI 路径层次结构的第一部分,以脚本名 | | | 称结尾。否则,它是整个 URI 路径。 | | | | +-------------------+-----------------------------------------------------+ | SERVER_NAME | 包含客户端请求所指向的服务器主机名。如果定 | | | 义了 "Host" 标头,则是该标头的值。否则,是 | | | 客户端连接的目标地址。 | | | | +-------------------+-----------------------------------------------------+ | SERVER_PORT | 包含客户端连接的目标 TCP 端口,即客户端连 | | | 接到的端口。 | | | | +-------------------+-----------------------------------------------------+ | SERVER_PROTOCOL | 包含请求的协议。 | | | | +-------------------+-----------------------------------------------------+ | SERVER_SOFTWARE | 包含字符串 "HAProxy",后跟当前的 HAProxy 版本。 | | | | +-------------------+-----------------------------------------------------+ | HTTPS | 如果脚本是通过 HTTPS 协议查询的,则设置为 | | | 非空值 ("on")。 | | | | +-------------------+-----------------------------------------------------+

10.3. 限制

当前实现存在一些限制。第一个限制是关于某些请求标头对 FastCGI 应用程序隐藏的方式。这发生在后端侧的标头分析期间,在建立连接之前。在此阶段,HAProxy 知道后端正在使用 FastCGI 应用程序,但它不知道请求是否会路由到 FastCGI 服务器。为了隐藏请求标头,它只是将它们从 HTX 消息中删除。因此,如果请求最终路由到 HTTP 服务器,它永远不会看到这些标头。出于这个原因,不建议在同一后端中混合使用 FastCGI 服务器和 HTTP 服务器。类似地,"set-param" 和 "pass-header" 规则在请求标头分析期间进行评估。因此,即使请求最终转发到 HTTP 服务器,评估也会始终执行。关于 "set-param" 规则,当应用规则时,会将一个伪标头添加到 HTX 消息中。因此,与 HTTP 标头重写相同,如果缓冲区已满,它可能会失败。"set-param" 规则将与 "http-request" 规则竞争。最后,所有 FastCGI 参数和 HTTP 标头都发送到一个唯一的记录 FCGI_PARAM 中。此记录的编码必须一次完成,否则将返回处理错误。这意味着 FCGI_PARAM 记录一旦编码,就不能超过缓冲区的大小。但是,这里没有要遵守的保留空间。
HAProxy 中的 Stick-tables 是一种机制,它允许将一定数量的信息和指标与特定类型的键关联起来,并且在上次更新后的特定持续时间内保持有效。这可以看作是表中的多列行,其中行号由键值定义,所有列都代表不同的标准。Stick-tables 最初设计用于存储客户端-服务器粘性信息,以保持这些实体之间的持久会话。客户端将连接或发送请求,此客户端将通过鉴别器(源地址、cookie、URL 参数)进行识别,并且所选服务器将与此鉴别器一起存储在粘性表中,持续可配置的持续时间,以便来自同一客户端的后续访问可以自动路由到同一服务器,该客户端已在该服务器上创建了其应用程序会话。如今,stick-tables 可以存储的信息不仅仅是服务器编号,还可以存储与特定客户端相关的活动指标(请求计数/速率、连接计数/速率、字节计数/速率等),以及一些任意事件计数器("gpc" 代表 "General Purpose Counters")和一些用于标记具有特定特征的客户端的标签("gpt" 代表 "General Purpose Tag")。Stick-tables 可以通过用于客户端-服务器粘性的 "stick" 指令引用,通过 "track-sc" 规则引用,这些规则用于描述要在哪个表中跟踪哪个键以收集指标,以及通过许多 sample-fetch 函数和转换器引用,这些函数和转换器可以执行给定键的即时查找以检索特定指标或数据。一般原则是,对表(gpt/gpc/metrics)的更新以及对粘性信息的查找会刷新被访问的条目并推迟其过期时间,而来自 sample-fetch 函数和转换器的纯粹查找只提取数据而不推迟条目的过期时间。为了使该机制能够扩展并抵御 HAProxy 重新加载和故障转移,可以通过 第 11.2 节 中描述的 "Peers" 机制与称为 "peers" 的其他节点共享 stick-tables 更新。为了精细调整与 peers 的通信,还可以决定某些表只接收来自 peers 的信息,或者来自 peers 的更新应该转发到不同的表。最后,stick-tables 可以在代理部分(frontends、backends)中使用 "stick-table" 关键字声明,其中每个部分只能有一个,并且它们将获得该部分的名称,或者在 peers 部分中使用 "table" 关键字后跟表名声明,这允许在同一 "peers" 部分中声明多个 stick-tables。如果需要多个 stick-tables,通常推荐的解决方案是将其声明在 peers 部分(如果它们打算共享),或者创建额外的 backend 部分,每个部分中只有 "stick-table" 定义。

11.1. stick-table 声明

在代理部分(“frontend”、“backend”、“listen”)和“peers”部分中声明 stick-table 非常相似,不同之处在于 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 [length <len>] 使用 "type string" 声明的表将存储最多 <len> 个字符的子字符串。如果模式提取器提供的字符串大于 <len>,则在存储之前会将其截断。在匹配期间,表中字符串与提取的模式之间最多比较 <len> 个字符。如果未指定,字符串将自动限制为 32 个字符。增加长度可能会对内存使用产生不可忽略的影响。 * binary [length <len>] 使用 "type binary" 声明的表将存储 <len> 字节的二进制块。如果模式提取器提供的块大于 <len>,则在存储之前会将其截断。如果示例表达式提供的块短于 <len>,则会用 0 填充。如果未指定,块将自动限制为 32 个字节。增加长度可能会对内存使用产生不可忽略的影响。 - size <size> 这个必需的参数将表中可容纳的最大条目数设置为 <size>。此值直接影响内存使用。除了上面的键大小和可选存储的指标(如果存在字符串,再加上字符串的大小)之外,每个条目大约计算 50 字节。大小支持后缀 "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 表示我们不打算使用该表执行更新操作,而只计划使用该表从我们感兴趣的远程 peer 检索数据。事实上,使用此关键字可以检索本地值,例如 "conn_cur",默认情况下不会学习这些值,因为它们会与本地 peer 对表执行的本地更新发生冲突。此选项的使用仅与不涉及跟踪规则或对表执行更新操作的方法的表相关,或者更简单地说:仅用于检索信息的远程表。 - peers <peersect> 创建、更新或刷新的条目将发送到 <peersect> 部分中的 peers 以进行同步,并且从该部分中的 peers 学习的键也将插入或更新到表中。此外,在启动时,可能会尝试从旧进程实例中学习条目,该旧进程实例通过此部分指定为 "local peer"。 - srvkey <srvkey> 指定如何为粘性表目的识别每个服务器。有效值是 "name" 和 "addr"。如果给定 "name",则为服务器的 <name> 参数(可能由模板生成)。如果给定 "addr",则通过其当前网络地址(包括端口)来识别服务器。如果使用服务发现为具有 peered stick-tables 的服务器生成地址,并希望在 peers 之间始终使用相同的主机进行粘性令牌,则 "addr" 特别有用。 - store <data_type> 这用于在粘性表中存储附加信息。ACLs 可以使用它来控制与匹配粘性表的客户端活动相关的各种条件。对于此处指定的每个项目,每个条目的大小都会增加,以便可以容纳附加数据。一个条目可以存储多种数据类型。可以在 "store" 关键字后面指定多种数据类型,以逗号分隔列表的形式。或者,可以重复 "store" 关键字,后跟一种或多种数据类型。除了自动检测和启用的 "server_id" 类型之外,所有数据类型都必须明确声明才能存储。如果 ACL 引用了未存储的数据类型,则 ACL 将不匹配。某些数据类型需要一个参数,该参数必须紧跟在类型后面的括号中传递。有关支持的数据类型及其参数,请参见下文。 - write-to <wtable> 指定另一个粘性表的名称,peers 更新将写入其中,作为源表的补充。<wtable> 必须与正在定义的表类型相同,并且必须具有相同的键长度,并且源表本身不能用作目标表。每当通过 peer 在源表上接收到条目更新时,HAProxy 将尝试刷新相关的 <wtable> 条目。如果条目尚不存在,则会创建它,否则会更新其值及其计时器。请注意,只有不涉及算术运算的类型(例如 server_id、server_key 和 gpt)才会写入 <wtable>,以防止来自远程表的已处理值干扰对本地目标表执行的算术运算。(即:防止共享累积计数器无限增长)此选项的一个常见用途是能够在 peers 集群设置中使用粘性规则(用于服务器持久性),因为匹配键将从远程表学习。
可以通过“store”指令与条目关联的数据类型如下所示。重要的是要记住,当存储许多数据类型时,内存需求可能很大。实际上,将以下所有指标一次存储在每个条目中可能需要数百字节/条目,或者对于一百万个条目的表需要数百兆字节。因此,每种类型后括号中都提到了近似存储大小。
参数
- bytes_in_cnt [4 bytes] 这是客户端到服务器的字节计数。它是一个正 64 位整数,用于计算与此条目匹配的客户端接收到的累计字节数。标头包含在计数中。这可用于限制照片或视频服务器上上传功能的滥用。请注意,值是在数据进入 haproxy 时测量的,因此计数不受压缩影响。 - bytes_in_rate(<period>) [12 bytes] 这是客户端到服务器字节的速率计数器。它接受一个整数参数 <period>,以毫秒为单位指示测量平均值的周期长度。它报告该周期内的平均传入字节速率,单位为字节/周期。它可用于检测上传过多过快的用户。警告:对于大型上传,上传数据量可能会在终止时计算一次,从而导致平均传输速度出现峰值,而不是平滑的传输速度。虽然 "option contstats" 可以部分平滑,但这并不完美。建议使用 byte_in_cnt 以获得更好的公平性。 - bytes_out_cnt [4 bytes] 这是服务器到客户端的字节计数。它是一个正 64 位整数,用于计算发送到与此条目匹配的客户端的累计字节数。标头包含在计数中。这可用于限制机器人吸取整个站点的滥用。请注意,值是在数据进入 haproxy 时测量的,因此计数不受压缩影响。 - bytes_out_rate(<period>) [12 bytes] 这是服务器到客户端字节的速率计数器。它接受一个整数参数 <period>,以毫秒为单位指示测量平均值的周期长度。它报告该周期内的平均传出字节速率,单位为字节/周期。它可用于检测下载过多过快的用户。警告:对于大型传输,传输数据量可能会在终止时计算一次,从而导致平均传输速度出现峰值,而不是平滑的传输速度。虽然 "option contstats" 可以部分平滑,但这并不完美。建议使用 byte_out_cnt 以获得更好的公平性。 - conn_cnt [4 bytes] 这是连接计数。它是一个正 32 位整数,用于计算与此条目匹配的客户端接收到的连接的绝对数量。这并不意味着连接被接受,只是接收到了它们。 - conn_cur [4 bytes] 这是当前连接数。它是一个正 32 位整数,用于存储条目的并发连接数。当传入连接与条目匹配时,它会递增,当连接离开时,它会递减。这样就可以随时知道条目的确切并发连接数。默认情况下,此类型不会从其他 peers 学习,因为它会忽略本地计数,因此无法表示任何内容。但是,与 recv-only 结合使用时,它可以用于了解 peers 看到的并发连接数。 - conn_rate(<period>) [12 bytes] 这是连接频率计数器。它接受一个整数参数 <period>,以毫秒为单位指示测量平均值的周期长度。它报告该周期内的平均传入连接速率,单位为连接数/周期。结果是一个整数,可以使用 ACLs 进行匹配。连接是否被接受或拒绝对其测量没有影响。 - glitch_cnt [4 bytes] 这是前端故障计数。它是一个正 32 位整数,用于计算前端连接上报告的累计故障数。故障对应于来自客户端的异常或意外操作(协议方面),可能表明客户端有严重缺陷,或者可能是攻击者。因此,此计数器有助于决定在这种情况下如何处理它们。 - glitch_rate(<period>) [12 bytes] 这是故障的频率计数器。它接受一个整数参数 <period>,以毫秒为单位指示测量平均值的周期长度。它报告该周期内的平均前端故障速率。它可用于检测有缺陷的客户端或潜在攻击者,这些攻击者从协议角度执行不常见或意外的操作,前提是 HAProxy 将它们标记为如此。 - gpc(<nb>) [4 * <nb> bytes] 这是一个 <nb> 个通用计数器元素的数组。这是一个正 32 位整数数组,可用于计算任何内容。大多数情况下,它们将用作某些条目的增量计数器,例如记录达到限制并触发某些操作。此数组最多限制为 100 个元素:gpc0 到 gpc99,以确保 peer 更新消息的构建可以容纳在缓冲区中。用户应考虑到大量的计数器会增加数据大小和使用 peers 协议的流量负载,因为每次更新时都会推送所有数据/计数器。此 data_type 将排除在同一表上使用遗留 data_type 'gpc0' 和 'gpc1'。使用 'gpc' 数组 data_type,所有与 'gpc0' 和 'gpc1' 相关的 sample fetch 函数和操作将应用于此数组的前两个元素。 - gpc_rate(<nb>,<period>) [12 * <nb> bytes] 这是通用计数器在一段时间内的增量速率数组。这些元素是正 32 位整数,可用于任何用途。就像 <gpc> 一样,计算事件,但不是保留累积数字,而是保持计数器递增的速率。大多数情况下,它将用于测量某些事件发生的频率(例如,对特定 URL 的请求)。此数组最多限制为 100 个元素:gpt(100) 允许存储 gpc0 到 gpc99,以确保 peer 更新消息的构建可以容纳在缓冲区中。数组不能包含少于 1 个元素:如果只想存储计数器 gpc0,请使用 gpc(1)。用户应考虑到大量的计数器会增加数据大小和使用 peers 协议的流量负载,因为每次更新时都会推送所有数据/计数器。此 data_type 将排除在同一表上使用遗留 data_type 'gpc0_rate' 和 'gpc1_rate'。使用 'gpc_rate' 数组 data_type,所有与 'gpc0' 和 'gpc1' 相关的 fetches 和 actions 将应用于此数组的前两个元素。 - gpc0 [4 bytes] 这是第一个通用计数器。它是一个正 32 位整数,可用于任何用途。大多数情况下,它将用于在某些条目上放置特殊标签,例如记录检测到特定行为并必须为将来的匹配所知。 - gpc0_rate(<period>) [12 bytes] 这是第一个通用计数器在一段时间内的增量速率。它是一个正 32 位整数,可用于任何用途。就像 <gpc0> 一样,它计算事件,但不是保留累积数字,而是保持计数器递增的速率。大多数情况下,它将用于测量某些事件发生的频率(例如,对特定 URL 的请求)。 - gpc1 [4 bytes] 这是第二个通用计数器。它是一个正 32 位整数,可用于任何用途。大多数情况下,它将用于在某些条目上放置特殊标签,例如记录检测到特定行为并必须为将来的匹配所知。 - gpc1_rate(<period>) [12 bytes] 这是第二个通用计数器在一段时间内的增量速率。它是一个正 32 位整数,可用于任何用途。就像 <gpc1> 一样,它计算事件,但不是保留累积数字,而是保持计数器递增的速率。大多数情况下,它将用于测量某些事件发生的频率(例如,对特定 URL 的请求)。 - gpt(<nb>) [4 * <nb> bytes] 这是一个 <nb> 个通用标签元素的数组。这是一个正 32 位整数数组,可用于任何用途。大多数情况下,它们将用于在某些条目上放置特殊标签,例如记录检测到特定行为并必须为将来的匹配所知。此数组最多限制为 100 个元素:gpt(100) 允许存储 gpt0 到 gpt99,以确保 peer 更新消息的构建可以容纳在缓冲区中。数组不能包含少于 1 个元素:如果只想存储标签 gpt0,请使用 gpt(1)。用户应考虑到大量的计数器会增加数据大小和使用 peers 协议的流量负载,因为每次更新时都会推送所有数据/计数器。此 data_type 将排除在同一表上使用遗留 data_type 'gpt0'。使用 'gpt' 数组 data_type,所有与 'gpt0' 相关的 fetches 和 actions 将应用于此数组的第一个元素。 - gpt0 [4 bytes] 这是第一个通用标签。它是一个正 32 位整数,可用于任何用途。大多数情况下,它将用于在某些条目上放置特殊标签,例如记录检测到特定行为并必须为将来的匹配所知。 - http_req_cnt [4 bytes] 这是 HTTP 请求计数。它是一个正 32 位整数,用于计算与此条目匹配的客户端接收到的 HTTP 请求的绝对数量。请求是否有效无关紧要。请注意,当客户端使用 keep-alive 时,这与会话不同。 - http_req_rate(<period>) [12 bytes] 这是请求频率计数器。它接受一个整数参数 <period>,以毫秒为单位指示测量平均值的周期长度。它报告该周期内的平均 HTTP 请求速率,单位为请求数/周期。结果是一个整数,可以使用 ACLs 进行匹配。请求是否有效无关紧要。请注意,当客户端使用 keep-alive 时,这与会话不同。 - http_err_cnt [4 bytes] 这是 HTTP 请求错误计数。它是一个正 32 位整数,用于计算与此条目匹配的客户端引起的 HTTP 请求错误的绝对数量。错误包括无效和截断的请求,以及被拒绝或 tarpitted 的请求,以及身份验证失败。如果服务器响应 4xx,则该请求也被计为错误,因为它是客户端触发的错误(例如漏洞扫描)。 - http_err_rate(<period>) [12 bytes] 这是 HTTP 请求频率计数器。它接受一个整数参数 <period>,以毫秒为单位指示测量平均值的周期长度。它报告该周期内的平均 HTTP 请求错误率,单位为请求数/周期(有关计为错误的内容,请参阅上面的 http_err_cnt)。结果是一个整数,可以使用 ACLs 进行匹配。 - http_fail_cnt [4 bytes] 这是 HTTP 响应失败计数。它是一个正 32 位整数,用于计算与此条目匹配的服务器引起的 HTTP 响应失败的绝对数量。错误包括无效和截断的响应,以及除 501 或 505 之外的任何 5xx 响应。它旨在与路径或 URI 结合使用以检测服务故障。 - http_fail_rate(<period>) [12 bytes] 这是 HTTP 响应失败频率计数器。它接受一个整数参数 <period>,以毫秒为单位指示测量平均值的周期长度。它报告该周期内的平均 HTTP 响应失败率,单位为请求数/周期(有关计为失败的内容,请参阅上面的 http_fail_cnt)。结果是一个整数,可以使用 ACLs 进行匹配。 - server_id [4 bytes] 这是一个整数,包含分配请求的服务器的数字 ID。它由 "stick match"、"stick store" 和 "stick on" 规则使用。引用时会自动启用。重要的是要理解基于学习信息的粘性有一些限制,包括所有学习的关联在重新启动时都会丢失,除非 properly 配置 peers 以在重新启动时传输此类信息(推荐)。通常,它可以作为其他粘性机制的补充,但并不总是作为唯一的机制。 - sess_cnt [4 bytes] 这是会话计数。它是一个正 32 位整数,用于计算与此条目匹配的客户端接收到的会话的绝对数量。会话是层 4 规则 ("tcp-request connection") 接受的连接。 - sess_rate(<period>) [12 bytes] 这是会话频率计数器。它接受一个整数参数 <period>,以毫秒为单位指示测量平均值的周期长度。它报告该周期内的平均传入会话速率,单位为会话数/周期。结果是一个整数,可以使用 ACLs 进行匹配。
示例
# 在 5 分钟内跟踪多达 100 万个 IP 地址的计数器 # 并存储一个通用计数器和在 30 秒滑动窗口上计算的 # 平均连接速率。 stick-table type ip size 1m expire 5m store gpc0,conn_rate(30s)

11.2. Peers 声明

可以将粘性表中任何数据类型的条目在多个 HAProxy 实例之间通过 TCP 连接以多主方式传播。每个实例将其本地更新和插入推送到远程 peers。推送的值会覆盖远程值,而不会聚合。一个例外是数据类型 "conn_cur",默认情况下它永远不会从 peers 学习,因为它应该反映本地值。早期版本默认会同步它,这在主动-主动设置中会导致负值,并且在重新加载或主动-被动切换时值会不断增加,因为本地值会反映比本地存在的连接更多的连接。然而,在某些设置中,从 peers 学习此值可能很相关,例如当表是被动远程表,仅用于从中学习/监视数据而不依赖它进行面向写入的操作或更新时。为了实现这一点,可以在表声明中添加 "recv-only" 关键字。在任何情况下,"conn_cur" 信息始终被推送,以便监控系统可以监视它。中断的交换会自动检测并从最后一个已知点恢复。此外,在软重启期间,旧进程使用此类 TCP 连接连接到新进程,在新进程尝试连接到其他 peers 之前推送其所有条目。这确保了重新加载期间的复制非常快,即使对于大型表,通常也只需几分之一秒。请注意,服务器 ID 用于远程识别服务器,因此配置看起来相似或至少在所有参与者上的每个服务器上都强制使用相同的 ID非常重要。
peers <peersect>
创建名为 <peersect> 的新对等节点列表。它是一个独立的部分,由一个或多个粘性表引用。
bind [<address>]:port [param*]
bind /<path> [param*]
定义此“peers”部分中本地对等节点的绑定参数。在同一个“peers”部分中,此类行不支持与“peer”行同时使用。
禁用一个对等节点部分。它会禁用与此部分相关的侦听和任何同步。这用于禁用粘性表的同步,而无需注释掉所有 "peers" 引用。
default-bind [param*]
定义本地对等节点的绑定参数,但不包括其地址。
更改“peers”部分中服务器的默认选项。
参数
<param*> 是此服务器的参数列表。关键字 "default-server" 接受大量选项,并有一个完整的专门部分。在 peers 部分中,支持 "default-server" 行的传输参数。请参阅 第 5 节 了解更多详细信息,以及本节中下面的 "server" 关键字了解一些限制。
这将重新启用先前通过“disabled”关键字禁用的 peers 部分。
log <target> [len <length>] [format <format>] [sample <ranges>:<sample_size>] <facility> [<level> [<minlevel>]]
"peers" 部分支持与代理相同的 "log" 关键字,用于记录有关 "peers" 侦听器的信息。有关代理的 "log" 选项的更多详细信息,请参阅。
peer <peername> [<address>]:port [param*]
peer <peername> /<path> [param*]
在 peers 部分中定义一个 peer。如果 <peername> 设置为本地 peer 名称(默认为主机名,或使用 "-L" 命令行选项或 "localpeer" 全局配置设置强制设置),HAProxy 将在提供的地址上侦听传入的远程 peer 连接。否则,地址定义了要连接到哪里以加入远程 peer,并且 <peername> 用于协议级别以在服务器端识别和验证远程 peer。在软重启期间,旧实例使用本地 peer 地址连接到新实例并启动完整的复制(教学过程)。强烈建议在所有 peers 上具有完全相同的 peers 声明,并且仅依赖 "-L" 命令行参数或 "localpeer" 全局配置设置来更改本地 peer 名称。这使得在所有 peers 之间维护一致的配置文件更加容易。您可能希望在地址参数中引用一些环境变量,请参阅 第 2.3 节 有关环境变量的内容。注意:"peer" 关键字可以透明地替换为 "server" 关键字(请参阅下面的 "server" 关键字解释)。
server <peername> [<address>:<port>] [param*]
server <peername> [/<path>] [param*]
如前所述,"peer" 关键字可以替换为 "server" 关键字,并支持第 5.2 段中与传输设置相关的所有 "server" 参数。如果底层 peer 是本地的,则地址参数不得存在;必须在 "bind" 行上提供(请参阅此 "peers" 部分的 "bind" 关键字)。许多 "server" 参数与 "peers" 部分不相关。peers 本身不支持动态主机名解析和健康检查,因此不支持 "init_addr"、"resolvers"、"check"、"agent-check" 或 "track" 等参数。同样,没有负载均衡和粘性,因此 "weight" 或 "cookie" 等参数无效。
示例
 # 旧方法。 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 示例: peers mypeers bind 192.168.0.1:1024 ssl crt mycerts/pem default-server ssl verify none server haproxy1 #本地对等节点 server haproxy2 192.168.0.2:1024 server haproxy3 10.2.0.1:1024
shards <shards>
在某些配置中,人们希望将 stick-table 内容分发给一些 peers,而不是将所有 stick-table 内容发送给“peers”部分中声明的每个 peer。在这种情况下,“shards”指定参与此 stick-table 内容分发的 peer 数量。另请参阅“shard”服务器参数。
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" 部分有自己的粘性表命名空间,以避免在不同 "peers" 部分中相同的粘性表名称之间发生冲突。这在内部通过在粘性表的名称前加上 "peers" 部分名称,后跟 '/' 字符来处理。如果在配置文件的其他位置必须引用在 "peers" 部分中声明的此类粘性表,则必须使用带有前缀的粘性表名称,如下所示: peers mypeers peer A ... peer B ... table t1 ... frontend fe1 tcp-request content track-sc0 src table mypeers/t1 这也是必须通过 CLI 引用粘性表时使用的带有前缀的粘性表名称。关于 "peers" 协议,由于只有属于同一部分的 "peers" 才能相互通信,因此不需要进行这种区分。多个 "peers" 部分可以声明具有相同名称的粘性表。这是通过网络发送的粘性表名称的较短版本。只有一个 '/' 字符作为前缀,以避免在声明为 backends 的粘性表和在 "peers" 部分中声明的粘性表之间发生粘性表名称冲突,如下所示(在 weird 但受支持的配置中): 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 在这里,在 "mypeers" 部分中声明的 "t1" 表的全局名称为 "mypeers/t1"。声明为 backends 的 "t1" 表的全局名称为 "t1"。但在 peer 协议级别,前一个表名为 "/t1",后一个表仍名为 "t1"。
下面描述的部分不太常用,通常只支持几个参数。它们之间没有隐含的关系。它们都使用单个关键字启动。在 "global" 部分之前不允许使用它们中的任何一个。对其中一些的支持可能取决于构建选项(例如,任何与 SSL 相关的内容)。

12.1. 跟踪

为了调试目的,可以激活 HAProxy 子系统的跟踪。这将转储有关特定子系统的调试消息。这是一个非常有用的诊断工具。跟踪可以通过 CLI 动态配置。也可以在配置文件中预定义一些设置,在专门的“traces”部分中。有关跟踪的更多详细信息,请参阅管理指南。它仍然是复杂调试会话中使用的开发工具。它非常详细且有成本,因此请谨慎使用。而且由于它是开发工具,因此不保证此部分的向后兼容性。
开始一个新的跟踪部分。可以使用一个或多个“traces”部分。所有指令都按照声明顺序进行评估,最后的指令将覆盖之前的指令。
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>
创建名为 <listname> 的新用户列表。可以使用许多独立的用户列表来存储独立客户的身份验证和授权数据。
group <groupname> [users <user>,<user>,(...)]
将组 <groupname> 添加到当前用户列表。也可以通过使用逗号分隔的名称列表(前面有 "users" 关键字)将用户附加到此组。
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 系列算法)或降低函数的“成本”(如果算法支持)。顺便说一句,musl(例如 Alpine Linux)实现在计算哈希时已知比 glibc 对应项慢,因此您可能也想考虑这一方面。所有密码都被视为普通参数,因此受制于 第 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>
创建名为 <mailersect> 的新邮件发送器列表。它是一个独立的部分,由一个或多个代引用。
mailer <mailername> <ip>:<port>
在邮件发送器部分内定义一个邮件发送器。
示例
global # git 存储库中提供的 mailers.lua 文件 # 根据需要调整路径 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
定义可用于建立邮件/连接并发送到邮件服务器的时间。如果未定义,默认值为 10 秒。为了允许在初始 TCP 握手期间至少发送两个 SYN-ACK 数据包,建议将此值保持在 4 秒以上。
示例
mailers mymailers timeout mail 20s mailer smtp1 192.168.0.1:587

12.4. HTTP 错误

可以全局声明多个 HTTP 错误组,以便之后在任何代理部分中导入。同一个组可以在多个地方被引用,并且可以全部或部分导入。
创建一个名为 <name> 的新 http-errors 组。它是一个独立的部分,可以由一个或多个代理通过其名称引用。
errorfile <code> <file>
将文件内容与一个 HTTP 错误码关联起来。
参数
<code> 是 HTTP 状态码。目前,HAProxy 能够生成 200、400、401、403、404、405、407、408、410、425、429、500、501、502、503 和 504 状态码。<file> 指定一个包含完整 HTTP 响应的文件。建议遵循通用做法,在文件名后附加 ".http",这样人们就不会将响应与 HTML 错误页面混淆,并建议使用绝对路径,因为文件在执行任何 chroot 之前被读取。
请参考第 4 节中的“errorfile”关键字以获取详细信息。
示例
http-errors website-1 errorfile 400 /etc/haproxy/errorfiles/site1/400.http errorfile 404 /etc/haproxy/errorfiles/site1/404.http errorfile 408 /dev/null # 解决 Chrome 预连接错误 http-errors website-2 errorfile 400 /etc/haproxy/errorfiles/site2/400.http errorfile 404 /etc/haproxy/errorfiles/site2/404.http errorfile 408 /dev/null # 解决 Chrome 预连接错误

12.5. 环形缓冲区

可以全局声明环形缓冲区,用作日志服务器或跟踪的目标。
ring <ringname>
创建一个名为 <ringname> 的新环形缓冲区。
这通过 RAM 映射文件替换常规内存分配来存储环。这对于收集跟踪或日志进行事后分析非常有用,而无需将慢速客户端连接到 CLI。较新的内容将自动替换较旧的内容,以便始终提供最新的内容。写入环的内容将在进程停止后在该文件中可见(最常见的是它们很快就会被看到,但没有这样的保证,因为写入不是同步的)。当使用此选项时,总存储区域会因区域开头的 "struct ring" 的大小而减小,并且需要恢复区域内容。该文件将以启动用户的所有权创建,模式为 0600,大小由 "size" 指令配置。当解析指令时(因此即使在配置检查期间),任何现有的非空文件将首先重命名为带有额外后缀 ".bak" 的文件,并且任何先前存在的带有后缀 ".bak" 的文件将被删除。这确保了进程的即时重新加载或重启不会清除宝贵的调试信息,并会给管理员留出时间来发现这个新的 ".bak" 文件并在需要时存档它。因此,在崩溃之后,由 <path> 指定的文件将包含最新的信息,如果服务重新启动,"<path>.bak" 文件将包含该信息。这意味着所需的总存储容量将是环大小的两倍。轮换文件失败将被静默忽略,因此将文件放置在没有写入权限的目录中足以避免备份文件(如果不需要)。警告:使用此功能存在稳定性和安全隐患。首先,将环备份到慢速设备(例如物理硬盘驱动器)可能会在访问期间导致明显减速,并且如果太多线程竞争访问,甚至可能导致恐慌。其次,修改区域的外部进程可能导致 haproxy 进程崩溃或覆盖其自身的一些内存中的跟踪。第三,如果文件系统在环之前填满,写入环可能会导致进程崩溃。此环中存在的信息是结构化的,不能直接使用文本编辑器读取(尽管其中大部分看起来几乎可读)。此文件的输出仅供开发人员使用。
描述是环形缓冲区的可选描述字符串。它将出现在 CLI 中。默认情况下,<name> 会被重用以填充此字段。
format <format>
用于将事件存储到环形缓冲区的格式。
参数
<format> 是生成 syslog 消息时使用的日志格式。它可以是以下之一: iso 仅包含 ISO 日期,后跟文本的消息。省略 PID、进程名和系统名。这设计用于本地日志服务器。 local 类似于 rfc3164 syslog 消息格式,但主机名字段被剥离。这是默认值。注意:选项 "log-send-hostname" 将默认值切换为 rfc3164。 raw 仅包含文本的消息。省略级别、PID、日期、时间、进程名和系统名。这设计用于容器或开发期间,其中严重性仅取决于使用的文件描述符(stdout/stderr)。这是默认值。 rfc3164 RFC3164 syslog 消息格式。(https://tools.ietf.org/html/rfc3164) rfc5424 RFC5424 syslog 消息格式。(https://tools.ietf.org/html/rfc5424) short 仅包含尖括号中级别(例如 '<3>')的消息,后跟文本。省略 PID、进程名和系统名。这设计用于本地日志服务器。此格式与 systemd logger 消耗的格式兼容。 priority 仅包含尖括号中级别加上 syslog facility(例如 '<63>')的消息,后跟文本。省略 PID、日期、时间、进程名和系统名。这设计用于本地日志服务器。 timed 仅包含尖括号中级别(例如 '<3>')的消息,后跟 ISO 日期和文本。省略 PID、进程名和系统名。这设计用于本地日志服务器。
maxlen <length>
存储在环形缓冲区中的事件消息的最大长度,包括格式化的头部。如果事件消息长于 <length>,它将被截断为此长度。
server <name> <address> [param*]
用于配置 syslog tcp 服务器以转发环缓冲区中的消息。这支持第 5.2 段中找到的所有 "server" 参数。其中一些参数与 "ring" 部分不相关。重要的一点是:向环中添加多个服务器几乎没有理由,因为所有服务器将接收完全相同的环内容副本,因此环将以最慢服务器的速度前进。如果一个服务器没有响应,它将阻止清除旧消息,并可能阻止新消息插入环中。向多个服务器发送消息的正确方法是为每个日志服务器使用一个不同的环,而不是将多个服务器附加到同一个环中。请注意,特定的服务器指令 "log-proto" 用于设置用于发送消息的协议。
size <size>
这是环形缓冲区的可选大小,以字节为单位。默认值设置为 BUFSIZE。
timeout connect <timeout>
设置等待服务器连接尝试成功的最大时间。
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
timeout server <timeout>
设置待处理数据在输出缓冲区中停留的最长时间。
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
示例
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 会将所有接收到的日志消息转发到一个日志服务器列表。
创建一个新的日志转发代理,标识为 <name>。
backlog <conns>
向系统提供关于连接接受时期望的监听队列(backlog)大致大小的提示。
bind <addr> [param*]
用于配置流日志侦听器以接收要转发的消息。这支持第 5.1 段中找到的 "bind" 参数,包括与 ssl 相关的参数,但某些语句(例如 "alpn")可能与通过 TCP 的 syslog 协议不相关。这些侦听器支持 rfc-6587 中定义的 "Octet Counting" 和 "Non-Transparent-Framing" 模式。
dgram-bind <addr> [param*]
用于配置数据报日志侦听器以接收要转发的消息。地址必须是 IPv4 或 IPv6 格式,后跟端口。这支持第 5.1 段中找到的 "bind" 参数中的一部分,其中包括 "interface"、"namespace" 或 "transparent",而其他参数则被静默忽略,因为它们与 UDP/syslog 情况不相关。
log <target> [len <length>] [format <format>] [sample <ranges>:<sample_size>] <facility> [<level> [<minlevel>]]
用于配置目标日志服务器。请参阅代理文档了解更多详情。如果未指定格式,HAProxy 会尝试保留传入的日志格式。配置的 facility 会被忽略,除非传入消息没有 facility 但在传出格式中是必需的。如果输入格式中没有时间戳,但输出格式中存在该字段,HAProxy 将使用本地日期。
示例
global log stderr format iso local7 ring myring description "我的本地缓冲区" format rfc5424 maxlen 1200 size 32764 timeout connect 5s timeout server 10s # syslog tcp 服务器 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 # 所有消息输出到 stderr log global # 所有消息输出到本地 tcp syslog 服务器 log ring@myring local0 # 在 4 个 udp syslog 服务器上负载均衡消息 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>
固定日志转发器上的最大并发连接数。默认值为 10。
timeout client <timeout>
设置客户端侧的最大不活动时间。
指示 HAProxy 始终将传入的 TCP 日志流视为使用非透明帧。此选项简化了帧逻辑并确保消息的一致处理,这在处理格式不正确的起始字符时特别有用。
启用 HAProxy 在不尝试解析和重构 syslog 消息的情况下转发它们,这对于转发可能不符合传统格式的消息很有用。此选项应与目标日志目标上的原始格式设置一起使用,以确保保留原始消息内容。
option host { replace | fill | keep | append }
设置 log-forward 部分应使用的主机策略,以处理出站 rfc3164 或 rfc5424 消息的 syslog 主机名字段。 replace 如果输入消息已包含主机名字段的值,我们将其替换为发送方的源 IP 地址。如果输入消息不包含主机名字段的值(即:作为输入 rfc5424 消息的 '-' 或不符合 rfc3164 或 rfc5424 消息),我们使用发送方的源 IP 地址作为主机名字段。 fill 如果输入消息已包含主机名字段的值,我们保留它。如果输入消息不包含主机名字段的值(即:作为输入 rfc5424 消息的 '-' 或不符合 rfc3164 或 rfc5424 消息),我们使用发送方的源 IP 地址作为主机名字段。(这是默认值) keep 如果输入消息已包含主机名字段的值,我们保留它。如果输入消息不包含主机名字段的值,我们将其设置为 'localhost' (rfc3164) 或 '-' (rfc5424)。 append 如果输入消息已包含主机名字段的值,我们在后面附加一个逗号,后跟发送方的 IP 地址。如果输入消息不包含主机名字段的值,我们使用发送方的源 IP 地址。对于上述所有选项,如果发送方的源 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" 指令一起使用相对路径时,分配一个默认目录来从中获取 SSL 证书。指定的绝对位置优先并忽略 "crt-base"。当在 crt-store 中使用时,全局部分的 crt-base 将被忽略。
key-base <dir>
当使用相对路径和 "key" 指令时,分配一个默认目录来获取 SSL 私钥。指定的绝对路径优先,并忽略 "key-base"。当在 crt-store 中使用时,将忽略全局部分的 key-base。
load [crt <filename>] [param*]
在证书存储中加载 SSL 文件。有关参数列表,请参见“12.7.1. 加载选项”部分
示例
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>
此参数是必需的,它加载一个 PEM 文件,该文件必须包含公用证书,但也可能包含中间证书和私钥。如果此文件中未提供私钥,则可以使用 "key" 关键字提供密钥。
acme <string>
此选项允许为给定证书配置 ACME 协议。这是一个实验性功能,需要在全局部分中使用 "expose-experimental-directives" 关键字。当在 crt-store 中使用 "acme" 关键字时,可以从磁盘上没有现有证书开始。相反,将使用临时密钥对,直到生成 ACME 证书。此行为是 crt-stores 独有的,crt-list 行和 ssl-f-use 行都无法在不先声明 crt-store 的情况下实现相同的功能。另请参阅 第 12.8 节 ("ACME") 和本节中的 "domains"。
alias <string>
可选参数。允许为证书命名一个别名,以便在配置中引用它。别名在配置的其他地方调用时必须以 '@/' 作为前缀。
domains <string>
配置将用于 ACME 证书的域列表。列表中的第一个域用作 CN。域在列表中用逗号分隔。另请参见第 12.8 节 ("ACME") 和本节中的 "acme"。
示例
load crt "example.com.pem" acme LE domains "bar.example.com,foo.example.com"
key <filename>
此参数是可选的。加载 PEM 格式的私钥。如果 "crt" 中已定义私钥,则此参数将覆盖它。
ocsp <filename>
此参数是可选的,它加载 DER 格式的 OCSP 响应。可以通过 CLI 进行更新。
issuer <filename>
此参数是可选的。加载 PEM 格式的 OCSP 颁发者。为了识别 OCSP 响应适用于哪个证书,需要颁发者的证书。如果颁发者的证书未在 "crt" 文件中找到,则可以从此参数加载。
sctl <filename>
此参数是可选的。支持证书透明度 (RFC6962) TLS 扩展。该文件必须包含一个有效的签名证书时间戳列表,如 RFC 中所述。文件将被解析以检查基本语法,但不验证签名。
ocsp-update [ off | on ]
当设置为 'on' 时启用自动 OCSP 响应更新,否则禁用它。其默认值为 'off'。要启用绑定行上的 OCSP 自动更新,您可以在 crt-store 中使用此选项,或者使用全局选项 "tune.ocsp-update.mode"。如果某个证书在多个 crt-list 中使用,并且 'ocsp-update' 的值不同,则会引发错误。同样,如果一个证书在绑定行上继承了全局选项,并且在 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 响应的到期日期早于此一小时限制,则更新频率会更高。仍然存在至少 5 分钟的最小更新间隔,以避免更新那些具有非常短的到期时间甚至根本没有 'Next Update' 的响应过于频繁。由于这个硬限制,请注意,当自动更新设置为 'on' 时,在初始化期间加载的任何 OCSP 响应都不会更新,直到至少 5 分钟,即使其到期时间在 now+5m 之前结束。这不应该太麻烦,因为 OCSP 响应在初始化期间加载时必须有效(其到期时间必须在将来),因此此响应在初始化后如此短的时间内到期的可能性很小。另一方面,如果证书指定了 OCSP uri 但没有 OCSP 响应,则将此选项设置为 'on' for the given certificate 将确保 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 请求/响应通过一个 http_client 实例发送和接收,该实例设置了 dontlog-normal 选项,并在发生错误时(例如,OCSP 响应程序无法访问)使用常规 HTTP 日志格式。如果发生此类错误,则将发出另一条包含 HTTP 相关信息的日志行以及“常规”OCSP 行(其文本状态可能为“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 response check failure”错误,您可能需要检查您提供的颁发者证书是否有效。在“generic”错误消息之后,括号中也可能会显示更精确的错误消息。它可能发生在“OCSP response check failure”或“Error during insertion”错误中。
jwt [ off | on ]
当设置为 'on' 时,允许此证书通过 "jwt_verify_cert" 转换器用于 JWT 验证。其默认值为 'off'。当为给定证书设置为 'on' 时,CLI 命令 "del ssl cert" 将不起作用。要删除证书,它必须不被使用,无论是用于 SSL 握手还是 JWT 验证。此选项可以在运行时通过 "add ssl jwt" 和 "del ssl jwt" CLI 命令进行更改。另请参阅 "show ssl jwt" CLI 命令。

12.8. ACME

acme <name>
可以使用 "acme" 部分配置 ACME 协议。该部分接受一个 "<name>" 参数,用于将证书链接到该部分。ACME 部分允许将 HAProxy 配置为 ACMEv2 客户端。此功能是实验性的,这意味着必须在全局部分中包含 "expose-experimental-directives" 才能使用此功能。截至 3.3 的当前限制: - 目前该功能仅限于 HTTP-01 或 DNS-01 质询。HTTP-01 完全由 HAProxy 处理,但 DNS-01 需要 dataplaneAPI 或另一个第三方工具才能与 DNS 提供商 API 对话。 - 可以在磁盘上没有现有证书的情况下启动。为此,必须在 crt-store 中配置证书。当在 crt-store 中使用 "acme" 关键字时,将使用临时密钥对,直到生成 ACME 证书。 - 当前的 HAProxy 架构是非阻塞模型,配置加载后不应进行磁盘访问,因为它可能会阻塞事件循环,阻塞同一线程上的流量。这意味着从 HAProxy 生成的证书和密钥需要从 HAProxy 外部使用 stats socket 上的 "dump ssl cert" 转储。可以使用 dataplaneAPI 或 admin/cli/ 目录中提供的 haproxy-dump-certs 脚本自动转储证书。 - 不支持外部帐户绑定 (EAB)。ACME 调度程序在 HAProxy 启动时启动,它将循环遍历证书,并在 notAfter 任务超过 curtime + (notAfter - notBefore) / 12 或如果未定义 notBefore 则为 7 天时启动 ACME 续订任务。然后调度程序将休眠并在 12 小时后唤醒。可以使用 "acme renew" 手动启动续订任务。另请参阅管理指南中的 "acme status"。以下关键字可在 ACME 部分中使用
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
bits <number>
配置生成 RSA 证书的位数。默认为 2048。设置过高的值,如果您的机器性能不足,可能会触发警告。(这可以通过 "warn-blocked-traffic-after" 进行配置,但阻塞流量时间过长可能会触发看门狗。)
challenge <string>
将质询类型作为参数,这必须是 http-01 或 dns-01。不使用时,默认为 http-01。
contact <string>
将与 CA 中的帐户密钥关联的联系电子邮件。
curves <string>
使用 ECDSA 密钥类型时,配置曲线。默认为 P-384。
directory <string>
此关键字配置此 acme 部分使用的 CA 的目录 URL。此关键字是强制性的,因为没有默认 URL。
示例
directory https://acme-staging-v02.api.letsencrypt.org/directory
keytype <string>
配置将生成的密钥类型。值可以是 "RSA" 或 "ECDSA"。您还可以为 ECDSA 配置 "curves" 以及为 RSA 配置 "bits" 的数量。默认情况下生成 EC384 密钥。
map <map>
配置将用于存储令牌(key)和指纹(value)的映射,这在有多个帐户用于响应质询时非常有用。acme 任务将在验证质询之前添加条目,并在任务结束时删除条目。
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


HAProxy 3.3.0 – 配置手册
, 2025/11/26