本文档涵盖了上述版本中实现的配置语言。它不提供任何提示、示例或建议。有关此类文档,请参阅参考手册或架构手册。以下摘要旨在帮助您按名称查找章节并在文档中导航。文档贡献者须知:本文档每行格式化为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. | ||
3. |
全局参数 | |
| 3.1. | ||
| 3.2. | ||
| 3.3. | ||
| 3.3.1. | ||
| 3.4. | ||
| 3.5. | ||
| 3.6. | ||
| 3.7. | ||
| 3.8. | ||
| 3.9. | ||
| 3.10. | ||
| 3.11. | ||
| 3.12. | ||
| 3.12.1. | ||
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. | ||
| 11.3. |
当 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 传输层。
HTTP 协议是事务驱动的。这意味着每个请求只会产生一个响应。最初,在协议 1.0 版本中,每个连接只有一个请求:客户端与服务器建立 TCP 连接,客户端通过连接发送请求,服务器响应,然后连接关闭。新的请求需要新的连接:[CON1] [REQ1] ... [RESP1] [CLO1] [CON2] [REQ2] ... [RESP2] [CLO2] ... 在这种模式下,通常称为“HTTP close”模式,有多少 HTTP 事务就有多少连接建立。由于服务器在响应后关闭连接,客户端不需要知道内容长度,它认为当连接关闭时响应就完成了。这也意味着如果某些响应由于网络错误而被截断,客户端可能会错误地认为响应已完成,这曾导致截断的图像有时会呈现在屏幕上。由于协议的事务性质,可以对其进行改进,以避免在两个后续事务之间关闭连接。然而,在这种模式下,服务器必须为每个响应指示内容长度,以便客户端不会无限期地等待。为此,使用了一个特殊的标头:“Content-length”。这种模式被称为“keep-alive”模式,随 HTTP/1.1 出现(某些 HTTP/1.0 代理支持它),在请求之间重用的连接被称为“持久连接”:[CON] [REQ1] ... [RESP1] [REQ2] ... [RESP2] [CLO] ... 它的优点是事务之间的延迟减少,服务器端所需的处理能力更少,并且能够检测到被截断的响应。它通常比关闭模式更快,但并非总是如此,因为有些客户端通常将其并发连接限制在较小的值,这在网络连接较差的情况下补偿较少。此外,一些服务器必须长时间保持连接活动,等待可能的新的请求,并且由于连接数量过多,可能会经历较高的内存使用量,而关闭过快可能会破坏在连接关闭时到达的某些请求。在这种模式下,响应大小需要事先知道,因此对于动态生成或压缩的内容来说并不总是可行。出于这个原因,实现了另一种模式,即“chunked mode”(分块模式),在这种模式下,发送方不是一次性宣布整个大小,而是只宣布它在缓冲区中已有的下一个“块”的块大小,并且可以随时以大小为零的块终止。在这种模式下,不使用 Content-Length 标头。通信中的另一个改进是管道模式。它仍然使用 keep-alive,但客户端在发送第二个请求时不需要等待第一个响应。这对于获取构成页面的大量图像很有用:[CON] [REQ1] [REQ2] ... [RESP1] [RESP2] [CLO] ... 这显然对性能有巨大的好处,因为后续请求之间的网络延迟被消除了。许多 HTTP 代理不支持管道操作,因为在 HTTP 中无法将响应与相应的请求关联起来。出于这个原因,服务器必须按照接收请求的完全相同的顺序回复。在实践中,在各种客户端尝试部署它几次后,由于它在某些服务器上缺乏可靠性而被完全放弃。但服务器必须支持它。下一个改进是多路复用模式,如 HTTP/2 和 HTTP/3 中实现的那样。在这种模式下,多个事务(即请求-响应对)在单个连接上并行传输,并且它们都以自己的速度进展,彼此独立。对于多路复用协议,引入了“流”(stream)的新概念,以表示在同一连接上发生的这些并行通信。每个流通常被分配一个给定连接的唯一标识符,两端都使用该标识符来知道将数据传送到何处。客户端在同一连接上并行启动许多(最多 100 个,有时更多)流是很常见的,并让服务器对它们进行排序,并根据哪个响应可用以任何顺序响应。多路复用模式的主要好处是它显著减少了往返次数,并加快了高延迟网络上的页面加载时间。这在使用许多图像的网站上有时可见,所有图像似乎都在并行加载。这些协议还通过采用一些机制来压缩标头字段以减少网络上的字节数来提高效率,因此如果没有适当的工具,它们不像 HTTP/1 那样可以手动操作,也无法肉眼读取。出于这个原因,HTTP 消息的各种示例继续在文献中(包括本文档)使用 HTTP/1 语法表示,即使是针对较新版本的协议。HTTP/2 存在一些设计限制,例如数据包丢失会同时影响所有流,如果客户端花费太多时间来检索对象(例如需要将其存储在磁盘上),它可能会减慢检索速度,并使得在此期间无法访问其后面待处理的数据。这被称为“队头阻塞”("head of line blocking" 或 "HoL blocking",有时简称 "HoL")。HTTP/3 是在 QUIC 上实现的,QUIC 本身是在 UDP 上实现的。QUIC 通过独立处理流的方式在传输层解决了队头阻塞问题。事实上,当遇到丢失时,受影响的流不会影响其他流,并且所有流都可以并行访问。QUIC 还提供连接迁移支持,但目前 haproxy 不支持它。默认情况下,HAProxy 在持久连接方面以 keep-alive 模式运行:对于每个连接,它处理每个请求和响应,并在响应结束和新请求开始之间将连接在两端保持空闲。当它从客户端接收到 HTTP/2 连接时,它并行处理所有请求并使连接空闲,等待新请求,就像它是一个 keep-alive HTTP 连接一样。HAProxy 主要支持 3 种连接模式:- keep alive:处理所有请求和响应,并且面向客户端和面向服务器的连接保持活动以进行新请求。这是默认设置,适用于现代 Web 和现代协议(HTTP/2 和 HTTP/3)。- server close:在响应后关闭面向服务器的连接。- close:在两端响应结束后主动关闭连接。除此之外,默认情况下,面向服务器的连接可以被来自任何客户端的任何请求重用,正如 HTTP 协议规范所要求的那样,因此如果需要(例如客户端的源地址等),任何与特定客户端相关的信息都必须随每个请求一起传递。当 HTTP/2 与服务器一起使用时,默认情况下 HAProxy 会将此连接专用于同一客户端,以避免客户端之间发生队头阻塞的风险。
在 HAProxy 内部,术语随着 HTTP 协议及其用法的演变而有所发展。虽然最初连接、会话、流或事务之间没有显著差异,但随着时间的推移,这些术语变得清晰,以密切匹配现代 HTTP 协议版本中存在的术语,尽管某些术语为了历史兼容性仍然在配置或命令行界面中可见。以下是适用于当前 HAProxy 版本的定义:- connection(连接):连接是远程代理(客户端或服务器)与 HAProxy 之间在最低级别上的单个双向通信通道。它通常对应于一对 IP 和端口之间建立的 TCP 套接字。在面向客户端的一侧,当客户端连接到 HAProxy 时,连接是实例化的第一个实体,并且在连接级别应用的规则是最早应用的规则。- session(会话):会话添加了一些与连接关联的上下文信息。这包括特定于传输层的信息(例如 TLS 密钥等)或变量。这个术语在 HAProxy 内部长期用于表示两端之间的端到端 HTTP/1.0 通信,因此尽管现在它表示流,但它仍然在某些 CLI 命令或统计信息的名称中可见,但帮助消息和描述试图使其明确。它在网络级别术语(例如操作系统内部的 TCP 会话,或跨防火墙的 TCP 会话)或非 HTTP 用户级别应用程序(例如 telnet 会话或 SSH 会话)方面仍然有效。它不得与用于在 cookie 中存储完整用户上下文并要求发送到同一服务器的“应用程序会话”混淆。- stream(流):流精确地对应于应用程序级别的端到端双向通信,可以在其中应用分析和转换。在 HTTP 中,它包含单个请求及其关联的响应,并通过请求的到达实例化,并在响应交付结束时完成。在这种上下文中,这种流与多路复用协议的流之间存在 1:1 的关系。在 TCP 通信中,每个连接只有一个流。- transaction(事务):事务仅是一对请求和关联的响应。在流出现之前,该术语与会话结合使用,但现在事务与流之间存在 1:1 的关系。它主要在变量范围“txn”中可见,该范围在整个事务期间有效,因此在流期间有效。- request(请求):它表示从客户端流向服务器的流量。它主要用于 HTTP,以指示执行操作的位置。此术语也存在于 TCP 操作中,以指示处理数据的位置。请求通常作为流量或活动的单位出现在计数器中。它们并不总是意味着响应(例如由于错误),但由于没有自发的响应而没有请求,请求仍然是总体活动的相关指标。在 TCP 中,请求数量与连接数量相同。- response(响应):这表示从服务器流向客户端的流量,或者有时是 HAProxy 自己生成的响应(例如 HTTP 重定向)时从 HAProxy 流向客户端的流量。- service(服务):这通常表示 HAProxy 中的一些内部处理,不需要服务器,例如 stats 页面、缓存或一些用于实现小型应用程序的 Lua 代码。服务通常读取请求,执行一些操作并生成响应。
首先,让我们考虑这个 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 个字段组成:- 方法(METHOD):GET- URI:/serv/login.php?lang=en&profile=2- 版本标签(version tag):HTTP/1.1所有这些都由标准所称的 LWS(线性空格)分隔,通常是空格,但也可能是制表符或换行符/回车符后跟空格/制表符。方法本身不能包含任何冒号(':'),并且仅限于字母。所有这些各种组合使得 HAProxy 最好自己执行拆分,而不是让用户编写复杂或不准确的正则表达式。URI 本身可以有几种形式:- “相对 URI”:/serv/login.php?lang=en&profile=2它是一个完整的 URL,不包含主机部分。这通常是服务器、反向代理和透明代理接收到的内容。- “绝对 URI”,也称为“URL”:http://192.168.0.12:8080/serv/login.php?lang=en&profile=2它由“方案”(协议名称后跟 '://')、主机名或地址、可选的冒号(':')后跟端口号,然后是在地址部分之后的第一个斜杠('/')开始的相对 URI 组成。这通常是代理接收到的内容,但支持 HTTP/1.1 的服务器也必须接受这种形式。- 星号('*'):这种形式仅与 OPTIONS 方法关联时才被接受,并且不可中继。它用于查询下一跳的能力。- address:port 组合:192.168.0.12:80这与 CONNECT 方法一起使用,CONNECT 方法用于通过 HTTP 代理建立 TCP 隧道,通常用于 HTTPS,但有时也用于其他协议。在相对 URI 中,识别出两个子部分。问号之前的部分称为 "path"(路径)。它通常是服务器上静态对象的相对路径。问号之后的部分称为“query string”(查询字符串)。它主要用于发送给动态脚本的 GET 请求,并且非常特定于正在使用的语言、框架或应用程序。HTTP/2 和 HTTP/3 不会随请求传输版本信息,因此版本被假定与底层协议的版本相同(即“HTTP/2”)。此外,这些协议不会将请求行作为一个部分发送,而是将其拆分为称为“伪标头”(pseudo-headers)的单个字段,其名称以冒号开头,并且 HAProxy 会方便地将它们重新组合成等效的请求行。因此,日志中发现的请求行在 HTTP/1.x 和 HTTP/2 或 HTTP/3 之间可能略有不同。
标头从第二行开始。它们由行开头的名称组成,紧跟着冒号(':')。传统上,在冒号后添加 LWS,但这不是必需的。然后是值。多个相同的标头可以折叠成一行,用逗号分隔值,前提是它们的顺序得到尊重。这在“Cookie:”字段中很常见。如果后续行以 LWS 开头,则标头可以跨多行。在 1.3 的示例中,第 4 行和第 5 行总共为“Accept:”标头定义了 3 个值。最后,根据规范,忽略标头开头或结尾处的所有 LWS,它们不属于值的一部分。与常见的误解相反,标头名称不区分大小写,如果它们引用其他标头名称(例如“Connection:”标头),则它们的值也不区分大小写。在 HTTP/2 和 HTTP/3 中,标头名称始终以小写字母发送,这可以在调试模式下运行时看到。在内部,所有标头名称都被规范化为小写,以便 HTTP/1.x 和 HTTP/2 或 HTTP/3 使用完全相同的表示形式,并且它们被原样发送到另一端。这解释了为什么使用驼峰式大小写的 HTTP/1.x 请求会以小写形式交付。标头的结束由第一个空行指示。人们常说它是双换行符,这不准确,即使双换行符是空行的一种有效形式。幸运的是,HAProxy 在索引标头、检查值和计数它们时会处理所有这些复杂的组合,因此无需担心它们的写入方式,但重要的是不要指责应用程序如果它做了不寻常但有效的事情就是有错误的。重要提示:根据 RFC7231 的建议,HAProxy 通过用 LWS 替换标头中间的换行符来规范化标头,以便连接多行标头。这对于正确的分析是必要的,并有助于能力较差的 HTTP 解析器正常工作,不被这种复杂的结构所迷惑。
HTTP 响应看起来与 HTTP 请求非常相似。两者都称为 HTTP 消息。让我们考虑一下这个 HTTP 响应:行号 内容1 HTTP/1.1 200 OK2 Content-length: 3503 Content-Type: text/html作为一个特例,HTTP 支持所谓的“信息性响应”,状态码为 1xx。这些消息很特别,因为它们不传达响应的任何部分,它们只用作一种信号消息,例如要求客户端继续发送其请求。在状态 100 响应的情况下,请求的信息将由跟随信息性响应的下一个非 100 响应消息携带。这意味着可以向单个请求发送多个响应,并且这仅在启用 keep-alive 时才有效(1xx 消息出现在 HTTP/1.1 中)。HAProxy 处理这些消息,并能够正确转发和跳过它们,只处理下一个非 100 响应。因此,除非另有明确说明,否则这些消息既不会被记录也不会被转换。状态 101 消息表示协议正在同一连接上更改,HAProxy 必须切换到隧道模式,就像发生了 CONNECT 一样。然后 Upgrade 标头将包含有关连接切换到的协议类型的附加信息。
第 1 行是“响应行”。它始终由 3 个字段组成:- 版本标签(version tag):HTTP/1.1- 状态码(status code):200- 原因短语(reason phrase):OK状态码始终是 3 位数字。第一位数字表示一般状态:- 1xx = 要跳过的信息性消息(例如 100, 101)- 2xx = OK,内容正在跟随(例如 200, 206)- 3xx = OK,没有内容跟随(例如 302, 304)- 4xx = 客户端引起的错误(例如 401, 403, 404)- 5xx = 服务器引起的错误(例如 500, 502, 503)状态码大于 599 不得在通信中发出,尽管某些代理可能会在日志中生成它们以报告其内部状态。有关所有此类代码的详细含义,请参阅 RFC9110。HTTP/2 及更高版本没有版本标签,并使用“:status”伪标头来报告状态码。“原因”字段只是一个提示,但客户端不解析它。那里可以找到任何东西,但尊重既定的消息是一种常见做法。它可以由一个或多个单词组成,例如“OK”、“Found”或“Authentication Required”。它在 HTTP/2 及更高版本中不存在,并且在那里不发出。当来自 HTTP/2 或更高版本的响应传输到 HTTP/1 客户端时,HAProxy 将生成与状态码匹配的常见原因字段。HAProxy 可能会自行发出以下状态码:代码 何时/原因200 访问统计信息页面,以及回复监控请求时301 执行重定向时,具体取决于配置的代码302 执行重定向时,具体取决于配置的代码303 执行重定向时,具体取决于配置的代码307 执行重定向时,具体取决于配置的代码308 执行重定向时,具体取决于配置的代码400 对于无效或过大的请求401 执行操作需要身份验证时(访问统计信息页面时)403 当请求被“http-request deny”规则禁止时404 当请求的资源找不到时408 在请求完成之前请求超时时410 当请求的资源不再可用且以后也不会再次可用时413 当 HTTP/1.0 GET/HEAD/DELETE 请求带有有效载荷时,另请参阅 "h1-accept-payload-with-any-method" 选项500 当 HAProxy 遇到不可恢复的内部错误时,例如内存分配失败,这不应该发生501 当 HAProxy 因不支持的功能而无法满足客户端请求时502 当服务器返回空、无效或不完整的响应时,或者当“http-response deny”规则阻止响应时。503 当没有可用的服务器来处理请求时,或者响应与 "monitor fail" 条件匹配的监控请求时504 在服务器响应之前响应超时时上面的错误 4xx 和 5xx 代码可以自定义(请参阅 4.2 节中的 "errorloc")。其他状态码可以通过特定操作有意发出(例如,请参阅 4.3 节中的 "deny"、"return" 和 "redirect" 操作)。
响应头的工作方式与请求头完全相同,因此,HAProxy 对两者使用相同的解析函数。有关更多详细信息,请参阅第 1.3.2 段。
HAProxy 的配置过程涉及 3 个主要参数来源:- 命令行参数,它始终优先- 配置文件,其格式在此处描述- 运行进程的环境,以防某些环境变量被明确引用配置文件遵循一个相当简单的层次结构格式,它遵循一些基本规则:1. 配置文件是一个有序的语句序列2. 语句是在任何未受保护的“#”(哈希)之前的一行非空行3. 一行是由未受保护的空格或制表符分隔的一系列令牌或“单词”4. 一行的第一个单词或单词序列是本文档中列出的关键字或关键字序列之一5. 所有其他单词都是第一个单词的所有参数,其中一些是本文档中列出的众所周知的关键字,其他是值、对配置其他部分的引用或表达式6. 某些关键字界定了一个部分,在该部分内只支持关键字的一个子集7. 一个部分在文件末尾或在新部分开始的特殊关键字处结束要编写简单可靠的配置生成器,只需要知道这些,但这不足以可靠地解析任何配置或弄清楚如何处理某些极端情况。首先,上面规则有一些推论。规则 6 和 7 意味着用于定义新部分的关键字在任何地方都有效,并且不能在特定部分中具有不同的含义。这些关键字始终是单个单词(而不是单词序列),并且传统上,跟随它们的部分使用相同的名称来指定。例如,当谈论“global section”(全局部分)时,它指的是跟随“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 # 或者 tcpand: global daemon # 这是公共 web 前端frontend foo mode http通常的做法是只将启动新部分的关键字左对齐,并缩进(即在前面加上制表符或几个空格)所有其他关键字,以便立即看出它们属于同一部分(如上例中的第二个示例所示)。在新部分之前放置注释有助于读者判断它是否是所需的部分。在部分末尾留一个空行也有助于在编辑时直观地发现末尾。制表符非常方便用于缩进,但它们复制粘贴效果不佳。如果使用空格代替,建议不要放置太多(2 到 4 个),这样在没有自动缩进支持的有限编辑器中编辑时不会成为负担。在早期,在固定制表符位置拆分参数是很常见的,因为大多数关键字不会接受超过两个参数。随着具有复杂表达式的现代版本,这种做法不再适用,也不推荐。
在现代配置中,某些参数需要使用以前被认为是纯分隔符的字符。为了使这成为可能,HAProxy 支持通过在要转义的字符前面加上反斜杠('\')来转义字符,使用双引号('"')进行弱引用,以及使用单引号("'")进行强引用。这与许多编程语言中所做的工作非常相似,并且非常接近于 Bourne shell 中常见的做法。原理如下:当配置解析器将行切割成单词时,它还会处理引号和反斜杠,以决定一个字符是分隔符还是当前单词中该字符的原始表示形式。然后删除转义字符,删除引号,剩余的单词原样用作关键字或参数。如果单词中需要反斜杠,则必须使用自身进行转义(即双反斜杠)或使用强引用。在引号外部转义是通过在特殊字符前加上反斜杠('\')实现的:\ 标记空格并将其与分隔符区分开来\# 标记哈希并将其与注释开头区分开来\\ 使用反斜杠\' 使用单引号并将其与强引用分隔符区分开来\" 使用双引号并将其与弱引用分隔符区分开来此外,可以使用通常的 C 语言表示法发出一些不可打印字符:\n 插入换行符(LF,字符 \x0a 或 ASCII 10 十进制)\r 插入回车符(CR,字符 \x0d 或 ASCII 13 十进制)\t 插入制表符(字符 \x09 或 ASCII 9 十进制)\xNN 插入 ASCII 码为十六进制 NN 的字符(例如 \x0a 表示 LF)。弱引用是通过在要保护的字符或字符序列周围加上双引号("")实现的。弱引用会阻止以下内容的解释:空格或制表符作为单词分隔符' 单引号作为强引用分隔符# 哈希作为注释开头弱引用允许解释环境变量(在引号外部不评估),方法是在其前面加上美元符号('$')。如果双引号内需要美元字符,则必须使用反斜杠转义。强引用是通过在要保护的字符或字符序列周围加上单引号('')实现的。在单引号内,不解释任何内容,这是引用正则表达式的有效方式。因此,这里是表示特殊字符在不同上下文中如何输入的矩阵(不可打印字符替换为其名称)。请注意,某些只能转义表示的字符在单引号内没有可能的表示,因此此处缺失
| 字符 | 无引号 | 弱引用 | 强引用 |
|---|---|---|---|
| <TAB> | \<TAB>, \x09 | "<TAB>", "\<TAB>", "\x09" | '<TAB>' |
| <LF> | \n, \x0a | "\n", "\x0a" | |
| <CR> | \r, \x0d | "\r", "\x0d" | |
| <SPC> | \<SPC>, \x20 | "<SPC>", "\<SPC>", "\x20" | '<SPC>' |
| " | \", \x22 | "\"", "\x22" | '"' |
| # | \#, \x23 | "#", "\#", "\x23" | '#' |
| $ | $, \$, \x24 | "\$", "\x24" | '$' |
| ' | \', \x27 | "'", "\'", "\x27" | |
| \ | \\, \x5c | "\\", "\x5c" | '\' |
# 以下这些都是完全等效的: log-format %{+Q}o\ %t\ %s\ %{-Q}r log-format "%{+Q}o %t %s %{-Q}r" log-format '%{+Q}o %t %s %{-Q}r' log-format "%{+Q}o %t"' %s %{-Q}r' log-format "%{+Q}o %t"' %s'\ %{-Q}r
There is one particular case where a second level of quoting or escaping may be necessary. Some keywords take arguments within parenthesis, sometimes delimited by commas. These arguments are commonly integers or predefined words, but when they are arbitrary strings, it may be required to perform a separate level of escaping to disambiguate the characters that belong to the argument from the characters that are used to delimit the arguments themselves. A pretty common case is the "regsub" converter. It takes a regular expression in argument, and if a closing parenthesis is needed inside, this one will require to have its own quotes. The keyword argument parser is exactly the same as the top-level one regarding quotes, except that the \#, \$, and \xNN escapes are not processed. But what is not always obvious is that the delimiters used inside must first be escaped or quoted so that they are not resolved at the top level. Let's take this example making use of the "regsub" converter which takes 3 arguments, one regular expression, one replacement string and one set of flags: # replace all occurrences of "foo" with "blah" in the path: http-request set-path %[path,regsub(foo,blah,g)] Here no special quoting was necessary. But if now we want to replace either "foo" or "bar" with "blah", we'll need the regular expression "(foo|bar)". We cannot write: http-request set-path %[path,regsub((foo|bar),blah,g)] because we would like the string to cut like this: http-request set-path %[path,regsub((foo|bar),blah,g)] |---------|----|-| arg1 _/ / / arg2 __________/ / arg3 ______________/ but actually what is passed is a string between the opening and closing parenthesis then garbage: http-request set-path %[path,regsub((foo|bar),blah,g)] |--------|--------| arg1=(foo|bar _/ / trailing garbage _________/ The obvious solution here seems to be that the closing parenthesis needs to be quoted, but alone this will not work, because as mentioned above, quotes are processed by the top-level parser which will resolve them before processing this word: http-request set-path %[path,regsub("(foo|bar)",blah,g)] ------------ -------- ---------------------------------- word1 word2 word3=%[path,regsub((foo|bar),blah,g)] So we didn't change anything for the argument parser at the second level which still sees a truncated regular expression as the only argument, and garbage at the end of the string. By escaping the quotes they will be passed unmodified to the second level: http-request set-path %[path,regsub(\"(foo|bar)\",blah,g)] ------------ -------- ------------------------------------ word1 word2 word3=%[path,regsub("(foo|bar)",blah,g)] |---------||----|-| arg1=(foo|bar) _/ / / arg2=blah ___________/ / arg3=g _______________/ Another approach consists in using single quotes outside the whole string and double quotes inside (so that the double quotes are not stripped again): http-request set-path '%[path,regsub("(foo|bar)",blah,g)]' ------------ -------- ---------------------------------- word1 word2 word3=%[path,regsub("(foo|bar)",blah,g)] |---------||----|-| arg1=(foo|bar) _/ / / arg2 ___________/ / arg3 _______________/ But in this case it's important to note that delimiters embedded into the higher level string remain pure characters and are not delimiters anymore. It particularly means that spaces and tabs around commas are part of the string. The example below is wrong on multiple points: http-request set-path '%[path, regsub("(foo|bar)", blah, g)]' ------------ -------- -------------------------------------- word1 word2 word3=%[path, regsub("(foo|bar)", blah, g)] |--------|---------||-----|--| converter=" regsub" _/ / / / arg1=(foo|bar) _/ / / arg2=" blah" ___________/ / arg3=" g" ______________/ The single fact of surrounding commas with spaces resulted in the spaces being part of the field itself, hence the converter " regsub" (starting with a space), which won't be found and will trigger an error, but more subtly, the replacement string " blah" will insert a space in the output. A good rule of thumb is to never insert unneeded spaces inside expressions. When using regular expressions, it can happen that the dollar ('$') character appears in the expression or that a backslash ('\') is used in the replacement string. In this case these ones will also be processed inside the double quotes thus single quotes are preferred (or double escaping). Example: http-request set-path '%[path,regsub("^/(here)(/|$)","my/\1",g)]' ------------ -------- ----------------------------------------- word1 word2 word3=%[path,regsub("^/(here)(/|$)","my/\1",g)] |-------------| |-----||-| arg1=(here)(/|$) _/ / / arg2=my/\1 ________________/ / arg3 ______________________/ Remember that backslashes are not escape characters within single quotes and that the whole word above is already protected against them using the single quotes. Conversely, if double quotes had been used around the whole expression, single the dollar character and the backslashes would have been resolved at top level, breaking the argument contents at the second level. Unfortunately, since single quotes can't be escaped inside of strong quoting, if you need to include single quotes in your argument, you will need to escape or quote them twice. There are a few ways to do this: http-request set-var(txn.foo) str("\\'foo\\'") http-request set-var(txn.foo) str(\"\'foo\'\") http-request set-var(txn.foo) str(\\\'foo\\\') When in doubt, simply do not use quotes anywhere, and start to place single or double quotes around arguments that require a comma or a closing parenthesis, and think about escaping these quotes using a backslash if the string contains a dollar or a backslash. Again, this is pretty similar to what is used under a Bourne shell when double-escaping a command passed to "eval". For API writers the best is probably to place escaped quotes around each and every argument, regardless of their contents. Users will probably find that using single quotes around the whole expression and double quotes around each argument provides more readable configurations.
HAProxy 的配置支持环境变量。这些变量仅在双引号内被解释。变量在配置解析期间被展开。变量名前必须有美元符号 ("$"),并且可以选择性地用大括号 ("{}") 括起来,类似于 Bourne shell 中的做法。变量名可以包含字母数字字符或下划线 ("_"),但不应以数字开头。如果变量包含由空格分隔的多个值列表,可以通过用大括号将变量括起来并在右大括号前附加后缀 '[*]' 来将其展开为单个参数。当变量未设置时,也可以通过在变量名旁边的破折号 '-' 后面附加该值来指定一个默认值。请注意,默认值只替换不存在的变量,而不是空变量。bind "fd@${FD_APP1}" log "${LOCAL_SYLOG-127.0.0.1}:514" local0 notice # 发送到本地服务器 user "$HAPROXY_USER"
HAProxy 定义了一些变量,这些变量可以在配置文件中使用,也可以被程序继承(参见 3.7. Programs)。这些变量分为四类,如下表所示: * usable (可用):变量可以从配置中访问,既可以按原样解析,也可以用于条件块或谓词中,以启用或禁用某些配置片段,如 section 2.4 "Conditional blocks" 中所述。 * modifiable (可修改):变量可以通过 "setenv"/"unsetenv" 关键字在配置中重新定义或取消设置。 * listed (可列出):变量列在 CLI 的 "show env" 命令输出中,如管理指南的 section 9.3 "Unix Sockets commands" 中所述。 * exported (已导出):变量导出到修改后的环境中以启动程序(参见 section 3.7 "Programs")。请注意,这不适用于外部检查,外部检查有自己的关于导出变量的规则。 还有两个子类别 "master" 和 "worker",分别在下表中标记为 'M' 和 'W',显示了 HAProxy 在 master-worker 模式下启动时,两个进程之间的差异。 * master:变量在 master 进程中设置并可访问。因此,它将出现在 master CLI 的 "show env" 输出中,并且可以用于条件块或指令中,以启用 master 的一些特殊设置(参见 section 2.4 "Conditional blocks" 中的示例)。 * worker:变量在 worker 进程中设置并可访问。它将出现在 worker CLI 的 "show env"(或 master CLI 的 "@1 show env")中,并且也可以限制某些 worker 进程参数(参见 section 2.4 "Conditional blocks" 中的示例)。 在独立模式下(没有 "-W" 选项或 "master-worker" 关键字),进程的行为类似于 worker,除了变量 "HAPROXY_MASTER_CLI" 和 "HAPROXY_MWORKER" 未定义。 有些变量被标记为不可用且不可修改: * HAPROXY_CFGFILES * HAPROXY_MWORKER * HAPROXY_CLI * HAPROXY_MASTER_CLI * HAPROXY_LOCALPEER 它们的值在配置解析期间未定义,而是在初始化期间设置。因此,建议不要在条件块中使用这些变量,也不要在 global 部分的 "setenv"/"resetenv"/"unsetenv" 关键字中引用它们。 下表总结了每个变量在不同工作模式下的状态: +--------------------------+----------+---------+------------+-----------+ | variable | exported | usable | modifiable | listed | | | +---------+------------+-----------+ | | | 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:包含默认 HTTP 日志格式的值,如 section 8.2.3 "HTTP log format" 中所定义。它可用于覆盖默认日志格式,而无需复制整个原始定义。 * HAPROXY_HTTP_CLF_LOG_FMT:包含默认 HTTP CLF 日志格式的值,如 section 8.2.3 "HTTP log format" 中所定义。它可用于覆盖默认日志格式,而无需复制整个原始定义。
# 将给出最终判决的规则添加到日志中 log-format "${HAPROXY_TCP_LOG_FMT} lr=last_rule_file:last_rule_line"
* HAPROXY_HTTPS_LOG_FMT:与 HAPROXY_HTTP_LOG_FMT 类似,但用于 HTTPS 日志格式,如 section 8.2.4 "HTTPS log format" 中所定义。 * HAPROXY_TCP_LOG_FMT:与 HAPROXY_HTTP_LOG_FMT 类似,但用于 TCP 日志格式,如 section 8.2.2 "TCP log format" 中所定义。 * HAPROXY_TCP_CLF_LOG_FMT:与 HAPROXY_HTTP_CLF_LOG_FMT 类似,但用于 TCP CLF 日志格式,如 section 8.2.2 "TCP log format" 中所定义。 * HAPROXY_MWORKER:在 master-worker 模式下,此变量设置为 1。 * HAPROXY_CLI:每个进程的 stats socket 的已配置监听器地址,这些地址以分号分隔。 * HAPROXY_MASTER_CLI:在 master-worker 模式下,master CLI 的监听器地址,以分号分隔。 * HAPROXY_STARTUP_VERSION:包含用于启动的版本,在 master-worker 模式下,这是用于启动 master 的版本,即使在更新二进制文件和重新加载之后也是如此。 * HAPROXY_BRANCH:包含 HAProxy 分支版本(例如 "2.8")。它不包含完整的版本号。在迁移期间,如果资源(例如 map 或证书)位于包含分支号的路径中,这可能会很有用。 此外,一些伪变量会在内部解析并可作为常规变量使用。伪变量始终以点('.')开头,并且是唯一允许使用点的变量。当前的伪变量列表如下: * .FILE:当前正在解析的配置文件的名称。 * .LINE:当前正在解析的配置文件的行号,从一开始计数。 * .SECTION:当前正在解析的节的名称,如果该节没有名称,则为其类型(例如 "global"),或者在第一个节之前为空字符串。 这些变量在它们被解析的位置解析。例如,如果 ".LINE" 变量用于位于 defaults 节中的 "log-format" 指令中,它的行号将在解析和编译 "log-format" 指令之前解析,因此后续代理将重用相同的行号。通过这种方式,可以将信息发送到变量、日志、错误状态、健康检查、标头值中,以帮助定位规则,甚至可以使用行号来命名一些配置对象,例如服务器。
有时,有条件地启用或禁用配置的某些任意部分可能很方便,例如启用/禁用 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. Starting 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. Quoting and escaping" 部分所述,一个好的经验法则是永远不要在表达式中插入不必要的空格。 请注意,与在其他语言中一样,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 在 master 和 # worker 进程环境中自动设置(参见 2.3. Environment variables 中的 HAProxy 变量矩阵)。 # 它的存在会启用一个额外的监听器。 global master-worker .if defined(HAPROXY_MWORKER) listen mwcli_px bind :1111 ... .endif # 2. HAPROXY_BRANCH 由 HAProxy 在 master 和 worker # 进程环境中自动设置(参见 2.3. Environment variables 中的 HAProxy 变量矩阵)。 # 我们检查 HAPROXY_BRANCH 值并有条件地启用 # mworker-max-reloads 参数。 global master-worker .if streq("$HAPROXY_BRANCH",3.1) mworker-max-reloads 5 .endif # 3. 用户在 global 节中设置了一些任意环境变量。 # 如果 HAProxy 在 master-worker 模式下启动,它们会呈现在 # master 和 worker 进程环境中。我们检查这些变量的值 # 并有条件地启用端口 80 和 443。环境变量 # 检查可以与特性和版本检查混合使用。 global setenv WITH_SSL yes unsetenv SSL_ONLY .if strneq("$SSL_ONLY",yes) bind :80 .endif .if streq("$WITH_SSL",yes) .if feature(OPENSSL) bind :443 ssl crt ... .endif .endif .if feature(OPENSSL) && (streq("$WITH_SSL",yes) || streq("$SSL_ONLY",yes)) bind :443 ssl crt ... .endif .if version_atleast(2.4-dev19) profiling.memory on .endif .if !feature(OPENSSL) .alert "SSL support is mandatory" .endif
还提供了另外四个指令来报告某些状态: - .diag "message" : 仅在诊断模式(-dD)下发出此消息 - .notice "message" : 以 NOTICE 级别发出此消息 - .warning "message" : 以 WARNING 级别发出此消息 - .alert "message" : 以 ALERT 级别发出此消息 如果启用了 "zero-warning",以 WARNING 级别发出的消息可能导致进程启动失败。以 ALERT 级别发出的消息将始终导致致命错误。这些可以用来检测一些不适当的条件并向用户提供建议。
.if "${A}" .if "${B}" .notice "A=1, B=1" .elif "${C}" .notice "A=1, B=0, C=1" .elif "${D}" .warning "A=1, B=0, C=0, D=1" .else .alert "A=1, B=0, C=0, D=0" .endif .else .notice "A=0" .endif .diag "WTA/2021-05-07: 切换到 2.4 后将 'redirect' 替换为 'return'" http-request redirect location /goaway if ABUSE
一些参数涉及表示时间的值,例如超时。这些值通常以毫秒表示(除非另有明确说明),但也可以通过在数值后附加单位来以任何其他单位表示。考虑这一点很重要,因为每个关键字都不会重复说明。支持的单位有:- 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
一些参数涉及表示大小的值,例如带宽限制。这些值通常以字节表示(除非另有明确说明),但也可以通过在数值后附加单位来以任何其他单位表示。考虑这一点很重要,因为每个关键字都不会重复说明。支持的单位不区分大小写:- k:千字节。1 千字节 = 1024 字节 - m:兆字节。1 兆字节 = 1048576 字节 - g:吉字节。1 吉字节 = 1073741824 字节 时间和大小格式都需要整数,不允许使用小数表示法。
可以对 map 或 ACL 使用模式列表。模式列表由其名称标识,可以在配置中的不同位置使用。模式列表根据名称格式分为三类: * 基于常规文件的模式列表:这是默认情况。文件名(绝对路径或相对路径)用作名称。文件必须存在,否则会触发错误。但它可以为空。也可以指定 "file@" 前缀,但它不是用于标识列表的名称的一部分。带前缀或不带前缀的文件名引用相同的模式列表。 * 基于可选文件的模式列表:文件名必须以 "opt@" 前缀开头。文件是否存在是可选的。如果文件存在,则加载其内容,否则不报告错误。前缀不是用于标识列表的名称的一部分。这意味着,对于给定的文件名,可选文件和常规文件引用相同的模式列表。 * 基于虚拟文件的模式列表:名称只是一个标识符。它不引用任何文件。必须使用 "virt@" 前缀。它是名称的一部分。因此,它不能与其他类型的列表混合使用。当模式完全动态管理,启动和重新加载时没有模式时,虚拟文件非常有用。可选文件可以在相同条件下使用。但是模式可以转储到文件中,例如通过基于 "show map" CLI 命令的外部脚本。通过这种方式,可以在重新加载时保留模式。 注意:尽管不太可能,这意味着不能加载以 "file@"、"opt@" 或 "virt@" 开头的常规文件,除非在文件名前面明确添加 "./"(例如 "file@./virt@map")。
在 HAProxy 配置中,变量可用于样本获取函数、转换器、log-format 字符串或 TCP/HTTP 操作。可以定义进程范围的变量,在整个进程生命周期内全局可访问。其他一些变量的生命周期较短。 变量类似于 shell 脚本中找到的变量。它是一块内存的符号名称。变量大小不受限制,并且是动态分配的。因此,必须谨慎使用,尤其是对于密集使用。但是,可以通过设置 "tune.vars" 全局参数来限制变量使用的最大内存量。 变量必须使用 "<scope>.<name>" 格式指定。<scope> 是一个单词,指示变量的生命周期。<name> 部分在范围内,只能包含字符 'a-z'、'A-Z'、'0-9' 和 '_'。它在此范围内是唯一的,但不同范围中的相同名称可以用于引用不同的变量。 支持的范围包括: * proc:用于在整个进程生命周期内已知且全局可访问的变量。可以使用 CLI 中的 "get var" 和 "set var" 命令来操作 "proc" 变量。它们也可以通过 "set-var" 和 "set-var-fmt" 指令从 "global" 节设置。 * sess:用于在整个会话生命周期内已知的变量。"sess" 变量是会话私有的,从外部不可见,不与其他会话共享。 * txn:用于在整个事务生命周期内已知的变量。"txn" 变量是流私有的,从外部不可见,不与其他流共享。 * req:用于在特定流的请求处理期间已知的变量。"req" 变量从流创建开始可见,直到第一次服务器连接尝试。它们是流私有的,从外部不可见,不与其他流共享。 "req" 和 "res" 变量之间没有任何重叠。 * res:用于在特定流的响应处理期间已知的变量。"res" 变量从第一次服务器连接尝试开始可见,直到流销毁。它们是流私有的,从外部不可见,不与其他流共享。 "req" 和 "res" 变量之间没有任何重叠。 * check:用于在健康检查执行期间已知的变量。"check" 变量是健康检查私有的,从外部不可见,不与其他健康检查共享。它们可以使用专用的 "tcp-check" 或 "http-check" 指令设置。 根据上下文,可以使用引用当前流父级的额外范围: * psess:与 "sess" 相同,但使用父流的会话(如果有)。 * ptxn:与 "txn" 相同,但使用父流的事务(如果有)。 * preq:与 "req" 相同,但使用父流(如果有)。"preq" 变量仅在父流的请求处理期间可访问。 * pres:与 "res" 相同,但使用父流(如果有)。"pres" 变量仅在父流的响应处理期间可访问。 引用父流的范围从定义时起即可使用。大多数情况下,没有父流。但是,如果适用,将明确指定。目前,只能检索父流范围内定义的变量的值。无法设置或取消设置此类变量。 通常,子流在特定时刻为父流执行一些处理,并阻止父流继续进行,直到其完成操作。这意味着父流可能在请求处理或响应处理中间停止。因此,子流将无法访问某些范围。例如,如果请求需要由子流执行一些分析,则此子流将无法在 "pres" 范围中找到任何变量,因为父流没有在处理响应,因此其 "res" 范围中没有变量。 变量的内容是样本获取表达式评估的结果,它继承了该表达式的输出类型。当使用变量时,这很重要,因为其类型必须与其用法兼容。例如,在 "add()" 转换器中使用的包含字符串的变量必须可转换为有效的整数才能成功。当变量与静态值进行比较时,情况尤其如此。必须使用正确的匹配方法。
# 一个简单的 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 - crt-base - daemon - default-path - description - deviceatlas-json-file - deviceatlas-log-level - deviceatlas-properties-cookie - deviceatlas-separator - 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.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-udp-gso - tune.quic.frontend.glitches-threshold - tune.quic.frontend.max-idle-timeout - tune.quic.frontend.max-streams-bidi - 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.tx-pacing - tune.quic.zero-copy-fwd-send - tune.renice.runtime - tune.renice.startup - tune.rcvbuf.backend - tune.rcvbuf.client - tune.rcvbuf.frontend - tune.rcvbuf.server - tune.recv_enough - tune.ring.queues - tune.runqueue-depth - tune.sched.low-latency - tune.sndbuf.backend - tune.sndbuf.client - tune.sndbuf.frontend - tune.sndbuf.server - tune.stick-counters - tune.ssl.cachesize - tune.ssl.capture-buffer-size - tune.ssl.capture-cipherlist-size (deprecated) - tune.ssl.default-dh-param - tune.ssl.force-private-cache - tune.ssl.hard-maxrecord - tune.ssl.keylog - tune.ssl.lifetime - tune.ssl.maxrecord - tune.ssl.ssl-ctx-cache-size - tune.ssl.ocsp-update.maxdelay (deprecated) - tune.ssl.ocsp-update.mindelay (deprecated) - tune.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 - force-cfg-parser-pause - quiet - warn-blocked-traffic-after - zero-warning * HTTPClient - httpclient.resolvers.disabled - httpclient.resolvers.id - httpclient.resolvers.prefer - httpclient.retries - httpclient.ssl.ca-file - httpclient.ssl.verify - httpclient.timeout.connect
用于提供设备检测服务的 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 的情况下可用。
当使用 "ca-file"、"ca-verify-file" 或 "crl-file" 指令时使用相对路径时,分配一个默认目录来获取 SSL CA 证书和 CRL。在 "ca-file"、"ca-verify-file" 和 "crl-file" 中指定的绝对位置优先,并忽略 "ca-base"。
在降低权限之前,将当前目录更改为 <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 集。这意味着指定的线程永远不会在其他 CPU 上运行。"cpu-map" 指令为单个线程或线程组指定 CPU 集。 第一个参数是线程组范围,可选后跟线程集。这些范围具有以下格式: all | odd | even | number[-[number]] <number> 必须是 1 到 32 或 64 之间的数字,具体取决于机器的字大小。任何超出 'thread-groups' 的组 ID 和超出机器字大小的线程 ID 都将被忽略。所有线程号都相对于它们所属的组。可以使用由短划线 ('-') 分隔的两个此类数字来指定范围。也可以使用 "all" 一次指定所有线程,使用 "odd" 指定奇数,或使用 "even" 指定偶数,就像使用 "thread" bind 指令一样。 第二个和后续参数是 CPU 集。每个 CPU 集要么是一个唯一的数字(从第一个 CPU 的 0 开始),要么是由短划线 ('-') 分隔的两个此类数字的范围。这些 CPU 数字和范围可以通过逗号分隔重复,或者通过在同一行上传递更多范围作为新参数来重复。 在 Linux 和 BSD 操作系统之外,最大 CPU 索引可能限制为 31 或 63。 可以指定多个 "cpu-map" 指令,但当它们重叠时,每个 "cpu-map" 指令将替换前一个。范围可以部分定义。可以省略上限。在这种情况下,它会被替换为相应的最大值,具体取决于机器的字大小,可能是 32 或 64。 可以在线程集之前添加前缀 "auto:",让 HAProxy 通过递增线程和 CPU 集自动将一组线程绑定到 CPU。为了有效,两个集必须具有相同的大小。无论 CPU 集的声明顺序如何,它都将从最低绑定到最高绑定。不支持同时具有组和线程范围且带有 "auto:" 前缀。只支持一个范围,另一个必须是固定数字。 请注意,支持组范围是出于历史原因。如今,一个单独的数字表示一个线程组,如果不使用线程组,则必须为 1,并且指定线程范围或数字需要在其前面加上 "1/"(如果不使用线程组)。最后,"1" 严格等同于 "1/all",表示组中的所有线程。
cpu-map 1/all 0-3 # 将第一个组的所有线程绑定到 # 前 4 个 CPU cpu-map 1/1- 0- # 将替换为 "cpu-map 1/1-64 0-63" # 或 "cpu-map 1/1-32 0-31",具体取决于机器的 # 字大小。 # 所有这些行都将线程 1 绑定到 cpu 0,线程 2 绑定到 cpu 1 # 等等。 cpu-map auto:1/1-4 0-3 cpu-map auto:1/1-4 0-1 2-3 cpu-map auto:1/1-4 3 2 1 0 cpu-map auto:1/1-4 3,2,1,0 # 使用 all/odd/even 关键字将每个线程绑定到恰好一个 CPU cpu-map auto:1/all 0-63 cpu-map auto:1/even 0-31 cpu-map auto:1/odd 32-63 # 无效的 cpu-map,因为线程集和 CPU 集的大小不同。 cpu-map auto:1/1-4 0 # 无效 cpu-map auto:1/1 0-3 # 无效 # 将这 4 个组的 40 个线程映射到单个 CPU cpu-map auto:1/1-10 0-9 cpu-map auto:2/1-10 10-19 cpu-map auto:3/1-10 20-29 cpu-map auto:4/1-10 30-39 # 将 80 个线程映射到一个物理套接字,将另外 80 个线程映射到另一个套接字 # 而不强制分配。这些被分成 4 个组,因为没有 # 组可以有超过 64 个线程。 cpu-map 1/1-40 0-39,80-119 # node0, siblings 0 & 1 cpu-map 2/1-40 0-39,80-119 cpu-map 3/1-40 40-79,120-159 # node1, siblings 0 & 1 cpu-map 4/1-40 40-79,120-159
当使用 "crtfile" 或 "crt" 指令时使用相对路径时,分配一个默认目录来获取 SSL 证书。指定的绝对位置优先,并忽略 "crt-base"。
使进程 fork 到后台运行。这是推荐的操作模式。它等同于命令行参数 "-D"。它可以通过命令行参数 "-db" 禁用。此选项在 systemd 模式下被忽略。
默认情况下,HAProxy 从进程启动位置加载由相对路径指定的所有文件。在某些情况下,可能需要强制所有相对路径从不同位置开始,就好像进程是从这些位置启动一样。这就是此指令的目的。从技术上讲,它将在处理每个配置文件时执行对指定位置的临时 chdir(),并在处理完每个文件后返回原始目录。 它接受一个参数,指示加载路径不以斜杠 ('/') 开头的文件时使用的策略: - "current" 表示所有相对文件都从进程启动的目录加载;这是默认值。 - "config" 表示所有相对文件都应从包含配置文件的目录加载。更具体地说,如果配置文件包含斜杠 ('/'),则使用到最后一个斜杠的最长部分作为要更改的目录,否则使用当前目录。此模式便于将 map、errorfile、证书和 Lua 脚本捆绑为可重定位包。当加载多个配置文件时,目录会为每个文件更新。 - "parent" 表示所有相对文件都应从包含配置文件的目录的父目录加载。更具体地说,如果配置文件包含斜杠 ('/'),则将 ".." 附加到直到最后一个斜杠的最长部分作为要更改的目录,否则目录为 ".."。此模式便于将 map、errorfile、证书和 Lua 脚本捆绑为可重定位包,但每个部分位于不同的子目录中(例如 "config/"、"certs/"、"maps/" 等)。 - "origin" 表示所有相对文件都应从指定的(强制)路径加载。这可用于简化在系统上并行运行的不同 HAProxy 实例的管理,其中每个实例使用不同的前缀,但其余部分易于重定位。 每个 "default-path" 指令会立即替换任何前一个指令,并可能导致切换到不同的目录。虽然这应该始终导致所需的行为,但使用多个 default-path 指令确实不是一个好的做法,如果使用,策略应该在所有配置文件中保持一致。 警告:某些配置元素(例如 map 或证书)由其配置的路径唯一标识。通过使用可重定位布局,它们中的几个可能最终具有相同的唯一名称,从而难以在运行时更新它们,尤其是当从不同目录加载多个配置文件时。在采用相对路径之前,必须遵守严格的无冲突文件命名方案。一种健壮的方法可以是为所有文件名添加相应站点名称的前缀,或者在目录级别执行此操作。添加描述实例的文本。请注意,需要转义某些字符(例如 #),并且此文本将插入 HTML 页面中,因此您应避免使用“<”和“>”字符。
设置要由 API 加载的 DeviceAtlas JSON 数据文件的路径。该路径必须是一个有效的 JSON 数据文件,并且 HAProxy 进程可以访问。
设置 API 返回的信息级别。此指令是可选的,如果未设置,则默认为 0。
设置用于检测请求期间是否使用了 DeviceAtlas 客户端组件的客户端 cookie 名称。此指令是可选的,如果未设置,则默认为 DAPROPS。
设置 API 属性结果的字符分隔符。此指令是可选的,如果未设置,则默认为 |。
此声明必须在使用一些标记为已弃用的指令之前出现,以消除警告并确保配置文件不会被拒绝。并非所有已弃用的指令都受此影响,只有那些没有任何替代解决方案的指令。
此语句必须出现在使用标记为实验性的指令之前,否则配置文件将被拒绝。请注意,此选项涵盖的功能不能保证运行良好,并且在维护周期中可能会中断。在开发下一个版本时,开发人员将尽最大努力维护它们,并将部署任何合理的努力来避免破坏它们,但不能保证。由于这些原因,这些功能预计在下一个 LTS 版本发布后不会得到支持。想要尝试实验性功能的用户应该尽快升级以受益于该功能的改进。
允许使用外部代理执行健康检查。出于安全预防措施,默认情况下禁用此功能,即使启用,检查仍可能失败,除非也启用了 "insecure-fork-wanted"。如果启动的程序使用 setuid 可执行文件(它真的不应该),您可能还需要在 global 节中设置 "insecure-setuid-wanted"。 默认情况下,检查以干净的环境开始,其中只包含后端节中 "external-check" 命令中定义的变量。但是,有时可能需要保留环境,例如当复杂脚本从那里检索额外的路径或信息时。这可以通过附加 "preserve-env" 关键字来完成。在这种情况下,强烈建议不要运行 setuid 或作为特权用户运行,因为这会将检查程序暴露给潜在的攻击。 有关详细信息,请参阅 "option external-check" 和 "insecure-fork-wanted" 和 "insecure-setuid-wanted"。
设置进程将使用的最大文件描述符数的上限,无论系统限制如何。虽然 "ulimit-n" 和 "maxconn" 可用于强制执行某个值,但当未设置时,进程将受限于 "ulimit -n -H" 报告的 RLIMIT_NOFILE 设置的硬限制。但是一些现代操作系统现在允许在这里设置非常大的值(在 10 亿数量级),这对于常规使用会消耗过多的 RAM。 提供 fd-hard-limit 设置是为了对该限制强制执行可能较低的上限。这意味着当系统施加的限制低于 <number> 时,它将始终尊重系统施加的限制,但如果系统施加的限制更高,则将使用指定的值。默认情况下,fd-hard-limit 设置为 1048576。可以通过 DEFAULT_MAXFD 编译时变量更改此默认值,该变量可以用作最大(内核)系统限制,如果 RLIMIT_NOFILE 硬限制非常大。在 global 节中设置 fd-hard-limit 允许暂时覆盖构建时通过 DEFAULT_MAXFD 提供的值。 在下面的示例中,未指定其他设置,maxconn 值将自动适应 "fd-hard-limit" 和 RLIMIT_NOFILE 限制中的较低者: global # 尽可能多地使用 FD,但不超过 50000 fd-hard-limit 50000
将进程的组 ID 更改为 <number>。建议将组 ID 专用于 HAProxy 或一小组类似的守护程序。必须使用属于此组的用户或具有超级用户权限来启动 HAProxy。请注意,如果 HAProxy 是从具有补充组的用户启动的,则只有在具有超级用户权限的情况下才能删除这些组。另请参阅 "group" 和 "uid"。
定义 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 }
与 "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,因为未考虑编码块大小的累积大小。因此,上述规则不仅是安全问题,也是在处理由于与旧版本不兼容而可能面临通信问题的代理。
定义应用于标头名称 <from> 的大小写调整,当启用时,在将其发送到 HTTP/1 客户端或服务器之前,将其更改为 <to>。<from> 必须是小写,<from> 和 <to> 必须除了大小写之外没有区别。如果需要调整多个标头名称,可以重复此指令。不允许重复条目。 如果需要调整大量标头名称,使用 "h1-case-adjust-file" 可能会更方便。 请注意,除非在代理中指定了 "option h1-case-adjust-bogus-client" 或 "option h1-case-adjust-bogus-server",否则不会应用任何转换。 标头名称没有标准大小写,因为如 RFC7230 所述,它们不区分大小写。因此,应用程序必须以不区分大小写的方式处理它们。但是一些错误的应用程序违反了标准,错误地依赖于浏览器最常用的大小写。HTTP/2 使这个问题变得至关重要,因为所有标头名称都必须以小写形式交换,HAProxy 也遵循相同的约定。所有标头名称都以小写形式发送给客户端和服务器,无论 HTTP 版本如何。未能正确处理请求或响应的应用程序可能需要暂时使用此类解决方法来调整发送给它们标头名称,以便在应用程序修复期间使用。请注意,需要此类解决方法的应用程序可能容易受到内容走私攻击,必须绝对修复。
global h1-case-adjust content-length Content-Length
请参阅 "h1-case-adjust-file"、"option h1-case-adjust-bogus-client" 和 "option h1-case-adjust-bogus-server"。
定义一个文件,其中包含键/值对列表,用于在将某些标头名称发送到 HTTP/1 客户端或服务器之前调整其大小写。文件 <hdrs-file> 每行必须包含 2 个标头名称。第一个必须是小写,并且两者除了大小写之外没有区别。以 '#' 开头的行将被忽略,空行也是如此。前导和尾随的制表符和空格被去除。不允许重复条目。 请注意,除非在代理中指定了 "option h1-case-adjust-bogus-client" 或 "option h1-case-adjust-bogus-server",否则不会应用任何转换。 如果重复此指令,则只处理最后一个。如果需要调整大量标头名称,它是指令 "h1-case-adjust" 的替代方案。 请阅读与使用此功能相关的风险。请参阅 "h1-case-adjust"、"option h1-case-adjust-bogus-client" 和 "option h1-case-adjust-bogus-server"。
禁用向客户端宣布支持 h2 websockets。这可用于克服在实施相对较新的 RFC8441 时遇到问题的客户端,例如 Firefox 88。要允许客户端自动降级到 http/1.1 以进行 websocket 隧道,请在 bind 行上使用 "alpn" 指定 h2 支持,而无需显式 "proto" 关键字。如果此语句以前已激活,则可以通过在关键字前面加上 "no" 来禁用。
定义执行干净的软停止所允许的最长时间。
<time> 是实例在通过 SIGUSR1 信号接收到软停止时将保持活动的最长时间(默认为毫秒)。
这可用于确保即使在软停止期间连接保持打开(例如,在 tcp 模式下为代理设置了长超时),实例也会退出。它适用于 TCP 和 HTTP 模式。
global hard-stop-after 30s
切换每个协议的保护,禁止与使用特权端口作为其源端口的客户端进行通信。此端口范围根据 RFC 6335 定义。默认情况下,对 QUIC 协议启用保护,因为这种行为是可疑的,并可能被用作欺骗或 DNS/NTP 放大攻击。
替换、减少或扩展定义错误的状态码列表,这些错误被终止码和粘性表中的 "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_cnt" 计数器所考虑。失败的默认范围是 500 到 599,除了 501 和 505,它们可以由客户端触发,通常表示服务器处理请求失败。一些用户更喜欢在某些情况下排除某些代码,当已知它们不相关时,例如在某些 SOAP 环境中的 500,因为它在那里不表示服务器故障。语法与上面的 http-err-codes 完全相同。另请参阅 "http-err-codes" 和 "http_fail_cnt"。
By default HAProxy tries hard to prevent any thread and process creation after it starts. Doing so is particularly important when using Lua files of uncertain origin, and when experimenting with development versions which may still contain bugs whose exploitability is uncertain. And generally speaking it's good hygiene to make sure that no unexpected background activity can be triggered by traffic. But this prevents external checks from working, and may break some very specific Lua scripts which actively rely on the ability to fork. This option is there to disable this protection. Note that it is a bad idea to disable it, as a vulnerability in a library or within HAProxy itself will be easier to exploit once disabled. In addition, forking from Lua or anywhere else is not reliable as the forked process may randomly embed a lock set by another thread and never manage to finish an operation. As such it is highly recommended that this option is never used and that any workload requiring such a fork be reconsidered and moved to a safer solution (such as agents instead of external checks). This option supports the "no" prefix to disable it. This can also be activated with "-dI" on the haproxy command line.
HAProxy doesn't need to call executables at run time (except when using external checks which are strongly recommended against), and is even expected to isolate itself into an empty chroot. As such, there basically is no valid reason to allow a setuid executable to be called without the user being fully aware of the risks. In a situation where HAProxy would need to call external checks and/or disable chroot, exploiting a vulnerability in a library or in HAProxy itself could lead to the execution of an external program. On Linux it is possible to lock the process so that any setuid bit present on such an executable is ignored. This significantly reduces the risk of privilege escalation in such a situation. This is what HAProxy does by default. In case this causes a problem to an external check (for example one which would need the "ping" command), then it is possible to disable this protection by explicitly adding this directive in the global section. If enabled, it is possible to turn it back off by prefixing it with the "no" keyword.
Assigns a directory to load certificate chain for issuer completion. All files must be in PEM format. For certificates loaded with "crt" or "crt-list", if certificate chain is not included in PEM (also commonly known as intermediate certificate), HAProxy will complete chain if the issuer of the certificate corresponds to the first certificate of the chain loaded with "issuers-chain-path". A "crt" file with PrivateKey+Certificate+IntermediateCA2+IntermediateCA1 could be replaced with PrivateKey+Certificate. HAProxy will complete the chain if a file with IntermediateCA2+IntermediateCA1 is present in "issuers-chain-path" directory. All other certificates with the same issuer will share the chain in memory. The OCSP features are able to use the completed chain when no .issuer was used, or no chain was provided in the PEM.
Assigns a default directory to fetch SSL private keys from when a relative path is used with "key" directives. Absolute locations specified prevail and ignore "key-base". This option only works with a crt-store load line.
当 haproxy 编译时所依赖的 TLS/SSL 库不支持 QUIC(通常是 OpenSSL)时,必须使用此设置来显式启用 QUIC 监听器绑定。当 haproxy 编译时所依赖的 TLS/SSL 库支持 QUIC(例如 quictls)时,此设置无效。请注意,设置此项后不支持 QUIC 0-RTT。
设置本地实例的对等名称。如果指定了 "-L" 命令行参数或在 "peers" 部分定义之后使用,它将被忽略。在这种情况下,在配置解析期间将发出警告消息。此选项还将设置 HAPROXY_LOCALPEER 环境变量。另请参阅管理指南中的 "-L" 和下面的 "peers" 部分。
Adds a global syslog server. Several global servers can be defined. They will receive logs for starts and exits, as well as all logs from proxies configured with "log global". See "log" option for proxies for more details.
设置 syslog 报头中的 hostname 字段。如果设置了可选的 "string" 参数,则报头将设置为该字符串内容,否则使用系统的主机名。通常在不通过中间 syslog 服务器中继日志或仅为自定义日志中打印的主机名时使用。
将 syslog 头中的标签字段设置为此字符串。它默认为从命令行启动的程序名称,通常是 "haproxy"。有时,区分在同一主机上运行的多个进程可能很有用。另请参阅每个代理的 "log-tag" 指令。此全局指令在对所有线程可见的共享上下文中加载并执行一个 Lua 文件。在此类上下文中设置的任何变量对任何线程都可见。这是加载 Lua 程序的最简单和推荐的方法,但如果执行大量 Lua 调用,它将无法很好地扩展,因为一次只有一个线程可以在全局状态上运行。以这种方式加载的程序在 "core.thread" 变量中将始终看到 0。此指令可以多次使用。在 Lua 文件的主体中使用以下代码可以使用参数。不要忘记 Lua 数组的索引从 1 开始。在文件中声明的 "local" 变量在整个文件中可用,但在其他文件中不可用。 local args = table.pack(...)
This global directive loads and executes a Lua file into each started thread. Any global variable has a thread-local visibility so that each thread could see a different value. As such it is strongly recommended not to use global variables in programs loaded this way. An independent copy is loaded and initialized for each thread, everything is done sequentially and in the thread's numeric order from 1 to nbthread. If some operations need to be performed only once, the program should check the "core.thread" variable to figure what thread is being initialized. Programs loaded this way will run concurrently on all threads and will be highly scalable. This is the recommended way to load simple functions that register sample-fetches, converters, actions or services once it is certain the program doesn't depend on global variables. For the sake of simplicity, the directive is available even if only one thread is used and even if threads are disabled (in which case it will be equivalent to lua-load). This directive can be used multiple times. See lua-load for usage of args.
Prepends the given string followed by a semicolon to Lua's package.<type> variable. <type> must either be "path" or "cpath". If <type> is not given it defaults to "path". Lua's paths are semicolon delimited lists of patterns that specify how the `require` function attempts to find the source file of a library. Question marks (?) within a pattern will be replaced by module name. The path is evaluated left to right. This implies that paths that are prepended later will be checked earlier. As an example by specifying the following path: lua-prepend-path /usr/share/haproxy-lua/?/init.lua lua-prepend-path /usr/share/haproxy-lua/?.lua When `require "example"` is being called Lua will first attempt to load the /usr/share/haproxy-lua/example.lua script, if that does not exist the /usr/share/haproxy-lua/example/init.lua will be attempted and the default paths if that does not exist either. See https://lua.ac.cn/pil/8.1.html for the details within the Lua documentation.
主-从模式(Master-worker mode)。它等同于命令行参数“-W”。此模式将启动一个“主进程”,该进程在读取配置后会 fork 一个“工作进程”来处理流量。主进程用作进程管理器,将监控“工作进程”。使用此模式,您可以通过向主进程发送 SIGUSR2 信号直接重新加载 HAProxy。重新加载将要求主进程再次读取配置并 fork 一个新的工作进程。先前的工作进程将保留直到其作业结束。主-从模式与前台或守护进程模式兼容。默认情况下,如果工作进程因错误返回码退出,例如发生段错误,所有工作进程都将被杀死,主进程将退出。将此行为与 systemd 单元文件中的 Restart=on-failure 结合使用,以重新启动整个进程,是很方便的。如果您不希望此行为,必须使用关键字“no-exit-on-failure”。另请参阅管理指南中的“-W”。
在主-从模式下,此选项限制了工作进程可以承受的重载次数。如果工作进程在重载后没有退出,一旦其重载次数大于此数字,该工作进程将收到一个 SIGTERM 信号。此选项有助于控制工作进程的数量。另请参阅管理指南中的“show proc”。
此设置仅在内置线程支持时可用。它使 HAProxy 在 <number> 个线程上运行。“nbthread” 在 HAProxy 在前台启动时也有效。在某些支持 CPU 亲和性的平台上,默认的 “nbthread” 值会自动设置为启动时进程绑定的 CPU 数量。这意味着线程数可以轻松地从调用进程中使用 "taskset" 或 "cpuset" 等命令进行调整。否则,此值默认为 1。默认值在 "haproxy -vv" 的输出中报告。请注意,此处设置或自动检测的值受 “thread-hard-limit”(如果设置)设置的限制。
禁用 QUIC 传输协议。所有 QUIC 监听器仍将被创建,但它们不会绑定其地址。因此,haproxy 将不会处理任何 QUIC 流量。另请参阅“quic_enabled”样本获取。
如果在 NUMA 感知平台上运行,HAProxy 会在启动时检查机器的 CPU 拓扑。如果检测到多插槽机器,则会自动计算亲和性以在单个节点的 CPU 上运行。这样做是为了避免因插槽间总线延迟而导致的性能损失。但是,如果在特定架构上应用的绑定不是最优的,可以使用 'no numa-cpu-mapping' 语句禁用它。如果配置中存在 nbthread 语句,或者已指定进程的亲和性(例如通过 'cpu-map' 指令或 taskset 实用程序),则此自动绑定也不会应用。
完全禁用 HAProxy 中的 ocsp-update。任何 ocsp-update 配置都将被忽略。默认为 "off"。有关自动更新机制的更多信息,请参阅选项 "ocsp-update"。
允许为 OCSP 更新使用 HTTP 代理。这仅适用于 HTTP,不支持 HTTPS。此选项将允许 OCSP 更新器在请求中向代理发送绝对 URI。
设置同一 OCSP 响应两次自动更新之间的最大间隔。此时间以秒表示,默认为 3600(1 小时)。它必须设置为高于 “ocsp-update.mindelay” 的值。有关自动更新机制的更多信息,请参阅选项 “ocsp-update”。
设置同一 OCSP 响应两次自动更新之间的最小间隔。此时间以秒表示,默认为 300(5 分钟)。它对于没有明确过期时间的 OCSP 响应特别有用。它必须设置为低于 “ocsp-update.maxdelay” 的值。有关自动更新机制的更多信息,请参阅选项 “ocsp-update”。
为配置中使用的所有证书设置默认的 ocsp-update 模式。此全局选项可以被 crt-list 的 “ocsp-update” 选项覆盖。此选项默认设置为 "off"。有关自动更新机制的更多信息,请参阅选项 “ocsp-update”。
在守护进程模式下,将所有守护进程的 PID 写入文件 <pidfile>;在主-工作者模式下,将主进程的 PID 写入文件 <pidfile>。此选项等同于 "-p" 命令行参数。该文件必须对启动进程的用户可访问。另请参阅 "daemon" 和 "master-worker"。
PROXY 协议 v2 实现中的一个错误存在于 HAProxy 2.1 之前的版本中,导致它为健康检查发出 PROXY 命令而不是 LOCAL 命令。这问题特别微小,但会混淆一些服务器的日志。遗憾的是,这个错误发现得很晚,并揭示出一些可能只针对 HAProxy 测试其 PROXY 协议实现的服务器无法正确处理 LOCAL 命令,并在 HAProxy 检查它们时永久保持在 "down" 状态。当这种情况发生时,可以启用此全局选项以恢复到旧的(错误的)行为,直到联系受影响组件的供应商并修复它们。此选项默认禁用,并作用于所有具有 "send-proxy-v2" 语句的服务器。
将环境变量 <name> 设置为值 <value>。如果该变量已存在,则不会被覆盖。更改会立即生效,以便配置文件中的下一行可以看到新值。另请参阅 "setenv"、"resetenv" 和 "unsetenv"。
执行一次性打开最大文件描述符的操作,从而预分配内核的数据结构。这可以防止当 nbthread>1 且 HAProxy 打开一个需要内核扩展其数据结构的文件描述符时出现的短暂暂停。
删除除参数中指定的环境变量之外的所有环境变量。它允许在使用 setenv 或 unsetenv 设置新值之前,使用一个干净受控的环境。请注意,一些内部函数可能会使用某些环境变量,例如时间操作函数,以及 OpenSSL 甚至外部检查。此命令必须极其小心使用,并且只能在完全验证后使用。更改会立即生效,因此配置文件中的下一行将看到新的环境。另请参阅 “setenv”、“presetenv” 和 “unsetenv”。
指定目录前缀,该前缀将附加在所有不以“/”开头的服务器状态文件名前面。另请参阅 "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"。
This option is better left disabled by default and enabled only upon a developer's request. If it has been enabled, it may still be forcibly disabled by prefixing it with the "no" keyword. It has no impact on performance nor stability but will try hard to re-enable core dumps that were possibly disabled by file size limitations (ulimit -f), core size limitations (ulimit -c), or "dumpability" of a process after changing its UID/GID (such as /proc/sys/fs/suid_dumpable on Linux). Core dumps might still be limited by the current directory's permissions (check what directory the file is started from), the chroot directory's permission (it may be needed to temporarily disable the chroot directive or to move it to a dedicated writable location), or any other system-specific constraint. For example, some Linux flavours are notorious for replacing the default core file with a path to an executable not even installed on the system (check /proc/sys/kernel/core_pattern). Often, simply writing "core", "core.%p" or "/var/log/core/core.%p" addresses the issue. When trying to enable this option waiting for a rare issue to re-appear, it's often a good idea to first try to obtain such a dump by issuing, for example, "kill -11" to the "haproxy" process and verify that it leaves a core where expected when dying.
将进程范围变量“<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)
将进程范围变量“<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"
Sets a list of capabilities that must be preserved when starting and running either as a non-root user (uid > 0), or when starting with uid 0 (root) and switching then to a non-root. By default all permissions are lost by the uid switch, but some are often needed when trying to connect to a server from a foreign address during transparent proxying, or when binding to a port below 1024, e.g. when using "tune.quic.socket-owner connection", resulting in setups running entirely under uid 0. Setting capabilities generally is a safer alternative, as only the required capabilities will be preserved. The feature is OS-specific and only enabled on Linux when USE_LINUX_CAP=1 is set at build time. The list of supported capabilities also depends on the OS and is enumerated by the error message displayed when an invalid capability name or an empty one is passed. Multiple capabilities may be passed, delimited by commas. Among those commonly used, "cap_net_raw" allows to transparently bind to a foreign address, and "cap_net_bind_service" allows to bind to a privileged port and may be used by QUIC. If the process is started and run under the same non-root user, needed capabilities should be set on haproxy binary file with setcap along with this keyword. For more details about setting capabilities on haproxy binary, please see chapter 13.1 Linux capabilities support in the Management guide.
global setcap cap_net_bind_service,cap_net_admin
将环境变量 <name> 设置为值 <value>。如果该变量存在,则会被覆盖。更改会立即生效,因此配置文件中的下一行将看到新的值。另请参阅 “presetenv”、“resetenv” 和 “unsetenv”。
This setting is only available when support for OpenSSL was built in. It sets the default string describing the list of cipher algorithms ("cipher suite") that are negotiated during the SSL/TLS handshake up to TLSv1.2 for all "bind" lines which do not explicitly define theirs. The format of the string is defined in "man 1 ciphers" from OpenSSL man pages. For background information and recommendations see e.g. (https://wiki.mozilla.org/Security/Server_Side_TLS) and (https://mozilla.github.io/server-side-tls/ssl-config-generator/). For TLSv1.3 cipher configuration, please check the "ssl-default-bind-ciphersuites" keyword. Please check the "bind" keyword for more information.This setting is only available when support for OpenSSL was built in and OpenSSL 1.1.1 or later was used to build HAProxy. It sets the default string describing the list of cipher algorithms ("cipher suite") that are negotiated during the TLSv1.3 handshake for all "bind" lines which do not explicitly define theirs. The format of the string is defined in "man 1 ciphers" from OpenSSL man pages under the section "ciphersuites". For cipher configuration for TLSv1.2 and earlier, please check the "ssl-default-bind-ciphers" keyword. This setting might accept TLSv1.2 ciphersuites however this is an undocumented behavior and not recommended as it could be inconsistent or buggy. The default TLSv1.3 ciphersuites of OpenSSL are: "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256" TLSv1.3 only supports 5 ciphersuites: - 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 Please check the "bind" keyword for more information.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
This setting is only available when support for OpenSSL was built in. It sets the default string describing the list of signature algorithms related to client authentication for all "bind" lines which do not explicitly define theirs. The format of the string is a colon-delimited list of signature algorithms. Each signature algorithm can use one of two forms: TLS1.3 signature scheme names ("rsa_pss_rsae_sha256") or the public key algorithm + digest form ("ECDSA+SHA256"). A list can contain both forms. For more information on the format, see SSL_CTX_set1_client_sigalgs(3). A list of signature algorithms is also available in RFC8446 section 4.2.3 and in OpenSSL in the ssl/t1_lib.c file. This setting is not applicable to TLSv1.1 and earlier versions of the protocol as the signature algorithms aren't separately negotiated in these versions. It is not recommended to change this setting unless compatibility with a middlebox is required.
此设置仅在编译时内置 OpenSSL 支持时可用。它设置了在 SSL/TLS 握手期间使用 ECDHE 协商的椭圆曲线算法列表(“曲线套件”)的默认字符串。字符串的格式是以冒号分隔的曲线名称列表。有关更多信息,请检查 "bind" 关键字。This setting is only available when support for OpenSSL was built in. It sets default ssl-options to force on all "bind" lines. Please check the "bind" keyword to see available options.
global ssl-default-bind-options ssl-min-ver TLSv1.0 no-tls-tickets
This setting is only available when support for OpenSSL was built in. It sets the default string describing the list of signature algorithms that are negotiated during the TLSv1.2 and TLSv1.3 handshake for all "bind" lines which do not explicitly define theirs. The format of the string is a colon-delimited list of signature algorithms. Each signature algorithm can use one of two forms: TLS1.3 signature scheme names ("rsa_pss_rsae_sha256") or the public key algorithm + digest form ("ECDSA+SHA256"). A list can contain both forms. For more information on the format, see SSL_CTX_set1_sigalgs(3). A list of signature algorithms is also available in RFC8446 section 4.2.3 and in OpenSSL in the ssl/t1_lib.c file. This setting is not applicable to TLSv1.1 and earlier versions of the protocol as the signature algorithms aren't separately negotiated in these versions. It is not recommended to change this setting unless compatibility with a middlebox is required.
This setting is only available when support for OpenSSL was built in. It sets the default string describing the list of cipher algorithms that are negotiated during the SSL/TLS handshake up to TLSv1.2 with the server, for all "server" lines which do not explicitly define theirs. The format of the string is defined in "man 1 ciphers" from OpenSSL man pages. For background information and recommendations see e.g. (https://wiki.mozilla.org/Security/Server_Side_TLS) and (https://mozilla.github.io/server-side-tls/ssl-config-generator/). For TLSv1.3 cipher configuration, please check the "ssl-default-server-ciphersuites" keyword. Please check the "server" keyword for more information.
This setting is only available when support for OpenSSL was built in and OpenSSL 1.1.1 or later was used to build HAProxy. It sets the default string describing the list of cipher algorithms that are negotiated during the TLSv1.3 handshake with the server, for all "server" lines which do not explicitly define theirs. The format of the string is defined in "man 1 ciphers" from OpenSSL man pages under the section "ciphersuites". For cipher configuration for TLSv1.2 and earlier, please check the "ssl-default-server-ciphers" keyword. Please check the "server" keyword for more information.
This setting is only available when support for OpenSSL was built in. It sets the default string describing the list of signature algorithms related to client authentication for all "server" lines which do not explicitly define theirs. The format of the string is a colon-delimited list of signature algorithms. Each signature algorithm can use one of two forms: TLS1.3 signature scheme names ("rsa_pss_rsae_sha256") or the public key algorithm + digest form ("ECDSA+SHA256"). A list can contain both forms. For more information on the format, see SSL_CTX_set1_client_sigalgs(3). A list of signature algorithms is also available in RFC8446 section 4.2.3 and in OpenSSL in the ssl/t1_lib.c file. This setting is not applicable to TLSv1.1 and earlier versions of the protocol as the signature algorithms aren't separately negotiated in these versions. It is not recommended to change this setting unless compatibility with a middlebox is required.
此设置仅在编译时内置 OpenSSL 支持时可用。它设置了在 SSL/TLS 握手期间使用 ECDHE 协商的椭圆曲线算法列表(“曲线套件”)的默认字符串。字符串的格式是以冒号分隔的曲线名称列表。有关更多信息,请检查 "server" 关键字。This setting is only available when support for OpenSSL was built in. It sets default ssl-options to force on all "server" lines. Please check the "server" keyword to see available options.
This setting is only available when support for OpenSSL was built in. It sets the default string describing the list of signature algorithms that are negotiated during the TLSv1.2 and TLSv1.3 handshake for all "server" lines which do not explicitly define theirs. The format of the string is a colon-delimited list of signature algorithms. Each signature algorithm can use one of two forms: TLS1.3 signature scheme names ("rsa_pss_rsae_sha256") or the public key algorithm + digest form ("ECDSA+SHA256"). A list can contain both forms. For more information on the format, see SSL_CTX_set1_sigalgs(3). A list of signature algorithms is also available in RFC8446 section 4.2.3 and in OpenSSL in the ssl/t1_lib.c file. This setting is not applicable to TLSv1.1 and earlier versions of the protocol as the signature algorithms aren't separately negotiated in these versions. It is not recommended to change this setting unless compatibility with a middlebox is required.
This setting is only available when support for OpenSSL was built in. It sets the default DH parameters that are used during the SSL/TLS handshake when ephemeral Diffie-Hellman (DHE) key exchange is used, for all "bind" lines which do not explicitly define theirs. It will be overridden by custom DH parameters found in a bind certificate file if any. If custom DH parameters are not specified either by using ssl-dh-param-file or by setting them directly in the certificate file, DHE ciphers will not be used, unless tune.ssl.default-dh-param is set. In this latter case, pre-defined DH parameters of the specified size will be used. Custom parameters are known to be more secure and therefore their use is recommended. Custom DH parameters may be generated by using the OpenSSL command "openssl dhparam <size>", where size should be at least 2048, as 1024-bit DH parameters should not be considered secure anymore.此设置仅在内置 OpenSSL 支持且 OpenSSL 版本至少为 3.0 时可用。它允许定义在提供程序中获取算法时使用的默认属性字符串。它的行为方式与 openssl propquery 选项相同,并遵循相同的语法(在 https://www.openssl.org/docs/man3.0/man7/property.html 中描述)。例如,如果您加载了两个提供程序,foo 和默认提供程序,则 propquery “?provider=foo” 允许默认选择由 foo 提供程序提供的算法实现,如果找不到,则回退到默认提供程序的实现。
This setting is only available when support for OpenSSL was built in and when OpenSSL's version is at least 3.0. It allows to load a provider during init. If loading is successful, any capabilities provided by the loaded provider might be used by HAProxy. Multiple 'ssl-provider' options can be specified in a configuration file. The providers will be loaded in their order of appearance. Please note that loading a provider explicitly prevents OpenSSL from loading the 'default' provider automatically. OpenSSL also allows to define the providers that should be loaded directly in its configuration file (openssl.cnf for instance) so it is not necessary to use this 'ssl-provider' option to load providers. The "show ssl providers" CLI command can be used to show all the providers that were successfully loaded. The default search path of OpenSSL provider can be found in the output of the "openssl version -a" command. If the provider is in another directory, you can set the OPENSSL_MODULES environment variable, which takes the directory where your provider can be found. See also "ssl-propquery" and "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”。
This setting alters the way HAProxy will look for unspecified files during the loading of the SSL certificates. This option applies to certificates associated to "bind" lines as well as "server" lines but some of the extra files will not have any functional impact for "server" line certificates. By default, HAProxy discovers automatically a lot of files not specified in the configuration, and you may want to disable this behavior if you want to optimize the startup time. "none": Only load the files specified in the configuration. Don't try to load a certificate bundle if the file does not exist. In the case of a directory, it won't try to bundle the certificates if they have the same basename. "all": This is the default behavior, it will try to load everything, bundles, sctl, ocsp, issuer, key. "bundle": When a file specified in the configuration does not exist, HAProxy will try to load a "cert bundle". Certificate bundles are only managed on the frontend side and will not work for backend certificates. Starting from HAProxy 2.3, the bundles are not loaded in the same OpenSSL certificate store, instead it will loads each certificate in a separate store which is equivalent to declaring multiple "crt". OpenSSL 1.1.1 is required to achieve this. Which means that bundles are now used only for backward compatibility and are not mandatory anymore to do an hybrid RSA/ECC bind configuration. To associate these PEM files into a "cert bundle" that is recognized by HAProxy, they must be named in the following way: All PEM files that are to be bundled must have the same base name, with a suffix indicating the key type. Currently, three suffixes are supported: rsa, dsa and ecdsa. For example, if www.example.com has two PEM files, an RSA file and an ECDSA file, they must be named: "example.pem.rsa" and "example.pem.ecdsa". The first part of the filename is arbitrary; only the suffix matters. To load this bundle into HAProxy, specify the base name only
bind :8443 ssl crt example.pem
Note that the suffix is not given to HAProxy; this tells HAProxy to look for a cert bundle. HAProxy will load all PEM files in the bundle as if they were configured separately in several "crt". The bundle loading does not have an impact anymore on the directory loading since files are loading separately. On the CLI, bundles are seen as separate files, and the bundle extension is required to commit them. OCSP files (.ocsp), issuer files (.issuer), Certificate Transparency (.sctl) as well as private keys (.key) are supported with multi-cert bundling. "sctl": Try to load "<basename>.sctl" for each crt keyword. If provided for a backend certificate, it will be loaded but will not have any functional impact. "ocsp": Try to load "<basename>.ocsp" for each crt keyword. If provided for a backend certificate, it will be loaded but will not have any functional impact. "issuer": Try to load "<basename>.issuer" if the issuer of the OCSP file is not provided in the PEM file. If provided for a backend certificate, it will be loaded but will not have any functional impact. "key": If the private key was not provided by the PEM file, try to load a file "<basename>.key" containing a private key. The default behavior is "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 验证的默认行为。如果指定为 'none',则不验证服务器证书。默认值为 'required',除非使用命令行选项 '-dV' 强制指定。
自签发 CA,即 x509 根 CA,是证书链验证的锚点:作为服务器发送它是无用的,客户端必须拥有它。标准配置需要不在 PEM 文件中包含此类 CA。此选项允许您在 PEM 文件中保留此类 CA 而不将其发送给客户端。用例是为 ocsp 提供颁发者,而无需“.issuer”文件,并能够与“issuers-chain-path”共享它。这涉及所有没有中间证书的证书。对于 BoringSSL 来说是无用的,.issuer 被忽略,因为 ocsp 位不需要它。至少需要 OpenSSL 1.0.2。
默认情况下,统计套接字限制为 10 个并发连接。可以使用 "stats maxconn" 更改此值。
将 UNIX 套接字绑定到 <path> 或将 TCPv4/v6 地址绑定到 <address:port>。对此套接字的连接将返回各种统计信息输出,甚至允许发出一些命令来更改某些运行时设置。有关更多详细信息,请参阅管理指南的 第 9.3 节 “Unix 套接字命令”。支持 "bind" 行支持的所有参数,例如限制某些用户或其访问权限。有关更多信息,请参阅 第 5.1 节。
统计套接字的默认超时时间设置为 10 秒。可以使用 "stats timeout" 更改此值。该值必须以毫秒为单位传递,或者带有时间单位后缀,如 { us, ms, s, m, h, d }。
生成的 haproxy stats-file 的路径。启动时,haproxy 会将值预加载到其内部计数器中。使用 CLI 命令 “dump stats-file” 生成此类 stats-file。有关更多详细信息,请参阅管理手册。
当 setrlimit 失败时,使进程在启动时失败。HAProxy 会根据计算结果尝试设置最佳的 setrlimit。如果失败,它将发出警告。此选项旨在保证当这些限制失败时 HAProxy 明确失败。它默认启用。仍可通过在其前添加“no”关键字来强制禁用它。
此设置仅在内置线程支持时可用。它枚举了将组成线程组 <group> 的线程列表。线程号和组号从 1 开始。线程范围可以一次使用单个线程号定义,也可以通过指定由破折号“-”分隔的下限和上限来定义(例如 “1-16”)。未分配的线程将自动分配给未分配的线程组,而使用此指令定义的线程组将永远不会接收超过定义的线程数。多次定义同一组会用新的定义覆盖以前的定义。另请参阅 “nbthread” 和 “thread-groups”。
此设置仅在内置线程支持时可用。它使 HAProxy 将其线程分成 <number> 个独立的组。目前,默认值为 1。线程组可以减少线程之间的共享以限制争用,但需要一些额外的配置工作。这也是使用超过 64 个线程的唯一方法,因为每个组最多可以配置 64 个线程。最大组数在编译时配置,默认为 16。另请参阅 “nbthread”。
此设置用于强制限制线程数,无论是检测到的还是配置的。这在线程数是自动检测的操作系统上特别有用,其中在通用和可移植的配置中希望线程数低于 CPU 数。实际上,虽然 “nbthread” 强制的线程数如果高于可用 CPU 数将导致警告和性能不佳,但 thread-hard-limit 只会限制最大值,并自动将线程数限制为不高于此值,但不会提高较低的值。如果 “nbthread” 被强制设置为更高的值,则 thread-hard-limit 生效,并发出警告,以便可以修复配置异常。默认情况下没有限制。另请参阅 “nbthread”。
Changes the process's user ID to <number>. It is recommended that the user ID is dedicated to HAProxy or to a small set of similar daemons. HAProxy must be started with superuser privileges in order to be able to switch to another one. See also "gid" and "user".
将每个进程的文件描述符最大数量设置为 <number>。默认情况下,它是自动计算的,因此建议不要使用此选项。如果目的只是限制文件描述符的数量,最好改用 “fd-hard-limit”。请注意,在此自动资源计算中未考虑动态服务器。如果使用大量动态服务器,可能需要手动指定此值。
Fixes common settings to UNIX listening sockets declared in "bind" statements. This is mainly used to simplify declaration of those UNIX sockets and reduce the risk of errors, since those settings are most commonly required but are also process-specific. The <prefix> setting can be used to force all socket path to be relative to that directory. This might be needed to access another component's chroot. Note that those paths are resolved before HAProxy chroots itself, so they are absolute. The <mode>, <user>, <uid>, <group> and <gid> all have the same meaning as their homonyms used by the "bind" statement. If both are specified, the "bind" statement has priority, meaning that the "unix-bind" settings may be seen as process-wide default settings.
删除参数中指定的环境变量。这对于隐藏某些操作期间偶尔从用户环境中继承的一些敏感信息很有用。不存在的变量会被静默忽略,因此操作后可以确定这些变量都不再存在。更改会立即生效,因此配置文件中的下一行将看不到这些变量。另请参阅 “setenv”、“presetenv” 和 “resetenv”。
Similar to "uid" but uses the UID of user name <user name> from /etc/passwd. See also "uid" and "group".
只允许字母、数字、连字符和下划线,与 DNS 名称类似。此语句在 HA 配置中很有用,其中两个或多个进程或服务器共享相同的 IP 地址。通过在所有节点上设置不同的节点名称,可以轻松地立即发现哪个服务器正在处理流量。
设置 WURFL User-Agent 缓存大小。为了更快地查找,已处理的用户代理会保存在 LRU 缓存中:- “0”:不使用缓存。- <size>:lru 缓存的大小(以元素为单位)。请注意,此选项仅在 HAProxy 编译时带有 USE_WURFL=1 时可用。
WURFL 数据文件的路径,用于提供设备检测服务。HAProxy 应具有相关权限才能访问该文件。请注意,此选项仅在 HAProxy 编译时带有 USE_WURFL=1 时可用。
A space-delimited list of WURFL capabilities, virtual capabilities, property names we plan to use in injected headers. A full list of capability and virtual capability names is available on the Scientiamobile website : https://www.scientiamobile.com/wurflCapability Valid WURFL properties are: - wurfl_id Contains the device ID of the matched device. - wurfl_root_id Contains the device root ID of the matched device. - wurfl_isdevroot Tells if the matched device is a root device. Possible values are "TRUE" or "FALSE". - wurfl_useragent The original useragent coming with this particular web request. - wurfl_api_version Contains a string representing the currently used Libwurfl API version. - wurfl_info A string containing information on the parsed wurfl.xml and its full path. - wurfl_last_load_time Contains the UNIX timestamp of the last time WURFL has been loaded successfully. - wurfl_normalized_useragent The normalized useragent. Please note that this option is only available when HAProxy has been compiled with USE_WURFL=1.
一个将用于在包含 WURFL 结果的响应头中分隔值的字符。如果未设置,则默认使用逗号(‘,’)。请注意,此选项仅在 HAProxy 编译时带有 USE_WURFL=1 时可用。
WURFL 补丁文件路径列表。请注意,补丁在启动期间加载,因此在 chroot 之前。请注意,此选项仅在 HAProxy 编译时带有 USE_WURFL=1 时可用。
In some situations, especially when dealing with low latency on processors supporting a variable frequency or when running inside virtual machines, each time the process waits for an I/O using the poller, the processor goes back to sleep or is offered to another VM for a long time, and it causes excessively high latencies. This option provides a solution preventing the processor from sleeping by always using a null timeout on the pollers. This results in a significant latency reduction (30 to 100 microseconds observed) at the expense of a risk to overheat the processor. It may even be used with threads, in which case improperly bound threads may heavily conflict, resulting in a worse performance and high values for the CPU stolen fields in "show info" output, indicating which threads are misconfigured. It is important not to let the process run on the same processor as the network interrupts when this option is used. It is also better to avoid using it on multiple CPU threads sharing the same core. This option is disabled by default. If it has been enabled, it may still be forcibly disabled by prefixing it with the "no" keyword. It is ignored by the "select" and "poll" pollers. This option is automatically disabled on old processes in the context of seamless reload; it avoids too much cpu conflicts when multiple processes stay around for some time waiting for the end of their current connections.
默认情况下,HAProxy 会尝试将健康检查的开始时间分散在服务器场中所有服务器的最小健康检查间隔内。其原则是避免对在同一台服务器上运行的服务进行密集冲击。但是当使用大的检查间隔(10 秒或更长)时,服务器场中的最后一个服务器需要一些时间才能开始被测试,这可能是一个问题。此参数用于强制规定第一次和最后一次检查之间的延迟上限,即使服务器的检查间隔较大。当服务器以较短的间隔运行时,它们的间隔仍将得到尊重。
设置 HAProxy 在停止新请求的压缩或降低当前请求的压缩级别之前可以达到的最大 CPU 使用率。它的工作方式类似于“maxcomprate”,但测量的是 CPU 使用率而不是传入数据带宽。该值以 HAProxy 使用的 CPU 百分比表示。值 100 表示禁用限制。默认值为 100。设置较低的值将防止压缩工作减慢整个进程的速度并引入高延迟。
将每个进程的最大输入压缩速率设置为 <number> 千字节/秒。对于每个流,如果达到最大值,压缩级别将在流期间降低。如果在流开始时达到最大值,则该流将完全不压缩。如果未达到最大值,压缩级别将增加到 tune.comp.maxlevel。值为零表示没有限制,这是默认值。
Sets the maximum per-process number of concurrent connections to <number>. It is equivalent to the command-line argument "-n". The value provided in command-line argument via "-n" takes the precedence over the maxconn value set in the global section. Haproxy process could be also compiled with SYSTEM_MAXCONN compile-time variable, which is served in this case as the system maxconn maximum. Again, the command-line "-n" argument allows at runtime to bypass SYSTEM_MAXCONN limit, if set. Proxies will stop accepting connections when maxconn is reached. The process soft file descriptor limit (could be obtained with "ulimit -n" command) is automatically adjusted according to provided maxconn. See also "ulimit-n". Note: the "select" poller cannot reliably use more than 1024 file descriptors on some platforms. If your platform only supports select and reports "select FAILED" on startup, you need to reduce the maxconn until it works (slightly below 500 in general). If maxconn value is not set, it will be automatically calculated based on the current file descriptors limits, reported by the "ulimit -nH" command (we take the maximum between the hard and soft values), then automatic value will be possibly reduced by "fd-hard-limit" and by memory limit, if the latter was enforced via "-m" command line option. Automatic value is also dependent from the buffer size, memory allocated to compression, SSL cache size, and the use or not of SSL and the associated maxsslconn (which can also be automatic).
将每个进程每秒的最大连接数设置为 <number>。当达到此限制时,代理将停止接受连接。它可以用来限制全局容量,而不考虑每个前端的容量。需要注意的是,这只能用作服务保护措施,因为当达到限制时,前端之间不一定会公平分配,所以最好也为每个前端限制一个接近其预期份额的值。此外,降低 tune.maxaccept 可以提高公平性。
将每个进程的最大管道数设置为 <number>。目前,管道仅由基于内核的 tcp 拼接使用。由于一个管道包含两个文件描述符,"ulimit-n" 值将相应增加。默认值为 maxconn/4,这对于大多数重度使用情况来说似乎已经足够了。拼接代码动态分配和释放管道,并且可以回退到标准复制,因此将此值设置得太低可能只会影响性能。
将每个进程每秒的最大会话数设置为 <number>。当达到此限制时,代理将停止接受连接。它可以用来限制全局容量,而不考虑每个前端的容量。需要注意的是,这只能用作服务保护措施,因为当达到限制时,前端之间不一定会公平分配,所以最好也为每个前端限制一个接近其预期份额的值。此外,降低 tune.maxaccept 可以提高公平性。
Sets the maximum per-process number of concurrent SSL connections to <number>. By default there is no SSL-specific limit, which means that the global maxconn setting will apply to all connections. Setting this limit avoids having openssl use too much memory and crash when malloc returns NULL (since it unfortunately does not reliably check for such conditions). Note that the limit applies both to incoming and outgoing connections, so one connection which is deciphered then ciphered accounts for 2 SSL connections. If this value is not set, but a memory limit is enforced, this value will be automatically computed based on the memory limit, maxconn, the buffer size, memory allocated to compression, SSL cache size, and use of SSL in either frontends, backends or both. If neither maxconn nor maxsslconn are specified when there is a memory limit, HAProxy will automatically adjust these values so that 100% of the connections can be made over SSL with no risk, and will consider the sides where it is enabled (frontend, backend, both).
将每个进程每秒的最大 SSL 会话数设置为 <number>。当达到此限制时,SSL 侦听器将停止接受连接。它可以用来限制全局 SSL CPU 使用率,而不考虑每个前端的容量。需要注意的是,这只能用作服务保护措施,因为当达到限制时,前端之间不一定会公平分配,所以最好也为每个前端限制一个接近其预期份额的值。同样重要的是要注意,会话是在进入 SSL 堆栈之前而不是之后计算的,这也保护了堆栈免受不良握手的影响。此外,降低 tune.maxaccept 可以提高公平性。
设置 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"。
启用('on')或禁用('off')按函数的内存分析。这将保留进程中任何地方(包括库)的 malloc/calloc/realloc/free 调用的使用统计信息,这些信息将通过 CLI 上的“show profiling”命令报告。这主要用于当观察到无法通过池信息解释的异常内存使用,并且需要其他信息时。性能损失通常在 1% 左右,在高度线程化的机器上可能会更高一些,因此通常适合在生产环境中使用。同样的功能也可以在运行时通过 CLI 上的“set profiling memory”命令实现,请查阅管理手册。
Enables ('on') or disables ('off') per-task CPU profiling. When set to 'auto' the profiling automatically turns on a thread when it starts to suffer from an average latency of 1000 microseconds or higher as reported in the "avg_loop_us" activity field, and automatically turns off when the latency returns below 990 microseconds (this value is an average over the last 1024 loops so it does not vary quickly and tends to significantly smooth short spikes). It may also spontaneously trigger from time to time on overloaded systems, containers, or virtual machines, or when the system swaps (which must absolutely never happen on a load balancer). CPU profiling per task can be very convenient to report where the time is spent and which requests have what effect on which other request. Enabling it will typically affect the overall's performance by less than 1%, thus it is recommended to leave it to the default 'auto' value so that it only operates when a problem is identified. This feature requires a system supporting the clock_gettime(2) syscall with clock identifiers CLOCK_MONOTONIC and CLOCK_THREAD_CPUTIME_ID, otherwise the reported time will be zero. This option may be changed at run time using "set profiling" on the CLI.有时,希望避免以精确的间隔向服务器发送代理和健康检查,例如当许多逻辑服务器位于同一物理服务器上时。借助此参数,可以在检查间隔中添加 0 到 +/- 50% 之间的随机性。2 到 5 之间的值似乎效果很好。默认值仍为 0。
Sets the OpenSSL engine to <name>. List of valid values for <name> may be obtained using the command "openssl engine". This statement may be used multiple times, it will simply enable multiple crypto engines. Referencing an unsupported engine will prevent HAProxy from starting. Note that many engines will lead to lower HTTPS performance than pure software with recent processors. The optional command "algo" sets the default algorithms an ENGINE will supply using the OPENSSL function ENGINE_set_default_string(). A value of "ALL" uses the engine for all cryptographic operations. If no list of algo is specified then the value of "ALL" is used. A comma-separated list of different algorithms may be specified, including: RSA, DSA, DH, EC, RAND, CIPHERS, DIGESTS, PKEY, PKEY_CRYPTO, PKEY_ASN1. This is the same format that openssl configuration file uses: https://www.openssl.org/docs/man1.0.2/apps/config.html HAProxy Version 2.6 disabled the support for engines in the default build. This option is only available when HAProxy has been built with support for it. In case the ssl-engine is required HAProxy can be rebuild with the USE_ENGINE=1 flag.
向 SSL 上下文添加 SSL_MODE_ASYNC 模式。如果使用支持异步的 SSL 引擎,这将启用异步 TLS I/O 操作。当前实现最多支持 32 个引擎。Openssl ASYNC API 不支持移动读/写缓冲区,并且与 HAProxy 的缓冲区管理不兼容。因此,在读/写操作上禁用了异步模式(它仅在初始和重新协商握手期间启用)。
启用('on')或禁用('off')小程序(applet)的数据零拷贝转发。默认启用。
为每个进程可分配的缓冲区数量设置一个硬限制。默认值为零,表示无限制。该限制将自动重新调整以满足紧急情况下的保留缓冲区,这样用户就不必进行复杂的计算。强制设置此值对于限制进程可能占用的内存量,同时保持正常的行为特别有用。当达到此限制时,请求缓冲区的任务会等待另一个缓冲区被释放。只要限制合理,大多数情况下等待时间非常短且不易察觉。然而,一些历史上的限制在不同版本中削弱了这一机制,已知在某些持续短缺的情况下,一些任务可能会冻结直到超时,因此在非严格必要时,最好避免使用此选项。
设置每个线程预分配并保留的缓冲区数量,这些缓冲区仅在内存分配失败导致的内存短缺情况下使用。最小值为 0,默认值为 4。除非核心开发人员出于非常具体的原因建议更改,否则用户没有理由更改此值。
Sets the buffer size to this size (in bytes). Lower values allow more streams to coexist in the same amount of RAM, and higher values allow some applications with very large cookies to work. The default value is 16384 and can be changed at build time. It is strongly recommended not to change this from the default value, as very low values will break some services such as statistics, and values larger than default size will increase memory usage, possibly causing the system to run out of memory. At least the global maxconn parameter should be decreased by the same factor as this one is increased. In addition, use of HTTP/2 mandates that this value must be 16384 or more. If an HTTP request is larger than (tune.bufsize - tune.maxrewrite), HAProxy will return HTTP 400 (Bad Request) error. Similarly if an HTTP response is larger than this size, HAProxy will return HTTP 502 (Bad Gateway). Note that the value set using this parameter will automatically be rounded up to the next multiple of 8 on 32-bit machines and 16 on 64-bit machines.
设置小缓冲区的字节大小。默认值为 1024。这些缓冲区设计用于一些内存消耗受限但似乎不必分配完整缓冲区的特定上下文中。然而,如果小缓冲区不足,会自动进行重新分配以切换到标准大小的缓冲区。目前,它仅由 HTTP/3 协议用于发出响应头。
设置最大压缩级别。压缩级别影响压缩过程中的 CPU 使用率。此值影响压缩过程中的 CPU 使用率。每个使用压缩的数据流都使用此值初始化压缩算法。默认值为 1。
禁用数据快速转发。这是一种通过将数据直接从一侧传递到另一侧而不唤醒流来优化数据转发的机制。通过此指令,可以禁用此优化。请注意,它还禁用了任何内核 TCP 拼接以及零拷贝转发。此命令不适用于常规使用,通常只会在复杂的调试会话中由开发人员建议使用。因此,它在内部被标记为实验性的,这意味着 "expose-experimental-directives" 必须在此指令之前的行上出现。
全局禁用数据的零拷贝转发。这是一种通过避免使用通道缓冲区来优化数据快速转发的机制。通过此指令,可以禁用此优化。注意,它还禁用了任何内核 TCP 拼接。
Along HAProxy's history, a few complex issues were met that were caused by bugs in the epoll mechanism in the Linux kernel. These ones usually are very rare and unreproducible outside the reporter's environment, and may only be worked around by disabling epoll and switching to poll instead, which is not very satisfying for high performance environments. Each time, issues affect only very specific (and rare) event types, and offering the ability to mask them can constitute a more acceptable work-around. This options offers this possibility by permitting to silently ignore events a few uncommon events and replace them with an input (which reports an unspecified incoming event). The effect is to avoid the fast error processing paths in certain places and only use the common paths. This should never be used unless being invited to do so by an expert in order to diagnose or work around a kernel bug. The option takes a single argument which is a comma-delimited list of words each designating an event to be masked. The currently supported list of events is: - "err": mask the EPOLLERR event - "hup": mask the EPOLLHUP events - "rdhup": mask the EPOLLRDHUP events
# 屏蔽所有非流量的 epoll 事件: tune.epoll.mask-events err,hup,rdhup
设置异步任务处理程序(来自 event_hdl API)一次可以处理的事件数量。<number> 应在 1 到 10000 之间。较大的数字可能导致线程争用,因为任务在不中断的情况下进行繁重的工作;另一方面,较小的数字可能导致任务不断被重新调度,因为它每次运行无法消耗足够多的事件,也无法跟上事件生成者的速度。默认值可以在构建时强制设置,否则默认为 100。
如果使用 DEBUG_FAIL_ALLOC 编译或使用 "-dMfail" 启动,则给出分配尝试失败的百分比机会。必须在 0(无失败)和 100(无成功)之间。这对于调试并确保内存故障得到妥善处理非常有用。未设置时,比率为 0。但是,命令行 "-dMfail" 选项会自动将其设置为 1% 的失败率,因此无需更改配置进行测试。
为支持它的文件描述符(FD)启用('on')或禁用('off')边缘触发轮询模式。目前仅在 epoll 下支持。在某些情况下,它可能会显著减少 epoll_ctl() 调用的数量并略微提高性能。这仍然是实验性的,如果仍然存在错误,可能会导致连接冻结,并且默认禁用。
启用('on')或禁用('off')H1 多路复用器的数据零拷贝接收。默认启用。
启用('on')或禁用('off')H1 多路复用器的数据零拷贝发送。默认启用。
设置后端连接上故障数量的阈值,超过该阈值连接将自动被终止。这允许自动终止行为不当的连接,而无需为其编写明确的规则。默认值为零,表示未设置阈值,因此任何事件都不会导致连接关闭。请注意,一些 H2 服务器可能会在长时间持续的连接上偶尔引起一些故障,因此这里的任何非零值可能应该在几百或几千的范围内才能有效,而不会影响轻微有问题的服务器。
设置传出连接的 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 的缓冲区)。
设置前端连接上故障数量的阈值,超过该阈值连接将自动被终止。这允许自动终止行为不当的连接,而无需为其编写明确的规则。默认值为零,表示未设置阈值,因此任何事件都不会导致连接关闭。请注意,一些 H2 客户端可能会在长时间持续的连接上偶尔引起一些故障,因此这里的任何非零值可能应该在几百或几千的范围内才能有效,而不会影响轻微有问题的客户端。
设置传入连接的 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 通常很好,建议不要更改此值。
Sets the HTTP/2 maximum number of total streams processed per incoming connection. Once this limit is reached, HAProxy will send a graceful GOAWAY frame informing the client that it will close the connection after all pending streams have been closed. In practice, clients tend to close as fast as possible when receiving this, and to establish a new connection for next requests. Doing this is sometimes useful and desired in situations where clients stay connected for a very long time and cause some imbalance inside a farm. For example, in some highly dynamic environments, it is possible that new load balancers are instantiated on the fly to adapt to a load increase, and that once the load goes down they should be stopped without breaking established connections. By setting a limit here, the connections will have a limited lifetime and will be frequently renewed, with some possibly being established to other nodes, so that existing resources are quickly released. It's important to understand that there is an implicit relation between this limit and "tune.h2.fe.max-concurrent-streams" above. Indeed, HAProxy will always accept to process any possibly pending streams that might be in flight between the client and the frontend, so the advertised limit will always automatically be raised by the value configured in max-concurrent-streams, and this value will serve as a hard limit above which a violation by a non- compliant client will result in the connection being closed. Thus when counting the number of requests per connection from the logs, any number between max-total-streams and (max-total-streams + max-concurrent-streams) may be observed depending on how fast streams are created by the client. The default value is zero, which enforces no limit beyond those implied by the protocol (2^30 ~= 1.07 billion). Values around 1000 may already cause frequent connection renewal without causing any perceptible latency to most clients. Setting it too low may result in an increase of CPU usage due to frequent TLS reconnections, in addition to increased page load time. Please note that some load testing tools do not support reconnections and may report errors with this setting; as such it may be needed to disable it when running performance benchmarks. See also "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 连接都会消耗此数量的内存。建议不要更改它。
Sets the default value for the HTTP/2 initial window size, on both incoming and outgoing connections. This value is used for incoming connections when tune.h2.fe.initial-window-size is not set, and by outgoing connections when tune.h2.be.initial-window-size is not set. This setting is used both as the initial value and as a minimum per stream. The default value equals 16384 (tune.bufsize), which for uploads roughly allows at least 1.25 Mbps of bandwidth per stream over a network showing a 100 ms ping time, or 125 Mbps over a 1-ms local network. When less receive buffers than the maximum are in use, within the limits defined by tune.h2.be.rxbuf and tune.h2.fe.rxbuf, unused buffers will be shared between receiving streams. As such there is normally no point in changing this default setting. Given that changing this default value will both increase upload speeds and cause more unfairness between clients on downloads, it is recommended to instead use the side- specific settings tune.h2.fe.initial-window-size and 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。
Sets the maximum number of headers allowed in received HTTP messages. When a message comes with a number of headers greater than this value (including the first line), it is rejected with a "400 Bad Request" status code for a request, or "502 Bad Gateway" for a response. The default value is 101, which is enough for all usages, considering that the widely deployed Apache server uses the same limit. It can be useful to push this limit further to temporarily allow a buggy application to work by the time it gets fixed. The accepted range is 1..32767. Keep in mind that each new header consumes 32bits of memory for each stream, so don't push this limit too high. Note that HTTP/1.1 is a text protocol, so there is no special limit when the message is sent. The limit during the message parsing is sufficient. HTTP/2 and HTTP/3 are binary protocols and require an encoding step. A limit is set too when headers are encoded to comply to limitation imposed by the protocols. This limit is large enough but not documented on purpose. The same limit is applied on the first steps of the decoding for the same reason.
启用('on')或禁用('off')同一服务器的空闲连接池在线程间的共享。默认是共享它们,以最小化到服务器的持久连接数,并优化连接重用率。但为了帮助调试或当怀疑 HAProxy 在连接重用方面存在错误时,强制禁用多线程间的空闲池共享,并将此选项设置为 "off" 可能很方便。默认是 on。强烈建议在禁用此选项时,不要为所有依赖连接重用以实现高性能的服务器设置一个保守的“pool-low-conn”值,否则随着线程数的增加,连接可能会被频繁关闭。
设置一个持续时间,在此之后 HAProxy 将认为一个空缓冲区可能与一个空闲流相关联。这用于在交替转发大数据和小数据时优化调整某些数据包的大小。使用 splice() 或在 SSL 中发送大缓冲区的决定受此参数调节。该值以毫秒为单位,介于 0 和 65535 之间。值为零表示 HAProxy 不会尝试检测空闲流。默认值为 1000,这似乎能正确检测最终用户的暂停(例如,在点击前阅读页面)。应该没有理由更改此值。请检查下面的 tune.ssl.maxrecord。
Normally, all "bind" lines will create a single shard, that is, a single socket that all threads of the process will listen to. With many threads, this is not very efficient, and may even induce some important overhead in the kernel for updating the polling state or even distributing events to the various threads. Modern operating systems support balancing of incoming connections, a mechanism that will consist in permitting multiple sockets to be bound to the same address and port, and to evenly distribute all incoming connections to these sockets so that each thread only sees the connections that are waiting in the socket it is bound to. This significantly reduces kernel-side overhead and increases performance in the incoming connection path. This is usually enabled in HAProxy using the "shards" setting on "bind" lines, which defaults to 1, meaning that each listener will be unique in the process. On systems with many processors, it may be more convenient to change the default setting to "by-thread" in order to always create one listening socket per thread, or "by-group" in order to always create one listening socket per thread group. Be careful about the file descriptor usage with "by-thread" as each listener will need as many sockets as there are threads. Also some operating systems (e.g. FreeBSD) are limited to no more than 256 sockets on a same address. Note that "by-group" will remain equivalent to "by-process" for default configurations involving a single thread group, and will fall back to sharing the same socket on systems that do not support this mechanism. The default is "by-group" with a fallback to "by-process" for systems or socket families that do not support multiple bindings.
Enables ('on' / 'fair') or disables ('off') the listener's multi-queue accept which spreads the incoming traffic to all threads a "bind" line is allowed to run on instead of taking them for itself. This provides a smoother traffic distribution and scales much better, especially in environments where threads may be unevenly loaded due to external activity (network interrupts colliding with one thread for example). The default mode, "on", optimizes the choice of a thread by picking in a sample the one with the less connections. It is often the best choice when connections are long-lived as it manages to keep all threads busy. A second mode, "fair", instead cycles through all threads regardless of their instant load level. It can be better suited for short- lived connections, or on machines with very large numbers of threads where the probability to find the least loaded thread with the first mode is low. Finally it is possible to forcefully disable the redistribution mechanism using "off" for troubleshooting, or for situations where connections are short-lived and it is estimated that the operating system already provides a good enough distribution. The default is "on".Explicitly tell haproxy how haproxy sample objects should be handled when pushed to Lua. Indeed, when leveraging native converters, sample fetches or variables from Lua script (to name a few), haproxy converts the internal smp type to equivalent Lua type. Because of historical implementation, there is an ambiguity around boolean handling: when doing Lua -> haproxy smp conversion, booleans are properly preserved, but when doing haproxy smp -> Lua conversion, booleans were converted to integers by mistake. This means that a sample fetch or converter returning a boolean would return an integer 0 or 1 when leveraged from Lua. Unfortunately, in Lua, booleans and integers are not interchangeable. Thus, to avoid ambiguities, "tune.lua.bool-sample-conversion" must explicitly be set to either "normal" (which means dropping the historical behavior for better consistency) or "pre-3.1-bug" (enforce historical behavior to prevent existing script logic from misbehaving). If the option is not set explicitly and a Lua script is loaded from the configuration, haproxy will emit a warning, and the option will implicitly default to "pre-3.1-bug" to match with the historical behavior. It is recommended to set this option to "normal" after ensuring that in-use Lua scripts are properly handling bool haproxy samples as booleans.
The "burst" execution timeout applies to any Lua handler. If the handler fails to finish or yield before timeout is reached, it will be aborted to prevent thread contention, to prevent traffic from not being served for too long, and ultimately to prevent the process from crashing because of the watchdog kicking in. Unlike other lua timeouts which are yield-cumulative, burst-timeout will ensure that the time spent in a single lua execution window does not exceed the configured timeout. Yielding here means that the lua execution is effectively interrupted either through an explicit call to lua-yielding function such as core.(m)sleep() or core.yield(), or following an automatic forced-yield (see tune.lua.forced-yield) and that it will be resumed later when the related task is set for rescheduling. Not all lua handlers may yield: we have to make a distinction between yieldable handlers and unyieldable handlers. For yieldable handlers (tasks, actions..), reaching the timeout means "tune.lua.forced-yield" might be too high for the system, reducing it could improve the situation, but it could also be a good idea to check if adding manual yields at some key points within the lua function helps or not. It may also indicate that the handler is spending too much time in a specific lua library function that cannot be interrupted. For unyieldable handlers (lua converters, sample fetches), it could simply indicate that the handler is doing too much computation, which could result from an improper design given that such handlers, which often block the request execution flow, are expected to terminate quickly to allow the request processing to go through. A common resolution approach here would be to try to better optimize the lua function for speed since decreasing "tune.lua.forced-yield" won't help. This timeout only counts the pure Lua runtime. If the Lua does a core.sleep, the sleeping time is not taken in account. The default timeout is 1000ms. Note: if a lua GC cycle is initiated from the handler (either explicitly requested or automatically triggered by lua after some time), the GC cycle time will also be accounted for. Indeed, there is no way to deduce the GC cycle time, so this could lead to some false positives on saturated systems (where GC is having hard time to catch up and consumes most of the available execution runtime). If it were to be the case, here are some resolution leads: - checking if the script could be optimized to reduce lua memory footprint - fine-tuning lua GC parameters and / or requesting manual GC cycles (see: https://lua.ac.cn/manual/5.4/manual.html#pdf-collectgarbage) - increasing tune.lua.burst-timeout Setting value to 0 completely disables this protection.
此指令强制 Lua 引擎每执行 <number> 条指令就执行一次让出(yield)。这允许中断一个长脚本,并让 HAProxy 调度器处理其他任务,如接受连接或转发流量。对于使用“lua-load-per-thread”加载的脚本,默认值为 10000 条指令;对于使用“lua-load”加载的脚本,默认值为 MAX(500, 10000 / nbthread) 条指令(这被认为是性能的最佳值,同时注意不要因多个线程竞争全局 Lua 锁而造成线程争用)。如果 HAProxy 经常执行一些 Lua 代码但需要更高的响应性,可以降低此值。如果 Lua 代码相当长且其结果对于处理数据是绝对必需的,可以增加 <number>,但应明智地设置该值,因为在多线程环境中它可能会增加争用。
启用('on')或禁用('off')通过适用于当前代理的日志记录器(如果有)记录 LUA 脚本的输出。默认为 'on'。
启用('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 时不必担心它。
Sets the per-thread amount of memory that will be kept hot in the local cache and will never be recoverable by other threads. Access to this memory is very fast (lockless), and having enough is critical to maintain a good performance level under extreme thread contention. The value is expressed in bytes, and the default value is configured at build time via CONFIG_HAP_POOL_CACHE_SIZE which defaults to 524288 (512 kB). A larger value may increase performance in some usage scenarios, especially when performance profiles show that memory allocation is stressed a lot. Experience shows that a good value sits between once to twice the per CPU core L2 cache size. Too large values will have a negative impact on performance by making inefficient use of the L3 caches in the CPUs, and will consume larger amounts of memory. It is recommended not to change this value, or to proceed in small increments. In order to completely disable the per-thread CPU caches, using a very small value could work, but it is better to use "-dMno-cache" on the command-line.
Sets the size of the pattern lookup cache to <number> entries. This is an LRU cache which reminds previous lookups and their results. It is used by ACLs and maps on slow pattern lookups, namely the ones using the "sub", "reg", "dir", "dom", "end", "bin" match methods as well as the case-insensitive strings. It applies to pattern expressions which means that it will be able to memorize the result of a lookup among all the patterns specified on a configuration line (including all those loaded from files). It automatically invalidates entries which are updated using HTTP actions or on the CLI. The default cache size is set to 10000 entries, which limits its footprint to about 5 MB per process/thread on 32-bit systems and 8 MB per process/thread on 64-bit systems, as caches are thread/process local. There is a very low risk of collision in this cache, which is in the order of the size of the cache divided by 2^64. Typically, at 10000 requests per second with the default cache size of 10000 entries, there's 1% chance that a brute force attack could cause a single collision after 60 years, or 0.1% after 6 years. This is considered much lower than the risk of a memory corruption caused by aging components. If this is not acceptable, the cache can be disabled by setting this parameter to 0.
设置 haproxy 在发送消息时一次将尝试处理的粘性表更新的最大数量。检索这些更新的数据需要一些锁定操作,这在高度线程化的机器上如果无限制可能会消耗大量 CPU,并且在旧进程和新进程之间的初始批量传输期间也可能增加流量延迟。相反,低值也可能导致更高的 CPU 开销,并需要更长的时间来完成。默认值为 200,建议不要更改它。
将内核管道缓冲区大小设置为此大小(以字节为单位)。默认情况下,管道是系统的默认大小。但有时在使用 TCP 拼接时,增加管道大小可以提高性能,特别是在怀疑管道未被填满且执行了许多 splice() 调用时。这对内核的内存占用有影响,因此如果影响不明确,则不应更改此值。
此设置设置 HAProxy 全局使用的文件描述符最大数量(百分比),相对于 HAProxy 在我们无法重用连接并且必须创建新连接时开始终止空闲连接之前可以使用的最大文件描述符数量。默认值为 25(四分之一的文件描述符将意味着大约一半的最大前端连接可以保留一个空闲的后端连接,任何超出此范围的在针对连接重用的通用情况下可能没有多大意义)。
此设置设置 HAProxy 全局使用的文件描述符最大数量(百分比),相对于 HAProxy 在我们停止将连接放入空闲池以供重用之前可以使用的最大文件描述符数量。默认值为 20。
启用('on')或禁用('off')直通(pass-through)多路复用器的数据零拷贝转发。要使用此功能,还必须配置内核拼接。默认启用。
启用('on')或禁用('off')用于 QUIC 连接的 HyStart++ (RFC 9406) 算法,作为拥塞控制算法慢启动阶段的替代方案,该阶段可能导致高丢包率。默认禁用。
Defines how many lost packets are needed for the Cubic congestion control algorithm to really consider a loss event. Normally, any loss event is considered as the result of a congestion and is sufficient for Cubic to restart from a smaller window. But experiments show that there can be a variety of causes for losses that are not at all caused by congestion and that can simply be qualified of spurious losses, and for which adjusting the window will have no effect, except slowing communication down. Poor radio signal, out-of-order delivery, high CPU usage on a client causing random delays, as well as system timer imprecision can be among the common causes for this. This setting allows to make Cubic a bit more tolerant to spurious losses, by changing the minimum number of cumulated losses between two ACKs to be considered as a loss event, which defaults to 1. Some significant gains have been observed experimentally, but always accompanied with an aggravation of the bandwidth wasted on retransmits, and an increased risk of saturation of congested links. The value 2 may be used for short periods of time to compare some metrics. Never go beyond 2 without an expert's prior analysis of the situation. The default and minimum value is 1. Always use 1.
Disable UDP GSO emission. This kernel feature allows to emit multiple datagrams via a single system call which is more efficient for large transfer. It may be useful to disable it on developers suggestion when suspecting an issue on emission.
Sets the threshold for the number of glitches on a frontend connection, where that connection will automatically be killed. This allows to automatically kill misbehaving connections without having to write explicit rules for them. The default value is zero, indicating that no threshold is set so that no event will cause a connection to be closed. Beware that some QUIC clients may occasionally cause a few glitches over long lasting connection, so any non- zero value here should probably be in the hundreds or thousands to be effective without affecting slightly bogus clients.
设置前端的 QUIC max_idle_timeout 传输参数(以毫秒为单位),该参数确定了连接在由两个端点宣告的两个 max_idle_timeout 值推导出的有效时间段内保持不活动后,静默关闭的时间段:- 如果两个值都不为空,则为两个值中的最小值,- 如果只有一个不为空,则为最大值,- 如果两个值都为空,则禁用此功能。默认值为 30000。
为前端设置 QUIC initial_max_streams_bidi 传输参数。这是远程对等方将被授权打开的初始最大双向流数。这决定了并发客户端请求的数量。默认值为 100。
Sets the default maximum window size for the congestion controller of a single QUIC connection. The value must be written as an integer with an optional suffix 'k', 'm' or 'g'. It must be between 10k and 4g. QUIC multiplexer also uses the current congestion window size to determine if it can allocate new stream buffers on data emission. As such, the maximum congestion window size also serves as a limit on this allocator. The default value is 480k. See also the "quic-cc-algo" bind option.
设置单个 QUIC 帧可以被标记为丢失的限制。如果超过此限制,连接将被视为失败并立即关闭。默认值为 10。
应用于计算出的数据包重排阈值的比率。如果太小,可能会触发高丢包检测。默认值为 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。
此选项全局指定 QUIC 连接如何使用套接字进行接收/发送操作。连接可以共享监听套接字,也可以每个连接分配自己的套接字。当设置为默认值 "connection" 时,每个 QUIC 连接都将分配一个专用的套接字。对于大量 QUIC 流量,这是实现最佳性能的首选选项。这也是确保 QUIC 连接正确执行软停止且不丢失数据,以及高效处理 sendto() 操作期间瞬态错误情况的唯一方法。然而,这依赖于 UDP 网络堆栈的一些高级功能。如果您的平台被认为不兼容,haproxy 将在启动时自动切换到 "listener" 模式。请注意,在特权端口上运行的 QUIC 监听器可能需要以 uid 0 身份运行,或者需要进行一些特定于操作系统的调整,以允许目标 uid 绑定此类端口,例如系统功能(system capabilities)。另请参阅 "setcap" 全局指令。值 "listener" 表示 QUIC 传输将发生在共享监听套接字上。此选项对于小流量可能是一个很好的折衷方案,因为它可以减少 FD 消耗。然而,如果监听器在许多线程之间共享或同时使用大量 QUIC 连接,由于较高的 CPU 使用率,性能将不会是最佳的。此设置与每个 "quic-socket" 绑定选项结合应用。如果在全局调优中使用了 "connection" 模式,它将为每个监听器激活,除非其绑定选项设置为 "listener"。然而,如果全局使用了 "listener",它将被强制应用于每个监听器实例,无论其单独配置如何。
启用 ('on') 或禁用 ('off') QUIC 发送的速率控制支持。默认情况下它是禁用的。速率控制的目的是平滑数据发送以减少网络丢失。在大多数情况下,它可以通过避免重传显着提高网络吞吐量。然而,对于具有非常高带宽/低延迟特性的网络,禁用它可能很有用,以防止不必要的延迟并减少 CPU 消耗。速率控制支持仍处于实验阶段,因此它需要 "expose-experimental-directives"。另请参阅 "quic-cc-algo" 绑定选项。启用('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 而导致的写入超时。
设置全局 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 相反,此设置不会动态调整。较小的记录可能会降低吞吐量,但在处理低占用客户端时可能是必需的。
此选项激活 TLS 密钥的日志记录。应谨慎使用,因为它会消耗每个 SSL 会话更多的内存并可能降低性能。默认情况下禁用此功能。这些样本获取应用于生成 SSLKEYLOGFILE,这是使用 wireshark 解密流量所必需的。https://mdn.org.cn/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format SSLKEYLOGFILE 是一系列行,格式如下:<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 是有效的,可以完全禁用粘性计数器)。
这五个调优有助于管理变量系统使用的最大内存量。"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。
这将全局匿名化密钥设置为 <密钥>,它必须是一个介于 0 和 4294967295 之间的 32 位数字。这是启用匿名模式时 CLI 命令默认使用的密钥。此密钥也可以在运行时通过 CLI 命令“set anon global-key”设置。另请参阅管理手册中的命令行参数“-dC”。
此命令将配置解析器暂停 <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 map 文件具有非常高的评估成本,都可能导致此类问题。相比之下,TLS 握手可能需要一到两毫秒,压缩 16kB HTTP 响应缓冲区大约需要一毫秒。输出包含一个违规任务的线程转储,其中包含回溯和一些上下文,有助于找出时间花在哪里。
设置此选项后,如果在处理和应用配置时发出任何警告,HAProxy 将拒绝启动。这意味着有关参数组合不佳的警告、有关无法设置的非常高限制的警告等等,都会使进程在启动期间因错误而退出。此选项无法捕获一些较晚的启动警告,例如在“daemon”或“master-worker”模式下更改组 ID 时未能丢弃补充组,或者在 fork() 后未能将进程标记为可转储。此选项不捕获运行时发出的警告。强烈建议在不经常更改的配置上设置此选项,因为它有助于检测细微的错误并保持配置的整洁和向前兼容。请注意,“haproxy -c”在这种情况下也会报告错误。此选项等同于命令行参数“-dW”。
出于调试目的,可以激活 HAProxy 子系统的跟踪。这将转储有关特定子系统的调试消息。这是一个诊断问题的强大工具。跟踪可以通过 CLI 动态配置。也可以在配置文件中预定义一些设置,在专门的 "traces" 部分中。有关跟踪的更多详细信息,请参阅管理指南。它仍然是开发人员在复杂调试会话期间使用的工具。它非常详细且有成本,因此请谨慎使用。而且由于它是一个开发人员工具,因此不保证此部分的向后兼容性。
开始一个新的跟踪部分。可以使用一个或多个“traces”部分。所有指令都按照声明顺序进行评估,最后的指令将覆盖之前的指令。
配置 "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
可以通过仅允许经过身份验证和授权的用户来控制对前端/后端/侦听部分或 http 统计信息的访问。为此,需要创建至少一个用户列表并定义用户。
创建名为 <listname> 的新用户列表。可以使用许多独立的用户列表来存储独立客户的身份验证和授权数据。
将组 <groupname> 添加到当前用户列表。也可以通过使用逗号分隔的名称列表(前面有 "users" 关键字)将用户附加到此组。
将用户 <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
请注意,这两个列表在功能上是相同的。
可以将任何数据类型在 stick-tables 中的条目通过 TCP 连接在多个 HAProxy 实例之间以多主方式传播。每个实例将其本地更新和插入推送到远程对等体。推送的值会覆盖远程值,而无需聚合。作为例外,数据类型 "conn_cur" 永远不会从对等体学习,因为它应该反映本地值。早期版本曾同步它,并在 active-active 设置中导致负值,并在重新加载或 active-passive 切换时导致值不断增长,因为本地值会反映比本地存在的连接更多的连接。然而,此信息被推送,以便监控系统可以监视它。中断的交换会自动检测并从最后一个已知点恢复。此外,在软重启期间,旧进程使用这样的 TCP 连接连接到新进程,以在新进程尝试连接到其他对等体之前推送其所有条目。这确保了在重新加载期间非常快速的复制,即使对于大型表,通常也只需一小部分时间。请注意,服务器 ID 用于远程识别服务器,因此重要的是所有参与者上的配置看起来相似,或者至少在每个服务器上强制使用相同的 ID。
创建名为 <peersect> 的新对等节点列表。它是一个独立的部分,由一个或多个粘性表引用。
定义此“peers”部分中本地对等节点的绑定参数。在同一个“peers”部分中,此类行不支持与“peer”行同时使用。
禁用一个对等节点部分。它会禁用与此部分相关的侦听和任何同步。这用于禁用粘性表的同步,而无需注释掉所有 "peers" 引用。
定义本地对等节点的绑定参数,但不包括其地址。
更改“peers”部分中服务器的默认选项。
<param*> 是此服务器的参数列表。关键字 "default-server" 接受大量选项,并有一个完整的专用部分。在对等体部分中,支持 "default-server" 行的传输参数。请参阅 第 5 节 了解更多详细信息,并参阅本节中下面的 "server" 关键字了解一些限制。
此选项重新启用一个先前通过“disabled”关键字禁用的 peers 部分。"peers" 部分支持与代理相同的 "log" 关键字,用于记录有关 "peers" 监听器的信息。有关代理的更多详细信息,请参阅 "log" 选项。
在 peers 部分中定义一个对等体。如果 <peername> 设置为本地对等体名称(默认为主机名,或使用 "-L" 命令行选项或 "localpeer" 全局配置设置强制设置),HAProxy 将监听在提供的地址上的传入远程对等体连接。否则,地址定义了连接到何处以加入远程对等体,<peername> 用于协议级别以在服务器端识别和验证远程对等体。在软重启期间,本地对等体地址被旧实例用于连接新实例并启动完整的复制(教学过程)。强烈建议在所有对等体上使用完全相同的 peers 声明,并且仅依赖 "-L" 命令行参数或 "localpeer" 全局配置设置来更改本地对等体名称。这使得跨所有对等体维护一致的配置文件更加容易。您可能希望在地址参数中引用一些环境变量,请参阅 第 2.3 节 有关环境变量的内容。注意:关键字 "peer" 可以透明地替换为关键字 "server"(请参阅下面的 "server" 关键字解释)。
如前所述,关键字 "peer" 可以替换为关键字 "server",并支持 第 5.2 段 中与传输设置相关的所有 "server" 参数。如果底层对等体是本地的,则地址参数不得存在;它必须在 "bind" 行上提供(请参阅此 "peers" 部分的 "bind" 关键字)。许多 "server" 参数与 "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
在某些配置中,人们可能希望将粘滞表(stick-table)的内容分发给某些对等节点,而不是将所有粘滞表内容发送给在“peers”部分中声明的每个对等节点。在这种情况下,“shards”指定了参与此粘滞表内容分发的对等节点的数量。另请参阅“shard”服务器参数。
为当前部分配置粘性表。此行解析方式与 "stick-table" 关键字在其他部分中的解析方式完全相同,除了这里不需要 "peers" 参数,并且多了一个强制性的第一个参数来指定粘性表。与其他部分相反,"peers" 部分中可能有多个 "table" 行(另请参阅 "stick-table" 关键字)。另请注意,"peers" 部分有自己的粘性表命名空间,以避免在不同的 "peers" 部分中粘性表名称相同而发生冲突。这在内部通过在粘性表名称前加上 "peers" 部分名称和字符 '/' 来处理。如果在配置文件的其他地方必须引用在 "peers" 部分中声明的此类粘性表,则必须使用带有前缀的粘性表名称,如下所示: peers mypeers peer A ... peer B ... table t1 ... frontend fe1 tcp-request content track-sc0 src table mypeers/t1 这也是通过 CLI 引用粘性表时必须使用的带有前缀的粘性表名称版本。关于 "peers" 协议,由于只有属于同一部分的 "peers" 可以相互通信,因此无需进行此类区分。几个 "peers" 部分可以声明具有相同名称的粘性表。这是通过网络发送的粘性表名称的较短版本。只有一个 '/' 字符作为前缀,以避免在后端声明的粘性表与在 "peers" 部分中声明的粘性表之间发生粘性表名称冲突,如下所示(在以下这种奇怪但支持的配置中): 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"。但在对等体协议级别,前者表名为 "/t1",后者仍名为 "t1"。
在服务器状态发生变化时,可以发送电子邮件警报。如果配置了电子邮件警报,则会发送给在 mailers 部分配置的每个邮件发送者。通过 Lua 发送电子邮件到邮件发送者(请参阅 examples/lua/mailers.lua)。
创建名为 <mailersect> 的新邮件发送器列表。它是一个独立的部分,由一个或多个代引用。
在邮件发送器部分内定义一个邮件发送器。
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
此部分已弃用,应在 HAProxy 3.3 中消失。此部分可以很容易地被单独的进程管理器取代。Systemd 单元文件或 sysvinit 脚本可以取代此部分,因为它们更可靠。在 docker 环境中,也可以找到 s6 或 supervisord 等替代方案。在主-工作模式下,可以使用主进程启动外部二进制文件,这些进程称为程序。这些程序的启动和管理方式与工作进程相同。自 3.1 版本以来,程序部分的行为略有不同,该部分被解析并且程序由主进程启动,但配置的其余部分加载到工作进程中。这意味着程序配置与工作进程配置完全分离,即使工作进程配置在重新加载时出错,程序也可以重新执行。在 HAProxy 重新加载期间,这些进程的处理顺序与工作进程相同: - 主进程重新执行 - 主进程向程序发送 SIGUSR1 信号 - 如果未禁用 "option start-on-reload",则主进程启动程序的新实例 在停止或重启期间,会向程序发送 SIGTERM。
这是一个新的程序部分,此部分将创建一个名为 <name> 的实例,该实例在 master CLI 的 "show proc" 中可见。(请参阅管理指南中的 "9.4. Master CLI")。
定义要启动的命令及可选参数。如果命令不包含绝对路径,则会在当前 PATH 中查找。这是 program 部分的一个强制选项。包含空格的参数必须用单引号或双引号括起来,或者以反斜杠为前缀。
将执行命令的用户 ID 更改为 /etc/passwd 中的 <user name>。另请参阅 "group"。将执行命令的组 ID 更改为 /etc/group 中的 <group name>。另请参阅 "user"。在 master 重载时启动(或不启动)程序的新实例。默认是启动新实例。此选项只能在 program 部分使用。
可以全局声明多个 HTTP 错误组,以便之后在任何代理部分中导入。同一个组可以在多个地方被引用,并且可以全部或部分导入。
创建一个名为 <name> 的新 http-errors 组。它是一个独立的部分,可以由一个或多个代理通过其名称引用。
将文件内容与一个 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 预连接错误
可以全局声明环形缓冲区,用作日志服务器或跟踪的目标。
创建一个名为 <ringname> 的新环形缓冲区。
这通过 RAM 映射文件替换常规内存分配来存储环形缓冲区。这对于收集跟踪或日志以进行事后分析非常有用,而无需将慢速客户端连接到 CLI。较新的内容将自动替换较旧的内容,以便始终提供最新的内容。写入环形缓冲区的内容在进程停止后将在该文件中可见(通常它们甚至会很快被看到,但由于写入不是同步的,因此不能保证)。使用此选项时,总存储区域会因区域开头的 "struct ring" 大小而减小,这对于恢复区域内容是必需的。文件将使用启动用户的所有权创建,模式为 0600,大小由 "size" 指令配置。解析指令时(因此即使在配置检查期间),任何现有的非空文件将首先重命名为带有额外后缀 ".bak" 的文件,并且任何先前存在的带有后缀 ".bak" 的文件将被删除。这确保了进程的即时重新加载或重启不会清除宝贵的调试信息,并留出时间让管理员发现这个新的 ".bak" 文件并在需要时进行存档。因此,在崩溃之后,<path> 指定的文件将包含最新信息,如果服务重新启动,"<path>.bak" 文件将包含该信息。这意味着所需的总存储容量将是环形缓冲区大小的两倍。文件轮换失败会被静默忽略,因此将文件放置在没有写入权限的目录中足以避免不需要备份文件。警告:使用此功能存在稳定性和安全隐患。首先,将环形缓冲区备份到慢速设备(例如物理硬盘驱动器)可能会在访问期间导致明显的减速,如果太多线程竞争访问,甚至可能导致崩溃。其次,外部进程修改该区域可能导致 haproxy 进程崩溃或用跟踪覆盖其自身的某些内存。第三,如果文件系统在环形缓冲区之前已满,写入环形缓冲区可能会导致进程崩溃。此环形缓冲区中存在的信息是结构化的,不能直接使用文本编辑器读取(尽管大部分看起来几乎可读)。此文件的输出仅供开发人员使用。
描述是环形缓冲区的可选描述字符串。它将出现在 CLI 中。默认情况下,<name> 会被重用以填充此字段。
用于将事件存储到环形缓冲区的格式。
<format> 是生成 syslog 消息时使用的日志格式。它可以是以下之一: iso 仅包含 ISO 日期,后跟文本的消息。省略 PID、进程名称和系统名称。这设计用于本地日志服务器。local 类似于 rfc3164 syslog 消息格式,只是省略了主机名字段。这是默认值。注意:选项 "log-send-hostname" 将默认值切换为 rfc3164。raw 仅包含文本的消息。省略级别、PID、日期、时间、进程名称和系统名称。这设计用于容器或开发期间,其中严重性仅取决于使用的文件描述符(stdout/stderr)。这是默认值。rfc3164 RFC3164 syslog 消息格式。(https://tools.ietf.org/html/rfc3164) rfc5424 RFC5424 syslog 消息格式。(https://tools.ietf.org/html/rfc5424) short 仅包含尖括号中的级别(例如 '<3>'),后跟文本的消息。省略 PID、日期、时间、进程名称和系统名称。这设计用于本地日志服务器。此格式与 systemd logger 消费的格式兼容。priority 仅包含尖括号中的级别加上 syslog facility(例如 '<63>'),后跟文本的消息。省略 PID、日期、时间、进程名称和系统名称。这设计用于本地日志服务器。timed 仅包含尖括号中的级别(例如 '<3>'),后跟 ISO 日期和文本的消息。省略 PID、进程名称和系统名称。这设计用于本地日志服务器。
存储在环形缓冲区中的事件消息的最大长度,包括格式化的头部。如果事件消息长于 <length>,它将被截断为此长度。
用于配置 syslog tcp 服务器以转发环形缓冲区中的消息。这支持 第 5.2 段 中找到的所有 "server" 参数。其中一些参数与 "ring" 部分无关。重要一点:没有太多理由向环形缓冲区添加多个服务器,因为所有服务器将接收完全相同的环形缓冲区内容副本,因此环形缓冲区将以最慢服务器的速度前进。如果一个服务器没有响应,它将阻止清除旧消息,并可能阻止将新消息插入环形缓冲区。向多个服务器发送消息的正确方法是为每个日志服务器使用一个不同的环形缓冲区,而不是将多个服务器连接到同一个环形缓冲区。请注意,特定的服务器指令 "log-proto" 用于设置用于发送消息的协议。
这是环形缓冲区的可选大小,以字节为单位。默认值设置为 BUFSIZE。
设置等待服务器连接尝试成功的最大时间。
<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
可以声明一个或多个日志转发部分,HAProxy 会将所有接收到的日志消息转发到一个日志服务器列表。
创建一个新的日志转发代理,标识为 <name>。
向系统提供关于连接接受时期望的监听队列(backlog)大致大小的提示。
用于配置流日志监听器以接收要转发的消息。这支持 第 5.1 段 中找到的 "bind" 参数,包括那些关于 ssl 的参数,但某些语句(例如 "alpn")可能与通过 TCP 的 syslog 协议无关。这些监听器支持 rfc-6587 中定义的 "Octet Counting" 和 "Non-Transparent-Framing" 模式。
用于配置数据报日志监听器以接收要转发的消息。地址必须是 IPv4 或 IPv6 格式,后跟一个端口。这支持 第 5.1 段 中找到的一些 "bind" 参数,其中包括 "interface"、"namespace" 或 "transparent",而其他参数则被静默忽略,因为它们与 UDP/syslog 情况无关。
用于配置目标日志服务器。请参阅代理文档了解更多详情。如果未指定格式,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
固定日志转发器上的最大并发连接数。默认值为 10。
设置客户端侧的最大不活动时间。
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 将被禁用。但是,当明确启用此选项时,如果失败,它将触发配置错误。其工作方式与服务器行上的 verify 选项相同。如果指定为 'none',则不验证服务器证书。默认选项是“required”。默认情况下以及不使用此选项时,值为“required”。如果失败,httpclient 的 SSL 将被禁用。但是,当明确启用此选项时,如果失败,它将触发配置错误。
为 httpclient 默认设置连接尝试的最大等待时间。
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
默认值为 5000ms。
HAProxy 使用内部存储机制来加载和存储配置中使用的证书。可以使用 "crt-store" 部分配置此存储。它允许配置证书定义以及应加载哪些文件。证书定义必须在使用它的配置中的其他地方之前编写。"crt-store" 采用一个可选名称作为参数。如果指定了名称,则此存储中的每个证书必须使用 "@<name>/<crt>" 或 "@<name>/<alias>" 来引用。证书存储中的文件也可以通过 CLI 动态更新。请参阅管理指南 第 9.3 节 中的 "set ssl cert"。 "crt-store" 部分支持以下关键字: - crt-base - key-base - load
当使用 "crt" 指令使用相对路径时,分配一个默认目录从中获取 SSL 证书。指定的绝对位置优先,并忽略 "crt-base"。当在 crt-store 中使用时,全局部分的 crt-base 被忽略。
当使用 "key" 指令使用相对路径时,分配一个默认目录从中获取 SSL 私钥。指定的绝对位置优先,并忽略 "key-base"。当在 crt-store 中使用时,全局部分的 key-base 被忽略。
将 SSL 文件加载到证书存储中。有关参数列表,请参阅 "3.12.1. Load options" 部分
crt-store load crt "site1.crt" key "site1.key" ocsp "site1.ocsp" alias "site1" load crt "site2.crt" key "site2.key" frontend in2 bind *:443 ssl crt "@/site1" crt "site2.crt" crt-store web crt-base /etc/ssl/certs/ key-base /etc/ssl/private/ load crt "site3.crt" alias "site3" load crt "site4.crt" key "site4.key" frontend in2 bind *:443 ssl crt "@/site1" crt "site2.crt" crt "@web/site3" crt "@web/site4.crt"
在证书存储中加载 SSL 文件。load 关键字可以接受多个参数,如下所示。这些关键字也可以在 crt-list 中使用。
此参数是必需的,它加载一个 PEM 文件,该文件必须包含公用证书,但也可能包含中间证书和私钥。如果此文件中未提供私钥,则可以使用 "key" 关键字提供密钥。
可选参数。允许为证书命名一个别名,以便在配置中引用它。别名在配置的其他地方调用时必须以 '@/' 作为前缀。
此参数是可选的。加载 PEM 格式的私钥。如果 "crt" 中已定义私钥,则此参数将覆盖它。此参数是可选的,它加载 DER 格式的 OCSP 响应。可以通过 CLI 进行更新。
此参数是可选的。加载 PEM 格式的 OCSP 颁发者。为了识别 OCSP 响应适用于哪个证书,需要颁发者的证书。如果颁发者的证书未在 "crt" 文件中找到,则可以从此参数加载。此参数是可选的。支持证书透明度 (RFC6962) TLS 扩展。该文件必须包含一个有效的签名证书时间戳列表,如 RFC 中所述。文件将被解析以检查基本语法,但不验证签名。
当设置为 '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 请求/响应通过设置了 dontlog-normal 选项的 http_client 实例发送和接收,并且在发生错误(例如 OCSP 响应者无法访问)时使用常规 HTTP 日志格式。如果发生此类错误,则会与“常规”OCSP 行(可能具有“HTTP error”作为文本状态)一起发出另一条包含 HTTP 相关信息的日志行。但如果发生纯 HTTP 错误(例如 OCSP 响应者无法访问),将发出另一条遵循常规 HTTP 日志格式的日志行。以下是此类日志行的两个示例,首先是成功的 OCSP 更新日志行,然后是带有两条不同行的 HTTP 错误示例(为便于阅读,行被拆分且 URL 被缩短): <133>Mar 6 11:16:53 haproxy[14872]: <OCSP-UPDATE> /path_to_cert/foo.pem 1 \ "Update successful" 0 1 <133>Mar 6 11:18:55 haproxy[14872]: <OCSP-UPDATE> /path_to_cert/bar.pem 2 \ "HTTP error" 1 0 <133>Mar 6 11:18:55 haproxy[14872]: -:- [06/Mar/2023:11:18:52.200] \ <OCSP-UPDATE> -/- 2/0/-1/-1/3009 503 217 - - SC-- 0/0/0/0/3 0/0 {} \ "GET http://127.0.0.1:12345/MEMwQT HTTP/1.1" 故障排除:使用 let's encrypt 证书时可能发生的一个常见错误是 DNS 解析提供 IPv6 地址而您的系统没有有效的传出 IPv6 路由。在这种情况下,您可以创建适当的路由或在全局部分中设置 "httpclient.resolvers.prefer ipv4" 选项。如果出现 "OCSP response check failure" 错误,您可能需要检查您提供的颁发者证书是否有效。
代理配置可以位于一组部分中: - 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 部分获取其初始设置,默认情况下是出现在新创建部分之前的最新 defaults 部分。可以通过在部分行上可选关键字 "from" 之后指示其名称来显式指定从中加载初始设置的特定 "defaults" 部分。虽然 "defaults" 部分不强制要求名称,但为了更好的可读性鼓励使用此用法。这也是指定要使用的特定部分而不是默认的上一个部分的唯一方法。由于 "defaults" 部分名称是可选的,因此默认情况下对其名称应用非常宽松的检查,甚至允许它们重叠。但是,如果 "defaults" 部分被任何其他部分引用,则其名称必须符合对所有代理名称施加的语法,并且此名称在 defaults 部分中必须是唯一的。请注意,无论当前允许什么,建议通常避免重复的部分名称,并遵守与代理名称相同的语法。此规则可能会在未来版本中强制执行。此外,如果 defaults 部分被代理显式使用,而又被另一个代理隐式使用(因为它是定义的最后一个),则会发出警告。强烈建议不要混合使用这两种用法,方法是始终使用显式引用,或者添加一个保留用于所有隐式使用的最后一个公共 defaults 部分。请注意,defaults 部分甚至可以从另一个 defaults 部分获取其初始设置,因此可以在多级 defaults 部分中继承设置。这对于建立某些配置配置文件以携带默认设置组(例如 TCP 与 HTTP 或短超时与长超时)很方便,但很快就会变得难以理解。所有代理名称必须由大小写字母、数字、'-'(破折号)、'_'(下划线)、'.'(点)和':'(冒号)组成。ACL 名称区分大小写,这意味着 "www" 和 "WWW" 是两个不同的代理。历史上,所有代理名称都可以重叠,只是在日志中造成麻烦。自从引入内容切换以来,具有重叠功能(frontend/backend)的两个代理必须具有不同的名称。但是,仍然允许前端和后端共享相同的名称,因为此配置似乎很常见。目前,支持两种主要的代理模式:"tcp",也称为第 4 层,以及 "http",也称为第 7 层。在第 4 层模式下,HAProxy 只是转发两侧之间的双向流量。在第 7 层模式下,HAProxy 分析协议,并可以与之交互,通过根据任意标准允许、阻止、切换、添加、修改或删除请求或响应中的任意内容。在 HTTP 模式下,应用于流经连接的请求和响应的处理取决于前端的 HTTP 选项和后端的组合。HAProxy 支持 3 种连接模式: - KAL:保持活动("option http-keep-alive"),这是默认模式:处理所有请求和响应,并且连接在响应和新请求之间保持打开但空闲。 - SCL:服务器关闭("option http-server-close"):在接收到响应结束之后关闭面向服务器的连接,但面向客户端的连接保持打开。 - CLO:关闭("option httpclose"):在响应结束之后关闭连接,并在两个方向上附加 "Connection: close"。通过前端和后端传递的连接将应用的有效模式可以根据以下矩阵由两种代理模式确定,但简而言之,模式是对称的,保持活动是最弱的选项,关闭是最强的选项。 Backend mode | KAL | SCL | CLO ----+-----+-----+---- KAL | KAL | SCL | CLO ----+-----+-----+---- mode SCL | SCL | SCL | CLO ----+-----+-----+---- CLO | CLO | CLO | CLO 可以将 TCP 前端链接到 HTTP 后端。如果只处理 HTTP 流量,则没有意义。但它可用于在同一前端内处理多种协议。在这种情况下,客户端的连接首先被视为原始 tcp 连接,然后升级为 HTTP。在升级之前,内容处理是在原始数据上执行的。一旦升级,数据将使用称为 HTX 的内部表示形式进行解析和存储,并且不再可能依赖原始表示形式。没有办法退回。有两种升级方式,就地升级和破坏性升级。第一种涉及 TCP 到 HTTP/1 的升级。在 HTTP/1 中,请求处理是序列化的,因此可以保留应用流。第二种涉及 TCP 到 HTTP/2 的升级。因为它是多路复用协议,应用流不能与任何 HTTP/2 流关联并被销毁。当 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 规则仍然在每个流上进行评估,这是无法更改的。
支持以下关键字列表。其中大多数可能仅在有限的一组部分类型中使用。其中一些被标记为“已弃用”,因为它们继承自可能令人困惑或功能受限的旧语法,并且有新的推荐关键字来替换它们。标有 "(*)" 的关键字可以使用 "no" 前缀可选地反转,例如 "no option contstats"。当选项默认启用并且必须针对特定实例禁用时,这很有意义。此类选项也可以加上 "default" 前缀,以便无论在以前的 "defaults" 部分中指定了什么,都恢复默认设置。在标有 "(!)" 的 defaults 部分中支持的关键字仅在命名 defaults 部分中支持,而不支持匿名 defaults 部分。注意:一些危险且不推荐的指令故意未在以下矩阵中列出。这是故意的。这些指令都有文档记录。但不在下面列出它们是劝阻任何人使用它们的另一种方式。
本节提供了每个关键字及其用法的描述。
声明或完成一个访问列表。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是(!)![]() | 是![]() | 是![]() | 是![]() |
此指令仅在命名的 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 节。
向系统提供关于期望的侦听积压队列大致大小的提示。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<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。
定义在后端中使用的负载均衡算法。可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<algorithm> 是用于在进行负载均衡时选择服务器的算法。这仅适用于没有持久性信息可用,或者连接被重新分派到另一台服务器时。<algorithm> 可以是以下之一: roundrobin 每个服务器根据其权重轮流使用。当服务器的处理时间保持均匀分布时,这是最平滑和最公平的算法。此算法是动态的,这意味着服务器权重可以即时调整,例如用于慢启动。它在设计上限制为每个后端最多 4095 个活动服务器。请注意,在某些大型集群中,当服务器在非常短的时间内停机后重新启动时,可能需要数百个请求才能重新集成到集群中并开始接收流量。这是正常的,尽管非常罕见。在此指出,以防您有机会观察到它,这样您就不会担心。注意:对于处于 LOG 模式的后端,权重会被忽略。 static-rr 每个服务器根据其权重轮流使用。此算法与 roundrobin 类似,但它是静态的,这意味着即时更改服务器的权重无效。另一方面,它对服务器数量没有设计限制,并且当服务器启动时,一旦重新计算完整映射,它总是立即重新引入集群。它运行所需的 CPU 资源也略少(大约 -1%)。此算法不能在 LOG 模式下使用。 leastconn 具有最低连接数的服务器接收连接。在具有相同负载的服务器组内执行轮询,以确保所有服务器都将被使用。建议在预期有非常长会话(例如 LDAP、SQL、TSE 等)的情况下使用此算法,但不太适合使用短会话的协议(例如 HTTP)。此算法是动态的,这意味着服务器权重可以即时调整,例如用于慢启动。它还会考虑排队连接的数量以及已建立的连接,以最大限度地减少排队。此算法不能在 LOG 模式下使用。 first 具有可用连接槽的第一个服务器接收连接。服务器按照从最低数字标识符到最高数字标识符的顺序选择(请参阅服务器参数 "id"),默认情况下是服务器在集群中的位置。一旦服务器达到其 maxconn 值,将使用下一个服务器。在不设置 maxconn 的情况下使用此算法没有意义。此算法的目的是始终使用最少的服务器数量,以便在非高峰时段可以关闭多余的服务器电源。此算法忽略服务器权重,对长会话(例如 RDP 或 IMAP)的好处大于 HTTP,尽管它在 HTTP 中也可能有用。为了有效地使用此算法,建议云控制器定期检查服务器使用情况,以便在未使用时将其关闭,并定期检查后端队列,以便在队列膨胀时打开新服务器。或者,使用 "http-check send-state" 可以通知服务器负载情况。此算法不能在 LOG 模式下使用。 hash 接受一个常规样本表达式作为参数。表达式对每个请求进行评估,并根据配置的 hash-type 进行哈希处理。哈希结果除以正在运行的服务器的总权重,以指定哪个服务器将接收请求。这可以用来代替 "source"、"uri"、"hdr()"、"url_param()"、"rdp-cookie" 来利用转换器、优化评估,或用于从局部变量中提取数据等。当数据不可用时,将应用 round robin。此算法默认是静态的,这意味着即时更改服务器的权重无效,但这可以通过使用 "hash-type" 进行更改。此算法不能在 LOG 模式的后端中使用,请改用 "log-hash"。 source 源 IP 地址被哈希处理并除以正在运行的服务器的总权重,以指定哪个服务器将接收请求。这确保了只要没有服务器停机或启动,相同的客户端 IP 地址将始终到达同一服务器。如果由于正在运行的服务器数量变化而导致哈希结果发生变化,许多客户端将被定向到不同的服务器。此算法通常用于无法插入 cookie 的 TCP 模式。它也可以在互联网上使用,为拒绝会话 cookie 的客户端提供尽力而为的粘性。此算法默认是静态的,这意味着即时更改服务器的权重无效,但这可以通过使用 "hash-type" 进行更改。另请参阅上面的 "hash" 选项。此算法不能在 LOG 模式的后端中使用。 uri 此算法对 URI 的左侧部分(问号之前)或整个 URI(如果存在 "whole" 参数)进行哈希处理,并将哈希值除以正在运行的服务器的总权重。结果指定哪个服务器将接收请求。这确保了只要没有服务器启动或停机,相同的 URI 将始终定向到同一服务器。这与代理缓存和防病毒代理一起使用,以最大限度地提高缓存命中率。请注意,此算法只能在 HTTP 后端中使用。此算法默认是静态的,这意味着即时更改服务器的权重无效,但这可以通过使用 "hash-type" 进行更改。此算法支持两个可选参数 "len" 和 "depth",两者都后跟一个正整数。当需要仅根据 URI 的开头来平衡服务器时,这些选项可能会有所帮助。"len" 参数指示算法应仅考虑 URI 开头的那么多字符来计算哈希。请注意,将 "len" 设置为 1 很少有意义,因为大多数 URI 都以开头的 "/" 开头。"depth" 参数指示用于计算哈希的最大目录深度。请求中的每个斜杠都算作一个级别。如果同时指定两个参数,则当达到任一参数时,评估停止。"path-only" 参数指示哈希键从路径的第一个 '/' 开始。这可用于忽略绝对 URI 的 authority 部分,并确保 HTTP/1 和 HTTP/2 URI 将提供相同的哈希。另请参阅上面的 "hash" 选项。 url_param 将在每个 HTTP GET 请求的查询字符串中查找参数中指定的 URL 参数。如果使用修饰符 "check_post",则在 URL 中的问号 ('?') 之后的查询字符串中未找到参数时,将在 HTTP POST 请求实体中搜索参数参数。消息正文将仅在收到 advertised 数据量或请求缓冲区已满时才开始分析。在不太可能使用分块编码的情况下,仅扫描第一个分块。如果参数值被分块边界分隔,则即使有平衡,也可能是随机平衡的。此关键字过去支持可选的 <max_wait> 参数,但现在被忽略。如果找到参数后跟等号 ('=') 和一个值,则该值将被哈希处理并除以正在运行的服务器的总权重。结果指定哪个服务器将接收请求。这用于跟踪请求中的用户标识符,并确保只要没有服务器启动或停机,相同的用户 ID 将始终发送到同一服务器。如果未找到值或未找到参数,则应用轮询算法。请注意,此算法只能在 HTTP 后端中使用。此算法默认是静态的,这意味着即时更改服务器的权重无效,但这可以通过使用 "hash-type" 进行更改。另请参阅上面的 "hash" 选项。 hdr(<name>) HTTP 标头 <name> 将在每个 HTTP 请求中查找。就像等效的 ACL 'hdr()' 函数一样,括号中的标头名称不区分大小写。如果标头不存在或不包含任何值,则应用 roundrobin 算法。一个可选的 'use_domain_only' 参数可用,用于将哈希算法减少到主域名部分,并带有一些特定的标头,例如 'Host'。例如,在 Host 值 "haproxy.1wt.eu" 中,只会考虑 "1wt"。此算法默认是静态的,这意味着即时更改服务器的权重无效,但这可以通过使用 "hash-type" 进行更改。另请参阅上面的 "hash" 选项。 random random(<draws>) 一个随机数将用作一致性哈希函数的键。这意味着服务器的权重得到尊重,动态权重更改立即生效,以及新服务器的添加。随机负载均衡对于大型集群或服务器频繁添加或删除时非常有用,因为它可以避免在这种情况下 roundrobin 或 leastconn 可能导致的锤击效应。 hash-balance-factor 指令可用于进一步提高负载均衡的公平性,尤其是在服务器响应时间变化很大的情况下。当存在参数 <draws> 时,它必须是一个大于或等于一的整数值,表示在选择这些服务器中负载最低的服务器之前抽取的次数。事实上,已经证明,在两个服务器中选择负载最低的一个足以显着提高算法的公平性,方法是始终避免在集群中选择负载最高的服务器,并消除一致性列表不公平分布可能导致的任何偏差。较高的值 N 将以牺牲性能为代价,移除 N-1 个负载最高的服务器。值非常高时,算法将收敛到 leastconn 的结果,但速度慢得多。默认值为 2,通常显示出非常好的分布和性能。此算法也称为“两个随机选择的力量”(Power of Two Random Choices),在此处描述:http://www.eecs.harvard.edu/~michaelm/postscripts/handbook2001.pdf 对于处于 LOG 模式的后端,抽取的次数会被忽略,并且只选择一个随机数,因为没有服务器负载的概念。随机日志均衡对于大型集群或服务器频繁添加到可用服务器池中时非常有用,因为它可以避免在这种情况下 roundrobin 可能导致的锤击效应。 rdp-cookie rdp-cookie(<name>) 将为每个传入的 TCP 请求查找 RDP cookie <name>(如果省略则为 "mstshash")并对其进行哈希处理。就像等效的 ACL 'req.rdp_cookie()' 函数一样,名称不区分大小写。此机制可用作降级的持久性模式,因为它使得始终将同一用户(或同一会话 ID)发送到同一服务器成为可能。如果未找到 cookie,则使用正常的 roundrobin 算法。请注意,为了使其工作,前端必须确保请求缓冲区中已存在 RDP cookie。为此,您必须使用 'tcp-request content accept' 规则与 'req.rdp_cookie_cnt' ACL 结合使用。此算法默认是静态的,这意味着即时更改服务器的权重无效,但这可以通过使用 "hash-type" 进行更改。另请参阅上面的 "hash" 选项。 log-hash 接受一个逗号分隔的转换器列表作为参数。这些转换器按顺序应用于输入日志消息,结果将转换为字符串,然后根据配置的 hash-type 进行哈希处理。生成的哈希将用于在日志后端中声明的服务器中选择目标服务器。此算法的目标是能够使用字符串转换器在最终日志消息中提取一个键,然后能够通过哈希粘性到同一服务器。目前仅支持“基于映射”的哈希。此算法仅适用于处于 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 # send all logs to mylog-rrb backend log backend@mylog-hash local0 # send all logs to mylog-hash backend backend mylog-rrb mode log balance roundrobin server s1 udp@127.0.0.1:514 # will receive 50% of log messages server s2 udp@127.0.0.1:514 backend mylog-hash mode log # extract "METHOD URL PROTO" at the end of the log message, # and let haproxy hash it so that log messages generated from # similar requests get sent to the same syslog server: balance log-hash 'field(-2,\")' # server list here server s1 127.0.0.1:514 #... Note: the following caveats and limitations on using the "check_post" extension with "url_param" must be considered : - all POST requests are eligible for consideration, because there is no way to determine if the parameters will be found in the body or entity which may contain binary data. Therefore another method may be required to restrict consideration of POST requests that have no URL parameters in the body. (see acl http_end) - using a <max_wait> value larger than the request buffer size does not make sense and is useless. The buffer size is set at build time, and defaults to 16 kB. - Content-Encoding is not supported, the parameter search will probably fail; and load balancing will fall back to Round Robin. - Expect: 100-continue is not supported, load balancing will fall back to Round Robin. - Transfer-Encoding (RFC7230 3.3.1) is only supported in the first chunk. If the entire parameter value is not present in the first chunk, the selection of server is undefined (actually, defined by how little actually appeared in the first chunk). - This feature does not support generation of a 100, 411 or 501 response. - In some cases, requesting "check_post" MAY attempt to scan the entire contents of a message body. Scanning normally terminates when linear white space or control characters are found, indicating the end of what might be a URL parameter list. This is probably not a concern with SGML type message bodies.
在前端中定义一个或多个监听地址和/或端口。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 否![]() |
<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。QUIC over IPv4 的性能说明同样适用。 - 'rhttp@' [ EXPERIMENTAL ] -> 用于反向 HTTP。地址必须是具有格式 '<backend>/<server>' 的服务器。该服务器将用于实例化与远程地址的连接。监听器将尝试保持 "nbconn" 连接。这是一个实验性功能,需要在绑定之前的一行上使用 "expose-experimental-directives"。您可能想在地址参数中引用一些环境变量,请参阅 section 2.3 有关环境变量的部分。<port_range> 是一个唯一的 TCP 端口,或者是代理将接受上述指定 IP 地址连接的端口范围。对于 TCP 监听器,端口是强制性的。请注意,在 IPv6 地址的情况下,端口始终是最后一个冒号 (':') 之后的数字。范围可以是: - 一个数字端口(例如:'80') - 一个以短划线分隔的端口范围,明确说明下限和上限(例如:'2000-2100'),这些都包含在范围内。必须特别注意端口范围,因为每个 <address:port> 对都会消耗一个套接字(= 一个文件描述符),因此很容易通过简单的范围消耗大量描述符,并耗尽套接字。此外,每个 <address:port> 对在同一系统上运行的所有实例中只能使用一次。请注意,绑定到低于 1024 的端口通常需要特定的权限才能启动程序,这与 'uid' 参数无关。<path> 是一个以斜杠 ('/') 开头的 UNIX 套接字路径。这是 TCP 监听端口的替代方案。HAProxy 将在位于此处的套接字上接收 UNIX 连接。路径必须以斜杠开头,默认情况下是绝对路径。它可以是相对于全局部分中由 "unix-bind" 定义的前缀的相对路径。请注意,前缀加上套接字路径的总长度不能超过 UNIX 套接字的一些系统限制,这些限制通常设置为 107 个字符。<param*> 是同一行上声明的所有套接字共有的参数列表。这些众多参数取决于操作系统和构建选项,并有专门的一节介绍它们。有关详细信息,请参阅 section 5。
可以指定一个由逗号分隔的地址:端口组合列表。然后,前端将监听所有这些地址。一个前端可以监听的地址和端口数量没有固定限制,同样,一个前端中的“bind”语句数量也没有限制。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 套接字族。
捕获并记录请求和响应中的 cookie。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 否![]() |
<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
捕获并记录指定请求头的最后一次出现。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 否![]() |
<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
捕获并记录指定响应头的最后一次出现。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 否![]() |
<name> 是要捕获的头的名称。头名称不区分大小写,但通常的做法是按照它们在响应中出现的样子来写,每个单词的首字母大写。头名称不会出现在日志中,只报告其值,但其在日志中的位置会得到尊重。<length> 是从值中提取并报告在日志中的最大字符数。如果字符串超过 <length>,它将被从右侧截断。
捕获该头最后一次出现的完整值。结果将添加到日志中,位于捕获的请求头之后,并用大括号('{}')括起来。如果捕获了多个头,它们将用竖线('|')分隔,并按照在配置中声明的相同顺序出现。不存在的头将被记录为空字符串。响应头捕获的常见用途包括指示预期返回字节数的 "Content-length" 头,以及跟踪重定向的 "Location" 头。捕获的响应头数量及其长度没有限制,但明智的做法是保持较低的值以限制每个流的内存使用。为了保持同一前端的日志格式一致,头捕获只能在前端中声明。不能在 "defaults" 部分中指定捕获。capture response header Content-length len 9 capture response header Location len 15
设置 TCP 在客户端侧断开连接之前应发送的最大 keepalive 探测次数。可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<count> 是 keepalive 探测的最大次数。
此关键字对应于套接字选项 TCP_KEEPCNT。如果未指定此关键字,则使用系统范围的 TCP 参数 (tcp_keepalive_probes)。此设置的可用性取决于操作系统。已知在 Linux 上可以工作。
设置连接需要保持空闲多长时间后,TCP 开始发送 keepalive 探测,如果启用了在客户端侧发送 TCP keepalive 数据包。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<timeout> 是连接需要保持空闲的时间,之后 TCP 开始发送 keepalive 探测。默认以秒为单位指定,但如果数字后跟单位后缀,也可以是任何其他单位,如本文档开头所述。
此关键字对应于套接字选项 TCP_KEEPIDLE。如果未指定此关键字,则使用系统范围的 TCP 参数 (tcp_keepalive_time)。此设置的可用性取决于操作系统。已知在 Linux 上可以工作。
设置客户端侧各个 keepalive 探测之间的时间。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<timeout> 是各个 keepalive 探测之间的时间。默认以秒为单位指定,但如果数字后跟单位后缀,也可以是任何其他单位,如本文档开头所述。
此关键字对应于套接字选项 TCP_KEEPINTVL。如果未指定此关键字,则使用系统范围的 TCP 参数 (tcp_keepalive_intvl)。此设置的可用性取决于操作系统。已知在 Linux 上可以工作。
启用 HTTP 压缩。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
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 压缩,这些指令将是 no-op:HAProxy 将看到压缩的响应,并且不会再次压缩。如果后端服务器不支持 HTTP 压缩,并且请求中有 Accept-Encoding 标头,HAProxy 将压缩匹配的响应。在以下情况下禁用压缩: * 请求未在 "Accept-Encoding" 标头中通告支持的压缩算法 * 响应消息不是 HTTP/1.1 或更高版本 * HTTP 状态码不是 200、201、202 或 203 之一 * 响应既不包含 "Content-Length" 标头也不包含 "Transfer-Encoding"(其最后一个值是 "chunked") * 响应包含 "Content-Type" 标头,其第一个值以 "multipart" 开头 * 响应在 "Cache-control" 标头中包含 "no-transform" 值 * User-Agent 匹配 "Mozilla/4",除非它是带 XP SP2 的 MSIE 6,或 MSIE 7 及更高版本 * 响应包含 "Content-Encoding" 标头,表示响应已压缩(请参阅 compression offload) * 响应包含无效的 "ETag" 标头或多个 ETag 标头 注意:压缩不会发出 Warning 标头。
compression algo gzip compression type text/html text/plain
使 HAProxy 仅作为压缩卸载器工作。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
"offload" 设置使 HAProxy 删除 Accept-Encoding 头,以防止后端服务器压缩响应。强烈建议不要这样做,因为这意味着所有的压缩工作都将在 HAProxy 所在的单点上完成。然而,在某些部署场景中,HAProxy 可能安装在一个有缺陷的网关前面,该网关的 HTTP 压缩实现有问题且无法关闭。在这种情况下,可以使用 HAProxy 来防止该网关发出无效的负载。在这种情况下,仅仅在配置中删除该头是行不通的,因为它在头被解析之前应用,这会阻止 HAProxy 进行压缩。因此,"offload" 设置应用于此类场景。如果在 defaults 部分中使用此设置,则会发出警告并忽略该选项。
使 haproxy 能够同时压缩请求和响应。有效值为 "request",仅压缩请求;"response",仅压缩响应;或 "both",当您想同时压缩两者时。默认值为 "response"。可在以下上下文中使用:http
在后端启用基于 cookie 的持久性。可在以下上下文中使用: http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<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 用于处理请求的服务器。如果服务器本身设置了此类 cookie,则会将其删除,除非还设置了 "preserve" 选项。在 "insert" 模式下,这还会从传输到服务器的请求中删除 cookie,从而使持久性机制从应用程序的角度来看完全透明。注意:强烈建议不要将 "indirect" 与 "prefix" 一起使用,否则服务器 cookie 更新将不会发送给客户端。 nocache 建议将此选项与 insert 模式结合使用,当客户端和 HAProxy 之间有缓存时,因为它确保如果需要插入 cookie,可缓存的响应将被标记为不可缓存。这很重要,因为如果所有持久性 cookie 都添加到可缓存的主页中,例如,所有客户都将从外部缓存中获取该页面,并且都将共享相同的持久性 cookie,导致一台服务器接收比其他服务器更多的流量。另请参阅 "insert" 和 "postonly" 选项。 postonly 此选项确保仅对 POST 请求的响应执行 cookie 插入。它是 "nocache" 选项的替代方案,因为 POST 响应不可缓存,因此这确保了持久性 cookie 永远不会被缓存。由于大多数站点在第一次 POST(通常是登录请求)之前不需要任何形式的持久性,因此这是一种优化缓存而不会冒险在缓存中找到持久性 cookie 的非常有效的方法。另请参阅 "insert" 和 "nocache" 选项。 preserve 此选项只能与 "insert" 和/或 "indirect" 一起使用。它允许服务器自己发出持久性 cookie。在这种情况下,如果在响应中找到 cookie,HAProxy 将保持不变。这对于例如在注销请求后结束持久性很有用。为此,服务器只需发出一个具有无效值(例如空)或过去日期的 cookie。通过将此机制与 "disable-on-404" 检查选项结合使用,可以执行完全优雅的关机,因为用户在注销后肯定会离开服务器。 httponly 此选项告诉 HAProxy 在插入 cookie 时添加 "HttpOnly" cookie 属性。此属性用于使用户代理不与非 HTTP 组件共享 cookie。请查看 RFC6265 以获取有关此属性的更多信息。 secure 此选项告诉 HAProxy 在插入 cookie 时添加 "Secure" cookie 属性。此属性用于使用户代理永远不会通过非安全通道发出此 cookie,这意味着使用此标志了解的 cookie 将仅通过 SSL/TLS 连接呈现。请查看 RFC6265 以获取有关此属性的更多信息。 domain 此选项允许指定插入 cookie 的域。它需要恰好一个参数:一个有效的域名。如果域以点开头,则允许浏览器将其用于以该名称结尾的任何主机。也可以通过多次调用此选项来指定多个域名。某些浏览器可能对域的数量有小的限制,因此在这样做时要小心。记录显示,向 MSIE 6 或 Firefox 2 发送 10 个域可以正常工作。 maxidle 此选项允许插入的 cookie 在闲置一段时间后被忽略。它仅适用于 insert-mode cookie。当 cookie 发送给客户端时,也会发送发出此 cookie 的日期。在后续呈现此 cookie 时,如果日期早于参数指示的延迟(以秒为单位),则会将其忽略。否则,如果在将响应发送给客户端时需要,它将被刷新。这对于防止从未关闭浏览器的用户在同一服务器上停留太长时间(例如,在集群大小更改后)特别有用。设置此选项且 cookie 没有日期时,它始终被接受,但在响应中会被刷新。这保持了管理员访问其站点的能力。日期比未来 24 小时更远的 cookie 将被忽略。这样做可以让管理员修复时区问题,而不会冒将用户踢出站点的风险。 maxlife 此选项允许插入的 cookie 在一段时间后被忽略,无论它们是否在使用中。它仅适用于 insert mode cookie。当 cookie 第一次发送给客户端时,也会发送发出此 cookie 的日期。在后续呈现此 cookie 时,如果日期早于参数指示的延迟(以秒为单位),则会将其忽略。如果请求中的 cookie 没有日期,它将被接受并设置日期。日期比未来 24 小时更远的 cookie 将被忽略。这样做可以让管理员修复时区问题,而不会冒将用户踢出站点的风险。与 maxidle 相反,此值不会刷新,仅计算第一次访问日期。maxidle 和 maxlife 可以同时使用。这对于防止从未关闭浏览器的用户在同一服务器上停留太长时间(例如,在集群大小更改后)特别有用。这比 maxidle 方法更强,因为它强制在某些绝对延迟后重新分派。 dynamic 激活动态 cookie。使用时,将为每个服务器动态创建一个会话 cookie,基于服务器的 IP 和端口以及在 "dynamic-cookie-key" 后端指令中指定的密钥。每次 IP 地址更改时,cookie 都会重新生成,并且仅针对 IPv4/IPv6 生成。 attr 此选项告诉 HAProxy 在插入 cookie 时添加额外的属性。属性值可以包含除控制字符或 ";" 之外的任何字符。此选项可以重复。
每个 HTTP 后端只能有一个持久性 cookie,并且可以在 defaults 部分声明。cookie 的值将是 "server" 语句中 "cookie" 关键字后面指示的值。如果未为给定服务器声明 cookie,则不会设置 cookie。
cookie JSESSIONID prefix cookie SRV insert indirect nocache cookie SRV insert postonly indirect cookie SRV insert indirect nocache maxidle 30m maxlife 8h
声明一个捕获槽。可在以下上下文中使用: tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 否![]() |
<length> 是允许捕获的长度。
此声明仅在 frontend 或 listen 配置段中可用,但保留的槽可以在 backend 中使用。“request”关键字分配一个用于请求中的捕获槽,“response”分配一个用于响应中的捕获槽。
更改后端中服务器的默认选项。可在以下上下文中使用: tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<param*> 是此服务器的参数列表。“default-server”关键字接受大量选项,并有专门的完整章节介绍。更多详情请参阅 第 5 节。
default-server inter 1000 weight 13
指定当没有匹配的 “use_backend” 规则时使用的后端。可在以下上下文中使用: tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<backend> 是要使用的后端的名称。
在使用“use_backend”关键字在前端和后端之间进行内容切换时,指明在没有规则匹配时将使用哪个后端通常很有用。这通常是动态后端,它将捕获所有未确定的请求。
use_backend dynamic if url_dyn use_backend static if url_css url_img extension_img default_backend dynamic
描述一个 listen、frontend 或 backend。可在以下上下文中使用: tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
允许添加一句话来在 HAProxy HTML 统计页面中描述相关对象。该描述将打印在其所描述对象名称的右侧。<string> 参数中的空格无需使用反斜杠转义。
禁用一个代理、前端或后端。可在以下上下文中使用: tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
"disabled" 关键字用于禁用实例,主要用于释放监听端口或临时禁用服务。实例仍将创建并检查其配置,但它将以 "stopped" 状态创建,并在统计信息中显示为如此。它不会接收任何流量,也不会发送任何健康检查或日志。通过在 "defaults" 部分中添加 "disabled" 关键字,可以一次禁用多个实例。
设置一个默认服务器地址。可在以下上下文中使用: tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<address> 是默认服务器的 IPv4 地址。或者,也支持可解析的主机名,但此名称将在启动期间解析。<ports> 是一个强制性的端口规范。所有连接都将发送到此端口,并且不允许像普通服务器那样使用端口偏移量。
“dispatch”关键字指定一个默认服务器,用于在没有其他服务器可以接收连接时使用。过去,它被用来将非持久性连接转发到一个辅助负载均衡器。由于其语法简单,它也被用于简单的 TCP 中继。为了更清晰,建议不要使用它,而是使用“server”指令。
为后端设置动态 cookie 的密钥。可在以下上下文中使用: http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
当启用动态 cookie 时(参见 cookie 的 "dynamic" 指令),会为每个服务器创建一个动态 cookie(除非在“server”行上明确指定了一个),使用服务器的 IP 地址、TCP 端口和密钥的哈希值。这样,我们可以确保跨多个负载均衡器的会话持久性,即使服务器是动态添加或删除的。启用一个代理、前端或后端。可在以下上下文中使用: tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
"enabled" 关键字用于显式启用实例,当 defaults 已设置为 "disabled" 时。这很少使用。
返回文件内容,而不是由 HAProxy 生成的错误。可在以下上下文中使用: http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<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 检测并返回的错误。这就是支持的错误列表仅限于一小组的原因。在响应匹配 "monitor-uri" 规则的请求时,会发出代码 200。文件在 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
全部或部分地导入在 <name> http-errors 部分中定义的错误文件。可在以下上下文中使用: http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<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
返回一个到 URL 的 HTTP 重定向,而不是由 HAProxy 生成的错误。可在以下上下文中使用: http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<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。
返回一个到 URL 的 HTTP 重定向,而不是由 HAProxy 生成的错误。可在以下上下文中使用: http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<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 之前设计的非常旧的浏览器可能不支持它,但到目前为止还没有报告过此类问题。
声明在电子邮件警报的信封和标头中使用的发件人电子邮件地址。这是发送电子邮件警报的地址。可在以下上下文中使用: tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<emailaddr> 是发送电子邮件警报时使用的发件人电子邮件地址
还需要设置“email-alert mailers”和“email-alert to”,如果设置了,则为该代理启用电子邮件警报发送功能。
声明将发送电子邮件警报的消息的最大日志级别。这充当发送电子邮件警报的过滤器。可在以下上下文中使用: tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<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 或更低,并且发生了健康检查状态更新
声明发送电子邮件警报时要使用的邮件发送器。可在以下上下文中使用: tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<mailersect> 是用于发送电子邮件警报的邮件程序部分的名称。
还需要设置“email-alert from”和“email-alert to”,如果设置了,则为该代理启用电子邮件警报发送功能。
声明与邮件发送器通信时使用的目标主机名地址。可在以下上下文中使用: tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<hostname> 是与邮件程序通信时使用的主机名
默认使用系统的主机名。还需要设置“email-alert from”、“email-alert mailers”和“email-alert to”,如果设置了,则为该代理启用电子邮件警报发送功能。
声明电子邮件警报的信封中的收件人地址和标头中的收件人地址。这是发送电子邮件警报的目标地址。可在以下上下文中使用: tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<emailaddr> 是发送电子邮件警报时使用的收件人电子邮件地址
还需要设置“email-alert mailers”和“email-alert to”,如果设置了,则为该代理启用电子邮件警报发送功能。
指定在前端发生连接错误时要使用的日志格式字符串。可在以下上下文中使用: tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
该指令指定了用于包含与错误、超时、重试、重新分派或 HTTP 状态码 5xx 相关信息的日志的格式字符串。简而言之,此格式将用于所有会受 “log-separate-errors” 选项影响的日志行,包括在第 8.2.5 节中描述的连接错误。如果在 defaults 部分中使用该指令,所有后续的前端都将使用相同的日志格式。请参阅深入介绍自定义日志格式字符串的第 8.2.6 节。“error-log-format” 指令会覆盖之前的 “error-log-format” 指令。
声明一个条件,以在服务器宕机时强制持久性。可在以下上下文中使用: tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
默认情况下,请求不会分派到宕机的服务器。可以使用 "option persist" 强制执行此操作,但它是无条件的,并且如果设置了 "option redispatch",则会重新分派到有效的服务器。这使得强制某些请求到达因维护操作而被人工标记为宕机的服务器的可能性非常小。"force-persist" 语句允许声明各种基于 ACL 的条件,当满足这些条件时,将导致请求忽略服务器的宕机状态,并仍然尝试连接到它。这使得启动服务器成为可能,该服务器仍回复健康检查错误,并运行特殊配置的浏览器来测试服务。在方便的方法中,可以使用特定的源 IP 地址或特定的 cookie。cookie 还有一个优势,即可以很容易地从测试页面在浏览器上添加/删除。一旦服务通过验证,就可以通过返回对健康检查的有效响应来向全世界开放服务。当满足 "if" 条件时,或除非满足 "unless" 条件时,强制持久性被启用。当使用此功能时,最终的重新分派始终被禁用。
将过滤器 <name> 添加到附加到代理的过滤器列表中。可在以下上下文中使用: tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
<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
指定后端负载达到何种程度时,服务器将达到其 maxconn。可在以下上下文中使用: tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<conns> 是后端上的连接数,该连接数将使服务器使用最大连接数。
当服务器指定了 "maxconn" 参数时,这意味着其并发连接数永远不会更高。此外,如果它有 "minconn" 参数,则表示一个跟随后端负载的动态限制。服务器将始终接受至少 <minconn> 个连接,永远不超过 <maxconn>,并且当后端并发连接数小于 <conns> 时,限制将在两个值之间逐渐增加。这使得可以在正常负载期间限制服务器上的负载,但在重要负载期间进一步推动它,而不会在特殊负载期间使服务器过载。由于很难正确设置此值,HAProxy 会自动将其设置为所有可能分支到此后端的 frontend 的 maxconn 总和的 10%(基于 "use_backend" 和 "default_backend" 规则)。这样,将其留空是安全的。但是,涉及动态名称的 "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
为此代理指定一个区分大小写的全局唯一 ID。可在以下上下文中使用: tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
<string> 在所有 haproxy 配置的所有对象类型中必须是唯一的。格式未指定,以允许用户选择其命名策略。唯一的限制是其长度不能超过 127 个字符。所有字母数字值和 '.'、':'、'-' 和 '_' 字符都是有效的。
为有界负载一致性哈希指定平衡因子。可在以下上下文中使用: tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 否![]() | 是![]() |
<factor> 是控制发送到服务器的最大并发请求数的参数,表示为所有活动服务器上平均并发请求数的百分比。
为具有 "hash-type consistent" 的服务器指定 "hash-balance-factor" 可启用一种算法,该算法可防止任何一台服务器同时接收过多请求,即使某些哈希桶接收的请求比其他哈希桶多得多。将 <factor> 设置为 0(默认值)将禁用此功能。否则,<factor> 是一个大于 100 的百分比。例如,如果 <factor> 为 150,则任何服务器的负载都不会超过平均负载的 1.5 倍。如果使用服务器权重,它们将得到尊重。如果第一选择服务器被取消资格,算法将根据请求哈希选择另一台服务器,直到找到具有额外容量的服务器。较高的 <factor> 允许服务器之间更大的不平衡,而较低的 <factor> 意味着平均将检查更多服务器,从而影响性能。合理的值范围是 125 到 200。此设置也用于 "balance random",它在内部依赖于一致性哈希机制。
指定一种用于将哈希映射到服务器的方法。可在以下上下文中使用: tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<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)的倍数时,出现任何不良影响。启用 avalanche 倾向于使结果更不可预测,但也不如使用原始函数平滑。可能需要对某些工作负载进行一些测试。此哈希是 Bob Jenkins 提出的众多哈希之一。
默认的哈希类型是“map-based”,建议在大多数情况下使用。默认的函数是“sdbm”,函数的选择应基于被哈希值的范围。
对所有第 7 层响应(服务器、小程序/服务和内部响应)进行访问控制。可在以下上下文中使用: http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是(!)![]() | 是![]() | 是![]() | 是![]() |
http-after-response 语句定义了一组适用于第 7 层处理的规则。这些规则在前端、监听或后端部分中按声明顺序评估。由于这些规则适用于响应,因此首先应用后端规则,然后应用前端规则。任何规则都可以选择后跟一个基于 ACL 的条件,在这种情况下,只有当条件评估为真时才会评估该规则。与 http-response 规则不同,这些规则适用于所有响应,即服务器响应,也适用于 HAProxy 生成的所有响应。这些规则在响应分析结束时、数据转发阶段之前进行评估。条件在执行操作之前立即评估,并且操作仅执行一次。因此,如果操作更改了作为条件一部分检查的元素,则没有问题。这也意味着多个操作可以依赖于相同的条件,因此更改条件评估的第一个操作足以隐式禁用其余操作。例如,当尝试从各种来源为变量赋值(当它为空时)时,会使用此方法。每个实例的 "http-after-response" 语句数量没有限制。语法中 "http-after-response" 之后的第一个关键字是规则的操作,可选择后跟可变数量的操作参数。支持的操作及其各自的语法在第 4.3 节“操作”中列举(查找选中“HTTP Aft”的操作)。此指令仅在命名 defaults 部分可用,而不在匿名部分可用。在 defaults 部分中定义的规则在相关代理部分中的规则之前进行评估。为避免歧义,在这种情况下,具有 frontend 能力的代理和具有 backend 能力的代理不能使用相同的 defaults 部分。这意味着 listen 部分不能使用定义此类规则的 defaults 部分。注意:在请求解析的早期阶段发出的错误由多路复用器在较低级别处理,在任何 http 分析之前。因此,不会对这些错误评估 http-after-response 规则集。
http-after-response set-header Strict-Transport-Security "max-age=31536000" http-after-response set-header Cache-Control "no-store,no-cache,private" http-after-response set-header Pragma "no-cache"
为接下来的 http-check 规则定义一个注释,如果失败,将在日志中报告。可在以下上下文中使用: tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<string> 是如果以下 http-check 规则失败时要在日志中添加的注释消息。
它仅适用于 connect、send 和 expect 规则。这对于进行用户友好的错误报告很有用。
打开一个新连接以执行 HTTP 健康检查。可在以下上下文中使用: tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
comment <msg> 定义当规则评估失败时要报告的消息。 default 使用服务器行的默认选项进行健康检查。仅当未重新定义时才使用服务器选项。 port <expr> 如果未设置,则使用检查端口或服务器端口。它告诉 HAProxy 连接到哪里。<port> 必须是有效的 TCP 端口整数,从 1 到 65535,或一个样本获取表达式。 addr <ip> 定义执行健康检查的 IP 地址。 send-proxy 发送 PROXY 协议字符串 via-socks4 使用上游 socks4 代理启用传出健康检查。 ssl 打开加密连接 sni <sni> 指定用于通过 SSL 执行健康检查的 SNI。 alpn <alpn> 定义要使用 ALPN 通告的协议。协议列表由逗号分隔的协议名称列表组成,例如:"h2,http/1.1"。如果未设置,则使用服务器 ALPN。 proto <name> 强制用于此连接的多路复用器协议。它必须是 HTTP mux 协议,并且必须可以在后端使用。可用协议列表在 haproxy -vv 中报告。 linger 干净地关闭连接,而不是使用单个 RST。
就像 tcp-check 健康检查一样,可以配置用于执行 HTTP 健康检查的连接。此指令也应用于描述涉及多个请求/响应交换的场景,可能在不同的端口上或与不同的服务器。当服务器行上既没有配置 TCP 端口,也没有服务器端口指令时,http-check 序列的第一步必须是使用 “http-check connect” 指定端口。在一个 http-check 规则集中,'connect' 是必需的,并且也必须以 'connect' 规则开始规则集。目的是确保管理员知道他们在做什么。当一个 connect 必须开始规则集时,它前面仍然可以有 set-var、unset-var 或 comment 规则。
# 检查服务器上的 HTTP 和 HTTPs 服务。 # 首先通过服务器行端口指令打开端口 80,然后 # tcp-check 打开端口 443,加密并在其上运行请求: option httpchk http-check connect http-check send meth GET uri / ver HTTP/1.1 hdr host haproxy.1wt.eu http-check expect status 200-399 http-check connect port 443 ssl sni haproxy.1wt.eu http-check send meth GET uri / ver HTTP/1.1 hdr host haproxy.1wt.eu http-check expect status 200-399 server www 10.0.0.1 check port 80
在健康检查响应为 HTTP/404 时启用维护模式。可在以下上下文中使用: tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
当设置此选项时,返回 HTTP 404 状态码的服务器将从后续的负载均衡中排除,但仍会接收持久连接。这为 Web 管理员提供了一种非常方便的方法来对其服务器进行平滑关闭。同样重要的是要注意,在此模式下被检测为失败的服务器不会生成警报,只会生成一个通知。如果服务器再次响应 2xx 或 3xx,它将立即重新插入到服务器场中。统计页面上的状态为此模式下的服务器报告为 "NOLB"。重要的是要注意,此选项仅与 “httpchk” 选项一起使用。如果此选项与 “http-check expect” 一起使用,则它优先于后者,因此 404 响应仍将被视为软停止。还要注意,已停止的服务器即使响应 404s 也会保持停止状态。此选项仅对正在运行的服务器进行评估。
使 HTTP 健康检查考虑响应内容或特定状态码。可在以下上下文中使用: tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
comment <msg> 定义当规则评估失败时要报告的消息。 min-recv 是可选的,可以定义评估当前 expect 规则所需的最小数据量。如果接收到的字节数低于此限制,检查将等待更多数据。此选项可用于解决一些模糊的匹配规则,或避免对已知仍不完整的内容执行代价高昂的正则表达式匹配。如果使用精确字符串,则使用字符串长度和此参数之间的最小值。如果此参数设置为 -1,则忽略此参数。如果 expect 规则不匹配,检查将等待更多数据。如果设置为 0,则评估结果始终是结论性的。 ok-status <st> 是可选的,可用于设置检查状态,如果 expect 规则成功评估并且它是 tcp-check 规则集中的最后一条规则。"L7OK"、"L7OKC"、"L6OK" 和 "L4OK" 受支持: - L7OK:检查通过第 7 层 - L7OKC:检查有条件通过第 7 层,将服务器设置为 NOLB 状态。 - L6OK:检查通过第 6 层 - L4OK:检查通过第 4 层 默认使用 "L7OK"。 error-status <st> 是可选的,可用于设置检查状态,如果在 expect 规则评估期间发生错误。"L7OKC"、"L7RSP"、"L7STS"、"L6RSP" 和 "L4CON" 受支持: - L7OKC:检查有条件通过第 7 层,将服务器设置为 NOLB 状态。 - L7RSP:第 7 层无效响应 - 协议错误 - L7STS:第 7 层响应错误,例如 HTTP 5xx - L6RSP:第 6 层无效响应 - 协议错误 - L4CON:第 1-4 层连接问题 默认使用 "L7RSP"。 tout-status <st> 是可选的,可用于设置检查状态,如果在 expect 规则评估期间发生超时。"L7TOUT"、"L6TOUT" 和 "L4TOUT" 受支持: - L7TOUT:第 7 层(HTTP/SMTP)超时 - L6TOUT:第 6 层(SSL)超时 - L4TOUT:第 1-4 层超时 默认使用 "L7TOUT"。 on-success <fmt> 是可选的,可用于自定义日志中报告的信息消息,如果 expect 规则成功评估并且它是 tcp-check 规则集中的最后一条规则。<fmt> 是一个自定义日志格式字符串(请参阅 section 8.2.6)。 on-error <fmt> 是可选的,可用于自定义日志中报告的信息消息,如果在 expect 规则评估期间发生错误。<fmt> 是一个自定义日志格式字符串(请参阅 section 8.2.6)。 <match> 是一个关键字,指示如何在响应中查找特定模式。关键字可以是 "status"、"rstatus"、"hdr"、"fhdr"、"string" 或 "rstring" 之一。关键字前面可以有感叹号 ("!") 来否定匹配。感叹号和关键字之间允许有空格。有关支持的关键字的更多详细信息,请参阅下文。 <pattern> 是要查找的模式。它可以是一个字符串、一个正则表达式或一个具有多个参数的更复杂模式。如果字符串模式包含空格,则必须使用通常的反斜杠 ('\') 进行转义。
默认情况下,"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> 被评估为自定义日志格式字符串(请参阅 section 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 响应正文中测试自定义日志格式字符串(请参阅 section 8.2.6)匹配。如果响应正文包含评估 <fmt> 产生的字符串(遵循日志格式规则),则健康检查响应将被视为有效。如果带有 "!" 前缀,则如果正文包含字符串,则响应将被视为无效。重要的是要注意,响应将限制为由全局 "tune.bufsize" 选项定义的特定大小,该选项默认为 16384 字节。因此,当使用 "string" 或 "rstring" 时,太大的响应可能不包含强制模式。如果绝对需要大响应,可以通过设置全局变量更改默认最大大小。但是,值得记住的是,解析非常大的响应会浪费一些 CPU 周期,尤其是在使用正则表达式时,并且始终最好将检查集中在较小的资源上。在 http-check 规则集中,最后一个 expect 规则可以是隐式的。如果在最后一个 "http-check send" 之后未指定 expect 规则,则定义一个隐式 expect 规则以匹配 2xx 或 3xx 状态码。这意味着,当只设置 "option httpchk" 时,如果没有 "http-check" 规则,也会定义此规则。最后,如果 "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 健康检查期间发送的请求添加可能的头列表和/或主体。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
comment <msg> 定义当规则评估失败时要报告的消息。 meth <method> 是与请求一起使用的可选 HTTP 方法。如果未设置,则使用 "OPTIONS" 方法,因为它通常需要较低的服务器处理,并且易于从日志中过滤掉。可以使用任何方法,但不建议发明非标准方法。 uri <uri> 是可选的,并将 HTTP 请求中引用的 URI 设置为字符串 <uri>。它默认为 "/",几乎在任何服务器上都可以默认访问,但可以更改为任何其他 URI。允许使用查询字符串。 uri-lf <fmt> 是可选的,并使用自定义日志格式 <fmt>(请参阅 section 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> 遵循 section 8.2.6 中描述的自定义日志格式规则。 body <string> 将由 <string> 定义的正文添加到 HTTP 健康检查期间发送的请求中。如果定义了,则 "Content-Length" 标头会自动添加到请求中。 body-lf <fmt> 将由自定义日志格式 <fmt>(请参阅 section 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 标头和请求 authority 都定义时,它们会自动同步。这意味着当发送 HTTP 请求时,当 Host 插入到请求中时,请求 authority 会相应更新。因此,如果 Host 标头值覆盖了配置的请求 authority,请不要感到惊讶。另请注意,目前没有 Host 标头会自动添加到 HTTP/1.1 或更高版本的请求中。您应该显式添加它。
在 HTTP 健康检查中启用状态头的发送。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
When this option is set, HAProxy will systematically send a special header "X-Haproxy-Server-State" with a list of parameters indicating to each server how they are seen by HAProxy. This can be used for instance when a server is manipulated without access to HAProxy and the operator needs to know whether HAProxy still sees it up or not, or if the server is the last one in a farm. The header is composed of fields delimited by semi-colons, the first of which is a word ("UP", "DOWN", "NOLB"), possibly followed by a number of valid checks on the total number before transition, just as appears in the stats interface. Next headers are in the form "<variable>=<value>", indicating in no specific order some values available in the stats interface : - a variable "address", containing the address of the backend server. This corresponds to the <address> field in the server declaration. For unix domain sockets, it will read "unix". - a variable "port", containing the port of the backend server. This corresponds to the <port> field in the server declaration. For unix domain sockets, it will read "unix". - a variable "name", containing the name of the backend followed by a slash ("/") then the name of the server. This can be used when a server is checked in multiple backends. - a variable "node" containing the name of the HAProxy node, as set in the global "node" variable, otherwise the system's hostname if unspecified. - a variable "weight" indicating the weight of the server, a slash ("/") and the total weight of the farm (just counting usable servers). This helps to know if other servers are available to handle the load when this one fails. - a variable "scur" indicating the current number of concurrent connections on the server, followed by a slash ("/") then the total number of connections on all servers of the same backend. - a variable "qcur" indicating the current number of requests in the server's queue. Example of a header received by the application server : >>> X-Haproxy-Server-State: UP 2/3; name=bck/srv2; node=lb1; weight=1/2; \ scur=13/22; qcur=0
此操作设置变量的内容。变量是内联声明的。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<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
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
http-check unset-var(check.port)
定义一个自定义错误消息,以替代 HAProxy 生成的错误。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
status <code> is the HTTP status code. It must be specified. Currently, HAProxy is capable of generating codes 200, 400, 401, 403, 404, 405, 407, 408, 410, 413, 414, 425, 429, 431, 500, 501, 502, 503, and 504. content-type <type> is the response content type, for instance "text/plain". This parameter is ignored and should be omitted when an errorfile is configured or when the payload is empty. Otherwise, it must be defined. default-errorfiles Reset the previously defined error message for current proxy for the status <code>. If used on a backend, the frontend error message is used, if defined. If used on a frontend, the default error message is used. errorfile <file> designates a file containing the full HTTP response. It is recommended to follow the common practice of appending ".http" to the filename so that people do not confuse the response with HTML error pages, and to use absolute paths, since files are read before any chroot is performed. errorfiles <name> designates the http-errors section to use to import the error message with the status code <code>. If no such message is found, the proxy's error messages are considered. file <file> specifies the file to use as response payload. If the file is not empty, its content-type must be set as argument to "content-type", otherwise, any "content-type" argument is ignored. <file> is considered as a raw string. string <str> specifies the raw string to use as response payload. The content-type must always be set as argument to "content-type". lf-file <file> specifies the file to use as response payload. If the file is not empty, its content-type must be set as argument to "content-type", otherwise, any "content-type" argument is ignored. <file> is evaluated as a Custom log format (see section 8.2.6). lf-string <str> specifies the log-format string to use as response payload. The content-type must always be set as argument to "content-type". hdr <name> <fmt> adds to the response the HTTP header field whose name is specified in <name> and whose value is defined by <fmt>, which follows the Custom log format rules (see section 8.2.6). This parameter is ignored if an errorfile is used.
This directive may be used instead of "errorfile", to define a custom error message. As "errorfile" directive, it is used for errors detected and returned by HAProxy. If an errorfile is defined, it is parsed when HAProxy starts and must be valid according to the HTTP standards. The generated response must not exceed the configured buffer size (BUFFSIZE), otherwise an internal error will be returned. Finally, if you consider to use some http-after-response rules to rewrite these errors, the reserved buffer space should be available (see "tune.maxrewrite"). The files are read at the same time as the configuration and kept in memory. For this reason, the errors continue to be returned even when the process is chrooted, and no file change is considered while the process is running. Note: 400/408/500 errors emitted in early stage of the request parsing are handled by the multiplexer at a lower level. No custom formatting is supported at this level. Thus only static error messages, defined with "errorfile" directive, are supported. However, this limitation only exists during the request headers parsing or between two transactions.
第 7 层请求的访问控制 可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是(!)![]() | 是![]() | 是![]() | 是![]() |
The http-request statement defines a set of rules which apply to layer 7 processing. The rules are evaluated in their declaration order when they are met in a frontend, listen or backend section. Any rule may optionally be followed by an ACL-based condition, in which case it will only be evaluated if the condition evaluates to true. The condition is evaluated just before the action is executed, and the action is performed exactly once. As such, there is no problem if an action changes an element which is checked as part of the condition. This also means that multiple actions may rely on the same condition so that the first action that changes the condition's evaluation is sufficient to implicitly disable the remaining actions. This is used for example when trying to assign a value to a variable from various sources when it's empty. There is no limit to the number of "http-request" statements per instance. The first keyword after "http-request" in the syntax is the rule's action, optionally followed by a varying number of arguments for the action. The supported actions and their respective syntaxes are enumerated in section 4.3 "Actions" (look for actions which tick "HTTP Req"). This directive is only available from named defaults sections, not anonymous ones. Rules defined in the defaults section are evaluated before ones in the associated proxy section. To avoid ambiguities, in this case the same defaults section cannot be used by proxies with the frontend capability and by proxies with the backend capability. It means a listen section cannot use a defaults section defining such rules.
acl nagios src 192.168.129.3 acl local_net src 192.168.0.0/16 acl auth_ok http_auth(L1) http-request allow if nagios http-request allow if local_net auth_ok http-request auth realm Gimme if local_net auth_ok http-request deny
acl key req.hdr(X-Add-Acl-Key) -m found acl add path /addacl acl del path /delacl acl myhost hdr(Host) -f myhost.lst http-request add-acl(myhost.lst) %[req.hdr(X-Add-Acl-Key)] if key add http-request del-acl(myhost.lst) %[req.hdr(X-Add-Acl-Key)] if key del
acl value req.hdr(X-Value) -m found acl setmap path /setmap acl delmap path /delmap use_backend bk_appli if { hdr(Host),map_str(map.lst) -m found } http-request set-map(map.lst) %[src] %[req.hdr(X-Value)] if setmap value http-request del-map(map.lst) %[src] if delmap
第 7 层响应的访问控制 可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是(!)![]() | 是![]() | 是![]() | 是![]() |
The http-response statement defines a set of rules which apply to layer 7 processing. The rules are evaluated in their declaration order when they are met in a frontend, listen or backend section. Since these rules apply on responses, the backend rules are applied first, followed by the frontend's rules. Any rule may optionally be followed by an ACL-based condition, in which case it will only be evaluated if the condition evaluates to true. The condition is evaluated just before the action is executed, and the action is performed exactly once. As such, there is no problem if an action changes an element which is checked as part of the condition. This also means that multiple actions may rely on the same condition so that the first action that changes the condition's evaluation is sufficient to implicitly disable the remaining actions. This is used for example when trying to assign a value to a variable from various sources when it's empty. There is no limit to the number of "http-response" statements per instance. The first keyword after "http-response" in the syntax is the rule's action, optionally followed by a varying number of arguments for the action. The supported actions and their respective syntaxes are enumerated in section 4.3 "Actions" (look for actions which tick "HTTP Res"). This directive is only available from named defaults sections, not anonymous ones. Rules defined in the defaults section are evaluated before ones in the associated proxy section. To avoid ambiguities, in this case the same defaults section cannot be used by proxies with the frontend capability and by proxies with the backend capability. It means a listen section cannot use a defaults section defining such rules.
acl key_acl res.hdr(X-Acl-Key) -m found acl myhost hdr(Host) -f myhost.lst http-response add-acl(myhost.lst) %[res.hdr(X-Acl-Key)] if key_acl http-response del-acl(myhost.lst) %[res.hdr(X-Acl-Key)] if key_acl
acl value res.hdr(X-Value) -m found use_backend bk_appli if { hdr(Host),map_str(map.lst) -m found } http-response set-map(map.lst) %[src] %[res.hdr(X-Value)] if value http-response del-map(map.lst) %[src] if ! value
声明如何在请求之间共享空闲的 HTTP 连接 可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
In order to avoid the cost of setting up new connections to backend servers for each HTTP request, HAProxy tries to keep such idle connections opened after being used. These connections are specific to a server and are stored in a list called a pool, and are grouped together by a set of common key properties. Subsequent HTTP requests will cause a lookup of a compatible connection sharing identical properties in the associated pool and result in this connection being reused instead of establishing a new one. A limit on the number of idle connections to keep on a server can be specified via the "pool-max-conn" server keyword. Unused connections are periodically purged according to the "pool-purge-delay" interval. The following connection properties are used to determine if an idle connection is eligible for reuse on a given request: - source and destination addresses - proxy protocol - TOS and mark socket options - connection name, determined either by the result of the evaluation of the "pool-conn-name" expression if present, otherwise by the "sni" expression In some occasions, connection lookup or reuse is not performed due to extra restrictions. This is determined by the reuse strategy specified via the keyword argument: - "never" : idle connections are never shared between sessions. This mode may be enforced to cancel a different strategy inherited from a defaults section or for troubleshooting. For example, if an old bogus application considers that multiple requests over the same connection come from the same client and it is not possible to fix the application, it may be desirable to disable connection sharing in a single backend. An example of such an application could be an old HAProxy using cookie insertion in tunnel mode and not checking any request past the first one. - "safe" : this is the default and the recommended strategy. The first request of a session is always sent over its own connection, and only subsequent requests may be dispatched over other existing connections. This ensures that in case the server closes the connection when the request is being sent, the browser can decide to silently retry it. Since it is exactly equivalent to regular keep-alive, there should be no side effects. There is also a special handling for the connections using protocols subject to Head-of-line blocking (backend with h2 or fcgi). In this case, when at least one stream is processed, the used connection is reserved to handle streams of the same session. When no more streams are processed, the connection is released and can be reused. - "aggressive" : this mode may be useful in webservices environments where all servers are not necessarily known and where it would be appreciable to deliver most first requests over existing connections. In this case, first requests are only delivered over existing connections that have been reused at least once, proving that the server correctly supports connection reuse. It should only be used when it's sure that the client can retry a failed request once in a while and where the benefit of aggressive connection reuse significantly outweighs the downsides of rare connection failures. - "always" : this mode is only recommended when the path to the server is known for never breaking existing connections quickly after releasing them. It allows the first request of a session to be sent to an existing connection. This can provide a significant performance increase over the "safe" strategy when the backend is a cache farm, since such components tend to show a consistent behavior and will benefit from the connection sharing. It is recommended that the "http-keep-alive" timeout remains low in this mode so that no dead connections remain usable. In most cases, this will lead to the same performance gains as "aggressive" but with more risks. It should only be used when it improves the situation over "aggressive". Also note that connections with certain bogus authentication schemes (relying on the connection) like NTLM are marked private if possible and never shared. This won't be the case however when using a protocol with multiplexing abilities and using reuse mode level value greater than the default "safe" strategy as in this case nothing prevents the connection from being already shared. The rules to decide to keep an idle connection opened or to close it after processing are also governed by the "tune.pool-low-fd-ratio" (default: 20%) and "tune.pool-high-fd-ratio" (default: 25%). These correspond to the percentage of total file descriptors spent in idle connections above which haproxy will respectively refrain from keeping a connection opened after a response, and actively kill idle connections. Some setups using a very high ratio of idle connections, either because of too low a global "maxconn", or due to a lot of HTTP/2 or HTTP/3 traffic on the frontend (few connections) but HTTP/1 connections on the backend, may observe a lower reuse rate because too few connections are kept open. It may be desirable in this case to adjust such thresholds or simply to increase the global "maxconn" value. When thread groups are explicitly enabled, it is important to understand that idle connections are only usable between threads from a same group. As such it may happen that unfair load between groups leads to more idle connections being needed, causing a lower reuse rate. The same solution may then be applied (increase global "maxconn" or increase pool ratios).
向请求添加服务器名称。使用由 <header> 给出的头字符串。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<header> 用于发送服务器名称的头字符串。
The "http-send-name-header" statement causes the header field named <header> to be set to the name of the target server at the moment the request is about to be sent on the wire. Any existing occurrences of this header are removed. Upon retries and redispatches, the header field is updated to always reflect the server being attempted to connect to. Given that this header is modified very late in the connection setup, it may have unexpected effects on already modified headers. For example using it with transport-level header such as connection, content-length, transfer-encoding and so on will likely result in invalid requests being sent to the server. Additionally it has been reported that this directive is currently being used as a way to overwrite the Host header field in outgoing requests; while this trick has been known to work as a side effect of the feature for some time, it is not officially supported and might possibly not work anymore in a future version depending on the technical difficulties this feature induces. A long-term solution instead consists in fixing the application which required this trick so that it binds to the correct host name.
为代理设置一个持久 ID。可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
为代理设置一个持久 ID。此 ID 必须是唯一的正数。如果未设置,将自动分配一个未使用的 ID。第一个分配的值将是 1。此 ID 当前仅在统计信息中返回。
声明一个忽略持久性的条件。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
默认情况下,当启用 cookie 持久性时,每个包含该 cookie 的请求都是无条件持久的(假设目标服务器正常运行)。"ignore-persist" 语句允许声明各种基于 ACL 的条件,当满足这些条件时,请求将忽略持久性。这有时对于负载均衡静态文件的请求很有用,因为这些文件通常不需要持久性。这也可以用于完全禁用特定 User-Agent 的持久性(例如,某些网络爬虫机器人)。 当 "if" 条件满足时,或者除非 "unless" 条件满足时,持久性将被忽略。
acl url_static path_beg /static /images /img /css acl url_static path_end .gif .png .jpg .css .js ignore-persist if url_static
允许 HAProxy 的无缝重载。可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
此指令将 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
启用每个实例的事件和流量日志记录。可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
前缀:当必须清除记录器列表时,应使用 no。例如,如果您不想从默认记录器列表继承。此前缀不允许有参数。
global should be used when the instance's logging parameters are the same as the global ones. This is the most common usage. "global" replaces all log arguments with those of the log entries found in the "global" section. Only one "log global" statement may be used per instance, and this form takes no other parameter. <target> indicates where to send the logs. It takes the same format as for the "global" section's logs, and can be one of : - An IPv4 address optionally followed by a colon (':') and a UDP port. If no port is specified, 514 is used by default (the standard syslog port). - An IPv6 address followed by a colon (':') and optionally a UDP port. If no port is specified, 514 is used by default (the standard syslog port). - A filesystem path to a UNIX domain socket, keeping in mind considerations for chroot (be sure the path is accessible inside the chroot) and uid/gid (be sure the path is appropriately writable). - A file descriptor number in the form "fd@<number>", which may point to a pipe, terminal, or socket. In this case unbuffered logs are used and one writev() call per log is performed. This is a bit expensive but acceptable for most workloads. Messages sent this way will not be truncated but may be dropped, in which case the DroppedLogs counter will be incremented. The writev() call is atomic even on pipes for messages up to PIPE_BUF size, which POSIX recommends to be at least 512 and which is 4096 bytes on most modern operating systems. Any larger message may be interleaved with messages from other processes. Exceptionally for debugging purposes the file descriptor may also be directed to a file, but doing so will significantly slow HAProxy down as non-blocking calls will be ignored. Also there will be no way to purge nor rotate this file without restarting the process. Note that the configured syslog format is preserved, so the output is suitable for use with a TCP syslog server. See also the "short" and "raw" formats below. - "stdout" / "stderr", which are respectively aliases for "fd@1" and "fd@2", see above. - A ring buffer in the form "ring@<name>", which will correspond to an in-memory ring buffer accessible over the CLI using the "show events" command, which will also list existing rings and their sizes. Such buffers are lost on reload or restart but when used as a complement this can help troubleshooting by having the logs instantly available. - A log backend in the form "backend@<name>", which will send log messages to the corresponding log backend responsible for sending the message to the proper server according to the backend's lb settings. A log backend is a backend section with "mode log" set (see "mode" for more information). - An explicit stream address prefix such as "tcp@","tcp6@", "tcp4@" or "uxst@" will allocate an implicit ring buffer with a stream forward server targeting the given address. You may want to reference some environment variables in the address parameter, see section 2.3 about environment variables. <length> is an optional maximum line length. Log lines larger than this value will be truncated before being sent. The reason is that syslog servers act differently on log line length. All servers support the default value of 1024, but some servers simply drop larger lines while others do log them. If a server supports long lines, it may make sense to set this value here in order to avoid truncating long lines. Similarly, if a server drops long lines, it is preferable to truncate them before sending them. Accepted values are 80 to 65535 inclusive. The default value of 1024 is generally fine for all standard usages. Some specific cases of long captures or JSON-formatted logs may require larger values. You may also need to increase "tune.http.logurilen" if your request URIs are truncated. <ranges> A list of comma-separated ranges to identify the logs to sample. This is used to balance the load of the logs to send to the log server. The limits of the ranges cannot be null. They are numbered from 1. The size or period (in number of logs) of the sample must be set with <sample_size> parameter. <sample_size> The size of the sample in number of logs to consider when balancing their logging loads. It is used to balance the load of the logs to send to the syslog server. This size must be greater or equal to the maximum of the high limits of the ranges. (see also <ranges> parameter). <format> is the log format used when generating syslog messages. It may be one of the following : local Analog to rfc3164 syslog message format except that hostname field is stripped. This is the default. Note: option "log-send-hostname" switches the default to rfc3164. rfc3164 The RFC3164 syslog message format. (https://tools.ietf.org/html/rfc3164) rfc5424 The RFC5424 syslog message format. (https://tools.ietf.org/html/rfc5424) priority A message containing only a level plus syslog facility between angle brackets such as '<63>', followed by the text. The PID, date, time, process name and system name are omitted. This is designed to be used with a local log server. short A message containing only a level between angle brackets such as '<3>', followed by the text. The PID, date, time, process name and system name are omitted. This is designed to be used with a local log server. This format is compatible with what the systemd logger consumes. timed A message containing only a level between angle brackets such as '<3>', followed by ISO date and by the text. The PID, process name and system name are omitted. This is designed to be used with a local log server. iso A message containing only the ISO date, followed by the text. The PID, process name and system name are omitted. This is designed to be used with a local log server. raw A message containing only the text. The level, PID, date, time, process name and system name are omitted. This is designed to be used in containers or during development, where the severity only depends on the file descriptor used (stdout/stderr). <prof> name of the optional "log-profile" section that will be considered during the log building process to override some log options. Check out "8.3.5. Log profiles" for more info. <facility> must be one of the 24 standard syslog facilities : kern user mail daemon auth syslog lpr news uucp cron auth2 ftp ntp audit alert cron2 local0 local1 local2 local3 local4 local5 local6 local7 Note that the facility is ignored for the "short" and "raw" formats, but still required as a positional field. It is recommended to use "daemon" in this case to make it clear that it's only supposed to be used locally. <level> is optional and can be specified to filter outgoing messages. By default, all messages are sent. If a level is specified, only messages with a severity at least as important as this level will be sent. An optional minimum level can be specified. If it is set, logs emitted with a more severe level than this one will be capped to this level. This is used to avoid sending "emerg" messages on all terminals on some default syslog configurations. Eight levels are known : emerg alert crit err warning notice info debug
重要的是要记住,是由前端决定要从连接中记录什么,并且在内容切换的情况下,来自后端的日志条目将被忽略。连接以 "info" 级别记录。然而,后端日志声明定义了服务器状态更改将如何以及在何处被记录。级别 "notice" 将用于指示服务器启动,"warning" 将用于终止信号和最终的服务终止,而 "alert" 将用于服务器宕机时。 注意:根据 RFC3164,消息在发出前会被截断为 1024 字节。
log global log stdout format short daemon # 发送日志到 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
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
此指令指定了将用于所有通过使用此行的前端的流量所产生的日志的日志格式字符串。如果该指令在 defaults 部分中使用,所有后续的前端将使用相同的日志格式。请参阅第 8.2.6 节,该节深入介绍了自定义日志格式字符串。也可以定义仅在连接错误情况下使用的特定日志格式,请参见 "error-log-format" 选项。"log-format" 指令会覆盖之前的 "option tcplog"、"log-format"、"option httplog" 和 "option httpslog" 指令。
指定用于生成 RFC5424 结构化数据的自定义日志格式字符串。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
该指令指定了 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\"]
指定在事务处理的哪些步骤应生成日志。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
在 tcp/http 事务处理期间,haproxy 可能会在处理的不同步骤(即:接受、连接、请求、响应、关闭)产生日志。默认情况下,HAProxy 每个事务只发出一个日志,一旦 logformat 表达式中使用的所有项目都能被满足,这意味着实际上日志通常在事务结束时发出(对于 HTTP 是在响应结束后,对于 TCP 是在连接结束后),除非使用了 "option logasap"。" log-steps " 指令允许精确地定义日志发出的时刻,甚至允许为同一事务发出多个日志。可以使用特殊值 'all' 来启用所有可用的日志源,从而可以从接受到关闭跟踪一个事务。也可以使用它们的名称(用空格分隔)来指定单个日志源,以选择性地启用何时应生成日志。常见的日志源有:accept, connect, request, response, close。
frontend myfront option httplog log-steps accept,close #仅记录事务的接受和关闭
Log origins specified as "logging steps" (such as accept, close) can be used as-is in log-profiles (after 'on' directive). Combining "log-steps" with log-profiles is really interesting to have fine-grained control over logs automatically generated by haproxy during transaction processing.
指定用于所有传出日志的日志标签。可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
Sets the tag field in the syslog header to this string. It defaults to the log-tag set in the global section, otherwise the program name as launched from the command line, which usually is "HAProxy". Sometimes it can be useful to differentiate between multiple processes running on the same host, or to differentiate customer instances running in the same process. In the backend, logs about servers up/down will use this tag. As a hint, it can be convenient to set a log-tag related to a hosted customer in a defaults section then put all the frontends and backends for that customer, then start another customer in a new defaults section. See also the global "log-tag" directive.设置用于维护 keep-alive 连接的最大服务器队列大小。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
HTTP keep-alive tries to reuse the same server connection whenever possible, but sometimes it can be counter-productive, for example if a server has a lot of connections while other ones are idle. This is especially true for static servers. The purpose of this setting is to set a threshold on the number of queued connections at which HAProxy stops trying to reuse the same server and prefers to find another one. The default value, -1, means there is no limit. A value of zero means that keep-alive requests will never be queued. For very close servers which can be reached with a low latency and which are not sensible to breaking keep-alive, a low value is recommended (e.g. local static server can use a value of 10 or less). For remote servers suffering from a high latency, higher values might be needed to cover for the latency and/or the cost of picking a different server. Note that this has no impact on responses which are maintained to the same server consecutively to a 401 response. They will still go to the same server even if they have to be queued.
设置我们可以为给定客户端会话保持空闲的最大传出连接数。默认值为 5(精确等于在构建时定义的 MAX_SRV_LIST)。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
设置前端的最大并发连接数。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<conns> 是前端将接受服务的最大并发连接数。超出的连接将由系统在套接字的侦听队列中排队,并在一个连接关闭后得到服务。
If the system supports it, it can be useful on big sites to raise this limit very high so that HAProxy manages connection queues, instead of leaving the clients with unanswered connection attempts. This value should not exceed the global maxconn. Also, keep in mind that a connection contains two buffers of tune.bufsize (16kB by default) each, as well as some other data resulting in about 33 kB of RAM being consumed per established connection. That means that a medium system equipped with 1GB of RAM can withstand around 20000-25000 concurrent connections if properly tuned. Also, when <conns> is set to large values, it is possible that the servers are not sized to accept such loads, and for this reason it is generally wise to assign them some reasonable connection limits. When this value is set to zero, which is the default, the global "maxconn" value is used.
设置实例的运行模式或协议
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
tcp The instance will work in pure TCP mode. A full-duplex connection will be established between clients and servers, and no layer 7 examination will be performed. This is the default mode. It should be used for SSL, SSH, SMTP, ... http The instance will work in HTTP mode. The client request will be analyzed in depth before connecting to any server. Any request which is not RFC-compliant will be rejected. Layer 7 filtering, processing and switching will be possible. This is the mode which brings HAProxy most of its value. log When used in a backend section, it will turn the backend into a log backend. Such backend can be used as a log destination for any "log" directive by using the "backend@<name>" syntax. Log messages will be distributed to the servers from the backend according to the lb settings which can be configured using the "balance" keyword. Log backends support UDP servers by prefixing the server's address with the "udp@" prefix. Common backend and server features are supported, but not TCP or HTTP specific ones. spop When used in a backend section, it will turn the backend into a log backend. This mode is mandatory and automatically set, if necessary, for backends referenced by SPOE engines.
在进行内容切换时,前端和后端必须处于相同的模式(通常是 HTTP),否则配置将被拒绝。
defaults http_instances mode http
添加一个条件,以便向监控 HTTP 请求报告失败。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 否![]() |
if <cond> 如果条件满足,监控请求将失败,否则将成功。该条件应描述一个组合测试,如果所有条件都满足,则必须导致失败,例如后端及其备份中的服务器数量都很少。 unless <cond> 只有当条件满足时,监控请求才会成功,否则将失败。这样的条件可以基于对后端列表中最小活动服务器数量的存在的测试。
This statement adds a condition which can force the response to a monitor request to report a failure. By default, when an external component queries the URI dedicated to monitoring, a 200 response is returned. When one of the conditions above is met, HAProxy will return 503 instead of 200. This is very useful to report a site failure to an external component which may base routing advertisements between multiple sites on the availability reported by HAProxy. In this case, one would rely on an ACL involving the "nbsrv" criterion. Note that "monitor fail" only works in HTTP mode. Both status messages may be tweaked using "errorfile" or "errorloc" if needed.
frontend www mode http acl site_dead nbsrv(dynamic) lt 2 acl site_dead nbsrv(static) lt 2 monitor-uri /site_alive monitor fail if site_dead
拦截外部组件监控请求使用的 URI。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<uri> 是我们想要拦截以返回 HAProxy 健康状态而不是转发请求的确切 URI。
When an HTTP request referencing <uri> will be received on a frontend, HAProxy will not forward it nor log it, but instead will return either "HTTP/1.0 200 OK" or "HTTP/1.0 503 Service unavailable", depending on failure conditions defined with "monitor fail". This is normally enough for any front-end HTTP probe to detect that the service is UP and running without forwarding the request to a backend server. Note that the HTTP method, the version and all headers are ignored, but the request must at least be valid at the HTTP level. This keyword may only be used with an HTTP-mode frontend. Monitor requests are processed very early, just after the request is parsed and even before any "http-request". The only rulesets applied before are the tcp-request ones. They cannot be logged either, and it is the intended purpose. Only one URI may be configured for monitoring; when multiple "monitor-uri" statements are present, the last one will define the URI to be used. They are only used to report HAProxy's health to an upper component, nothing more. However, it is possible to add any number of conditions using "monitor fail" and ACLs so that the result can be adjusted to whatever check can be imagined (most often the number of available servers in a backend). Note: if <uri> starts by a slash ('/'), the matching is performed against the request's path instead of the request's uri. It is a workaround to let the HTTP/2 requests match the monitor-uri. Indeed, in HTTP/2, clients are encouraged to send absolute URIs only.
# 使用 /haproxy_test 报告 HAProxy 的状态 frontend www mode http monitor-uri /haproxy_test
启用或禁用对队列中待处理的已中止请求的提前丢弃。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
In presence of very high loads, the servers will take some time to respond. The per-instance connection queue will inflate, and the response time will increase respective to the size of the queue times the average per-stream response time. When clients will wait for more than a few seconds, they will often hit the "STOP" button on their browser, leaving a useless request in the queue, and slowing down other users, and the servers as well, because the request will eventually be served, then aborted at the first error encountered while delivering the response. As there is no way to distinguish between a full STOP and a simple output close on the client side, HTTP agents should be conservative and consider that the client might only have closed its output channel while waiting for the response. However, this introduces risks of congestion when lots of users do the same, and is completely useless nowadays because probably no client at all will close the stream while waiting for the response. Some HTTP agents support this behavior (Squid, Apache, HAProxy), and others do not (TUX, most hardware-based load balancers). So the probability for a closed input channel to represent a user hitting the "STOP" button is close to 100%, and the risk of being the single component to break rare but valid traffic is extremely low, which adds to the temptation to be able to abort a stream early while still not served and not pollute the servers. In HAProxy, the user can choose the desired behavior using the option "abortonclose". By default (without the option) the behavior is HTTP compliant and aborted requests will be served. But when the option is specified, a stream with an incoming channel closed will be aborted while it is still possible, either pending in the queue for a connection slot, or during the connection establishment if the server has not yet acknowledged the connection request. This considerably reduces the queue size and the load on saturated servers when users are tempted to click on STOP, which in turn reduces the response time for other users. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
启用或禁用放宽 HTTP 请求解析。“accept-invalid-http-request”关键字已弃用,请改用 "option accept-unsafe-violations-in-http-request"。
启用或禁用放宽 HTTP 响应解析。“accept-invalid-http-response”关键字已弃用,请改用 "option accept-unsafe-violations-in-http-response"。
启用或禁用放宽 HTTP 请求解析。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
By default, HAProxy complies with the different HTTP RFCs in terms of message parsing. This means the message parsing is quite strict and causes an error to be returned to the client for malformed messages. This is the desired behavior as such malformed messages are essentially used to build attacks exploiting server weaknesses, and bypass security filtering. Sometimes, a buggy browser will not respect these RCFs for whatever reason (configuration, implementation...) and the issue will not be immediately fixed. In such case, it is possible to relax HAProxy's parser to accept some invalid requests by specifying this option. Most of rules concern the H1 parsing for historical reason. Newer HTTP versions tends to be cleaner and applications follow more stickly these protocols. When this option is set, the following rules are observed: * In H1 only, invalid characters, including NULL character, in header name will be accepted; * In H1 only, NULL character in header value will be accepted; * In H1 only, characters above 127 in the URI will be accepted. The list of characters allowed to appear in a URI is well defined by RFC3986, and chars 0-31, 32 (space), 34 ('"'), 60 ('<'), 62 ('>'), 92 ('\'), 94 ('^'), 96 ('`'), 123 ('{'), 124 ('|'), 125 ('}'), 127 (delete) and anything above are normally not allowed. In H1, all character between (0..32) and 127 will always be blocked. All characters above 127 (excluded) will also be blocked, except when this option is enabled. Other characters (33..126) will not be checked at all. * In H1 and H2, URLs containing fragment references ('#' after the path) will be accepted; * In H1 only, no check will be performed on the authority for CONNECT requests; * In H1 only, no check will be performed against the authority and the Host header value. * In H1 only, tests on the HTTP version will be relaxed. It will allow HTTP/0.9 GET requests to pass through (no version specified), as well as different protocol names (e.g. RTSP), and multiple digits for both the major and the minor version. This option should never be enabled by default as it hides application bugs and open security breaches. It should only be deployed after a problem has been confirmed. When this option is enabled, invalid but accepted H1 requests will be captured in order to permit later analysis using the "show errors" request on the UNIX stats socket.Doing this also helps confirming that the issue has been solved. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.启用或禁用放宽 HTTP 响应解析。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
Similarly to "option accept-unsafe-violations-in-http-request", this option may be used to relax parsing rules of HTTP responses. It should only be enabled for trusted legacy servers to accept some invalid responses. Most of rules concern the H1 parsing for historical reason. Newer HTTP versions tends to be cleaner and applications follow more stickly these protocols. When this option is set, the following rules are observed: * In H1 only, invalid characters, including NULL character, in header name will be accepted; * In H1 only, NULL character in header value will be accepted; * In H1 only, empty values or several "chunked" value occurrences for Transfer-Encoding header will be accepted; * In H1 only, no check will be performed against the authority and the Host header value. * In H1 only, tests on the HTTP version will be relaxed. It will allow different protocol names (e.g. RTSP), and multiple digits for both the major and the minor version. This option should never be enabled by default as it hides application bugs and open security breaches. It should only be deployed after a problem has been confirmed. When this option is enabled, erroneous header names will still be accepted in responses, but the complete response will be captured in order to permit later analysis using the "show errors" request on the UNIX stats socket. Doing this also helps confirming that the issue has been solved. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
选择一次性使用所有备份服务器,还是只使用第一个。可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
默认情况下,当所有正常服务器都宕机时,第一个可用的备用服务器将获得所有流量。有时,可能希望一次使用多个备用服务器,因为一个可能不够用。当启用 "option allbackups" 时,当所有正常服务器都不可用时,将在所有备用服务器之间执行负载均衡。将使用相同的负载均衡算法,并遵守服务器的权重。因此,备用服务器之间将不再有任何优先级顺序。此选项主要用于专用于在应用程序完全离线时返回“抱歉”页面的静态服务器群。 如果此选项已在 "defaults" 部分中启用,可以通过在其前面添加 "no" 关键字来在特定实例中禁用它。
分析所有服务器响应并阻止带有可缓存 cookie 的响应。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
Some high-level frameworks set application cookies everywhere and do not always let enough control to the developer to manage how the responses should be cached. When a session cookie is returned on a cacheable object, there is a high risk of session crossing or stealing between users traversing the same caches. In some situations, it is better to block the response than to let some sensitive session information go in the wild. The option "checkcache" enables deep inspection of all server responses for strict compliance with HTTP specification in terms of cacheability. It carefully checks "Cache-control", "Pragma" and "Set-cookie" headers in server response to check if there's a risk of caching a cookie on a client-side proxy. When this option is enabled, the only responses which can be delivered to the client are : - all those without "Set-Cookie" header; - all those with a return code other than 200, 203, 204, 206, 300, 301, 404, 405, 410, 414, 501, provided that the server has not set a "Cache-control: public" header field; - all those that result from a request using a method other than GET, HEAD, OPTIONS, TRACE, provided that the server has not set a 'Cache-Control: public' header field; - those with a 'Pragma: no-cache' header - those with a 'Cache-control: private' header - those with a 'Cache-control: no-store' header - those with a 'Cache-control: max-age=0' header - those with a 'Cache-control: s-maxage=0' header - those with a 'Cache-control: no-cache' header - those with a 'Cache-control: no-cache="set-cookie"' header - those with a 'Cache-control: no-cache="set-cookie,' header (allowing other fields after set-cookie) If a response doesn't respect these requirements, then it will be blocked just as if it was from an "http-response deny" rule, with an "HTTP 502 bad gateway". The session state shows "PH--" meaning that the proxy blocked the response during headers processing. Additionally, an alert will be sent in the logs so that admins are informed that there's something to be fixed. Due to the high impact on the application, the application should be tested in depth with the option enabled before going to production. It is also a good practice to always activate it during tests, even if it is not used in production, as it will report potentially dangerous application behaviors. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
启用或禁用在客户端发送 TCP keepalive 数据包。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
When there is a firewall or any session-aware component between a client and a server, and when the protocol involves very long sessions with long idle periods (e.g. remote desktops), there is a risk that one of the intermediate components decides to expire a session which has remained idle for too long. Enabling socket-level TCP keep-alives makes the system regularly send packets to the other end of the connection, leaving it active. The delay between keep-alive probes is controlled by the system only and depends both on the operating system and its tuning parameters. It is important to understand that keep-alive packets are neither emitted nor received at the application level. It is only the network stacks which sees them. For this reason, even if one side of the proxy already uses keep-alives to maintain its connection alive, those keep-alive packets will not be forwarded to the other side of the proxy. Please note that this has nothing to do with HTTP keep-alive. Using option "clitcpka" enables the emission of TCP keep-alive probes on the client side of a connection, which should help when session expirations are noticed between HAProxy and a client. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
启用持续的流量统计更新。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
默认情况下,用于统计计算的计数器仅在流结束时递增。这在处理小对象时效果很好,但对于大对象(例如大图片或存档)或音视频流,从 HAProxy 计数器生成的图表看起来像一只刺猬。启用此选项后,计数器会随着流的进行而频繁递增,通常每 5 秒一次,这通常足以生成清晰的图表。重新计数直接触及热路径,因此默认情况下未启用,因为它可能导致大量会话计数的唤醒,并导致轻微的性能下降。
启用或禁用从 HTTP/1.x 客户端连接的隐式 HTTP/2 升级。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
默认情况下,如果 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
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
有些大型网站每秒处理数千个连接,日志记录对它们来说是一个主要的痛点。其中一些甚至被迫关闭日志,无法调试生产问题。设置此选项可确保正常的连接,即那些没有经历错误、超时、重试或重新分派的连接,将不会被记录。这为异常情况留下了磁盘空间。在 HTTP 模式下,会检查响应状态码,返回码为 5xx 的仍将被记录。 强烈建议不要使用此选项,因为大多数情况下,复杂问题的关键在于正常的日志中,而这些日志在这里不会被记录。如果您需要分离日志,请改用 "log-separate-errors" 选项。
启用或禁用对空连接的日志记录。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
在某些环境中,有些组件会定期连接到各种系统,以确保它们仍然存活。这可能是来自另一个负载均衡器以及监控系统的情况。默认情况下,即使是简单的端口探测或扫描也会产生一条日志。如果这些连接过多地污染了日志,可以启用选项“dontlognull”,以指示没有传输任何数据的连接将不会被记录,这通常对应于那些探测。请注意,错误仍将返回给客户端并在统计信息中计算。如果这不是期望的,可以使用 http-ignore-probes 选项。通常建议不要在不受控制的环境(例如互联网)中使用此选项,否则扫描和其他恶意活动将不会被记录。如果此选项已在“defaults”部分启用,则可以通过在其前面加上“no”关键字来在特定实例中禁用它。
启用在发送到服务器的请求中插入 rfc 7239 forwarded 头部。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<host_expr> 可选参数,用于指定一个自定义样本表达式,其结果将用作 'host' 参数值 <by_expr> 可选参数,用于指定一个自定义样本表达式,其结果将用作 'by' 参数的 nodename 值 <for_expr> 可选参数,用于指定一个自定义样本表达式,其结果将用作 'for' 参数的 nodename 值 <by_port_expr> 可选参数,用于指定一个自定义样本表达式,其结果将用作 'by' 参数的 nodeport 值 <for_port_expr> 可选参数,用于指定一个自定义样本表达式,其结果将用作 'for' 参数的 nodeport 值
Since HAProxy works in reverse-proxy mode, servers are losing some request context (request origin: client ip address, protocol used...) A common way to address this limitation is to use the well known x-forward-for and x-forward-* friends to expose some of this context to the underlying servers/applications. While this use to work and is widely deployed, it is not officially supported by the IETF and can be the root of some interoperability as well as security issues. To solve this, a new HTTP extension has been described by the IETF: forwarded header (RFC7239). More information here: https://www.rfc-editor.org/rfc/rfc7239.html The use of this single header allow to convey numerous details within the same header, and most importantly, fixes the proxy chaining issue. (the rfc allows for multiple chained proxies to append their own values to an already existing header). This option may be specified in defaults, listen or backend section, but it will be ignored for frontend sections. Setting option forwarded without arguments results in using default implicit behavior. Default behavior enables proto parameter and injects original client ip. The equivalent explicit/manual configuration would be: option forwarded proto for The keyword 'by' is used to enable 'by' parameter ("nodename") in forwarded header. It allows to embed request proxy information. 'by' value will be set to proxy ip (destination address) If not available (ie: UNIX listener), 'by' will be set to "unknown". The keyword 'by-expr' is used to enable 'by' parameter ("nodename") in forwarded header. It allows to embed request proxy information. 'by' value will be set to the result of the sample expression <by_expr>, if valid, otherwise it will be set to "unknown". The keyword 'for' is used to enable 'for' parameter ("nodename") in forwarded header. It allows to embed request client information. 'for' value will be set to client ip (source address) If not available (ie: UNIX listener), 'for' will be set to "unknown". The keyword 'for-expr' is used to enable 'for' parameter ("nodename") in forwarded header. It allows to embed request client information. 'for' value will be set to the result of the sample expression <for_expr>, if valid, otherwise it will be set to "unknown". The keyword 'by_port' is used to provide "nodeport" info to 'by' parameter. 'by_port' requires 'by' or 'by-expr' to be set or it will be ignored. "nodeport" will be set to proxy (destination) port if available, otherwise it will be ignored. The keyword 'by_port-expr' is used to provide "nodeport" info to 'by' parameter. 'by_port-expr' requires 'by' or 'by-expr' to be set or it will be ignored. "nodeport" will be set to the result of the sample expression <by_port_expr>, if valid, otherwise it will be ignored. The keyword 'for_port' is used to provide "nodeport" info to 'for' parameter. 'for_port' requires 'for' or 'for-expr' to be set or it will be ignored. "nodeport" will be set to client (source) port if available, otherwise it will be ignored. The keyword 'for_port-expr' is used to provide "nodeport" info to 'for' parameter. 'for_port-expr' requires 'for' or 'for-expr' to be set or it will be ignored. "nodeport" will be set to the result of the sample expression <for_port_expr>, if valid, otherwise it will be ignored.# Those servers want the ip address and protocol of the client request # Resulting header would look like this: # forwarded: proto=http;for=127.0.0.1 backend www_default mode http option forwarded #equivalent to: option forwarded proto for # Those servers want the requested host and hashed client ip address # as well as client source port (you should use seed for xxh32 if ensuring # ip privacy is a concern) # Resulting header would look like this: # forwarded: host="haproxy.org";for="_000000007F2F367E:60138" backend www_host mode http option forwarded host for-expr src,xxh32,hex for_port # Those servers want custom data in host, for and by parameters # Resulting header would look like this: # forwarded: host="host.com";by=_haproxy;for="[::1]:10" backend www_custom mode http option forwarded host-expr str(host.com) by-expr str(_haproxy) for for_port-expr int(10) # Those servers want random 'for' obfuscated identifiers for request # tracing purposes while protecting sensitive IP information # Resulting header would look like this: # forwarded: for=_000000002B1F4D63 backend www_for_hide mode http option forwarded for-expr rand,hex
启用向发送到服务器的请求中插入 X-Forwarded-For 头部。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<network> 是一个可选参数,用于对匹配 <network> 的源禁用此选项。<name> 是一个可选参数,用于指定一个不同的 "X-Forwarded-For" 头部名称。
Since HAProxy works in reverse-proxy mode, the servers see its IP address as their client address. This is sometimes annoying when the client's IP address is expected in server logs. To solve this problem, the well-known HTTP header "X-Forwarded-For" may be added by HAProxy to all requests sent to the server. This header contains a value representing the client's IP address. Since this header is always appended at the end of the existing header list, the server must be configured to always use the last occurrence of this header only. See the server's manual to find how to enable use of this standard header. Note that only the last occurrence of the header must be used, since it is really possible that the client has already brought one. The keyword "header" may be used to supply a different header name to replace the default "X-Forwarded-For". This can be useful where you might already have a "X-Forwarded-For" header from a different application (e.g. stunnel), and you need preserve it. Also if your backend server doesn't use the "X-Forwarded-For" header and requires different one (e.g. Zeus Web Servers require "X-Cluster-Client-IP"). Sometimes, a same HAProxy instance may be shared between a direct client access and a reverse-proxy access (for instance when an SSL reverse-proxy is used to decrypt HTTPS traffic). It is possible to disable the addition of the header for a known source address or network by adding the "except" keyword followed by the network address. In this case, any source IP matching the network will not cause an addition of this header. Most common uses are with private networks or 127.0.0.1. IPv4 and IPv6 are both supported. Alternatively, the keyword "if-none" states that the header will only be added if it is not present. This should only be used in perfectly trusted environment, as this might cause a security issue if headers reaching HAProxy are under the control of the end-user. This option may be specified either in the frontend or in the backend. If at least one of them uses it, the header will be added. Note that the backend's setting of the header subargument takes precedence over the frontend's if both are defined. In the case of the "if-none" argument, if at least one of the frontend or the backend does not specify it, it wants the addition to be mandatory, so it wins.
# 公共 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
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
There is no standard case for header names because, as stated in RFC7230, they are case-insensitive. So applications must handle them in a case- insensitive manner. But some bogus applications violate the standards and erroneously rely on the cases most commonly used by browsers. This problem becomes critical with HTTP/2 because all header names must be exchanged in lower case, and HAProxy follows the same convention. All header names are sent in lower case to clients and servers, regardless of the HTTP version. When HAProxy receives an HTTP/1 response, its header names are converted to lower case and manipulated and sent this way to the clients. If a client is known to violate the HTTP standards and to fail to process a response coming from HAProxy, it is possible to transform the lower case header names to a different format when the response is formatted and sent to the client, by enabling this option and specifying the list of headers to be reformatted using the global directives "h1-case-adjust" or "h1-case-adjust-file". This must only be a temporary workaround for the time it takes the client to be fixed, because clients which require such workarounds might be vulnerable to content smuggling attacks and must absolutely be fixed. Please note that this option will not affect standards-compliant clients. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
启用或禁用发送给有问题的服务器的 HTTP/1 头部的大小写调整。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
There is no standard case for header names because, as stated in RFC7230, they are case-insensitive. So applications must handle them in a case- insensitive manner. But some bogus applications violate the standards and erroneously rely on the cases most commonly used by browsers. This problem becomes critical with HTTP/2 because all header names must be exchanged in lower case, and HAProxy follows the same convention. All header names are sent in lower case to clients and servers, regardless of the HTTP version. When HAProxy receives an HTTP/1 request, its header names are converted to lower case and manipulated and sent this way to the servers. If a server is known to violate the HTTP standards and to fail to process a request coming from HAProxy, it is possible to transform the lower case header names to a different format when the request is formatted and sent to the server, by enabling this option and specifying the list of headers to be reformatted using the global directives "h1-case-adjust" or "h1-case-adjust-file". This must only be a temporary workaround for the time it takes the server to be fixed, because servers which require such workarounds might be vulnerable to content smuggling attacks and must absolutely be fixed. Please note that this option will not affect standards-compliant servers. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
启用或禁用在处理前等待整个 HTTP 请求体。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
有时,在做出决定之前等待 HTTP 请求的主体是可取的。例如,“balance url_param”就是这样做的。第一个用例是在连接到服务器之前缓冲来自慢速客户端的请求。另一个用例是基于请求主体的内容做出路由决策。此选项放置在前端或后端中,强制 HTTP 处理等待直到接收到整个主体或请求缓冲区已满。它可能与一些滥用 HTTP 的应用程序产生不希望的副作用,这些应用程序期望前端和后端之间有无缓冲的传输,因此绝对不应默认使用。
启用或禁用对空连接和请求超时的日志记录。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
Recently some browsers started to implement a "pre-connect" feature consisting in speculatively connecting to some recently visited web sites just in case the user would like to visit them. This results in many connections being established to web sites, which end up in 408 Request Timeout if the timeout strikes first, or 400 Bad Request when the browser decides to close them first. These ones pollute the log and feed the error counters. There was already "option dontlognull" but it's insufficient in this case. Instead, this option does the following things : - prevent any 400/408 message from being sent to the client if nothing was received over a connection before it was closed; - prevent any log from being emitted in this situation; - prevent any error counter from being incremented That way the empty connection is silently ignored. Note that it is better not to use this unless it is clear that it is needed, because it will hide real problems. The most common reason for not receiving a request and seeing a 408 is due to an MTU inconsistency between the client and an intermediary element such as a VPN, which blocks too large packets. These issues are generally seen with POST requests as well as GET with large cookies. The logs are often the only way to detect them. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
为 HTTP/1.x 连接启用或禁用从客户端到服务器的 HTTP keep-alive。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
By default HAProxy operates in keep-alive mode with regards to persistent HTTP/1.x connections: for each connection it processes each request and response, and leaves the connection idle on both sides. This mode may be changed by several options such as "option http-server-close" or "option httpclose". This option allows to set back the keep-alive mode, which can be useful when another mode was used in a defaults section. Setting "option http-keep-alive" enables HTTP keep-alive mode on the client- and server- sides. This provides the lowest latency on the client side (slow network) and the fastest session reuse on the server side at the expense of maintaining idle connections to the servers. In general, it is possible with this option to achieve approximately twice the request rate that the "http-server-close" option achieves on small objects. There are mainly two situations where this option may be useful : - when the server is non-HTTP compliant and authenticates the connection instead of requests (e.g. NTLM authentication) - when the cost of establishing the connection to the server is significant compared to the cost of retrieving the associated object from the server. This last case can happen when the server is a fast static server of cache. At the moment, logs will not indicate whether requests came from the same session or not. The accept date reported in the logs corresponds to the end of the previous request, and the request time corresponds to the time spent waiting for a new request. The keep-alive request time is still bound to the timeout defined by "timeout http-keep-alive" or "timeout http-request" if not set. This option disables and replaces any previous "option httpclose" or "option http-server-close".
指示系统在 HTTP 中优先考虑低交互延迟而不是性能。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
In HTTP, each payload is unidirectional and has no notion of interactivity. Any agent is expected to queue data somewhat for a reasonably low delay. There are some very rare server-to-server applications that abuse the HTTP protocol and expect the payload phase to be highly interactive, with many interleaved data chunks in both directions within a single request. This is absolutely not supported by the HTTP specification and will not work across most proxies or servers. When such applications attempt to do this through HAProxy, it works but they will experience high delays due to the network optimizations which favor performance by instructing the system to wait for enough data to be available in order to only send full packets. Typical delays are around 200 ms per round trip. Note that this only happens with abnormal uses. Normal uses such as CONNECT requests nor WebSockets are not affected. When "option http-no-delay" is present in either the frontend or the backend used by a connection, all such optimizations will be disabled in order to make the exchanges as fast as possible. Of course this offers no guarantee on the functionality, as it may break at any other place. But if it works via HAProxy, it will work as fast as possible. This option should never be used by default, and should never be used at all unless such a buggy application is discovered. The impact of using this option is an increase of bandwidth usage and CPU usage, which may significantly lower performance in high latency environments.
定义 HAProxy 是否会向服务器宣告 HTTP/1.x 连接的 keepalive。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
When running with "option http-server-close" or "option httpclose", HAProxy adds a "Connection: close" header to the HTTP/1.x request forwarded to the server. Unfortunately, when some servers see this header, they automatically refrain from using the chunked encoding for responses of unknown length, while this is totally unrelated. The effect is that a client or a cache could receive an incomplete response without being aware of it, and consider the response complete. By setting "option http-pretend-keepalive", HAProxy will make the server believe it will keep the connection alive. The server will then not fall back to the abnormal undesired above. When HAProxy gets the whole response, it will close the connection with the server just as it would do with the "option httpclose". That way the client gets a normal response and the connection is correctly closed on the server side. It is recommended not to enable this option by default, because most servers will more efficiently close the connection themselves after the last packet, and release its buffers slightly earlier. Also, the added packet on the network could slightly reduce the overall peak performance. However it is worth noting that when this option is enabled, HAProxy will have slightly less work to do. So if HAProxy is the bottleneck on the whole architecture, enabling this option might save a few CPU cycles. This option may be set in backend and listen sections. Using it in a frontend section will be ignored and a warning will be reported during startup. It is a backend related option, so there is no real reason to set it on a frontend. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
设置 HAProxy 关于包含 "[a-zA-Z0-9-]" 字符集之外字符的 HTTP 请求头部名称的策略。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
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
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
By default HAProxy operates in keep-alive mode with regards to persistent HTTP/1.x connections: for each connection it processes each request and response, and leaves the connection idle on both sides. This mode may be changed by several options such as "option http-server-close" or "option httpclose". Setting "option http-server-close" enables HTTP connection-close mode on the server side while keeping the ability to support HTTP keep-alive and pipelining on the client side. This provides the lowest latency on the client side (slow network) and the fastest session reuse on the server side to save server resources, similarly to "option httpclose". It also permits non-keepalive capable servers to be served in keep-alive mode to the clients if they conform to the requirements of RFC7230. Please note that some servers do not always conform to those requirements when they see "Connection: close" in the request. The effect will be that keep-alive will never be used. A workaround consists in enabling "option http-pretend-keepalive". At the moment, logs will not indicate whether requests came from the same session or not. The accept date reported in the logs corresponds to the end of the previous request, and the request time corresponds to the time spent waiting for a new request. The keep-alive request time is still bound to the timeout defined by "timeout http-keep-alive" or "timeout http-request" if not set. This option may be set both in a frontend and in a backend. It is enabled if at least one of the frontend or backend holding a connection has it enabled. It disables and replaces any previous "option httpclose" or "option http-keep-alive". Please check section 4 ("Proxies") to see how this option combines with others when frontend and backend options differ. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
使用非标准的 Proxy-Connection 头代替 Connection 可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
While RFC7230 explicitly states that HTTP/1.1 agents must use the Connection header to indicate their wish of persistent or non-persistent connections, both browsers and proxies ignore this header for proxied connections and make use of the undocumented, non-standard Proxy-Connection header instead. The issue begins when trying to put a load balancer between browsers and such proxies, because there will be a difference between what HAProxy understands and what the client and the proxy agree on. By setting this option in a frontend, HAProxy can automatically switch to use that non-standard header if it sees proxied requests. A proxied request is defined here as one where the URI begins with neither a '/' nor a '*'. This is incompatible with the HTTP tunnel mode. Note that this option can only be specified in a frontend and will affect the request along its whole life. Also, when this option is set, a request which requires authentication will automatically switch to use proxy authentication headers if it is itself a proxied request. That makes it possible to check or enforce authentication in front of an existing proxy. This option should normally never be used, except in front of a proxy.
启用 HTTP 协议来检查服务器健康状况 可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<method> 是与请求一起使用的可选 HTTP 方法。如果未设置,则使用“OPTIONS”方法,因为它通常需要较低的服务器处理能力,并且易于从日志中过滤掉。可以使用任何方法,但不建议发明非标准方法。<uri> 是 HTTP 请求中引用的 URI。它默认为“/”,这在几乎所有服务器上都是默认可访问的,但可以更改为任何其他 URI。允许使用查询字符串。<version> 是可选的 HTTP 版本字符串。它默认为“HTTP/1.0”,但有些服务器在 HTTP 1.0 中可能会行为不正确,因此将其更改为 HTTP/1.1 有时会有所帮助。请注意,Host 字段在 HTTP/1.1 中是强制性的。<host> 是可选的 HTTP Host 头的值。默认情况下不设置。它是一个日志格式字符串。
By default, server health checks only consist in trying to establish a TCP connection. When "option httpchk" is specified, a complete HTTP request is sent once the TCP connection is established, and responses 2xx and 3xx are considered valid, while all other ones indicate a server failure, including the lack of any response. Combined with "http-check" directives, it is possible to customize the request sent during the HTTP health checks or the matching rules on the response. It is also possible to configure a send/expect sequence, just like with the directive "tcp-check" for TCP health checks. The server configuration is used by default to open connections to perform HTTP health checks. By it is also possible to overwrite server parameters using "http-check connect" rules. "httpchk" option does not necessarily require an HTTP backend, it also works with plain TCP backends. This is particularly useful to check simple scripts bound to some dedicated ports using the inetd daemon. However, it will always internally relies on an HTX multiplexer. Thus, it means the request formatting and the response parsing will be strict.
# 将 HTTPS 流量中继到 Apache 实例,并使用 HTTP 请求 "OPTIONS * HTTP/1.1" # 在端口 80 上检查服务可用性。 backend https_relay mode tcp option httpchk OPTIONS * HTTP/1.1 http-check send hdr Host www server apache1 192.168.1.1:443 check port 80
启用或禁用 HTTP/1.x 连接关闭 可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
By default HAProxy operates in keep-alive mode with regards to persistent HTTP/1.x connections: for each connection it processes each request and response, and leaves the connection idle on both sides. This mode may be changed by several options such as "option http-server-close" or "option httpclose". If "option httpclose" is set, HAProxy will close the client or the server connection, depending where the option is set. The frontend is considered for client connections while the backend is considered for server ones. If the option is set on a listener, it is applied both on client and server connections. It will check if a "Connection: close" header is already set in each direction, and will add one if missing. This option may also be combined with "option http-pretend-keepalive", which will disable sending of the "Connection: close" request header, but will still cause the connection to be closed once the whole response is received. It disables and replaces any previous "option http-server-close" or "option http-keep-alive". If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
启用 HTTP 请求、流状态和计时器的日志记录 可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
clf 如果添加了“clf”参数,则输出格式将是 CLF 格式,而不是 HAProxy 的默认 HTTP 格式。当您需要将 HAProxy 的日志输入到只支持 CLF 格式且不可扩展的特定日志分析器时,可以使用此选项。
默认情况下,日志输出格式非常简单,只包含源地址、目标地址和实例名称。通过指定“option httplog”,每条日志行都会变成更丰富的格式,包括但不限于 HTTP 请求、连接计时器、流状态、连接数、捕获的头和 cookie、前端、后端和服务器名称,当然还有源地址和端口。仅指定“option httplog”将自动清除默认设置的“clf”模式。“option httplog”会覆盖任何先前的“log-format”指令。
启用 HTTPS 请求、流状态和计时器的日志记录 可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
默认情况下,日志输出格式非常简单,只包含源地址、目标地址和实例名称。通过指定“option httpslog”,每条日志行都会变成更丰富的格式,包括但不限于 HTTP 请求、连接计时器、流状态、连接数、捕获的头和 cookie、前端、后端和服务器名称、SSL 证书验证和 SSL 握手状态,当然还有源地址和端口。“option httpslog”会覆盖任何先前的“log-format”指令。
启用或禁用双向独立的超时处理 可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
By default, when data is sent over a socket, both the write timeout and the read timeout for that socket are refreshed, because we consider that there is activity on that socket, and we have no other means of guessing if we should receive data or not. While this default behavior is desirable for almost all applications, there exists a situation where it is desirable to disable it, and only refresh the read timeout if there are incoming data. This happens on streams with large timeouts and low amounts of exchanged data such as telnet session. If the server suddenly disappears, the output data accumulates in the system's socket buffers, both timeouts are correctly refreshed, and there is no way to know the server does not receive them, so we don't timeout. However, when the underlying protocol always echoes sent data, it would be enough by itself to detect the issue using the read timeout. Note that this problem does not happen with more verbose protocols because data won't accumulate long in the socket buffers. When this option is set on the frontend, it will disable read timeout updates on data sent to the client. There probably is little use of this case. When the option is set on the backend, it will disable read timeout updates on data sent to the server. Doing so will typically break large HTTP posts from slow lines, so use it with caution.
使用 LDAPv3 健康检查来测试服务器 可在以下上下文中使用:tcp
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
可以测试服务器是否正确地使用 LDAPv3 通信,而不仅仅是测试它是否接受 TCP 连接。设置此选项后,会向服务器发送一个 LDAPv3 匿名简单绑定消息,并分析响应以查找 LDAPv3 绑定响应消息。只有当 LDAP 响应包含成功 resultCode (http://tools.ietf.org/html/rfc4511#section-4.1.9) 时,服务器才被认为是有效的。绑定请求的日志记录取决于服务器,请参阅您的文档如何配置它。
option ldap-check
使用外部进程进行服务器健康检查 可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
可以使用外部命令测试服务器的健康状况。这是通过运行使用 "external-check command" 设置的可执行文件来实现的。需要设置全局的 "external-check"。
避免在软停止期间关闭空闲的前端连接 可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
By default, idle connections will be closed during a soft stop. In some environments, a client talking to the proxy may have prepared some idle connections in order to send requests later. If there is no proper retry on write errors, this can result in errors while haproxy is reloading. Even though a proper implementation should retry on connection/write errors, this option was introduced to support backwards compatibility with haproxy prior to version 2.4. Indeed before v2.4, haproxy used to wait for a last request and response to add a "connection: close" header before closing, thus notifying the client that the connection would not be reusable. In a real life example, this behavior was seen in AWS using the ALB in front of a haproxy. The end result was ALB sending 502 during haproxy reloads. Users are warned that using this option may increase the number of old processes if connections remain idle for too long. Adjusting the client timeouts and/or the "hard-stop-after" parameter accordingly might be needed in case of frequent reloads.
启用或禁用健康检查状态更新的日志记录 可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
默认情况下,如果服务器处于 UP 状态,则记录失败的健康检查;如果服务器处于 DOWN 状态,则记录成功的健康检查,因此额外的信息量是有限的。启用此选项后,健康检查状态或服务器健康状况的任何变化都将被记录,这样就可以知道服务器在崩溃前偶尔会检查失败,或者确切知道它何时未能响应有效的 HTTP 状态,然后端口何时开始拒绝连接,以及服务器何时完全停止响应。请注意,此选项有意不记录非健康检查引起的状态变化(例如,在 CLI 上启用/禁用)。
更改非完全成功连接的日志级别 可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
有时在日志中查找错误并不容易。此选项使 HAProxy 提高包含潜在有用信息的日志级别,例如错误、超时、重试、重新分派或 HTTP 状态码 5xx。级别从“info”变为“err”。这使得大多数 syslog 守护进程可以将它们单独记录到不同的文件中。请注意不要从原始文件中删除它们,否则会丢失提供非常重要信息的顺序。使用此选项,处理每秒数千个连接的大型站点可以将正常流量记录到循环缓冲区中,并仅归档较小的错误日志。
启用或禁用早期日志记录。 可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
By default, logs are emitted when all the log format aliases and sample fetches used in the definition of the log-format string return a value, or when the stream is terminated. This allows the built in log-format strings to account for the transfer time, or the number of bytes in log messages. When handling long lived connections such as large file transfers or RDP, it may take a while for the request or connection to appear in the logs. Using "option logasap", the log message is created as soon as the server connection is established in mode tcp, or as soon as the server sends the complete headers in mode http. Missing information in the logs will be the total number of bytes which will only indicate the amount of data transferred before the message was created and the total time which will not take the remainder of the connection life or transfer time into account. For the case of HTTP, it is good practice to capture the Content-Length response header so that the logs at least indicate how many bytes are expected to be transferred.
listen http_proxy 0.0.0.0:80 mode http option httplog option logasap log 192.168.2.200 local3 >>> Feb 6 12:14:14 localhost \ haproxy[14389]: 10.0.1.2:33317 [06/Feb/2009:12:14:14.655] http-in \ static/srv1 9/10/7/14/+30 200 +243 - - ---- 3/1/1/1/0 1/0 \ "GET /image.iso HTTP/1.0"
使用 MySQL 健康检查来测试服务器 可在以下上下文中使用:tcp
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<username> 这是连接到 MySQL 服务器时将使用的用户名。 post-41 发送与 v4.1 后客户端兼容的检查(默认) pre-41 发送与 v4.1 前客户端兼容的检查
If you specify a username, the check consists of sending two MySQL packet, one Client Authentication packet, and one QUIT packet, to correctly close MySQL session. We then parse the MySQL Handshake Initialization packet and/or Error packet. It is a basic but useful test which does not produce error nor aborted connect on the server. However, it requires an unlocked authorised user without a password. To create a basic limited user in MySQL with optional resource limits: CREATE USER '<username>'@'<ip_of_haproxy|network_of_haproxy/netmask>' /*!50701 WITH MAX_QUERIES_PER_HOUR 1 MAX_UPDATES_PER_HOUR 0 */ /*M!100201 MAX_STATEMENT_TIME 0.0001 */; If you don't specify a username (it is deprecated and not recommended), the check only consists in parsing the Mysql Handshake Initialization packet or Error packet, we don't send anything in this mode. It was reported that it can generate lockout if check is too frequent and/or if there is not enough traffic. In fact, you need in this case to check MySQL "max_connect_errors" value as if a connection is established successfully within fewer than MySQL "max_connect_errors" attempts after a previous connection was interrupted, the error count for the host is cleared to zero. If HAProxy's server get blocked, the "FLUSH HOSTS" statement is the only way to unblock it. Remember that this does not check database presence nor database consistency. To do this, you can use an external check with xinetd for example. The check requires MySQL >=3.22, for older version, please use TCP check. Most often, an incoming MySQL server needs to see the client's IP address for various purposes, including IP privilege matching and connection logging. When possible, it is often wise to masquerade the client's IP address when connecting to the server using the "usesrc" argument of the "source" keyword, which requires the transparent proxy feature to be compiled in, and the MySQL server to route the client via the machine hosting HAProxy.启用或禁用关闭后立即清理会话资源 可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
When clients or servers abort connections in a dirty way (e.g. they are physically disconnected), the session timeouts triggers and the session is closed. But it will remain in FIN_WAIT1 state for some time in the system, using some resources and possibly limiting the ability to establish newer connections. When this happens, it is possible to activate "option nolinger" which forces the system to immediately remove any socket's pending data on close. Thus, a TCP RST is emitted, any pending data are truncated, and the session is instantly purged from the system's tables. The generally visible effect for a client is that responses are truncated if the close happens with a last block of data (e.g. on a redirect or error response). On the server side, it may help release the source ports immediately when forwarding a client aborts in tunnels. In both cases, TCP resets are emitted and given that the session is instantly destroyed, there will be no retransmit. On a lossy network this can increase problems, especially when there is a firewall on the lossy side, because the firewall might see and process the reset (hence purge its session) and block any further traffic for this session,, including retransmits from the other side. So if the other side doesn't receive it, it will never receive any RST again, and the firewall might log many blocked packets. For all these reasons, it is strongly recommended NOT to use this option, unless absolutely needed as a last resort. In most situations, using the "client-fin" or "server-fin" timeouts achieves similar results with a more reliable behavior. On Linux it's also possible to use the "tcp-ut" bind or server setting. This option may be used both on frontends and backends, depending on the side where it is required. Use it on the frontend for clients, and on the backend for servers. While this option is technically supported in "defaults" sections, it must really not be used there as it risks to accidentally propagate to sections that must no use it and to cause problems there. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
启用向服务器发送的请求中插入 X-Original-To 头 可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<network> 是一个可选参数,用于为匹配 <network> 的源禁用此选项。<name> 是一个可选参数,用于指定一个不同的 "X-Original-To" 标头名称。
Since HAProxy can work in transparent mode, every request from a client can be redirected to the proxy and HAProxy itself can proxy every request to a complex SQUID environment and the destination host from SO_ORIGINAL_DST will be lost. This is annoying when you want access rules based on destination ip addresses. To solve this problem, a new HTTP header "X-Original-To" may be added by HAProxy to all requests sent to the server. This header contains a value representing the original destination IP address. Since this must be configured to always use the last occurrence of this header only. Note that only the last occurrence of the header must be used, since it is really possible that the client has already brought one. The keyword "header" may be used to supply a different header name to replace the default "X-Original-To". This can be useful where you might already have a "X-Original-To" header from a different application, and you need preserve it. Also if your backend server doesn't use the "X-Original-To" header and requires different one. Sometimes, a same HAProxy instance may be shared between a direct client access and a reverse-proxy access (for instance when an SSL reverse-proxy is used to decrypt HTTPS traffic). It is possible to disable the addition of the header for a known destination address or network by adding the "except" keyword followed by the network address. In this case, any destination IP matching the network will not cause an addition of this header. Most common uses are with private networks or 127.0.0.1. IPv4 and IPv6 are both supported. This option may be specified either in the frontend or in the backend. If at least one of them uses it, the header will be added. Note that the backend's setting of the header subargument takes precedence over the frontend's if both are defined.
# 原始目标地址 frontend www mode http option originalto except 127.0.0.1 # 这些服务器希望在 X-Client-Dst 中获取 IP 地址 backend www mode http option originalto header X-Client-Dst
启用或禁用对故障服务器的强制持久性 可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
当 HTTP 请求到达一个带有引用故障服务器的 cookie 的后端时,默认情况下它会被重新分派到另一台服务器。如果绝对需要,可以使用 "option persist" 强制将请求首先发送到故障服务器。一个常见的用例是当服务器处于极端负载下并不断地出现状态切换时。在这种情况下,用户仍将被导向到他们打开会话的服务器,希望他们能得到正确的服务。建议将 "option redispatch" 与此选项结合使用,以便在无法连接到服务器的情况下(服务器确定故障),客户端最终将被重定向到另一台有效的服务器。如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
使用 PostgreSQL 健康检查来测试服务器 可在以下上下文中使用:tcp
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<username> 这是连接到 PostgreSQL 服务器时将使用的用户名。
此检查发送一个 PostgreSQL StartupMessage 并等待认证请求或 ErrorResponse 消息。这是一个基本但有用的测试,不会在服务器上产生错误或中止连接。此检查与 "mysql-check" 相同。
允许多个负载均衡的请求保留在同一台服务器上 可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
When the load balancing algorithm in use is not deterministic, and a previous request was sent to a server to which HAProxy still holds a connection, it is sometimes desirable that subsequent requests on a same session go to the same server as much as possible. Note that this is different from persistence, as we only indicate a preference which HAProxy tries to apply without any form of warranty. The real use is for keep-alive connections sent to servers. When this option is used, HAProxy will try to reuse the same connection that is attached to the server instead of rebalancing to another server, causing a close of the connection. This can make sense for static file servers. It does not make much sense to use this in combination with hashing algorithms. Note, HAProxy already automatically tries to stick to a server which sends a 401 or to a proxy which sends a 407 (authentication required), when the load balancing algorithm is not deterministic. This is mandatory for use with the broken NTLM authentication challenge, and significantly helps in troubleshooting some faulty applications. Option prefer-last-server might be desirable in these environments as well, to avoid redistributing the traffic after every other response. It may be useful to precise here, which load balancing algorithms are considered deterministic. Deterministic algorithms will always select the same server for a given client data, assuming the set of available servers has not changed. In general, deterministic algorithms involve hasing or lookups on the incoming requests to choose the target server. However, this is not always the case; "static-rr", for example, can be also considered as deterministic because the server choice is based on the server's static weight, making the selection predictable. "sticky" algorithm provides deterministic routing for the returning clients. As for non-deterministic algorithms, these algorithms select a server based on dynamic server state or simple rotation, so two consecutive requests are not guaranteed to land on the same server. option prefer-last-server is designed specifically for these. roundrobin, leastconn are examples of such algorithms. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
启用或禁用在连接失败时会话重新分发 可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<interval> 可选的整数值,用于控制重试连接时重新分发的频率。正值 P 表示希望在每第 P 次重试时进行重新分发,负值 N 表示希望在最后一次重试前的第 N 次重试时进行重新分发。例如,默认值 -1 保留了在最后一次重试时重新分发的历史行为,正值 1 表示每次重试都重新分发,正值 3 表示每三次重试重新分发一次。您可以使用值 0 禁用重新分发。
In HTTP mode, if a server designated by a cookie is down, clients may definitely stick to it, for example when using "option persist" or "force-persist", because they cannot flush the cookie, so they will not be able to access the service anymore. Specifying "option redispatch" will allow the proxy to break cookie or consistent hash based persistence and redistribute them to a working server. Active servers are selected from a subset of the list of available servers. Active servers that are not down or in maintenance (i.e., whose health is not checked or that have been checked as "up"), are selected in the following order: 1. Any active, non-backup server, if any, or, 2. If the "allbackups" option is not set, the first backup server in the list, or 3. If the "allbackups" option is set, any backup server. When a retry occurs, HAProxy tries to select another server than the last one. The new server is selected from the current list of servers. Sometimes, if the list is updated between retries (e.g., if numerous retries occur and last longer than the time needed to check that a server is down, remove it from the list and fall back on the list of backup servers), connections may be redirected to a backup server, though. It also allows to retry connections to another server in case of multiple connection failures. Of course, it requires having "retries" set to a nonzero value. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
使用 redis 健康检查来测试服务器 可在以下上下文中使用:tcp
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
可以测试服务器是否正确地使用 REDIS 协议通信,而不仅仅是测试它是否接受 TCP 连接。设置此选项后,会向服务器发送一个 PING redis 命令,并分析响应以查找 "+PONG" 响应消息。
option redis-check
使用 SMTP 健康检查来测试服务器 可在以下上下文中使用:tcp
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<hello> 是一个可选参数。它是要使用的“hello”命令。它可以是“HELO”(用于 SMTP)或“EHLO”(用于 ESMTP)。所有其他值都将转换为默认命令(“HELO”)。<domain> 是要呈现给服务器的域名。只有在指定了 hello 命令时才能指定(并且是强制性的)。默认情况下,使用“localhost”。
When "option smtpchk" is set, the health checks will consist in TCP connections followed by an SMTP command. By default, this command is "HELO localhost". The server's return code is analyzed and only return codes starting with a "2" will be considered as valid. All other responses, including a lack of response will constitute an error and will indicate a dead server. This test is meant to be used with SMTP servers or relays. Depending on the request, it is possible that some servers do not log each connection attempt, so you may want to experiment to improve the behavior. Using telnet on port 25 is often easier than adjusting the configuration. Most often, an incoming SMTP server needs to see the client's IP address for various purposes, including spam filtering, anti-spoofing and logging. When possible, it is often wise to masquerade the client's IP address when connecting to the server using the "usesrc" argument of the "source" keyword, which requires the transparent proxy feature to be compiled in.
option smtpchk HELO mydomain.org
启用或禁用为每个套接字收集并提供单独的统计信息。 可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
启用或禁用双向套接字上的自动内核加速 可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
When this option is enabled either on a frontend or on a backend, HAProxy will automatically evaluate the opportunity to use kernel tcp splicing to forward data between the client and the server, in either direction. HAProxy uses heuristics to estimate if kernel splicing might improve performance or not. Both directions are handled independently. Note that the heuristics used are not much aggressive in order to limit excessive use of splicing. This option requires splicing to be enabled at compile time, and may be globally disabled with the global option "nosplice". Since splice uses pipes, using it requires that there are enough spare pipes. Important note: kernel-based TCP splicing is a Linux-specific feature which first appeared in kernel 2.6.25. It offers kernel-based acceleration to transfer data between sockets without copying these data to user-space, thus providing noticeable performance gains and CPU cycles savings. Since many early implementations are buggy, corrupt data and/or are inefficient, this feature is not enabled by default, and it should be used with extreme care. While it is not possible to detect the correctness of an implementation, 2.6.29 is the first version offering a properly working implementation. In case of doubt, splicing may be globally disabled using the global "nosplice" keyword.
option splice-auto
如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
启用或禁用请求套接字上的自动内核加速 可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
当此选项在前端或后端启用时,HAProxy 将尽可能使用内核 TCP 拼接来转发从客户端到服务器的数据。如果备用管道不足,它可能仍会使用 recv/send 方案。此选项需要在编译时启用拼接,并且可以通过全局选项“nosplice”全局禁用。由于 splice 使用管道,因此使用它需要有足够的备用管道。重要说明:有关使用限制,请参阅“option splice-auto”。
option splice-request
如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
启用或禁用响应套接字上的自动内核加速 可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
当此选项在前端或后端启用时,HAProxy 将尽可能使用内核 TCP 拼接来转发从服务器到客户端的数据。如果备用管道不足,它可能仍会使用 recv/send 方案。此选项需要在编译时启用拼接,并且可以通过全局选项“nosplice”全局禁用。由于 splice 使用管道,因此使用它需要有足够的备用管道。重要说明:有关使用限制,请参阅“option splice-auto”。
option splice-response
如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
使用 SPOP 健康检查来测试服务器 可在以下上下文中使用:tcp
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
可以测试服务器是否正确地使用 SPOP 协议进行通信,而不仅仅是测试它是否接受 TCP 连接。设置此选项后,HAProxy 和服务器之间会执行 HELLO 握手,并分析响应以检查是否报告了错误。
option spop-check
启用或禁用在服务器端发送 TCP keepalive 数据包 可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
When there is a firewall or any session-aware component between a client and a server, and when the protocol involves very long sessions with long idle periods (e.g. remote desktops), there is a risk that one of the intermediate components decides to expire a session which has remained idle for too long. Enabling socket-level TCP keep-alives makes the system regularly send packets to the other end of the connection, leaving it active. The delay between keep-alive probes is controlled by the system only and depends both on the operating system and its tuning parameters. It is important to understand that keep-alive packets are neither emitted nor received at the application level. It is only the network stacks which sees them. For this reason, even if one side of the proxy already uses keep-alives to maintain its connection alive, those keep-alive packets will not be forwarded to the other side of the proxy. Please note that this has nothing to do with HTTP keep-alive. Using option "srvtcpka" enables the emission of TCP keep-alive probes on the server side of a connection, which should help when session expirations are noticed between HAProxy and a server. If this option has been enabled in a "defaults" section, it can be disabled in a specific instance by prepending the "no" keyword before it.
使用 SSLv3 客户端 hello 健康检查来测试服务器 可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
当某些基于 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
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
This health check method is intended to be combined with "tcp-check" command lists in order to support send/expect types of health check sequences. TCP checks currently support 4 modes of operations : - no "tcp-check" directive : the health check only consists in a connection attempt, which remains the default mode. - "tcp-check send" or "tcp-check send-binary" only is mentioned : this is used to send a string along with a connection opening. With some protocols, it helps sending a "QUIT" message for example that prevents the server from logging a connection error for each health check. The check result will still be based on the ability to open the connection only. - "tcp-check expect" only is mentioned : this is used to test a banner. The connection is opened and HAProxy waits for the server to present some contents which must validate some rules. The check result will be based on the matching between the contents and the rules. This is suited for POP, IMAP, SMTP, FTP, SSH, TELNET. - both "tcp-check send" and "tcp-check expect" are mentioned : this is used to test a hello-type protocol. HAProxy sends a message, the server responds and its response is analyzed. the check result will be based on the matching between the response contents and the rules. This is often suited for protocols which require a binding or a request/response model. LDAP, MySQL, Redis and SSL are example of such protocols, though they already all have their dedicated checks with a deeper understanding of the respective protocols. In this mode, many questions may be sent and many answers may be analyzed. A fifth mode can be used to insert comments in different steps of the script. For each tcp-check rule you create, you can add a "comment" directive, followed by a string. This string will be reported in the log and stderr in debug mode. It is useful to make user-friendly error reporting. The "comment" is of course optional. During the execution of a health check, a variable scope is made available to store data samples, using the "tcp-check set-var" operation. Freeing those variable is possible using "tcp-check unset-var".
# perform a POP check (analyze only server's banner) option tcp-check tcp-check expect string +OK\ POP3\ ready comment POP\ protocol # perform an IMAP check (analyze only server's banner) option tcp-check tcp-check expect string *\ OK\ IMAP4\ ready comment IMAP\ protocol # look for the redis master server after ensuring it speaks well # redis protocol, then it exits properly. # (send a command then analyze the response 3 times) option tcp-check tcp-check comment PING\ phase tcp-check send PING\r\n tcp-check expect string +PONG tcp-check comment role\ check tcp-check send info\ replication\r\n tcp-check expect string role:master tcp-check comment QUIT\ phase tcp-check send QUIT\r\n tcp-check expect string +OK forge a HTTP request, then analyze the response (send many headers before analyzing) option tcp-check tcp-check comment forge\ and\ send\ HTTP\ request tcp-check send HEAD\ /\ HTTP/1.1\r\n tcp-check send Host:\ www.mydomain.com\r\n tcp-check send User-Agent:\ HAProxy\ tcpcheck\r\n tcp-check send \r\n tcp-check expect rstring HTTP/1\..\ (2..|3..) comment check\ HTTP\ response
启用或禁用在接受序列中节省一个 ACK 数据包 可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
When an HTTP connection request comes in, the system acknowledges it on behalf of HAProxy, then the client immediately sends its request, and the system acknowledges it too while it is notifying HAProxy about the new connection. HAProxy then reads the request and responds. This means that we have one TCP ACK sent by the system for nothing, because the request could very well be acknowledged by HAProxy when it sends its response. For this reason, in HTTP mode, HAProxy automatically asks the system to avoid sending this useless ACK on platforms which support it (currently at least Linux). It must not cause any problem, because the system will send it anyway after 40 ms if the response takes more time than expected to come. During complex network debugging sessions, it may be desirable to disable this optimization because delayed ACKs can make troubleshooting more complex when trying to identify where packets are delayed. It is then possible to fall back to normal behavior by specifying "no option tcp-smart-accept". It is also possible to force it for non-HTTP proxies by simply specifying "option tcp-smart-accept". For instance, it can make sense with some services such as SMTP where the server speaks first. It is recommended to avoid forcing this option in a defaults section. In case of doubt, consider setting it back to automatic values by prepending the "default" keyword before it, or disabling it using the "no" keyword.
启用或禁用在连接序列中节省一个 ACK 数据包 可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
在某些系统(至少是 Linux)上,HAProxy 可以请求内核在收到连接请求时不立即发送一个空的 ACK,而是直接发送带有数据的请求。这可以在网络上节省一个数据包,从而提高性能。这对某些服务器也很有用,因为它们可以立即随传入连接一起获取请求。当在后端设置了 "option tcp-smart-connect" 时,此功能被启用。默认情况下不启用,因为它会使网络故障排除变得更加复杂。只在客户端先说话的协议(如 HTTP)中启用它才有意义。在其他情况下,如果没有数据可以代替 ACK 发送,则会发送一个正常的 ACK。如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字来在特定实例中禁用它。
启用或禁用在两端发送 TCP keepalive 数据包 可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
When there is a firewall or any session-aware component between a client and a server, and when the protocol involves very long sessions with long idle periods (e.g. remote desktops), there is a risk that one of the intermediate components decides to expire a session which has remained idle for too long. Enabling socket-level TCP keep-alives makes the system regularly send packets to the other end of the connection, leaving it active. The delay between keep-alive probes is controlled by the system only and depends both on the operating system and its tuning parameters. It is important to understand that keep-alive packets are neither emitted nor received at the application level. It is only the network stacks which sees them. For this reason, even if one side of the proxy already uses keep-alives to maintain its connection alive, those keep-alive packets will not be forwarded to the other side of the proxy. Please note that this has nothing to do with HTTP keep-alive. Using option "tcpka" enables the emission of TCP keep-alive probes on both the client and server sides of a connection. Note that this is meaningful only in "defaults" or "listen" sections. If this option is used in a frontend, only the client side will get keep-alives, and if this option is used in a backend, only the server side will get keep-alives. For this reason, it is strongly recommended to explicitly use "option clitcpka" and "option srvtcpka" when the configuration is split between frontends and backends.
启用 TCP 连接的高级日志记录,包含流状态和计时器 可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
clf 如果添加了 "clf" 参数,那么输出格式将是 CLF 格式,而不是 HAProxy 的默认 TCP 格式。当您需要将 HAProxy 的日志输入到仅支持 CLF 格式且不可扩展的特定日志分析器时,可以使用此选项。由于这需要 HTTP 格式,因此某些值已被预设。HTTP 请求将显示为 TCP,响应代码将显示为 000。
默认情况下,日志输出格式非常简单,只包含源地址和目标地址以及实例名称。通过指定 "option tcplog",每条日志行都会变成一种更丰富的格式,包括但不限于连接计时器、流状态、连接数、前端、后端和服务器名称,当然还有源地址和端口。此选项对于纯 TCP 代理非常有用,可以找出客户端或服务器是哪一方断开连接或超时。对于普通的 HTTP 代理,最好使用 "option httplog",它甚至更完整。 "option tcplog" 会覆盖任何先前的 "log-format" 指令。
启用客户端透明代理 可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
引入此选项是为了给第 3 层负载均衡器提供第 7 层持久性。其思想是利用操作系统的能力,将针对远程地址的传入连接重定向到本地进程(此处为 HAProxy),并让该进程知道最初请求的地址。使用此选项时,没有 cookie 的会话将被转发到传入请求的原始目标 IP 地址(该地址应与另一台设备的地址匹配),而带有 cookie 的请求仍将被转发到适当的服务器。请注意,与普遍看法相反,此选项不会使 HAProxy 在建立连接时向服务器呈现客户端的 IP。
执行外部检查时要运行的可执行文件 可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<command> 是要运行的外部命令
The arguments passed to the to the command are: <proxy_address> <proxy_port> <server_address> <server_port> The <proxy_address> and <proxy_port> are derived from the first listener that is either IPv4, IPv6 or a UNIX socket. In the case of a UNIX socket listener the proxy_address will be the path of the socket and the <proxy_port> will be the string "NOT_USED". In a backend section, it's not possible to determine a listener, and both <proxy_address> and <proxy_port> will have the string value "NOT_USED". Some values are also provided through environment variables. Environment variables : HAPROXY_PROXY_ADDR The first bind address if available (or empty if not applicable, for example in a "backend" section). HAPROXY_PROXY_ID The backend id. HAPROXY_PROXY_NAME The backend name. HAPROXY_PROXY_PORT The first bind port if available (or empty if not applicable, for example in a "backend" section or for a UNIX socket). HAPROXY_SERVER_ADDR The server address. HAPROXY_SERVER_CURCONN The current number of connections on the server. HAPROXY_SERVER_ID The server id. HAPROXY_SERVER_MAXCONN The server max connections. HAPROXY_SERVER_NAME The server name. HAPROXY_SERVER_PORT The server port if available (or empty for a UNIX socket). HAPROXY_SERVER_SSL "0" when SSL is not used, "1" when it is used HAPROXY_SERVER_PROTO The protocol used by this server, which can be one of "cli" (the haproxy CLI), "syslog" (syslog TCP server), "peers" (peers TCP server), "h1" (HTTP/1.x server), "h2" (HTTP/2 server), or "tcp" (any other TCP server). PATH The PATH environment variable used when executing the command may be set using "external-check path". If the command executed and exits with a zero status then the check is considered to have passed, otherwise the check is considered to have failed.
external-check command /bin/true
运行外部检查时使用的 PATH 环境变量的值 可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<path> 是执行外部命令时使用的路径
默认路径为 ""。
external-check path "/usr/bin:/bin"
启用基于 RDP cookie 的持久性 可在以下上下文中使用:tcp
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<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 初始数据包执行操作。与 "tcp-request connection" 不同,此操作在任何连接元素实例化、SSL 握手开始和完成之前执行,这在希望拒绝连接尝试时更有效。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是(!)![]() | 是![]() | 是![]() | 否![]() |
<action> 定义了在条件适用时要执行的操作。见下文。<condition> 是一个标准的仅限第 4 层的基于 ACL 的条件(见第 7 节)。然而,QUIC 初始规则执行得太早,即使对于某些第 4 层的样本提取方法也是如此,尽管没有配置警告,但可能会导致未指定的运行时行为,虽然它们不会崩溃。请考虑目前仅支持内部样本和第 4 层的 "src*" 和 "dst*"。
此操作在 QUIC 数据包解析的早期执行。因此,只支持最少的操作列表: - accept - dgram-drop - reject - send-retry
设置前端每秒接受的新会话数限制 可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<rate> <rate> 参数是一个整数,指定前端每秒接受的最大新会话数。
When the frontend reaches the specified number of new sessions per second, it stops accepting new connections until the rate drops below the limit again. During this time, the pending sessions will be kept in the socket's backlog (in system buffers) and HAProxy will not even be aware that sessions are pending. When applying very low limit on a highly loaded service, it may make sense to increase the socket's backlog using the "backlog" keyword. This feature is particularly efficient at blocking connection-based attacks or service abuse on fragile servers. Since the session rate is measured every millisecond, it is extremely accurate. Also, the limit applies immediately, no delay is needed at all to detect the threshold.将 SMTP 的连接速率限制为最大每秒 10 个listen smtp mode tcp bind :25 rate-limit sessions 10 server smtp1 127.0.0.1:1025
注意:当达到最大速率时,前端的状态不会改变,但如果启用了 "socket-stats" 选项,其套接字在统计信息中将显示为 "WAITING"。
如果/除非条件匹配,则返回 HTTP 重定向 可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
如果/除非条件匹配,HTTP 请求将导致重定向响应。如果未指定条件,则重定向无条件适用。
<loc> With "redirect location", the exact value in <loc> is placed into the HTTP "Location" header. When used in an "http-request" rule, <loc> value follows the Custom log format rules and can include some dynamic values (see Custom log format in section 8.2.6). <pfx> With "redirect prefix", the "Location" header is built from the concatenation of <pfx> and the complete URI path, including the query string, unless the "drop-query" option is specified (see below). As a special case, if <pfx> equals exactly "/", then nothing is inserted before the original URI. It allows one to redirect to the same URL (for instance, to insert a cookie). When used in an "http-request" rule, <pfx> value follows the Custom Log Format rules and can include some dynamic values (see Custom Log Format in section 8.2.6). <sch> With "redirect scheme", then the "Location" header is built by concatenating <sch> with "://" then the first occurrence of the "Host" header, and then the URI path, including the query string unless the "drop-query" option is specified (see below). If no path is found or if the path is "*", then "/" is used instead. If no "Host" header is found, then an empty host component will be returned, which most recent browsers interpret as redirecting to the same host. This directive is mostly used to redirect HTTP to HTTPS. When used in an "http-request" rule, <sch> value follows the Custom log format rules and can include some dynamic values (see Custom log format in section 8.2.6). <code> The code is optional. It indicates which type of HTTP redirection is desired. Only codes 301, 302, 303, 307 and 308 are supported, with 302 used by default if no code is specified. 301 means "Moved permanently", and a browser may cache the Location. 302 means "Moved temporarily" and means that the browser should not cache the redirection. 303 is equivalent to 302 except that the browser will fetch the location with a GET method. 307 is just like 302 but makes it clear that the same method must be reused. Likewise, 308 replaces 301 if the same method must be used. <option> There are several options which can be specified to adjust the expected behavior of a redirection : - "drop-query" When this keyword is used in a prefix-based redirection, then the location will be set without any possible query-string, which is useful for directing users to a non-secure page for instance. It has no effect with a location-type redirect. - "append-slash" This keyword may be used in conjunction with "drop-query" to redirect users who use a URL not ending with a '/' to the same one with the '/'. It can be useful to ensure that search engines will only see one URL. For this, a return code 301 is preferred. - "ignore-empty" This keyword only has effect when a location is produced using a log format expression (i.e. when used in http-request or http-response). It indicates that if the result of the expression is empty, the rule should silently be skipped. The main use is to allow mass-redirects of known paths using a simple map. - "set-cookie NAME[=value]" A "Set-Cookie" header will be added with NAME (and optionally "=value") to the response. This is sometimes used to indicate that a user has been seen, for instance to protect against some types of DoS. No other cookie option is added, so the cookie will be a session cookie. Note that for a browser, a sole cookie name without an equal sign is different from a cookie with an equal sign. - "set-cookie-fmt <fmt>" It is equivaliant to the option above, except the "Set-Cookie" header will be filled with the result of the log-format string <fmt> evaluation. Be carefull to respect the "NAME[=value]" format because no special check are performed during the configuration parsing. - "clear-cookie NAME[=]" A "Set-Cookie" header will be added with NAME (and optionally "="), but with the "Max-Age" attribute set to zero. This will tell the browser to delete this cookie. It is useful for instance on logout pages. It is important to note that clearing the cookie "NAME" will not remove a cookie set with "NAME=value". You have to clear the cookie "NAME=" for that, because the browser makes the difference. - "keep-query" When this keyword is used in a location-based redirection, then the query-string of the original URI, if any, will be appended to the location. If no query-string is found, nothing is added. If the location already contains a query-string, the original one will be appended with the '&' delimiter.
仅将登录 URL 移动到 HTTPS。acl clear dst_port 80 acl secure dst_port 8080 acl login_page url_beg /login acl logout url_beg /logout acl uid_given url_reg /login?userid=[^&]+ acl cookie_set hdr_sub(cookie) SEEN=1 redirect prefix https://mysite.com set-cookie SEEN=1 if !cookie_set redirect prefix https://mysite.com if login_page !secure redirect prefix http://mysite.com drop-query if login_page !uid_given redirect location http://mysite.com/ if !login_page secure redirect location / clear-cookie USERID= if logout
为不带 '/' 的文章请求发送重定向。acl missing_slash path_reg ^/article/[^/]*$ redirect code 301 prefix / drop-query append-slash if missing_slash
当 SSL 由 HAProxy 处理时,将所有 HTTP 流量重定向到 HTTPS。redirect scheme https if !{ ssl_fc }
在所有没有 'www.' 前缀的主机前添加该前缀http-request redirect code 301 location \ http://www.%[hdr(host)]%[capture.req.uri] \ unless { hdr_beg(host) -i www }
仅将旧 URL 永久重定向到新 URLhttp-request redirect code 301 location \ %[path,map_str(old-blog-articles.map)] ignore-empty
有关 ACL 的用法,请参见第 7 节。
设置在服务器失败后对其执行的重试次数 可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<value> 是在服务器失败后,请求或连接尝试应重试的次数。
By default, retries apply only to new connection attempts. However, when the "retry-on" directive is used, other conditions might trigger a retry (e.g. empty response, undesired status code), and each of them will count one attempt, and when the total number attempts reaches the value here, an error will be returned. In order to avoid immediate reconnections to a server which is restarting, a turn-around timer of min("timeout connect", one second) is applied before a retry occurs on the same server. When "option redispatch" is set, some retries may be performed on another server even if a cookie references a different server. By default this will only be the last retry unless an argument is passed to "option redispatch".
指定何时尝试自动重试失败的请求。此设置仅在 "mode" 设置为 http 时有效,否则将被静默忽略。可在以下上下文中使用:tcp, http可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<keywords> is a space-delimited list of keywords or HTTP status codes, each representing a type of failure event on which an attempt to retry the request is desired. Please read the notes at the bottom before changing this setting. The following keywords are supported : none never retry conn-failure retry when the connection or the SSL handshake failed and the request could not be sent. This is the default. empty-response retry when the server connection was closed after part of the request was sent, and nothing was received from the server. This type of failure may be caused by the request timeout on the server side, poor network condition, or a server crash or restart while processing the request. junk-response retry when the server returned something not looking like a complete HTTP response. This includes partial responses headers as well as non-HTTP contents. It usually is a bad idea to retry on such events, which may be caused a configuration issue (wrong server port) or by the request being harmful to the server (buffer overflow attack for example). response-timeout the server timeout stroke while waiting for the server to respond to the request. This may be caused by poor network condition, the reuse of an idle connection which has expired on the path, or by the request being extremely expensive to process. It generally is a bad idea to retry on such events on servers dealing with heavy database processing (full scans, etc) as it may amplify denial of service attacks. 0rtt-rejected retry requests which were sent over early data and were rejected by the server. These requests are generally considered to be safe to retry. <status> any HTTP status code among "401" (Unauthorized), "403" (Forbidden), "404" (Not Found), "408" (Request Timeout), "421" (Misdirected Request), "425" (Too Early), "429" (Too Many Requests), "500" (Server Error), "501" (Not Implemented), "502" (Bad Gateway), "503" (Service Unavailable), "504" (Gateway Timeout). all-retryable-errors retry request for any error that are considered retryable. This currently activates "conn-failure", "empty-response", "junk-response", "response-timeout", "0rtt-rejected", "500", "502", "503", and "504".
Using this directive replaces any previous settings with the new ones; it is not cumulative. Please note that using anything other than "none" and "conn-failure" requires to allocate a buffer and copy the whole request into it, so it has memory and performance impacts. Requests not fitting in a single buffer will never be retried (see the global tune.bufsize setting). You have to make sure the application has a replay protection mechanism built in such as a unique transaction IDs passed in requests, or that replaying the same request has no consequence, or it is very dangerous to use any retry-on value beside "conn-failure" and "none". Static file servers and caches are generally considered safe against any type of retry. Using a status code can be useful to quickly leave a server showing an abnormal behavior (out of memory, file system issues, etc), but in this case it may be a good idea to immediately redispatch the connection to another server (please see "option redispatch" for this). Last, it is important to understand that most causes of failures are the requests themselves and that retrying a request causing a server to misbehave will often make the situation even worse for this server, or for the whole service in case of redispatch. Unless you know exactly how the application deals with replayed requests, you should not use this directive. The default is "conn-failure".
retry-on 503 504
在后端声明一个服务器 可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<name> is the internal name assigned to this server. This name will appear in logs and alerts. If "http-send-name-header" is set, it will be added to the request header sent to the server. <address> is the IPv4 or IPv6 address of the server. Alternatively, a resolvable hostname is supported, but this name will be resolved during start-up. Address "0.0.0.0" or "*" has a special meaning. It indicates that the connection will be forwarded to the same IP address as the one from the client connection. This is useful in transparent proxy architectures where the client's connection is intercepted and HAProxy must forward to the original destination address. This is more or less what the "transparent" keyword does except that with a server it's possible to limit concurrency and to report statistics. Optionally, an address family prefix may be used before the address to force the family regardless of the address format, which can be useful to specify a path to a unix socket with no slash ('/'). Currently supported prefixes are : - 'ipv4@' -> address is always IPv4 - 'ipv6@' -> address is always IPv6 - 'unix@' -> address is a path to a local unix socket - 'abns@' -> address is in abstract namespace (Linux only) - 'abnsz@' -> address is in abstract namespace (Linux only) but it is explicitly zero-terminated. This means no \0 padding is used to complete sun_path. It is useful to interconnect with programs that don't implement the default abns naming logic that haproxy uses. - 'sockpair@' -> address is the FD of a connected unix socket or of a socketpair. During a connection, the backend creates a pair of connected sockets, and passes one of them over the FD. The bind part will use the received socket as the client FD. Should be used carefully. - 'rhttp@' [ EXPERIMENTAL ] -> custom address family for a passive server in HTTP reverse context. This is an experimental features which requires "expose-experimental-directives" on a line before this server. You may want to reference some environment variables in the address parameter, see section 2.3 about environment variables. The "init-addr" setting can be used to modify the way IP addresses should be resolved upon startup. <port> is an optional port specification. If set, all connections will be sent to this port. If unset, the same port the client connected to will be used. The port may also be prefixed by a "+" or a "-". In this case, the server's port will be determined by adding this value to the client's port. <param*> is a list of parameters for this server. The "server" keywords accepts an important number of options and has a complete section dedicated to it. Please refer to section 5 for more details.
server first 10.1.1.1:1080 cookie first check inter 1000 server second 10.1.1.2:1080 cookie second check inter 1000 server transp ipv4@ server backup "${SRV_BACKUP}:1080" backup server www1_dc1 "${LAN_DC1}.101:80" server www1_dc2 "${LAN_DC2}.101:80"
注意:关于 Linux 的抽象命名空间套接字,“abns” HAProxy 套接字使用整个 sun_path 长度作为地址长度。其他一些程序(如 socat)默认只使用字符串长度。在 socat 中向任何抽象套接字定义传递选项 “,unix-tightsocklen=0” 以使其与 HAProxy 兼容,或者改用 “abnsz” HAProxy 套接字族。
设置要读取、加载并应用于此后端中可用服务器的服务器状态文件。可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
它仅在指令 "load-server-state-from-file" 设置为 "local" 时适用。当未提供 <file> 时,如果使用了 "use-backend-name" 或未设置此指令,则使用后端名称。如果 <file> 以斜杠 '/' 开头,则它被视为绝对路径。否则,<file> 将与全局指令 "server-state-base" 连接。
下面的最小配置将使 HAProxy 查找状态服务器文件 '/etc/haproxy/states/bk'global server-state-file-base /etc/haproxy/states backend bk load-server-state-from-file
设置一个模板来初始化具有共享参数的服务器。这些服务器的名称由 <prefix> 和 <num | range> 参数构建。可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<prefix> A prefix for the server names to be built. <num | range> If <num> is provided, this template initializes <num> servers with 1 up to <num> as server name suffixes. A range of numbers <num_low>-<num_high> may also be used to use <num_low> up to <num_high> as server name suffixes. <fqdn> A FQDN for all the servers this template initializes. <port> Same meaning as "server" <port> argument (see "server" keyword). <params*> Remaining server parameters among all those supported by "server" keyword.
# 初始化 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
设置出站连接的源地址 可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<addr> is the IPv4 address HAProxy will bind to before connecting to a server. This address is also used as a source for health checks. The default value of 0.0.0.0 means that the system will select the most appropriate address to reach its destination. Optionally an address family prefix may be used before the address to force the family regardless of the address format, which can be useful to specify a path to a unix socket with no slash ('/'). Currently supported prefixes are : - 'ipv4@' -> address is always IPv4 - 'ipv6@' -> address is always IPv6 - 'unix@' -> address is a path to a local unix socket - 'abns@' -> address is in abstract namespace (Linux only) - 'abnsz@' -> address is in zero-terminated abstract namespace (Linux only) You may want to reference some environment variables in the address parameter, see section 2.3 about environment variables. <port> is an optional port. It is normally not needed but may be useful in some very specific contexts. The default value of zero means the system will select a free port. Note that port ranges are not supported in the backend. If you want to force port ranges, you have to specify them on each "server" line. <addr2> is the IP address to present to the server when connections are forwarded in full transparent proxy mode. This is currently only supported on some patched Linux kernels. When this address is specified, clients connecting to the server will be presented with this address, while health checks will still use the address <addr>. <port2> is the optional port to present to the server when connections are forwarded in full transparent proxy mode (see <addr2> above). The default value of zero means the system will select a free port. <hdr> is the name of a HTTP header in which to fetch the IP to bind to. This is the name of a comma-separated header list which can contain multiple IP addresses. By default, the last occurrence is used. This is designed to work with the X-Forwarded-For header and to automatically bind to the client's IP address as seen by previous proxy, typically Stunnel. In order to use another occurrence from the last one, please see the <occ> parameter below. When the header (or occurrence) is not found, no binding is performed so that the proxy's default IP address is used. Also keep in mind that the header name is case insensitive, as for any HTTP header. <occ> is the occurrence number of a value to be used in a multi-value header. This is to be used in conjunction with "hdr_ip(<hdr>)", in order to specify which occurrence to use for the source IP address. Positive values indicate a position from the first occurrence, 1 being the first one. Negative values indicate positions relative to the last one, -1 being the last one. This is helpful for situations where an X-Forwarded-For header is set at the entry point of an infrastructure and must be used several proxy layers away. When this value is not specified, -1 is assumed. Passing a zero here disables the feature. <name> is an optional interface name to which to bind to for outgoing traffic. On systems supporting this features (currently, only Linux), this allows one to bind all traffic to the server to this interface even if it is not the one the system would select based on routing tables. This should be used with extreme care. Note that using this option requires root privileges.
The "source" keyword is useful in complex environments where a specific address only is allowed to connect to the servers. It may be needed when a private address must be used through a public gateway for instance, and it is known that the system cannot determine the adequate source address by itself. An extension which is available on certain patched Linux kernels may be used through the "usesrc" optional keyword. It makes it possible to connect to the servers with an IP address which does not belong to the system itself. This is called "full transparent proxy mode". For this to work, the destination servers have to route their traffic back to this address through the machine running HAProxy, and IP forwarding must generally be enabled on this machine. In this "full transparent proxy" mode, it is possible to force a specific IP address to be presented to the servers. This is not much used in fact. A more common use is to tell HAProxy to present the client's IP address. For this, there are two methods : - present the client's IP and port addresses. This is the most transparent mode, but it can cause problems when IP connection tracking is enabled on the machine, because a same connection may be seen twice with different states. However, this solution presents the huge advantage of not limiting the system to the 64k outgoing address+port couples, because all of the client ranges may be used. - present only the client's IP address and select a spare port. This solution is still quite elegant but slightly less transparent (downstream firewalls logs will not match upstream's). It also presents the downside of limiting the number of concurrent connections to the usual 64k ports. However, since the upstream and downstream ports are different, local IP connection tracking on the machine will not be upset by the reuse of the same session. This option sets the default source for all servers in the backend. It may also be specified in a "defaults" section. Finer source address specification is possible at the server level using the "source" server option. Refer to section 5 for more information. In order to work, "usesrc" requires root privileges, or on supported systems, the "cap_net_raw" capability. See also the "setcap" global directive.
backend private # Connect to the servers using our 192.168.1.200 source address source 192.168.1.200 backend transparent_ssl1 # Connect to the SSL farm from the client's source address source 192.168.1.200 usesrc clientip backend transparent_ssl2 # Connect to the SSL farm from the client's source address and port # not recommended if IP conntrack is present on the local machine. source 192.168.1.200 usesrc client backend transparent_ssl3 # Connect to the SSL farm from the client's source address. It # is more conntrack-friendly. source 192.168.1.200 usesrc clientip backend transparent_smtp # Connect to the SMTP farm from the client's source address/port # with Tproxy version 4. source 0.0.0.0 usesrc clientip backend transparent_http # Connect to the servers using the client's IP as seen by previous # proxy. source 0.0.0.0 usesrc hdr_ip(x-forwarded-for,-1)
设置 TCP 在服务器端断开连接之前应发送的最大 keepalive 探测次数。可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<count> 是 keepalive 探测的最大次数。
此关键字对应于套接字选项 TCP_KEEPCNT。如果未指定此关键字,则使用系统范围的 TCP 参数 (tcp_keepalive_probes)。此设置的可用性取决于操作系统。已知在 Linux 上可以工作。
设置连接需要保持空闲多长时间后,TCP 开始发送 keepalive 探测(如果在服务器端启用了 TCP keepalive 数据包的发送)。可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<timeout> 是连接需要保持空闲的时间,之后 TCP 开始发送 keepalive 探测。默认以秒为单位指定,但如果数字后跟单位后缀,也可以是任何其他单位,如本文档开头所述。
此关键字对应于套接字选项 TCP_KEEPIDLE。如果未指定此关键字,则使用系统范围的 TCP 参数 (tcp_keepalive_time)。此设置的可用性取决于操作系统。已知在 Linux 上可以工作。
设置服务器端各个 keepalive 探测之间的时间。可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<timeout> 是各个 keepalive 探测之间的时间。默认以秒为单位指定,但如果数字后跟单位后缀,也可以是任何其他单位,如本文档开头所述。
此关键字对应于套接字选项 TCP_KEEPINTVL。如果未指定此关键字,则使用系统范围的 TCP 参数 (tcp_keepalive_intvl)。此设置的可用性取决于操作系统。已知在 Linux 上可以工作。
如果/除非条件匹配,则启用统计信息管理级别 可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
此语句如果/除非条件匹配,则启用统计信息管理级别。管理级别允许从 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
启用带身份验证的统计信息并授予帐户访问权限 可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<user> 是要授予访问权限的用户名 <passwd> 是与此用户关联的明文密码
This statement enables statistics with default settings, and restricts access to declared users only. It may be repeated as many times as necessary to allow as many users as desired. When a user tries to access the statistics without a valid account, a "401 Forbidden" response will be returned so that the browser asks the user to provide a valid user and password. The real which will be returned to the browser is configurable using "stats realm". Since the authentication method is HTTP Basic Authentication, the passwords circulate in cleartext on the network. Thus, it was decided that the configuration file would also use cleartext passwords to remind the users that those ones should not be sensitive and not shared with any other account. It is also possible to reduce the scope of the proxies which appear in the report using "stats scope". Though this statement alone is enough to enable statistics reporting, it is recommended to set all other settings in order to avoid relying on default unobvious parameters.
# 公共访问(仅限于此后端) 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
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
此语句使用构建时定义的默认设置启用统计报告。除非另有说明,否则将使用以下设置:- 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
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
默认情况下,统计页面会报告一些有用的状态信息以及统计数据。其中包括 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
统计信息访问控制 可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
与 "http-request" 类似,这组选项允许精细控制对统计信息的访问。每个选项后面都可以跟 if/unless 和 acl。第一个匹配条件的选项(或没有条件的选项)是最终的。对于 "deny",将返回 403 错误;对于 "allow",将执行正常处理;对于 "auth",将返回 401/407 错误代码,以便要求客户端输入用户名和密码。每个实例的 http-request 语句数量没有固定限制。
启用统计信息并设置身份验证领域 可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<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
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<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
启用统计信息并限制访问范围 可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<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
在统计信息页面上启用描述报告。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<desc> 是一个可选的要报告的描述。如果未指定,则自动使用全局部分的描述。此语句对于向客户提供共享服务的用户非常有用,其中每个客户的节点或描述应该不同。尽管此语句本身足以启用统计报告,但建议设置所有其他设置,以避免依赖默认的不明显参数。默认情况下不显示描述。
# 内部监控访问(无限制) backend private_monitoring stats enable stats show-desc Master node for Europe, Asia, Africa stats uri /admin?stats stats refresh 5s
在统计信息页面上启用报告附加信息 可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
在统计信息页面上启用报告附加信息: - cap: 功能(代理) - mode: tcp, http 或 health 之一(代理) - id: SNMP ID(代理、套接字、服务器) - IP(套接字、服务器) - cookie(后端、服务器) 尽管仅此语句就足以启用统计信息报告,但建议设置所有其他设置,以避免依赖默认的不明显参数。默认行为是不显示此信息。
启用在统计页面上显示额外的统计模块。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
新的列会以工具提示的形式添加到包含额外统计值行的末尾。虽然仅此语句就足以启用统计报告,但建议设置所有其他设置,以避免依赖于默认的不明显参数。默认行为是不显示此信息。
在统计页面上启用主机名报告。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<name> 是一个可选的要报告的名称。如果未指定,则自动使用全局部分的节点名称。
此语句对于向其客户提供共享服务的用户非常有用,在为每个客户提供的统计页面上,节点或描述可能会有所不同。默认行为是不显示主机名。虽然仅此语句就足以启用统计报告,但建议设置所有其他设置,以避免依赖于默认的不明显参数。
# 内部监控访问(无限制) backend private_monitoring stats enable stats show-node Europe-1 stats uri /admin?stats stats refresh 5s
启用统计并定义用于访问它们的 URI 前缀。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<prefix> 是任何将被重定向到统计信息的 URI 的前缀。此前缀可能包含一个问号('?')以指示查询字符串的一部分。
The statistics URI is intercepted on the relayed traffic, so it appears as a page within the normal application. It is strongly advised to ensure that the selected URI will never appear in the application, otherwise it will never be possible to reach it in the application. The default URI compiled in HAProxy is "/haproxy?stats", but this may be changed at build time, so it's better to always explicitly specify it here. It is generally a good idea to include a question mark in the URI so that intermediate proxies refrain from caching the results. Also, since any string beginning with the prefix will be accepted as a stats request, the question mark helps ensuring that no valid URI will begin with the same words. It is sometimes very convenient to use "/" as the URI prefix, and put that statement in a "listen" instance of its own. That makes it easy to dedicate an address or a port to statistics only. Though this statement alone is enough to enable statistics reporting, it is recommended to set all other settings in order to avoid relying on default unobvious parameters.
# 公共访问(仅限于此后端) 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)到一台服务器。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<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
定义一个请求模式,将用户与服务器关联。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
注意:此形式完全等同于后跟 "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
定义一个请求模式,用于在粘滞表中创建一个条目。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<pattern> 是 第 7.3 节 中描述的样本表达式规则。它描述了在选择服务器后,将分析、提取并存储在表中的传入请求或连接的哪些元素。 <table> 是一个可选的粘性表名称。如果未指定,则使用相同后端的表。粘性表使用 "stick-table" 语句声明。 <cond> 是一个可选的存储条件。它使得仅在满足(或不满足)某些条件时才存储某些标准成为可能。例如,它可以用于存储源 IP 地址,除非请求通过一个已知的代理,在这种情况下,我们将存储一个包含该 IP 地址的头的转换形式。
有些协议或应用程序需要复杂的粘性规则,不能总是简单地依赖 cookie 或哈希。"stick store-request" 语句描述了一个规则,用于决定从请求中提取什么以及何时提取,以便将其存储到粘性表中,供后续请求使用 "stick match" 语句进行匹配。显然,提取的部分必须有意义,并且有机会在后续请求中被匹配。例如,存储客户端的 IP 地址通常有意义。存储在 URL 参数中找到的 ID 也有意义。存储源端口几乎永远没有意义,因为它会被随机匹配。有关可能的模式和转换规则的完整列表,请参阅第 7 节。该表必须使用 "stick-table" 语句声明。它必须是与模式兼容的类型。默认情况下,它位于同一后端中。可以通过使用 "table" 关键字引用它来与其他后端共享表。如果引用了另一个表,则使用后端内部的服务器 ID。默认情况下,每个后端中的所有服务器 ID 都从 1 开始,因此服务器顺序就足够了。但在有疑问的情况下,强烈建议使用其 "id" 设置强制指定服务器 ID。可以使用后跟条件的 "if" 或 "unless" 来限制 "stick store-request" 语句的适用条件。此条件将在解析请求时进行评估,因此可以使用任何标准。有关基于 ACL 的条件,请参阅第 7 节。对 "stick store-request" 语句的数量没有限制,但每个请求或响应最多有 8 个并发存储。这使得最多可以存储 8 个标准,所有这些标准都从请求或响应中提取,无论规则数量如何。只有前 8 个匹配项会被保留。使用此功能,可以一次性填充多个表,以期增加在另一种协议或访问方法上识别用户的机会。使用多个具有相同表的 store-request 规则是可能的,并且可以通过按偏好降序排列规则来查找要依赖的最佳标准。对于给定的表,只存储第一个提取的标准。引用同一表的所有后续 store-request 规则都将被跳过,并且不会评估其 ACL。在建立服务器连接后评估 "store-request" 规则,以便表将包含处理请求的真实服务器。
# 将 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
为当前部分配置粘滞表。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
ip 声明为 "type ip" 的表将只存储 IPv4 地址。此形式非常紧凑(每个条目约 50 字节),允许非常快的条目查找和存储,几乎没有开销。这主要用于存储客户端源 IP 地址。ipv6 声明为 "type ipv6" 的表将只存储 IPv6 地址。此形式非常紧凑(每个条目约 60 字节),允许非常快的条目查找和存储,几乎没有开销。这主要用于存储客户端源 IP 地址。integer 声明为 "type integer" 的表将存储 32 位整数,例如,它可以表示在请求中找到的客户端标识符。string 声明为 "type string" 的表将存储最多 <len> 个字符的子字符串。如果模式提取器提供的字符串大于 <len>,则在存储之前将其截断。在匹配期间,表中字符串与提取模式之间最多比较 <len> 个字符。如果未指定,字符串会自动限制为 32 个字符。binary 声明为 "type binary" 的表将存储 <len> 字节的二进制块。如果模式提取器提供的块大于 <len>,则在存储之前将其截断。如果示例表达式提供的块短于 <len>,则将用 0 填充。如果未指定,块会自动限制为 32 字节。<length> 是将存储在 "string" 类型表中的最大字符数(请参阅上面的 "string" 类型)。或者是 "binary" 类型表中块的字节数。更改此参数时要小心,因为内存使用量将按比例增加。<size> 是表中可容纳的最大条目数。此值直接影响内存使用量。每个条目大约计算 50 字节,加上字符串的大小(如果有)。大小支持后缀 "k"、"m"、"g" 分别表示 2^10、2^20 和 2^30 因子。[nopurge] 表示当表满时,我们拒绝清除较旧的条目。如果未指定,并且当 HAProxy 想要在表中存储条目时表已满,它将刷新一些最旧的条目,以便为新条目释放空间。这通常是期望的行为。在某些特定情况下,可能需要拒绝新条目而不是清除旧条目。当要存储的数据量远远超出硬件限制时,或者我们宁愿不向新客户端提供访问权限,也不愿拒绝已连接的客户端时,可能会出现这种情况。使用此参数时,请确保正确设置 "expire" 参数(请参阅下文)。<peersect> 是用于复制的对等部分名称。将键与服务器 ID 相关联的条目与在此部分中声明的远程对等体保持同步。在软重启期间,所有条目也会自动从本地对等体(旧进程)中学习。<wtable> 是粘性表的名称,除了源表之外,对等体更新也将写入该表。<wtable> 必须与正在定义的表类型相同,并且必须具有相同的键长度,并且源表本身不能用作目标表。每当通过对等体在源表上接收到条目更新时,haproxy 将尝试刷新相关的 <wtable> 条目。如果条目尚不存在,则会创建它,否则会更新其值及其计时器。请注意,只有不涉及算术运算的类型(例如 server_id、server_key 和 gpt)才会被写入 <wtable>,以防止来自远程表的已处理值干扰在本地目标表上执行的算术运算。(即:防止共享累加计数器无限增长)此选项的一个常见用途是能够在对等集群设置中使用粘性规则(用于服务器持久性),因为匹配键将从远程表学习。<expire> 定义了条目在表中自上次创建、使用 'track-sc' 刷新或使用 'stick match' 或 'stick on' 规则匹配以来的最大持续时间。过期延迟使用标准时间格式定义,类似于各种超时。最大持续时间略高于 24 天。有关详细信息,请参阅第 2.5 节。如果未指定此延迟,则会话不会自动过期,但一旦满,较旧的条目将被删除。如果未指定过期延迟,请确保不要使用 "nopurge" 参数。注意:'table_*' 转换器执行查找,但不会更新触摸过期时间,因为它们不需要 'track-sc'。<srvkey> 指定如何为粘性表的目的标识每个服务器。有效值是 "name" 和 "addr"。如果给定 "name",则为服务器的 <name> 参数(可能由模板生成)。如果给定 "addr",则通过其当前网络地址(包括端口)标识服务器。如果您使用服务发现来生成具有对等粘性表的服务器地址,并希望在对等体之间始终如一地使用同一主机进行粘性令牌,则 "addr" 特别有用。<data_type> 用于在粘性表中存储附加信息。ACL 可以使用此信息来控制与匹配粘性表的客户端活动相关的各种标准。对于此处指定的每个项目,每个条目的大小都会膨胀,以便附加数据可以容纳。可以与条目一起存储几种数据类型。可以在 "store" 关键字之后指定多个数据类型,作为逗号分隔列表。或者,可以重复 "store" 关键字,后跟一个或多个数据类型。除了自动检测和启用的 "server_id" 类型外,所有数据类型都必须明确声明才能存储。如果 ACL 引用了未存储的数据类型,则 ACL 将简单地不匹配。某些数据类型需要一个参数,该参数必须紧跟在类型之后(在括号内)传递。有关支持的数据类型及其参数,请参阅下文。<factor> 用于定义应用于输入/输出字节速率的因子。不是计算每个字节,而是计算字节块。在内部,速率是在 32 位计数器上定义的。通过使用此参数,可以使速率超过定义周期内的 4G。该因子必须大于 0 且小于或等于 1024。
可以与条目一起存储的数据类型如下:- server_id:这是一个整数,保存分配给请求的服务器的数字 ID。它由 "stick match"、"stick store" 和 "stick on" 规则使用。引用时会自动启用。- gpc(<nb>):通用计数器数组,包含 <nb> 个元素。这是一个正 32 位整数数组,可用于计算任何内容。大多数情况下,它们将用作某些条目上的增量计数器,例如,用于记录达到限制并触发某些操作。此数组最多限制为 100 个元素:gpc0 到 gpc99,以确保对等更新消息的构建可以容纳在缓冲区中。用户应考虑到大量的计数器会增加数据大小,并增加使用对等协议的流量负载,因为每次更新时都会推送所有数据/计数器。此 data_type 将排除在同一表上使用遗留 data_type 'gpc0' 和 'gpc1'。使用 'gpc' 数组 data_type,所有与 'gpc0' 和 'gpc1' 相关的获取和操作都将应用于此数组的前两个元素。- gpc_rate(<nb>,<period>):通用计数器在一段时间内的增量率数组。这些元素是正 32 位整数,可用于任何目的。就像 <gpc> 一样,计算事件,但不是保留累积数字,而是保持计数器增加的速率。大多数情况下,它将用于测量某些事件(例如,对特定 URL 的请求)发生的频率。此数组最多限制为 100 个元素:gpt(100) 允许存储 gpc0 到 gpc99,以确保对等更新消息的构建可以容纳在缓冲区中。数组不能包含少于 1 个元素:如果您只想存储计数器 gpc0,请使用 gpc(1)。用户应考虑到大量的计数器会增加数据大小,并增加使用对等协议的流量负载,因为每次更新时都会推送所有数据/计数器。此 data_type 将排除在同一表上使用遗留 data_type 'gpc0_rate' 和 'gpc1_rate'。使用 'gpc_rate' 数组 data_type,所有与 'gpc0' 和 'gpc1' 相关的获取和操作都将应用于此数组的前两个元素。- gpc0:第一个通用计数器。它是一个正 32 位整数,可用于任何目的。大多数情况下,它将用于在某些条目上放置特殊标签,例如,用于记录检测到特定行为,并且必须了解以供将来匹配。- gpc0_rate(<period>):第一个通用计数器在一段时间内的增量率。它是一个正 32 位整数,可用于任何目的。就像 <gpc0> 一样,它计算事件,但不是保留累积数字,而是保持计数器增加的速率。大多数情况下,它将用于测量某些事件(例如,对特定 URL 的请求)发生的频率。- gpc1:第二个通用计数器。它是一个正 32 位整数,可用于任何目的。大多数情况下,它将用于在某些条目上放置特殊标签,例如,用于记录检测到特定行为,并且必须了解以供将来匹配。- gpc1_rate(<period>):第二个通用计数器在一段时间内的增量率。它是一个正 32 位整数,可用于任何目的。就像 <gpc1> 一样,它计算事件,但不是保留累积数字,而是保持计数器增加的速率。大多数情况下,它将用于测量某些事件(例如,对特定 URL 的请求)发生的频率。- gpt(<nb>):通用标签数组,包含 <nb> 个元素。这是一个正 32 位整数数组,可用于任何目的。大多数情况下,它们将用于在某些条目上放置特殊标签,例如,用于记录检测到特定行为,并且必须了解以供将来匹配。此数组最多限制为 100 个元素:gpt(100) 允许存储 gpt0 到 gpt99,以确保对等更新消息的构建可以容纳在缓冲区中。数组不能包含少于 1 个元素:如果您只想存储标签 gpt0,请使用 gpt(1)。用户应考虑到大量的计数器会增加数据大小,并增加使用对等协议的流量负载,因为每次更新时都会推送所有数据/计数器。此 data_type 将排除在同一表上使用遗留 data_type 'gpt0'。使用 'gpt' 数组 data_type,所有与 'gpt0' 相关的获取和操作都将应用于此数组的第一个元素。- gpt0:第一个通用标签。它是一个正 32 位整数,可用于任何目的。大多数情况下,它将用于在某些条目上放置特殊标签,例如,用于记录检测到特定行为,并且必须了解以供将来匹配- conn_cnt:连接计数。它是一个正 32 位整数,用于计算匹配此条目的客户端收到的连接绝对数。这并不意味着连接被接受,只是收到了它们。- conn_cur:当前连接数。它是一个正 32 位整数,用于存储条目的并发连接数。一旦传入连接匹配条目,它就会递增,一旦连接离开,它就会递减。这样,可以随时知道条目的确切并发连接数。- conn_rate(<period>):频率计数器(占用 12 字节)。它接受一个整数参数 <period>,以毫秒为单位指示测量平均值的周期长度。它报告该周期内的平均传入连接速率,以每周期连接数表示。结果是一个整数,可以使用 ACL 进行匹配。- sess_cnt:会话计数。它是一个正 32 位整数,用于计算匹配此条目的客户端收到的会话绝对数。会话是层 4 规则接受的连接。- sess_rate(<period>):频率计数器(占用 12 字节)。它接受一个整数参数 <period>,以毫秒为单位指示测量平均值的周期长度。它报告该周期内的平均传入会话速率,以每周期会话数表示。结果是一个整数,可以使用 ACL 进行匹配。- http_req_cnt:HTTP 请求计数。它是一个正 32 位整数,用于计算匹配此条目的客户端收到的 HTTP 请求绝对数。无论它们是否是有效请求都无关紧要。请注意,当客户端使用 keep-alive 时,这与会话不同。- http_req_rate(<period>):频率计数器(占用 12 字节)。它接受一个整数参数 <period>,以毫秒为单位指示测量平均值的周期长度。它报告该周期内的平均 HTTP 请求速率,以每周期请求数表示。结果是一个整数,可以使用 ACL 进行匹配。无论它们是否是有效请求都无关紧要。请注意,当客户端使用 keep-alive 时,这与会话不同。- http_err_cnt:HTTP 错误计数。它是一个正 32 位整数,用于计算匹配此条目的客户端引起的 HTTP 请求错误绝对数。在无效和截断的请求、被拒绝或被拖延的请求以及身份验证失败时计算错误。如果服务器响应 4xx,则该请求也被计为错误,因为它是客户端触发的错误(例如漏洞扫描)。- http_err_rate(<period>):频率计数器(占用 12 字节)。它接受一个整数参数 <period>,以毫秒为单位指示测量平均值的周期长度。它报告该周期内的平均 HTTP 请求错误率,以每周期请求数表示(有关计为错误的内容,请参阅上面的 http_err_cnt)。结果是一个整数,可以使用 ACL 进行匹配。- http_fail_cnt:HTTP 失败计数。它是一个正 32 位整数,用于计算匹配此条目的服务器引起的 HTTP 响应失败绝对数。在无效和截断的响应以及除 501 或 505 之外的任何 5xx 响应时计算错误。它旨在与路径或 URI 结合使用以检测服务故障。- http_fail_rate(<period>):频率计数器(占用 12 字节)。它接受一个整数参数 <period>,以毫秒为单位指示测量平均值的周期长度。它报告该周期内的平均 HTTP 响应失败率,以每周期请求数表示(有关计为失败的内容,请参阅上面的 http_fail_cnt)。结果是一个整数,可以使用 ACL 进行匹配。- bytes_in_cnt:客户端到服务器字节数。它是一个正 64 位整数,用于计算从匹配此条目的客户端收到的累积字节数。标头包含在计数中。这可用于限制照片或视频服务器上上传功能的滥用。- bytes_in_rate(<period>):频率计数器(占用 12 字节)。它接受一个整数参数 <period>,以毫秒为单位指示测量平均值的周期长度。它报告该周期内的平均传入字节率,以每周期字节数表示。它可用于检测上传过多且过快的用户。警告:对于大上传,上传数据量可能会在终止时计算一次,从而导致平均传输速度出现峰值,而不是平滑的传输速度。使用 "option contstats" 可以部分平滑,但这还不完美。建议使用 byte_in_cnt 以获得更好的公平性。- bytes_out_cnt:服务器到客户端字节数。它是一个正 64 位整数,用于计算发送到匹配此条目的客户端的累积字节数。标头包含在计数中。这可用于限制机器人吸取整个站点的滥用。- bytes_out_rate(<period>):频率计数器(占用 12 字节)。它接受一个整数参数 <period>,以毫秒为单位指示测量平均值的周期长度。它报告该周期内的平均传出字节率,以每周期字节数表示。它可用于检测下载过多且过快的用户。警告:对于大传输,传输数据量可能会在终止时计算一次,从而导致平均传输速度出现峰值,而不是平滑的传输速度。使用 "option contstats" 可以部分平滑,但这还不完美。建议使用 byte_out_cnt 以获得更好的公平性。- glitch_cnt:前端故障计数。它是一个正 32 位整数,用于计算在前端连接上报告的累积故障数。故障对应于来自客户端的异常或意外操作(协议方面),可能表明客户端有严重缺陷或可能是攻击者。因此,此计数器有助于决定在这种情况下如何处理它们。- glitch_rate(<period>):频率计数器(占用 12 字节)。它接受一个整数参数 <period>,以毫秒为单位指示测量平均值的周期长度。它报告该周期内的平均前端故障率。它可用于检测有缺陷的客户端或潜在攻击者,这些攻击者执行从协议角度来看不常见或意外的操作,前提是 HAProxy 将它们标记为如此。每个代理只有一个粘性表。在撰写本文档时,每个代理拥有多个表似乎没有用。如果需要,只需创建一个带有粘性表的虚拟后端并引用它。重要的是要理解,基于学习信息的粘性有一些限制,包括除非正确配置对等体以在重启时传输此类信息(推荐),否则所有学习的关联都会在重启时丢失这一事实。通常,它可以作为补充,但不总是作为唯一的粘性。最后,存储许多数据类型时,内存需求可能很重要。确实,在每个条目中一次存储所有上述指示器需要 116 字节/条目,或者对于 100 万个条目的表需要 116 MB。这绝对不能忽视。
# 在 5 分钟内跟踪多达 100 万个 IP 地址的计数器 # 并存储一个通用计数器和在 30 秒滑动窗口上计算的 # 平均连接速率。 stick-table type ip size 1m expire 5m store gpc0,conn_rate(30s)
定义一个响应模式,用于在粘滞表中创建一个条目。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<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 client 和 server hello。 tcp-request inspect-delay 5s tcp-request content accept if clienthello # 默认情况下,响应检查延迟没有超时。 tcp-response content accept if serverhello # SSL 会话 ID (SSLID) 可能存在于 client hello 或 server hello 中。 # 它的长度在偏移量 43 处编码为 1 字节,其值始于 # 偏移量 44。 # 如果是 client hello,则在请求上匹配并学习。 stick on req.payload_lv(43,1) if clienthello # 如果是 server hello,则在响应上学习。 stick store-response resp.payload_lv(43,1) if serverhello server s1 192.168.1.1:443 server s2 192.168.1.1:443
为以下 tcp-check 规则定义一个注释,如果失败,将在日志中报告。可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<字符串> 是如果以下 tcp-check 规则失败时要在日志中添加的注释消息。
它仅适用于 connect、send 和 expect 规则。这对于进行用户友好的错误报告很有用。
打开一个新连接。可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
comment <msg> 定义了如果规则评估失败要报告的消息。default 使用服务器行的默认选项执行健康检查。仅当未重新定义时才使用服务器选项。port <expr> 如果未设置,则使用检查端口或服务器端口。它告诉 HAProxy 连接到哪里。<port> 必须是有效的 TCP 端口整数,从 1 到 65535,或者是 sample-fetch 表达式。addr <ip> 定义执行健康检查的 IP 地址。send-proxy 发送 PROXY 协议字符串via-socks4 启用使用上游 socks4 代理的传出健康检查。ssl 打开加密连接sni <sni> 指定用于通过 SSL 执行健康检查的 SNI。alpn <alpn> 定义要使用 ALPN 宣传的协议。协议列表由逗号分隔的协议名称列表组成,例如:"http/1.1,http/1.0"(不带引号)。如果未设置,则使用服务器 ALPN。proto <name> 强制连接使用多路复用器的协议。它必须是 TCP mux 协议,并且必须可以在后端使用。可用协议列表在 haproxy -vv 中报告。linger 干净地关闭连接,而不是使用单个 RST。
当一个应用程序依赖于多个 TCP 端口,或者当 HAProxy 在一个后端中对许多服务进行负载均衡时,有必要在将服务器视为可运行之前单独探测所有服务。当服务器行上既没有配置 TCP 端口也没有 server port 指令时,那么 'tcp-check connect port <端口>' 必须是序列的第一步。在 tcp-check 规则集中,'connect' 是必需的,并且也必须用 'connect' 规则来开始规则集。目的是确保管理员知道他们在做什么。当一个 connect 必须开始规则集时,它前面仍然可以有 set-var、unset-var 或 comment 规则。
# 检查服务器上的 HTTP 和 HTTPs 服务。 # 首先由于服务器行端口指令打开端口 80,然后 # tcp-check 打开端口 443,加密并在其上运行请求: option tcp-check tcp-check connect tcp-check send GET\ /\ HTTP/1.0\r\n tcp-check send Host:\ haproxy.1wt.eu\r\n tcp-check send \r\n tcp-check expect rstring (2..|3..) tcp-check connect port 443 ssl tcp-check send GET\ /\ HTTP/1.0\r\n tcp-check send Host:\ haproxy.1wt.eu\r\n tcp-check send \r\n tcp-check expect rstring (2..|3..) server www 10.0.0.1 check port 80 # 从单个服务器检查 POP 和 IMAP: option tcp-check tcp-check connect port 110 linger tcp-check expect string +OK\ POP3\ ready tcp-check connect port 143 tcp-check expect string *\ OK\ IMAP4\ ready server mail 10.0.0.1 check
指定在通用健康检查期间要收集和分析的数据。可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
comment <msg> 定义了如果规则评估失败要报告的消息。min-recv 是可选的,可以定义评估当前 expect 规则所需的最小数据量。如果收到的字节数低于此限制,则检查将等待更多数据。此选项可用于解决一些模糊的匹配规则,或避免对已知仍不完整的内容执行代价高昂的 regex 匹配。如果使用精确字符串(string 或 binary),则使用字符串长度与此参数之间的最小值。如果此参数设置为 -1,则忽略此参数。如果 expect 规则不匹配,则检查将等待更多数据。如果设置为 0,则评估结果始终是结论性的。<match> 是一个关键字,指示如何在响应中查找特定模式。关键字可以是 "string"、"rstring"、"binary" 或 "rbinary" 之一。关键字前面可以有感叹号 ("!") 来否定匹配。感叹号和关键字之间允许有空格。有关支持的关键字的更多详细信息,请参阅下文。ok-status <st> 是可选的,可用于设置检查状态,如果 expect 规则成功评估并且它是 tcp-check 规则集中的最后一条规则。支持 "L7OK"、"L7OKC"、"L6OK" 和 "L4OK":- L7OK:检查通过第 7 层- L7OKC:检查有条件地通过第 7 层,将服务器设置为 NOLB 状态。- L6OK:检查通过第 6 层- L4OK:检查通过第 4 层默认使用 "L7OK"。error-status <st> 是可选的,可用于设置检查状态,如果在 expect 规则评估期间发生错误。支持 "L7OKC"、"L7RSP"、"L7STS"、"L6RSP" 和 "L4CON":- L7OKC:检查有条件地通过第 7 层,将服务器设置为 NOLB 状态。- L7RSP:第 7 层无效响应 - 协议错误- L7STS:第 7 层响应错误,例如 HTTP 5xx- L6RSP:第 6 层无效响应 - 协议错误- L4CON:第 1-4 层连接问题默认使用 "L7RSP"。tout-status <st> 是可选的,可用于设置检查状态,如果在 expect 规则评估期间发生超时。支持 "L7TOUT"、"L6TOUT" 和 "L4TOUT":- L7TOUT:第 7 层(HTTP/SMTP)超时- L6TOUT:第 6 层(SSL)超时- L4TOUT:第 1-4 层超时默认使用 "L7TOUT"。on-success <fmt> 是可选的,可用于自定义日志中报告的信息消息,如果 expect 规则成功评估并且它是 tcp-check 规则集中的最后一条规则。<fmt> 是自定义日志格式(请参阅第 8.2.6 节)。on-error <fmt> 是可选的,可用于自定义日志中报告的信息消息,如果在 expect 规则评估期间发生错误。<fmt> 是自定义日志格式(请参阅第 8.2.6 节)。status-code <expr> 是可选的,可用于设置日志中报告的检查状态代码,无论成功还是错误。<expr> 是由 sample-fetch 和一些转换器组成的标准 HAProxy 表达式。<pattern> 是要查找的模式。它可以是字符串或正则表达式。如果模式包含空格,则必须使用通常的反斜杠 ('\') 进行转义。如果 match 设置为 binary,则模式必须以偶数个十六进制数字的形式传递。每两个数字序列将代表一个字节。十六进制数字可以使用大写或小写。
可用的匹配项有意类似于它们的 http-check 表亲:string <string>:测试响应缓冲区中的精确字符串匹配。如果响应缓冲区包含此精确字符串,则健康检查响应将被视为有效。如果 "string" 关键字前面带有 "!",则如果正文包含此字符串,则响应将被视为无效。这可用于在协议响应中查找强制模式,或者在协议横幅中出现特定错误时检测故障。rstring <regex>:在响应缓冲区上测试正则表达式。如果响应缓冲区匹配此表达式,则健康检查响应将被视为有效。如果 "rstring" 关键字前面带有 "!",则如果正文匹配表达式,则响应将被视为无效。string-lf <fmt>:在响应缓冲区中测试自定义日志格式匹配。如果响应缓冲区包含评估 <fmt> 所产生的字符串(遵循第 8.2.6 节中描述的自定义日志格式规则),则健康检查响应将被视为有效。如果前面带有 "!",则如果缓冲区包含该字符串,则响应将被视为无效。binary <hexstring>:在响应缓冲区中测试其十六进制形式的精确字符串匹配。如果响应缓冲区包含此精确十六进制字符串,则健康检查响应将被视为有效。目的是匹配二进制协议上的数据。rbinary <regex>:在响应缓冲区上测试正则表达式,如 "rstring"。但是,响应缓冲区会转换为其十六进制形式,包括 NUL 字节。这允许使用所有 regex 引擎来匹配任何二进制内容。十六进制转换的大小是原始响应的两倍。因此,预期的模式应该在最多一半的响应缓冲区大小上工作。binary-lf <hexfmt>:在响应缓冲区中测试其十六进制形式的自定义日志格式匹配。如果响应缓冲区包含评估 <fmt> 所产生的十六进制字符串(遵循自定义日志格式规则,请参阅第 8.2.6 节),则健康检查响应将被视为有效。如果前面带有 "!",则如果缓冲区包含十六进制字符串,则响应将被视为无效。在匹配响应缓冲区之前,十六进制字符串会转换为二进制字符串。重要的是要注意,响应将限制为由全局 "tune.bufsize" 选项定义的大小,该选项默认为 16384 字节。因此,使用 "string"、"rstring" 或 binary 时,太大的响应可能不包含强制模式。如果绝对需要大响应,可以通过设置全局变量来更改默认最大大小。但是,值得记住的是,解析非常大的响应会浪费一些 CPU 周期,尤其是使用正则表达式时,并且最好始终将检查重点放在较小的资源上。此外,在当前状态下,检查将找不到响应中空字符之后的任何字符串或 regex。同样,无法请求匹配空字符。
# 执行 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, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
comment <消息> 定义了如果规则评估失败时要报告的消息。 <数据> 是在通用健康检查会话期间将发送的字符串。 <格式> 是在通用健康检查会话期间(请参见第 8.2.6 节)评估后将发送的自定义日志格式。
# 查找 redis 主服务器 option tcp-check tcp-check send info\ replication\r\n tcp-check expect string role:master
指定一个十六进制数字字符串或十六进制数字自定义日志格式,作为原始 tcp 健康检查期间的二进制问题发送。可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
comment <消息> 定义了如果规则评估失败时要报告的消息。 <十六进制字符串> 是在通用健康检查会话期间,转换为二进制后将发送的十六进制字符串。 <十六进制格式> 是在通用健康检查会话期间(请参见第 8.2.6 节),评估并转换为二进制后将发送的十六进制自定义日志格式。
# 二进制 redis 检查 option tcp-check tcp-check send-binary 50494e470d0a # PING\r\n tcp-check expect binary 2b504F4e47 # +PONG
此操作设置变量的内容。变量是内联声明的。可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<变量名> 变量的名称。只能使用 "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, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
tcp-check unset-var(check.port)
根据第 4 层条件对传入连接执行一个动作。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是(!)![]() | 是![]() | 是![]() | 否![]() |
<action> 定义了如果条件适用要执行的操作。见下文。<condition> 是一个标准的仅第 4 层的基于 ACL 的条件(见第 7 节)。
在接受新的传入连接后,可以立即评估一些条件来决定是否必须接受或丢弃此连接,或者是否跟踪其计数器。这些条件不能使用任何数据内容,因为连接尚未读取,并且尚未分配缓冲区。这用于以非常低的开销选择性地快速接受或丢弃来自各种来源的连接。如果需要检查某些内容才能做出决定,则必须使用 "tcp-request content" 语句。"tcp-request connection" 规则按照其确切的声明顺序进行评估。如果没有规则匹配或没有规则,则默认操作是接受传入连接。可以插入的规则数量没有特定的限制。任何规则都可以选择后跟基于 ACL 的条件,在这种情况下,只有当条件评估为真时才会评估该规则。在执行操作之前评估条件,并且操作只执行一次。因此,如果操作更改了作为条件一部分检查的元素,则不会出现问题。这也意味着多个操作可以依赖同一条件,因此更改条件评估的第一个操作足以隐式禁用其余操作。例如,当尝试在变量为空时从各种来源向其分配值时,会使用此功能。语法中 "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 节。
根据第 4-7 层条件对新会话执行一个动作。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是(!)![]() | 是![]() | 是![]() | 是![]() |
<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 代理匹配第 7 层内容是完全可能的,因为 HTTP 特定的 ACL 匹配能够在提取所需数据之前初步解析缓冲区的内容。如果缓冲的内容无法解析为有效的 HTTP 消息,则 ACL 不匹配。此处涉及的解析器与所有其他 HTTP 处理的解析器完全相同,因此不存在以不同方式解析的风险。在 HTTP 前端或 HTTP 后端中,保证在首次评估规则时 HTTP 内容始终立即存在,因为 HTTP 解析是在连接处理的早期阶段(在会话级别)执行的。但是对于此类代理,使用 "http-request" 规则更自然且推荐。跟踪 layer7 信息也是可能的,前提是当处理规则时信息存在。规则处理引擎能够等待直到检查延迟到期,当要跟踪的数据尚不可用时。
tcp-request content use-service lua.deny if { src -f /etc/haproxy/blacklist.lst }
tcp-request content set-var(sess.my_var) src tcp-request content set-var-fmt(sess.from) %[src]:%[src_port] tcp-request content unset-var(sess.my_var2)
# 接受 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
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是(!)![]() | 是![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
使用 HAProxy 作为 TCP 中继的人们通常担心在没有任何分析的情况下将任何类型的协议传递给服务器的风险。为了能够分析请求内容,我们必须首先保留数据,然后分析它们。此语句只是启用保留数据,最长不超过指定时间。TCP 内容检查在连接到达前端时非常早地应用,然后在连接转发到后端时非常早地应用。这意味着如果前端和后端都有 tcp-request 规则,则连接可能会在前端经历第一次延迟,在后端经历第二次延迟。请注意,在执行内容检查时,HAProxy 将评估传入的每个新块的整个规则,同时考虑到这些数据是部分的。如果在上述延迟之前没有规则匹配,则会在到期时执行最后一次检查,此时认为内容是确定的。如果未设置延迟,HAProxy 将根本不等待,并根据可用信息立即应用裁决。显然,这不太可能非常有用,甚至可能存在竞争条件,因此不建议使用此类设置。请注意,如果发生连接错误或关闭,或者请求缓冲区看起来已满,则检查延迟会缩短。一旦规则匹配,请求就会释放并照常继续。如果达到超时且没有规则匹配,则默认策略是让它不受影响地通过。对于大多数协议,将其设置为几秒钟就足够了,因为大多数客户端在连接后会立即发送完整的请求。添加 3 秒或更多秒以涵盖 TCP 重传,仅此而已。对于某些协议,使用较大的值可能是有意义的,例如确保客户端在服务器之前从不说话(例如 SMTP),或等待客户端说话,然后再将数据传递给服务器(例如 SSL)。请注意,客户端超时必须至少覆盖检查延迟,否则它将首先过期。如果客户端关闭连接或缓冲区已满,则延迟会立即过期,因为内容将无法再更改。此指令仅在命名默认部分中可用,在匿名默认部分中不可用。代理从其默认部分继承此值。
根据第 5 层条件对已验证的会话执行一个动作。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是(!)![]() | 是![]() | 是![]() | 否![]() |
<动作> 定义了如果条件适用时要执行的动作。见下文。 <条件> 是一个标准的仅第 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 节。
根据第 4-7 层的条件对会话响应执行操作。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是(!)![]() | 否![]() | 是![]() | 是![]() |
<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
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是(!)![]() | 否![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
此指令仅在命名的 defaults 部分中可用,不能在匿名部分中使用。代理从其 defaults 部分继承此值。
设置额外的检查超时,但仅在连接已经建立之后。可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<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" 部分中一次性指定。这实际上是确保不会忘记它的最简单解决方案之一。
设置客户端侧的最大不活动时间。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<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
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
当客户端预期在其中一个方向已关闭时确认或发送数据时,非活动超时适用。此超时与 "timeout client" 不同,因为它仅适用于在一个方向上关闭的连接。这对于避免当客户端未干净断开连接时,连接长时间处于 FIN_WAIT 状态特别有用。这个问题在 RDP 或 WebSocket 等长连接上尤为常见。请注意,当连接在一个方向关闭时,此超时可以覆盖 "timeout tunnel"。一旦发送 GOAWAY 帧,它就会应用于空闲的 HTTP/2 连接,通常表示期望连接快速结束。此参数特定于前端,但可以在 "defaults" 部分中一次性指定。默认情况下未设置,因此半关闭连接将使用其他超时(timeout.client 或 timeout.tunnel)。
设置等待客户端 TLS 握手完成的最长时间。这可用于 TCP 和 QUIC 连接。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
如果未设置此握手超时,则将使用客户端超时来替代。
设置等待到服务器的连接尝试成功的最大时间。可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
如果服务器与 HAProxy 位于同一局域网内,连接应该是即时的(少于几毫秒)。无论如何,指定略高于 3 秒倍数的超时(例如 4 或 5 秒)以覆盖一个或多个 TCP 数据包丢失是一个好习惯。默认情况下,如果未指定队列和 tarpit 超时,连接超时也会将它们预设为相同的值。此参数特定于后端,但可以在 "defaults" 部分中为所有后端一次性指定。这实际上是避免忘记它的最简单解决方案之一。未指定的超时会导致无限超时,这是不推荐的。这种用法被接受并且可以工作,但在启动时会报告警告,因为如果系统超时也未配置,可能会导致系统中失败会话的累积。
设置等待新 HTTP 请求出现的最长允许时间。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
By default, the time to wait for a new request in case of keep-alive is set by "timeout http-request". However this is not always convenient because some people want very short keep-alive timeouts in order to release connections faster, and others prefer to have larger ones but still have short timeouts once the request has started to present itself. The "http-keep-alive" timeout covers these needs. It will define how long to wait for a new HTTP request to start coming after a response was sent. Once the first byte of request has been seen, the "http-request" timeout is used to wait for the complete request to come. Note that empty lines prior to a new request do not refresh the timeout and are not counted as a new request. There is also another difference between the two timeouts : when a connection expires during timeout http-keep-alive, no error is returned, the connection just closes. If the connection expires in "http-request" while waiting for a request to complete, an HTTP 408 error is returned to the client before closing the connection, unless "option http-ignore-probes" is set in the frontend. In general "timeout http-keep-alive" is best used to prevent clients from holding open an otherwise idle connection too long on sites seeing large amounts of short connections. This can be accomplished by setting the value to a few tens to hundreds of milliseconds in HTTP/1.1. This will close the connection after the client requests a page without having to hold that connection open to wait for more activity from the client. In that scenario, a new activity from the browser would result in a new handshake at the TCP and/or SSL layer. A common use case for this is HTTP sites serving only a redirect to the HTTPS page. Such connections are better not kept idle too long because they won't be reused, unless maybe to fetch a favicon. Another use case is the exact opposite: some sites want to permit clients to reuse idle connections for a long time (e.g. 30 seconds to one minute) but do not want to wait that long for the first request, in order to avoid a very inexpensive attack vector. In this case, the http-keep-alive timeout would be set to a large value, but http-request would remain low (a few seconds). When set to a very small value additional requests that are not pipelined are likely going to be handled over another connection unless the requests are truly pipelined, which is very rare with HTTP/1.1 (requests being sent back-to-back without waiting for a response). Most HTTP/1.1 implementations send a request, wait for a response and then send another request. A small value here for HTTP/1.1 may be advantageous to use less memory and sockets for sites with hundreds of thousands of clients, at the expense of an increase in handshake computation costs. Special care should be taken with small values when dealing with HTTP/2. The nature of HTTP/2 is to multiplex requests over a connection in order to save on the overhead of reconnecting the TCP and/or SSL layers. The protocol also uses control frames which cope poorly with early TCP connection closures, on very rare occasions this may result in truncated responses when data are destroyed in flight after leaving HAProxy (which then cannot even log an error). A suggested low starting value for HTTP/2 connections would be around 4 seconds. This would prevent most modern keep-alive implementations from needlessly holding open stale connections, and at the same time would allow subsequent requests to reuse the connection. However, this should be adjusted as needed and is simply a starting point. If this parameter is not set, the "http-request" timeout applies, and if both are not set, "timeout client" still applies at the lower level. It should be set in the frontend to take effect, unless the frontend is in TCP mode, in which case the HTTP backend's timeout will be used.
设置等待一个完整的 HTTP 请求的最长允许时间。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
为了提供DoS保护,可能需要降低接收完整 HTTP 请求的最大可接受时间,同时不影响客户端超时。这有助于防止在已建立连接上未发送任何内容的情况。客户端超时无法提供针对此滥用的良好保护,因为它是非活动超时,这意味着如果攻击者偶尔发送一个字符,超时将不会触发。使用 HTTP 请求超时,无论客户端输入速度如何,如果请求未及时完成,都将被中止。当超时过期时,会向客户端返回 HTTP 408 错误响应,告知其问题所在,并关闭连接。日志将报告终止代码 "cR"。一些最近的浏览器对这种标准、有详细文档记录的行为存在问题,因此可能需要使用 "option http-ignore-probes" 或 "errorfile 408 /dev/null" 来隐藏 408 代码。有关更多详细信息,请参阅 section 8.5 中关于 "cR" 终止代码的解释。默认情况下,此超时仅应用于请求的标头部分,而不应用于任何数据。一旦接收到空行,此超时将不再使用。当与 "option http-buffer-request" 结合使用时,此超时也适用于请求正文。如果未设置 "timeout http-keep-alive",则再次在 keep-alive 连接上使用此超时来等待第二个请求。通常将其设置为几秒钟就足够了,因为大多数客户端会在连接后立即发送完整请求。增加 3 秒或更多时间以覆盖 TCP 重传,但仅此而已。将其设置为非常低的值(例如 50 毫秒)通常在本地网络上有效,前提是没有丢包。这将防止人们使用 telnet 发送裸 HTTP 请求。如果未设置此参数,则客户端超时仍适用于传入请求的每个块之间。应在前端设置它才能生效,除非前端处于 TCP 模式,在这种情况下将使用 HTTP 后端的超时。
设置在队列中等待一个可用连接槽的最长时间。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
当服务器的 maxconn 达到时,连接会保留在队列中等待,该队列可能是服务器特定的,也可能是后端全局的。为了避免无限期等待,对队列中等待的请求应用超时。如果达到超时,则认为请求几乎永远不会被服务,因此将其丢弃并向客户端返回 503 错误。"timeout queue" 语句允许设置请求在队列中等待的最长时间。如果未指定,则使用与后端连接超时 ("timeout connect") 相同的值,以实现与没有 "timeout queue" 参数的旧版本的向后兼容性。
设置服务器侧的最大不活动时间。可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
非活动超时适用于预期服务器确认或发送数据的情况。在 HTTP 模式下,此超时在服务器响应的第一阶段尤其重要,即当它必须发送标头时,因为它直接表示服务器对请求的处理时间。要确定设置什么值,通常最好从被认为是不可接受的响应时间开始,然后检查日志以观察响应时间分布,并相应调整该值。默认情况下,该值以毫秒为单位指定,但如果数字后带有单位后缀,则可以采用任何其他单位,如本文档开头所述。在 TCP 模式下(以及在较小程度上,在 HTTP 模式下),强烈建议客户端超时与服务器超时保持相等,以避免调试复杂情况。无论预期的服务器响应时间如何,一个好的做法是至少覆盖一次或多次 TCP 丢包,方法是指定略高于 3 秒倍数的超时时间(例如,至少 4 或 5 秒)。如果一些长期流与短期流混合在一起(例如 WebSocket 和 HTTP),则值得考虑 "timeout tunnel",它会覆盖 "timeout client" 和 "timeout server" 用于隧道。此参数特定于后端,但可以在 "defaults" 部分中一次性指定。这实际上是确保不会忘记它的最简单解决方案之一。未指定的超时会导致无限超时,这是不推荐的。这种用法被接受并且有效,但在启动期间会报告警告,因为如果系统超时也未配置,可能会导致系统中积累过期的会话。
为半关闭连接设置服务器侧的不活动超时。可在以下上下文中使用:tcp, http, log
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
非活动超时适用于预期服务器确认或发送数据而其中一个方向已关闭的情况。此超时与 "timeout server" 的不同之处在于,它仅适用于在一个方向上关闭的连接。这对于避免当远程服务器未干净断开连接时,连接长时间处于 FIN_WAIT 状态特别有用。这个问题在 RDP 或 WebSocket 等长连接中特别常见。请注意,当连接在一个方向关闭时,此超时可以覆盖 "timeout tunnel"。提供此设置是为了完整性,但在大多数情况下,不需要它。此参数特定于后端,但可以在 "defaults" 部分中一次性指定。默认情况下未设置,因此半关闭连接将使用其他超时(timeout.server 或 timeout.tunnel)。
设置被置于 tarpit 状态的连接将维持的时长。可在以下上下文中使用:http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<timeout> 是 tarpit 的持续时间,默认以毫秒为单位指定,但如果数字后跟单位后缀,也可以是任何其他单位,如本文档开头所述。
当使用 "http-request tarpit" 将一个连接置于 tarpit 状态时,它会在没有任何活动的情况下保持打开一段时间,然后关闭。“timeout tarpit”定义了它将保持打开的时间长度。默认情况下,该值以毫秒为单位指定,但如果数字后跟有单位后缀,则可以是任何其他单位,如本文档开头所述。如果未指定,将使用与后端连接超时(“timeout connect”)相同的值,以向后兼容没有“timeout tarpit”参数的旧版本。
为隧道设置客户端和服务器侧的最大不活动时间。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
隧道超时适用于客户端和服务器之间建立双向连接,并且连接在两个方向都保持非活动状态的情况。一旦连接成为隧道,此超时将取代客户端和服务器超时。在 TCP 中,一旦没有分析器附加到任一连接(例如,tcp content rules 被接受),就会使用此超时。在 HTTP 中,当连接升级时(例如,切换到 WebSocket 协议,或将 CONNECT 请求转发到代理),或者在第一次响应后未指定 keepalive/close 选项时,会使用此超时。由于此超时通常与长期连接结合使用,因此最好也设置 "timeout client-fin" 来处理客户端突然从网络中消失且未确认关闭,或发送关闭且不再确认待处理数据的情况。这可能发生在存在防火墙的有损网络中,并通过存在大量处于 FIN_WAIT 状态的会话来检测。默认情况下,该值以毫秒为单位指定,但如果数字后带有单位后缀,则可以采用任何其他单位,如本文档开头所述。无论预期的正常空闲时间如何,一个好的做法是至少覆盖一次或多次 TCP 丢包,方法是指定略高于 3 秒倍数的超时时间(例如,至少 4 或 5 秒)。此参数特定于后端,但可以在 "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 的超时
启用客户端透明代理 可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
引入此关键字是为了向第 3 层负载均衡器提供第 7 层持久性。其思想是利用操作系统的能力将远程地址的传入连接重定向到本地进程(此处为 HAProxy),并让该进程知道最初请求的地址。使用此选项时,没有 cookie 的会话将被转发到传入请求的原始目标 IP 地址(该地址应与另一设备的地址匹配),而带有 cookie 的请求仍将被转发到适当的服务器。" transparent" 关键字已弃用,请改用 "option transparent"。请注意,与普遍看法相反,此选项在建立连接时并不会使 HAProxy 向服务器呈现客户端的 IP。
为每个请求生成一个唯一 ID。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<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
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<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"
如果/除非满足基于 ACL 的条件,则切换到特定的后端。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 否![]() |
<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> 是一个 Custom log format,则在配置时可能不会进行检查,因此后端名称在运行时动态解析。如果生成的后端名称与任何有效的后端不对应,则不会评估其他规则,而是应用 default_backend 指令。请注意,当使用动态后端名称时,强烈建议使用其他后端未使用的前缀,以确保不能从请求中强制使用未经授权的后端。值得一提的是,具有显式名称的 "use_backend" 规则用于检测前端和后端之间的关联,以计算后端的 "fullconn" 设置。动态名称无法做到这一点。
定义用于后端的 FastCGI 应用程序。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<name> 是要使用的 FastCGI 应用程序的名称。
有关 FastCGI 应用程序设置的详细信息,请参见第 10.1 节。
仅在/除非满足基于 ACL 的条件时才使用特定服务器。可在以下上下文中使用:tcp, http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
默认情况下,到达后端的连接会根据配置的算法在可用服务器之间进行负载均衡,除非在请求中使用了持久性机制(例如 cookie)并找到了它。有时需要将特定请求转发到特定服务器,而无需为该服务器声明专用的后端。这可以通过使用 "use-server" 规则来实现。这些规则在评估 "redirect" 规则之后和评估 cookie 之前进行评估,并且它们优先于 cookie。可以有任意数量的 "use-server" 规则。所有这些规则都按照声明顺序进行评估,第一个匹配的规则将分配服务器。如果规则指定的服务器已关闭,并且未使用 "option persist" 且未验证 force-persist 规则,则忽略该规则,评估继续进行下一个规则,直到匹配为止。在第一种形式中,如果条件匹配,则使用服务器。在第二种形式中,如果条件不匹配,则使用服务器。如果没有条件有效,则继续处理,并根据其他持久性机制分配服务器。请注意,即使规则匹配,cookie 处理仍会执行,但不会分配服务器。这允许剥离带前缀的 cookie 的前缀。"use-server" 语句在 HTTP 和 TCP 模式下都有效。这使得它适用于基于内容的检查。例如,在使用隐式 TLS 的协议时,可以根据 TLS SNI 字段在服务器场中选择服务器(另请参阅 "req.ssl_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 规则,而是回退到负载均衡。
在请求或响应处理的各个阶段会评估多个规则集,对于这些规则集中的每个规则,如果可选条件匹配,则可以执行操作。默认提供了大量操作,它们可以修改内容、接受/阻止处理、更改内部状态等。并且可以在 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" 规则有效 下面的参考 section 4.4 中使用了相同的缩写。
本节使用与上述第 4.3 节中描述的相同的规则集术语标记,提供了每个操作及其用法的详细描述。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() | ![]() |
此操作停止规则的评估,并让请求或响应通过检查。此操作是最终的,即对于当前部分,不会评估同一规则集中的任何后续规则。此操作与“allow”操作没有区别,只是为了历史兼容性,“accept”用于 TCP 和 QUIC 规则,而“allow”用于 HTTP 规则。另请参见下面的“allow”操作。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() |
这用于向 ACL 中添加一个新条目。ACL 必须从文件中加载(即使是虚拟的空文件)。要更新的 ACL 的文件名在括号中传递。它接受一个参数:<key fmt>,该参数遵循第 8.2.6 节中描述的自定义日志格式规则,以收集新条目的内容。它在插入前会先在 ACL 中进行查找,以避免重复(或更多)的值。它等同于 stats 套接字中的 "add acl" 命令,但可以由 HTTP 请求触发。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() |
此操作附加一个 HTTP 标头字段,其名称由 <name> 指定,其值由 <fmt> 定义,<fmt> 遵循自定义日志格式规则(参见第 8.2.6 节中的自定义日志格式)。这对于向服务器传递特定于连接的信息(例如客户端的 SSL 证书)或将多个标头合并为一个特别有用。此规则不是最终的,因此可以添加其他类似的规则。请注意,标头添加是立即执行的,因此一个规则可能会重用前一个规则产生的结果标头。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() |
此操作停止规则的评估,并让请求通过检查。此操作是最终的,即对于当前部分,不会评估同一规则集中的任何后续规则。此操作与“accept”操作没有区别,只是为了历史兼容性,“accept”用于 TCP 规则,而“allow”用于 HTTP 规则。另请参见上面的“accept”操作。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() |
这用于在成功建立 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。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() |
这会停止规则评估并立即以 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 Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() |
在缓存中存储一个 http-response。响应头的存储在此步骤完成,这意味着您可以使用其他 http-response 操作在存储响应之前或之后修改头。此操作负责设置缓存存储过滤器。有关缓存设置,请参见第 6.2 节。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() |
尝试从缓存 <name> 中提供一个缓存对象。此指令对于存储缓存也是必需的,因为它计算缓存哈希值。如果您想对存储和提供都使用一个条件,最好将其放在此指令之后。有关缓存设置,请参见第 6.2 节。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() |
这会从请求或响应缓冲区捕获示例表达式 <sample>,并将其转换为最多 <len> 个字符的字符串。结果字符串存储在下一个 "capture" 插槽中(请求或响应),因此它可能会出现在某些捕获的 HTTP 标头旁边。然后它将自动出现在日志中,并且可以使用示例获取方法提取它以将其馈送到标头或任何内容中。应该限制长度,因为在整个流生命周期内将为每次捕获分配此大小。请注意,长度仅适用于 "http-request" 规则。请查看 section 7.3(获取样本)、"capture request header" 和 "capture response header" 以获取更多信息。如果使用关键字 "id" 代替 "len",则该操作会尝试将捕获的字符串存储在先前声明的捕获插槽中。这对于在后端运行捕获非常有用。插槽 id 可以通过先前的指令 "http-request capture" 或使用 "declare capture" 关键字声明。在后端使用此操作时,请仔细检查相关前端是否具有所需的捕获插槽,否则此规则将在运行时被忽略。由于 HAProxy 能够在运行时动态解析后端名称,因此在配置解析时无法检测到这一点。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() |
此操作用于立即关闭与服务器的连接。后续的“tcp-response content”规则将不再被评估。此操作的主要目的是,在应用程序协议期望先经过一段较长的超时时间的情况下,强制结束客户端与服务器之间的交换后的连接。其目标是消除那些在某些协议下会占用大量服务器资源的空闲连接。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() |
此操作用于从 ACL 中删除一个条目。该 ACL 必须是从文件中加载的(即使是一个虚拟的空文件)。要更新的 ACL 的文件名在括号中传递。它接受一个参数:<key fmt>,该参数遵循第 8.2.6 节中的自定义日志格式规则,用于收集要删除条目的内容。它等效于 stats socket 中的 "del acl" 命令,但可以由 HTTP 请求或响应触发。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() |
此操作移除所有名称在 <name> 中指定的 HTTP 标头字段。<meth> 是应用于标头名称的匹配方法。支持的匹配方法有“str”(精确匹配)、“beg”(前缀匹配)、“end”(后缀匹配)、“sub”(子串匹配)和“reg”(正则表达式匹配)。如果未指定,则使用精确匹配方法。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() |
此操作用于从 MAP 中删除一个条目。<map-name> 必须遵循 2.7 节中关于 maps 和 ACLs 名称格式的描述。要更新的 MAP 名称在括号中传递。它接受一个参数:<key fmt>,该参数遵循第 8.2.6 节中的自定义日志格式规则,用于收集要删除条目的内容。它等效于 stats socket 中的 "del map" 命令,但可以由 HTTP 请求或响应触发。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() |
此操作停止规则评估并立即拒绝请求或响应。默认情况下,对请求返回 HTTP 403 错误,对响应返回 502 错误,但返回的响应可以使用与“return”操作相同的语法进行自定义。因此,详情请参见下文的“return”。为了兼容性,当没有定义参数,或仅定义了 "deny_status" 时,会隐含 "default-errorfiles" 参数。这意味着 "deny [deny_status <status>]" 是 "deny [status <status>] default-errorfiles" 的别名。此操作是最终的,即同一规则集中的后续规则将不会对当前部分进行评估。另请参阅“return”操作以了解高级语法。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() |
此操作会静默忽略收到的 QUIC 初始数据包,否则该数据包将导致新的 QUIC 连接实例化并执行其 SSL 握手。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() |
此操作会禁止任何因连接失败以外的原因而重试请求的尝试。例如,这对于确保 POST 请求在失败时不会被重试非常有用。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
此操作手动触发代理上的日志发送。这意味着代理上的日志选项将被考虑(包括诸如“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
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() |
此操作对的输出执行 DNS 解析,并将结果存储在变量 中。它使用由 指向的 DNS 解析器部分。可以通过可选参数 'ipv4' 或 'ipv6' 选择解析首选项。执行 DNS 解析时,客户端连接会暂停,等待解析结束。如果找到 IP 地址,则将其存储在 中。如果发生任何错误,则 不会被设置。可以使用此操作来发现服务器 IP 地址并在运行时基于请求中的信息(例如 Host 标头)进行操作。如果此操作用于查找服务器 IP 地址(使用 "set-dst" 操作),则后端中的服务器 IP 地址必须设置为 0.0.0.0。do-resolve 操作接受一个仅主机参数,必须从字符串中删除任何端口。
resolvers mydns nameserver local 127.0.0.53:53 nameserver google 8.8.8.8:53 timeout retry 1s hold valid 10s hold nx 3s hold other 3s hold obsolete 0s accepted_payload_size 8192 frontend fe bind 10.42.0.1:80 http-request do-resolve(txn.myip,mydns,ipv4) hdr(Host),host_only http-request capture var(txn.myip) len 40 # return 503 when the variable is not set, # which mean DNS resolution error use_backend b_503 unless { var(txn.myip) -m found } default_backend be backend b_503 # dummy backend used to return 503. # one can use the errorfile directive to send a nice # 503 error page to end users backend be # rule to prevent HAProxy from reconnecting to services # on the local network (forged DNS name used to scan the network) http-request deny if { var(txn.myip) -m ip 127.0.0.0/8 10.0.0.0/8 } http-request set-dst var(txn.myip) server clear 0.0.0.0:0
注意:不要忘记设置“保护”规则,以确保 HAProxy 不会被用于扫描网络,或更糟糕的是,不会循环访问自身……
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() |
此操作用于在任何其他响应之前构建一个 HTTP 103 Early Hints 响应。它会向此响应中追加一个 HTTP 标头字段,其名称由 <name> 指定,其值由 <fmt> 定义,该 <fmt> 遵循自定义日志格式规则(参见第 8.2.6 节中的自定义日志格式)。这对于向客户端传递一些 Link 标头以预加载渲染 HTML 文档所需的资源特别有用。更多信息请参阅 RFC 8297。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() |
这将配置面向客户端的连接,以在从套接字读取任何字节之前接收 NetScaler 客户端 IP 插入协议头。这相当于在 "bind" 行上使用 "accept-netscaler-cip" 关键字,不同之处在于使用 TCP 规则允许仅对某些 IP 地址范围使用 ACL 接受 PROXY 协议。当来自公共主机的流量通过多层负载均衡器时,这很方便。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() |
这将配置面向客户端的连接,以在从套接字读取任何字节之前接收 PROXY 协议头。这相当于在 "bind" 行上使用 "accept-proxy" 关键字,不同之处在于使用 TCP 规则允许仅对某些 IP 地址范围使用 ACL 接受 PROXY 协议。当来自公共主机的流量通过多层负载均衡器时,这很方便。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() |
执行请求 URI 的规范化。HAProxy 2.4 中的 URI 规范化目前作为实验性技术预览提供。因此,它首先需要全局指令 'expose-experimental-directives' 才能调用它。您应该做好准备,规范化器的行为可能会更改以修复可能的问题,这可能会破坏您基础设施中正确的请求处理。每个规范化器处理一种类型的规范化,以允许对支持的后端选择适当的规范化级别进行细粒度控制。例如,"path-strip-dotdot" 规范化器可能对将请求 URI 直接映射到本地文件系统内路径的静态文件服务器有用。但是,它可能会破坏需要特定数量路径段的 API 路由。重要的是要注意,某些规范化器可能会对损坏的 URI 导致不安全的转换。也可能发生的是,单独安全的规范化器组合在一起时,如果组合不当,会导致不安全的转换。例如,当损坏的 URI 包含裸百分号字符时,"percent-decode-unreserved" 规范化器可能会导致意外结果。例如,一个损坏的 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
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() |
这会根据重定向规则执行 HTTP 重定向。这与 "redirect" 语句完全相同,不同之处在于它插入了一个重定向规则,该规则在其他 "http-request" 或 "http-response" 规则中间处理,并且这些规则使用 Custom log format。对于响应,只允许 "location" 类型的重定向。此外,当在响应期间执行重定向时,从服务器到 HAProxy 的传输会中断,以便不会将有效负载转发给客户端。这可能会导致 HTTP/1 上的某些连接关闭。此操作是最终操作,即不会对当前部分评估同一规则集中的其他规则。有关规则语法,请参阅 "redirect" 关键字。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
这会停止规则评估并立即关闭连接,而无需发送任何响应。对于 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 错误代码通知客户端。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() |
此操作将标头字段 <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。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() |
此操作的工作方式类似于“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/ }
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() |
此操作与 "http-request replace-path" 相同,不同之处在于路径包含了查询字符串(如果存在)。因此,路径和查询字符串都会被替换。
# 在路径后添加后缀 /foo:将 /bar?q=1 变为 /bar/foo?q=1: http-request replace-pathq ([^?]*)(\?(.*))? \1/foo\2
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() |
这类似于 "replace-header",不同之处在于它作用于请求的 URI 部分而不是标头。URI 部分可能包含可选的方案、权威机构或查询字符串。这些被视为与匹配的值的一部分。值得注意的是,正则表达式的评估成本可能高于某些 ACL,因此罕见的替换可能会受益于条件,以避免在不匹配时根本不执行评估。重要说明:历史上在 HTTP/1.x 中,绝大多数浏览器发送的请求使用“origin form”,这与“absolute form”不同,因为它们在 URI 部分不包含方案或权威机构。大多数只有发送给代理的请求、手动伪造的请求以及某些应用程序发出的请求使用绝对形式。因此,"replace-uri" 在 HTTP/1.x 中通常适用于以 "/" 开头的规则。但是对于 HTTP/2,鼓励客户端仅发送绝对 URI,这些 URI 看起来像 HTTP/1 客户端用于与代理通信的 URI。因此,此类部分 replace-uri 规则在 HTTP/2 中可能会失败,而在 HTTP/1 中有效。要么需要调整规则以可选地匹配方案和权威机构,要么应该使用 replace-path。
# 将所有 "http" 绝对请求重写为 "https": http-request replace-uri ^http://(.*) https://\1 # 添加前缀 /foo:将 /bar?q=1 变为 /foo/bar?q=1: http-request replace-uri ([^/:]*://[^/]*)?(.*) \1/foo\2
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() |
此操作的工作方式类似于“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
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() |
这会停止规则评估并立即返回响应。用于响应的默认状态码为 200。它可以作为 "status" 的参数可选指定。响应 content-type 也可以作为 "content-type" 的参数指定。最后,可以定义响应本身。它可以是指定要使用的 errorfile 的完整 HTTP 响应,也可以是指定要使用的文件或字符串的响应有效负载。遵循这些规则来创建响应:* 如果既没有定义 errorfile 也没有定义要使用的有效负载,则返回一个虚拟响应。仅考虑 "status" 参数。它可以是范围 [200, 599] 中的任何代码。如果存在 "content-type" 参数,则忽略它。* 如果设置了 "default-errorfiles" 参数,则考虑代理的 errorfiles。如果定义了 "status" 参数,它必须是 HAProxy 处理的状态码之一(200、400、403、404、405、408、410、413、414、425、429、431、500、501、502、503 和 504)。如果存在 "content-type" 参数,则忽略它。* 如果使用 "errorfile" 参数定义了特定的 errorfile,则返回包含完整 HTTP 响应的相应文件。仅考虑 "status" 参数。它必须是 HAProxy 处理的状态码之一(200、400、403、404、405、408、410、413、414、425、429、431、500、501、502、503 和 504)。如果存在 "content-type" 参数,则忽略它。* 如果定义了 http-errors 部分,并带有 "errorfiles" 参数,则返回指定 http-errors 部分中的相应文件,其中包含完整的 HTTP 响应。仅考虑 "status" 参数。它必须是 HAProxy 处理的状态码之一(200、400、403、404、405、408、410、413、414、425、429、431、500、501、502、503 和 504)。如果存在 "content-type" 参数,则忽略它。* 如果指定了 "file" 或 "lf-file" 参数,则使用文件内容作为响应有效负载。如果文件不为空,则其 content-type 必须设置为 "content-type" 的参数。否则,任何 "content-type" 参数都会被忽略。使用 "lf-file" 参数,文件内容被评估为 Custom log format(参见 section 8.2.6)。使用 "file" 参数,它被视为原始内容。* 如果指定了 "string" 或 "lf-string" 参数,则使用定义的字符串作为响应有效负载。content-type 必须始终设置为 "content-type" 的参数。使用 "lf-string" 参数,字符串被评估为 Custom log format(参见 section 8.2.6)。使用 "string" 参数,它被视为原始字符串。当响应不基于 errorfile 时,可以使用 "hdr" 参数将 HTTP 标头字段附加到响应中。否则,所有 "hdr" 参数都会被忽略。对于每个参数,标头名称在 <name> 中指定,其值由遵循 section 8.2.6 中描述的 Custom log format 规则的 <fmt> 定义。请注意,生成的响应必须小于缓冲区。为了避免任何警告,当加载 errorfile 或原始文件时,为标头重写保留的缓冲区空间也应该空闲。此操作是最终操作,即不会对当前部分评估同一规则集中的其他规则。
http-request return errorfile /etc/haproxy/errorfiles/200.http \ if { path /ping } http-request return content-type image/x-icon file /var/www/favicon.ico \ if { path /favicon.ico } http-request return status 403 content-type text/plain \ lf-string "Access denied. IP %[src] is blacklisted." \ if { src -f /etc/haproxy/blacklist.lst }
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
此操作将与由 <sc-id> 指定的 sticky counter 关联的数组中索引 <idx> 处的 General Purpose Counter 增加 <int> 整数值或表达式 <expr> 的整数评估值。整数和表达式限制为无符号 32 位值。如果发生错误,此操作会静默失败,并且操作评估继续进行。<idx> 是 0 到 99 之间的整数,<sc-id> 是 0 到 2 之间的整数。如果此索引处没有存储 GPC,它也会静默失败。即使值为零,表中的条目也会刷新。'gpc_rate' 会自动调整以反映 gpc 值的平均增长率。此操作仅适用于 'gpc' 和 'gpc_rate' array data_types(而不适用于旧版 'gpc0'、'gpc1'、'gpc0_rate' 也不适用于 'gpc1_rate' data_types)。旧版数据类型没有等效函数,但如果值始终为 1,请参阅 'sc-inc-gpc()'、'sc-inc-gpc0()' 和 'sc-inc-gpc1()'。也无法减少值,但可以使用 'sc-set-gpt()' 将精确值存储在 General Purpose Tag 中。此操作的主要用途是计算分数或总卷(例如,服务器或 WAF 报告的每个源 IP 的估计危险、上传的总字节数等)。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
此操作将与由 <sc-id> 指定的粘性计数器关联的数组中,索引为 <idx> 的通用目的计数器(GPC)递增 1。如果发生错误,此操作将静默失败,并且操作评估继续。<idx> 是 0 到 99 之间的整数,<sc-id> 是 0 到 2 之间的整数。如果在此索引处没有存储 GPC,它也会静默失败。此操作仅适用于 'gpc' 和 'gpc_rate' 数组数据类型(不适用于旧的 'gpc0'、'gpc1'、'gpc0_rate' 或 'gpc1_rate' 数据类型)。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
此操作根据由 <sc-id> 指定的粘性计数器来递增 GPC0 或 GPC1 计数器。如果发生错误,此操作将静默失败,并且操作评估继续。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
此操作将与由 <sc-id> 指定的粘性计数器关联的数组中,索引为 <idx> 的 32 位无符号 GPT 设置为 <int>/<expr> 的值。预期结果是一个布尔值。如果发生错误,此操作将静默失败,并且操作评估继续。<idx> 是 0 到 99 之间的整数,<sc-id> 是 0 到 2 之间的整数。如果在此索引处没有存储 GPT,它也会静默失败。此操作仅适用于 'gpt' 数组数据类型(不适用于旧的 'gpt0' 数据类型)。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
此操作根据由 <sc-id> 指定的粘性计数器和 <int>/<expr> 的值来设置 32 位无符号 GPT0 标签。预期结果是一个布尔值。如果发生错误,此操作将静默失败,并且操作评估继续。此操作是 "sc-set-gpt(0,<sc-id>)" 的别名。另请参阅“sc-set-gpt”操作。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() |
此操作强制发送一个 Retry 数据包以响应没有 token 的客户端 Initial 数据包。这对于在实例化任何连接元素和开始握手之前确保客户端地址得到验证非常有用。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() |
此操作用于触发发送一组 SPOE 消息。为此,必须定义用于发送消息的 SPOE 引擎,以及要发送的 SPOE 组。当然,SPOE 引擎必须引用一个现有的 SPOE 过滤器。如果在 SPOE 过滤器行上未提供引擎名称,则必须使用 SPOE 代理名称。
<engine-name> SPOE 引擎名称。 <group-name> 在引擎配置中指定的 SPOE 组名称。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() |
此操作用于启用带宽限制过滤器 <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 节。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() |
在支持此功能的平台上,此操作用于将后端连接(所有发送到服务器的数据包)上的 Netfilter/IPFW MARK 设置为 <mark> 或 <expr> 中传递的值。该值为一个无符号 32 位值,可以被 netfilter/ipfw 和路由表匹配,或通过 DTrace 监控数据包。<mark> 可以用十进制或十六进制格式(以 "0x" 为前缀)表示。或者,可以使用 <expr>:它是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成,必须解析为整数类型。此操作可用于强制某些数据包采用不同的路由(例如,对于大批量下载使用更便宜的网络路径)。此功能在 Linux 内核 2.6.32 及以上版本以及 FreeBSD 和 OpenBSD 上可用,并需要管理员权限。该标记将在整个后端/服务器连接期间(从连接到关闭)设置。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() |
在支持此功能的平台上,此操作用于将后端连接(所有发送到服务器的数据包)上的 TOS 或 DSCP 字段值设置为 <tos> 或 <expr> 中传递的值。该值表示 IP TOS 字段的整个 8 位。请注意,在 DSCP 或 TOS 中只使用较高的 6 位,较低的 2 位始终为 0。或者,可以使用 <expr>:它是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成,必须解析为整数类型。此操作可用于根据请求中的某些信息调整内部路由器的某些路由行为。tos 将在整个后端/服务器连接期间(从连接到关闭)设置。有关更多信息,请参阅 RFC 2474、2597、3260 和 4594。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() |
此操作用于将目标 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 Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() |
此操作用于将目标端口地址设置为指定表达式的值。如果要连接到新的地址/端口,请在后端中使用 '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"。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
在支持此功能的平台上,此操作用于将所有发送到客户端的数据包上的 Netfilter/IPFW MARK 设置为 <mark> 或 <expr> 中传递的值。该值为一个无符号 32 位值,可以被 netfilter/ipfw 和路由表匹配,或通过 DTrace 监控数据包。<mark> 可以用十进制或十六进制格式(以 "0x" 为前缀)表示。或者,可以使用 <expr>:它是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成,必须解析为整数类型。此操作可用于强制某些数据包采用不同的路由(例如,对于大批量下载使用更便宜的网络路径)。此功能在 Linux 内核 2.6.32 及以上版本以及 FreeBSD 和 OpenBSD 上可用,并需要管理员权限。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
在支持此功能的平台上,此操作用于将发送到客户端的数据包的 TOS 或 DSCP 字段值设置为 <tos> 或 <expr> 中传递的值。该值表示 IP TOS 字段的整个 8 位。请注意,在 DSCP 或 TOS 中只使用较高的 6 位,较低的 2 位始终为 0。或者,可以使用 <expr>:它是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成,必须解析为整数类型。此操作可用于根据请求中的某些信息调整边界路由器的某些路由行为。有关更多信息,请参阅 RFC 2474、2597、3260 和 4594。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() |
此操作与“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 Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() | ![]() |
此操作用于在满足特定条件时更改当前请求的日志级别。有效级别是 8 个 syslog 级别(参见“log”关键字)以及特殊级别“silent”,它会禁用此请求的日志记录。此规则不是最终的,因此最后一个匹配的规则生效。此规则可用于禁用来自其他设备的健康检查。可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() |
此操作用于向 map 中添加一个新条目。<map-name> 必须遵循 2.7 节中关于 maps 和 ACLs 名称格式的描述。要更新的 MAP 名称在括号中传递。它接受 2 个参数:<key fmt>,遵循第 8.2.6 节中描述的自定义日志格式规则,用于收集 map 键;以及 <value fmt>,遵循自定义日志格式规则,用于收集新条目的内容。它在插入前会先在 map 中进行查找,以避免重复(或更多)的值。它等效于 stats socket 中的 "set map" 命令,但可以由 HTTP 请求触发。
这是“set-fc-mark”的别名(应改用后者)。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() |
此操作使用格式化字符串 <fmt> 的求值结果来重写请求方法。这样做应该有极少数的正当理由,因为它更有可能破坏某些东西而不是修复它。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() |
此操作设置当前正在处理的请求/响应的 "nice" 因子。它仅对同时处理的其他请求产生影响。默认值为 0,除非通过 "bind" 行上的 "nice" 设置进行更改。接受的范围是 -1024..1024。值越高,请求就越“nice”。较低的值将使请求比其他请求更重要。这对于提高某些请求的速度或降低不重要请求的优先级很有用。未经事先试验而使用此设置可能会导致严重减速。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() |
此操作使用格式化字符串 <fmt> 的求值结果来重写请求路径。查询字符串(如果有)保持不变。如果在路径之前找到了 scheme 和 authority,它们也保持不变。如果请求没有路径("*"),则该路径将被格式替换。例如,这可以用于在路径前添加一个目录组件。另请参阅 "http-request set-query" 和 "http-request set-uri"。
# 在路径前添加主机名 http-request set-path /%[hdr(host)]%[path]
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() |
此操作与 "http-request set-path" 相同,不同之处在于查询字符串也被重写。它可用于移除查询字符串,包括问号(使用 "http-request set-query" 是不可能的)。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() |
此操作用于设置当前请求的队列优先级类别。该值必须是一个样本表达式,其转换结果为 -2047 到 2047 范围内的整数。超出此范围的结果将被截断。优先级类别决定了排队请求的处理顺序。值越低,优先级越高。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() |
此操作用于设置当前请求的队列优先级时间戳偏移量。该值必须是一个样本表达式,其转换结果为 -524287 到 524287 范围内的整数。超出此范围的结果将被截断。当一个请求进入队列时,它首先按优先级类别排序,然后按当前时间戳加上给定的偏移量(以毫秒为单位)进行排序。值越低,优先级越高。请注意,结果时间戳的跟踪精度仅足以表示 524,287 毫秒(8 分 44 秒 287 毫秒)。如果请求排队时间足够长,以至于调整后的时间戳超过此值,它将被错误地识别为最高优先级。因此,将“timeout queue”设置为一个值,使其与偏移量相加后不超过此限制,这一点很重要。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() |
此操作使用格式化字符串 <fmt> 的求值结果来重写请求中出现在第一个问号("?")之后的查询字符串。问号之前的部分保持不变。如果请求不包含问号且新值不为空,则会在 URI 的末尾添加一个问号,后跟新值。如果问号已存在,即使新值为空,它也永远不会被移除。这可以用于从查询字符串中添加或删除参数。另请参阅 "http-request set-path" 和 "http-request set-uri"。
# 在查询字符串中将“%3D”替换为“=” http-request set-query %[query,regsub(%3D,=,g)]
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() |
此操作仅对当前流覆盖指定的“retries”值。它可以是一个整数值,范围在 [0, 100] 之间,也可以是一个表达式,其必须返回一个在 [0, 100] 范围内的整数。请注意,此操作仅在后端侧相关,因此该规则仅适用于具有后端能力的代理。它也不允许在 "defaults" 部分中使用。
tcp-request content set-retries 3 http-request set-retries var(txn.retries)
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() |
此操作用于将源 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 Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() |
此操作用于将源端口地址设置为指定表达式的值。
<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"。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() |
此操作将响应状态码替换为 <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".
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() |
此操作仅对当前流覆盖指定的 "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-fc-tos”的别名(应改用后者)。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() |
此操作使用格式化字符串 <fmt> 的求值结果来重写请求 URI。scheme、authority、path 和查询字符串都会被一次性替换。这可以用于在代理前重写主机,或对 URI 进行复杂的修改,例如在路径和查询字符串之间移动部分。如果设置了绝对 URI,它将按原样发送到 HTTP/1.1 服务器。如果这不是期望的行为,则应分别设置主机、路径和/或查询字符串。另请参阅 "http-request set-path" 和 "http-request set-query"。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
此操作用于设置变量的内容。变量是内联声明的。
<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]
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
这会停止规则评估,并使用一种系统相关的方式使面向客户端的连接突然消失,该方式试图防止客户端被通知。当不带 rst-ttl 参数调用时,我们尝试使用 TCP_REPAIR 防止向客户端发送任何 FIN 或 RST 数据包。如果失败(主要是因为缺少权限),我们会回退到发送一个 TTL 为 1 的 RST 数据包。效果是客户端仍然看到已建立的连接,而 HAProxy 上没有连接,从而节省了资源。然而,放置在 HAProxy 和客户端之间的有状态设备(防火墙、代理、负载均衡器)也会在它们的会话表中保留已建立的连接。可选的 rst-ttl 会改变这种行为:不使用 TCP_REPAIR,而是发送一个可配置 TTL 的 RST 数据包。当设置为合理的值时,RST 数据包会穿过本地基础设施,删除防火墙和其他系统中的连接,但在到达客户端之前消失。来自客户端的未来数据包将被前端设备丢弃。这些本地 RST 可保护本地资源,但不保护客户端资源。除非完全理解这样做的后果,否则不得使用此功能。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() |
此操作为后续规则启用或禁用严格重写模式。它不影响在其之前声明的规则,并且仅适用于对请求执行重写的规则。当启用严格模式时,任何重写失败都会触发内部错误。否则,此类错误将被静默忽略。严格重写模式的目的是使某些重写是可选的,而其他重写必须执行才能继续请求处理。默认情况下,严格重写模式是启用的。当规则集评估结束时,其值也会被重置。因此,例如,如果您在前端更改模式,当 HAProxy 开始后端规则评估时,默认模式将被恢复。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() |
此操作用于执行连接升级。目前仅支持 HTTP 升级。协议可以可选地指定。此操作仅适用于具有前端能力的代理。连接升级会立即执行,后续的“tcp-request content”规则不会被评估。应优先使用此升级方法,而不是依赖后端模式的隐式方法。使用此方法时,可以在前端设置 HTTP 指令而不会有任何警告。如果执行了 HTTP 升级,这些指令将被有条件地评估。但是,仍然必须选择一个 HTTP 后端。将 HTTP 连接(无论是否升级)路由到 TCP 服务器仍然不受支持。有关 HTTP 升级的更多详细信息,请参见第 4 节关于代理的部分。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() |
这会停止规则评估并立即阻止请求,阻止时间由 "timeout tarpit" 指定的延迟或如果未设置前者则由 "timeout connect" 指定。在此延迟之后,如果客户端仍处于连接状态,则返回响应,以便客户端不会怀疑它已被困住。日志将报告标志 "PT"。tarpit 规则的目标是在攻击期间减慢机器人的速度,此时它们受限于并发请求的数量。它对非常愚蠢的机器人非常有效,并且与 "deny" 规则相比,可以显着减少防火墙上的负载。但是,当面对“正确”开发的机器人时,它可能会通过强迫 HAProxy 和前端防火墙支持大量并发连接而使情况变得更糟。默认情况下,返回 HTTP 错误 500。但可以使用与 "http-request return" 规则相同的语法自定义响应。因此,有关详细信息,请参阅 "http-request return"。出于兼容性目的,当未定义参数或仅定义 "deny_status" 时,暗示参数 "default-errorfiles"。这意味着 "http-request tarpit [deny_status <status>]" 是 "http-request tarpit [status <status>] default-errorfiles" 的别名。不会评估进一步的 "http-request" 规则。另请参阅 "http-request return" 和 "http-request silent-drop"。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() | ![]() |
这会启用从当前请求跟踪 sticky counters。这些规则不会停止评估,也不会更改默认操作。同一连接可以同时跟踪的计数器数量由全局 "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 检查,都只执行一次表查找。
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
这用于取消设置一个变量。有关 <var-name> 的详细信息,请参阅“set-var”操作。http-request unset-var(req.my_var)
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() |
此操作会执行配置的 TCP 或 HTTP 服务来响应请求,具体取决于它所在的规则集。该规则是最终的,即在同一规则集中不会再评估其他规则。服务可以选择发送任何有效响应来回复,也可以选择立即关闭连接而不发送任何响应。对于 HTTP 服务,有效响应需要是一个有效的 HTTP 响应。除了原生服务(例如用于 HTTP 服务的 Prometheus 导出器),还可以用 Lua 编写自定义的 TCP 和 HTTP 服务。
<service-name> 是必需的。它是要调用的服务。
http-request use-service prometheus-exporter if { path /metrics }
可用
| QUIC Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() | ![]() |
这会延迟请求或响应的处理,直到发生以下条件之一:- 收到完整的请求体,此时处理正常进行。- 当给出 "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 Ini | TCP RqCon | RqSes | RqCnt | RsCnt | HTTP Req | Res | Aft |
|---|---|---|---|---|---|---|---|
![]() |
这会延迟请求的处理,直到 SSL 握手完成。这主要用于延迟处理早期数据,直到我们确定它们是有效的。
关键字 "bind"、"server" 和 "default-server" 支持许多设置,具体取决于某些构建选项和构建 HAProxy 的系统。这些设置通常每个都包含一个单词,有时后跟一个值,写在与 "bind" 或 "server" 行相同的行上。所有这些选项都在本节中描述。
"bind"关键字支持多种设置,这些设置都作为参数在同一行上传递。这些参数出现的顺序无关紧要,只要它们出现在绑定地址之后即可。所有这些参数都是可选的。其中一些由单个单词组成(布尔值),而另一些则需要一个值。在这种情况下,值必须紧跟在设置名称之后。当前支持的设置如下。强制在同一行上声明的任何 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”操作。
这会启用 TLS ALPN 扩展,并宣传指定的协议列表作为 ALPN 支持的协议。协议列表由逗号分隔的协议名称列表组成,例如:"http/1.1,http/1.0"(不带引号)。这要求 SSL 库在构建时启用了对 TLS 扩展的支持(使用 haproxy -vv 检查)。ALPN 扩展取代了最初的 NPN 扩展。在协议层,ALPN 是在 HTTPS 前端启用 HTTP/2 和在 QUIC 前端启用 HTTP/3 所必需的。但是,当此类前端没有设置 "npn"、"alpn" 和 "no-alpn" 中的任何一个时,对于常规 HTTPS 前端,将使用默认值 "h2,http/1.1",对于 QUIC 前端,将使用 "h3"。OpenSSL 1.0.2 之前的版本不支持 ALPN,只支持现在已弃用的 NPN 扩展。在撰写本文时,大多数浏览器仍然同时支持 ALPN 和 NPN 用于 HTTP/2,因此回退到 NPN 可能仍然有效一段时间。但是只要可能就必须使用 ALPN。未宣传的协议不会被协商。例如,可以使用以下方式仅接受 HTTP/2 连接:bind :443 ssl crt pub.pem alpn h2 # explicitly disable HTTP/1.1 QUIC 仅支持 h3 和 hq-interop 作为 ALPN。h3 用于 HTTP/3,hq-interop 用于 http/0.9 和 QUIC 互操作运行器(请参阅 https://interop.seemann.io)。每个 "alpn" 语句将替换前一个语句。要删除它们,请使用 "no-alpn"。请注意,一些旧浏览器(如 Firefox 88)过去在 WebSocket over H2 方面遇到问题,如果遇到此类设置,可能需要通过强制将其设置为 "http/1.1" 或 "no-alpn" 来显式禁用 "alpn" 字符串中的 HTTP/2,或者全局启用 "h2-workaround-bogus-websocket-clients"。
将套接字的 backlog 设置为此值。如果未指定或为 0,则使用前端的 backlog,通常默认为 maxconn 值。
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载验证客户端证书的 CA 证书。可以加载包含多个 CA 的目录,在这种情况下,HAProxy 将尝试加载目录中所有可用的“.pem”、“.crt”、“.cer”和“.crl”文件,以点开头的文件将被忽略。警告:可以使用“@system-ca”参数代替 cafile,以使用您系统的受信任 CA,就像 server 指令一样。但除非您知道自己在做什么,否则不应使用它。这样配置基本上意味着 bind 将接受由您系统上存在的任何 CA 生成的任何客户端证书,这是极其不安全的。
此设置仅在内置 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 握手不会中止。
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,其中包含用于创建和签署服务器证书的 CA 证书和 CA 私钥。当启用证书动态生成时,这是一个强制性设置。有关详细信息,请参见 'generate-certificates'。
此设置仅在内置 OpenSSL 支持时可用。它是 CA 私钥的密码。此设置是可选的,仅在启用证书动态生成时使用。有关详细信息,请参见 'generate-certificates'。
此设置指定一个 PEM 文件,用于加载验证客户端证书的 CA 证书。它指定的 CA 证书不应包含在服务器 hello 消息中发送的 CA 名称中。通常,“ca-file”必须用中间证书定义,而“ca-verify-file”则用终止证书链的证书(如根 CA)定义。
此设置仅在内置 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”关键字。此设置仅在内置 OpenSSL 支持且使用 OpenSSL 1.1.1 或更高版本构建 HAProxy 时可用。它设置描述在 TLSv1.3 握手期间协商的密码算法("cipher suite")列表的字符串。字符串的格式在 OpenSSL 手册页中的 "man 1 ciphers" 的 "ciphersuites" 部分中定义。对于 TLSv1.2 及更早版本的密码配置,请检查 "ciphers" 关键字。此设置可能接受 TLSv1.2 密码套件,但这是一种未记录的行为,不推荐,因为它可能不一致或有错误。OpenSSL 的默认 TLSv1.3 密码套件是:"TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256" TLSv1.3 仅支持 5 个密码套件:- TLS_AES_128_GCM_SHA256 - TLS_AES_256_GCM_SHA384 - TLS_CHACHA20_POLY1305_SHA256 - TLS_AES_128_CCM_SHA256 - TLS_AES_128_CCM_8_SHA256
ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256 ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256
此设置仅在内置 OpenSSL 支持时可用。它设置描述与客户端身份验证相关的协商签名算法列表的字符串。该字符串的格式在 OpenSSL 手册页的“man 3 SSL_CTX_set1_client_sigalgs”中定义。如果没有确定特定的用例,不建议使用此设置。
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载验证客户端证书的证书吊销列表。您需要为您证书颁发机构链中的每个证书提供一个证书吊销列表。
此设置仅在内置 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 subject 匹配的客户端。支持通配符,其中通配符字符 '*' 用于代替第一个主机名组件(例如 *.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 stapling")的支持。此文件的内容是可选的。如果非空,它必须包含 DER 格式的有效 OCSP 响应。为了有效,OCSP 响应必须符合以下规则:它必须指示良好状态,它必须是 PEM 文件证书的单个响应,并且在添加时必须有效。如果不遵守这些规则,则忽略 OCSP 响应并发出警告。为了识别 OCSP 响应适用于哪个证书,需要颁发者的证书。如果在 PEM 文件中找不到颁发者的证书,如果存在,它将从与 PEM 文件相同路径且后缀为 ".issuer" 的文件中加载,否则将因错误而失败。对于每个 PEM 文件,HAProxy 还会检查同一路径下后缀为 ".sctl" 的文件是否存在。如果找到此类文件,则启用证书透明度 (RFC6962) TLS 扩展的支持。将解析文件以检查基本语法,但不会验证签名。在某些情况下,需要支持多种密钥类型,例如在提供给客户端的密码套件中支持 RSA 和 ECDSA。这允许支持 EC 证书的客户端能够使用 EC 密码,同时支持较旧的、仅限 RSA 的客户端。为此,需要 OpenSSL 1.1.1,您可以通过为每种证书类型提供一个 crt 条目来配置此行为,或者像 HAProxy 1.8 之前所要求的那样配置“证书捆绑包”。请参阅 "ssl-load-extra-files"。.
此设置仅在内置 OpenSSL 支持时可用。设置在深度 == 0 的验证期间要忽略的以逗号分隔的 errorID 列表。它可以是数字 ID,也可以是常量名称 (X509_V_ERR),可在 OpenSSL 文档中找到:https://www.openssl.org/docs/manmaster/man3/X509_STORE_CTX_get_error.html#ERROR-CODES 建议使用常量名称,因为数值在新版本的 OpenSSL 中可能会改变。如果设置为 'all',则忽略所有错误。如果忽略了某个错误,SSL 握手不会中止。
此设置仅在内置 OpenSSL 支持时可用。它指定 PEM 文件列表,每个证书带有可选的 ssl 配置和 SNI 过滤器,格式如下:<crtfile> [\[<sslbindconf> ...\]] [[!]<snifilter> ...] sslbindconf 支持来自 bind 行的以下关键字(参见 Section 5.1. Bind options):- allow-0rtt - alpn - ca-file - ca-verify-file - ciphers - ciphersuites - client-sigalgs - crl-file - curves - ecdhe - no-alpn - no-ca-names - npn - sigalgs - ssl-min-ver - ssl-max-ver - verify sslbindconf 还支持来自 crt-store load 关键字的以下关键字(参见 Section 3.12.1. Load options):- crt - key - ocsp - issuer - sctl - ocsp-update 它覆盖 bind 行中为证书设置的配置。SNI 过滤器中支持通配符。还支持否定过滤器,在与通配符过滤器结合使用以排除特定 SNI,或在第一个证书之后排除其 CN 或 Subject Alt Name (SAN) 中的模式时非常有用。证书将呈现给提供有效 TLS 服务器名称指示字段且与 SNI 过滤器之一匹配的客户端。如果未指定 SNI 过滤器,则使用 CN 和 SAN。可以多次指定此指令。有关更多信息,请参阅 "crt" 选项。默认证书仍然需要满足 OpenSSL 期望。如果不使用它,可以使用 'strict-sni' 选项。crt-list 支持多证书捆绑(参见 "ssl-load-extra-files"),只要在 crt-list 中只给出基本名称即可。SNI 过滤器将对所有捆绑证书执行相同的工作。空行以及以哈希符号 ('#') 开头的行将被忽略。bind 行中声明的第一个证书用作默认证书,无论是来自 crt 还是 crt-list 选项,当没有其他证书匹配时,HAProxy 应在 TLS 握手中使用它。如果提供的 SNI 匹配其 CN 或 SAN,即使在任何 crt-list 上找到了匹配的 SNI 过滤器,也会使用此证书。SNI 过滤器 !* 可以在第一个声明的证书之后使用,以不将其 CN 和 SAN 包含在 SNI 树中,因此除非没有其他证书匹配,否则它永远不会匹配。这样,第一个声明的证书充当后备。也可以声明一个 '*' 过滤器,这将允许选择此证书作为默认值。当定义了多个默认证书时,HAProxy 能够根据客户端支持的内容选择正确的 ECDSA 或 RSA 证书。如果未设置 ALPN,则使用 "bind" 行的默认值。如果 "bind" 行没有设置 "no-alpn"、"alpn" 也不设置 "npn",则将根据协议使用默认值(参见上面的 "alpn")。但是,如果 "bind" 行有不同的默认值,或者使用 "no-alpn" 显式禁用 ALPN,则可以为证书强制设置特定值。crt-list 文件示例:cert1.pem !* # comment 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 default.pem.rsa * default.pem.ecdsa * foo.crt [key bar.pem ocsp foo.ocsp ocsp-update on] foo.bar.com
此选项执行与 "crt" 选项相同的功能,不同之处在于此证书将用作默认证书。可以添加多个默认证书以具有一个 ECDSA 和一个 RSA 证书,拥有更多证书并不是很有用。当 bind 行上未使用 "strict-sni" 选项时,将使用默认证书。当客户端未使用 servername 扩展名,或者当 servername 与任何配置的证书不匹配时,将提供默认证书。
bind *:443 default-crt foobar.pem.rsa default-crt foobar.pem.ecdsa crt website.pem.rsa
另请参阅“crt”关键字。此设置仅在内置 OpenSSL 支持时可用。它设置描述在与 ECDHE 的 SSL/TLS 握手期间协商的椭圆曲线算法列表(“曲线套件”)的字符串。该字符串的格式是以冒号分隔的曲线名称列表。
是一个可选关键字,仅在某些 Linux 内核上受支持。它规定只有在连接上有数据到达时,或者最坏情况下在第一次重传后,才会接受连接。这只应在客户端首先发言的协议(例如 HTTP)上使用。它可以通过确保在接受连接时大部分请求已经可用,从而略微提高性能。另一方面,它将无法检测到不发言的连接。重要的是要注意,此选项在所有 2.6.31 之前的内核中都是有问题的,因为在客户端发言之前连接永远不会被接受。这可能会导致前端防火墙出现问题,前端防火墙会看到一个已建立的连接,而代理只会看到它处于 SYN_RECV 状态。此选项仅在 TCPv4/TCPv6 套接字上受支持,其他套接字会忽略它。
此设置仅在内置 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 的内存占用,以减少多次使用同一证书时的延迟。
将 UNIX 套接字的组设置为指定的系统 gid。也可以在全局部分的 "unix-bind" 语句中默认设置。请注意,某些平台会忽略此设置。此设置与 "group" 设置等效,只是使用了组 ID 而非组名称。非 UNIX 套接字会忽略此设置。
将 UNIX 套接字的组设置为指定的系统组。也可以在全局部分的 "unix-bind" 语句中默认设置。请注意,某些平台会直接忽略此设置。此设置与 "gid" 设置等效,不同之处在于它使用组名而不是组 ID。此设置对非 UNIX 套接字无效。
为在此 bind 行上分配的每个侦听套接字生成区分大小写的全局唯一 ID。前缀将与当前 bind 行上侦听器的位置索引连接,使用字符“-”作为分隔符。有关其格式的更多信息,请参阅“guid”代理关键字描述。固定套接字 ID。默认情况下,套接字 ID 是自动分配的,但有时为了方便监控而固定它们会更方便。此值必须是严格正数,并且在侦听器/前端内是唯一的。此选项只能在定义单个套接字时使用。
将套接字限制到特定接口。指定后,只有从该特定接口接收的数据包才会由套接字处理。目前仅在 Linux 上受支持。该接口必须是主系统接口,而不是别名接口。如果多个前端绑定到不同的接口,也可以将它们绑定到同一地址。请注意,绑定到网络接口需要 root 权限。此参数仅与 TCPv4/TCPv6 套接字兼容。指定后,返回流量将使用与入站流量相同的接口及其关联的路由表,即使配置了通过不同接口的显式路由也是如此。当同一客户端 IP 地址需要能够访问托管在不同接口上的前端时,这对于解决非对称路由问题非常有用。
此设置仅用于 stats 套接字,用于限制可在套接字上发出的命令类型。其他套接字会忽略此设置。<level> 可以是以下之一: - "user" 是权限最低的级别;只允许读取非敏感统计数据,不允许进行更改。在难以限制套接字访问的系统上,此设置很有意义。 - "operator" 是默认级别,适用于大多数常见用途。可以读取所有数据,并且只允许进行非敏感更改(例如清除最大计数器)。 - "admin" 应谨慎使用,因为它允许执行所有操作(例如清除所有计数器)。
将套接字限制为此数量的并发连接。多余的连接将保留在系统的 backlog 中,直到释放一个连接。如果未指定,限制将与前端的 maxconn 相同。请注意,在端口范围或多个地址的情况下,相同的值将应用于每个套接字。此设置允许对昂贵的套接字进行不同的限制,例如 SSL 条目,它们很容易耗尽所有内存。
设置用于定义 UNIX 套接字访问权限的八进制模式。也可以在全局部分的 "unix-bind" 语句中默认设置。请注意,某些平台会直接忽略此设置。此设置对非 UNIX 套接字无效。
设置要在传入连接上通告的 TCP 最大段大小(MSS)值。这可用于为某些特定端口强制使用较低的 MSS,例如用于通过 VPN 的连接。请注意,这依赖于一个内核功能,理论上在 Linux 下受支持,但在 2.6.28 之前的所有版本中都有错误。它可能在其他操作系统上工作,也可能不工作。它也可能不改变通告的值,而是改变传出段的有效大小。在以太网网络上,TCPv4 的通常通告值为 1460 = 1500(MTU) - 40(IP+TCP)。如果此值为正,它将用作通告的 MSS。如果为负,它将指示传出段应比传入连接的通告 MSS 减少多少。此参数仅与 TCP v4/v6 套接字兼容。
为这些套接字设置一个可选名称,该名称将在统计页面上报告。
在 Linux 上,可以指定套接字将属于哪个网络命名空间。此指令使得可以显式地将侦听器绑定到不同于默认命名空间的命名空间。请参考您的操作系统文档以了解有关网络命名空间的更多详细信息。
此设置仅对使用反向 HTTP 的侦听器实例有效。这将定义将并行建立的连接数。如果未指定,则使用默认值 1。反向 HTTP 目前仍在积极开发中。配置机制将来可能会改变。因此,它在内部被标记为实验性,这意味着在使用此指令之前必须在一行上出现“expose-experimental-directives”。
设置从套接字发起的连接的“友好度”(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 支持时可用。它禁用无状态会话恢复(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 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 证书。
强制用于传入连接的多路复用器协议。它必须与前端模式(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 特定设置,用于选择对配置的 QUIC 监听器的任何连接尝试的拥塞控制算法。它们类似于 TCP 中使用的算法。可以在拥塞算法之上激活 Pacing 以减少损失并提高吞吐量。这是通过 "tune.quic.tx-pacing" 实验性全局关键字执行的。使用 BBR 时需要特别注意,因为它依赖 pacing 才能正常工作。在没有 pacing 的情况下使用 BBR 可能会导致传输过程中速度变慢或高丢包率。另请注意,haproxy 的 BBR 实现也被认为是实验性的,如果没有 "expose-experimental-directives",则无法启用。默认值: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 特定设置允许为特定监听器定义套接字分配模式。有关其用法的完整描述,请参见“tune.quic.socket-owner”。
此设置仅与 stats 套接字一起使用,用于配置附加到信息反馈消息前的严重性级别输出。消息的严重性级别范围可以在 0 到 7 之间,符合 syslog rfc5424。请求数据的有效且成功的套接字命令(例如“show map”、“get acl foo”等)绝不会附加严重性级别。其他套接字会忽略此设置。<format> 可以是以下之一:- “none”(默认)不向反馈消息前附加严重性级别。- “number” 严重性级别作为数字附加。- “string” 严重性级别作为遵循 rfc5424 约定的字符串附加。
在多线程模式下,在支持同一 IP:port 上多个监听器的操作系统上,这会自动为此行创建数量相同的多个相同监听器,所有这些监听器都绑定到此监听器所附加线程数的公平份额。当使用非常大的线程数时,单个套接字上的内核内锁定开始导致显著开销时,这有时会很有用。在这种情况下,传入流量分布在多个套接字上,减少了争用。请注意,这样做很容易通过使更多线程工作一点点来增加 CPU 使用率。如果分片数量高于可用线程数,它将自动修剪为线程数(即每个线程一个分片)。特殊值 "by-thread" 也会创建与 "bind" 行上的线程一样多的分片。由于系统将在所有这些分片之间平均分配传入流量,因此此数字是线程数的整数除数非常重要。或者,另一个特殊值 "by-group" 将为每个线程组创建一个分片。这在处理许多线程且不希望创建太多套接字时非常有用。负载分配会稍微不那么理想,但争用(尤其是在系统中)仍将低于单个套接字。在不支持绑定到同一地址的多个套接字的操作系统上,"by-thread" 和 "by-group" 将自动回退到单个分片。对于 "by-group",这是在没有任何警告的情况下完成的,因为它不会改变单个组的任何内容,并且无论如何都会导致套接字为每个组重复。但是,对于 "by-thread",如果发生这种情况,将发出诊断警告,因为生成的监听器数量将不是预期的数量。此设置仅在内置 OpenSSL 支持时可用。它设置一个字符串,描述在 TLSv1.2 和 TLSv1.3 握手期间协商的签名算法列表。字符串的格式在 OpenSSL 手册页的“man 3 SSL_CTX_set1_sigalgs”中定义。不建议使用此设置,除非需要与中间件兼容。
此设置仅在内置 OpenSSL 支持时可用。它在此监听器实例化的连接上启用 SSL 解密。需要一个证书(参见上面的“crt”)。缓冲区中的所有内容都将以明文形式出现,因此 ACL 和 HTTP 处理将只能访问解密后的内容。SSLv3 默认被禁用,使用“ssl-min-ver SSLv3”来启用它。此选项强制此监听器实例化的 SSL 连接使用 <version> 或更低版本。在不使用 "ssl-min-ver" 的情况下使用此设置可能会产生歧义,因为默认 ssl-min-ver 值可能会在未来的 HAProxy 版本中更改。此选项也可用于全局语句 "ssl-default-bind-options"。另请参阅 "ssl-min-ver"。
此选项强制在此监听器实例化的 SSL 连接上使用 <version> 或更高版本。默认值为“TLSv1.2”。此选项也适用于全局语句“ssl-default-bind-options”。另请参见“ssl-max-ver”。
此设置仅在内置 OpenSSL 支持时可用。仅当客户端提供了与证书匹配的 SNI 时,才允许 SSL/TLS 协商。不使用默认证书。此选项还允许在 bind 行上不带任何证书启动,因此可以使用空目录,稍后从 stats 套接字填充。有关更多信息,请参阅 "crt" 选项。请参阅管理指南中的 "add ssl crt-list" 命令。为从此监听套接字实例化的所有传入连接设置 TCP 用户超时。此选项自 Linux 2.6.37 版本起可用。它允许 HAProxy 为包含未在配置的延迟内收到确认的数据的套接字配置超时。这对于经历长空闲期的长连接(例如远程终端或数据库连接池)特别有用,其中客户端和服务器超时必须保持较高以允许长时间的空闲,但同时检测客户端是否已消失以释放与其连接(及服务器会话)相关的所有资源又非常重要。参数是一个以毫秒为单位的延迟,默认情况下。这仅适用于常规 TCP 连接,对其他协议无效。
是一个可选关键字,仅在 Linux 内核版本 >= 3.7 上受支持。它在监听套接字上启用 TCP 快速打开(TCP Fast Open),这意味着支持此功能的客户端将能够在第二次连接开始的三次握手期间发送请求并接收响应,从而在第一次连接后节省一次往返时间。这仅对连接率高且每次往返都很重要的协议有意义。这可能会导致许多防火墙出现问题,因为它们不接受 SYN 数据包上的数据,因此只应在经过充分测试后才启用此选项。此选项仅在 TCPv4/TCPv6 套接字上受支持,并被其他套接字忽略。如果您的 libc 未定义 TCP_FASTOPEN,您可能需要使用 USE_TFO=1 来构建 HAProxy。
这限制了此监听器允许运行的线程列表。它不会强制执行其中任何一个,而是消除不匹配的线程。它限制了允许处理此监听器传入连接的线程。有两种编号方案。默认情况下,线程编号在进程中是绝对的,介于 1 和 global.nbthread 中指定的值之间。也可以使用其在线程组中的相对编号来指定线程编号,方法是首先指定线程组编号,然后是斜杠 ('/') 和相对线程编号。在这种情况下,线程编号也从 1 开始,到 32 或 64 结束,具体取决于平台。指定绝对线程编号时,一旦知道线程组,它们将自动转换为相对编号。通常,绝对编号适用于简单配置,而相对编号适用于 CPU 排列对性能很重要的复杂配置。在可选的线程组编号之后,"thread-set" 规范必须使用以下格式:"all" | "odd" | "even" | [number][-[number]] 顾名思义,"all" 验证集合中的所有线程(如果指定了组,则为组中的所有线程,否则为进程中的所有线程),"odd" 验证所有奇数编号的线程(从 1 开始,每隔一个线程),无论是针对进程还是组,"even" 验证所有偶数编号的线程(从 2 开始,每隔一个线程)。如果改用线程编号范围,则验证从第一个到最后一个线程编号范围内的所有线程。编号是相对于组还是绝对编号取决于是否存在线程组编号。如果省略第一个线程编号,则使用 "1",表示组中的第一个线程或进程中的第一个线程。如果省略最后一个线程编号,则使用组中的最后一个线程编号(32 或 64)或进程中的最后一个线程编号 (global.nbthread)。这些范围可以重复并用逗号分隔,以便可以指定不连续的线程集,并且如果存在组,则必须为每个新范围再次指定该组。请注意,不允许混合使用组相对和绝对规范,因为整个 "bind" 行必须使用绝对表示法或相对表示法,因为未设置的表示法将在解析结束时解析。重要的是要知道由 "bind" 行描述的每个监听器都会创建至少一个由至少一个文件描述符表示的套接字。由于文件描述符不能跨越多个线程组,如果 "bind" 行指定的线程范围覆盖多个组,则会自动创建多个文件描述符,以便每个组至少有一个文件描述符。从技术上讲,它们在内核中都指向同一个套接字,但它们在 haproxy 中将具有不同的标识符,并且如果使用 "option socket-stats",它们甚至会有一个专用的 stats 条目。主要目的是让多个 bind 行共享相同的 IP:port,但在监听器中不共享同一线程,以便系统可以将传入连接分配到多个队列中,从而绕过 haproxy 的内部队列负载平衡。目前已知 Linux 3.9 及更高版本支持此功能。另请参阅上文的 "shards" 关键字,它会自动复制 "bind" 行并将其分配给多个线程组。此关键字与反向 HTTP 绑定兼容。但是,对于此类监听器,禁止指定跨越多个线程组的线程集,因为这可能会导致 "nbconn" 无法按预期工作。设置从中加载密钥的 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 套接字兼容,具体取决于内核版本。一些发行版的内核包含该功能的向后移植版本,因此请向您的供应商查询支持情况。
将 UNIX 套接字的属主设置为指定的系统 uid。也可以在全局部分的 "unix-bind" 语句中默认设置。请注意,某些平台会忽略此设置。此设置与 "user" 设置等效,只是使用了用户数字 ID 而非用户名称。非 UNIX 套接字会忽略此设置。
将 UNIX 套接字的所有者设置为指定的系统用户。它也可以在全局部分的“unix-bind”语句中默认设置。请注意,某些平台会直接忽略此设置。此设置与“uid”设置等效,不同之处在于使用的是用户名而不是其 uid。此设置被非 UNIX 套接字忽略。
是一个可选关键字,仅在包括 Linux 内核版本 >= 2.4.21 在内的大多数最新系统上受支持。它用于在使用默认地址时将套接字同时绑定到 IPv4 和 IPv6。在默认情况下仅绑定到 IPv6 的系统上,这样做有时是必要的。它对非 IPv6 套接字没有影响,并被“v6only”选项覆盖。
是一个可选关键字,仅在包括 Linux 内核版本 >= 2.4.21 在内的大多数最新系统上受支持。它用于在使用默认地址时将套接字仅绑定到 IPv6。这样做有时比系统范围的设置更受欢迎,因为它是针对每个监听器的。它对非 IPv6 套接字没有影响,并优先于“v4v6”选项。
此设置仅在构建时包含 OpenSSL 支持时可用。如果设置为 'none',则不请求客户端证书。这是默认设置。在其他情况下,会请求客户端证书。如果客户端在请求后未提供证书,并且 'verify' 设置为 'required',则握手将中止,而如果设置为 'optional',则会成功。客户端提供的证书始终使用来自 'ca-file' 的 CA 和来自 'crl-file' 的可选 CRL 进行验证。验证失败时,握手将中止,无论 'verify' 选项如何设置,除非错误代码与 'ca-ignore-err' 或 'crt-ignore-err' 中列出的错误代码完全匹配。
"server" 和 "default-server" 关键字支持一定数量的设置,所有这些设置都作为参数在 server 行上传递。这些参数出现的顺序无关紧要,并且它们都是可选的。其中一些设置是单个单词(布尔值),而另一些则需要它们后面跟一个或多个值。在这种情况下,值必须紧跟在设置名称之后。除了 default-server 之外,所有这些设置如果使用,都必须在服务器地址之后指定: server <name> <address>[:port] [settings ...] default-server [settings ...] 请注意,所有这些设置都受 "server" 和 "default-server" 关键字支持,除了 "id" 仅受 "server" 支持。目前支持的设置为以下内容。
可在以下上下文中使用: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,但由于单词本身在统计信息页面上报告,因此差异允许管理员知道情况是否符合预期:服务可能有意停止,可能看起来正常但未能通过某些有效性测试,或者可能被视为 down(例如缺少进程,或者端口无响应)。 - 单词 "up" 将服务器的操作状态重新设置为 UP,前提是健康检查也报告该服务可访问。代理未通告的参数不会更改。例如,代理可能旨在监视 CPU 使用率,并且只报告相对权重,从不与操作状态交互。同样,代理可以设计为具有 3 个单选按钮的用户界面,允许管理员仅更改管理状态。但是,重要的是要考虑只有代理才能恢复其自身的操作,因此如果使用代理将服务器设置为 DRAIN 模式或 DOWN 状态,则代理必须实现其他等效操作才能使服务重新投入运行。无法连接到代理不被视为错误,因为连接性由通过 "check" 参数启用的常规健康检查进行测试。请注意,在代理报告 "down" 后停止代理不是一个好主意,因为只有报告 "up" 的代理才能再次将服务器设置为 up。请注意,Unix stats 套接字上的 CLI 也可以强制代理结果,以便在需要时解决错误的代理。需要设置 "agent-port" 参数。另请参阅 "agent-inter" 和 "no-agent-check" 参数。
可在以下上下文中使用:tcp, http, log 如果指定了此选项,HAProxy 将在连接时将给定的字符串(逐字)发送到代理服务器。例如,您可以将后端名称编码到此字符串中,这将使您的代理能够根据后端发送不同的响应。如果您想用换行符终止请求,请确保包含一个 '\n'。
可在以下上下文中使用:tcp、http、log "agent-inter" 参数将两次代理检查之间的时间间隔设置为 <delay> 毫秒。如果未指定,则延迟默认为 2000 ms。就像所有其他基于时间的参数一样,它可以以任何其他明确的单位输入,包括 { us, ms, s, m, h, d }。如果未设置 "timeout check",则 "agent-inter" 参数也用作代理检查的超时。为了减少当多个服务器托管在同一硬件上时的“共振”效应,所有服务器的代理和健康检查都以很小的时间偏移启动。也可以使用全局 "spread-checks" 关键字在代理和健康检查间隔中添加一些随机噪声。例如,当许多后端使用相同的服务器时,这很有意义。另请参阅 "agent-check" 和 "agent-port" 参数。
可在以下上下文中使用:tcp, http, log “agent-addr”参数设置代理检查的地址。您可以将代理检查卸载到另一个目标,这样如果您无法实现自感知和自管理的服务,就可以在一个地方管理 HAProxy 中定义的服务器的状态和权重。您可以同时指定 IP 或主机名,它将被解析。
可在以下上下文中使用:tcp, http, log “agent-port”参数设置用于代理检查的 TCP 端口。另请参见“agent-check”和“agent-inter”参数。
可在以下上下文中使用:tcp, http, log, peers, ring 允许在使用 TLS 1.3 时向服务器发送早期数据。请注意,只有在客户端使用了早期数据,或者后端使用了带有“0rtt-rejected”关键字的“retry-on”时,才会发送早期数据。
可在以下上下文中使用: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”选项。
可在以下上下文中使用: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 此选项强制在传出的健康检查中发送 PROXY 协议行,无论服务器是否为正常流量使用 send-proxy。默认情况下,如果 PROXY 协议已为正常流量启用,并且没有“port”或“addr”指令存在,则为健康检查启用 PROXY 协议。但是,如果存在这样的指令,则需要使用“check-send-proxy”选项来强制使用该协议。有关更多信息,请参见“send-proxy”选项。
可在以下上下文中使用:tcp, http 定义要通过 ALPN 通告的协议。协议列表由一个以逗号分隔的协议名称列表组成,例如:"http/1.1,http/1.0"(不含引号)。如果未设置,则使用服务器的 ALPN。
可在以下上下文中使用:tcp、http 强制用于服务器健康检查连接的多路复用器协议。它必须与健康检查类型(TCP 或 HTTP)兼容。它也必须能在后端使用。可用协议列表在 haproxy -vv 中报告。报告了协议属性:模式 (TCP/HTTP)、端 (FE/BE)、mux 名称及其标志。某些协议在服务器端容易出现队头阻塞 (flag=HOL_RISK)。最后,某些协议不支持升级 (flag=NO_UPG)。还报告了 HTX 兼容性 (flag=HTX)。以下是可用作服务器行上 "check-proto" 指令参数的协议: h2:mode=HTTP side=FE|BE mux=H2 flags=HTX|HOL_RISK|NO_UPG fcgi:mode=HTTP side=BE mux=FCGI flags=HTX|HOL_RISK|NO_UPG h1:mode=HTTP side=FE|BE mux=H1 flags=HTX|NO_UPG none:mode=TCP side=FE|BE mux=PASS flags=NO_UPG 此选项的目的是绕过对此服务器建立的健康检查连接选择最佳多路复用器协议。如果未定义,将使用服务器的协议(如果已设置)。
可在以下上下文中使用: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 隧道,健康检查也不会通过它。
可在以下上下文中使用: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”关键字。可在以下上下文中使用:tcp、http、log、peers、ring 此设置仅在内置 OpenSSL 支持且使用 OpenSSL 1.1.1 或更高版本构建 HAProxy 时可用。此选项设置描述在 TLS 1.3 握手期间与服务器协商的密码算法列表的字符串。字符串的格式在 OpenSSL man pages 的 "man 1 ciphers" 中 "ciphersuites" 部分中定义。对于 TLSv1.2 及更早版本的密码配置,请检查 "ciphers" 关键字。
可在以下上下文中使用:tcp、http、log、peers、ring 此设置仅在内置 OpenSSL 支持时可用。它设置一个描述协商的与客户端身份验证相关的签名算法列表的字符串。该字符串的格式在 OpenSSL 手册页的 "man 3 SSL_CTX_set1_client_sigalgs" 中定义。如果没有确定特定的用例,不建议使用此设置。
可在以下上下文中使用:http "cookie" 参数将分配给服务器的 cookie 值设置为 <value>。将在传入请求中检查此值,并选择具有相同值的第一个操作服务器。反过来,在 cookie 插入或重写模式下,此值将分配给发送到客户端的 cookie。多个服务器共享相同的 cookie 值没有问题,这在正常服务器和备份服务器之间实际上很常见。另请参阅后端部分中的 "cookie" 关键字。
可在以下上下文中使用:tcp、http、log、peers、ring 此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载证书吊销列表以验证服务器的证书。
可在以下上下文中使用:tcp、http、log、peers、ring 此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载证书及其关联的私钥。此文件可以通过将两个 PEM 文件连接成一个来构建。如果服务器发送客户端证书请求,则将发送此证书。如果该文件不包含私钥,HAProxy 将尝试在同一路径下加载带有“.key”后缀的密钥(前提是相应地设置了“ssl-load-extra-files”选项)。
可在以下上下文中使用:tcp、http、log、peers、ring 此设置仅在内置 OpenSSL 支持时可用。它设置一个字符串,描述在 SSL/TLS 握手期间与 ECDHE 协商的椭圆曲线算法列表(“曲线套件”)。该字符串的格式是一个以冒号分隔的曲线名称列表。
"X25519:P-256" (不带引号)
可在以下上下文中使用:tcp、http、log "disabled" 关键字以 "disabled" 状态启动服务器。这意味着它在维护模式下被标记为 down,除了持久模式允许的连接之外,没有其他连接会到达它。它非常适合设置新服务器,因为正常流量永远不会到达它们,同时仍然可以通过使用 force-persist 机制来测试服务。另请参阅 "enabled" 设置。
可在以下上下文中使用:tcp、http、log 此选项可用作'server'设置,以重置任何从'default-server'指令继承为默认值的'disabled'设置。它也可用作'default-server'设置,以重置任何先前的'default-server' 'disabled'设置。
可在以下上下文中使用:tcp、http、log 如果启用了健康状况观察,"error-limit"参数指定触发由"on-error"选项选择的事件的连续错误数。默认设置为 10 个连续错误。另请参见"check"、"error-limit"和"on-error"。
可在以下上下文中使用: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"。
可在以下上下文中使用:tcp、http、log 为此服务器指定一个区分大小写的全局唯一 ID。此 ID 在所有 haproxy 配置中的所有对象类型中必须是唯一的。有关其格式的更多信息,请参阅“guid”代理关键字描述。可在以下上下文中使用:tcp、http、log 指定“hash-type consistent”节点密钥的计算方式
<key> <key> 可以是以下之一: id 节点键将派生自服务器的数字标识符,如通过 "id" 设置或默认为其在服务器列表中的位置。 addr 节点键将派生自服务器的地址(如果可用),否则回退到 "id"。 addr-port 节点键将派生自服务器的地址和端口(如果可用),否则回退到 "id"。
"addr" 和 "addr-port" 选项在多个 HAProxy 进程对同一组服务器进行负载均衡的场景中可能很有用。如果每个进程的服务器顺序不同(例如,因为 DNS 记录以不同顺序解析),这将允许每个独立的 HAProxy 进程就路由决策达成一致。
可在以下上下文中使用:tcp、http、log 为服务器设置一个持久 ID。此 ID 必须为正数且对于该代理是唯一的。如果未设置,将自动分配一个未使用的 ID。第一个分配的值将是 1。此 ID 当前仅在统计信息中返回。
可在以下上下文中使用:tcp、http、log 指示如果服务器使用 FQDN,则在启动时应按什么顺序解析服务器地址。尝试通过依次应用逗号分隔列表中提到的每种方法来解析地址。使用第一个成功的方法。如果到达列表末尾仍未找到可用的方法,则会引发错误。方法 "last" 建议选择出现在状态文件中的地址(请参阅 "server-state-file")。方法 "libc" 使用 libc 的内部解析器 (gethostbyname() 或 getaddrinfo(),具体取决于操作系统和构建选项)。方法 "none" 特别指示服务器应在 down 状态下启动,不带任何有效的 IP 地址。这对于忽略启动时的一些 DNS 问题很有用,等待稍后情况得到解决。最后,可以提供一个 IP 地址(IPv4 或 IPv6)。它可以是服务器当前已知的地址(例如由配置生成器填充),或者是用于捕获旧会话并向其显示适当错误消息的虚拟服务器的地址。当使用 "first" 负载平衡算法时,此 IP 地址可以指向一个用于触发即时创建新实例的虚假服务器。此选项默认为 "last,libc",表示首先使用状态文件中找到的上一个地址(如果有),否则使用 libc 的解析器。这确保了与历史行为的持续兼容性。当使用内部解析器时,通常建议要么禁用基于 libc 的解析,要么使其显式(有关更多详细信息,请参阅第 5.3 节)。示例 1:defaults # never fail on address resolution default-server init-addr last,libc,none 示例 2:defaults # disable libc resolution in combination with resolvers default-server init-addr last,none
可在以下上下文中使用:tcp、http、log "inter" 参数将两次连续健康检查之间的时间间隔设置为 <delay> 毫秒。如果未指定,则延迟默认为 2000 ms。也可以使用 "fastinter" 和 "downinter" 根据服务器状态优化检查之间的延迟
| 服务器状态 | 使用的间隔 |
|---|---|
| UP 100% (非过渡状态) | “inter” |
| 过渡性 UP (正在变为 down "fall"), 过渡性 DOWN (正在变为 up "rise"), 或尚未检查。 | 如果设置了“fastinter”,则使用它, 否则使用“inter”。 |
| DOWN 100% (非过渡状态) | 如果设置了“downinter”,则使用它, 否则使用“inter”。 |
就像所有其他基于时间的参数一样,它们可以以任何其他明确的单位输入,包括 { us, ms, s, m, h, d }。如果未设置 "timeout check",则 "inter" 参数也用作发送到服务器的健康检查的超时。为了减少当多个服务器托管在同一硬件上时的“共振”效应,所有服务器的代理和健康检查都以很小的时间偏移启动。也可以使用全局 "spread-checks" 关键字在代理和健康检查间隔中添加一些随机噪声。例如,当许多后端使用相同的服务器时,这很有意义。全局 "tune.max-checks-per-thread" 设置(如果定义为非零值)将限制在任何给定线程上同时执行的检查数量。为了实现此目的,haproxy 会将即将在一个达到此限制的线程上开始的检查放入队列中,直到另一个检查完成。这将导致有效检查间隔延长。在这种情况下,减小 "inter" 设置的效果非常有限,因为它无法减少在队列中花费的时间。可在以下上下文中使用:tcp、http
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
"init-state" 选项设置服务器的初始状态: - 设置为 'fully-up' 时,服务器被立即视为可用,并且当所有健康检查失败时可以转为 DOWN 状态。 - 设置为 'up'(默认值)时,服务器被立即视为可用,并将启动健康检查,如果失败,可以立即将其转为 DOWN 状态。 - 设置为 'down' 时,服务器最初被视为不可用,并将启动健康检查,如果成功,可以立即将其转为 UP 状态。 - 设置为 'fully-down' 时,服务器最初被视为不可用,并且当所有健康检查成功时可以转为 UP 状态。当 HAProxy 实例(重新)启动、检测到新服务器(例如通过服务发现/DNS 解析)、动态服务器上线、服务器退出维护等时,会考虑服务器的 init-state。
# 仅将客户端流量传递给 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 “log-bufsize”指定用于与日志后端中的日志服务器关联的隐式环形缓冲区的 bufsize。如果未指定,则默认为 BUFSIZE。使用更大的值会增加内存使用量,但可以帮助防止在服务器慢速时丢失日志消息,因为缓冲区将能够容纳更多待处理的消息。此关键字只能在日志后端部分(使用“mode log”)中使用
可在以下上下文中使用:log、ring “log-proto”指定用于将事件消息转发到在日志或环形部分中配置的服务器的协议。可能的值为“legacy”和“octet-count”,分别对应 rfc6587 中的“非透明成帧”和“八位字节计数”。“legacy”是默认值。
可在以下上下文中使用:tcp、http "maxconn" 参数指定将发送到此服务器的最大并发连接数。如果传入并发连接数高于此值,它们将被排队,等待槽位释放。此参数非常重要,因为它可以在极端负载下保护脆弱的服务器不宕机。如果指定了 "minconn" 参数,则限制变为动态限制。默认值为 "0",表示无限制。另请参阅 "minconn" 和 "maxqueue" 参数,以及后端的 "fullconn" 关键字。在 HTTP 模式下,此参数限制并发请求数而不是连接数。多个请求可以通过单个 TCP 连接多路复用到服务器。例如,如果您指定 maxconn 为 50,您可能会看到 1 到 50 个实际服务器连接,但并发请求不超过 50 个。
可在以下上下文中使用:tcp、http "maxqueue" 参数指定将在此服务器队列中等待的最大连接数。如果达到此限制,下一个请求将被重新分配到其他服务器,而不是无限期地等待服务。这会破坏持久性,但可能允许用户在他们尝试连接的服务器即将崩溃时快速重新登录。某些负载平衡算法(例如 leastconn)会考虑到这一点,如果明确设置为大于零的值,则接受将请求添加到服务器队列中,这通常允许在处理个位数 maxconn 值时更好地平滑负载。默认值为 "0",表示队列无限制。另请参阅 "maxconn" 和 "minconn" 参数以及 "balance leastconn"。
可在以下上下文中使用:http、ring 当在 http 上下文中使用时:"max-reuse" 参数指示 HTTP 连接处理器不应将服务器连接重用于发送新请求的次数超过此数字。允许的值是 -1(默认值),它禁用此限制,或任何正值。值零将有效地禁用 keep-alive。这仅用于解决某些服务器错误,这些错误会导致它们随时间泄漏资源。该参数不一定受到较低层的尊重,因为可能存在使其无法强制执行的技术限制。至少到服务器的 HTTP/2 连接会尊重它。当在 ring 上下文中使用时:"max-reuse" 参数指示接收器 TCP 连接处理器不应将服务器连接重用于发送消息的次数超过此数字。这意味着一旦在同一连接上处理了至少 "max-reuse + 1" 条消息,与服务器的连接将被强制销毁。然后,与服务器的连接将自动重新创建。在多线程上下文中处理大量消息时,这有助于更好地将环的负载分布到多个线程上。实际上,每个连接在其整个持续时间内都绑定到同一个 CPU 线程:与 HTTP 不同,没有 syslog 事务之类的东西,因此服务器连接可以无限期地存在,只要服务器不关闭连接或不发生网络错误。通过不时销毁连接,我们为其他线程提供了依次处理某些消息的机会。它还有助于在 haproxy 和日志服务器之间存在额外的负载平衡层的情况下,平稳地轮换日志服务器。但是,请记住,每次连接回收都会在现代操作系统上留下处于 TIME_WAIT 状态的出站端口,该端口在大约一分钟内不可重用,因此必须小心不要使用太低的值,以防止源端口快速耗尽。根据经验,确保每秒关闭次数不要超过几次,最好更少。允许的值是 -1(默认值),它禁用此限制,或任何正值。与 HTTP 上下文不同,当与接收器服务器一起使用时,"max-reuse" 是一种尽力而为:环消息是分批处理的,因此在每批之间检查限制。
可在以下上下文中使用:tcp、http 当设置了 "minconn" 参数时,maxconn 限制将变为跟随后端负载的动态限制。服务器将始终接受至少 <minconn> 个连接,永不超过 <maxconn> 个连接,当后端并发连接数少于 <fullconn> 时,限制将在两个值之间呈斜坡状。这使得在正常负载期间限制服务器上的负载成为可能,但在重要负载期间进一步推动它,同时又不会在异常负载期间使服务器过载。另请参阅 "maxconn" 和 "maxqueue" 参数,以及 "fullconn" 后端关键字。
可在以下上下文中使用: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、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 当使用 SSL 与服务器通信时,此选项禁用对 SSLv3 的支持。请注意,SSLv2 在代码中已被禁用,无法使用任何配置选项启用。请改用 "ssl-min-ver" 和 "ssl-max-ver"。支持 default-server:否
可用于以下上下文:tcp、http、log、peers、ring 仅当内置了对 OpenSSL 的支持时,此设置才可用。它禁用无状态会话恢复(RFC 5077 TLS Ticket 扩展)并强制使用有状态会话恢复。无状态会话恢复对服务器的 CPU 使用率更高。此选项也可用于全局语句 "ssl-default-server-options"。TLS ticket 机制仅用于 TLS 1.2 及以下版本。除非定期轮换 ticket 密钥(通过重新加载或使用 "tls-ticket-keys"),否则使用 TLS ticket 会损害前向保密性。另请参阅 "tls-tickets"。
可用于以下上下文:tcp、http、log、peers、ring 当使用 SSL 与服务器通信时,此选项禁用对 TLSv1.0 的支持。请注意,SSLv2 在代码中已被禁用,无法使用任何配置选项启用。TLSv1 比 SSLv3 的开销更大,因此在与本地服务器通信时禁用它通常是有意义的。此选项也可用于全局语句 "ssl-default-server-options"。请改用 "ssl-min-ver" 和 "ssl-max-ver"。支持 default-server:否
可用于以下上下文:tcp、http、log、peers、ring 当使用 SSL 与服务器通信时,此选项禁用对 TLSv1.1 的支持。请注意,SSLv2 在代码中已被禁用,无法使用任何配置选项启用。TLSv1 比 SSLv3 的开销更大,因此在与本地服务器通信时禁用它通常是有意义的。此选项也可用于全局语句 "ssl-default-server-options"。请改用 "ssl-min-ver" 和 "ssl-max-ver"。支持 default-server:否
可用于以下上下文:tcp、http、log、peers、ring 当使用 SSL 与服务器通信时,此选项禁用对 TLSv1.2 的支持。请注意,SSLv2 在代码中已被禁用,无法使用任何配置选项启用。TLSv1 比 SSLv3 的开销更大,因此在与本地服务器通信时禁用它通常是有意义的。此选项也可用于全局语句 "ssl-default-server-options"。请改用 "ssl-min-ver" 和 "ssl-max-ver"。支持 default-server:否
可用于以下上下文:tcp、http、log、peers、ring 当使用 SSL 与服务器通信时,此选项禁用对 TLSv1.3 的支持。请注意,SSLv2 在代码中已被禁用,无法使用任何配置选项启用。TLSv1 比 SSLv3 的开销更大,因此在与本地服务器通信时禁用它通常是有意义的。此选项也可用于全局语句 "ssl-default-server-options"。请改用 "ssl-min-ver" 和 "ssl-max-ver"。支持 default-server:否
可用于以下上下文:tcp、http、log、peers、ring 此选项可用作 "server" 设置,用于重置任何从 "default-server" 指令继承而来的 "verifyhost" 设置的默认值。它也可用作 "default-server" 设置,用于重置任何先前的 "default-server" "verifyhost" 设置。
可用于以下上下文:tcp、http、log、peers、ring 此选项可用作 "server" 设置,用于重置任何从 "default-server" 指令继承而来的 "tfo" 设置的默认值。它也可用作 "default-server" 设置,用于重置任何先前的 "default-server" "tfo" 设置。
可在以下上下文中使用:tcp、http 从不将分配给此服务器的连接添加到粘性表中。这可以与备份结合使用,以确保对备份服务器禁用粘性表持久性。
可在以下上下文中使用:tcp、http 这将启用 NPN TLS 扩展,并通告指定的协议列表作为 NPN 之上支持的协议。协议列表由一个逗号分隔的协议名称列表组成,例如:“http/1.1,http/1.0”(不带引号)。这要求 SSL 库在构建时启用了对 TLS 扩展的支持(请使用 haproxy -vv 进行检查)。请注意,NPN 扩展已被 ALPN 扩展取代(参见“alpn”关键字),但后者仅从 OpenSSL 1.0.2 开始可用。可在以下上下文中使用:tcp, http。此选项启用基于观察与服务器通信的健康状况调整。默认情况下此功能是禁用的,启用它也需要启用健康检查。支持两种模式:“layer4” 和 “layer7”。在 layer4 模式下,只有成功/不成功的 TCP 连接是重要的。在 layer7 模式下(仅允许用于 http 代理),将验证从服务器收到的响应,例如有效/错误的 http 状态码、无法解析的标头、超时等。有效的状态码包括 100 到 499、501 和 505。另请参阅 “check”、“on-error” 和 “error-limit”。
可在以下上下文中使用: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”)记录。动作默认是禁用的。
可在以下上下文中使用:tcp, http, log。修改当服务器被标记为 up 时发生的操作。目前有一个可用动作: - shutdown-backup-sessions:关闭所有备份服务器上的流。仅当服务器不处于备份状态且未被禁用(其有效权重 > 0)时才会执行此操作。在处理长会话(例如 LDAP、SQL 等)时,有时可以使用此功能强制活动服务器在恢复后重新接管所有流量。这样做可能比它试图解决的问题带来更多麻烦(例如,不完整的事务),因此请极其谨慎地使用此功能。因服务器恢复而终止的流将以 'U' 终止代码(表示“Up”)记录。动作默认是禁用的。
可在以下上下文中使用:http。当建立后端连接时,会评估此表达式以生成连接名称。此名称是空闲服务器池中连接的关键属性之一。请参阅 “http-reuse” 关键字。当请求查找现有空闲连接时,会评估此表达式以匹配相同的连接。在后端连接使用 SSL SNI 的上下文中,连接名称会自动分配给 “sni” 表达式的结果。这适用于最常见的用法。对于更高级的设置,可以使用 “pool-conn-name” 来覆盖此设置。
可用于以下上下文:http 设置服务器空闲连接数的低阈值,低于此阈值时,线程不会尝试从其他线程窃取连接。这对于涉及许多非常快的服务器的场景中改善 CPU 使用模式非常有用,以确保所有线程始终保持少量空闲连接,而不是让它们在某个线程上累积并从线程迁移到线程。对于亚毫秒级响应时间,两倍于线程数的典型值已经显示出非常好的性能。默认值为零,表示任何空闲连接都可以在任何时候使用。这是正常使用的推荐设置。这仅适用于根据与 "http-reuse" 相同的原则可以共享的连接。如果通过 "tune.idle-pool.shared" 禁用线程之间的连接共享,则使用此设置来确保每个线程始终拥有少量连接可能非常重要,否则连接重用率会随着线程数的增加而降低。
可在以下上下文中使用:http。设置服务器的空闲连接最大数量。-1 表示无限连接,0 表示没有空闲连接。默认值为 -1。当启用空闲连接时,不再属于任何客户端会话的孤立空闲连接将被移动到一个专用池中,以便未来的客户端可以使用它们。这仅适用于可以根据与 “http-reuse” 相同的原则共享的连接。
可在以下上下文中使用:http。设置开始清除空闲连接的延迟。每个 <delay> 间隔,一半的空闲连接将被关闭。0 表示我们不保留任何空闲连接。默认值为 5 秒。
可在以下上下文中使用:tcp, http, log。使用 “port” 参数,可以使用不同的端口来发送健康检查或探测代理检查(agent-check)。在某些服务器上,可能希望将一个端口专用于能够执行比应用程序更适合健康检查的复杂测试的特定组件。例如,在 inetd 中运行一个简单的脚本是很常见的。如果未设置 “check” 参数,则此参数将被忽略。另请参阅 “addr” 参数。
可用于以下上下文: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 流。
可用于以下上下文: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
可在以下上下文中使用:tcp, http, log。“rise” 参数指出,一个服务器在连续 <count> 次成功的健康检查后将被视为可操作。如果未指定,此值默认为 2。另请参阅 “check”、“inter” 和 “fall” 参数。
可用于以下上下文:tcp、http、log 与此服务器相关的 DNS 解析应用选项的逗号分隔列表。可用选项:* allow-dup-ip 默认情况下,当 DNS 运行时解析运行时,HAProxy 会阻止后端中 IP 地址重复。话虽如此,对于某些情况,两个服务器(在同一个后端中,由同一个 FQDN 解析)具有相同的 IP 地址是有意义的。对于这种情况,只需启用此选项即可。这与 prevent-dup-ip 相反。* ignore-weight 忽略 SRV 记录中设置的任何权重。当您想使用替代方法(例如使用 "agent-check" 或通过运行时 api)控制权重时,此功能非常有用。* prevent-dup-ip 确保 HAProxy 的默认行为在服务器上强制执行:阻止在同一后端中为服务器重复使用已设置的 IP 地址并共享相同的 fqdn。这与 allow-dup-ip 相反。
backend b_myapp default-server init-addr none resolvers dns server s1 myapp.example.com:80 check resolve-opts allow-dup-ip server s2 myapp.example.com:81 check resolve-opts allow-dup-ip
设置了 allow-dup-ip 选项后:* 如果域名服务器返回单个 IP 地址,则两个服务器都将使用它 * 如果域名服务器返回 2 个 IP 地址,则每个服务器将选择一个不同的地址 默认值:未设置
可用于以下上下文:tcp、http、log 当为服务器启用 DNS 解析并且返回来自不同族的多个 IP 地址时,HAProxy 将优先使用 "resolve-prefer" 参数中提到的族的 IP 地址。可用族:“ipv4” 和 “ipv6” 默认值:ipv6
server s1 app1.domain.com:80 resolvers mydns resolve-prefer ipv6
可在以下上下文中使用:tcp, http, log。此选项优先选择与网络匹配的 IP 地址。这对于云环境优先选择本地 IP 很有用。在某些情况下,云高可用性服务可以在许多不同的数据中心上通过许多 IP 地址进行通告。数据中心之间的延迟不可忽略,因此此补丁允许优先选择本地数据中心。如果没有地址与配置的网络匹配,则会选择另一个地址。
server s1 app1.domain.com:80 resolvers mydns resolve-net 10.0.0.0/8
可在以下上下文中使用:tcp, http, log。指向一个现有的 “resolvers” 部分,以解析当前服务器的主机名。在使用解析器时,通常建议禁用基于 libc 的解析,尽管存在例外情况(参见 第 5.3.1 节)。在任何情况下,使用解析器时明确指定 “init-addr” 是一个好习惯,以免忽略此元素。
server s1 app1.domain.com:80 init-addr last,none check resolvers mydns
另请参阅 第 5.3 节 了解实现细节和需要注意的陷阱。
可用于以下上下文:tcp、http "send-proxy" 参数强制对此服务器建立的任何连接使用 PROXY 协议。PROXY 协议通知另一端传入连接的第 3/4 层地址,以便它可以知道客户端的地址或它访问的公共地址,无论上层协议是什么。对于由 "accept-proxy" 或 "accept-netscaler-cip" 侦听器接受的连接,将使用通告的地址。仅支持 TCPv4 和 TCPv6 地址族。其他族(例如 Unix 套接字)将报告 UNKNOWN 族。使用此选项的服务器可以完全链接到另一个 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。
可用于以下上下文:tcp、http 当使用 "send-proxy-v2" 时,"proxy-v2-options" 参数添加要在 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" 选项。
可用于以下上下文:peers 此参数仅用于 stick-table 与 peers 协议同步的上下文。"shard" 参数标识将接收具有此分片作为分发哈希的密钥的所有 stick-table 更新的对等体。接受的值是从 0 到 "peers" 部分中指定的 "shards" 参数值。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
可在以下上下文中使用:tcp, http, log, peers, ring。此设置仅在构建时包含 OpenSSL 支持时可用。它设置了描述在 TLSv1.2 和 TLSv1.3 握手期间协商的签名算法列表的字符串。字符串的格式在 OpenSSL 手册页的 “man 3 SSL_CTX_set1_sigalgs” 中定义。除非需要与中间设备兼容,否则不建议使用此设置。
可用于以下上下文:tcp、http 服务器的 "slowstart" 参数接受一个以毫秒为单位的值,指示服务器恢复正常运行后需要多长时间才能达到全速运行。与所有其他基于时间的参数一样,它可以以任何其他明确单位 {us、ms、s、m、h、d} 输入。在此期间,速度从 0% 线性增长到 100%。此限制适用于两个参数:- maxconn:服务器接受的连接数将从 1% 增长到由 (minconn,maxconn,fullconn) 定义的通常动态限制的 100%。- weight:当后端使用动态加权算法时,权重从 1% 线性增长到 100%。在这种情况下,权重会在每次健康检查时更新。因此,重要的是 "inter" 参数小于 "slowstart",以最大化步数。slowstart 永远不会在 HAProxy 启动时应用,否则会对正在运行的服务器造成麻烦。它仅在服务器先前被视为失败时应用。
可用于以下上下文:tcp、http、log、peers、ring "sni" 参数评估样本获取表达式,将其转换为字符串,并将结果用作发送到服务器的 SNI TLS 扩展中的主机名。一个典型的用例是在桥接 TCP/SSL 场景中发送从客户端接收到的 SNI,使用 "ssl_fc_sni" 样本获取表达式。这绝对不能用于 HTTPS,因为 HTTPS 中的 SNI 必须始终与 Host 字段匹配,并且允许客户端在同一连接上使用不同的主机名。如果设置了 "verify required"(这是推荐设置),则结果名称也将与服务器证书的名称匹配。有关更多详细信息,请参阅 "verify" 指令。如果要为健康检查设置 SNI,请参阅 "check-sni" 指令以获取更多详细信息。默认情况下,SNI 分配给 "http-reuse" 的连接名称,除非被 "pool-conn-name" 服务器关键字覆盖。
可用于以下上下文:tcp、http、log、peers、ring "source" 参数设置连接到服务器时将使用的源地址。它遵循与后端 "source" 关键字完全相同的参数和原理,只是它仅适用于引用它的服务器。有关详细信息,请查阅 "source" 关键字。此外,服务器行上的 "source" 语句允许通过指示由破折号 ('-') 分隔的下限和上限来指定源端口范围。某些操作系统可能要求在指定源端口范围时使用有效的 IP 地址。允许多个服务器使用相同的 IP/范围。这样做可以绕过总并发连接数 64k 的最大限制。然后,限制将达到每台服务器 64k 连接。自 Linux 4.2/libc 2.23 以来,对于指定没有端口的源地址的连接,设置了 IP_BIND_ADDRESS_NO_PORT。
可用于以下上下文:tcp、http、log、peers、ring 此选项在传出到服务器的连接上启用 SSL 加密。当使用 SSL 连接到服务器时,使用 "verify" 验证服务器证书至关重要,否则通信容易受到琐碎的中间人攻击,使 SSL 毫无用处。使用此选项时,健康检查也会自动以 SSL 方式发送,除非有 "port" 或 "addr" 指令指示检查应发送到不同的位置。请参阅 "no-ssl" 禁用 "ssl" 选项和 "check-ssl" 选项以强制执行 SSL 健康检查。
可在以下上下文中使用:tcp, http, log, peers, ring。当使用 SSL 与服务器通信时,此选项强制使用 <version> 或更低版本。此选项也可在全局语句 “ssl-default-server-options” 中使用。另请参阅 “ssl-min-ver”。
可在以下上下文中使用: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, log, peers, ring。此选项为与服务器的传出连接启用上游 socks4 隧道。默认情况下,使用此选项不会强制健康检查通过 socks4。您必须使用关键字 “check-via-socks4” 来启用它。
可在以下上下文中使用: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”。
可在以下上下文中使用: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 ticket 机制仅用于 TLS 1.2 及以下版本。除非定期轮换 ticket 密钥(通过重新加载或使用 "tls-ticket-keys"),否则使用 TLS ticket 会损害前向保密性。它也可用作 "default-server" 设置,用于重置任何先前的 "default-server" "no-tls-tickets" 设置。
可用于以下上下文:tcp、http、log、peers、ring 仅当内置了对 OpenSSL 的支持时,此设置才可用。如果设置为 'none',则不验证服务器证书。在另一种情况下,在检查证书的主题和 subjectAlternateNames 属性中提供的名称是否与使用 "sni" 指令传递的名称匹配,或者在未提供的情况下是否与使用 "verifyhost" 指令传递的静态主机名匹配之后,使用 'ca-file' 中的 CA 和 'crl-file' 中的可选 CRL 验证服务器提供的证书。如果未找到名称,则忽略证书的名称。因此,如果没有 SNI,使用 "verifyhost" 非常重要。如果验证失败,握手将中止。当使用 SSL 连接到服务器时,验证服务器证书至关重要,否则通信容易受到琐碎的中间人攻击,使 SSL 完全无用。除非 "ssl_server_verify" 出现在全局部分中,否则 "verify" 默认设置为 "required"。
可用于以下上下文:tcp、http、log、peers、ring 仅当内置了对 OpenSSL 的支持时,此设置才可用,并且仅在同时指定了 'verify required' 时才生效。当没有使用 SNI 连接到服务器时,此指令设置一个默认的静态主机名来检查服务器的证书。如果未使用 SNI,这是启用主机名验证的唯一方法。设置此静态主机名后,它也将用于健康检查(健康检查无法提供 SNI 值)。如果证书中的任何主机名与指定的主机名不匹配,则握手将中止。服务器提供的证书中的主机名可能包含通配符。另请参阅 "verify"、"sni" 和 "no-verifyhost" 选项。
可在以下上下文中使用:tcp, http。“weight” 参数用于调整服务器相对于其他服务器的权重。所有服务器将接收与其权重相对于所有权重总和成比例的负载,因此权重越高,负载越高。默认权重为 1,最大值为 256。值为 0 表示服务器不参与负载均衡,但仍接受持久连接。如果使用此参数根据服务器容量分配负载,建议从既可以增长也可以缩小的值开始,例如在 10 到 100 之间,以便为以后的调整留出足够的空间。
可用于以下上下文:http 此选项允许配置中继 websocket 流时使用的协议。当使用不支持 RFC8441 H2 websockets 的 HTTP/2 后端时,这特别有用。默认模式是 "auto"。这将重用与主协议相同的协议。唯一的区别是在使用 ALPN 时。在这种情况下,如果配置的服务器 ALPN 包含 "http/1.1",它可以尝试将 ALPN 降级为 "http/1.1",仅用于 websocket 流。值 "h1" 用于强制 HTTP/1.1 用于 websockets 流,如果为服务器激活了 SSL ALPN,则通过 ALPN。类似地,"h2" 可用于强制 HTTP/2.0 websockets。请谨慎使用此值:服务器必须支持 RFC8441,否则 haproxy 在中继 websockets 时将报告错误。请注意,NPN 未被考虑在内,因为它的使用已被弃用,取而代之的是 ALPN 扩展。另请参阅 "alpn" 和 "proto"。
HAProxy 允许在服务器行上使用主机名,通过域名服务器检索其 IP 地址。默认情况下,HAProxy 在解析配置文件时、启动时解析名称,并为进程的生命周期缓存结果。在某些情况下,这并不足够,例如在亚马逊中,服务器的 IP 可能会在重启后更改,或者 ELB 虚拟 IP 可能会根据当前工作负载而更改。本章描述了如何配置 HAProxy 以在运行时处理服务器的名称解析。无论是否启用了运行时服务器名称解析,默认情况下 HAProxy 将在启动时通过 libc 在配置解析期间进行第一次解析,除非被 “init-addr” 参数禁用。
正如我们在引言中看到的,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"。
此部分专门用于 HAProxy 中与名称解析相关的主机信息。可以根据需要有任意数量的解析器部分。每个部分可以包含许多名称服务器。在启动时,如果没有在配置中命名此部分,HAProxy 会尝试生成一个名为 "default" 的解析器部分。此部分默认由 httpclient 使用,并使用 parse-resolv-conf 关键字。如果 HAProxy 自动生成此部分失败,则不会发出错误或警告。当解析器部分中配置了多个名称服务器时,HAProxy 使用第一个有效的响应。如果响应无效,则仅处理最后一个响应。目的是给较慢的服务器一个机会在快速故障或过时的服务器之后提供有效的答案。当每个服务器返回不同的错误类型时,HAProxy 仅使用最后一个错误。以下处理应用于此错误:1. HAProxy 使用新的查询类型重试相同的 DNS 查询。A 查询切换到 AAAA 或相反。SRV 查询不在此处涉及。超时错误也排除在外。2. 完成(或不适用)查询类型的回退后,HAProxy 使用首选查询类型重试原始 DNS 查询。3. HAProxy 重试前述步骤 <resolve_retries> 次。如果在此之后没有收到有效响应,它将停止 DNS 解析并报告错误。例如,在解析器部分中配置了 2 个名称服务器时,可能出现以下场景:- 第一个响应有效并直接应用,第二个响应被忽略- 第一个响应无效,第二个响应有效,则应用第二个响应- 第一个响应是 NX 域,第二个响应被截断,则 HAProxy 使用新类型重试查询- 第一个响应是 NX 域,第二个响应是超时,则 HAProxy 使用新类型重试查询- 两个名称服务器的查询都超时,则 HAProxy 使用相同的查询类型重试查询由于 DNS 服务器可能不会在一个 DNS 请求中回答所有 IP,HAProxy 会保留以前答案的缓存,如果 <hold obsolete> 秒内未返回 IP,则答案将被视为过时。
创建一个新的名为 <resolvers id> 的域名服务器列表。resolvers 部分接受以下参数:
定义 HAProxy 接受并向此 resolvers 部分中配置的所有域名服务器通告的最大有效负载大小。<nb> 以字节为单位。如果未设置,HAProxy 通告 512。(RFC 6891 定义的最小值)注意:允许的最大值为 65535。UDP 的推荐值为 4096,不建议超过 8192,除非您确定您的系统和网络可以处理此大小(超过 65507 没有意义,因为这是 UDP 的最大有效负载大小)。如果您只使用 TCP 域名服务器来处理巨大的 DNS 响应,您应该将此值设置为最大值:65535。
用于配置名称服务器。名称服务器的 <name> 应该是唯一的。默认情况下,<address> 被视为数据报类型。这意味着如果配置了 IPv4 或 IPv6 而没有特殊地址前缀(第 11 段),将使用 UDP 协议。如果使用了流协议地址前缀,则名称服务器将被视为流服务器(例如 TCP),并且将考虑第 5.2 段中与 DNS 解析相关的 "server" 参数。注意:目前,在 TCP 模式下,4 个查询在同一连接上进行流水线处理。每 5 秒移除一批空闲连接。可以配置 "maxconn" 来限制这些并发连接的数量,并且如果服务器支持,TLS 也应该可用。
将 /etc/resolv.conf 中找到的所有域名服务器添加到此 resolvers 域名服务器列表中。顺序如同 /etc/resolv.conf 中的每个域名服务器被单独放置在此指令的位置。
收到 DNS 响应 <status> 后,确定服务器的状态是否应从 UP 更改为 DOWN。为了做出该决定,它会检查在过去 <period> 内是否收到了任何有效状态,以抵消刚刚收到的无效状态。<status>:上次名称解析状态。nx 收到 NXDOMAIN 状态后,在结束期间检查是否有任何有效状态。refused 收到 REFUSED 状态后,在结束期间检查是否有任何有效状态。timeout 在 "timeout retry" 命中后,在结束期间检查是否有任何有效状态。other 收到任何其他无效状态后,在结束期间检查是否有任何有效状态。valid 仅适用于 "http-request do-resolve" 和 "tcp-request content do-resolve" 操作。它定义了服务器在触发另一次解析之前将保持有效响应的期限。它不影响服务器的动态解析。obsolete 定义在收到更新的答案记录后等待多长时间才移除过时的 DNS 记录。它适用于 SRV 记录。<period>:在过去的一段时间内必须收到有效响应的时长。它遵循 HAProxy 时间格式,默认以毫秒为单位。对于依赖动态 DNS 解析来确定其 IP 地址的服务器,接收无效 DNS 响应(例如 NXDOMAIN)将导致服务器状态从 UP 更改为 DOWN。hold 指令定义了要回溯多远以查找有效响应。如果在 <period> 内收到了有效响应,则刚刚收到的无效状态将被忽略。除非在结束期间收到了有效响应,否则服务器将被标记为 DOWN。例如,如果设置了 "hold nx 30s",并且最后收到的 DNS 响应是 NXDOMAIN,则除非在最后 30 秒内收到了有效响应,否则服务器将被标记为 DOWN。一旦从 DNS 服务器收到有效状态,处于 DOWN 状态的服务器将立即标记为 UP。对于 "hold valid" 和 "hold obsolete",存在单独的行为。默认值是 "valid" 10s,"obsolete" 0s,其他 30s。
定义在放弃之前为解析服务器名称而发送的查询次数 <nb>。默认值:3。当名称服务器超时或完整的 DNS 查询类型故障转移序列结束并且我们需要从默认的 ANY 查询类型重新开始时,会发生重试。
定义与名称解析相关的超时。<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>”。
在以下情况下,缓存不会存储也不会提供对象:- 如果响应不是 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 标头
要设置缓存,您必须定义一个 cache 部分,并在代理中使用相应的 http-request 和 http-response 动作来使用它。
声明一个缓存部分,分配一个名为 <name> 的共享缓存内存,缓存大小是强制性的。
以兆字节为单位定义缓存的 RAM 大小。此大小被分成 1kB 的块,供缓存条目使用。其最大值为 4095。
定义要缓存的对象最大大小。不得大于 “total-max-size” 的一半。如果未设置,则等于缓存大小的 256 分之一。所有大小大于 “max-object-size” 的对象将不会被缓存。
定义最大过期持续时间。过期时间设置为 Cache-Control 响应标头中的 s-maxage 或 max-age(按此顺序)指令与此值之间的最小值。默认值为 60 秒,这意味着默认情况下您不能缓存超过 60 秒的对象。
启用或禁用对 Vary 标头的处理。禁用时,包含此类标头的响应将永远不会被缓存。启用时,我们需要对所有传入请求的请求标头子集计算一个初步哈希(这可能会带来 cpu 成本),该哈希将用于为给定请求构建一个二级键(参见 RFC 7234#4.1)。目前,二级键是根据 'accept-encoding'、'referer' 和 'origin' 标头的内容构建的。默认值为 off(禁用)。
定义缓存中具有相同主键的同时二级条目的最大数量。这需要启用 vary 支持。其默认值为 10,应传递一个严格的正整数。
使用缓存的代理部分将需要在 “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 能够从请求或响应流、客户端或服务器信息、表、环境信息等中提取数据……提取此类数据的操作称为获取样本。一旦检索到,这些样本可用于各种目的,例如作为粘滞表的键,但最常见的用法是将其与称为模式的预定义常量数据进行匹配。
访问控制列表(ACL)的使用提供了一种灵活的解决方案,可以执行内容切换,并且通常根据从请求、响应或任何环境状态中提取的内容做出决策。原理很简单:- 从流、表或环境中提取数据样本- 可选地对提取的样本应用一些格式转换- 对此样本应用一种或多种模式匹配方法- 仅当模式匹配样本时才执行操作操作通常包括阻止请求、选择后端或添加标头。为了定义测试,使用了 "acl" 关键字。语法是:acl <aclname> <criterion> [flags] [operator] [<value>] ...这将创建新的 ACL <aclname> 或使用新的测试完成现有 ACL。这些测试应用于 <criterion> 中指定的请求/响应部分,并且可以使用可选标志 [flags] 进行调整。某些条件还支持一个运算符,该运算符可以在值集之前指定。可选地,一些转换运算符可以应用于样本,它们将指定为第一个关键字之后的逗号分隔关键字列表。值是条件支持的类型,并用空格分隔。ACL 名称必须由大小写字母、数字、'-'(破折号)、'_'(下划线)、'.'(点)和 ':'(冒号)组成。ACL 名称区分大小写,这意味着 "my_acl" 和 "My_Acl" 是两个不同的 ACL。ACL 数量没有强制限制。未使用的 ACL 不会影响性能,它们只会消耗少量内存。条件通常是样本获取方法的名称,或者是其 ACL 特定变体之一。默认测试方法由该样本获取方法的输出类型暗示。ACL 变体可以描述同一样本获取方法的替代匹配方法。样本获取方法是唯一支持转换的方法。样本获取方法返回的数据可以是以下类型:- boolean- integer(有符号或无符号)- IPv4 或 IPv6 地址- string- data block转换器将这些数据中的任何一种转换为这些数据中的任何一种。例如,某些转换器可能将字符串转换为小写字符串,而其他转换器可能将字符串转换为 IPv4 地址,或将子网掩码应用于 IP 地址。结果样本的类型是应用于列表的最后一个转换器的类型,默认为样本获取方法的类型。每个样本或转换器都返回特定类型的数据,其关键字在此文档中指定。当使用标准样本获取方法声明 ACL 时,某些类型会自动涉及默认匹配方法,这些方法总结在下表中:+---------------------+-----------------+ | 样本或转换器 | 默认 | | 输出类型 | 匹配方法 | +---------------------+-----------------+ | boolean | bool | +---------------------+-----------------+ | integer | int | +---------------------+-----------------+ | ip | ip | +---------------------+-----------------+ | string | str | +---------------------+-----------------+ | binary | none,使用 "-m" | +---------------------+-----------------+请注意,为了匹配二进制样本,必须指定匹配方法,请参阅下文。ACL 引擎可以将这些类型与以下类型的模式匹配:- boolean- integer 或 integer 范围- IP 地址 / 网络- string(精确、子字符串、后缀、前缀、子目录、域)- regular expression- hex block目前支持以下 ACL 标志:-i:匹配后续所有模式时忽略大小写。-f:从列表中加载模式。-m:使用特定的模式匹配方法-n:禁止 DNS 解析-M:像 map 一样加载 -f 指向的文件。-u:强制 ACL 的唯一 ID--:强制结束标志。当字符串看起来像其中一个标志时很有用。"-f" 标志后跟的名称必须遵循 2.7 中描述的 map 和 ACL 名称格式。甚至可以传递多个 "-f" 参数,如果模式要从多个列表中加载。如果引用了现有文件,所有行都将作为单个值读取。空行以及以 sharp ('#') 开头的行将被忽略。所有前导空格和制表符都将被剥离。如果绝对需要插入以 sharp 开头的有效模式,只需在其前面加上一个空格,这样它就不会被视为注释。根据数据类型和匹配方法,HAProxy 可能会将行加载到二叉树中,从而实现非常快速的查找。这对于 IPv4 和精确字符串匹配是正确的。在这种情况下,重复项将自动删除。"-M" 标志允许 ACL 使用 map。如果设置了此标志,则列表将解析为两列条目。第一列包含 ACL 使用的模式,第二列包含样本。样本稍后可由 map 使用。在某些罕见情况下,ACL 仅用于检查 map 中是否存在模式,然后才应用映射时,这很有用。"-u" 标志强制 ACL 的唯一 ID。此唯一 ID 用于套接字接口,用于识别 ACL 并动态更改其值。请注意,即使设置了 ID,文件也始终由其名称标识。另请注意,"-i" 标志适用于后续条目,而不适用于在其之前从文件加载的条目。例如:acl valid-ua hdr(user-agent) -f exact-ua.lst -i -f generic-ua.lst test在此示例中,"exact-ua.lst" 中的每一行将与请求的 "user-agent" 标头进行精确匹配。然后,"generic-ua" 中的每一行将不区分大小写地匹配。然后,“test”一词也将不区分大小写地匹配。"-m" 标志用于在输入样本上选择特定的模式匹配方法。所有 ACL 特定条件都暗示了一种模式匹配方法,通常不需要此标志。但是,此标志对于通用样本获取方法很有用,用于描述它们将如何与模式匹配。对于返回数据类型(例如 string 或 binary)没有明显匹配方法的样本获取,这是必需的。当指定 "-m" 并且后跟模式匹配方法名称时,此方法用于代替条件的默认方法。这使得可以以最初未计划的方式匹配内容,或者使用返回字符串的样本获取方法。匹配方法也会影响模式的解析方式。"-n" 标志禁止 DNS 解析。它与加载 ip 文件一起使用。默认情况下,如果解析器无法解析 ip 地址,它会认为解析后的字符串可能是域名并尝试 DNS 解析。标志 "-n" 禁用此解析。它对于检测格式错误的 ip 列表很有用。请注意,如果 DNS 服务器不可访问,HAProxy 配置解析可能需要数分钟等待超时。在此期间不会显示任何错误消息。标志 "-n" 禁用此行为。另请注意,在运行时,此功能对于动态 ACL 修改是禁用的。但是有一些限制。并非所有方法都可以与所有样本获取方法一起使用。此外,如果 "-m" 与 "-f" 一起使用,则必须先放置它。模式匹配方法必须是以下之一:- "found":仅检查是否可以在流中找到请求的样本,但不将其与任何模式进行比较。建议不要传递任何模式以避免混淆。此匹配方法特别适用于检测某些内容(例如标头、cookie 等)的存在,即使它们为空,也不将其与任何内容进行比较或计数。- "bool":将值作为布尔值进行检查。它只能应用于返回布尔值或整数值的获取,并且不带模式。值为零或 false 不匹配,所有其他值匹配。- "int":将值作为整数匹配。它可以与整数和布尔样本一起使用。布尔 false 是整数 0,true 是整数 1。- "ip":将值作为 IPv4 或 IPv6 地址匹配。它仅与 IP 地址样本兼容,因此它是隐含的,不需要。- "bin":将内容与代表二进制序列的十六进制字符串匹配。这可用于二进制或字符串样本。- "len":将样本的长度作为整数匹配。这可用于二进制或字符串样本。- "str":精确匹配:将内容与字符串匹配。这可用于二进制或字符串样本。- "sub":子字符串匹配:检查内容是否包含至少一个提供的字符串模式。这可用于二进制或字符串样本。- "reg":正则表达式匹配:将内容与正则表达式列表匹配。这可用于二进制或字符串样本。- "beg":前缀匹配:将模式与提取的字符串开头进行比较,如果其中任何一个匹配,则 ACL 匹配。这可用于二进制或字符串样本。- "end":后缀匹配:将模式与提取的字符串末尾进行比较,如果其中任何一个匹配,则 ACL 匹配。这可用于二进制或字符串样本。- "dir":子目录匹配:检查内容的斜杠分隔部分是否与提供的字符串模式之一精确匹配。这可用于二进制或字符串样本。因此,字符串 "/images/png/logo/32x32.png" 将匹配 "/images"、"/images/png"、"images/png"、"/png/logo"、"logo/32x32.png" 或 "32x32.png",但不匹配 "png" 或 "32x32"。- "dom":域匹配:检查内容的点分隔部分是否与提供的字符串模式之一精确匹配。这可用于二进制或字符串样本。这是用于 URL 的。模式中的前导和尾随分隔符将被忽略。如果其中任何一个匹配,则 ACL 匹配。因此,在示例字符串 "http://www1.dc-eu.example.com:80/blah" 中,模式 "http"、"www1"、".www1"、"dc-eu"、"example"、"com"、"80"、"dc-eu.example"、"blah"、":www1:"、"dc-eu.example:80" 将匹配,但不匹配 "eu" 或 "dc"。使用它来匹配域后缀进行过滤或路由通常不是一个好主意,因为路由很容易被通过在另一个域前面加上匹配前缀来欺骗。字符串匹配适用于按原样传递的逐字字符串,但反斜杠 ("\") 除外,它使得可以转义某些字符(例如空格)。如果在第一个字符串之前传递了 "-i" 标志,则将执行不区分大小写的匹配。为了匹配字符串 "-i",请将其设置为第二个,或在第一个字符串之前传递 "--" 标志。当然,匹配字符串 "--" 也适用。请勿将字符串匹配用于可能包含空字节 (0x00) 的二进制获取,因为比较会在第一个空字节出现时停止。相反,首先使用 hex 转换器将二进制获取转换为十六进制字符串。所有 ACL 特定条件都暗示了默认匹配方法。通常,这些条件由原始样本获取方法的名称和匹配方法串联组成。例如,"hdr_beg" 将 "beg" 匹配应用于使用 "hdr" 获取方法检索的样本。此匹配方法仅在关键字单独使用时可用,不带任何转换器。如果在此类 ACL 关键字之后应用任何此类转换器,则 ACL 关键字的默认匹配方法将被忽略,因为匹配重要的是最后一个转换器的输出类型。由于所有 ACL 特定条件都依赖于样本获取方法,因此始终可以使用原始样本获取方法和使用 "-m" 的显式匹配方法。如果使用 "-m" 在 ACL 特定条件上指定了替代匹配,则匹配方法仅应用于基础样本获取方法。例如,下面的所有 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" 即可工作时,用尖括号 ">" 和 "<" 括起来。+-------------------------------------------------+ | 输入样本类型 | +----------------------+---------+---------+---------+---------+---------+ | 模式类型 | boolean | integer | ip | string | binary | +----------------------+---------+---------+---------+---------+---------+ | none(仅存在) | found | found | found | found | found | +----------------------+---------+---------+---------+---------+---------+ | none(布尔值) |> bool <| bool | | bool | | +----------------------+---------+---------+---------+---------+---------+ | integer(值) | int |> int <| int | int | | +----------------------+---------+---------+---------+---------+---------+ | integer(长度) | len | len | len | len | len | +----------------------+---------+---------+---------+---------+---------+ | IP 地址 | | |> ip <| ip | ip | +----------------------+---------+---------+---------+---------+---------+ | exact string | str | str | str |> str <| str | +----------------------+---------+---------+---------+---------+---------+ | prefix | beg | beg | beg | beg | beg | +----------------------+---------+---------+---------+---------+---------+ | suffix | end | end | end | end | end | +----------------------+---------+---------+---------+---------+---------+ | substring | sub | sub | sub | sub | sub | +----------------------+---------+---------+---------+---------+---------+ | subdir | dir | dir | dir | dir | dir | +----------------------+---------+---------+---------+---------+---------+ | domain | dom | dom | dom | dom | dom | +----------------------+---------+---------+---------+---------+---------+ | regex | reg | reg | reg | reg | reg | +----------------------+---------+---------+---------+---------+---------+ | hex block | | | | bin | bin | +----------------------+---------+---------+---------+---------+---------+
为了匹配布尔值,不需要任何值,所有值都会被忽略。布尔匹配默认用于所有类型为“boolean”的获取方法。当使用布尔匹配时,获取的值会按原样返回,这意味着布尔值“true”将始终匹配,而布尔值“false”将永远不匹配。布尔匹配也可以通过在返回整数值的获取方法上使用“-m bool”来强制执行。然后,整数值 0 会被转换为布尔值“false”,所有其他值都会被转换为“true”。
整数匹配默认应用于整数获取方法。也可以使用 "-m int" 在布尔获取上强制执行它。在这种情况下,"false" 转换为整数 0,"true" 转换为整数 1。整数匹配还支持整数范围和运算符。请注意,整数匹配仅适用于正值。范围是用冒号分隔的下限和上限表示的值,两者都可以省略。例如,"1024:65535" 是表示非特权端口范围的有效范围,"1024:" 也可以使用。"0:1023" 是特权端口的有效表示,":1023" 也可以使用。作为特殊情况,某些 ACL 函数支持小数点数字,这实际上是用点分隔的两个整数。这用于某些版本检查。所有整数属性都适用于这些小数点数字,包括范围和运算符。为了更方便使用,还支持比较运算符。请注意,将运算符与范围一起使用没有多大意义,强烈不鼓励这样做。同样,对一组值执行顺序比较没有多大意义。整数匹配的可用运算符是:eq:如果测试值等于至少一个值,则为 truege:如果测试值大于或等于至少一个值,则为 truegt:如果测试值大于至少一个值,则为 truele:如果测试值小于或等于至少一个值,则为 truelt:如果测试值小于至少一个值,则为 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
字符串匹配适用于字符串或二进制获取方法,并存在 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) 的二进制获取,因为比较会在第一个空字节出现时停止。相反,首先使用 hex 转换器将二进制获取转换为十六进制字符串。# 如果字符串 <tag> 存在于二进制样本中,则匹配 acl tag_found req.payload(0,0),hex -m sub 3C7461673E
与字符串匹配一样,正则表达式匹配也适用于按字面传递的字符串,但反斜杠("\")除外,它使得可以转义某些字符,如空格。如果在第一个正则表达式之前传递了“-i”标志,则匹配将忽略大小写。为了匹配字符串“-i”,要么将其放在第二个位置,要么在第一个正则表达式之前传递“--”标志。当然,匹配字符串“--”也适用相同的原则。
可以将一些提取的样本与一个可能无法安全地表示为字符串的二进制块进行匹配。为此,当匹配方法设置为二进制时,模式必须以偶数个十六进制数字的形式传递。每两个数字的序列将代表一个字节。十六进制数字可以使用大写或小写。
# 在输入流中匹配 "Hello\n" (\x48 \x65 \x6c \x6c \x6f \x0a) acl hello req.payload(0,6) -m bin 48656c6c6f0a
IPv4 地址值可以指定为纯地址或附加网络掩码,在这种情况下,只要 IPv4 地址在网络内,它就匹配。纯地址也可以替换为可解析的主机名,但通常不鼓励这种做法,因为它使配置更难阅读和调试。如果使用主机名,您至少应确保它们存在于 /etc/hosts 中,这样配置就不会依赖于解析配置时任何随机 DNS 匹配。点分 IPv4 地址表示法支持常规形式以及省略所有 0 字节的缩写形式: +------------------+------------------+------------------+ | 示例 1 | 示例 2 | 示例 3 | +------------------+------------------+------------------+ | 192.168.0.1 | 10.0.0.12 | 127.0.0.1 | | 192.168.1 | 10.12 | 127.1 | | 192.168.0.1/22 | 10.0.0.12/8 | 127.0.0.1/8 | | 192.168.1/22 | 10.12/8 | 127.1/8 | +------------------+------------------+------------------+ 请注意,这与 RFC 4632 CIDR 地址表示法不同,后者中 192.168.42/24 等同于 192.168.42.0/24。IPv6 可以按其常用形式输入,无论是否附加网络掩码。IPv6 网络掩码只接受位计数。为了避免随机解析 IP 地址带来的任何麻烦风险,IPv6 模式中绝不允许使用主机名。HAProxy 还能在以下情况下将 IPv4 地址与 IPv6 地址匹配: - 被测地址是 IPv4,模式地址是 IPv4,匹配适用于 IPv4,使用提供的掩码(如果有)。 - 被测地址是 IPv6,模式地址是 IPv6,匹配适用于 IPv6,使用提供的掩码(如果有)。 - 被测地址是 IPv6,模式地址是 IPv4,如果 IPv6 地址与 2002:IPV4::、::IPV4 或 ::ffff:IPV4 匹配,则匹配适用于 IPv4,使用模式的掩码,否则失败。 - 被测地址是 IPv4,模式地址是 IPv6,IPv4 地址首先通过在其前面加上 ::ffff: 转换为 IPv6,然后匹配适用于 IPv6,使用提供的 IPv6 掩码。
有些操作只在有效条件下执行。条件是 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 节。
从历史上看,样本获取方法仅用于检索数据以与使用 ACL 的模式进行匹配。随着 stick-tables 的出现,创建了一类新的样本获取方法,它们通常与其 ACL 对应项共享相同的语法。这些样本获取方法也称为 "fetches"。截至目前,ACL 和 fetches 已经融合。所有 ACL 获取方法都已作为获取方法提供,ACL 也可以使用任何样本获取方法。本节详细介绍了所有可用的样本获取方法及其输出类型。一些样本获取方法具有已弃用的别名,用于保持与现有配置的兼容性。它们被明确标记为已弃用,不应在新设置中使用。如果可用,还会指示 ACL 派生词及其各自的匹配方法。这些都具有明确定义的默认模式匹配方法,因此无需(尽管允许)传递 "-m" 选项来指示如何使用 ACL 匹配样本。如上所示的样本类型与匹配兼容性矩阵所示,在 ACL 中使用通用样本获取方法时,除非样本类型是布尔值、整数、IPv4 或 IPv6 之一,否则 "-m" 选项是强制性的。当相同的关键字作为 ACL 关键字和标准获取方法存在时,ACL 引擎将默认自动选择仅 ACL 的关键字。其中一些关键字支持一个或多个必需参数,以及一个或多个可选参数。这些参数是强类型的,并在解析配置时进行检查,因此没有运行不正确参数的风险(例如,未解析的后端名称)。获取函数参数在括号之间传递,并用逗号分隔。当参数是可选的时,将在下面用方括号 ('[ ]') 指示。当所有参数都是可选时,可以省略括号。因此,标准样本获取方法的语法是以下之一: - name - name(arg1) - name(arg1,arg2)样本获取方法可以与转换器结合使用,以应用于获取的样本之上(也称为 "converters")。这些组合形成了所谓的 "样本表达式",结果是一个 "样本"。最初这仅受 "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 的情况下报告匹配。支持以下关键字
以下是转换器关键字的详细列表
以字符串形式返回所请求属性的值,值之间由“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)]
将 <value> 添加到类型为有符号整数的输入值中,并以有符号整数形式返回结果。<value> 可以是数值或变量名。有关变量的详细信息,请参见第 2.8 节。
在当前样本之后连接最少 2 个最多 3 个字段,然后将其转换为字符串。第一个字段 <delim> 是一个常量字符串,如果现有样本不为空且 <var> 或 <suff> 不为空,它将紧跟在现有样本之后附加。第二个字段 <var> 是一个变量名。将查找该变量,将其内容转换为字符串,并将其紧跟在 <delim> 部分之后附加。如果找不到该变量,则不附加任何内容。它是可选的,并且可以选择后跟一个常量字符串 <suff>,但是如果省略 <var>,则 <suff> 是强制性的。此转换器类似于 concat 转换器,可用于构建由一系列其他变量组成的新变量,但主要区别在于它会检查添加分隔符是否有意义,例如,如果当前样本为空,则不会添加分隔符。这种情况将需要使用 concat 转换器的 2 条单独规则,其中第一条规则必须在添加分隔符之前检查当前样本字符串是否为空。如果逗号或右括号需要用作分隔符,则必须用引号或反斜杠保护它们,反斜杠本身也需要保护,以免被第一级解析器剥离(有关引用和转义,请参阅第 2.2 节)。请参阅下面的示例。
http-request set-var(req.tagged) 'var(req.tagged),add_item(",",req.score1,"(site1)") if src,in_table(site1)' http-request set-var(req.tagged) 'var(req.tagged),add_item(",",req.score2,"(site2)") if src,in_table(site2)' http-request set-var(req.tagged) 'var(req.tagged),add_item(",",req.score3,"(site3)") if src,in_table(site3)' http-request set-header x-tagged %[var(req.tagged)] http-request set-var(req.tagged) 'var(req.tagged),add_item(",",req.score1),add_item(",",req.score2)' http-request set-var(req.tagged) 'var(req.tagged),add_item(",",,(site1))' if src,in_table(site1)
根据 <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)]
根据 <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)]
对类型为有符号整数的输入值与 <value> 执行按位“与”操作,并以有符号整数形式返回结果。<value> 可以是数值或变量名。有关变量的详细信息,请参见第 2.8 节。
将 base64 编码的输入字符串转换(解码)为其二进制表示。它执行 base64() 的反向操作。对于 base64url(“URL 和文件名安全字母表”(RFC 4648))变体,请参见“ub64dec”。
将二进制输入样本转换为 base64 字符串。它用于以可靠传输的方式记录或传输二进制内容(例如,SSL ID 可以复制到标头中)。对于 base64url(“URL 和文件名安全字母表”(RFC 4648))变体,请参见“ub64enc”。
将大端二进制输入样本转换为一个字符串,其中每个 <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
将大端二进制输入样本转换为一个十六进制字符串,其中每个输入字节对应两个十六进制数字。它用于以可靠的方式记录或传输某些二进制输入数据的十六进制转储(例如,可以将 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() 结合使用,可用于报告输入值的位测试的真/假(例如,验证标志的存在)。
从输入二进制样本中提取一些字节。结果是一个二进制样本,从原始样本的偏移量(以字节为单位)开始,并可选地在给定的长度处截断。<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> 中的字符串条目,并按原样返回该条目。如果槽不存在,捕获将静默失败。
在当前样本之后连接最多 3 个字段,然后将其转换为字符串。第一个字段 <start> 是一个常量字符串,它将紧跟在现有样本之后附加。如果未使用,可以省略它。第二个字段 <var> 是一个变量名。将查找该变量,将其内容转换为字符串,并将其紧跟在 <first> 部分之后附加。如果找不到该变量,则不附加任何内容。也可以省略它。第三个字段 <end> 是一个常量字符串,它将附加在变量之后。也可以省略它。这些元素共同允许将变量与分隔符连接到现有变量集。这可用于构建由一系列其他变量组成的新变量,例如冒号分隔的值。如果逗号或右括号需要用作分隔符,则必须用引号或反斜杠保护它们,反斜杠本身也需要保护,以免被第一级解析器剥离。这通常用于从其他变量构建复合变量,但有时使用具有多个字段的格式字符串可能更方便。请参阅下面的示例。
tcp-request session set-var(sess.src) src tcp-request session set-var(sess.dn) ssl_c_s_dn tcp-request session set-var(txn.sig) str(),concat(<ip=,sess.ip,>),concat(<dn=,sess.dn,>) tcp-request session set-var(txn.ipport) "str(),concat('addr=(',sess.ip),concat(',',sess.port,')')" tcp-request session set-var-fmt(txn.ipport) "addr=(%[sess.ip],%[sess.port])" ## 功能相同 http-request set-header x-hap-sig %[var(txn.sig)]
获取类型为有符号整数的输入值,应用取反(翻转所有位)并以有符号整数的形式返回结果。
使用 CRC32 哈希函数将二进制输入样本哈希成一个无符号 32 位量。可选地,如果可选的 <avalanche> 参数等于 1,则可以对输出应用完整的雪崩哈希函数。此转换器使用与各种基于哈希的负载均衡算法相同的函数,因此它将提供完全相同的结果。它旨在与其他需要对某些输入键计算 CRC32 的软件兼容,因此它遵循在以太网、Gzip、PNG 等中最常见的实现。它比其他算法慢,但可能提供更好或至少更不可预测的分布。它不得用于安全目的,因为 32 位哈希很容易被破解。另请参见“djb2”、“sdbm”、“wt6”、“crc32c”和“hash-type”指令。
使用 CRC32C 哈希函数将二进制输入样本哈希成一个无符号 32 位量。可选地,如果可选的 <avalanche> 参数等于 1,则可以对输出应用完整的雪崩哈希函数。此转换器使用 RFC4960 附录 B [8] 中描述的相同函数。它旨在与其他需要对某些输入键计算 CRC32C 的软件兼容。它比其他算法慢,并且不得用于安全目的,因为 32 位哈希很容易被破解。另请参见“djb2”、“sdbm”、“wt6”、“crc32”和“hash-type”指令。
在找到的第一个回车符('\r')或换行符('\n')处截断输入样本的字符串表示。仅更新字符串长度。
请求 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
此转换器用作调试工具。它捕获输入样本并将其发送到事件接收器 <destination>,该接收器可以指定一个环形缓冲区,如“buf0”,以及“stdout”或“stderr”。可用的接收器可以在运行时通过在 CLI 上发出“show events”来检查。如果未指定,输出将是“buf0”,可以通过 CLI 的“show events”命令进行查询。可以传递一个可选的前缀 <prefix> 来帮助区分来自多个表达式的输出。然后它将出现在输出消息的冒号之前。输入样本按原样传递到输出,因此将调试转换器插入链中的任何位置都是安全的,即使对于不可打印的样本类型也是如此。
tcp-request connection track-sc0 src,debug(track-sc)
将二进制输入样本转换为消息摘要。结果是一个二进制样本。<algorithm> 必须是一个 OpenSSL 消息摘要名称(例如 sha256)。请注意,此转换器仅在 HAProxy 使用 USE_OPENSSL 编译时可用。
将类型为有符号整数的输入值除以 <value>,并以有符号整数形式返回结果。如果 <value> 为空,则返回最大的无符号整数(通常为 2^63-1)。<value> 可以是数值或变量名。有关变量的详细信息,请参见第 2.8 节。
使用 DJB2 哈希函数将二进制输入样本哈希成一个无符号 32 位量。可选地,如果可选的 <avalanche> 参数等于 1,则可以对输出应用完整的雪崩哈希函数。此转换器使用与各种基于哈希的负载均衡算法相同的函数,因此它将提供完全相同的结果。它主要用于调试,但可以用作粘性表条目来收集粗略统计。它不得用于安全目的,因为 32 位哈希很容易被破解。另请参见“crc32”、“sdbm”、“wt6”、“crc32c”和“hash-type”指令。
如果类型为有符号整数的输入值为偶数,则返回布尔值 TRUE,否则返回 FALSE。它在功能上等同于 "not,and(1),bool"。
从输入字符串中,根据给定的分隔符,从开头(正索引)或结尾(负索引)提取给定索引处的子字符串。索引从 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 复制到标头中)。
将每个输入字节包含两个十六进制数字的十六进制字符串转换为整数。如果输入值无法转换,则返回零。
使用给定的密钥将二进制输入样本转换为消息认证码。结果是一个二进制样本。<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 标头字段、响应中与正偏移量结合使用的 Expires 值,或者当偏移量为负时使用的 Last-Modified 值特别有用。如果指定了单位值,则将时间戳视为“s”(秒,默认行为)、“ms”(毫秒)或“us”(微秒)自纪元以来。偏移量假定与输入时间戳具有相同的单位。
如果输入值为 true,则返回 <true> 字符串。否则返回 <false> 字符串。
http-request set-header x-forwarded-proto %[ssl_fc,iif(https,http)]
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回布尔 false。否则,返回布尔 true。这可用于验证表中是否存在某个键,该表跟踪某些元素(例如,是否已看到源 IP 地址或 Authorization 标头)。
将掩码应用于 IP 地址,并使用结果进行查找和存储。这可用于使某个掩码内的所有主机共享相同的表条目,从而使用相同的服务器。mask4 可以以点分十进制形式(例如 255.255.255.0)或 CIDR 形式(例如 24)传递。mask6 可以以四元组形式(例如 ffff:ffff::)或 CIDR 形式(例如 64)传递。如果未提供 mask6,出于向后兼容的原因,IPv6 地址将转换失败。
转义输入字符串并生成一个可用于 JSON 字符串的 ASCII 输出字符串。转换器尝试根据 <input-code> 参数解码输入字符串。它可以是 "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 类型 string、boolean、number 和 array。浮点数将作为字符串返回。通过指定 output_type 'int',该值将被转换为整数。数组将作为字符串返回,以方括号开头和结尾。内容是 CSV。根据数据类型,数组值可能会被引用。如果数组值是复杂类型,则字符串包含每个值的完整 json 表示,并用逗号分隔。例如,对 JWT 进行角色查询的结果:["manage-account","manage-account-links","view-profile"] 如果无法转换,则 json_query 转换器失败。<json_path> 必须是有效的 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')
当输入为 JSON Web Token (JWT) 时,如果没有提供参数,则返回令牌的已解码头部部分(JWT 的第一个 base64-url 编码部分);否则,对令牌的已解码头部部分执行 json_query 操作。有关接受的 json_path 和 output_type 参数的详细信息,请参见“json_query”转换器。请注意,此转换器仅在 HAProxy 编译时使用了 USE_OPENSSL 时才可用。
当输入为 JSON Web Token (JWT) 时,如果没有提供参数,则返回令牌的已解码负载部分(JWT 的第二个 base64-url 编码部分);否则,对令牌的已解码负载部分执行 json_query 操作。有关接受的 json_path 和 output_type 参数的详细信息,请参见“json_query”转换器。请注意,此转换器仅在 HAProxy 编译时使用了 USE_OPENSSL 时才可用。
通过使用 <alg> 算法和 <key> 参数对输入中的 JSON Web Token (JWT) 执行签名验证,<key> 参数应包含密钥或公钥的路径。公钥应采用 PKCS#1 格式(对于 RSA 密钥,以 BEGIN RSA PUBLIC KEY 开头)或 SPKI 格式(Subject Public Key Info,以 BEGIN PUBLIC KEY 开头)。验证成功返回 1,验证失败返回 0,任何其他错误返回严格负值。由于所有这些非空错误返回值,此转换器的结果不应转换为布尔值。请参阅下面了解可能的返回值完整列表。目前,只能处理使用 Compact Serialization 格式的 JWS 令牌(三个用点分隔的 base64-url 编码字符串)。支持 RFC7518 第 3.1 节中提到的所有算法(HS、ES、RS 和 PS,具有 256、384 或 512 密钥大小,以及特殊的 "none" 情况)。如果使用的算法是 HMAC 家族,<key> 应该是用于 HMAC 签名计算的密钥。否则,<key> 应该是可用于验证令牌签名的公钥路径。用于验证 JWT 的所有公钥必须在初始化期间已知,以便添加到专用缓存中,以便在运行时无需磁盘访问。因此,任何使用的公钥必须在 jwt_verify 调用中至少显式提及一次。因此不建议将中间变量作为第二个参数传递。此转换器仅验证令牌的签名,不执行 RFC7519 第 7.2 节中指定的完整 JWT 验证。我们不确保解码后的标头和有效负载内容是完全有效的 JSON,例如,并且不执行有关其各自内容的检查。可能的返回值如下: +----+----------------------------------------------------------------------+ | ID | message | +----+----------------------------------------------------------------------+ | 0 | "Verification failure" | | 1 | "Verification success" | | -1 | "Unknown algorithm (not mentioned in RFC7518)" | | -2 | "Unmanaged algorithm" | | -3 | "Invalid token" | | -4 | "Out of memory" | | -5 | "Unknown certificate" | +----+----------------------------------------------------------------------+ 请注意,此转换器仅在 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 }
从 "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
获取字符串的长度。这只能放在字符串样本提取函数或返回字符串类型的转换关键字之后。结果是整数类型。
将字符串样本转换为小写。这只能放在字符串样本获取函数之后或返回字符串类型的转换关键字之后。结果类型为字符串。
将一个应包含自纪元以来日期的整数转换为表示该日期的本地时间的字符串,使用 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
从输入样本的字符串表示的开头跳过任何属于 <chars> 的字符。
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 |
|---|---|---|---|---|---|
| str | str | map_str | map_str_int | map_str_ip | map_str_key |
| str | beg | map_beg | map_beg_int | map_end_ip | map_end_key |
| str | sub | map_sub | map_sub_int | map_sub_ip | map_sub_key |
| str | dir | map_dir | map_dir_int | map_dir_ip | map_dir_key |
| str | dom | map_dom | map_dom_int | map_dom_ip | map_dom_key |
| str | end | map_end | map_end_int | map_end_ip | map_end_key |
| str | reg | map_reg | map_reg_int | map_reg_ip | map_reg_key |
| str | reg | map_regm | map_reg_int | map_reg_ip | map_reg_key |
| int | int | map_int | map_int_int | map_int_ip | map_int_key |
| ip | ip | map_ip | map_ip_int | map_ip_ip | map_ip_key |
名为“map_regm”的特殊 map 期望正则表达式中有匹配区域,并通过用相应的匹配文本替换反向引用(如“\1”)来修改输出。输出类型“key”表示将返回匹配条目的键(如在 map 文件中找到的)作为字符串,而不是值。请注意,当使用“key”输出类型时,不支持可选的 <default_value> 参数。<map_name> 引用的文件每行包含一个键 + 值。以'#'开头的行和空行都将被忽略。前导的制表符和空格会被去除。然后,键是第一个“word”(一系列非空格/制表符字符),值是这一系列空格/制表符之后直到行尾的内容,不包括尾随的空格/制表符。
# 这是一条注释,会被忽略 2.22.246.0/23 United Kingdom \n <-><-----------><--><------------><----> | | | | `- 尾随空格被忽略 | | | `---------- 值 | | `-------------------- 中间空格被忽略 | `---------------------------- 键 `------------------------------------ 前导空格被忽略
将有符号整数类型的输入值除以 <value>,并返回余数作为有符号整数。如果 <value> 为 null,则返回零。<value> 可以是数值或变量名。有关变量的详细信息,请参见 第 2.8 节。
返回在 <packettype> 类型的输入 MQTT 有效负载中找到的 <fieldname> 的值。<packettype> 可以是字符串(不区分大小写的匹配)或对应于我们应该从中提取数据的包类型的数值。支持的字符串和整数可以在这里找到: https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718021 https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901022 <fieldname> 取决于 <packettype>,可以是以下任何一个(注意 <fieldname> 匹配不区分大小写)。<property id> 只能在 MQTT v5.0 流中找到。查看此表: https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901029 - CONNECT (或 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 }
此转换器功能类似“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
此转换器功能类似“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
将有符号整数类型的输入值乘以 <value>,并返回乘积作为有符号整数。如果发生溢出,将返回该符号的最大可能值,以防止运算环绕。<value> 可以是数值或变量名。有关变量的详细信息,请参见 第 2.8 节。
接受一个字符串类型的输入值,将其解释为后端名称,并返回该后端中可用服务器的数量。可用于需要从动态名称(如 map 查找的结果)查找后端的地方。
获取类型为有符号整数的输入值,计算其相反值,并以有符号整数的形式返回余数。0 是单位元。此运算符用于反向减法:为了从一个常量中减去输入值,只需执行 "neg,add(value)"。
如果输入的有符号整数值非零,则返回布尔值 FALSE,否则返回 TRUE。与 and() 结合使用,可用于报告输入值的位测试结果是真还是假(例如,验证某个标志是否存在)。
如果类型为有符号整数的输入值为奇数,则返回布尔值 TRUE,否则返回 FALSE。它在功能上等同于 "and(1),bool"。
对 <value> 和输入的有符号整数值执行按位“或”运算,并返回结果作为有符号整数。<value> 可以是数值或变量名。有关变量的详细信息,请参见 第 2.8 节。
这会提取输入字符串中参数 <name> 的第一个出现,其中参数由 <delim> 分隔,<delim> 默认为 "&",参数的名称和值由 "=" 分隔。如果在参数段结束之前没有 "=" 和值,则将其视为等同于空字符串值。这对于从查询字符串或可能是 x-www-form-urlencoded 正文中提取参数很有用。特别是,`query,param(<name>)` 可以用作 `urlp(<name>)` 的替代方案,后者仅使用 "&" 作为分隔符,而 "urlp" 也使用 "?" 和 ";"。请注意,此转换器不会对 URL 编码字符执行任何特殊操作。如果要解码该值,可以在输出上使用 url_dec 转换器。如果输入中的参数名称可能包含编码字符,则在调用 "param" 之前,您可能需要对输入进行规范化。这可以通过使用 "http-request normalize-uri" 来完成,特别是 percent-decode-unreserved 和 percent-to-uppercase 选项。
str(a=b&c=d&a=r),param(a) # b str(a&b=c),param(a) # "" str(a=&b&c=a),param(b) # "" str(a=1;b=2;c=4),param(b,;) # 2 query,param(redirect_uri),urldec()
将包含 Host 标头值的字符串转换为一个整数,方法是返回其端口。输入必须遵循 Host 标头值的格式 (rfc9110#section-7.2)。它将支持以下类型的输入:hostname, hostname:80, 127.0.0.1, 127.0.0.1:80, [::1], [::1]:80。如果输入中未提供端口,它将返回 0。
如果不存在 <field_type>,则以原始模式提取输入二进制样本表示的协议缓冲区消息字段,其中 <field_number> 作为字段编号(点分表示法),如果此字段存在,则作为整数样本(另请参见下面的 "ungrpc")。授权类型的列表如下:"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
对输入字符串执行基于正则表达式的替换。它执行与众所周知的 "sed" 实用程序相同的操作,使用 "s/<regex>/<subst>/"。默认情况下,它将替换输入字符串中匹配正则表达式 <regex> 的最大部分中的第一个匹配项,并替换为替换字符串 <subst>。可以通过在第三个参数 <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)]
从符合 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>
从输入样本的字符串表示的末尾跳过任何属于 <chars> 的字符。
使用 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)
使用输入内容设置变量,如果所有指定的条件都为真(请参阅下面了解可能的条件列表),则将输入样本按原样传递给输出。变量保留该值和关联的输入类型。有关详细信息,请参阅第 2.8 节关于变量的内容。您可以向转换器传递最多四个条件,这些条件来自以下可能的条件: - "ifexists"/"ifnotexists":检查变量在当前 set-var 调用之前是否已存在。变量通常是通过成功的 set-var 调用创建的。请注意,作用域 "proc" 的变量是在配置解析期间创建的,因此 "ifexists" 条件始终为真。 - "ifempty"/"ifnotempty":检查输入是否为空。标量类型永远不为空,因此无论输入内容如何(整数、布尔值、IP 等),ifempty 条件都将为假。 - "ifset"/"ifnotset":检查变量之前是否已设置,或者是否对变量调用了 unset-var。尚未存在的变量被视为未设置。一个 "proc" 变量可以存在但未设置,因为它们是在配置解析期间创建的。 - "ifgt"/"iflt":检查变量的内容是否 "大于" 或 "小于" 输入。此检查只能在输入和变量都是整数类型时执行。否则,检查默认被视为真。
将二进制输入样本转换为 SHA-1 摘要。结果是一个长度为 20 字节的二进制样本。
将二进制输入样本转换为 SHA-2 家族的摘要。结果是一个长度为 <bits>/8 字节的二进制样本。<bits> 的有效值为 224、256、384、512,分别对应 SHA-<bits>。默认值为 256。请注意,此转换器仅在 HAProxy 编译时使用了 USE_OPENSSL 时才可用。
接受字符串类型的输入值,可以是服务器名称或 <backend>/<server> 格式,并返回该服务器上排队流的数量。当需要从动态名称(如 cookie 值,例如 req.cook(SRVID),srv_queue)查找排队流并据此做出决定以打破持久性或将请求定向到其他地方时,可以使用它。
将 <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
从有符号整数类型的输入值中减去 <value>,并返回结果作为有符号整数。注意:为了从一个常量中减去输入值,只需执行 "neg,add(value)"。<value> 可以是数值或变量名。有关变量的详细信息,请参见 第 2.8 节。
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的平均客户端到服务器字节速率,以字节量/周期(在表中配置)衡量。另请参阅 sc_bytes_in_rate 样本获取关键字。
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的平均服务器到客户端字节速率,以字节量/周期(在表中配置)衡量。另请参阅 sc_bytes_out_rate 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回与指定表中输入样本关联的传入连接的累积数量。另请参见 sc_conn_cnt 样本获取关键字。
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的当前并发跟踪连接数。另请参阅 sc_conn_cur 样本获取关键字。
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的平均传入连接速率。另请参阅 sc_conn_rate 样本获取关键字。
使用输入样本在指定表中进行查找。如果在表中找不到键,则转换器将失败,除非设置了 <default_value>:这会使转换器成功并返回 <default_value>。如果找到键,则转换器将返回与指定表中输入样本关联的键过期延迟。另请参见 table_idle 样本获取关键字。
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回与指定表中的输入样本相关联的前端连接故障的累积数量。另请参阅 sc_glitch_cnt 样本获取关键字和 fc_glitches(用于测量当前前端连接上的值)。
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回与指定表中的输入样本相关联的平均前端连接故障率。另请参阅 sc_glitch_rate 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的数组中索引为 <idx> 的通用目的计数器的当前值。<idx> 是介于 0 和 99 之间的整数。如果在此索引处没有存储 GPC,它还将返回布尔值 0。这仅适用于“gpc”数组数据类型(而不适用于旧版“gpc0”或“gpc1”数据类型)。另请参见 sc_get_gpc 样本获取关键字。
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的第一个通用目的计数器的当前值。另请参阅 sc_get_gpc0 样本获取关键字。
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回在表中配置的周期内 gpc0 计数器递增的频率,与指定表中输入样本相关联。另请参阅 sc_get_gpc0_rate 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的第二个通用目的计数器的当前值。另请参见 sc_get_gpc1 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的 gpc1 计数器在表中配置的时间段内增量的频率。另请参见 sc_get_gpc1_rate 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表(stick-table)中与输入样本关联的数组中索引为 <idx> 的全局目的计数器在配置的时间段内增量的频率。<idx> 是介于 0 和 99 之间的整数。如果在此索引处没有存储 gpc_rate,它还将返回布尔值 0。这仅适用于“gpc_rate”数组数据类型(而不适用于旧版“gpc0_rate”或“gpc1_rate”数据类型)。另请参见 sc_gpc_rate 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回布尔值零。否则,转换器将返回指定表中与输入样本关联的数组中索引为 <idx> 的通用目的标签的当前值。<idx> 是介于 0 和 99 之间的整数。如果在此索引处没有存储 GPT,它还将返回布尔值 0。这仅适用于“gpt”数组数据类型(而不适用于旧版“gpt0”数据类型)。另请参见 sc_get_gpt 样本获取关键字。
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回布尔值零。否则,转换器返回与指定表中输入样本关联的第一个通用目的标签的当前值。另请参阅 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 样本提取关键字。
使用输入样本在指定表中进行查找。如果在表中找不到键,则转换器将失败,除非设置了 <default_value>:这会使转换器成功并返回 <default_value>。如果找到键,则转换器将返回自上次更新以来,指定表中与输入样本关联的键条目的空闲时间。另请参见 table_expire 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的客户端到服务器数据的累积数量,以千字节为单位。当前测试是在 32 位整数上进行的,这会将值限制在 4 TB。另请参见 sc_kbytes_in 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的服务器到客户端数据的累积数量,以千字节为单位。当前测试是在 32 位整数上进行的,这会将值限制在 4 TB。另请参见 sc_kbytes_out 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的服务器 ID。当连接到服务器成功时,服务器 ID 通过“stick”规则进行关联。服务器 ID 零表示没有与此键关联的服务器。使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的传入会话的累积数量。请注意,此处会话是指由“tcp-request connection”规则集接受的传入连接。另请参见 sc_sess_cnt 样本获取关键字。
使用输入样本的字符串表示形式在指定表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回与指定表中的输入样本关联的平均传入会话速率。请注意,此处的会话指的是被“tcp-request connection”规则集接受的传入连接。另请参阅 sc_sess_rate 样本提取关键字。
使用输入样本的字符串表示形式在指定表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回在指定表中跟踪与输入样本相同键的当前并发连接数。它与 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 变体。
如果不存在 <field_type>,则以原始模式提取输入二进制样本表示的 gRPC 消息字段,其中 <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) # 第一个 PPoint 的 "lo" 的 "latitude" req.body,ungrpc(48.59.2,int32) # 第一个 PPoint 的 "lo" 的 "longitude" req.body,ungrpc(49.59.1,int32) # 第二个 PPoint 的 "hi" 的 "latitude" req.body,ungrpc(49.59.2,int32) # 第二个 PPoint 的 "hi" 的 "longitude" 我们还可以按如下方式将中间字段 48.59 提取为二进制样本: req.body,ungrpc(48.59) 由于 gRPC 消息始终由 gRPC 标头后跟协议缓冲区消息组成,在前面的示例中,可以使用这些等效指令提取第一个 PPoint 的 "lo" 的 "latitude": req.body,ungrpc(48.59),protobuf(1,int32) req.body,ungrpc(48),protobuf(59.1,int32) req.body,ungrpc(48),protobuf(59),protobuf(1,int32) 请注意,第一个转换器必须是 "ungrpc",其余的必须是 "protobuf",并且只有最后一个转换器可以有或没有第二个参数来解释上一个二进制样本。
如果输入内容已定义,则取消设置变量。变量的名称以其作用域的指示开头。有关变量的详细信息,请参阅第 2.8 节。
将字符串样本转换为大写。这只能放在字符串样本提取函数之后或返回字符串类型的转换关键字之后。结果为字符串类型。
接受一个经过 URL 编码的字符串作为输入,并返回其解码后的版本作为输出。输入和输出的类型都是字符串。如果将 <in_form> 参数设置为非零整数值,则假定输入字符串是表单或查询字符串的一部分,并且“+”字符将被转换为空格(' ')。否则,只有在表示查询字符串的问号(“?”)之后才会发生这种情况。
接受一个字符串作为输入,并返回其编码后的版本作为输出。输入和输出的类型都是字符串。默认情况下,编码类型用于`query`类型。目前不支持其他类型,但可选参数是为了将来的更改而保留的。
这类似于 "ltime",但以微秒为单位获取输入。它还支持受 date(1) 启发的 %N 转换说明符。将假设包含自纪元以来的日期的整数转换为表示该日期的本地时间字符串,使用 strftime(3) 定义的 <format> 字符串。目的是允许在日志中使用任何日期格式。可以对输入日期应用可选的微秒 <offset>(正值或负值)。有关您的操作系统支持的格式,请参阅 strftime() 手册页。%N 转换说明符允许您输出日期的纳秒部分,精度有限,因为输入是微秒 (000000000..999999000)。%N 可以在 % 和 N 之间使用宽度参数。它对于显示毫秒 (%3N) 或微秒 (%6N) 非常有用。默认和最大宽度为 9 (%N = %9N)。另请参阅 "utime" 转换器(用于 UTC)以及 "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
这类似于 "utime",但以微秒为单位获取输入。它还支持受 date(1) 启发的 %N 转换说明符。将假设包含自纪元以来的日期的整数转换为表示该日期的 UTC 时间字符串,使用 strftime(3) 定义的 <format> 字符串。目的是允许在日志中使用任何日期格式。可以对输入日期应用可选的微秒 <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
将一个应包含自纪元以来日期的整数,使用由 <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
评估条件,如果为真,则将输入样本按原样传递给输出,否则不返回任何内容。这专门用于生成一些很少需要的数据,这些数据只应在特定条件下发出,例如遇到错误时发出调试信息。条件由以下列表中的关键字组成,前面可选地加上感叹号 ('!') 来否定它,后面可选地加上特定于该条件的一些参数: - "error" 在处理请求或流期间遇到错误时返回 true。它使用与 "dontlog-normal" 相同的规则(例如,成功的重新调度算作错误)。 - "forwarded" 在请求被转发到后端服务器时返回 true - "normal" 在没有发生错误时返回 true(这等同于 "!error")。 - "processed" 在请求被转发到后端服务器或由 applet 处理时返回 true。 - "stopping" 如果在评估规则时进程当前正在停止,则返回 true - "toapplet" 在请求由 applet 处理时返回 true。 - "acl" 在由下一个参数指定的 ACL 评估为 true 时返回 true。请注意,ACL 由转换器内联评估,因此它引用的内容在该上下文中必须有效。一个特定的用例是评估总传输时间是否过长,然后决定是否记录异常长时间传输的详细信息。请注意,内容无论如何都会被评估,因此这样做并不能避免生成该信息。它只是为了避免产生该信息。一个例子是在日志中添加后端流调试信息,仅当在处理过程中遇到错误时,或者在停止时记录额外信息等。# 正常时记录 "dbg={-}",错误时记录 "dbg={... 调试信息 ...}": log-format "$HAPROXY_HTTP_LOG_FMT dbg={%[bs.debug_str,when(!normal)]}" 在这里,当规则未验证时,日志中的“dbg”字段将只包含一个破折号('-')以表示内容缺失,而验证通过时将发出整个调试块。
示例 # 正常时记录 "dbg={-}",传输缓慢时记录 "dbg={... 调试信息 ...}" acl slow_xfer res.timer.data ge 10000 # 超过 10 秒即为慢速 log-format "$HAPROXY_HTTP_LOG_FMT \ fsdbg={%[fs.debug_str,when(acl,slow_xfer)]} \ bsdbg={%[bs.debug_str,when(acl,slow_xfer)]}" 示例 # 仅在发出真实连接时才发出后端源 IP/端口: log-format "$HAPROXY_HTTP_LOG_FMT \ src=[%[bc_src,when(forwarded)]:%[bc_src_port,when(forwarded)]]" 由于当条件不为真时它会终止表达式的评估,因此也可以用它来阻止后续转换器的调用。例如,这可以用于仅在出错时调用 debug() 转换器,以便仅在绝对必要时记录元素。# 仅在出错且输出为连接时,才将整个响应头列表输出到 stderr。 # 这里我们滥用了一个虚拟变量。 http-after-response set-var(res.test) \ res.hdrs,when(error),when(forwarded),debug(hdrs,stderr)
根据给定的分隔符,从输入字符串中提取从头开始(正索引)或从尾开始(负索引)计数的第 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 哈希函数将二进制输入样本哈希为一个无符号 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]
在 <value> 和有符号整数类型的输入值之间执行按位“XOR”(异或)操作,并返回结果作为有符号整数。<value> 可以是数值或变量名。有关变量的详细信息,请参阅第 2.8 节。
使用 XXhash 哈希函数的 XXH3 64 位变体将二进制输入样本哈希为一个有符号 64 位整数。此哈希支持一个种子,默认为零,但可以通过 <seed> 参数传递不同的值。此哈希以其优异性能和极快速度而闻名,因此可用于哈希 URL 和/或 URL 参数,作为粘滞表键来收集具有低碰撞率的统计数据,但必须注意,该算法不被认为是密码学安全的。
使用 XXHash 哈希函数的 32 位变体将二进制输入样本哈希为一个无符号 32 位整数。此哈希支持一个种子,默认为零,但可以通过 <seed> 参数传递不同的值。此哈希以其优异性能和极快速度而闻名,因此可用于哈希 URL 和/或 URL 参数,作为粘滞表键来收集具有低碰撞率的统计数据,但必须注意,该算法不被认为是密码学安全的。
使用 XXHash 哈希函数的 64 位变体将二进制输入样本哈希为一个有符号 64 位整数。此哈希支持一个种子,默认为零,但可以通过 <seed> 参数传递不同的值。此哈希以其优异性能和极快速度而闻名,因此可用于哈希 URL 和/或 URL 参数,作为粘滞表键来收集具有低碰撞率的统计数据,但必须注意,该算法不被认为是密码学安全的。
第一组样本提取方法适用于甚至与任何客户端信息都无关的内部信息。这些有时与“monitor fail”指令一起使用,以向外部观察者报告内部状态。本节中描述的样本提取方法可在任何地方使用。本节中样本提取方法及其各自类型的摘要
详细列表
返回进程上的活动并发连接总数。
如果所有指定 ACL 的评估结果都为 true,则返回 true,否则返回 false。最多可以提供 12 个 ACL,每个 ACL 用逗号分隔。每个指定的 ACL 都可以以“!”为前缀来反转结果。如果任何评估产生错误,则样本也返回错误。请注意,HAProxy 不会对引用的 ACL 执行任何验证检查,例如在响应上下文中使用使用 http 请求样本的 ACL。此行为将来可能会更改。
始终返回布尔值“false”。在调整配置时,它可以与 ACL 一起用作另一个 ACL 的临时替代品。
始终返回布尔值“true”。在调整配置时,它可以与 ACL 一起用作另一个 ACL 的临时替代品。
返回指定后端的排队连接总数除以活动服务器数。如果未指定后端,则使用当前后端。这与 "queue" 非常相似,只是考虑了场的大小,以便更准确地测量新连接的处理时间。主要用法是与 ACL 一起使用,当确定新用户将获得降级服务时向他们返回抱歉页面,或者在标头中传递给后端服务器,以便它们决定在降级模式下工作或禁用某些功能以加快处理速度。请注意,如果没有活动服务器,则排队连接数的两倍将被视为测量值。这是一个公平的估计,因为我们预计一台服务器很快就会恢复,但我们仍然更愿意将新流量发送到状态更好的另一个后端。另请参阅 "queue"、"be_conn" 和 "be_sess_rate" 样本获取。
适用于后端上当前已建立的连接数,可能包括正在评估的连接。如果未指定后端名称,则使用当前后端。但也可以检查另一个后端。当标称服务器组已满时,它可用于使用特定的服务器组。另请参见“fe_conn”、“queue”、“be_conn_free”和“be_sess_rate”标准。
返回一个整数值,对应于后端中可用服务器上的可用连接数。不包括队列槽位。也不包括备份服务器,除非所有其他服务器都已关闭。如果未指定后端名称,则使用当前后端。但也可以检查另一个后端。当标称服务器组已满时,它可用于使用特定的服务器组。另请参见“be_conn”、“connslots”和“srv_conn_free”标准。其他注意事项和说明:如果任何服务器的 maxconn 或 maxqueue 为 0(表示无限制),则此提取显然没有意义,在这种情况下返回的值将为 -1。
返回一个整数值,对应于后端上的会话创建速率,以每秒新会话数表示。这与 ACL 一起使用,以便在昂贵或脆弱的后端达到过高的会话速率时切换到备用后端,或限制服务滥用(例如防止在线词典被爬取)。使用 log-format 指令将此元素添加到日志中也很有用。
# 如果字典请求过于频繁,则重定向到错误页面 backend dynamic mode http acl being_scanned be_sess_rate gt 100 redirect location /denied.html if being_scanned
返回一个二进制链。输入是字符串的十六进制表示。
返回一个布尔值。<bool> 可以是 'true'、'false'、'1' 或 '0'。'false' 和 '0' 相同。'true' 和 '1' 相同。
通过汇总所有服务器上的最大连接数和最大队列大小,返回对应于后端中仍可用的连接槽数的整数值。这可能只与 ACL 一起使用。这里的基本思想是能够测量仍可用的连接 "槽" 数(连接 + 队列),以便任何超出此范围的内容(预期用途;请参阅 "use_backend" 关键字)都可以重定向到不同的后端。'connslots' = 可用服务器连接槽数 + 可用服务器队列槽数。请注意,虽然可以使用 "fe_conn",但当您遇到流量流向单个 IP,然后分成多个后端(可能使用 ACL 进行基于名称的负载平衡)并且您希望能够区分不同的后端及其可用的 "connslots" 时,"connslots" 特别有用。此外,尽管 "nbsrv" 仅测量实际 *关闭* 的服务器,此获取更精细,并查看可用连接槽的数量。另请参阅 "queue" 和 "avg_queue"。其他注意事项和说明:目前,代码不处理动态连接。此外,如果任何服务器 maxconn 或 maxqueue 为 0,则此获取显然没有意义,在这种情况下返回的值将为 -1。
返回自处理流或当前请求的任务分配以来对其的调用次数。在 HTTP keep-alive 的情况下,每次新请求都会在同一连接上重置此数字。此值通常应较低且稳定(对于典型的简单请求约为 2 次调用),但如果执行了某些处理(压缩、缓存或分析),则可能会变高。这纯粹是为了性能监控。
返回处理流或当前请求的每个任务调用的平均纳秒数。在 HTTP keep-alive 的情况下,每次新请求都会在同一连接上重置此数字。此值表示每次调用处理请求或连接的总体成本。没有好坏之分,但调用中花费的时间会自动导致其他处理的延迟(参见下面的 lat_ns_avg),并可能影响其他连接的表观响应时间。某些操作(如压缩、复杂正则表达式匹配或繁重的 Lua 操作)可能会直接影响此值,将其记录在日志中将更容易发现需要修复以恢复良好性能的错误处理。注意:此值正好是 cpu_ns_tot 除以 cpu_calls。
返回处理流或当前请求的每个任务调用的总纳秒数。在 HTTP keep-alive 的情况下,每次新请求都会在同一连接上重置此数字。此值表示每次调用处理请求或连接的总体成本。没有好坏之分,但调用中花费的时间会自动导致其他处理的延迟(参见下面的 lat_ns_avg),导致机器上的 CPU 成本,并可能影响其他连接的表观响应时间。某些操作(如压缩、复杂正则表达式匹配或繁重的 Lua 操作)可能会直接影响此值,将其记录在日志中将更容易发现需要修复以恢复良好性能的错误处理。由于 cpu_calls 计数较高(例如,在处理许多 HTTP 块时),该值可能会人为地偏高,因此通常首选记录 cpu_ns_avg。
以纪元(自 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 样本返回)。此样本与 date 样本一致,因为它来自相同的 timeval 结构。
返回一个包含环境变量 <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 }
返回前端上当前已建立的连接数,可能包括正在评估的连接。如果未指定前端名称,则使用当前前端。但也可以检查另一个前端。它可用于在硬阻塞之前返回一个“抱歉”页面,或者在服务器场被认为已满时使用特定的后端来处理新请求。这主要与 ACL 一起使用,但也可以用于在 HTTP 头中将一些统计信息传递给服务器。另请参阅“dst_conn”、“be_conn”、“fe_sess_rate”提取。
返回一个整数值,对应于每秒发送到前端的 HTTP 请求数。在启用客户端保持连接(keep-alive)的情况下,此数字可能与“fe_sess_rate”不同。
返回一个整数值,对应于前端上的会话创建速率,单位为每秒新会话数。这与 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
返回系统主机名。
返回一个有符号整数。
返回一个 IPv4 地址。
返回一个 IPv6 地址。
这返回流分析期间评估的最后一个实体的标识。它可能是匹配的最终规则,也可能是中断处理的过滤器。最终规则是终止规则集评估的规则(如 "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"。
这返回配置文件中包含流分析期间匹配的最后一个最终规则的行号。最终规则是终止规则集评估的规则(如 "accept"、"deny" 或 "redirect")。这适用于对 "content" 规则集起作用的 TCP 请求和响应规则,以及来自 "http-request"、"http-response" 和 "http-after-response" 规则集的 HTTP 规则。不支持旧版 "redirect" 规则集(此类信息未存储在那里),也不支持 "tcp-request connection" 和 "tcp-request session" 规则集,因为信息存储在流级别,并且在这些规则期间流不存在。此函数的主要目的是能够在日志中报告给出最终裁决的规则的位置,以帮助找出请求被拒绝的原因。另请参阅 "last_rule_file"。
返回处理流的任务被唤醒到实际调用之间花费的平均纳秒数。对于 HTTP keep-alive,此数字会在同一连接上的每个新请求时重置。此值指示当前请求受到所有并行处理的其他请求影响的总体延迟,并且是由于邻居嘈杂而导致感知性能的直接指标。为了保持较低的值,可以使用 "tune.runqueue-depth" 减少调度程序的运行队列深度,使用 "tune.maxpollevents" 减少一次处理的并发事件数,使用 "bind" 行或前端中的 "nice" 选项降低流的 nice 值,使用 "tune.sched.low-latency" 启用低延迟调度,或者在日志中查找其他重请求(显示较大的 "cpu_ns_avg" 值),需要调整或修复其处理。大缓冲区压缩可能是一个罪魁祸首,例如重正则表达式或长正则表达式列表。注意:此值正好是 lat_ns_tot 除以 cpu_calls。
返回处理流的任务被唤醒到实际调用之间花费的总纳秒数。对于 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,它是一个更相关的性能指标。
返回一个方法。
返回一个整数值,对应于当前后端或指定后端的可用服务器数量。这主要与 ACL 一起使用,但在添加到日志中时也很有用。这通常用于在服务器数量过低而无法处理某些负载时切换到备用后端。当与“monitor fail”结合使用时,报告故障很有用。
返回当前流(对于 http 模式)或连接(对于 tcp 模式)的优先级类别。该值将是最后一次调用“http-request set-priority-class”或“tcp-request content set-priority-class”所设置的值。
返回当前流(对于 http 模式)或连接(对于 tcp 模式)的优先级偏移量。该值将是最后一次调用“http-request set-priority-offset”或“tcp-request content set-priority-offset”所设置的值。
返回当前进程的 PID。在大多数情况下,这是工作进程的 PID。
始终返回值 1(历史上它会返回调用进程号)。
返回指定后端的排队连接总数,包括服务器队列中的所有连接。如果未指定后端名称,则使用当前后端,但也可以检查另一个后端。这对于 ACL 或将统计信息传递给后端服务器很有用。这可用于在排队超过已知水平时采取行动,这通常表示流量激增或服务器大规模减速。一个可能的操作是拒绝新用户但仍然接受老用户。另请参阅“avg_queue”、“be_conn”和“be_sess_rate”提取。
当 QUIC 传输协议支持已编译且此协议未被 "no-quic" 全局选项禁用时返回 true。另请参阅 "no-quic" 全局选项。
返回一个在 <range> 个可能值范围内的随机整数值,从零开始。如果未指定范围,则默认为 2^32,即数字介于 0 和 4294967295 之间。例如,传递一些需要用于做出某些路由决策的值可能很有用,或者仅仅用于调试目的。此随机数不得用于安全目的。
返回一个整数值,对应于指定服务器上当前已建立的连接数,可能包括正在评估的连接。如果省略 <backend>,则在当前后端中查找服务器。当一台服务器已满时,它可用于使用特定的服务器组,或告知服务器我们对其活动连接数的看法。另请参见“fe_conn”、“be_conn”、“queue”和“srv_conn_free”提取方法。
返回一个整数值,对应于指定服务器上的可用连接数,可能包括正在评估的连接。该值不包括队列槽位。如果省略 <backend>,则在当前后端中查找服务器。当一台服务器已满时,它可用于使用特定的服务器组,或告知服务器我们对其活动连接数的看法。另请参见“be_conn_free”和“srv_conn”提取方法。其他注意事项和说明:如果服务器的 maxconn 为 0,则此提取显然没有意义,在这种情况下返回的值将为 -1。
当指定服务器处于 UP 状态时返回 true,当其处于 DOWN 或维护模式时返回 false。如果省略 <backend>,则在当前后端中查找服务器。它主要用于根据通过健康检查报告的外部状态采取行动(例如,地理站点的可用性)。另一种可能的用途,更像是一种技巧,是使用虚拟服务器作为布尔变量,可以从 CLI 启用或禁用,以便可以实时调整依赖于这些 ACL 的规则。
返回一个整数值,对应于当前在指定服务器队列中等待的连接数。如果省略 <backend>,则在当前后端中查找服务器。有时可以与“use-server”指令一起使用,以在已知更快的服务器负载不大时强制使用它。另请参见“srv_conn”、“avg_queue”和“queue”样本提取方法。
返回一个对应于指定服务器上的会话创建速率的整数,以每秒新会话数表示。如果省略 <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
返回一个对应于服务器初始权重的整数。如果省略 <backend>,则在当前后端中查找服务器。另请参见“srv_weight”和“srv_uweight”。
返回一个对应于用户可见服务器权重的整数。如果省略 <backend>,则在当前后端中查找服务器。另请参见“srv_weight”和“srv_iweight”。
返回一个对应于当前(或有效)服务器权重的整数。如果省略 <backend>,则在当前后端中查找服务器。另请参见“srv_iweight”和“srv_uweight”。
如果调用该函数的进程当前正在停止,则返回 TRUE。这对于日志记录,或在优雅关闭时放宽某些检查或帮助关闭某些连接很有用。
返回一个字符串。
返回当前代理的粘性表或指定粘性表中可用条目的总数。另请参阅 table_cnt。
返回当前代理的粘性表或指定粘性表中当前使用的条目总数。有关其他条目计数方法,请参阅 src_conn_cnt 和 table_avl。
返回一个整数值,对应于调用该函数的线程的位置,介于 0 和 (global.nbthread-1) 之间。这对于日志记录和调试目的很有用。
返回内部事务 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" }
返回当前 HAProxy 工作进程的正常运行时间(以秒为单位)。
根据 RFC 9562 标准返回一个 UUID。如果未指定版本,则返回 UUID 版本 4(完全随机)。支持版本 4 和 7。
返回一个具有存储类型的变量。如果未设置变量,则样本提取失败,除非提供了默认值,在这种情况下,它将以字符串形式返回该默认值。允许空字符串。有关变量的详细信息,请参见第 2.8 节。
此获取在检查周期结束时返回 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)]"
第 4 层通常仅描述传输层,在 HAProxy 中最接近连接,此时尚无内容可用。除非需要一些未来信息,否则此处描述的获取方法在 "tcp-request connection" 规则集上可用。这些通常包括 TCP/IP 地址和端口,以及与传入连接相关的 stick-tables 中的元素。对于从粘性计数器中检索值,可以使用预定义的 "sc0_"、"sc1_" 或 "sc2_" 前缀将计数器编号显式设置为 0、1 或 2。只有在全局 "tune.stick-counters" 值不超过 3 时才能使用这三个预定义前缀,否则在使用 "sc_" 前缀时,计数器编号可以指定为第一个整数参数,从 "sc_0" 到 "sc_N",其中 N 是 (tune.stick-counters-1)。可以使用 "sc*" 形式指定可选表,在这种情况下,将在该备用表中查找当前跟踪的键,而不是当前正在跟踪的表。本节中的样本获取方法及其各自类型的摘要
详细列表
这是 HAProxy 接收到连接的确切日期(如果系统中存在一些排队,可能与网络上观察到的日期略有不同)。这通常是任何上游防火墙日志中可能出现的日期。当在 HTTP 模式下使用时,accept_date 字段将被重置为连接准备好接收新请求的第一个时刻(HTTP/1 的前一个响应结束,HTTP/2 的前一个请求之后立即)。返回自纪元以来的秒数。 <unit> 是可选的,可以设置为“s”表示秒(默认行为)、“ms”表示毫秒或“us”表示微秒。如果设置了 unit,返回值将是一个整数,表示自纪元以来的秒、毫秒或微秒。当需要小于一秒的时间分辨率时,它很有用。
建立到服务器的 TCP 连接的总时间。这是日志格式中 %Tc 的等效项。以毫秒 (ms) 为单位报告。有关更多信息,请参阅第 8.4 节“计时事件”。
在等待目标后端连接槽时出列的流的数量。这是日志格式中 %bq 的等效项。
这是服务器端的连接的目标 IP 地址,即 HAProxy 连接到的服务器地址。它属于 IP 类型,并且适用于 IPv4 和 IPv6 表。在 IPv6 表中,IPv4 地址根据 RFC 4291 映射到其 IPv6 等效项。
返回一个整数值,对应于服务器端的连接的目标 TCP 端口,即 HAProxy 连接到的端口。
返回可能发生在当前后端连接上的错误的 ID。有关错误代码及其对应错误消息的完整列表,请参阅“fc_err_str”提取。
返回描述后端连接上发生的问题并导致连接失败的内部错误名称。此字符串由一个单词组成,在没有错误时为空。它对应于“fc_err_str”关键字中表格的“name”列。
返回描述当前后端连接上发生的问题并导致连接失败的错误消息。有关错误代码及其对应错误消息的完整列表,请参阅“fc_err_str”提取。
返回后端连接上计数的协议故障数量。这些通常涵盖协议违规以及表明服务器错误或行为异常的小异常,这些异常可能导致基础设施出现问题(例如,导致连接提前中止,引起频繁的 TLS 重新协商)。这些也可能由于响应过大而无法装入单个缓冲区而导致,从而解释 HTTP 502 错误。理想情况下,此数字应保持为零,尽管与请求总数相比,它保持非常低通常是可以的。这些值通常不应被视为令人警觉(尤其是小的),尽管突然跳变可能表明某个地方存在异常。并非所有协议复用器都测量此指标,并且要获取事件的更多详细信息的唯一方法是启用跟踪以捕获所有交换。
返回后端连接的 HTTP 主版本编码,可以是 1(用于 HTTP/0.9 到 HTTP/1.1)或 2(用于 HTTP/2)。请注意,这基于线上传输的编码,而不是请求标头中存在的版本。
返回后端连接上打开的流的数量。
这是服务器端的连接源 IP 地址,即 HAProxy 从中连接的服务器地址。它属于 IP 类型,并且适用于 IPv4 和 IPv6 表。在 IPv6 表中,IPv4 地址根据 RFC 4291 映射到其 IPv6 等效项。
返回一个整数值,对应于服务器端的连接的 TCP 源端口,即 HAProxy 连接的端口。
在等待目标服务器连接槽时出列的流的数量。这是日志格式中 %sq 的等效项。
返回后端连接上允许的最大流数。对于 TCP 和 HTTP/1.1 连接,始终为 1。对于其他协议,它取决于与服务器协商的设置。
返回一个整数,包含当前后端的 ID。它可以在前端使用响应来检查哪个后端处理了请求。如果在前端使用并且没有使用后端,它将返回当前前端的 ID。它也可以在 tcp-check 或 http-check 规则集中使用。
返回一个字符串,包含当前后端的名称。它可以在前端使用响应来检查哪个后端处理了请求。如果在前端使用并且没有使用后端,它将返回当前前端的名称。它也可以在 tcp-check 或 http-check 规则集中使用。
返回内核为后端连接测量的往返时间 (RTT)。<unit> 是可选的,默认单位是毫秒。<unit> 可以设置为“ms”表示毫秒或“us”表示微秒。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
返回内核为后端连接测量的往返时间 (RTT) 方差。<unit> 是可选的,默认单位是毫秒。<unit> 可以设置为“ms”表示毫秒或“us”表示微秒。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
返回当前后端服务器超时配置值(以毫秒为单位)。此超时可以通过“set-timeout”规则覆盖。另请参阅“cur_server_timeout”。
返回当前后端隧道超时配置值(以毫秒为单位)。此超时可以通过“set-timeout”规则覆盖。另请参阅“cur_tunnel_timeout”。
此函数返回从客户端上传到服务器的字节数。
这是从服务器传输到客户端的字节数。
返回流当前应用的服务器超时(以毫秒为单位)。在默认情况下,这将等于 be_server_timeout,除非应用了“set-timeout”规则。另请参阅“be_server_timeout”。
返回流当前应用的隧道超时(以毫秒为单位)。在默认情况下,这将等于 be_tunnel_timeout,除非应用了“set-timeout”规则。另请参阅“be_tunnel_timeout”。
返回流当前应用的客户端超时(以毫秒为单位)。在默认情况下,这将等于 fe_client_timeout,除非应用了“set-timeout”规则。另请参阅“fe_client_timeout”。
这是客户端上的连接目标 IP 地址,即客户端连接到的地址。任何 tcp/http 规则都可能更改此地址。在透明模式下运行时可能很有用。它属于 IP 类型,并且适用于 IPv4 和 IPv6 表。在 IPv6 表中,IPv4 地址根据 RFC 4291 映射到其 IPv6 等效项。当传入连接经过地址转换或涉及连接跟踪的重定向时,将报告重定向之前的原始目标地址。在 Linux 系统上,由于晚期响应可能会重新打开已超时的连接并切换被认为是源和目标的地址,如果设置了 nf_conntrack_tcp_loose sysctl,源和目标可能很少出现颠倒。
返回一个整数值,对应于同一套接字上当前建立的连接数,包括正在评估的连接。它通常与 ACL 一起使用,但也可以用于在 HTTP 头中或日志中将信息传递给服务器。它可以用于在硬阻塞之前返回一个“抱歉”页面,或者在套接字被认为饱和时使用特定的后端来处理新请求。这提供了为不同的侦听端口或地址分配不同限制的能力。另请参阅“fe_conn”和“be_conn”提取。
如果传入连接的目标地址是本地系统地址,则返回 true;如果地址不存在于系统中(意味着它在透明模式下被拦截),则返回 false。这对于默认情况下对转发流量应用某些规则,而对定向到机器实际地址的流量应用其他规则可能很有用。例如,统计页面可能仅在该地址上提供,或者 SSH 访问可能被本地重定向。请注意,该检查涉及一些系统调用,因此最好每个连接只执行一次。
返回客户端上的连接目标 TCP 端口的整数值,即客户端连接到的端口。任何 tcp/http 规则都可能更改此地址。在透明模式下运行时,为某个应用程序会话为某些客户端分配动态端口,将所有用户粘性到同一服务器,或通过 HTTP 标头将目标端口信息传递给服务器时,可以使用此端口。
接受 TCP 连接并执行低级协议握手(当前包括 proxy-protocol 和 SSL)的总时间。这是日志格式中 %Th 的等效项。以毫秒 (ms) 为单位报告。有关更多信息,请参阅第 8.4 节“计时事件”。
流的总持续时间,从代理接受它到两端都关闭。这是日志格式中 %Tt 的等效项。以毫秒 (ms) 为单位报告。有关更多信息,请参阅第 8.4 节“计时事件”。
这是客户端上的连接的原始目标 IP 地址。只有“tcp-request connection”规则可能更改此地址。有关详细信息,请参阅“dst”。
如果传入连接的原始目标地址是本地系统地址,则返回 true;如果地址不存在于系统中,则返回 false。有关详细信息,请参阅“dst_is_local”。
返回客户端上的连接的原始目标 TCP 端口的整数值。只有“tcp-request connection”规则可能更改此地址。有关详细信息,请参阅“dst-port”。
返回可能发生在当前连接上的错误的 ID。此提取器的任何严格正值都表示连接不成功,并且将导致输出错误日志(如 第 8.2.5 节 中所述)。有关错误代码及其对应错误消息的完整列表,请参阅“fc_err_str”提取。
返回描述前端连接上发生的问题并导致连接失败的内部错误名称。此字符串由一个单词组成,在没有错误时为空。它对应于“fc_err_str”关键字中表格的“name”列。
返回描述当前连接上发生的问题的错误消息,导致连接失败。此字符串对应于错误日志格式的 "message" 部分(请参阅第 8.2.5 节)。请参阅下面了解错误代码及其对应错误消息的完整列表: +----+------------------+-------------------------------------------------------------------------+ | ID | name | message | +----+------------------+-------------------------------------------------------------------------+ | 0 | - | "Success" | | 1 | CONF_FDLIM | "Reached configured maxconn value" | | 2 | PROC_FDLIM | "Too many sockets on the process" | | 3 | SYS_FDLIM | "Too many sockets on the system" | | 4 | SYS_MEMLIM | "Out of system buffers" | | 5 | NOPROTO | "Protocol or address family not supported" | | 6 | SOCK_ERR | "General socket error" | | 7 | PORT_RANGE | "Source port range exhausted" | | 8 | CANT_BIND | "Can't bind to source address" | | 9 | FREE_PORTS | "Out of local source ports on the system" | | 10 | ADDR_INUSE | "Local source address already in use" | | 11 | PRX_EMPTY | "Connection closed while waiting for PROXY protocol header" | | 12 | PRX_ABORT | "Connection error while waiting for PROXY protocol header" | | 13 | PRX_TIMEOUT | "Timeout while waiting for PROXY protocol header" | | 14 | PRX_TRUNCATED | "Truncated PROXY protocol header received" | | 15 | PRX_NOT_HDR | "Received something which does not look like a PROXY protocol header" | | 16 | PRX_BAD_HDR | "Received an invalid PROXY protocol header" | | 17 | PRX_BAD_PROTO | "Received an unhandled protocol in the PROXY protocol header" | | 18 | CIP_EMPTY | "Connection closed while waiting for NetScaler Client IP header" | | 19 | CIP_ABORT | "Connection error while waiting for NetScaler Client IP header" | | 20 | CIP_TIMEOUT | "Timeout while waiting for a NetScaler Client IP header" | | 21 | CIP_TRUNCATED | "Truncated NetScaler Client IP header received" | | 22 | CIP_BAD_MAGIC | "Received an invalid NetScaler Client IP magic number" | | 23 | CIP_BAD_PROTO | "Received an unhandled protocol in the NetScaler Client IP header" | | 24 | SSL_EMPTY | "Connection closed during SSL handshake" | | 25 | SSL_ABORT | "Connection error during SSL handshake" | | 26 | SSL_TIMEOUT | "Timeout during SSL handshake" | | 27 | SSL_TOO_MANY | "Too many SSL connections" | | 28 | SSL_NO_MEM | "Out of memory when initializing an SSL connection" | | 29 | SSL_RENEG | "Rejected a client-initiated SSL renegotiation attempt" | | 30 | SSL_CA_FAIL | "SSL client CA chain cannot be verified" | | 31 | SSL_CRT_FAIL | "SSL client certificate not trusted" | | 32 | SSL_MISMATCH | "Server presented an SSL certificate different from the configured one" | | 33 | SSL_MISMATCH_SNI | "Server presented an SSL certificate different from the expected one" | | 34 | SSL_HANDSHAKE | "SSL handshake failure" | | 35 | SSL_HANDSHAKE_HB | "SSL handshake failure after heartbeat" | | 36 | SSL_KILLED_HB | "Stopped a TLSv1 heartbeat attack (CVE-2014-0160)" | | 37 | SSL_NO_TARGET | "Attempt to use SSL on an unknown target (internal error)" | | 38 | SSL_EARLY_FAILED | "Server refused early data" | | 39 | SOCKS4_SEND | "SOCKS4 Proxy write error during handshake" | | 40 | SOCKS4_RECV | "SOCKS4 Proxy read error during handshake" | | 41 | SOCKS4_DENY | "SOCKS4 Proxy deny the request" | | 42 | SOCKS4_ABORT | "SOCKS4 Proxy handshake aborted by server" | | 43 | SSL_FATAL | "SSL fatal error" | | 44 | REVERSE | "Reverse connect failure" | | 45 | POLLERR | "Poller reported POLLERR" | | 46 | EREFUSED | "ECONNREFUSED returned by OS" | | 47 | ERESET | "ECONNRESET returned by OS" | | 48 | EUNREACH | "ENETUNREACH returned by OS" | | 49 | ENOMEM | "ENOMEM returned by OS" | | 50 | EBADF | "EBADF returned by OS" | | 51 | EFAULT | "EFAULT returned by OS" | | 52 | EINVAL | "EINVAL returned by OS" | | 53 | ENCONN | "ENCONN returned by OS" | | 54 | ENSOCK | "ENSOCK returned by OS" | | 55 | ENOBUFS | "ENOBUFS returned by OS" | | 56 | EPIPE | "EPIPE returned by OS" | +----+------------------+-------------------------------------------------------------------------+
返回内核为客户端连接测量的 fack 计数器。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
返回在前端连接上计数的协议故障数。这些通常涵盖协议违规以及小异常,这些异常通常表明客户端有故障或行为不端,可能会导致基础设施出现问题,例如日志中错误过多,或者许多连接过早中止,导致频繁的 TLS 重新协商。这些也可能由无法放入单个缓冲区而导致 HTTP 400 错误的大请求引起。理想情况下,此数字应保持为零,尽管某些浏览器在协议边界上玩耍时可能会偶尔触发它。这些值通常不应被视为警报(尤其是小值),尽管突然跳跃可能表明某处存在异常。大值(即每个连接数百到数千次,或与请求一样多)可能表明客户端是故意构建的,试图对协议栈进行指纹识别或攻击。并非所有协议多路复用器都测量此指标,获取有关事件的更多详细信息的唯一方法是启用跟踪以捕获所有交换。
报告前端连接的 HTTP 主版本编码,可以是 1(用于 HTTP/0.9 到 HTTP/1.1)或 2(用于 HTTP/2)。请注意,这基于线上传输的编码,而不是请求标头中存在的版本。
如果连接不是 TCP 或 QUIC,则样本提取失败。对于 QUIC,返回客户端连接丢失的 QUIC 数据包数量。对于 TCP,返回内核为客户端连接测量的丢失计数器。如果服务器连接未建立,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
返回前端连接上打开的流的数量。
返回客户端在 PROXY 协议头中发送的第一个 authority TLV(如果存在)。
返回客户端在 PROXY 协议头中发送的第一个 unique ID TLV(如果存在)。
返回给定 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 协议头启动连接,则返回 true。
如果连接不是 TCP 或 QUIC,则样本提取失败。对于 QUIC,返回客户端连接的 QUIC 重排序数据包数量。对于 TCP,返回内核为客户端连接测量的重排序计数器。如果服务器连接未建立,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
返回内核为客户端连接测量的重传计数器。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
如果连接不是 TCP 或 QUIC,则样本提取失败。对于 QUIC,返回客户端连接的平滑往返时间。对于 TCP,返回内核为客户端连接测量的往返时间 (RTT)。<unit> 是可选的,默认单位是毫秒。<unit> 可以设置为“ms”表示毫秒或“us”表示微秒。如果服务器连接未建立,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
如果连接不是 TCP 或 QUIC,则样本提取失败。对于 QUIC,返回客户端连接的平滑往返时间方差。对于 TCP,返回内核为客户端连接测量的往返时间 (RTT) 方差。<unit> 是可选的,默认单位是毫秒。<unit> 可以设置为“ms”表示毫秒或“us”表示微秒。如果服务器连接未建立,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
返回内核为客户端连接测量的 sacked 计数器。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
这是客户端上的连接的原始源 IP 地址。只有“tcp-request connection”规则可能更改此地址。有关详细信息,请参阅“src”。
如果传入连接的源地址是本地系统地址,则返回 true;如果地址不存在于系统中,则返回 false。有关详细信息,请参阅“src_is_local”。
返回客户端上的连接的 TCP 源端口的整数值。只有“tcp-request connection”规则可能更改此地址。有关详细信息,请参阅“src-port”。
返回前端连接上允许的最大流数。对于 TCP 和 HTTP/1.1 连接,始终为 1。对于其他协议,它取决于与客户端协商的设置。
返回内核为客户端连接测量的未确认计数器。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
返回前端的默认后端名称的字符串。它可以在前端用于检查哪个后端将默认处理请求。
返回一个包含当前前端 ID 的整数。它可以在后端使用,以检查它是从哪个前端调用的,或将通过同一前端进入的所有用户粘滞到同一台服务器。
返回当前前端名称的字符串。它可以在后端用于检查它是由哪个前端调用的,或者将来自同一前端的所有用户粘性到同一服务器。
返回当前前端的客户端超时配置值(以毫秒为单位)。此超时可以通过“set-timeout”规则覆盖。
这是响应负载直到发送到客户端的最后一个字节的总传输时间。在 HTTP 中,它发生在最后一个响应头(Tr)之后。这相当于日志格式中的 %Td,以毫秒(ms)为单位报告。有关更多信息,请参见第 8.4 节“计时事件”。
返回当前跟踪的计数器中客户端到服务器的平均字节速率,以表中配置的时间段内的字节量来衡量。另请参阅 src_bytes_in_rate。
返回当前跟踪的计数器中服务器到客户端的平均字节速率,以表中配置的时间段内的字节量来衡量。另请参阅 src_bytes_out_rate。
清除当前代理的粘滞表(stick table)中与指定跟踪计数器 ID <ctr> 关联的数组中索引为 <idx> 的通用计数器(General Purpose Counter),并返回其先前的值。<idx> 是一个介于 0 到 99 之间的整数,<ctr> 是一个介于 0 到 2 之间的整数。在第一次调用之前,存储的值为零,因此第一次调用将始终返回零。此获取仅适用于 'gpc' 数组的数据类型(而不适用于旧的 'gpc0' 或 'gpc1' 数据类型)。
清除与当前跟踪的计数器相关联的第一个通用计数器,并返回其先前的值。在第一次调用之前,存储的值为零,因此第一次调用将始终返回零。这通常用作表达式中的第二个 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
清除与当前跟踪计数器关联的第二个通用计数器,并返回其先前的值。在第一次调用之前,存储的值为零,因此第一次调用将始终返回零。这通常用作表达式中的第二个 ACL,以便在第一个 ACL 被验证后标记连接。
返回当前跟踪的计数器所统计的传入连接的总数。另请参阅 src_conn_cnt。
返回跟踪相同跟踪计数器的当前并发连接数。此数字在跟踪开始时自动递增,在跟踪停止时自动递减。另请参阅 src_conn_cur。
返回当前跟踪的计数器中的平均连接速率,以表中配置的时间段内的连接数量来衡量。另请参阅 src_conn_rate。
返回 GPC 数组中索引为 <idx> 的通用目的计数器的值,该计数器与当前代理的 stick-table 中 ID 为 <ctr> 的跟踪计数器相关联,或者与指定的 stick-table <table> 相关联。<idx> 是一个介于 0 和 99 之间的整数,<ctr> 是一个介于 0 和 2 之间的整数。如果在此索引处没有存储 gpc,则返回零。此获取仅适用于“gpc”数组数据类型(而不适用于旧的“gpc0”或“gpc1”数据类型)。另请参阅 src_get_gpc 和 sc_inc_gpc。
返回与当前跟踪的计数器关联的第一个通用计数器的值。另请参阅 src_get_gpc0 和 sc/sc0/sc1/sc2_inc_gpc0。
返回与当前跟踪的计数器关联的第二个通用目的计数器的值。另请参阅 src_get_gpc1 和 sc/sc0/sc1/sc2_inc_gpc1。
返回与 ID 为 <ctr> 的跟踪计数器以及当前代理的 stick-table 或指定的 stick-table <table> 关联的数组中索引为 <idx> 的第一个通用目的标签的值。<idx> 是一个介于 0 和 99 之间的整数,<ctr> 是一个介于 0 和 2 之间的整数。如果在此索引处没有存储 GPT,则返回零。此获取仅适用于“gpt”数组数据类型(而不适用于旧的“gpt0”数据类型)。另请参阅 src_get_gpt。
返回与当前跟踪的计数器关联的第一个通用标签(General Purpose Tag)的值。另请参阅 src_get_gpt0。
返回与当前跟踪计数器关联的入站连接发生的正面连接故障(front connection glitches)的累计数量。通常,这些故障会导致请求或连接被中止,因此返回的值通常对应于过去的连接。没有“好”或“坏”的值,但质量差的客户端每连接可能会偶尔导致几次故障,而非常糟糕或恶意的客户端可能会快速导致每连接数千个事件被添加。另请参阅 fc_glitches(影响当前连接的数量)、src_glitch_cnt(按源查找)以及 sc_glitch_rate(事件速率测量)。
返回在当前跟踪的计数器上观察到的前端连接故障的平均速率,以表中配置的周期内的事件量来衡量。通常,这些故障会导致请求或连接中止,因此返回的值通常与过去的连接相关。没有好坏之分,但质量差的客户端可能会偶尔导致每个连接出现一些故障,因此通常预期速率较低。然而,一个非常有故障或恶意的客户端可能会很快导致每个连接添加数千个事件,并在此处保持高速率。另请参阅 src_glitch_rate 和 sc_glitch_cnt。
返回与指定 ID <ctr> 的跟踪计数器关联的数组中索引为 <idx> 的通用计数器的平均增量率,该计数器来自当前代理的 stick-table 或指定的 stick-table <table>。它报告 gpc 计数器在配置周期内的增量频率。<idx> 是一个介于 0 到 99 之间的整数,<ctr> 是一个介于 0 到 2 之间的整数。请注意,'gpc_rate' 计数器数组必须存储在 stick-table 中才能返回值,因为 'gpc' 只包含事件计数。此获取仅适用于 'gpc_rate' 数组数据类型(而不适用于旧的 'gpc0_rate' 和 'gpc1_rate' 数据类型)。另请参阅 src_gpc_rate、sc_get_gpc 和 sc_inc_gpc。
返回与当前跟踪的计数器关联的第一个通用计数器的平均增量速率。它报告在配置的时间段内 gpc0 计数器递增的频率。另请参阅 src_gpc0_rate、sc/sc0/sc1/sc2_get_gpc0 和 sc/sc0/sc1/sc2_inc_gpc0。请注意,必须在粘性表中存储“gpc0_rate”计数器才能返回值,因为“gpc0”仅保存事件计数。
返回与当前跟踪计数器关联的第二个通用计数器的平均增量速率。它报告了在配置的时间段内 gpc1 计数器被增量的频率。另请参阅 src_gpcA_rate、sc/sc0/sc1/sc2_get_gpc1 和 sc/sc0/sc1/sc2_inc_gpc1。请注意,“gpc1_rate”计数器必须存储在粘滞表中才能返回一个值,因为“gpc1”只保存事件计数。
返回当前跟踪计数器中的 HTTP 错误总数。这包括请求错误和 4xx 错误响应。另请参阅 src_http_err_cnt。
返回当前跟踪的计数器中 HTTP 错误的平均速率,以表中配置的时间段内的错误数量来衡量。这包括请求错误和 4xx 错误响应。另请参阅 src_http_err_rate。
返回当前跟踪计数器中的 HTTP 响应失败总数。这包括响应错误和除 501 和 505 之外的 5xx 状态码。另请参阅 src_http_fail_cnt。
返回当前跟踪计数器中的 HTTP 响应失败的平均速率,以配置周期内的失败次数衡量。这包括响应错误和除 501 和 505 之外的 5xx 状态码。另请参阅 src_http_fail_rate。
返回当前跟踪计数器的累计 HTTP 请求数。这包括所有开始的请求,无论有效与否。另请参阅 src_http_req_cnt。
返回当前跟踪的计数器中 HTTP 请求的平均速率,以表中配置的时间段内的请求数量来衡量。这包括每个已启动的请求,无论其有效与否。另请参阅 src_http_req_rate。
递增当前代理的粘滞表或指定的粘滞表 <table> 中与指定跟踪计数器 ID <ctr> 关联的数组中索引为 <idx> 的通用计数器,并返回其新值。<idx> 是一个介于 0 到 99 之间的整数,<ctr> 是一个介于 0 到 2 之间的整数。在第一次调用之前,存储的值为零,因此第一次调用会将其增加到 1 并返回 1。此获取仅适用于 'gpc' 数组的数据类型(而不适用于旧的 'gpc0' 或 'gpc1' 数据类型)。
递增与当前跟踪的计数器相关联的第一个通用计数器,并返回其新值。在第一次调用之前,存储的值为零,因此第一次调用会将其增加到 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
递增与当前跟踪计数器关联的第二个通用计数器,并返回其新值。在第一次调用之前,存储的值为零,因此第一次调用会将其增加到 1 并返回 1。这通常用作表达式中的第二个 ACL,以便在第一个 ACL 被验证后标记连接。
返回当前跟踪的计数器中客户端到服务器的总数据量,以千字节为单位。该测试目前在 32 位整数上执行,这将值限制为 4 TB。另请参阅 src_kbytes_in。
返回当前跟踪的计数器中服务器到客户端的总数据量,以千字节为单位。该测试目前在 32 位整数上执行,这将值限制为 4 TB。另请参阅 src_kbytes_out。
返回从当前跟踪计数器中转换为会话的传入连接总数,这意味着它们被“tcp-request connection”规则接受。后端可能会计算比连接更多的会话,因为每个连接都可能导致许多后端会话,如果通过与客户端的连接执行了某些 HTTP keep-alive。另请参阅 src_sess_cnt。
返回当前跟踪的计数器中的平均会话速率,以表中配置的时间段内的会话数量来衡量。会话是通过早期“tcp-request connection”规则的连接。一个后端可能会计算比连接更多的会话,因为如果通过与客户端的连接执行了 HTTP 保持连接(keep-alive),每个连接可能会导致多个后端会话。另请参阅 src_sess_rate。
如果指定的会话计数器当前正被当前会话跟踪,则返回 true。这在决定是否要在传递给服务器的头中设置某些值时很有用。
返回跟踪相同跟踪计数器的当前并发连接数。此数字在跟踪开始时自动递增,在跟踪停止时自动递减。它与 sc0_conn_cur 的不同之处在于,它不依赖于任何存储的信息,而是依赖于表的引用计数(即在 CLI 上通过“show table”返回的“use”值)。这有时可能更适合于第 7 层跟踪。例如,它可以用来告诉服务器来自给定地址的并发连接数。
返回一个包含当前侦听套接字 ID 的整数。它在涉及多个“bind”行的前端中非常有用,或者可以将所有来自同一套接字的用户粘性地绑定到同一台服务器。返回一个包含当前侦听套接字名称的字符串,该名称在“bind”行中使用 name 定义。它可以与 so_id 具有相同的目的,但使用字符串而不是整数。这是会话客户端的源 IP 地址。任何 tcp/http 规则都可能更改此地址。它是 IP 类型,适用于 IPv4 和 IPv6 表。在 IPv6 表上,IPv4 地址根据 RFC 4291 映射到其 IPv6 等效项。请注意,使用的是 TCP 级别的源地址,而不是代理后面的客户端地址。但是,如果使用了 "accept-proxy" 或 "accept-netscaler-cip" bind 指令,则对于所有规则集(除了 "tcp-request connection" 看到真实地址之外),它都可以是另一个兼容 PROXY 协议的组件后面的客户端地址。当传入连接通过涉及连接跟踪的地址转换或重定向时,将报告重定向前的原始目标地址。在 Linux 系统上,如果设置了 nf_conntrack_tcp_loose sysctl,源地址和目标地址可能偶尔会颠倒,因为后期响应可能会重新打开超时连接并切换被认为是源和目标的地址。
# 在请求中添加一个带有源地址国家的 HTTP 头 http-request set-header X-Country %[src,map_ip(geoip.lst)]
返回当前代理的粘性表或指定粘性表中,来自传入连接源地址的平均字节速率,以表中配置的时间段内的字节量来衡量。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_bytes_in_rate。
返回当前代理的粘性表或指定粘性表中,发往传入连接源地址的平均字节速率,以表中配置的时间段内的字节量来衡量。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_bytes_out_rate。
清除当前代理的 stick-table 或指定的 stick-table <table> 中与传入连接的源地址关联的数组中索引为 <idx> 的通用计数器,并返回其先前的值。<idx> 是一个介于 0 到 99 之间的整数。如果未找到该地址,则会创建一个条目并返回 0。此获取仅适用于 'gpc' 数组数据类型(而不适用于旧的 'gpc0' 和 'gpc1' 数据类型)。另请参阅 sc_clr_gpc。
清除与当前连接的源地址相关联的第一个通用计数器,在当前代理的 stick-table 或指定的 stick-table 中,并返回其先前的值。如果找不到该地址,则创建条目并返回 0。这通常用作表达式中的第二个 ACL,以便在第一个 ACL 被验证时标记连接。
# 如果连续 5 个请求的速率持续高于每秒 10 个会话,则阻止, # 并在流量减慢时立即重置计数器。 acl abuse src_http_req_rate gt 10 acl kill src_inc_gpc0 gt 5 acl save src_clr_gpc0 ge 0 tcp-request connection accept if !abuse save tcp-request connection reject if abuse kill
清除当前代理的 stick-table 或指定 stick-table 中与传入连接的源地址关联的第二个通用计数器,并返回其先前的值。如果未找到该地址,则会创建一个条目并返回 0。这通常用作表达式中的第二个 ACL,以便在验证第一个 ACL 时标记连接。
返回当前代理的 stick-table 或指定 stick-table 中与传入连接的源地址关联的已建立连接的总数。如果未找到该地址,则返回零。另请参阅 sc/sc0/sc1/sc2_conn_cnt。
返回当前代理的粘性表或指定粘性表中,从当前传入连接的源地址发起的当前并发连接数。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_conn_cur。
返回当前代理的粘性表或指定粘性表中,来自传入连接源地址的平均连接速率,以表中配置的时间段内的连接数量来衡量。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_conn_rate。
返回当前代理的 stick-table 或指定 stick-table <table> 中与传入连接的源地址关联的数组中索引为 <idx> 的通用计数器的值。<idx> 是一个介于 0 到 99 之间的整数。如果未找到该地址或在此索引处没有存储 gpc,则返回零。此获取仅适用于 'gpc' 数组数据类型(而不适用于旧的 'gpc0' 和 'gpc1' 数据类型)。另请参阅 sc_get_gpc 和 src_inc_gpc。
返回与当前代理的粘性表或指定粘性表中传入连接的源地址关联的第一个通用计数器的值。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_get_gpc0 和 src_inc_gpc0。
返回当前代理的 stick-table 或指定 stick-table 中与传入连接的源地址关联的第二个通用计数器的值。如果未找到该地址,则返回零。另请参阅 sc/sc0/sc1/sc2_get_gpc1 和 src_inc_gpc1。
返回当前代理的 stick-table 或指定 stick-table <table> 中与传入连接的源地址关联的数组中索引为 <idx> 的第一个通用标记的值。<idx> 是一个介于 0 到 99 之间的整数。如果未找到该地址或未存储 GPT,则返回零。另请参阅 sc_get_gpt 示例获取关键字。
返回与当前代理的粘性表或指定粘性表中传入连接的源地址关联的第一个通用标签的值。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_get_gpt0。
返回在来自当前连接源地址的连接上观察到的前端连接故障的累积数量。通常,这些会导致请求或连接中止,因此返回的值通常对应于过去的连接。没有好坏之分,但质量差的客户端可能会偶尔导致每个连接出现一些故障,而一个非常有故障或恶意的客户端可能会很快导致连接上添加数千个事件。另请参阅 fc_glitches(用于影响当前连接的数量)、sc_glitch_cnt(用于在当前跟踪的计数器中查找它们)和 src_glitch_rate(用于事件速率测量)。
返回在来自当前连接源地址的连接上观察到的前端连接故障的平均速率,以表中配置的周期内的事件量来衡量。通常,这些故障会导致请求或连接中止,因此返回的值通常与过去的连接相关。没有好坏之分,但质量差的客户端可能会偶尔导致每个连接出现一些故障,因此通常预期速率较低。然而,一个非常有故障或恶意的客户端可能会很快导致每个连接添加数千个事件,并在此处保持高速率。另请参阅 sc_glitch_rate 和 src_glitch_cnt。
返回当前代理的 stick-table 或指定 stick-table <table> 中与传入连接的源地址关联的数组中索引为 <idx> 的通用计数器的平均增量率。它报告 gpc 计数器在配置周期内的增量频率。<idx> 是一个介于 0 到 99 之间的整数。请注意,'gpc_rate' 计数器必须存储在 stick-table 中才能返回值,因为 'gpc' 只包含事件计数。此获取仅适用于 'gpc_rate' 数组数据类型(而不适用于旧的 'gpc0_rate' 和 'gpc1_rate' 数据类型)。另请参阅 sc_gpc_rate、src_get_gpc 和 sc_inc_gpc。
返回与当前代理的粘性表或指定粘性表中传入连接的源地址关联的第一个通用计数器的平均增量速率。它报告在配置的时间段内 gpc0 计数器递增的频率。另请参阅 sc/sc0/sc1/sc2_gpc0_rate、src_get_gpc0 和 sc/sc0/sc1/sc2_inc_gpc0。请注意,必须在粘性表中存储“gpc0_rate”计数器才能返回值,因为“gpc0”仅保存事件计数。
返回当前代理的 stick-table 或指定 stick-table 中与传入连接的源地址关联的第二个通用计数器的平均增量率。它报告 gpc1 计数器在配置周期内的增量频率。另请参阅 sc/sc0/sc1/sc2_gpc1_rate、src_get_gpc1 和 sc/sc0/sc1/sc2_inc_gpc1。请注意,“gpc1_rate”计数器必须存储在 stick-table 中才能返回值,因为“gpc1”只包含事件计数。
返回当前代理的 stick-table 或指定 stick-table 中传入连接的源地址的 HTTP 错误总数。这包括请求错误和 4xx 错误响应。另请参阅 sc/sc0/sc1/sc2_http_err_cnt。如果未找到该地址,则返回零。
返回当前代理的粘性表或指定粘性表中,来自传入连接源地址的 HTTP 错误的平均速率,以表中配置的时间段内的错误数量来衡量。这包括请求错误和 4xx 错误响应。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_http_err_rate。
返回当前代理的 stick-table 或指定 stick-table 中由传入连接的源地址触发的 HTTP 响应失败总数。这包括响应错误和除 501 和 505 之外的 5xx 状态码。另请参阅 sc/sc0/sc1/sc2_http_fail_cnt。如果未找到该地址,则返回零。
返回当前代理的 stick-table 或指定 stick-table 中由传入连接的源地址触发的 HTTP 响应失败的平均速率,以配置周期内的失败次数衡量。这包括响应错误和除 501 和 505 之外的 5xx 状态码。如果未找到该地址,则返回零。另请参阅 sc/sc0/sc1/sc2_http_fail_rate。
返回当前代理的 stick-table 或指定 stick-table 中传入连接的源地址的 HTTP 请求总数。这包括每个已启动的请求,无论是否有效。如果未找到该地址,则返回零。另请参阅 sc/sc0/sc1/sc2_http_req_cnt。
返回当前代理的粘性表或指定粘性表中,来自传入连接源地址的 HTTP 请求的平均速率,以表中配置的时间段内的请求数量来衡量。这包括每个已启动的请求,无论其有效与否。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_http_req_rate。
递增当前代理的 stick-table 或指定 stick-table <table> 中与传入连接的源地址关联的数组中索引为 <idx> 的通用计数器,并返回其新值。<idx> 是一个介于 0 到 99 之间的整数。如果未找到该地址,则会创建一个条目并返回 1。此获取仅适用于 'gpc' 数组数据类型(而不适用于旧的 'gpc0' 和 'gpc1' 数据类型)。另请参阅 sc_inc_gpc。
递增与当前连接的源地址相关联的第一个通用计数器,在当前代理的 stick-table 或指定的 stick-table 中,并返回其新值。如果找不到该地址,则创建条目并返回 1。另请参阅 sc0/sc2/sc2_inc_gpc0。这通常用作表达式中的第二个 ACL,以便在第一个 ACL 被验证时标记连接。
acl abuse src_http_req_rate gt 10 acl kill src_inc_gpc0 gt 0 tcp-request connection reject if abuse kill
递增当前代理的 stick-table 或指定 stick-table 中与传入连接的源地址关联的第二个通用计数器,并返回其新值。如果未找到该地址,则会创建一个条目并返回 1。另请参阅 sc0/sc2/sc2_inc_gpc1。这通常用作表达式中的第二个 ACL,以便在验证第一个 ACL 时标记连接。
如果入站连接的源地址是本地的,则返回 true,如果地址不存在于系统中(意味着它来自远程计算机),则返回 false。请注意,UNIX 地址被视为本地的。这有助于根据客户端的来源应用某些访问限制(例如,对远程计算机要求身份验证或 https)。请注意,此检查涉及一些系统调用,因此最好每个连接只执行一次。
返回当前代理的粘性表或指定粘性表中,从传入连接源地址接收的总数据量,以千字节为单位。如果找不到地址,则返回零。该测试目前在 32 位整数上执行,这将值限制为 4 TB。另请参阅 sc/sc0/sc1/sc2_kbytes_in。
返回当前代理的粘性表或指定粘性表中,发送到传入连接源地址的总数据量,以千字节为单位。如果找不到地址,则返回零。该测试目前在 32 位整数上执行,这将值限制为 4 TB。另请参阅 sc/sc0/sc1/sc2_kbytes_out。
返回一个整数值,对应于客户端侧连接的 TCP 源端口,这是客户端连接的端口。任何 tcp/http 规则都可能更改此地址。此函数的使用非常有限,因为现代协议如今对源端口不太关心。
返回当前代理的 stick-table 或指定 stick-table 中传入连接的源 IPv4 地址建立的连接总数,这些连接已转换为会话,这意味着它们已被“tcp-request”规则接受。如果未找到该地址,则返回零。另请参阅 sc/sc0/sc1/sc2_sess_cnt。
返回当前代理的粘性表或指定粘性表中,来自传入连接源地址的平均会话速率,以表中配置的时间段内的会话数量来衡量。会话是通过早期“tcp-request”规则的连接。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_sess_rate。
在当前代理的粘滞表或指定的粘滞表中,为传入连接的源地址创建或更新关联的条目。此表必须配置为存储 "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
返回一个整数,包含处理响应时服务器的 ID。虽然它几乎只用于 ACL,但也可用于日志记录或调试。它也可以在 tcp-check 或 http-check 规则集中使用。
返回一个字符串,包含处理响应时服务器的名称。虽然它几乎只用于 ACL,但也可用于日志记录或调试。它也可以在 tcp-check 或 http-check 规则集中使用。
返回此流在尝试连接到服务器时经历的连接重试次数。在连接完全建立之前,此值可能会发生变化。对于 HTTP 连接,L7 重试可能会影响该值。
根据“option redispatch”配置,如果在重试时发生重新调度,则返回 true。在连接完全建立之前,此值可能会发生变化。对于 HTTP 连接,L7 重试可能会影响该值。
第 5 层通常只描述会话层,在 HAProxy 中,一旦所有连接握手完成,并且在内容可用之前,它最接近会话层。此处描述的获取方法可用于低至“tcp-request content”的规则集,除非它们需要一些未来的信息。这些通常包括 SSL 协商的结果。本节中示例获取方法及其相应类型的摘要。
详细列表
以字符串形式返回请求的属性值,值之间用“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)]
如果从服务器收到当前流的中止(abort)信号,则返回 true。否则返回 false。
此函数旨在供开发人员在某些复杂的故障排除会话中使用。它从后端流和连接的较低层提取一些内部状态,并将它们排列为字符串,通常采用以空格分隔的一系列 "name=value" 形式。可选参数 <bitmap> 指示要从中提取信息的层,并且是以下值的算术 OR(或总和): - 套接字层:16 - 连接层:8 - 传输层(例如 SSL):4 - mux 连接:2 - mux 流:1 这些值可能会在不同版本中更改。默认值 0 是特殊的,启用所有层。请不要依赖此函数的输出来进行长期生产监控。它旨在在稳定分支内发展,因为对增加详细信息的需求不断增加。一个典型的用例是在 log-format 的最后连接这些信息,以及 fs.debug_str()。示例:log-format "$HAPROXY_HTTP_LOG_FMT fs=<%[fs.debug_str]> bs=<%[bs.debug_str]>"
返回服务器端的复用器(multiplexer)流 ID。由复用器负责返回适当的信息。
返回从服务器收到的当前流的重置代码。返回从服务器接收到的 H2 RST_STREAM 帧或 QUIC STOP_SENDING 帧的代码。如果未收到中止信号或服务器流不是 H2/QUIC 流,则此示例获取失败。
当后端连接是通过 SSL/TLS 传输层建立并已本地解密时,返回 true。这意味着出站连接是使用“ssl”选项与服务器建立的。它可以用于 tcp-check 或 http-check 规则集。如果从客户端收到当前流的中止(abort)信号,则返回 true。否则返回 false。
此函数旨在供开发人员在某些复杂的故障排除会话中使用。它从前端流和连接的较低层提取一些内部状态,并将它们排列为字符串,通常采用以空格分隔的一系列 "name=value" 形式。可选参数 <bitmap> 指示要从中提取信息的层,并且是以下值的算术 OR(或总和): - 套接字层:16 - 连接层:8 - 传输层(例如 SSL):4 - mux 连接:2 - mux 流:1 这些值可能会在不同版本中更改。默认值 0 是特殊的,启用所有层。请不要依赖此函数的输出来进行长期生产监控。它旨在在稳定分支内发展,因为对增加详细信息的需求不断增加。一个典型的用例是在 log-format 的最后连接这些信息,以及 bs.debug_str()。示例:log-format "$HAPROXY_HTTP_LOG_FMT fs=<%[fs.debug_str]> bs=<%[bs.debug_str]>"
返回客户端的复用器(multiplexer)流 ID。由复用器负责返回适当的信息。例如,在原始 TCP 上,总是返回 0,因为没有流。
返回从客户端收到的当前流的重置代码。返回从客户端接收到的 H2 RST_STREAM 帧或 QUIC STOP_SENDING 帧的代码。如果未收到中止信号或客户端流不是 H2/QUIC 流,则此示例获取失败。
返回出站连接通过 SSL/TLS 传输层建立时支持的对称密码(cipher)密钥大小(以位为单位)。它可以用于 tcp-check 或 http-check 规则集。
这会从通过 TLS 传输层建立的传出连接中提取应用层协议协商字段。结果是包含与服务器协商的协议名称的字符串。必须使用启用 TLS 扩展支持构建 SSL 库(检查 haproxy -vv)。请注意,除非 "server" 行上的 "alpn" 关键字指定了协议列表,否则不会通告 TLS ALPN 扩展。此外,没有任何东西强制服务器从该列表中选择协议,可以请求任何其他协议。TLS ALPN 扩展旨在取代 TLS NPN 扩展。另请参阅 "ssl_bc_npn"。它可用于 tcp-check 或 http-check 规则集。
返回通过 SSL/TLS 传输层建立的出站连接所使用的密码(cipher)的名称。它可以用于 tcp-check 或 http-check 规则集。
当入站连接通过 SSL/TLS 传输层建立时,返回后端连接的客户端随机数(client random)。它对于解密使用临时密码(ephemeral ciphers)发送的流量很有用。这需要 OpenSSL >= 1.1.0,或 BoringSSL。它可以用于 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”。
当通过 TLS 1.3 传输层建立出站连接时,返回 CLIENT_TRAFFIC_SECRET_0 作为十六进制字符串,用于后端连接。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调用于生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志记录必须通过全局部分的“tune.ssl.keylog on”进行激活。另请参阅“tune.ssl.keylog”。
当通过 TLS 1.3 传输层建立出站连接时,返回 EXPORTER_SECRET 作为十六进制字符串,用于后端连接。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调用于生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志记录必须通过全局部分的“tune.ssl.keylog on”进行激活。另请参阅“tune.ssl.keylog”。
当通过 TLS 1.3 传输层建立出站连接时,返回 EARLY_EXPORTER_SECRET 作为十六进制字符串,用于后端连接。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调用于生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志记录必须通过全局部分的“tune.ssl.keylog on”进行激活。另请参阅“tune.ssl.keylog”。
返回通过 SSL/TLS 传输层建立连接时使用的密钥协议的曲线名称。这需要 OpenSSL >= 3.0.0。
当出站连接通过 SSL/TLS 传输层建立时,返回后端端最后一个错误堆栈的第一个错误的 ID。它可能引发握手错误以及连接生命周期中发生的其他读写错误。为了获得此错误代码的文本描述,您可以使用“ssl_bc_err_str”示例获取,或使用“openssl errstr”命令(该命令以十六进制表示形式的错误代码作为参数)。请参考您的 SSL 库文档以查找错误代码的完整列表。
当出站连接通过 SSL/TLS 传输层建立时,返回后端角度的连接上发生的最后一个错误堆栈的第一个错误的字符串表示。另请参阅“ssl_fc_err”。
当后端连接通过 SSL/TLS 传输层建立,并且新创建的 SSL 会话是通过缓存会话或 TLS 票据恢复的,则返回 true。它可以用于 tcp-check 或 http-check 规则集。
这会从通过 TLS 传输层建立的传出连接中提取下一个协议协商字段。结果是包含与服务器协商的协议名称的字符串。必须使用启用 TLS 扩展支持构建 SSL 库(检查 haproxy -vv)。请注意,除非 "server" 行上的 "npn" 关键字指定了协议列表,否则不会通告 TLS NPN 扩展。此外,没有任何东西强制客户端从该列表中选择协议,可以使用任何其他协议。请注意,TLS NPN 扩展已被 ALPN 取代。它可用于 tcp-check 或 http-check 规则集。
返回通过 SSL/TLS 传输层建立的出站连接所使用的协议的名称。它可以用于 tcp-check 或 http-check 规则集。
当出站连接通过 SSL/TLS 传输层建立时,返回 RFC 5929 第 3 节定义的 TLS 唯一 ID。可以使用转换器将唯一 ID 编码为 base64:“ssl_bc_unique_id,base64”。它可以用于 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”。
当通过 TLS 1.3 传输层建立出站连接时,返回 SERVER_TRAFFIC_SECRET_0 作为十六进制字符串,用于后端连接。需要 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 规则集。
当出站连接通过 SSL/TLS 传输层建立时,返回后端连接的 SSL ID。如果想要知道会话是否被重用,它对于日志记录很有用。它可以用于 tcp-check 或 http-check 规则集。
当出站连接通过 SSL/TLS 传输层建立时,返回后端连接的 SSL 会话主密钥。它对于解密使用临时密码(ephemeral ciphers)发送的流量很有用。这需要 OpenSSL >= 1.1.0,或 BoringSSL。它可以用于 tcp-check 或 http-check 规则集。
此项检索连接到服务器时使用的服务器名称指示(Server Name Indication, SNI)TLS 扩展字段。返回的结果(如果存在)通常是一个字符串,匹配 HTTPS 主机名(最多 253 个字符)。主要用例是用于日志记录和调试目的(例如,在建立连接时找出使用的 SNI,并将其与服务器看到的进行匹配)。
返回出站连接通过 SSL/TLS 传输层建立时使用的对称密码(cipher)密钥大小(以位为单位)。它可以用于 tcp-check 或 http-check 规则集。
当传入连接通过 SSL/TLS 传输层建立时,如果在验证深度 > 0 的客户端证书期间检测到第一个错误,则返回该错误的 ID;如果在此验证过程中未遇到错误,则返回 0。请参考您的 SSL 库文档以查找完整的错误代码列表。
当传入连接通过 SSL/TLS 传输层建立时,如果在验证客户端证书期间检测到第一个错误,则返回该错误在 CA 链中的深度。如果未遇到错误,则返回 0。
当入站连接通过 SSL/TLS 传输层建立时,返回客户端提供的 DER 格式的链证书。当用于 ACL 时,可以以十六进制形式传递要匹配的值。可以使用任何接受 ASN.1 DER 数据的库来解析结果。它目前不支持恢复的会话。
当传入连接通过 SSL/TLS 传输层建立时,返回由客户端提供的 DER 格式证书。当用于 ACL 时,用于匹配的值可以以十六进制形式传递。
当传入连接通过 SSL/TLS 传输层建立时,如果在深度为 0 的验证期间检测到第一个错误,则返回该错误的 ID;如果在此验证过程中未遇到错误,则返回 0。请参考您的 SSL 库文档以查找完整的错误代码列表。
当入站连接通过 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/TLS 传输层建立时,返回用于生成客户端证书密钥的算法名称。
当传入连接通过 SSL/TLS 传输层建立时,返回客户端证书中显示的结束日期,格式为 YYMMDDhhmmss[Z] 字符串。
当传入连接通过 SSL/TLS 传输层建立时,返回客户端证书中显示的开始日期,格式为 YYMMDDhhmmss[Z] 字符串。
当入站连接通过 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/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/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/TLS 传输层建立时,返回客户端证书的序列号。当用于 ACL 时,用于匹配的值可以以十六进制形式传递。
当传入连接通过 SSL/TLS 传输层建立时,返回客户端证书的 SHA-1 指纹。这可用于将客户端粘滞到某个服务器,或将此信息传递给服务器。请注意,输出是二进制格式,因此如果要将该签名传递给服务器,您需要将其编码为十六进制或 base64,如下例所示:
http-request set-header X-SSL-Client-SHA1 %[ssl_c_sha1,hex]
当传入连接通过 SSL/TLS 传输层建立时,返回用于签署客户端证书的算法名称。
如果当前 SSL 会话使用了客户端证书,则返回 true,即使当前连接使用的是 SSL 会话恢复。另请参阅 "ssl_fc_has_crt"。
当传入连接通过 SSL/TLS 传输层建立时,返回验证结果的错误 ID;如果未遇到错误,则返回零。有关完整的错误代码列表,请参考您的 SSL 库文档。
当传入连接通过 SSL/TLS 传输层建立时,返回客户端证书的版本。
当传入连接通过 SSL/TLS 传输层建立时,返回前端提供的 DER 格式证书。当用于 ACL 时,用于匹配的值可以以十六进制形式传递。
当入站连接通过 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/TLS 传输层建立时,返回用于生成前端证书密钥的算法名称。
当传入连接通过 SSL/TLS 传输层建立时,返回前端证书中显示的结束日期,格式为 YYMMDDhhmmss[Z] 字符串。
当传入连接通过 SSL/TLS 传输层建立时,返回前端证书中显示的开始日期,格式为 YYMMDDhhmmss[Z] 字符串。
当入站连接通过 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/TLS 传输层建立时,返回前端证书的序列号。当用于 ACL 时,用于匹配的值可以以十六进制形式传递。
当传入连接通过 SSL/TLS 传输层建立时,返回前端证书的 SHA-1 指纹。这可用于了解使用 SNI 选择了哪个证书。
当传入连接通过 SSL/TLS 传输层建立时,返回用于签署前端证书的算法名称。
当传入连接通过 SSL/TLS 传输层建立时,返回前端证书的版本。
当前端连接通过 SSL/TLS 传输层建立并在本地解密时返回 true。这意味着它匹配了一个使用带有 "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 传输层建立时,返回支持的对称加密密钥大小(以位为单位)。
这会从通过 TLS 传输层建立并由 HAProxy 在本地解密的传入连接中提取应用层协议协商字段。结果是包含客户端通告的协议名称的字符串。必须使用启用 TLS 扩展支持构建 SSL 库(检查 haproxy -vv)。请注意,除非 "bind" 行上的 "alpn" 关键字指定了协议列表,否则不会通告 TLS ALPN 扩展。此外,没有任何东西强制客户端从该列表中选择协议,可以请求任何其他协议。TLS ALPN 扩展旨在取代 TLS NPN 扩展。另请参阅 "ssl_fc_npn"。
当传入连接通过 SSL/TLS 传输层建立时,返回所使用的加密套件的名称。
返回客户端 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
以十六进制编码的形式返回客户端 hello 密码列表的二进制形式。最大返回值的长度受由“tune.ssl.capture-buffer-size”设置控制的共享捕获缓冲区大小的限制。设置 <filter_option> 允许过滤返回的数据。可接受的值:0:返回完整的密码列表(默认)1:从输出中排除 GREASE(RFC8701)值
返回客户端 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 时才有效,但哈希值考虑了密码列表的所有数据。
当入站连接通过 SSL/TLS 传输层建立时,返回密钥协议(key agreement)中使用的曲线的名称。这需要 OpenSSL >= 3.0.0。
返回客户端 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
返回客户端 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
返回客户端 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/TLS 传输层建立时,返回前端连接的客户端随机数(client random)。它对于解密使用临时密码(ephemeral ciphers)发送的流量很有用。这需要 OpenSSL >= 1.1.0,或 BoringSSL。
当通过 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”。
当通过 TLS 1.3 传输层建立入站连接时,返回 CLIENT_TRAFFIC_SECRET_0 作为十六进制字符串,用于前端连接。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调用于生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志记录必须通过全局部分的“tune.ssl.keylog on”进行激活。另请参阅“tune.ssl.keylog”。
当通过 TLS 1.3 传输层建立入站连接时,返回 EXPORTER_SECRET 作为十六进制字符串,用于前端连接。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调用于生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志记录必须通过全局部分的“tune.ssl.keylog on”进行激活。另请参阅“tune.ssl.keylog”。
当通过 TLS 1.3 传输层建立入站连接时,返回 EARLY_EXPORTER_SECRET 作为十六进制字符串,用于前端连接。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调用于生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志记录必须通过全局部分的“tune.ssl.keylog on”进行激活。另请参阅“tune.ssl.keylog”。
当入站连接通过 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”。
如果传入的 SSL/TLS 传输层连接中存在客户端证书,则返回 true。在 'verify' 语句设置为 'optional' 时很有用。注意:在使用会话 ID 或 TLS 票据进行 SSL 会话恢复时,当前连接中不存在客户端证书,但可以从缓存或票据中检索。因此,如果您想检查当前 SSL 会话是否使用了客户端证书,请优先使用 "ssl_c_used"。
如果发送了早期数据且握手尚未完成,则返回 true。由于它具有安全隐患,因此能够拒绝这些数据或等到握手完成(通过 "wait-for-handshake" 操作)非常有用。
这会检查入站连接是否通过 SSL/TLS 传输层建立,以及是否包含服务器名称指示(Server Name Indication, SNI)TLS 扩展。当入站连接提供 TLS SNI 字段时,返回 true。这需要 SSL 库已构建为支持 TLS 扩展(请检查 haproxy -vv)。
如果通过 SSL/TLS 传输层传入的连接上,SSL/TLS 会话已通过使用 SSL 会话缓存或 TLS 票据得到恢复,则返回 true。
这会从通过 TLS 传输层建立并由 HAProxy 在本地解密的传入连接中提取下一个协议协商字段。结果是包含客户端通告的协议名称的字符串。必须使用启用 TLS 扩展支持构建 SSL 库(检查 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
当连接通过 SSL/TLS 传输层建立时,返回 RFC5929 第 3 节中定义的 TLS 唯一 ID。可以使用转换器 "ssl_fc_unique_id,base64" 将唯一 ID 编码为 base64。
当传入连接通过 TLS 1.3 传输层建立时,以十六进制字符串形式返回前端连接的 SERVER_HANDSHAKE_TRAFFIC_SECRET。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调函数转储以生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志必须在全局部分使用 "tune.ssl.keylog on" 激活。另请参阅 "tune.ssl.keylog"
当传入连接通过 TLS 1.3 传输层建立时,以十六进制字符串形式返回前端连接的 SERVER_TRAFFIC_SECRET_0。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调函数转储以生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志必须在全局部分使用 "tune.ssl.keylog on" 激活。另请参阅 "tune.ssl.keylog"
在连接通过 SSL/TLS 传输层建立时,返回前端连接的服务器随机数。这对于解密使用临时密码发送的流量非常有用。这需要 OpenSSL >= 1.1.0 或 BoringSSL。
当传入连接通过 SSL/TLS 传输层建立时,返回前端连接的 SSL ID。这对于将给定客户端粘滞到某个服务器很有用。需要注意的是,某些浏览器每隔几分钟就会刷新其会话 ID。
在连接通过 SSL/TLS 传输层建立时,返回前端连接的 SSL 会话主密钥。这对于解密使用临时密码发送的流量非常有用。这需要 OpenSSL >= 1.1.0 或 BoringSSL。
返回客户端 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/TLS 传输层建立并由 HAProxy 在本地解密的传入连接中提取 Server Name Indication (SNI) TLS 扩展字段。结果(如果存在)通常是匹配 HTTPS 主机名(253 个字符或更少)的字符串。必须使用启用 TLS 扩展支持构建 SSL 库(检查 haproxy -vv)。此获取与上面的 "req.ssl_sni" 不同,因为它适用于 HAProxy 正在解密的连接,而不是盲目转发的 SSL 内容。另请参阅下面的 "ssl_fc_sni_end" 和 "ssl_fc_sni_reg"。这需要使用启用 TLS 扩展支持构建 SSL 库(检查 haproxy -vv)。注意!除非在非常特定的条件下,否则使用此字段代替 HTTP "Host" 标头字段通常是不正确的。例如,将 HTTPS 连接转发到服务器时,必须使用 "req.hdr(host)" 而不是前端 SNI 值设置 SNI 字段。原因是 SNI 仅用于选择服务器端将呈现的证书,并且允许客户端发送具有不同 Host 值(只要它们匹配证书中的名称)的请求。因此,"ssl_fc_sni" 通常不应作为 "sni" 服务器关键字的参数使用,除非后端在 TCP 模式下工作。ACL 派生词:ssl_fc_sni_end:后缀匹配 ssl_fc_sni_reg:正则表达式匹配
返回客户端 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 传输层建立时,返回实际使用的对称加密密钥大小(以位为单位)。
当出站连接通过 SSL/TLS 传输层建立时,返回服务器呈现的 DER 格式的证书。当用于 ACL 时,用于匹配的值可以以十六进制形式传递。
当出站连接通过 SSL/TLS 传输层建立时,返回服务器呈现的 DER 格式的链证书。当用于 ACL 时,用于匹配的值可以以十六进制形式传递。可以使用任何接受 ASN.1 DER 数据的库来解析结果。它目前不支持恢复的会话。
当出站连接通过 SSL/TLS 传输层建立时,返回用于生成服务器呈现的证书密钥的算法名称。
当出站连接通过 SSL/TLS 传输层建立时,以 YYMMDDhhmmss[Z] 格式的字符串返回服务器呈现的到期日期。
当出站连接通过 SSL/TLS 传输层建立时,以 YYMMDDhhmmss[Z] 格式的字符串返回服务器呈现的开始日期。
当出站连接通过 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/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/TLS 传输层建立时,返回服务器呈现的证书序列号。当用于 ACL 时,用于匹配的值可以以十六进制形式传递。
当出站连接通过 SSL/TLS 传输层建立时,返回服务器呈现的证书的 SHA-1 指纹。这可以用来知道使用 SNI 选择的证书。
当出站连接通过 SSL/TLS 传输层建立时,返回用于签名服务器呈现的证书的算法名称。
当出站连接通过 SSL/TLS 传输层建立时,返回服务器呈现的证书的版本。
从客户端看到的总估计时间,从代理接受它到双方都关闭,不包括空闲时间。这相当于日志格式中的 %Tu,并以毫秒 (ms) 为单位报告。有关更多详细信息,请参阅第 8.4 节“计时事件”。
从缓冲区内容中提取样本与上面介绍的样本提取方式有所不同,因为采样数据是瞬态的。这些数据只有在可用时才能被使用,一旦转发就会丢失。因此,在请求期间从缓冲区内容中提取的样本不能用于响应中。即使在数据被提取的过程中,它们也可能发生变化。有时需要设置一些延迟或结合多种样本提取方法,以确保预期数据完整且可用,例如通过TCP请求内容检查。有关该主题的详细信息,请参阅“tcp-request content”关键字。警告:如果在HTTP代理中使用,以下样本提取将被忽略。它们只处理缓冲区中的原始内容。HTTP代理使用结构化内容。因此,这些数据的原始表示没有意义。如果ACL依赖于以下样本提取之一,将发出警告。但无法检测所有无效使用情况(例如在自定义日志格式或样本表达式内部)。因此请务必小心。本节中样本提取方法的摘要及其各自的类型
详细列表
解析 distcc 消息并返回与 token <token> 的 occurrence #<occ> 关联的正文。Occurrence 从 1 开始,如果未指定,则任何 occurrence 都可能匹配,但实际上目前只检查第一个。这可以用于提取通过 HAProxy 构建的文件中的文件名或参数。有关支持的 token 的完整列表,请参阅 distcc 的协议文档。
解析 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 }
这是 "req.payload" 在请求上下文(例如,“stick on”、“stick match”)中的别名,在响应上下文(例如“stick store response”)中是 "res.payload" 的别名。
这是 "req.payload_lv" 在请求上下文(例如,“stick on”、“stick match”)中的别名,在响应上下文(例如“stick store response”)中是 "res.payload_lv" 的别名。
返回请求缓冲区中存在的字节数。这主要用于 ACL。重要的是要理解,只要缓冲区在变化,此测试就不会返回 false。这意味着等于零的检查几乎总是在会话开始时立即匹配,而对更多数据的测试将等待数据进入,直到 HAProxy 确定不再有数据进来时才返回 false。此测试旨在与 TCP 请求内容检查一起使用。
这会从请求缓冲区中提取 <length> 字节的二进制块,从字节 <offset> 开始。作为特殊情况,如果 <length> 参数为零,则提取从 <offset> 到末尾的整个缓冲区。这可以与 ACL 一起使用,以检查缓冲区中任何位置是否存在某些内容。ACL 派生:req.payload(<offset>,<length>):十六进制二进制匹配
这会提取一个二进制块,其大小由 <offset1> 指定 <length> 字节,如果指定了 <offset2>,则从该位置开始,否则紧跟在请求缓冲区中的长度之后。<offset2> 参数如果以 '+' 或 '-' 符号开头,也支持相对偏移。ACL 派生:req.payload_lv(<offset1>,<length>[,<offset2>]):十六进制二进制匹配
请参考 "stick store-response" 关键字中的示例。
当请求缓冲区中的数据看起来像 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
当请求缓冲区看起来像 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
尝试将请求缓冲区解析为 RDP 协议,然后返回一个整数,表示找到的 RDP cookie 的数量。如果提供了可选的 cookie 名称,则只考虑匹配该名称的 cookie。这主要用于 ACL。ACL 派生:req.rdp_cookie_cnt([<name>]):整数匹配
返回一个字符串,其中包含客户端在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
返回一个布尔值,用于标识客户端是否在SSL ClientHello消息中发送了RFC4492第5.1节中定义的Supported Elliptic Curves Extension。这可用于向支持ECC的客户端提供EC证书,而对其他客户端使用RSA,所有这些都在同一个IP地址上。请注意,这仅适用于请求缓冲区中的原始内容,而不适用于通过SSL数据层解密的内容,因此这不适用于带有“ssl”选项的“bind”行。
如果请求缓冲区中的数据可解析为完整的SSL(v3或更高版本)客户端Hello消息,则返回一个整数值,其中包含该SSL Hello消息的类型。请注意,这仅适用于请求缓冲区中的原始内容,而不适用于通过SSL数据层解密的内容,因此这不适用于带有“ssl”选项的“bind”行。这主要用于ACL中,以检测假定包含可用于粘性会话的SSL会话ID的SSL Hello消息的存在。
如果缓冲区包含可解析为完整的SSL(v3或更高版本)客户端Hello消息的数据,则返回一个字符串,其中包含客户端在通过请求缓冲区时发送的Server Name TLS扩展的值。请注意,这仅适用于请求缓冲区中的原始内容,而不适用于通过SSL数据层解密的内容,因此这不适用于带有“ssl”选项的“bind”行。这仅适用于实际的隐式TLS协议,如HTTPS (443)、IMAPS (993)、SMTPS (465),但不适用于显式TLS协议,如SMTP (25/587)或IMAP (143)。SNI通常包含客户端尝试连接的主机名(对于新版浏览器)。当客户端使用SSL/TLS时,SNI对于允许或拒绝访问特定主机非常有用。此测试旨在与TCP请求内容检查一起使用。如果需要内容切换,建议首先等待完整的客户端Hello(类型1),如下例所示。另请参阅“ssl_fc_sni”。ACL衍生品:req.ssl_sni:精确字符串匹配
# 等待客户端 hello 最多 5 秒 tcp-request inspect-delay 5s tcp-request content accept if { req.ssl_hello_type 1 } use_backend bk_allow if { req.ssl_sni -f allowed_sites } default_backend bk_sorry_page
如果客户端未发送SessionTicket TLS Extension (RFC5077),则返回0;如果客户端发送了SessionTicket TLS Extension,则返回1;如果客户端也发送了非零长度的TLS SessionTicket,则返回2。请注意,这仅适用于请求缓冲区中的原始内容,而不适用于通过SSL数据层解密的内容,因此这不适用于带有“ssl”选项的“bind”行。例如,这可用于检测客户端是否发送了SessionTicket,并相应地进行粘性处理,如果没有SessionTicket,则基于SessionID进行粘性处理,或者不进行粘性处理,因为在使用SessionTicket时服务器端没有状态。
返回一个整数值,其中包含请求缓冲区中存在的流的SSL/TLS协议版本。支持SSLv2 Hello消息和SSLv3消息。TLSv1被宣布为SSL版本3.1。该值由主版本乘以65536,再加上次版本组成。请注意,这仅适用于请求缓冲区中的原始内容,而不适用于通过SSL数据层解密的内容,因此这不适用于带有“ssl”选项的“bind”行。ACL版本的测试匹配MAJOR.MINOR形式的十进制表示法(例如3.1)。此提取主要用于ACL。ACL衍生品:req.ssl_ver:十进制匹配
返回响应缓冲区中存在的字节数的整数值。这主要用于 ACL。重要的是要理解,只要缓冲区在变化,此测试就不会返回 false。这意味着等于零的检查几乎总是在流开始时立即匹配,而对更多数据的测试将等待数据进入,直到 HAProxy 确定不再有数据进来时才返回 false。此测试旨在与 TCP 响应内容检查一起使用。但也可用于基于 tcp-check 的 expect 规则。
这会从响应缓冲区中提取 <length> 字节的二进制块,从字节 <offset> 开始。作为特殊情况,如果 <length> 参数为零,则提取从 <offset> 到末尾的整个缓冲区。这可以与 ACL 一起使用,以检查缓冲区中任何位置是否存在某些内容。它也可用于基于 tcp-check 的 expect 规则。
这会提取一个二进制块,其大小由 <offset1> 指定 <length> 字节,如果指定了 <offset2>,则从该位置开始,否则紧跟在响应缓冲区中的长度之后。<offset2> 参数如果以 '+' 或 '-' 符号开头,也支持相对偏移。它也可用于基于 tcp-check 的 expect 规则。
请参考 "stick store-response" 关键字中的示例。
如果响应缓冲区中的数据可解析为完整的SSL(v3或更高版本)Hello消息,则返回一个整数值,其中包含该SSL Hello消息的类型。请注意,这仅适用于响应缓冲区中的原始内容,而不适用于通过SSL数据层解密的内容,因此这不适用于带有“ssl”选项的“server”行。这主要用于ACL中,以检测假定包含可用于粘性会话的SSL Hello消息的存在。
可以从HTTP内容、请求和响应中提取样本。此应用层也称为第7层。只有当从各自的请求或响应缓冲区解析出完整的HTTP请求或响应时,才能提取本节中的数据。对于所有HTTP特定规则和运行在“mode http”下的部分,情况总是如此。使用TCP内容检查时,可能需要支持检查延迟,以便首先接收请求或响应。这些提取可能比第4层的提取需要更多的CPU资源,但由于请求和响应已建立索引,因此不会太多。注意:对于来自tcp-request内容规则的HTTP处理,一切都将如HTTP代理所期望的那样工作。但是,对于TCP代理,如果没有HTTP升级,它只适用于HTTP/1内容。对于HTTP/2内容,只能看到序言。因此,只能依赖“req.proto_http”、“req.ver”和最终的“method”样本提取。所有其他L7样本提取都将失败。在HTTP升级之后,它们将以与HTTP代理相同的方式工作。本节中样本提取方法的摘要及其各自的类型
详细列表
此函数返回第一个 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:子串匹配
此函数返回上面 "base" 获取方法返回值的 32 位哈希值。这对于在高流量网站上跟踪每个 URL 的活动很有用,而无需存储所有 URL。相反,存储一个更短的哈希值,可以节省大量内存。输出类型是无符号整数。使用的哈希函数是 SDBM,输出具有完全雪崩效应。技术上,base32 完全等同于 "base,sdbm(1)"。
此函数返回上面 base32 获取结果和下面 src 获取结果的拼接。结果类型为 binary,大小为 8 或 20 字节,具体取决于源地址族。这可用于跟踪每个 IP、每个 URL 的计数器。
这会返回第一个 Host 标头与请求的路径部分(包含查询字符串)的连接,路径从第一个斜杠开始。使用此项而不是“base”可以正确标识目标资源,用于统计或缓存用例。另请参阅“path”、“pathq”和“base”。
此函数提取由 "capture request header" 捕获的头部内容,idx 是 capture 关键字在配置中的位置。
此函数提取 HTTP 请求的 METHOD。它可以在请求和响应中使用。与 "method" 不同,因为它被分配了内存,所以可以在请求和响应中使用。
capture.req.uri : string
此函数提取请求的 HTTP 版本,并返回 "HTTP/1.0" 或 "HTTP/1.1"。与 "req.ver" 不同,因为它依赖于一个持久性标志,所以可以在请求、响应和日志中使用。
此函数提取由 "capture response header" 捕获的头部内容,idx 是 capture 关键字在配置中的位置。第一个条目的索引为 0。
此函数提取响应的 HTTP 版本,并返回 "HTTP/1.0" 或 "HTTP/1.1"。与 "res.ver" 不同,因为它依赖于一个持久性标志,所以可以在日志中使用。
这会返回 HTTP 请求的可用正文作为数据块。建议使用 "option http-buffer-request" 来确保尽可能等待请求的正文。
此获取假定 POST 请求的正文是 url 编码的。用户可以检查“content-type”是否包含值“application/x-www-form-urlencoded”。这会提取正文中参数 <name> 的第一次出现,该参数在 '&' 之前结束。参数名称区分大小写,除非添加 "i" 作为第二个参数。如果未给出名称,则任何参数都将匹配,并返回第一个。结果是对应于请求正文中参数 <name> 值的字符串(不执行 URL 解码)。请注意,此获取的 ACL 版本会迭代多个参数,如果未给出名称,则会迭代并报告所有参数值。
这会返回 HTTP 请求可用正文的长度(以字节为单位)。如果正文大于缓冲区,则其长度可能小于广告长度。建议使用 "option http-buffer-request" 来确保尽可能等待请求的正文。
这会返回 HTTP 请求正文的广告长度(以字节为单位)。它将代表广告的 Content-Length 标头,或在分块编码情况下可用数据的大小。
这会从请求的“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>]):子字符串匹配
返回一个整数值,表示名为 <name> 的 cookie 在请求中出现的次数;如果未指定 <name>,则表示所有 cookie 的数量。
此函数从请求的 "Cookie" 头部行中提取名为 <name> 的 cookie 的最后一次出现,并将其值转换为整数返回。如果未指定名称,则返回第一个 cookie 的值。在 ACL 中使用时,将遍历所有匹配的名称,直到找到一个匹配的值。
在规则求值时,此函数会创建一个字符串,该字符串由请求(Cookie 标头)中出现的所有 cookie 名称连接而成。默认分隔符是逗号 (','),但可以作为可选参数 <delim> 覆盖。在这种情况下,只考虑 <delim> 的第一个字符。从请求的“Cookie”标头行中提取 cookie 名称 <name> 的最后一次出现,或从响应的“Set-Cookie”标头中提取,并返回其值作为字符串。典型的用途是让共享相同配置文件的多个客户端使用相同的服务器。这可以与“appsession”通过“request-learn”语句所做的类似,但支持多对同步和跨重启的状态保持。如果未指定名称,则返回第一个 cookie 值。此获取不应再使用,应替换为 req.cook() 或 res.cook(),因为它根据使用它的上下文含糊地使用方向。
在请求上使用时,此函数等同于 req.hdr();在响应上使用时,等同于 res.hdr()。有关更多详细信息,请参考这些各自的获取。如果不确定获取方向,请使用明确的函数。请注意,与 hdr() 样本获取方法相反,hdr_* ACL 关键字明确地应用于请求头部。
这是 HAProxy 接收到 HTTP 请求的第一个字节的确切日期(日志格式别名 %tr)。这是从 accept_date + handshake time (%Th) + idle time (%Ti) 计算得出的。返回自 epoch 以来的秒数。<unit> 是可选的,可以设置为“s”表示秒(默认行为),“ms”表示毫秒或“us”表示微秒。如果设置了 unit,则返回值是一个整数,表示自 epoch 以来的秒、毫秒或微秒。当需要小于一秒的时间分辨率时,它很有用。
返回 HTTP 请求中标头 <name> 的最后一次出现的完整值。它与 req.hdr() 的区别在于,它会返回值中存在的任何逗号,而不会将它们用作分隔符。这有时对 User-Agent 等标头很有用。从 ACL 使用时,会迭代所有出现直到找到匹配。可选地,可以通过位置编号指定特定的出现次数。正数表示从第一次出现开始的位置,1 是第一个。负数表示相对于最后一个的位置,-1 是最后一个。一个典型的用途是与 X-Forwarded-For 标头(在转换为 IP 后)相关联。
返回请求标头字段名称 <name> 的出现次数的整数值,如果未指定 <name>,则返回总标头字段数。与 req.fhdr() 不同,它不会在逗号处分割标头。ACL 中,它可以用于检测特定标头的存在、不存在或滥用,以及通过拒绝包含多个特定标头的请求来阻止请求伪装攻击。有关标头匹配的更多信息,请参阅 req.hdr()。
这将返回HTTP请求中header的最后一个逗号分隔值。提取将任何逗号视为不同值的分隔符。如果您需要处理定义为值列表的header(例如Accept或X-Forwarded-For),这将非常有用。如果需要完整的行header,请使用req.fhdr()。请仔细检查RFC 7231以了解某些header应如何解析。此外,其中一些是不区分大小写的(例如Connection)。在ACL中使用时,所有出现都会被迭代,直到找到匹配项。可选地,可以指定特定出现的序数。正值表示从第一次出现开始的位置,1是第一个。负值表示相对于最后一次出现的位置,-1是最后一个。一个典型用途是与X-Forwarded-For header一起使用,一旦转换为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>]]):子字符串匹配
返回请求标头字段名称 <name> 的出现次数的整数值,如果未指定 <name>,则返回所有标头字段值。与 req.hdr() 一样,它计算标头值中每个逗号分隔的部分。如果需要计算完整的行标头,则应改用 req.fhdr_cnt()。使用 ACL,它可以用于检测特定标头的存在、不存在或滥用,以及通过拒绝包含多个特定标头的请求来阻止请求伪装攻击。有关更多信息,请参阅 req.hdr()。
提取 HTTP 请求中最后一个标头 <name> 的值,将其转换为 IPv4 或 IPv6 地址,并返回该地址。与 ACL 一起使用时,会检查所有出现;如果省略 <name>,则检查每个标头的所有值。解析器严格遵循 RFC7239 中描述的格式,并扩展支持 IPv4 地址后面可选地跟着一个冒号 (':') 和一个有效的十进制端口号(0 到 65535),该端口号将被静默删除。所有其他格式将不匹配并导致地址被忽略。<occ> 参数的处理方式与 req.hdr() 相同。典型的用法是 X-Forwarded-For 和 X-Client-IP 标头。提取 HTTP 请求中最后一个标头 <name> 的值,并将其转换为整数值。与 ACL 一起使用时,会检查所有出现;如果省略 <name>,则检查每个标头的所有值。<occ> 参数的处理方式与 req.hdr() 相同。典型的用法是 X-Forwarded-For 标头。
以字符串形式返回当前请求标头,包括分隔标头和请求正文的最后空行。最后空行可用于检测截断的标头块。此样本获取对于某些 SPOE 标头分析器和高级日志记录非常有用。
以预解析的二进制形式返回当前请求标头。这对于使用 SPOE 进行部分处理非常有用。每个字符串由长度后面跟着长度指示的字节数描述。长度使用 SPOE 文档中详细的可变整数编码表示。列表的末尾由一对空标头名称和值(长度均为 0)标记。*(<str:header-name><str:header-value>)<empty string><empty string> int:参考 SPOE 文档的编码 str:<int:length><bytes>
获取客户端请求的总时间(仅限 HTTP 模式)。这是从接收到第一个字节到代理接收到标记 HTTP 标头结束的空行之间经过的时间。以毫秒 (ms) 为单位报告,相当于日志格式中的 %TR。有关更多详细信息,请参阅第 8.4 节“计时事件”。
这是 HTTP 请求之前的空闲时间(仅限 HTTP 模式)。此计时器在握手结束和 HTTP 请求的第一个字节之间进行计数。以毫秒为单位报告,相当于日志格式中的 %Ti。有关更多详细信息,请参阅第 8.4 节“计时事件”。
在队列中等待连接槽的总时间。以毫秒为单位报告,相当于日志格式中的 %Tw。有关更多详细信息,请参阅第 8.4 节“计时事件”。
从接受日期或自上一个响应的最后一个字节发出以来,获取客户端请求的总时间。以毫秒为单位报告,相当于日志格式中的 %Tq。有关更多详细信息,请参阅第 8.4 节“计时事件”。
这是从建立到服务器的 TCP 连接到服务器发送其完整响应标头之间经过的时间。以毫秒为单位报告,相当于日志格式中的 %Tr。有关更多详细信息,请参阅第 8.4 节“计时事件”。
返回一个布尔值,指示从客户端收到的身份验证数据是否与指定用户列表中存储的用户名和密码匹配。此获取函数在 ACL 之外并不真正有用。目前仅支持 http 基本身份验证。
返回客户端在使用 Bearer 方案(例如,发送 JSON Web Tokens)的授权数据中找到的客户端提供的 token。不对客户端发送的数据执行任何检查。如果提供了特定的 <header>,它将解析该标头而不是 Authorization 标头。
如果从客户端收到的身份验证数据中的用户名和密码根据指定用户列表均有效,则返回一个对应于该用户名的字符串。其主要目的是在 ACL 中使用,然后检查该用户是否属于列表中的任何组。此获取函数在 ACL 之外并不真正有用。目前仅支持 http 基本身份验证。ACL 派生词:http_auth_group(<userlist>) : group ... 当从请求中提取的用户(其密码根据指定用户列表有效)属于至少一个组时返回 true。
返回用户在从客户端接收到的身份验证数据中找到的密码,该数据在 Authorization 标头中提供。此样本获取不执行任何检查。仅支持 Basic 身份验证。
返回用户在从客户端接收到的身份验证数据中找到的身份验证方法,该数据在 Authorization 标头中提供。此样本获取不执行任何检查。仅支持 Basic 身份验证。
返回用户在从客户端接收到的身份验证数据中找到的用户名,该数据在 Authorization 标头中提供。此样本获取不执行任何检查。仅支持 Basic 身份验证。
当正在处理的请求是连接的第一个请求时返回 true。这可用于添加或删除在请求不是第一个时某些请求中可能缺少的头部,或帮助在日志中对请求进行分组。
返回一个对应于 HTTP 请求中方法的整数值。例如,"GET" 等于 1(检查源代码以确定匹配关系)。值 9 表示“其他方法”,并可能转换为从流中提取的字符串。这不应直接用作样本,它仅用于 ACL,ACL 会透明地将方法从模式转换为这些整数 + 字符串值。一些预定义的 ACL 已经检查了最常见的方法。ACL 派生词:method:不区分大小写的方法匹配
# 只接受 GET 和 HEAD 请求 acl valid_method method GET HEAD http-request deny if ! valid_method
这会提取请求的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:子字符串匹配
这会提取请求的 URL 路径(包含查询字符串),路径从第一个斜杠开始。这个样本获取非常方便,可以始终检索相对 URI,不包括 scheme 和 authority 部分(如果有)。事实上,虽然这是 HTTP/1.1 请求目标的一种常见表示,但在 HTTP/2 中,通常使用绝对 URI。这个样本获取在这两种情况下都会返回相同的结果。请注意,URI 中的任何片段引用(路径后的“#”)都严格禁止由 HTTP 标准,并将被拒绝。但是,如果接收请求的前端具有“option accept-unsafe-violations-in-http-request”,则将接受此片段部分,并且它也会出现在路径中。
这会提取请求的查询字符串,该字符串从第一个问号开始。如果不存在问号,则此获取返回空。如果存在问号但后面没有内容,则返回空字符串。这意味着可以使用“found”匹配方法轻松知道是否存在查询字符串。此获取是“path”(在问号之前停止)和“query_string”(包含问号)的补充。可以使用可选参数来自定义返回值。支持以下选项:- with_qm:如果查询字符串不为空,则在其开头包含问号。
此函数构建一个字符串,该字符串由规则评估时请求中出现的所有头部名称拼接而成。默认分隔符是逗号 (','),但可以通过可选参数 <delim> 进行覆盖。在这种情况下,只考虑 <delim> 的第一个字符。返回 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:精确字符串匹配
这会返回 HTTP 响应的可用正文作为数据块。与请求端不同,没有指令可以等待响应的正文。此样本获取在健康检查上下文中非常有用(且可用)。它可用于基于 tcp-check 的 expect 规则。
这会返回 HTTP 响应可用正文的长度(以字节为单位)。与请求端不同,没有指令可以等待响应的正文。此样本获取在健康检查上下文中非常有用(且可用)。它可用于基于 tcp-check 的 expect 规则。
这会返回 HTTP 响应正文的广告长度(以字节为单位)。它将代表广告的 Content-Length 标头,或在分块编码情况下可用数据的大小。与请求端不同,没有指令可以等待响应正文。此样本获取在健康检查上下文中非常有用(且可用)。它可用于基于 tcp-check 的 expect 规则。
如果响应是由 HTTP 缓存条目构建的,则返回布尔值“true”,否则返回布尔值“false”。
返回用于构建 HTTP 响应的 HTTP 缓存名称的字符串(如果 res.cache_hit 为 true),否则返回空字符串。
如果响应已被 HAProxy 压缩,则返回布尔值 "true",否则返回布尔值 "false"。这可用于在日志中添加信息。
如果响应被 HAProxy 压缩,则返回一个包含所用算法名称的字符串,例如:“deflate”。这可用于在日志中添加一些信息。
从响应的“Set-Cookie”标头行中提取 cookie 名称 <name> 的最后一次出现,并返回其值。如果未指定名称,则返回第一个 cookie 值。它可用于基于 tcp-check 的 expect 规则。ACL 派生:res.scook([<name>]:精确字符串匹配
返回响应中 cookie <name> 的出现次数的整数值,如果未指定 <name>,则返回所有 cookie。这在与 ACL 结合以检测可疑响应时非常有用。它可用于基于 tcp-check 的 expect 规则。
从响应的“Set-Cookie”标头行中提取 cookie 名称 <name> 的最后一次出现,并将其值转换为整数返回。如果未指定名称,则返回第一个 cookie 值。它可用于基于 tcp-check 的 expect 规则。
在规则求值时,此函数会创建一个字符串,该字符串由响应(Set-Cookie 标头)中出现的所有 cookie 名称连接而成。默认分隔符是逗号 (','),但可以作为可选参数 <delim> 覆盖。在这种情况下,只考虑 <delim> 的第一个字符。它可用于基于 tcp-check 的 expect 规则。此获取器的工作方式类似于 req.fhdr() 获取器,区别在于它作用于 HTTP 响应中的标头。与 req.fhdr() 一样,res.fhdr() 获取器返回完整值。如果标头定义为列表,则应使用 res.hdr()。此获取器有时对 Date 或 Expires 等标头很有用。它可用于基于 tcp-check 的 expect 规则。
此获取器的工作方式类似于 req.fhdr_cnt() 获取器,区别在于它作用于 HTTP 响应中的标头。与 req.fhdr_cnt() 一样,res.fhdr_cnt() 获取器作用于完整值。如果标头定义为列表,则应使用 res.hdr_cnt()。它可用于基于 tcp-check 的 expect 规则。
此获取的工作方式类似于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>]]):子字符串匹配
此获取器的工作方式类似于 req.hdr_cnt() 获取器,区别在于它作用于 HTTP 响应中的标头。与 req.hdr_cnt() 一样,res.hdr_cnt() 获取器将逗号视为分隔符。如果不需要,应使用 res.fhdr_cnt()。它可用于基于 tcp-check 的 expect 规则。
此获取器的工作方式类似于 req.hdr_ip() 获取器,区别在于它作用于 HTTP 响应中的标头。这有助于将某些数据学习到粘滞表中。它可用于基于 tcp-check 的 expect 规则。
在规则求值时,此函数会创建一个字符串,该字符串由响应中出现的名称相同的标头连接而成。默认分隔符是逗号 (','),但可以作为可选参数 <delim> 覆盖。在这种情况下,只考虑 <delim> 的第一个字符。它可用于基于 tcp-check 的 expect 规则。此获取器的工作方式类似于 req.hdr_val() 获取器,区别在于它作用于 HTTP 响应中的标头。这有助于将某些数据学习到粘滞表中。它可用于基于 tcp-check 的 expect 规则。
以字符串形式返回当前响应标头,包括分隔标头和请求正文的最后空行。最后空行可用于检测截断的标头块。此样本获取对于某些 SPOE 标头分析器和高级日志记录非常有用。它也可用于基于 tcp-check 的 expect 规则。
以预解析的二进制形式返回当前响应标头。这对于使用 SPOE 进行部分处理非常有用。它可用于基于 tcp-check 的 expect 规则。每个字符串由长度后面跟着长度指示的字节数描述。长度使用 SPOE 文档中详细的可变整数编码表示。列表的末尾由一对空标头名称和值(长度均为 0)标记。*(<str:header-name><str:header-value>)<empty string><empty string> int:参考 SPOE 文档的编码 str:<int:length><bytes>
返回 HTTP 响应中的版本字符串,例如“1.1”。这在日志中很有用,但主要用于 ACL。它可用于基于 tcp-check 的 expect 规则。ACL 派生:resp.ver:精确字符串匹配
返回一个整数,其中包含从服务器收到的 HTTP 状态代码。如果没有从服务器收到响应,则样本获取失败。
从响应的“Set-Cookie”标头行中提取 cookie 名称 <name> 的最后一次出现,并使用相应的值进行匹配。这可以与“appsession”的默认选项所做的相媲美,但支持多对同步和跨重启的状态保持。此获取函数已弃用,已被“res.cook”获取器取代。此关键字很快就会消失。
返回一个整数,其中包含 HTTP 响应中的 HTTP 状态代码,例如 302。它主要用于 ACL 和整数范围,例如,如果响应不是 3xx,则删除任何 Location 标头。如果状态代码未更改,则将是客户端收到的状态代码(例如,通过 'set-status' 操作)。它可用于基于 tcp-check 的 expect 规则。
以整数形式返回事务的 HTTP 状态代码,如日志中所示。
HTTP 请求的总活动时间,从代理接收到请求标头的第一个字节到响应正文的最后一个字节发出之间。这相当于日志格式中的 %Ta,并以毫秒 (ms) 为单位报告。有关更多信息,请参阅第 8.4 节“计时事件”。
返回附加到请求的唯一 ID。必须设置“unique-id-format”指令。如果未设置,则 unique-id 样本获取将失败。请注意,unique-id 通常与 HTTP 请求一起使用,但是此样本获取也可以与其他协议一起使用。显然,如果它与 HTTP 以外的协议一起使用,unique-id-format 指令不应包含 HTTP 部分。另请参阅:unique-id-format 和 unique-id-header
这会提取请求中显示的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:子字符串匹配
当主机部分以IP地址形式呈现时,这会从请求的URL中提取IP地址。其用途非常有限。例如,监控系统可能会将此字段用作源IP的替代项,以测试给定源地址将遵循的路径,或为给定源地址强制写入表项。它可以与“http-request set-dst”结合使用,以模拟旧的“option http_proxy”。
这会从请求的URL中提取端口部分。请注意,如果请求中未指定端口,则假定端口为80。
这会提取查询字符串中参数的第一次出现,该字符串在'?'或<delim>之后开始,在'&'、';'或<delim>之前结束。参数名称区分大小写,除非将"i"添加为第三个参数。如果未给出名称,则任何参数都将匹配,并返回第一个。结果是一个字符串,对应于请求中显示的参数 的值(未执行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"。此函数提取请求中的 URL 参数 <name> 并将其转换为整数值。例如,这可用于基于用户 ID 的会话粘性,或与 ACL 一起匹配页码或价格。
此函数返回一个 32 位哈希值,该值由连接第一个 Host 标头和整个 URL(包括参数,而不仅仅是请求的路径部分,如上面的 "base32" 提取)得到。这对于跟踪每个 URL 的活动很有用。存储一个较短的哈希值可以节省大量内存。输出类型是无符号整数。
此函数返回 "url32" 提取和 "src" 提取的连接结果。结果类型为 binary,大小为 8 或 20 字节,具体取决于源地址族。这可用于跟踪每个 IP、每个 URL 的计数器。
这组样本fetch方法保留给开发人员,除非在调试目的下按开发人员的要求,否则绝不能在生产环境中使用。此外,在向后兼容性方面不会采取任何特殊措施。无法保证以下样本fetch方法永远不会更改、重命名或删除。因此,如果您使用其中一个,请务必小心。为避免任何歧义,这些样本fetch方法被放置在专用的“internal”作用域中,例如“internal.strm.is_htx”。本节中的样本fetch方法及其各自类型的摘要。
详细列表
返回与通道关联的HTX消息中数据使用的字节数。通道的选择取决于样本方向。
返回与通道关联的HTX消息中的可用空间(大小-已用)的字节数。通道的选择取决于样本方向。
返回与通道关联的HTX消息中数据使用的可用空间的字节数。通道的选择取决于样本方向。
如果与通道关联的HTX消息包含消息结束标志(EOM),则返回true。否则,返回false。通道的选择取决于样本方向。
返回与通道关联的HTX消息中存在的块的数量。通道的选择取决于样本方向。
返回与通道关联的HTX消息的总字节大小。通道的选择取决于样本方向。
返回与通道关联的HTX消息中使用的总大小(数据+元数据)的字节数。通道的选择取决于样本方向。
返回与通道关联的HTX消息中位置<idx>处的块的大小,如果不存在则返回0。通道的选择取决于样本方向。<idx>可以是任何正整数或以下特殊值之一:* head:最先插入的块* tail:最新插入的块* first:进行(重新)分析的第一个块
返回与通道关联的HTX消息中位置<idx>处的块的类型,如果不存在则返回“HTX_BLK_UNUSED”。通道的选择取决于样本方向。<idx>可以是任何正整数或以下特殊值之一:* head:最先插入的块* tail:最新插入的块* first:进行(重新)分析的第一个块
返回与通道关联的HTX消息中位置<idx>处的DATA块的值,如果不存在或不是DATA块,则返回空字符串。通道的选择取决于样本方向。<idx>可以是任何正整数或以下特殊值之一:* head:最先插入的块* tail:最新插入的块* first:进行(重新)分析的第一个块
返回与通道关联的HTX消息中位置<idx>处的HEADER块的头部名称,如果不存在或不是HEADER块,则返回空字符串。通道的选择取决于样本方向。<idx>可以是任何正整数或以下特殊值之一:* head:最先插入的块* tail:最新插入的块* first:进行(重新)分析的第一个块
返回与通道关联的HTX消息中位置<idx>处的HEADER块的头部值,如果不存在或不是HEADER块,则返回空字符串。通道的选择取决于样本方向。<idx>可以是任何正整数或以下特殊值之一:* head:最先插入的块* tail:最新插入的块* first:进行(重新)分析的第一个块
返回与通道关联的HTX消息中位置<idx>处的REQ_SL或RES_SL块的值,如果不存在或不是SL块,则返回空字符串。通道的选择取决于样本方向。<idx>可以是任何正整数或以下特殊值之一:* head:最先插入的块* tail:最新插入的块* first:进行(重新)分析的第一个块
如果当前流是HTX流,则返回true。这意味着通道缓冲区中的数据使用内部HTX表示法存储。否则,返回false。
一些预定义的 ACL 是硬编码的,因此不必在每个需要它们的前端中声明。它们的名称都使用大写字母,以避免混淆。下面提供了它们的等效项。
| ACL 名称 | 等同于Usage | |
|---|---|---|
| FALSE | always_false | 从不匹配 |
| HTTP | req.proto_http | 匹配如果协议是有效的HTTP |
| HTTP_1.0 | req.ver 1.0 | 匹配如果HTTP请求版本是1.0 |
| HTTP_1.1 | req.ver 1.1 | 匹配如果HTTP请求版本是1.1 |
| HTTP_2.0 | req.ver 2.0 | 匹配如果HTTP请求版本是2.0 |
| HTTP_3.0 | req.ver 3.0 | 匹配如果HTTP请求版本是3.0 |
| HTTP_CONTENT | req.hdr_val(content-length) gt 0 | 匹配HTTP请求中存在的content-length |
| HTTP_URL_ABS | url_reg ^[^/:]*:// | 匹配带协议方案的绝对 URL |
| HTTP_URL_SLASH | url_beg / | 匹配以 "/" 开头的 URL |
| HTTP_URL_STAR | url * | 匹配等于 "*" 的 URL |
| LOCALHOST | src 127.0.0.1/8 ::1 | 匹配来自本地主机的连接 |
| METH_CONNECT | method CONNECT | 匹配 HTTP CONNECT 方法 |
| METH_DELETE | method DELETE | 匹配HTTP DELETE方法 |
| METH_GET | method GET HEAD | 匹配 HTTP GET 或 HEAD 方法 |
| METH_HEAD | method HEAD | 匹配 HTTP HEAD 方法 |
| METH_OPTIONS | method OPTIONS | 匹配 HTTP OPTIONS 方法 |
| METH_POST | method POST | 匹配 HTTP POST 方法 |
| METH_PUT | method PUT | 匹配HTTP PUT方法 |
| METH_TRACE | method TRACE | 匹配 HTTP TRACE 方法 |
| RDP_COOKIE | req.rdp_cookie_cnt gt 0 | 匹配请求缓冲区中是否存在RDP cookie |
| REQ_CONTENT | req.len gt 0 | 匹配请求缓冲区中的数据 |
| TRUE | always_true | 总是匹配 |
| WAIT_END | wait_end | 等待内容分析结束 |
HAProxy的一个强项无疑在于其精确的日志。它可能提供了此类产品中最精细的信息级别,这对于排除复杂环境中的故障非常重要。日志中提供的标准信息包括客户端端口、TCP/HTTP状态计时器、终止时的精确流状态和精确终止原因、关于将流量导向服务器的决策信息,当然还有捕获任意header的能力。为了提高管理员的反应能力,它对遇到的问题(无论是内部还是外部)提供了极大的透明度,并且可以同时将日志发送到不同的源,并使用不同的级别过滤器:- 全局进程级日志(系统错误、启动/停止等)- 每个实例的系统和内部错误(资源不足、错误等)- 每个实例的外部故障(服务器启动/停止、最大连接数)- 每个实例的活动(客户端连接),无论是在建立时还是在终止时。- 对每个请求的日志级别控制,例如 http-request set-log-level silent if sensitive_request。将不同级别的日志分发到不同的日志服务器的能力使多个生产团队能够进行交互,并尽快解决他们的问题。例如,系统团队可能会监控系统范围的错误,而应用程序团队可能会实时监控其服务器的启动/停止,安全团队可能会延迟一小时分析活动日志。
TCP和HTTP连接可以记录日期、时间、源IP地址、目标地址、连接持续时间、响应时间、HTTP请求、HTTP返回代码、传输字节数、流结束条件,甚至是交换的cookie值等信息。例如,跟踪特定用户的问题。所有消息最多可以发送到两个syslog服务器。有关日志设施的更多信息,请查看第4.2节中的“log”关键字。
HAProxy支持5种日志格式。这些格式之间有几个共同字段,将在以下部分详细介绍。由于某些选项特有的指示符,其中一些可能会因配置而略有不同。支持的格式如下:- 默认格式,非常基础且很少使用。它仅提供有关传入连接在接受时非常基本的信息:源IP:port、目标IP:port和前端名称。此模式最终将消失,因此不会进行详细描述。- TCP格式,更高级。当前端设置了“option tcplog”时启用此格式。HAProxy通常会等到连接终止后才记录日志。此格式提供更丰富的信息,例如计时器、连接计数、队列大小等。此格式推荐用于纯TCP代理。- HTTP格式,用于HTTP代理最先进。当前端设置了“option httplog”时启用此格式。它提供与TCP格式相同的信息以及一些HTTP特定字段,例如请求、状态代码以及header和cookie的捕获。此格式推荐用于HTTP代理。- CLF HTTP格式,等同于HTTP格式,但字段排列顺序与CLF格式相同。在此模式下,所有计时器、捕获、标志等都按标准HTTP格式中出现的相同顺序出现在公共字段之后,每个字段一个。- 自定义日志格式,允许您创建自己的日志行。接下来的部分将深入介绍每种格式的详细信息。格式规范将以“field”为基础执行。除非另有说明,否则字段是由任意数量的空格分隔的一段文本。由于syslog服务器可能会在行首插入字段,因此始终假定第一个字段是包含进程名称和标识符的字段。注意:由于日志行可能很长,下面的部分中的日志示例可能会分成多行。示例日志行将以三个右尖括号('>>>')开头,并且每次日志被分成多行时,每个非最后一行将以反斜杠('\')结尾,下一行将缩进两个字符开始。
当没有设置特定选项时,使用此格式。日志在连接被接受后立即发出。需要注意的是,这目前是唯一记录请求目标 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相同)。建议新安装不要使用此已弃用格式,因为它最终将消失。TCP格式在前端指定“option tcplog”时使用,是纯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" 是发起与HAProxy的TCP连接的客户端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”参数,可以轻松估算缺少服务器的数量。值得注意的是,如果一个会话经历重新调度,它可能会两次通过后端队列,此时两个位置将是累加的。除非发生重新调度,否则请求不应同时通过服务器队列和后端队列。
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" 是发起与HAProxy的TCP连接的客户端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 header。如果指定了“option logasap”,则此值前面会加上“+”号,表示最终值可能会更大。请注意,此值是一个64位计数器,因此日志分析工具必须能够处理它而不会溢出。- "captured_request_cookie" 是一个可选的“name=value”条目,表示客户端在请求中包含此cookie。cookie名称及其最大长度由前端配置中的“capture cookie”语句定义。未设置选项时,该字段为单个短划线('-')。只能捕获一个cookie,它通常用于跟踪客户端和服务器之间的会话ID交换,以检测由于应用程序错误导致的客户端之间的会话交叉。有关更多详细信息,请参阅下面的“捕获HTTP header和cookie”部分。- "captured_response_cookie" 是一个可选的“name=value”条目,表示服务器已返回一个cookie及其响应。cookie名称及其最大长度由前端配置中的“capture cookie”语句定义。未设置选项时,该字段为单个短划线('-')。只能捕获一个cookie,它通常用于跟踪客户端和服务器之间的会话ID交换,以检测由于应用程序错误导致的客户端之间的会话交叉。有关更多详细信息,请参阅下面的“捕获HTTP header和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”语句而在请求中捕获的header列表。可以捕获多个header,它们将由竖线('|')分隔。未启用捕获时,大括号不显示,导致剩余字段移位。重要的是要注意此字段可能包含空格,并且使用它需要比不使用时更智能的日志解析器。有关更多详细信息,请参阅下面的“捕获HTTP header和cookie”部分。- "captured_response_headers" 是由于前端存在“capture response header”语句而在响应中捕获的header列表。可以捕获多个header,它们将由竖线('|')分隔。未启用捕获时,大括号不显示,导致剩余字段移位。重要的是要注意此字段可能包含空格,并且使用它需要比不使用时更智能的日志解析器。有关更多详细信息,请参阅下面的“捕获HTTP header和cookie”部分。- "http_request" 是完整的HTTP请求行,包括方法、请求和HTTP版本字符串。不可打印字符经过编码(请参阅下面的“不可打印字符”部分)。这始终是最后一个字段,并且始终由引号分隔,并且是唯一可以包含引号的字段。如果将新字段添加到日志格式中,它们将在此字段之前添加。如果请求太大且不适合标准syslog缓冲区(1024个字符),则此字段可能会被截断。这是此字段必须始终保持在最后的原因。HTTPS格式最适合通过SSL连接的HTTP。它是HTTP格式的扩展(见第8.2.3节),其中添加了SSL相关信息。当前端指定“option httpslog”时启用。与TCP和HTTP格式一样,日志通常在流结束时发出,除非指定了“option logasap”。与“monitor”规则匹配的流永远不会被记录。通过指定前端中的“option dontlognull”,也可以不记录客户端没有发送数据的流。如果前端中指定了“option dontlog-normal”,则不会记录成功的连接。HTTPS日志格式在内部声明为基于以下确切字符串的自定义日志格式,如果需要,也可以将其用作扩展格式的基础。此外,可以使用HAPROXY_HTTPS_LOG_FMT变量代替。请参阅第8.2.6节“自定义日志格式”了解如何使用:# 严格等同于“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(Server Name Indication)。它通常与连接第一个请求的主机名匹配。缺少此字段可能表示客户端未发送SNI,并将导致haproxy使用默认证书,或者在strict-sni情况下拒绝连接。- "ssl_version" 是前端的SSL版本。- "ssl_ciphers" 是用于连接的SSL密码。当传入连接由于SSL握手失败或PROXY协议header无效而失败时,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示例,它将报告源地址和端口、连接accept()日期、前端名称、进程和此前端上的活动连接数、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"
历史上,自定义日志格式仅用于生成日志。但由于其方便性,当用于通过组合多个复杂表达式来生成字符串时,它们已被许多指令采用,这些指令以前只接受字符串作为参数,现在也可以接受这种自定义日志格式定义。本文档中通常用 "<fmt>" 来表示的此类参数的定义方式与此处所述的 "log-format" 指令的参数完全相同。当涉及日志且默认日志格式不足时,可以非常详细地定义新的日志格式。由于从头开始创建日志格式并非总是易事,因此强烈建议首先查看现有格式("option tcplog"、"option httplog"、"option httpslog"),选择与预期最接近的格式,复制其 "log-format" 等效字符串并进行调整。从配置角度来看,自定义日志格式定义是一个单独的参数。这意味着它不能包含空白(空格或制表符),除非这些空白使用反斜杠字符 ('\') 进行转义,或者整个定义用引号括起来(这是推荐的使用方式)。不再推荐使用不带引号的格式字符串,因为历史表明它非常容易出错,因为缺少一个反斜杠字符可能导致格式的静默截断。由于在版本 1.5-dev9 之后(引号可用之前 3 年)日志格式被广泛采用,这种配置仍然很常见,但建议现在将它们转换为带引号的字符串并删除反斜杠。日志格式定义由任意数量的日志格式项组成,这些项由文本和空格分隔。日志格式项以字符 '%' 开头。为了发出一个字面上的 '%',它必须在前面加上另一个 '%',形成 '%%'。日志格式项可以是别名或样本表达式:如果一个项被方括号 ('[' .. ']') 括起来命名,那么它被用作样本表达式规则(参见第 7.3 节)。这对于添加一些不太常见的信息非常有用,例如客户端的 SSL 证书的 DN,或者记录用于将条目存储到粘性表中的键。它也常用于非日志操作(标头操作、变量等)。否则,如果该项使用字母数字名称命名,则它是一个别名。(有关可用别名的列表,请参阅下表)项可以使用花括号 ('{}') 接受参数,多个参数在花括号内用逗号分隔。可以通过在标志前加上 '+' 或 '-' 符号来添加或删除标志(有关可用标志的列表,请参见下文)。特殊别名 "%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、rings 和支持二进制的日志端点。此选项只能全局设置(使用 %o),如果在单个项的选项上设置,它将被忽略。* json:自动将值编码为 JSON 格式(全局设置时,只考虑命名的日志格式项)不完整的数值(例如:%B,当使用 logasap 时),通常在不编码的情况下以 '+' 为前缀,将按原样编码。此外,'+E' 选项将被忽略。* cbor:自动将值编码为 CBOR 格式(全局设置时,只考虑命名的日志格式项)默认情况下,cbor 编码数据以 HEX 形式表示,以便它在 stdout 上保持可打印,并且可以与常见的 syslog 端点一起使用。与 json 编码一样,不完整的数值将按原样编码,'+E' 选项将被忽略。与 '+bin' 选项结合使用时,它将直接生成原始二进制 CBOR 负载。请注意,因为它显然会生成不可打印的字符,因此它主要用于 set-var-fmt、rings 和支持二进制的日志端点。
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 | 别名 | 字段名称(描述见 8.2.2 和 8.2.3) | 类型 | | | | 样本获取替代 | | +===+======+======================================================+=========+ | | %o | 特殊,对所有后续项应用标志 | | +---+------+------------------------------------------------------+---------+ | 日期格式 | +---+------+------------------------------------------------------+---------+ | | %T | 接受日期 UTC + 时区 | | | | | %[accept_date,utime("%d/%b/%Y:%H:%M:%S %z")] | date | +---+------+------------------------------------------------------+---------+ | | %Tl | 接受日期本地 + 时区 | | | | | %[accept_date,ltime("%d/%b/%Y:%H:%M:%S %z")] | date | +---+------+------------------------------------------------------+---------+ | | %Ts | 接受日期作为 UNIX 时间戳 | numeric | | | | %[accept_date] | | +---+------+------------------------------------------------------+---------+ | | %t | 接受日期本地(带毫秒分辨率) | | | | | %[accept_date(ms),ms_ltime("%d/%b/%Y:%H:%M:%S.%3N")] | date | +---+------+------------------------------------------------------+---------+ | | %ms | 接受日期毫秒 | | | | | %[accept_date(ms),ms_utime("%3N")] | numeric | +---+------+------------------------------------------------------+---------+ | H | %tr | 请求日期本地(带毫秒分辨率) | | | | | %[request_date(ms),ms_ltime("%d/%b/%Y:%H:%M:%S.%3N")]| date | +---+------+------------------------------------------------------+---------+ | H | %trg | 请求日期 UTC + 时区 | | | | | %[request_date,utime("%d/%b/%Y:%H:%M:%S %z")] | date | +---+------+------------------------------------------------------+---------+ | H | %trl | 请求日期本地 + 时区 | | | | | %[request_date,ltime("%d/%b/%Y:%H:%M:%S %z")] | date | +---+------+------------------------------------------------------+---------+ | 计时事件 | +---+------+------------------------------------------------------+---------+ | H | %Ta | 请求的活动时间(从 TR 到结束) | | | | | %[txn.timer.total] | numeric | +---+------+------------------------------------------------------+---------+ | | %Tc | Tc | | | | | %[bc.timer.connect] | numeric | +---+------+------------------------------------------------------+---------+ | | %Td | Td = Tt - (Tq + Tw + Tc + Tr) | | | | | %[res.timer.data] | numeric | +---+------+------------------------------------------------------+---------+ | | %Th | 连接握手时间 (SSL, PROXY proto) | | | | | %[fc.timer.handshake] | numeric | +---+------+------------------------------------------------------+---------+ | H | %Ti | HTTP 请求之前的空闲时间 | | | | | %[req.timer.idle] | numeric | +---+------+------------------------------------------------------+---------+ | H | %Tq | Th + Ti + TR | | | | | %[req.timer.tq] | numeric | +---+------+------------------------------------------------------+---------+ | H | %TR | 从第一个字节开始接收完整请求的时间 | | | | | %[req.timer.hdr] | numeric | +---+------+------------------------------------------------------+---------+ | H | %Tr | Tr (响应时间) | | | | | %[res.timer.hdr] | numeric | +---+------+------------------------------------------------------+---------+ | | %Tt | Tt | | | | | %[fc.timer.total] | numeric | +---+------+------------------------------------------------------+---------+ | | %Tu | Tu | | | | | %[txn.timer.user] | numeric | +---+------+------------------------------------------------------+---------+ | | %Tw | Tw | | | | | %[req.timer.queue] | numeric | +---+------+------------------------------------------------------+---------+ | 其他 | +---+------+------------------------------------------------------+---------+ | | %B | bytes_read (从服务器到客户端) | numeric | | | | %[bytes_out] | | +---+------+------------------------------------------------------+---------+ | H | %CC | captured_request_cookie | string | +---+------+------------------------------------------------------+---------+ | H | %CS | captured_response_cookie | string | +---+------+------------------------------------------------------+---------+ | | %H | hostname | string | | | | %[hostname] | | +---+------+------------------------------------------------------+---------+ | H | %HM | HTTP method (例如: POST) | string | | | | %[method] | | +---+------+------------------------------------------------------+---------+ | H | %HP | HTTP request URI without query string | string | +---+------+------------------------------------------------------+---------+ | H | %HPO | HTTP path only (without host nor query string)| string | +---+------+------------------------------------------------------+---------+ | H | %HQ | HTTP request URI query string (例如: ?bar=baz) | string | | | | ?%[query] | | +---+------+------------------------------------------------------+---------+ | H | %HU | HTTP request URI (例如: /foo?bar=baz) | string | +---+------+------------------------------------------------------+---------+ | H | %HV | HTTP version (例如: HTTP/1.0) | string | | | | HTTP/%[req.ver] | | +---+------+------------------------------------------------------+---------+ | | %ID | unique-id | string | | | | %[unique-id] | | +---+------+------------------------------------------------------+---------+ | | %ST | status_code | numeric | | | | %[txn.status] | | +---+------+------------------------------------------------------+---------+ | | %U | bytes_uploaded (从客户端到服务器) | numeric | | | | %[bytes_in] | | +---+------+------------------------------------------------------+---------+ | | %ac | actconn | | | | | %[act_conn] | numeric | +---+------+------------------------------------------------------+---------+ | | %b | backend_name | | | | | %[be_name] | string | +---+------+------------------------------------------------------+---------+ | | %bc | beconn (backend concurrent connections) | numeric | | | | %[be_conn] | | +---+------+------------------------------------------------------+---------+ | | %bi | backend_source_ip (连接地址) | | | | | %[bc_src] | IP | +---+------+------------------------------------------------------+---------+ | | %bp | backend_source_port (连接地址) | | | | | %[bc_src_port] | numeric | +---+------+------------------------------------------------------+---------+ | | %bq | backend_queue | numeric | | | | %[bc_be_queue] | | +---+------+------------------------------------------------------+---------+ | | %ci | client_ip (接受地址) | | | | | %[src] | IP | +---+------+------------------------------------------------------+---------+ | | %cp | client_port (接受地址) | | | | | %[src_port] | numeric | +---+------+------------------------------------------------------+---------+ | | %f | frontend_name | string | | | | %[fe_name] | | +---+------+------------------------------------------------------+---------+ | | %fc | feconn (frontend concurrent connections) | numeric | | | | %[fe_conn] | | +---+------+------------------------------------------------------+---------+ | | %fi | frontend_ip (接受地址) | | | | | %[dst] | IP | +---+------+------------------------------------------------------+---------+ | | %fp | frontend_port (接受地址) | | | | | %[dst_port] | numeric | +---+------+------------------------------------------------------+---------+ | | %ft | frontend_name_transport ('~' suffix for SSL) | string | +---+------+------------------------------------------------------+---------+ | | %lc | frontend_log_counter | numeric | +---+------+------------------------------------------------------+---------+ | | %hr | captured_request_headers default style | string | +---+------+------------------------------------------------------+---------+ | | %hrl | captured_request_headers CLF style | string | | | | | list | +---+------+------------------------------------------------------+---------+ | | %hs | captured_response_headers default style | string | +---+------+------------------------------------------------------+---------+ | | %hsl | captured_response_headers CLF style | string | | | | | list | +---+------+------------------------------------------------------+---------+ | L | %OG | human readable log origin | string | +---+------+------------------------------------------------------+---------+ | | %pid | PID | | | | | %[pid] | numeric | +---+------+------------------------------------------------------+---------+ | H | %r | http_request | string | +---+------+------------------------------------------------------+---------+ | | %rc | retries | numeric | | | | %[txn.redispatched,iif(+,)]%[txn.conn_retries] | | +---+------+------------------------------------------------------+---------+ | | %rt | request_counter (HTTP req or TCP session) | numeric | | | | %[txn.id32] | | +---+------+------------------------------------------------------+---------+ | | %s | server_name | string | | | | %[srv_name] | | +---+------+------------------------------------------------------+---------+ | | %sc | srv_conn (server concurrent connections) | numeric | +---+------+------------------------------------------------------+---------+ | | %si | server_IP (target address) | | | | | %[bc_dst] | IP | +---+------+------------------------------------------------------+---------+ | | %sp | server_port (target address) | | | | | %[bc_dst_port] | numeric | +---+------+------------------------------------------------------+---------+ | | %sq | srv_queue | numeric | | | | %[bc_srv_queue] | | +---+------+------------------------------------------------------+---------+ | S | %sslc| ssl_ciphers (ex: AES-SHA) | | | | | %[ssl_fc_cipher] | string | +---+------+------------------------------------------------------+---------+ | S | %sslv| ssl_version (ex: TLSv1) | | | | | %[ssl_fc_protocol] | string | +---+------+------------------------------------------------------+---------+ | | %ts | termination_state | string | | | | %[txn.sess_term_state] | | +---+------+------------------------------------------------------+---------+ | H | %tsc | termination_state with cookie status | string | +---+------+------------------------------------------------------+---------+ R = 限制:H = 仅 HTTP 模式;S = 仅 SSL;L = 仅日志一些高级日志记录选项经常被寻找,但仅通过查看各种选项不容易找到。这里是几个可以实现更好日志记录的选项的入口点。有关其用法的更多信息,请参考关键字参考。
监控工具对 HAProxy 进行健康检查是很常见的。有时它是一个第 3 层负载均衡器,例如 LVS 或任何商业负载均衡器,有时它只是一个更完整的监控系统,例如 Nagios。当测试非常频繁时,用户经常会问如何禁用这些检查的日志记录。有三种可能性:- 如果连接来自四面八方且只是 TCP 探测,通常希望通过在前端设置 "option dontlognull" 来禁用没有数据交换的连接日志记录。它还会禁用端口扫描的日志记录,这可能合意也可能不合意。- 可以使用各种条件(源网络、路径、用户代理等)使用 "http-request set-log-level silent" 操作。- 如果测试是在一个已知的 URI 上执行的,请使用 "monitor-uri" 将此 URI 声明为专门用于监控。发送此请求的任何主机将只获得健康检查的结果,并且请求不会被记录。
在连接结束时进行日志记录的问题在于,您无法了解在非常长的流(例如远程终端会话或大文件下载)期间发生了什么。通过在前端指定“option logasap”可以解决此问题。HAProxy 将尽快记录,就在数据传输开始之前。这意味着在 TCP 的情况下,它仍将记录到服务器的连接状态,在 HTTP 的情况下,它将在处理服务器头信息后进行记录。在这种情况下,报告的字节数是发送到客户端的头字节数。为了避免与正常日志混淆,总时间字段和字节数前面会加上“+”号,表示实际数字肯定更大。
有时,将正常流量与错误日志分开会更方便,例如,为了简化从日志文件中监控错误。当使用 "log-separate-errors" 选项时,遇到错误、超时、重试、重新分派或 HTTP 状态码为 5xx 的连接,其 syslog 级别将从 "info" 提高到 "err"。这将帮助 syslog 守护进程将日志存储在一个单独的文件中。将错误也保留在正常流量文件中非常重要,这样日志顺序就不会改变。如果您已经配置了 syslog 守护进程将所有高于 "notice" 的日志存储在 "admin" 文件中,您也应该小心,因为 "err" 级别高于 "notice"。
虽然这乍听起来可能很奇怪,但一些大型站点必须处理每秒数千条日志,并且在长时间保持其完整性或在其中检测错误方面遇到困难。如果在前端设置了 "dontlog-normal" 选项,所有正常的连接都不会被记录。在这方面,正常连接定义为没有任何错误、超时、重试或重新分派的连接。在 HTTP 中,状态码也会被检查,状态为 5xx 的响应不被认为是正常的,也会被记录。当然,这样做是强烈不鼓励的,因为它会从日志中删除大部分有用的信息。只有在没有其他选择的情况下才这样做。
虽然 "log-format"、"log-format-sd"、"error-log-format" 或 "log-tag" 等指令可以全局或在代理级别配置日志格式,但在离日志端点尽可能近的地方配置此类设置可能更相关,即每个 "log" 指令。这就是 "log-profile" 部分发挥作用的地方:"log-profile" 可以在配置中的任何位置定义。此部分接受一组不同的关键字,用于描述应如何构建为给定 `log` 指令发出的日志。从 "log" 指令中,可以选择按名称使用特定的日志配置文件。同一个配置文件可以被多个 "log" 指令使用。
创建一个新的日志配置文件,标识为 <name>
覆盖全局或按代理设置的 syslog 日志标记,使用“log-tag”指令。在 <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" 指令有意义的上下文(例如:http 和 tcp 代理)中使用的 "log" 指令相关。否则它将被忽略。
log-profile myprof log-tag "custom-tag" on error format "%ci: error" on connect drop on any sd "custom-sd" listen myproxy mode http option httplog log-tag "normal" log stdout format rfc5424 local0 # success: # <134>1 2024-06-12T10:09:11.823400+02:00 - normal 224482 - - 127.0.0.1:53594 [12/Jun/2024:10:09:11.814] myproxy myproxy/<NOSRV> 0/-1/-1/-1/0 200 49 - - LR-- 1/1/0/0/0 0/0 "GET / HTTP/1.1" # # error: # <134>1 2024-06-12T10:09:44.810929+02:00 - normal 224482 - - 127.0.0.1:59258 [12/Jun/2024:10:09:44.426] myproxy myproxy/<NOSRV> -1/-1/-1/-1/384 400 0 - - CR-- 1/1/0/0/0 0/0 "<BADREQ>" log 127.0.0.1:514 format rfc5424 profile myprof local0 # success: # <134>1 2024-06-12T10:09:11.823428+02:00 - custom-tag 224482 - custom-sd 127.0.0.1:53594 [12/Jun/2024:10:09:11.814] myproxy myproxy/<NOSRV> 0/-1/-1/-1/0 200 49 - - LR-- 1/1/0/0/0 0/0 "GET / HTTP/1.1" # # error: # <134>1 2024-06-12T10:09:51.566524+02:00 - custom-tag 224482 - - 127.0.0.1: error
计时器对排查网络问题有很大帮助。所有值均以毫秒 (ms) 为单位报告。这些计时器应与流终止标志结合使用。在 TCP 模式下,如果前端设置了 "option tcplog",则以 "Tw/Tc/Tt" 的形式报告 3 个控制点;在 HTTP 模式下,以 "TR/Tw/Tc/Tr/Ta" 的形式报告 5 个控制点。此外,还提供了另外三个度量:"Th"、"Ti" 和 "Tq"。HTTP 模式下的计时事件:第一个请求 第二个请求 |<-------------------------------->|<-------------- ... t tr t tr ... ---|----|----|----|----|----|----|----|----|-- : Th Ti TR Tw Tc Tr Td : Ti ... :<---- Tq ---->: : :<-------------- Tt -------------->: :<-- -----Tu--------------->: :<--------- Ta --------->: TCP 模式下的计时事件:TCP 会话 |<----------------->| t t ---|----|----|----|----|--- | Th Tw Tc Td | |<------ Tt ------->| - Th:接受 tcp 连接并执行低级协议握手的总时间。目前,这些协议是 proxy-protocol 和 SSL。这在整个连接生命周期中只发生一次。这里的时间较长可能表明客户端只预先建立了连接但没有通信,或者客户端遇到网络问题导致无法在合理的时间内完成握手(例如 MTU 问题),或者 SSL 握手计算成本很高。请注意,此时间仅在第一个请求之前报告,因此可以安全地将其平均到所有请求中以计算摊销值。第二个及后续请求在此处始终报告零。此计时器的日志格式别名为 %Th,样本获取别名为 fc.timer.handshake。- Ti:HTTP 请求之前的空闲时间(仅限 HTTP 模式)。此计时器在握手结束和 HTTP 请求的第一个字节之间计数。在 keep-alive 模式下处理第二个请求时,它在传输上一个响应结束之后开始计数。当使用 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:从客户端看,从代理接受它到两端关闭之间的总估计时间,不包括空闲时间。这对于粗略测量用户看到的端到端时间非常有用,没有请求之间的 keep-alive 时间造成的空闲时间污染。此计时器仅是对用户看到的时间的估计,因为它假定两个方向的网络延迟相同。例外情况是指定了 "logasap" 选项。在这种情况下,它只等于 (Th+TR+Tw+Tc+Tr),并且以 '+' 号为前缀。此计时器的日志格式别名为 %Tu,样本获取别名为 txn.timer.user。这些计时器提供了有关故障原因的宝贵指示。由于 TCP 协议定义了 3、6、12... 秒的重传延迟,我们确切地知道接近 3s 倍数的计时器几乎总是与由于网络问题(线路、协商、拥塞)造成的数据包丢失有关。此外,如果 "Ta" 或 "Tt" 接近配置中指定的超时值,则通常意味着流已因超时而中止。最常见的情况:- 如果 "Th" 或 "Ti" 接近 3000,则客户端和代理之间可能丢失了一个数据包。这在本地网络上非常罕见,但当客户端位于遥远的远程网络并发送大请求时可能会发生。有时,即使没有网络原因,也可能出现比平时更大的值。有时,在攻击期间或资源耗尽刚结束时,HAProxy 可能会在几毫秒内接受数千个连接。接受这些连接所花费的时间不可避免地会稍微延迟其他连接的处理,并且可能会在一次接受数千个新连接后测量到几十毫秒的请求时间。使用其中一种 keep-alive 模式可能会显示更长的空闲时间,因为 "Ti" 测量的是等待额外请求所花费的时间。- 如果 "Tc" 接近 3000,则服务器连接阶段服务器和代理之间可能丢失了一个数据包。该值应始终非常低,例如在本地网络上为 1 毫秒,在远程网络上小于几十毫秒。- 如果 "Tr" 几乎总是低于 3000,除了一些罕见的值似乎是平均值加上 3000,则代理和服务器之间可能丢失了一些数据包。- 如果 "Ta" 即使对于小的字节数也很长,通常是因为当 HAProxy 在隧道模式下运行且双方都同意 keep-alive 连接模式时,客户端和服务器都不决定关闭连接。为了解决这个问题,需要指定其中一个 HTTP 选项来在前端或后端操作 keep-alive 或 close 选项。当连接调节与服务器上的 "maxconn" 选项一起使用时,拥有尽可能小的 'Ta' 或 'Tt' 很重要,因为在另一个连接释放之前,不会向服务器发送新连接。其他值得注意的 HTTP 日志案例('xx' 表示要忽略的任何值):TR/Tw/Tc/Tr/+Ta "option logasap" 存在于前端,日志在数据阶段之前发出。所有计时器都有效,除了 "Ta" 比实际短。-1/xx/xx/xx/Ta 客户端无法及时发送完整的请求或过早中止。检查流终止标志,然后检查 "timeout http-request" 和 "timeout client" 设置。TR/-1/xx/xx/Ta 无法处理请求,可能是因为服务器出现故障,或者因为请求无效或被 ACL 规则禁止。检查流终止标志。TR/Tw/-1/xx/Ta 连接无法在服务器上建立。要么它主动拒绝了它,要么它在 Ta-(TR+Tw) 毫秒后超时。检查流终止标志,然后检查 "timeout connect" 设置。请注意,tarpit 操作可能会返回看起来相似的模式,其中 "Tw" 等于客户端连接保持打开的时间。TR/Tw/Tc/-1/Ta 服务器已接受连接,但未及时返回完整响应,或者它在 Ta-(TR+Tw+Tc) 毫秒后意外关闭连接。检查流终止标志,然后检查 "timeout server" 设置。
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:请求被 tarpitted。它与客户端保持打开状态,持续了整个 "timeout tarpit" 持续时间,或者直到客户端关闭,两者都将在 "Tw" 计时器中报告。-:数据传输结束后的正常流完成。- 第三个字符,告诉客户端是否提供了持久性 cookie(仅限 HTTP 模式):N:客户端没有提供 cookie。这通常是新访问者的情况,因此计算日志中此标志的出现次数通常表示网站访问的有效趋势。I:客户端提供了与任何已知服务器都不匹配的 INVALID cookie。这可能是由最近的配置更改、HTTP/HTTPS 站点之间的混合 cookie、有条件地忽略持久性或攻击引起的。D:客户端提供了一个指定 DOWN 服务器的 cookie,因此要么使用了 "option persist",客户端被发送到该服务器,要么没有设置,客户端被重新调度到另一个服务器。V:客户端提供了 VALID cookie,并被发送到关联的服务器。E:客户端提供了有效的 cookie,但最后一个日期早于 "maxidle" cookie 参数允许的日期,因此 cookie 被视为 EXPIRED 并被忽略。请求将像没有 cookie 一样被重新调度。O:客户端提供了有效的 cookie,但第一个日期早于 "maxlife" cookie 参数允许的日期,因此 cookie 被视为太 OLD 并被忽略。请求将像没有 cookie 一样被重新调度。U:存在 cookie,但未用于选择服务器,因为使用了其他服务器选择机制(通常是 "use-server" 规则)。-:不适用(配置中未设置 cookie)。- 最后一个字符,报告对服务器返回的持久性 cookie 执行了哪些操作(仅限 HTTP 模式):N:服务器没有提供 cookie,也没有插入 cookie。I:服务器没有提供 cookie,代理 INSERTED 了一个。请注意,在 "cookie insert" 模式下,如果服务器提供了 cookie,它仍将被覆盖并在此处报告为 "I"。U:代理 UPDATED 了客户端提供的 cookie 中的最后一个日期。这只能在 insert 模式下使用 "maxidle" 发生。每当活动日期与 cookie 中指示的日期不同时,就会发生这种情况。如果发生任何其他更改,例如重新调度,则 cookie 将被标记为插入。P:服务器提供了 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 客户端在等待服务器开始响应时中止。可能是服务器响应时间太长,或者客户端点击了 'Stop' 按钮太快。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。注意:最近,一些浏览器开始实现 "pre-connect" 功能,即推测性地连接到一些最近访问过的网站,以防用户想要访问它们。这导致与网站建立了许多连接,如果超时先到期,则以 408 Request Timeout 结束,如果浏览器决定先关闭它们,则以 400 Bad Request 结束。这些会污染日志并增加错误计数器。据报道,某些版本的某些浏览器甚至会显示错误代码。可以通过在前端添加 "option http-ignore-probes" 来解决这种行为的不良影响,从而完全忽略没有数据传输的连接。但这肯定会隐藏那些遇到连接问题的人的错误。CT 客户端在其流被 tarpitted 时中止。检查这是否发生在有效请求上非常重要,以确保没有编写错误的 tarpit 规则。如果发生很多次,降低 "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 在服务器发出标头之后,代理阻止了请求或响应中格式不正确的 chunked 编码消息。在大多数情况下,这将表明服务器发出了无效消息。HAProxy 支持最大为 2GB - 1 (2147483647 字节) 的块大小。任何更大的大小都将被视为错误。PH 代理阻止了服务器的响应,因为它是无效的、不完整的、危险的(缓存控制)或匹配了安全过滤器。在任何情况下,都会向客户端发送 HTTP 502 错误。此错误的一个可能原因是 HTTP 标头名称中包含未经授权字符的无效语法。代理阻止客户端的 chunked 编码请求(由于语法无效)在服务器响应之前也是可能的,但非常罕见。在这种情况下,会向客户端发送 HTTP 400 错误并在日志中报告。最后,它可能是由于响应上的 HTTP 标头重写失败。在这种情况下,会发送 HTTP 500 错误(有关详细信息,请参阅 "tune.maxrewrite" 和 "http-response strict-mode")。PR 代理阻止了客户端的 HTTP 请求,要么是因为 HTTP 语法无效(在这种情况下它返回 HTTP 400 错误给客户端),要么是因为匹配了拒绝过滤器(在这种情况下它返回 HTTP 403 错误)。它也可能是由于请求上的 HTTP 标头重写失败。在这种情况下,会发送 HTTP 500 错误(有关详细信息,请参阅 "tune.maxrewrite" 和 "http-request strict-mode")。PT 代理阻止了客户端的请求,并在返回 500 服务器错误之前 tarpitted 了它的连接。没有向服务器发送任何内容。连接保持打开状态,持续时间由 "Tw" 计时器字段报告。RC 本地资源已耗尽(内存、套接字、源端口),阻止与服务器建立连接。错误日志将精确说明缺少什么。这种情况非常罕见,只能通过适当的系统调优来解决。最后两个标志的组合提供了大量关于客户端、服务器和 HAProxy 如何处理持久性的信息。这对于排查断开连接非常重要,当用户抱怨他们必须重新验证身份时。常见的标志组合是:-- 未启用持久性 cookie。NN 客户端未提供 cookie,响应中未插入 cookie。例如,这可能是在 "postonly" 设置在 GET 请求上的 insert 模式下。II 客户端提供了一个指定无效服务器的 cookie,响应中插入了一个有效的 cookie。当从配置中删除 "server" 条目时,通常会发生这种情况,因为客户端可能会提供其 cookie 值,而其他服务器不知道它。NI 客户端未提供 cookie,响应中插入了一个 cookie。这通常发生在 "insert" 模式下每个用户的第一个请求中,这使得它成为计算真实用户的简单方法。VN 客户端提供了 cookie,响应中未插入 cookie。这发生在客户端已经获得 cookie 的大多数响应中。VU 客户端提供了 cookie,最后一个访问日期不是完全最新的,因此在响应中提供了一个更新的 cookie。如果根本没有日期,或者有日期但未设置 "maxidle" 参数,以便可以将 cookie 切换到无限时间,也可能发生这种情况。EI 客户端提供了 cookie,但最后一个访问日期对于 "maxidle" 参数来说太旧了,因此 cookie 被忽略并在响应中插入了一个新 cookie。OI 客户端提供了 cookie,但第一个访问日期对于 "maxlife" 参数来说太旧了,因此 cookie 被忽略并在响应中插入了一个新 cookie。DI cookie 指定的服务器已关闭,选择了新服务器并在响应中发出了新 cookie。VI cookie 指定的服务器未被标记为关闭,但无法访问。发生了重新调度并选择了另一个服务器,然后在响应中进行了通告。
为了在查阅日志时避免给日志分析工具或终端带来麻烦,不可打印的字符不会按原样发送到日志文件中,而是会转换为其 ASCII 码的两位十六进制表示,并以字符“#”为前缀。唯一可以不经转义直接记录的字符范围是 32 到 126(含)。显然,转义字符“#”本身也会被编码以避免任何歧义(“#23”)。字符“"”也是如此,它会变成“#22”,以及在记录头时,“{”、“|”和“}”也是如此。请注意,空格字符(' ')在头中不被编码,这可能会给依赖空格计数来定位字段的工具带来问题。一个包含空格的典型头是“User-Agent”。最后,据观察,一些 syslog 守护进程(如 syslog-ng)会用反斜杠('\')来转义引号('\"')。可以安全地执行反向操作,因为日志中其他任何地方都不会出现引号。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
标头捕获对于跟踪上层代理设置的唯一请求标识符、虚拟主机名、用户代理、POST 内容长度、引荐来源等非常有用。在响应中,可以搜索有关响应长度、服务器如何要求缓存行为或重定向期间的对象位置的信息。标头捕获是使用前端中的 "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 # 记录 content-length 对 "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 >>> Aug 9 20:26:09 localhost \ haproxy[2022]: 127.0.0.1:34014 [09/Aug/2004:20:26:09] proxy-out \ proxy-out/cache1 0/0/0/162/+162 200 +350 - - ---- 0/0/0/0/0 0/0 \ {fr.adserver.yahoo.co||http://fr.f416.mail.} {|864|private||} \ "GET http://fr.adserver.yahoo.com/" >>> Aug 9 20:30:46 localhost \ haproxy[2022]: 127.0.0.1:34020 [09/Aug/2004:20:30:46] proxy-out \ proxy-out/cache1 0/0/0/182/+182 200 +279 - - ---- 0/0/0/0/0 0/0 \ {w.ods.org||} {Formilux/0.1.8|3495|||} \ "GET http://trafic.1wt.eu/ HTTP/1.1" >>> Aug 9 20:30:46 localhost \ haproxy[2022]: 127.0.0.1:34028 [09/Aug/2004:20:30:46] proxy-out \ proxy-out/cache1 0/0/2/126/+128 301 +223 - - ---- 0/0/0/0/0 0/0 \ {www.sytadin.equipement.gouv.fr||http://trafic.1wt.eu/} \ {Apache|230|||http://www.sytadin.} \ "GET http://www.sytadin.equipement.gouv.fr/ HTTP/1.1"
These are real-world examples of logs accompanied with an explanation. Some of them have been made up by hand. The syslog part has been removed for better reading. Their sole purpose is to explain how to decipher them. >>> 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" => long request (6.5s) entered by hand through 'telnet'. The server replied in 147 ms, and the session ended normally ('----') >>> haproxy[674]: 127.0.0.1:33319 [15/Oct/2003:08:31:57.149] px-http \ px-http/srv1 6559/1230/7/147/6870 200 243 - - ---- 324/239/239/99/0 \ 0/9 "HEAD / HTTP/1.0" => Idem, but the request was queued in the global queue behind 9 other requests, and waited there for 1230 ms. >>> haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17.654] px-http \ px-http/srv1 9/0/7/14/+30 200 +243 - - ---- 3/3/3/1/0 0/0 \ "GET /image.iso HTTP/1.0" => request for a long data transfer. The "logasap" option was specified, so the log was produced just before transferring data. The server replied in 14 ms, 243 bytes of headers were sent to the client, and total time from accept to first data byte is 30 ms. >>> haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17.925] px-http \ 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" => the proxy blocked a server response either because of an "http-response deny" rule, or because the response was improperly formatted and not HTTP-compliant, or because it blocked sensitive information which risked being cached. In this case, the response is replaced with a "502 bad gateway". The flags ("PH--") tell us that it was HAProxy who decided to return the 502 and not the server. >>> haproxy[18113]: 127.0.0.1:34548 [15/Oct/2003:15:18:55.798] px-http \ px-http/<NOSRV> -1/-1/-1/-1/8490 -1 0 - - CR-- 2/2/2/0/0 0/0 "" => the client never completed its request and aborted itself ("C---") after 8.5s, while the proxy was waiting for the request headers ("-R--"). Nothing was sent to any server. >>> haproxy[18113]: 127.0.0.1:34549 [15/Oct/2003:15:19:06.103] px-http \ px-http/<NOSRV> -1/-1/-1/-1/50001 408 0 - - cR-- 2/2/2/0/0 0/0 "" => The client never completed its request, which was aborted by the time-out ("c---") after 50s, while the proxy was waiting for the request headers ("-R--"). Nothing was sent to any server, but the proxy could send a 408 return code to the client. >>> haproxy[18989]: 127.0.0.1:34550 [15/Oct/2003:15:24:28.312] px-tcp \ px-tcp/srv1 0/0/5007 0 cD 0/0/0/0/0 0/0 => This log was produced with "option tcplog". The client timed out after 5 seconds ("c----"). >>> haproxy[18989]: 10.0.0.1:34552 [15/Oct/2003:15:26:31.462] px-http \ px-http/srv1 3183/-1/-1/-1/11215 503 0 - - SC-- 205/202/202/115/3 \ 0/0 "HEAD / HTTP/1.0" => The request took 3s to complete (probably a network problem), and the connection to the server failed ('SC--') after 4 attempts of 2 seconds (config says 'retries 3'), and no redispatch (otherwise we would have seen "/+3"). Status code 503 was returned to the client. There were 115 connections on this server, 202 connections on this proxy, and 205 on the global process. It is possible that the server refused the connection because of too many already established.此处列出了官方支持的过滤器及其接受的参数。根据编译选项,其中一些过滤器可能不可用。可用过滤器的列表将在 haproxy -vv 中报告。
<name> 是一个任意名称,将在消息中报告。如果未提供名称,则使用“TRACE”。 <quiet> 会抑制跟踪消息。 <random-forwarding> 启用对解析数据的随机转发。默认情况下,此过滤器转发所有先前解析的数据。使用此参数,它仅转发解析数据的随机量。 <hexdump> 将所有转发的数据转储到服务器和客户端。
此过滤器可用作开发新过滤器的基础。它定义了所有回调,并在标准错误流(stderr)上打印一条包含所有回调有用信息的消息。调试其他过滤器活动或 HAProxy 本身活动时可能很有用。使用 <;random-parsing> 和/或 <;random-forwarding> 参数是通过在处理中增加延迟来测试解析客户端和服务器之间交换数据的过滤器行为的好方法。
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.
<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”。
<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.
<name> is name of the fcgi-app section this filter will use.
FastCGI 应用程序使用一个过滤器来评估请求路径上的所有自定义参数,并处理响应路径上的头部信息。<name> 必须引用一个现有的 fcgi-app 节。指令 "use-fcgi-app" 应该用于定义要使用的应用程序。默认情况下,相应的过滤器是隐式定义的。当只使用缓存或压缩过滤器时,这就足够了。但是,当同一后端使用了除压缩或缓存之外的至少一个其他过滤器时,必须显式地使用 fcgi-app 的过滤器行。了解过滤器评估顺序非常重要。OpenTracing过滤器增加了对 HAProxy 中分布式跟踪的原生支持。通过向 Datadog、Jaeger、Lightstep 和 Zipkin 追踪器等受支持的追踪器发送符合 OpenTracing 标准的请求来启用此功能。请注意:追踪器列表不分先后,按字母顺序排列。此功能仅在 HAProxy 使用 USE_OT=1 构建时启用。OpenTracing 过滤器的激活通过在 HAProxy 配置中显式指定来实现。如果未这样做,OpenTracing 过滤器将不会参与 HAProxy 的任何工作。
<id> 是 OpenTracing 过滤器的 ID,用于在配置文件中查找正确的范围。如果未指定过滤器 ID,则默认使用 'ot-filter'。如果在配置文件中未指定范围,则适用于所有已定义的 OpenTracing 过滤器。<file> 是 OpenTracing 配置文件路径。同一文件可以同时包含多个 OpenTracing 过滤器的配置。在这种情况下,我们不需要定义范围,因此相同的配置适用于所有过滤器,或者每个过滤器必须定义自己的范围。
有关过滤器的操作、配置和使用的更详细文档可以在 addons/ot 目录中找到。注意:OpenTracing 过滤器不应在新设计中使用,因为 OpenTracing 本身不再由其作者维护或支持。基于 OpenTelemetry 的替代过滤器正在开发中,预计在 HAProxy 3.2 左右准备就绪。因此,OpenTracing 将在 3.3 中弃用,并在 3.5 中移除。
<name> 是过滤器名称,将被 'set-bandwidth-limit' 操作用于引用特定的带宽限制过滤器。<size> 是在此期间可以转发的最大字节数。必须为 per-stream 和 shared 带宽限制过滤器指定该值。它遵循 HAProxy 的大小格式,以字节为单位表示。<pattern> 是一个示例表达式规则,如 第 7.3 节 所述。它描述了将分析、提取、组合和用于选择更新计数器的表项的元素。它必须仅为 shared 带宽限制过滤器指定。<table> 是一个可选表,用于代替默认表,即在当前代理中声明的 stick-table。它只能为 shared 带宽限制过滤器指定。<time> 是用于评估带宽限制速率的默认时间段。它只能为 per-stream 带宽限制过滤器指定。它遵循 HAProxy 的时间格式,以毫秒为单位表示。<min-size> 是一个可选的最小字节数,流一次转发的字节数,不包括可能更小的最后一个数据包。此值可以为 per-stream 和 shared 带宽限制过滤器指定。它遵循 HAProxy 的大小格式,以字节为单位表示。
带宽限制过滤器应用于限制流级别的数据转发速度。因此,此类过滤器限制了资源消耗的网络带宽。可以使用多个带宽限制过滤器。例如,可以定义一个按源地址限制,以确保客户端不会消耗所有网络带宽,从而惩罚其他客户端;还可以定义另一个按流限制,以便公平处理给定客户端的多个连接。这些过滤器的定义顺序很重要。如果流上启用了多个带宽过滤器,则过滤将按其定义顺序应用。了解其他过滤器的定义顺序也很重要。例如,根据 HTTP 压缩过滤器是在带宽限制过滤器之前还是之后定义,限制将应用于压缩后的有效载荷或不应用。缓存过滤器也是如此。有两种带宽限制过滤器。第一种是实施默认限制并应用于每个流。第二种使用粘性表(stickiness table)来实施限制,该限制在共享同一表项的所有流之间平均分配。此外,对于给定的过滤器,根据使用的过滤器关键字,限制可以应用于传入数据(从客户端接收并转发到服务器)或传出数据(从服务器接收并发送到客户端)。要对传入数据应用限制,必须使用 "bwlim-in" 关键字。要对传出数据应用限制,必须使用 "bwlim-out" 关键字。在这两种情况下,带宽限制都应用于流级别的转发数据。带宽限制应用于流级别而不是连接级别。对于多路复用协议(H2、H3 和 FastCGI),同一连接的流可以有不同的限制。对于 per-stream 带宽限制过滤器,必须定义默认时间段和限制。顾名思义,它们是用于设置流带宽限制速率的默认值。但是,对于这种过滤器,并且只有这种过滤器,可以在使用 TCP/HTTP "set-bandwidth-limit" 操作启用过滤器时,使用示例表达式重新定义这些值。对于 shared 带宽限制过滤器,根据它是应用于传入数据还是传出数据,使用的粘性表必须存储相应的字节速率信息。必须存储 "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 为 Responder 应用程序实现了 FastCGI 规范的所有功能。特别是,它能够在单个连接上多路复用多个请求。声明一个名为 <name> 的 FastCGI 应用程序。要使其有效,至少必须定义 document root。
声明或完成访问列表。有关 ACL 用法的详细信息,请参见 第 4.2 节和 第 7 节中的“acl”关键字。为 FastCGI 应用程序定义的 ACL 是私有的。其他任何应用程序或代理都无法使用它们。同样,任何其他部分中定义的 ACL 也不适用于 FastCGI 应用程序。但是,预定义的 ACL 是可用的。
定义将在以斜杠 ("/") 结尾的 URI 之后附加的脚本名称,用于设置 FastCGI 参数 SCRIPT_NAME 的默认值。这是一个可选设置。index index.php
启用 FastCGI 应用程序报告的 STDERR 消息的日志记录。有关详细信息,请参见 第 4.2 节中的“log”关键字。这是一个可选设置。默认情况下,STDERR 消息会被忽略。
指定将传递到 FastCGI 应用程序的请求头名称。它可能可选地跟一个基于 ACL 的条件,在这种情况下,只有当条件为真时才会对其进行评估。大多数请求头已经可供 FastCGI 应用程序使用,并带有“HTTP_”前缀。因此,此指令仅用于传递故意省略的头。当前,“Authorization”、“Proxy-Authorization”以及 hop-by-hop 头都会被省略。请注意,“Content-type”和“Content-length”头永远不会传递给 FastCGI 应用程序,因为它们已经被转换为参数。
定义一个正则表达式,用于从 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 变量,此选项可能会被覆盖。默认情况下禁用。
设置一个应传递给此应用程序的 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)]
定义要用于后端的 FastCGI 应用程序。
<name> 是要使用的 FastCGI 应用程序的名称。
此关键字仅适用于具有后端功能且至少有一个 FastCGI 服务器的 HTTP 代理。但是,FastCGI 服务器可以与 HTTP 服务器混合。但除非有充分理由,否则不建议这样做(有关详细信息,请参见第 10.3 节的限制)。每个后端一次只能定义一个应用程序。请注意,一旦为后端引用了 FastCGI 应用程序,根据配置,即使请求未发送到 FastCGI 服务器,也可能会执行某些处理。将参数设置或将头传递到应用程序的规则会被评估。
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)(/.*)?$Responder FastCGI 应用程序与 CGI/1.1 程序具有相同的用途。在 CGI/1.1 规范 (RFC3875) 中,必须将几个变量传递给脚本。因此 HAProxy 设置了它们以及 FastCGI 应用程序常用的一些其他变量。所有这些变量都可以被覆盖,但需要谨慎。+-------------------+-----------------------------------------------------+ | AUTH_TYPE | 标识 HAProxy 用于验证用户的机制(如果有)。 | | | 具体来说,只支持 BASIC 验证机制。 | | | | +-------------------+-----------------------------------------------------+ | CONTENT_LENGTH | 包含附加到请求的消息体的大小。这意味着 | | | 只有具有已知大小的请求才被视为有效并发送到 | | | 应用程序。 | | | | +-------------------+-----------------------------------------------------+ | CONTENT_TYPE | 包含附加到请求的消息体的类型。它可能未设置。 | | | | | +-------------------+-----------------------------------------------------+ | DOCUMENT_ROOT | 包含脚本应在远程主机上执行的文档根目录, | | | 如应用程序配置中所定义。 | | | | +-------------------+-----------------------------------------------------+ | GATEWAY_INTERFACE | 包含 HAProxy 用于与 FastCGI 应用程序通信的 CGI 方言。 | | | 具体来说,它设置为 "CGI/1.1"。 | | | | +-------------------+-----------------------------------------------------+ | PATH_INFO | 包含 URI 路径层次结构中标识脚本本身的 | | | 部分之后的部分。要设置此项,必须定义指令 "path-info"。| | | | +-------------------+-----------------------------------------------------+ | PATH_TRANSLATED | 如果设置了 PATH_INFO,它是其翻译版本。 | | | 它是 DOCUMENT_ROOT 和 PATH_INFO 的串联。| | | 如果未设置 PATH_INFO,则此参数也未设置。 | | | | +-------------------+-----------------------------------------------------+ | QUERY_STRING | 包含请求的查询字符串。它可能未设置。 | | | | | +-------------------+-----------------------------------------------------+ | REMOTE_ADDR | 包含发送请求的客户端的网络地址。 | | | | | +-------------------+-----------------------------------------------------+ | REMOTE_USER | 包含客户端作为用户身份验证一部分提供的用户身份标识字符串。 | | | | | +-------------------+-----------------------------------------------------+ | REQUEST_METHOD | 包含脚本应用于处理请求的方法。 | | | | | +-------------------+-----------------------------------------------------+ | REQUEST_URI | 包含请求的 URI。 | | | | | +-------------------+-----------------------------------------------------+ | SCRIPT_FILENAME | 包含脚本的绝对路径名。它是 DOCUMENT_ROOT 和 SCRIPT_NAME 的串联。| | | | +-------------------+-----------------------------------------------------+ | SCRIPT_NAME | 包含脚本的名称。如果定义了指令 "path-info",| | | 它是 URI 路径层次结构的第一个部分,以脚本名称结尾。| | | 否则,它是整个 URI 路径。 | | | | +-------------------+-----------------------------------------------------+ | SERVER_NAME | 包含客户端请求所针对的服务器主机名。 | | | 如果定义了 "Host" 头部,则是其值。否则,是连接在客户端侧的 | | | 目标地址。 | | | | +-------------------+-----------------------------------------------------+ | SERVER_PORT | 包含连接在客户端侧的目标 TCP 端口,即客户端连接到的端口。 | | | | +-------------------+-----------------------------------------------------+ | SERVER_PROTOCOL | 包含请求的协议。 | | | | | +-------------------+-----------------------------------------------------+ | SERVER_SOFTWARE | 包含字符串 "HAProxy",后跟当前的 HAProxy 版本。 | | | | +-------------------+-----------------------------------------------------+ | HTTPS | 如果脚本是通过 HTTPS 协议查询的,则设置为非空值 ("on")。 | | | | +-------------------+-----------------------------------------------------+
当前的实现有一些限制。第一个是关于某些请求头部对 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 一旦编码,不得超过缓冲区的大小。但是,此处没有保留大小的要求。
有几个语句,如 "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"。可选地,可以使用前缀来强制地址族和/或套接字类型和传输方法。
'abns@<name>' 在 <name> 之后是一个抽象命名空间(仅限 Linux)。'abnsz@<name>' 在 <name> 之后是一个以零结尾的抽象命名空间(仅限 Linux)。'fd@<n>' 在地址之后是一个从父进程继承的文件描述符 <n>。fd 必须已绑定,并且可能已在侦听或未在侦听。'ip@<address>[:port1[-port2]]' 在 <address> 之后被视为 IPv4 或 IPv6 地址,具体取决于语法。根据使用此地址的语句,可以或必须指定端口或端口范围。'ipv4@<address>[:port1[-port2]]' 在 <address> 之后始终被视为 IPv4 地址。根据使用此地址的语句,可以或必须指定端口或端口范围。'ipv6@<address>[:port1[-port2]]' 在 <address> 之后始终被视为 IPv6 地址。根据使用此地址的语句,可以或必须指定端口或端口范围。'sockpair@<n>' 在地址之后是连接的 unix 套接字或 socketpair 的文件描述符。在连接期间,发起者创建一对连接的套接字,并将其中一个通过 FD 传递给另一端。侦听器等待从 unix 套接字接收 FD,并将其用作 accept() 的 FD。应谨慎使用。错误:已知此协议在 macOS 上不可靠,因为 macOS sendmsg(2) 实现存在问题。连接可能无法正确接受。'unix@<path>' 在字符串之后被视为 UNIX 套接字 <path>。此前缀可用于声明不以斜杠 '/' 开头的 UNIX 套接字路径。
以前的“地址族前缀”也可以作为前缀来强制套接字类型和传输方法。默认值取决于使用此地址的语句,但在某些情况下,用户可能会强制将其更改为不同的值。例如 "log" 语句,其中默认是 over UDP 的 syslog,但我们可以强制使用 over TCP 的 syslog。这些前缀是为内部目的设计的,用户应该使用下一节“11.3 协议前缀”的别名。然而,在某些情况下,这些可能很方便,例如与通过其文件描述符编号已知的继承套接字结合使用,在这种情况下,地址族是 "fd",并且必须声明套接字类型。如果用户需要其中一个前缀来执行他们期望的操作,因为他们无法使用协议前缀配置相同的功能,则应向维护人员报告。'stream+<family>@<address>' 强制套接字类型和传输方法为 "stream"'dgram+<family>@<address>' 强制套接字类型和传输方法为 "datagram"'quic+<family>@<address>' 强制套接字类型为 "datagram",传输方法为 "stream"。'quic4@<address>[:port1[-port2]]' 在 <address> 之后始终被视为 IPv4 地址,但套接字类型被强制为 "datagram",传输方法被强制为 "stream"。根据使用此地址的语句,可以或必须指定 UDP 端口或端口范围。它等效于 "quic+ipv4@"'quic6@<address>[:port1[-port2]]' 在 <address> 之后始终被视为 IPv6 地址,但套接字类型被强制为 "datagram",传输方法被强制为 "stream"。根据使用此地址的语句,可以或必须指定 UDP 端口或端口范围。它等效于 "quic+ipv6@"'tcp@<address>[:port1[-port2]]' 在 <address> 之后被视为 IPv4 或 IPv6 地址,具体取决于语法,但套接字类型和传输方法被强制为 "stream"。根据使用此地址的语句,可以或必须指定端口或端口范围。它被视为 'stream+ip@' 的别名。'tcp4@<address>[:port1[-port2]]' 在 <address> 之后始终被视为 IPv4 地址,但套接字类型和传输方法被强制为 "stream"。根据使用此地址的语句,可以或必须指定端口或端口范围。它被视为 'stream+ipv4@' 的别名。'tcp6@<address>[:port1[-port2]]' 在 <address> 之后始终被视为 IPv6 地址,但套接字类型和传输方法被强制为 "stream"。根据使用此地址的语句,可以或必须指定端口或端口范围。它被视为 'stream+ipv4@' 的别名。'mptcp@<address>[:port1[-port2]]' 在 <address> 之后被视为 IPv4 或 IPv6 地址,具体取决于语法,但套接字类型和传输方法被强制为 "stream",使用 MPTCP 协议。根据使用此地址的语句,可以或必须指定端口或端口范围。'mptcp4@<address>[:port1[-port2]]' 在 <address> 之后始终被视为 IPv4 地址,但套接字类型和传输方法被强制为 "stream",使用 MPTCP 协议。根据使用此地址的语句,可以或必须指定端口或端口范围。'mptcp6@<address>[:port1[-port2]]' 在 <address> 之后始终被视为 IPv6 地址,但套接字类型和传输方法被强制为 "stream",使用 MPTCP 协议。根据使用此地址的语句,可以或必须指定端口或端口范围。'udp@<address>[:port1[-port2]]' 在 <address> 之后被视为 IPv4 或 IPv6 地址,具体取决于语法,但套接字类型和传输方法被强制为 "datagram"。根据使用此地址的语句,可以或必须指定端口或端口范围。它被视为 'dgram+ip@' 的别名。'udp4@<address>[:port1[-port2]]' 在 <address> 之后始终被视为 IPv4 地址,但套接字类型和传输方法被强制为 "datagram"。根据使用此地址的语句,可以或必须指定端口或端口范围。它被视为 'dgram+ipv4@' 的别名。'udp6@<address>[:port1[-port2]]' 在 <address> 之后始终被视为 IPv6 地址,但套接字类型和传输方法被强制为 "datagram"。根据使用此地址的语句,可以或必须指定端口或端口范围。它被视为 'dgram+ipv4@' 的别名。'uxdg@<path>' 在字符串之后被视为 unix 套接字 <path>,但传输方法被强制为 "datagram"。它被视为 'dgram+unix@' 的别名。'uxst@<path>' 在字符串之后被视为 unix 套接字 <path>,但传输方法被强制为 "stream"。它被视为 'stream+unix@' 的别名。在未来的版本中,可以使用其他前缀来指定 QUIC 等协议,这些协议基于 "datagram" 类型的套接字提供流传输。