配置手册

3.2.9 版本

2025/11/21

本文档涵盖了上述版本中实现的配置语言。它不提供任何提示、示例或建议。有关此类文档,请参阅参考手册或架构手册。以下摘要旨在帮助您按名称查找章节并在文档中导航。文档贡献者须知:本文档每行格式化为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.
12.9.
当 HAProxy 在 HTTP 模式下运行时,请求和响应都会被完全分析和索引,因此可以根据内容中找到的几乎任何信息构建匹配标准。然而,了解 HTTP 请求和响应的构成方式以及 HAProxy 如何分解它们是很重要的。这样一来,编写正确的规则和调试现有配置就会变得更加容易。首先,HTTP 由一系列 RFC 标准化,HAProxy 尽可能地遵循这些标准: - RFC 9110: HTTP 语义 (解释协议元素的含义) - RFC 9111: HTTP 缓存 (解释 HTTP 缓存应遵循的规则) - RFC 9112: HTTP/1.1 (表示、互操作性规则、安全) - RFC 9113: HTTP/2 (表示、互操作性规则、安全) - RFC 9114: HTTP/3 (表示、互操作性规则、安全) 除此之外,RFC 8999 到 9002 规定了 HTTP/3 协议使用的 QUIC 传输层。

1.1. HTTP 事务模型

HTTP 协议是事务驱动的。这意味着每个请求将只导致一个响应。最初,在协议 1.0 版本中,每个连接只有一个请求:客户端与服务器建立 TCP 连接,客户端通过连接发送请求,服务器响应,然后连接关闭。一个新的请求随后涉及到新的连接:[CON1] [REQ1] ... [RESP1] [CLO1] [CON2] [REQ2] ... [RESP2] [CLO2] ... 在这种模式下,通常称为“HTTP 关闭”模式,连接建立的次数与 HTTP 事务的次数相同。由于服务器在响应后关闭连接,客户端不需要知道内容长度,它认为当连接关闭时响应就完成了。这也意味着如果某些响应由于网络错误而被截断,客户端可能会错误地认为响应已完成,这有时会导致屏幕上显示截断的图像。由于协议的事务性性质,可以对其进行改进以避免在两个后续事务之间关闭连接。然而,在这种模式下,服务器必须为每个响应指示内容长度,以便客户端不会无限期地等待。为此,使用了一个特殊标头:“Content-length”。这种模式称为“keep-alive”模式,随 HTTP/1.1 出现(一些 HTTP/1.0 代理也支持它),在请求之间重用的连接称为“持久连接”:[CON] [REQ1] ... [RESP1] [REQ2] ... [RESP2] [CLO] ... 它的优点是事务之间的延迟减少,服务器端所需的处理能力减少,以及能够检测截断的响应。它通常比关闭模式更快,但并非总是如此,因为某些客户端通常将其并发连接限制在较小的值,这在很大程度上无法弥补糟糕的网络连接。此外,一些服务器必须长时间保持连接活动以等待可能的新请求,并且由于连接数量过多可能会导致高内存使用,而过快关闭可能会中断在连接关闭时到达的某些请求。在这种模式下,响应大小需要预先知道,因此对于动态生成或压缩的内容来说并不总是可能。出于这个原因,实现了另一种模式,即“分块模式”,其中发送方不是一次性宣布整个大小,而是只公布它在缓冲区中已经拥有的下一个“块”的响应大小,并且可以在任何时候以零大小的块终止。在这种模式下,不使用 Content-Length 标头。通信中的另一个改进是管道模式。它仍然使用 keep-alive,但客户端不会等待第一个响应就发送第二个请求。这对于获取构成页面的大量图像很有用:[CON] [REQ1] [REQ2] ... [RESP1] [RESP2] [CLO] ... 这显然对性能有巨大的好处,因为后续请求之间的网络延迟被消除了。许多 HTTP 代理不正确支持管道,因为在 HTTP 中无法将响应与相应的请求关联起来。出于这个原因,服务器必须按照接收请求的完全相同顺序进行回复。实际上,在各种客户端多次尝试部署后,由于其在某些服务器上的可靠性不足,它已被完全放弃。但服务器必须支持它。下一个改进是多路复用模式,如 HTTP/2 和 HTTP/3 中实现的那样。在这种模式下,多个事务(即请求-响应对)通过单个连接并行传输,并且它们都以自己的速度进行,相互独立。通过多路复用协议,引入了“流”的新概念,以表示通过同一连接发生的这些并行通信。每个流通常被分配一个给定连接的唯一标识符,两端都使用该标识符来知道将数据传递到何处。客户端通过同一连接并行启动许多(最多 100 个,有时更多)流是很常见的,并让服务器对它们进行排序并根据可用的响应以任何顺序进行响应。多路复用模式的主要好处是它显著减少了往返次数,并加快了高延迟网络上的页面加载时间。这在许多使用图像的网站上有时可见,所有图像似乎都是并行加载的。这些协议还通过采用一些机制来压缩标头字段以减少线路上的字节数来提高效率,因此如果没有适当的工具,它们无法像 HTTP/1 那样通过手动操作或肉眼识别。因此,HTTP 消息的各种示例在文献中(包括本文档)继续使用 HTTP/1 语法表示,即使是较新版本的协议也是如此。HTTP/2 存在一些设计限制,例如数据包丢失会同时影响所有流,如果客户端花费太多时间检索对象(例如,需要将其存储在磁盘上),它可能会减慢其检索速度,并使其在此期间无法访问其后面待处理的数据。这称为“队头阻塞”或“HoL 阻塞”,有时也简称“HoL”。HTTP/3 是在 QUIC 之上实现的,QUIC 本身是在 UDP 之上实现的。QUIC 通过独立处理的流在传输层解决了队头阻塞问题。实际上,当发生丢失时,受影响的流不会影响其他流,并且所有流都可以并行访问。QUIC 还提供连接迁移支持,但目前 haproxy 不支持。默认情况下,HAProxy 在持久连接方面以 keep-alive 模式运行:对于每个连接,它处理每个请求和响应,并在响应结束和新请求开始之间将连接在两端保持空闲。当它从客户端接收 HTTP/2 连接时,它并行处理所有请求并使连接空闲,等待新请求,就像它是 keep-alive HTTP 连接一样。HAProxy 主要支持 3 种连接模式:- keep alive:处理所有请求和响应,并且面向客户端和面向服务器的连接保持活动状态以处理新请求。这是默认设置,适用于现代网络和现代协议(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 中的一些不需要服务器的内部处理,例如统计页面、缓存或一些用于实现小型应用程序的 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 个字段组成:- 方法:GET - URI:/serv/login.php?lang=en&profile=2 - 版本标签: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 它由一个“方案”(协议名称后跟 '://')、一个主机名或地址,可选的一个冒号(':')后跟一个端口号,然后是一个以地址部分后的第一个斜杠('/')开头的相对 URI。这通常是代理接收到的内容,但支持 HTTP/1.1 的服务器也必须接受这种形式。- 星号('*'):这种形式仅在与 OPTIONS 方法关联时接受,且不可转发。它用于查询下一跳的功能。- 地址:端口组合:192.168.0.12:80 这与 CONNECT 方法一起使用,该方法用于通过 HTTP 代理建立 TCP 隧道,通常用于 HTTPS,但有时也用于其他协议。在相对 URI 中,识别出两个子部分。问号之前的部分称为“path”。它通常是服务器上静态对象的相对路径。问号之后的部分称为“查询字符串”。它主要与发送到动态脚本的 GET 请求一起使用,并且非常特定于所使用的语言、框架或应用程序。HTTP/2 和 HTTP/3 不在请求中传输版本信息,因此版本被假定为与底层协议的版本相同(即“HTTP/2”)。此外,这些协议不将请求行作为一部分发送,而是将其拆分为称为“伪标头”的单独字段,其名称以冒号开头,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 在索引标头、检查值和计数时会处理所有这些复杂的组合,因此没有理由担心它们的书写方式,但重要的是,如果应用程序做出了不寻常但有效的事情,不要指责它有 bug。重要提示:正如 RFC7231 建议的那样,HAProxy 通过用 LWS 替换标头中间的换行符来规范化标头,以连接多行标头。这对于正确的分析是必要的,并有助于能力较弱的 HTTP 解析器正确工作,不被此类复杂结构所迷惑。

1.4. HTTP 响应

HTTP 响应看起来非常像 HTTP 请求。两者都被称为 HTTP 消息。让我们考虑这个 HTTP 响应:行内容编号 1 HTTP/1.1 200 OK 2 Content-length: 350 3 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 个字段组成:- 版本标签:HTTP/1.1 - 状态码:200 - 原因: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 和: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
在一种特定情况下,可能需要第二层的引用或转义。一些关键字在括号内接受参数,有时用逗号分隔。这些参数通常是整数或预定义词,但当它们是任意字符串时,可能需要执行单独的转义级别,以区分属于参数的字符和用于分隔参数本身的字符。一个非常常见的情况是"regsub"转换器。它将正则表达式作为参数,如果内部需要闭括号,则该括号需要有自己的引号。关键字参数解析器与顶层解析器在引号方面完全相同,只是不处理#、$和\xNN转义。但并非总是显而易见的是,内部使用的分隔符必须首先进行转义或引用,以免它们在顶层被解析。让我们以使用"regsub"转换器为例,该转换器接受3个参数:一个正则表达式、一个替换字符串和一组标志:# 替换路径中所有"foo"为"blah": http-request set-path %[path,regsub(foo,blah,g)] 这里不需要特殊的引用。但如果现在我们想将"foo"或"bar"替换为"blah",我们将需要正则表达式"(foo|bar)"。我们不能写:http-request set-path %[path,regsub((foo|bar),blah,g)] 因为我们希望字符串像这样分割:http-request set-path %[path,regsub((foo|bar),blah,g)] |---------|----|-| arg1 _/ / / arg2 __________/ / arg3 ______________/ 但实际上,传递的是一个在开括号和闭括号之间的字符串,然后是垃圾:http-request set-path %[path,regsub((foo|bar),blah,g)] |--------|--------| arg1=(foo|bar _/ / trailing garbage _________/ 这里的明显解决方案似乎是闭括号需要被引用,但单独这样做是行不通的,因为如上所述,引号由顶层解析器处理,它会在处理此词之前解析它们:http-request set-path %[path,regsub("(foo|bar)",blah,g)] ------------ -------- ---------------------------------- word1 word2 word3=%[path,regsub((foo|bar),blah,g)] 所以我们没有改变第二层参数解析器的任何东西,它仍然将截断的正则表达式视为唯一的参数,并在字符串末尾看到垃圾。通过转义引号,它们将未经修改地传递到第二层:http-request set-path %[path,regsub(\"(foo|bar)\",blah,g)] ------------ -------- ------------------------------------ word1 word2 word3=%[path,regsub("(foo|bar)",blah,g)] |---------||----|-| arg1=(foo|bar) _/ / / arg2=blah ___________/ / arg3=g _______________/ 另一种方法是使用整个字符串外面的单引号和里面的双引号(这样双引号不会再次被剥离):http-request set-path '%[path,regsub("(foo|bar)",blah,g)]' ------------ -------- ---------------------------------- word1 word2 word3=%[path,regsub("(foo|bar)",blah,g)] |---------||----|-| arg1=(foo|bar) _/ / / arg2 ___________/ / arg3 _______________/ 但在这种情况下,重要的是要注意嵌入到更高层字符串中的分隔符仍然是纯字符,不再是分隔符。这特别意味着逗号周围的空格和制表符是字符串的一部分。下面的例子在多个方面是错误的:http-request set-path '%[path, regsub("(foo|bar)", blah, g)]' ------------ -------- -------------------------------------- word1 word2 word3=%[path, regsub("(foo|bar)", blah, g)] |--------|---------||-----|--| converter=" regsub" _/ / / / arg1=(foo|bar) _/ / / arg2=" blah" ___________/ / arg3=" g" ______________/ 仅仅用空格包围逗号就导致空格成为字段本身的一部分,因此转换器是" regsub"(以空格开头),它将找不到并触发错误,但更微妙的是,替换字符串" blah"将在输出中插入一个空格。一个好的经验法则是永远不要在表达式中插入不必要的空格。当使用正则表达式时,表达式中可能会出现美元符('$')字符,或者替换字符串中使用反斜杠('\')。在这种情况下,这些也会在双引号内处理,因此首选单引号(或双重转义)。示例:http-request set-path '%[path,regsub("^/(here)(/|$)","my/\1",g)]' ------------ -------- ----------------------------------------- word1 word2 word3=%[path,regsub("^/(here)(/|$)","my/\1",g)] |-------------| |-----||-| arg1=(here)(/|$) _/ / / arg2=my/\1 ________________/ / arg3 ______________________/ 请记住,反斜杠在单引号内不是转义字符,并且上面的整个词已经使用单引号对其进行了保护。相反,如果整个表达式都使用双引号,则美元符和反斜杠将在顶层解析,从而破坏第二层的参数内容。不幸的是,由于单引号不能在强引用内转义,如果您需要在参数中包含单引号,则需要对其进行两次转义或引用。有几种方法可以做到这一点:http-request set-var(txn.foo) str("\\'foo\\'") http-request set-var(txn.foo) str(\"\'foo\'\") http-request set-var(txn.foo) str(\\\'foo\\\') 当有疑问时,只需在任何地方都不要使用引号,然后开始在需要逗号或闭括号的参数周围放置单引号或双引号,并考虑如果字符串包含美元符或反斜杠,则使用反斜杠转义这些引号。再次强调,这与Bourne shell中将命令双重转义传递给"eval"时所用的方法非常相似。对于API编写者来说,最好的方法可能是围绕每个参数放置转义引号,无论其内容如何。用户可能会发现,在整个表达式周围使用单引号并在每个参数周围使用双引号可以提供更具可读性的配置。

2.3. 环境变量

HAProxy 的配置支持环境变量。这些变量仅在双引号内被解释。变量在配置解析期间被展开。变量名前必须有美元符号 ("$"),并且可以选择性地用大括号 ("{}") 括起来,类似于 Bourne shell 中的做法。变量名可以包含字母数字字符或下划线 ("_"),但不应以数字开头。如果变量包含由空格分隔的多个值列表,可以通过用大括号将变量括起来并在右大括号前附加后缀 '[*]' 来将其展开为单个参数。当变量未设置时,也可以通过在变量名旁边的破折号 '-' 后面附加该值来指定一个默认值。请注意,默认值只替换不存在的变量,而不是空变量。
示例
bind "fd@${FD_APP1}" log "${LOCAL_SYLOG-127.0.0.1}:514" local0 notice # 发送到本地服务器 user "$HAPROXY_USER"
HAProxy定义了一些变量,它们可以在配置文件中使用,也可以被程序继承(参见12.9. 程序)。这些变量在下面的矩阵中列出,并分为四类:* 可用:变量可从配置中访问,可以按原样解析,也可以在条件块或谓词中使用,以启用或禁用某些配置片段,如第2.4节“条件块”所述。* 可修改:变量可以通过"setenv"/"unsetenv"关键字在配置中重新定义或取消设置。* 已列出:变量在CLI的"show env"命令输出中列出,如管理指南的第9.3节“Unix套接字命令”所述。* 已导出:变量被导出以在修改后的环境中启动程序(参见第12.9节“程序”)。请注意,这不适用于外部检查,外部检查对导出变量有自己的规则。还有两个子类别“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 它们的值在配置解析期间未定义,在初始化期间稍后设置。因此,建议不要在条件块中使用这些变量,也不要在全局部分的"setenv"/"resetenv"/"unsetenv"关键字中引用它们。下表总结了每种变量在不同工作模式下的状态:+--------------------------+----------+---------+------------+-----------+ | 变量 | 导出 | 可用 | 可修改 | 已列出 | | | +---------+------------+-----------+ | | | M | W | M | W | M | W | +--------------------------+----------+----+----+------+-----+-----+-----+ | HAPROXY_STARTUP_VERSION | X | X | X | | | X | X | | HAPROXY_BRANCH | X | X | X | | | X | X | | HAPROXY_CFGFILES | X | | | | | X | X | | HAPROXY_MWORKER | X | | | | | 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: 在主从模式下,此变量设置为 1。 * HAPROXY_CLI: 配置的每个进程的统计套接字监听器地址,这些地址以分号分隔。 * HAPROXY_MASTER_CLI: 在主从模式下,主 CLI 的监听器地址,以分号分隔。 * HAPROXY_STARTUP_VERSION: 包含用于启动的版本,在主从模式下,这是用于启动主的版本,即使在更新二进制文件和重新加载之后也是如此。 * HAPROXY_BRANCH: 包含 HAProxy 分支版本(例如 "2.8")。它不包含完整的版本号。如果资源(例如映射或证书)位于包含分支号的路径中,则在迁移时可能有用。此外,一些伪变量在内部解析并可用作常规变量。伪变量始终以点号('.')开头,并且是唯一允许使用点号的变量。当前的伪变量列表是: * .FILE: 当前正在解析的配置文件的名称。 * .LINE: 当前正在解析的配置文件的行号,从一开始。 * .SECTION: 当前正在解析的节的名称,如果该节没有名称(例如 "global"),则为其类型,或者在第一个节之前为空字符串。这些变量在它们被解析的位置解析。例如,如果 ".LINE" 变量在默认节中的 "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)"。目前支持的谓词列表如下:- 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 在主进程和 # 工作进程环境中自动设置(参见 2.3. 环境变量中的 HAProxy 变量矩阵)。 # 它的存在会启用一个额外的监听器。 global master-worker .if defined(HAPROXY_MWORKER) listen mwcli_px bind :1111 ... .endif # 2. HAPROXY_BRANCH 由 HAProxy 在主进程和工作 # 进程环境中自动设置(参见 2.3. 环境变量中的 HAProxy 变量矩阵)。 # 我们检查 HAPROXY_BRANCH 值并有条件地启用 # mworker-max-reloads 参数。 global master-worker .if streq("$HAPROXY_BRANCH",3.1) mworker-max-reloads 5 .endif # 3. 用户在全局部分设置了一些任意环境变量。 # 如果 HAProxy 以主从模式启动,它们会出现在主进程和 # 工作进程环境中。我们检查这些 # 变量的值并有条件地启用端口 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 配置中,变量可以在样本获取函数、转换器、日志格式字符串或 TCP/HTTP 操作中使用。可以定义进程范围的变量,这些变量在进程的整个生命周期中全局可访问。其他一些变量的生命周期较短。变量类似于 shell 脚本中的变量。它是内存块的符号名称。变量的大小不受限制,并且是动态分配的。因此,必须谨慎使用它们,尤其是在大量使用时。但是,可以通过设置“tune.vars”全局参数来限制变量使用的最大内存量。变量必须使用“<scope>.<name>”格式指定。<scope> 是一个单词,表示变量的生命周期。<name> 部分在作用域内,只能包含字符 'a-z'、'A-Z'、'0-9' 和 '_'。它在此作用域中是唯一的,但不同作用域中的相同名称可以引用不同的变量。支持的作用域有:* proc:用于在整个进程生命周期中已知并全局可访问的变量。“proc”变量可以使用“get var”和“set var”命令从 CLI 操作。它们也可以通过“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>。该文件描述符必须已绑定,并且可能已或未在监听。 'ip@<address>[:port1[-port2]]' 后跟 <address> 被视为 IPv4 或 IPv6 地址,具体取决于语法。根据使用此地址的语句,端口或端口范围可能或必须指定。 'ipv4@<address>[:port1[-port2]]' 后跟 <address> 始终被视为 IPv4 地址。根据使用此地址的语句,端口或端口范围可能或必须指定。 'ipv6@<address>[:port1[-port2]]' 后跟 <address> 始终被视为 IPv6 地址。根据使用此地址的语句,端口或端口范围可能或必须指定。 'sockpair@<n>' 后跟地址是已连接的 unix 套接字或套接字对的文件描述符。在连接期间,发起方创建一对已连接的套接字,并通过 FD 将其中一个传递给另一端。监听器等待从 unix 套接字接收 FD,并将其用作 accept() 的 FD。应谨慎使用。错误:已知此协议在 macOS 上不可靠,因为 macOS sendmsg(2) 实现存在问题。连接可能无法正确接受。 'unix@<path>' 后跟字符串被视为 UNIX 套接字 <path>。此前缀对于声明不以斜杠 '/' 开头的 UNIX 套接字路径很有用。

2.9.2. 套接字类型前缀

前面的“地址族前缀”也可以作为前缀来强制套接字类型和传输方法。默认值取决于使用此地址的语句,但在某些情况下,用户可以强制将其设置为不同的值。"log"语句就是这种情况,其默认值是通过 UDP 的 syslog,但我们可以强制使用通过 TCP 的 syslog。这些前缀是为内部目的设计的,用户应该改为使用下一节“2.9.3 协议前缀”的别名。但是,这些有时会很方便,例如与通过文件描述符号已知的继承套接字结合使用时,在这种情况下,地址族是“fd”,并且必须声明套接字类型。如果用户需要这些前缀来执行他们期望的操作,因为他们无法使用协议前缀配置相同的功能,他们应该向维护者报告。'stream+<family>@<address>' 强制套接字类型和传输方法为“stream”。'dgram+<family>@<address>' 强制套接字类型和传输方法为“datagram”。'quic+<family>@<address>' 强制套接字类型为“datagram”,传输方法为“stream”。

2.9.3. 协议前缀

'quic4@<address>[:port1[-port2]]' 后跟 <address> 始终被视为 IPv4 地址,但套接字类型强制为“数据报”,传输方法强制为“流”。根据使用此地址的语句,可以或必须指定 UDP 端口或端口范围。它等同于 "quic+ipv4@"。 'quic6@<address>[:port1[-port2]]' 后跟 <address> 始终被视为 IPv6 地址,但套接字类型强制为“数据报”,传输方法强制为“流”。根据使用此地址的语句,可以或必须指定 UDP 端口或端口范围。它等同于 "quic+ipv6@"。 'tcp@<address>[:port1[-port2]]' 后跟 <address> 根据语法被视为 IPv4 或 IPv6 地址,但套接字类型和传输方法强制为“流”。根据使用此地址的语句,可以或必须指定端口或端口范围。它被视为 'stream+ip@' 的别名。 'tcp4@<address>[:port1[-port2]]' 后跟 <address> 始终被视为 IPv4 地址,但套接字类型和传输方法强制为“流”。根据使用此地址的语句,可以或必须指定端口或端口范围。它被视为 'stream+ipv4@' 的别名。 'tcp6@<address>[:port1[-port2]]' 后跟 <address> 始终被视为 IPv6 地址,但套接字类型和传输方法强制为“流”。根据使用此地址的语句,可以或必须指定端口或端口范围。它被视为 'stream+ipv4@' 的别名。 'mptcp@<address>[:port1[-port2]]' 后跟 <address> 根据语法被视为 IPv4 或 IPv6 地址,但套接字类型和传输方法强制为“流”,并使用 MPTCP 协议。根据使用此地址的语句,可以或必须指定端口或端口范围。 'mptcp4@<address>[:port1[-port2]]' 后跟 <address> 始终被视为 IPv4 地址,但套接字类型和传输方法强制为“流”,并使用 MPTCP 协议。根据使用此地址的语句,可以或必须指定端口或端口范围。 'mptcp6@<address>[:port1[-port2]]' 后跟 <address> 始终被视为 IPv6 地址,但套接字类型和传输方法强制为“流”,并使用 MPTCP 协议。根据使用此地址的语句,可以或必须指定端口或端口范围。 'udp@<address>[:port1[-port2]]' 后跟 <address> 根据语法被视为 IPv4 或 IPv6 地址,但套接字类型和传输方法强制为“数据报”。根据使用此地址的语句,可以或必须指定端口或端口范围。它被视为 'dgram+ip@' 的别名。 'udp4@<address>[:port1[-port2]]' 后跟 <address> 始终被视为 IPv4 地址,但套接字类型和传输方法强制为“数据报”。根据使用此地址的语句,可以或必须指定端口或端口范围。它被视为 'dgram+ipv4@' 的别名。 'udp6@<address>[:port1[-port2]]' 后跟 <address> 始终被视为 IPv6 地址,但套接字类型和传输方法强制为“数据报”。根据使用此地址的语句,可以或必须指定端口或端口范围。它被视为 'dgram+ipv4@' 的别名。 'uxdg@<path>' 后跟字符串被视为 unix 套接字 <path>,但传输方法强制为“数据报”。它被视为 'dgram+unix@' 的别名。 'uxst@<path>' 后跟字符串被视为 unix 套接字 <path>,但传输方法强制为“流”。它被视为 'stream+unix@' 的别名。 在未来的版本中,可以使用其他前缀来指定 QUIC 等协议,这些协议提供了基于“数据报”类型套接字的流传输。

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 - no-quic - 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 - 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.cc-hystart - tune.quic.cc.cubic.min-losses - tune.quic.disable-tx-pacing - tune.quic.disable-udp-gso - tune.quic.frontend.glitches-threshold - tune.quic.frontend.max-data-size - tune.quic.frontend.max-idle-timeout - tune.quic.frontend.max-streams-bidi - tune.quic.frontend.max-tx-mem - tune.quic.frontend.stream-data-ratio - tune.quic.frontend.default-max-window-size - tune.quic.max-frame-loss - tune.quic.reorder-ratio - tune.quic.retry-threshold - tune.quic.socket-owner - tune.quic.zero-copy-fwd-send - tune.renice.runtime - tune.renice.startup - tune.rcvbuf.backend - tune.rcvbuf.client - tune.rcvbuf.frontend - tune.rcvbuf.server - tune.recv_enough - tune.ring.queues - tune.runqueue-depth - tune.sched.low-latency - tune.sndbuf.backend - tune.sndbuf.client - tune.sndbuf.frontend - tune.sndbuf.server - tune.stick-counters - tune.ssl.cachesize - tune.ssl.capture-buffer-size - tune.ssl.capture-cipherlist-size (已废弃) - 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 (已废弃) - tune.ssl.ocsp-update.mindelay (已废弃) - tune.takeover-other-tg-connections - tune.vars.global-max-size - tune.vars.proc-max-size - tune.vars.reqres-max-size - tune.vars.sess-max-size - tune.vars.txn-max-size - tune.zlib.memlevel - tune.zlib.windowsize * 调试 - anonkey - debug.counters - force-cfg-parser-pause - quiet - warn-blocked-traffic-after - zero-warning * 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 集要么是一个唯一的数字(从 0 开始表示第一个 CPU),要么是一个由短划线 ('-') 分隔的两个这样的数字范围。这些 CPU 号和范围可以通过逗号分隔或通过在同一行上作为新参数传递更多范围来重复。在 Linux 和 BSD 操作系统之外,最大 CPU 索引可能限制为 31 或 63。可以指定多个“cpu-map”指令,但每个“cpu-map”指令在它们重叠时将替换之前的指令。范围可以部分定义。可以省略上限。在这种情况下,它将替换为相应的最大值,即 32 或 64,具体取决于机器的字长。可以在线程集之前添加“auto:”前缀,让 HAProxy 通过递增线程和 CPU 集自动将一组线程绑定到 CPU。为了有效,两个集合必须具有相同的大小。无论 CPU 集的声明顺序如何,它都将从最低绑定到最高绑定。不支持同时使用带有“auto:”前缀的组和线程范围。只支持一个范围,另一个必须是固定数字。请注意,支持组范围是出于历史原因。现在,单个数字表示一个线程组,如果未使用线程组,则必须为 1,并且如果未使用线程组,则指定线程范围或数字需要在其前面加上“1/”。最后,“1”严格等同于“1/all”,表示组中的所有线程。
示例
cpu-map 1/all 0-3 # 将第一个组的所有线程绑定到 # 前 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分配给线程和线程组。这种映射通常使用“cpu-map”指令执行,尽管在异构系统上维护它可能特别困难。“cpu-policy”指令选择少数分配策略中的哪一个,当不使用“cpu-map”时使用。目前支持以下策略:- none 不执行任何特定的后选择。所有启用的CPU都将可用,如果未设置线程数,它将设置为可用CPU的数量,但每个线程组不超过32位系统上的32个或64位系统上的64个。如果未设置线程组数,它将设置为1。- efficiency 恰好与下面的“group-by-ccx”相同,只是性能比下一个性能较低的CPU高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的CPU可能是有意义的,以避免创建许多组,或者在并非所有核都在使用时稍微平滑分配。请注意,当CCX之间的通信缓慢时,这可能产生非常糟糕的性能影响。通常不建议这样做。- group-by-2-clusters 与“group-by-cluster”相同,但每两个集群创建一个组。这对于具有许多小核集群的CPU可能是有意义的,以避免创建许多组,或者在并非所有核都在使用时稍微平滑分配。请注意,当集群之间的通信缓慢时,这可能产生非常糟糕的性能影响。通常不建议这样做。- group-by-3-ccx 与下面的“group-by-ccx”相同,但每三个CCX创建一个组。这对于具有许多小核CCX的CPU可能是有意义的,以避免创建许多组,或者在并非所有核都在使用时稍微平滑分配。请注意,当CCX之间的通信缓慢时,这可能产生非常糟糕的性能影响。通常不建议这样做。- group-by-3-clusters 与“group-by-cluster”相同,但每三个集群创建一个组。这对于具有许多小核集群的CPU可能是有意义的,以避免创建许多组,或者在并非所有核都在使用时稍微平滑分配。请注意,当集群之间的通信缓慢时,这可能产生非常糟糕的性能影响。通常不建议这样做。- group-by-4-ccx 与下面的“group-by-ccx”相同,但每四个CCX创建一个组。这对于具有许多小核CCX的CPU可能是有意义的,以避免创建许多组,或者在并非所有核都在使用时稍微平滑分配。请注意,当CCX之间的通信缓慢时,这可能产生非常糟糕的性能影响。通常不建议这样做。- group-by-4-clusters 与“group-by-cluster”相同,但每四个集群创建一个组。这对于具有许多小核集群的CPU可能是有意义的,以避免创建许多组,或者在并非所有核都在使用时稍微平滑分配。请注意,当集群之间的通信缓慢时,这可能产生非常糟糕的性能影响。通常不建议这样做。- group-by-ccx 如果既未设置“nbthread”也未设置“nbtgroups”,则为每个具有可用CPU的CPU核心复合体(“CCX”)创建一个线程组,每个组的线程数与CPU数相同。一个CCX将CPU分组在一起,这些CPU对最后一级缓存(“LLC”,通常是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”相同,只是性能比下一个性能较高的CPU低80%以下的CPU集群将被驱逐。这些通常是“小核”或“高效核”,它们的增加通常不会带来显著的增益,并且很容易适得其反(例如TLS握手)。通常,将这些核心用于其他任务,例如网络处理,会更有效。在开发系统上,这些也可以用于运行辅助工具,例如负载生成器和监控工具。- resource 这与上面的“group-by-cluster”类似,只是将只使用最小且最有效的CPU集群,而所有其他集群将被忽略。这可用于将资源使用限制在仍然提供体面性能的最低限度,例如尝试进一步降低功耗或最小化某些租用系统上旁路设置所需的核数,以便更容易地向下扩展系统。请注意,如果只有一个集群存在,它仍将完全使用。
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" 表示所有相对文件都应从包含配置文件的目录加载。更具体地说,如果配置文件包含斜杠 ('/'),则使用直到最后一个斜杠的最长部分作为要更改的目录,否则使用当前目录。此模式便于将映射、错误文件、证书和 Lua 脚本捆绑为可重定位的包。当加载多个配置文件时,每个文件的目录都会更新。- "parent" 表示所有相对文件都应从包含配置文件的父目录加载。更具体地说,如果配置文件包含斜杠 ('/'),则在直到最后一个斜杠的最长部分后附加 ".." 作为要更改的目录,否则目录为 ".."。此模式便于将映射、错误文件、证书和 Lua 脚本捆绑为可重定位的包,但每个部分位于不同的子目录中(例如 "config/"、"certs/"、"maps/" 等)。- "origin" 表示所有相对文件都应从指定的(强制性)路径加载。这可用于简化管理系统上并行运行的不同 HAProxy 实例,其中每个实例使用不同的前缀,但其余部分易于重定位。每个 "default-path" 指令会立即替换任何之前的指令,并可能导致切换到不同的目录。虽然这应该总是能产生所需行为,但使用多个 default-path 指令确实不是一个好习惯,如果使用,策略应在所有配置文件中保持一致。警告:某些配置元素,例如映射或证书,通过其配置路径唯一标识。通过使用可重定位布局,可能会导致其中几个以相同的唯一名称结束,从而难以在运行时更新它们,尤其是在从不同目录加载多个配置文件时。在采用相对路径之前,必须遵守严格的无冲突文件命名方案。一种稳健的方法可以是为所有文件名添加其各自站点名称前缀,或在目录级别执行此操作。
添加描述实例的文本。请注意,需要转义某些字符(例如 #),并且此文本将插入 HTML 页面中,因此您应避免使用“<”和“>”字符。
设置要由 API 加载的 DeviceAtlas JSON 数据文件的路径。该路径必须是一个有效的 JSON 数据文件,并且 HAProxy 进程可以访问。
设置 API 返回的信息级别。此指令是可选的,如果未设置,则默认为 0。
设置用于检测请求期间是否使用了 DeviceAtlas 客户端组件的客户端 cookie 名称。此指令是可选的,如果未设置,则默认为 DAPROPS。
设置 API 属性结果的字符分隔符。此指令是可选的,如果未设置,则默认为 |。
dns-accept-family <family>[,...]
默认情况下,DNS 解析器接受 IPv4 和 IPv6 地址。这可以通过服务器行上的 "resolve-prefer" 关键字以及 "do-resolve" 操作的 family 参数来影响,但这只是一种偏好,并不会阻止在单独使用时使用其他家族。在某些双栈不可用的环境中,遇到无法访问的纯 IPv6 DNS 记录可能会导致严重问题,因为它会替换之前可能一直工作到下一个请求的 IPv4 记录。"dns-accept-family" 全局选项允许强制仅使用一个(或两个)地址家族。参数是一个逗号分隔的以下单词列表:- "ipv4":查询并接受 IPv4 地址 ("A" 记录) - "ipv6":查询并接受 IPv6 地址 ("AAAA" 记录) - "auto":使用 IPv4,如果系统有 IPv6 的默认网关,则使用 IPv6。上次检查的结果缓存 30 秒。当仅使用一个家族时,不会向解析器发送其他家族的请求,并且会忽略其他家族的任何响应。默认值为 "ipv4,ipv6",它有效地启用两个家族。
此声明必须在使用一些标记为已弃用的指令之前出现,以消除警告并确保配置文件不会被拒绝。并非所有已弃用的指令都受此影响,只有那些没有任何替代解决方案的指令。
此语句必须出现在使用标记为实验性的指令之前,否则配置文件将被拒绝。请注意,此选项涵盖的功能不能保证良好运行,并且可能在维护周期中出现故障。开发人员将在开发下一版本期间尽最大努力维护它们,并将尽一切合理努力避免破坏它们,但不作保证。因此,这些功能预计在下一个 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 亿),这将消耗过多的 RAM 用于常规使用。fd-hard-limit 设置用于对此限制强制执行一个可能较低的上限。这意味着它将始终遵守系统施加的限制(如果它们低于 <number>),但如果系统施加的限制更高,则将使用指定值。默认情况下,fd-hard-limit 设置为 1048576。此默认值可以通过 DEFAULT_MAXFD 编译时变量更改,该变量可以作为最大(内核)系统限制,如果 RLIMIT_NOFILE 硬限制非常大。在全局部分设置的 fd-hard-limit 允许临时覆盖构建时通过 DEFAULT_MAXFD 提供的值。在下面的示例中,没有指定其他设置,maxconn 值将自动适应 "fd-hard-limit" 和 RLIMIT_NOFILE 限制中的较低值:global # 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。为了允许客户端自动降级到 websocket 隧道使用 http/1.1,请在绑定行上使用 "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 是不可靠的,因为 fork 的进程可能会随机嵌入另一个线程设置的锁,并且永远无法完成操作。因此,强烈建议永远不要使用此选项,并且任何需要此类 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 将完成该链。所有其他具有相同颁发者的证书将共享内存中的链。OCSP 功能能够在未使用 .issuer 或 PEM 中未提供链时使用已完成的链。
key-base <dir>
当使用 "key" 指令并使用相对路径时,指定一个用于获取 SSL 私钥的默认目录。指定的绝对路径优先,并忽略 "key-base"。此选项仅在使用 crt-store 加载行时有效。
当 haproxy 编译时所依赖的 TLS/SSL 库不支持 QUIC(通常是 OpenSSL)时,必须使用此设置来显式启用 QUIC 监听器绑定。当 haproxy 编译时所依赖的 TLS/SSL 库支持 QUIC(例如 quictls)时,此设置无效。请注意,设置此项后不支持 QUIC 0-RTT。
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)。此指令可以多次使用。有关参数的使用,请参阅 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 [no-exit-on-failure]
主-从模式(Master-worker mode)。它等同于命令行参数“-W”。此模式将启动一个“主进程”,该进程在读取配置后会 fork 一个“工作进程”来处理流量。主进程用作进程管理器,将监控“工作进程”。使用此模式,您可以通过向主进程发送 SIGUSR2 信号直接重新加载 HAProxy。重新加载将要求主进程再次读取配置并 fork 一个新的工作进程。先前的工作进程将保留直到其作业结束。主-从模式与前台或守护进程模式兼容。默认情况下,如果工作进程因错误返回码退出,例如发生段错误,所有工作进程都将被杀死,主进程将退出。将此行为与 systemd 单元文件中的 Restart=on-failure 结合使用,以重新启动整个进程,是很方便的。如果您不希望此行为,必须使用关键字“no-exit-on-failure”。另请参阅管理指南中的“-W”。
在主-从模式下,此选项限制了工作进程可以承受的重载次数。如果工作进程在重载后没有退出,一旦其重载次数大于此数字,该工作进程将收到一个 SIGTERM 信号。此选项有助于控制工作进程的数量。另请参阅管理指南中的“show proc”。
nbthread <number>
此设置仅在内置线程支持时可用。它使 HAProxy 在 <number> 个线程上运行。“nbthread” 在 HAProxy 在前台启动时也有效。在某些支持 CPU 亲和性的平台上,默认的 “nbthread” 值会自动设置为启动时进程绑定的 CPU 数量。这意味着线程数可以轻松地从调用进程中使用 "taskset" 或 "cpuset" 等命令进行调整。否则,此值默认为 1。默认值在 "haproxy -vv" 的输出中报告。请注意,此处设置或自动检测的值受 “thread-hard-limit”(如果设置)设置的限制。
禁用 QUIC 传输协议。所有 QUIC 监听器仍将被创建,但它们不会绑定其地址。因此,haproxy 将不会处理任何 QUIC 流量。另请参阅“quic_enabled”样本获取。
当在支持 NUMA 的平台上运行,并且 cpu-policy 设置为 "first-usable-node"(默认值)时,HAProxy 在启动时会检查机器的 CPU 拓扑。如果检测到多插槽机器,则会自动计算亲和性以在单个节点的 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.socket-owner connection" 时,通常需要一些权限,这会导致完全在 uid 0 下运行的设置。设置功能通常是更安全的替代方案,因为只会保留所需的权限。此功能是操作系统特定的,并且仅在 Linux 上构建时设置 USE_LINUX_CAP=1 时启用。支持的功能列表也取决于操作系统,并在传递无效功能名称或空名称时显示错误消息中枚举。可以传递多个功能,以逗号分隔。其中常用的有 "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”。
此设置仅在内置 OpenSSL 支持时可用。它设置描述了在 SSL/TLS 握手期间(直到 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 握手期间协商的密码算法(“密码套件”)列表的默认字符串,适用于所有未明确定义其密码套件的 "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-options,以强制应用于所有 "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-options,以强制应用于所有 "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 支持时可用。它设置了在 SSL/TLS 握手期间使用临时 Diffie-Hellman (DHE) 密钥交换时使用的默认 DH 参数,适用于所有未明确定义其参数的 "bind" 行。如果绑定证书文件中包含自定义 DH 参数,它将被覆盖。如果未通过 ssl-dh-param-file 或直接在证书文件中指定自定义 DH 参数,则 DHE 密码将不被使用,除非设置了 tune.ssl.default-dh-param。在后一种情况下,将使用指定大小的预定义 DH 参数。已知自定义参数更安全,因此建议使用它们。自定义 DH 参数可以使用 OpenSSL 命令 "openssl dhparam <size>" 生成,其中大小应至少为 2048,因为 1024 位 DH 参数不应再被视为安全。
此设置仅在内置 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、颁发者、密钥。"bundle":当配置中指定的文件不存在时,HAProxy 将尝试加载“证书捆绑包”。证书捆绑包仅在前端侧进行管理,不适用于后端证书。从 HAProxy 2.3 开始,捆绑包不再加载到相同的 OpenSSL 证书存储中,而是将每个证书加载到单独的存储中,这等效于声明多个 "crt"。需要 OpenSSL 1.1.1 才能实现此功能。这意味着捆绑包现在仅用于向后兼容性,不再是进行混合 RSA/ECC 绑定配置的强制要求。要将这些 PEM 文件关联到 HAProxy 识别的“证书捆绑包”中,它们必须按以下方式命名:所有要捆绑的 PEM 文件必须具有相同的基本名称,并带有一个指示密钥类型的后缀。目前支持三个后缀:rsa、dsa 和 ecdsa。例如,如果 www.example.com 有两个 PEM 文件,一个 RSA 文件和一个 ECDSA 文件,它们必须命名为:“example.pem.rsa”和“example.pem.ecdsa”。文件名的第一部分是任意的;只有后缀很重要。要将此捆绑包加载到 HAProxy 中,只需指定基本名称
示例
bind :8443 ssl crt example.pem
请注意,后缀不会提供给 HAProxy;这会告诉 HAProxy 查找证书捆绑包。HAProxy 将加载捆绑包中的所有 PEM 文件,就好像它们在多个 "crt" 中单独配置一样。捆绑包加载不再影响目录加载,因为文件是单独加载的。在 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 时,处理器都会重新进入睡眠状态或长时间提供给另一个虚拟机,这会导致过高的延迟。此选项提供了一种解决方案,通过始终在轮询器上使用 null 超时来防止处理器进入睡眠状态。这会显著降低延迟(观察到 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 的最大值。同样,命令行 "-n" 参数允许在运行时绕过 SYSTEM_MAXCONN 限制(如果设置)。当达到 maxconn 时,代理将停止接受连接。进程软文件描述符限制(可以通过 "ulimit -n" 命令获取)会根据提供的 maxconn 自动调整。另请参阅 "ulimit-n"。注意:"select" 轮询器在某些平台上无法可靠地使用超过 1024 个文件描述符。如果您的平台仅支持 select 并在启动时报告 "select FAILED",则需要减小 maxconn 直到它工作(通常略低于 500)。如果未设置 maxconn 值,它将根据当前文件描述符限制(由 "ulimit -nH" 命令报告,我们取硬限制和软限制之间的最大值)自动计算,然后自动值可能会被 "fd-hard-limit" 和内存限制(如果通过 "-m" 命令行选项强制执行后者)减小。自动值还取决于缓冲区大小、分配给压缩的内存、SSL 缓存大小以及是否使用 SSL 和相关的 maxsslconn(也可以是自动的)。
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 进行,且没有风险,并将考虑启用它的侧(前端、后端、两者)。
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"。
禁用“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_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" 使用 OPENSSL 函数 ENGINE_set_default_string() 设置 ENGINE 将提供的默认算法。值为 "ALL" 表示引擎用于所有加密操作。如果未指定算法列表,则使用 "ALL" 值。可以指定逗号分隔的不同算法列表,包括:RSA、DSA、DH、EC、RAND、CIPHERS、DIGESTS、PKEY、PKEY_CRYPTO、PKEY_ASN1。这与 openssl 配置文件使用的格式相同:https://www.openssl.org/docs/man1.0.2/apps/config.html HAProxy 2.6 版默认构建中禁用了对引擎的支持。此选项仅在 HAProxy 已构建支持时可用。如果需要 ssl-engine,可以使用 USE_ENGINE=1 标志重新构建 HAProxy。
向 SSL 上下文添加 SSL_MODE_ASYNC 模式。如果使用支持异步的 SSL 引擎,这将启用异步 TLS I/O 操作。当前实现最多支持 32 个引擎。Openssl ASYNC API 不支持移动读/写缓冲区,并且与 HAProxy 的缓冲区管理不兼容。因此,在读/写操作上禁用了异步模式(它仅在初始和重新协商握手期间启用)。
启用('on')或禁用('off')小程序(applet)的数据零拷贝转发。默认启用。
为每个进程可分配的缓冲区数量设置一个硬限制。默认值为零,表示无限制。该限制将自动重新调整以满足紧急情况下的保留缓冲区,这样用户就不必进行复杂的计算。强制设置此值对于限制进程可能占用的内存量,同时保持正常的行为特别有用。当达到此限制时,请求缓冲区的任务会等待另一个缓冲区被释放。只要限制合理,大多数情况下等待时间非常短且不易察觉。然而,一些历史上的限制在不同版本中削弱了这一机制,已知在某些持续短缺的情况下,一些任务可能会冻结直到超时,因此在非严格必要时,最好避免使用此选项。
设置每个线程预分配并保留的缓冲区数量,这些缓冲区仅在内存分配失败导致的内存短缺情况下使用。最小值为 0,默认值为 4。除非核心开发人员出于非常具体的原因建议更改,否则用户没有理由更改此值。
将缓冲区大小设置为此大小(以字节为单位)。较低的值允许在相同内存量中共存更多流,而较高的值允许某些具有非常大 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。
tune.disable-fast-forward [ EXPERIMENTAL ]
禁用数据快速转发。这是一种通过将数据直接从一侧传递到另一侧而不唤醒流来优化数据转发的机制。通过此指令,可以禁用此优化。请注意,它还禁用了任何内核 TCP 拼接以及零拷贝转发。此命令不适用于常规使用,通常只会在复杂的调试会话中由开发人员建议使用。因此,它在内部被标记为实验性的,这意味着 "expose-experimental-directives" 必须在此指令之前的行上出现。
全局禁用数据的零拷贝转发。这是一种通过避免使用通道缓冲区来优化数据快速转发的机制。通过此指令,可以禁用此优化。注意,它还禁用了任何内核 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.frontend.glitches-threshold 的情况下无效。另请参阅全局参数 "tune.h2.fe.glitches-threshold" 和 "tune.quic.frontend.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 ~= 10.7亿)之外,没有其他限制。大约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中,通常通过在“bind”行上使用“shards”设置来启用此功能,该设置默认为1,表示每个监听器在进程中都是唯一的。在具有多个处理器的系统上,将默认设置更改为“by-thread”可能更方便,以便始终为每个线程创建一个监听套接字,或者更改为“by-group”,以便始终为每个线程组创建一个监听套接字。使用“by-thread”时要小心文件描述符的使用,因为每个监听器将需要与线程数一样多的套接字。此外,某些操作系统(例如FreeBSD)限制在同一地址上最多只有256个套接字。请注意,“by-group”对于涉及单个线程组的默认配置将等同于“by-process”,并且在不支持此机制的系统上将回退到共享同一个套接字。对于不支持多个绑定的系统或套接字家族,默认是“by-group”并回退到“by-process”。
tune.listener.multi-queue { on | fair | off }
启用('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 脚本将布尔型 HAProxy 样本正确地处理为布尔值后,将此选项设置为“normal”。此设置必须在任何“lua-load”或“lua-load-per-thread”指令之前设置,否则将被忽略。
“burst”执行超时适用于任何 Lua 处理程序。如果处理程序在超时前未能完成或让步,它将被中止,以防止线程争用,防止流量长时间未得到服务,并最终防止进程因看门狗介入而崩溃。与其他累积让步的 Lua 超时不同,burst-timeout 将确保单个 Lua 执行窗口中花费的时间不超过配置的超时。这里的让步意味着 Lua 执行通过显式调用 lua-yielding 函数(如 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)多路复用器的数据零拷贝转发。要使用此功能,还必须配置内核拼接。默认启用。
启用('on')或禁用('off')用于 QUIC 连接的 HyStart++ (RFC 9406) 算法,作为拥塞控制算法慢启动阶段的替代方案,该阶段可能导致高丢包率。默认禁用。
定义Cubic拥塞控制算法真正考虑丢失事件所需的丢失数据包数量。通常,任何丢失事件都被认为是拥塞的结果,足以让Cubic从较小的窗口重新开始。但实验表明,丢失的原因多种多样,根本不是由拥塞引起的,可以简单地归类为虚假丢失,对于这些丢失,调整窗口将不起作用,只会减慢通信速度。无线电信号差、乱序传输、客户端CPU使用率高导致随机延迟以及系统定时器不精确都可能是常见原因。此设置允许Cubic对虚假丢失更加宽容,通过更改两个ACK之间累积丢失的最小数量以被视为丢失事件,默认值为1。实验观察到了一些显著的增益,但总是伴随着重传浪费的带宽增加,以及拥塞链路饱和的风险增加。值2可以用于短时间比较一些指标。在没有专家事先分析情况的情况下,切勿超过2。默认值和最小值是1。始终使用1。
禁用 QUIC 发送的步调支持。步调的目的是平滑数据发送以减少网络丢失。在大多数情况下,它将通过避免重传显著提高网络吞吐量。但是,对于具有非常高带宽/低延迟特性的网络,禁用它可能很有用,以防止不必要的延迟并降低 CPU 消耗。另请参阅“quic-cc-algo”绑定选项。
禁用UDP GSO发送。此内核功能允许通过单个系统调用发送多个数据报,这对于大数据传输更有效。在开发人员建议怀疑发送有问题时,禁用此功能可能很有用。
设置前端连接上故障数量的阈值,一旦达到该阈值,连接将自动终止。这允许自动终止行为异常的连接,而无需为其编写显式规则。默认值为零,表示未设置阈值,因此任何事件都不会导致连接关闭。请注意,某些 QUIC 客户端可能会在长时间连接中偶尔导致一些故障,因此任何非零值此处可能都应该在数百或数千范围内才能有效,而不会影响轻微异常的客户端。也可以通过使用“tune.glitches.kill.cpu-usage”仅在 CPU 使用率超过某个水平时终止连接。
此设置是 QUIC 前端连接上空中数据字节数的硬性限制。它被重用为 initial_max_data 传输参数的值。它直接影响对等体的上传带宽,具体取决于延迟和 haproxy 中每个连接的内存消耗。默认情况下,该值设置为 0,表示它必须自动生成为 max-streams-bidi 和 bufsize 的乘积。例如,如果后端应用程序依赖于高延迟网络上的大量上传,则可以增加此值。
设置前端的 QUIC max_idle_timeout 传输参数(以毫秒为单位),该参数确定了连接在由两个端点宣告的两个 max_idle_timeout 值推导出的有效时间段内保持不活动后,静默关闭的时间段:- 如果两个值都不为空,则为两个值中的最小值,- 如果只有一个不为空,则为最大值,- 如果两个值都为空,则禁用此功能。默认值为 30000。
为前端设置 QUIC initial_max_streams_bidi 传输参数。这是远程对等体将被授权打开的双向流的初始最大数量。这决定了并发客户端请求的数量。默认值为 100。请注意,如果降低此值,可能会限制流在接收时的缓冲能力,从而导致上传吞吐量不佳。可以通过增加 tune.quic.frontend.max-data-size 设置来纠正。
设置 QUIC 协议栈在传输层用于发送的最大可用内存量。这既是飞行中字节的限制,也是多路复用器输出缓冲区的限制。请注意,为防止线程竞争,此限制并非严格执行,因此在某些情况下可能会超过。此外,每个连接将始终能够使用至少 2 个数据报的窗口,因此应与适当的 maxconn 结合使用。
此设置允许配置每个流传输中的数据字节数的硬限制。它以相对于“tune.quic.frontend.max-data-size”设置的百分比表示,结果向上取整到 bufsize。默认值为 90。这适用于最常见的 Web 场景,即上传仅针对一个或几个流执行,而其余流仅用于下载。如果 max-data-size 连接限制保持在合理水平,它将确保只有一部分打开的流可以分配到其最大容量。如果应用程序并行使用许多上传流并存在这些流之间的不公平问题,则降低此比例以增加公平性并减少每个流的带宽可能是有意义的。
设置单个 QUIC 连接拥塞控制器的默认最大窗口大小。该值必须写为整数,可选用后缀“k”、“m”或“g”。它必须介于 10k 和 4g 之间。QUIC 多路复用器还使用当前拥塞窗口大小来确定是否可以在数据发送时分配新的流缓冲区。因此,最大拥塞窗口大小也作为此分配器的限制。默认值为 480k。另请参阅“quic-cc-algo”绑定选项。
设置单个 QUIC 帧可以被标记为丢失的限制。如果超过此限制,连接将被视为失败并立即关闭。默认值为 10。
tune.quic.reorder-ratio <0..100, in percent>
应用于计算出的数据包重排阈值的比率。如果太小,可能会触发高丢包检测。默认值为 50。
一旦半开连接数达到此数值,将为所有已配置的 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.socket-owner { connection | listener }
全局指定QUIC连接如何使用套接字进行接收/发送操作。连接可以共享监听套接字,也可以每个连接分配自己的套接字。当设置默认“connection”值时,每个QUIC连接将分配一个专用套接字。此选项是实现大量QUIC流量最佳性能的首选方案。这也是确保QUIC连接软停止(soft-stop)在没有数据丢失的情况下正确进行,并有效处理sendto()操作期间瞬时错误情况的唯一方法。然而,这依赖于UDP网络堆栈的一些高级功能。如果您的平台被认为不兼容,haproxy将在启动时自动切换到“listener”模式。请注意,在特权端口上运行的QUIC监听器可能需要以uid 0运行,或者一些OS特定的调整以允许目标uid绑定此类端口,例如系统能力。另请参阅全局指令“setcap”。“listener”值表示QUIC传输将在共享监听套接字上进行。此选项对于小流量可能是一个很好的折衷方案,因为它可以减少FD消耗。然而,如果监听器在大量线程或大量QUIC连接之间共享,则由于较高的CPU使用率,性能将不是最佳的。此设置与每个“quic-socket”绑定选项结合应用。如果在全局调优中使用“connection”模式,它将为每个监听器激活,除非其绑定选项设置为“listener”。但是,如果在全局中使用“listener”,它将强制在每个监听器实例上,无论其单独配置如何。
启用('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 是一系列行,其格式如下:<Label> <space> <ClientRandom> <space> <Secret> ClientRandom 由 %[ssl_fc_client_random,hex] 样本获取提供,secret 和 Label 可以在下面的数组中找到。您需要生成一个包含此数组中所有标签的 SSLKEYLOGFILE。以下样本获取是十六进制字符串,无需转换。SSLKEYLOGFILE Label | Secrets 的样本获取 --------------------------------|----------------------------------------- CLIENT_EARLY_TRAFFIC_SECRET | %[ssl_xx_client_early_traffic_secret] CLIENT_HANDSHAKE_TRAFFIC_SECRET | %[ssl_xx_client_handshake_traffic_secret] SERVER_HANDSHAKE_TRAFFIC_SECRET | %[ssl_xx_server_handshake_traffic_secret] CLIENT_TRAFFIC_SECRET_0 | %[ssl_xx_client_traffic_secret_0] SERVER_TRAFFIC_SECRET_0 | %[ssl_xx_server_traffic_secret_0] EXPORTER_SECRET | %[ssl_xx_exporter_secret] EARLY_EXPORTER_SECRET | %[ssl_xx_early_exporter_secret] 这些获取存在于前端 (fc) 或后端 (bc) 侧,将“xx”替换为“fc”或“bc”以使用正确的侧。这仅适用于 OpenSSL 1.1.1,并且对 TLS1.3 会话有用。如果您想使用 TLS < 1.3 生成 SSLKEYLOGFILE 的内容,您只需此行:“CLIENT_RANDOM %[ssl_fc_client_random,hex] %[ssl_fc_session_key,hex]” 一个完整的密钥日志可以通过这种方式生成日志格式,尽管这对于 syslog 来说并不理想:log-format "CLIENT_EARLY_TRAFFIC_SECRET %[ssl_bc_client_random,hex] %[ssl_bc_client_early_traffic_secret]\n CLIENT_HANDSHAKE_TRAFFIC_SECRET %[ssl_bc_client_random,hex] %[ssl_bc_client_handshake_traffic_secret]\n SERVER_HANDSHAKE_TRAFFIC_SECRET %[ssl_bc_client_random,hex] %[ssl_bc_server_handshake_traffic_secret]\n CLIENT_TRAFFIC_SECRET_0 %[ssl_bc_client_random,hex] %[ssl_bc_client_traffic_secret_0]\n SERVER_TRAFFIC_SECRET_0 %[ssl_bc_client_random,hex] %[ssl_bc_server_traffic_secret_0]\n EXPORTER_SECRET %[ssl_bc_client_random,hex] %[ssl_bc_exporter_secret]\n EARLY_EXPORTER_SECRET %[ssl_bc_client_random,hex] %[ssl_bc_early_exporter_secret]"
设置缓存的 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。使用此设置可以更改该值并忽略构建时传递的值。在将复杂配置移植到 HAProxy 时可能需要增加此值,但请用户注意其成本:每个条目每个连接占用 16 字节,每个请求占用 16 字节,所有这些都需要为所有请求分配和清零,即使未使用。因此,值为 10 将使每个请求的内存消耗增加 320 字节,并导致该内存在每个请求时都被擦除,这确实会对 CPU 产生可测量的影响。相反,当不使用 "track-sc" 规则时,可以降低该值(0 是有效的,可以完全禁用粘性计数器)。
默认情况下,我们不会尝试使用其他线程组的空闲连接。但是,这可以更改。<值> 的有效值为:“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 毫秒之间(含)。较低的值会频繁触发警告,而较高的值则很少触发。看门狗无论如何都会在运行失控任务两次未响应一秒钟后将其杀死,因此 1000 毫秒的警告延迟通常不会触发任何警告。建议将值保持在 10 毫秒到 100 毫秒之间,以检测可能降低用户体验、导致长时间响应或交互式会话卡顿的配置异常。例如,设计不良的 Lua 样本获取函数执行大量计算,或非常大的 map_reg 或 map_regm 映射文件具有非常高的评估成本,都可能导致此类问题。相比之下,一次 TLS 握手可能耗时 1 到 2 毫秒,压缩一个 16KB 的 HTTP 响应缓冲区大约需要 1 毫秒。输出包含违规任务的线程转储,其中包含回溯和一些上下文,有助于找出时间花费在哪里。
设置此选项后,如果在处理和应用配置时发出任何警告,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”是两个不同的代理。从历史上看,所有代理名称都可以重叠,只是在日志中造成了麻烦。自从引入内容切换以来,具有重叠功能(前端/后端)的两个代理必须具有不同的名称。然而,前端和后端共享相同的名称仍然是允许的,因为这种配置似乎很常见。目前,支持两种主要的代理模式:“tcp”,也称为第 4 层,和“http”,也称为第 7 层。在第 4 层模式下,HAProxy 只是在两端之间转发双向流量。在第 7 层模式下,HAProxy 分析协议,并可以通过允许、阻止、切换、添加、修改或删除请求或响应中的任意内容(基于任意条件)来与其交互。在 HTTP 模式下,应用于流经连接的请求和响应的处理取决于前端的 HTTP 选项和后端的 HTTP 选项的组合。HAProxy 支持 3 种连接模式:- KAL:保持活动(“option http-keep-alive”),这是默认模式:所有请求和响应都经过处理,连接在响应和新请求之间保持打开但空闲。- SCL:服务器关闭(“option http-server-close”):在接收到响应结束时,面向服务器的连接关闭,但面向客户端的连接保持打开。- CLO:关闭(“option httpclose”):在响应结束时关闭连接,并在两个方向添加“Connection: close”。应用于通过前端和后端连接的有效模式可以通过以下矩阵根据两种代理模式确定,但简而言之,这些模式是对称的,keep-alive 是最弱的选项,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. 代理关键字矩阵

支持以下关键字列表。其中大多数只能在有限的章节类型中使用。有些被标记为“已弃用”,因为它们继承自可能令人困惑或功能受限的旧语法,并且有新的推荐关键字来替换它们。带有“(*)”标记的关键字可以使用“no”前缀可选地反转,例如“no option contstats”。当选项已默认启用,但必须针对特定实例禁用时,这很有意义。此类选项也可以加上“default”前缀,以便无论在之前的“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
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 abortoncloseX XX
(*)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 
(*)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 监听器,backlog 为活动握手的最大数量和等待接受的连接设置了一个共享限制。握手阶段主要依赖于与远程对等体的网络延迟,而第二阶段则完全取决于 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”来使用转换器、细化评估或用于从局部变量中提取数据等。当数据不可用时,将应用轮询。此算法默认是静态的,这意味着即时更改服务器权重将无效,但可以通过使用“hash-type”进行更改。此算法不适用于 LOG 模式下的后端,请改用“log-hash”。source 源 IP 地址被哈希并除以正在运行的服务器的总权重,以指定哪个服务器将接收请求。这确保了只要没有服务器宕机或启动,相同的客户端 IP 地址将始终到达相同的服务器。如果由于正在运行的服务器数量变化而导致哈希结果发生变化,则许多客户端将被定向到不同的服务器。此算法通常用于 TCP 模式,其中不能插入 cookie。它也可以在 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 参数中指定的 URL 参数将在每个 HTTP GET 请求的查询字符串中查找。如果使用“check_post”修饰符,则当在 URL 中问号('?')后的查询字符串中找不到参数时,将在 HTTP POST 请求实体中搜索参数。消息体只有在收到指定数量的数据或请求缓冲区已满后才会开始分析。在极不可能使用分块编码的情况下,只会扫描第一个分块。由分块边界分隔的参数值可能会随机平衡(如果根本平衡)。此关键字曾经支持可选的 <max_wait> 参数,但现在已忽略。如果找到参数后跟等号('=')和值,则该值将被哈希并除以正在运行的服务器的总权重。结果指定哪个服务器将接收请求。这用于跟踪请求中的用户标识符,并确保只要没有服务器启动或关闭,相同的用户 ID 将始终发送到相同的服务器。如果没有找到值或没有找到参数,则应用轮询算法。请注意,此算法只能在 HTTP 后端中使用。此算法默认是静态的,这意味着即时更改服务器权重将无效,但可以通过使用“hash-type”进行更改。另请参阅上面的“hash”选项。hdr(<name>) HTTP 头部 <name> 将在每个 HTTP 请求中查找。与等效的 ACL 'hdr()' 函数一样,括号中的头部名称不区分大小写。如果头部不存在或不包含任何值,则改为应用轮询算法。一个可选的 'use_domain_only' 参数可用,用于将哈希算法缩减为主要域部分,并与某些特定头部(如 'Host')一起使用。例如,在 Host 值“haproxy.1wt.eu”中,只会考虑“1wt”。此算法默认是静态的,这意味着即时更改服务器权重将无效,但可以通过使用“hash-type”进行更改。另请参阅上面的“hash”选项。random random(<draws>) 将使用一个随机数作为一致哈希函数的键。这意味着服务器的权重受到尊重,动态权重更改立即生效,以及新服务器的添加。随机负载均衡在大型集群或服务器频繁添加或删除时很有用,因为它可以避免在这种情况下由轮询或最少连接可能导致的锤击效应。 hash-balance-factor 指令可用于进一步提高负载均衡的公平性,尤其是在服务器响应时间变化很大的情况下。当存在参数 <draws> 时,它必须是一个大于或等于一的整数值,表示在选择这些服务器中负载最少的服务器之前进行抽取的次数。事实证明,选择两个服务器中负载最少的那个足以显著提高算法的公平性,始终避免选择集群中负载最重的服务器,并消除一致列表不公平分布可能引起的任何偏差。较高的值 N 将以牺牲性能为代价去除 N-1 个负载最高的服务器。当值非常高时,算法将趋向于 leastconn 的结果,但速度会慢得多。默认值为 2,通常表现出非常好的分布和性能。此算法也称为“二选一的幂”算法,描述于此处:http://www.eecs.harvard.edu/~michaelm/postscripts/handbook2001.pdf 对于 LOG 模式下的后端,抽取的次数将被忽略,因为没有服务器负载的概念,因此只选择一个随机数。随机日志均衡在大型集群或服务器频繁从可用服务器池中添加或删除时很有用,因为它可以避免在这种情况下由轮询可能导致的锤击效应。rdp-cookie rdp-cookie(<name>) RDP cookie <name>(如果省略,则为“mstshash”)将在每个传入 TCP 请求中查找并哈希。与等效的 ACL 'req.rdp_cookie()' 函数一样,名称不区分大小写。此机制作为一种降级持久性模式很有用,因为它使得始终将同一用户(或同一会话 ID)发送到同一服务器成为可能。如果未找到 cookie,则改为使用正常的轮询算法。请注意,要使其正常工作,前端必须确保请求缓冲区中已存在 RDP cookie。为此,您必须使用 'tcp-request content accept' 规则与 'req.rdp_cookie_cnt' ACL 结合使用。此算法默认是静态的,这意味着即时更改服务器权重将无效,但可以通过使用“hash-type”进行更改。另请参阅上面的“hash”选项。log-hash 接受逗号分隔的转换器列表作为参数。这些转换器按顺序应用于输入日志消息,结果将被转换为字符串,然后根据配置的 hash-type 进行哈希。生成的哈希将用于在日志后端声明的服务器中选择目标服务器。此算法的目标是能够使用字符串转换器在最终日志消息中提取一个键,然后通过哈希将其粘性到同一服务器。目前仅支持“基于映射”的哈希。此算法仅适用于 LOG 模式下的后端,对于其他模式,请改用“hash”。sticky 尽可能粘性到同一服务器。可用服务器列表中的第一个服务器接收所有日志消息。当服务器宕机时,列表中的下一个服务器取代其位置。当之前宕机的服务器重新上线时,它被添加到列表的末尾,以便粘性服务器在它宕机之前不会改变。<arguments> 是一个可选的参数列表,某些算法可能需要。目前,只有“url_param”、“uri”和“log-hash”支持可选参数。
当没有设置其他算法、模式或选项时,后端的负载均衡算法默认为 roundrobin。每个后端只能设置一次算法。对于需要相同连接的认证方案,如 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 # 发送所有日志到 mylog-rrb backend log backend@mylog-hash local0 # 发送所有日志到 mylog-hash backend backend mylog-rrb mode log balance roundrobin server s1 udp@127.0.0.1:514 # 将接收 50% 的日志消息 server s2 udp@127.0.0.1:514 backend mylog-hash mode log # 提取日志消息末尾的 "METHOD URL PROTO", # 并让 haproxy 对其进行哈希,以便从 # 类似请求生成的日志消息发送到相同的 syslog 服务器:balance log-hash 'field(-2,\")' # 服务器列表在此 server s1 127.0.0.1:514 #... 注意:在使用“url_param”的“check_post”扩展时,必须考虑以下注意事项和限制: - 所有 POST 请求都符合考虑条件,因为无法确定参数是否会在可能包含二进制数据的主体或实体中找到。因此,可能需要另一种方法来限制对主体中没有 URL 参数的 POST 请求的考虑。(参见 acl http_end) - 使用大于请求缓冲区大小的 <max_wait> 值没有意义且无用。缓冲区大小在构建时设置,默认为 16 KB。 - 不支持 Content-Encoding,参数搜索可能会失败;负载均衡将回退到 Round Robin。 - 不支持 Expect: 100-continue,负载均衡将回退到 Round Robin。 - Transfer-Encoding (RFC7230 3.3.1) 仅在第一个分块中受支持。如果整个参数值不在第一个分块中,则服务器选择是未定义的(实际上,由第一个分块中实际出现的少量内容定义)。 - 此功能不支持生成 100、411 或 501 响应。 - 在某些情况下,请求“check_post”可能会尝试扫描消息体的全部内容。扫描通常在找到线性空白或控制字符时终止,这表示可能是 URL 参数列表的结束。对于 SGML 类型消息体,这可能不是问题。
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.socket-owner" 在连接上。否则,QUIC 连接将通过监听套接字进行多路复用。另一种替代方法是将 QUIC 监听器实例复制到多个线程中,例如使用 "shards" 关键字以至少减少线程争用。 - 'quic6@' -> 地址解析为 IPv6 并使用 UDP 协议。IPv4 上的 QUIC 性能说明也适用。 - 'rhttp@' [ 实验性 ] -> 用于反向 HTTP。地址必须是格式为 '<backend>/<server>' 的服务器。该服务器将用于实例化与远程地址的连接。监听器将尝试维护 "nbconn" 连接。这是一个实验性功能,需要在此绑定之前的一行中包含 "expose-experimental-directives"。您可能希望在地址参数中引用一些环境变量,请参阅 第 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*> 是同一行上声明的所有套接字的通用参数列表。这些众多参数取决于操作系统和构建选项,并有专门的部分介绍。请参阅 第 5 节 以获取更多详细信息。
可以指定一个由逗号分隔的地址:端口组合列表。然后前端将在所有这些地址上进行监听。前端可以监听的地址和端口数量没有固定限制,同样,前端中的 "bind" 语句数量也没有限制。
示例
listen http_proxy bind :80,:443 bind 10.0.0.1:10080,10.0.0.1:10443 bind /var/run/ssl-frontend.sock user root mode 600 accept-proxy listen http_https_proxy bind :80 bind :443 ssl crt /etc/haproxy/site.pem listen http_https_proxy_explicit bind ipv6@:80 bind ipv4@public_ssl:443 ssl crt /etc/haproxy/site.pem bind unix@ssl-frontend.sock user root mode 600 accept-proxy listen external_bind_app1 bind "fd@${FD_APP1}" listen h3_quic_proxy bind quic4@10.0.0.1:8888 ssl crt /etc/mycrt
注意:关于 Linux 的抽象命名空间套接字,“abns” HAProxy 套接字使用整个 sun_path 长度作为地址长度。其他一些程序(如 socat)默认只使用字符串长度。在 socat 中向任何抽象套接字定义传递选项 “,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" 头,表示响应已压缩(参见压缩卸载) * 响应包含无效的 "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 在客户端和 HAProxy 之间存在缓存时,建议将此选项与 insert 模式结合使用,因为它确保如果需要插入 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。它只适用于插入模式的 cookie。当 cookie 发送给客户端时,也会发送该 cookie 发出的日期。在进一步呈现此 cookie 时,如果日期比参数指示的延迟(以秒为单位)更早,则将忽略它。否则,如果需要在响应发送给客户端时,它将刷新。这对于防止从未关闭浏览器的用户在同一服务器上停留过长时间(例如,在农场大小更改后)特别有用。当设置此选项并且 cookie 没有日期时,它总是被接受,但在响应中会刷新。这保持了管理员访问其站点的能力。日期在未来超过 24 小时的 cookie 将被忽略。这样做可以使管理员修复时区问题,而不会冒险将用户踢出站点。 maxlife 此选项允许在一段时间后忽略插入的 cookie,无论它们是否在使用中。它只适用于插入模式的 cookie。当 cookie 首次发送给客户端时,也会发送该 cookie 发出的日期。在进一步呈现此 cookie 时,如果日期比参数指示的延迟(以秒为单位)更早,则将忽略它。如果请求中的 cookie 没有日期,则接受它并设置日期。日期在未来超过 24 小时的 cookie 将被忽略。这样做可以使管理员修复时区问题,而不会冒险将用户踢出站点。与 maxidle 相反,此值不会刷新,只有首次访问日期才算数。maxidle 和 maxlife 可以同时使用。这对于防止从未关闭浏览器的用户在同一服务器上停留过长时间(例如,在农场大小更改后)特别有用。这比 maxidle 方法更强,因为它强制在某个绝对延迟后重新分派。 dynamic 激活动态 cookie。使用时,将根据服务器的 IP 和端口以及在 "dynamic-cookie-key" 后端指令中指定的密钥,为每个服务器动态创建一个会话 cookie。每次 IP 地址更改时,cookie 都会重新生成,并且只为 IPv4/IPv6 生成。 attr 此选项告诉 HAProxy 在插入 cookie 时添加一个额外的属性。属性值可以包含除控制字符或 ";" 之外的任何字符。此选项可以重复。
每个 HTTP 后端只能有一个持久性 cookie,并且可以在默认部分中声明。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 节
示例
default-server inter 1000 weight 13
default_backend <backend>
指定当没有匹配的 “use_backend” 规则时使用的后端。可在以下上下文中使用: tcp, http

可在以下部分中使用

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<backend> 是要使用的后端的名称。
在使用“use_backend”关键字在前端和后端之间进行内容切换时,指明在没有规则匹配时将使用哪个后端通常很有用。这通常是动态后端,它将捕获所有未确定的请求。
示例
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" 用于禁用实例,主要是为了释放监听端口或临时禁用服务。实例仍将创建并检查其配置,但将以“停止”状态创建,并在统计信息中显示为该状态。它将不会接收任何流量,也不会发送任何健康检查或日志。通过在“defaults”部分添加 "disabled" 关键字,可以一次禁用多个实例。
dispatch <address>:<port>
设置一个默认服务器地址。可在以下上下文中使用: tcp, http

可在以下部分中使用

defaultsfrontendlistenbackend

no

no

yes

yes
参数
<address> 是默认服务器的 IPv4 地址。或者,也支持可解析的主机名,但此名称将在启动期间解析。<ports> 是一个强制性的端口规范。所有连接都将发送到此端口,并且不允许像普通服务器那样使用端口偏移量。
关键字 "dispatch" 指定一个默认服务器,用于在没有其他服务器可以接受连接时使用。过去,它用于将非持久连接转发到辅助负载均衡器。由于其简单的语法,它也被用于简单的 TCP 中继。建议为了更清晰而不要使用它,而是使用 "server" 指令。
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
参数:
关键字 "enabled" 用于在默认设置为 "disabled" 时显式启用实例。这种情况非常少见。
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。
示例
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” 指令手动声明所有错误文件完全相同。
示例
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 会自动将其设置为所有可能分支到此后端的前端 (基于 "use_backend" 和 "default_backend" 规则) 的 maxconn 之和的 10%。这样,可以安全地将其保留为未设置。但是,涉及动态名称的 "use_backend" 不会被计算在内,因为无法知道它们是否会匹配。
示例
# 服务器将接受 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 个字符。所有字母数字值和 '.'、':'、'-' 和 '_' 字符都是有效的。
为有界负载一致性哈希指定平衡因子。可在以下上下文中使用: 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 这是以太网、gzip、PNG 等中使用的最常见的 CRC32 实现。它比其他实现慢,但可能提供更好的分布或更不可预测的结果,尤其是在字符串上使用时。 none 不对键进行哈希,键将直接用作哈希,这对于手动使用转换器对键进行哈希并让 haproxy 直接使用结果很有用。 <modifier> 指示在对键进行哈希后应用的可选方法: avalanche 此指令指示上述哈希函数的结果不应以原始形式使用,而必须首先应用 4 字节的完全雪崩哈希。此步骤的目的是混合前一个哈希的结果位,以避免当输入包含某些有限值或服务器数量是哈希组件之一(SDBM 为 64,DJB2 为 33)的倍数时出现任何不希望的效果。启用雪崩往往会使结果更不可预测,但它也不像使用原始函数那样平滑。可能需要对某些工作负载进行一些测试。此哈希是 Bob Jenkins 提出的众多哈希之一。
默认的哈希类型是“map-based”,建议在大多数情况下使用。默认的函数是“sdbm”,函数的选择应基于被哈希值的范围。
http-after-response <动作> <选项...> [ { if | unless } <条件> ]
对所有第 7 层响应(服务器、小程序/服务和内部响应)进行访问控制。可在以下上下文中使用: http

可在以下部分中使用

defaultsfrontendlistenbackend
是(!)
yes(!)

yes

yes

yes
http-after-response 语句定义了一组适用于第 7 层处理的规则。这些规则在前端、监听或后端部分中遇到时,按照其声明顺序进行评估。由于这些规则适用于响应,因此后端规则首先应用,然后是前端规则。任何规则都可以选择性地后跟一个基于 ACL 的条件,在这种情况下,只有当条件评估为真时才会评估该规则。与 http-response 规则不同,这些规则适用于所有响应,包括服务器响应和 HAProxy 生成的所有响应。这些规则在响应分析结束、数据转发阶段之前进行评估。条件在操作执行之前进行评估,并且操作只执行一次。因此,如果操作更改了作为条件一部分检查的元素,则不会出现问题。这也意味着多个操作可以依赖相同的条件,因此更改条件评估的第一个操作足以隐式禁用其余操作。例如,当尝试从各种来源向变量分配值而该变量为空时,就会使用此方法。每个实例的 "http-after-response" 语句数量没有限制。语法中 "http-after-response" 之后的第一个关键字是规则的操作,可选择后跟可变数量的操作参数。支持的操作及其各自的语法在第 4.3 节 "Actions" 中枚举(查找勾选 "HTTP Aft" 的操作)。此指令仅可用于命名默认部分,不可用于匿名部分。在默认部分中定义的规则在关联的代理部分中的规则之前进行评估。为了避免歧义,在这种情况下,同一个默认部分不能用于具有前端功能的代理和具有后端功能的代理。这意味着监听部分不能使用定义此类规则的默认部分。注意:在请求解析的早期阶段发出的错误由多路复用器在较低级别处理,在任何 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 或样本获取表达式。 addr <ip> 定义执行健康检查的 IP 地址。 send-proxy 通过 Socks4 代理发送 PROXY 协议字符串启用出站健康检查。 ssl 打开加密连接。 sni <sni> 指定通过 SSL 执行健康检查时使用的 SNI。 alpn <alpn> 定义使用 ALPN 宣传哪些协议。协议列表由逗号分隔的协议名称列表组成,例如:“h2,http/1.1”。如果未设置,则使用服务器 ALPN。 proto <name> 强制多路复用器的协议用于此连接。它必须是 HTTP 多路复用协议,并且必须在后端可用。可用协议列表在 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> 是一个自定义日志格式字符串(参见 第 8.2.6 节)。 on-error <fmt> 是可选的,可用于自定义在 expect 规则评估期间发生错误时在日志中报告的信息消息。<fmt> 是一个自定义日志格式字符串(参见 第 8.2.6 节)。 <match> 是一个关键字,指示如何在响应中查找特定模式。关键字可以是 "status"、“rstatus”、“hdr”、“fhdr”、“string”或“rstring”。关键字前面可以有一个感叹号 (“!”) 来否定匹配。感叹号和关键字之间允许有空格。有关支持的关键字的更多详细信息,请参见下文。 <pattern> 是要查找的模式。它可以是字符串、正则表达式或具有多个参数的更复杂模式。如果字符串模式包含空格,则必须使用通常的反斜杠 ('\') 进行转义。
默认情况下,"option httpchk" 认为响应状态 2xx 和 3xx 是有效的,而其他状态是无效的。当使用 "http-check expect" 时,它定义了什么是有效或无效的。一个后端中只支持一个 "http-check" 语句。如果服务器无法响应或超时,则检查显然失败。 可用的匹配项是: status <codes>:解析 <codes> 字符串中找到的状态码。它必须是逗号分隔的状态码列表或范围码。如果响应的状态码与列表中的任何状态码匹配或在任何范围内,则健康检查响应将被视为有效。如果 "status" 关键字带有 "!" 前缀,则如果状态码匹配,则响应将被视为无效。 rstatus <regex>:测试 HTTP 状态码的正则表达式。如果响应的状态码匹配该表达式,则健康检查响应将被视为有效。如果 "rstatus" 关键字带有 "!" 前缀,则如果状态码匹配,则响应将被视为无效。这主要用于检查多个代码。 hdr { name | name-lf } [ -m <meth> ] <name> [ { value | value-lf } [ -m <meth> ] <value>:测试 HTTP 响应头中指定的头模式。名称模式是强制性的,但值模式是可选的。如果未指定,则仅验证头的存在。<meth> 是匹配方法,应用于头名称或头值。支持的匹配方法有 "str"(精确匹配)、"beg"(前缀匹配)、"end"(后缀匹配)、"sub"(子字符串匹配)或 "reg"(正则表达式匹配)。如果未指定,则使用精确匹配方法。如果使用 "name-lf" 参数,则 <name> 将作为自定义日志格式字符串进行评估(参见 第 8.2.6 节)。如果使用 "value-lf" 参数,则 <value> 将作为日志格式字符串进行评估。这些参数不能与正则表达式匹配方法一起使用。最后,头值被视为逗号分隔列表。请注意,头名称的匹配不区分大小写。 fhdr { name | name-lf } [ -m <meth> ] <name> [ { value | value-lf } [ -m <meth> ] <value>:测试 HTTP 响应头中指定的完整头模式。它的作用与 "hdr" 关键字完全相同,只是测试完整的头值,逗号不被视为分隔符。 string <string>:测试 HTTP 响应体中的精确字符串匹配。如果响应体包含此精确字符串,则健康检查响应将被视为有效。如果 "string" 关键字带有 "!" 前缀,则如果响应体包含此字符串,则响应将被视为无效。这可用于在动态页面末尾查找强制性单词,或在检查页面上出现特定错误(例如堆栈跟踪)时检测故障。 rstring <regex>:测试 HTTP 响应体上的正则表达式。如果响应体匹配此表达式,则健康检查响应将被视为有效。如果 "rstring" 关键字带有 "!" 前缀,则如果响应体匹配该表达式,则响应将被视为无效。这可用于在动态页面末尾查找强制性单词,或在检查页面上出现特定错误(例如堆栈跟踪)时检测故障。 string-lf <fmt>:测试 HTTP 响应体中的自定义日志格式字符串(参见 第 8.2.6 节)匹配。如果响应体包含 <fmt> 评估结果的字符串(遵循日志格式规则),则健康检查响应将被视为有效。如果带有 "!" 前缀,则如果响应体包含该字符串,则响应将被视为无效。重要的是要注意,响应将被限制为由全局 "tune.bufsize" 选项定义的大小,默认为 16384 字节。因此,在使用 "string" 或 "rstring" 时,过大的响应可能不包含强制模式。如果绝对需要大响应,可以通过设置全局变量来更改默认最大大小。但是,值得记住的是,解析非常大的响应可能会浪费一些 CPU 周期,尤其是在使用正则表达式时,并且始终最好将检查集中在较小的资源上。在 http-check 规则集中,最后一个 expect 规则可以是隐式的。如果在最后一个 "http-check send" 之后没有指定 expect 规则,则定义一个隐式 expect 规则以匹配 2xx 或 3xx 状态码。这意味着如果没有 "http-check" 规则,只有 "option httpchk" 设置时,此规则也会被定义。最后,如果 "http-check expect" 与 "http-check disable-on-404" 结合使用,则当服务器响应 404 时,后者具有优先级。
示例
# 只接受状态码 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> 定义了规则评估失败时要报告的消息。 meth <method> 是请求使用的可选 HTTP 方法。未设置时,使用 "OPTIONS" 方法,因为它通常需要较少的服务器处理,并且易于从日志中筛选出来。可以使用任何方法,但不建议使用非标准方法。 uri <uri> 是可选的,并将 HTTP 请求中引用的 URI 设置为字符串 <uri>。它默认为 "/",几乎在任何服务器上都可默认访问,但可以更改为任何其他 URI。允许使用查询字符串。 uri-lf <fmt> 是可选的,并使用自定义日志格式 <fmt>(参见 第 8.2.6 节)设置 HTTP 请求中引用的 URI。它默认为 "/",几乎在任何服务器上都可默认访问,但可以更改为任何其他 URI。允许使用查询字符串。 ver <version> 是可选的 HTTP 版本字符串。它默认为 "HTTP/1.0",但有些服务器在 HTTP 1.0 中可能行为不正确,因此将其更改为 HTTP/1.1 有时会有帮助。请注意,Host 字段在 HTTP/1.1 中是强制性的,请使用 "hdr" 参数添加它。 hdr <name> <fmt> 添加 HTTP 标头字段,其名称在 <name> 中指定,其值由 <fmt> 定义,该 <fmt> 遵循 第 8.2.6 节 中描述的自定义日志格式规则。 body <string> 将由 <string> 定义的主体添加到 HTTP 健康检查期间发送的请求中。如果定义,则 "Content-Length" 标头会自动添加到请求中。 body-lf <fmt> 将由自定义日志格式 <fmt>(参见 第 8.2.6 节)定义的主体添加到 HTTP 健康检查期间发送的请求中。如果定义,则 "Content-Length" 标头会自动添加到请求中。
除了由 "option httpchk" 指令定义的请求行之外,此指令是向 HTTP 健康检查期间发送的请求添加一些头和可选正文的有效方式。如果定义了正文,则会自动添加关联的 "Content-Length" 头。因此,此头或 "Transfer-encoding" 头不应出现在 "http-check send" 提供的请求中。如果出现,它将被忽略。在 "option httpchk" 行的版本字符串之后添加头的旧技巧现已弃用。此外,"http-check send" 不支持 HTTP keep-alive。请记住,它会自动附加 "Connection: close" 头,除非已通过 hdr 条目配置了 Connection 头。请注意,Host 头和请求授权(当两者都定义时)会自动同步。这意味着当发送 HTTP 请求时,当 Host 插入到请求中时,请求授权会相应更新。因此,如果 Host 头值覆盖了配置的请求授权,请不要感到惊讶。另请注意,目前 HTTP/1.1 或更高版本的请求中不会自动添加 Host 头。您应该明确添加它。
在 HTTP 健康检查中启用状态头的发送。可在以下上下文中使用:tcp, http

可在以下部分中使用

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
当设置此选项时,HAProxy 将系统地发送一个特殊的头 "X-Haproxy-Server-State",其中包含一系列参数,指示每个服务器 HAProxy 如何看待它们。例如,当在无法访问 HAProxy 的情况下操作服务器时,操作员需要知道 HAProxy 是否仍然将其视为正常运行,或者服务器是否是集群中的最后一个时,可以使用此功能。该头由分号分隔的字段组成,第一个字段是一个单词("UP"、"DOWN"、"NOLB"),后面可能跟有在转换前有效检查总数,与统计界面中显示的一样。接下来的头采用 "<variable>=<value>" 的形式,以不特定的顺序指示统计界面中可用的一些值: - 变量 "address",包含后端服务器的地址。这对应于服务器声明中的 <address> 字段。对于 Unix 域套接字,它将读取 "unix"。 - 变量 "port",包含后端服务器的端口。这对应于服务器声明中的 <port> 字段。对于 Unix 域套接字,它将读取 "unix"。 - 变量 "name",包含后端名称,后跟斜杠 ("/"),然后是服务器名称。当在多个后端中检查服务器时可以使用此变量。 - 变量 "node",包含 HAProxy 节点的名称,如全局 "node" 变量中设置的,如果未指定,则为系统主机名。 - 变量 "weight",指示服务器的权重,一个斜杠 ("/"),以及集群的总权重(仅计算可用的服务器)。这有助于了解当服务器发生故障时是否有其他服务器可用于处理负载。 - 变量 "scur",指示服务器上当前的并发连接数,后跟斜杠 ("/"),然后是同一后端所有服务器上的总连接数。 - 变量 "qcur",指示服务器队列中当前的请求数。 应用程序服务器接收到的头示例: >>> 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> 是 HTTP 状态码。它必须指定。目前,HAProxy 能够生成代码 200、400、401、403、404、405、407、408、410、413、414、425、429、431、500、501、502、503 和 504。 content-type <type> 是响应内容类型,例如 "text/plain"。当配置了错误文件或有效负载为空时,此参数将被忽略,应省略。否则,必须定义。 default-errorfiles 为当前代理重置之前为状态 <code> 定义的错误消息。如果在后端上使用,则使用前端错误消息(如果已定义)。如果在前端上使用,则使用默认错误消息。 errorfile <file> 指定包含完整 HTTP 响应的文件。建议遵循常见做法,在文件名后附加 ".http",以避免人们将响应与 HTML 错误页面混淆,并使用绝对路径,因为文件在执行任何 chroot 之前读取。 errorfiles <name> 指定要用于导入状态码 <code> 错误消息的 http-errors 部分。如果找不到此类消息,则考虑代理的错误消息。 file <file> 指定用作响应有效负载的文件。如果文件不为空,其 content-type 必须设置为 "content-type" 的参数,否则,任何 "content-type" 参数都将被忽略。<file> 被视为原始字符串。 string <str> 指定用作响应有效负载的原始字符串。content-type 必须始终设置为 "content-type" 的参数。 lf-file <file> 指定用作响应有效负载的文件。如果文件不为空,其 content-type 必须设置为 "content-type" 的参数,否则,任何 "content-type" 参数都将被忽略。<file> 作为自定义日志格式进行评估(参见 第 8.2.6 节)。 lf-string <str> 指定用作响应有效负载的日志格式字符串。content-type 必须始终设置为 "content-type" 的参数。 hdr <name> <fmt> 将 HTTP 标头字段添加到响应中,其名称在 <name> 中指定,其值由 <fmt> 定义,该 <fmt> 遵循自定义日志格式规则(参见 第 8.2.6 节)。如果使用了错误文件,此参数将被忽略。
此指令可以替代 "errorfile" 使用,以定义自定义错误消息。与 "errorfile" 指令一样,它用于 HAProxy 检测并返回的错误。如果定义了错误文件,则在 HAProxy 启动时解析该文件,并且必须符合 HTTP 标准。生成的响应不能超过配置的缓冲区大小 (BUFFSIZE),否则将返回内部错误。最后,如果您考虑使用一些 http-after-response 规则来重写这些错误,则应提供预留的缓冲区空间(参见 "tune.maxrewrite")。文件与配置同时读取并保存在内存中。因此,即使进程 chrooted,错误也会继续返回,并且在进程运行时不考虑文件更改。注意:在请求解析的早期阶段发出的 400/408/500 错误由多路复用器在较低级别处理。在此级别不支持自定义格式。因此,只支持使用 "errorfile" 指令定义的静态错误消息。但是,此限制仅存在于请求头解析期间或两次事务之间。
http-request <action> [options...] [ { if | unless } <condition> ]
第 7 层请求的访问控制 可在以下上下文中使用:http

可在以下部分中使用

defaultsfrontendlistenbackend
是(!)
yes(!)

yes

yes

yes
http-request 语句定义了一组适用于第 7 层处理的规则。这些规则在前端、监听或后端部分中遇到时,按照其声明顺序进行评估。任何规则都可以选择性地后跟一个基于 ACL 的条件,在这种情况下,只有当条件评估为真时才会评估该规则。条件在操作执行之前进行评估,并且操作只执行一次。因此,如果操作更改了作为条件一部分检查的元素,则不会出现问题。这也意味着多个操作可以依赖相同的条件,因此更改条件评估的第一个操作足以隐式禁用其余操作。例如,当尝试从各种来源向变量分配值而该变量为空时,就会使用此方法。每个实例的 "http-request" 语句数量没有限制。语法中 "http-request" 之后的第一个关键字是规则的操作,可选择后跟可变数量的操作参数。支持的操作及其各自的语法在 第 4.3 节 "Actions" 中枚举(查找勾选 "HTTP Req" 的操作)。此指令仅可用于命名默认部分,不可用于匿名部分。在默认部分中定义的规则在关联的代理部分中的规则之前进行评估。为了避免歧义,在这种情况下,同一个默认部分不能用于具有前端功能的代理和具有后端功能的代理。这意味着监听部分不能使用定义此类规则的默认部分。
示例
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
http-response 语句定义了一组适用于第 7 层处理的规则。这些规则在前端、监听或后端部分中遇到时,按照其声明顺序进行评估。由于这些规则适用于响应,因此后端规则首先应用,然后是前端规则。任何规则都可以选择性地后跟一个基于 ACL 的条件,在这种情况下,只有当条件评估为真时才会评估该规则。条件在操作执行之前进行评估,并且操作只执行一次。因此,如果操作更改了作为条件一部分检查的元素,则不会出现问题。这也意味着多个操作可以依赖相同的条件,因此更改条件评估的第一个操作足以隐式禁用其余操作。例如,当尝试从各种来源向变量分配值而该变量为空时,就会使用此方法。每个实例的 "http-response" 语句数量没有限制。语法中 "http-response" 之后的第一个关键字是规则的操作,可选择后跟可变数量的操作参数。支持的操作及其各自的语法在 第 4.3 节 "Actions" 中枚举(查找勾选 "HTTP Res" 的操作)。此指令仅可用于命名默认部分,不可用于匿名部分。在默认部分中定义的规则在关联的代理部分中的规则之前进行评估。为了避免歧义,在这种情况下,同一个默认部分不能用于具有前端功能的代理和具有后端功能的代理。这意味着监听部分不能使用定义此类规则的默认部分。
示例
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
为了避免每个HTTP请求都为后端服务器建立新连接的开销,HAProxy尝试在连接使用后保持这些空闲连接打开。这些连接特定于一个服务器,存储在一个称为连接池的列表中,并按一组共同的关键属性进行分组。后续的HTTP请求将导致在关联的连接池中查找共享相同属性的兼容连接,并重用该连接,而不是建立新连接。可以通过“pool-max-conn”服务器关键字指定每个服务器保持的空闲连接数限制。未使用的连接会根据“pool-purge-delay”间隔定期清除。以下连接属性用于确定空闲连接是否适合在给定请求中重用: - 源地址和目标地址 - 代理协议 - TOS和标记套接字选项 - 连接名称,由“pool-conn-name”表达式(如果存在)的评估结果决定,否则由“sni”表达式决定。在某些情况下,由于额外的限制,不执行连接查找或重用。这由关键字参数指定的重用策略决定: - “never”:空闲连接从不在会话之间共享。可以强制使用此模式以取消从默认部分继承的不同策略,或用于故障排除。例如,如果一个旧的错误应用程序认为同一连接上的多个请求来自同一客户端,并且无法修复该应用程序,则可能需要在单个后端禁用连接共享。此类应用程序的一个例子是使用隧道模式下的cookie插入且不检查第一个请求之后的任何请求的旧HAProxy。 - “safe”:这是默认和推荐的策略。会话的第一个请求始终通过其自己的连接发送,只有后续请求才可以通过其他现有连接分派。这确保了在服务器发送请求时关闭连接的情况下,浏览器可以决定静默重试。由于它与常规的keep-alive完全等效,因此不应有副作用。对于使用Head-of-line blocking协议(后端为h2或fcgi)的连接,还有特殊处理。在这种情况下,当至少处理一个流时,使用的连接将保留以处理同一会话的流。当不再处理流时,连接被释放并可以重用。 - “aggressive”:此模式可能在所有服务器不一定已知且希望通过现有连接交付大多数首次请求的Web服务环境中很有用。在这种情况下,首次请求仅通过至少重用过一次的现有连接交付,证明服务器正确支持连接重用。它仅应在确信客户端可以偶尔重试失败请求,并且激进连接重用的好处显著大于罕见连接失败的缺点时使用。 - “always”:此模式仅在服务器路径已知在释放连接后不会很快中断现有连接时推荐使用。它允许会话的第一个请求发送到现有连接。当后端是缓存集群时,这比“safe”策略可以显著提高性能,因为此类组件往往表现出一致的行为,并将受益于连接共享。建议在这种模式下“http-keep-alive”超时保持较低,以便没有死连接仍然可用。在大多数情况下,这将导致与“aggressive”相同的性能增益,但风险更大。仅当它改善“aggressive”情况时才应使用。另请注意,某些带有虚假身份验证方案(依赖于连接)的连接(如NTLM)如果可能则标记为私有,并且永不共享。但是,当使用具有多路复用能力的协议且重用模式级别值大于默认“safe”策略时,情况并非如此,因为在这种情况下,没有什么可以阻止连接被共享。决定保持空闲连接打开或在处理后关闭的规则也受“tune.pool-low-fd-ratio”(默认值:20%)和“tune.pool-high-fd-ratio”(默认值:25%)的控制。这些对应于空闲连接中消耗的文件描述符总数的百分比,高于此百分比,HAProxy将分别避免在响应后保持连接打开,并主动杀死空闲连接。一些使用非常高比例空闲连接的设置,无论是由于全局“maxconn”太低,还是由于前端(连接少)有大量HTTP/2或HTTP/3流量,但后端使用HTTP/1连接,可能会观察到较低的重用率,因为保持打开的连接太少。在这种情况下,可能需要调整这些阈值或简单地增加全局“maxconn”值。当明确启用线程组时,理解空闲连接只能在同一组的线程之间使用是很重要的。因此,组之间负载不均可能导致需要更多的空闲连接,从而导致较低的重用率。此时可以应用相同的解决方案(增加全局“maxconn”或增加连接池比例)。
向请求添加服务器名称。使用由 <header> 给出的头字符串。可在以下上下文中使用:http

可在以下部分中使用

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<header> 用于发送服务器名称的头字符串。
http-send-name-header”语句会使名为<header>的头部字段在请求即将发送时设置为目标服务器的名称。此头部字段的任何现有实例都将被删除。在重试和重新分派时,头部字段会更新以始终反映正在尝试连接的服务器。鉴于此头部字段在连接建立的后期才被修改,它可能会对已修改的头部字段产生意想不到的影响。例如,将其与传输层头部(如connection、content-length、transfer-encoding等)一起使用,很可能导致发送到服务器的请求无效。此外,据报道,此指令目前被用作覆盖出站请求中Host头部字段的一种方式;虽然这种技巧作为该功能的一个副作用已有一段时间,但它不受官方支持,并且将来可能会因该功能引起的技术困难而不再有效。一个长期的解决方案是修复需要这种技巧的应用程序,使其绑定到正确的主机名。
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”。这是最常见的用法。“global”将所有日志参数替换为“global”部分中找到的日志条目。每个实例只能使用一个“log global”语句,并且此形式不带其他参数。<target>表示将日志发送到何处。它采用与“global”部分的日志相同的格式,可以是以下之一: - IPv4地址,可选择后跟冒号(':')和UDP端口。如果未指定端口,则默认使用514(标准syslog端口)。 - IPv6地址,后跟冒号(':')和可选的UDP端口。如果未指定端口,则默认使用514(标准syslog端口)。 - UNIX域套接字的 filesystem 路径,需考虑chroot(确保路径在chroot内部可访问)和uid/gid(确保路径可适当写入)。 - 文件描述符号,格式为“fd@<number>”,可指向管道、终端或套接字。在这种情况下,使用无缓冲日志,并且每个日志执行一次writev()调用。这有点昂贵,但对于大多数工作负载来说可以接受。以这种方式发送的消息不会被截断,但可能会被丢弃,在这种情况下,DroppedLogs计数器将增加。writev()调用对于最大为PIPE_BUF大小的消息甚至是原子性的,POSIX建议至少为512,在大多数现代操作系统上为4096字节。任何更大的消息都可能与来自其他进程的消息交错。仅出于调试目的,文件描述符也可以指向文件,但这样做会显著降低HAProxy的速度,因为非阻塞调用将被忽略。此外,无法在不重新启动进程的情况下清除或轮换此文件。请注意,保留配置的syslog格式,因此输出适用于TCP syslog服务器。另请参阅下面的“short”和“raw”格式。 - “stdout”/“stderr”,它们分别是“fd@1”和“fd@2”的别名,参见上文。 - 环形缓冲区,格式为“ring@<name>”,它将对应一个可通过CLI使用“show events”命令访问的内存中环形缓冲区,该命令还将列出现有环形缓冲区及其大小。此类缓冲区在重新加载或重新启动时会丢失,但作为补充使用时,可以通过即时获取日志来帮助故障排除。参见第12.5节关于环形缓冲区。 - 日志后端,格式为“backend@<name>”,它将日志消息发送到相应的日志后端,该后端根据后端的lb设置负责将消息发送到正确的服务器。日志后端是设置了“mode log”的后端部分(有关更多信息,请参见“mode”)。 - 明确的流地址前缀,例如“tcp@”、“tcp6@”、“tcp4@”或“uxst@”,将分配一个隐式环形缓冲区,其中包含一个流转发服务器,目标是给定地址。您可能希望在地址参数中引用一些环境变量,参见第2.3节关于环境变量。<length>是可选的最大行长度。大于此值的日志行在发送前将被截断。原因是syslog服务器对日志行长度的处理方式不同。所有服务器都支持默认值1024,但有些服务器会直接丢弃较长的行,而有些则会记录它们。如果服务器支持长行,则在此处设置此值以避免截断长行可能是有意义的。类似地,如果服务器丢弃长行,则最好在发送前截断它们。接受的值为80到65535(含)。默认值1024通常适用于所有标准用法。某些特殊情况下的长捕获或JSON格式日志可能需要更大的值。如果您的请求URI被截断,您可能还需要增加“tune.http.logurilen”。<ranges>是一个逗号分隔的范围列表,用于标识要采样的日志。这用于平衡发送到日志服务器的日志负载。范围的限制不能为空。它们从1开始编号。采样的数量或周期(以日志数量计)必须通过<sample_size>参数设置。<sample_size>是平衡日志记录负载时要考虑的日志采样大小。它用于平衡发送到syslog服务器的日志负载。此大小必须大于或等于范围上限的最大值(另请参见<ranges>参数)。<format>是生成syslog消息时使用的日志格式。它可以是以下之一:local 类似于rfc3164 syslog消息格式,只是主机名字段被剥离。这是默认值。注意:选项“log-send-hostname”将默认值切换到rfc3164。rfc3164 RFC3164 syslog消息格式。(https://tools.ietf.org/html/rfc3164)rfc5424 RFC5424 syslog消息格式。(https://tools.ietf.org/html/rfc5424)priority 包含级别和syslog facility(在尖括号内,如“<63>”)的消息,后跟文本。省略PID、日期、时间、进程名和系统名。这旨在与本地日志服务器一起使用。short 仅包含级别(在尖括号内,如“<3>”)的消息,后跟文本。省略PID、日期、时间、进程名和系统名。这旨在与本地日志服务器一起使用。此格式与systemd日志记录器所消费的兼容。timed 仅包含级别(在尖括号内,如“<3>”)的消息,后跟ISO日期和文本。省略PID、进程名和系统名。这旨在与本地日志服务器一起使用。iso 仅包含ISO日期的消息,后跟文本。省略PID、进程名和系统名。这旨在与本地日志服务器一起使用。raw 仅包含文本的消息。省略级别、PID、日期、时间、进程名和系统名。这旨在用于容器或开发期间,其中严重性仅取决于使用的文件描述符(stdout/stderr)。<prof>是可选的“log-profile”部分的名称,将在日志构建过程中考虑以覆盖某些日志选项。有关更多信息,请查看“8.3.5. Log profiles”。<facility>必须是24个标准syslog facility之一:kern user mail daemon auth syslog lpr news uucp cron auth2 ftp ntp audit alert cron2 local0 local1 local2 local3 local4 local5 local6 local7 请注意,对于“short”和“raw”格式,facility被忽略,但仍作为位置字段是必需的。在这种情况下,建议使用“daemon”以表明它仅用于本地。<level>是可选的,可以指定以过滤出站消息。默认情况下,所有消息都发送。如果指定了级别,则只发送严重性至少与此级别一样重要的消息。可以指定可选的最小级别。如果设置,则比此级别更严重的日志将限制为此级别。这用于避免在某些默认syslog配置上向所有终端发送“emerg”消息。已知有八个级别:emerg alert crit err warning notice info debug
重要的是要记住,是由前端决定要从连接中记录什么,并且在内容切换的情况下,来自后端的日志条目将被忽略。连接以 "info" 级别记录。然而,后端日志声明定义了服务器状态更改将如何以及在何处被记录。级别 "notice" 将用于指示服务器启动,"warning" 将用于终止信号和最终的服务终止,而 "alert" 将用于服务器宕机时。 注意:根据 RFC3164,消息在发出前会被截断为 1024 字节。
示例
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”的记录器。
示例
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 #仅记录事务的接受和关闭
日志来源(如accept、close)可以按原样在日志配置文件(“on”指令之后)中使用。将“log-steps”与日志配置文件结合使用非常有趣,可以对HAProxy在事务处理过程中自动生成的日志进行精细控制。
log-tag <string>
指定用于所有传出日志的日志标签。可在以下上下文中使用:tcp, http, log

可在以下部分中使用

defaultsfrontendlistenbackend

yes

yes

yes

yes
将syslog头部的tag字段设置为此字符串。它默认为全局部分中设置的log-tag,否则为从命令行启动的程序名,通常是“HAProxy”。有时,区分在同一主机上运行的多个进程,或区分在同一进程中运行的客户实例可能很有用。在后端,有关服务器启动/关闭的日志将使用此tag。作为提示,方便的做法是在defaults部分设置与托管客户相关的log-tag,然后将该客户的所有前端和后端都放在该部分,然后在新的defaults部分启动另一个客户。另请参阅全局“log-tag”指令。
设置用于维护 keep-alive 连接的最大服务器队列大小。可在以下上下文中使用:http

可在以下部分中使用

defaultsfrontendlistenbackend

yes

no

yes

yes
HTTP keep-alive 尝试尽可能重用同一服务器连接,但有时会适得其反,例如如果一个服务器有很多连接而其他服务器空闲。对于静态服务器尤其如此。此设置的目的是设置一个排队连接数的阈值,HAProxy 在达到该阈值时停止尝试重用同一服务器,而倾向于寻找另一个服务器。默认值 -1 表示没有限制。值为零表示 keep-alive 请求将永远不会排队。对于延迟低且对中断 keep-alive 不敏感的非常接近的服务器,建议使用低值(例如,本地静态服务器可以使用 10 或更小的值)。对于遭受高延迟的远程服务器,可能需要更高值以弥补延迟和/或选择不同服务器的成本。请注意,这不会影响因 401 响应而连续维护到同一服务器的响应。它们仍将发送到同一服务器,即使它们必须排队。
设置我们可以为给定客户端会话保持空闲的最大传出连接数。默认值为 5(精确等于在构建时定义的 MAX_SRV_LIST)。可在以下上下文中使用:tcp, http

可在以下部分中使用

defaultsfrontendlistenbackend

yes

yes

yes

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

可在以下部分中使用

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<conns> 是前端将接受服务的最大并发连接数。超出的连接将由系统在套接字的侦听队列中排队,并在一个连接关闭后得到服务。
如果系统支持,在大站点上将此限制设置得很高可能很有用,这样HAProxy就可以管理连接队列,而不是让客户端面临未响应的连接尝试。此值不应超过全局maxconn。此外,请记住,一个连接包含两个tune.bufsize(默认为16kB)的缓冲区,以及其他一些数据,导致每个已建立连接消耗大约33kB的RAM。这意味着,一个配备1GB RAM的中型系统,如果配置得当,可以承受大约20000-25000个并发连接。此外,当<conns>设置为大值时,服务器可能无法承受如此大的负载,因此,通常明智的做法是为它们分配一些合理的连接限制。当此值设置为零(默认值)时,将使用全局“maxconn”值。
mode { tcp|http|log|spop }
设置实例的运行模式或协议

可在以下部分中使用

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
tcp 实例将以纯TCP模式工作。客户端和服务器之间将建立全双工连接,不执行任何第七层检查。这是默认模式。它应用于SSL、SSH、SMTP等。http 实例将以HTTP模式工作。客户端请求在连接到任何服务器之前将进行深入分析。任何不符合RFC的请求都将被拒绝。第七层过滤、处理和切换将成为可能。这是HAProxy最有价值的模式。log 在后端部分使用时,它将把后端转换为日志后端。这样的后端可以通过使用“backend@<name>”语法作为任何“log”指令的日志目标。日志消息将根据lb设置(可以使用“balance”关键字配置)分发到后端的服务器。日志后端通过在服务器地址前添加“udp@”前缀支持UDP服务器。支持常见的后端和服务器功能,但不支持TCP或HTTP特定功能。spop 在后端部分使用时,它将把后端转换为日志后端。如果SPOE引擎引用的后端需要,此模式是强制性的并且会自动设置。
在进行内容切换时,前端和后端必须处于相同的模式(通常是 HTTP),否则配置将被拒绝。
示例
defaults http_instances mode http
monitor fail { if | unless } <condition>
添加一个条件,以便向监控 HTTP 请求报告失败。可在以下上下文中使用:http

可在以下部分中使用

defaultsfrontendlistenbackend

no

yes

yes

no
参数
if <cond> 如果条件满足,监控请求将失败,否则将成功。该条件应描述一个组合测试,如果所有条件都满足,则必须导致失败,例如后端及其备份中的服务器数量都很少。 unless <cond> 只有当条件满足时,监控请求才会成功,否则将失败。这样的条件可以基于对后端列表中最小活动服务器数量的存在的测试。
此语句添加了一个条件,可以强制监控请求的响应报告失败。默认情况下,当外部组件查询专用于监控的URI时,返回200响应。当满足上述条件之一时,HAProxy将返回503而不是200。这对于向外部组件报告站点故障非常有用,外部组件可能根据HAProxy报告的可用性在多个站点之间进行路由广告。在这种情况下,将依赖于涉及“nbsrv”标准的ACL。请注意,“monitor fail”仅在HTTP模式下工作。如果需要,可以使用“errorfile”或“errorloc”调整两种状态消息。
示例
frontend www mode http acl site_dead nbsrv(dynamic) lt 2 acl site_dead nbsrv(static) lt 2 monitor-uri /site_alive monitor fail if site_dead
拦截外部组件监控请求使用的 URI。可在以下上下文中使用:http

可在以下部分中使用

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<uri> 是我们想要拦截以返回 HAProxy 健康状态而不是转发请求的确切 URI。
当前端收到引用<uri>的HTTP请求时,HAProxy不会转发或记录它,而是返回“HTTP/1.0 200 OK”或“HTTP/1.0 503 Service unavailable”,具体取决于使用“monitor fail”定义的失败条件。这通常足以让任何前端HTTP探测器检测服务是否正常运行,而无需将请求转发到后端服务器。请注意,HTTP方法、版本和所有标头都会被忽略,但请求至少在HTTP级别必须有效。此关键字只能与HTTP模式前端一起使用。监控请求处理非常早,就在请求解析之后,甚至在任何“http-request”之前。唯一在此之前应用的规则集是tcp-request规则集。它们也无法被记录,这是其预定目的。只能配置一个URI进行监控;当存在多个“monitor-uri”语句时,最后一个将定义要使用的URI。它们仅用于向更高级别的组件报告HAProxy的健康状况,仅此而已。但是,可以通过“monitor fail”和ACL添加任意数量的条件,以便根据可以想象的任何检查(最常见的是后端可用服务器的数量)调整结果。注意:如果<uri>以斜杠('/')开头,则匹配是针对请求的路径而不是请求的URI执行的。这是为了让HTTP/2请求匹配monitor-uri的变通方法。实际上,在HTTP/2中,客户端被鼓励只发送绝对URI。
示例
# 使用 /haproxy_test 报告 HAProxy 的状态 frontend www mode http monitor-uri /haproxy_test
启用或禁用对队列中待处理的已中止请求的提前丢弃。可在以下上下文中使用:tcp, http

可在以下部分中使用

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
在高负载情况下,服务器需要一些时间才能响应。每个实例的连接队列将膨胀,响应时间将随着队列大小乘以平均每个流的响应时间而增加。当客户端等待超过几秒钟时,他们通常会点击浏览器上的“停止”按钮,导致队列中留下无用的请求,并减慢其他用户和服务器的速度,因为请求最终会被服务,然后在交付响应时遇到的第一个错误处中止。由于无法区分客户端的完全停止和简单的输出关闭,HTTP代理应该保守地认为客户端可能只是关闭了其输出通道,同时等待响应。然而,当许多用户这样做时,这会带来拥塞的风险,并且现在完全无用,因为可能根本没有客户端会在等待响应时关闭流。一些HTTP代理支持这种行为(Squid、Apache、HAProxy),而其他代理不支持(TUX、大多数基于硬件的负载均衡器)。因此,关闭输入通道表示用户点击“停止”按钮的可能性接近100%,并且作为唯一中断罕见但有效流量的组件的风险极低,这增加了在尚未服务且不污染服务器的情况下尽早中止流的诱惑。在HAProxy中,用户可以使用选项“abortonclose”选择所需的行为。默认情况下(不带该选项),行为符合HTTP标准,中止的请求将得到服务。但当指定该选项时,入站通道已关闭的流将在可能的情况下中止,无论是在队列中等待连接槽,还是在连接建立期间(如果服务器尚未确认连接请求)。这显著减少了队列大小和饱和服务器上的负载,当用户倾向于点击“停止”时,这反过来又减少了其他用户的响应时间。如果此选项已在“defaults”部分启用,则可以通过在其前面添加“no”关键字来在特定实例中禁用它。
启用或禁用放宽 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
参数:
默认情况下,HAProxy在消息解析方面遵守不同的HTTP RFC。这意味着消息解析相当严格,并导致向客户端返回格式错误消息的错误。这是期望的行为,因为此类格式错误的消息主要用于利用服务器弱点构建攻击,并绕过安全过滤。有时,一个有缺陷的浏览器出于某种原因(配置、实现...)不会遵守这些RFC,并且问题不会立即得到修复。在这种情况下,可以通过指定此选项来放宽HAProxy的解析器以接受一些无效请求。出于历史原因,大多数规则涉及H1解析。较新的HTTP版本倾向于更清晰,并且应用程序更严格地遵循这些协议。设置此选项时,将遵循以下规则: * 仅在H1中,标头名称中的无效字符(包括NULL字符)将被接受; * 仅在H1中,标头值中的NULL字符将被接受; * 仅在H1中,URI中大于127的字符将被接受。URI中允许出现的字符列表由RFC3986明确定义,字符0-31、32(空格)、34('"')、60('<')、62('>')、92('\')、94('^')、96('`')、123('{')、124('|')、125('}')、127(删除)以及任何高于这些的字符通常不允许。在H1中,所有(0..32)和127之间的字符将始终被阻塞。所有大于127(不包括)的字符也将被阻塞,除非启用此选项。其他字符(33..126)将完全不进行检查。 * 在H1和H2中,包含片段引用(路径后面的'#')的URL将被接受; * 仅在H1中,不对CONNECT请求的authority进行检查; * 仅在H1中,不对authority和Host标头值进行检查。 * 仅在H1中,HTTP版本测试将放宽。它将允许HTTP/0.9 GET请求通过(未指定版本),以及不同的协议名称(例如RTSP),以及主版本和次版本的多个数字。 * 仅在H1中,未能提供有效“Sec-Websocket-Key”标头字段的WebSocket(RFC6455)请求将被接受。默认情况下绝不应启用此选项,因为它会隐藏应用程序错误并打开安全漏洞。它应仅在问题得到确认后部署。启用此选项时,无效但被接受的H1请求将被捕获,以便以后使用UNIX统计套接字上的“show errors”请求进行分析。这样做也有助于确认问题已解决。如果此选项已在“defaults”部分启用,则可以通过在其前面添加“no”关键字来在特定实例中禁用它。
启用或禁用放宽 HTTP 响应解析。可在以下上下文中使用:http

可在以下部分中使用

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
与“option accept-unsafe-violations-in-http-request”类似,此选项可用于放宽HTTP响应的解析规则。它只应为受信任的传统服务器启用,以接受某些无效响应。出于历史原因,大多数规则涉及H1解析。较新的HTTP版本倾向于更清晰,并且应用程序更严格地遵循这些协议。设置此选项时,将遵循以下规则: * 仅在H1中,标头名称中的无效字符(包括NULL字符)将被接受; * 仅在H1中,标头值中的NULL字符将被接受; * 仅在H1中,Transfer-Encoding标头的空值或多个“chunked”值实例将被接受; * 仅在H1中,不对authority和Host标头值进行检查。 * 仅在H1中,HTTP版本测试将放宽。它将允许不同的协议名称(例如RTSP),以及主版本和次版本的多个数字。 * 仅在H1中,未能提供有效“Sec-Websocket-Accept”标头字段的WebSocket(RFC6455)响应将被接受。默认情况下绝不应启用此选项,因为它会隐藏应用程序错误并打开安全漏洞。它应仅在问题得到确认后部署。启用此选项时,响应中仍将接受错误的标头名称,但将捕获完整的响应,以便以后使用UNIX统计套接字上的“show errors”请求进行分析。这样做也有助于确认问题已解决。如果此选项已在“defaults”部分启用,则可以通过在其前面添加“no”关键字来在特定实例中禁用它。
选择一次性使用所有备份服务器,还是只使用第一个。可在以下上下文中使用:tcp, http, log

可在以下部分中使用

defaultsfrontendlistenbackend

yes

no

yes

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

可在以下部分中使用

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
一些高级框架在任何地方都设置应用程序cookie,并且并不总是能让开发人员充分控制响应应该如何缓存。当可缓存对象返回会话cookie时,用户在遍历相同缓存时存在会话交叉或被窃取的高风险。在某些情况下,阻止响应比让一些敏感会话信息泄露出去更好。选项“checkcache”启用对所有服务器响应的深度检查,以严格遵守HTTP规范中的可缓存性。它仔细检查服务器响应中的“Cache-control”、“Pragma”和“Set-cookie”标头,以检查是否存在在客户端代理上缓存cookie的风险。启用此选项时,可以传递给客户端的响应只有: - 所有不带“Set-Cookie”标头的响应; - 所有返回码不是200、203、204、206、300、301、404、405、410、414、501的响应,前提是服务器未设置“Cache-control: public”标头字段; - 所有使用GET、HEAD、OPTIONS、TRACE以外的方法发出的请求的响应,前提是服务器未设置“Cache-Control: public”标头字段; - 带有“Pragma: no-cache”标头的响应 - 带有“Cache-control: private”标头的响应 - 带有“Cache-control: no-store”标头的响应 - 带有“Cache-control: max-age=0”标头的响应 - 带有“Cache-control: s-maxage=0”标头的响应 - 带有“Cache-control: no-cache”标头的响应 - 带有“Cache-control: no-cache="set-cookie"”标头的响应 - 带有“Cache-control: no-cache="set-cookie,”标头的响应(允许set-cookie之后有其他字段)如果响应不符合这些要求,则它将被阻止,就像它来自“http-response deny”规则一样,并返回“HTTP 502 bad gateway”。会话状态显示“PH--”,表示代理在处理标头时阻止了响应。此外,日志中将发送警报,以便管理员得知有需要修复的问题。由于对应用程序影响很大,在生产环境中使用此选项之前,应深入测试应用程序。在测试期间始终激活它也是一个好习惯,即使在生产环境中不使用,因为它将报告潜在危险的应用程序行为。如果此选项已在“defaults”部分启用,则可以通过在其前面添加“no”关键字来在特定实例中禁用它。
启用或禁用在客户端发送 TCP keepalive 数据包。可在以下上下文中使用:tcp, http

可在以下部分中使用

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
当客户端和服务器之间存在防火墙或任何会话感知组件时,并且当协议涉及具有长时间空闲期的非常长的会话(例如远程桌面)时,存在中间组件决定使空闲时间过长的会话过期​​的风险。启用套接字级TCP keep-alive使系统定期向连接的另一端发送数据包,使其保持活动状态。keep-alive探测之间的延迟仅由系统控制,并取决于操作系统及其调优参数。重要的是要理解,keep-alive数据包既不会在应用程序级别发出也不会在应用程序级别接收。只有网络堆栈才能看到它们。因此,即使代理的一侧已经使用keep-alive来保持其连接活动,这些keep-alive数据包也不会转发到代理的另一侧。请注意,这与HTTP keep-alive无关。使用选项“clitcpka”可以在连接的客户端侧启用TCP keep-alive探测的发出,这应该有助于在HAProxy和客户端之间发现会话过期​​时。如果此选项已在“defaults”部分启用,则可以通过在其前面添加“no”关键字来在特定实例中禁用它。
启用持续的流量统计更新。可在以下上下文中使用: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 值
由于HAProxy工作在反向代理模式,服务器会将其IP地址视为客户端地址。这有时在服务器日志中期望客户端IP地址时会很麻烦。为了解决这个问题,HAProxy可以向发送到服务器的所有请求添加众所周知的HTTP头“X-Forwarded-For”。此头包含一个表示客户端IP地址的值。由于此头始终附加到现有头列表的末尾,因此服务器必须配置为始终只使用此头的最后一个实例。请参阅服务器手册以了解如何启用此标准头的使用。请注意,只应使用头的最后一个实例,因为客户端确实可能已经带有一个。关键字“header”可用于提供不同的头名称来替换默认的“X-Forwarded-For”。这在您可能已经有来自不同应用程序(例如stunnel)的“X-Forwarded-For”头,并且需要保留它时很有用。此外,如果您的后端服务器不使用“X-Forwarded-For”头并需要不同的头(例如Zeus Web Servers需要“X-Cluster-Client-IP”)。有时,同一个HAProxy实例可能在直接客户端访问和反向代理访问之间共享(例如当使用SSL反向代理解密HTTPS流量时)。可以通过添加“except”关键字后跟网络地址来禁用已知源地址或网络的头添加。在这种情况下,任何匹配网络的源IP都不会导致此头的添加。最常见的用途是私有网络或127.0.0.1。IPv4和IPv6都支持。或者,关键字“if-none”表示只有当头不存在时才添加。这只应在完全受信任的环境中使用,因为如果到达HAProxy的头受最终用户控制,这可能会导致安全问题。此选项可以在defaults、listen或backend部分指定,但对于frontend部分将被忽略。不带参数设置option forwarded将导致使用默认隐式行为。默认行为启用proto参数并注入原始客户端IP。等效的显式/手动配置将是:option forwarded proto for 关键字“by”用于在forwarded头中启用“by”参数(“nodename”)。它允许嵌入请求代理信息。“by”值将设置为代理IP(目标地址),如果不可用(即:UNIX监听器),“by”将设置为“unknown”。关键字“by-expr”用于在forwarded头中启用“by”参数(“nodename”)。它允许嵌入请求代理信息。“by”值将设置为样本表达式<by_expr>的结果(如果有效),否则将设置为“unknown”。关键字“for”用于在forwarded头中启用“for”参数(“nodename”)。它允许嵌入请求客户端信息。“for”值将设置为客户端IP(源地址),如果不可用(即:UNIX监听器),“for”将设置为“unknown”。关键字“for-expr”用于在forwarded头中启用“for”参数(“nodename”)。它允许嵌入请求客户端信息。“for”值将设置为样本表达式<for_expr>的结果(如果有效),否则将设置为“unknown”。关键字“by_port”用于向“by”参数提供“nodeport”信息。“by_port”需要设置“by”或“by-expr”,否则将被忽略。“nodeport”将设置为代理(目标)端口(如果可用),否则将被忽略。关键字“by_port-expr”用于向“by”参数提供“nodeport”信息。“by_port-expr”需要设置“by”或“by-expr”,否则将被忽略。“nodeport”将设置为样本表达式<by_port_expr>的结果(如果有效),否则将被忽略。关键字“for_port”用于向“for”参数提供“nodeport”信息。“for_port”需要设置“for”或“for-expr”,否则将被忽略。“nodeport”将设置为客户端(源)端口(如果可用),否则将被忽略。关键字“for_port-expr”用于向“for”参数提供“nodeport”信息。“for_port-expr”需要设置“for”或“for-expr”,否则将被忽略。“nodeport”将设置为样本表达式<for_port_expr>的结果(如果有效),否则将被忽略。
示例
# 这些服务器需要客户端请求的IP地址和协议 # 结果头部将如下所示: # forwarded: proto=http;for=127.0.0.1 backend www_default mode http option forwarded #等同于: option forwarded proto for # 这些服务器需要请求的主机和哈希后的客户端IP地址 # 以及客户端源端口(如果关注IP隐私,则应为xxh32使用种子) # 结果头部将如下所示: # forwarded: host="haproxy.org";for="_000000007F2F367E:60138" backend www_host mode http option forwarded host for-expr src,xxh32,hex for_port # 这些服务器希望在host、for和by参数中包含自定义数据 # 结果头部将如下所示: # 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) # 这些服务器希望为了请求跟踪目的使用随机的混淆“for”标识符 # 同时保护敏感的IP信息 # 结果头部将如下所示: # 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" 头部名称。
由于HAProxy工作在反向代理模式,服务器会将其IP地址视为客户端地址。当服务器日志中期望客户端IP地址时,这有时会很麻烦。为了解决这个问题,HAProxy可以将众所周知的HTTP头“X-Forwarded-For”添加到发送到服务器的所有请求中。此头包含一个表示客户端IP地址的值。由于此头始终附加到现有头列表的末尾,因此服务器必须配置为始终只使用此头的最后一个实例。请参阅服务器手册以了解如何启用此标准头的使用。请注意,只应使用头的最后一个实例,因为客户端确实可能已经带有一个。关键字“header”可用于提供不同的头名称来替换默认的“X-Forwarded-For”。这在您可能已经有来自不同应用程序(例如stunnel)的“X-Forwarded-For”头,并且需要保留它时很有用。此外,如果您的后端服务器不使用“X-Forwarded-For”头并需要不同的头(例如Zeus Web Servers需要“X-Cluster-Client-IP”)。有时,同一个HAProxy实例可能在直接客户端访问和反向代理访问之间共享(例如当使用SSL反向代理解密HTTPS流量时)。可以通过添加“except”关键字后跟网络地址来禁用已知源地址或网络的头添加。在这种情况下,任何匹配网络的源IP都不会导致此头的添加。最常见的用途是私有网络或127.0.0.1。IPv4和IPv6都支持。或者,关键字“if-none”表示只有当头不存在时才添加。这只应在完全受信任的环境中使用,因为如果到达HAProxy的头受最终用户控制,这可能会导致安全问题。此选项可以在前端或后端指定。如果至少有一个使用它,则会添加该头。请注意,如果两者都定义,则后端的头子参数设置优先于前端的设置。在“if-none”参数的情况下,如果前端或后端中至少有一个没有指定它,它会要求强制添加,因此它获胜。
示例
# 公共 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
参数:
由于RFC7230中指出标头名称不区分大小写,因此没有标准的大小写格式。因此,应用程序必须以不区分大小写的方式处理它们。但一些有问题的应用程序违反了标准,错误地依赖于浏览器最常用的大小写。这个问题在HTTP/2中变得至关重要,因为所有标头名称必须以小写形式交换,并且HAProxy遵循相同的约定。无论HTTP版本如何,所有标头名称都以小写形式发送给客户端和服务器。当HAProxy收到HTTP/1响应时,其标头名称会转换为小写,并以这种方式处理和发送给客户端。如果已知客户端违反HTTP标准并且无法处理来自HAProxy的响应,则可以在格式化响应并将其发送给客户端时,通过启用此选项并使用全局指令“h1-case-adjust”或“h1-case-adjust-file”指定要重新格式化的标头列表,将小写标头名称转换为不同的格式。这只能作为客户端修复期间的临时解决方法,因为需要此类解决方法的客户端可能容易受到内容走私攻击,并且必须绝对修复。请注意,此选项不会影响符合标准的客户端。如果此选项已在“defaults”部分启用,则可以通过在其前面添加“no”关键字来在特定实例中禁用它。
启用或禁用发送给有问题的服务器的 HTTP/1 头部的大小写调整。可在以下上下文中使用:http

可在以下部分中使用

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
由于RFC7230中指出标头名称不区分大小写,因此没有标准的大小写格式。因此,应用程序必须以不区分大小写的方式处理它们。但一些有问题的应用程序违反了标准,错误地依赖于浏览器最常用的大小写。这个问题在HTTP/2中变得至关重要,因为所有标头名称必须以小写形式交换,并且HAProxy遵循相同的约定。无论HTTP版本如何,所有标头名称都以小写形式发送给客户端和服务器。当HAProxy收到HTTP/1请求时,其标头名称会转换为小写,并以这种方式处理和发送给服务器。如果已知服务器违反HTTP标准并且无法处理来自HAProxy的请求,则可以在格式化请求并将其发送给服务器时,通过启用此选项并使用全局指令“h1-case-adjust”或“h1-case-adjust-file”指定要重新格式化的标头列表,将小写标头名称转换为不同的格式。这只能作为服务器修复期间的临时解决方法,因为需要此类解决方法的服务器可能容易受到内容走私攻击,并且必须绝对修复。请注意,此选项不会影响符合标准的服务器。如果此选项已在“defaults”部分启用,则可以通过在其前面添加“no”关键字来在特定实例中禁用它。
启用或禁用在处理前等待整个 HTTP 请求体。可在以下上下文中使用:http

可在以下部分中使用

defaultsfrontendlistenbackend

yes

yes

yes

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

可在以下部分中使用

defaultsfrontendlistenbackend

yes

no

no

yes
参数:
启用此选项后,请求中发现的任何HTTP尾部都将在发送到服务器之前被删除。RFC9110#section-6.5.1指出尾部字段可以合并到头部字段中。这应该是有意为之的,但对于某些应用程序可能会有问题,特别是如果恶意客户端在尾部部分隐藏敏感头部字段,并且一些中间件在没有特定检查的情况下将其与头部合并。在这种情况下,可以在后端启用此选项,以在将请求发送到服务器之前删除请求中发现的任何尾部字段。如果此选项已在“defaults”部分启用,则可以通过在其前面添加“no”关键字来在特定实例中禁用它。
在发送到客户端时从响应中删除 HTTP trailers。可在以下上下文中使用:http

可在以下部分中使用

defaultsfrontendlistenbackend

yes

yes

yes

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

可在以下部分中使用

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
最近,一些浏览器开始实现“预连接”功能,即推测性地连接到一些最近访问过的网站,以防用户想要访问它们。这导致许多连接建立到网站,如果超时首先发生,则以408请求超时结束,或者当浏览器决定首先关闭它们时,以400错误请求结束。这些会污染日志并增加错误计数器。虽然已经有“option dontlognull”,但在这种情况下它是不够的。相反,此选项执行以下操作: - 如果在连接关闭之前未收到任何内容,则阻止向客户端发送任何400/408消息; - 在这种情况下阻止发出任何日志; - 阻止增加任何错误计数器 这样,空连接就会被静默忽略。请注意,除非明确需要,否则最好不要使用此选项,因为它会隐藏实际问题。未收到请求并出现408的最常见原因是客户端和VPN等中间元素之间存在MTU不一致,这会阻止过大的数据包。这些问题通常在使用POST请求以及带有大cookie的GET请求时出现。日志通常是检测它们的唯一方法。如果此选项已在“defaults”部分启用,则可以通过在其前面添加“no”关键字来在特定实例中禁用它。
为 HTTP/1.x 连接启用或禁用从客户端到服务器的 HTTP keep-alive。可在以下上下文中使用:http

可在以下部分中使用

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
默认情况下,HAProxy在处理持久HTTP/1.x连接时以keep-alive模式运行:对于每个连接,它处理每个请求和响应,并使连接在两侧保持空闲。此模式可以通过“option http-server-close”或“option httpclose”等几个选项进行更改。此选项允许将模式重新设置为keep-alive,这在默认部分使用了其他模式时可能很有用。设置“option http-keep-alive”可在客户端和服务器端启用HTTP keep-alive模式。这在客户端(慢速网络)提供最低延迟,并在服务器端实现最快的会话重用,但代价是维护到服务器的空闲连接。通常,通过此选项,在小对象上可以实现大约是“http-server-close”选项请求率两倍的请求率。此选项主要在两种情况下可能有用: - 当服务器不符合HTTP规范并对连接而不是请求进行身份验证时(例如NTLM身份验证) - 当建立到服务器的连接成本相对于从服务器检索关联对象的成本显著时。后一种情况可能发生在服务器是快速静态服务器或缓存时。目前,日志不会指示请求是否来自同一会话。日志中报告的接受日期对应于上一个请求的结束,请求时间对应于等待新请求所花费的时间。如果未设置,keep-alive请求时间仍受“timeout http-keep-alive”或“timeout http-request”定义的超时限制。此选项禁用并替换任何先前的“option httpclose”或“option http-server-close”。
指示系统在 HTTP 中优先考虑低交互延迟而不是性能。可在以下上下文中使用:http

可在以下部分中使用

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
在HTTP中,每个负载都是单向的,没有交互性的概念。任何代理都应在合理低的延迟下对数据进行排队。存在一些非常罕见的服务器到服务器应用程序滥用HTTP协议,并期望负载阶段具有高度交互性,在单个请求中以两个方向交错许多数据块。这绝对不受HTTP规范支持,并且在大多数代理或服务器上都无法工作。当此类应用程序试图通过HAProxy执行此操作时,它会起作用,但它们将经历高延迟,这是由于网络优化通过指示系统等待足够的数据可用以便仅发送完整数据包来优先考虑性能。典型的延迟大约为每次往返200毫秒。请注意,这仅发生在异常使用情况下。CONNECT请求和WebSockets等正常使用不受影响。当连接使用的前端或后端中存在“option http-no-delay”时,所有此类优化都将被禁用,以使交换尽可能快。当然,这并不能保证功能,因为它可能在任何其他地方中断。但如果它通过HAProxy工作,它将尽可能快地工作。此选项绝不应默认使用,并且除非发现此类有问题的应用程序,否则绝不应使用。使用此选项的影响是带宽使用和CPU使用增加,这可能会在高延迟环境中显著降低性能。
定义 HAProxy 是否会向服务器宣告 HTTP/1.x 连接的 keepalive。可在以下上下文中使用:http

可在以下部分中使用

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
当使用“option http-server-close”或“option httpclose”运行时,HAProxy会将“Connection: close”头添加到转发到服务器的HTTP/1.x请求中。不幸的是,当某些服务器看到此头时,它们会自动避免对未知长度的响应使用分块编码,尽管这完全不相关。其结果是,客户端或缓存可能会收到不完整的响应而不知情,并认为响应已完成。通过设置“option http-pretend-keepalive”,HAProxy会使服务器相信它将保持连接活动。服务器 then 将不会回退到上述异常不希望的行为。当HAProxy获得整个响应后,它将像使用“option httpclose”一样关闭与服务器的连接。这样,客户端获得正常响应,并且连接在服务器端正确关闭。不建议默认启用此选项,因为大多数服务器在最后一个数据包之后会更有效地自行关闭连接,并稍微早一点释放其缓冲区。此外,网络上添加的数据包可能会略微降低整体峰值性能。然而,值得注意的是,当启用此选项时,HAProxy的工作量会稍微减少。因此,如果HAProxy是整个架构的瓶颈,启用此选项可能会节省一些CPU周期。此选项可以在backend和listen部分设置。在frontend部分使用它将被忽略,并在启动期间报告警告。这是一个后端相关的选项,因此没有真正的原因在frontend上设置它。如果此选项已在“defaults”部分启用,则可以通过在其前面添加“no”关键字来在特定实例中禁用它。
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
参数:
默认情况下,HAProxy在处理持久HTTP/1.x连接时以keep-alive模式运行:对于每个连接,它处理每个请求和响应,并使连接在两侧保持空闲。此模式可以通过“option http-server-close”或“option httpclose”等几个选项进行更改。设置“option http-server-close”可在服务器端启用HTTP连接关闭模式,同时在客户端保留支持HTTP keep-alive和流水线的能力。这在客户端(慢速网络)提供最低延迟,并在服务器端实现最快的会话重用以节省服务器资源,类似于“option httpclose”。它还允许不具备keep-alive能力的服务器在keep-alive模式下向客户端提供服务,如果它们符合RFC7230的要求。请注意,当某些服务器在请求中看到“Connection: close”时,它们并不总是符合这些要求。结果将是永远不会使用keep-alive。一种解决方法是启用“option http-pretend-keepalive”。目前,日志不会指示请求是否来自同一会话。日志中报告的接受日期对应于上一个请求的结束,请求时间对应于等待新请求所花费的时间。如果未设置,keep-alive请求时间仍受“timeout http-keep-alive”或“timeout http-request”定义的超时限制。此选项可以在前端和后端设置。如果前端或后端中至少有一个启用此选项,则此选项将启用。它禁用并替换任何先前的“option httpclose”或“option http-keep-alive”。请查看第4节(“代理”)以了解当前后端和前端选项不同时此选项如何与其他选项结合。如果此选项已在“defaults”部分启用,则可以通过在其前面添加“no”关键字来在特定实例中禁用它。
使用非标准的 Proxy-Connection 头代替 Connection 可在以下上下文中使用:http

可在以下部分中使用

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
虽然RFC7230明确指出HTTP/1.1代理必须使用Connection头来指示它们对持久或非持久连接的意愿,但浏览器和代理都忽略代理连接的此头,而是使用未文档化的非标准Proxy-Connection头。问题始于尝试在浏览器和此类代理之间放置负载均衡器时,因为HAProxy的理解与客户端和代理的协商之间会存在差异。通过在前端设置此选项,HAProxy可以自动切换到使用该非标准头,如果它看到代理请求。此处定义的代理请求是指URI既不以“/”也不以“*”开头的请求。这与HTTP隧道模式不兼容。请注意,此选项只能在前端指定,并将影响请求的整个生命周期。此外,当设置此选项时,如果请求本身是代理请求,则需要身份验证的请求将自动切换到使用代理身份验证头。这使得可以在现有代理前面检查或强制执行身份验证。此选项通常绝不应使用,除非在代理前面。
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 头的值。默认情况下不设置。它是一个日志格式字符串。
默认情况下,服务器健康检查仅包括尝试建立TCP连接。当指定“option httpchk”时,一旦建立TCP连接,就会发送完整的HTTP请求,并且2xx和3xx响应被视为有效,而所有其他响应(包括没有任何响应)都表示服务器故障。结合“http-check”指令,可以自定义HTTP健康检查期间发送的请求或响应上的匹配规则。也可以配置发送/期望序列,就像TCP健康检查的“tcp-check”指令一样。默认使用服务器配置来打开连接以执行HTTP健康检查。但也可以使用“http-check connect”规则覆盖服务器参数。“httpchk”选项不一定需要HTTP后端,它也适用于纯TCP后端。这对于检查绑定到某些专用端口的使用inetd守护程序的简单脚本特别有用。然而,它将始终内部依赖于HTX多路复用器。因此,这意味着请求格式化和响应解析将是严格的。
示例
# 将 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
参数:
默认情况下,HAProxy在处理持久HTTP/1.x连接时以keep-alive模式运行:对于每个连接,它处理每个请求和响应,并使连接在两侧保持空闲。此模式可以通过“option http-server-close”或“option httpclose”等几个选项进行更改。如果设置了“option httpclose”,HAProxy将关闭客户端或服务器连接,具体取决于选项设置的位置。前端被视为客户端连接,后端被视为服务器连接。如果选项设置在监听器上,则它同时应用于客户端和服务器连接。它将检查每个方向是否已设置“Connection: close”头,如果缺少则会添加一个。此选项还可以与“option http-pretend-keepalive”结合使用,后者将禁用发送“Connection: close”请求头,但仍会在收到整个响应后导致连接关闭。它禁用并替换任何先前的“option http-server-close”或“option http-keep-alive”。如果此选项已在“defaults”部分启用,则可以通过在其前面添加“no”关键字来在特定实例中禁用它。
启用 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
参数:
默认情况下,当数据通过套接字发送时,该套接字的写入超时和读取超时都会刷新,因为我们认为该套接字上有活动,并且没有其他方法可以猜测我们是否应该接收数据。虽然这种默认行为适用于几乎所有应用程序,但在某些情况下,希望禁用它,并且仅在有传入数据时才刷新读取超时。这种情况发生在具有大超时和少量交换数据的流上,例如telnet会话。如果服务器突然消失,输出数据会累积在系统的套接字缓冲区中,两个超时都会正确刷新,并且无法知道服务器是否未收到它们,因此我们不会超时。然而,当底层协议始终回显发送的数据时,仅凭读取超时就足以检测问题。请注意,这个问题不会在更冗长的协议中发生,因为数据不会长时间累积在套接字缓冲区中。当此选项在前端设置时,它将禁用发送到客户端的数据的读取超时更新。这种情况可能很少有用。当此选项在后端设置时,它将禁用发送到服务器的数据的读取超时更新。这样做通常会中断来自慢速线路的大型HTTP POST,因此请谨慎使用。
使用 LDAPv3 健康检查来测试服务器 可在以下上下文中使用:tcp

可在以下部分中使用

defaultsfrontendlistenbackend

yes

no

yes

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

可在以下部分中使用

defaultsfrontendlistenbackend

yes

no

yes

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

可在以下部分中使用

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
默认情况下,空闲连接将在软停止期间关闭。在某些环境中,与代理通信的客户端可能已经准备好一些空闲连接,以便稍后发送请求。如果写入错误没有适当的重试机制,这可能导致haproxy重新加载时出现错误。尽管正确的实现应在连接/写入错误时重试,但引入此选项是为了支持与haproxy 2.4版本之前版本的向后兼容性。实际上,在v2.4之前,haproxy会在关闭之前等待最后一个请求和响应以添加“connection: close”头,从而通知客户端该连接将不可重用。在一个真实示例中,在AWS中使用ALB位于haproxy之前时观察到了这种行为。最终结果是ALB在haproxy重新加载期间发送502。警告用户,使用此选项可能会增加旧进程的数量,如果连接长时间保持空闲。在频繁重新加载的情况下,可能需要相应地调整客户端超时和/或“hard-stop-after”参数。
启用或禁用健康检查状态更新的日志记录 可在以下上下文中使用: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
参数:
默认情况下,当日志格式字符串定义中使用的所有日志格式别名和样本获取都返回一个值,或者当流终止时,才会发出日志。这允许内置的日志格式字符串考虑传输时间或日志消息中的字节数。在处理长时间连接(如大文件传输或RDP)时,请求或连接可能需要一段时间才能出现在日志中。使用“option logasap”,日志消息会在TCP模式下建立服务器连接时立即创建,或者在HTTP模式下服务器发送完整头信息时立即创建。日志中缺失的信息将是总字节数,这只表示在消息创建之前传输的数据量,以及总时间,这不包括连接剩余的生命周期或传输时间。对于HTTP的情况,最好捕获Content-Length响应头,以便日志至少能指示预期传输的字节数。
示例
listen http_proxy 0.0.0.0:80 mode http option httplog option logasap log 192.168.2.200 local3 >>> Feb 6 12:14:14 localhost \ haproxy[14389]: 10.0.1.2:33317 [06/Feb/2009:12:14:14.655] http-in \ static/srv1 9/10/7/14/+30 200 +243 - - ---- 3/1/1/1/0 1/0 \ "GET /image.iso HTTP/1.0"
option 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 前客户端兼容的检查
如果您指定了用户名,检查包括发送两个MySQL数据包,一个客户端认证数据包,和一个QUIT数据包,以正确关闭MySQL会话。然后我们解析MySQL握手初始化数据包和/或错误数据包。这是一个基本但有用的测试,不会在服务器上产生错误或中止连接。但是,它需要一个没有密码的未锁定授权用户。要在MySQL中创建一个带有可选资源限制的基本受限用户:CREATE USER '<username>'@'<ip_of_haproxy|network_of_haproxy/netmask>' /*!50701 WITH MAX_QUERIES_PER_HOUR 1 MAX_UPDATES_PER_HOUR 0 */ /*M!100201 MAX_STATEMENT_TIME 0.0001 */; 如果您不指定用户名(不推荐且已弃用),检查只包括解析MySQL握手初始化数据包或错误数据包,在此模式下我们不发送任何内容。据报道,如果检查过于频繁和/或流量不足,可能会导致锁定。事实上,在这种情况下,您需要检查MySQL的“max_connect_errors”值,因为如果前一个连接中断后,在少于MySQL“max_connect_errors”次尝试内成功建立连接,则主机的错误计数将被清除为零。如果HAProxy的服务器被阻塞,“FLUSH HOSTS”语句是唯一能解除阻塞的方法。请记住,这不会检查数据库是否存在或数据库一致性。为此,您可以例如使用xinetd进行外部检查。该检查要求MySQL版本>=3.22,对于旧版本,请使用TCP检查。通常,传入的MySQL服务器需要看到客户端的IP地址,用于各种目的,包括IP权限匹配和连接日志记录。如果可能,通常明智的做法是使用“source”关键字的“usesrc”参数,在连接到服务器时伪装客户端的IP地址,这需要编译透明代理功能,并且MySQL服务器将客户端通过托管HAProxy的机器路由。
启用或禁用关闭后立即清理会话资源 可在以下上下文中使用:tcp, http, log

可在以下部分中使用

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
当客户端或服务器以不正常的方式中止连接时(例如,物理断开),会话超时触发并会话关闭。但它会在系统中以 FIN_WAIT1 状态停留一段时间,占用一些资源并可能限制建立新连接的能力。当这种情况发生时,可以激活“option nolinger”,它强制系统在关闭时立即移除任何套接字上的待处理数据。因此,会发出一个 TCP RST,任何待处理的数据都会被截断,并且会话会立即从系统表中清除。对客户端而言,通常可见的效果是,如果关闭发生在最后一批数据(例如,重定向或错误响应)时,响应会被截断。在服务器端,当在隧道中转发客户端中止时,它可能有助于立即释放源端口。在这两种情况下,都会发出 TCP 重置,并且由于会话会立即销毁,所以不会有重传。在有损网络中,这可能会增加问题,尤其是在有损侧有防火墙时,因为防火墙可能会看到并处理重置(因此清除其会话)并阻止此会话的任何进一步流量,包括来自另一侧的重传。因此,如果另一侧没有收到它,它将永远不会再次收到任何 RST,并且防火墙可能会记录许多被阻止的数据包。由于所有这些原因,强烈建议不要使用此选项,除非绝对需要作为最后手段。在大多数情况下,使用“client-fin”或“server-fin”超时可以以更可靠的行为实现类似的结果。在 Linux 上,也可以使用“tcp-ut”绑定或服务器设置。此选项可以在前端和后端使用,具体取决于需要它的那一侧。在前端用于客户端,在后端用于服务器。虽然此选项在“defaults”部分中技术上受支持,但绝不能在那里使用,因为它可能会意外传播到不应使用它的部分并导致问题。如果此选项已在“defaults”部分中启用,则可以通过在其前面加上“no”关键字来在特定实例中禁用它。
option originalto [ except <network> ] [ header <name> ]
启用向服务器发送的请求中插入 X-Original-To 头 可在以下上下文中使用:http

可在以下部分中使用

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<network> 是一个可选参数,用于为匹配 <network> 的源禁用此选项。<name> 是一个可选参数,用于指定一个不同的 "X-Original-To" 标头名称。
由于HAProxy可以在透明模式下工作,因此来自客户端的每个请求都可以重定向到代理,并且HAProxy本身可以将每个请求代理到一个复杂的SQUID环境,而SO_ORIGINAL_DST中的目标主机将会丢失。当您想要基于目标IP地址的访问规则时,这会很烦人。为了解决这个问题,HAProxy可能会向发送到服务器的所有请求添加一个新的HTTP头“X-Original-To”。此头包含一个表示原始目标IP地址的值。由于这必须配置为始终只使用此头的最后一个出现。请注意,只能使用头的最后一个出现,因为客户端很可能已经带来了一个。关键字“header”可以用于提供一个不同的头名称来替换默认的“X-Original-To”。当您可能已经有一个来自不同应用程序的“X-Original-To”头,并且需要保留它时,这会很有用。此外,如果您的后端服务器不使用“X-Original-To”头而需要不同的头。有时,同一个HAProxy实例可能在直接客户端访问和反向代理访问之间共享(例如,当使用SSL反向代理解密HTTPS流量时)。通过添加“except”关键字,然后是网络地址,可以禁用为已知目标地址或网络添加头。在这种情况下,任何与网络匹配的目标IP都不会导致添加此头。最常见的用途是私有网络或127.0.0.1。IPv4和IPv6都支持。此选项可以在前端或后端中指定。如果其中至少一个使用它,则会添加头。请注意,如果同时定义,后端的头子参数设置将优先于前端的设置。
示例
# 原始目标地址 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
参数:
当使用的负载均衡算法不是确定性的,并且之前的请求已发送到 HAProxy 仍持有连接的服务器时,有时希望同一会话上的后续请求尽可能地发送到同一服务器。请注意,这与持久性不同,因为我们只表示 HAProxy 尝试应用但不提供任何形式保证的偏好。真正的用途是发送到服务器的 keep-alive 连接。使用此选项时,HAProxy 将尝试重用连接到服务器的相同连接,而不是重新均衡到另一个服务器,从而导致连接关闭。这对于静态文件服务器可能是有意义的。在与哈希算法结合使用时,这没有太大意义。请注意,当负载均衡算法不是确定性的时,HAProxy 已经自动尝试坚持使用发送 401 的服务器或发送 407(需要身份验证)的代理。这对于使用有问题的 NTLM 身份验证挑战是强制性的,并且显著有助于解决一些有故障的应用程序。在这些环境中,prefer-last-server 选项可能也值得考虑,以避免在每个响应后重新分配流量。在此处明确指出哪些负载均衡算法被认为是确定性的可能很有用。确定性算法在服务器集未更改的情况下,将始终为给定的客户端数据选择相同的服务器。通常,确定性算法涉及对传入请求进行哈希或查找以选择目标服务器。然而,情况并非总是如此;例如,“static-rr”也可以被认为是确定性的,因为服务器选择基于服务器的静态权重,使选择可预测。“sticky”算法为返回的客户端提供确定性路由。至于非确定性算法,这些算法根据动态服务器状态或简单轮换选择服务器,因此不保证两个连续请求落在同一服务器上。option prefer-last-server 专为这些算法设计。roundrobin、leastconn 是此类算法的示例。如果此选项已在“defaults”部分中启用,则可以通过在其前面加上“no”关键字来在特定实例中禁用它。
启用或禁用在连接失败时会话重新分发 可在以下上下文中使用:tcp, http

可在以下部分中使用

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<interval> 可选的整数值,用于控制重试连接时重新分发的频率。正值 P 表示希望在每第 P 次重试时进行重新分发,负值 N 表示希望在最后一次重试前的第 N 次重试时进行重新分发。例如,默认值 -1 保留了在最后一次重试时重新分发的历史行为,正值 1 表示每次重试都重新分发,正值 3 表示每三次重试重新分发一次。您可以使用值 0 禁用重新分发。
在HTTP模式下,如果由cookie指定的服务器宕机,客户端可能会一直粘滞在该服务器上,例如使用“option persist”或“force-persist”时,因为它们无法清除cookie,所以将无法再访问该服务。指定“option redispatch”将允许代理打破基于cookie或一致性哈希的持久性,并将其重新分配到正常工作的服务器。活动服务器从可用服务器列表的子集中选择。未宕机或未维护(即,其健康状况未检查或已检查为“up”)的活动服务器按以下顺序选择:1. 任何活动的、非备份服务器(如果有),或者,2. 如果未设置“allbackups”选项,则列表中的第一个备份服务器,或者,3. 如果设置了“allbackups”选项,则任何备份服务器。当发生重试时,HAProxy会尝试选择与上次不同的服务器。新服务器从当前服务器列表中选择。有时,如果重试之间列表更新(例如,如果发生多次重试且持续时间超过检查服务器是否宕机、将其从列表中移除并回退到备份服务器列表所需的时间),连接可能会被重定向到备份服务器。它还允许在多次连接失败的情况下重试连接到另一个服务器。当然,它要求将“retries”设置为非零值。如果此选项已在“defaults”部分中启用,则可以通过在其前面加上“no”关键字来在特定实例中禁用它。
使用 redis 健康检查来测试服务器 可在以下上下文中使用:tcp

可在以下部分中使用

defaultsfrontendlistenbackend

yes

no

yes

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

可在以下部分中使用

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<hello> 是一个可选参数。它是要使用的“hello”命令。它可以是“HELO”(用于 SMTP)或“EHLO”(用于 ESMTP)。所有其他值都将转换为默认命令(“HELO”)。<domain> 是要呈现给服务器的域名。只有在指定了 hello 命令时才能指定(并且是强制性的)。默认情况下,使用“localhost”。
当设置了“option smtpchk”时,健康检查将包括TCP连接,然后是一个SMTP命令。默认情况下,此命令是“HELO localhost”。服务器的返回代码将被分析,只有以“2”开头的返回代码才会被视为有效。所有其他响应,包括无响应,都将构成错误并指示服务器已死。此测试旨在用于SMTP服务器或中继。根据请求,某些服务器可能不会记录每次连接尝试,因此您可能需要进行试验以改善行为。使用telnet在端口25上通常比调整配置更容易。通常,传入的SMTP服务器需要看到客户端的IP地址,用于各种目的,包括垃圾邮件过滤、反欺骗和日志记录。如果可能,通常明智的做法是使用“source”关键字的“usesrc”参数,在连接到服务器时伪装客户端的IP地址,这需要编译透明代理功能。
示例
option smtpchk HELO mydomain.org
启用或禁用为每个套接字收集并提供单独的统计信息。 可在以下上下文中使用:tcp, http

可在以下部分中使用

defaultsfrontendlistenbackend

yes

yes

yes

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

可在以下部分中使用

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
当此选项在前端或后端启用时,HAProxy 将自动评估是否使用内核 tcp splicing 在客户端和服务器之间双向转发数据。HAProxy 使用启发式算法来估计内核 splicing 是否能提高性能。两个方向独立处理。请注意,使用的启发式算法并不激进,以限制过度使用 splicing。此选项要求在编译时启用 splicing,并且可以通过全局选项“nosplice”全局禁用。由于 splice 使用管道,因此使用它需要有足够的备用管道。重要提示:基于内核的 TCP splicing 是 Linux 特有的功能,首次出现在内核 2.6.25 中。它提供基于内核的加速,用于在套接字之间传输数据而无需将这些数据复制到用户空间,从而提供显著的性能提升和 CPU 周期节省。由于许多早期实现存在错误、数据损坏和/或效率低下,此功能默认不启用,应谨慎使用。虽然无法检测实现的正确性,但 2.6.29 是第一个提供正常工作的实现的版本。如有疑问,可以使用全局关键字“nosplice”全局禁用 splicing。
示例
option splice-auto
如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
启用或禁用请求套接字上的自动内核加速 可在以下上下文中使用:tcp, http

可在以下部分中使用

defaultsfrontendlistenbackend

yes

yes

yes

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

可在以下部分中使用

defaultsfrontendlistenbackend

yes

yes

yes

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

可在以下部分中使用

defaultsfrontendlistenbackend

yes

no

yes

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

可在以下部分中使用

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
当客户端和服务器之间存在防火墙或任何会话感知组件时,并且当协议涉及具有长时间空闲期的非常长会话(例如远程桌面)时,存在中间组件决定使长时间空闲的会话过期的风险。启用套接字级别的 TCP keep-alive 使系统定期向连接的另一端发送数据包,使其保持活动状态。keep-alive 探测之间的延迟仅由系统控制,并取决于操作系统及其调优参数。重要的是要理解 keep-alive 数据包既不在应用程序级别发出也不在应用程序级别接收。只有网络堆栈才能看到它们。因此,即使代理的一侧已经使用 keep-alive 来保持其连接活动,这些 keep-alive 数据包也不会转发到代理的另一侧。请注意,这与 HTTP keep-alive 无关。使用选项“srvtcpka”可以在连接的服务器端启用 TCP keep-alive 探测的发射,这应该有助于解决 HAProxy 和服务器之间会话过期的问题。如果此选项已在“defaults”部分中启用,则可以通过在其前面加上“no”关键字来在特定实例中禁用它。
使用 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
此健康检查方法旨在与“tcp-check”命令列表结合使用,以支持发送/预期类型的健康检查序列。TCP 检查目前支持 4 种操作模式:- 没有“tcp-check”指令:健康检查仅包括连接尝试,这仍然是默认模式。- 仅提及“tcp-check send”或“tcp-check send-binary”:这用于在连接打开时发送字符串。对于某些协议,例如发送“QUIT”消息,这有助于防止服务器为每个健康检查记录连接错误。检查结果仍将仅基于打开连接的能力。- 仅提及“tcp-check expect”:这用于测试横幅。连接打开后,HAProxy 等待服务器呈现必须验证某些规则的内容。检查结果将基于内容与规则的匹配。这适用于 POP、IMAP、SMTP、FTP、SSH、TELNET。- 同时提及“tcp-check send”和“tcp-check expect”:这用于测试 hello 类型协议。HAProxy 发送消息,服务器响应并分析其响应。检查结果将基于响应内容与规则的匹配。这通常适用于需要绑定或请求/响应模型的协议。LDAP、MySQL、Redis 和 SSL 是此类协议的示例,尽管它们都已经有专门的检查,对各自的协议有更深入的理解。在此模式下,可以发送许多问题并分析许多答案。第五种模式可用于在脚本的不同步骤中插入注释。对于您创建的每个 tcp-check 规则,您可以添加一个“comment”指令,后跟一个字符串。此字符串将在日志和调试模式下的 stderr 中报告。这对于提供用户友好的错误报告很有用。“comment”当然是可选的。在健康检查执行期间,可以使用“tcp-check set-var”操作提供一个变量范围来存储数据样本。可以使用“tcp-check unset-var”释放这些变量。
示例
# 执行POP检查(仅分析服务器的banner) option tcp-check tcp-check expect string +OK\ POP3\ ready comment POP\ protocol # 执行IMAP检查(仅分析服务器的banner) option tcp-check tcp-check expect string *\ OK\ IMAP4\ ready comment IMAP\ protocol # 在确保Redis主服务器正常运行后,查找Redis主服务器 # redis协议,然后它会正确退出。 # (发送命令,然后分析响应3次) 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 伪造HTTP请求,然后分析响应(在分析之前发送许多头信息) 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
参数:
当HTTP连接请求传入时,系统会代表HAProxy确认它,然后客户端立即发送其请求,系统也会确认它,同时通知HAProxy关于新连接。HAProxy然后读取请求并响应。这意味着系统会发送一个无用的TCP ACK,因为HAProxy在发送响应时也可以确认请求。因此,在HTTP模式下,HAProxy会自动要求支持此功能的平台(目前至少是Linux)避免发送此无用的ACK。它不应该引起任何问题,因为如果响应花费的时间超过预期,系统无论如何都会在40毫秒后发送它。在复杂的网络调试会话期间,可能需要禁用此优化,因为延迟的ACK在尝试识别数据包延迟的位置时会使故障排除更加复杂。然后可以通过指定“no option tcp-smart-accept”来恢复正常行为。也可以通过简单指定“option tcp-smart-accept”来强制将其用于非HTTP代理。例如,对于某些服务(如服务器先发言的SMTP),这可能是有意义的。建议避免在默认部分强制使用此选项。如有疑问,请考虑在其前面加上“default”关键字,或使用“no”关键字禁用它,以将其设置回自动值。
启用或禁用在连接序列中节省一个 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
参数:
当客户端和服务器之间存在防火墙或任何会话感知组件时,并且当协议涉及具有长时间空闲期的非常长会话(例如远程桌面)时,存在中间组件决定使长时间空闲的会话过期的风险。启用套接字级别的 TCP keep-alive 使系统定期向连接的另一端发送数据包,使其保持活动状态。keep-alive 探测之间的延迟仅由系统控制,并取决于操作系统及其调优参数。重要的是要理解 keep-alive 数据包既不在应用程序级别发出也不在应用程序级别接收。只有网络堆栈才能看到它们。因此,即使代理的一侧已经使用 keep-alive 来保持其连接活动,这些 keep-alive 数据包也不会转发到代理的另一侧。请注意,这与 HTTP keep-alive 无关。使用选项“tcpka”可以在连接的客户端和服务器两侧启用 TCP keep-alive 探测的发射。请注意,这仅在“defaults”或“listen”部分中有意义。如果此选项在前端使用,则只有客户端会收到 keep-alive,如果此选项在后端使用,则只有服务器会收到 keep-alive。因此,强烈建议在配置分离为前端和后端时,明确使用“option clitcpka”和“option srvtcpka”。
启用 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" 指令。
启用客户端透明代理 可在以下上下文中使用:tcp, http

可在以下部分中使用

defaultsfrontendlistenbackend

yes

no

yes

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

可在以下部分中使用

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<command> 是要运行的外部命令
传递给命令的参数是: <proxy_address> <proxy_port> <server_address> <server_port> <proxy_address> 和 <proxy_port> 来自第一个 IPv4、IPv6 或 UNIX 套接字监听器。在 UNIX 套接字监听器的情况下,proxy_address 将是套接字的路径,而 <proxy_port> 将是字符串“NOT_USED”。在后端部分,无法确定监听器,<proxy_address> 和 <proxy_port> 都将具有字符串值“NOT_USED”。一些值也通过环境变量提供。环境变量: HAPROXY_PROXY_ADDR 如果可用,则为第一个绑定地址(如果不适用,例如在“backend”部分中,则为空)。 HAPROXY_PROXY_ID 后端ID。 HAPROXY_PROXY_NAME 后端名称。 HAPROXY_PROXY_PORT 如果可用,则为第一个绑定端口(如果不适用,例如在“backend”部分中或对于 UNIX 套接字,则为空)。 HAPROXY_SERVER_ADDR 服务器地址。 HAPROXY_SERVER_CURCONN 服务器上的当前连接数。 HAPROXY_SERVER_ID 服务器ID。 HAPROXY_SERVER_MAXCONN 服务器最大连接数。 HAPROXY_SERVER_NAME 服务器名称。 HAPROXY_SERVER_PORT 如果可用,则为服务器端口(对于 UNIX 套接字,则为空)。 HAPROXY_SERVER_SSL 不使用 SSL 时为“0”,使用时为“1” HAPROXY_SERVER_PROTO 此服务器使用的协议,可以是“cli”(haproxy CLI)、“syslog”(syslog TCP 服务器)、“peers”(对等 TCP 服务器)、“h1”(HTTP/1.x 服务器)、“h2”(HTTP/2 服务器)或“tcp”(任何其他 TCP 服务器)。 PATH 执行命令时使用的 PATH 环境变量可以使用“external-check path”设置。如果执行的命令以零状态退出,则认为检查通过,否则认为检查失败。
示例
external-check command /bin/true
运行外部检查时使用的 PATH 环境变量的值 可在以下上下文中使用:tcp, http, log

可在以下部分中使用

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<path> 是执行外部命令时使用的路径
默认路径为 ""。
示例
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 地址重定向" 选项被禁用。
示例
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> 参数是一个整数,指定前端每秒接受的最大新会话数。
当前端每秒新会话数达到指定数量时,它将停止接受新连接,直到速率再次降至限制以下。在此期间,待处理的会话将保留在套接字积压队列(系统缓冲区)中,HAProxy 甚至不会意识到有会话待处理。当对高负载服务应用非常低的限制时,增加套接字积压队列(使用“backlog”关键字)可能是有意义的。此功能在阻止基于连接的攻击或脆弱服务器上的服务滥用方面特别有效。由于会话速率每毫秒测量一次,因此它非常准确。此外,限制立即生效,检测阈值无需任何延迟。
示例
将 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> 使用“redirect location”时,<loc> 中的确切值会放入 HTTP 的“Location”头部。在“http-request”规则中使用时,<loc> 值遵循自定义日志格式规则,并且可以包含一些动态值(参见第8.2.6节中的自定义日志格式)。 <pfx> 使用“redirect prefix”时,“Location”头部由 <pfx> 和完整的 URI 路径(包括查询字符串)连接而成,除非指定了“drop-query”选项(见下文)。作为特例,如果 <pfx> 恰好等于“/”,则在原始 URI 前面不插入任何内容。它允许重定向到相同的 URL(例如,插入一个 cookie)。在“http-request”规则中使用时,<pfx> 值遵循自定义日志格式规则,并且可以包含一些动态值(参见第8.2.6节中的自定义日志格式)。 <sch> 使用“redirect scheme”时,则“Location”头部由 <sch> 与“://”,然后是第一个“Host”头部,然后是 URI 路径(包括查询字符串)连接而成,除非指定了“drop-query”选项(见下文)。如果没有找到路径,或者路径是“*”,则使用“/”代替。如果没有找到“Host”头部,则返回一个空主机组件,最近的浏览器将其解释为重定向到同一主机。此指令主要用于将 HTTP 重定向到 HTTPS。在“http-request”规则中使用时,<sch> 值遵循自定义日志格式规则,并且可以包含一些动态值(参见第8.2.6节中的自定义日志格式)。 <code> 代码是可选的。它指示所需的 HTTP 重定向类型。只支持代码 301、302、303、307 和 308,如果未指定代码,则默认使用 302。301 表示“永久移动”,浏览器可能会缓存 Location。302 表示“临时移动”,表示浏览器不应缓存重定向。303 等同于 302,只是浏览器将使用 GET 方法获取 Location。307 就像 302,但明确表示必须重用相同的方法。同样,如果必须使用相同的方法,则 308 替换 301。 <option> 可以指定以下几个选项来调整重定向的预期行为: - “drop-query” 当此关键字在基于前缀的重定向中使用时,Location 将设置为不包含任何可能的查询字符串,这对于将用户定向到非安全页面等很有用。它对 Location 类型重定向没有影响。 - “append-slash” 此关键字可与“drop-query”结合使用,将使用不以“/”结尾的 URL 的用户重定向到以“/”结尾的相同 URL。这对于确保搜索引擎只看到一个 URL 很有用。为此,首选返回代码 301。 - “ignore-empty” 此关键字仅在使用日志格式表达式生成 Location 时有效(即在 http-request 或 http-response 中使用时)。它表示如果表达式结果为空,则应静默跳过该规则。主要用途是允许使用简单映射对已知路径进行大量重定向。 - “set-cookie NAME[=value]” 响应中将添加一个带有 NAME(和可选的“=value”)的“Set-Cookie”头部。这有时用于指示用户已被看到,例如为了防范某些类型的 DoS。不添加其他 cookie 选项,因此该 cookie 将是一个会话 cookie。请注意,对于浏览器而言,没有等号的纯 cookie 名称与带有等号的 cookie 不同。 - “set-cookie-fmt <fmt>” 它等同于上述选项,只是“Set-Cookie”头部将填充日志格式字符串 <fmt> 评估的结果。请注意遵守“NAME[=value]”格式,因为在配置解析期间不会执行特殊检查。 - “clear-cookie NAME[=]” 响应中将添加一个带有 NAME(和可选的“=”)的“Set-Cookie”头部,但“Max-Age”属性设置为零。这将告诉浏览器删除此 cookie。例如,这对于注销页面很有用。重要的是要注意,清除 cookie“NAME”不会删除使用“NAME=value”设置的 cookie。您必须清除 cookie“NAME=”才能实现此目的,因为浏览器会区分它们。 - “keep-query” 当此关键字在基于 Location 的重定向中使用时,原始 URI 的查询字符串(如果有)将附加到 Location。如果没有找到查询字符串,则不添加任何内容。如果 Location 已经包含查询字符串,则原始查询字符串将与“&”分隔符一起附加。
示例
仅将登录 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> 是在服务器失败后,请求或连接尝试应重试的次数。
默认情况下,重试仅适用于新的连接尝试。但是,当使用“retry-on”指令时,其他条件可能会触发重试(例如空响应、不期望的状态码),并且每个条件都将计为一次尝试,当总尝试次数达到此处的值时,将返回错误。为了避免立即重新连接到正在重新启动的服务器,在对同一服务器进行重试之前,将应用一个min(“timeout connect”、一秒)的周转计时器。当设置了“option redispatch”时,即使cookie引用了不同的服务器,也可以在另一台服务器上执行一些重试。默认情况下,这只会是最后一次重试,除非将参数传递给“option redispatch”。
retry-on [以空格分隔的关键字列表]
指定何时尝试自动重试失败的请求。此设置仅在 "mode" 设置为 http 时有效,否则将被静默忽略。可在以下上下文中使用:tcp, http

可在以下部分中使用

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<keywords> 是一个以空格分隔的关键字或 HTTP 状态码列表,每个都代表一种故障事件类型,希望在该事件上重试请求。在更改此设置之前,请阅读底部的注意事项。支持以下关键字: none 从不重试 conn-failure 当连接或 SSL 握手失败且请求无法发送时重试。这是默认设置。 empty-response 当服务器连接在请求的一部分发送后关闭,且未从服务器收到任何内容时重试。此类故障可能是由服务器端的请求超时、网络状况不佳或在处理请求时服务器崩溃或重启引起的。 junk-response 当服务器返回的内容看起来不像完整的 HTTP 响应时重试。这包括部分响应头以及非 HTTP 内容。在此类事件上重试通常不是一个好主意,这可能是由配置问题(错误的服务器端口)或请求对服务器有害(例如缓冲区溢出攻击)引起的。 response-timeout 等待服务器响应请求时服务器超时。这可能是由网络状况不佳、路径上已过期的空闲连接的重用,或请求处理成本极高引起的。在处理繁重数据库处理(全表扫描等)的服务器上重试此类事件通常不是一个好主意,因为它可能会放大拒绝服务攻击。 0rtt-rejected 重试通过早期数据发送并被服务器拒绝的请求。这些请求通常被认为是安全的重试。 <status> 任何 HTTP 状态码,包括“401”(未经授权)、“403”(禁止)、“404”(未找到)、“408”(请求超时)、“421”(误导性请求)、“425”(过早)、“429”(请求过多)、“500”(服务器错误)、“501”(未实现)、“502”(错误网关)、“503”(服务不可用)、“504”(网关超时)。 all-retryable-errors 对任何被认为是可重试的错误重试请求。这目前激活“conn-failure”、“empty-response”、“junk-response”、“response-timeout”、“0rtt-rejected”、“500”、“502”、“503”和“504”。
使用此指令将用新设置替换任何以前的设置;它不是累积的。请注意,使用“none”和“conn-failure”之外的任何内容都需要分配一个缓冲区并将整个请求复制到其中,因此它会影响内存和性能。不适合单个缓冲区的请求将永远不会重试(请参阅全局 tune.bufsize 设置)。您必须确保应用程序内置了重播保护机制,例如在请求中传递唯一的事务 ID,或者重播相同的请求没有后果,否则使用“conn-failure”和“none”之外的任何 retry-on 值都非常危险。静态文件服务器和缓存通常被认为对任何类型的重试都是安全的。使用状态码可能有助于快速离开表现异常的服务器(内存不足、文件系统问题等),但在这种情况下,立即将连接重新分派到另一个服务器可能是一个好主主意(为此请参阅“option redispatch”)。最后,重要的是要理解,大多数故障原因都是请求本身,并且重试导致服务器行为异常的请求通常会使该服务器的情况变得更糟,或者在重新分派的情况下,会使整个服务的情况变得更糟。除非您确切知道应用程序如何处理重播请求,否则不应使用此指令。默认值为“conn-failure”。
示例
retry-on 503 504
server <name> <address>[:[port]] [param*]
在后端声明一个服务器 可在以下上下文中使用:tcp, http, log

可在以下部分中使用

defaultsfrontendlistenbackend

no

no

yes

yes
参数
<name> 是分配给此服务器的内部名称。此名称将出现在日志和警报中。如果设置了“http-send-name-header”,它将添加到发送到服务器的请求头中。 <address> 是服务器的 IPv4 或 IPv6 地址。或者,支持可解析的主机名,但此名称将在启动时解析。地址“0.0.0.0”或“*”具有特殊含义。它表示连接将转发到与客户端连接的 IP 地址相同的 IP 地址。这在透明代理架构中很有用,其中客户端的连接被拦截,HAProxy 必须转发到原始目标地址。这或多或少是“transparent”关键字的作用,只不过对于服务器,可以限制并发并报告统计信息。可选地,可以在地址前使用地址族前缀来强制使用该族,而不考虑地址格式,这对于指定没有斜杠 ('/') 的 Unix 套接字路径很有用。目前支持的前缀有: - 'ipv4@' -> 地址始终是 IPv4 - 'ipv6@' -> 地址始终是 IPv6 - 'unix@' -> 地址是本地 Unix 套接字的路径 - 'abns@' -> 地址在抽象命名空间中(仅限 Linux) - 'abnsz@' -> 地址在抽象命名空间中(仅限 Linux),但明确以零终止。这意味着不使用 \0 填充来完成 sun_path。这对于与不实现 haproxy 使用的默认 abns 命名逻辑的程序进行互连很有用。 - 'sockpair@' -> 地址是已连接的 Unix 套接字或套接字对的 FD。在连接期间,后端创建一对已连接的套接字,并将其中一个通过 FD 传递。绑定部分将使用接收到的套接字作为客户端 FD。应谨慎使用。 - 'rhttp@' [ 实验性 ] -> HTTP 反向上下文中的被动服务器的自定义地址族。这是一个实验性功能,需要在此服务器之前的一行上使用“expose-experimental-directives”。您可能希望在地址参数中引用一些环境变量,请参阅第 2.3 节关于环境变量。可以使用“init-addr”设置来修改启动时解析 IP 地址的方式。 <port> 是一个可选的端口规范。如果设置,所有连接都将发送到此端口。如果未设置,将使用客户端连接到的相同端口。端口也可以带有“+”或“-”前缀。在这种情况下,服务器的端口将通过将此值添加到客户端端口来确定。 <param*> 是此服务器的参数列表。“server”关键字接受大量选项,并有一个专门的部分对此进行介绍。请参阅第 5 节了解更多详细信息。
示例
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> 用于构建服务器名称的前缀。 <num | range> 如果提供了 <num>,此模板将初始化 <num> 个服务器,服务器名称后缀从 1 到 <num>。也可以使用数字范围 <num_low>-<num_high> 作为服务器名称后缀,从 <num_low> 到 <num_high>。 <fqdn> 此模板初始化的所有服务器的 FQDN。 <port> 与“server” <port> 参数的含义相同(参见“server”关键字)。 <params*> 剩余的服务器参数,包括“server”关键字支持的所有参数。
示例
# 初始化 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 套接字路径很有用。目前支持的前缀有: - 'ipv4@' -> 地址始终是 IPv4 - 'ipv6@' -> 地址始终是 IPv6 - 'unix@' -> 地址是本地 Unix 套接字的路径 - 'abns@' -> 地址在抽象命名空间中(仅限 Linux) - 'abnsz@' -> 地址在零终止抽象命名空间中(仅限 Linux) 您可能希望在地址参数中引用一些环境变量,请参阅第 2.3 节关于环境变量。 <port> 是一个可选端口。通常不需要,但在某些非常特定的情况下可能有用。默认值为零表示系统将选择一个空闲端口。请注意,后端不支持端口范围。如果要强制使用端口范围,则必须在每个“server”行上指定它们。 <addr2> 是在完全透明代理模式下转发连接时呈现给服务器的 IP 地址。这目前仅在某些修补的 Linux 内核上受支持。指定此地址后,连接到服务器的客户端将显示此地址,而健康检查仍将使用地址 <addr>。 <port2> 是在完全透明代理模式下转发连接时呈现给服务器的可选端口(参见上面的 <addr2>)。默认值为零表示系统将选择一个空闲端口。 <hdr> 是一个 HTTP 头的名称,用于从中获取要绑定的 IP。这是一个以逗号分隔的头列表的名称,可以包含多个 IP 地址。默认情况下,使用最后一次出现的。这旨在与 X-Forwarded-For 头一起使用,并自动绑定到前一个代理看到的客户端 IP 地址,通常是 Stunnel。为了使用除最后一次出现之外的另一个出现,请参阅下面的 <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 # 使用我们的 192.168.1.200 源地址连接到服务器 source 192.168.1.200 backend transparent_ssl1 # 从客户端的源地址连接到 SSL 场 source 192.168.1.200 usesrc clientip backend transparent_ssl2 # 从客户端的源地址和端口连接到 SSL 场 # 如果本地机器上存在 IP 连接跟踪,则不建议使用。 source 192.168.1.200 usesrc client backend transparent_ssl3 # 从客户端的源地址连接到 SSL 场。它 # 对连接跟踪更友好。 source 192.168.1.200 usesrc clientip backend transparent_smtp # 使用 Tproxy 版本 4 从客户端的源地址/端口连接到 SMTP 场。 source 0.0.0.0 usesrc clientip backend transparent_http # 使用前一个代理看到的客户端 IP 连接到服务器。 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 请求受限于缓冲区大小减去保留的缓冲区空间,这意味着如果服务器列表太长,请求将不会被处理。建议一次只更改少量服务器。
示例
# 仅对 localhost 启用统计信息管理级别 backend stats_localhost stats enable stats admin if LOCALHOST
示例
# 由于身份验证,统计信息管理级别始终启用 backend stats_auth stats enable stats auth admin:AdMiN123 stats admin if TRUE
示例
# 统计信息管理级别取决于经过身份验证的用户 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 节 Bind options): - allow-0rtt - alpn - ca-file - ca-verify-file - ciphers - ciphersuites - client-sigalgs - crl-file - curves - ecdhe - no-alpn - no-ca-names - npn - sigalgs - ssl-min-ver - ssl-max-ver - verify sslbindconf 还支持来自 crt-store load 关键字的以下关键字(参见第 12.7.1 节 Load options): - crt - key - ocsp - issuer - sctl - ocsp-update
将证书 <crtname> 分配给一个自动创建的 crt-list,该列表以前端名称并以 @ 为前缀(例如:'@frontend1')。这个隐式的 crt-list 将被分配给当前前端中所有 "ssl" 绑定行。来自 stats 套接字的 crt-list 命令对这个 crt-list 有效,因此可以替换、删除或向其添加证书和 SSL 选项。
示例
frontend https bind :443 ssl bind quic4@:443 ssl ssl-f-use crt foobar.pem.rsa sigalgs "RSA-PSS+SHA256" ssl-f-use crt test.foobar.pem ssl-f-use crt test2.foobar.crt key test2.foobar.key ocsp test2.foobar.ocsp ocsp-update on
stats auth <user>:<passwd>
启用带身份验证的统计信息并授予帐户访问权限 可在以下上下文中使用:http

可在以下部分中使用

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<user> 是要授予访问权限的用户名 <passwd> 是与此用户关联的明文密码
此语句启用具有默认设置的统计信息,并限制访问仅限于已声明的用户。它可以根据需要重复多次,以允许尽可能多的用户。当用户在没有有效帐户的情况下尝试访问统计信息时,将返回“401 Forbidden”响应,以便浏览器要求用户提供有效的用户和密码。返回给浏览器的实际内容可以使用“stats realm”进行配置。由于认证方法是 HTTP 基本认证,密码在网络上以明文形式传输。因此,决定配置也使用明文密码,以提醒用户这些密码不应是敏感的,也不应与任何其他帐户共享。还可以使用“stats scope”缩小报告中出现的代理范围。尽管此语句本身足以启用统计信息报告,但建议设置所有其他设置,以避免依赖默认的非显而易见的参数。
示例
# 公共访问(仅限于此后端) 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 : 无限制 尽管此语句本身足以启用统计报告,但建议设置所有其他设置,以避免依赖默认的不明显参数。
示例
# 公共访问(仅限于此后端) 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”语句从统计报告中移除版本信息。建议对公共站点或任何具有弱登录名/密码的站点使用此功能。尽管此语句本身足以启用统计报告,但建议设置所有其他设置,以避免依赖默认的不明显参数。
示例
# 公共访问(仅限于此后端) 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”结合使用时才有用,因为它只与身份验证相关。尽管此语句本身足以启用统计报告,但建议设置所有其他设置,以避免依赖默认的不明显参数。
示例
# 公共访问(仅限于此后端) 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 报告页面将包含一个“刷新”/“停止刷新”链接,以便用户可以选择是否希望页面自动刷新。尽管仅此语句就足以启用统计信息报告,但建议设置所有其他设置,以避免依赖默认的不明显参数。
示例
# 公共访问(仅限于此后端) 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 部分的名称。特殊名称“.”(一个点)表示该语句所在的节。
指定此语句后,只有使用此语句枚举的部分才会出现在报告中。所有其他部分都将被隐藏。如果需要报告多个部分,此语句可以根据需要出现多次。请注意,名称检查是作为简单的字符串比较执行的,并且从不检查给定的部分名称是否真的存在。尽管此语句本身足以启用统计报告,但建议设置所有其他设置,以避免依赖默认的不明显参数。
示例
# 公共访问(仅限于此后端) 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> 是一个可选的要报告的描述。如果未指定,则自动使用全局部分的描述。此语句对于向客户提供共享服务的用户非常有用,其中每个客户的节点或描述应该不同。尽管此语句本身足以启用统计报告,但建议设置所有其他设置,以避免依赖默认的不明显参数。默认情况下不显示描述。
示例
# 内部监控访问(无限制) 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”实例中非常方便。这使得为统计信息专门分配地址或端口变得容易。尽管此语句本身足以启用统计信息报告,但建议设置所有其他设置,以避免依赖默认的非显而易见的参数。
示例
# 公共访问(仅限于此后端) 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 之间保持粘滞性变得非常容易。
示例
# 将 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> 是一个可选的存储条件。它使得只有在满足(或不满足)某些条件时才能存储某些标准。例如,它可以用于仅当响应是 SSL 服务器 hello 时才存储 SSL 会话 ID。
有些协议或应用程序需要复杂的粘滞规则,并且不能总是简单地依赖 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”规则在建立服务器连接后进行评估,因此该表将包含处理请求的真实服务器。
示例
# 将 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 服务器 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 规则也可以使用相同的表。这意味着每个表可以一次从请求中学习一个元素,从响应中学习一个元素。该表将包含处理请求的真实服务器。
示例
# 从请求和响应中学习 SSL 会话 ID 并创建亲和性。 backend https mode tcp balance roundrobin # 最大 SSL 会话 ID 长度为 32 字节。 stick-table type binary len 32 size 30k expire 30m acl clienthello req.ssl_hello_type 1 acl serverhello res.ssl_hello_type 2 # 使用 tcp content accepts 检测 ssl 客户端和服务器 hello。 tcp-request inspect-delay 5s tcp-request content accept if clienthello # 默认情况下,响应检查延迟没有超时。 tcp-response content accept if serverhello # SSL 会话 ID (SSLID) 可能存在于客户端或服务器 hello 中。 # 它的长度在偏移量 43 处编码为 1 字节,其值从 # 偏移量 44 处开始。 # 如果是客户端 hello,则在请求上匹配并学习。 stick on req.payload_lv(43,1) if clienthello # 如果是服务器 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> 必须是 1 到 65535 之间有效的 TCP 端口源整数,或采样获取表达式。addr <ip> 定义了进行健康检查的 IP 地址。send-proxy 通过上游 socks4 代理发送 PROXY 协议字符串 via-socks4 启用出站健康检查。ssl 打开加密连接 sni <sni> 指定用于通过 SSL 进行健康检查的 SNI。alpn <alpn> 定义要与 ALPN 一起通告的协议。协议列表由逗号分隔的协议名称列表组成,例如:“http/1.1,http/1.0”(不带引号)。如果未设置,则使用服务器 ALPN。proto <name> 强制连接使用多路复用器的协议。它必须是 TCP 多路复用协议,并且必须可以在后端使用。可用协议列表在 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 规则所需的最小数据量。如果收到的字节数低于此限制,检查将等待更多数据。此选项可用于解决一些模糊的匹配规则,或避免对已知仍不完整的内容执行代价高昂的正则表达式匹配。如果使用精确字符串(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> 是要查找的模式。它可以是字符串或正则表达式。如果模式包含空格,则必须使用通常的反斜杠 ('\') 进行转义。如果匹配设置为 binary,则模式必须以偶数形式的十六进制数字序列传递。每两个数字序列将代表一个字节。十六进制数字可以使用大写或小写。
可用的匹配项有意地与其 http-check 对应项相似: string <string>:测试响应缓冲区中的精确字符串匹配。如果响应缓冲区包含此精确字符串,则健康检查响应将被视为有效。如果 "string" 关键字前缀为 "!",则如果正文包含此字符串,则响应将被视为无效。这可用于在协议响应中查找强制模式,或在协议横幅中出现特定错误时检测故障。 rstring <regex>:对响应缓冲区测试正则表达式。如果响应缓冲区匹配此表达式,则健康检查响应将被视为有效。如果 "rstring" 关键字前缀为 "!",则如果正文匹配该表达式,则响应将被视为无效。 string-lf <fmt>:测试响应缓冲区中的自定义日志格式匹配。如果响应缓冲区包含评估 <fmt> 产生​​的字符串,该字符串遵循第 8.2.6 节中描述的自定义日志格式规则,则健康检查响应将被视为有效。如果前缀为 "!",则如果缓冲区包含该字符串,则响应将被视为无效。 binary <hexstring>:测试其十六进制形式的精确字符串在响应缓冲区中匹配。如果响应缓冲区包含此精确的十六进制字符串,则健康检查响应将被视为有效。目的是匹配二进制协议上的数据。 rbinary <regex>:对响应缓冲区测试正则表达式,如 "rstring"。但是,响应缓冲区被转换为其十六进制形式,包括 NUL 字节。这允许使用所有正则表达式引擎匹配任何二进制内容。十六进制转换的大小是原始响应的两倍。因此,预期的模式应该在最多一半的响应缓冲区大小上工作。 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 的条件,在这种情况下,只有当条件评估为 true 时才会被评估。条件在执行操作之前进行评估,并且操作只执行一次。因此,如果操作更改了作为条件一部分检查的元素,则没有问题。这也意味着多个操作可以依赖相同的条件,因此更改条件评估的第一个操作足以隐式禁用其余操作。例如,当尝试在变量为空时从各种源向变量分配值时,会使用此方法。“tcp-request connection”语法中的第一个关键字是规则的操作,可选地后跟操作的可变数量的参数。支持的操作及其各自的语法在第 4.3 节“操作”(查找标记“TCP RqCon”的操作)中列举。此指令仅在命名默认部分中可用,而不在匿名部分中可用。默认部分中定义的规则在关联的代理部分中的规则之前进行评估。为避免歧义,在这种情况下,具有前端功能的代理和具有后端功能的代理不能使用相同的默认部分。这意味着侦听部分不能使用定义此类规则的默认部分。请注意,“if/unless”条件是可选的。如果操作上未设置条件,则仅无条件执行。这对于“track-sc*”操作以及将默认操作更改为拒绝可能很有用。
示例
接受所有来自白名单主机的连接,拒绝过快的连接而不计数,并跟踪已接受的连接。这导致来自滥用来源的连接速率受到限制。
tcp-request connection accept if { src -f /etc/haproxy/whitelist.lst } tcp-request connection reject if { src_conn_rate gt 10 } tcp-request connection track-sc0 src
示例
接受所有来自白名单主机的连接,计算所有其他连接并拒绝过快的连接。这导致滥用者只要不减速就会被阻止。
tcp-request connection accept if { src -f /etc/haproxy/whitelist.lst } tcp-request connection track-sc0 src tcp-request connection reject if { sc0_conn_rate gt 10 }
示例
为来自所有已知代理的流量启用 PROXY 协议。
tcp-request connection expect-proxy layer4 if { src -f proxies.lst }
有关 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”规则可以使用内容来做出决策。通常,这些决策会考虑协议识别或有效性。第二个区别是,基于内容的规则可以在前端和后端使用。在与客户端进行 HTTP keep-alive 的情况下,所有 tcp-request content 规则都会再次评估,因此 HAProxy 会记录“tcp-request connection”规则与“tcp-request content”规则分配的粘性计数器,并在处理 HTTP 请求后刷新所有与内容相关的计数器,以便它们可以由针对下一个请求再次评估的规则再次评估。当规则跟踪某些 L7 信息或受基于 L7 的 ACL 条件限制时,这一点尤为重要,因为跟踪可能会在请求之间发生变化。基于内容的规则按其精确的声明顺序进行评估。如果没有规则匹配,或者没有规则,则默认操作是接受内容。插入的规则数量没有特定限制。虽然没有强制性要求,但建议在“tcp-request connection”规则中使用 track-sc0,在前端的“tcp-request content”规则中使用 track-sc1,在后端的“tcp-request content”规则中使用 track-sc2,因为这使得配置更具可读性且更容易排除故障,但这只是一项指导,所有计数器都可以在任何地方使用。“tcp-request content”语法中的第一个关键字是规则的操作,可选地后跟操作的可变数量的参数。支持的操作及其各自的语法在第 4.3 节“操作”(查找标记“TCP RqCnt”的操作)中列举。此指令仅在命名默认部分中可用,而不在匿名部分中可用。默认部分中定义的规则在关联的代理部分中的规则之前进行评估。为避免歧义,在这种情况下,具有前端功能的代理和具有后端功能的代理不能使用相同的默认部分。这意味着侦听部分不能使用定义此类规则的默认部分。请注意,“if/unless”条件是可选的。如果操作上未设置条件,则仅无条件执行。这对于“track-sc*”操作以及将默认操作更改为拒绝可能很有用。另请注意,建议使用“tcp-request session”规则来跟踪不依赖于第 7 层内容的信息,尤其是对于 HTTP 前端。某些 HTTP 处理在会话级别执行,可能会导致请求的早期拒绝。因此,在这种情况下,内容级别的跟踪可能会受到干扰。在启动期间会发出警告,以尽可能防止此类不可靠的使用。使用 TCP 代理的“tcp-request content”规则匹配第 7 层内容是完全可能的,因为 HTTP 特定的 ACL 匹配能够在提取所需数据之前初步解析缓冲区的内容。如果缓冲的内容无法解析为有效的 HTTP 消息,则 ACL 不匹配。此处涉及的解析器与所有其他 HTTP 处理完全相同,因此没有解析不同内容的风险。在 HTTP 前端或 HTTP 后端,保证在首次评估规则时 HTTP 内容始终立即存在,因为 HTTP 解析是在连接处理的早期阶段(会话级别)执行的。但对于此类代理,使用“http-request”规则更自然且更推荐。如果信息在处理规则时存在,也可以跟踪第 7 层信息。当要跟踪的数据尚未可用时,规则处理引擎能够等待直到检查延迟到期。
示例
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 中继的人们通常担心在不进行任何分析的情况下将任何类型的协议传递给服务器的风险。为了能够分析请求内容,我们必须首先保留数据,然后进行分析。此语句只是启用数据保留,最长持续指定的时间。TCP 内容检查在连接到达前端时非常早地应用,然后当连接转发到后端时也非常早地应用。这意味着如果前端和后端都有 tcp-request 规则,连接可能会在前端经历第一次延迟,在后端经历第二次延迟。请注意,在执行内容检查时,HAProxy 会为每个新收到的数据块评估所有规则,同时考虑到这些数据是部分数据。如果在上述延迟到期之前没有规则匹配,则会在到期时执行最后一次检查,此时认为内容是确定的。如果未设置延迟,HAProxy 将根本不会等待,并将立即根据可用信息应用判决。显然,这不太可能非常有用,甚至可能存在竞争条件,因此不建议采用此类设置。请注意,如果发生连接错误或关闭,或者请求缓冲区已满,则检查延迟会缩短。一旦规则匹配,请求就会被释放并照常继续。如果超时达到且没有规则匹配,则默认策略是让其不受影响地通过。对于大多数协议,将其设置为几秒钟就足够了,因为大多数客户端在连接后会立即发送完整的请求。再增加 3 秒或更多时间以涵盖 TCP 重传,但仅此而已。对于某些协议,使用较大的值可能是有意义的,例如确保客户端在服务器之前从不说话(例如 SMTP),或等待客户端说话,然后再将数据传递给服务器(例如 SSL)。请注意,客户端超时必须至少覆盖检查延迟,否则它会首先到期。如果客户端关闭连接或缓冲区已满,则延迟会立即到期,因为内容将无法再更改。此指令仅在命名默认部分中可用,而不在匿名部分中可用。代理从其默认部分继承此值。
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”的操作)中列举。此指令仅在命名默认部分中可用,而不在匿名部分中可用。默认部分中定义的规则在关联的代理部分中的规则之前进行评估。为避免歧义,在这种情况下,具有前端功能的代理和具有后端功能的代理不能使用相同的默认部分。这意味着侦听部分不能使用定义此类规则的默认部分。请注意,“if/unless”条件是可选的。如果操作上未设置条件,则仅无条件执行。这对于“track-sc*”操作以及将默认操作更改为拒绝可能很有用。
示例
默认跟踪原始源地址,或者对于来自本地代理的连接,跟踪 PROXY 协议头中通告的地址。第一个连接级别的规则为这些连接启用了 PROXY 协议的接收,第二个规则跟踪我们在可选解码后决定保留的任何地址。
tcp-request connection expect-proxy layer4 if { src -f proxies.lst } tcp-request session track-sc0 src
示例
接受所有来自白名单主机的会话,拒绝过快的会话而不对其进行计数,并跟踪已接受的会话。这导致来自滥用来源的会话速率受到限制。
tcp-request session accept if { src -f /etc/haproxy/whitelist.lst } tcp-request session reject if { src_sess_rate gt 10 } tcp-request session track-sc0 src
示例
接受所有来自白名单主机的会话,对所有其他会话进行计数,并拒绝过快的会话。这导致滥用会话被阻止,直到它们减速为止。
tcp-request session accept if { src -f /etc/haproxy/whitelist.lst } tcp-request session track-sc0 src tcp-request session reject if { sc0_sess_rate gt 10 }
有关 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”的操作)中列举。此指令仅在命名默认部分中可用,而不在匿名部分中可用。默认部分中定义的规则在关联的代理部分中的规则之前进行评估。为避免歧义,在这种情况下,具有前端功能的代理和具有后端功能的代理不能使用相同的默认部分。这意味着侦听部分不能使用定义此类规则的默认部分。请注意,“if/unless”条件是可选的。如果操作上未设置条件,则仅无条件执行。这对于将默认操作更改为拒绝可能很有用。支持多种类型的操作:使用“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”。此参数特定于后端,但可以在“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”。此参数特定于前端,但可以在“defaults”部分中一次性指定。这实际上是确保不会忘记它的最简单解决方案之一。未指定的超时会导致无限超时,不建议这样做。这种用法是允许的并且有效,但在启动期间会报告警告,因为它可能导致如果系统超时未配置,则系统中会积累过期的会话。
为半关闭连接设置客户端侧的不活动超时。可在以下上下文中使用:tcp, http

可在以下部分中使用

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
当客户端预期确认或发送数据,而一个方向已经关闭时,将应用不活动超时。此超时与“timeout client”不同,因为它仅适用于在一个方向上关闭的连接。这对于避免当客户端未干净断开连接时,连接长时间处于 FIN_WAIT 状态特别有用。此问题在 RDP 或 WebSocket 等长时间连接中特别常见。请注意,当连接在一个方向上关闭时,此超时可以覆盖“timeout tunnel”。一旦发送 GOAWAY 帧,通常表示连接将快速结束,此超时将应用于空闲的 HTTP/2 连接。此参数特定于前端,但可以在“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> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
默认情况下,在保持活动状态下等待新请求的时间由“timeout http-request”设置。然而,这并非总是方便的,因为有些人希望保持活动超时很短,以便更快地释放连接,而另一些人则希望有更长的超时,但在请求开始时仍然有短超时。“http-keep-alive”超时涵盖了这些需求。它将定义在发送响应后等待新 HTTP 请求开始的时间。一旦看到请求的第一个字节,将使用“http-request”超时来等待完整请求的到来。请注意,新请求之前的空行不会刷新超时,也不算作新请求。两个超时之间还有另一个区别:当连接在 timeout http-keep-alive 期间过期时,不会返回错误,连接只是关闭。如果连接在“http-request”中等待请求完成时过期,除非在前端设置了“option http-ignore-probes”,否则会向客户端返回 HTTP 408 错误,然后关闭连接。通常,“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 后在传输中被销毁时(HAProxy 甚至无法记录错误),这可能会导致响应被截断。HTTP/2 连接建议的低起始值约为 4 秒。这将防止大多数现代保持活动实现不必要地保持陈旧连接打开,同时允许后续请求重用连接。但是,这应根据需要进行调整,只是一个起点。如果未设置此参数,“http-request”超时适用,如果两者都未设置,则“timeout client”仍在较低级别适用。应在前端设置才能生效,除非前端处于 TCP 模式,在这种情况下将使用 HTTP 后端的超时。
设置等待一个完整的 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”,则在保持活动连接上再次使用此超时以等待第二个请求。通常,将其设置为几秒钟就足够了,因为大多数客户端在连接后会立即发送完整的请求。再增加 3 秒或更多时间以涵盖 TCP 重传,但仅此而已。将其设置为非常低的值(例如 50 毫秒)通常在本地网络上有效,只要没有数据包丢失。这将防止人们使用 telnet 发送裸 HTTP 请求。如果未设置此参数,则客户端超时仍适用于传入请求的每个数据块之间。应在前端设置才能生效,除非前端处于 TCP 模式,在这种情况下将使用 HTTP 后端的超时。
timeout queue <timeout>
设置在队列中等待一个可用连接槽的最长时间。可在以下上下文中使用:tcp, http

可在以下部分中使用

defaultsfrontendlistenbackend

yes

no

yes

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

可在以下部分中使用

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
不活动超时适用于服务器预期确认或发送数据的情况。在 HTTP 模式下,此超时在服务器响应的第一阶段尤为重要,当它必须发送头部时,因为它直接代表服务器处理请求的时间。要确定设置什么值,通常最好从被认为是不可接受的响应时间开始,然后检查日志以观察响应时间分布,并相应调整值。默认情况下,该值以毫秒为单位指定,但如果数字后跟单位,则可以以任何其他单位指定,如本文档顶部所述。在 TCP 模式下(以及在较小程度上,在 HTTP 模式下),强烈建议客户端超时与服务器超时保持相等,以避免复杂的调试情况。无论预期的服务器响应时间如何,指定略高于 3 秒倍数(例如最小 4 或 5 秒)的超时以覆盖至少一次或多次 TCP 数据包丢失是一个好习惯。如果一些长寿命流与短寿命流混合在一起(例如 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 状态的会话来检测。默认情况下,该值以毫秒为单位指定,但如果数字后跟单位,则可以以任何其他单位指定,如本文档顶部所述。无论预期的正常空闲时间如何,指定略高于 3 秒倍数(例如最小 4 或 5 秒)的超时以覆盖至少一次或多次 TCP 数据包丢失是一个好习惯。此参数特定于后端,但可以在“defaults”部分中一次性指定。这实际上是确保不会忘记它的最简单解决方案之一。
示例
defaults http option http-server-close timeout connect 5s timeout client 30s timeout client-fin 30s timeout server 30s timeout tunnel 1h # 用于 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 的协议时(另请参阅“req.ssl_sni”),可以根据 TLS SNI 字段在服务器场中选择服务器。如果这些服务器的权重设置为零,则它们将不会用于其他流量。
示例
# 基于 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 地址。如果此操作用于查找服务器 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 # 当变量未设置时返回 503, # 这意味着 DNS 解析错误 use_backend b_503 unless { var(txn.myip) -m found } default_backend be backend b_503 # 用于返回 503 的虚拟后端。 # 可以使用 errorfile 指令向最终用户发送漂亮的 # 503 错误页面 backend be # 阻止 HAProxy 重新连接到本地网络上的服务 # (用于扫描网络的伪造 DNS 名称) 的规则 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 导致不安全的转换。还可能出现一种情况,即本身安全的规范化器组合在不正确组合时导致不安全的转换。例如,“percent-decode-unreserved”规范化器在损坏的 URI 包含裸百分号字符时可能会导致意外结果。一个这样的损坏 URI 是“/%%36%36”,它将被解码为“/%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 部分不包含方案或授权。主要只有发送给代理的请求、手动伪造的请求以及某些应用程序发出的请求才使用绝对形式。因此,在 HTTP/1.x 中,以“/”开头的规则,"replace-uri" 通常都能正常工作。但在 HTTP/2 中,客户端被鼓励只发送绝对 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" 的参数指定。最后,可以定义响应本身。它可以是一个完整的 HTTP 响应,指定要使用的错误文件,或者指定要使用的文件或字符串的响应负载。创建响应遵循以下规则:* 如果既未定义错误文件也未定义要使用的负载,则返回一个虚拟响应。只考虑 "status" 参数。它可以是 [200, 599] 范围内的任何代码。如果存在 "content-type" 参数,则忽略它。* 如果设置了 "default-errorfiles" 参数,则考虑代理的错误文件。如果定义了 "status" 参数,则它必须是 HAProxy 处理的状态码之一(200, 400, 403, 404, 405, 408, 410, 413, 414, 425, 429, 431, 500, 501, 502, 503 和 504)。如果存在 "content-type" 参数,则忽略它。* 如果定义了特定的错误文件,并带有 "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" 参数,它被视为原始字符串。当响应不基于错误文件时,可以使用 "hdr" 参数向响应附加 HTTP 标头字段。否则,所有 "hdr" 参数都将被忽略。对于每个参数,标头名称在  中指定,其值由  定义, 遵循第 8.2.6 节中描述的自定义日志格式规则。请注意,生成的响应必须小于缓冲区。为了避免任何警告,当加载错误文件或原始文件时,为标头重写保留的缓冲区空间也应为空闲。此操作是最终的,即同一规则集的后续规则不会对当前部分进行评估。
示例
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”数组数据类型(不适用于旧版“gpc0”、“gpc1”、“gpc0_rate”或“gpc1_rate”数据类型)。对于旧版数据类型没有等效函数,但如果值始终为 1,请参阅“sc-inc-gpc()”、“sc-inc-gpc0()”和“sc-inc-gpc1()”。也没有办法递减该值,但可以使用“sc-set-gpt()”将精确值存储在通用标签中。此操作的主要用途是计算分数或总容量(例如,服务器或 WAF 报告的每个源 IP 的估计危险、总上传字节等)。
sc-inc-gpc(<idx>,<sc-id>)

可用

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"。
示例
# 在路径前添加主机名 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"(如果前者未设置)指定。在此延迟之后,如果客户端仍处于连接状态,则会返回响应,以便客户端不会怀疑自己被“tarpit”(陷阱)了。日志将报告标志 "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”操作。
alpn <protocols>
这会启用 TLS ALPN 扩展,并宣传指定的协议列表为 ALPN 上支持的协议。协议列表由逗号分隔的协议名称列表组成,例如:“http/1.1,http/1.0”(不带引号)。这要求 SSL 库在构建时启用了 TLS 扩展支持(使用 haproxy -vv 检查)。ALPN 扩展取代了最初的 NPN 扩展。在协议层面上,ALPN 是在 HTTPS 前端启用 HTTP/2 和在 QUIC 前端启用 HTTP/3 所必需的。然而,当这些前端都没有设置 "npn"、"alpn" 和 "no-alpn" 时,常规 HTTPS 前端将使用默认值“h2,http/1.1”,QUIC 前端将使用“h3”。OpenSSL 1.0.2 之前的版本不支持 ALPN,只支持现在已废弃的 NPN 扩展。在撰写本文时,大多数浏览器仍然支持 ALPN 和 NPN 用于 HTTP/2,因此回退到 NPN 可能仍然有效一段时间。但应尽可能使用 ALPN。未宣传的协议不会协商。例如,可以使用以下方式仅接受 HTTP/2 连接:bind :443 ssl crt pub.pem alpn h2 # 明确禁用 HTTP/1.1 QUIC 仅支持 h3 和 hq-interop 作为 ALPN。h3 用于 HTTP/3,hq-interop 用于 http/0.9 和 QUIC 互操作运行器(参见 https://interop.seemann.io)。每个 "alpn" 语句将替换前一个语句。要删除它们,请使用 "no-alpn"。请注意,某些旧版浏览器(例如 Firefox 88)在 H2 上使用 WebSocket 时曾出现问题,如果遇到此类设置,可能需要明确禁用 "alpn" 字符串中的 HTTP/2,强制其为“http/1.1”或 "no-alpn",或者全局启用 "h2-workaround-bogus-websocket-clients"。
backlog <backlog>
将套接字的 backlog 设置为此值。如果未指定或为 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)定义。
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 握手期间协商的密码算法(“密码套件”)列表的字符串。字符串的格式在 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 种选择:- 可以将多证书捆绑包配置为第一个证书(在配置中,现有的文件是 foobar.pem.ecdsa 和 foobar.pem.rsa,则为 `crt foobar.pem`)。- 或者在 crt-list 行中为每个证书使用 '*' 过滤器。- 可以使用 'default-crt' 关键字。请注意,相同的证书可以加载多次而不会产生副作用。某些 CA(例如 GoDaddy)在获取证书时会提供服务器类型下拉列表,其中不包括 HAProxy。如果发生这种情况,请务必选择 CA 认为需要中间 CA 的 Web 服务器(对于 GoDaddy,选择 Apache Tomcat 将获得正确的捆绑包,但许多其他服务器,例如 nginx,会导致捆绑包错误,并且对某些客户端无效)。对于每个 PEM 文件,HAProxy 会检查同一路径下是否存在以 ".ocsp" 为后缀的文件。如果找到此类文件,则会自动启用 TLS 证书状态请求扩展(也称为“OCSP 封装”)的支持。此文件的内容是可选的。如果非空,它必须包含 DER 格式的有效 OCSP 响应。为了有效,OCSP 响应必须符合以下规则:它必须指示良好状态,它必须是 PEM 文件证书的单个响应,并且在添加时必须有效。如果不遵守这些规则,OCSP 响应将被忽略并发出警告。为了识别 OCSP 响应适用于哪个证书,需要颁发者证书。如果 PEM 文件中未找到颁发者证书,则将从与 PEM 文件相同路径下以 ".issuer" 为后缀的文件中加载(如果存在),否则将失败并显示错误。对于每个 PEM 文件,HAProxy 还会检查同一路径下是否存在以 ".sctl" 为后缀的文件。如果找到此类文件,则启用证书透明度 (RFC6962) TLS 扩展的支持。该文件必须包含有效的签名证书时间戳列表,如 RFC 中所述。文件会被解析以检查基本语法,但不验证签名。在某些情况下,需要支持多种密钥类型,例如在提供给客户端的密码套件中支持 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" 选项时,将使用默认证书。当客户端未使用服务器名称扩展或服务器名称与任何配置的证书不匹配时,将提供默认证书。
示例
# 此 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。
此选项仅可与 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>
为在此 bind 行上分配的每个侦听套接字生成区分大小写的全局唯一 ID。前缀将与当前 bind 行上侦听器的位置索引连接,使用字符“-”作为分隔符。有关其格式的更多信息,请参阅“guid”代理关键字描述。
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 地址需要能够访问托管在不同接口上的前端时,这对于解决非对称路由问题非常有用。
label <label>
为这些套接字设置一个可选标签。它可以用于按标签对套接字进行分组,而与 bind 行的声明位置无关。
level <level>
此设置仅用于 stats sockets,以限制可在 socket 上发出的命令类型。其他 socket 会忽略此设置。<level> 可以是以下之一:- "user" 是权限最低的级别;只能读取非敏感统计信息,不允许任何更改。在难以限制 socket 访问的系统上,此级别可能很有用。- "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)。以下是可在 bind 行上作为 "proto" 指令参数使用的协议: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 此选项的目的是绕过为从该监听套接字实例化的所有连接选择最佳多路复用器协议。例如,可以通过在 bind 行上指定“proto h2”来强制在纯 TCP 上使用 http/2。
quic-cc-algo { cubic | newreno | bbr | nocc }[(<args,...>)]
这是一个 QUIC 特定设置,用于为尝试连接到配置的 QUIC 监听器的任何连接选择拥塞控制算法。它们与 TCP 使用的算法相似。拥塞算法之上激活了速率控制以减少丢包并提高吞吐量。它可以通过 "tune.quic.disable-tx-pacing" 全局关键字关闭。在大多数情况下,速率控制应保持激活,尤其是在使用 BBR 时,因为它依赖于速率控制才能正常工作。在没有速率控制的情况下使用 BBR 可能会导致传输期间的减速或高丢包率。默认值:cubic 对于进一步的自定义,可以在算法令牌后指定参数列表。它必须写在括号内,用逗号分隔。每个参数都是可选的,如果需要可以为空。以下是每个参数的强制顺序:- 最大窗口大小(以字节为单位)。它必须大于 10k 且小于 4g。默认情况下使用 "tune.quic.frontend.default-max-window-size" 值。
示例
# newreno 拥塞控制算法 quic-cc-algo newreno # cubic 拥塞控制算法,窗口大小为 1MB quic-cc-algo cubic(1m)
可以使用一个特殊值“nocc”来强制使用一个始终设置为最大尺寸的固定拥塞窗口。这保留用于调试场景,以消除拥塞控制器引起的任何副作用。它绝不能在生产环境中使用,因为它可能很快导致网络问题,如高丢包率。
这是一个 QUIC 特定设置,它强制为所有到配置的 QUIC 监听器的连接尝试使用 QUIC Retry 功能。它包括验证对端是否能够在其用于发起新连接的传输地址上接收数据包,方法是向它们发送一个包含令牌的 Retry 数据包。此令牌必须被发回给 Retry 数据包的发送方,后者是唯一能够验证该令牌的一方。请注意,即使设置了 Retry 阈值(参见“tune.quic.retry-threshold”设置),QUIC Retry 也将始终被使用。此设置要求设置集群密钥,否则在启动时会报告错误(参见“cluster-secret”)。有关 QUIC retry 的更多信息,请参见 https://www.rfc-editor.org/rfc/rfc9000.html#section-8.1.2。
quic-socket [ connection | listener ]
这个 QUIC 特定设置允许为特定监听器定义套接字分配模式。有关其用法的完整描述,请参见“tune.quic.socket-owner”。
此设置仅与 stats 套接字一起使用,用于配置附加到信息反馈消息前的严重性级别输出。消息的严重性级别范围可以在 0 到 7 之间,符合 syslog rfc5424。请求数据的有效且成功的套接字命令(例如“show map”、“get acl foo”等)绝不会附加严重性级别。其他套接字会忽略此设置。<format> 可以是以下之一:- “none”(默认)不向反馈消息前附加严重性级别。- “number” 严重性级别作为数字附加。- “string” 严重性级别作为遵循 rfc5424 约定的字符串附加。
shards { <number> | by-thread | by-group }
在多线程模式下,如果操作系统支持在相同 IP:端口上拥有多个监听器,此设置将自动为此行创建指定数量的多个相同监听器,所有这些监听器都绑定到此监听器所附带的线程数量的公平份额。当使用非常大的线程数时,内核锁在单个套接字上开始导致显著开销时,这有时会很有用。在这种情况下,传入流量分布到多个套接字上,从而减少了争用。请注意,这样做很容易通过让更多线程工作一点点来增加 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 socket 填充。此选项也可在全局语句 "ssl-default-bind-options" 上使用,并且可以通过在 "bind" 行上使用 "no-strict-sni" 来选择性禁用。有关更多信息,请参阅 "crt" 选项。请参阅管理指南中的 "add ssl crt-list" 命令。
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",甚至会有一个专门的统计条目。主要目的是让多条 bind 行共享相同的 IP:端口,但不在监听器中使用相同的线程,以便系统可以将传入连接分配到多个队列中,绕过 haproxy 的内部队列负载均衡。目前已知 Linux 3.9 及更高版本支持此功能。另请参阅上面的 "shards" 关键字,它会自动复制 "bind" 行并将其分配给多个线程组。此关键字与反向 HTTP 绑定兼容。但是,对于此类监听器,禁止指定跨越多个线程组的线程集,因为这可能导致 "nbconn" 无法按预期工作。
此设置仅在内置 OpenSSL 支持时可用。它启用了无状态会话恢复(RFC 5077 TLS Ticket 扩展)。这是默认设置,但如果通过 "no-tls-tickets" 全局禁用,则可能需要在 "bind" 行上选择性地重新启用此功能,该功能在 "ssl-default-bind-options" 中提到。另请参阅 "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" 关键字支持一定数量的设置,所有这些设置都作为参数传递到服务器行。这些参数出现的顺序无关紧要,并且它们都是可选的。其中一些设置是单个单词(布尔值),而另一些则在其后需要一个或多个值。在这种情况下,值必须紧随设置名称。除 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”,可选地后跟一个井号('#')后的描述字符串。所有这些都将服务器的操作状态标记为DOWN,但由于单词本身报告在统计页面上,因此这种区别允许管理员知道情况是否在意料之中:服务可能被有意停止,可能显示为UP但未能通过某些有效性测试,或者可能被视为DOWN(例如,缺少进程或端口无响应)。 - 单词“up”将服务器的操作状态重新设置为UP,如果健康检查也报告服务可访问。代理未宣传的参数不会更改。例如,代理可能设计用于监视CPU使用率,并且只报告相对权重,从不与操作状态交互。同样,代理可以设计为一个具有3个单选按钮的最终用户界面,允许管理员只更改管理状态。然而,重要的是要考虑只有代理可以撤销其自身的操作,因此如果服务器使用代理设置为DRAIN模式或DOWN状态,代理必须实现其他等效操作以使服务重新投入运行。未能连接到代理不被视为错误,因为连接性由由“check”参数启用的常规健康检查进行测试。但请注意,在代理报告“down”后停止代理不是一个好主意,因为只有报告“up”的代理才能使服务器再次启动。请注意,Unix stats socket上的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”时,才会发送早期数据。
alpn <protocols>
可在以下上下文中使用:tcp, http 这将启用 TLS ALPN 扩展,并通告指定的协议列表作为 ALPN 之上支持的协议。协议列表是一个以逗号分隔的协议名称列表,例如:"http/1.1,http/1.0"(不含引号)。这需要 SSL 库在构建时启用了对 TLS 扩展的支持(可通过 haproxy -vv 查看)。ALPN 扩展取代了最初的 NPN 扩展。连接到 HTTP/2 服务器需要 ALPN。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 环境变量来覆盖。
可用于以下场景: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 此选项允许检查重用空闲连接(如果可用),而不是打开专用连接。连接在检查完成后重新插入池中。主要目标是限制特定服务器上的连接打开和关闭数量。请注意,为了配置简单,如果定义了任何特定的检查连接选项(无论是在服务器行上还是通过自定义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)、多路复用器名称及其标志。一些协议在服务器端可能存在队头阻塞(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 此选项的目的是绕过为与此服务器建立的健康检查连接选择最佳多路复用器协议。如果未定义,将使用服务器的协议(如果已设置)。
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”状态。这意味着它在维护模式下被标记为停用,除了持久模式允许的连接之外,没有其他连接会到达它。这非常适合设置新服务器,因为正常流量永远不会到达它们,同时仍然可以通过使用强制持久机制来测试服务。另请参阅“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。此 ID 在所有 haproxy 配置中的所有对象类型中必须是唯一的。有关其格式的更多信息,请参阅“guid”代理关键字描述。
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 # address resolution never fails 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}中的任何其他显式单位输入。“inter”参数也用作发送到服务器的健康检查的超时,如果未设置“timeout check”。为了减少当多个服务器托管在同一硬件上时的“共振”效应,所有服务器的代理和健康检查都以一个小的时移启动。还可以使用全局“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
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(默认值,禁用此限制)或任何正值。值为零将有效禁用keep-alive。这仅用于解决某些服务器随时间泄漏资源的bug。此参数不一定被下层遵守,因为可能存在技术限制使其无法强制执行。至少HTTP/2到服务器的连接将遵守它。 在ring上下文中使用时:“max-reuse”参数指示sink TCP连接处理器不应将服务器连接重用超过此次数来发送消息。这意味着一旦在同一连接上处理了至少“max-reuse + 1”条消息,到服务器的连接将被强制销毁。然后,到服务器的连接将自动重新创建。在多线程环境中处理大量消息时,这有助于更好地将ring的负载分配到多个线程上。实际上,每个连接在其整个持续时间内都绑定到相同的CPU线程:与HTTP不同,没有syslog事务之类的东西,因此服务器连接可以无限期地存在,只要服务器不关闭连接或不发生网络错误。通过不时销毁连接,我们为其他线程提供了轮流处理一些消息的机会。这也有助于在haproxy和日志服务器之间存在额外负载均衡层的情况下,优雅地轮换日志服务器。然而,请记住,每次连接回收都会在现代操作系统上留下一个处于TIME_WAIT状态的出站端口,该端口在大约一分钟内无法重复使用,因此,必须注意不要使用过低的值以防止源端口快速耗尽。通常情况下,请确保每秒关闭次数不要超过几次,并且最好远低于此频率。允许的值是-1(默认值,禁用此限制)或任何正值。与HTTP上下文不同,当与sink服务器一起使用时,“max-reuse”是尽力而为的:ring消息是分批处理的,因此在每批之间检查限制。
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”设置,以重置从“default-server”指令继承的任何“check-ssl”设置作为默认值。它也可以用作“default-server”设置,以重置任何先前的“default-server”“check-ssl”设置。
可用于以下场景: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”设置,以重置从“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 仅当内置了OpenSSL支持时,此设置才可用。当SSL用于与服务器通信时,此选项禁用对SSLv3的支持。请注意,SSLv2在代码中已被禁用,无法通过任何配置选项启用。请改用“ssl-min-ver”和“ssl-max-ver”。在default-server中支持:否
可用于以下场景:tcp, http, log, peers, ring 仅当内置了OpenSSL支持时,此设置才可用。它禁用无状态会话恢复(RFC 5077 TLS票证扩展),并强制使用有状态会话恢复。无状态会话恢复对服务器的CPU使用率更高。此选项也可用于全局语句“ssl-default-server-options”。TLS票证机制仅用于TLS 1.2及更早版本。除非定期轮换票证密钥(通过重新加载或使用“tls-ticket-keys”),否则前向保密性会受到TLS票证的影响。另请参阅“tls-tickets”。
可用于以下场景:tcp, http, log, peers, ring 仅当内置了OpenSSL支持时,此设置才可用。当SSL用于与服务器通信时,此选项禁用对TLSv1.0的支持。请注意,SSLv2在代码中已被禁用,无法通过任何配置选项启用。TLSv1比SSLv3更耗费资源,因此在与本地服务器通信时禁用它通常是有意义的。此选项也可用于全局语句“ssl-default-server-options”。请改用“ssl-min-ver”和“ssl-max-ver”。在default-server中支持:否
可用于以下场景:tcp, http, log, peers, ring 仅当内置了OpenSSL支持时,此设置才可用。当SSL用于与服务器通信时,此选项禁用对TLSv1.1的支持。请注意,SSLv2在代码中已被禁用,无法通过任何配置选项启用。TLSv1比SSLv3更耗费资源,因此在与本地服务器通信时禁用它通常是有意义的。此选项也可用于全局语句“ssl-default-server-options”。请改用“ssl-min-ver”和“ssl-max-ver”。在default-server中支持:否
可用于以下场景:tcp, http, log, peers, ring 仅当内置了OpenSSL支持时,此设置才可用。当SSL用于与服务器通信时,此选项禁用对TLSv1.2的支持。请注意,SSLv2在代码中已被禁用,无法通过任何配置选项启用。TLSv1比SSLv3更耗费资源,因此在与本地服务器通信时禁用它通常是有意义的。此选项也可用于全局语句“ssl-default-server-options”。请改用“ssl-min-ver”和“ssl-max-ver”。在default-server中支持:否
可用于以下场景:tcp, http, log, peers, ring 仅当内置了OpenSSL支持时,此设置才可用。当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)、多路复用器名称及其标志。一些协议在服务器端可能存在队头阻塞(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 此选项的目的是绕过为与此服务器建立的所有连接选择最佳多路复用器协议。另请参阅“ws”以使用websocket流的替代协议。
redir <prefix>
可用于以下场景:http “redir”参数为此服务器的所有GET和HEAD请求启用重定向模式。这意味着HAProxy不会将请求转发到服务器,而是发送一个“HTTP 302”响应,其中“Location”头由此前缀构成,紧接着是请求的URI,从路径组件的开头“/”开始。这意味着在<prefix>之后不应使用尾部斜杠。所有无效请求都将被拒绝,所有非GET或HEAD请求将由服务器正常处理。请注意,由于响应是完全伪造的,因此无法在响应中进行头信息篡改或cookie插入。但是,请求中的cookie仍然会被分析,这使得该解决方案在本地发生灾难时完全可用,可以将用户引导到远程位置。主要用途是通过让客户端直接连接到静态服务器来增加其带宽。注意:此处切勿使用相对位置,这会导致客户端和HAProxy之间的循环!
示例
server srv1 192.168.1.1:80 redir http://image1.mydomain.com check
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”监听器接受的连接,将使用 advertised 地址。仅支持TCPv4和TCPv6地址族。其他地址族,如Unix套接字,将报告UNKNONW家族。使用此选项的服务器可以完全链式连接到另一个HAProxy实例,该实例使用“accept-proxy”设置进行监听。如果服务器不了解该协议,则不得使用此设置。当健康检查发送到服务器时,如果设置了此选项,则会自动使用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也用于Keep-Alive连接中的第一个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信息扩展以及客户端证书主题中的通用名称(如果有)会添加到PROXY协议头中。如果服务器不了解此版本的协议,则不得使用此设置。另请参阅本节的“no-send-proxy-v2-ssl-cn”选项和“bind”关键字的“send-proxy-v2”选项。
shard <shard>
可用于以下场景:peers 此参数仅在stick-tables与peers协议同步的上下文中使⽤。 “shard”参数标识将接收所有具有此 shard 作为分发哈希的键的stick-table更新的对等体。允许的值为0到“shards”参数值(在“peers”部分指定)。 0值是默认值,表示对等体将接收所有键更新。大于“shards”的值将被忽略。对本地对等体提供的任何值也是如此。
示例
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:服务器接受的连接数将从通常由(minconn, maxconn, fullconn)定义的动态限制的1%增长到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中绝不能使用此选项,而应使用req.hdr(host),因为HTTPS中的SNI必须始终与Host字段匹配,并且客户端允许在同一连接上使用不同的主机名。如果设置了“verify required”(这是推荐设置),则结果名称也将与服务器证书的名称进行匹配。有关更多详细信息,请参阅“verify”指令。如果要为健康检查设置SNI,请参阅“check-sni”指令以获取更多详细信息。默认情况下,SNI分配给“http-reuse”的连接名称,除非被“pool-conn-name”服务器关键字覆盖。
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 形同虚设。当使用此选项时,除非有“port”或“addr”指令指示检查应发送到不同的位置,否则健康检查也会自动以 SSL 形式发送。请参阅“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-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,则必须在两个代理上都启用它。
示例
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 票据机制仅在 TLS 1.2 及更早版本中使用。除非票据密钥定期轮换(通过重新加载或使用“tls-ticket-keys”),否则前向保密性会受到 TLS 票据的损害。它也可用作“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降级为仅用于WebSocket流的“http/1.1”。“h1”值用于通过ALPN强制WebSocket流使用HTTP/1.1,如果SSL ALPN对服务器启用。类似地,“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”时,应始终从“init-addr”中排除“libc”。

5.3.2. resolvers 部分

本节专门介绍 HAProxy 中与名称解析相关的主机信息。可以根据需要有任意数量的解析器部分。每个部分可以包含许多名称服务器。在启动时,如果配置文件中没有命名为“default”的解析器部分,HAProxy 会尝试生成一个名为“default”的解析器部分。此部分由 httpclient 默认使用,并使用 parse-resolv-conf 关键字。如果 HAProxy 无法自动生成此部分,则不会发出错误或警告。当解析器部分中配置了多个名称服务器时,HAProxy 会使用第一个有效响应。在无效响应的情况下,只处理最后一个。目的是让慢速服务器有机会在快速故障或过时的服务器之后提供有效答案。当每个服务器返回不同的错误类型时,HAProxy 只使用最后一个错误。对该错误应用以下处理:1. HAProxy 使用新的查询类型重试相同的 DNS 查询。A 查询切换到 AAAA 或反之。SRV 查询不在此处。超时错误也被排除。2. 当查询类型回退完成(或不适用)时,HAProxy 使用首选查询类型重试原始 DNS 查询。3. HAProxy 重试前述步骤  次。如果在此之后未收到有效响应,则停止 DNS 解析并报告错误。例如,在解析器部分中配置了 2 个名称服务器时,可能出现以下场景:- 第一个响应有效并直接应用,第二个响应被忽略- 第一个响应无效,第二个响应有效,然后应用第二个响应- 第一个响应是 NX 域,第二个响应是截断响应,然后 HAProxy 使用新类型重试查询- 第一个响应是 NX 域,第二个响应是超时,然后 HAProxy 使用新类型重试查询- 两个名称服务器的查询都超时,然后 HAProxy 使用相同的查询类型重试它由于 DNS 服务器可能无法在一次 DNS 请求中回答所有 IP,HAProxy 会保留以前答案的缓存,如果 IP 在  秒内未返回,则答案将被视为过时。
resolvers <resolvers id>
创建一个新的名为 <resolvers id> 的域名服务器列表。resolvers 部分接受以下参数:
定义 HAProxy 接受并向此 resolvers 部分中配置的所有域名服务器通告的最大有效负载大小。<nb> 以字节为单位。如果未设置,HAProxy 通告 512。(RFC 6891 定义的最小值)注意:允许的最大值为 65535。UDP 的推荐值为 4096,不建议超过 8192,除非您确定您的系统和网络可以处理此大小(超过 65507 没有意义,因为这是 UDP 的最大有效负载大小)。如果您只使用 TCP 域名服务器来处理巨大的 DNS 响应,您应该将此值设置为最大值:65535。
nameserver <名称> <地址>[:端口] [参数*]
用于配置一个域名服务器。域名服务器的名称应该唯一。默认情况下,
被认为是数据报类型。这意味着如果配置了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 响应  后,确定服务器的状态是否应从 UP 变为 DOWN。为了做出此决定,它会检查在过去  内是否收到了任何有效状态,以抵消刚刚收到的无效状态。 : 最近的名称解析状态。nx 在收到 NXDOMAIN 状态后,检查在结束周期内是否有任何有效状态。refused 在收到 REFUSED 状态后,检查在结束周期内是否有任何有效状态。timeout 在“超时重试”发生后,检查在结束周期内是否有任何有效状态。other 在收到任何其他无效状态后,检查在结束周期内是否有任何有效状态。valid 仅适用于“http-request do-resolve”和“tcp-request content do-resolve”操作。它定义了服务器在触发另一次解析之前保持有效响应的期限。它不影响服务器的动态解析。obsolete 定义在收到更新的答案记录后,等待多久才删除过时的 DNS 记录。它适用于 SRV 记录。 : 在过去接收到有效响应的时间量。它遵循 HAProxy 时间格式,默认以毫秒为单位。对于依赖动态 DNS 解析来确定其 IP 地址的服务器,收到无效 DNS 响应(例如 NXDOMAIN)将导致服务器状态从 UP 变为 DOWN。hold 指令定义了要追溯到多远的时间来查找有效响应。如果在  内收到了有效响应,则刚刚收到的无效状态将被忽略。除非在结束周期内收到了有效响应,否则服务器将被标记为 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 客户端标头中进行变化 - 如果请求不是 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 变形可以描述相同样本获取方法的替代匹配方法。样本获取方法是唯一支持转换的方法。样本获取方法返回的数据可以是以下类型:- 布尔值- 整数(有符号或无符号)- IPv4 或 IPv6 地址- 字符串- 数据块转换器将任何这些数据转换为任何这些数据。例如,一些转换器可能将字符串转换为小写字符串,而另一些则将字符串转换为 IPv4 地址,或将子网掩码应用于 IP 地址。结果样本的类型是应用于列表的最后一个转换器的类型,默认为样本获取方法的类型。每个样本或转换器返回特定类型的数据,在本文档中通过其关键字指定。当使用标准样本获取方法声明 ACL 时,某些类型会自动涉及默认匹配方法,总结在下表中:+---------------------+-----------------+ | 样本或转换器 | 默认 | | 输出类型 | 匹配方法 | +---------------------+-----------------+ | 布尔值 | bool | +---------------------+-----------------+ | 整数 | int | +---------------------+-----------------+ | ip | ip | +---------------------+-----------------+ | 字符串 | str | +---------------------+-----------------+ | 二进制 | none,使用“-m” | +---------------------+-----------------+请注意,为了匹配二进制样本,必须指定匹配方法,见下文。ACL 引擎可以将这些类型与以下类型的模式进行匹配:- 布尔值- 整数或整数范围- IP 地址/网络- 字符串(精确、子字符串、后缀、前缀、子目录、域)- 正则表达式- 十六进制块目前支持以下 ACL 标志:-i : 在匹配所有后续模式时忽略大小写。-f : 从列表中加载模式。-m : 使用特定的模式匹配方法。-n : 禁止 DNS 解析。-M : 像映射一样加载 -f 指向的文件。-u : 强制 ACL 的唯一 ID。-- : 强制标志结束。当字符串看起来像其中一个标志时很有用。“-f”标志后面是必须遵循 2.7 中描述的映射和 ACL 名称格式的名称。甚至可以传递多个“-f”参数,如果模式要从多个列表中加载。如果引用现有文件,则所有行都将作为单个值读取。空行以及以井号('#')开头的行将被忽略。所有前导空格和制表符都将被删除。如果绝对有必要插入以井号开头的有效模式,只需在其前面添加一个空格,使其不被视为注释。根据数据类型和匹配方法,HAProxy 可能会将行加载到二叉树中,从而实现非常快速的查找。这对于 IPv4 和精确字符串匹配是正确的。在这种情况下,重复项将自动删除。“-M”标志允许 ACL 使用映射。如果设置此标志,则列表被解析为两列条目。第一列包含 ACL 使用的模式,第二列包含样本。样本稍后可由映射使用。这在某些罕见情况下可能很有用,即 ACL 仅用于在应用映射之前检查映射中模式的存在。“-u”标志强制 ACL 的唯一 ID。此唯一 ID 与套接字接口一起使用,以识别 ACL 并动态更改其值。请注意,即使设置了 ID,文件也始终由其名称标识。此外,请注意,“-i”标志适用于后续条目,而不适用于其之前的从文件加载的条目。例如:acl valid-ua hdr(user-agent) -f exact-ua.lst -i -f generic-ua.lst test在此示例中,“exact-ua.lst”的每一行都将与请求的“user-agent”标头进行精确匹配。然后,“generic-ua”的每一行都将进行不区分大小写的匹配。然后,“test”一词也将进行不区分大小写的匹配。“-m”标志用于在输入样本上选择特定的模式匹配方法。所有 ACL 特定条件都暗示一种模式匹配方法,通常不需要此标志。但是,此标志对于通用样本获取方法很有用,用于描述它们将如何与模式进行匹配。这对于返回没有明显匹配方法的数据类型(例如字符串或二进制)的样本获取是必需的。当指定“-m”并后跟模式匹配方法名称时,此方法将代替条件的默认方法。这使得可以以最初未计划的方式或使用返回字符串的样本获取方法匹配内容。匹配方法还会影响模式的解析方式。“-n”标志禁止 DNS 解析。它与 IP 文件的加载一起使用。默认情况下,如果解析器无法解析 IP 地址,它会认为解析的字符串可能是域名并尝试 DNS 解析。标志“-n”禁用此解析。它对于检测格式错误的 IP 列表很有用。请注意,如果 DNS 服务器无法访问,HAProxy 配置解析可能需要等待超时数分钟。在此期间不显示错误消息。标志“-n”禁用此行为。另请注意,在运行时,此功能对于动态 ACL 修改是禁用的。但是,存在一些限制。并非所有方法都可以与所有样本获取方法一起使用。此外,如果“-m”与“-f”结合使用,则必须先放置“-m”。模式匹配方法必须是以下之一:- “found”:只检查是否在流中找到了请求的样本,但不与任何模式进行比较。建议不要传递任何模式以避免混淆。此匹配方法特别有用,用于检测某些内容(例如标头、cookie 等)是否存在,即使它们为空,也不与任何内容进行比较或计数。- “bool”:将值视为布尔值进行检查。它只能应用于返回布尔值或整数值的获取,并且不带模式。值零或 false 不匹配,所有其他值都匹配。- “int”:将值作为整数进行匹配。它可以与整数和布尔样本一起使用。布尔 false 是整数 0,true 是整数 1。- “ip”:将值作为 IPv4 或 IPv6 地址进行匹配。它仅与 IP 地址样本兼容,因此它是隐含的,从不需要。- “bin”:将内容与表示二进制序列的十六进制字符串进行匹配。这可以与二进制或字符串样本一起使用。- “len”:将样本的长度作为整数进行匹配。这可以与二进制或字符串样本一起使用。- “str”:精确匹配:将内容与字符串进行匹配。这可以与二进制或字符串样本一起使用。- “sub”:子字符串匹配:检查内容是否包含至少一个提供的字符串模式。这可以与二进制或字符串样本一起使用。- “reg”:正则表达式匹配:将内容与正则表达式列表进行匹配。这可以与二进制或字符串样本一起使用。- “beg”:前缀匹配:检查内容是否与提供的字符串模式开头匹配。这可以与二进制或字符串样本一起使用。- “end”:后缀匹配:检查内容是否与提供的字符串模式结尾匹配。这可以与二进制或字符串样本一起使用。- “dir”:子目录匹配:检查内容中由斜杠(“/”)分隔的部分是否精确匹配提供的字符串模式之一。这可以与二进制或字符串样本一起使用。- “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”不匹配。使用它来匹配域后缀进行过滤或路由通常不是一个好主意,因为路由很容易通过在另一个域前面添加匹配前缀来欺骗。例如,要快速检测 HTTP 请求中是否存在 cookie“JSESSIONID”,可以使用:acl jsess_present req.cook(JSESSIONID) -m found为了对缓冲区中前 500 字节的数据应用正则表达式,可以使用以下 ACL:acl script_tag req.payload(0,500) -m reg -i <script>在正则表达式库在使用“-i”时慢得多的系统上,可以在匹配之前将样本转换为小写,如下所示:acl script_tag req.payload(0,500),lower -m reg <script>所有 ACL 特定条件都暗示一个默认匹配方法。通常,这些条件是通过连接原始样本获取方法的名称和匹配方法组成的。例如,“hdr_beg”将“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”的情况下默认工作时,名称会用尖括号“>”和“<”括起来。+-------------------------------------------------+ | 输入样本类型 | +----------------------+---------+---------+---------+---------+---------+ | 模式类型 | 布尔值 | 整数 | ip | 字符串 | 二进制 | +----------------------+---------+---------+---------+---------+---------+ | 无 (仅存在) | found | found | found | found | found | +----------------------+---------+---------+---------+---------+---------+ | 无 (布尔值) |> bool <| bool | | bool | | +----------------------+---------+---------+---------+---------+---------+ | 整数 (值) | int |> int <| int | int | | +----------------------+---------+---------+---------+---------+---------+ | 整数 (长度) | len | len | len | len | len | +----------------------+---------+---------+---------+---------+---------+ | IP 地址 | | |> ip <| ip | ip | +----------------------+---------+---------+---------+---------+---------+ | 精确字符串 | str | str | str |> str <| str | +----------------------+---------+---------+---------+---------+---------+ | 前缀 | beg | beg | beg | beg | beg | +----------------------+---------+---------+---------+---------+---------+ | 后缀 | end | end | end | end | end | +----------------------+---------+---------+---------+---------+---------+ | 子字符串 | sub | sub | sub | sub | sub | +----------------------+---------+---------+---------+---------+---------+ | 子目录 | dir | dir | dir | dir | dir | +----------------------+---------+---------+---------+---------+---------+ | 域 | dom | dom | dom | dom | dom | +----------------------+---------+---------+---------+---------+---------+ | 正则表达式 | reg | reg | reg | reg | reg | +----------------------+---------+---------+---------+---------+---------+ | 十六进制块 | | | | 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:如果测试值等于至少一个值,则为 true ge:如果测试值大于或等于至少一个值,则为 true gt:如果测试值大于至少一个值,则为 true le:如果测试值小于或等于至少一个值,则为 true lt:如果测试值小于至少一个值,则为 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”,请将其设置为第二个,或者在第一个字符串之前传递“--”标志。当然,匹配字符串“--”也适用。不要将字符串匹配用于可能包含空字节(0x00)的二进制获取,因为比较会在第一个空字节出现时停止。相反,首先使用十六进制转换器将二进制获取转换为十六进制字符串。
示例
# 如果字符串 <tag> 存在于二进制样本中,则匹配 acl tag_found req.payload(0,0),hex -m sub 3C7461673E

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

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

7.1.5. 匹配任意数据块

可以将一些提取的样本与一个可能无法安全地表示为字符串的二进制块进行匹配。为此,当匹配方法设置为二进制时,模式必须以偶数个十六进制数字的形式传递。每两个数字的序列将代表一个字节。十六进制数字可以使用大写或小写。
示例
# 在输入流中匹配 "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 地址表示法支持常规形式和省略全零八位字节的缩写形式:+------------------+------------------+------------------+ | 示例 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. # 现在对所有仅静态主机和主机“www”的静态 URL 使用后端“static”。对其他使用后端“www”。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 和获取已经融合。所有 ACL 获取方法都已作为获取方法提供,ACL 也可以使用任何样本获取方法。本节详细介绍了所有可用的样本获取方法及其输出类型。一些样本获取方法具有已弃用的别名,用于保持与现有配置的兼容性。它们被明确标记为已弃用,不应在新设置中使用。如果可用,还会指示 ACL 派生方法及其各自的匹配方法。这些都具有明确定义的默认模式匹配方法,因此无需(但允许)传递“-m”选项来指示如何使用 ACL 匹配样本。如上文样本类型与匹配兼容性矩阵所示,当在 ACL 中使用通用样本获取方法时,除非样本类型是布尔值、整数、IPv4 或 IPv6 之一,否则“-m”选项是强制性的。当相同的关键字作为 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)二进制二进制
aes_gcm_enc(bits,nonce,key,aead_tag)二进制二进制
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)字符串整数
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”值。
示例
# 此处,标头 "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 个字段连接起来,然后将当前样本转换为字符串。第一个字段  是一个常量字符串,如果现有样本不为空且  都不为空,它将立即附加到现有样本之后。第二个字段  是一个变量名。将查找该变量,将其内容转换为字符串,并立即附加到  部分之后。如果未找到变量,则不附加任何内容。它是可选的,并且可以选择后跟一个常量字符串 ,但是如果省略 ,则  是强制性的。此转换器类似于 concat 转换器,可用于构建由其他变量序列组成的新变量,但主要区别在于它会检查添加分隔符是否合理,例如在当前样本为空时则不合理。这种情况需要使用 concat 转换器进行两个单独的规则,其中第一个规则必须在添加分隔符之前检查当前样本字符串是否为空。如果逗号或右括号需要作为分隔符,则必须用引号或反斜杠保护它们,它们本身也需要保护,以免被第一级解析器删除(请参阅第 2.2 节了解引号和转义)。请参阅以下示例。
示例
http-request set-var(req.tagged) 'var(req.tagged),add_item(",",req.score1,"(site1)") if src,in_table(site1)' http-request set-var(req.tagged) 'var(req.tagged),add_item(",",req.score2,"(site2)") if src,in_table(site2)' http-request set-var(req.tagged) 'var(req.tagged),add_item(",",req.score3,"(site3)") if src,in_table(site3)' http-request set-header x-tagged %[var(req.tagged)] http-request set-var(req.tagged) 'var(req.tagged),add_item(",",req.score1),add_item(",",req.score2)' http-request set-var(req.tagged) 'var(req.tagged),add_item(",",,(site1))' if src,in_table(site1)
aes_gcm_dec(<bits>,<nonce>,<key>,<aead_tag>)
根据 <bits> 参数,使用 AES128-GCM、AES192-GCM 或 AES256-GCM 算法解密原始字节输入。所有其他参数都需要进行 base64 编码,返回的结果是原始字节格式。如果 <aead_tag> 验证失败,转换器不会返回任何数据。<nonce>、<key> 和 <aead_tag> 可以是字符串或变量。此转换器至少需要 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>)
根据 <bits> 参数,使用 AES128-GCM、AES192-GCM 或 AES256-GCM 算法加密原始字节输入。<nonce> 和 <key> 参数必须是 base64 编码的。最后一个参数 <aead_tag> 必须是一个变量。AEAD 标签将以 base64 编码存储到该变量中。返回的结果是原始字节格式。<nonce> 和 <key> 可以是字符串或变量。此转换器至少需要 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 个字段连接到当前样本之后,然后将当前样本转换为字符串。第一个字段  是一个常量字符串,它将紧接着现有样本之后附加。如果未使用,可以省略。第二个字段  是一个变量名。将查找该变量,将其内容转换为字符串,并立即附加到  部分之后。如果未找到变量,则不附加任何内容。它也可以省略。第三个字段  是一个常量字符串,它将附加在变量之后。它也可以省略。这些元素共同允许将带分隔符的变量连接到现有变量集。这可以用于构建由其他变量序列组成的新变量,例如冒号分隔的值。如果逗号或右括号需要作为分隔符,则必须用引号或反斜杠保护它们,它们本身也需要保护,以免被第一级解析器删除。这通常用于从其他变量构建复合变量,但有时使用包含多个字段的格式字符串可能更方便。请参阅以下示例。
示例
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 表示提取所有剩余字段。
示例
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 输出字符串。转换器尝试根据  参数解码输入字符串。它可以是“ascii”、“utf8”、“utf8s”、“utf8p”或“utf8ps”。“ascii”解码器永不失败。“utf8”解码器检测 3 种类型的错误:- 错误的 UTF-8 序列(孤立的延续字节、错误的延续字节数等)- 无效范围(解码值在 UTF-8 禁止范围内)- 编码过长(值使用比必要更多的字节编码)。当 UTF-8 字符大于 0xffff 时,UTF-8 JSON 编码可能会产生“值过长”错误,因为 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 类型字符串、布尔值、数字和数组。浮点数将以字符串形式返回。通过指定 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 键的提取是未定义的,可能会返回输入内容中相同键的第一个、最后一个或任何其他出现,如果键名以编码形式传递,它们可能并不总是匹配。简而言之,此转换器不适用于内容清理。
示例
# 从请求体中获取一个整数值 # "{"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>)
通过使用  算法和  参数,对输入中的 JSON Web 令牌 (JWT) 执行签名验证。 参数应包含密钥或公钥的路径。公钥应为 PKCS#1 格式(用于 RSA 密钥,以 BEGIN RSA PUBLIC KEY 开头)或 SPKI 格式(Subject Public Key Info,以 BEGIN PUBLIC KEY 开头)。验证成功返回 1,验证失败返回 0,任何其他错误返回严格负值。由于所有这些非空错误返回值,此转换器的结果不应转换为布尔值。有关可能的返回值的完整列表,请参阅下文。目前,只能处理使用紧凑序列化格式(三个用点分隔的 base64-url 编码字符串)的 JWS 令牌。RFC7518 的第 3.1 节中提到的所有算法都受管理(HS、ES、RS 和 PS,具有 256、384 或 512 密钥大小,以及特殊的“none”情况)。如果使用的算法属于 HMAC 系列,则  应为 HMAC 签名计算中使用的密钥。否则, 应为可用于验证令牌签名的公钥路径。所有可能用于验证 JWT 的公钥都必须在初始化期间已知,以便添加到专用缓存中,从而在运行时无需磁盘访问。因此,任何使用的公钥必须在 jwt_verify 调用中至少明确提及一次。因此不建议将中间变量作为第二个参数传递。此转换器仅验证令牌的签名,不执行 RFC7519 第 7.2 节中指定的完整 JWT 验证。例如,我们不确保标头和负载内容在解码后是完全有效的 JSON,也不对其各自的内容进行检查。可能的返回值如下:+----+----------------------------------------------------------------------+ | ID | 消息 | +----+----------------------------------------------------------------------+ | 0 | “验证失败” | | 1 | “验证成功” | | -1 | “未知算法(未在 RFC7518 中提及)” | | -2 | “不受管理的算法” | | -3 | “无效令牌” | | -4 | “内存不足” | | -5 | “未知证书” | +----+----------------------------------------------------------------------+请注意,此转换器仅在 HAProxy 使用 USE_OPENSSL 编译时可用。
示例
# 从 authorization 标头中获取 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 }
language(<value>[,<default>])
从 "accept-language" 标头中使用 "req.fhdr" 提取的列表中返回具有最高 q-factor 的值。没有 q-factor 的值其 q-factor 为 1。q-factor 为 0 的值被丢弃。只有属于分号分隔的 <values> 列表中的值才会被考虑。<value> 参数的语法是 "lang[;lang[;lang[;...]]]"。如果没有值与给定列表匹配,并且提供了默认值,则返回默认值。请注意,语言名称在破折号('-')后可能有变体。如果此变体存在于列表中,它将被匹配,但如果不存在,则只检查基础语言。匹配是区分大小写的,输出字符串始终是参数中提供的字符串之一。参数的顺序没有意义,只有请求中值的顺序有意义,因为在共享相同 q-factor 的多个值中,第一个值被使用。
示例
# 此配置根据请求切换到匹配 # 给定语言的后端: 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 转换器。
示例
# 输出两列,一列是本地时间,另一列是 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 中关于映射和 ACL 名称格式的描述。重要的是要避免键之间的重叠:IP 地址和字符串存储在树中,因此将使用最精细匹配的第一个。其他键存储在列表中,因此将使用第一个匹配的出现。以下数组包含所有可用映射函数的列表,按输入类型、匹配类型和输出类型排序。
输入类型匹配方法输出类型 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”(一系列非空格/制表符字符),值是这一系列空格/制表符之后直到行尾的内容,不包括尾随的空格/制表符。
示例
# 这是一条注释,会被忽略 2.22.246.0/23 United Kingdom \n <-><-----------><--><------------><----> | | | | `- 尾随空格被忽略 | | | `---------- 值 | | `-------------------- 中间空格被忽略 | `----------------------------  `------------------------------------ 前导空格被忽略
mod(<value>)
将有符号整数类型的输入值除以 <value>,并返回余数作为有符号整数。如果 <value> 为 null,则返回零。<value> 可以是数值或变量名。有关变量的详细信息,请参见 第 2.8 节
mqtt_field_value(<packettype>,<fieldname_or_property_ID>)
返回在类型为  的输入 MQTT 负载中找到的  的值。 可以是字符串(不区分大小写匹配)或对应于我们应该从中提取数据的包类型的数值。支持的字符串和整数可以在这里找到: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  取决于 ,可以是以下任何一个(请注意  匹配不区分大小写)。 只能在 MQTT v5.0 流中找到。请查阅此表:https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901029 - CONNECT (或 1):flags, protocol_name, protocol_version, client_identifier, will_topic, will_payload, username, password, keepalive 或者任何属性 ID 作为数值(仅适用于 MQTT v5.0 包):17: 会话过期间隔 33: 接收最大值 39: 最大包大小 34: 主题别名最大值 25: 请求响应信息 23: 请求问题信息 21: 认证方法 22: 认证数据 18: 遗嘱延迟间隔 1: 负载格式指示器 2: 消息过期间隔 3: 内容类型 8: 响应主题 9: 关联数据 尚不支持:38: 用户属性 - CONNACK (或 2):flags, protocol_version, reason_code 或者任何属性 ID 作为数值(仅适用于 MQTT v5.0 包):17: 会话过期间隔 33: 接收最大值 36: 最大 QoS 37: 保留可用 39: 最大包大小 18: 分配的客户端标识符 34: 主题别名最大值 31: 原因字符串 40; 通配符订阅可用 41: 订阅标识符可用 42: 共享订阅可用 19: 服务器心跳间隔 26: 响应信息 28: 服务器引用 21: 认证方法 22: 认证数据 尚不支持:38: 用户属性 由于 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”转换器。
示例
# 输出 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”转换器。
示例
# 输出 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>])
这会从输入字符串中提取参数  的第一次出现,其中参数由  分隔(默认为“&”),参数的名称和值由“=”分隔。如果没有“=”并且在参数段结束前没有值,则将其视为等同于空字符串的值。这对于从查询字符串或可能是 x-www-form-urlencoded 正文中提取参数很有用。特别是,`query,param()` 可以用作 `urlp()` 的替代品,后者只使用“&”作为分隔符,而“urlp”还使用“?”和“;”。请注意,此转换器不会对 URL 编码字符做任何特殊处理。如果要解码值,可以在输出上使用 url_dec 转换器。如果输入中参数的名称可能包含编码字符,您可能需要在调用“param”之前对输入进行规范化。这可以通过使用“http-request normalize-uri”来完成,特别是 percent-decode-unreserved 和 percent-to-uppercase 选项。
示例
str(a=b&c=d&a=r),param(a) # b str(a&b=c),param(a) # "" str(a=&b&c=a),param(b) # "" str(a=1;b=2;c=4),param(b,;) # 2 query,param(redirect_uri),urldec()
将包含 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>])
这以原始模式从协议缓冲区消息的输入二进制样本表示中提取协议缓冲区消息字段,如果不存在 ,则  作为字段号(点表示法),或者如果此字段存在,则作为整数样本(另请参阅下面的“ungrpc”)。授权类型列表如下:“int32”、“int64”、“uint32”、“uint64”、“sint32”、“sint64”、“bool”、“enum”用于“varint”线型 0,“fixed64”、“sfixed64”、“double”用于 64 位线型 1,“fixed32”、“sfixed32”、“float”用于线型 5。请注意,“string”被视为长度分隔类型,因此不需要任何  参数来提取。有关协议缓冲区消息字段类型的更多信息,请参见此处: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 时才可用。
示例
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 转换器。
示例
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”用于“varint”线型0,“fixed64”、“sfixed64”、“double”用于64位线型1,“fixed32”、“sfixed32”、“float”用于线型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) # “lo”第一个PPoint的“latitude” req.body,ungrpc(48.59.2,int32) # “lo”第一个PPoint的“longitude” req.body,ungrpc(49.59.1,int32) # “hi”第二个PPoint的“latitude” req.body,ungrpc(49.59.2,int32) # “hi”第二个PPoint的“longitude” 我们还可以将中间的48.59字段提取为二进制样本,如下所示:req.body,ungrpc(48.59) 由于gRPC消息总是由gRPC头和协议缓冲区消息组成,在前面的示例中,“lo”第一个PPoint的“latitude”可以通过以下等效指令提取:req.body,ungrpc(48.59),protobuf(1,int32) req.body,ungrpc(48),protobuf(59.1,int32) req.body,ungrpc(48),protobuf(59),protobuf(1,int32) 请注意,第一个转换器必须是“ungrpc”,其余的必须是“protobuf”,并且只有最后一个可以有或没有第二个参数来解释先前的二进制样本。
unset-var(<var>)
如果输入内容已定义,则取消设置变量。变量的名称以其作用域的指示开头。有关变量的详细信息,请参阅第 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"转换器。
示例
# 输出 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"转换器。
示例
# 输出 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”。
示例
# 输出两个部分,一个包含 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"在处理请求或流期间遇到错误时返回真。它使用与"dontlog-normal"相同的规则(例如,成功的重新分发计为错误)。 - "forwarded"在请求被转发到后端服务器时返回真 - "normal"在没有发生错误时返回真(这等同于"!error")。 - "processed"在请求被转发到后端服务器或由applet处理时返回真。 - "stopping"如果进程在评估规则时当前正在停止,则返回真 - "toapplet"在请求由applet处理时返回真。 - "acl"在下一个参数指定的ACL评估为真时返回真。请注意,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 表示提取所有剩余的单词。
示例
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 指令将此元素添加到日志中也很有用。
示例
# 如果字典请求过于频繁,则重定向到错误页面 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,则返回值是一个整数,反映自纪元以来的秒数、毫秒数或微秒数,再加上偏移量。当需要不到一秒的时间分辨率时,这很有用。
示例
# 在每个响应中设置一个到期头,时间为现在+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”指令。
示例
# 此前端将传入邮件限制为 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传输协议支持并且此协议未被“no-quic”全局选项禁用时,返回true。另请参见“no-quic”全局选项。
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 一起使用,但在日志中也可能有意义。这用于在昂贵或脆弱的服务器达到过高的会话速率时切换到备用后端,或限制服务滥用(例如防止潜在请求使服务器过载)。
示例
# 重定向到单独的后端 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-table元素。要从粘性计数器中检索值,计数器编号可以显式设置为0、1或2,使用预定义的“sc0_”、“sc1_”或“sc2_”前缀。这三个预定义前缀仅当全局“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字符串
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
这返回从客户端上传到服务器的字节数。该值对应于HAProxy收到的内容,包括一些头部和一些内部编码开销。请求压缩不影响此处报告的值。
bytes_out : integer
这是从服务器传输到客户端的字节数。该值对应于HAProxy收到的内容,包括一些头部和一些内部编码开销。响应压缩不影响此处报告的值。
返回流当前应用的客户端超时(以毫秒为单位)。在默认情况下,这将等于 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 | 名称 | 消息 | +----+------------------+-------------------------------------------------------------------------+ | 0 | - | "成功" | | 1 | CONF_FDLIM | "已达到配置的最大连接数" | | 2 | PROC_FDLIM | "进程上的套接字过多" | | 3 | SYS_FDLIM | "系统上的套接字过多" | | 4 | SYS_MEMLIM | "系统缓冲区不足" | | 5 | NOPROTO | "协议或地址族不支持" | | 6 | SOCK_ERR | "一般套接字错误" | | 7 | PORT_RANGE | "源端口范围已耗尽" | | 8 | CANT_BIND | "无法绑定到源地址" | | 9 | FREE_PORTS | "系统上本地源端口不足" | | 10 | ADDR_INUSE | "本地源地址已在使用" | | 11 | PRX_EMPTY | "等待PROXY协议头时连接关闭" | | 12 | PRX_ABORT | "等待PROXY协议头时连接错误" | | 13 | PRX_TIMEOUT | "等待PROXY协议头超时" | | 14 | PRX_TRUNCATED | "收到截断的PROXY协议头" | | 15 | PRX_NOT_HDR | "收到不像是PROXY协议头的内容" | | 16 | PRX_BAD_HDR | "收到无效的PROXY协议头" | | 17 | PRX_BAD_PROTO | "PROXY协议头中收到未处理的协议" | | 18 | CIP_EMPTY | "等待NetScaler客户端IP头时连接关闭" | | 19 | CIP_ABORT | "等待NetScaler客户端IP头时连接错误" | | 20 | CIP_TIMEOUT | "等待NetScaler客户端IP头超时" | | 21 | CIP_TRUNCATED | "收到截断的NetScaler客户端IP头" | | 22 | CIP_BAD_MAGIC | "收到无效的NetScaler客户端IP魔术数字" | | 23 | CIP_BAD_PROTO | "NetScaler客户端IP头中收到未处理的协议" | | 24 | SSL_EMPTY | "SSL握手期间连接关闭" | | 25 | SSL_ABORT | "SSL握手期间连接错误" | | 26 | SSL_TIMEOUT | "SSL握手期间超时" | | 27 | SSL_TOO_MANY | "SSL连接过多" | | 28 | SSL_NO_MEM | "初始化SSL连接时内存不足" | | 29 | SSL_RENEG | "拒绝客户端发起的SSL重新协商尝试" | | 30 | SSL_CA_FAIL | "SSL客户端CA链无法验证" | | 31 | SSL_CRT_FAIL | "SSL客户端证书不受信任" | | 32 | SSL_MISMATCH | "服务器提供的SSL证书与配置的不同" | | 33 | SSL_MISMATCH_SNI | "服务器提供的SSL证书与预期的不同" | | 34 | SSL_HANDSHAKE | "SSL握手失败" | | 35 | SSL_HANDSHAKE_HB | "心跳后SSL握手失败" | | 36 | SSL_KILLED_HB | "阻止了TLSv1心跳攻击 (CVE-2014-0160)" | | 37 | SSL_NO_TARGET | "尝试在未知目标上使用SSL(内部错误)" | | 38 | SSL_EARLY_FAILED | "服务器拒绝早期数据" | | 39 | SOCKS4_SEND | "SOCKS4代理握手期间写入错误" | | 40 | SOCKS4_RECV | "SOCKS4代理握手期间读取错误" | | 41 | SOCKS4_DENY | "SOCKS4代理拒绝请求" | | 42 | SOCKS4_ABORT | "SOCKS4代理握手被服务器中止" | | 43 | SSL_FATAL | "SSL致命错误" | | 44 | REVERSE | "反向连接失败" | | 45 | POLLERR | "Poller报告POLLERR" | | 46 | EREFUSED | "操作系统返回ECONNREFUSED" | | 47 | ERESET | "操作系统返回ECONNRESET" | | 48 | EUNREACH | "操作系统返回ENETUNREACH" | | 49 | ENOMEM | "操作系统返回ENOMEM" | | 50 | EBADF | "操作系统返回EBADF" | | 51 | EFAULT | "操作系统返回EFAULT" | | 52 | EINVAL | "操作系统返回EINVAL" | | 53 | ENCONN | "操作系统返回ENCONN" | | 54 | ENSOCK | "操作系统返回ENSOCK" | | 55 | ENOBUFS | "操作系统返回ENOBUFS" | | 56 | EPIPE | "操作系统返回EPIPE" | +----+------------------+-------------------------------------------------------------------------+
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
返回当前前端名称的字符串。它可以在后端用于检查它是由哪个前端调用的,或者将来自同一前端的所有用户粘性到同一服务器。
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”绑定指令,则除了“tcp-request connection”规则集(它看到真实地址)之外,它可能是PRO​​XY协议兼容组件后面的客户端地址。当传入连接通过涉及连接跟踪的地址转换或重定向时,将报告重定向前的原始目标地址。在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*" 操作。
示例
# 此前端限制每个源地址的传入 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”。
示例
# 此处将头部 "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
此函数旨在供开发人员在某些复杂的故障排除会话中使用。它从后端流和连接的下层提取一些内部状态,并将其整理成字符串,通常以一系列“名称=值”的形式用空格分隔。<bitmap>可选参数指示从哪个层提取信息,它是以下值的算术或运算(或总和): - 套接字层: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
此函数旨在供开发人员在某些复杂的故障排除会话中使用。它从前端流和连接的下层提取一些内部状态,并将其整理成字符串,通常以一系列“名称=值”的形式用空格分隔。<bitmap>可选参数指示从哪个层提取信息,它是以下值的算术或运算(或总和): - 套接字层: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传输层建立并已在本地解密时返回真。这意味着它匹配了一个使用带有“ssl”选项的“bind”行声明的套接字。
示例
# 当客户端通过 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本地解密的传入连接中提取服务器名称指示(SNI)TLS扩展字段。结果(如果存在)通常是与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连接转发到服务器时,SNI字段必须使用“req.hdr(host)”从HTTP Host头部字段设置,而不是从前端SNI值设置。原因是SNI仅用于选择服务器端将呈现的证书,并且客户端可以发送具有不同Host值的请求,只要它们与证书中的名称匹配。因此,除非后端工作在TCP模式下,“ssl_fc_sni”通常不应用于“sni”服务器关键字的参数。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 的协议文档。
示例
# 等待预处理文件上传最多 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>]):十六进制二进制匹配
示例
请参考 "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>]):精确字符串匹配
示例
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消息中发送的Application-Layer Protocol Negotiation (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”选项时使用。
示例
# 等待客户端 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 证书,并对所有其他客户端在同一 IP 地址上使用 RSA。请注意,这仅适用于请求缓冲区中的原始内容,而不适用于通过 SSL 数据层解密的内容,因此这不适用于带有“ssl”选项的“bind”行。
req_ssl_hello_type : integer (已弃用)
如果请求缓冲区包含可解析为完整 SSL(v3或更高版本)客户端Hello消息的数据,则返回一个整数值,其中包含请求缓冲区中找到的SSL Hello消息的类型。请注意,这仅适用于请求缓冲区中的原始内容,而不适用于通过SSL数据层解密的内容,因此这不适用于带有“ssl”选项的“bind”行。这主要用于ACL中,以检测假定包含可用于粘性的SSL会话ID的SSL Hello消息的存在。
返回客户端在 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”选项时使用。
示例
# 等待客户端 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 扩展的值。请注意,这仅适用于请求缓冲区中的原始内容,而不适用于通过 SSL 数据层解密的内容,因此这不适用于带有“ssl”选项的“bind”行。这仅适用于实际隐式基于 TLS 的协议,如 HTTPS (443)、IMAPS (993)、SMTPS (465),但它不适用于显式基于 TLS 的协议,如 SMTP (25/587) 或 IMAP (143)。SNI 通常包含客户端尝试连接的主机名(对于最新浏览器)。SNI 对于在使用 SSL/TLS 时允许或拒绝访问某些主机很有用。此测试旨在与 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 进行粘性处理或不进行粘性处理,因为在使用 SessionTicket 时没有服务器端状态。
返回客户端在TLS ClientHello中报告的支持的受支持组列表的二进制形式,用于密钥交换,可包括椭圆曲线和非EC密钥交换。请注意,这仅适用于请求缓冲区中的原始内容,而不适用于通过SSL数据层解密的内容,因此这不适用于带有“ssl”选项的“bind”行。请参阅“ssl_fc_eclist_bin”,它是SSL绑定等效项,可在指定“ssl”选项时使用。
示例
# 等待客户端 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 规则。
示例
请参考 "stick store-response" 关键字中的示例。
rep_ssl_hello_type : integer (已弃用)
如果响应缓冲区包含可解析为完整 SSL(v3 或更高版本)hello 消息的数据,则返回一个整数值,其中包含响应缓冲区中找到的 SSL hello 消息的类型。请注意,这仅适用于响应缓冲区中的原始内容,而不适用于通过 SSL 数据层解密的内容,因此这不适用于带有“ssl”选项的“server”行。这主要用于 ACL 中,以检测假定包含可用于粘性的 SSL hello 消息的存在。

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

可以从HTTP内容、请求和响应中获取样本。此应用层也称为第7层。只有当从其各自的请求或响应缓冲区解析出完整的HTTP请求或响应时,才能在此部分中获取数据。对于所有HTTP特定规则以及以“mode http”运行的部分,情况总是如此。使用TCP内容检查时,可能需要支持检查延迟,以首先让请求或响应进入。这些获取可能比第4层的获取需要更多的CPU资源,但不多,因为请求和响应已索引。注意:关于TCP请求内容规则的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 滥用以及提高共享缓存效率很有用。将其与有限大小的粘滞表一起使用,还可以收集有关按主机/路径最常请求对象的数据。通过 ACL,它可以实现涉及主机和路径的简单内容切换规则,例如 "www.example.com/favicon.ico"。另请参阅 "path" 和 "uri"。ACL 派生词:base:精确字符串匹配 base_beg:前缀匹配 base_dir:子目录匹配 base_dom:域名匹配 base_end:后缀匹配 base_len:长度匹配 base_reg:正则表达式匹配 base_sub:子串匹配
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:不区分大小写的方法匹配
示例
# 只接受 GET 和 HEAD 请求 acl valid_method method GET HEAD http-request deny if ! valid_method
path : string
这提取请求的URL路径,该路径从第一个斜杠开始,到问号之前结束(不包括主机部分)。典型的用途是与支持预取的缓存和需要聚合多个数据库信息并将其保存在缓存中的门户网站。请注意,对于出站缓存,使用“url”而不是此方法会更明智。对于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:子字符串匹配
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>]):子字符串匹配
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>]]):子字符串匹配
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>]]):子字符串匹配
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:子字符串匹配
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
这提取查询字符串中参数 <name> 的第一次出现,该参数在 '?' 或 <delim> 之后开始,在 '&'、';' 或 <delim> 之前结束。参数名称区分大小写,除非将“i”作为第三个参数添加。如果没有给出名称,任何参数都将匹配,并且返回第一个参数。结果是对应于请求中呈现的参数 <name> 的值的字符串(未执行 URL 解码)。这可用于基于客户端 ID 的会话粘性,以提取作为 URL 参数传递的应用程序 cookie,或在 ACL 中应用某些检查。请注意,此获取的 ACL 版本会迭代多个参数,如果未给出名称,则会迭代报告所有参数值。ACL 派生:urlp(<name>[,<delim>]):精确字符串匹配 urlp_beg(<name>[,<delim>]):前缀匹配 urlp_dir(<name>[,<delim>]):子目录匹配 urlp_dom(<name>[,<delim>]):域名匹配 urlp_end(<name>[,<delim>]):后缀匹配 urlp_len(<name>[,<delim>]):长度匹配 urlp_reg(<name>[,<delim>]):正则表达式匹配 urlp_sub(<name>[,<delim>]):子字符串匹配
示例
# 匹配 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 的强大之处之一无疑在于其精确的日志。它可能提供了此类产品可用的最精细的信息级别,这对于复杂环境的故障排除非常重要。日志中提供的标准信息包括客户端端口、TCP/HTTP 状态计时器、终止时的精确流状态和精确终止原因、关于将流量导向服务器的决策信息,当然还有捕获任意头部信息的能力。为了提高管理员的响应能力,它提供了对内部和外部问题的极大透明度,并且可以同时将不同级别的日志发送到不同的源,并带有不同的级别过滤器: - 全局进程级日志(系统错误、启动/停止等) - 每个实例的系统和内部错误(资源不足、错误等) - 每个实例的外部问题(服务器启动/停止、最大连接数) - 每个实例的活动(客户端连接),无论是在建立时还是在终止时。 - 每个请求的日志级别控制,例如 http-request set-log-level silent if sensitive_request 能够将不同级别的日志分发到不同的日志服务器,允许多个生产团队进行交互,并尽快解决他们的问题。例如,系统团队可能会监控全系统错误,而应用程序团队可能会实时监控其服务器的启动/停止,安全团队可能会延迟一小时分析活动日志。

8.1. 日志级别

TCP 和 HTTP 连接可以记录日期、时间、源 IP 地址、目标地址、连接持续时间、响应时间、HTTP 请求、HTTP 返回码、传输字节数、流结束条件,甚至交换的 cookie 值等信息。例如,跟踪特定用户的问题。所有消息最多可以发送到两个 syslog 服务器。有关日志设施的更多信息,请查看第4.2节中的“log”关键字。

8.2. 日志格式

HAProxy 支持 5 种日志格式。这些格式之间有几个通用字段将在以下章节中详细说明。其中一些可能会因特定选项的指示器而略有不同。支持的格式如下: - 默认格式,非常基本,很少使用。它仅在连接被接受时提供传入连接的最基本信息:源 IP:port、目标 IP:port 和前端名称。此模式最终将消失,因此不会对其进行详细描述。 - TCP 格式,更高级。当在前端设置 "option tcplog" 时,此格式启用。HAProxy 通常会等待连接终止后才记录日志。此格式提供更丰富的信息,例如计时器、连接计数、队列大小等... 此格式推荐用于纯 TCP 代理。 - HTTP 格式,这是 HTTP 代理中最先进的格式。当在前端设置 "option httplog" 时,此格式启用。它提供与 TCP 格式相同的信息,并包含一些 HTTP 特定字段,例如请求、状态码以及头部和 cookie 的捕获。此格式推荐用于 HTTP 代理。 - CLF HTTP 格式,等同于 HTTP 格式,但字段以与 CLF 格式相同的顺序排列。在此模式下,所有计时器、捕获、标志等... 在通用字段结束后,按它们在标准 HTTP 格式中出现的相同顺序,每个字段显示一个。 - 自定义日志格式,允许您创建自己的日志行。接下来的章节将深入探讨这些格式中的每一个。格式规范将以“field”为基础进行。除非另有说明,否则字段是由任意数量的空格分隔的文本部分。由于 syslog 服务器可能会在行首插入字段,因此始终假定第一个字段是包含进程名称和标识符的字段。注意:由于日志行可能很长,以下章节中的日志示例可能会分成多行。示例日志行将以 3 个右尖括号('>>>')作为前缀,并且每次日志分成多行时,每个非最终行将以反斜杠('\')结尾,下一行将以两个字符的缩进开始。

8.2.1. 默认日志格式

当没有设置特定选项时,使用此格式。日志在连接被接受后立即发出。需要注意的是,这目前是唯一记录请求目标 IP 和端口的格式。
示例
listen www mode http log global server srv1 127.0.0.1:8000 >>> Feb 6 12:12:09 localhost \ haproxy[14385]: Connect from 10.0.1.2:33312 to 10.0.3.31:8012 \ (www/HTTP)
字段格式 提取自上例 1 process_name '[' pid ']:' haproxy[14385]: 2 'Connect from' Connect from 3 source_ip ':' source_port 10.0.1.2:33312 4 'to' to 5 destination_ip ':' destination_port 10.0.3.31:8012 6 '(' frontend_name '/' mode ')' (www/HTTP) 详细字段描述: - "source_ip" 是发起连接的客户端的 IP 地址。 - "source_port" 是发起连接的客户端的 TCP 端口。 - "destination_ip" 是客户端连接到的 IP 地址。 - "destination_port" 是客户端连接到的 TCP 端口。 - "frontend_name" 是接收和处理连接的前端(或监听器)的名称。 - "mode" 是前端操作的模式(TCP 或 HTTP)。 在 UNIX 套接字的情况下,源地址和目标地址标记为 "unix:",端口反映接受连接的套接字的内部 ID(与统计信息中报告的 ID 相同)。 建议新安装不要使用此已弃用的格式,因为它最终将消失。

8.2.2. TCP 日志格式

当前端中指定“option tcplog”时使用TCP格式,这是纯TCP代理推荐的格式。它为故障排除提供了大量宝贵信息。由于此格式包含计时器和字节计数,日志通常在会话结束时发出。如果指定了“option logasap”,它可以在更早的时候发出,这在大多数具有长会话(如远程终端)的环境中是有意义的。匹配“monitor”规则的会话永远不会被记录。通过在前端指定“option dontlognull”,也可以不记录客户端和服务器之间没有交换数据的会话。如果前端中指定了“option dontlog-normal”,成功的连接将不会被记录。TCP日志格式在内部被声明为基于以下精确字符串的自定义日志格式,该字符串也可以作为扩展格式的基础(如果需要)。此外,可以使用HAPROXY_TCP_LOG_FMT变量代替。请参阅第8.2.6节“自定义日志格式”以了解如何使用: # 严格等同于“option tcplog” log-format "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts \ %ac/%fc/%bc/%sc/%rc %sq/%bq" # 或使用HAPROXY_TCP_LOG_FMT变量 log-format "${HAPROXY_TCP_LOG_FMT}" 并且CLF日志格式在内部被声明为基于此精确字符串的自定义日志格式: # 严格等同于“option tcplog clf” log-format "%{Q}o %{-Q}ci - - [%T] \"TCP \" 000 %B \"\" \"\" %cp \ %ms %ft %b %s %Th %Tw %Tc %Tt %U %ts-- %ac %fc %bc \ %sc %rc %sq %bq \"\" \"\" " 少数字段可能会根据某些配置选项略有不同,这些字段在字段名称后用星号('*')标记。
示例
frontend fnt mode tcp option tcplog log global default_backend bck backend bck server srv1 127.0.0.1:8000 >>> Feb 6 12:12:56 localhost \ haproxy[14387]: 10.0.1.2:33313 [06/Feb/2009:12:12:51.443] fnt \ bck/srv1 0/0/5007 212 -- 0/0/0/0/3 0/0
字段格式 摘自以上示例 1 process_name '[' pid ']:' haproxy[14387]: 2 client_ip ':' client_port 10.0.1.2:33313 3 '[' accept_date ']' [06/Feb/2009:12:12:51.443] 4 frontend_name fnt 5 backend_name '/' server_name bck/srv1 6 Tw '/' Tc '/' Tt* 0/0/5007 7 bytes_read* 212 8 termination_state -- 9 actconn '/' feconn '/' beconn '/' srv_conn '/' retries* 0/0/0/0/3 10 srv_queue '/' backend_queue 0/0 详细字段说明: - "client_ip" 是发起 TCP 连接到 HAProxy 的客户端的 IP 地址。如果连接是在 UNIX 套接字上接受的,IP 地址将替换为单词 "unix"。请注意,当连接是在配置了 "accept-proxy" 的套接字上接受并且 PROXY 协议正确使用时,或者是在配置了 "accept-netscaler-cip" 并且 NetScaler 客户端 IP 插入协议正确使用时,日志将反映转发连接的信息。 - "client_port" 是发起连接的客户端的 TCP 端口。如果连接是在 UNIX 套接字上接受的,端口将替换为接受套接字的 ID,该 ID 也报告在统计接口中。 - "accept_date" 是 HAProxy 收到连接的确切日期(如果系统积压中存在一些排队,这可能与网络上观察到的日期略有不同)。这通常是可能出现在任何上游防火墙日志中的相同日期。在 HTTP 模式下使用时,accept_date 字段将重置为连接准备好接收新请求的第一个时刻(HTTP/1 的前一个响应结束,HTTP/2 的前一个请求之后立即)。 - "frontend_name" 是接收和处理连接的前端(或监听器)的名称。 - "backend_name" 是为管理到服务器的连接而选择的后端(或监听器)的名称。如果没有应用切换规则,这将与前端相同,这对于 TCP 应用程序很常见。 - "server_name" 是连接发送到的最后一个服务器的名称,如果存在连接错误并发生重新调度,则可能与第一个服务器不同。请注意,此服务器属于处理请求的后端。如果连接在到达服务器之前中止,则显示 "<NOSRV>" 而不是服务器名称。 - "Tw" 是在各种队列中等待的总时间(以毫秒为单位)。如果连接在到达队列之前中止,则可能为 "-1"。有关更多详细信息,请参阅下面的“计时器”。 - "Tc" 是等待与最终服务器建立连接的总时间(以毫秒为单位),包括重试。如果连接在建立连接之前中止,则可能为 "-1"。有关更多详细信息,请参阅下面的“计时器”。 - "Tt" 是从接受到最后关闭之间经过的总时间(以毫秒为单位)。它涵盖所有可能的处理。有一个例外,如果指定了 "option logasap",则时间计数在日志发出时停止。在这种情况下,值前会加上一个 '+' 号,表示最终值会更大。有关更多详细信息,请参阅下面的“计时器”。 - "bytes_read" 是日志发出时从服务器传输到客户端的总字节数。如果指定了 "option logasap",则此值将带有 '+' 号前缀,表示最终值可能更大。请注意,此值为 64 位计数器,因此日志分析工具必须能够处理它而不会溢出。 - "termination_state" 是会话结束时会话所处的状态。这表示会话状态、哪一方导致会话结束以及原因(超时、错误等)。正常标志应为 "--",表示会话由任一端关闭,缓冲区中没有剩余数据。有关更多详细信息,请参阅下面的“断开连接时的流状态”。 - "actconn" 是记录会话时进程上的并发连接总数。它有助于检测何时达到某些进程系统限制。例如,如果发生多个连接错误时 actconn 接近 512,则系统很可能将进程限制为最多使用 1024 个文件描述符,并且所有这些都已使用。请参阅 第 3 节“全局参数”以了解如何调整系统。 - "feconn" 是记录会话时前端上的并发连接总数。它有助于估计维持高负载所需的资源量,并检测何时达到前端的 "maxconn"。通常当此值大幅增加时,是因为后端服务器出现拥塞,但有时也可能是由拒绝服务攻击引起的。 - "beconn" 是记录会话时后端处理的并发连接总数。它包括服务器上活动的并发连接总数以及队列中挂起的连接数。它有助于估计给定应用程序支持高负载所需的额外服务器数量。通常当此值大幅增加时,是因为后端服务器出现拥塞,但有时也可能是由拒绝服务攻击引起的。 - "srv_conn" 是记录会话时服务器上仍处于活动状态的并发连接总数。它永远不能超过服务器配置的 "maxconn" 参数。如果此值经常接近或等于服务器的 "maxconn",则表示大量涉及流量调节,这意味着服务器的 maxconn 值太低,或者没有足够的服务器以最佳响应时间处理负载。当只有一个服务器的 "srv_conn" 值很高时,通常意味着此服务器存在一些问题,导致连接处理时间比其他服务器长。 - "retries" 是此会话尝试连接到服务器时经历的连接重试次数。通常应为零,除非在尝试连接的同一时刻服务器正在停止。频繁的重试通常表示 HAProxy 和服务器之间的网络问题,或者服务器上配置错误的系统积压导致新连接无法排队。此字段可以选择带有 '+' 号前缀,表示会话在初始服务器上达到最大重试次数后已重新调度。在这种情况下,日志中出现的服务器名称是连接重新调度到的服务器,而不是第一个服务器,尽管在哈希的情况下两者有时可能相同。因此,作为一般经验法则,当重试次数前面存在 '+' 时,此计数不应归因于记录的服务器。 - "srv_queue" 是在服务器队列中此请求之前处理的请求总数。如果请求未经过服务器队列,则为零。它可以通过将队列中花费的时间除以队列中的请求数来估算近似的服务器响应时间。值得注意的是,如果一个会话经历重新调度并经过两个服务器队列,它们的头寸将是累积的。除非发生重新调度,否则请求不应同时经过服务器队列和后端队列。 - "backend_queue" 是在后端全局队列中此请求之前处理的请求总数。如果请求未经过全局队列,则为零。它可以通过将平均队列长度除以服务器的 "maxconn" 参数来估算平均队列长度,这很容易转换为缺少服务器的数量。值得注意的是,如果一个会话经历重新调度,它可能会两次经过后端队列,然后两个头寸将是累积的。除非发生重新调度,否则请求不应同时经过服务器队列和后端队列。

8.2.3. HTTP 日志格式

HTTP 格式是最完整、最适合 HTTP 代理的格式。当在前端中指定 "option httplog" 时启用。它提供了与 TCP 格式相同的信息级别,并具有 HTTP 协议特有的附加功能。就像 TCP 格式一样,日志通常在流结束时发出,除非指定了 "option logasap",这通常只对下载站点有意义。匹配 "monitor" 规则的流永远不会被记录。通过在前端指定 "option dontlognull" 也可以不记录客户端未发送数据的流。如果前端中指定了 "option dontlog-normal",则不会记录成功的连接。HTTP 日志格式在内部声明为基于以下精确字符串的自定义日志格式,该字符串也可以用作根据需要扩展格式的基础。此外,还可以使用 HAPROXY_HTTP_LOG_FMT 变量。请参阅 第 8.2.6 节 “自定义日志格式”以了解如何使用: # 严格等同于 "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" # 或使用 HAPROXY_HTTP_LOG_FMT 变量 log-format "${HAPROXY_HTTP_LOG_FMT}" CLF 日志格式在内部声明为基于以下精确字符串的自定义日志格式: # 严格等同于 "option httplog clf" log-format "%{+Q}o %{-Q}ci - - [%trg] %r %ST %B \"\" \"\" %cp \ %ms %ft %b %s %TR %Tw %Tc %Tr %Ta %tsc %ac %fc \ %bc %sc %rc %sq %bq %CC %CS %hrl %hsl" 大多数字段与 TCP 日志共享,有些不同。少数字段可能因某些配置选项而略有不同。这些字段名称后面带有一个星号 ('*')。
示例
frontend http-in mode http option httplog log global default_backend bck backend static server srv1 127.0.0.1:8000 >>> Feb 6 12:14:14 localhost \ haproxy[14389]: 10.0.1.2:33317 [06/Feb/2009:12:14:14.655] http-in \ static/srv1 10/0/30/69/109 200 2750 - - ---- 1/1/1/1/0 0/0 {1wt.eu} \ {} "GET /index.html HTTP/1.1"
字段格式 摘自以上示例 1 process_name '[' pid ']:' haproxy[14389]: 2 client_ip ':' client_port 10.0.1.2:33317 3 '[' request_date ']' [06/Feb/2009:12:14:14.655] 4 frontend_name http-in 5 backend_name '/' server_name static/srv1 6 TR '/' Tw '/' Tc '/' Tr '/' Ta* 10/0/30/69/109 7 status_code 200 8 bytes_read* 2750 9 captured_request_cookie - 10 captured_response_cookie - 11 termination_state ---- 12 actconn '/' feconn '/' beconn '/' srv_conn '/' retries* 1/1/1/1/0 13 srv_queue '/' backend_queue 0/0 14 '{' captured_request_headers* '}' {haproxy.1wt.eu} 15 '{' captured_response_headers* '}' {} 16 '"' http_request '"' "GET /index.html HTTP/1.1" 详细字段说明: - "client_ip" 是发起 TCP 连接到 HAProxy 的客户端的 IP 地址。如果连接是在 UNIX 套接字上接受的,IP 地址将替换为单词 "unix"。请注意,当连接是在配置了 "accept-proxy" 的套接字上接受并且 PROXY 协议正确使用时,或者是在配置了 "accept-netscaler-cip" 并且 NetScaler 客户端 IP 插入协议正确使用时,日志将反映转发连接的信息。 - "client_port" 是发起连接的客户端的 TCP 端口。如果连接是在 UNIX 套接字上接受的,端口将替换为接受套接字的 ID,该 ID 也报告在统计接口中。 - "request_date" 是 HAProxy 收到 HTTP 请求第一个字节的确切日期(日志字段 %tr)。 - "frontend_name" 是接收和处理连接的前端(或监听器)的名称。 - "backend_name" 是为管理到服务器的连接而选择的后端(或监听器)的名称。如果未应用切换规则,这将与前端相同。 - "server_name" 是连接发送到的最后一个服务器的名称,如果存在连接错误并发生重新调度,则可能与第一个服务器不同。请注意,此服务器属于处理请求的后端。如果请求在到达服务器之前中止,则显示 "<NOSRV>" 而不是服务器名称。如果请求被统计子系统拦截,则显示 "<STATS>"。 - "TR" 是从收到第一个字节后等待客户端发送完整 HTTP 请求(不包括正文)的总时间(以毫秒为单位)。如果连接在收到完整请求之前中止或收到错误的请求,则可能为 "-1"。它应该总是非常小,因为请求通常在一个数据包中。此处时间过长通常表示客户端和 HAProxy 之间存在网络问题或手动键入请求。有关更多详细信息,请参阅 第 8.4 节 “计时事件”。 - "Tw" 是在各种队列中等待的总时间(以毫秒为单位)。如果连接在到达队列之前中止,则可能为 "-1"。有关更多详细信息,请参阅 第 8.4 节 “计时事件”。 - "Tc" 是等待与最终服务器建立连接的总时间(以毫秒为单位),包括重试。如果请求在建立连接之前中止,则可能为 "-1"。有关更多详细信息,请参阅 第 8.4 节 “计时事件”。 - "Tr" 是等待服务器发送完整 HTTP 响应(不包括数据)的总时间(以毫秒为单位)。如果请求在收到完整响应之前中止,则可能为 "-1"。它通常与服务器处理请求的时间匹配,尽管它可能会因客户端发送到服务器的数据量而改变。此处“GET”请求时间过长通常表示服务器过载。有关更多详细信息,请参阅 第 8.4 节 “计时事件”。 - "Ta" 是请求在 HAProxy 中保持活动的时间,即从收到请求的第一个字节到发送响应的最后一个字节之间经过的总时间(以毫秒为单位)。它涵盖所有可能的处理,除了握手(请参阅 Th)和空闲时间(请参阅 Ti)。有一个例外,如果指定了 "option logasap",则时间计数在日志发出时停止。在这种情况下,值前会加上一个 '+' 号,表示最终值会更大。有关更多详细信息,请参阅 第 8.4 节 “计时事件”。 - "status_code" 是返回给客户端的 HTTP 状态代码。此状态通常由服务器设置,但当无法访问服务器或其响应被 HAProxy 阻止时,也可能由 HAProxy 设置。 - "bytes_read" 是日志发出时传输到客户端的总字节数。这包括 HTTP 标头。如果指定了 "option logasap",此值将带有 '+' 号前缀,表示最终值可能更大。请注意,此值为 64 位计数器,因此日志分析工具必须能够处理它而不会溢出。 - "captured_request_cookie" 是一个可选的 "name=value" 条目,表示客户端在请求中包含此 cookie。cookie 名称及其最大长度由前端配置中的 "capture cookie" 语句定义。当未设置该选项时,该字段为单个短划线 ('-')。只能捕获一个 cookie,它通常用于跟踪客户端和服务器之间的会话 ID 交换,以检测由于应用程序错误导致的客户端之间会话交叉。有关更多详细信息,请参阅下面的“捕获 HTTP 标头和 cookie”部分。 - "captured_response_cookie" 是一个可选的 "name=value" 条目,表示服务器已通过其响应返回 cookie。cookie 名称及其最大长度由前端配置中的 "capture cookie" 语句定义。当未设置该选项时,该字段为单个短划线 ('-')。只能捕获一个 cookie,它通常用于跟踪客户端和服务器之间的会话 ID 交换,以检测由于应用程序错误导致的客户端之间会话交叉。有关更多详细信息,请参阅下面的“捕获 HTTP 标头和 cookie”部分。 - "termination_state" 是流结束时流所处的状态。这表示流状态、哪一方导致流结束以及原因(超时、错误等),就像在 TCP 日志中一样,以及最后两个字符中有关 cookie 持久化操作的信息。正常标志应以 "--" 开头,表示流由任一端关闭,缓冲区中没有剩余数据。有关更多详细信息,请参阅下面的“断开连接时的流状态”。 - "actconn" 是记录流时进程上的并发连接总数。它有助于检测何时达到某些进程系统限制。例如,如果发生多个连接错误时 actconn 接近 512 或 1024,则系统很可能将进程限制为最多使用 1024 个文件描述符,并且所有这些都已使用。请参阅 第 3 节 “全局参数”以了解如何调整系统。 - "feconn" 是记录流时前端上的并发连接总数。它有助于估计维持高负载所需的资源量,并检测何时达到前端的 "maxconn"。通常当此值大幅增加时,是因为后端服务器出现拥塞,但有时也可能是由拒绝服务攻击引起的。 - "beconn" 是记录流时后端处理的并发连接总数。它包括服务器上活动的并发连接总数以及队列中挂起的连接数。它有助于估计给定应用程序支持高负载所需的额外服务器数量。通常当此值大幅增加时,是因为后端服务器出现拥塞,但有时也可能是由拒绝服务攻击引起的。 - "srv_conn" 是记录流时服务器上仍处于活动状态的并发连接总数。它永远不能超过服务器配置的 "maxconn" 参数。如果此值经常接近或等于服务器的 "maxconn",则表示大量涉及流量调节,这意味着服务器的 maxconn 值太低,或者没有足够的服务器以最佳响应时间处理负载。当只有一个服务器的 "srv_conn" 值很高时,通常意味着此服务器存在一些问题,导致请求处理时间比其他服务器长。 - "retries" 是此流尝试连接到服务器时经历的连接重试次数。通常应为零,除非在尝试连接的同一时刻服务器正在停止。频繁的重试通常表示 HAProxy 和服务器之间的网络问题,或者服务器上配置错误的系统积压导致新连接无法排队。此字段可以选择带有 '+' 号前缀,表示流在初始服务器上达到最大重试次数后已重新调度。在这种情况下,日志中出现的服务器名称是连接重新调度到的服务器,而不是第一个服务器,尽管在哈希的情况下两者有时可能相同。因此,作为一般经验法则,当重试次数前面存在 '+' 时,此计数不应归因于记录的服务器。 - "srv_queue" 是在服务器队列中此请求之前处理的请求总数。如果请求未经过服务器队列,则为零。它可以通过将队列中花费的时间除以队列中的请求数来估算近似的服务器响应时间。值得注意的是,如果一个流经历重新调度并经过两个服务器队列,它们的头寸将是累积的。除非发生重新调度,否则请求不应同时经过服务器队列和后端队列。 - "backend_queue" 是在后端全局队列中此请求之前处理的请求总数。如果请求未经过全局队列,则为零。它可以通过将平均队列长度除以服务器的 "maxconn" 参数来估算平均队列长度,这很容易转换为缺少服务器的数量。值得注意的是,如果一个流经历重新调度,它可能会两次经过后端队列,然后两个头寸将是累积的。除非发生重新调度,否则请求不应同时经过服务器队列和后端队列。 - "captured_request_headers" 是由于前端中存在 "capture request header" 语句而在请求中捕获的标头列表。可以捕获多个标头,它们将由竖线 ('|') 分隔。如果未启用捕获,则括号不出现,导致剩余字段移位。重要的是要注意,此字段可能包含空格,并且使用它需要比不使用它更智能的日志解析器。有关更多详细信息,请参阅下面的“捕获 HTTP 标头和 cookie”部分。 - "captured_response_headers" 是由于前端中存在 "capture response header" 语句而在响应中捕获的标头列表。可以捕获多个标头,它们将由竖线 ('|') 分隔。如果未启用捕获,则括号不出现,导致剩余字段移位。重要的是要注意,此字段可能包含空格,并且使用它需要比不使用它更智能的日志解析器。有关更多详细信息,请参阅下面的“捕获 HTTP 标头和 cookie”部分。 - "http_request" 是完整的 HTTP 请求行,包括方法、请求和 HTTP 版本字符串。不可打印字符已编码(请参阅下面的“不可打印字符”部分)。这始终是最后一个字段,并且始终由引号分隔,并且是唯一可以包含引号的字段。如果将新字段添加到日志格式,它们将在此字段之前添加。如果请求太大且不适合标准 syslog 缓冲区(1024 个字符),则此字段可能会被截断。这就是此字段必须始终保持最后一个字段的原因。

8.2.4. HTTPS日志格式

HTTPS 格式最适合用于 HTTP over SSL 连接。它是 HTTP 格式的扩展(请参阅 第 8.2.3 节),其中添加了与 SSL 相关的信息。当在前端中指定 "option httpslog" 时启用。就像 TCP 和 HTTP 格式一样,日志通常在流结束时发出,除非指定了 "option logasap"。匹配 "monitor" 规则的流永远不会被记录。通过在前端指定 "option dontlognull" 也可以不记录客户端未发送数据的流。如果前端中指定了 "option dontlog-normal",则不会记录成功的连接。HTTPS 日志格式在内部声明为基于以下精确字符串的自定义日志格式,该字符串也可以用作根据需要扩展格式的基础。此外,还可以使用 HAPROXY_HTTPS_LOG_FMT 变量。请参阅 第 8.2.6 节 “自定义日志格式”以了解如何使用: # 严格等同于 "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" # 或使用 HAPROXY_HTTPS_LOG_FMT 变量 log-format "${HAPROXY_HTTPS_LOG_FMT}" 此格式基本上是 HTTP 格式(请参阅 第 8.2.3 节),并附加了新字段。新字段(第 17 行和第 18 行)将在此处详细说明。有关 HTTP 字段,请参阅 HTTP 部分。
示例
frontend https-in mode http option httpslog log global bind *:443 ssl crt mycerts/srv.pem ... default_backend bck backend static server srv1 127.0.0.1:8000 ssl crt mycerts/clt.pem ... >>> Feb 6 12:14:14 localhost \ haproxy[14389]: 10.0.1.2:33317 [06/Feb/2009:12:14:14.655] https-in \ static/srv1 10/0/30/69/109 200 2750 - - ---- 1/1/1/1/0 0/0 {1wt.eu} \ {} "GET /index.html HTTP/1.1" 0/0/0/0/0 \ 1wt.eu/TLSv1.3/TLS_AES_256_GCM_SHA384
字段格式 摘自以上示例 1 process_name '[' pid ']:' haproxy[14389]: 2 client_ip ':' client_port 10.0.1.2:33317 3 '[' request_date ']' [06/Feb/2009:12:14:14.655] 4 frontend_name https-in 5 backend_name '/' server_name static/srv1 6 TR '/' Tw '/' Tc '/' Tr '/' Ta* 10/0/30/69/109 7 status_code 200 8 bytes_read* 2750 9 captured_request_cookie - 10 captured_response_cookie - 11 termination_state ---- 12 actconn '/' feconn '/' beconn '/' srv_conn '/' retries* 1/1/1/1/0 13 srv_queue '/' backend_queue 0/0 14 '{' captured_request_headers* '}' {haproxy.1wt.eu} 15 '{' captured_response_headers* '}' {} 16 '"' http_request '"' "GET /index.html HTTP/1.1" 17 fc_err '/' ssl_fc_err '/' ssl_c_err '/' ssl_c_ca_err '/' ssl_fc_is_resumed 0/0/0/0/0 18 ssl_fc_sni '/' ssl_version '/' ssl_ciphers 1wt.eu/TLSv1.3/TLS_AES_256_GCM_SHA384 详细字段说明: - "fc_err" 是前端侧连接的状态。它对应于 "fc_err" 样本获取。有关更多信息,请参阅 "fc_err" 和 "fc_err_str" 样本获取函数。 - "ssl_fc_err" 是从前端角度来看,连接上出现的第一个 SSL 错误堆栈的最后一个错误。例如,它可以用于检测 SSL 握手错误。如果一切顺利,它将为 0。有关更多信息,请参阅 "ssl_fc_err" 样本获取的描述。 - "ssl_c_err" 是客户端证书验证过程的状态。如果忽略错误代码,即使握手成功,也可能存在非空验证错误代码。请参阅 "ssl_c_err" 样本获取和 "crt-ignore-err" 选项。 - "ssl_c_ca_err" 是客户端证书链验证过程的状态。如果忽略错误代码,即使握手成功,也可能存在非空验证错误代码。请参阅 "ssl_c_ca_err" 样本获取和 "ca-ignore-err" 选项。 - "ssl_fc_is_resumed" 如果传入的 TLS 会话已通过有状态缓存或无状态票证恢复,则为 true。请不要忘记 TLS 会话可以由多个请求共享。 - "ssl_fc_sni" 是客户端为选择要使用的证书而提供的 SNI(服务器名称指示)。它通常与连接的第一个请求的主机名匹配。此字段的缺失可能表示客户端未发送 SNI,并将导致 haproxy 使用默认证书,或者在 strict-sni 的情况下拒绝连接。 - "ssl_version" 是前端的 SSL 版本。 - "ssl_ciphers" 是用于连接的 SSL 密码。

8.2.5. 错误日志格式

当传入连接由于 SSL 握手或无效的 PROXY 协议头而失败时,HAProxy 将使用更短、固定行格式记录事件,除非通过 "error-log-format" 行定义了专门的错误日志格式。默认情况下,日志以 LOG_INFO 级别发出,除非在后端设置了选项 "log-separate-errors",在这种情况下将使用 LOG_ERR 级别。如果设置了 "dontlognull" 选项,则不记录未交换数据的连接(例如探测)。默认格式如下: >>> Dec 3 18:27:14 localhost \ haproxy[6103]: 127.0.0.1:56059 [03/Dec/2012:17:35:10.380] frt/f1: \ Connection error during SSL handshake 字段格式 摘自以上示例 1 process_name '[' pid ']:' haproxy[6103]: 2 client_ip ':' client_port 127.0.0.1:56059 3 '[' accept_date ']' [03/Dec/2012:17:35:10.380] 4 frontend_name "/" bind_name ":" frt/f1: 5 message Connection error during SSL handshake 这些字段只提供最少的信息,以帮助调试连接失败。通过使用 "error-log-format" 指令,上述旧日志格式将不再使用,所有错误日志行将遵循定义的格式。下面是一个合理完整的 error-log-format 示例,它将报告源地址和端口、连接接受日期、前端名称、进程和此前端上的活动连接数、haproxy 在前端连接上的内部错误标识符、十六进制的 OpenSSL 错误号(可以复制粘贴到 "openssl errstr" 进行完全解码)、客户端证书提取状态(0 表示无错误)、使用 CA 的客户端证书验证状态(0 表示无错误)、一个布尔值指示连接是新连接还是已恢复连接、客户端提供的可选服务器名称指示 (SNI)、SSL 版本名称和连接上使用的 SSL 密码(如果有)。请注意,此处从不报告后端连接错误,因为后端连接要失败,它必须已经通过成功的流,因此将作为常规流量日志提供(请参阅 option httplog 或 option httpslog)。 # 详细前端连接错误日志 error-log-format "%ci:%cp [%tr] %ft %ac/%fc %[fc_err]/\ %[ssl_fc_err,hex]/%[ssl_c_err]/%[ssl_c_ca_err]/%[ssl_fc_is_resumed] \ %[ssl_fc_sni]/%sslv/%sslc"

8.2.6. 自定义日志格式

历史上,自定义日志格式仅用于生成日志。但它们在通过组合多个复杂表达式来生成字符串时的便利性使得许多曾经只接受字符串作为参数的指令现在也采用了它们,并且现在也可以接受这种自定义日志格式定义。本文档中通常用 "<fmt>" 表示的此类参数与此处描述的 "log-format" 指令的参数定义方式完全相同。对于日志,当默认日志格式不足时,可以非常详细地定义新格式。由于从头开始创建日志格式并非总是简单的任务,因此强烈建议首先查看现有格式("option tcplog"、"option httplog"、"option httpslog"),选择最接近预期的格式,复制其 "log-format" 等效字符串并进行调整。从配置角度来看,自定义日志格式定义是单个参数。这意味着它可能不包含空白(空格或制表符),除非这些空白使用反斜杠字符 ('\') 转义,或者整个定义用引号括起来(这是推荐的使用方式)。不再推荐使用未加引号的格式字符串,因为历史表明它非常容易出错,因为一个丢失的反斜杠字符可能导致格式的静默截断。由于在版本 1.5-dev9 之后,引号可用前 3 年,日志格式被大量采用,因此仍然常见此类配置,但建议现在将其转换为带引号的字符串并删除反斜杠。日志格式定义由任意数量的日志格式项组成,这些项由文本和空格分隔。日志格式项以字符 '%' 开头。为了发出逐字 '%',必须在其前面加上另一个 '%',从而产生 '%%'。日志格式项可以是别名或样本表达式:如果项名在方括号 ('[' .. ']') 之间,则将其用作样本表达式规则(请参阅 第 7.3 节)。这对于添加一些不常见的信息(例如客户端的 SSL 证书的 DN)或记录将用于将条目存储到 sticky 表中的键很有用。它也常用于非日志操作(标头操作、变量等)。否则,如果项名使用字母数字名称,则它是一个别名。(请参阅下表了解可用别名列表)项可以使用大括号 ('{}') 接受参数,多个参数在大括号内用逗号分隔。可以通过在其前面加上 '+' 或 '-' 号来添加或删除标志(请参阅下文了解可用标志列表)。特殊别名 "%o" 可用于将其标志传播到同一格式字符串上的所有其他日志格式项。这对于带引号 ("Q") 和转义 ("E") 字符串格式特别方便。特殊别名 "%OG" 可用于以人类可读的格式检索日志源(日志生成的时间/位置)。这在使用 "option logasap" 时特别有用,因为某些日志变量或样本获取可能会报告不完整的值或根据日志格式表达式评估的时间/位置表现不同。可能的值有: - "sess_error":日志是在会话错误处理期间生成的 - "sess_killed":日志是在会话中止期间生成的(终止胚胎会话) - "txn_accept":日志是在前端连接被接受后立即生成的 - "txn_request":日志是在客户端请求收到后生成的 - "txn_connect":日志是在后端连接建立后生成的 - "txn_response":日志是在服务器响应处理期间生成的 - "txn_close":日志是在最终事务步骤、关闭之前生成的 - "unspec":未知或未指定 "%OG" 仅在日志上下文中相关。项可以选择使用 ('()') 命名。名称必须在 '%' 之后(参数之前)提供。当设置了 "json" 或 "cbor" 等编码标志时,它将自动用作键名。未指定编码标志(默认)时,项名将被忽略。还可以通过在名称后附加 ':type' 来强制项的输出为给定类型,例如:%(itemname:itemtype)aliasname 或 %(itemname:itemtype)[expr],其中 itemtype 可以是 'str'、'sint' 或 'bool'。指定类型仅在使用编码方法时相关。此外,支持提供空名称以强制匿名项的输出类型:%(:itemtype),即:当未全局设置编码时,请参阅下面的标志定义以获取更多信息。由于自定义日志格式的最初目标是仅用于日志记录,因此存在非打印和不安全字符(ASCII 代码 32 到 126 以外的字符以及其他一些字符)的特殊情况,具体取决于它们的使用位置。第 8.6 节描述了为日志精确完成的操作,以确保不会发送不安全代码,这些代码会改变终端中输出的可读性。当用于形成标头字段、健康检查或有效负载响应时,规则不那么严格,并且只有 HTTP 标头字段中禁止的字符才会被其十六进制编码替换,前面加上字符 '%'。这通常不是问题,但当预期字符被逐字复制时(例如,在构建错误页面或完整响应有效负载时,换行符可能显示为 "%0A"),它可能会影响输出。注意:在配置指令 "log-format"、"log-format-sd" 和 "unique-id-format" 中,空格被视为分隔符并合并。注意:当使用 RFC5424 syslog 消息格式时,PARAM-VALUE 中的字符 '"'、'\' 和 ']' 应以 '\' 作为前缀进行转义(有关更多详细信息,请参阅 https://tools.ietf.org/html/rfc5424#section-6.3.3)。在这种情况下,应考虑使用标志 "E"。支持的项标志有(可以通过项的参数启用/禁用): * Q:引用字符串 * X:十六进制表示(IP、端口、%Ts、%rt、%pid) * E:用 '\' 作为前缀转义字符串中的字符 '"'、'\' 和 ']'(预期目的是用于 RFC5424 结构化数据日志格式) * bin:尝试保留二进制数据,这对于输出二进制数据的样本表达式很有用,以保留原始数据。但是要小心,因为它显然可以生成不可打印字符,包括 NULL 字节,而大多数 syslog 端点不期望这些字符。因此,它主要用于 set-var-fmt、环和支持二进制的日志端点。此选项只能全局设置(使用 %o),如果在单个项的选项中设置,则将被忽略。 * json:自动以 JSON 格式编码值(全局设置时,只考虑命名日志格式项)。不完整的数值(例如:使用 logasap 时的 '%B'),通常在没有编码的情况下以 '+' 为前缀,将按原样编码。此外,'+E' 选项将被忽略。 * cbor:自动以 CBOR 格式编码值(全局设置时,只考虑命名日志格式项)。默认情况下,CBOR 编码数据以 HEX 形式表示,以便它仍然可以在 stdout 上打印,并可与常规 syslog 端点一起使用。与 json 编码一样,不完整的数值将按原样编码,并且 '+E' 选项将被忽略。当与 '+bin' 选项结合使用时,它将直接生成原始二进制 CBOR 有效负载。请注意,因为它显然会生成不可打印字符,因此它主要用于 set-var-fmt、环和支持二进制的日志端点。
示例
log-format %T\ %t\ Some\ Text log-format %{+Q}o\ %t\ %s\ %{-Q}r log-format-sd %{+Q,+E}o\ [exampleSDID@1234\ header=%[capture.req.hdr(0)]] log-format "%{+json}o %(request)r %(custom_expr)[str(custom)]" log-format "%{+cbor}o %(request)r %(custom_expr)[str(custom)]"
请参考下表了解当前定义的别名: +---+------+------------------------------------------------------+---------+ | R | alias| 字段名(8.2.2 和 8.2.3 描述)                       | 类型    | |   |      | 样本获取替代                                         |         | +===+======+======================================================+=========+ |   | %o   | 特殊,对所有后续项应用标志                           |         | +---+------+------------------------------------------------------+---------+ | 日期格式                                                 |         | +---+------+------------------------------------------------------+---------+ |   | %T   | 接受日期 UTC + 时区                                |         | |   |      | %[accept_date,utime("%d/%b/%Y:%H:%M:%S %z")]         | 日期    | +---+------+------------------------------------------------------+---------+ |   | %Tl  | 接受日期 本地 + 时区                               |         | |   |      | %[accept_date,ltime("%d/%b/%Y:%H:%M:%S %z")]         | 日期    | +---+------+------------------------------------------------------+---------+ |   | %Ts  | 接受日期作为 UNIX 时间戳                           | 数字    | |   |      | %[accept_date]                                       |         | +---+------+------------------------------------------------------+---------+ |   | %t   | 接受日期 本地(毫秒分辨率)                        |         | |   |      | %[accept_date(ms),ms_ltime("%d/%b/%Y:%H:%M:%S.%3N")]| 日期    | +---+------+------------------------------------------------------+---------+ |   | %ms  | 接受日期 毫秒                                      |         | |   |      | %[accept_date(ms),ms_utime("%3N")]                    | 数字    | +---+------+------------------------------------------------------+---------+ | H | %tr  | 请求日期 本地(毫秒分辨率)                        |         | |   |      | %[request_date(ms),ms_ltime("%d/%b/%Y:%H:%M:%S.%3N")]| 日期    | +---+------+------------------------------------------------------+---------+ | H | %trg | 请求日期 UTC + 时区                                |         | |   |      | %[request_date,utime("%d/%b/%Y:%H:%M:%S %z")]         | 日期    | +---+------+------------------------------------------------------+---------+ | H | %trl | 请求日期 本地 + 时区                               |         | |   |      | %[request_date,ltime("%d/%b/%Y:%H:%M:%S %z")]         | 日期    | +---+------+------------------------------------------------------+---------+ | 计时事件                                                 |         | +---+------+------------------------------------------------------+---------+ | H | %Ta  | 请求的活动时间(从 TR 到结束)                     |         | |   |      | %[txn.timer.total]                                   | 数字    | +---+------+------------------------------------------------------+---------+ |   | %Tc  | Tc                                                   |         | |   |      | %[bc.timer.connect]                                  | 数字    | +---+------+------------------------------------------------------+---------+ |   | %Td  | Td = Tt - (Tq + Tw + Tc + Tr)                        |         | |   |      | %[res.timer.data]                                    | 数字    | +---+------+------------------------------------------------------+---------+ |   | %Th  | 连接握手时间(SSL, PROXY 协议)                    |         | |   |      | %[fc.timer.handshake]                                | 数字    | +---+------+------------------------------------------------------+---------+ | H | %Ti  | HTTP 请求之前的空闲时间                            |         | |   |      | %[req.timer.idle]                                    | 数字    | +---+------+------------------------------------------------------+---------+ | H | %Tq  | Th + Ti + TR                                         |         | |   |      | %[req.timer.tq]                                      | 数字    | +---+------+------------------------------------------------------+---------+ | H | %TR  | 从第一个字节接收完整请求的时间                     |         | |   |      | %[req.timer.hdr]                                     | 数字    | +---+------+------------------------------------------------------+---------+ | H | %Tr  | Tr (响应时间)                                      |         | |   |      | %[res.timer.hdr]                                     | 数字    | +---+------+------------------------------------------------------+---------+ |   | %Tt  | Tt                                                   |         | |   |      | %[fc.timer.total]                                    | 数字    | +---+------+------------------------------------------------------+---------+ |   | %Tu  | Tu                                                   |         | |   |      | %[txn.timer.user]                                    | 数字    | +---+------+------------------------------------------------------+---------+ |   | %Tw  | Tw                                                   |         | |   |      | %[req.timer.queue]                                   | 数字    | +---+------+------------------------------------------------------+---------+ | 其他                                                     |         | +---+------+------------------------------------------------------+---------+ |   | %B   | bytes_read(从服务器到客户端)                     | 数字    | |   |      | %[bytes_out]                                         |         | +---+------+------------------------------------------------------+---------+ | H | %CC  | captured_request_cookie                              | 字符串  | +---+------+------------------------------------------------------+---------+ | H | %CS  | captured_response_cookie                             | 字符串  | +---+------+------------------------------------------------------+---------+ |   | %H   | hostname                                             | 字符串  | |   |      | %[hostname]                                          |         | +---+------+------------------------------------------------------+---------+ | H | %HM  | HTTP 方法(例如:POST)                            | 字符串  | |   |      | %[method]                                            |         | +---+------+------------------------------------------------------+---------+ | H | %HP  | HTTP 请求 URI(不带查询字符串)                    | 字符串  | +---+------+------------------------------------------------------+---------+ | H | %HPO | 仅 HTTP 路径(不带主机和查询字符串)              | 字符串  | +---+------+------------------------------------------------------+---------+ | H | %HQ  | HTTP 请求 URI 查询字符串(例如:?bar=baz)         | 字符串  | |   |      | ?%[query]                                            |         | +---+------+------------------------------------------------------+---------+ | H | %HU  | HTTP 请求 URI(例如:/foo?bar=baz)                 | 字符串  | +---+------+------------------------------------------------------+---------+ | H | %HV  | HTTP 版本(例如:HTTP/1.0)                        | 字符串  | |   |      | HTTP/%[req.ver]                                      |         | +---+------+------------------------------------------------------+---------+ |   | %ID  | unique-id                                            | 字符串  | |   |      | %[unique-id]                                         |         | +---+------+------------------------------------------------------+---------+ |   | %ST  | status_code                                          | 数字    | |   |      | %[txn.status]                                        |         | +---+------+------------------------------------------------------+---------+ |   | %U   | bytes_uploaded(从客户端到服务器)                 | 数字    | |   |      | %[bytes_in]                                          |         | +---+------+------------------------------------------------------+---------+ |   | %ac  | actconn                                              |         | |   |      | %[act_conn]                                          | 数字    | +---+------+------------------------------------------------------+---------+ |   | %b   | backend_name                                         |         | |   |      | %[be_name]                                           | 字符串  | +---+------+------------------------------------------------------+---------+ |   | %bc  | beconn(后端并发连接数)                           | 数字    | |   |      | %[be_conn]                                           |         | +---+------+------------------------------------------------------+---------+ |   | %bi  | backend_source_ip(连接地址)                      |         | |   |      | %[bc_src]                                            | IP      | +---+------+------------------------------------------------------+---------+ |   | %bp  | backend_source_port(连接地址)                    |         | |   |      | %[bc_src_port]                                       | 数字    | +---+------+------------------------------------------------------+---------+ |   | %bq  | backend_queue                                        | 数字    | |   |      | %[bc_be_queue]                                       |         | +---+------+------------------------------------------------------+---------+ |   | %ci  | client_ip(接受地址)                              |         | |   |      | %[src]                                               | IP      | +---+------+------------------------------------------------------+---------+ |   | %cp  | client_port(接受地址)                            |         | |   |      | %[src_port]                                          | 数字    | +---+------+------------------------------------------------------+---------+ |   | %f   | frontend_name                                        | 字符串  | |   |      | %[fe_name]                                           |         | +---+------+------------------------------------------------------+---------+ |   | %fc  | feconn(前端并发连接数)                           | 数字    | |   |      | %[fe_conn]                                           |         | +---+------+------------------------------------------------------+---------+ |   | %fi  | frontend_ip(接受地址)                            |         | |   |      | %[dst]                                               | IP      | +---+------+------------------------------------------------------+---------+ +---+------+------------------------------------------------------+---------+ |   | %fp  | frontend_port(接受地址)                          |         | |   |      | %[dst_port]                                          | 数字    | +---+------+------------------------------------------------------+---------+ |   | %ft  | frontend_name_transport(SSL 为 '~' 后缀)           | 字符串  | +---+------+------------------------------------------------------+---------+ |   | %lc  | frontend_log_counter                                 | 数字    | +---+------+------------------------------------------------------+---------+ |   | %hr  | captured_request_headers 默认样式                    | 字符串  | +---+------+------------------------------------------------------+---------+ |   | %hrl | captured_request_headers CLF 样式                    | 字符串  | |   |      |                                                      | 列表    | +---+------+------------------------------------------------------+---------+ |   | %hs  | captured_response_headers 默认样式                   | 字符串  | +---+------+------------------------------------------------------+---------+ |   | %hsl | captured_response_headers CLF 样式                   | 字符串  | |   |      |                                                      | 列表    | +---+------+------------------------------------------------------+---------+ | L | %OG  | 人类可读的日志来源                                 | 字符串  | +---+------+------------------------------------------------------+---------+ |   | %pid | PID                                                  |         | |   |      | %[pid]                                               | 数字    | +---+------+------------------------------------------------------+---------+ | H | %r   | http_request                                         | 字符串  | +---+------+------------------------------------------------------+---------+ |   | %rc  | retries                                              | 数字    | |   |      | %[txn.redispatched,iif(+,)]%[txn.conn_retries]      |         | +---+------+------------------------------------------------------+---------+ |   | %rt  | request_counter(HTTP 请求或 TCP 会话)              | 数字    | |   |      | %[txn.id32]                                          |         | +---+------+------------------------------------------------------+---------+ |   | %s   | server_name                                          | 字符串  | |   |      | %[srv_name]                                          |         | +---+------+------------------------------------------------------+---------+ |   | %sc  | srv_conn(服务器并发连接数)                       | 数字    | +---+------+------------------------------------------------------+---------+ |   | %si  | server_IP(目标地址)                              |         | |   |      | %[bc_dst]                                            | IP      | +---+------+------------------------------------------------------+---------+ |   | %sp  | server_port(目标地址)                            |         | |   |      | %[bc_dst_port]                                       | 数字    | +---+------+------------------------------------------------------+---------+ |   | %sq  | srv_queue                                            | 数字    | |   |      | %[bc_srv_queue]                                      |         | +---+------+------------------------------------------------------+---------+ | S | %sslc| ssl_ciphers(例如:AES-SHA)                       |         | |   |      | %[ssl_fc_cipher]                                     | 字符串  | +---+------+------------------------------------------------------+---------+ | S | %sslv| ssl_version(例如:TLSv1)                         |         | |   |      | %[ssl_fc_protocol]                                   | 字符串  | +---+------+------------------------------------------------------+---------+ |   | %ts  | termination_state                                    | 字符串  | |   |      | %[txn.sess_term_state]                               |         | +---+------+------------------------------------------------------+---------+ | H | %tsc | termination_state with cookie status                 | 字符串  | +---+------+------------------------------------------------------+---------+ R = 限制: H = 仅限 HTTP 模式;S = 仅限 SSL;L = 仅限日志

8.3. 高级日志记录选项

一些高级日志记录选项经常被寻找,但仅通过查看各种选项不容易找到。这里是几个可以实现更好日志记录的选项的入口点。有关其用法的更多信息,请参考关键字参考。

8.3.1. 禁用外部测试的日志记录

拥有一些监控工具对 HAProxy 执行健康检查是很常见的。有时它是一个第 3 层负载均衡器,例如 LVS 或任何商业负载均衡器,有时它只是一个更完整的监控系统,例如 Nagios。当测试非常频繁时,用户经常会询问如何禁用这些检查的日志记录。有三种可能性: - 如果连接来自各地并且只是 TCP 探测,通常希望通过在前端设置 "option dontlognull" 来简单地禁用没有数据交换的连接的日志记录。它还禁用了端口扫描的日志记录,这可能是或可能不是所期望的。 - 可以使用 "http-request set-log-level silent" 操作,使用各种条件(源网络、路径、用户代理等)。 - 如果在已知 URI 上执行测试,请使用 "monitor-uri" 将此 URI 声明为专门用于监控。任何发送此请求的主机都只会获得健康检查的结果,并且请求不会被记录。

8.3.2. 在等待流终止之前进行日志记录

在连接结束时进行日志记录的问题在于,您无法了解在非常长的流(例如远程终端会话或大文件下载)期间发生了什么。通过在前端指定“option logasap”可以解决此问题。HAProxy 将尽快记录,就在数据传输开始之前。这意味着在 TCP 的情况下,它仍将记录到服务器的连接状态,在 HTTP 的情况下,它将在处理服务器头信息后进行记录。在这种情况下,报告的字节数是发送到客户端的头字节数。为了避免与正常日志混淆,总时间字段和字节数前面会加上“+”号,表示实际数字肯定更大。

8.3.3. 发生错误时提高日志级别

有时,将正常流量与错误日志分开会更方便,例如,为了简化从日志文件中监控错误。当使用 "log-separate-errors" 选项时,遇到错误、超时、重试、重新分派或 HTTP 状态码为 5xx 的连接,其 syslog 级别将从 "info" 提高到 "err"。这将帮助 syslog 守护进程将日志存储在一个单独的文件中。将错误也保留在正常流量文件中非常重要,这样日志顺序就不会改变。如果您已经配置了 syslog 守护进程将所有高于 "notice" 的日志存储在 "admin" 文件中,您也应该小心,因为 "err" 级别高于 "notice"。

8.3.4. 禁用成功连接的日志记录

虽然这乍听起来可能很奇怪,但一些大型站点必须处理每秒数千条日志,并且在长时间保持其完整性或在其中检测错误方面遇到困难。如果在前端设置了 "dontlog-normal" 选项,所有正常的连接都不会被记录。在这方面,正常连接定义为没有任何错误、超时、重试或重新分派的连接。在 HTTP 中,状态码也会被检查,状态为 5xx 的响应不被认为是正常的,也会被记录。当然,这样做是强烈不鼓励的,因为它会从日志中删除大部分有用的信息。只有在没有其他选择的情况下才这样做。

8.3.5. 日志配置文件

虽然某些指令,如 "log-format"、"log-format-sd"、"error-log-format" 或 "log-tag",允许全局或在代理级别配置日志格式,但在日志端点(即每个 "log" 指令)尽可能接近地配置此类设置可能更相关。这就是 "log-profile" 部分发挥作用的地方:"log-profile" 可以在配置中的任何位置定义。此部分接受一组不同的关键字,用于描述如何构建为给定 `log` 指令发出的日志。从 "log" 指令,可以选择使用特定名称的日志配置文件。相同的配置文件可以从多个 "log" 指令中使用。
创建一个新的日志配置文件,标识为 <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-format" 指令有意义的上下文中使用的 "log" 指令(例如:http 和 tcp 代理)。否则它将被忽略。
示例
log-profile myprof log-tag "custom-tag" on error format "%ci: error" on connect drop on any sd "custom-sd" listen myproxy mode http option httplog log-tag "normal" log stdout format rfc5424 local0 # 成功: # <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" # # 错误: # <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 # 成功: # <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" # # 错误: # <134>1 2024-06-12T10:09:51.566524+02:00 - custom-tag 224482 - - 127.0.0.1: error

8.4. 计时事件

计时器在解决网络问题时提供了极大的帮助。所有值都以毫秒 (ms) 为单位报告。这些计时器应与流终止标志结合使用。在 TCP 模式下,如果前端设置了"option tcplog",则会报告 3 个控制点,形式为 "Tw/Tc/Tt";在 HTTP 模式下,则会报告 5 个控制点,形式为 "TR/Tw/Tc/Tr/Ta"。此外,还提供了另外三个测量值,"Th"、"Ti" 和 "Tq"。HTTP 模式下的计时事件:第一个请求 第二个请求 |<-------------------------------->|<-------------- ... 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 连接并执行低级协议握手的总时间。目前,这些协议是代理协议和 SSL。这可能在整个连接生命周期中只发生一次。这里的时间过长可能表示客户端只预先建立了连接但未进行通信,或者它遇到网络问题导致无法在合理的时间内完成握手(例如 MTU 问题),或者 SSL 握手计算成本很高。请注意,此时间仅在第一个请求之前报告,因此可以将其平均到所有请求中以计算摊销值。第二个及后续请求此处始终报告零。此计时器在日志格式别名中命名为 %Th,在样本抓取中命名为 fc.timer.handshake。 - Ti:HTTP 请求之前的空闲时间(仅限 HTTP 模式)。此计时器计算从握手结束到 HTTP 请求的第一个字节之间的时间。在保持活动模式下处理第二个请求时,它在上次响应传输结束后开始计数。当使用 HTTP/2 等多路复用协议时,它在上次请求后立即开始计数。某些浏览器会预先建立与服务器的连接,以减少未来请求的延迟,并保持这些连接挂起直到需要它们。此延迟将报告为空闲时间。值为 -1 表示连接上未收到任何内容。此计时器在日志格式别名中命名为 %Ti,在样本抓取中命名为 req.timer.idle。 - TR:获取客户端请求的总时间(仅限 HTTP 模式)。它是从收到第一个字节到代理收到表示 HTTP 头部结束的空行之间经过的时间。值 "-1" 表示从未看到头部结束。这发生在客户端过早关闭或超时时。此时间通常非常短,因为大多数请求都适合单个数据包。时间过长可能表示在测试期间手动输入的请求。此计时器在日志格式别名中命名为 %TR,在样本抓取中命名为 req.timer.hdr。 - Tq:从接受日期或自上次响应的最后一个字节发出以来获取客户端请求的总时间(仅限 HTTP 模式)。它精确等于 Th + Ti + TR,除非其中任何一个为 -1,在这种情况下它也返回 -1。在 HTTP keep-alive 和浏览器预连接功能出现之前,此计时器非常有用。建议现在将其替换为 TR,因为空闲时间给报告增加了大量噪音。此计时器在日志格式别名中命名为 %Tq,在样本抓取中命名为 req.timer.tq。 - Tw:在队列中等待连接槽的总时间。它包括后端队列以及服务器队列,并取决于队列大小和服务器完成先前请求所需的时间。值 "-1" 表示请求在到达队列之前被终止,这通常发生在无效或被拒绝的请求中。此计时器在日志格式别名中命名为 %Tw,在样本抓取中命名为 req.timer.queue。 - Tc:建立与服务器的 TCP 连接的总时间。它是从代理发送连接请求到服务器确认连接之间经过的时间,或者从 TCP SYN 数据包到返回的匹配 SYN/ACK 数据包之间的时间。值 "-1" 表示连接从未建立。此计时器在日志格式别名中命名为 %Tc,在样本抓取中命名为 bc.timer.connect。 - Tr:服务器响应时间(仅限 HTTP 模式)。它是从与服务器建立 TCP 连接到服务器发送完整响应头部之间经过的时间。它纯粹显示其请求处理时间,不包括数据传输造成的网络开销。值得注意的是,当客户端有数据要发送到服务器时(例如在 POST 请求期间),时间已经开始运行,这可能会扭曲表观响应时间。因此,对于来自不受信任网络后的客户端发起的 POST 请求,通常不宜过多信任此字段。此处的值 "-1" 表示从未看到最后一个响应头部(空行),很可能是因为服务器在处理请求之前超时,或者服务器返回了无效响应。此计时器在日志格式别名中命名为 %Tr,在样本抓取中命名为 res.timer.hdr。 - Td:这是响应有效负载传输到发送给客户端的最后一个字节的总传输时间。在 HTTP 中,它在最后一个响应头部(Tr 之后)之后开始。发送的数据不保证会被客户端接收,它们可能停留在内核或网络中。此计时器在日志格式别名中命名为 %Td,在样本抓取中命名为 res.timer.data。 - Ta:HTTP 请求的总活动时间,从代理收到请求头部的第一个字节到发出响应体的最后一个字节之间。例外情况是指定了"logasap"选项。在这种情况下,它仅等于 (TR+Tw+Tc+Tr),并带有“+”号前缀。通过此字段,我们可以通过减去其他有效计时器来推导出数据传输时间 "Td":Td = Ta - (TR + Tw + Tc + Tr)。值为 "-1" 的计时器必须从此方程中排除。请注意,"Ta" 永远不能为负。此计时器在日志格式别名中命名为 %Ta,在样本抓取中命名为 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)。此计时器在日志格式别名中命名为 %Tt,在样本抓取中命名为 fc.timer.total。 - Tu:从客户端角度看,从代理接受到两端关闭之间的总估计时间,不包括空闲时间。这对于粗略测量用户所见的端到端时间非常有用,而不会受到请求之间保持活动时间的空闲时间污染。此计时器只是用户所见时间的估计,因为它假设网络延迟在两个方向上是相同的。例外情况是指定了"logasap"选项。在这种情况下,它仅等于 (Th+TR+Tw+Tc+Tr),并带有“+”号前缀。此计时器在日志格式别名中命名为 %Tu,在样本抓取中命名为 txn.timer.user。 这些计时器提供了关于故障原因的宝贵指示。由于 TCP 协议定义了 3、6、12... 秒的重传延迟,因此我们可以确定接近 3 秒倍数的计时器几乎总是与网络问题(线路、协商、拥塞)导致的数据包丢失有关。此外,如果 "Ta" 或 "Tt" 接近配置中指定的超时值,则通常意味着流已因超时而中止。 最常见的情况: - 如果 "Th" 或 "Ti" 接近 3000,则客户端与代理之间可能丢失了一个数据包。这在本地网络上非常罕见,但当客户端位于遥远的网络并发送大量请求时可能会发生。有时,在攻击期间或资源耗尽刚结束后,HAProxy 可能会在几毫秒内接受数千个连接。接受这些连接所花费的时间不可避免地会略微延迟其他连接的处理,并且可能会在一次接受数千个新连接后测量到几十毫秒的请求时间。使用其中一种保持活动模式可能会显示更长的空闲时间,因为 "Ti" 测量等待额外请求所花费的时间。 - 如果 "Tc" 接近 3000,则服务器与代理之间在服务器连接阶段可能丢失了一个数据包。此值应始终非常低,例如在本地网络上为 1 毫秒,在远程网络上小于几十毫秒。 - 如果 "Tr" 几乎总是低于 3000,除了少数几个似乎是平均值加上 3000 的罕见值,则代理与服务器之间可能丢失了一些数据包。 - 如果 "Ta" 即使对于少量字节也很长,通常是因为在 HAProxy 处于隧道模式且客户端和服务器都已同意保持活动连接模式时,客户端和服务器都没有决定关闭连接。为了解决此问题,需要指定其中一个 HTTP 选项来操作前端或后端的保持活动或关闭选项。 当服务器使用"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:代理正在等待客户端的完整、有效 REQUEST(仅限 HTTP 模式)。未向任何服务器发送任何内容。 Q:代理正在 QUEUE 中等待连接槽。这只可能发生在服务器设置了 'maxconn' 参数时。在连接到即将死亡的服务器失败后进行重新调度,也可能发生在全局队列中。如果没有报告重新调度,则未尝试连接任何服务器。 C:代理正在等待与服务器建立 CONNECTION。服务器最多可能注意到连接尝试。 H:代理正在等待服务器的完整、有效响应 HEADERS(仅限 HTTP)。 D:流处于 DATA 阶段。 L:代理仍在向客户端传输 LAST 数据,而服务器已完成。这非常罕见,因为它只可能发生在客户端在接收最后一个数据包时死亡。 T:请求被陷阱。它在整个 "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 中的最后日期。这只可能发生在带有 "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 在客户端发送完整的 HTTP 请求之前,"timeout http-request" 超时。这有时是由于客户端 PPPoE 网络上 TCP MSS 值过大导致无法传输完整数据包,或者客户端手动发送请求但输入速度不够快,或者忘记在请求末尾输入空行。这里的 HTTP 状态码可能是 408。 注意:最近,一些浏览器开始实现“预连接”功能,包括推测性地连接到一些最近访问过的网站,以防用户想访问它们。这导致许多连接建立到网站,如果超时首先发生,则以 408 Request Timeout 结束,或者当浏览器决定首先关闭它们时,以 400 Bad Request 结束。这些会污染日志并增加错误计数器。据报道,某些版本的某些浏览器甚至会显示错误代码。可以通过在前端添加 "option http-ignore-probes" 来解决这种行为的不良影响,从而使零数据传输的连接完全被忽略。但这肯定会隐藏遇到连接问题的人的错误。 CT 客户端在其流被陷阱时中止。重要的是检查这是否发生在有效请求上,以确保没有编写错误的陷阱规则。如果发生很多次,降低 "timeout tarpit" 值到更接近平均报告的 "Tw" 计时器可能是有意义的,以免仅为少数攻击者消耗资源。 LC 请求被 HAProxy 拦截并本地处理。请求未发送到服务器。这仅在由于服务器行上的 "redir" 参数而发生重定向时发生。 LR 请求被 HAProxy 拦截并本地处理。请求未发送到服务器。通常这意味着返回了重定向,处理了 HTTP return 语句,或者请求由小程序(统计、缓存、Prometheus 导出、lua 小程序...)处理。 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 设备(防火墙、负载均衡器等)上的超时设置过短,以及客户端和服务器之间维持的 keep-alive 会话在 HAProxy 上首先过期。 SH 服务器在发送完整的 HTTP 响应头之前中止,或者在处理请求时崩溃。由于服务器在此刻中止的情况非常罕见,因此最好检查其日志以控制它是否崩溃以及原因。日志记录的请求可能指示一小部分故障请求,从而证明应用程序中的错误。有时这可能也是由 IDS 终止 HAProxy 和服务器之间的连接引起的。 sH 在服务器返回其响应头之前,"timeout server" 超时。这是最常见的异常,表示事务时间过长,可能是由服务器或数据库饱和引起的。立即的解决方案是增加 "timeout server" 设置,但重要的是要记住用户体验会受到这些长响应时间的影响。唯一的长期解决方案是修复应用程序。 sQ 流在队列中停留时间过长并已过期。如果这种情况经常发生,请参阅 "timeout queue" 和 "timeout connect" 设置,以了解如何修复。如果它在短时间内大量发生,可能表明受影响的服务器由于 I/O 或数据库拥塞,或外部攻击导致的饱和而存在普遍问题。 PC 代理拒绝建立与服务器的连接,因为在尝试连接时已达到进程的套接字限制。可以在配置中增加全局 "maxconn" 参数,使其不再发生。此状态非常罕见,可能在手动强制设置全局 "ulimit-n" 参数时发生。 PD 代理在服务器发出头部后阻止了请求或响应中格式不正确的块编码消息。在大多数情况下,这表示服务器向客户端发送了无效消息。HAProxy 支持最大 2GB - 1 (2147483647 字节) 的块大小。任何更大的大小都将被视为错误。 PH 代理阻止了服务器的响应,因为它无效、不完整、危险(缓存控制)或匹配了安全过滤器。在任何情况下,都会向客户端发送 HTTP 502 错误。此错误的一个可能原因是 HTTP 头部名称中包含未经授权字符的无效语法。也可能但非常罕见的是,代理在服务器响应之前阻止了客户端的块编码请求,因为语法无效。在这种情况下,会向客户端发送 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 服务器错误之前对连接进行了陷阱处理。未向服务器发送任何内容。连接保持打开状态,持续时间由 "Tw" 计时器字段报告。 RC 本地资源已耗尽(内存、套接字、源端口),阻止了与服务器的连接建立。错误日志将精确说明缺少什么。这非常罕见,只能通过适当的系统调优来解决。 后两个标志的组合提供了大量关于客户端、服务器和 HAProxy 如何处理持久性的信息。这对于解决断开连接问题(当用户抱怨必须重新验证身份时)非常重要。常见的标志如下: -- 未启用持久性 cookie。 NN 客户端未提供任何 cookie,响应中也未插入任何 cookie。例如,这可以在插入模式下对 GET 请求设置 "postonly" 时发生。 II 客户端提供了指定无效服务器的 cookie,响应中插入了一个有效 cookie。这通常发生在从配置中删除 "server" 条目时,因为当没有其他服务器知道其 cookie 值时,客户端可以呈现它。 NI 客户端未提供任何 cookie,响应中插入了一个。这通常发生在“插入”模式下每个用户的第一个请求时,这使其成为计算真实用户的简便方法。 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 节)将其分配给变量。自定义日志格式将允许在需要的地方呈现这些变量(参见 第 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" 动作(参见 第 4.3 节)从 "http-request" 和 "http-response" 规则集中的作用域为 "txn" 的变量,然后可以从自定义日志格式中引用这些变量(参见 第 8.2.6 节)。这是捕获 HTTP 标头的推荐方法。 还有一种传统的旧方法,它早于 http-request 规则和变量,不涉及调整日志格式,并且长期以来一直用于日志记录和作为在整个 HTTP 事务中传递请求信息的“人工”方式,使用旧的 "capture" 规则集。本节描述的就是这种方法。传统头部捕获是使用前端的 "capture request header" 和 "capture response header" 语句执行的。有关更多详细信息,请参阅 第 4.2 节 中的定义。 可以同时包含请求头部和响应头部。不存在的头部将记录为空字符串,如果一个头部出现多次,则只记录其最后一次出现。请求头部按声明的顺序用大括号 '{' 和 '}' 分组,并用竖线 '|' 分隔,没有任何空格。响应头部遵循相同的表示形式,但在请求头部块后面的空格后显示。这些块在日志中的 HTTP 请求之前显示。作为特例,可以在 TCP 前端指定 HTTP 头部捕获。目的是启用对将在 HTTP 后端中解析的头部的日志记录(如果请求随后切换到此 HTTP 后端)。
示例
    # 此实例链接到传出代理 listen proxy-out mode http option httplog option logasap log global server cache1 192.168.1.1:3128 # 记录虚拟服务器的名称 capture request header Host len 20 # 记录 POST 期间上传的数据量 capture request header Content-Length len 10 # 记录引荐来源的开头 capture request header Referer len 20 # 服务器名称(仅适用于传出代理) capture response header Server len 20 # 使用 "option logasap" 时记录内容长度非常有用 capture response header Content-Length len 10 # 记录响应上的预期缓存行为 capture response header Cache-Control len 8 # Via 头部将报告下一个代理的名称 capture response header Via len 20 # 重定向期间记录 URL 位置 capture response header Location len 20 >>> 8 月 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/" >>> 8 月 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" >>> 8 月 9 日 20:30:46 localhost \ haproxy[2022]: 127.0.0.1:34028 [09/Aug/2004:20:30:46] proxy-out \ proxy-out/cache1 0/0/2/126/+128 301 +223 - - ---- 0/0/0/0/0 0/0 \ {www.sytadin.equipement.gouv.fr||http://trafic.1wt.eu/} \ {Apache|230|||http://www.sytadin.} \ "GET http://www.sytadin.equipement.gouv.fr/ HTTP/1.1"

8.9. 日志示例

这些是带有解释的真实日志示例。其中一些是手动编造的。为了更好的阅读,已删除 syslog 部分。它们唯一的目的是解释如何解读它们。 >>> haproxy[674]: 127.0.0.1:33318 [15/Oct/2003:08:31:57.130] px-http \ 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> 是在指定周期内可以转发的最大字节数。此值必须为每个流和共享带宽限制过滤器指定。它遵循 HAProxy 大小格式,以字节表示。 <pattern> 是 第 7.3 节 中描述的样本表达式规则。它描述了将分析、提取、组合和用于选择要更新计数器的表条目。它只必须为共享带宽限制过滤器指定。 <table> 是一个可选的表,用于代替默认表,默认表是当前代理中声明的 stick-table。它只可以为共享带宽限制过滤器指定。 <time> 是用于评估带宽限制速率的默认时间周期。它只可以为每个流的带宽限制过滤器指定。它遵循 HAProxy 时间格式,以毫秒表示。 <min-size> 是流一次转发的最小可选字节数,不包括可能更小的最后一个数据包。此值可以为每个流和共享带宽限制过滤器指定。它遵循 HAProxy 大小格式,以字节表示。
带宽限制过滤器应用于限制流级别的数据转发速度。因此,此类过滤器限制了资源消耗的网络带宽。可以使用多个带宽限制过滤器。例如,可以定义每个源地址的限制,以确保客户端永远不会消耗所有网络带宽,从而惩罚其他客户端,并为每个流定义另一个限制,以便能够公平地处理给定客户端的多个连接。 这些过滤器的定义顺序很重要。如果在流上启用了多个带宽过滤器,则过滤将按其定义顺序应用。了解其他过滤器的定义顺序也很重要。例如,根据 HTTP 压缩过滤器是在带宽限制过滤器之前还是之后定义,限制将应用于压缩后的有效载荷还是原始有效载荷。缓存过滤器也一样。 有两种带宽限制过滤器。第一种强制执行默认限制并按流应用。第二种使用粘性表强制执行在表中共享相同条目的所有流之间平均分配的限制。 此外,对于给定的过滤器,根据使用的过滤器关键字,限制可以应用于传入数据(从客户端接收并转发到服务器)或传出数据(从服务器接收并发送到客户端)。 要对传入数据应用限制,必须使用 "bwlim-in" 关键字。要对传出数据应用限制,必须使用 "bwlim-out" 关键字。在这两种情况下,带宽限制都应用于转发数据,在流级别。 带宽限制应用于流级别而不是连接级别。对于多路复用协议(H2、H3 和 FastCGI),同一连接的流可能具有不同的限制。 对于每个流的带宽限制过滤器,必须定义默认周期和限制。顾名思义,它们是用于设置流的带宽限制速率的默认值。但是,对于这种过滤器,并且仅此一种,可以在使用 TCP/HTTP "set-bandwidth-limit" 动作启用过滤器时使用样本表达式重新定义这些值。 对于共享带宽限制过滤器,根据它是应用于传入数据还是传出数据,所使用的粘性表必须存储相应的字节速率信息。"bytes_in_rate(<period>)" 计数器必须存储以限制传入数据,"bytes_out_rate(<period>)" 计数器必须用于限制传出数据。 最后,可以设置带宽限制过滤器可以一次为给定流转发的最小字节数。它应用于避免转发过少量数据,以减少 CPU 使用率。必须仔细定义。太小的值会增加 CPU 使用率。太高则会增加延迟。它还与定义的带宽限制高度相关。如果它与带宽限制太接近,可能会遇到一些暂停以不超过限制,因为一次消耗的字节数太多。它高度依赖于过滤器配置。一个好主意是开始时设置为大约 2 个 TCP MSS,通常为 2896 字节,并在一些实验后进行调整。
示例
frontend http bind *:80 mode http # 如果启用此过滤器,流将与所有具有相同源地址的其他流共享 10m/s 的下载限制。 filter bwlim-out limit-by-src key src table limit-by-src limit 10m # 如果启用此过滤器,流将被限制为以 1m/s 的速度下载, # 独立于所有其他流。 filter bwlim-out limit-by-strm default-limit 1m default-period 1s # 限制所有流为 1m/s(默认限制),访问内部 API 的流为 100k/s。限制每个源地址为 10m/s。共享 # 限制首先应用。两者都限制下载速率。 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 # <limit-by-src> 过滤器使用的粘性表 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 实现了 FastCGI 规范中所有用于 Responder 应用程序的功能。特别是,它能够在一个简单的连接上多路复用多个请求。

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 的默认值。这是一个可选设置。
示例
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 解码的路径中找到这两个字符中的任何一个,将向客户端返回错误。此处应用了最小惊讶原则。
示例
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 参数的值。如果将值评估为空字符串,则忽略该规则。这些指令按声明顺序进行评估。
示例
# 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. 默认参数

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

11.2. Peers 声明

可以在多个 HAProxy 实例之间通过 TCP 连接以多主模式传播 stick-tables 中的任何数据类型条目。每个实例将其本地更新和插入推送到远程 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”部分有自己的 stick-table 命名空间,以避免在不同“peers”部分中具有相同名称的 stick-table 之间发生冲突。这在内部通过将“peers”部分名称添加到 stick-table 名称前,后跟“/”字符来处理。如果在配置文件的其他地方必须引用在“peers”部分中声明的此类 stick-table,则必须使用带有前缀的 stick-table 名称,如下所示: peers mypeers peer A ... peer B ... table t1 ... frontend fe1 tcp-request content track-sc0 src table mypeers/t1 这也是必须用于通过 CLI 引用 stick-table 的带有前缀的版本。关于“peers”协议,由于只有属于同一部分的“peers”才能相互通信,因此无需进行这种区分。几个“peers”部分可以声明具有相同名称的 stick-table。这是通过网络发送的 stick-table 名称的较短版本。只有一个“/”字符作为前缀,以避免在后端声明的 stick-table 和在“peers”部分中声明的 stick-table 之间发生 stick-table 名称冲突,如下面的这种奇怪但受支持的配置: peers mypeers peer A ... peer B ... table t1 type string size 10m store gpc0 backend t1 stick-table type string size 10m store gpc0 peers mypeers 此处在“mypeers”部分中声明的“t1”表具有“mypeers/t1”作为全局名称。声明为后端的“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 日志记录器所消费的兼容。 priority 仅包含尖括号内的级别加 syslog 设施(例如“<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 中定义的“八位字节计数”和“非透明帧”模式。
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 }
设置 syslog 主机名字段在 log-forward 部分出站 rfc3164 或 rfc5424 消息中应使用的主机策略。 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" 关键字。另请参见第 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”将确保在初始化后立即自动获取 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 日志格式。如果发生此类错误,则会在“常规”OCSP 日志行旁边发出另一行包含 HTTP 相关信息的日志行(其文本状态可能为“HTTP 错误”)。但如果发生纯粹的 HTTP 错误(例如,OCSP 响应器不可达),则会发出一行遵循常规 HTTP 日志格式的额外日志行。以下是此类日志行的两个示例,首先是成功的 OCSP 更新日志行,然后是 HTTP 错误的示例,其中包含两条不同的日志行(为提高可读性,行已拆分,URL 已缩短): <133>3 月 6 日 11:16:53 haproxy[14872]: <OCSP-UPDATE> /path_to_cert/foo.pem 1 \ "更新成功" 0 1 <133>3 月 6 日 11:18:55 haproxy[14872]: <OCSP-UPDATE> /path_to_cert/bar.pem 2 \ "HTTP 错误" 1 0 <133>3 月 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" 错误,您可能需要检查您提供的颁发者证书是否有效。在“通用”错误消息之后,括号中也可能会显示更精确的错误消息。这可能发生在 "OCSP response check failure" 或 "Error during insertion" 错误中。

12.8. ACME

acme <name>
ACME 协议可以使用 "acme" 部分进行配置。该部分接受一个 "<name>" 参数,用于将证书链接到该部分。ACME 部分允许将 HAProxy 配置为 ACMEv2 客户端。此功能是实验性的,这意味着必须在全局部分中使用 "expose-experimental-directives" 才能使用此功能。3.2 版的当前限制: - 该功能目前仅限于 HTTP-01 或 DNS-01 质询。HTTP-01 完全由 HAProxy 处理,但 DNS-01 需要 dataplaneAPI 或另一个第三方工具来与 DNS 提供商 API 通信。 - 配置 acme 需要具有 crt 的配置,目前无法在磁盘上没有此 crt 的情况下启动,必须已经存在密钥对才能启动 haproxy。建议为此使用过期的证书。 - 当前的 HAProxy 架构是非阻塞模型,配置加载后不应访问磁盘,因为它可能会阻塞事件循环,从而阻塞同一线程上的流量。这意味着从 HAProxy 生成的证书和密钥需要使用 stats socket 上的 "dump ssl cert" 从 HAProxy 外部转储。可以使用 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

12.9. 程序(已废弃)

此部分已废弃,预计将在 HAProxy 3.3 中移除。此部分可以很容易地被分离的进程管理器取代。Systemd 单元文件或 sysvinit 脚本可以取代此部分,因为它们更可靠。在 Docker 环境中,也可以找到一些替代方案,例如 s6 或 supervisord。在主从模式下,可以使用主进程启动外部二进制文件,这些进程称为程序。这些程序的启动和管理方式与工作进程相同。自 3.1 版本以来,程序部分的行为略有不同,程序部分被解析,程序由主进程启动,但其余配置加载到工作进程中。这意味着程序配置与工作进程配置完全分离,并且即使工作进程配置在重新加载时错误,程序也可以重新执行。在 HAProxy 重新加载期间,这些进程与工作进程的处理序列相同: - 主进程重新执行 - 主进程向程序发送 SIGUSR1 信号 - 如果未禁用 "option start-on-reload",主进程将启动程序的新实例 在停止或重新启动期间,会向程序发送 SIGTERM。
program <name>
这是一个新的程序部分,此部分将创建一个名为 <name> 的实例,该实例在 master CLI 的 "show proc" 中可见。(请参阅管理指南中的 "9.4. Master CLI")。
command <command> [arguments*]
定义要启动的命令及可选参数。如果命令不包含绝对路径,则会在当前 PATH 中查找。这是 program 部分的一个强制选项。包含空格的参数必须用单引号或双引号括起来,或者以反斜杠为前缀。
user <user name>
将执行命令的用户 ID 更改为 /etc/passwd 中的 <user name>。另请参见 "group"。
group <group name>
将执行命令的组 ID 更改为 /etc/group 中的 <group name>。另请参见 "user"。
在 master 重载时启动(或不启动)程序的新实例。默认是启动新实例。此选项只能在 program 部分使用。


HAProxy 3.2.9 – 配置手册
, 2025/11/21