本文档涵盖了上述版本中实现的配置语言。它不提供任何提示、示例或建议。有关此类文档,请参阅参考手册或架构手册。以下摘要旨在帮助您按名称查找章节并在文档中导航。文档贡献者须知:本文档每行格式化为80列,使用偶数个空格进行缩进,不使用制表符。请严格遵守这些规则,以便在任何地方都能轻松打印。如果某行需要逐字打印且不适合,请在每行末尾加上反斜杠('\'),并在下一行继续,缩进两个字符。有时,为了强调输入和输出之间的差异,当它们可能模糊不清时,用三个闭合尖括号('>>>')作为所有输出行(日志、控制台输出)的前缀也很有用。如果添加新章节,请更新下面的摘要以便于搜索。
| 1. | 关于 HTTP 的快速提醒 | |
| 1.1. | ||
| 1.2. | ||
| 1.2.1. | ||
| 1.2.2. | ||
| 1.3. | ||
| 1.3.1. | ||
| 1.3.2. | ||
2. |
配置 HAProxy | |
| 2.1. | ||
| 2.2. | ||
| 2.3. | ||
| 2.4. | ||
| 2.5. | ||
3. |
全局参数 | |
| 3.1. | ||
| 3.2. | ||
| 3.3. | ||
| 3.4. | ||
| 3.5. | ||
| 3.6. | ||
| 3.7. | ||
4. |
代理 | |
| 4.1. | ||
| 4.2. | ||
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.4. | ||
8. |
日志 | |
| 8.1. | ||
| 8.2. | ||
| 8.2.1. | ||
| 8.2.2. | ||
| 8.2.3. | ||
| 8.2.4. | ||
| 8.2.5. | ||
| 8.3. | ||
| 8.3.1. | ||
| 8.3.2. | ||
| 8.3.3. | ||
| 8.3.4. | ||
| 8.4. | ||
| 8.5. | ||
| 8.6. | ||
| 8.7. | ||
| 8.8. | ||
| 8.9. | ||
9. |
支持的过滤器 | |
| 9.1. | ||
| 9.2. | ||
| 9.3. | ||
| 9.4. | ||
| 9.5. | ||
10. |
FastCGI 应用程序 | |
| 10.1. | ||
| 10.1.1. | ||
| 10.1.2. | ||
| 10.1.3. | ||
| 10.2. | ||
| 10.3. |
当 HAProxy 在 HTTP 模式下运行时,请求和响应都会被完全分析和索引,因此可以根据内容中找到的几乎任何信息来构建匹配标准。然而,重要的是要了解 HTTP 请求和响应是如何构成的,以及 HAProxy 是如何分解它们的。这样将更容易编写正确的规则并调试现有配置。
HTTP 协议是事务驱动的。这意味着每个请求都会且只会产生一个响应。传统上,客户端会建立一个到服务器的 TCP 连接,客户端通过该连接发送一个请求,服务器响应,然后连接关闭。一个新的请求需要一个新的连接:[CON1] [REQ1] ... [RESP1] [CLO1] [CON2] [REQ2] ... [RESP2] [CLO2] ... 在这种模式下,称为“HTTP close”模式,有多少 HTTP 事务就有多少连接建立。由于服务器在响应后关闭连接,客户端不需要知道内容长度。由于协议的事务特性,可以对其进行改进,以避免在两个后续事务之间关闭连接。然而,在这种模式下,服务器必须为每个响应指示内容长度,以便客户端不会无限期地等待。为此,使用了一个特殊的标头:“Content-length”。这种模式被称为“keep-alive”模式:[CON] [REQ1] ... [RESP1] [REQ2] ... [RESP2] [CLO] ... 它的优点是事务之间的延迟减少,并且服务器端所需的处理能力更少。它通常优于 close 模式,但并非总是如此,因为客户端通常会将其并发连接限制在一个较小的值。通信中的另一个改进是流水线(pipelining)模式。它仍然使用 keep-alive,但客户端不等第一个响应就发送第二个请求。这对于获取构成页面的大量图像很有用:[CON] [REQ1] [REQ2] ... [RESP1] [RESP2] [CLO] ... 这显然对性能有巨大的好处,因为后续请求之间的网络延迟被消除了。许多 HTTP 代理不支持正确的流水线操作,因为 HTTP 中没有办法将响应与相应的请求关联起来。因此,服务器必须按照接收请求的完全相同的顺序回复。下一个改进是多路复用模式,如 HTTP/2 中实现的那样。这一次,每个事务都被分配一个流标识符,所有流都在现有连接上多路复用。客户端可以并行发送许多请求,响应可以以任何顺序到达,因为它们也携带着流标识符。默认情况下,HAProxy 在处理持久连接时以 keep-alive 模式运行:对于每个连接,它处理每个请求和响应,并在一个响应结束和新请求开始之间将连接置于空闲状态。当它从客户端接收到 HTTP/2 连接时,它会并行处理所有请求并使连接空闲,等待新请求,就像它是一个 keep-alive HTTP 连接一样。HAProxy 支持 4 种连接模式:- keep alive:处理所有请求和响应(默认)- tunnel:只处理第一个请求和响应,其余内容不经分析直接转发(已弃用)。- server close:服务器端的连接在响应后关闭。- close:连接在响应结束时被主动关闭。
首先,让我们考虑这个 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 方法关联时被接受,并且不可中继。它用于查询下一跳的功能。- 地址:端口组合:192.168.0.12:80这与 CONNECT 方法一起使用,CONNECT 方法用于通过 HTTP 代理建立 TCP 隧道,通常用于 HTTPS,但有时也用于其他协议。在相对 URI 中,识别出两个子部分。问号之前的部分称为“路径”。它通常是服务器上静态对象的相对路径。问号之后的部分称为“查询字符串”。它主要用于发送给动态脚本的 GET 请求,并且非常特定于所使用的语言、框架或应用程序。HTTP/2 不会随请求传输版本信息,因此版本被假定为与底层协议的版本相同(即“HTTP/2”)。
标头从第二行开始。它们由行首的名称组成,紧跟着一个冒号(':')。传统上,冒号后会添加 LWS,但这不是必需的。然后是值。多个相同的标头可以折叠成一行,用逗号分隔值,前提是它们的顺序得到尊重。这在 "Cookie:" 字段中很常见。如果后续行以 LWS 开头,则标头可以跨多行。在 1.2 中的示例中,第 4 行和第 5 行定义了 "Accept:" 标头的总共 3 个值。与常见的误解相反,标头名称不区分大小写,如果它们引用其他标头名称(例如 "Connection:" 标头),它们的值也不区分大小写。在 HTTP/2 中,标头名称总是以小写形式发送,在调试模式下运行时可以看到这一点。在内部,所有标头名称都被规范化为小写,以便 HTTP/1.x 和 HTTP/2 使用完全相同的表示形式,并且它们按原样发送到另一端。这解释了为什么以驼峰式大小写键入的 HTTP/1.x 请求会以小写形式传递。标头的结束由第一个空行指示。人们经常说这是双换行符,这不准确,即使双换行符是空行的一种有效形式。幸运的是,HAProxy 在索引标头、检查值和计数时会处理所有这些复杂的组合,因此无需担心它们的写入方式,但重要的是不要因为应用程序执行不寻常但有效的事情而指责它有错误。重要提示:正如 RFC7231 所建议的那样,HAProxy 通过用 LWS 替换标头中间的换行符来规范化标头,以便连接多行标头。这对于正确的分析是必要的,并有助于功能较弱的 HTTP 解析器正常工作,不被此类复杂结构所欺骗。
HTTP 响应看起来非常像 HTTP 请求。两者都称为 HTTP 消息。让我们考虑这个 HTTP 响应:行号 内容 1 HTTP/1.1 200 OK 2 Content-length: 350 3 Content-Type: text/html 作为一个特例,HTTP 支持所谓的 "信息性响应",即状态码 1xx。这些消息的特殊之处在于它们不传达响应的任何部分,它们仅用作一种信号消息,例如要求客户端继续发送请求。在状态 100 响应的情况下,请求的信息将由紧随信息性消息之后的下一个非 100 响应消息携带。这意味着可以向单个请求发送多个响应,并且只有在启用保持活动状态时才有效(1xx 消息仅限于 HTTP/1.1)。HAProxy 处理这些消息,并能够正确地转发和跳过它们,只处理下一个非 100 响应。因此,除非另有明确说明,否则这些消息既不会被记录也不会被转换。状态 101 消息表示协议正在同一连接上更改,haproxy 必须切换到隧道模式,就像发生了 CONNECT 一样。然后 Upgrade 标头将包含有关连接正在切换到的协议类型的附加信息。
第 1 行是“响应行”。它总是由 3 个字段组成:- 版本标签:HTTP/1.1 - 状态码:200 - 原因短语:OK 状态码始终为 3 位数字。第一位数字表示一般状态:- 1xx = 要跳过的信息性消息(例如 100、101) - 2xx = OK,内容正在发送中(例如 200、206) - 3xx = OK,没有内容发送中(例如 302、304) - 4xx = 客户端导致的错误(例如 401、403、404) - 5xx = 服务器导致的错误(例如 500、502、503) 请参阅 RFC7231 了解所有此类代码的详细含义。“原因”字段只是一个提示,但不会被客户端解析。那里可以找到任何内容,但尊重既定的消息是一种常见做法。它可以由一个或多个单词组成,例如 "OK"、"Found" 或 "Authentication Required"。HAProxy 本身可能会发出以下状态码:代码 时间/原因 200 访问统计信息页面,以及回复监控请求时 301 执行重定向时,具体取决于配置的代码 302 执行重定向时,具体取决于配置的代码 303 执行重定向时,具体取决于配置的代码 307 执行重定向时,具体取决于配置的代码 308 执行重定向时,具体取决于配置的代码 400 请求无效或太大 401 执行操作需要身份验证时(访问统计信息页面时) 403 请求被 "http-request deny" 规则禁止时 404 找不到请求的资源时 408 请求超时在请求完成之前发生时 410 请求的资源不再可用且以后也不会再可用时 500 haproxy 遇到不可恢复的内部错误时,例如内存分配失败,这不应该发生 502 服务器返回空、无效或不完整的响应时,或者 "http-response deny" 规则阻止响应时。 503 没有可用的服务器来处理请求时,或者响应与 "monitor fail" 条件匹配的监控请求时 504 响应超时在服务器响应之前发生时 上述 4xx 和 5xx 错误代码可以自定义(请参阅第 4.2 节中的 "errorloc")。
响应头的处理方式与请求头完全相同,因此 HAProxy 对两者使用相同的解析函数。更多详情请参考 1.2.2 段。
HAProxy 的配置过程涉及 3 个主要的参数来源: - 命令行参数,它们总是优先 - “global”部分,设置进程范围的参数 - 代理部分,可以采用“defaults”、“listen”、“frontend”和“backend”的形式。配置文件语法由以本手册中引用的关键字开头的行组成,后面可以选择性地跟一个或多个由空格分隔的参数。
HAProxy 的配置引入了类似于许多编程语言的引用和转义系统。配置文件支持 3 种类型:反斜杠转义、双引号弱引用和单引号强引用。如果必须在字符串中输入空格,则必须在其前面加上反斜杠 ('\') 或将其引用。反斜杠本身也必须通过加倍或强引用来转义。转义是通过在特殊字符前加上反斜杠 ('\') 来实现的: \ 标记一个空格并将其与分隔符区分开来 \# 标记一个哈希并将其与注释区分开来 \\ 使用反斜杠 \' 使用单引号并将其与强引用区分开来 \" 使用双引号并将其与弱引用区分开来 弱引用是通过使用双引号 ("") 来实现的。弱引用会阻止对以下内容的解释: 空格作为参数分隔符 ' 单引号作为强引用分隔符 # 哈希作为注释开始 弱引用允许解释变量,如果要在双引号字符串中使用未解释的美元符号,则应使用反斜杠 ("\$")对其进行转义,这在弱引用之外不起作用。弱引用不会阻止转义和特殊字符的解释。强引用是通过使用单引号 ('') 来实现的。在单引号内,不解释任何内容,这是引用正则表达式的有效方式。被引用和转义的字符串在内存中被替换为它们的解释等价物,这允许您执行连接操作。# 以下是等价的: 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 # 以下是等价的: reqrep "^([^\ :]*)\ /static/(.*)" \1\ /\2 reqrep "^([^ :]*)\ /static/(.*)" '\1 /\2' reqrep "^([^ :]*)\ /static/(.*)" "\1 /\2" reqrep "^([^ :]*)\ /static/(.*)" "\1\ /\2"
HAProxy 的配置支持环境变量。这些变量仅在双引号内被解释。变量在配置解析期间展开。变量名前必须加上美元符号("$"),并可选地用大括号("{}")括起来,类似于 Bourne shell 中的做法。变量名可以包含字母数字字符或下划线("_"),但不应以数字开头。bind "fd@${FD_APP1}" log "${LOCAL_SYSLOG}:514" local0 notice # 发送到本地服务器 user "$HAPROXY_USER"
一些变量由 HAProxy 定义,它们可以在配置文件中使用,或者可以被程序继承(参见 3.7. 程序): * HAPROXY_LOCALPEER:在进程启动时定义,包含本地对等体的名称。(参见管理指南中的 "-L"。) * HAPROXY_CFGFILES:由 HAProxy 加载的配置文件列表,以分号分隔。如果您指定了一个目录,这可能很有用。 * HAPROXY_MWORKER:在主-工作者模式下,此变量设置为 1。 * HAPROXY_CLI:为每个进程配置的统计套接字的监听地址,以分号分隔。 * HAPROXY_MASTER_CLI:在主-工作者模式下,主 CLI 的监听地址,以分号分隔。另请参见“external-check command”了解其他变量。
一些参数涉及表示时间的值,例如超时。这些值通常以毫秒表示(除非另有明确说明),但也可以通过在数值后附加单位来以任何其他单位表示。考虑这一点很重要,因为每个关键字都不会重复说明。支持的单位有:- 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
# 一个简单的 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" 部分支持以下关键字:* 进程管理和安全性 - ca-base - chroot - crt-base - cpu-map - daemon - description - deviceatlas-json-file - deviceatlas-log-level - deviceatlas-separator - deviceatlas-properties-cookie - external-check - gid - group - hard-stop-after - h1-case-adjust - h1-case-adjust-file - log - log-tag - log-send-hostname - lua-load - lua-prepend-path - mworker-max-reloads - nbproc - nbthread - node - pidfile - presetenv - resetenv - uid - ulimit-n - user - set-dumpable - setenv - stats - ssl-default-bind-ciphers - ssl-default-bind-ciphersuites - ssl-default-bind-options - ssl-default-server-ciphers - ssl-default-server-ciphersuites - ssl-default-server-options - ssl-dh-param-file - ssl-server-verify - unix-bind - unsetenv - 51degrees-data-file - 51degrees-property-name-list - 51degrees-property-separator - 51degrees-cache-size - wurfl-data-file - wurfl-information-list - wurfl-information-list-separator - wurfl-cache-size - strict-limits * 性能调优 - busy-polling - max-spread-checks - maxconn - maxconnrate - maxcomprate - maxcompcpuusage - maxpipes - maxsessrate - maxsslconn - maxsslrate - maxzlibmem - noepoll - nokqueue - noevports - nopoll - nosplice - nogetaddrinfo - noreuseport - profiling.tasks - spread-checks - server-state-base - server-state-file - ssl-engine - ssl-mode-async - tune.buffers.limit - tune.buffers.reserve - tune.bufsize - tune.chksize - tune.comp.maxlevel - tune.h2.header-table-size - tune.h2.initial-window-size - tune.h2.max-concurrent-streams - tune.http.cookielen - tune.http.logurilen - tune.http.maxhdr - tune.idletimer - tune.lua.forced-yield - tune.lua.maxmem - tune.lua.session-timeout - tune.lua.task-timeout - tune.lua.service-timeout - tune.maxaccept - tune.maxpollevents - tune.maxrewrite - tune.pattern.cache-size - tune.pipesize - tune.pool-high-fd-ratio - tune.pool-low-fd-ratio - tune.rcvbuf.client - tune.rcvbuf.server - tune.recv_enough - tune.runqueue-depth - tune.sndbuf.client - tune.sndbuf.server - tune.ssl.cachesize - tune.ssl.lifetime - tune.ssl.force-private-cache - tune.ssl.maxrecord - tune.ssl.default-dh-param - tune.ssl.ssl-ctx-cache-size - tune.ssl.capture-cipherlist-size - 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 * 调试 - debug - quiet
当使用相对路径与 "ca-file" 或 "crl-file" 指令时,分配一个默认目录来获取 SSL CA 证书和 CRL。在 "ca-file" 和 "crl-file" 中指定的绝对位置优先,并忽略 "ca-base"。
在降低权限之前,将当前目录更改为 <jail dir> 并在那里执行 chroot()。这提高了安全级别,以防未知漏洞被利用,因为它会使攻击者很难利用系统。这仅在进程以超级用户权限启动时有效。确保 <jail_dir> 既为空又对任何人不可写非常重要。
在 Linux 2.6 及更高版本上,可以将进程或线程绑定到特定的 CPU 集。这意味着进程或线程永远不会在其他 CPU 上运行。"cpu-map" 指令指定进程集或线程集的 CPU 集。第一个参数是进程集,后面跟着线程集(可选)。这些集的格式为 all | odd | even | number[-[number]]必须是 1 到 32 或 64 之间的数字,具体取决于机器的字大小。任何大于 nbproc 的进程 ID 和任何大于 nbthread 的线程 ID 都将被忽略。可以使用两个用破折号 ('-') 分隔的数字来指定范围。也可以使用 "all" 一次指定所有进程,使用 "odd" 仅指定奇数,或使用 "even" 仅指定偶数,就像使用 "bind-process" 指令一样。第二个及后续参数是 CPU 集。每个 CPU 集要么是 0 到 31 或 63 之间的唯一数字,要么是用破折号 ('-') 分隔的两个此类数字的范围。可以指定多个 CPU 号码或范围,并且允许进程或线程绑定到所有这些号码或范围。显然,可以指定多个 "cpu-map" 指令。每个 "cpu-map" 指令在重叠时会替换前面的指令。线程将绑定到其映射与所附进程映射的交集。如果交集为空,则不会为线程设置特定的绑定。范围可以部分定义。可以省略上限。在这种情况下,它会被替换为相应的最大值,即 32 或 64,具体取决于机器的字大小。可以在进程集前添加 "auto:" 前缀,让 HAProxy 通过递增进程/线程和 CPU 集来自动将进程或线程绑定到 CPU。为了有效,两个集必须具有相同的大小。无论 CPU 集的声明顺序如何,它都将从最低绑定到最高绑定。不支持使用 "auto:" 前缀的进程范围和线程范围。只支持一个范围,另一个必须是固定数字。
cpu-map 1-4 0-3 # 将进程 1 到 4 绑定到前 4 个 CPU cpu-map 1/all 0-3 # 将第一个进程的所有线程绑定到 # 前 4 个 CPU cpu-map 1- 0- # 将被替换为 "cpu-map 1-64 0-63" # 或 "cpu-map 1-32 0-31",具体取决于机器的 # 字大小。 # 所有这些行都将进程 1 绑定到 cpu 0,进程 2 绑定到 cpu 1 # 等等。 cpu-map auto:1-4 0-3 cpu-map auto:1-4 0-1 2-3 cpu-map auto:1-4 3 2 1 0 # 所有这些行都将线程 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 # 使用 all/odd/even 关键字将每个进程绑定到一个 CPU cpu-map auto:all 0-63 cpu-map auto:even 0-31 cpu-map auto:odd 32-63 # 无效的 cpu-map,因为进程集和 CPU 集的大小不同。 cpu-map auto:1-4 0 # 无效 cpu-map auto:1 0-3 # 无效 # 无效的 cpu-map,因为自动绑定与进程范围 # 和线程范围一起使用。 cpu-map auto:all/all 0 # 无效 cpu-map auto:all/1-4 0 # 无效 cpu-map auto:1-4/all 0 # 无效
当使用 "crtfile" 指令的相对路径时,分配一个用于获取 SSL 证书的默认目录。"crtfile" 后面指定的绝对位置优先,并忽略 "crt-base"。
使进程 fork 到后台运行。这是推荐的操作模式。它等同于命令行参数 "-D"。它可以通过命令行参数 "-db" 禁用。此选项在 systemd 模式下被忽略。
设置要由 API 加载的 DeviceAtlas JSON 数据文件的路径。该路径必须是一个有效的 JSON 数据文件,并且 HAProxy 进程可以访问。
设置 API 返回的信息级别。此指令是可选的,如果未设置,则默认为 0。
设置 API 属性结果的字符分隔符。此指令是可选的,如果未设置,则默认为 |。
设置用于检测请求期间是否使用了 DeviceAtlas 客户端组件的客户端 cookie 名称。此指令是可选的,如果未设置,则默认为 DAPROPS。
允许使用外部代理执行健康检查。作为安全预防措施,此功能默认禁用。请参阅 "option external-check"。
将进程的组 ID 更改为 <number>。建议将组 ID 专用于 HAProxy 或一小组类似的守护程序。HAProxy 必须以属于此组的用户或具有超级用户权限的用户身份启动。请注意,如果 haproxy 是从具有辅助组的用户启动的,则只有在具有超级用户权限的情况下才能删除这些组。另请参阅 "group" 和 "uid"。
类似于 "gid",但使用 /etc/group 中组名 <group name> 的 GID。另请参阅 "gid" 和 "user"。
定义执行干净的软停止所允许的最长时间。
<time> 是实例在通过 SIGUSR1 信号接收到软停止时将保持活动的最长时间(默认为毫秒)。
这可用于确保即使在软停止期间连接保持打开(例如,在 tcp 模式下为代理设置了长超时),实例也会退出。它适用于 TCP 和 HTTP 模式。
global hard-stop-after 30s
定义在发送给 HTTP/1 客户端或服务器之前,对标头名称 <from> 应用的大小写调整,将其更改为 <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"。
添加一个全局 syslog 服务器。可以定义多个全局服务器。它们将接收启动和退出日志,以及配置了 "log global" 的代理的所有日志。<address> 可以是以下之一: - IPv4 地址,可选后跟冒号和 UDP 端口。如果未指定端口,则默认使用 514(标准 syslog 端口)。 - IPv6 地址,后跟冒号和可选的 UDP 端口。如果未指定端口,则默认使用 514(标准 syslog 端口)。 - 数据报 UNIX 域套接字的 filesystem 路径,需要考虑 chroot(确保路径在 chroot 内部可访问)和 uid/gid(确保路径可适当写入)。 - 形式为 "fd@<number>" 的文件描述符号码,可以指向管道、终端或套接字。在这种情况下,使用非缓冲日志,并且每个日志执行一次 writev() 调用。这有点昂贵,但对于大多数工作负载来说是可以接受的。以这种方式发送的消息不会被截断,但可能会被丢弃,在这种情况下,DroppedLogs 计数器会增加。即使在管道上,writev() 调用对于小于 PIPE_BUF 大小的消息也是原子的,POSIX 建议至少为 512,在大多数现代操作系统上为 4096 字节。任何更大的消息都可能与来自其他进程的消息交错。对于调试目的,文件描述符也可以指向文件,但这会显着降低 haproxy 的速度,因为非阻塞调用将被忽略。此外,没有办法在不重新启动进程的情况下清除或旋转此文件。请注意,配置的 syslog 格式会保留下来,因此输出适合与 TCP syslog 服务器一起使用。另请参阅下面的 "short" 和 "raw" 格式。 - "stdout" / "stderr",它们分别是 "fd@1" 和 "fd@2" 的别名,如上所述。 - 形式为 "ring@<name>" 的环形缓冲区,它对应于可通过 CLI 使用 "show events" 命令访问的内存中环形缓冲区,该命令还会列出现有环形缓冲区及其大小。此类缓冲区在重新加载或重新启动时会丢失,但作为补充使用时,可以通过立即获得日志来帮助故障排除。您可能希望在地址参数中引用一些环境变量,请参阅关于环境变量的第 2.3 节。<length> 是一个可选的最大行长度。大于此值的日志行在发送前将被截断。原因是 syslog 服务器对日志行长度的处理方式不同。所有服务器都支持默认值 1024,但有些服务器只是丢弃较长的行,而另一些服务器则会记录它们。如果服务器支持长行,则在此处设置此值以避免截断长行可能是有意义的。同样,如果服务器丢弃长行,最好在发送前截断它们。接受的值为 80 到 65535(包括)。默认值 1024 通常适用于所有标准用法。某些特定的长捕获或 JSON 格式日志可能需要更大的值。如果您的请求 URI 被截断,您可能还需要增加 "tune.http.logurilen"。<format> 是生成 syslog 消息时使用的日志格式。它可以是以下之一: rfc3164 RFC3164 syslog 消息格式。这是默认值。(https://tools.ietf.org/html/rfc3164) rfc5424 RFC5424 syslog 消息格式。(https://tools.ietf.org/html/rfc5424) short 仅包含尖括号中级别的消息,例如 '<3>',后跟文本。PID、日期、时间、进程名称和系统名称被省略。这旨在用于本地日志服务器。此格式与 systemd logger 消费的格式兼容。 raw 仅包含文本的消息。级别、PID、日期、时间、进程名称和系统名称被省略。这旨在用于容器或开发期间,其中严重性仅取决于使用的文件描述符(stdout/stderr)。<ranges> 逗号分隔的范围列表,用于标识要采样的日志。这用于平衡发送到日志服务器的日志负载。范围的限制不能为 null。它们从 1 开始编号。样本的大小或周期(以日志数量计)必须使用 <sample_size> 参数设置。<sample_size> 在平衡日志记录负载时要考虑的日志数量中的样本大小。它用于平衡发送到 syslog 服务器的日志负载。此大小必须大于或等于范围高限制的最大值。(另请参阅 <ranges> 参数)。<facility> 必须是 24 个标准 syslog 设施之一:kern user mail daemon auth syslog lpr news uucp cron auth2 ftp ntp audit alert cron2 local0 local1 local2 local3 local4 local5 local6 local7 请注意,对于 "short" 和 "raw" 格式,设施会被忽略,但仍需要作为位置字段。建议在这种情况下使用 "daemon",以明确它只应该在本地使用。可以指定一个可选级别来过滤出站消息。默认情况下,所有消息都发送。如果指定了最大级别,则只发送严重性至少与此级别一样重要的消息。可以指定一个可选的最小级别。如果设置了,则以比此级别更严重的级别发出的日志将被限制为此级别。这用于避免在某些默认 syslog 配置上向所有终端发送 "emerg" 消息。已知有八个级别:emerg alert crit err warning notice info debug
设置 syslog 报头中的 hostname 字段。如果设置了可选的 "string" 参数,则报头将设置为该字符串内容,否则使用系统的主机名。通常在不通过中间 syslog 服务器中继日志或仅为自定义日志中打印的主机名时使用。
将 syslog 报头中的 tag 字段设置为此字符串。它默认为从命令行启动的程序名,通常是 "haproxy"。有时,区分同一主机上运行的多个进程会很有用。另请参阅每个代理的 "log-tag" 指令。此全局指令加载并执行一个 Lua 文件。此指令可以多次使用。
在 Lua 的 package.<type> 变量前面添加给定的字符串,后跟一个分号。<type> 必须是 "path" 或 "cpath"。如果未给出 <type>,则默认为 "path"。Lua 的路径是以分号分隔的模式列表,用于指定 `require` 函数如何尝试查找库的源文件。模式中的问号 (?) 将替换为模块名称。路径从左到右评估。这意味着稍后添加的路径将首先被检查。例如,通过指定以下路径:lua-prepend-path /usr/share/haproxy-lua/?/init.lua lua-prepend-path /usr/share/haproxy-lua/?.lua 当调用 `require "example"` 时,Lua 将首先尝试加载 /usr/share/haproxy-lua/example.lua 脚本,如果不存在,则尝试 /usr/share/haproxy-lua/example/init.lua,如果仍不存在,则尝试默认路径。有关 Lua 文档中的详细信息,请参阅 https://lua.ac.cn/pil/8.1.html。
主-工作者模式。它等同于命令行参数“-W”。此模式将启动一个“主进程”,该进程将监控“工作进程”。使用此模式,您可以通过向主进程发送 SIGUSR2 信号来直接重新加载 HAProxy。主-工作者模式与前台或守护进程模式兼容。建议在多进程和 systemd 环境下使用此模式。默认情况下,如果一个工作进程以错误的返回码退出,例如在发生段错误的情况下,所有工作进程都将被杀死,主进程将退出。将此行为与 systemd 单元文件中的 Restart=on-failure 结合使用,以重新启动整个进程是很方便的。如果您不希望有此行为,则必须使用关键字“no-exit-on-failure”。另请参见管理指南中的“-W”。
在主-从模式下,此选项限制了工作进程可以承受的重载次数。如果工作进程在重载后没有退出,一旦其重载次数大于此数字,该工作进程将收到一个 SIGTERM 信号。此选项有助于控制工作进程的数量。另请参阅管理指南中的“show proc”。
创建 <number> 个进程以进入 daemon 模式。这需要“daemon”模式。默认情况下,只创建一个进程,这是推荐的操作模式。对于文件描述符数量有限的系统,可能需要派生多个守护进程。当设置为大于 1 的值时,线程会自动禁用。使用多个进程更难调试,并且强烈不推荐。另请参阅“daemon”和“nbthread”。
此设置仅在内置线程支持时可用。它使 haproxy 运行 <number> 个线程。这与 "nbproc" 互斥。虽然 "nbproc" 历史上曾是使用多个处理器D的唯一方式,但它也涉及许多与进程之间缺乏同步(健康检查、对等体、粘性表、统计数据等)相关的缺点,这些缺点不影响线程。因此,强烈建议任何现代配置从 "nbproc" 迁移到 "nbthread"。"nbthread" 在 HAProxy 在前台启动时也有效。在某些支持 CPU 亲和性的平台上,当不使用 nbproc 时,默认的 "nbthread" 值会自动设置为进程在启动时绑定到的 CPU 数量。这意味着线程数可以很容易地通过调用进程使用 "taskset" 或 "cpuset" 等命令进行调整。否则,此值默认为 1。默认值在 "haproxy -vv" 的输出中报告。另请参阅 "nbproc"。
将所有守护进程的 PID 写入文件 <pidfile>。此选项等同于“-p”命令行参数。该文件必须对启动进程的用户可访问。另请参阅“daemon”。
将环境变量 <name> 设置为值 <value>。如果该变量已存在,则不会被覆盖。更改会立即生效,以便配置文件中的下一行可以看到新值。另请参阅 "setenv"、"resetenv" 和 "unsetenv"。
删除除参数中指定的环境变量之外的所有环境变量。它允许在使用 setenv 或 unsetenv 设置新值之前,使用一个干净受控的环境。请注意,一些内部函数可能会使用某些环境变量,例如时间操作函数,以及 OpenSSL 甚至外部检查。此命令必须极其小心使用,并且只能在完全验证后使用。更改会立即生效,因此配置文件中的下一行将看到新的环境。另请参阅 “setenv”、“presetenv” 和 “unsetenv”。
将统计套接字限制为一组特定的进程号。默认情况下,统计套接字绑定到所有进程,当 nbproc 大于 1 时会发出警告,因为连接时无法选择目标进程。但是,通过使用此设置,可以将统计套接字固定到一组特定的进程,通常是第一个进程。使用此设置后,无论使用多少个进程,警告都将自动禁用。最大进程 ID 取决于机器的字长(32 位或 64 位)。范围可以部分定义。可以省略上限。在这种情况下,它将被相应的最大值替换。一个更好的选择是在“stats socket”行的“process”设置中强制指定每行的进程。
指定目录前缀,该前缀将附加在所有不以“/”开头的服务器状态文件名前面。另请参阅 "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"。
将环境变量 <name> 设置为值 <value>。如果该变量存在,则会被覆盖。更改会立即生效,因此配置文件中的下一行将看到新的值。另请参阅 “presetenv”、“resetenv” 和 “unsetenv”。
此选项最好默认禁用,仅在开发人员要求时启用。如果已启用,可以通过在其前面加上“no”关键字来强制禁用。它对性能或稳定性没有影响,但会尽力重新启用可能因文件大小限制(ulimit -f)、核心大小限制(ulimit -c)或更改 UID/GID 后进程的“可转储性”(例如 Linux 上的 /proc/sys/fs/suid_dumpable)而禁用的核心转储。核心转储可能仍受到当前目录权限(检查启动文件的目录)、chroot 目录权限(可能需要暂时禁用 chroot 指令或将其移动到专用的可写位置)或任何其他系统特定约束的限制。例如,一些 Linux 发行版以将默认核心文件替换为系统上甚至未安装的可执行文件路径而臭名昭著(检查 /proc/sys/kernel/core_pattern)。通常,只需写入“core”、“core.%p”或“/var/log/core/core.%p”即可解决问题。当尝试启用此选项并等待罕见问题再次出现时,通常最好先尝试通过向 haproxy 进程发出例如“kill -11”来获取此类转储,并验证它在崩溃时是否按预期留下了核心文件。
此设置仅在内置 OpenSSL 支持时可用。它设置了默认字符串,描述了在 SSL/TLS 握手期间协商的密码算法列表(“密码套件”),最高支持 TLSv1.2,适用于所有未明确定义自己的 "bind" 行。该字符串的格式在 OpenSSL 手册页中的“man 1 ciphers”中定义。有关背景信息和建议,请参阅例如 (https://wiki.mozilla.org/Security/Server_Side_TLS) 和 (https://mozilla.github.io/server-side-tls/ssl-config-generator/)。对于 TLSv1.3 密码配置,请检查 "ssl-default-bind-ciphersuites" 关键字。请检查 "bind" 关键字以获取更多信息。
此设置仅在内置 OpenSSL 支持且用于构建 HAProxy 的 OpenSSL 版本为 1.1.1 或更高版本时可用。它设置了默认字符串,描述了在 TLSv1.3 握手期间协商的密码算法列表(“密码套件”),适用于所有未明确定义自己的 "bind" 行。该字符串的格式在 OpenSSL 手册页中的“man 1 ciphers”的 "ciphersuites" 部分下定义。对于 TLSv1.2 及更早版本的密码配置,请检查 "ssl-default-bind-ciphers" 关键字。请检查 "bind" 关键字以获取更多信息。
仅当启用了 OpenSSL 支持时,此设置才可用。它为所有“bind”行设置了要强制使用的默认 ssl-options。有关可用选项,请检查“bind”关键字。
global ssl-default-bind-options ssl-min-ver TLSv1.0 no-tls-tickets
此设置仅在内置 OpenSSL 支持时可用。它设置了默认字符串,描述了在 SSL/TLS 握手期间与服务器协商的密码算法列表,最高支持 TLSv1.2,适用于所有未明确定义自己的 "server" 行。该字符串的格式在 OpenSSL 手册页中的“man 1 ciphers”中定义。有关背景信息和建议,请参阅例如 (https://wiki.mozilla.org/Security/Server_Side_TLS) 和 (https://mozilla.github.io/server-side-tls/ssl-config-generator/)。对于 TLSv1.3 密码配置,请检查 "ssl-default-server-ciphersuites" 关键字。请检查 "server" 关键字以获取更多信息。
此设置仅在内置 OpenSSL 支持且用于构建 HAProxy 的 OpenSSL 版本为 1.1.1 或更高版本时可用。它设置了默认字符串,描述了在 TLSv1.3 握手期间与服务器协商的密码算法列表,适用于所有未明确定义自己的 "server" 行。该字符串的格式在 OpenSSL 手册页中的“man 1 ciphers”的 "ciphersuites" 部分下定义。对于 TLSv1.2 及更早版本的密码配置,请检查 "ssl-default-server-ciphers" 关键字。请检查 "server" 关键字以获取更多信息。
此设置仅在内置 OpenSSL 支持时可用。它设置了默认的 ssl 选项,强制应用于所有 "server" 行。请检查 "server" 关键字以查看可用选项。
此设置仅在内置 OpenSSL 支持时可用。它设置了默认的 DH 参数,用于在 SSL/TLS 握手期间使用短暂 Diffie-Hellman (DHE) 密钥交换时,适用于所有未明确定义自己的 "bind" 行。如果绑定证书文件中存在自定义 DH 参数,则此设置将被覆盖。如果未使用 ssl-dh-param-file 指定自定义 DH 参数,也未在证书文件中直接设置,则将使用由 tune.ssl.default-dh-param 指定大小的预生成 DH 参数。已知自定义参数更安全,因此建议使用它们。可以使用 OpenSSL 命令 "openssl dhparam <size>" 生成自定义 DH 参数,其中 size 应该至少为 2048,因为 1024 位 DH 参数不应再被视为安全。服务器端 SSL 验证的默认行为。如果指定为 'none',则不验证服务器证书。默认值为 'required',除非使用命令行选项 '-dV' 强制指定。
将 UNIX 套接字绑定到 <path> 或 TCPv4/v6 地址到 <address:port>。连接到此套接字将返回各种统计信息输出,甚至允许发出一些命令来更改一些运行时设置。有关详细信息,请参阅管理指南的第 9.3 节“Unix 套接字命令”。“bind”行支持的所有参数均可用于此,例如限制某些用户或其访问权限。有关更多信息,请参阅第 5.1 节。统计套接字的默认超时时间设置为 10 秒。可以使用 "stats timeout" 更改此值。该值必须以毫秒为单位传递,或者带有时间单位后缀,如 { us, ms, s, m, h, d }。
默认情况下,统计套接字限制为 10 个并发连接。可以使用 "stats maxconn" 更改此值。
将进程的用户 ID 更改为 <number>。建议用户 ID 专用于 HAProxy 或一小组类似守护进程。HAProxy 必须以超级用户权限启动才能切换到另一个用户 ID。另请参阅 "gid" 和 "user"。
将每个进程的最大文件描述符数设置为 <number>。默认情况下,它是自动计算的,因此建议不要使用此选项。
修复在 "bind" 语句中声明的 UNIX 监听套接字的通用设置。这主要用于简化这些 UNIX 套接字的声明并减少错误风险,因为这些设置通常是必需的,但也是进程特定的。<prefix> 设置可用于强制所有套接字路径相对于该目录。这可能是访问另一个组件的 chroot 所必需的。请注意,这些路径是在 haproxy chroot 自身之前解析的,因此它们是绝对路径。<mode>、<user>、<uid>、<group> 和 <gid> 都具有与 "bind" 语句中使用的同名参数相同的含义。如果两者都指定,"bind" 语句具有优先级,这意味着 "unix-bind" 设置可以被视为进程范围的默认设置。
删除参数中指定的环境变量。这对于隐藏某些操作期间偶尔从用户环境中继承的一些敏感信息很有用。不存在的变量会被静默忽略,因此操作后可以确定这些变量都不再存在。更改会立即生效,因此配置文件中的下一行将看不到这些变量。另请参阅 “setenv”、“presetenv” 和 “resetenv”。
类似于 "uid",但使用 /etc/passwd 中用户名为 <user name> 的 UID。另请参阅 "uid" 和 "group"。
只允许字母、数字、连字符和下划线,与 DNS 名称类似。此语句在 HA 配置中很有用,其中两个或多个进程或服务器共享相同的 IP 地址。通过在所有节点上设置不同的节点名称,可以轻松地立即发现哪个服务器正在处理流量。
添加描述实例的文本。请注意,需要转义某些字符(例如 #),并且此文本将插入 HTML 页面中,因此您应避免使用“<”和“>”字符。
提供设备检测服务的 51Degrees 数据文件路径。该文件应解压缩并可由 HAProxy 访问,并具有相关权限。请注意,只有当 haproxy 使用 USE_51DEGREES 编译时,此选项才可用。
要从数据集中加载的 51Degrees 属性名称列表。完整的名称列表可在 51Degrees 网站上找到:https://51degrees.com/resources/property-dictionary 请注意,此选项仅在 haproxy 编译时启用了 USE_51DEGREES 时可用。
一个字符,将附加到包含 51Degrees 结果的响应头中的每个属性值之后。如果未设置,则默认为“,”。请注意,此选项仅在 haproxy 编译时启用了 USE_51DEGREES 时可用。
将 51Degrees 转换器缓存的大小设置为 <number> 个条目。这是一个 LRU 缓存,用于记住以前的设备检测及其结果。默认情况下,此缓存是禁用的。请注意,此选项仅在 haproxy 编译时启用了 USE_51DEGREES 时可用。
提供设备检测服务的 WURFL 数据文件路径。该文件应由 HAProxy 访问,并具有相关权限。请注意,只有当 haproxy 使用 USE_WURFL=1 编译时,此选项才可用。
WURFL 功能、虚拟功能、我们计划在注入标头中使用的属性名称的空格分隔列表。Scientiamobile 网站上提供了功能和虚拟功能的完整列表:https://www.scientiamobile.com/wurflCapability 有效的 WURFL 属性包括: - wurfl_id 包含匹配设备的设备 ID。 - wurfl_root_id 包含匹配设备的设备根 ID。 - wurfl_isdevroot 告知匹配设备是否为根设备。可能的值为 "TRUE" 或 "FALSE"。 - wurfl_useragent 随此特定 Web 请求而来的原始 useragent。 - wurfl_api_version 包含一个字符串,表示当前使用的 Libwurfl API 版本。 - wurfl_info 一个字符串,包含有关已解析的 wurfl.xml 及其完整路径的信息。 - wurfl_last_load_time 包含 WURFL 最后一次成功加载的 UNIX 时间戳。 - wurfl_normalized_useragent 规范化的 useragent。请注意,此选项仅在 haproxy 使用 USE_WURFL=1 编译时可用。
用于分隔包含 WURFL 结果的响应标头中值的字符。如果未设置,则默认使用逗号 (',')。请注意,只有当 haproxy 使用 USE_WURFL=1 编译时,此选项才可用。WURFL 补丁文件路径列表。请注意,补丁是在启动时加载的,因此在 chroot 之前加载。请注意,只有当 haproxy 使用 USE_WURFL=1 编译时,此选项才可用。
设置 WURFL 用户代理缓存大小。为了加快查找速度,已处理的用户代理会保留在 LRU 缓存中:-“0”:不使用缓存。- <size>:LRU 缓存的大小(以元素为单位)。请注意,只有当 haproxy 使用 USE_WURFL=1 编译时,此选项才可用。
当 setrlimit 失败时,使进程在启动时失败。Haproxy 尝试根据已计算出的值设置最佳 setrlimit。如果失败,它将发出警告。如果您希望 haproxy 在这些限制失败时明确失败,请使用此选项。此选项默认禁用。如果已启用,可以通过在其前面加上“no”关键字来强制禁用。
在某些情况下,尤其是在处理支持可变频率的处理器上的低延迟或在虚拟机内部运行时,每次进程使用轮询器等待 I/O 时,处理器都会返回睡眠状态或长时间提供给另一个 VM,这会导致过高的延迟。此选项提供了一种解决方案,通过始终在轮询器上使用 null 超时来防止处理器休眠。这会导致延迟显著降低(观察到 30 到 100 微秒),但代价是处理器过热的风险。它甚至可以与线程一起使用,在这种情况下,绑定不当的线程可能会严重冲突,导致性能变差,并且“show info”输出中的 CPU stolen 字段值很高,表明哪些线程配置错误。使用此选项时,重要的是不要让进程在与网络中断相同的处理器上运行。最好避免在共享同一核心的多个 CPU 线程上使用它。此选项默认禁用。如果已启用,可以通过在其前面加上“no”关键字来强制禁用。它被“select”和“poll”轮询器忽略。在无缝重新加载的上下文中,此选项会自动在旧进程上禁用;它避免了当多个进程停留一段时间等待当前连接结束时过多的 CPU 冲突。
默认情况下,haproxy 会尝试将健康检查的开始时间分散到服务器场中所有服务器的最小健康检查间隔内。其原理是避免对同一服务器上运行的服务进行密集检查。但是当使用较大的检查间隔(10 秒或更长)时,服务器场中的最后几个服务器需要一些时间才能开始被测试,这可能是一个问题。此参数用于强制设置第一个和最后一个检查之间的延迟上限,即使服务器的检查间隔较大。当服务器以较短的间隔运行时,它们的间隔仍将得到尊重。
将每个进程的并发连接数最大值设置为 <number>。它等同于命令行参数“-n”。当达到此限制时,代理将停止接受连接。“ulimit-n”参数会根据此值自动调整。另请参阅“ulimit-n”。注意:在某些平台上,“select”轮询器无法可靠地使用超过 1024 个文件描述符。如果您的平台仅支持 select 并在启动时报告“select FAILED”,您需要减少 maxconn 直到它正常工作(通常略低于 500)。如果未设置此值,它将根据“ulimit -n”命令报告的当前文件描述符限制自动计算,如果强制执行内存限制,可能会根据缓冲区大小、分配给压缩的内存、SSL 缓存大小以及是否使用 SSL 和相关的 maxsslconn(也可以是自动的)而减少到一个较低的值。
将每个进程每秒的最大连接数设置为 <number>。当达到此限制时,代理将停止接受连接。它可以用来限制全局容量,而不考虑每个前端的容量。需要注意的是,这只能用作服务保护措施,因为当达到限制时,前端之间不一定会公平分配,所以最好也为每个前端限制一个接近其预期份额的值。此外,降低 tune.maxaccept 可以提高公平性。
将每个进程的最大输入压缩速率设置为 <number> 千字节/秒。对于每个会话,如果达到最大值,会话期间的压缩级别将降低。如果在会话开始时达到最大值,该会话将完全不压缩。如果未达到最大值,压缩级别将增加到 tune.comp.maxlevel。值为零表示没有限制,这是默认值。
设置 HAProxy 在停止对新请求进行压缩或降低当前请求的压缩级别之前可以达到的最大 CPU 使用率。它的工作方式类似于 'maxcomprate',但衡量的是 CPU 使用率而不是传入数据带宽。该值以 haproxy 使用的 CPU 百分比表示。在多进程(nbproc > 1)的情况下,每个进程管理其各自的使用率。值为 100 将禁用此限制。默认值为 100。设置较低的值将防止压缩工作减慢整个进程的速度并引入高延迟。
将每个进程的最大管道数设置为 <number>。目前,管道仅由基于内核的 tcp 拼接使用。由于一个管道包含两个文件描述符,"ulimit-n" 值将相应增加。默认值为 maxconn/4,这对于大多数重度使用情况来说似乎已经足够了。拼接代码动态分配和释放管道,并且可以回退到标准复制,因此将此值设置得太低可能只会影响性能。
将每个进程每秒的最大会话数设置为 <number>。当达到此限制时,代理将停止接受连接。它可以用来限制全局容量,而不考虑每个前端的容量。需要注意的是,这只能用作服务保护措施,因为当达到限制时,前端之间不一定会公平分配,所以最好也为每个前端限制一个接近其预期份额的值。此外,降低 tune.maxaccept 可以提高公平性。
设置每个进程的最大并发 SSL 连接数为 <number>。默认情况下没有 SSL 特定的限制,这意味着全局 maxconn 设置将应用于所有连接。设置此限制可避免 openssl 使用过多内存并在 malloc 返回 NULL 时崩溃(因为它不幸地无法可靠地检查此类情况)。请注意,此限制同时适用于传入和传出连接,因此一个解密然后加密的连接计为 2 个 SSL 连接。如果未设置此值,但强制实施了内存限制,则将根据内存限制、maxconn、缓冲区大小、分配给压缩的内存、SSL 缓存大小以及 SSL 在前端、后端或两者中的使用情况自动计算此值。如果在有内存限制时既未指定 maxconn 也未指定 maxsslconn,haproxy 将自动调整这些值,以便 100% 的连接可以通过 SSL 进行,没有风险,并将考虑启用它的方面(前端、后端、两者)。
将每个进程每秒的最大 SSL 会话数设置为 <number>。当达到此限制时,SSL 侦听器将停止接受连接。它可以用来限制全局 SSL CPU 使用率,而不考虑每个前端的容量。需要注意的是,这只能用作服务保护措施,因为当达到限制时,前端之间不一定会公平分配,所以最好也为每个前端限制一个接近其预期份额的值。同样重要的是要注意,会话是在进入 SSL 堆栈之前而不是之后计算的,这也保护了堆栈免受不良握手的影响。此外,降低 tune.maxaccept 可以提高公平性。
设置 zlib 每个进程可用的最大 RAM 量(以兆字节为单位)。当达到最大量时,只要 RAM 不可用,将来的会话将不会压缩。当设置为 0 时,没有限制。默认值为 0。该值在 UNIX 套接字上以字节为单位可用,通过 "show info" 命令的 "MaxZlibMemUsage" 行显示,zlib 使用的内存为 "ZlibMemUsage"(以字节为单位)。
禁用在 Linux 上使用 "epoll" 事件轮询系统。它等同于命令行参数 "-de"。下一个使用的轮询系统通常是 "poll"。另请参阅 "nopoll"。
禁用在 BSD 上使用 "kqueue" 事件轮询系统。它等同于命令行参数 "-dk"。下一个使用的轮询系统通常是 "poll"。另请参阅 "nopoll"。
在源自 Solaris 10 及更高版本的 SunOS 系统上禁用事件端口(event ports)事件轮询系统的使用。它等同于命令行参数“-dv”。下一个使用的轮询系统通常是“poll”。另请参阅“nopoll”。
禁用“poll”事件轮询系统的使用。它等同于命令行参数“-dp”。下一个使用的轮询系统将是“select”。通常不需要禁用“poll”,因为它在 HAProxy 支持的所有平台上都可用。另请参阅“nokqueue”、“noepoll”和“noevports”。
禁用在 Linux 上使用内核在套接字之间进行 tcp 拼接。它等同于命令行参数 "-dS"。数据将使用传统的、更具可移植性的 recv/send 调用进行复制。内核 tcp 拼接仅限于一些非常近期的内核 2.6 实例。大多数 2.6.25 到 2.6.28 之间的版本都有错误,会转发损坏的数据,因此不得使用。此选项使得在有疑问时可以轻松地全局禁用内核拼接。另请参阅 "option splice-auto"、"option splice-request" 和 "option splice-response"。
禁用使用 getaddrinfo(3) 进行名称解析。它等同于命令行参数 "-dG"。将使用已弃用的 gethostbyname(3)。
禁用 SO_REUSEPORT 的使用 - 请参阅 socket(7)。它等同于命令行参数 "-dR"。
启用('on')或禁用('off')按任务进行的 CPU 分析。当设置为 'auto' 时,当线程开始遭受平均延迟为 1000 微秒或更高(如 "avg_loop_us" 活动字段中所报告)时,分析会自动开启,当延迟返回到 990 微秒以下时自动关闭(此值是过去 1024 个循环的平均值,因此变化不快,并且倾向于显著平滑短时峰值)。在过载系统、容器或虚拟机上,或者当系统交换时(这在负载均衡器上绝对不应该发生)时,它也可能会不时自发触发。按任务进行的 CPU 分析对于报告时间花费在哪里以及哪些请求对哪些其他请求有什么影响非常方便。启用它通常会对整体性能产生不到 1% 的影响,因此建议将其保留为默认值 'auto',以便仅在发现问题时才运行。此功能要求系统支持带有时钟标识符 CLOCK_MONOTONIC 和 CLOCK_THREAD_CPUTIME_ID 的 clock_gettime(2) 系统调用,否则报告的时间将为零。此选项可以在运行时使用 CLI 上的 "set profiling" 进行更改。
有时,希望避免以精确的间隔向服务器发送代理和健康检查,例如当许多逻辑服务器位于同一物理服务器上时。借助此参数,可以在检查间隔中添加 0 到 +/- 50% 之间的随机性。2 到 5 之间的值似乎效果很好。默认值仍为 0。
将 OpenSSL 引擎设置为 <name>。可以使用命令“openssl engine”获取 <name> 的有效值列表。此语句可以多次使用,它只会启用多个加密引擎。引用不支持的引擎将导致 haproxy 无法启动。请注意,许多引擎将导致 HTTPS 性能低于最新处理器上的纯软件。可选命令“algo”使用 OPENSSL 函数 ENGINE_set_default_string() 设置 ENGINE 将提供的默认算法。值为“ALL”时,引擎用于所有加密操作。如果未指定 algo 列表,则使用“ALL”的值。可以指定由不同算法组成的逗号分隔列表,包括:RSA、DSA、DH、EC、RAND、CIPHERS、DIGESTS、PKEY、PKEY_CRYPTO、PKEY_ASN1。这与 openssl 配置文件使用的格式相同:https://www.openssl.org/docs/man1.0.2/apps/config.html
将 SSL_MODE_ASYNC 模式添加到 SSL 上下文。如果使用支持异步的 SSL 引擎,这将启用异步 TLS I/O 操作。当前实现最多支持 32 个引擎。Openssl ASYNC API 不支持移动读/写缓冲区,并且不兼容 haproxy 的缓冲区管理。因此,异步模式在读/写操作时被禁用(它仅在初始握手和重新协商握手期间启用)。
设置每个进程可以分配的缓冲区数量的硬限制。默认值为零,表示无限制。最小非零值将始终大于 "tune.buffers.reserve",理想情况下应始终大约是其两倍大。强制设置此值对于限制进程可能占用的内存量同时保持正常的行为特别有用。当达到此限制时,需要缓冲区的会话会等待另一个会话释放缓冲区。由于缓冲区是动态分配和释放的,因此等待时间非常短,并且只要限制保持合理,就不会察觉到。事实上,有时减少限制甚至可以通过提高 CPU 缓存效率来提高性能。测试显示,对于平均 HTTP 流量,限制为预期全局 maxconn 设置的 1/10 时效果良好,这也显著减少了内存使用。内存节省来自于许多连接不会分配 2*tune.bufsize。除非 haproxy 核心开发人员建议,否则最好不要触动此值。
设置预分配并保留的缓冲区数量,仅在内存分配失败导致的内存短缺情况下使用。最小值为 2,也是默认值。用户没有理由更改此值,它主要针对 haproxy 核心开发人员。
将缓冲区大小设置为此大小(以字节为单位)。较低的值允许在相同数量的 RAM 中共存更多会话,而较高的值允许某些具有非常大 cookie 的应用程序工作。默认值是 16384,可以在构建时更改。强烈建议不要更改此默认值,因为非常低的值会破坏某些服务(例如统计信息),而大于默认值的值会增加内存使用,可能导致系统内存不足。至少全局 maxconn 参数应按此值增加的相同因子减小。此外,使用 HTTP/2 要求此值必须为 16384 或更大。如果 HTTP 请求大于 (tune.bufsize - tune.maxrewrite),haproxy 将返回 HTTP 400(Bad Request)错误。同样,如果 HTTP 响应大于此大小,haproxy 将返回 HTTP 502(Bad Gateway)。请注意,使用此参数设置的值将在 32 位机器上自动向上舍入到下一个 8 的倍数,在 64 位机器上自动向上舍入到下一个 16 的倍数。
将检查缓冲区大小设置为此大小(以字节为单位)。较高的值可能有助于在非常大的页面中查找字符串或正则表达式模式,但这可能意味着更多的内存和 CPU 使用。默认值为 16384,可以在构建时更改。不建议更改此值,而应尽可能使用更好的检查方法。
设置最大压缩级别。压缩级别影响压缩期间的 CPU 使用率。此值影响压缩期间的 CPU 使用率。每个使用压缩的会话都使用此值初始化压缩算法。默认值为 1。
如果使用 DEBUG_FAIL_ALLOC 编译,则给出分配尝试失败的百分比几率。必须介于 0(无失败)和 100(无成功)之间。这对于调试和确保内存故障得到妥善处理非常有用。
设置 HTTP/2 动态头表大小。默认为 4096 字节,不能大于 65536 字节。较大的值可能有助于某些客户端发送更紧凑的请求,具体取决于它们的能力。每个 HTTP/2 连接都会消耗此数量的内存。建议不要更改它。
设置 HTTP/2 的初始窗口大小,即客户端在等待 haproxy 确认之前可以上传的字节数。此设置仅影响有效负载内容(即 POST 请求的正文),而不影响标头。默认值为 65535,在大约 100 毫秒的 ping 时间的网络上,每位客户端的上传带宽约为 5 Mbps,在 1 毫秒的本地网络上约为 500 Mbps。增加此值以允许更快的上传,或在处理多个客户端时减小此值以增加公平性是有意义的。它不影响资源使用。
设置每个连接的 HTTP/2 最大并发流数(即单个连接上的未完成请求数)。默认值为 100。在具有高延迟的网络上访问时,更大的值可能会略微改善复杂站点的页面加载时间,但会增加单个客户端可能分配的资源量。值为零会禁用限制,因此单个客户端可以创建 haproxy 可分配的任意数量的流。强烈建议不要更改此值。
设置 haproxy 向其对等节点宣告愿意接收的最大帧大小。默认值是 16384 和缓冲区大小 (tune.bufsize) 之间的较大者。在任何情况下,haproxy 都不会宣告支持大于缓冲区的帧大小。此设置的主要目的是在配置大缓冲区时允许限制最大帧大小。过大的帧大小可能会影响性能或导致某些对等节点行为异常。强烈建议不要更改此值。
设置捕获的 cookie 的最大长度。"capture cookie xxx len yyy" 允许的最大值将是此值,任何更高的值都将自动截断为此值。重要的是不要设置太高的值,因为所有 cookie 捕获无论其配置值如何都会分配此大小(它们共享一个池)。此值是每个请求每个响应的,因此每个连接分配的内存是此值的两倍。如果未指定,限制设置为 63 个字符。建议不要更改此值。
设置日志中请求 URI 的最大长度。这可以防止在日志行中截断带有有价值查询字符串的长请求 URI。这与 syslog 的限制无关。如果增加此限制,您可能还需要增加 'log ... len yyy' 参数。您的 syslog 守护进程可能也需要特定的配置指令。默认值为 1024。
设置请求中的最大报头数。当请求的报头数(包括第一行)大于此值时,它将被拒绝,并返回 "400 Bad Request" 状态码。同样,过大的响应将被阻止,并返回 "502 Bad Gateway"。默认值为 101,对于所有用途来说已经足够,考虑到广泛部署的 Apache 服务器也使用相同的限制。有时可以进一步提高此限制,以便在修复错误的应用程序之前临时允许其工作。可接受的范围是 1..32767。请记住,每个新报头都会为每个会话消耗 32 位的内存,因此不要将此限制设置得太高。
设置 haproxy 将认为空缓冲区可能与空闲流关联的时间。这用于在转发大量和小数据时优化某些数据包大小。使用 splice() 或在 SSL 中发送大缓冲区进行数据的决定受此参数的调节。该值以毫秒为单位,在 0 到 65535 之间。值为零表示 haproxy 不会尝试检测空闲流。默认值为 1000,它似乎能正确检测最终用户暂停(例如,在点击之前阅读页面)。没有理由更改此值。请查看下面的 tune.ssl.maxrecord。
启用('on')或禁用('off')监听器的多队列 accept,它将传入流量分散到 "bind" 行允许运行的所有线程,而不是由它自己接管。这提供了更平滑的流量分布和更好的扩展性,尤其是在由于外部活动(例如网络中断与一个线程冲突)导致线程负载不均衡的环境中。此选项默认启用,但可以为了故障排除或在估计操作系统已提供足够好的分布且连接寿命极短的情况下强制禁用。该指令强制 Lua 引擎每执行 <number> 条指令就执行一次让出(yield)。这允许中断一个长时间运行的脚本,并让 HAProxy 调度器处理其他任务,如接受连接或转发流量。默认值为 10000 条指令。如果 HAProxy 经常执行一些 Lua 代码但需要更高的响应性,可以降低这个值。如果 Lua 代码相当长,并且其结果对于处理数据是绝对必需的,可以增加这个 <number>。
设置 Lua 每个进程可用的最大 RAM 量(以兆字节为单位)。默认情况下为零,表示无限制。设置限制很重要,以确保脚本中的错误不会导致系统内存耗尽。
这是 Lua 会话的执行超时。这对于防止无限循环或在 Lua 中花费太多时间很有用。此超时仅计算纯 Lua 运行时。如果 Lua 执行了休眠,休眠时间不计入。默认超时为 4 秒。
目的与 "tune.lua.session-timeout" 相同,但此超时专用于任务。默认情况下,此超时未设置,因为任务可能在 HAProxy 的整个生命周期内保持活动状态。例如,用于检查服务器的任务。
这是 Lua 服务的执行超时。这对于防止无限循环或在 Lua 中花费太多时间很有用。此超时仅计算纯 Lua 运行时。如果 Lua 执行了休眠,休眠时间不计入。默认超时为 4 秒。
设置一个进程在切换到其他工作之前可以连续接受的最大连接数。在单进程模式下,较高的数字在高连接率下性能更好。然而,在多进程模式下,在进程之间保持一点公平性通常能更好地提高性能。此值单独应用于每个侦听器,以便考虑到侦听器绑定的进程数。此值默认为 64。在多进程模式下,它除以侦听器绑定的进程数的两倍。将此值设置为 -1 将完全禁用此限制。通常不需要调整此值。
设置一次调用轮询系统可以处理的最大事件量。默认值根据操作系统进行调整。已经注意到,将其降低到 200 以下会略微降低延迟,但会牺牲网络带宽,而将其增加到 200 以上则会以延迟换取略微增加的带宽。
将保留的缓冲区空间设置为此大小(以字节为单位)。保留空间用于报头重写或追加。套接字上的第一次读取永远不会超过 bufsize-maxrewrite。历史上,它默认为 bufsize 的一半,但这没有太大意义,因为很少有大量的报头需要添加。设置得太高会妨碍处理大的请求或响应。设置得太低会妨碍向已有的较大请求或 POST 请求添加新报头。通常明智的做法是将其设置为大约 1024。如果大于 bufsize 的一半,它会自动调整为 bufsize 的一半。这意味着您在更改 bufsize 时不必担心它。
设置模式查找缓存的大小为 <number> 个条目。这是一个 LRU 缓存,用于记住以前的查找及其结果。它被 ACL 和映射用于慢速模式查找,即使用 "sub"、"reg"、"dir"、"dom"、"end"、"bin" 匹配方法以及不区分大小写的字符串的查找。它适用于模式表达式,这意味着它能够记住在配置行上指定的所有模式(包括从文件加载的所有模式)中的查找结果。它会自动使使用 HTTP 操作或 CLI 更新的条目失效。默认缓存大小设置为 10000 个条目,将其占用空间限制在 32 位系统上每个进程/线程约 5 MB,64 位系统上每个进程/线程约 8 MB,因为缓存是线程/进程本地的。此缓存中发生冲突的风险非常低,大约是缓存大小除以 2^64。通常,在每秒 10000 个请求且默认缓存大小为 10000 个条目的情况下,蛮力攻击在 60 年后可能导致一次冲突的几率为 1%,在 6 年后为 0.1%。这被认为远低于由老化组件引起的内存损坏风险。如果这不可接受,可以通过将此参数设置为 0 来禁用缓存。
将内核管道缓冲区大小设置为此大小(以字节为单位)。默认情况下,管道是系统的默认大小。但有时在使用 TCP 拼接时,增加管道大小可以提高性能,特别是在怀疑管道未被填满且执行了许多 splice() 调用时。这对内核的内存占用有影响,因此如果影响不明确,则不应更改此值。
此设置设置了haproxy全局使用的文件描述符数量(百分比)与haproxy可以使用但在此之前我们将开始在无法重用连接且必须创建新连接时杀死空闲连接的最大文件描述符数量之间的比率。默认值为25(四分之一的文件描述符意味着大约一半的最大前端连接可以保留一个空闲连接,超出此范围在一般情况下目标是连接重用时意义不大)。
此设置设置了haproxy全局使用的文件描述符数量(百分比)与haproxy可以使用但在此之前我们将停止将连接放入空闲池进行重用的最大文件描述符数量之间的比率。默认值为20。
强制将客户端或服务器端的内核套接字接收缓冲区大小设置为指定的字节值。此值适用于所有 TCP/HTTP 前端和后端。通常不应设置此值,默认大小(0)让内核根据可用内存量自动调整此值。但是,有时将其设置为非常低的值(例如 4096)有助于节省内核内存,因为它阻止内核缓冲过多的接收数据。不过,较低的值会显著增加 CPU 使用率。
HAProxy 使用一些提示来检测短读是否表示套接字缓冲区的末尾。其中之一是读取返回的字节数超过 <recv_enough>,默认为 10136(7 个 1448 字节的段)。此默认值可以通过此设置更改,以更好地处理涉及大量短消息的工作负载,例如 telnet 或 SSH 会话。
设置运行任务时一次可以处理的最大任务量。默认值为 200。增加它可能会在处理 I/O 时导致延迟,而设置得太小可能会导致额外的开销。
将客户端或服务器端的内核套接字发送缓冲区大小强制设置为指定的字节数。此值适用于所有TCP/HTTP前端和后端。通常不应设置它,默认大小(0)允许内核根据可用内存量自动调整此值。但是,有时将其设置为非常小的值(例如4096)可以通过阻止内核缓冲过多的接收数据来节省内核内存。然而,较低的值将显著增加CPU使用率。另一种用例是防止由于内核等待缓冲区的大部分被读取然后再次通知haproxy而导致的极慢客户端的写入超时。
设置全局 SSL 会话缓存的大小(以块数为单位)。一个块足够大,可以包含一个编码会话而无需对等证书。带有对等证书的编码会话根据对等证书的大小存储在多个块中。一个块大约使用 200 字节的内存(基于用于 `shctx_init` 函数的 `sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE` 计算)。默认值可以在构建时强制设置,否则默认为 20000。当缓存已满时,最空闲的条目会被清除并重新分配。较高的值减少了此类清除的发生,从而减少了 CPU 密集型 SSL 握手的次数,确保所有用户尽可能长时间地保持其会话。所有条目都在启动时预先分配,并且如果 "nbproc" 大于 1,则在所有进程之间共享。将此值设置为 0 会禁用 SSL 会话缓存。此选项禁用所有进程之间的 SSL 会话缓存共享。通常不应使用它,因为它会由于客户端命中随机进程而强制进行许多重新协商。但在某些操作系统上可能需要它,因为这些操作系统上可能无法使用任何 SSL 缓存同步方法。在这种情况下,在 SSL 层之前添加第一层基于哈希的负载均衡可能会限制缺少会话共享的影响。
设置缓存的 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)。
在 DHE 密钥交换的情况下,设置用于生成临时/瞬时 Diffie-Hellman 密钥的 Diffie-Hellman 参数的最大大小。最终大小将尝试匹配服务器的 RSA(或 DSA)密钥的大小(例如,对于 2048 位 RSA 密钥使用 2048 位临时 DH 密钥),但不会超过此最大值。默认值为 1024。只允许 1024 或更高的值。较高的值会增加 CPU 负载,而大于 1024 位的值不受 Java 7 及更早版本的客户端支持。如果直接在证书文件中或使用 ssl-dh-param-file 参数提供了静态 Diffie-Hellman 参数,则不使用此值。
将用于存储生成证书的缓存大小设置为 <number> 个条目。这是一个 LRU 缓存。因为动态生成 SSL 证书的开销很大,所以它们被缓存起来。默认缓存大小设置为 1000 个条目。
设置用于捕获客户端hello密码列表的缓冲区最大大小。如果值为0(默认值),则禁用捕获;否则,为每个SSL/TLS连接分配一个缓冲区。
这五个调优有助于管理变量系统使用的最大内存量。“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。
启用调试模式,将所有交换信息转储到标准输出,并禁止 fork 到后台。它等同于命令行参数 "-d"。它绝不应在生产配置中使用,因为它可能会阻止系统完全启动。
启动期间不显示任何消息。它等同于命令行参数 "-q"。
可以通过仅允许经过身份验证和授权的用户来控制对前端/后端/侦听部分或 http 统计信息的访问。为此,需要创建至少一个用户列表并定义用户。
创建名为 <listname> 的新用户列表。可以使用许多独立的用户列表来存储独立客户的身份验证和授权数据。
将组 <groupname> 添加到当前用户列表。也可以通过使用逗号分隔的名称列表(前面有 "users" 关键字)将用户附加到此组。
将用户 <username> 添加到当前用户列表。可以使用安全(加密)和不安全(未加密)密码。加密密码使用 crypt(3) 函数进行评估,因此根据系统的功能,支持不同的算法。例如,基于现代 Glibc 的 Linux 系统支持 MD5、SHA-256、SHA-512,当然还有经典的基于 DES 的密码加密方法。注意:请注意,使用加密密码可能会导致 CPU 使用率显著增加,具体取决于请求数量和所使用的算法。对于任何散列变体,每个请求的密码都必须经过所选算法的处理,然后才能与配置文件中指定的值进行比较。大多数当前算法都经过精心设计,计算成本高昂,以实现对蛮力攻击的抵抗力。它们不仅仅对明文密码进行一次加盐/散列,而是成千上万次。这可能很快成为 haproxy 整体 CPU 消耗的主要因素!
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
请注意,这两个列表在功能上是相同的。
可以在多个 haproxy 实例之间通过 TCP 连接以多主方式传播粘性表中的任何数据类型的条目。每个实例将其本地更新和插入推送到远程对等节点。推送的值会覆盖远程值,而不进行聚合。中断的交换会自动检测并从最后一个已知点恢复。此外,在软重启期间,旧进程使用这样的 TCP 连接连接到新进程,以在新进程尝试连接其他对等节点之前推送其所有条目。这确保了在重新加载期间的快速复制,即使对于大型表,通常也只需要几分之一秒。请注意,服务器 ID 用于远程识别服务器,因此重要的是配置看起来相似,或者至少在所有参与者上对每个服务器强制使用相同的 ID。
创建名为 <peersect> 的新对等节点列表。它是一个独立的部分,由一个或多个粘性表引用。
定义此“peers”部分中本地对等节点的绑定参数。在同一个“peers”部分中,此类行不支持与“peer”行同时使用。
禁用一个对等节点部分。它会禁用与此部分相关的侦听和任何同步。这用于禁用粘性表的同步,而无需注释掉所有 "peers" 引用。
定义本地对等节点的绑定参数,但不包括其地址。
更改“peers”部分中服务器的默认选项。
<param*> 是此服务器的参数列表。“default-server”关键字接受大量选项,并有专门的完整章节介绍。更多详情请参阅 第 5 节。
这会重新启用先前被禁用的对等节点部分。
"peers" 部分支持与代理相同的 "log" 关键字,用于记录有关 "peers" 监听器的信息。有关更多详细信息,请参阅代理的 "log" 选项。
在 peers 部分中定义一个对等体。如果 <peername> 设置为本地对等体名称(默认为主机名,或使用 "-L" 命令行选项强制设置),haproxy 将在 <ip>:<port> 上侦听传入的远程对等体连接。否则,<ip>:<port> 定义了连接到远程对等体的位置,<peername> 用于协议级别以在服务器端识别和验证远程对等体。在软重启期间,旧实例使用本地对等体 <ip>:<port> 连接新实例并启动完全复制(教学过程)。强烈建议在所有对等体上使用完全相同的 peers 声明,并且仅依靠 "-L" 命令行参数来更改本地对等体名称。这使得在所有对等体之间维护一致的配置文件更加容易。您可能希望在地址参数中引用一些环境变量,请参阅 section 2.3 关于环境变量。注意:“peer”关键字可以透明地替换为 "server" 关键字(请参阅下面的 "server" 关键字解释)。
如前所述,“peer”关键字可以替换为 "server" 关键字,并支持 5.2 段落中找到的所有 "server" 参数。如果底层对等体是本地的,则不能出现 <ip>:<port> 参数。这些参数必须在 "bind" 行上提供(请参阅此 "peers" 部分的 "bind" 关键字)。其中一些参数与 "peers" 部分无关。
# 旧方式。 peers mypeers peer haproxy1 192.168.0.1:1024 peer haproxy2 192.168.0.2:1024 peer haproxy3 10.2.0.1:1024 backend mybackend mode tcp balance roundrobin stick-table type ip size 20k peers mypeers stick on src server srv1 192.168.0.30:80 server srv2 192.168.0.31:80 Example: peers mypeers bind 127.0.0.11:10001 ssl crt mycerts/pem default-server ssl verify none server hostA 127.0.0.10:10000 server hostB #local peer
为当前部分配置粘性表。此行的解析方式与在其他部分中的 "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" 部分中声明的粘性表之间的粘性表名称冲突,如下所示(在 weird 但受支持的配置中):peers mypeers peer A ... peer B ... table t1 type string size 10m store gpc0 backend t1 stick-table type string size 10m store gpc0 peers mypeers 此处在 "mypeeers" 部分中声明的 "t1" 表的全局名称为 "mypeers/t1"。在后端声明的 "t1" 表的全局名称为 "t1"。但在对等协议级别,前一个表名为 "/t1",后一个表仍名为 "t1"。
当服务器状态发生变化时,可以发送电子邮件警报。如果配置了电子邮件警报,则会发送到邮件发送器部分中配置的每个邮件发送器。电子邮件使用 SMTP 发送给邮件发送器。
创建名为 <mailersect> 的新邮件发送器列表。它是一个独立的部分,由一个或多个代引用。
在邮件发送器部分内定义一个邮件发送器。
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
在 master-worker 模式下,可以与 master 一起启动外部二进制文件,这些进程称为程序。这些程序的启动和管理方式与 worker 相同。在 HAProxy 重载期间,这些进程将经历与 worker 相同的序列: - master 被重新执行 - master 向程序发送一个 SIGUSR1 信号 - 如果没有禁用“option start-on-reload”,master 将启动一个新的程序实例 在停止或重启期间,会向程序发送一个 SIGTERM 信号。
这是一个新的程序部分,此部分将创建一个名为 <name> 的实例,该实例在 master CLI 的 "show proc" 中可见。(请参阅管理指南中的 "9.4. Master CLI")。
定义要启动的命令及可选参数。如果命令不包含绝对路径,则会在当前 PATH 中查找。这是 program 部分的一个强制选项。包含空格的参数必须用单引号或双引号括起来,或者以反斜杠为前缀。
将执行的命令用户 ID 更改为 /etc/passwd 中的 <用户名>。另请参阅“group”。将执行的命令组 ID 更改为 /etc/group 中的 <组名>。另请参阅“user”。在 master 重载时启动(或不启动)程序的新实例。默认是启动新实例。此选项只能在 program 部分使用。
代理配置可以位于一组部分中: - defaults [<name>] - frontend <name> - backend <name> - listen <name> “defaults”部分为其声明之后的所有其他部分设置默认参数。这些默认参数会被下一个“defaults”部分重置。有关可以在“defaults”部分中设置的参数列表,请参见下文。名称是可选的,但鼓励使用它以提高可读性。 “frontend”部分描述了一组接受客户端连接的监听套接字。 “backend”部分描述了一组服务器,代理将连接到这些服务器以转发传入连接。 “listen”部分定义了一个完整的代理,其前端和后端部分组合在一个部分中。它通常适用于纯 TCP 流量。 所有代理名称必须由大小写字母、数字、“-”(破折号)、“_”(下划线)、“.”(点)和“:”(冒号)组成。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”。 将应用于流经前端和后端的连接的有效模式可以根据以下矩阵由两种代理模式确定,但简而言之,模式是对称的,keep-alive 是最弱的选项,close 是最强的选项。 后端模式 | KAL | SCL | CLO ----+-----+-----+---- KAL | KAL | SCL | CLO ----+-----+-----+---- mode SCL | SCL | SCL | CLO ----+-----+-----+---- CLO | CLO | CLO | CLO
支持以下关键字列表。它们中的大多数只能在有限的段落类型中使用。其中一些被标记为“已弃用”,因为它们继承自一个可能令人困惑或功能有限的旧语法,并且有新的推荐关键字来替换它们。 标有“(*)”的关键字可以选择性地使用“no”前缀进行反转,例如“no option contstats”。当该选项默认启用并且必须为特定实例禁用时,这样做是有意义的。此类选项也可以使用“default”前缀,以便恢复默认设置,而不管之前的“defaults”段落中指定了什么。
本节提供了每个关键字及其用法的描述。
声明或完成一个访问控制列表。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
acl invalid_src src 0.0.0.0/7 224.0.0.0/3 acl invalid_src src_port 0:1023 acl local_dst hdr(host) -i localhost
有关 ACL 的用法,请参见第 7 节。
向系统提供关于期望的监听队列(backlog)大致大小的提示。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<conns> 是待处理连接的数量。根据操作系统的不同,它可能表示已确认的连接数、未确认的连接数或两者之和。
为了防范 SYN 洪水攻击,一种解决方案是增加系统的 SYN 队列大小。根据系统的不同,有时它只能通过系统参数进行调整,有时根本无法调整,有时系统依赖于应用程序在调用 listen() 系统调用时给出的提示。默认情况下,HAProxy 将前端的 maxconn 值传递给 listen() 系统调用。在可以利用此值的系统上,有时能够指定一个不同的值会很有用,因此有了这个 backlog 参数。在 Linux 2.4 上,该参数被系统忽略。在 Linux 2.6 上,它被用作一个提示,系统最多接受不小于该值的最小的 2 的幂次方,并且永远不会超过某些限制(通常是 32768)。
定义在后端中使用的负载均衡算法。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<algorithm> 是在进行负载均衡时用于选择服务器的算法。这仅适用于没有可用持久性信息的情况,或者当连接被重新分派到另一台服务器时。 <algorithm> 可以是以下之一: roundrobin 每个服务器根据其权重轮流使用。当服务器的处理时间保持均匀分布时,这是最平滑和最公平的算法。此算法是动态的,这意味着可以即时调整服务器权重,例如用于慢启动。它在设计上限制为每个后端 4095 个活动服务器。请注意,在某些大型集群中,当服务器在非常短的时间内停机后重新启动时,可能需要数百个请求才能重新集成到集群中并开始接收流量。这是正常的,尽管非常罕见。在此处指出,以防您有机会观察到它,这样您就不用担心了。 static-rr 每个服务器根据其权重轮流使用。此算法与 roundrobin 非常相似,只是它是静态的,这意味着即时更改服务器的权重将无效。另一方面,它对服务器数量没有设计限制,并且当服务器启动时,一旦重新计算完整映射,它总是立即重新引入集群。它运行所需的 CPU 也稍微少一些(大约 -1%)。 leastconn 连接数最少的服务器接收连接。在具有相同负载的服务器组中执行轮询,以确保所有服务器都将被使用。建议在需要非常长会话(例如 LDAP、SQL、TSE 等)的情况下使用此算法,但不太适合使用短会话(例如 HTTP)的协议。此算法是动态的,这意味着可以即时调整服务器权重,例如用于慢启动。 first 第一个具有可用连接槽的服务器接收连接。服务器从最低数字标识符到最高数字标识符进行选择(请参阅 server 参数“id”),默认为服务器在集群中的位置。一旦服务器达到其 maxconn 值,将使用下一个服务器。如果不设置 maxconn,使用此算法没有意义。此算法的目的是始终使用最少的服务器数量,以便在非高峰时段可以关闭多余的服务器电源。此算法忽略服务器权重,对 RDP 或 IMAP 等长会话比 HTTP 带来更多好处,尽管它在那里也可能有用。为了有效地使用此算法,建议云控制器定期检查服务器使用情况,以便在未使用时将其关闭,并定期检查后端队列,以便在队列膨胀时启动新服务器。或者,使用“http-check send-state”可以通知服务器负载情况。 source 源 IP 地址被哈希并除以正在运行的服务器的总权重,以指定哪个服务器将接收请求。这确保了只要没有服务器停机或启动,相同的客户端 IP 地址将始终到达同一台服务器。如果由于正在运行的服务器数量发生变化而导致哈希结果发生变化,则许多客户端将被定向到不同的服务器。此算法通常用于无法插入 cookie 的 TCP 模式。它也可以用于 Internet,为拒绝会话 cookie 的客户端提供尽力而为的粘性。默认情况下,此算法是静态的,这意味着即时更改服务器的权重将无效,但这可以使用“hash-type”进行更改。 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 将提供相同的哈希值。 url_param 将在每个 HTTP GET 请求的查询字符串中查找参数中指定的 URL 参数。如果使用修饰符“check_post”,则当在 URL 中问号('?')之后的查询字符串中未找到参数时,将在 HTTP POST 请求实体中搜索参数参数。消息正文将仅在接收到 advertised 数据量或请求缓冲区已满时才开始分析。在不太可能使用分块编码的情况下,仅扫描第一个块。由块边界分隔的参数值,如果根本没有,可能会随机平衡。此关键字过去支持可选的 <max_wait> 参数,该参数现在已被忽略。如果找到参数后面跟着等号('=')和一个值,则该值被哈希并除以正在运行的服务器的总权重。结果指定哪个服务器将接收请求。这用于跟踪请求中的用户标识符,并确保只要没有服务器启动或停机,相同的用户 ID 将始终发送到同一台服务器。如果未找到值或未找到参数,则应用轮询算法。请注意,此算法只能在 HTTP 后端中使用。默认情况下,此算法是静态的,这意味着即时更改服务器的权重将无效,但这可以使用“hash-type”进行更改。 hdr(<name>) HTTP 标头 <name> 将在每个 HTTP 请求中查找。就像等效的 ACL 'hdr()' 函数一样,括号中的标头名称不区分大小写。如果标头不存在或者它不包含任何值,则应用轮询算法代替。可选的“use_domain_only”参数可用,用于将哈希算法缩减为主要域部分,并带有一些特定的标头,例如“Host”。例如,在 Host 值“haproxy.1wt.eu”中,只会考虑“1wt”。默认情况下,此算法是静态的,这意味着即时更改服务器的权重将无效,但这可以使用“hash-type”进行更改。 random random(<draws>) 一个随机数将用作一致哈希函数的键。这意味着服务器的权重得到尊重,动态权重更改立即生效,新服务器的添加也立即生效。随机负载均衡对于大型集群或服务器频繁添加或删除的情况可能很有用,因为它可以避免在这种情况下轮询或 leastconn 可能导致的敲击效应。hash-balance-factor 指令可用于进一步提高负载均衡的公平性,尤其是在服务器响应时间变化很大的情况下。当存在参数 <draws> 时,它必须是一个大于或等于一的整数值,表示在选择这些服务器中负载最小的服务器之前抽取的次数。确实有证据表明,选择两个服务器中负载最小的服务器足以显着提高算法的公平性,方法是始终避免选择集群中负载最大的服务器,并消除一致列表的不公平分布可能引起的任何偏差。较高的值 N 将以性能为代价移除 N-1 个负载最高的服务器。对于非常高的值,算法将收敛到 leastconn 的结果,但速度慢得多。默认值为 2,通常显示出非常好的分布和性能。此算法也称为“两个随机选择的力量”(Power of Two Random Choices),在此处进行了描述:http://www.eecs.harvard.edu/~michaelm/postscripts/handbook2001.pdf rdp-cookie rdp-cookie(<name>) RDP cookie <name>(如果省略,则为“mstshash”)将在每个传入的 TCP 请求中查找并哈希。就像等效的 ACL 'req_rdp_cookie()' 函数一样,名称不区分大小写。此机制可用作降级的持久性模式,因为它使得将同一用户(或同一会话 ID)始终发送到同一台服务器成为可能。如果未找到 cookie,则使用正常的轮询算法代替。请注意,为了使其工作,前端必须确保请求缓冲区中已存在 RDP cookie。为此,您必须使用“tcp-request content accept”规则并结合“req_rdp_cookie_cnt”ACL。默认情况下,此算法是静态的,这意味着即时更改服务器的权重将无效,但这可以使用“hash-type”进行更改。另请参阅 rdp_cookie 模式获取功能。 <arguments> 是一个可选参数列表,某些算法可能需要这些参数。目前,只有“url_param”和“uri”支持可选参数。
当没有设置其他算法、模式或选项时,后端的负载均衡算法被设置为 roundrobin。每个后端只能设置一次算法。对于需要相同连接的认证方案(如 NTLM),不得使用基于 URI 的算法,因为它们会导致后续请求被路由到不同的后端服务器,从而破坏 NTLM 所依赖的无效假设。
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
注意:使用“url_param”的“check_post”扩展时,必须考虑以下警告和限制: - 所有 POST 请求都有资格进行考虑,因为无法确定是否会在可能包含二进制数据的正文或实体中找到参数。因此,可能需要另一种方法来限制对正文中没有 URL 参数的 POST 请求的考虑。(请参阅 acl http_end) - 使用大于请求缓冲区大小的 <max_wait> 值没有意义且无用。缓冲区大小在构建时设置,默认为 16 kB。 - 不支持 Content-Encoding,参数搜索可能会失败;负载均衡将回退到轮询。 - 不支持 Expect: 100-continue,负载均衡将回退到轮询。 - Transfer-Encoding (RFC7230 3.3.1) 仅在第一个块中受支持。如果整个参数值不存在于第一个块中,则服务器的选择是不确定的(实际上,由第一个块中实际出现的多少来定义)。 - 此功能不支持生成 100、411 或 501 响应。 - 在某些情况下,请求“check_post”可能会尝试扫描整个消息正文内容。扫描通常在找到线性空白或控制字符时终止,这表示可能是 URL 参数列表的末尾。对于 SGML 类型消息正文来说,这可能不是问题。
在前端(frontend)中定义一个或多个监听地址和/或端口。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 否![]() |
<address> 是可选的,可以是主机名、IPv4 地址、IPv6 地址或“*”。它指定前端将监听的地址。如果未设置,将监听系统的所有 IPv4 地址。对于“*”或系统的特殊地址“0.0.0.0”也将适用。IPv6 等效项是“::”。 可选地,可以在地址之前使用地址族前缀来强制使用该族,而不管地址格式如何,这对于指定没有斜杠('/')的 unix 套接字路径很有用。目前支持的前缀有: - 'ipv4@' -> 地址始终为 IPv4 - 'ipv6@' -> 地址始终为 IPv6 - 'unix@' -> 地址是本地 unix 套接字的路径 - 'abns@' -> 地址位于抽象命名空间中(仅限 Linux)。注意:由于抽象套接字不可“重新绑定”,因此它们在软重启期间与多进程模式不兼容,因此如果 nbproc 大于 1,最好避免使用它们。效果是,如果新进程启动失败,只有一个旧进程能够重新绑定到套接字。 - 'fd@<n>' -> 使用从父级继承的文件描述符 <n>。fd 必须已绑定并且可能已在监听。 - 'sockpair@<n>' -> 类似于 fd@,但您必须使用已连接的 unix 套接字或 socketpair 的 fd。bind 等待通过 unix 套接字接收 FD,并将其用作 accept() 的 FD。应谨慎使用。您可能希望在地址参数中引用一些环境变量,请参阅第 2.3 节关于环境变量的内容。 <port_range> 是唯一的 TCP 端口,或者是代理将接受上述指定 IP 地址连接的端口范围。对于 TCP 监听器,端口是强制性的。请注意,在 IPv6 地址的情况下,端口始终是最后一个冒号(':')之后的数字。范围可以是: - 数字端口(例如:“80”) - 带有破折号分隔的端口范围,明确说明下限和上限(例如:“2000-2100”),这些端口包含在范围内。必须特别注意端口范围,因为每个 <address:port> 对都会消耗一个套接字(= 一个文件描述符),因此很容易通过简单的范围消耗大量描述符,并耗尽套接字。此外,每个 <address:port> 对在同一系统上运行的所有实例中必须只使用一次。请注意,绑定到低于 1024 的端口通常需要特定的权限才能启动程序,这些权限独立于“uid”参数。 <path> 是以斜杠('/')开头的 UNIX 套接字路径。这是 TCP 监听端口的替代方案。然后 HAProxy 将在位于此处的套接字上接收 UNIX 连接。路径必须以斜杠开头,并且默认情况下是绝对路径。它可以是相对于全局部分中由“unix-bind”定义的前缀的相对路径。请注意,前缀后跟套接字路径的总长度不能超过 UNIX 套接字的一些系统限制,这些限制通常设置为 107 个字符。 <param*> 是同一行上声明的所有套接字共有的参数列表。这些众多参数取决于操作系统和构建选项,并有专门的部分介绍它们。请参阅第 5 节了解更多详细信息。
可以指定由逗号分隔的地址:端口组合列表。然后前端将侦听所有这些地址。前端可以侦听的地址和端口数量没有固定限制,前端中的“bind”语句的数量也没有限制。listen http_proxy bind :80,:443 bind 10.0.0.1:10080,10.0.0.1:10443 bind /var/run/ssl-frontend.sock user root mode 600 accept-proxy listen http_https_proxy bind :80 bind :443 ssl crt /etc/haproxy/site.pem listen http_https_proxy_explicit bind ipv6@:80 bind ipv4@public_ssl:443 ssl crt /etc/haproxy/site.pem bind unix@ssl-frontend.sock user root mode 600 accept-proxy listen external_bind_app1 bind "fd@${FD_APP1}"
注意:关于 Linux 的抽象命名空间套接字,HAProxy 使用整个 sun_path 长度作为地址长度。其他一些程序,如 socat,默认只使用字符串长度。在 socat 中对任何抽象套接字定义传递选项 ",unix-tightsocklen=0",以使其与 HAProxy 兼容。
将一个实例的可见性限制在特定的进程号集合中。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
all 所有进程都将看到此实例。这是默认设置。它可用于覆盖默认值。 odd 此实例将在进程 1、3、5、...、63 上启用。此选项可与其他数字组合使用。 even 此实例将在进程 2、4、6、...、64 上启用。此选项可与其他数字组合使用。如果进程少于 2 个,请不要使用它,否则某些实例可能会在所有进程中都缺失。 process_num 此实例将在此进程号或范围内启用,其值必须全部在 1 到 32 或 64 之间,具体取决于机器的字长。范围可以部分定义。可以省略上限。在这种情况下,它将被相应的最大值替换。如果一个代理被绑定到大于配置的 global.nbproc 的进程号,如果指定了单个进程,它将被强制到进程 #1,否则将被强制到所有进程。
此关键字限制某些实例绑定到某些进程。这有助于避免过多进程监听同一端口。例如,在双核机器上,在全局部分设置“nbproc 2”然后将监听器分配给“odd”和“even”实例可能是有意义的。目前,使用此关键字无法引用超过 32 或 64 个进程,但这对于大多数设置来说应该足够了。请注意,“all”确实表示所有进程,无论机器的字大小如何,并且不限于前 32 或 64 个。每行“bind”可以进一步限制为代理进程的子集,请参阅第 5.1 节中的“process”bind 关键字。当前端没有显式的“bind-process”行时,它会尝试绑定到其“bind”行引用的所有进程。这意味着前端可以轻松适应其监听器的进程。如果某些后端被绑定到其他进程的前端引用,则后端会自动继承前端的进程。
listen app_ip1 bind 10.0.0.1:80 bind-process odd listen app_ip2 bind 10.0.0.2:80 bind-process even listen management bind 10.0.0.3:80 bind-process 1 2 3 4 listen management bind 10.0.0.4:80 bind-process 1-4
在请求和响应中捕获并记录一个 cookie。
可用于节
| 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
捕获并记录指定请求头的最后一次出现。
可用于节
| 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
捕获并记录指定响应头的最后一次出现。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 否![]() |
<name> 是要捕获的头的名称。头名称不区分大小写,但通常的做法是按照它们在响应中出现的样子来写,每个单词的首字母大写。头名称不会出现在日志中,只报告其值,但其在日志中的位置会得到尊重。<length> 是从值中提取并报告在日志中的最大字符数。如果字符串超过 <length>,它将被从右侧截断。
捕获该头最后一次出现的完整值。结果将在捕获的请求头之后,添加在日志中的大括号 ('{}') 之间。如果捕获了多个头,它们将由竖线 ('|') 分隔,并按照它们在配置中声明的相同顺序出现。不存在的头将被记录为空字符串。响应头捕获的常见用途包括 "Content-length" 头,它指示预计将返回多少字节,以及 "Location" 头,用于跟踪重定向。捕获的响应头数量及其长度没有限制,但明智的做法是保持它们较低以限制每个会话的内存使用。为了保持同一前端的日志格式一致,头捕获只能在前端声明。不能在 "defaults" 配置段中指定捕获。capture response header Content-length len 9 capture response header Location len 15
启用 HTTP 压缩。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
algo 后面是支持的压缩算法列表。type 后面是将要被压缩的 MIME 类型列表。offload 使 haproxy 仅作为压缩卸载器工作(见说明)。
目前支持的算法有: identity 这主要用于调试,对于开发压缩功能很有用。Identity 不对数据应用任何更改。 gzip 应用 gzip 压缩。此设置仅在内置 zlib 或 libslz 支持时可用。 deflate 与“gzip”相同,但使用 deflate 算法和 zlib 格式。请注意,许多浏览器对此算法的支持不明确,最近的浏览器根本不支持。强烈建议不要将其用于实验以外的任何目的。此设置仅在内置 zlib 或 libslz 支持时可用。 raw-deflate 与“deflate”相同,没有 zlib 包装器,当浏览器想要“deflate”时用作替代方案。所有主要浏览器都理解它,尽管违反了标准,但它已知比“deflate”工作得更好,至少在 MSIE 和某些版本的 Safari 上。不要与“deflate”结合使用,因为两者都对相同的 Accept-Encoding 令牌做出反应。此设置仅在内置 zlib 或 libslz 支持时可用。 压缩将根据 Accept-Encoding 请求标头激活。使用 identity 时,它不关心该标头。如果后端服务器支持 HTTP 压缩,这些指令将无效:haproxy 将看到压缩的响应,并且不会再次压缩。如果后端服务器不支持 HTTP 压缩且请求中存在 Accept-Encoding 标头,haproxy 将压缩匹配的响应。 “offload”设置使 haproxy 删除 Accept-Encoding 标头,以防止后端服务器压缩响应。强烈建议不要这样做,因为这意味着所有压缩工作都将在 haproxy 所在的单个点上完成。但是在某些部署场景中,haproxy 可能安装在具有损坏 HTTP 压缩实现且无法关闭的错误网关前面。在这种情况下,可以使用 haproxy 来防止该网关发出无效负载。在这种情况下,简单地在配置中删除标头不起作用,因为它在解析标头之前应用,从而阻止 haproxy 压缩。然后应将“offload”设置用于此类场景。注意:目前,在 defaults 部分中设置“offload”设置时会被忽略。 在以下情况下禁用压缩: * 请求未在“Accept-Encoding”标头中宣传支持的压缩算法 * 响应消息不是 HTTP/1.1 或更高版本 * HTTP 状态代码不是 200、201、202 或 203 之一 * 响应既不包含“Content-Length”标头,也不包含最后一个值为“chunked”的“Transfer-Encoding” * 响应包含“Content-Type”标头,其第一个值以“multipart”开头 * 响应在“Cache-control”标头中包含“no-transform”值 * User-Agent 与“Mozilla/4”匹配,除非它是带有 XP SP2 的 MSIE 6,或者是 MSIE 7 及更高版本 * 响应包含“Content-Encoding”标头,表明响应已被压缩(请参阅 compression offload) * 响应包含无效的“ETag”标头或多个 ETag 标头 注意:压缩不会发出 Warning 标头。
compression algo gzip compression type text/html text/plain
在后端启用基于 cookie 的持久性。
可用于节
| 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,则会将其删除,除非同时设置了 "preserve" 选项。在 "insert" 模式下,这还将从传输到服务器的请求中删除 cookie,从而使持久性机制从应用程序的角度来看完全透明。注意:强烈建议不要将 "indirect" 与 "prefix" 一起使用,否则服务器 cookie 更新将不会发送给客户端。nocache 当客户端和 HAProxy 之间存在缓存时,建议将此选项与 insert 模式结合使用,因为它确保如果需要插入 cookie,可缓存的响应将被标记为不可缓存。这很重要,因为如果所有持久性 cookie 都添加在可缓存的主页上,例如,所有客户都将从外部缓存中获取该页面,并且都将共享相同的持久性 cookie,导致一个服务器接收的流量比其他服务器多得多。另请参阅 "insert" 和 "postonly" 选项。postonly 此选项确保 cookie 插入将仅在对 POST 请求的响应上执行。它是 "nocache" 选项的替代方案,因为 POST 响应不可缓存,因此这确保了持久性 cookie 永远不会被缓存。由于大多数站点在第一次 POST(通常是登录请求)之前不需要任何形式的持久性,因此这是一种优化缓存而不会冒在缓存中找到持久性 cookie 风险的非常有效的方法。另请参阅 "insert" 和 "nocache" 选项。preserve 此选项只能与 "insert" 和/或 "indirect" 一起使用。它允许服务器自己发出持久性 cookie。在这种情况下,如果在响应中找到 cookie,haproxy 将保持不变。例如,这在注销请求后结束持久性时很有用。为此,服务器只需发出一个具有无效值(例如空)或过去日期的 cookie。通过将此机制与 "disable-on-404" 检查选项结合使用,可以执行完全优雅的关机,因为用户在注销后会明确离开服务器。httponly 此选项告诉 haproxy 在插入 cookie 时添加 "HttpOnly" cookie 属性。使用此属性是为了让用户代理不与非 HTTP 组件共享 cookie。请查看 RFC6265 以获取有关此属性的更多信息。secure 此选项告诉 haproxy 在插入 cookie 时添加 "Secure" cookie 属性。使用此属性是为了让用户代理永远不会通过非安全通道发出此 cookie,这意味着使用此标志学到的 cookie 将仅通过 SSL/TLS 连接呈现。请查看 RFC6265 以获取有关此属性的更多信息。domain 此选项允许指定插入 cookie 的域。它需要一个参数:一个有效的域名。如果域以点开头,则允许浏览器将其用于以该名称结尾的任何主机。也可以通过多次调用此选项来指定多个域名。某些浏览器可能对域的数量有限制,因此在使用时要小心。根据记录,向 MSIE 6 或 Firefox 2 发送 10 个域可以按预期工作。maxidle 此选项允许在一些空闲时间后忽略插入的 cookie。它仅适用于 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。使用时,会根据服务器的 IP 和端口以及在 "dynamic-cookie-key" 后端指令中指定的密钥为每个服务器动态创建一个会话 cookie。每次 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
声明一个捕获槽。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 否![]() |
<length> 是允许捕获的长度。
此声明仅在 frontend 或 listen 配置段中可用,但保留的槽可以在 backend 中使用。“request”关键字分配一个用于请求中的捕获槽,“response”分配一个用于响应中的捕获槽。
更改后端中服务器的默认选项。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<param*> 是此服务器的参数列表。“default-server”关键字接受大量选项,并有专门的完整章节介绍。更多详情请参阅 第 5 节。
default-server inter 1000 weight 13
指定在没有匹配到“use_backend”规则时使用的后端。
可用于节
| 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。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
允许添加一句话来在 HAProxy HTML 统计页面中描述相关对象。该描述将打印在其所描述对象名称的右侧。<string> 参数中的空格无需使用反斜杠转义。
禁用一个 proxy、frontend 或 backend。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
关键字 "disabled" 用于禁用实例,主要用于释放监听端口或临时禁用服务。实例仍将创建并检查其配置,但它将以 "stopped" 状态创建,并在统计数据中显示为如此。它不会接收任何流量,也不会发送任何健康检查或日志。通过在 "defaults" 部分添加 "disabled" 关键字,可以一次禁用多个实例。
设置一个默认服务器地址
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<address> 是默认服务器的 IPv4 地址。或者,也支持可解析的主机名,但此名称将在启动期间解析。<ports> 是一个强制性的端口规范。所有连接都将发送到此端口,并且不允许像普通服务器那样使用端口偏移量。
关键字 "dispatch" 指定在没有其他服务器可以接受连接时使用的默认服务器。过去,它用于将非持久连接转发到辅助负载均衡器。由于其简单的语法,它也被用于简单的 TCP 中继。建议不要使用它以获得更高的清晰度,并改用 "server" 指令。
为后端设置动态 cookie 的密钥。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
启用动态 cookie 时(请参阅 cookie 的 "dynamic" 指令),会为每个服务器创建一个动态 cookie(除非在 "server" 行上明确指定),使用服务器 IP 地址、TCP 端口和密钥的哈希值。这样,我们可以确保跨多个负载均衡器的会话持久性,即使服务器是动态添加或删除的。启用一个 proxy、frontend 或 backend。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
当 defaults 设置为 "disabled" 时,关键字 "enabled" 用于显式启用实例。这很少使用。
返回文件内容以替代 HAProxy 生成的错误
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<code> 是 HTTP 状态码。目前,HAProxy 能够生成代码 200、400、403、404、405、408、410、413、425、429、500、502、503 和 504。<file> 指定包含完整 HTTP 响应的文件。建议遵循惯例,在文件名后附加 ".http",这样人们就不会将响应与 HTML 错误页面混淆,并使用绝对路径,因为文件是在执行任何 chroot 之前读取的。
重要的是要理解此关键字并非旨在重写服务器返回的错误,而是 HAProxy 检测并返回的错误。这就是支持的错误列表仅限于一小组的原因。在响应匹配 "monitor-uri" 规则的请求时,会发出代码 200。文件按原样返回到 TCP 套接字。这允许任何技巧,例如重定向到另一个 URL 或站点,以及清理 cookie、强制启用或禁用缓存等技巧...该包提供了返回与默认错误相同内容的默认错误文件。文件不应超过配置的缓冲区大小 (BUFSIZE),通常为 8 或 16 kB,否则它们将被截断。明智的做法是不要在文件中放置对本地内容(例如图像)的任何引用,以避免在所有服务器都关闭时在客户端和 HAProxy 之间发生循环,导致返回错误而不是图像。为了更好地符合 HTTP,建议所有标头行以 CR-LF 结尾,而不是单独的 LF。文件在配置的同时读取并保留在内存中。因此,即使进程被 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
返回一个到某个 URL 的 HTTP 重定向,以替代 HAProxy 生成的错误
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<code> 是 HTTP 状态码。目前,HAProxy 能够生成代码 200、400、403、404、405、408、410、413、425、429、500、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 生成的错误
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<code> 是 HTTP 状态码。目前,HAProxy 能够生成代码 200、400、403、404、405、408、410、413、425、429、500、502、503 和 504。<url> 是 "Location" 标头的确切内容。它可以包含指向同一站点上托管的错误页面的相对 URI,也可以包含指向另一个站点上的错误页面的绝对 URI。应特别注意相对 URI,以避免如果 URI 本身可能生成相同的错误(例如 500)时发生重定向循环。
重要的是要理解,此关键字并非用于重写服务器返回的错误,而是用于重写 HAProxy 检测并返回的错误。这就是为什么支持的错误列表仅限于一小部分。状态码 200 是为响应匹配“monitor-uri”规则的请求而发出的。请注意,这两个关键字都返回 HTTP 303 状态码,它告诉客户端使用相同的 HTTP GET 方法获取指定的 URL。这解决了与“errorloc”和 302 状态码相关的常见问题。一些在 HTTP/1.1 之前设计的非常旧的浏览器可能不支持它,但到目前为止还没有报告过此类问题。
声明用于电子邮件警报的信封和头部的发件人电子邮件地址。这是发送电子邮件警报的来源地址。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<emailaddr> 是发送电子邮件警报时使用的发件人电子邮件地址
还需要设置“email-alert mailers”和“email-alert to”,如果设置了,则为该代理启用电子邮件警报发送功能。
声明将发送电子邮件警报的消息的最大日志级别。这充当发送电子邮件警报的过滤器。
可用于节
| 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 或更低,并且发生了健康检查状态更新
声明发送电子邮件警报时要使用的邮件程序
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<mailersect> 是用于发送电子邮件警报的邮件程序部分的名称。
还需要设置“email-alert from”和“email-alert to”,如果设置了,则为该代理启用电子邮件警报发送功能。
声明与邮件程序通信时要使用的主机名地址。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<hostname> 是与邮件程序通信时使用的主机名
默认使用系统的主机名。还需要设置“email-alert from”、“email-alert mailers”和“email-alert to”,如果设置了,则为该代理启用电子邮件警报发送功能。
声明邮件警报信封中的收件人地址和邮件头中的 to 地址。这是邮件警报发送到的地址。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<emailaddr> 是发送电子邮件警报时使用的收件人电子邮件地址
还需要设置“email-alert mailers”和“email-alert to”,如果设置了,则为该代理启用电子邮件警报发送功能。
声明一个条件以强制在宕机服务器上保持持久性
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
默认情况下,请求不会分派到关闭的服务器。可以使用 "option persist" 强制执行此操作,但它是无条件的,如果设置了 "option redispatch",则会重新分派到有效的服务器。这使得强制某些请求到达因维护操作而被人工标记为关闭的服务器的可能性很小。"force-persist" 语句允许声明各种基于 ACL 的条件,当满足这些条件时,将导致请求忽略服务器的关闭状态,并仍尝试连接到它。这使得启动服务器、仍对健康检查返回错误以及运行专门配置的浏览器来测试服务成为可能。在便捷方法中,可以使用特定的源 IP 地址或特定的 cookie。cookie 还有一个优点,即可以轻松地从测试页面在浏览器上添加/删除。一旦服务经过验证,就可以通过对健康检查返回有效响应来向全世界开放服务。当满足 "if" 条件时,或除非满足 "unless" 条件时,强制持久性才会启用。当使用此功能时,最终的重新分派总是被禁用。
将过滤器 <name> 添加到附加到代理的过滤器列表中。
可用于节
| 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
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<conns> 是后端上的连接数,该连接数将使服务器使用最大连接数。
当服务器指定了 "maxconn" 参数时,这意味着其并发连接数永远不会更高。此外,如果它有 "minconn" 参数,它表示一个遵循后端负载的动态限制。当后端并发连接数少于 <conns> 时,服务器将始终接受至少 <minconn> 个连接,永远不超过 <maxconn> 个连接,并且限制将在两个值之间的斜坡上。这使得在正常负载期间限制服务器上的负载成为可能,但在重要负载期间将其推得更远,同时又不会在异常负载期间使服务器过载。由于很难正确设置此值,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
在软停止后,维持代理在一段时间内可操作
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<time> 是当通过 SIGUSR1 信号接收到软停止时,实例将保持可操作且前端套接字仍在监听的时间(默认为毫秒)。
这可以用来确保服务按特定顺序消失。它被设计成这样,专用于外部设备监控的前端会立即失败,而其他前端则会保持运行,直到设备检测到故障所需的时间。请注意,目前使用此参数的好处非常小,实际上它可能会使软重新配置过程复杂化,而不是简化它。
指定有界负载一致性哈希的平衡因子
可用于节
| 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",它在内部依赖于一致性哈希机制。
指定一种将哈希值映射到服务器的方法
可用于节
| 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 这是最常见的 CRC32 实现,用于以太网、gzip、PNG 等。它比其他实现慢,但可以提供更好的分布或更不可预测的结果,尤其是在对字符串使用时。<modifier> 指示在对键进行哈希处理后应用的可选方法:avalanche 此指令指示上面哈希函数的结果不应以原始形式使用,而必须首先应用 4 字节的完整雪崩哈希。此步骤的目的是混合前一个哈希的结果位,以避免当输入包含一些有限值或服务器数量是哈希组件之一(SDBM 为 64,DJB2 为 33)的倍数时出现任何不需要的效果。启用雪崩往往会使结果不那么可预测,但它也不如使用原始函数时平滑。可能需要对某些工作负载进行一些测试。此哈希是 Bob Jenkins 提出的众多哈希之一。
默认的哈希类型是“map-based”,建议在大多数情况下使用。默认的函数是“sdbm”,函数的选择应基于被哈希值的范围。
在对健康检查响应 HTTP/404 时启用维护模式
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
当设置此选项时,返回 HTTP 404 状态码的服务器将从进一步的负载均衡中排除,但仍会接收持久连接。这为 Web 管理员提供了一种非常方便的方法来优雅地关闭他们的服务器。同样重要的是要注意,在此模式下被检测为失败的服务器不会生成警报,只会生成一个通知。如果服务器再次响应 2xx 或 3xx,它将立即被重新插入到服务器组中。在统计页面上,处于此模式的服务器状态报告为“NOLB”。重要的是要注意,此选项仅与“httpchk”选项一起使用。如果此选项与“http-check expect”一起使用,则它优先于后者,因此 404 响应仍将被视为软停止。
使 HTTP 健康检查考虑响应内容或特定状态码
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<match> 是一个关键字,指示如何在响应中查找特定模式。该关键字可以是“status”、“rstatus”、“string”或“rstring”之一。关键字前面可以加上感叹号(“!”)以否定匹配。感叹号和关键字之间允许有空格。有关支持的关键字的更多详细信息,请参见下文。<pattern> 是要查找的模式。它可以是字符串或正则表达式。如果模式包含空格,必须使用通常的反斜杠('\')进行转义。
默认情况下,"option httpchk" 认为响应状态 2xx 和 3xx 是有效的,而其他状态是无效的。使用 "http-check expect" 时,它定义了什么是有效或无效的。一个后端只支持一个 "http-check" 语句。如果服务器无法响应或超时,检查显然会失败。可用的匹配项是:status <string>:测试 HTTP 状态码的精确字符串匹配。如果响应的状态码与此字符串完全匹配,则健康检查响应将被视为有效。如果 "status" 关键字带有 "!" 前缀,则如果状态码匹配,则响应将被视为无效。rstatus <regex>:测试 HTTP 状态码的正则表达式。如果响应的状态码匹配正则表达式,则健康检查响应将被视为有效。如果 "rstatus" 关键字带有 "!" 前缀,则如果状态码匹配,则响应将被视为无效。这主要用于检查多个代码。string <string>:测试 HTTP 响应正文中的精确字符串匹配。如果响应正文包含此精确字符串,则健康检查响应将被视为有效。如果 "string" 关键字带有 "!" 前缀,则如果正文包含此字符串,则响应将被视为无效。这可用于查找动态页面末尾的必需单词,或在检查页面上出现特定错误(例如堆栈跟踪)时检测故障。rstring <regex>:测试 HTTP 响应正文中的正则表达式。如果响应正文匹配此表达式,则健康检查响应将被视为有效。如果 "rstring" 关键字带有 "!" 前缀,则如果正文匹配表达式,则响应将被视为无效。这可用于查找动态页面末尾的必需单词,或在检查页面上出现特定错误(例如堆栈跟踪)时检测故障。需要注意的是,响应将受限于由全局 "tune.chksize" 选项定义的特定大小,该选项默认为 16384 字节。因此,使用 "string" 或 "rstring" 时,太大的响应可能不包含必需的模式。如果绝对需要大响应,可以通过设置全局变量来更改默认最大大小。但是,值得记住的是,解析非常大的响应会浪费一些 CPU 周期,尤其是使用正则表达式时,并且最好始终将检查重点放在较小的资源上。此外,"http-check expect" 不支持 HTTP keep-alive。请记住,它会自动附加 "Connection: close" 标头,这意味着 "option httpchk" 提供的请求中不应存在此标头。最后,如果 "http-check expect" 与 "http-check disable-on-404" 结合使用,则当服务器响应 404 时,后者优先。
# 只接受状态 200 为有效 http-check expect status 200 # 将 SQL 错误视为错误 http-check expect ! string SQL\ Error # 仅将状态 5xx 视为错误 http-check expect ! rstatus ^5 # 检查在 /html 之前是否有一个正确的十六进制标签 http-check expect rstring <!--tag:[0-9a-f]*--></html>
在 HTTP 健康检查期间,向发送的请求添加可能的头信息列表和/或一个主体。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
hdr <name> <value> 在 HTTP 健康检查期间发送的请求中添加指定名称为 <name> 且值定义为 <value> 的 HTTP 头字段。body <string> 在 HTTP 健康检查期间发送的请求中添加由 <string> 定义的请求体。如果定义了,"Content-Length" 头将自动添加到请求中。
除了由 "option httpchk" 指令定义的请求行之外,这是在 HTTP 健康检查期间发送的请求中添加一些头并可选地添加正文的有效方法。如果定义了正文,则会自动添加关联的 "Content-Length" 头。在 "option httpchk" 行的协议版本字符串后添加头的老技巧现在已弃用。另请注意,如果定义了 "http-check expect" 指令(与此指令无关),则仍然会添加 "Connection: close" 头,就像如果定义了 "http-check send-state" 指令一样,也会添加状态头。
启用在 HTTP 健康检查中发送状态头
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
设置此选项后,haproxy 将系统地发送一个特殊的标头 "X-Haproxy-Server-State",其中包含一系列参数,指示每个服务器 haproxy 如何看待它们。例如,当在没有访问 haproxy 的情况下操作服务器时,如果操作员需要知道 haproxy 是否仍然认为它启动或服务器是否是农场中的最后一个时,可以使用此功能。标头由分号分隔的字段组成,第一个字段是一个单词("UP"、"DOWN"、"NOLB"),后面可能跟着在转换之前对总数进行的一些有效检查,就像在 stats 接口中显示的那样。接下来的标头形式为 "<variable>=<value>",以不特定的顺序指示 stats 接口中可用的一些值:- 变量 "address",包含后端服务器的地址。这对应于服务器声明中的 <address> 字段。对于 unix 域套接字,它将读取 "unix"。- 变量 "port",包含后端服务器的端口。这对应于服务器声明中的 <port> 字段。对于 unix 域套接字,它将读取 "unix"。- 变量 "name",包含后端名称,后跟斜杠 ("/"),然后是服务器名称。当在多个后端中检查服务器时,可以使用此功能。- 变量 "node",包含 haproxy 节点的名称,如全局 "node" 变量中设置的那样,如果未指定,则为系统的 hostname。- 变量 "weight",指示服务器的权重、斜杠 ("/") 和农场的总权重(仅计算可用服务器)。这有助于了解当此服务器发生故障时是否有其他服务器可用于处理负载。- 变量 "scur",指示服务器上当前的并发连接数,后跟斜杠 ("/"),然后是同一后端所有服务器上的总连接数。- 变量 "qcur",指示服务器队列中当前请求数。应用程序服务器接收到的标头示例:>>> X-Haproxy-Server-State: UP 2/3; name=bck/srv2; node=lb1; weight=1/2; \ scur=13/22; qcur=0
第 7 层请求的访问控制
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
http-request 语句定义了一组适用于第 7 层处理的规则。当在 frontend、listen 或 backend 部分遇到规则时,将按声明顺序对其进行评估。任何规则都可以选择性地后跟一个基于 ACL 的条件,在这种情况下,只有在条件为真时才会对其进行评估。第一个关键字是规则的操作。支持的操作如下所述。每个实例的 http-request 语句数量没有限制。
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
此操作用于向 ACL 中添加一个新条目。ACL 必须从一个文件加载(即使是一个虚拟的空文件)。要更新的 ACL 的文件名在括号中传递。它接受一个参数:<key fmt>,该参数遵循日志格式规则,用于收集新条目的内容。它在插入前会先在 ACL 中进行查找,以避免重复(或更多)的值。此查找通过线性搜索完成,对于大列表可能会很耗费资源!它等同于 stats socket 中的“add acl”命令,但可以由 HTTP 请求触发。
此操作附加一个 HTTP 头部字段,其名称由 <name> 指定,其值由 <fmt> 定义,<fmt> 遵循日志格式规则(请参阅 第 8.2.4 节 中的自定义日志格式)。这对于向服务器传递特定于连接的信息(例如,客户端的 SSL 证书)或将多个头部合并为一个特别有用。此规则不是最终的,因此可以添加其他类似的规则。请注意,头部添加是立即执行的,因此一个规则可能会重用前一个规则产生的头部。
这会停止规则的评估,并允许请求通过检查。不再评估其他“http-request”规则。这会停止对规则的评估,并立即以 HTTP 401 或 407 错误代码响应,以邀请用户提供有效的用户名和密码。不会评估进一步的 "http-request" 规则。支持可选的 "realm" 参数,它设置与响应一起返回的身份验证领域(通常是应用程序的名称)。acl auth_ok http_auth_group(L1) G1 http-request auth unless auth_ok
请参阅关于缓存设置的第 6.2 节。
这会从请求缓冲区捕获样本表达式 <sample>,并将其转换为最多 <len> 个字符的字符串。生成的字符串存储在下一个请求 "capture" 插槽中,因此它可能会出现在一些捕获的 HTTP 标头旁边。然后它将自动出现在日志中,并且可以使用样本获取规则将其提取出来以馈送到标头或任何东西中。长度应受到限制,因为在整个会话生命周期内,每个捕获都将分配此大小。请查看 第 7.3 节(获取样本)和 "capture request header" 以获取更多信息。如果使用关键字 "id" 而不是 "len",则该操作会尝试将捕获的字符串存储在先前声明的捕获插槽中。这对于在后端运行捕获很有用。插槽 ID 可以由先前的指令 "http-request capture" 或使用 "declare capture" 关键字声明。在后端使用此操作时,请仔细检查相关前端是否具有所需的捕获插槽,否则此规则将在运行时被忽略。由于 HAProxy 能够在运行时动态解析后端名称,因此在配置解析时无法检测到这一点。
此操作用于从 ACL 中删除一个条目。ACL 必须从一个文件加载(即使是一个虚拟的空文件)。要更新的 ACL 的文件名在括号中传递。它接受一个参数:<key fmt>,该参数遵循日志格式规则,用于收集要删除的条目的内容。它等同于 stats socket 中的“del acl”命令,但可以由 HTTP 请求触发。
这会删除指定名称为 <name> 的所有 HTTP 头字段。
此操作用于从 MAP 中删除一个条目。MAP 必须从一个文件加载(即使是一个虚拟的空文件)。要更新的 MAP 的文件名在括号中传递。它接受一个参数:<key fmt>,该参数遵循日志格式规则,用于收集要删除的条目的内容。它接受一个参数:“file name”。它等同于 stats socket 中的“del map”命令,但可以由 HTTP 请求触发。
这会停止对规则的评估,并立即拒绝请求并发出 HTTP 403 错误,或者可选地发出指定为 "deny_status" 参数的状态码。允许的状态码列表仅限于可通过 "errorfile" 指令覆盖的状态码。不会评估进一步的 "http-request" 规则。
此操作会禁止任何因连接失败以外的原因而重试请求的尝试。例如,这对于确保 POST 请求在失败时不会被重试非常有用。
此操作对 <expr> 的输出执行 DNS 解析,并将结果存储在变量 <var> 中。它使用 <resolvers> 指向的 DNS 解析器部分。可以使用可选参数 'ipv4' 或 'ipv6' 选择解析偏好。执行 DNS 解析时,客户端连接暂停,等待解析结束。如果找到 IP 地址,它将存储到 <var> 中。如果发生任何错误,则不设置 <var>。可以使用此操作在运行时发现服务器 IP 地址,并基于请求中找到的信息(例如 Host 标头)。如果使用此操作查找服务器的 IP 地址(使用 "set-dst" 操作),则后端中的服务器 IP 地址必须设置为 0.0.0.0。
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),lower http-request capture var(txn.myip) len 40 # 如果变量未设置,则返回 503, # 这意味着 DNS 解析错误 use_backend b_503 unless { var(txn.myip) -m found } default_backend be backend b_503 # 用于返回 503 的虚拟后端。 # 可以使用 errorfile 指令向最终用户发送漂亮的 # 503 错误页面 backend be # 规则以防止 HAProxy 重新连接到本地网络上的服务 # (使用伪造的 DNS 名称扫描网络) http-request deny if { var(txn.myip) -m ip 127.0.0.0/8 10.0.0.0/8 } http-request set-dst var(txn.myip) server clear 0.0.0.0:0
注意:不要忘记设置“保护”规则,以确保 HAProxy 不会被用于扫描网络,或更糟糕的是,不会循环访问自身……
此操作用于在任何其他响应之前构建一个 HTTP 103 Early Hints 响应。此操作向此响应附加一个 HTTP 头部字段,其名称由 <name> 指定,其值由 <fmt> 定义,<fmt> 遵循日志格式规则(请参阅 第 8.2.4 节 中的自定义日志格式)。这对于向客户端传递一些 Link 头部以预加载渲染 HTML 文档所需的资源特别有用。更多信息请参阅 RFC 8297。
此操作基于重定向规则执行 HTTP 重定向。这与“redirect”语句完全相同,只是它插入一个重定向规则,该规则可以在其他“http-request”规则中间进行处理,并且这些规则使用“log-format”字符串。有关规则的语法,请参见“redirect”关键字。
这会停止规则的评估,并立即关闭连接而不发送任何响应。它的作用类似于“tcp-request content reject”规则。强制关闭 HTTP/2 连接可能很有用。
此操作将头部字段 <名称> 的所有出现的值与 <匹配正则表达式> 进行匹配。匹配是区分大小写的。匹配的值将被 <替换格式> 完全替换。在 <替换格式> 中允许使用格式化字符,其工作方式类似于“http-request add-header”中的 <fmt> 参数。支持使用反斜杠 ('\') 后跟数字的标准后向引用。此操作作用于整个头部行,无论它们可能包含多少个值。因此,它非常适合处理值中自然包含逗号的头部,例如 If-Modified-Since。包含逗号分隔值列表的头部,例如 Accept,应使用“http-request 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
此操作的工作方式类似于“replace-header”,但它作用于请求的路径组件而不是头部。路径组件从可选的协议+授权之后第一个'/'开始,到问号之前结束。因此,替换不会修改协议、授权和查询字符串。值得注意的是,正则表达式的评估可能比某些 ACL 更昂贵,因此对于罕见的替换,使用条件来避免在不匹配时执行评估可能会更有利。
# 在 /foo 前加上前缀:将 /bar?q=1 变为 /foo/bar?q=1: http-request replace-path (.*) /foo\1 # 去除 /foo:将 /foo/bar?q=1 变为 /bar?q=1 http-request replace-path /foo/(.*) /\1 # 或者如果只有部分请求匹配,这样更高效: http-request replace-path /foo/(.*) /\1 if { url_beg /foo/ }
此操作类似于 "replace-header",但它作用于请求的 URI 部分而不是标头。URI 部分可能包含可选的方案、权威机构或查询字符串。这些被视为与匹配值的一部分。值得注意的是,正则表达式的评估成本可能高于某些 ACL,因此罕见的替换可能会受益于条件,以避免在不匹配时完全执行评估。重要提示:从历史上看,在 HTTP/1.x 中,浏览器发送的绝大多数请求都使用 "origin form",它与 "absolute form" 的区别在于 URI 部分不包含方案或权威机构。大多数只有发送给代理的请求、手动伪造的请求以及某些应用程序发出的请求使用绝对形式。因此,"replace-uri" 在 HTTP/1.x 中通常适用于以 "/" 开头的规则。但对于 HTTP/2,鼓励客户端仅发送绝对 URI,这些 URI看起来像 HTTP/1 客户端用于与代理通信的 URI。因此,这些部分 replace-uri 规则在 HTTP/2 中可能会失败,而在 HTTP/1 中却有效。规则需要适应以可选地匹配方案和权威机构,或者应该使用 replace-path。
# 将所有 "http" 绝对请求重写为 "https": http-request replace-uri ^http://(.*) https://\1 # 添加前缀 /foo:将 /bar?q=1 变为 /foo/bar?q=1: http-request replace-uri ([^/:]*://[^/]*)?(.*) \1/foo\2
此操作的工作方式类似于“replace-header”,但它将正则表达式与头部字段 <名称> 的每个逗号分隔的值进行匹配,而不是整个头部。这适用于所有允许携带多个值的头部。例如 Accept 头部。
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
此操作根据由 <sc-id> 指定的粘性计数器来递增 GPC0 或 GPC1 计数器。如果发生错误,此操作将静默失败,并且操作评估继续。
此操作根据由 <sc-id> 指定的粘性计数器和 <int>/<expr> 的值来设置 32 位无符号 GPT0 标签。预期结果为布尔值。如果发生错误,此操作将静默失败,并继续评估操作。
此操作用于将目标 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。
此操作用于将目标端口地址设置为指定表达式的值。如果要连接到新的地址/端口,请在后端中使用 '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"。
此操作与“http-request add-header”相同,只是如果头部名称已存在,则会首先删除它。这在向服务器传递安全信息时很有用,因为此时头部不应被外部用户操纵。请注意,新值是在删除之前计算的,因此可以将一个值连接到现有头部。
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]
当满足特定条件时,这用于更改当前请求的日志级别。有效级别是 8 个 syslog 级别(请参阅 "log" 关键字)加上特殊级别 "silent",它禁用此请求的日志记录。此规则不是最终规则,因此最后一个匹配的规则获胜。此规则可用于禁用来自其他设备的健康检查。此操作用于向 MAP 中添加一个新条目。MAP 必须从一个文件加载(即使是一个虚拟的空文件)。要更新的 MAP 的文件名在括号中传递。它需要 2 个参数:<键格式>,它遵循日志格式规则,用于收集 MAP 键;以及 <值格式>,它遵循日志格式规则,用于收集新条目的内容。它在插入前会进行一次 MAP 查找,以避免重复(或更多)的值。此查找通过线性搜索完成,对于大型列表可能会很耗时!它等同于 stats 套接字中的“set map”命令,但可以由 HTTP 请求触发。
在支持的平台上,此操作将 Netfilter MARK 设置为传递给 <mark> 的值,该值将发送到客户端的所有数据包上。该值是一个无符号 32 位值,netfilter 和路由表都可以匹配。它可以表示为十进制或十六进制格式(以“0x”为前缀)。这对于强制某些数据包采用不同的路由(例如,更便宜的批量下载网络路径)非常有用。这适用于 Linux 内核 2.6.32 及更高版本,并且需要管理员权限。
此操作使用格式化字符串 <fmt> 的求值结果来重写请求方法。这样做应该有极少数的正当理由,因为它更有可能破坏某些东西而不是修复它。
这会设置正在处理的当前请求的 "nice" 因子。它只对同时处理的其他请求有效。默认值为 0,除非在 "bind" 行上的 "nice" 设置进行了更改。可接受的范围是 -1024..1024。值越高,请求的优先级越低。较低的值会使请求比其他请求更重要。这有助于提高某些请求的速度,或降低不重要请求的优先级。未经事先试验而使用此设置可能会导致一些严重的减速。
此操作用格式字符串 <格式> 的评估结果重写请求路径。查询字符串(如果存在)保持不变。如果在路径之前找到协议和授权,它们也保持不变。如果请求没有路径(“*”),则此路径将被格式替换。例如,这可用于在路径前添加一个目录组件。另请参见“http-request set-query”和“http-request set-uri”。
# 在路径前添加主机名 http-request set-path /%[hdr(host)]%[path]
此操作用于设置当前请求的队列优先级类别。该值必须是一个样本表达式,其转换结果为 -2047 到 2047 范围内的整数。超出此范围的结果将被截断。优先级类别决定了排队请求的处理顺序。值越低,优先级越高。
此操作用于设置当前请求的队列优先级时间戳偏移量。该值必须是一个样本表达式,其转换结果为 -524287 到 524287 范围内的整数。超出此范围的结果将被截断。当一个请求进入队列时,它首先按优先级类别排序,然后按当前时间戳加上给定的偏移量(以毫秒为单位)进行排序。值越低,优先级越高。请注意,结果时间戳的跟踪精度仅足以表示 524,287 毫秒(8 分 44 秒 287 毫秒)。如果请求排队时间足够长,以至于调整后的时间戳超过此值,它将被错误地识别为最高优先级。因此,将“timeout queue”设置为一个值,使其与偏移量相加后不超过此限制,这一点很重要。
此操作用格式字符串 <格式> 的评估结果重写请求的查询字符串,即第一个问号(“?”)之后的部分。问号之前的部分保持不变。如果请求不包含问号且新值不为空,则在 URI 的末尾添加一个问号,后跟新值。如果问号已存在,即使值为空,它也永远不会被删除。这可用于从查询字符串中添加或删除参数。另请参见“http-request set-query”和“http-request set-uri”。
# 在查询字符串中将“%3D”替换为“=” http-request set-query %[query,regsub(%3D,=,g)]
此操作用于将源 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。
此操作用于将源端口地址设置为指定表达式的值。
<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"。
此操作用于在支持此功能的平台上,将发送给客户端的数据包的 TOS 或 DSCP 字段值设置为 <tos> 中传递的值。此值代表 IP TOS 字段的全部 8 位,可以用十进制或十六进制格式(以“0x”为前缀)表示。请注意,DSCP 或 TOS 中仅使用较高的 6 位,而较低的两位始终为 0。这可用于根据请求中的某些信息调整边界路由器上的一些路由行为。有关更多信息,请参阅 RFC 2474, 2597, 3260 和 4594。
这会使用格式字符串 <fmt> 的评估结果重写请求 URI。scheme、authority、path 和 query string 会同时被替换。这可以用于在代理前面重写主机,或对 URI 进行复杂修改,例如在 path 和 query string 之间移动部分。另请参阅 "http-request set-path" 和 "http-request set-query"。
此操作用于设置变量的内容。变量是内联声明的。
<var-name> 变量的名称以作用域指示符开头。允许的作用域有:"proc" : 变量在整个进程中共享 "sess" : 变量在整个会话中共享 "txn" : 变量在整个事务(请求和响应)中共享 "req" : 变量仅在请求处理期间共享 "res" : 变量仅在响应处理期间共享 该前缀后跟一个名称。分隔符是"."。名称只能包含字符 'a-z', 'A-Z', '0-9' 和 '_'。 <expr> 是一个标准的 HAProxy 表达式,由一个 sample-fetch 后跟一些转换器组成。
http-request set-var(req.my_var) req.fhdr(user-agent),lower
此操作用于触发发送一组 SPOE 消息。为此,必须定义用于发送消息的 SPOE 引擎,以及要发送的 SPOE 组。当然,SPOE 引擎必须引用一个现有的 SPOE 过滤器。如果在 SPOE 过滤器行上未提供引擎名称,则必须使用 SPOE 代理名称。
<engine-name> SPOE 引擎名称。 <group-name> 在引擎配置中指定的 SPOE 组名称。
此操作停止规则评估,并使用一种系统相关的方法使面向客户端的连接突然消失,该方法试图阻止客户端被通知。其效果是客户端仍然看到已建立的连接,而 HAProxy 上没有连接。目的是实现与 "tarpit" 相似的效果,但它根本不使用 HAProxy 运行机器上的任何本地资源。它可以抵抗比 "tarpit" 更高的负载,并减缓更强的攻击者。了解使用此机制的影响非常重要。放置在客户端和 HAProxy 之间的所有有状态设备(防火墙、代理、负载均衡器)也将长时间保持已建立的连接,并可能因此操作而受损。在具有足够权限的现代 Linux 系统上,使用 TCP_REPAIR 套接字选项来阻止 TCP 重置的发送。在其他系统上,套接字的 TTL 减少到 1,以便 TCP 重置不会通过第一个路由器,尽管它仍然会发送到本地网络。除非你完全理解它的工作原理,否则不要使用它。
这会停止规则的评估,并立即阻止请求,在由 "timeout tarpit" 或 "timeout connect"(如果前者未设置)指定的延迟内不响应。在此延迟之后,如果客户端仍然连接,则会返回 HTTP 错误 500(或可选地由 "deny_status" 参数指定的响应码),以便客户端不会怀疑它已被 tarpitted。日志将报告标志 "PT"。tarpit 规则的目标是在攻击期间,当机器人受限于并发请求数量时,减慢其速度。它对非常愚蠢的机器人非常有效,并且与 "deny" 规则相比,可以显着减少防火墙的负载。但是,在面对 "正确" 开发的机器人时,它可能会使情况变得更糟,因为它会迫使 haproxy 和前端防火墙支持数量惊人的并发连接。另请参阅 "silent-drop" 操作。
此操作用于跟踪当前请求的粘性计数器。这些规则不会停止评估,也不会更改默认操作。同一连接可以同时跟踪的计数器数量在构建时设置为 MAX_SESS_STKCTR(在 haproxy -vv 中报告),默认为 3,因此 track-sc 编号在 0 到 (MAX_SESS_STCKTR-1) 之间。第一个执行的 "track-sc0" 规则将指定表的计数器作为第一组进行跟踪。第一个执行的 "track-sc1" 规则将指定表的计数器作为第二组进行跟踪。第一个执行的 "track-sc2" 规则将指定表的计数器作为第三组进行跟踪。建议使用第一组计数器用于 per-frontend 计数器,第二组用于 per-backend 计数器。但这只是一个指南,所有计数器都可以在任何地方使用。
<键> 是强制性的,并且是第 7.3 节中描述的样本表达式规则。它描述了将要分析、提取、组合和用于选择更新哪个表条目计数器的传入请求或连接的元素。 <表> 是一个可选的表,用于替代默认表,默认表是在当前代理中声明的粘性表。然后,所有匹配和更新键的计数器都将在该表中执行,直到会话结束。
一旦执行了“track-sc*”规则,将在表中查找该键,如果未找到,则会为其分配一个条目。然后,在整个会话生命周期内都会保留一个指向该条目的指针,并且该条目的计数器会尽可能频繁地更新,即每当会话的计数器更新时,以及在会话结束时系统性地更新。计数器只为跟踪开始后发生的事件更新。作为一个例外,连接计数器和请求计数器会系统性地更新,以反映有用的信息。如果该条目跟踪并发连接计数器,只要该条目被跟踪,就会计为一个连接,并且在此期间该条目不会过期。跟踪计数器相比仅检查键值还提供了性能优势,因为对于所有使用它的 ACL 检查,都只执行一次表查找。
此操作用于取消设置一个变量。有关 <变量名> 的详细信息,请参见上文。
http-request unset-var(req.my_var)
该指令执行配置的 HTTP 服务以响应请求,并停止规则的评估。HTTP 服务可以选择通过发送任何有效的 HTTP 响应来回复,或者可以立即关闭连接而不发送任何响应。除了原生服务,例如 Prometheus 导出器,还可以用 Lua 编写自己的服务。不再评估更多的“http-request”规则。<service-name> 是必需的。它是要调用的服务。
http-request use-service prometheus-exporter if { path /metrics }
这会延迟请求的处理,直到 SSL 握手完成。这主要用于延迟处理早期数据,直到我们确定它们是有效的。
第 7 层响应的访问控制
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
http-response 语句定义了一组适用于第 7 层处理的规则。当在前端、listen 或后端部分遇到规则时,它们将按声明顺序进行评估。任何规则都可以选择性地后跟一个基于 ACL 的条件,在这种情况下,只有当条件为真时,它才会被评估。由于这些规则适用于响应,因此后端规则首先应用,然后是前端的规则。第一个关键字是规则的操作。支持的操作如下所述。每个实例的 http-response 语句数量没有限制。
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
这用于将新条目添加到 ACL 中。ACL 必须从文件中加载(即使是空的虚拟文件)。要更新的 ACL 的文件名在括号中传递。它接受一个参数:<key fmt>,遵循 log-format 规则,用于收集新条目的内容。它在插入之前执行查找,以避免重复(或更多)值。此查找通过线性搜索完成,对于大型列表可能会很昂贵!它等同于 stats socket 的 "add acl" 命令,但可以由 HTTP 响应触发。
此操作附加一个 HTTP 头部字段,其名称由 <name> 指定,其值由遵循日志格式规则的 <fmt> 定义(参见 第 8.2.4 节中的自定义日志格式)。例如,这可用于向客户端发送 cookie,或传递一些内部信息。此规则不是最终的,因此可以添加其他类似的规则。请注意,头部添加是立即执行的,因此一个规则可能会重用前一个规则产生的头部。
此操作停止规则的评估,并让响应通过检查。当前部分不再评估更多的“http-response”规则。请参阅关于缓存设置的第 6.2 节。
此操作从响应缓冲区捕获示例表达式 <sample>,并将其转换为字符串。生成的字符串存储在下一个请求的 "capture" 插槽中,因此它可能会出现在一些捕获的 HTTP 标头旁边。然后它将自动出现在日志中,并且可以使用样本获取规则提取它,以将其填充到标头或任何其他内容中。请查看 第 7.3 节(获取样本)和 "capture response header" 以获取更多信息。关键字 "id" 是用于存储字符串的捕获插槽的 id。捕获插槽必须在关联的前端中定义。这对于在后端中运行捕获非常有用。插槽 id 可以通过先前的指令 "http-response capture" 或使用 "declare capture" 关键字声明。在后端中使用此操作时,请仔细检查相关前端是否具有所需的捕获插槽,否则此规则将在运行时被忽略。由于 HAProxy 能够在运行时动态解析后端名称,因此在配置解析时无法检测到此问题。
这用于从 ACL 中删除条目。ACL 必须从文件中加载(即使是空的虚拟文件)。要更新的 ACL 的文件名在括号中传递。它接受一个参数:<key fmt>,遵循 log-format 规则,用于收集要删除的条目的内容。它等同于 stats socket 的 "del acl" 命令,但可以由 HTTP 响应触发。
这会删除指定名称为 <name> 的所有 HTTP 头字段。
这用于从 MAP 中删除条目。MAP 必须从文件中加载(即使是空的虚拟文件)。要更新的 MAP 的文件名在括号中传递。它接受一个参数:<key fmt>,遵循 log-format 规则,用于收集要删除的条目的内容。它接受一个参数:"文件名" 它等同于 stats socket 的 "del map" 命令,但可以由 HTTP 响应触发。
此操作停止规则评估并立即拒绝响应并发出 HTTP 502 错误。不再评估进一步的 "http-response" 规则。此操作基于重定向规则执行 HTTP 重定向。它支持与“http-request redirect”规则类似的格式字符串,但例外是响应上只可能进行“location”类型的重定向。有关规则的语法,请参见“redirect”关键字。当在响应期间应用重定向规则时,与服务器的连接将被关闭,以便无法将任何数据从服务器转发到客户端。
此操作的工作方式类似于“http-request replace-header”,但它作用于服务器的响应而不是客户端的请求。
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。
此操作类似于 "http-response replace-value",但它作用于服务器的响应而不是客户端的请求。
http-response replace-value Cache-control ^public$ private # 应用于: Cache-Control: max-age=3600, public # 输出: Cache-Control: max-age=3600, private
此操作根据 <sc-id> 指定的粘性计数器递增 GPC0 或 GPC1 计数器。如果发生错误,此操作将静默失败,并继续评估操作。
此操作根据由 <sc-id> 指定的粘性计数器和 <int>/<expr> 的值来设置 32 位无符号 GPT0 标签。预期结果为布尔值。如果发生错误,此操作将静默失败,并继续评估操作。
此操作用于触发发送一组 SPOE 消息。为此,必须定义用于发送消息的 SPOE 引擎,以及要发送的 SPOE 组。当然,SPOE 引擎必须引用一个现有的 SPOE 过滤器。如果在 SPOE 过滤器行上未提供引擎名称,则必须使用 SPOE 代理名称。
<engine-name> SPOE 引擎名称。 <group-name> 在引擎配置中指定的 SPOE 组名称。
这与 "add-header" 的作用相同,只是如果头名称已存在,会先将其删除。当向服务器传递安全信息,且该头不能被外部用户操纵时,这很有用。
当满足特定条件时,这用于更改当前请求的日志级别。有效级别是 8 个 syslog 级别(请参阅 "log" 关键字)加上特殊级别 "silent",它禁用此请求的日志记录。此规则不是最终规则,因此最后一个匹配的规则获胜。此规则可用于禁用来自其他设备的健康检查。这用于将新条目添加到 MAP 中。MAP 必须从文件中加载(即使是空的虚拟文件)。要更新的 MAP 的文件名在括号中传递。它接受 2 个参数:<key fmt>,遵循 log-format 规则,用于收集 MAP 键,以及 <value fmt>,遵循 log-format 规则,用于收集新条目的内容。它在插入之前执行查找,以避免重复(或更多)值。此查找通过线性搜索完成,对于大型列表可能会很昂贵!它等同于 stats socket 的 "set map" 命令,但可以由 HTTP 响应触发。
在支持的平台上,此操作将 Netfilter MARK 设置为传递给 <mark> 的值,该值将发送到客户端的所有数据包上。该值是一个无符号 32 位值,netfilter 和路由表都可以匹配。它可以表示为十进制或十六进制格式(以“0x”为前缀)。这对于强制某些数据包采用不同的路由(例如,更便宜的批量下载网络路径)非常有用。这适用于 Linux 内核 2.6.32 及更高版本,并且需要管理员权限。
这会设置正在处理的当前请求的 "nice" 因子。它只对同时处理的其他请求有效。默认值为 0,除非在 "bind" 行上的 "nice" 设置进行了更改。可接受的范围是 -1024..1024。值越高,请求的优先级越低。较低的值会使请求比其他请求更重要。这有助于提高某些请求的速度,或降低不重要请求的优先级。未经事先试验而使用此设置可能会导致一些严重的减速。
这将用 <status> 替换响应状态码,该值必须是 100 到 999 之间的整数。可以选择性地提供由 <str> 定义的自定义原因文本,否则将使用指定状态码的默认原因作为后备。
# 返回“431 Request Header Fields Too Large” http-response set-status 431 # 返回“503 Slow Down”,自定义原因 http-response set-status 503 reason "Slow Down".
此操作用于在支持此功能的平台上,将发送给客户端的数据包的 TOS 或 DSCP 字段值设置为 <tos> 中传递的值。此值代表 IP TOS 字段的全部 8 位,可以用十进制或十六进制格式(以“0x”为前缀)表示。请注意,DSCP 或 TOS 中仅使用较高的 6 位,而较低的两位始终为 0。这可用于根据请求中的某些信息调整边界路由器上的一些路由行为。有关更多信息,请参阅 RFC 2474, 2597, 3260 和 4594。
此操作用于设置变量的内容。变量是内联声明的。
<var-name> 变量名以其作用域的指示开头。允许的作用域有: “proc”:变量与整个进程共享 “sess”:变量与整个会话共享 “txn”:变量与事务(请求和响应)共享 “req”:变量仅在请求处理期间共享 “res”:变量仅在响应处理期间共享 此前缀后跟一个名称。分隔符是“.”。名称只能包含字符“a-z”、“A-Z”、“0-9”、“.”和“_”。 <expr> 是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成。
http-response set-var(sess.last_redir) res.hdr(location)
此操作停止规则评估,并使用一种系统相关的方法使面向客户端的连接突然消失,该方法试图阻止客户端被通知。其效果是客户端仍然看到已建立的连接,而 HAProxy 上没有连接。目的是实现与 "tarpit" 相似的效果,但它根本不使用 HAProxy 运行机器上的任何本地资源。它可以抵抗比 "tarpit" 更高的负载,并减缓更强的攻击者。了解使用此机制的影响非常重要。放置在客户端和 HAProxy 之间的所有有状态设备(防火墙、代理、负载均衡器)也将长时间保持已建立的连接,并可能因此操作而受损。在具有足够权限的现代 Linux 系统上,使用 TCP_REPAIR 套接字选项来阻止 TCP 重置的发送。在其他系统上,套接字的 TTL 减少到 1,以便 TCP 重置不会通过第一个路由器,尽管它仍然会发送到本地网络。除非你完全理解它的工作原理,否则不要使用它。
此操作用于跟踪当前响应的粘性计数器。请参阅 "http-request track-sc" 以获取完整描述。与 "http-request track-sc" 的唯一区别是 <key> 样本表达式只能使用响应中的样本(例如,res.*、status 等)以及第 6 层以下的样本(例如,SSL 相关样本,请参阅 第 7.3.4 节)。如果样本不支持,haproxy 在解析配置时将失败并发出警告。
这用于取消设置变量。有关 <var-name> 的详细信息,请参阅 "http-response set-var"。
http-response unset-var(sess.last_redir)
声明空闲的 HTTP 连接如何在请求之间共享
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
默认情况下,haproxy 和后端服务器之间建立的被认为可以安全重用的连接会被移回服务器的空闲连接池,以便任何其他请求都可以使用它。这是下面的 "safe" 策略。参数指示所需的连接重用策略:- "never":空闲连接永远不会在会话之间共享。可以强制使用此模式来取消从 defaults 部分继承的不同策略或用于故障排除。例如,如果一个旧的错误应用程序认为同一连接上的多个请求来自同一客户端,并且无法修复该应用程序,则可能需要在单个后端中禁用连接共享。此类应用程序的一个示例是使用隧道模式下的 cookie 插入且不检查第一个请求之后的任何请求的旧 haproxy。- "safe":这是默认且推荐的策略。会话的第一个请求始终通过其自己的连接发送,只有后续请求才可能通过其他现有连接分派。这可确保在服务器在发送请求时关闭连接的情况下,浏览器可以决定静默重试。由于它与常规 keep-alive 完全等效,因此不应产生副作用。- "aggressive":此模式可能在 webservices 环境中有用,其中并非所有服务器都已知,并且希望通过现有连接传递大多数第一个请求。在这种情况下,第一个请求仅通过至少重用过一次的现有连接传递,证明服务器正确支持连接重用。它应该仅在确定客户端可以偶尔重试失败的请求并且激进连接重用的好处明显大于罕见连接失败的缺点时使用。- "always":此模式仅在已知到服务器的路径在释放后永远不会很快中断现有连接时才推荐使用。它允许会话的第一个请求发送到现有连接。当后端是缓存场时,这可以提供比 "safe" 策略显着的性能提升,因为此类组件倾向于显示一致的行为,并且将受益于连接共享。建议在此模式下保持 "http-keep-alive" 超时较低,以便没有死连接保持可用。在大多数情况下,这将导致与 "aggressive" 相同的性能提升,但风险更大。它应该仅在改善情况优于 "aggressive" 时使用。启用 http 连接共享时,会非常小心地遵守连接属性和兼容性。具体来说:- 使用 "usesrc" 后跟客户端相关值 ("client", "clientip", "hdr_ip") 建立的连接被标记为私有且永不共享;- 发送到带有 TLS SNI 扩展的服务器的连接被标记为私有且永不共享;- 具有某些错误身份验证方案(依赖于连接)的连接(如 NTLM)被检测到,标记为私有且永不共享;涉及连接池,可使用 "pool-max-conn" 进行配置。注意:连接重用提高了 "server maxconn" 设置的准确性,因为当空闲连接仍然可用时,几乎不会建立新连接。对于 "always" 策略尤其如此。
将服务器名称添加到请求中。使用由 <header> 给出的头字符串。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<header> 用于发送服务器名称的头字符串。
"http-send-name-header" 语句导致在请求即将通过网络发送时,将名为 <header> 的标头字段设置为目标服务器的名称。此标头的任何现有出现都会被删除。在重试和重新分派时,标头字段会更新以始终反映正在尝试连接的服务器。鉴于此标头在连接设置的后期才被修改,它可能对已修改的标头产生意外影响。例如,将其与传输级标头(如 connection、content-length、transfer-encoding 等)一起使用可能会导致向服务器发送无效请求。此外,据报道,此指令目前被用作覆盖传出请求中的 Host 标头字段的一种方式;虽然这种技巧作为该功能的副作用已经有一段时间了,但它并未得到官方支持,并且在未来版本中可能会因为该功能引起的技术困难而不再有效。相反,一个长期解决方案是修复需要此技巧的应用程序,以便它绑定到正确的主机名。
为代理设置一个持久 ID。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
为代理设置一个持久 ID。此 ID 必须是唯一的正数。如果未设置,将自动分配一个未使用的 ID。第一个分配的值将是 1。此 ID 当前仅在统计信息中返回。
声明一个忽略持久性的条件
可用于节
| 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 的无缝重载
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
此指令将 HAProxy 指向一个文件,其中保存了先前运行进程的服务器状态。这样,在启动时,在处理流量之前,新进程可以将旧状态应用于服务器,就像没有发生重新加载一样。“load-server-state-from-file”指令的目的是告诉 haproxy 使用哪个文件。目前,只有两个参数,它们可以防止加载状态或从包含所有后端和服务器的文件加载状态。状态文件可以通过在 stats socket 上运行“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
启用事件和流量的每个实例日志记录。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
前缀:当必须清除记录器列表时,应使用 no。例如,如果您不想从默认记录器列表继承。此前缀不允许有参数。
当实例的日志记录参数与全局参数相同时,应使用 global。这是最常见的用法。"global" 将 <address>、<facility> 和 <level> 替换为 "global" 部分中找到的日志条目。每个实例只能使用一个 "log global" 语句,并且此形式不接受其他参数。<address> 指示将日志发送到何处。它采用与 "global" 部分的日志相同的格式,可以是以下之一:- IPv4 地址,可选地后跟冒号 (':') 和 UDP 端口。如果未指定端口,则默认使用 514(标准 syslog 端口)。- IPv6 地址,后跟冒号 (':') 和可选的 UDP 端口。如果未指定端口,则默认使用 514(标准 syslog 端口)。- UNIX 域套接字的 filesystem 路径,记住 chroot 的注意事项(确保路径在 chroot 内部可访问)和 uid/gid(确保路径可适当写入)。- 形式为 "fd@<number>" 的文件描述符编号,它可能指向管道、终端或套接字。在这种情况下,使用非缓冲日志,并且每个日志执行一个 writev() 调用。这有点昂贵,但对于大多数工作负载来说是可以接受的。以这种方式发送的消息不会被截断,但可能会被丢弃,在这种情况下,DroppedLogs 计数器将递增。writev() 调用是原子的,即使对于消息大小高达 PIPE_BUF 的管道也是如此,POSIX 建议至少为 512,在大多数现代操作系统上为 4096 字节。任何较大的消息都可能与来自其他进程的消息交错。对于调试目的,文件描述符也可以指向文件,但这样做会显着减慢 haproxy 的速度,因为非阻塞调用将被忽略。此外,无法在不重新启动进程的情况下清除或旋转此文件。请注意,配置的 syslog 格式会保留,因此输出适用于 TCP syslog 服务器。另请参阅下面的 "short" 和 "raw" 格式。- "stdout" / "stderr",它们分别是 "fd@1" 和 "fd@2" 的别名,如上所述。- 形式为 "ring@<name>" 的环形缓冲区,它对应于可通过 CLI 使用 "show events" 命令访问的内存中环形缓冲区,该命令还将列出现有环形缓冲区及其大小。此类缓冲区在重新加载或重新启动时会丢失,但作为补充使用时,这可以通过立即提供日志来帮助进行故障排除。你可能希望在 address 参数中引用一些环境变量,请参阅 第 2.3 节 有关环境变量的信息。<length> 是一个可选的最大行长度。大于此值的日志行在发送前将被截断。原因是 syslog 服务器对日志行长度的处理方式不同。所有服务器都支持默认值 1024,但有些服务器只是丢弃较长的行,而另一些服务器则会记录它们。如果服务器支持长行,则在此处设置此值以避免截断长行可能是有意义的。类似地,如果服务器丢弃长行,最好在发送前截断它们。接受的值为 80 到 65535(含)。默认值 1024 通常适用于所有标准用法。某些特定的长捕获或 JSON 格式的日志可能需要更大的值。<ranges> 逗号分隔的范围列表,用于识别要采样的日志。这用于平衡发送到日志服务器的日志负载。范围的限制不能为 null。它们从 1 开始编号。样本的大小或周期(以日志数量计)必须使用 <sample_size> 参数设置。<sample_size> 样本的大小(以日志数量计),用于平衡日志记录负载时考虑。它用于平衡发送到 syslog 服务器的日志负载。此大小必须大于或等于范围高限制的最大值。(另请参阅 <ranges> 参数)。<format> 是生成 syslog 消息时使用的日志格式。它可以是以下之一:rfc3164 RFC3164 syslog 消息格式。这是默认值。(https://tools.ietf.org/html/rfc3164)rfc5424 RFC5424 syslog 消息格式。(https://tools.ietf.org/html/rfc5424)short 仅包含尖括号之间级别(例如 '<3>')的消息,后跟文本。省略 PID、日期、时间、进程名称和系统名称。这设计用于本地日志服务器。此格式与 systemd logger 消耗的格式兼容。raw 仅包含文本的消息。省略级别、PID、日期、时间、进程名称和系统名称。这设计用于容器中或开发期间,其中严重性仅取决于使用的文件描述符 (stdout/stderr)。<facility> 必须是 24 个标准 syslog facility 之一:kern user mail daemon auth syslog lpr news uucp cron auth2 ftp ntp audit alert cron2 local0 local1 local2 local3 local4 local5 local6 local7 请注意,对于 "short" 和 "raw" 格式,facility 会被忽略,但仍需要作为位置字段。建议在这种情况下使用 "daemon",以明确它仅用于本地。<level> 是可选的,可以指定以过滤传出消息。默认情况下,发送所有消息。如果指定了级别,则仅发送严重性至少与此级别相同的消息。可以指定一个可选的最低级别。如果设置了它,则发出的严重性高于此级别的日志将被限制为此级别。这用于避免在某些默认 syslog 配置上在所有终端上发送 "emerg" 消息。已知有八个级别:emerg alert crit err warning notice info debug
重要的是要记住,是由前端决定要从连接中记录什么,并且在内容切换的情况下,来自后端的日志条目将被忽略。连接以 "info" 级别记录。然而,后端日志声明定义了服务器状态更改将如何以及在何处被记录。级别 "notice" 将用于指示服务器启动,"warning" 将用于终止信号和最终的服务终止,而 "alert" 将用于服务器宕机时。 注意:根据 RFC3164,消息在发出前会被截断为 1024 字节。
log global log stdout format short daemon # 发送日志到 systemd log stdout format raw daemon # 发送所有内容到 stdout log stderr format raw daemon notice # 将重要事件发送到 stderr log 127.0.0.1:514 local0 notice # 只发送重要事件 log 127.0.0.1:514 local0 notice notice # 相同,但限制输出级别 log "${LOCAL_SYSLOG}:514" local0 notice # 发送到本地服务器
指定用于流量日志的日志格式字符串
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
此指令指定了将用于所有通过此行所在前端的流量产生的日志的日志格式字符串。如果在 defaults 部分使用此指令,所有后续的前端都将使用相同的日志格式。请参阅深入介绍日志格式字符串的第 8.2.4 节。"log-format" 指令会覆盖之前的 "option tcplog"、"log-format" 和 "option httplog" 指令。
指定 RFC5424 结构化数据日志格式字符串
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
此指令指定了 RFC5424 结构化数据日志格式字符串,该字符串将用于所有通过此行所在前端的流量产生的日志。如果在 defaults 部分使用此指令,所有后续的前端都将使用相同的日志格式。请参阅深入介绍日志格式字符串的第 8.2.4 节。有关 RFC5424 结构化数据部分的更多信息,请参阅 https://tools.ietf.org/html/rfc5424#section-6.3。 注意:此日志格式字符串仅用于将日志格式设置为 "rfc5424" 的记录器。
log-format-sd [exampleSDID@1234\ bytes=\"%B\"\ status=\"%ST\"]
指定用于所有传出日志的日志标签
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
将 syslog 标头中的 tag 字段设置为此字符串。它默认为全局部分中设置的 log-tag,否则为从命令行启动的程序名称,通常为 "haproxy"。有时区分在同一主机上运行的多个进程,或区分在同一进程中运行的客户实例可能很有用。在后端中,有关服务器 up/down 的日志将使用此标签。作为提示,将与托管客户相关的 log-tag 设置在 defaults 部分中,然后将该客户的所有前端和后端放在其中,然后在新 defaults 部分中启动另一个客户可能会很方便。另请参阅全局 "log-tag" 指令。设置用于维护 keep-alive 连接的最大服务器队列大小
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
HTTP keep-alive 尝试尽可能重用同一个服务器连接,但有时它可能适得其反,例如如果一个服务器有很多连接而其他服务器处于空闲状态。对于静态服务器尤其如此。此设置的目的是设置排队连接数的阈值,超过该阈值时 haproxy 会停止尝试重用同一服务器并倾向于寻找另一个服务器。默认值 -1 表示没有限制。值为零表示 keep-alive 请求永远不会排队。对于可以通过低延迟访问且对中断 keep-alive 不敏感的非常接近的服务器,建议使用低值(例如,本地静态服务器可以使用 10 或更小的值)。对于遭受高延迟的远程服务器,可能需要更高的值来弥补延迟和/或选择不同服务器的成本。请注意,这对连续发送到同一服务器的响应没有影响,这些响应在 401 响应之后维护。即使它们必须排队,它们仍将发送到同一服务器。
设置对于给定的客户端会话,我们可以保持空闲的最大传出连接数。默认值为 5(它精确等于构建时定义的 MAX_SRV_LIST)。
固定前端的最大并发连接数
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<conns> 是前端将接受服务的最大并发连接数。超出的连接将由系统在套接字的侦听队列中排队,并在一个连接关闭后得到服务。
如果系统支持,在大站点上将此限制提高得很高可能很有用,以便 haproxy 管理连接队列,而不是让客户端留下未回答的连接尝试。此值不应超过全局 maxconn。此外,请记住,一个连接包含两个 tune.bufsize(默认 16kB)缓冲区,以及一些其他数据,导致每个已建立连接消耗约 33 kB 的 RAM。这意味着配置了 1GB RAM 的中等系统如果正确调整,可以承受大约 20000-25000 个并发连接。此外,当 <conns> 设置为较大值时,服务器可能没有足够的大小来接受此类负载,因此通常明智地为它们分配一些合理的连接限制。当此值设置为零(默认值)时,使用全局 "maxconn" 值。
设置实例的运行模式或协议
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
tcp 实例将在纯 TCP 模式下工作。客户端和服务器之间将建立全双工连接,并且不执行第 7 层检查。这是默认模式。它应用于 SSL、SSH、SMTP 等。http 实例将在 HTTP 模式下工作。在连接到任何服务器之前,将深入分析客户端请求。任何不符合 RFC 的请求都将被拒绝。第 7 层过滤、处理和切换将成为可能。这是 HAProxy 最有价值的模式。health 实例将在 "health" 模式下工作。它将只对传入连接回复 "OK" 并关闭连接。或者,如果设置了 "httpchk" 选项,将发送 "HTTP/1.0 200 OK"。在任何一种情况下都不会记录任何内容。此模式用于回复外部组件的健康检查。此模式已弃用,不应再使用,因为通过将 TCP 或 HTTP 模式与 "monitor" 关键字结合使用可以实现相同甚至更好的效果。
在进行内容切换时,前端和后端必须处于相同的模式(通常是 HTTP),否则配置将被拒绝。
defaults http_instances mode http
添加一个条件以向监控 HTTP 请求报告失败。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 否![]() |
if <cond> 如果条件满足,监控请求将失败,否则将成功。该条件应描述一个组合测试,如果所有条件都满足,则必须导致失败,例如后端及其备份中的服务器数量都很少。 unless <cond> 只有当条件满足时,监控请求才会成功,否则将失败。这样的条件可以基于对后端列表中最小活动服务器数量的存在的测试。
此语句添加了一个条件,该条件可以强制监视请求的响应报告失败。默认情况下,当外部组件查询专用于监视的 URI 时,返回 200 响应。当满足上述条件之一时,haproxy 将返回 503 而不是 200。这对于向外部组件报告站点故障非常有用,外部组件可能基于 haproxy 报告的可用性在多个站点之间进行路由广告。在这种情况下,将依赖涉及 "nbsrv" 标准的 ACL。请注意,"monitor fail" 仅在 HTTP 模式下有效。两个状态消息都可以根据需要使用 "errorfile" 或 "errorloc" 进行调整。
frontend www mode http acl site_dead nbsrv(dynamic) lt 2 acl site_dead nbsrv(static) lt 2 monitor-uri /site_alive monitor fail if site_dead
声明一个仅限于监控请求的源网络
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<source> 是源 IPv4 地址或网络,该网络只能对任何请求获取监控响应。它可以是 IPv4 地址、主机名或后跟斜杠('/')和掩码的地址。
在 TCP 模式下,来自匹配 <source> 的任何连接将导致连接立即关闭,不记录任何内容。这允许另一个设备探测端口并验证它是否仍在侦听,而不会将连接转发到远程服务器。在 HTTP 模式下,来自匹配 <source> 的连接将被接受,将发送以下响应而不等待请求,然后连接将关闭:"HTTP/1.0 200 OK"。这通常足以让任何前端 HTTP 探针检测到服务已启动并正在运行,而无需将请求转发到后端服务器。请注意,此响应以原始格式发送,没有任何转换。这很重要,因为它意味着它不会在 SSL 侦听器上进行 SSL 加密。监视请求处理得非常早,仅在 tcp-request connection ACL 之后,后者是唯一能够阻止它们的 ACL。这些连接生命周期短,从不等待来自客户端的任何数据。它们无法记录,这是预期的目的。它们仅用于向更高层组件报告 HAProxy 的健康状况,仅此而已。请注意,"monitor fail" 规则不适用于被 "monitor-net" 拦截的连接。最后,请注意,一个前端中只能指定一个 "monitor-net" 语句。如果找到多个,则只考虑最后一个。
# 地址 .252 和 .253 只是在探测我们。 frontend www monitor-net 192.168.0.252/31
拦截外部组件监控请求使用的 URI
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<uri> 是我们想要拦截以返回 HAProxy 健康状态而不是转发请求的确切 URI。
当在前端收到引用 <uri> 的 HTTP 请求时,HAProxy 将不会转发或记录它,而是返回 "HTTP/1.0 200 OK" 或 "HTTP/1.0 503 Service unavailable",具体取决于使用 "monitor fail" 定义的故障条件。这通常足以让任何前端 HTTP 探针检测到服务已启动并正在运行,而无需将请求转发到后端服务器。请注意,HTTP 方法、版本和所有标头都会被忽略,但请求必须至少在 HTTP 级别上有效。此关键字只能与 HTTP 模式前端一起使用。监视请求处理得非常早,仅在请求解析之后,甚至在任何 "http-request" 之前。之前应用的唯一规则集是 tcp-request 规则集。它们也无法记录,这是预期的目的。它们仅用于向更高层组件报告 HAProxy 的健康状况,仅此而已。但是,可以使用 "monitor fail" 和 ACL 添加任意数量的条件,以便结果可以根据可以想象的任何检查进行调整(最常见的是后端中可用服务器的数量)。注意:如果 <uri> 以斜杠 ('/') 开头,则匹配是针对请求的路径而不是请求的 uri 执行的。这是让 HTTP/2 请求匹配 monitor-uri 的一种变通方法。实际上,在 HTTP/2 中,鼓励客户端仅发送绝对 URI。
# 使用 /haproxy_test 来报告 haproxy 的状态 frontend www mode http monitor-uri /haproxy_test
启用或禁用对队列中待处理的已中止请求的提前丢弃。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
在非常高的负载下,服务器需要一些时间来响应。每个实例的连接队列将膨胀,响应时间将随着队列大小乘以每个会话的平均响应时间而增加。当客户端等待超过几秒钟时,他们通常会点击浏览器上的 "STOP" 按钮,在队列中留下一个无用的请求,并减慢其他用户的速度,以及服务器的速度,因为请求最终会被服务,然后在交付响应时遇到的第一个错误处中止。由于无法区分完全 STOP 和客户端上的简单输出关闭,因此 HTTP 代理应保守地考虑客户端可能仅在等待响应时关闭了其输出通道。然而,当大量用户做同样的事情时,这会带来拥塞风险,并且如今完全没用,因为可能根本没有客户端会在等待响应时关闭会话。一些 HTTP 代理支持这种行为(Squid、Apache、HAProxy),而其他代理不支持(TUX、大多数基于硬件的负载均衡器)。因此,关闭的输入通道代表用户点击 "STOP" 按钮的概率接近 100%,并且成为中断罕见但有效流量的单个组件的风险极低,这增加了能够在仍未提供服务且不污染服务器时尽早中止会话的诱惑。在 HAProxy 中,用户可以使用选项 "abortonclose" 选择所需的行为。默认情况下(没有此选项),行为符合 HTTP 规范,中止的请求将得到服务。但是当指定此选项时,如果传入通道关闭,会话将在仍有可能时中止,无论是在队列中等待连接插槽,还是在连接建立期间(如果服务器尚未确认连接请求)。这显着减少了队列大小以及当用户倾向于点击 STOP 时饱和服务器上的负载,这反过来又减少了其他用户的响应时间。如果此选项已在 "defaults" 部分中启用,则可以通过在其前面添加 "no" 关键字在特定实例中将其禁用。
启用或禁用放宽 HTTP 请求解析
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
默认情况下,HAProxy 在消息解析方面符合 RFC7230。这意味着标头名称中的无效字符是不允许的,并且会导致向客户端返回错误。这是所需的行为,因为此类禁用字符本质上用于构建利用服务器弱点和绕过安全过滤的攻击。有时,有缺陷的浏览器或服务器会出于某种原因(配置、实现)发出无效的标头名称,并且问题不会立即得到修复。在这种情况下,可以通过指定此选项来放宽 HAProxy 的标头名称解析器以接受任何字符,即使这没有意义。同样,RFC3986 明确定义了允许出现在 URI 中的字符列表,并且字符 0-31、32(空格)、34('"')、60('<')、62('>')、92('\')、94('^')、96('`')、123('{')、124('|')、125('}')、127(删除)以及任何高于这些的字符都是完全不允许的。HAProxy 总是阻止其中的一部分 (0..32, 127)。除非启用此选项,否则默认情况下会阻止其余部分。此选项还放宽了对 HTTP 版本的测试,它允许 HTTP/0.9 请求通过(未指定版本)以及主要版本和次要版本的多个数字。此选项不应默认启用,因为它会隐藏应用程序错误并打开安全漏洞。它应仅在问题得到确认后部署。启用此选项后,请求中仍将接受错误的标头名称,但将捕获完整的请求,以便以后可以使用 UNIX stats socket 上的 "show errors" 请求进行分析。同样,将记录 URI 部分包含无效字符的请求。这样做也有助于确认问题已解决。如果此选项已在 "defaults" 部分中启用,则可以通过在其前面添加 "no" 关键字在特定实例中将其禁用。启用或禁用放宽 HTTP 响应解析
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
默认情况下,HAProxy 在消息解析方面符合 RFC7230。这意味着标头名称中的无效字符是不允许的,并且会导致向客户端返回错误。这是所需的行为,因为此类禁用字符本质上用于构建利用服务器弱点和绕过安全过滤的攻击。有时,有缺陷的浏览器或服务器会出于某种原因(配置、实现)发出无效的标头名称,并且问题不会立即得到修复。在这种情况下,可以通过指定此选项来放宽 HAProxy 的标头名称解析器以接受任何字符,即使这没有意义。此选项还放宽了对 HTTP 版本格式的测试,它允许主要版本和次要版本的多个数字。此选项不应默认启用,因为它会隐藏应用程序错误并打开安全漏洞。它应仅在问题得到确认后部署。启用此选项后,响应中仍将接受错误的标头名称,但将捕获完整的响应,以便以后可以使用 UNIX stats socket 上的 "show errors" 请求进行分析。这样做也有助于确认问题已解决。如果此选项已在 "defaults" 部分中启用,则可以通过在其前面添加 "no" 关键字在特定实例中将其禁用。
一次使用所有备用服务器,或仅使用第一个
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
默认情况下,当所有正常服务器都宕机时,第一个可用的备用服务器将获得所有流量。有时,可能希望一次使用多个备用服务器,因为一个可能不够用。当启用 "option allbackups" 时,当所有正常服务器都不可用时,将在所有备用服务器之间执行负载均衡。将使用相同的负载均衡算法,并遵守服务器的权重。因此,备用服务器之间将不再有任何优先级顺序。此选项主要用于专用于在应用程序完全离线时返回“抱歉”页面的静态服务器群。 如果此选项已在 "defaults" 部分中启用,可以通过在其前面添加 "no" 关键字来在特定实例中禁用它。
分析所有服务器响应并阻止带有可缓存 cookie 的响应
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
有些高级框架会在任何地方设置应用程序 cookie,并且不总是给开发人员足够的控制权来管理响应应该如何缓存。当可缓存对象上返回会话 cookie 时,在遍历相同缓存的用户之间发生会话交叉或窃取的风险很高。在某些情况下,阻止响应比让一些敏感的会话信息在野外传播要好。选项 "checkcache" 能够对所有服务器响应进行深度检查,以确保在可缓存性方面严格遵守 HTTP 规范。它仔细检查服务器响应中的 "Cache-control"、"Pragma" 和 "Set-cookie" 标头,以检查是否存在在客户端代理上缓存 cookie 的风险。启用此选项后,可以交付给客户端的响应只有: - 所有没有 "Set-Cookie" 标头的响应; - 所有返回码不是 200、203、204、206、300、301、404、405、410、414、501 的响应,前提是服务器没有设置 "Cache-control: public" 标头字段; - 所有使用 GET、HEAD、OPTIONS、TRACE 以外的方法发出的请求所产生的响应,前提是服务器没有设置 'Cache-Control: public' 标头字段; - 带有 'Pragma: no-cache' 标头的响应 - 带有 'Cache-control: private' 标头的响应 - 带有 'Cache-control: no-store' 标头的响应 - 带有 'Cache-control: max-age=0' 标头的响应 - 带有 'Cache-control: s-maxage=0' 标头的响应 - 带有 'Cache-control: no-cache' 标头的响应 - 带有 'Cache-control: no-cache="set-cookie"' 标头的响应 - 带有 'Cache-control: no-cache="set-cookie,' 标头的响应(允许 set-cookie 后面有其他字段) 如果响应不符合这些要求,则它将被阻止,就像它来自 "http-response deny" 规则一样,并返回 "HTTP 502 bad gateway"。会话状态显示 "PH--",这意味着代理在标头处理期间阻止了响应。此外,将在日志中发送警报,以便管理员知道需要修复某些问题。由于对应用程序有重大影响,在投入生产之前,应在启用此选项的情况下对应用程序进行深入测试。在测试期间始终激活它也是一种很好的做法,即使在生产中不使用它,因为它会报告潜在危险的应用程序行为。如果此选项已在 "defaults" 部分中启用,则可以通过在其前面添加 "no" 关键字来在特定实例中禁用它。
启用或禁用在客户端发送 TCP keepalive 数据包
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
当客户端和服务器之间有防火墙或任何会话感知组件时,并且当协议涉及具有较长空闲期的非常长的会话(例如远程桌面)时,存在中间组件决定使空闲时间过长的会话过期的风险。启用套接字级 TCP keep-alives 使系统定期向连接的另一端发送数据包,使其保持活动状态。keep-alive 探测之间的延迟仅由系统控制,并且取决于操作系统及其调整参数。重要的是要理解 keep-alive 数据包既不在应用程序级别发出也不在应用程序级别接收。只有网络堆栈才能看到它们。因此,即使代理的一侧已经使用 keep-alives 来保持其连接活动,这些 keep-alive 数据包也不会转发到代理的另一侧。请注意,这与 HTTP keep-alive 无关。使用选项 "clitcpka" 可在连接的客户端启用 TCP keep-alive 探测的发送,这在 HAProxy 和客户端之间注意到会话过期时会有所帮助。如果此选项已在 "defaults" 部分中启用,则可以通过在其前面添加 "no" 关键字来在特定实例中禁用它。
启用连续流量统计更新
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
默认情况下,用于统计计算的计数器仅在会话完成时递增。处理小型对象时效果很好,但处理大型对象(例如大型图像或存档)或 A/V 流时,从 haproxy 计数器生成的图看起来会像刺猬。启用此选项后,计数器会频繁地在会话期间递增,通常每 5 秒一次,这足以生成清晰的图表。重新计数直接触及热路径,因此默认情况下不启用它,因为它可能会导致会话计数非常大的情况下大量唤醒并导致性能略有下降。
启用或禁用对正常、成功连接的日志记录
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
有些大型网站每秒处理数千个连接,日志记录对它们来说是一个主要的痛点。其中一些甚至被迫关闭日志,无法调试生产问题。设置此选项可确保正常的连接,即那些没有经历错误、超时、重试或重新分派的连接,将不会被记录。这为异常情况留下了磁盘空间。在 HTTP 模式下,会检查响应状态码,返回码为 5xx 的仍将被记录。 强烈建议不要使用此选项,因为大多数情况下,复杂问题的关键在于正常的日志中,而这些日志在这里不会被记录。如果您需要分离日志,请改用 "log-separate-errors" 选项。
启用或禁用对空连接的日志记录
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
在某些环境中,有些组件会定期连接到各种系统,以确保它们仍然存活。这可能是来自另一个负载均衡器以及监控系统的情况。默认情况下,即使是简单的端口探测或扫描也会产生一条日志。如果这些连接过多地污染了日志,可以启用选项“dontlognull”,以指示没有传输任何数据的连接将不会被记录,这通常对应于那些探测。请注意,错误仍将返回给客户端并在统计信息中计算。如果这不是期望的,可以使用 http-ignore-probes 选项。通常建议不要在不受控制的环境(例如互联网)中使用此选项,否则扫描和其他恶意活动将不会被记录。如果此选项已在“defaults”部分启用,则可以通过在其前面加上“no”关键字来在特定实例中禁用它。
启用向发送到服务器的请求中插入 X-Forwarded-For 头部
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<network> 是一个可选参数,用于对匹配 <network> 的源禁用此选项。<name> 是一个可选参数,用于指定一个不同的 "X-Forwarded-For" 头部名称。
由于 HAProxy 工作在反向代理模式,服务器将 HAProxy 的 IP 地址视为其客户端地址。当服务器日志中需要客户端的 IP 地址时,这有时会很烦人。为了解决这个问题,HAProxy 可以将众所周知的 HTTP 标头 "X-Forwarded-For" 添加到发送到服务器的所有请求中。此标头包含一个表示客户端 IP 地址的值。由于此标头始终附加到现有标头列表的末尾,因此必须配置服务器以始终仅使用此标头的最后一次出现。请参阅服务器手册以了解如何启用此标准标头的使用。请注意,只必须使用标头的最后一次出现,因为客户端确实可能已经带来了标头。关键字 "header" 可用于提供不同的标头名称来替换默认的 "X-Forwarded-For"。当您可能已经有来自不同应用程序(例如 stunnel)的 "X-Forwarded-For" 标头,并且您需要保留它时,这会很有用。如果您后端服务器不使用 "X-Forwarded-For" 标头并且需要不同的标头(例如 Zeus Web Servers 需要 "X-Cluster-Client-IP")也是如此。有时,同一个 HAProxy 实例可能在直接客户端访问和反向代理访问之间共享(例如当使用 SSL 反向代理来解密 HTTPS 流量时)。可以通过添加 "except" 关键字后跟网络地址来禁用为已知源地址或网络添加标头。在这种情况下,任何匹配网络的源 IP 都不会导致添加此标头。最常见的用途是私有网络或 127.0.0.1。或者,关键字 "if-none" 表示仅当标头不存在时才会添加标头。这只应在完全受信任的环境中使用,因为如果到达 haproxy 的标头处于最终用户的控制之下,这可能会导致安全问题。只支持 IPv4 地址。 "http-request add-header" 或 "http-request set-header" 规则可用于解决此限制。此选项可以在 frontend 或 backend 中指定。如果其中至少一个使用它,则会添加标头。请注意,如果同时定义了 backend 和 frontend,则 backend 的标头子参数设置优先于 frontend。在 "if-none" 参数的情况下,如果 frontend 或 backend 中至少有一个没有指定它,则它希望添加是强制性的,因此它获胜。
# 公共 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 头部的大小写调整
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
标头名称没有标准大小写,因为正如 RFC7230 中所述,它们不区分大小写。因此,应用程序必须以不区分大小写的方式处理它们。但一些有问题的应用程序违反了标准,错误地依赖于浏览器最常用的大小写。这个问题在 HTTP/2 中变得至关重要,因为所有标头名称都必须以小写形式交换,HAProxy 也遵循相同的约定。无论 HTTP 版本如何,所有标头名称都以小写形式发送给客户端和服务器。当 HAProxy 收到 HTTP/1 响应时,其标头名称会转换为小写,并以这种方式进行操作并发送给客户端。如果已知某个客户端违反 HTTP 标准并且无法处理来自 HAProxy 的响应,则可以通过启用此选项并使用全局指令 "h1-case-adjust" 或 "h1-case-adjust-file" 指定要重新格式化的标头列表,在格式化响应并发送给客户端时,将小写标头名称转换为不同的格式。这只能作为在客户端修复之前的一种临时解决方法,因为需要此类解决方法的客户端可能容易受到内容走私攻击,并且必须绝对修复。请注意,此选项不会影响符合标准的客户端。如果此选项已在 "defaults" 部分中启用,则可以通过在其前面添加 "no" 关键字来在特定实例中禁用它。
启用或禁用对发送给有问题的服务器的 HTTP/1 头部的大小写调整
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
标头名称没有标准大小写,因为正如 RFC7230 中所述,它们不区分大小写。因此,应用程序必须以不区分大小写的方式处理它们。但一些有问题的应用程序违反了标准,错误地依赖于浏览器最常用的大小写。这个问题在 HTTP/2 中变得至关重要,因为所有标头名称都必须以小写形式交换,HAProxy 也遵循相同的约定。无论 HTTP 版本如何,所有标头名称都以小写形式发送给客户端和服务器。当 HAProxy 收到 HTTP/1 请求时,其标头名称会转换为小写,并以这种方式进行操作并发送给服务器。如果已知某个服务器违反 HTTP 标准并且无法处理来自 HAProxy 的请求,则可以通过启用此选项并使用全局指令 "h1-case-adjust" 或 "h1-case-adjust-file" 指定要重新格式化的标头列表,在格式化请求并发送给服务器时,将小写标头名称转换为不同的格式。这只能作为在服务器修复之前的一种临时解决方法,因为需要此类解决方法的服务器可能容易受到内容走私攻击,并且必须绝对修复。请注意,此选项不会影响符合标准的服务器。如果此选项已在 "defaults" 部分中启用,则可以通过在其前面添加 "no" 关键字来在特定实例中禁用它。
启用或禁用在处理前等待整个 HTTP 请求体
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
有时,在做出决定之前等待 HTTP 请求的主体是可取的。例如,“balance url_param”就是这样做的。第一个用例是在连接到服务器之前缓冲来自慢速客户端的请求。另一个用例是基于请求主体的内容做出路由决策。此选项放置在前端或后端中,强制 HTTP 处理等待直到接收到整个主体或请求缓冲区已满。它可能与一些滥用 HTTP 的应用程序产生不希望的副作用,这些应用程序期望前端和后端之间有无缓冲的传输,因此绝对不应默认使用。
启用或禁用空连接和请求超时的日志记录
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
最近一些浏览器开始实现“预连接”功能,即推测性地连接到一些最近访问过的网站,以防用户想要访问它们。这导致与网站建立了许多连接,如果超时先发生,则以 408 Request Timeout 结束,或者当浏览器决定先关闭它们时以 400 Bad Request 结束。这些会污染日志并增加错误计数器。已经有了 "option dontlognull",但在这种情况下不够用。相反,此选项执行以下操作: - 如果在连接关闭之前未收到任何内容,则阻止向客户端发送任何 400/408 消息; - 在这种情况下阻止发出任何日志; - 阻止增加任何错误计数器 这样,空连接就会被静默忽略。请注意,最好不要使用此选项,除非明确需要它,因为它会隐藏真正的问题。未收到请求并看到 408 的最常见原因是客户端和中间元素(例如 VPN)之间的 MTU 不一致,这会阻止过大的数据包。这些问题通常出现在 POST 请求以及带有大 cookie 的 GET 请求中。日志通常是检测它们的唯一方法。如果此选项已在 "defaults" 部分中启用,则可以通过在其前面添加 "no" 关键字来在特定实例中禁用它。
启用或禁用从客户端到服务器的 HTTP keep-alive
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
默认情况下,HAProxy 在关于持久连接方面以 keep-alive 模式运行:对于每个连接,它处理每个请求和响应,并在响应结束和新请求开始之间将连接在两侧保持空闲。此模式可以通过多个选项更改,例如 "option http-server-close" 或 "option httpclose"。此选项允许重新设置 keep-alive 模式,当在 defaults 部分使用了另一种模式时,这会很有用。设置 "option http-keep-alive" 可在连接的客户端和服务器端启用 HTTP keep-alive 模式。这在客户端(慢速网络)提供最低延迟,并在服务器端提供最快的会话重用,但代价是维护到服务器的空闲连接。通常,使用此选项可以在小对象上实现大约两倍于 "http-server-close" 选项实现的请求率。此选项主要在两种情况下有用: - 当服务器不符合 HTTP 规范并对连接而不是请求进行身份验证时(例如 NTLM 身份验证) - 当建立与服务器的连接成本相对于从服务器检索相关对象的成本很高时。后一种情况可能发生在服务器是快速静态服务器或缓存时。在这种情况下,服务器需要进行适当调整以支持足够高的连接数,因为连接将持续到客户端发送另一个请求。如果由于内容切换或负载平衡算法,客户端请求必须转到另一个后端或另一个服务器,空闲连接将立即关闭并重新打开一个新连接。选项 "prefer-last-server" 可用于尝试优化服务器选择,以便如果当前连接到空闲连接的服务器可用,它将被使用。目前,日志不会指示请求是否来自同一会话。日志中报告的接受日期对应于上一个请求的结束,请求时间对应于等待新请求所花费的时间。如果未设置,keep-alive 请求时间仍受限于 "timeout http-keep-alive" 或 "timeout http-request" 定义的超时。此选项禁用并替换任何先前的 "option httpclose" 或 "option http-server-close"。当 backend 和 frontend 选项不同时,这 4 个选项都优先于 "option http-keep-alive"。
指示系统在 HTTP 中优先考虑低交互延迟而非性能
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
在 HTTP 中,每个有效负载都是单向的,没有交互性的概念。任何代理都应该排队数据,以便延迟合理地低。有一些非常罕见的服务器到服务器应用程序滥用 HTTP 协议,并期望有效负载阶段具有高度交互性,在单个请求中在两个方向上交错许多数据块。这绝对不受 HTTP 规范支持,并且在大多数代理或服务器上不起作用。当此类应用程序尝试通过 haproxy 执行此操作时,它可以工作,但它们会遇到高延迟,因为网络优化通过指示系统等待足够的数据可用以仅发送完整数据包来优先考虑性能。典型的延迟约为每个往返 200 毫秒。请注意,这仅发生在异常使用的情况下。正常使用(例如 CONNECT 请求或 WebSockets)不受影响。当连接使用的 frontend 或 backend 中存在 "option http-no-delay" 时,所有此类优化都将被禁用,以便使交换尽可能快。当然,这并不能保证功能正常,因为它可能会在任何其他地方中断。但是如果它通过 HAProxy 工作,它将以最快的速度工作。默认情况下不应使用此选项,除非发现此类有问题的应用程序,否则根本不应使用。使用此选项的影响是带宽使用增加和 CPU 使用增加,这可能会在具有高延迟的环境中显着降低性能。
定义 haproxy 是否向服务器宣告 keep-alive
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
当使用 "option http-server-close" 或 "option httpclose" 运行时,haproxy 会向转发到服务器的请求添加 "Connection: close" 标头。不幸的是,当某些服务器看到此标头时,它们会自动避免对未知长度的响应使用分块编码,而这完全不相关。直接效果是这会阻止 haproxy 保持客户端连接活动。第二个效果是客户端或缓存可能会收到不完整的响应而没有意识到它,并认为响应已完成。通过设置 "option http-pretend-keepalive",haproxy 将使服务器相信它将保持连接活动。然后服务器将不会回退到上述异常不需要的行为。当 haproxy 获取整个响应时,它将关闭与服务器的连接,就像使用 "option httpclose" 一样。这样,客户端会收到正常响应,并且连接在服务器端正确关闭。不建议默认启用此选项,因为大多数服务器会更有效地在最后一个数据包之后自行关闭连接,并稍微早一点释放其缓冲区。此外,网络上增加的数据包可能会略微降低整体峰值性能。然而,值得注意的是,当启用此选项时,haproxy 要做的工作会稍微少一些。因此,如果 haproxy 是整个架构中的瓶颈,启用此选项可能会节省一些 CPU 周期。此选项可以在 backend 和 listen 部分中设置。在 frontend 部分中使用它将被忽略,并在启动期间报告警告。这是一个与 backend 相关的选项,因此没有真正的原因将其设置在 frontend 上。此选项可以与 "option httpclose" 结合使用,这将导致向服务器宣布 keepalive 并向客户端宣布 close。然而,不鼓励这种做法。如果此选项已在 "defaults" 部分中启用,则可以通过在其前面添加 "no" 关键字来在特定实例中禁用它。
启用或禁用服务器端的 HTTP 连接关闭
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
默认情况下,HAProxy 在关于持久连接方面以 keep-alive 模式运行:对于每个连接,它处理每个请求和响应,并在响应结束和新请求开始之间将连接在两侧保持空闲。此模式可以通过多个选项更改,例如 "option http-server-close" 或 "option httpclose"。设置 "option http-server-close" 可在服务器端启用 HTTP connection-close 模式,同时保持在客户端支持 HTTP keep-alive 和流水线化的能力。这在客户端(慢速网络)提供最低延迟,并在服务器端提供最快的会话重用以节省服务器资源,类似于 "option httpclose"。如果服务器符合 RFC7230 的要求,它还允许非 keep-alive capable 服务器以 keep-alive 模式提供给客户端。请注意,当某些服务器在请求中看到 "Connection: close" 时,它们并不总是符合这些要求。效果是 keep-alive 永远不会被使用。一种解决方法是启用 "option http-pretend-keepalive"。目前,日志不会指示请求是否来自同一会话。日志中报告的接受日期对应于上一个请求的结束,请求时间对应于等待新请求所花费的时间。如果未设置,keep-alive 请求时间仍受限于 "timeout http-keep-alive" 或 "timeout http-request" 定义的超时。此选项可以在 frontend 和 backend 中设置。如果持有连接的 frontend 或 backend 中至少有一个启用了它,则启用它。它禁用并替换任何先前的 "option httpclose" 或 "option http-keep-alive"。请检查第 4 节(“代理”)以了解当 frontend 和 backend 选项不同时,此选项如何与其他选项结合。如果此选项已在 "defaults" 部分中启用,则可以通过在其前面添加 "no" 关键字来在特定实例中禁用它。
使用非标准的 Proxy-Connection 标头代替 Connection
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
虽然 RFC7230 明确指出 HTTP/1.1 代理必须使用 Connection 标头来指示他们希望持久或非持久连接,但浏览器和代理都忽略此标头进行代理连接,而是使用未记录的非标准 Proxy-Connection 标头。当尝试将负载平衡器放置在浏览器和此类代理之间时,问题就开始了,因为 haproxy 理解的内容与客户端和代理达成一致的内容之间存在差异。通过在 frontend 中设置此选项,haproxy 可以自动切换使用该非标准标头(如果它看到代理请求)。此处定义的代理请求是指 URI 既不以 '/' 也不以 '*' 开头。这与 HTTP 隧道模式不兼容。请注意,此选项只能在 frontend 中指定,并且会影响请求的整个生命周期。此外,当设置此选项时,如果请求本身是代理请求,则需要身份验证的请求将自动切换为使用代理身份验证标头。这使得可以在现有代理前面检查或强制执行身份验证。通常不应使用此选项,除非在代理前面。
启用 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 中是强制性的,请使用 "http-check send" 指令来添加它。
默认情况下,服务器运行状况检查仅尝试建立 TCP 连接。当指定“option httpchk”时,在建立 TCP 连接后会发送一个完整的 HTTP 请求,响应 2xx 和 3xx 被视为有效,而所有其他响应都表示服务器失败,包括没有任何响应。端口和间隔在服务器配置中指定。此选项不一定需要 HTTP 后端,它也适用于纯 TCP 后端。这对于使用 inetd 守护程序检查绑定到特定端口的简单脚本特别有用。注意:有一段时间,无法在用于 HTTP 健康检查的请求中添加标头或正文。因此,一种变通方法是将其隐藏在版本字符串的末尾,并在版本后添加“\r\n”。现在已弃用。必须使用指令“http-check send”代替。
# 将 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 连接关闭
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
默认情况下,HAProxy 在关于持久连接方面以 keep-alive 模式运行:对于每个连接,它处理每个请求和响应,并在响应结束和新请求开始之间将连接在两侧保持空闲。此模式可以通过多个选项更改,例如 "option http-server-close" 或 "option httpclose"。如果设置了 "option httpclose",HAProxy 将在收到请求和响应后立即关闭与服务器和客户端的连接。它还会检查每个方向是否已设置 "Connection: close" 标头,如果缺少则添加一个。任何不同于 "close" 的 "Connection" 标头也将被删除。此选项还可以与 "option http-pretend-keepalive" 结合使用,这将禁用发送 "Connection: close" 标头,但仍会在收到整个响应后导致连接关闭。此选项可以在 frontend 和 backend 中设置。如果持有连接的 frontend 或 backend 中至少有一个启用了它,则启用它。它禁用并替换任何先前的 "option http-server-close" 或 "option http-keep-alive"。请检查第 4 节(“代理”)以了解当 frontend 和 backend 选项不同时,此选项如何与其他选项结合。如果此选项已在 "defaults" 部分中启用,则可以通过在其前面添加 "no" 关键字来在特定实例中禁用它。
启用 HTTP 请求、会话状态和计时器的日志记录
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
clf 如果添加了“clf”参数,则输出格式将是 CLF 格式,而不是 HAProxy 的默认 HTTP 格式。当您需要将 HAProxy 的日志输入到只支持 CLF 格式且不可扩展的特定日志分析器时,可以使用此选项。
默认情况下,日志输出格式非常简陋,只包含源地址和目标地址以及实例名称。通过指定 "option httplog",每条日志行都会变成一种更丰富的格式,包括但不限于 HTTP 请求、连接计时器、会话状态、连接数、捕获的头部和 cookie、前端、后端和服务器名称,当然还有源地址和端口。仅指定 "option httplog" 将自动清除默认设置的 'clf' 模式。"option httplog" 会覆盖任何先前的 "log-format" 指令。
启用或禁用纯 HTTP 代理模式
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
有时人们需要一个纯粹的 HTTP 代理,它能理解基本的代理请求,而不需要缓存或任何花哨的功能。在这种情况下,设置一个启用了 "option http_proxy" 的 HAProxy 实例可能是值得的。在这种模式下,不声明任何服务器,连接被转发到 URL 中 "http://" 方案后的 IP 地址和端口。不执行主机地址解析,因此这仅在传递纯 IP 地址时有效。由于此选项的使用范围相当有限,它可能只会被那些知道自己确切需要它的专家使用。这与 HTTP 隧道模式不兼容。如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
# 此后端理解 HTTP 代理请求并直接转发它们。 backend direct_forward option httpclose option http_proxy
启用或禁用对两个方向的独立超时处理
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
默认情况下,当数据通过套接字发送时,该套接字的写入超时和读取超时都会刷新,因为我们认为该套接字上有活动,并且我们没有其他方法来猜测是否应该接收数据。虽然此默认行为适用于几乎所有应用程序,但在某些情况下,禁用此行为是可取的,并且仅在有传入数据时才刷新读取超时。这发生在具有大超时和少量交换数据的会话上,例如 telnet 会话。如果服务器突然消失,输出数据会累积在系统的套接字缓冲区中,两个超时都会正确刷新,并且无法知道服务器是否没有接收到它们,因此我们不会超时。然而,当底层协议总是回显发送的数据时,仅凭它本身就足以使用读取超时来检测问题。请注意,此问题不会发生在更详细的协议上,因为数据不会长时间累积在套接字缓冲区中。当在 frontend 上设置此选项时,它将禁用发送给客户端的数据的读取超时更新。这种情况可能很少使用。当在 backend 上设置此选项时,它将禁用发送给服务器的数据的读取超时更新。这样做通常会破坏来自慢速线路的大型 HTTP post,因此请谨慎使用。
使用 LDAPv3 健康检查进行服务器测试
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
可以测试服务器是否正确地使用 LDAPv3 通信,而不仅仅是测试它是否接受 TCP 连接。设置此选项后,会向服务器发送一个 LDAPv3 匿名简单绑定消息,并分析响应以查找 LDAPv3 绑定响应消息。只有当 LDAP 响应包含成功 resultCode (http://tools.ietf.org/html/rfc4511#section-4.1.9) 时,服务器才被认为是有效的。绑定请求的日志记录取决于服务器,请参阅您的文档如何配置它。
option ldap-check
使用外部进程进行服务器健康检查
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
可以使用外部命令测试服务器的健康状况。这是通过运行使用 "external-check command" 设置的可执行文件来实现的。需要设置全局的 "external-check"。
启用或禁用健康检查状态更新的日志记录
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
默认情况下,如果服务器处于 UP 状态,则记录失败的健康检查;如果服务器处于 DOWN 状态,则记录成功的健康检查,因此额外的信息量是有限的。启用此选项后,健康检查状态或服务器健康状况的任何变化都将被记录,这样就可以知道服务器在崩溃前偶尔会检查失败,或者确切知道它何时未能响应有效的 HTTP 状态,然后端口何时开始拒绝连接,以及服务器何时完全停止响应。请注意,此选项有意不记录非健康检查引起的状态变化(例如,在 CLI 上启用/禁用)。
更改非完全成功连接的日志级别
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
有时在日志中查找错误并不容易。此选项使 haproxy 提高包含潜在有趣信息(如错误、超时、重试、重新分派或 HTTP 状态码 5xx)的日志级别。级别从 "info" 变为 "err"。这使得可以使用大多数 syslog 守护进程将它们单独记录到不同的文件中。注意不要将它们从原始文件中删除,否则你会丢失提供非常重要信息的顺序。使用此选项,处理每秒数千个连接的大型站点可以将正常流量记录到循环缓冲区中,并只归档较小的错误日志。
启用或禁用早期日志记录。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
默认情况下,当 log-format 字符串定义中使用的所有日志格式变量和样本提取都返回值时,或者当会话终止时,会发出日志。这允许内置日志格式字符串在日志消息中考虑传输时间或字节数。在处理大型文件传输或 RDP 等长连接时,请求或连接可能需要一段时间才能出现在日志中。使用 "option logasap",日志消息会在 tcp 模式下建立服务器连接后立即创建,或者在 http 模式下服务器发送完整标头后立即创建。日志中缺失的信息将是总字节数,它将仅指示在创建消息之前传输的数据量,并且总时间将不考虑连接生命周期或传输时间的其余部分。对于 HTTP 的情况,捕获 Content-Length 响应标头是一种很好的做法,以便日志至少指示预期传输的字节数。
listen http_proxy 0.0.0.0:80 mode http option httplog option logasap log 192.168.2.200 local3 >>> Feb 6 12:14:14 localhost \ haproxy[14389]: 10.0.1.2:33317 [06/Feb/2009:12:14:14.655] http-in \ static/srv1 9/10/7/14/+30 200 +243 - - ---- 3/1/1/1/0 1/0 \ "GET /image.iso HTTP/1.0"
使用 MySQL 健康检查进行服务器测试
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<username> 这是连接到 MySQL 服务器时将使用的用户名。 post-41 发送与 v4.1 后版本客户端兼容的检查
如果您指定用户名,检查包括发送两个 MySQL 数据包,一个客户端身份验证数据包和一个 QUIT 数据包,以正确关闭 MySQL 会话。然后我们解析 MySQL 握手初始化数据包和/或错误数据包。这是一个基本但有用的测试,不会在服务器上产生错误或中止连接。但是,它需要在 MySQL 表中添加授权,如下所示: USE mysql; INSERT INTO user (Host,User) values ('<ip_of_haproxy>','<username>'); FLUSH PRIVILEGES; 如果您不指定用户名(不推荐和不建议),检查仅包括解析 Mysql 握手初始化数据包或错误数据包,我们在此模式下不发送任何内容。据报道,如果检查过于频繁和/或流量不足,它可能会产生锁定。实际上,在这种情况下,您需要检查 MySQL "max_connect_errors" 值,因为如果在先前连接中断后,在少于 MySQL "max_connect_errors" 次尝试内成功建立连接,则主机的错误计数将清除为零。如果 HAProxy 的服务器被阻止,"FLUSH HOSTS" 语句是解除阻止的唯一方法。请记住,这不会检查数据库是否存在或数据库一致性。为此,您可以使用带有 xinetd 的外部检查。检查需要 MySQL >=3.22,对于旧版本,请使用 TCP 检查。通常,传入的 MySQL 服务器需要查看客户端的 IP 地址用于各种目的,包括 IP 特权匹配和连接日志记录。如果可能,使用 "source" 关键字的 "usesrc" 参数连接到服务器时,伪装客户端的 IP 地址通常是明智的,这需要编译透明代理功能,并且 MySQL 服务器通过托管 haproxy 的机器路由客户端。启用或禁用关闭后立即清理会话资源
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
当客户端或服务器以不干净的方式中止连接时(例如它们物理断开连接),会话超时触发并关闭会话。但它将在系统中的 FIN_WAIT1 状态中保留一段时间,占用一些资源并可能限制建立新连接的能力。发生这种情况时,可以激活 "option nolinger",它会强制系统在关闭时立即删除任何套接字的待处理数据。因此,会话会立即从系统表中清除。这通常会产生副作用,例如由于旧的重传立即被拒绝而导致 TCP 重置次数增加。一些防火墙有时也会对此抱怨。因此,不建议在绝对不需要时使用此选项。当您的系统上有数千个 FIN_WAIT1 会话(TIME_WAIT 会话不计算在内)时,您就知道需要它。此选项可以在 frontend 和 backend 上使用,具体取决于需要它的那一侧。在 frontend 上用于客户端,在 backend 上用于服务器。如果此选项已在 "defaults" 部分中启用,则可以通过在其前面添加 "no" 关键字来在特定实例中禁用它。
启用向发送到服务器的请求插入 X-Original-To 标头
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<network> 是一个可选参数,用于为匹配 <network> 的源禁用此选项。<name> 是一个可选参数,用于指定一个不同的 "X-Original-To" 标头名称。
由于 HAProxy 可以以透明模式工作,来自客户端的每个请求都可以重定向到代理,HAProxy 本身可以将每个请求代理到复杂的 SQUID 环境,并且 SO_ORIGINAL_DST 中的目标主机将丢失。当您想要基于目标 IP 地址的访问规则时,这很烦人。为了解决这个问题,HAProxy 可以将新的 HTTP 标头 "X-Original-To" 添加到发送到服务器的所有请求中。此标头包含一个表示原始目标 IP 地址的值。由于这必须配置为始终仅使用此标头的最后一次出现。请注意,只必须使用标头的最后一次出现,因为客户端确实可能已经带来了标头。关键字 "header" 可用于提供不同的标头名称来替换默认的 "X-Original-To"。当您可能已经有来自不同应用程序的 "X-Original-To" 标头,并且您需要保留它时,这会很有用。如果您后端服务器不使用 "X-Original-To" 标头并且需要不同的标头也是如此。有时,同一个 HAProxy 实例可能在直接客户端访问和反向代理访问之间共享(例如当使用 SSL 反向代理来解密 HTTPS 流量时)。可以通过添加 "except" 关键字后跟网络地址来禁用为已知源地址或网络添加标头。在这种情况下,任何匹配网络的源 IP 都不会导致添加此标头。最常见的用途是私有网络或 127.0.0.1。只支持 IPv4 地址。 "http-request add-header" 或 "http-request set-header" 规则可用于解决此限制。此选项可以在 frontend 或 backend 中指定。如果其中至少一个使用它,则会添加标头。请注意,如果同时定义了 backend 和 frontend,则 backend 的标头子参数设置优先于 frontend。
# 原始目标地址 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
启用或禁用对故障服务器的强制持久性
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
当 HTTP 请求到达一个带有引用故障服务器的 cookie 的后端时,默认情况下它会被重新分派到另一台服务器。如果绝对需要,可以使用 "option persist" 强制将请求首先发送到故障服务器。一个常见的用例是当服务器处于极端负载下并不断地出现状态切换时。在这种情况下,用户仍将被导向到他们打开会话的服务器,希望他们能得到正确的服务。建议将 "option redispatch" 与此选项结合使用,以便在无法连接到服务器的情况下(服务器确定故障),客户端最终将被重定向到另一台有效的服务器。如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
使用 PostgreSQL 健康检查进行服务器测试
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<username> 这是连接到 PostgreSQL 服务器时将使用的用户名。
此检查发送一个 PostgreSQL StartupMessage 并等待认证请求或 ErrorResponse 消息。这是一个基本但有用的测试,不会在服务器上产生错误或中止连接。此检查与 "mysql-check" 相同。
允许多个负载均衡的请求保留在同一台服务器上
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
当使用的负载平衡算法不是确定性时,并且先前的请求已发送到 haproxy 仍保持连接的服务器时,有时希望同一会话上的后续请求尽可能发送到同一服务器。请注意,这与持久性不同,因为我们只表示一种偏好,haproxy 尝试应用,但不提供任何保证。真正的用途是发送到服务器的 keep-alive 连接。使用此选项时,haproxy 将尝试重用附加到服务器的相同连接,而不是重新平衡到另一台服务器,从而导致连接关闭。这对于静态文件服务器可能是有意义的。将其与哈希算法结合使用意义不大。请注意,当负载平衡算法不是确定性时,haproxy 已经自动尝试粘滞到发送 401 的服务器或发送 407(需要身份验证)的代理。这对于与有问题的 NTLM 身份验证挑战一起使用是强制性的,并且有助于排除一些有故障的应用程序的故障。选项 prefer-last-server 在这些环境中也是可取的,以避免在每隔一个响应后重新分配流量。如果此选项已在 "defaults" 部分中启用,则可以通过在其前面添加 "no" 关键字来在特定实例中禁用它。
启用或禁用连接失败时的会话重新分发
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<interval> 可选的整数值,用于控制重试连接时重新分发的频率。正值 P 表示希望在每第 P 次重试时进行重新分发,负值 N 表示希望在最后一次重试前的第 N 次重试时进行重新分发。例如,默认值 -1 保留了在最后一次重试时重新分发的历史行为,正值 1 表示每次重试都重新分发,正值 3 表示每三次重试重新分发一次。您可以使用值 0 禁用重新分发。
在HTTP模式下,如果cookie指定的服务器宕机,客户端可能会一直粘滞在该服务器上,因为它们无法清除cookie,因此将无法再访问服务。指定 "option redispatch" 将允许代理打破基于cookie或一致性哈希的持久性,并将它们重新分配给一个正常工作的服务器。它还允许在多次连接失败的情况下重试连接到另一个服务器。当然,这需要将 "retries" 设置为一个非零值。如果此选项已在 "defaults" 部分启用,则可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
使用 Redis 健康检查进行服务器测试
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
可以测试服务器是否正确地使用 REDIS 协议通信,而不仅仅是测试它是否接受 TCP 连接。设置此选项后,会向服务器发送一个 PING redis 命令,并分析响应以查找 "+PONG" 响应消息。
option redis-check
使用 SMTP 健康检查进行服务器测试
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<hello> 是一个可选参数。它是要使用的“hello”命令。它可以是“HELO”(用于 SMTP)或“EHLO”(用于 ESMTP)。所有其他值都将转换为默认命令(“HELO”)。<domain> 是要呈现给服务器的域名。只有在指定了 hello 命令时才能指定(并且是强制性的)。默认情况下,使用“localhost”。
当设置了 "option smtpchk" 时,健康检查将包括TCP连接,然后发送一个SMTP命令。默认情况下,此命令是 "HELO localhost"。服务器的返回代码将被分析,只有以 "2" 开头的返回代码才会被认为是有效的。所有其他响应,包括没有响应,都将构成一个错误,并指示服务器已死。此测试旨在用于SMTP服务器或中继。根据请求的不同,一些服务器可能不会记录每次连接尝试,因此您可能需要进行试验以改进其行为。使用telnet到端口25通常比调整配置更容易。通常情况下,传入的SMTP服务器需要查看客户端的IP地址,用于各种目的,包括垃圾邮件过滤、反欺骗和日志记录。如果可能,通常明智的做法是使用 "source" 关键字的 "usesrc" 参数连接到服务器时伪装客户端的IP地址,这需要编译时启用透明代理功能。
option smtpchk HELO mydomain.org
启用或禁用为每个套接字收集并提供单独的统计信息。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
启用或禁用双向套接字上的自动内核加速
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
当此选项在前端或后端启用时,HAProxy将自动评估使用内核TCP拼接在客户端和服务器之间双向转发数据的机会。HAProxy使用启发式方法来估计内核拼接是否能提高性能。两个方向都是独立处理的。请注意,使用的启发式方法不是很激进,以限制过度使用拼接。此选项要求在编译时启用拼接,并且可以通过全局选项 "nosplice" 全局禁用。由于拼接使用管道,因此使用它需要有足够的备用管道。重要说明:基于内核的TCP拼接是Linux特有的功能,最早出现在内核2.6.25中。它提供了基于内核的加速,用于在套接字之间传输数据,而无需将这些数据复制到用户空间,从而提供显著的性能提升和CPU周期节省。由于许多早期实现存在错误、数据损坏和/或效率低下,此功能默认情况下未启用,应谨慎使用。虽然无法检测实现的正确性,但2.6.29是第一个提供正常工作的实现的版本。如有疑问,可以使用全局 "nosplice" 关键字全局禁用拼接。
option splice-auto
如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
启用或禁用请求套接字上的自动内核加速
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
当在前台或后台启用此选项时,haproxy 将尽可能使用内核 TCP 拼接来转发从客户端到服务器的数据。如果没有备用管道,它可能仍会使用 recv/send 方案。此选项需要在编译时启用拼接,并且可以通过全局选项 "nosplice" 全局禁用。由于 splice 使用管道,使用它需要有足够的备用管道。重要说明:有关使用限制,请参阅 "option splice-auto"。
option splice-request
如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
启用或禁用响应套接字上的自动内核加速
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
当在前台或后台启用此选项时,haproxy 将尽可能使用内核 TCP 拼接来转发从服务器到客户端的数据。如果没有备用管道,它可能仍会使用 recv/send 方案。此选项需要在编译时启用拼接,并且可以通过全局选项 "nosplice" 全局禁用。由于 splice 使用管道,使用它需要有足够的备用管道。重要说明:有关使用限制,请参阅 "option splice-auto"。
option splice-response
如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
使用 SPOP 健康检查进行服务器测试
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 否![]() | 是![]() |
可以测试服务器是否正确地使用 SPOP 协议进行通信,而不仅仅是测试它是否接受 TCP 连接。设置此选项后,HAProxy 和服务器之间会执行 HELLO 握手,并分析响应以检查是否报告了错误。
option spop-check
启用或禁用在服务器端发送 TCP keepalive 数据包
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
当客户端和服务器之间存在防火墙或任何会话感知组件时,并且当协议涉及具有较长空闲期的非常长的会话(例如远程桌面)时,存在中间组件决定使空闲时间过长的会话过期的风险。启用套接字级TCP keep-alive使系统定期向连接的另一端发送数据包,使其保持活动状态。keep-alive探测之间的时间延迟仅由系统控制,并取决于操作系统及其调整参数。重要的是要理解keep-alive数据包既不是在应用程序级别发送也不是在应用程序级别接收的。只有网络堆栈才能看到它们。因此,即使代理的一侧已经使用keep-alive来保持其连接处于活动状态,这些keep-alive数据包也不会转发到代理的另一侧。请注意,这与HTTP keep-alive无关。使用选项 "srvtcpka" 可在连接的服务器端启用TCP keep-alive探测的发送,这在HAProxy和服务器之间发现会话过期时应该有所帮助。如果此选项已在 "defaults" 部分启用,则可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
使用 SSLv3 客户端 hello 健康检查进行服务器测试
可用于节
| 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 发送/期望序列执行健康检查
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
此健康检查方法旨在与 "tcp-check" 命令列表结合使用,以支持send/expect类型的健康检查序列。TCP检查目前支持4种操作模式: - 没有 "tcp-check" 指令:健康检查仅包括连接尝试,这仍然是默认模式。 - 仅提到了 "tcp-check send" 或 "tcp-check send-binary":这用于在连接打开时发送一个字符串。对于某些协议,例如发送 "QUIT" 消息,可以防止服务器为每个健康检查记录连接错误。检查结果仍将仅基于打开连接的能力。 - 仅提到了 "tcp-check expect":这用于测试横幅。连接打开后,haproxy等待服务器呈现一些内容,这些内容必须验证一些规则。检查结果将基于内容与规则之间的匹配。这适用于POP、IMAP、SMTP、FTP、SSH、TELNET。 - 同时提到了 "tcp-check send" 和 "tcp-check expect":这用于测试hello型协议。HAProxy发送一条消息,服务器响应,并分析其响应。检查结果将基于响应内容与规则之间的匹配。这通常适用于需要绑定或请求/响应模型的协议。LDAP、MySQL、Redis和SSL就是此类协议的示例,尽管它们都已经有专用的检查,对各自的协议有更深入的理解。在此模式下,可以发送许多问题并分析许多答案。可以使用第五种模式来在脚本的不同步骤中插入注释。对于您创建的每个tcp-check规则,您可以添加一个 "comment" 指令,后跟一个字符串。此字符串将在调试模式下记录在日志和stderr中。这对于制作用户友好的错误报告很有用。"comment" 当然是可选的。
# 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 数据包
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
当HTTP连接请求传入时,系统代表HAProxy确认它,然后客户端立即发送其请求,系统也确认它,同时通知HAProxy有关新连接的信息。HAProxy然后读取请求并响应。这意味着系统发送了一个TCP ACK,这是没有必要的,因为HAProxy在发送响应时可以很好地确认请求。因此,在HTTP模式下,HAProxy会自动要求系统避免在支持它的平台(目前至少是Linux)上发送这个无用的ACK。它不应该引起任何问题,因为如果响应花费的时间比预期要长,系统无论如何都会在40毫秒后发送它。在复杂的网络调试会话中,可能需要禁用此优化,因为延迟的ACK在尝试识别数据包延迟位置时可能会使故障排除更加复杂。然后可以通过指定 "no option tcp-smart-accept" 来恢复正常行为。也可以通过简单指定 "option tcp-smart-accept" 来强制它用于非HTTP代理。例如,对于某些服务(如SMTP,其中服务器首先发言)来说,这可能是有意义的。建议避免在 defaults 部分强制使用此选项。如有疑问,请考虑在其前面加上 "default" 关键字以将其设置回自动值,或使用 "no" 关键字将其禁用。
启用或禁用在连接序列期间节省一个 ACK 数据包
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
在某些系统(至少是 Linux)上,HAProxy 可以请求内核在收到连接请求时不立即发送一个空的 ACK,而是直接发送带有数据的请求。这可以在网络上节省一个数据包,从而提高性能。这对某些服务器也很有用,因为它们可以立即随传入连接一起获取请求。当在后端设置了 "option tcp-smart-connect" 时,此功能被启用。默认情况下不启用,因为它会使网络故障排除变得更加复杂。只在客户端先说话的协议(如 HTTP)中启用它才有意义。在其他情况下,如果没有数据可以代替 ACK 发送,则会发送一个正常的 ACK。如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字来在特定实例中禁用它。
启用或禁用在两侧发送 TCP keepalive 数据包
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
当客户端和服务器之间存在防火墙或任何会话感知组件时,并且当协议涉及具有较长空闲期的非常长的会话(例如远程桌面)时,存在中间组件决定使空闲时间过长的会话过期的风险。启用套接字级TCP keep-alive使系统定期向连接的另一端发送数据包,使其保持活动状态。keep-alive探测之间的时间延迟仅由系统控制,并取决于操作系统及其调整参数。重要的是要理解keep-alive数据包既不是在应用程序级别发送也不是在应用程序级别接收的。只有网络堆栈才能看到它们。因此,即使代理的一侧已经使用keep-alive来保持其连接处于活动状态,这些keep-alive数据包也不会转发到代理的另一侧。请注意,这与HTTP keep-alive无关。使用选项 "tcpka" 可在连接的客户端和服务器端启用TCP keep-alive探测的发送。请注意,这仅在 "defaults" 或 "listen" 部分中有意义。如果此选项用于前端,则只有客户端一侧会获得keep-alive,如果此选项用于后端,则只有服务器一侧会获得keep-alive。因此,当配置在前端和后端之间拆分时,强烈建议明确使用 "option clitcpka" 和 "option srvtcpka"。
启用包含会话状态和计时器的 TCP 连接高级日志记录
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
默认情况下,日志输出格式非常简陋,只包含源地址和目标地址以及实例名称。通过指定 "option tcplog",每条日志行都会变成一种更丰富的格式,包括但不限于连接计时器、会话状态、连接数、前端、后端和服务器名称,当然还有源地址和端口。此选项对于纯 TCP 代理很有用,以便找出是客户端还是服务器断开连接或超时。对于普通的 HTTP 代理,最好使用 "option httplog",它甚至更完整。"option tcplog" 会覆盖任何先前的 "log-format" 指令。
启用客户端透明代理
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
引入此选项是为了给第 3 层负载均衡器提供第 7 层持久性。其思想是利用操作系统的能力,将针对远程地址的传入连接重定向到本地进程(此处为 HAProxy),并让该进程知道最初请求的地址。使用此选项时,没有 cookie 的会话将被转发到传入请求的原始目标 IP 地址(该地址应与另一台设备的地址匹配),而带有 cookie 的请求仍将被转发到适当的服务器。请注意,与普遍看法相反,此选项不会使 HAProxy 在建立连接时向服务器呈现客户端的 IP。
执行外部检查时要运行的可执行文件
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<command> 是要运行的外部命令
传递给命令的参数是: <proxy_address> <proxy_port> <server_address> <server_port> <proxy_address> 和 <proxy_port> 派生自第一个是IPv4、IPv6或UNIX套接字的监听器。如果是UNIX套接字监听器,proxy_address将是套接字的路径,<proxy_port> 将是字符串 "NOT_USED"。在后端部分中,无法确定监听器,<proxy_address> 和 <proxy_port> 都将具有字符串值 "NOT_USED"。一些值也通过环境变量提供。环境变量:HAPROXY_PROXY_ADDR 如果可用,第一个绑定地址(如果在 "backend" 部分中不适用,则为空)。HAPROXY_PROXY_ID 后端ID。HAPROXY_PROXY_NAME 后端名称。HAPROXY_PROXY_PORT 如果可用,第一个绑定端口(如果在 "backend" 部分中或对于UNIX套接字不适用,则为空)。HAPROXY_SERVER_ADDR 服务器地址。HAPROXY_SERVER_CURCONN 服务器上的当前连接数。HAPROXY_SERVER_ID 服务器ID。HAPROXY_SERVER_MAXCONN 服务器最大连接数。HAPROXY_SERVER_NAME 服务器名称。HAPROXY_SERVER_PORT 如果可用,服务器端口(对于UNIX套接字为空)。PATH 执行命令时使用的PATH环境变量可以使用 "external-check path" 设置。有关其他变量,请参阅 "2.3. Environment variables"。如果执行的命令退出状态为零,则检查被认为已通过,否则检查被认为已失败。
external-check command /bin/true
运行外部检查时使用的 PATH 环境变量的值
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<path> 是执行外部命令时使用的路径
默认路径为 ""。
external-check path "/usr/bin:/bin"
启用基于 RDP cookie 的持久性
可用于节
| 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
设置前端每秒接受的新会话数限制
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<rate> <rate> 参数是一个整数,指定前端每秒接受的最大新会话数。
当前端达到每秒指定的新会话数时,它会停止接受新连接,直到速率再次降至限制以下。在此期间,待处理的会话将保留在套接字的积压队列中(在系统缓冲区中),haproxy甚至不会意识到会话正在等待。在高度加载的服务上应用非常低的限制时,增加套接字的积压队列可能是有意义的,可以使用 "backlog" 关键字。此功能在阻止基于连接的攻击或对脆弱服务器的服务滥用方面特别有效。由于会话速率是每毫秒测量的,因此它非常准确。此外,限制立即生效,检测阈值根本不需要延迟。将 SMTP 的连接速率限制为最大每秒 10 个listen smtp mode tcp bind :25 rate-limit sessions 10 server smtp1 127.0.0.1:1025
注意:当达到最大速率时,前端的状态不会改变,但如果启用了 "socket-stats" 选项,其套接字在统计信息中将显示为 "WAITING"。
如果/除非条件匹配,则返回 HTTP 重定向
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
如果/除非条件匹配,HTTP 请求将导致重定向响应。如果未指定条件,则重定向无条件适用。
<loc> 使用 "redirect location",<loc> 中的确切值放置在HTTP "Location" 标头中。当在 "http-request" 规则中使用时,<loc> 值遵循日志格式规则,并且可以包含一些动态值(请参阅 section 8.2.4 中的自定义日志格式)。<pfx> 使用 "redirect prefix","Location" 标头是通过连接 <pfx> 和完整的URI路径(包括查询字符串)构建的,除非指定了 "drop-query" 选项(见下文)。作为一个特例,如果 <pfx> 恰好等于 "/",则不会在原始URI之前插入任何内容。它允许重定向到相同的URL(例如,插入cookie)。当在 "http-request" 规则中使用时,<pfx> 值遵循日志格式规则,并且可以包含一些动态值(请参阅 section 8.2.4 中的自定义日志格式)。<sch> 使用 "redirect scheme","Location" 标头是通过连接 <sch> 和 "://",然后是第一个出现的 "Host" 标头,然后是URI路径(包括查询字符串,除非指定了 "drop-query" 选项(见下文))构建的。如果未找到路径或路径为 "*",则使用 "/" 代替。如果未找到 "Host" 标头,则返回空主机组件,大多数最近的浏览器将其解释为重定向到同一主机。此指令主要用于将HTTP重定向到HTTPS。当在 "http-request" 规则中使用时,<sch> 值遵循日志格式规则,并且可以包含一些动态值(请参阅 section 8.2.4 中的自定义日志格式)。<code> code是可选的。它指示所需的HTTP重定向类型。仅支持代码301、302、303、307和308,如果未指定代码,则默认使用302。301表示 "永久移动",浏览器可能会缓存Location。302表示 "临时移动",意味着浏览器不应缓存重定向。303等同于302,但浏览器将使用GET方法获取location。307就像302一样,但明确表示必须重用相同的方法。同样,如果必须使用相同的方法,308取代301。<option> 可以指定几个选项来调整重定向的预期行为: - "drop-query" 当此关键字用于基于前缀的重定向时,location将设置时不包含任何可能的查询字符串,这对于将用户定向到非安全页面很有用。它对location类型的重定向没有影响。 - "append-slash" 此关键字可与 "drop-query" 结合使用,以将使用不以 '/' 结尾的URL的用户重定向到带有 '/' 的相同URL。确保搜索引擎只看到一个URL可能很有用。为此,首选返回代码301。 - "set-cookie NAME[=value]" 将向响应添加一个带有NAME(和可选的 "=value")的 "Set-Cookie" 标头。这有时用于指示已看到用户,例如用于防止某些类型的DoS。没有添加其他cookie选项,因此cookie将是会话cookie。请注意,对于浏览器来说,不带等号的单个cookie名称与带有等号的cookie不同。 - "clear-cookie NAME[=]" 将添加一个带有NAME(和可选的 "=")的 "Set-Cookie" 标头,但 "Max-Age" 属性设置为零。这将告诉浏览器删除此cookie。例如,在注销页面上很有用。重要的是要注意,清除cookie "NAME" 不会删除使用 "NAME=value" 设置的cookie。您必须清除cookie "NAME=" 才能删除它,因为浏览器会区分两者。
仅将登录 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 }
有关 ACL 的用法,请参见第 7 节。
设置连接失败后在服务器上执行的重试次数
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<value> 是当连接被拒绝或超时时,应在服务器上重试连接尝试的次数。默认值为 3。
重要的是要理解,此值适用于连接尝试的次数,而不是完整的请求。当与服务器有效建立连接后,将不再进行重试。为了避免立即重新连接到正在重启的服务器,在重试发生之前会应用一个 min("timeout connect", 一秒) 的周转计时器。当设置了 "option redispatch" 时,即使 cookie 引用了不同的服务器,最后一次重试也可能在另一台服务器上执行。指定何时尝试自动重试失败的请求。此设置仅在 "mode" 设置为 http 时有效,否则将被静默忽略。可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<keywords> 是关键字或HTTP状态代码的列表,每个关键字都代表一种失败事件类型,希望在发生该事件时尝试重试请求。在更改此设置之前,请阅读底部的注释。支持以下关键字:none 从不重试 conn-failure 当连接或SSL握手失败且请求无法发送时重试。这是默认值。empty-response 当服务器连接在发送部分请求后关闭,并且未从服务器收到任何内容时重试。此类故障可能由服务器端的请求超时、网络状况不佳或服务器在处理请求时崩溃或重新启动引起。junk-response 当服务器返回的内容看起来不像一个完整的HTTP响应时重试。这包括部分响应标头以及非HTTP内容。对此类事件重试通常是一个坏主意,这可能是由配置问题(错误的服务器端口)或请求对服务器有害(例如缓冲区溢出攻击)引起的。response-timeout 等待服务器响应请求时服务器超时。这可能是由网络状况不佳、路径上已过期的空闲连接重用,或请求处理成本极高引起的。对于处理繁重数据库处理(全表扫描等)的服务器,重试此类事件通常是一个坏主意,因为它可能会放大拒绝服务攻击。0rtt-rejected 重试通过早期数据发送并被服务器拒绝的请求。这些请求通常被认为是安全的重试。<status> 任何HTTP状态代码,包括 "404"(未找到)、"408"(请求超时)、"425"(太早)、"500"(服务器错误)、"501"(未实现)、"502"(网关错误)、"503"(服务不可用)、"504"(网关超时)。all-retryable-errors 对所有被认为是可重试的错误重试请求。这目前激活 "conn-failure"、"empty-response"、"junk-response"、"response-timeout"、"0rtt-rejected"、"500"、"502"、"503" 和 "504"。
使用此指令将替换所有以前的设置;它不是累积的。请注意,使用 "none" 和 "conn-failure" 以外的任何内容都需要分配缓冲区并将整个请求复制到其中,因此它具有内存和性能影响。不适合单个缓冲区的请求将永远不会重试(请参阅全局 tune.bufsize 设置)。您必须确保应用程序具有内置的重放保护机制,例如在请求中传递唯一的事务ID,或者重放相同的请求没有后果,否则使用除 "conn-failure" 和 "none" 之外的任何 retry-on 值都非常危险。静态文件服务器和缓存通常被认为是安全的,可以抵御任何类型的重试。使用状态代码对于快速离开显示异常行为(内存不足、文件系统问题等)的服务器可能很有用,但在这种情况下,立即将连接重新分配给另一台服务器可能是一个好主意(请参阅 "option redispatch")。最后,重要的是要理解大多数故障原因都是请求本身,并且重试导致服务器行为不当的请求通常会使该服务器的情况,或者在重新分配的情况下使整个服务的情况变得更糟。除非您确切知道应用程序如何处理重放的请求,否则不应使用此指令。默认值是 "conn-failure"。
在后端中声明一个服务器
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<name> 是分配给此服务器的内部名称。此名称将出现在日志和警报中。如果设置了 "http-send-name-header",它将添加到发送到服务器的请求标头中。<address> 是服务器的IPv4或IPv6地址。或者,支持可解析的主机名,但此名称将在启动期间解析。地址 "0.0.0.0" 或 "*" 具有特殊含义。它表示连接将转发到与客户端连接相同的IP地址。这在透明代理架构中很有用,其中客户端的连接被拦截,haproxy必须转发到原始目标地址。这或多或少是 "transparent" 关键字所做的,只是使用服务器可以限制并发并报告统计信息。可选地,可以在地址前使用地址族前缀来强制使用该族,无论地址格式如何,这对于指定没有斜杠 ('/') 的unix套接字路径很有用。目前支持的前缀有: - 'ipv4@' -> 地址始终为IPv4 - 'ipv6@' -> 地址始终为IPv6 - 'unix@' -> 地址是本地unix套接字的路径 - 'abns@' -> 地址位于抽象命名空间中(仅限Linux) - 'sockpair@' -> 地址是已连接的unix套接字或socketpair的文件描述符。在连接期间,后端创建一对已连接的套接字,并通过FD传递其中一个。绑定部分将使用接收到的套接字作为客户端FD。应谨慎使用。您可能希望在地址参数中引用一些环境变量,请参阅关于环境变量的 section 2.3。"init-addr" 设置可用于修改启动时解析IP地址的方式。<port> 是可选的端口规范。如果设置,所有连接都将发送到此端口。如果未设置,将使用客户端连接到的同一端口。端口也可以以 "+" 或 "-" 为前缀。在这种情况下,服务器的端口将通过将此值添加到客户端端口来确定。<param*> 是此服务器的参数列表。"server" 关键字接受大量选项,并有一个专门的部分进行介绍。请参阅 section 5 获取更多详细信息。
server first 10.1.1.1:1080 cookie first check inter 1000 server second 10.1.1.2:1080 cookie second check inter 1000 server transp ipv4@ server backup "${SRV_BACKUP}:1080" backup server www1_dc1 "${LAN_DC1}.101:80" server www1_dc2 "${LAN_DC2}.101:80"
注意:关于 Linux 的抽象命名空间套接字,HAProxy 使用整个 sun_path 长度作为地址长度。其他一些程序,如 socat,默认只使用字符串长度。在 socat 中对任何抽象套接字定义传递选项 ",unix-tightsocklen=0",以使其与 HAProxy 兼容。
设置要读取、加载并应用于此后端中可用服务器的服务器状态文件。
可用于节
| 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> 参数构建。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<prefix> 用于构建服务器名称的前缀。<num | range> 如果提供了 <num>,此模板将初始化 <num> 个服务器,其中1到 <num> 作为服务器名称后缀。也可以使用数字范围 <num_low>-<num_high> 来使用 <num_low> 到 <num_high> 作为服务器名称后缀。<fqdn> 此模板初始化的所有服务器的FQDN。<port> 与 "server" <port> 参数具有相同的含义(请参阅 "server" 关键字)。<params*> "server" 关键字支持的所有剩余服务器参数。
# 初始化 3 个服务器,名称分别为 srv1、srv2 和 srv3, # FQDN 为 google.com,并启用了健康检查。 server-template srv 1-3 google.com:80 check # 或 server-template srv 3 google.com:80 check # 将等同于: server srv1 google.com:80 check server srv2 google.com:80 check server srv3 google.com:80 check
设置出站连接的源地址
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<addr> 是HAProxy在连接到服务器之前将绑定的IPv4地址。此地址也用作健康检查的源地址。默认值0.0.0.0表示系统将选择最合适的地址来到达其目的地。可选地,可以在地址前使用地址族前缀来强制使用该族,无论地址格式如何,这对于指定没有斜杠 ('/') 的unix套接字路径很有用。目前支持的前缀有: - 'ipv4@' -> 地址始终为IPv4 - 'ipv6@' -> 地址始终为IPv6 - 'unix@' -> 地址是本地unix套接字的路径 - 'abns@' -> 地址位于抽象命名空间中(仅限Linux) 您可能希望在地址参数中引用一些环境变量,请参阅关于环境变量的 section 2.3。<port> 是可选端口。通常不需要它,但在某些非常特定的上下文中可能有用。默认值零表示系统将选择一个空闲端口。请注意,后端不支持端口范围。如果要强制使用端口范围,则必须在每条 "server" 行上指定它们。<addr2> 是在全透明代理模式下转发连接时向服务器显示的IP地址。目前仅在某些打补丁的Linux内核上支持此功能。当指定此地址时,连接到服务器的客户端将显示此地址,而健康检查仍将使用地址 <addr>。<port2> 是在全透明代理模式下转发连接时向服务器显示的可选端口(请参阅上面的 <addr2>)。默认值零表示系统将选择一个空闲端口。<hdr> 是一个HTTP标头的名称,用于从中获取要绑定的IP。这是一个逗号分隔的标头列表的名称,其中可以包含多个IP地址。默认情况下,使用最后一个出现。这旨在与X-Forwarded-For标头配合使用,并自动绑定到上一个代理(通常是Stunnel)看到的客户端IP地址。为了使用除最后一个之外的其他出现,请参阅下面的 <occ> 参数。当未找到标头(或出现)时,不执行绑定,以便使用代理的默认IP地址。另请记住,标头名称不区分大小写,与任何HTTP标头一样。<occ> 是用于多值标头中要使用的值的出现编号。这与 "hdr_ip(<hdr>)" 结合使用,以指定要用于源IP地址的出现。正值表示从第一次出现开始的位置,1是第一次出现。负值表示相对于最后一次出现的位置,-1是最后一次出现。这对于X-Forwarded-For标头在基础设施入口点设置并且必须在几个代理层之后使用的情况很有帮助。未指定此值时,假定为-1。此处传递零将禁用该功能。<name> 是一个可选接口名称,用于绑定到此接口以进行出站流量。在支持此功能的系统上(目前仅限Linux),这允许将所有流量绑定到服务器到此接口,即使它不是系统根据路由表选择的接口。应谨慎使用。请注意,使用此选项需要root权限。
在复杂的环境中,如果只允许特定地址连接到服务器,则"source"关键字非常有用。例如,当必须通过公共网关使用私有地址,并且已知系统无法自行确定适当的源地址时,可能需要使用它。可以通过“usesrc”可选关键字使用某些打了补丁的 Linux 内核上提供的扩展。它使得可以使用不属于系统本身的 IP 地址连接到服务器。这被称为“完全透明代理模式”。为了实现这一点,目标服务器必须通过运行 HAProxy 的机器将流量路由回此地址,并且通常必须在此机器上启用 IP 转发。在这种“完全透明代理”模式下,可以强制向服务器提供特定的 IP 地址。实际上,这种用法并不多见。更常见的用法是告诉 HAProxy 提供客户端的 IP 地址。为此,有两种方法: - 提供客户端的 IP 和端口地址。这是最透明的模式,但当机器上启用了 IP 连接跟踪时可能会导致问题,因为同一个连接可能会以不同的状态被看到两次。然而,这个解决方案的巨大优势在于,它不会将系统限制在 64k 个出站地址+端口对,因为可以使用所有客户端范围。 - 仅提供客户端的 IP 地址并选择一个备用端口。这个解决方案仍然非常优雅,但透明度稍低(下游防火墙日志将与上游不匹配)。它还具有将并发连接数限制为通常的 64k 端口的缺点。然而,由于上游和下游端口不同,机器上的本地 IP 连接跟踪不会因为同一会话的重用而感到困扰。此选项设置后端中所有服务器的默认源。它也可以在“defaults”部分中指定。使用"source"服务器选项可以在服务器级别上进行更精细的源地址规范。有关更多信息,请参阅第 5 节。为了工作,“usesrc”需要 root 权限。
backend private # 使用我们的 192.168.1.200 源地址连接到服务器 source 192.168.1.200 backend transparent_ssl1 # 从客户端的源地址连接到 SSL 场 source 192.168.1.200 usesrc clientip backend transparent_ssl2 # 从客户端的源地址和端口连接到 SSL 场 # 如果本地机器上存在 IP conntrack,则不推荐使用。 source 192.168.1.200 usesrc client backend transparent_ssl3 # 从客户端的源地址连接到 SSL 场。它 # 对 conntrack 更友好。 source 192.168.1.200 usesrc clientip backend transparent_smtp # 使用 Tproxy 版本 4 从客户端的源地址/端口连接到 SMTP 场。 source 0.0.0.0 usesrc clientip backend transparent_http # 使用上一个代理看到的客户端 IP 连接到服务器。 source 0.0.0.0 usesrc hdr_ip(x-forwarded-for,-1)
如果/除非条件匹配,则启用统计信息管理级别
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
此语句在满足 if/unless 条件时启用统计信息的管理员级别。管理员级别允许从 Web 界面启用/禁用服务器。默认情况下,出于安全原因,统计信息页面是只读的。注意:在多进程模式(nbproc > 1)下,请谨慎使用此功能,除非您了解其作用:进程之间不共享内存,这可能导致行为不确定。目前,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
启用带身份验证的统计信息,并为一个账户授予访问权限
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<user> 是要授予访问权限的用户名 <passwd> 是与此用户关联的明文密码
此语句启用具有默认设置的统计信息,并限制对声明用户的访问。它可以根据需要重复多次以允许任意数量的用户。当用户尝试访问统计信息而没有有效帐户时,将返回“401 Forbidden”响应,以便浏览器要求用户提供有效的用户和密码。返回给浏览器的实际领域可以使用“stats realm”配置。由于身份验证方法是 HTTP 基本身份验证,密码在网络上以明文形式传输。因此,决定配置也使用明文密码来提醒用户这些密码不应敏感,也不应与其他帐户共享。还可以使用“stats scope”缩小报告中显示的代理范围。尽管此语句本身足以启用统计信息报告,但建议设置所有其他设置以避免依赖默认的、不明显的参数。
# 公共访问(仅限于此后端) backend public_www server srv1 192.168.0.1:80 stats enable stats hide-version stats scope . stats uri /admin?stats stats realm HAProxy\ Statistics stats auth admin1:AdMiN123 stats auth admin2:AdMiN321 # 内部监控访问(无限制) backend private_monitoring stats enable stats uri /admin?stats stats refresh 5s
使用默认设置启用统计报告
可用于节
| 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 版本报告
可用于节
| 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
统计信息的访问控制
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
与 "http-request" 类似,这组选项允许精确控制对统计信息的访问。每个选项后面可以跟 if/unless 和 acl。第一个匹配条件(或没有条件的选项)的选项是最终的。对于 "deny",将返回 403 错误;对于 "allow",将执行正常处理;对于 "auth",将返回 401/407 错误代码,以便客户端被要求输入用户名和密码。每个实例的 http-request 语句数量没有固定限制。
启用统计信息并设置身份验证领域
可用于节
| 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
启用带自动刷新的统计信息
可用于节
| 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
启用统计信息并限制访问范围
可用于节
| 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
在统计页面上启用描述的报告。
可用于节
| 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
在统计页面上启用额外信息的报告
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
在统计信息页面上启用报告附加信息: - cap: 功能(代理) - mode: tcp, http 或 health 之一(代理) - id: SNMP ID(代理、套接字、服务器) - IP(套接字、服务器) - cookie(后端、服务器) 尽管仅此语句就足以启用统计信息报告,但建议设置所有其他设置,以避免依赖默认的不明显参数。默认行为是不显示此信息。
在统计页面上启用主机名的报告。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<name> 是一个可选的要报告的名称。如果未指定,则自动使用全局部分的节点名称。
此语句对于向其客户提供共享服务的用户非常有用,在为每个客户提供的统计页面上,节点或描述可能会有所不同。默认行为是不显示主机名。虽然仅此语句就足以启用统计报告,但建议设置所有其他设置,以避免依赖于默认的不明显参数。
# 内部监控访问(无限制) backend private_monitoring stats enable stats show-node Europe-1 stats uri /admin?stats stats refresh 5s
启用统计信息并定义访问它们的 URI 前缀
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<prefix> 是任何将被重定向到统计信息的 URI 的前缀。此前缀可能包含一个问号('?')以指示查询字符串的一部分。
统计信息 URI 在转发的流量上被拦截,因此它显示为正常应用程序中的页面。强烈建议确保所选 URI 永远不会出现在应用程序中,否则将永远无法在应用程序中访问它。haproxy 中编译的默认 URI 是 "/haproxy?stats",但这可以在构建时更改,因此最好始终在此处显式指定它。通常在 URI 中包含问号是一个好主意,这样中间代理就不会缓存结果。此外,由于任何以该前缀开头的字符串都将被接受为统计信息请求,因此问号有助于确保没有有效的 URI 以相同的词开头。有时使用 "/" 作为 URI 前缀非常方便,并将其放在自己的“listen”实例中。这使得将地址或端口专用于统计信息变得容易。尽管此语句本身足以启用统计信息报告,但建议设置所有其他设置以避免依赖默认的、不明显的参数。
# 公共访问(仅限于此后端) backend public_www server srv1 192.168.0.1:80 stats enable stats hide-version stats scope . stats uri /admin?stats stats realm HAProxy\ Statistics stats auth admin1:AdMiN123 stats auth admin2:AdMiN321 # 内部监控访问(无限制) backend private_monitoring stats enable stats uri /admin?stats stats refresh 5s
定义一个请求模式匹配条件,以将用户粘滞到一台服务器上
可用于节
| 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 之间的粘性变得非常容易。注意:除非您知道自己在做什么:内存不会在进程之间共享,否则请考虑不要在多进程模式(nbproc > 1)下使用此功能,这可能导致随机行为。
# 将 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
定义一个请求模式,将用户与服务器关联起来
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
注意:此形式等同于 "stick match" 后跟 "stick store-request",所有参数相同。请参考这两个关键字了解详情。它仅为方便编写更易于维护的配置而提供。注意:在多进程模式(nbproc > 1)下,请谨慎使用此功能,除非您了解其作用:进程之间不共享内存,这可能导致行为不确定。
# 以下形式... 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
定义一个用于在粘滞表中创建条目的请求模式
可用于节
| 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”规则在建立服务器连接后进行评估,以便表将包含处理请求的真实服务器。注意:除非您知道自己在做什么:内存不会在进程之间共享,否则请考虑不要在多进程模式(nbproc > 1)下使用此功能,这可能导致随机行为。
# 将 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
为当前部分配置粘滞表
可用于节
| 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" 类型表中的最大字符数(请参阅上面的 type "string")。或者是 "binary" 类型表中的块字节数。更改此参数时要小心,因为内存使用量将按比例增加。<size> 是可以容纳在表中的最大条目数。此值直接影响内存使用。每个条目大约计算 50 字节,加上字符串的大小(如果有)。大小支持后缀 "k"、"m"、"g",分别表示 2^10、2^20 和 2^30 因子。[nopurge] 表示当表满时,我们拒绝清除较旧的条目。如果未指定,并且当 haproxy 想要存储一个条目时表已满,它将刷新一些最旧的条目以释放一些空间给新的条目。这通常是期望的行为。在某些特定情况下,可能需要拒绝新条目而不是清除旧条目。当要存储的数据量远远超出硬件限制时,我们宁愿不向新客户端提供访问权限,也不愿拒绝已连接的客户端。使用此参数时,请确保正确设置 "expire" 参数(请参阅下文)。<peersect> 是用于复制的 peers 部分的名称。将键与服务器 ID 相关联的条目会与此部分中声明的远程对等体保持同步。在软重启期间,所有条目也会自动从本地对等体(旧进程)中学习。注意:每个 peers 部分只能被属于同一唯一进程的表引用。<expire> 定义了条目自上次创建、刷新或匹配以来在表中的最大持续时间。过期延迟使用标准时间格式定义,类似于各种超时。最大持续时间略高于 24 天。有关更多信息,请参阅第 2.4 节。如果未指定此延迟,则会话不会自动过期,但一旦满了,旧条目将被删除。如果未指定过期延迟,请确保不要使用 "nopurge" 参数。<data_type> 用于在粘性表中存储附加信息。ACL 可以使用它来控制与匹配粘性表的客户端活动相关的各种标准。对于此处指定的每个项目,每个条目的大小都会增加,以便可以容纳附加数据。一个条目可以存储多种数据类型。可以在 "store" 关键字之后指定多个数据类型,作为逗号分隔列表。或者,可以重复 "store" 关键字后跟一个或多个数据类型。除了自动检测和启用的 "server_id" 类型外,所有数据类型都必须明确声明才能存储。如果 ACL 引用了未存储的数据类型,则 ACL 将简单地不匹配。某些数据类型需要一个参数,该参数必须紧跟在类型之后并在括号之间传递。请参阅下面支持的数据类型及其参数。
可以随条目存储的数据类型如下: - server_id:这是一个整数,它保存分配给请求的服务器的数字 ID。它由"stick match"、"stick store" 和"stick on"规则使用。当被引用时,它会自动启用。 - gpc0:第一个通用计数器。它是一个正的 32 位整数,可用于任何目的。大多数情况下,它用于在某些条目上放置一个特殊标签,例如记录检测到特定行为并必须在未来匹配中知晓。 - gpc0_rate(<period>):第一个通用计数器在一段时间内的增量率。它是一个正的 32 位整数,可用于任何目的。就像 <gpc0> 一样,它计算事件,但不是保留累积数字,而是维护计数器增加的速率。大多数情况下,它用于衡量某些事件(例如,对特定 URL 的请求)发生的频率。 - gpc1:第二个通用计数器。它是一个正的 32 位整数,可用于任何目的。大多数情况下,它用于在某些条目上放置一个特殊标签,例如记录检测到特定行为并必须在未来匹配中知晓。 - gpc1_rate(<period>):第二个通用计数器在一段时间内的增量率。它是一个正的 32 位整数,可用于任何目的。就像 <gpc1> 一样,它计算事件,但不是保留累积数字,而是维护计数器增加的速率。大多数情况下,它用于衡量某些事件(例如,对特定 URL 的请求)发生的频率。 - 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 请求速率,以每周期请求数计算。无论它们是否是有效请求都无关紧要。请注意,当客户端使用 keep-alive 时,这与会话不同。 - http_err_cnt:HTTP 错误计数。它是一个正的 32 位整数,用于计算匹配此条目的客户端引起的 HTTP 请求错误的绝对数量。错误计数包括无效和截断的请求,以及被拒绝或被限制的请求,以及失败的身份验证。如果服务器响应 4xx,则该请求也被计为错误,因为它是客户端触发的错误(例如漏洞扫描)。 - http_err_rate(<period>):频率计数器(占用 12 字节)。它接受一个整数参数 <period>,该参数以毫秒为单位指示测量平均值的周期长度。它报告该周期内的平均 HTTP 请求错误率,以每周期请求数计算(有关哪些被计为错误,请参阅上面的 http_err_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 以获得更好的公平性。每个代理只有一个粘性表。在撰写本文档时,每个代理拥有多个表似乎没有用处。如果需要,只需创建一个带有粘性表的虚拟后端并引用它即可。重要的是要理解,基于学习信息的粘性有一些限制,包括所有学习到的关联在重启时都会丢失,除非正确配置了对等体以在重启时传输此类信息(推荐)。总的来说,它可以作为补充,但不一定作为唯一的粘性。最后,存储许多数据类型时,内存需求可能很大。实际上,将上述所有指标一次性存储在每个条目中需要 116 字节/条目,或者对于 100 万个条目的表需要 116 MB。这绝对不能忽视。
# 在 5 分钟内跟踪多达 100 万个 IP 地址的计数器 # 并存储一个通用计数器和在 30 秒滑动窗口上计算的 # 平均连接速率。 stick-table type ip size 1m expire 5m store gpc0,conn_rate(30s)
定义一个用于在粘滞表中创建条目的响应模式
可用于节
| 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 rep_ssl_hello_type 2 # 使用 tcp content accepts 来检测 ssl 客户端和服务器 hello。 tcp-request inspect-delay 5s tcp-request content accept if clienthello # 默认情况下,响应检查延迟没有超时。 tcp-response content accept if serverhello # SSL 会话 ID (SSLID) 可能存在于客户端或服务器 hello 中。 # 它的长度在偏移量 43 处以 1 字节编码,其值从偏移量开始 # 在 44 处。 # 如果是客户端 hello,则匹配并学习请求。 stick on payload_lv(43,1) if clienthello # 如果是服务器 hello,则学习响应。 stick store-response payload_lv(43,1) if serverhello server s1 192.168.1.1:443 server s2 192.168.1.1:443
打开一个新连接
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
当一个应用程序依赖于多个 TCP 端口,或者当 HAProxy 在单个后端中负载均衡多个服务时,有必要在将服务器视为可操作之前单独探测所有服务。当服务器行上没有配置 TCP 端口,也没有服务器端口指令时,'tcp-check connect port <port>' 必须是序列的第一步。在 tcp-check 规则集中,'connect' 是必需的,并且也必须以 'connect' 规则开始规则集。目的是确保管理员知道他们在做什么。参数:它们是可选的,可用于描述 HAProxy 应如何打开和使用 TCP 连接。port 如果未设置,则使用检查端口或服务器端口。它告诉 HAProxy 在哪里打开连接。<port> 必须是有效的 TCP 端口源整数,从 1 到 65535。send-proxy 发送一个 PROXY 协议字符串 ssl 打开一个加密连接
# 检查服务器上的 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 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
指定在通用健康检查期间要收集和分析的数据
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<match> 是一个关键字,指示如何在响应中查找特定模式。该关键字可以是 "string"、"rstring" 或 binary。该关键字前面可以加上感叹号 ("!") 来否定匹配。感叹号和关键字之间允许有空格。有关支持的关键字的更多详细信息,请参见下文。<pattern> 是要查找的模式。它可以是字符串或正则表达式。如果模式包含空格,则必须用普通的反斜杠 ('\') 进行转义。如果匹配设置为 binary,则模式必须以偶数个十六进制数字序列的形式传递。每两个数字的序列将代表一个字节。十六进制数字可以使用大写或小写。
可用的匹配项有意与其 http-check 对应项相似: string <string>:测试响应缓冲区中的精确字符串匹配。如果响应缓冲区包含此精确字符串,则健康检查响应将被视为有效。如果 "string" 关键字前面有 "!",则如果正文包含此字符串,则响应将被视为无效。这可用于在协议响应中查找强制模式,或在协议横幅中出现特定错误时检测失败。rstring <regex>:在响应缓冲区上测试正则表达式。如果响应缓冲区匹配此表达式,则健康检查响应将被视为有效。如果 "rstring" 关键字前面有 "!",则如果正文匹配此表达式,则响应将被视为无效。binary <hexstring>:测试响应缓冲区中的精确字符串(十六进制形式)。如果响应缓冲区包含此精确十六进制字符串,则健康检查响应将被视为有效。目的是匹配二进制协议上的数据。重要的是要注意,响应将受限于由全局"tune.chksize"选项定义的特定大小,该选项默认为 16384 字节。因此,当使用 "string"、"rstring" 或 binary 时,太大的响应可能不包含强制模式。如果绝对需要大响应,可以通过设置全局变量来更改默认最大大小。然而,值得记住的是,解析非常大的响应会浪费一些 CPU 周期,尤其是使用正则表达式时,并且最好始终将检查重点放在较小的资源上。此外,在当前状态下,检查将找不到响应中空字符之后的任何字符串或正则表达式。同样,不可能请求匹配空字符。
# 执行 POP 检查 option tcp-check tcp-check expect string +OK\ POP3\ ready # 执行 IMAP 检查 option tcp-check tcp-check expect string *\ OK\ IMAP4\ ready # 查找 redis 主服务器 option tcp-check tcp-check send PING\r\n tcp-check expect string +PONG tcp-check send info\ replication\r\n tcp-check expect string role:master tcp-check send QUIT\r\n tcp-check expect string +OK
在通用健康检查期间指定一个要作为问题发送的字符串
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<data>:在通用健康检查会话期间要作为问题发送的数据。目前,<data> 必须是字符串。
# 查找 redis 主服务器 option tcp-check tcp-check send info\ replication\r\n tcp-check expect string role:master
指定一个十六进制数字字符串,在原始 TCP 健康检查期间作为二进制问题发送
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<data>:在通用健康检查会话中要发送作为问题的数据。目前,<data> 必须是字符串。<hexstring>:测试响应缓冲区中的精确字符串的十六进制形式匹配。如果响应的缓冲区包含此精确十六进制字符串,则健康检查响应将被视为有效。目的是在二进制协议上发送二进制数据以进行查询。
# 二进制 redis 检查 option tcp-check tcp-check send-binary 50494e470d0a # PING\r\n tcp-check expect binary 2b504F4e47 # +PONG
根据第 4 层条件对传入连接执行操作
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 否![]() |
<action> 定义了如果条件适用要执行的操作。见下文。<condition> 是一个标准的仅第 4 层的基于 ACL 的条件(见第 7 节)。
Immediately after acceptance of a new incoming connection, it is possible to evaluate some conditions to decide whether this connection must be accepted or dropped or have its counters tracked. Those conditions cannot make use of any data contents because the connection has not been read from yet, and the buffers are not yet allocated. This is used to selectively and very quickly accept or drop connections from various sources with a very low overhead. If some contents need to be inspected in order to take the decision, the "tcp-request content" statements must be used instead. The "tcp-request connection" rules are evaluated in their exact declaration order. If no rule matches or if there is no rule, the default action is to accept the incoming connection. There is no specific limit to the number of rules which may be inserted. Four types of actions are supported : - accept : accepts the connection if the condition is true (when used with "if") or false (when used with "unless"). The first such rule executed ends the rules evaluation. - reject : rejects the connection if the condition is true (when used with "if") or false (when used with "unless"). The first such rule executed ends the rules evaluation. Rejected connections do not even become a session, which is why they are accounted separately for in the stats, as "denied connections". They are not considered for the session rate-limit and are not logged either. The reason is that these rules should only be used to filter extremely high connection rates such as the ones encountered during a massive DDoS attack. Under these extreme conditions, the simple action of logging each event would make the system collapse and would considerably lower the filtering capacity. If logging is absolutely desired, then "tcp-request content" rules should be used instead, as "tcp-request session" rules will not log either. - expect-proxy layer4 : configures the client-facing connection to receive a PROXY protocol header before any byte is read from the socket. This is equivalent to having the "accept-proxy" keyword on the "bind" line, except that using the TCP rule allows the PROXY protocol to be accepted only for certain IP address ranges using an ACL. This is convenient when multiple layers of load balancers are passed through by traffic coming from public hosts. - expect-netscaler-cip layer4 : configures the client-facing connection to receive a NetScaler Client IP insertion protocol header before any byte is read from the socket. This is equivalent to having the "accept-netscaler-cip" keyword on the "bind" line, except that using the TCP rule allows the PROXY protocol to be accepted only for certain IP address ranges using an ACL. This is convenient when multiple layers of load balancers are passed through by traffic coming from public hosts. - capture <sample> len <length> : This only applies to "tcp-request content" rules. It captures sample expression <sample> from the request buffer, and converts it to a string of at most <len> characters. The resulting string is stored into the next request "capture" slot, so it will possibly appear next to some captured HTTP headers. It will then automatically appear in the logs, and it will be possible to extract it using sample fetch rules to feed it into headers or anything. The length should be limited given that this size will be allocated for each capture during the whole session life. Please check section 7.3 (Fetching samples) and "capture request header" for more information. - { track-sc0 | track-sc1 | track-sc2 } <key> [table <table>] : enables tracking of sticky counters from current connection. These rules do not stop evaluation and do not change default action. The number of counters that may be simultaneously tracked by the same connection is set in MAX_SESS_STKCTR at build time (reported in haproxy -vv) which defaults to 3, so the track-sc number is between 0 and (MAX_SESS_STCKTR-1). The first "track-sc0" rule executed enables tracking of the counters of the specified table as the first set. The first "track-sc1" rule executed enables tracking of the counters of the specified table as the second set. The first "track-sc2" rule executed enables tracking of the counters of the specified table as the third set. It is a recommended practice to use the first set of counters for the per-frontend counters and the second set for the per-backend ones. But this is just a guideline, all may be used everywhere. These actions take one or two arguments : <key> is mandatory, and is a sample expression rule as described in section 7.3. It describes what elements of the incoming request or connection will be analyzed, extracted, combined, and used to select which table entry to update the counters. Note that "tcp-request connection" cannot use content-based fetches. <table> is an optional table to be used instead of the default one, which is the stick-table declared in the current proxy. All the counters for the matches and updates for the key will then be performed in that table until the session ends. Once a "track-sc*" rule is executed, the key is looked up in the table and if it is not found, an entry is allocated for it. Then a pointer to that entry is kept during all the session's life, and this entry's counters are updated as often as possible, every time the session's counters are updated, and also systematically when the session ends. Counters are only updated for events that happen after the tracking has been started. For example, connection counters will not be updated when tracking layer 7 information, since the connection event happens before layer7 information is extracted. If the entry tracks concurrent connection counters, one connection is counted for as long as the entry is tracked, and the entry will not expire during that time. Tracking counters also provides a performance advantage over just checking the keys, because only one table lookup is performed for all ACL checks that make use of it. - sc-inc-gpc0(<sc-id>): The "sc-inc-gpc0" increments the GPC0 counter according to the sticky counter designated by <sc-id>. If an error occurs, this action silently fails and the actions evaluation continues. - sc-inc-gpc1(<sc-id>): The "sc-inc-gpc1" increments the GPC1 counter according to the sticky counter designated by <sc-id>. If an error occurs, this action silently fails and the actions evaluation continues. - sc-set-gpt0(<sc-id>) { <int> | <expr> }: This action sets the 32-bit unsigned GPT0 tag according to the sticky counter designated by <sc-id> and the value of <int>/<expr>. The expected result is a boolean. If an error occurs, this action silently fails and the actions evaluation continues. - set-src <expr> : Is used to set the source IP address to the value of specified expression. Useful if you want to mask source IP for privacy. If you want to provide an IP from a HTTP header use "http-request set-src".
<expr> 是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成。
tcp-request connection set-src src,ipmask(24)
在可能的情况下,set-src 会保留原始源端口,只要地址系列允许,否则源端口设置为 0。- set-src-port <expr>:用于将源端口地址设置为指定表达式的值。
<expr> 是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成。
tcp-request connection set-src-port int(4000)
在可能的情况下,set-src-port 会保留原始源地址,只要地址系列支持端口,否则它会将源地址强制设置为 IPv4 "0.0.0.0",然后再重写端口。- set-dst <expr>:用于将目标 IP 地址设置为指定表达式的值。如果您想在日志中掩盖 IP 以保护隐私,则很有用。如果您想提供来自 HTTP 标头的 IP,请使用“http-request set-dst”。如果您想连接到新的地址/端口,请在后端使用“0.0.0.0:0”作为服务器地址。<expr> 是一个标准的 HAProxy 表达式,由样本提取后跟一些转换器组成。
tcp-request connection set-dst dst,ipmask(24) tcp-request connection set-dst ipv4(10.0.0.1)
在可能的情况下,set-dst 会保留原始目标端口,只要地址系列允许,否则目标端口设置为 0。- set-dst-port <expr>:用于将目标端口地址设置为指定表达式的值。如果您想连接到新的地址/端口,请在后端使用“0.0.0.0:0”作为服务器地址。<expr> 是一个标准的 HAProxy 表达式,由样本提取后跟一些转换器组成。
tcp-request connection set-dst-port int(4000)
When possible, set-dst-port preserves the original destination address as long as the address family supports a port, otherwise it forces the destination address to IPv4 "0.0.0.0" before rewriting the port. - "silent-drop" : This stops the evaluation of the rules and makes the client-facing connection suddenly disappear using a system-dependent way that tries to prevent the client from being notified. The effect it then that the client still sees an established connection while there's none on HAProxy. The purpose is to achieve a comparable effect to "tarpit" except that it doesn't use any local resource at all on the machine running HAProxy. It can resist much higher loads than "tarpit", and slow down stronger attackers. It is important to understand the impact of using this mechanism. All stateful equipment placed between the client and HAProxy (firewalls, proxies, load balancers) will also keep the established connection for a long time and may suffer from this action. On modern Linux systems running with enough privileges, the TCP_REPAIR socket option is used to block the emission of a TCP reset. On other systems, the socket's TTL is reduced to 1 so that the TCP reset doesn't pass the first router, though it's still delivered to local networks. Do not use it unless you fully understand how it works. Note that the "if/unless" condition is optional. If no condition is set on the action, it is simply performed unconditionally. That can be useful for "track-sc*" actions as well as for changing the default action to a reject.
接受所有来自白名单主机的连接,拒绝过快的连接而不计数,并跟踪已接受的连接。这导致来自滥用来源的连接速率受到限制。tcp-request connection accept if { src -f /etc/haproxy/whitelist.lst } tcp-request connection reject if { src_conn_rate gt 10 } tcp-request connection track-sc0 src
接受所有来自白名单主机的连接,计算所有其他连接并拒绝过快的连接。这导致滥用者只要不减速就会被阻止。tcp-request connection accept if { src -f /etc/haproxy/whitelist.lst } tcp-request connection track-sc0 src tcp-request connection reject if { sc0_conn_rate gt 10 }
为来自所有已知代理的流量启用 PROXY 协议。tcp-request connection expect-proxy layer4 if { src -f proxies.lst }
有关 ACL 的用法,请参见第 7 节。
根据第 4-7 层条件对新会话执行操作
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
<action> 定义了如果条件适用要执行的操作。见下文。<condition> 是一个标准的第 4-7 层基于 ACL 的条件(见第 7 节)。
A request's contents can be analyzed at an early stage of request processing called "TCP content inspection". During this stage, ACL-based rules are evaluated every time the request contents are updated, until either an "accept" or a "reject" rule matches, or the TCP request inspection delay expires with no matching rule. The first difference between these rules and "tcp-request connection" rules is that "tcp-request content" rules can make use of contents to take a decision. Most often, these decisions will consider a protocol recognition or validity. The second difference is that content-based rules can be used in both frontends and backends. In case of HTTP keep-alive with the client, all tcp-request content rules are evaluated again, so haproxy keeps a record of what sticky counters were assigned by a "tcp-request connection" versus a "tcp-request content" rule, and flushes all the content-related ones after processing an HTTP request, so that they may be evaluated again by the rules being evaluated again for the next request. This is of particular importance when the rule tracks some L7 information or when it is conditioned by an L7-based ACL, since tracking may change between requests. Content-based rules are evaluated in their exact declaration order. If no rule matches or if there is no rule, the default action is to accept the contents. There is no specific limit to the number of rules which may be inserted. Several types of actions are supported : - accept : the request is accepted - do-resolve: perform a DNS resolution - reject : the request is rejected and the connection is closed - capture : the specified sample expression is captured - set-priority-class <expr> | set-priority-offset <expr> - { track-sc0 | track-sc1 | track-sc2 } <key> [table <table>] - sc-inc-gpc0(<sc-id>) - sc-inc-gpc1(<sc-id>) - sc-set-gpt0(<sc-id>) { <int> | <expr> } - set-dst <expr> - set-dst-port <expr> - set-var(<var-name>) <expr> - unset-var(<var-name>) - silent-drop - send-spoe-group <engine-name> <group-name> - use-service <service-name> They have the same meaning as their counter-parts in "tcp-request connection" so please refer to that section for a complete description. For "do-resolve" action, please check the "http-request do-resolve" configuration section. While there is nothing mandatory about it, it is recommended to use the track-sc0 in "tcp-request connection" rules, track-sc1 for "tcp-request content" rules in the frontend, and track-sc2 for "tcp-request content" rules in the backend, because that makes the configuration more readable and easier to troubleshoot, but this is just a guideline and all counters may be used everywhere. Note that the "if/unless" condition is optional. If no condition is set on the action, it is simply performed unconditionally. That can be useful for "track-sc*" actions as well as for changing the default action to a reject. It is perfectly possible to match layer 7 contents with "tcp-request content" rules from a TCP proxy, since HTTP-specific ACL matches are able to preliminarily parse the contents of a buffer before extracting the required data. If the buffered contents do not parse as a valid HTTP message, then the ACL does not match. The parser which is involved there is exactly the same as for all other HTTP processing, so there is no risk of parsing something differently. In an HTTP frontend or an HTTP backend, it is guaranteed that HTTP contents will always be immediately present when the rule is evaluated first because the HTTP parsing is performed in the early stages of the connection processing, at the session level. But for such proxies, using "http-request" rules is much more natural and recommended. Tracking layer7 information is also possible provided that the information are present when the rule is processed. The rule processing engine is able to wait until the inspect delay expires when the data to be tracked is not yet available. The "set-dst" and "set-dst-port" are used to set respectively the destination IP and port. More information on how to use it at "http-request set-dst". The "set-var" is used to set the content of a variable. The variable is declared inline. For "tcp-request session" rules, only session-level variables can be used, without any layer7 contents. <var-name> The name of the variable starts with an indication about its scope. The scopes allowed are: "proc" : the variable is shared with the whole process "sess" : the variable is shared with the whole session "txn" : the variable is shared with the transaction (request and response) "req" : the variable is shared only during request processing "res" : the variable is shared only during response processing This prefix is followed by a name. The separator is a '.'. The name may only contain characters 'a-z', 'A-Z', '0-9', '.' and '_'. <expr> Is a standard HAProxy expression formed by a sample-fetch followed by some converters. The "unset-var" is used to unset a variable. See above for details about <var-name>. The "set-priority-class" is used to set the queue priority class of the current request. The value must be a sample expression which converts to an integer in the range -2047..2047. Results outside this range will be truncated. The priority class determines the order in which queued requests are processed. Lower values have higher priority. The "set-priority-offset" is used to set the queue priority timestamp offset of the current request. The value must be a sample expression which converts to an integer in the range -524287..524287. Results outside this range will be truncated. When a request is queued, it is ordered first by the priority class, then by the current timestamp adjusted by the given offset in milliseconds. Lower values have higher priority. Note that the resulting timestamp is is only tracked with enough precision for 524,287ms (8m44s287ms). If the request is queued long enough to where the adjusted timestamp exceeds this value, it will be misidentified as highest priority. Thus it is important to set "timeout queue" to a value, where when combined with the offset, does not exceed this limit. The "send-spoe-group" is used to trigger sending of a group of SPOE messages. To do so, the SPOE engine used to send messages must be defined, as well as the SPOE group to send. Of course, the SPOE engine must refer to an existing SPOE filter. If not engine name is provided on the SPOE filter line, the SPOE agent name must be used. <engine-name> The SPOE engine name. <group-name> The SPOE group name as specified in the engine configuration. The "use-service" is used to executes a TCP service which will reply to the request and stop the evaluation of the rules. This service may choose to reply by sending any valid response or it may immediately close the connection without sending anything. Outside natives services, it is possible to write your own services in Lua. No further "tcp-request" rules are evaluated.
tcp-request content use-service lua.deny { src -f /etc/haproxy/blacklist.lst }
tcp-request content set-var(sess.my_var) src tcp-request content unset-var(sess.my_var2)
# 接受包含 Host 头部为 "example.com" 的 HTTP 请求 # 并拒绝所有其他请求。 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
# 如果客户端先发言,则拒绝 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 节。
设置在内容检测期间等待数据的最大允许时间
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
People using haproxy primarily as a TCP relay are often worried about the risk of passing any type of protocol to a server without any analysis. In order to be able to analyze the request contents, we must first withhold the data then analyze them. This statement simply enables withholding of data for at most the specified amount of time. TCP content inspection applies very early when a connection reaches a frontend, then very early when the connection is forwarded to a backend. This means that a connection may experience a first delay in the frontend and a second delay in the backend if both have tcp-request rules. Note that when performing content inspection, haproxy will evaluate the whole rules for every new chunk which gets in, taking into account the fact that those data are partial. If no rule matches before the aforementioned delay, a last check is performed upon expiration, this time considering that the contents are definitive. If no delay is set, haproxy will not wait at all and will immediately apply a verdict based on the available information. Obviously this is unlikely to be very useful and might even be racy, so such setups are not recommended. As soon as a rule matches, the request is released and continues as usual. If the timeout is reached and no rule matches, the default policy will be to let it pass through unaffected. For most protocols, it is enough to set it to a few seconds, as most clients send the full request immediately upon connection. Add 3 or more seconds to cover TCP retransmits but that's all. For some protocols, it may make sense to use large values, for instance to ensure that the client never talks before the server (e.g. SMTP), or to wait for a client to talk before passing data to the server (e.g. SSL). Note that the client timeout must cover at least the inspection delay, otherwise it will expire first. If the client closes the connection or if the buffer is full, the delay immediately expires since the contents will not be able to change anymore.
根据第 4-7 层条件对会话响应执行操作
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<action> 定义了如果条件适用要执行的操作。见下文。<condition> 是一个标准的第 4-7 层基于 ACL 的条件(见第 7 节)。
Response contents can be analyzed at an early stage of response processing called "TCP content inspection". During this stage, ACL-based rules are evaluated every time the response contents are updated, until either an "accept", "close" or a "reject" rule matches, or a TCP response inspection delay is set and expires with no matching rule. Most often, these decisions will consider a protocol recognition or validity. Content-based rules are evaluated in their exact declaration order. If no rule matches or if there is no rule, the default action is to accept the contents. There is no specific limit to the number of rules which may be inserted. Several types of actions are supported : - accept : accepts the response if the condition is true (when used with "if") or false (when used with "unless"). The first such rule executed ends the rules evaluation. - close : immediately closes the connection with the server if the condition is true (when used with "if"), or false (when used with "unless"). The first such rule executed ends the rules evaluation. The main purpose of this action is to force a connection to be finished between a client and a server after an exchange when the application protocol expects some long time outs to elapse first. The goal is to eliminate idle connections which take significant resources on servers with certain protocols. - reject : rejects the response if the condition is true (when used with "if") or false (when used with "unless"). The first such rule executed ends the rules evaluation. Rejected session are immediately closed. - set-var(<var-name>) <expr> Sets a variable. - unset-var(<var-name>) Unsets a variable. - sc-inc-gpc0(<sc-id>): This action increments the GPC0 counter according to the sticky counter designated by <sc-id>. If an error occurs, this action fails silently and the actions evaluation continues. - sc-inc-gpc1(<sc-id>): This action increments the GPC1 counter according to the sticky counter designated by <sc-id>. If an error occurs, this action fails silently and the actions evaluation continues. - sc-set-gpt0(<sc-id>) { <int> | <expr> } This action sets the 32-bit unsigned GPT0 tag according to the sticky counter designated by <sc-id> and the value of <int>/<expr>. The expected result is a boolean. If an error occurs, this action silently fails and the actions evaluation continues. - "silent-drop" : This stops the evaluation of the rules and makes the client-facing connection suddenly disappear using a system-dependent way that tries to prevent the client from being notified. The effect it then that the client still sees an established connection while there's none on HAProxy. The purpose is to achieve a comparable effect to "tarpit" except that it doesn't use any local resource at all on the machine running HAProxy. It can resist much higher loads than "tarpit", and slow down stronger attackers. It is important to understand the impact of using this mechanism. All stateful equipment placed between the client and HAProxy (firewalls, proxies, load balancers) will also keep the established connection for a long time and may suffer from this action. On modern Linux systems running with enough privileges, the TCP_REPAIR socket option is used to block the emission of a TCP reset. On other systems, the socket's TTL is reduced to 1 so that the TCP reset doesn't pass the first router, though it's still delivered to local networks. Do not use it unless you fully understand how it works. - send-spoe-group <engine-name> <group-name> Send a group of SPOE messages. Note that the "if/unless" condition is optional. If no condition is set on the action, it is simply performed unconditionally. That can be useful for for changing the default action to a reject. It is perfectly possible to match layer 7 contents with "tcp-response content" rules, but then it is important to ensure that a full response has been buffered, otherwise no contents will match. In order to achieve this, the best solution involves detecting the HTTP protocol during the inspection period. The "set-var" is used to set the content of a variable. The variable is declared inline. <var-name> The name of the variable starts with an indication about its scope. The scopes allowed are: "proc" : the variable is shared with the whole process "sess" : the variable is shared with the whole session "txn" : the variable is shared with the transaction (request and response) "req" : the variable is shared only during request processing "res" : the variable is shared only during response processing This prefix is followed by a name. The separator is a '.'. The name may only contain characters 'a-z', 'A-Z', '0-9', '.' and '_'. <expr> Is a standard HAProxy expression formed by a sample-fetch followed by some converters.tcp-request content set-var(sess.my_var) src
“unset-var”用于取消设置变量。有关<var-name>的详细信息,请参阅上文。
tcp-request content unset-var(sess.my_var)
“send-spoe-group”用于触发发送一组SPOE消息。为此,必须定义用于发送消息的SPOE引擎以及要发送的SPOE组。当然,SPOE引擎必须引用现有的SPOE过滤器。如果在SPOE过滤器行中未提供引擎名称,则必须使用SPOE代理名称。<engine-name>SPOE引擎名称。<group-name>引擎配置中指定的SPOE组名称。请参阅第7节了解ACL用法。
根据第 5 层条件对已验证的会话执行操作
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 否![]() |
<动作> 定义了如果条件适用时要执行的动作。见下文。 <条件> 是一个标准的仅第 5 层的基于 ACL 的条件(见第 7 节)。
Once a session is validated, (i.e. after all handshakes have been completed), it is possible to evaluate some conditions to decide whether this session must be accepted or dropped or have its counters tracked. Those conditions cannot make use of any data contents because no buffers are allocated yet and the processing cannot wait at this stage. The main use case it to copy some early information into variables (since variables are accessible in the session), or to keep track of some information collected after the handshake, such as SSL-level elements (SNI, ciphers, client cert's CN) or information from the PROXY protocol header (e.g. track a source forwarded this way). The extracted information can thus be copied to a variable or tracked using "track-sc" rules. Of course it is also possible to decide to accept/reject as with other rulesets. Most operations performed here could also be performed in "tcp-request content" rules, except that in HTTP these rules are evaluated for each new request, and that might not always be acceptable. For example a rule might increment a counter on each evaluation. It would also be possible that a country is resolved by geolocation from the source IP address, assigned to a session-wide variable, then the source address rewritten from an HTTP header for all requests. If some contents need to be inspected in order to take the decision, the "tcp-request content" statements must be used instead. The "tcp-request session" rules are evaluated in their exact declaration order. If no rule matches or if there is no rule, the default action is to accept the incoming session. There is no specific limit to the number of rules which may be inserted. Several types of actions are supported : - accept : the request is accepted - reject : the request is rejected and the connection is closed - { track-sc0 | track-sc1 | track-sc2 } <key> [table <table>] - sc-inc-gpc0(<sc-id>) - sc-inc-gpc1(<sc-id>) - sc-set-gpt0(<sc-id>) { <int> | <expr> } - set-var(<var-name>) <expr> - unset-var(<var-name>) - silent-drop These actions have the same meaning as their respective counter-parts in "tcp-request connection" and "tcp-request content", so please refer to these sections for a complete description. Note that the "if/unless" condition is optional. If no condition is set on the action, it is simply performed unconditionally. That can be useful for "track-sc*" actions as well as for changing the default action to a reject.
默认跟踪原始源地址,或者对于来自本地代理的连接,跟踪 PROXY 协议头中通告的地址。第一个连接级别的规则为这些连接启用了 PROXY 协议的接收,第二个规则跟踪我们在可选解码后决定保留的任何地址。tcp-request connection expect-proxy layer4 if { src -f proxies.lst } tcp-request session track-sc0 src
接受所有来自白名单主机的会话,拒绝过快的会话而不对其进行计数,并跟踪已接受的会话。这导致来自滥用来源的会话速率受到限制。tcp-request session accept if { src -f /etc/haproxy/whitelist.lst } tcp-request session reject if { src_sess_rate gt 10 } tcp-request session track-sc0 src
接受所有来自白名单主机的会话,对所有其他会话进行计数,并拒绝过快的会话。这导致滥用会话被阻止,直到它们减速为止。tcp-request session accept if { src -f /etc/haproxy/whitelist.lst } tcp-request session track-sc0 src tcp-request session reject if { sc0_sess_rate gt 10 }
有关 ACL 的用法,请参见第 7 节。
设置内容检测期间等待响应的最大允许时间
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
设置额外的检查超时,但仅在连接已经建立之后。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
If set, haproxy uses min("timeout connect", "inter") as a connect timeout for check and "timeout check" as an additional read timeout. The "min" is used so that people running with *very* long "timeout connect" (e.g. those who needed this due to the queue or tarpit) do not slow down their checks. (Please also note that there is no valid reason to have such long connect timeouts, because "timeout queue" and "timeout tarpit" can always be used to avoid that). If "timeout check" is not set haproxy uses "inter" for complete check timeout (connect + read) exactly like all <1.3.15 version. In most cases check request is much simpler and faster to handle than normal requests and people may want to kick out laggy servers so this timeout should be smaller than "timeout server". This parameter is specific to backends, but can be specified once for all in "defaults" sections. This is in fact one of the easiest solutions not to forget about it.
设置客户端侧的最大不活动时间。
可用于节
| 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"。此参数特定于前端(frontend),但可以在 "defaults" 部分中一次性指定。这实际上是确保不会遗忘的最简单解决方案之一。未指定的超时会导致无限超时,这是不推荐的。这种用法被接受并且有效,但在启动期间会报告警告,因为它可能导致系统中过期会话的积累,如果系统的超时设置也没有配置的话。这也适用于 HTTP/2 连接,这些连接将以 GOAWAY 关闭。
为半关闭连接设置客户端侧的不活动超时。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
不活动超时适用于客户端应确认或发送数据,而一端已关闭连接的情况。此超时与“timeout client”不同,因为它仅适用于单向关闭的连接。这对于避免在客户端未干净断开连接时,使连接长时间处于 FIN_WAIT 状态特别有用。此问题在 RDP 或 WebSocket 等长连接中尤其常见。请注意,当连接单向关闭时,此超时可能会覆盖“timeout tunnel”。它应用于已发送 GOAWAY 帧的空闲 HTTP/2 连接,通常表示连接将很快结束。此参数特定于前端,但可以在“defaults”部分统一指定。默认情况下未设置,因此半关闭的连接将使用其他超时(timeout.client 或 timeout.tunnel)。
设置等待服务器连接尝试成功的最大时间。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
如果服务器与 haproxy 位于同一局域网内,连接应立即建立(毫秒级)。无论如何,通过设置略高于 3 秒倍数的超时(例如 4 或 5 秒)来涵盖一个或多个 TCP 数据包丢失是一种好习惯。默认情况下,如果未指定,连接超时还会将队列和弹坑超时设置为相同的值。此参数特定于后端,但可以在“defaults”部分统一指定。这实际上是最容易记住的解决方案之一。未指定的超时将导致无限超时,这是不推荐的。此类用法是可接受的并且可以正常工作,但在启动时会报告警告,因为它可能导致系统中的失败会话累积,除非系统的超时也已配置。
设置等待新 HTTP 请求出现的最大允许时间
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
默认情况下,在保持活动(keep-alive)情况下等待新请求的时间由 "timeout http-request" 设置。然而,这并不总是方便的,因为有些人希望保持活动超时时间非常短,以便更快地释放连接,而另一些人则希望有更长的保持活动时间,但在请求开始后仍有较短的超时时间。"http-keep-alive" 超时涵盖了这些需求。它定义了在发送响应后等待新 HTTP 请求开始到来的时间。一旦看到请求的第一个字节,就会使用 "http-request" 超时来等待完整的请求到来。请注意,新请求之前的空行不会刷新超时时间,也不算作新请求。两个超时之间还有另一个区别:当连接在 http-keep-alive 超时期间过期时,不会返回错误,连接只是关闭。如果在 "http-request" 中等待连接完成时过期,则返回 HTTP 408 错误。通常情况下,将此值设置为几十到几百毫秒是最佳的,以便允许用户一次性获取页面的所有对象,但又不至于等待后续点击。此外,如果设置得非常小(例如 1 毫秒),它可能只接受流水线请求,而不接受非流水线请求。对于运行着数万到数十万客户端的大型网站来说,这可能是一个很好的权衡。如果未设置此参数,则应用 "http-request" 超时,如果两者都未设置,则较低级别的 "timeout client" 仍然适用。它应该在前端(frontend)中设置才能生效,除非前端处于 TCP 模式,在这种情况下将使用 HTTP 后端(backend)的超时。使用 HTTP/2 时,应用的是 "timeout client"。这样做是为了我们可以在 HTTP/1.1 中继续使用短的保持活动超时,而在 HTTP/2 中使用更长的超时(因为每个客户端只有一个连接,并且需要连接设置)。
设置等待完整 HTTP 请求的最大允许时间
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
为了提供 DoS 保护,可能需要降低接收完整 HTTP 请求的最大可接受时间,而又不影响客户端超时。这有助于防止在已建立的连接上不发送任何内容的滥用行为。客户端超时无法针对这种滥用提供良好的保护,因为它是不活动超时,这意味着如果攻击者偶尔发送一个字符,超时将不会触发。有了 HTTP 请求超时,无论客户端输入的速度如何,如果请求未及时完成,它都将被中止。当超时过期时,会向客户端发送 HTTP 408 响应以告知问题,并且连接会关闭。日志将报告终止代码 "cR"。一些最近的浏览器对这种标准且有良好文档的行为存在问题,因此可能需要使用 "option http-ignore-probes" 或 "errorfile 408 /dev/null" 来隐藏 408 代码。有关 "cR" 终止代码的详细信息,请参阅第 8.5 节中的解释。默认情况下,此超时仅适用于请求的头部部分,不适用于任何数据。一旦接收到空行,此超时将不再使用。当与 "option http-buffer-request" 结合使用时,此超时也适用于请求主体。如果未设置 "timeout http-keep-alive",则在保持活动连接上会再次使用它来等待第二个请求。通常,将其设置为几秒钟就足够了,因为大多数客户端在连接后会立即发送完整的请求。增加 3 秒或更多秒以覆盖 TCP 重传,但仅此而已。将其设置得非常低(例如 50 毫秒)通常在本地网络上有效,只要没有数据包丢失。这将阻止人们使用 telnet 发送裸 HTTP 请求。如果未设置此参数,则在传入请求的每个块之间仍然应用客户端超时。它应该在前端(frontend)中设置才能生效,除非前端处于 TCP 模式,在这种情况下将使用 HTTP 后端(backend)的超时。
设置在队列中等待可用连接槽的最大时间
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
当服务器的 maxconn 达到时,连接会留在队列中等待,该队列可能是服务器特定的或后端全局的。为了避免无限期等待,会对队列中的待处理请求应用超时。如果达到超时,则认为该请求几乎永远不会被处理,因此会丢弃它并向客户端返回 503 错误。" timeout queue" 语句允许固定请求在队列中等待的最长时间。如果未指定,则使用与后端连接超时("timeout connect")相同的值,以与没有 "timeout queue" 参数的旧版本向后兼容。
设置服务器端的最大不活动时间。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
不活动超时适用于服务器需要确认或发送数据的情况。在 HTTP 模式下,这个超时在服务器响应的第一阶段尤其重要,即当服务器必须发送头部时,因为它直接代表了服务器对请求的处理时间。要找出应该设置的值,通常最好从被认为不可接受的响应时间开始,然后检查日志以观察响应时间分布,并相应地调整值。默认情况下,该值以毫秒为单位指定,但如果数字后带有单位后缀,则可以以任何其他单位指定,如本文档开头所述。在 TCP 模式下(以及在较小程度上,在 HTTP 模式下),强烈建议客户端超时与服务器超时保持相等,以避免复杂的调试情况。无论预期的服务器响应时间如何,一个好的做法是指定略高于 3 秒倍数的超时时间(例如至少 4 或 5 秒),以覆盖至少一次或多次 TCP 数据包丢失。如果长连接会话与短连接会话混合使用(例如 WebSocket 和 HTTP),则值得考虑 "timeout tunnel",它会覆盖隧道连接的 "timeout client" 和 "timeout server"。此参数特定于后端(backend),但可以在 "defaults" 部分中一次性指定。这实际上是确保不会遗忘的最简单解决方案之一。未指定的超时会导致无限超时,这是不推荐的。这种用法被接受并且有效,但在启动期间会报告警告,因为它可能导致系统中过期会话的积累,如果系统的超时设置也没有配置的话。
为半关闭连接设置服务器侧的不活动超时。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
当一个方向已经关闭,但期望服务器确认或发送数据时,适用此不活动超时。此超时与 "timeout server" 的不同之处在于,它仅适用于单向关闭的连接。这对于避免在远程服务器未正常断开连接时将连接长时间保持在 FIN_WAIT 状态特别有用。此问题在 RDP 或 WebSocket 等长连接中尤为常见。请注意,当连接在一个方向上关闭时,此超时可以覆盖 "timeout tunnel"。提供此设置是为了完整性,但在大多数情况下,应该不需要它。此参数特定于后端,但可以在 "defaults" 部分中为所有后端一次性指定。默认情况下不设置,因此半关闭连接将使用其他超时(timeout.server 或 timeout.tunnel)。
设置被tarpit的连接将维持的时间
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<timeout> 是 tarpit 的持续时间,默认以毫秒为单位指定,但如果数字后跟单位后缀,也可以是任何其他单位,如本文档开头所述。
当使用 "http-request tarpit" 捕获连接(tarpitted)时,它会在一定时间内保持开放但没有活动,然后关闭。"timeout tarpit" 定义了它将保持开放的时间长度。默认情况下,该值以毫秒为单位指定,但如果数字后带有单位后缀,则可以以任何其他单位指定,如本文档开头所述。如果未指定,则使用与后端连接超时("timeout connect")相同的值,以实现与没有 "timeout tarpit" 参数的旧版本的向后兼容性。
为隧道设置客户端和服务器侧的最大不活动时间。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
隧道超时适用于客户端和服务器之间建立双向连接,并且连接在两个方向上都保持不活动状态。一旦连接成为隧道,此超时将取代客户端和服务器超时。在 TCP 中,只要没有分析器附加到任一连接(例如 tcp 内容规则被接受),就会使用此超时。在 HTTP 中,当连接升级时(例如,切换到 WebSocket 协议,或将 CONNECT 请求转发到代理),或者在第一个响应之后未指定 keepalive/close 选项时,会使用此超时。由于此超时通常与长连接会话结合使用,因此最好也设置 "timeout client-fin" 来处理客户端突然从网络中消失且不确认关闭,或者发送关闭但不再确认待处理数据的情况。这可能发生在存在防火墙的有损网络中,并通过存在大量处于 FIN_WAIT 状态的会话来检测。默认情况下,该值以毫秒为单位指定,但如果数字后带有单位后缀,则可以以任何其他单位指定,如本文档开头所述。无论预期的正常空闲时间如何,一个好的做法是指定略高于 3 秒倍数的超时时间(例如至少 4 或 5 秒),以覆盖至少一次或多次 TCP 数据包丢失。此参数特定于后端(backend),但可以在 "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 的超时
启用客户端透明代理
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
引入此关键字是为了向第 3 层负载均衡器提供第 7 层持久性。其思想是利用操作系统的能力将远程地址的传入连接重定向到本地进程(此处为 HAProxy),并让该进程知道最初请求的地址。使用此选项时,没有 cookie 的会话将被转发到传入请求的原始目标 IP 地址(该地址应与另一设备的地址匹配),而带有 cookie 的请求仍将被转发到适当的服务器。" transparent" 关键字已弃用,请改用 "option transparent"。请注意,与普遍看法相反,此选项在建立连接时并不会使 HAProxy 向服务器呈现客户端的 IP。
为每个请求生成一个唯一的 ID。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<string> 是一个日志格式字符串。
此关键字使用自定义日志格式为每个请求创建一个 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 头部。
可用于节
| 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 的条件,则切换到特定的后端。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 否![]() |
<backend> 是一个有效的后端或 "listen" 部分的名称,或一个解析为后端名称的 "log-format" 字符串。<condition> 是由 ACL 组成的条件,如 第 7 节 所述。如果省略,则无条件应用该规则。
在进行内容切换时,连接到达前端,然后根据许多条件分派到不同的后端。"use_backend" 关键字描述了条件与后端之间的关系。虽然它通常用于 HTTP 处理,但也可以用于纯 TCP,要么不使用内容(使用无状态 ACL,例如源地址验证),要么结合 "tcp-request" 规则来等待某些有效载荷。可以有任意数量的 "use_backend" 规则。所有这些规则都按照声明顺序进行评估,第一个匹配的规则将分配后端。在第一种形式中,如果条件满足,将使用后端。在第二种形式中,如果条件不满足,将使用后端。如果没有条件有效,将使用 "default_backend" 定义的后端。如果没有定义默认后端,则使用同一部分中的服务器(如果是 "listen" 部分),或者如果是前端,则不使用服务器并返回 503 service unavailable 响应。请注意,可以从 TCP 前端切换到 HTTP 后端。在这种情况下,要么前端已经检查了协议是 HTTP,后端处理将立即进行,要么后端将等待完整的 HTTP 请求进入。当一个前端必须在一个唯一的端口上解码多个协议,其中一个是 HTTP 时,此功能非常有用。当 <backend> 是一个简单的名称时,它在配置时解析,如果指定的后端不存在,则报告错误。如果 <backend> 是一个日志格式字符串,则在配置时可能不进行检查,因此后端名称在运行时动态解析。如果解析出的后端名称不对应于任何有效的后端,则不评估其他规则,而是应用 default_backend 指令。请注意,在使用动态后端名称时,强烈建议使用其他后端未使用的前缀,以确保无法通过请求强制使用未经授权的后端。值得一提的是,具有明确名称的 "use_backend" 规则用于检测前端和后端之间的关联,以计算后端的 "fullconn" 设置。动态名称无法做到这一点。
定义用于后端的FastCGI应用程序。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<name> 是要使用的 FastCGI 应用程序的名称。
有关 FastCGI 应用程序设置的详细信息,请参见第 10.1 节。
仅在匹配/不匹配基于 ACL 的条件时才使用特定的服务器。
可用于节
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<server> 是同一后端部分中有效服务器的名称。<condition> 是由 ACL 组成的条件,如 第 7 节 所述。
默认情况下,到达后端的连接会根据配置的算法在可用服务器之间进行负载均衡,除非在请求中找到并使用了持久性机制(例如 cookie)。有时需要将特定请求转发到特定服务器,而无需为该服务器声明专用的后端。这可以通过使用 "use-server" 规则来实现。这些规则在评估 "redirect" 规则之后和评估 cookie 之前进行评估,并且它们优先于 cookie。可以有任意数量的 "use-server" 规则。所有这些规则都按照声明顺序进行评估,第一个匹配的规则将分配服务器。如果规则指定的服务器处于关闭状态,并且未使用 "option persist" 且未验证 force-persist 规则,则忽略该规则,并继续评估下一个规则直到匹配为止。在第一种形式中,如果条件满足,将使用服务器。在第二种形式中,如果条件不满足,将使用服务器。如果没有条件有效,则继续处理,并根据其他持久性机制分配服务器。请注意,即使规则匹配,cookie 处理仍会执行,但不会分配服务器。这允许剥离带有前缀的 cookie 的前缀。"use-server" 语句在 HTTP 和 TCP 模式下都有效。这使其适用于基于内容的检查。例如,可以根据 TLS SNI 字段在服务器场中选择服务器。如果这些服务器的权重设置为零,则它们将不用于其他流量。
# 根据 SNI 字段拦截传入的 TLS 请求 use-server www if { req_ssl_sni -i www.example.com } server www 192.168.0.1:443 weight 0 use-server mail if { req_ssl_sni -i mail.example.com } server mail 192.168.0.1:587 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
关键字 "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 扩展。启用 HTTP/2 需要 ALPN。OpenSSL 1.0.2 之前的版本不支持 ALPN,只支持现已过时的 NPN 扩展。在撰写本文时,大多数浏览器仍然同时支持 ALPN 和 NPN 用于 HTTP/2,因此回退到 NPN 可能在一段时间内仍然有效。但应尽可能使用 ALPN。如果希望同时支持 HTTP/2 和 HTTP/1.1,可以按优先顺序通告这两个版本,如下所示: bind :443 ssl crt pub.pem alpn h2,http/1.1
将套接字的 backlog 设置为此值。如果未指定或为 0,则使用前端的 backlog,通常默认为 maxconn 值。
此设置仅在内置 OpenSSL 支持时可用。它设置描述在与 ECDHE 的 SSL/TLS 握手期间协商的椭圆曲线算法列表(“曲线套件”)的字符串。该字符串的格式是以冒号分隔的曲线名称列表。
此设置仅在内置 OpenSSL 支持时可用。它设置用于生成 ECDH 临时密钥的命名曲线(RFC 4492)。默认情况下,使用的命名曲线是 prime256v1。
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载验证客户端证书的 CA 证书。
此设置仅在内置 OpenSSL 支持时可用。设置一个逗号分隔的错误 ID 列表,在深度 > 0 的验证期间忽略这些错误。如果设置为 'all',则忽略所有错误。如果忽略了某个错误,SSL 握手不会中止。
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,其中包含用于创建和签署服务器证书的 CA 证书和 CA 私钥。当启用证书动态生成时,这是一个强制性设置。有关详细信息,请参见 'generate-certificates'。
此设置仅在内置 OpenSSL 支持时可用。它是 CA 私钥的密码。此设置是可选的,仅在启用证书动态生成时使用。有关详细信息,请参见 'generate-certificates'。
此设置仅在内置 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 握手期间协商的密码算法列表(“密码套件”)的字符串。字符串的格式在 OpenSSL 手册页中 "man 1 ciphers" 的 "ciphersuites" 部分中定义。对于 TLSv1.2 及更早版本的密码配置,请检查 "ciphers" 关键字。
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载验证客户端证书的证书吊销列表。
此设置仅在构建时支持 OpenSSL 时可用。它指定一个 PEM 文件,其中包含所需的证书和任何相关的私钥。此文件可以通过将多个 PEM 文件连接成一个文件来构建(例如 cat cert.pem key.pem > combined.pem)。如果您的 CA 需要中间证书,也可以将其连接到此文件中。如果使用的 OpenSSL 支持 Diffie-Hellman,则会加载此文件中存在的参数。如果使用目录名称而不是 PEM 文件,则将按字母顺序加载在该目录中找到的所有文件,除非它们的名称以 '.issuer'、'.ocsp' 或 '.sctl' 结尾(保留扩展名)。此指令可以多次指定,以便从多个文件或目录加载证书。证书将呈现给提供有效 TLS 服务器名称指示(SNI)字段的客户端,该字段与证书的 CN 或 alt subject 之一匹配。支持通配符,其中通配符字符 '*' 用于代替第一个主机名组件(例如 *.example.org 匹配 www.example.org,但不匹配 www.sub.example.org)。如果客户端未提供 SNI,或者 SSL 库不支持 TLS 扩展,或者客户端提供的 SNI 主机名与任何证书都不匹配,则将呈现第一个加载的证书。这意味着从目录加载证书时,强烈建议首先作为文件加载默认证书,或者确保它始终是目录中的第一个。请注意,可以多次加载同一证书而没有副作用。一些 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 扩展的支持。该文件必须包含有效的签名证书时间戳列表,如 RFC 中所述。文件会经过解析以检查基本语法,但不会验证签名。在某些情况下,需要支持多种密钥类型,例如 RSA 和 ECDSA,以用于提供给客户端的密码套件。这允许支持 EC 证书的客户端能够使用 EC 密码,同时支持较旧的仅 RSA 客户端。为了提供此功能,需要多个具有不同密钥类型的 PEM 文件。为了将这些 PEM 文件捆绑成 HAProxy 识别的“证书捆绑包”,它们必须按以下方式命名:所有要捆绑的 PEM 文件必须具有相同的基本名称,并带有指示密钥类型的后缀。目前支持三个后缀:rsa、dsa 和 ecdsa。例如,如果 www.example.com 有两个 PEM 文件,一个 RSA 文件和一个 ECDSA 文件,它们必须命名为:"example.pem.rsa" 和 "example.pem.ecdsa"。文件名的第一部分是任意的;只有后缀才重要。要将此捆绑包加载到 haproxy 中,只需指定基本名称
bind :8443 ssl crt example.pem
请注意,不会将后缀提供给 haproxy;这会告诉 haproxy 查找证书包。HAProxy 将同时加载包中的所有 PEM 文件,以尝试支持多种密钥类型。PEM 文件基于通用名称(CN)和主题备用名称(SAN)进行组合,以支持 SNI 查找。这意味着即使您向 haproxy 提供了一个证书包,如果该包中的证书没有共享的 CN/SAN 条目,haproxy 也将无法提供多证书支持。假设上面的示例中的包包含以下内容:
| 文件名 | CN | SAN |
|---|---|---|
| example.pem.rsa | www.example.com | rsa.example.com |
| example.pem.ecdsa | www.example.com | ecdsa.example.com |
使用 SNI“www.example.com”连接的用户将能够使用 RSA 和 ECDSA 密码套件。使用 SNI“rsa.example.com”连接的用户将只能使用 RSA 密码套件,而使用“ecdsa.example.com”连接的用户将只能使用 ECDSA 密码套件。使用 BoringSSL 和 Openssl >= 1.1.1 时,多证书是原生支持的,无需打包证书。如果客户端支持 ECDSA 证书,则会优先选择 ECDSA 证书。如果为 <cert> 参数提供了目录名,haproxy 将自动在该目录中搜索并加载打包的文件。OSCP 文件(.ocsp)和颁发者文件(.issuer)支持多证书打包。每个证书都可以有自己的 .ocsp 和 .issuer 文件。目前,sctl 不支持多证书打包。
此设置仅在内置 OpenSSL 支持时可用。设置一个逗号分隔的错误 ID 列表,在深度 == 0 的验证期间忽略这些错误。如果设置为 'all',则忽略所有错误。如果忽略了某个错误,SSL 握手不会中止。
此设置仅在构建时支持 OpenSSL 时可用。它指定一个 PEM 文件列表,每个证书可选地包含 SSL 配置和 SNI 过滤器,每行的格式如下:<crtfile> [\[<sslbindconf> ...\]] [[!]<snifilter> ...\] sslbindconf 支持 "allow-0rtt"、"alpn"、"ca-file"、"ciphers"、"ciphersuites"、"crl-file"、"curves"、"ecdhe"、"no-ca-names"、"npn"、"verify" 配置。对于 BoringSSL 和 Openssl >= 1.1.1,也支持 "ssl-min-ver" 和 "ssl-max-ver"。它会覆盖 bind 行中为证书设置的配置。SNI 过滤器支持通配符。也支持负过滤器,仅在与通配符过滤器结合使用以排除特定 SNI 时有用。证书将呈现给提供有效 TLS 服务器名称指示(SNI)字段且与其中一个 SNI 过滤器匹配的客户端。如果未指定 SNI 过滤器,则使用 CN 和 alt subject。此指令可以多次指定。有关更多信息,请参阅 "crt" 选项。仍然需要默认证书以满足 OpenSSL 期望。如果不使用,可以使用 'strict-sni' 选项。crt-list 支持多证书捆绑(参见 "crt"),只要在 crt-list 中只给出基本名称即可。SNI 过滤器将对所有捆绑证书执行相同的工作。对于 BoringSSL 和 Openssl >= 1.1.1,原生支持多证书,避免多证书捆绑。RSA 和 ECDSA 证书可以连续声明,并设置不同的 ssl 和 filter 参数。crt-list 文件示例:cert1.pem 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
是一个可选关键字,仅在某些 Linux 内核上受支持。它规定只有在连接上有数据到达时,或者最坏情况下在第一次重传后,才会接受连接。这只应在客户端首先发言的协议(例如 HTTP)上使用。它可以通过确保在接受连接时大部分请求已经可用,从而略微提高性能。另一方面,它将无法检测到不发言的连接。重要的是要注意,此选项在所有 2.6.31 之前的内核中都是有问题的,因为在客户端发言之前连接永远不会被接受。这可能会导致前端防火墙出现问题,前端防火墙会看到一个已建立的连接,而代理只会看到它处于 SYN_RECV 状态。此选项仅在 TCPv4/TCPv6 套接字上受支持,其他套接字会忽略它。
此选项仅可用于 stats 套接字。它使您的 stats 套接字能够将监听器 FD 传递给另一个 HAProxy 进程。在 master-worker 模式下进行重载时,进程会自动重新执行,并添加 -x 和带有此选项的 stats 套接字之一。另请参见管理指南中的“-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 套接字无效。
固定套接字 ID。默认情况下,套接字 ID 是自动分配的,但有时为了方便监控而固定它们会更方便。此值必须是严格正数,并且在侦听器/前端内是唯一的。此选项只能在定义单个套接字时使用。
将套接字限制到特定接口。指定后,只有从该特定接口接收的数据包才会由套接字处理。目前仅在 Linux 上受支持。该接口必须是主系统接口,而不是别名接口。如果多个前端绑定到不同的接口,也可以将它们绑定到同一地址。请注意,绑定到网络接口需要 root 权限。此参数仅与 TCPv4/TCPv6 套接字兼容。指定后,返回流量将使用与入站流量相同的接口及其关联的路由表,即使配置了通过不同接口的显式路由也是如此。当同一客户端 IP 地址需要能够访问托管在不同接口上的前端时,这对于解决非对称路由问题非常有用。
此设置仅用于 stats socket,以限制可以在 socket 上发出的命令性质。其他 socket 会忽略它。<level> 可以是以下之一: - "user" 是权限最低的级别;只能读取非敏感统计信息,不允许进行更改。在不容易限制对 socket 访问的系统上,这很有意义。 - "operator" 是默认级别,适用于大多数常见用途。可以读取所有数据,并且只允许进行非敏感更改(例如清除最大计数器)。 - "admin" 应谨慎使用,因为允许进行任何操作(例如清除所有计数器)。此设置仅与 stats 套接字一起使用,用于配置附加到信息反馈消息前的严重性级别输出。消息的严重性级别范围可以在 0 到 7 之间,符合 syslog rfc5424。请求数据的有效且成功的套接字命令(例如“show map”、“get acl foo”等)绝不会附加严重性级别。其他套接字会忽略此设置。<format> 可以是以下之一:- “none”(默认)不向反馈消息前附加严重性级别。- “number” 严重性级别作为数字附加。- “string” 严重性级别作为遵循 rfc5424 约定的字符串附加。
将套接字限制为此数量的并发连接。多余的连接将保留在系统的 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 上,可以指定套接字将属于哪个网络命名空间。此指令使得可以显式地将侦听器绑定到不同于默认命名空间的命名空间。请参考您的操作系统文档以了解有关网络命名空间的更多详细信息。
设置从套接字发起的连接的“友好度”(niceness)。值必须在 -1024 到 1024(含)之间,默认为零。正值意味着此类连接对其他连接更友好,并且容易在调度器中让出位置。相反,负值意味着连接希望以比其他连接更高的优先级运行。这种差异仅在高负载下,当系统接近饱和时才会发生。负值适用于低延迟或管理服务,而高值通常推荐用于 CPU 密集型任务,如 SSL 处理或对延迟不那么敏感的批量传输。例如,为 SMTP 套接字使用正值,为 RDP 套接字使用负值可能是有意义的。
此设置仅在内置 OpenSSL 支持时可用。它在使用 `ca-file` 时,可防止在服务器 hello 消息中发送 CA 名称。
此设置仅在构建时支持 OpenSSL 时可用。它在支持 SSL 的情况下禁用从该监听器实例化的任何 socket 上的 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 的情况下禁用从该监听器实例化的任何 socket 上的 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 或更高版本中可用。如果需要 HTTP/2 并且使用的是较旧版本的 OpenSSL,在撰写本文时,NPN 可能仍然可以使用,因为大多数客户端仍然支持它。可以同时启用 NPN 和 ALPN,尽管这在测试之外可能没有任何意义。在选择密码套件时使用客户端的偏好,默认情况下强制使用服务器的偏好。此选项也可在全局语句“ssl-default-bind-options”中使用。请注意,对于 OpenSSL >= 1.1.1,如果 ChaCha20-Poly1305 密码位于客户端密码列表的顶部,ChaCha20-Poly1305 无论如何都会被重新优先排序(无需设置此选项)。
这会限制允许运行此侦听器的进程或线程列表。它不会强制任何进程,但会消除不匹配的进程。如果前端使用“bind-process”设置,则应用两者之间的交集。如果最后侦听器不允许在任何剩余进程上运行,则会发出警告,如果指定了单个进程,则侦听器将在该侦听器的第一个进程上运行;如果指定了多个进程,则在所有进程上运行。如果指定了线程集,则会限制允许处理此侦听器传入连接的线程,用于该进程集。如果配置了多个进程和线程,则会发出警告,因为这要么是配置错误,要么是对这些模型的误解。对于需要多个范围的不太可能的情况,此指令可以重复。<process-set> 和 <thread-set> 必须使用 all | odd | even | number[-[number]] 格式。范围可以部分定义。可以省略上限。在这种情况下,它会被替换为相应的最大值。此指令的主要目的是与 stats 套接字一起使用,并为每个进程设置一个不同的套接字。第二个目的是让多个绑定行在侦听器中共享相同的 IP:port,但不共享相同的进程,以便系统可以将传入连接分配到多个队列中,并允许更平滑的进程间负载平衡。目前已知 Linux 3.9 及更高版本支持此功能。另请参阅“bind-process”和“nbproc”。
强制使用多路复用器协议处理传入连接。它必须与前端模式(TCP 或 HTTP)兼容。它也必须能在前端使用。可用协议列表在 `haproxy -vv` 中报告。此选项的目的是绕过为从该侦听套接字实例化的所有连接选择最佳的多路复用器协议。例如,可以通过在绑定行中指定“proto h2”来强制在纯 TCP 上使用 http/2。
此设置仅在内置 OpenSSL 支持时可用。它在此监听器实例化的连接上启用 SSL 解密。需要一个证书(参见上面的“crt”)。缓冲区中的所有内容都将以明文形式出现,因此 ACL 和 HTTP 处理只能访问解密后的内容。默认情况下禁用 SSLv3,使用“ssl-min-ver SSLv3”来启用它。此选项强制使用 <version> 或更低版本来处理从此侦听器实例化的 SSL 连接。此选项在全局语句“ssl-default-bind-options”中也可用。另请参阅“ssl-min-ver”。
此选项强制使用 <version> 或更高版本来处理从此侦听器实例化的 SSL 连接。此选项在全局语句“ssl-default-bind-options”中也可用。另请参阅“ssl-max-ver”。
此设置仅在内置 OpenSSL 支持时可用。仅当客户端提供的 SNI 与证书匹配时,才允许 SSL/TLS 协商。不使用默认证书。有关更多信息,请参见 "crt" 选项。为此监听套接字发起的任何传入连接设置 TCP 用户超时。此选项在 Linux 2.6.37 及更高版本中可用。它允许 haproxy 配置套接字的超时,这些套接字包含在配置延迟内未收到确认的数据。这对于经历长时间空闲期的长连接特别有用,例如远程终端或数据库连接池,其中客户端和服务器超时必须保持高位以允许长时间空闲,但重要的是要检测到客户端已消失,以便释放与之连接(以及服务器会话)相关的所有资源。参数默认以毫秒为单位表示延迟。这仅适用于常规 TCP 连接,并且会被其他协议忽略。
是一个可选关键字,仅在 Linux 内核版本 >= 3.7 上受支持。它在监听套接字上启用 TCP 快速打开(TCP Fast Open),这意味着支持此功能的客户端将能够在第二次连接开始的三次握手期间发送请求并接收响应,从而在第一次连接后节省一次往返时间。这仅对连接率高且每次往返都很重要的协议有意义。这可能会导致许多防火墙出现问题,因为它们不接受 SYN 数据包上的数据,因此只应在经过充分测试后才启用此选项。此选项仅在 TCPv4/TCPv6 套接字上受支持,并被其他套接字忽略。如果您的 libc 未定义 TCP_FASTOPEN,您可能需要使用 USE_TFO=1 来构建 HAProxy。
设置从中加载密钥的 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 套接字兼容,具体取决于内核版本。一些发行版的内核包含该功能的向后移植版本,因此请向您的供应商查询支持情况。
是一个可选关键字,仅在包括 Linux 内核版本 >= 2.4.21 在内的大多数最新系统上受支持。它用于在使用默认地址时将套接字同时绑定到 IPv4 和 IPv6。在默认情况下仅绑定到 IPv6 的系统上,这样做有时是必要的。它对非 IPv6 套接字没有影响,并被“v6only”选项覆盖。
是一个可选关键字,仅在包括 Linux 内核版本 >= 2.4.21 在内的大多数最新系统上受支持。它用于在使用默认地址时将套接字仅绑定到 IPv6。这样做有时比系统范围的设置更受欢迎,因为它是针对每个监听器的。它对非 IPv6 套接字没有影响,并优先于“v4v6”选项。
将 UNIX 套接字的所有者设置为指定的系统 UID。也可以在全局部分的“unix-bind”语句中默认设置。请注意,某些平台会直接忽略此设置。此设置等同于“user”设置,不同之处在于使用用户的数字 ID 而不是其名称。非 UNIX 套接字会忽略此设置。
将 UNIX 套接字的所有者设置为指定的系统用户。它也可以在全局部分的“unix-bind”语句中默认设置。请注意,某些平台会直接忽略此设置。此设置与“uid”设置等效,不同之处在于使用的是用户名而不是其 uid。此设置被非 UNIX 套接字忽略。
此设置仅在构建时包含 OpenSSL 支持时可用。如果设置为 'none',则不请求客户端证书。这是默认设置。在其他情况下,会请求客户端证书。如果客户端在请求后未提供证书,并且 'verify' 设置为 'required',则握手将中止,而如果设置为 'optional',则会成功。客户端提供的证书始终使用来自 'ca-file' 的 CA 和来自 'crl-file' 的可选 CRL 进行验证。验证失败时,握手将中止,无论 'verify' 选项如何设置,除非错误代码与 'ca-ignore-err' 或 'crt-ignore-err' 中列出的错误代码完全匹配。
“server”和“default-server”关键字支持一定数量的设置,所有这些设置都作为参数在服务器行上传递。这些参数出现的顺序无关紧要,并且它们都是可选的。其中一些设置是单个单词(布尔值),而另一些则要求在它们之后有一个或多个值。在这种情况下,值必须紧跟在设置名称之后。除了 default-server 之外,所有这些设置如果使用,都必须在服务器地址之后指定:server <name> <address>[:port] [settings ...] default-server [settings ...] 请注意,所有这些设置都受“server”和“default-server”关键字支持,除了“id”仅受“server”支持。目前支持的设置如下。
使用“addr”参数,可以为发送健康检查或探测 agent-check 使用不同的 IP 地址。在某些服务器上,可能需要将一个 IP 地址专用于能够执行复杂测试的特定组件,这些测试比应用程序本身更适合进行健康检查。如果未设置“check”参数,则此参数将被忽略。另请参见“port”参数。
启用辅助代理检查,该检查独立于常规健康检查运行。代理健康检查通过与“agent-port”参数设置的端口建立 TCP 连接并读取以第一个 '\r' 或 '\n' 结尾的 ASCII 字符串来执行。该字符串由一系列以空格、制表符或逗号分隔的单词组成,顺序不限,每个单词包括: - 正整数百分比的 ASCII 表示,例如:“75%”。这种格式的值将设置与 haproxy 启动时配置的服务器初始权重成比例的权重。请注意,零权重在统计信息页面上报告为“DRAIN”,因为它对服务器具有相同的效果(它从 LB 场中移除)。 - 字符串“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”参数。
如果指定了此选项,haproxy 将在连接时将给定的字符串(按原样)发送到代理服务器。例如,您可以将后端名称编码到此字符串中,这将使您的代理能够根据后端发送不同的响应。请确保包含 `\n`,如果您想以换行符终止您的请求。
“agent-inter”参数将两次 agent 检查之间的间隔设置为 <delay> 毫秒。如果未指定,延迟默认为 2000 毫秒。与所有其他基于时间的参数一样,它可以输入任何其他明确的单位,如 { us, ms, s, m, h, d }。“agent-inter”参数在未设置“timeout check”时也用作 agent 检查的超时。为了减少当多个服务器托管在同一硬件上时的“共振”效应,所有服务器的 agent 和健康检查都以一个小的时差启动。也可以使用全局“spread-checks”关键字在 agent 和健康检查间隔中添加一些随机噪声。例如,当许多后端使用相同的服务器时,这样做是有意义的。另请参见“agent-check”和“agent-port”参数。
`agent-addr` 参数设置代理检查的地址。您可以将代理检查卸载到另一个目标,这样您就可以在一个地方管理 haproxy 中定义的服务器的状态和权重,以防您无法创建自我意识和自我管理的 à 服务。您可以指定 IP 或主机名,它们都将被解析。
“agent-port”参数设置用于 agent 检查的 TCP 端口。另请参见“agent-check”和“agent-inter”参数。
在使用 TLS 1.3 时,允许向服务器发送早期数据。请注意,只有当客户端使用了早期数据,或者后端使用了带有“0rtt-rejected”关键字的“retry-on”时,才会发送早期数据。
此功能启用 TLS ALPN 扩展,并宣布指定的协议列表作为 ALPN 之上的支持协议。协议列表由逗号分隔的协议名称组成,例如:“http/1.1,http/1.0”(不带引号)。这要求 SSL 库已启用 TLS 扩展支持(通过 `haproxy -vv` 检查)。ALPN 扩展取代了原始的 NPN 扩展。ALPN 是连接到 HTTP/2 服务器所必需的。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`
当 server 行上存在“backup”时,该服务器仅在所有其他非备份服务器都不可用时才用于负载均衡。但是,带有引用该服务器的持久性 cookie 的请求将始终被处理。默认情况下,只使用第一个可操作的备份服务器,除非在后端设置了“allbackups”选项。另请参见“no-backup”和“allbackups”选项。
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,从中加载用于验证服务器证书的 CA 证书。
此选项启用服务器上的健康检查。默认情况下,服务器始终被视为可用。如果设置了“check”,则服务器在接受定期 TCP 连接时可用,以确保它确实能够提供请求。发送测试的默认地址和端口是服务器的地址和端口,默认源与后端中定义的相同。可以使用“addr”参数更改地址,使用“port”参数更改端口,使用“source”地址更改源地址,使用“inter”、“rise”和“fall”参数更改间隔和计时器。请求方法在后端使用“httpchk”、“smtpchk”、“mysql-check”、“pgsql-check”和“ssl-hello-chk”选项定义。有关更多信息,请参阅这些选项和参数。另请参阅“no-check”选项。
此选项强制在出站健康检查中发送 PROXY 协议行,无论服务器是否为正常流量使用 send-proxy。默认情况下,如果 PROXY 协议已为正常流量启用,并且不存在“port”或“addr”指令,则为健康检查启用 PROXY 协议。但是,如果存在此类指令,则需要使用“check-send-proxy”选项来强制使用该协议。有关更多信息,请参见“send-proxy”选项。
定义要通过 ALPN 通告的协议。协议列表由逗号分隔的协议名称组成,例如:“http/1.1,http/1.0”(不含引号)。如果未设置,将使用服务器的 ALPN。
此选项允许您指定在通过 SSL 进行健康检查时使用的 SNI。只能使用字符串来设置 <sni>。如果您想为代理的流量设置 SNI,请参见“sni”。
此选项强制通过 SSL 对所有健康检查进行加密,无论服务器是否将 SSL 用于正常流量。这通常在指定了显式“port”或“addr”指令且未继承 SSL 健康检查时使用。重要的是要了解此选项在检查下方插入了一个 SSL 传输层,因此简单的 TCP 连接检查变为 SSL 连接,它取代了旧的 ssl-hello-chk。最常见的用途是将“httpchk”与 SSL 检查结合使用发送 HTTPS 检查。所有 SSL 设置对健康检查和流量都是通用的(例如,密码套件)。有关更多信息,请参阅“ssl”选项,并使用“no-check-ssl”禁用此选项。
此选项启用使用上游 socks4 代理的传出运行状况检查。默认情况下,即使已为主流量启用 Socks 隧道,运行状况检查也不会通过 Socks 隧道。
此设置仅在内置 OpenSSL 支持时可用。此选项设置一个字符串,该字符串描述了在与服务器进行 SSL/TLS 握手期间协商的密码算法列表。字符串的格式定义在 OpenSSL man 页面的“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 时可用。此选项设置描述在与服务器进行 TLS 1.3 握手期间协商的密码算法列表的字符串。字符串的格式在 OpenSSL 手册页中“man 1 ciphers”的“ciphersuites”部分中定义。有关 TLSv1.2 及更早版本的密码配置,请检查“ciphers”关键字。
“cookie”参数将分配给服务器的 cookie 值设置为 <value>。将在传入请求中检查此值,并选择具有相同值的第一个可操作服务器。反过来,在 cookie 插入或重写模式下,此值将分配给发送到客户端的 cookie。多个服务器共享相同的 cookie 值没有问题,这在正常服务器和备份服务器之间实际上很常见。另请参阅后端部分中的“cookie”关键字。
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载用于验证服务器证书的证书吊销列表。
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载证书和关联的私钥。通过将这两个 PEM 文件连接到一个文件中,可以创建此文件。如果服务器发送客户端证书请求,则会发送此证书。
“disabled”关键字以“disabled”状态启动服务器。这意味着它在维护模式下被标记为 down,除了持久模式允许的连接之外,没有其他连接会到达它。这非常适合设置新服务器,因为正常流量永远不会到达它们,同时仍然可以通过使用 force-persist 机制来测试服务。另请参阅“enabled”设置。
此选项可用作“server”设置,以重置从“default-server”指令继承的任何“disabled”设置作为默认值。它也可作为“default-server”设置,以重置任何以前的“default-server”“disabled”设置。
如果启用了运行状况监视,“error-limit”参数指定触发“on-error”选项所选事件的连续错误次数。默认设置为 10 次连续错误。另请参阅“check”、“error-limit”和“on-error”。
“fall”参数表示服务器将在 <count> 次连续不成功的运行状况检查后被视为死亡。如果未指定,此值默认为 3。另请参阅“check”、“inter”和“rise”参数。
此选项强制仅使用 SSLv3,当 SSL 用于与服务器通信时。SSLv3 对于高连接速率通常比 TLS 对应项成本更低。此选项在全局语句“ssl-default-server-options”上也可使用。另请参阅“ssl-min-ver”和 ssl-max-ver”。
此选项强制仅使用 TLSv1.0,当 SSL 用于与服务器通信时。此选项在全局语句“ssl-default-server-options”上也可使用。另请参阅“ssl-min-ver”和 ssl-max-ver”。
此选项强制仅使用 TLSv1.1,当 SSL 用于与服务器通信时。此选项在全局语句“ssl-default-server-options”上也可使用。另请参阅“ssl-min-ver”和 ssl-max-ver”。
此选项强制仅使用 TLSv1.2,当 SSL 用于与服务器通信时。此选项在全局语句“ssl-default-server-options”上也可使用。另请参阅“ssl-min-ver”和 ssl-max-ver”。
此选项强制仅使用 TLSv1.3,当 SSL 用于与服务器通信时。此选项在全局语句“ssl-default-server-options”上也可使用。另请参阅“ssl-min-ver”和 ssl-max-ver”。
为服务器设置一个持久化 ID。此 ID 必须是正数且对代理是唯一的。如果未设置,将自动分配一个未使用的 ID。第一个分配的值将是 1。此 ID 目前仅在统计信息中返回。
指示如果服务器使用 FQDN,则在启动时应按什么顺序解析其地址。尝试通过依次应用逗号分隔列表中提到的每种方法来解析地址。使用第一个成功的方法。如果到达列表末尾仍未找到可用的方法,则会引发错误。方法“last”建议选择出现在状态文件中的地址(请参阅“server-state-file”)。方法“libc”使用 libc 的内部解析器(取决于操作系统和构建选项,使用 gethostbyname() 或 getaddrinfo())。方法“none”特别指示服务器应以 down 状态启动,没有任何有效的 IP 地址。这对于忽略启动时的一些 DNS 问题,等待情况稍后得到修复很有用。最后,可以提供一个 IP 地址(IPv4 或 IPv6)。它可以是服务器当前已知的地址(例如,由配置生成器填充),或者是用于捕获旧会话并向其显示适当错误消息的虚拟服务器的地址。当使用“first”负载平衡算法时,此 IP 地址可以指向用于触发动态创建新实例的虚假服务器。此选项默认为“last,libc”,表示首先使用状态文件中找到的上一个地址(如果有),否则使用 libc 的解析器。这确保了与历史行为的持续兼容性。
defaults # 地址解析永不失败 default-server init-addr last,libc,none
“inter”参数将两次连续健康检查之间的时间间隔设置为 <delay> 毫秒。如果未指定,延迟默认为 2000 毫秒。也可以使用“fastinter”和“downinter”来根据服务器状态优化检查之间的延迟。
| 服务器状态 | 使用的间隔 |
|---|---|
| UP 100% (非过渡状态) | “inter” |
| 过渡性 UP (正在变为 down "fall"), 过渡性 DOWN (正在变为 up "rise"), 或尚未检查。 | 如果设置了“fastinter”,则使用它, 否则使用“inter”。 |
| DOWN 100% (非过渡状态) | 如果设置了“downinter”,则使用它, 否则使用“inter”。 |
与所有其他基于时间的参数一样,它们可以以任何其他显式单位 {us, ms, s, m, h, d} 输入。“inter”参数在未设置“timeout check”时,也用作服务器运行状况检查的超时。为了减少托管在同一硬件上的多个服务器之间的“共振”效应,代理和所有服务器的运行状况检查都以它们之间一个小的时差开始。还可以使用全局“spread-checks”关键字在代理和运行状况检查间隔中添加一些随机噪声。例如,当许多后端使用相同的服务器时,这很有意义。“maxconn”参数指定将发送到此服务器的最大并发连接数。如果传入并发连接数高于此值,它们将被排队,等待槽位释放。此参数非常重要,因为它可以防止脆弱的服务器在极端负载下崩溃。如果指定了“minconn”参数,则限制变为动态的。默认值为“0”,表示无限制。另请参阅“minconn”和“maxqueue”参数,以及后端的“fullconn”关键字。在 HTTP 模式下,此参数限制并发请求数而不是连接数。多个请求可以通过单个 TCP 连接多路复用到服务器。例如,如果您指定 maxconn 为 50,您可能会看到 1 到 50 个实际服务器连接,但并发请求数不超过 50 个。
“maxqueue”参数指定将在此服务器队列中等待的最大连接数。如果达到此限制,下一个请求将被重新分配到其他服务器,而不是无限期地等待服务。这会破坏持久性,但可能允许人们在他们尝试连接的服务器即将崩溃时快速重新登录。默认值为“0”,表示队列无限制。另请参阅“maxconn”和“minconn”参数。
“max-reuse”参数指示 HTTP 连接处理器,它们不应将服务器连接重复使用超过此次数来发送新请求。允许的值为 -1(默认值),它禁用此限制,或任何正值。值为零将有效禁用 keep-alive。这仅用于解决某些服务器随时间推移而导致资源泄漏的 bug。由于可能存在技术限制使其无法强制执行,因此底层可能不会完全遵守此参数。至少 HTTP/2 连接到服务器会遵守它。
设置“minconn”参数后,maxconn 限制将成为遵循后端负载的动态限制。服务器将始终接受至少 <minconn> 个连接,永不超过 <maxconn> 个连接,并且当后端并发连接数少于 <fullconn> 时,限制将在两个值之间平稳过渡。这使得在正常负载期间限制服务器上的负载成为可能,但在重要负载期间进一步推动它,同时又不会在异常负载期间使服务器过载。另请参阅“maxconn”和“maxqueue”参数,以及“fullconn”后端关键字。
在 Linux 上,可以指定套接字属于哪个网络命名空间。此指令使得可以明确地将服务器绑定到不同于默认命名空间的命名空间。有关网络命名空间的更多详细信息,请参阅您的操作系统文档。
此选项可用作“server”设置,以重置任何从“default-server”指令继承的“agent-check”设置作为默认值。它也可用作“default-server”设置,以重置任何先前的“default-server” “agent-check”设置。
此选项可用作“server”设置,以重置任何从“default-server”指令继承的“backup”设置作为默认值。它也可用作“default-server”设置,以重置任何先前的“default-server” “backup”设置。
此选项可用作“server”设置,以重置任何从“default-server”指令继承的“check”设置作为默认值。它也可用作“default-server”设置,以重置任何先前的“default-server” “check”设置。
此选项可用作“server”设置,以重置任何从“default-server”指令继承的“check-ssl”设置作为默认值。它也可用作“default-server”设置,以重置任何先前的“default-server” “check-ssl”设置。
此选项可用作“server”设置,以重置任何从“default-server”指令继承的“send-proxy”设置作为默认值。它也可用作“default-server”设置,以重置任何先前的“default-server” “send-proxy”设置。
此选项可用作“server”设置,以重置任何从“default-server”指令继承的“send-proxy-v2”设置作为默认值。它也可用作“default-server”设置,以重置任何先前的“default-server” “send-proxy-v2”设置。
此选项可用作“server”设置,以重置任何从“default-server”指令继承的“send-proxy-v2-ssl”设置作为默认值。它也可用作“default-server”设置,以重置任何先前的“default-server” “send-proxy-v2-ssl”设置。
此选项可用作 "server" 设置,用于重置任何从 "default-server" 指令继承的 "send-proxy-v2-ssl-cn" 设置作为默认值。它也可用作 "default-server" 设置,用于重置任何以前的 "default-server" "send-proxy-v2-ssl-cn" 设置。
此选项可用作 "server" 设置,用于重置任何从 "default-server" 指令继承的 "ssl" 设置作为默认值。它也可用作 "default-server" 设置,用于重置任何以前的 "default-server" "ssl" 设置。
此选项在 SSL 用于与服务器通信时禁用 SSL 会话重用。它将强制服务器为每个新连接执行完整的握手。这可能只对基准测试、故障排除和多疑用户有用。
当使用 SSL 与服务器通信时,此选项禁用对 SSLv3 的支持。请注意,SSLv2 已在代码中禁用,无法使用任何配置选项启用。请改用 "ssl-min-ver" 和 "ssl-max-ver"。在 default-server 中支持:否
此设置仅在构建时支持 OpenSSL 时可用。它禁用无状态会话恢复(RFC 5077 TLS Ticket 扩展)并强制使用有状态会话恢复。无状态会话恢复在服务器的 CPU 使用率方面成本更高。此选项也可用在全局语句 "ssl-default-server-options" 中。TLS Ticket 机制仅用于 TLS 1.2 及以下版本。前向保密会因 TLS Ticket 而受到损害,除非 Ticket 密钥被定期轮换(通过重载或使用 "tls-ticket-keys")。另请参阅 "tls-tickets"。
当使用 SSL 与服务器通信时,此选项禁用对 TLSv1.0 的支持。请注意,SSLv2 已在代码中禁用,无法使用任何配置选项启用。TLSv1 比 SSLv3 更耗资源,因此在与本地服务器通信时禁用它通常是有意义的。此选项也可用于全局语句 "ssl-default-server-options"。请改用 "ssl-min-ver" 和 "ssl-max-ver"。在 default-server 中支持:否
当使用 SSL 与服务器通信时,此选项禁用对 TLSv1.1 的支持。请注意,SSLv2 已在代码中禁用,无法使用任何配置选项启用。TLSv1 比 SSLv3 更耗资源,因此在与本地服务器通信时禁用它通常是有意义的。此选项也可用于全局语句 "ssl-default-server-options"。请改用 "ssl-min-ver" 和 "ssl-max-ver"。在 default-server 中支持:否
当使用 SSL 与服务器通信时,此选项禁用对 TLSv1.2 的支持。请注意,SSLv2 已在代码中禁用,无法使用任何配置选项启用。TLSv1 比 SSLv3 更耗资源,因此在与本地服务器通信时禁用它通常是有意义的。此选项也可用于全局语句 "ssl-default-server-options"。请改用 "ssl-min-ver" 和 "ssl-max-ver"。在 default-server 中支持:否
当使用 SSL 与服务器通信时,此选项禁用对 TLSv1.3 的支持。请注意,SSLv2 已在代码中禁用,无法使用任何配置选项启用。TLSv1 比 SSLv3 更耗资源,因此在与本地服务器通信时禁用它通常是有意义的。此选项也可用于全局语句 "ssl-default-server-options"。请改用 "ssl-min-ver" 和 "ssl-max-ver"。在 default-server 中支持:否
此选项可用作 "server" 设置,用于重置任何从 "default-server" 指令继承的 "verifyhost" 设置作为默认值。它也可用作 "default-server" 设置,用于重置任何以前的 "default-server" "verifyhost" 设置。
此选项可用作 "server" 设置,用于重置任何从 "default-server" 指令继承的 "tfo" 设置作为默认值。它也可用作 "default-server" 设置,用于重置任何以前的 "default-server" "tfo" 设置。
永远不要将分配给此服务器的连接添加到 stick-table。这可以与 backup 结合使用,以确保为 backup 服务器禁用 stick-table 持久性。
这会启用 NPN TLS 扩展,并在 NPN 之上声明支持的协议列表。协议列表是一系列由逗号分隔的协议名称,例如:"http/1.1,http/1.0"(不带引号)。这要求 SSL 库在启用 TLS 扩展支持的情况下构建(通过 haproxy -vv 检查)。请注意,NPN 扩展已被 ALPN 扩展取代(请参阅 "alpn" 关键字),尽管后者仅在 OpenSSL 1.0.2 及以上版本可用。此选项启用基于观察与服务器通信的健康状况调整。默认情况下,此功能被禁用,启用它还需要启用健康检查。支持两种模式:"layer4" 和 "layer7"。在 layer4 模式下,只有成功的/不成功的 tcp 连接是重要的。在 layer7 模式下(仅允许用于 http 代理),会验证从服务器收到的响应,例如有效的/无效的 http 代码、无法解析的头信息、超时等。有效的状态码包括 100 到 499、501 和 505。另请参阅 "check"、"on-error" 和 "error-limit"。
选择在检测到足够多的连续错误时应执行的操作。目前提供四种模式:- fastinter:强制 fastinter - fail-check:模拟失败的检查,也强制 fastinter(默认) - sudden-death:模拟一个预致命的健康检查失败,再多一次失败的检查将导致服务器标记为宕机,强制 fastinter - mark-down:立即将服务器标记为宕机并强制 fastinter 另请参阅 "check"、"observe" 和 "error-limit"。
修改服务器被标记为宕机时发生的操作。目前提供一种操作:- shutdown-sessions:关闭会话。启用此设置后,当服务器宕机时,所有到该服务器的连接将立即终止。如果健康检查检测到的情况比简单的连接状态更复杂,并且长时间的超时会导致服务长时间无响应,则可能需要使用此选项。例如,健康检查可能检测到数据库卡死,并且没有机会重用现有连接。以此方式终止的连接将以 'D' 终止代码(表示 "Down")进行记录。默认情况下,操作是禁用的。
修改服务器被标记为正常时发生的操作。目前提供一种操作:- shutdown-backup-sessions:关闭所有备用服务器上的会话。这仅在服务器未处于备用状态且未被禁用(其有效权重必须 > 0)时执行。当处理长会话(例如 LDAP、SQL 等)时,这有时可用于强制活动服务器在恢复后重新承担所有流量。这样做可能会比试图解决的问题更多(例如,未完成的事务),因此请谨慎使用此功能。因服务器启动而终止的会话将以 'U' 终止代码(表示 "Up")进行记录。默认情况下,操作是禁用的。
设置服务器的空闲连接最大数量。-1 表示无限连接,0 表示无空闲连接。默认值为 -1。启用空闲连接后,不再属于任何客户端会话的孤立空闲连接将被移至专用池,以便未来的客户端可以使用它们。这仅适用于可以根据与 "http-reuse" 相同的原则共享的连接。
设置开始清除空闲连接的延迟。每隔 <delay> 时间间隔,一半的空闲连接将被关闭。0 表示不保留任何空闲连接。默认值为 5 秒。
使用 "port" 参数,可以为健康检查使用不同的端口。在某些服务器上,可能希望将一个端口专门用于能够执行复杂测试的特定组件,这些测试比应用程序更适合健康检查。例如,通常在 inetd 中运行一个简单的脚本。如果未设置 "check" 参数,则此参数将被忽略。另请参阅 "addr" 参数。
强制用于到此服务器的出站连接的多路复用器协议。它必须与后端的模式(TCP 或 HTTP)兼容。它也必须能在后端侧使用。可用协议列表在 haproxy -vv 中报告。此选项的目的是绕过为建立到此服务器的所有连接选择最佳多路复用器协议。
"redir" 参数为此服务器上所有寻址的 GET 和 HEAD 请求启用重定向模式。这意味着 HAProxy 不会转发请求到服务器,而是发送一个 "HTTP 302" 响应,其 "Location" 标头由此前缀紧跟请求 URI 组成,从路径组件的开头 '/' 开始。这意味着之后不应使用尾部斜杠。所有无效请求都将被拒绝,所有非 GET 或 HEAD 请求将由服务器正常处理。请注意,由于响应是完全伪造的,因此响应中无法进行标头篡改或 cookie 插入。然而,请求中的 cookie 仍然会被分析,这使得此解决方案在本地发生故障时可完全用于将用户定向到远程位置。主要用途是通过让客户端直接连接到静态服务器来增加带宽。注意:在此处切勿使用相对位置,否则会导致客户端和 HAProxy 之间发生循环!
server srv1 192.168.1.1:80 redir http://image1.mydomain.com check
"rise" 参数指定服务器将在连续 <count> 次成功的健康检查后被视为可运行。如果未指定,此值默认为 2。另请参阅 "check"、"inter" 和 "fall" 参数。
以逗号分隔的选项列表,应用于与此服务器关联的DNS解析。可用选项: * allow-dup-ip 默认情况下,HAProxy在运行时DNS解析操作时会阻止后端中IP地址重复。也就是说,在某些情况下,两个服务器(在同一个后端,由同一个FQDN解析)具有相同的IP地址是有意义的。对于这种情况,只需启用此选项。这与prevent-dup-ip相反。 * ignore-weight 忽略SRV记录中设置的任何权重。当您希望使用其他方法(例如使用"agent-check"或通过运行时API)控制权重时,此功能非常有用。 * prevent-dup-ip 确保HAProxy的默认行为在服务器上强制执行:防止在同一后端中,共享相同FQDN的服务器之间重复使用已设置的IP地址。这与allow-dup-ip相反。
backend b_myapp default-server init-addr none resolvers dns server s1 myapp.example.com:80 check resolve-opts allow-dup-ip server s2 myapp.example.com:81 check resolve-opts allow-dup-ip
设置了 allow-dup-ip 选项后:* 如果域名服务器返回单个 IP 地址,则两个服务器都将使用它 * 如果域名服务器返回 2 个 IP 地址,则每个服务器将选择一个不同的地址 默认值:未设置
当为服务器启用 DNS 解析并且返回了来自不同族的多个 IP 地址时,HAProxy 将优先使用 "resolve-prefer" 参数中指定的族中的 IP 地址。可用族:"ipv4" 和 "ipv6" 默认值:ipv6
server s1 app1.domain.com:80 resolvers mydns resolve-prefer ipv6
此选项优先选择匹配网络的 IP 地址。这在云环境中很有用,可以优先选择本地 IP。在某些情况下,云高可用服务可以通过多个数据中心上的多个 IP 地址进行 anúnciate。数据中心之间的延迟不可忽略,因此此补丁允许优先选择本地数据中心。如果没有任何地址与配置的网络匹配,则会选择其他地址。
server s1 app1.domain.com:80 resolvers mydns resolve-net 10.0.0.0/8
指向一个现有的 "resolvers" 部分,以解析当前服务器的主机名。server s1 app1.domain.com:80 check resolvers mydns
另请参见 第 5.3 节
"send-proxy" 参数强制对与此服务器建立的任何连接使用 PROXY 协议。PROXY 协议通知另一端传入连接的第 3/4 层地址,以便它可以知道客户端的地址或它访问的公共地址,无论上层协议是什么。对于由 "accept-proxy" 或 "accept-netscaler-cip" 监听器接受的连接,将使用通告的地址。仅支持 TCPv4 和 TCPv6 地址族。其他族(如 Unix 套接字)将报告 UNKNOWN 族。使用此选项的服务器可以完全链接到另一个使用 "accept-proxy" 设置监听的 HAProxy 实例。如果服务器不知道该协议,则不得使用此设置。当健康检查发送到服务器时,如果设置了此选项,会自动使用 PROXY 协议,除非有显式的 "port" 或 "addr" 指令,在这种情况下,还需要显式的 "check-send-proxy" 指令才能使用 PROXY 协议。另请参阅此部分的 "no-send-proxy" 选项以及 "bind" 关键字的 "accept-proxy" 和 "accept-netscaler-cip" 选项。
"send-proxy-v2" 参数强制对与此服务器建立的任何连接使用 PROXY 协议版本 2。PROXY 协议通知另一端传入连接的第 3/4 层地址,以便它可以知道客户端的地址或它访问的公共地址,无论上层协议是什么。如果协商了 ALPN,它还会发送 ALPN 信息。如果服务器不知道此版本的协议,则不得使用此设置。另请参阅此部分的 "no-send-proxy-v2" 选项以及 "bind" 关键字的 send-proxy" 选项。
"proxy-v2-options" 参数在使用了 "send-proxy-v2" 时,会添加选项以发送到 PROXY 协议版本 2。可用选项包括:"ssl"(另请参阅 send-proxy-v2-ssl)、"cert-cn"(另请参阅 "send-proxy-v2-ssl-cn")、"ssl-cipher":使用的密码名称,"cert-sig":所用证书的签名算法,"cert-key":所用证书的密钥算法),"authority":客户端传递的主机名值(仅支持 TLS 连接的 sni),"crc32c":代理协议 v2 头的校验和。
"send-proxy-v2-ssl" 参数强制对与此服务器建立的任何连接使用 PROXY 协议版本 2。PROXY 协议通知另一端传入连接的第 3/4 层地址,以便它可以知道客户端的地址或它访问的公共地址,无论上层协议是什么。此外,PROXY 协议的 SSL 信息扩展会添加到 PROXY 协议标头中。如果服务器不知道此版本的协议,则不得使用此设置。另请参阅此部分的 "no-send-proxy-v2-ssl" 选项以及 "bind" 关键字的 "send-proxy-v2" 选项。
"send-proxy-v2-ssl" 参数强制对与此服务器建立的任何连接使用 PROXY 协议版本 2。PROXY 协议通知另一端传入连接的第 3/4 层地址,以便它可以知道客户端的地址或它访问的公共地址,无论上层协议是什么。此外,PROXY 协议的 SSL 信息扩展,以及客户端证书主题中的通用名称(如果有),会添加到 PROXY 协议标头中。如果服务器不知道此版本的协议,则不得使用此设置。另请参阅此部分的 "no-send-proxy-v2-ssl-cn" 选项以及 "bind" 关键字的 "send-proxy-v2" 选项。
服务器的 "slowstart" 参数接受一个毫秒值,表示服务器恢复正常后需要多长时间才能全速运行。与所有其他基于时间的参数一样,它可以以任何其他明确单位 { us, ms, s, m, h, d } 输入。在此期间,速度从 0 线性增长到 100%。此限制适用于两个参数: - maxconn:服务器接受的连接数将从 1 增长到由 (minconn,maxconn,fullconn) 定义的通常动态限制的 100%。 - weight:当后端使用动态加权算法时,权重会从 1 线性增长到 100%。在这种情况下,权重会在每次健康检查时更新。因此,重要的是 "inter" 参数小于 "slowstart",以最大化步数。slowstart 在 haproxy 启动时从不适用,否则会对正在运行的服务器造成麻烦。它仅适用于服务器先前被视为失败的情况。
"sni" 参数评估样本获取表达式,将其转换为字符串,并将结果用作发送到服务器的 SNI TLS 扩展中的主机名。一个典型的用例是在桥接 HTTPS 场景中发送从客户端接收到的 SNI,使用 "ssl_fc_sni" 样本获取表达式,尽管诸如 req.hdr(host) 之类的替代方案也可能是有意义的。如果设置了 "verify required"(这是推荐的设置),则生成的名字也将与服务器证书的名字进行匹配。有关更多详细信息,请参阅 "verify" 指令。如果要为健康检查设置 SNI,请参阅 "check-sni" 指令以获取更多详细信息。
"source" 参数设置连接到服务器时将使用的源地址。它遵循与后端 "source" 关键字完全相同的参数和原理,只是它仅适用于引用它的服务器。有关详细信息,请参阅 "source" 关键字。此外,服务器行上的 "source" 语句允许通过指示由破折号 ('-') 分隔的下限和上限来指定源端口范围。某些操作系统可能要求在指定源端口范围时提供有效的 IP 地址。允许为多个服务器使用相同的 IP/范围。这样做可以绕过总共 64k 并发连接的上限。此时限制将达到每个服务器 64k 连接。自 Linux 4.2/libc 2.23 起,对于指定没有端口的源地址的连接,设置了 IP_BIND_ADDRESS_NO_PORT。
此选项启用对服务器出站连接的 SSL 加密。当使用 SSL 连接到服务器时,使用 "verify" 验证服务器证书至关重要,否则通信容易受到微不足道的中间人攻击,使 SSL 失去作用。使用此选项时,健康检查也会自动以 SSL 发送,除非有 "port" 或 "addr" 指令指示检查应发送到不同的位置。请参阅 "no-ssl" 禁用 "ssl" 选项,并参阅 "check-ssl" 选项强制执行 SSL 健康检查。
使用 SSL 与服务器通信时,此选项强制使用 <version> 或更低版本。此选项也可用在全局语句 "ssl-default-server-options" 中。另请参阅 "ssl-min-ver"。
使用 SSL 与服务器通信时,此选项强制使用 <version> 或更高版本。此选项也可用在全局语句 "ssl-default-server-options" 中。另请参阅 "ssl-max-ver"。
此选项可用作 "server" 设置,用于重置任何从 "default-server" 指令继承的 "no-ssl-reuse" 设置作为默认值。它也可用作 "default-server" 设置,用于重置任何以前的 "default-server" "no-ssl-reuse" 设置。
此选项可用作 "server" 设置,用于重置任何从 "default-server" 指令继承的 "non-stick" 设置作为默认值。它也可用作 "default-server" 设置,用于重置任何以前的 "default-server" "non-stick" 设置。
此选项为到服务器的出站连接启用上游 socks4 隧道。使用此选项默认不会强制健康检查通过 socks4。您需要使用关键字 "check-via-socks4" 来启用它。
设置到此服务器的所有出站连接的 TCP 用户超时。此选项自 Linux 2.6.37 版本起可用。它允许 haproxy 为包含在配置延迟内未收到确认的数据的套接字配置超时。这对于经历长时间空闲期的长连接特别有用,例如远程终端或数据库连接池,其中客户端和服务器超时必须保持较高以允许长时间空闲,但重要的是要检测到服务器已消失,以便释放与其连接(以及客户端会话)相关的所有资源。另一个典型用例是强制死服务器连接在健康检查太慢或在软重新加载期间(因为此时健康检查被禁用)终止。参数默认以毫秒为单位表示延迟。这仅适用于常规 TCP 连接,对于其他协议将被忽略。
此选项在支持它的系统(目前仅限 Linux 内核 >= 4.11)上启用连接到服务器时使用 TCP Fast Open。有关 TCP Fast Open 的更多信息,请参阅 "tfo" bind 选项。请注意,在使用 tfo 时,您还应该为 "retry-on" 使用 "conn-failure"、"empty-response" 和 "response-timeout" 关键字,否则 haproxy 将无法在失败时重试连接。另请参阅 "no-tfo"。
此选项使服务器能够通过跟踪另一个服务器来设置其当前状态。可以跟踪本身跟踪另一个服务器的服务器,前提是链的末端有一个已启用健康检查的服务器。如果省略<proxy>,则使用当前代理。如果使用了disable-on-404,则必须在两个代理上都启用。
此选项可用作 "server" 设置,用于重置任何从 "default-server" 指令继承的 "no-tls-tickets" 设置作为默认值。TLS 票证机制仅用于 TLS 1.2 及以下版本。除非定期轮换票证密钥(通过重新加载或使用 "tls-ticket-keys"),否则前向保密性会受到 TLS 票证的损害。它也可用作 "default-server" 设置,用于重置任何以前的 "default-server" "no-tls-tickets" 设置。
此设置仅在内置 OpenSSL 支持时可用。如果设置为 'none',则不验证服务器证书。在另一种情况下,使用 'ca-file' 中的 CA 和可选的 'crl-file' 中的 CRL 验证服务器提供的证书,前提是已检查证书主题和 subjectAlternateNames 属性中提供的名称是否与使用 "sni" 指令传递的名称匹配,或者如果未提供,则与使用 "verifyhost" 指令传递的静态主机名匹配。如果未找到名称,则忽略证书的名称。因此,如果没有 SNI,使用 "verifyhost" 很重要。验证失败时,握手将中止。当使用 SSL 连接到服务器时,验证服务器证书至关重要,否则通信容易受到微不足道的中间人攻击,使 SSL 完全失去作用。除非全局部分出现 "ssl_server_verify",否则 "verify" 默认设置为 "required"。
此设置仅在内置 OpenSSL 支持时可用,并且仅在同时指定了 'verify required' 时才生效。当没有使用 SNI 连接到服务器时,此指令设置一个默认的静态主机名来检查服务器的证书。如果未使用 SNI,这是启用主机名验证的唯一方法。设置此静态主机名后,它也将用于健康检查(无法提供 SNI 值)。如果证书中的任何主机名与指定的主机名不匹配,则握手将中止。服务器提供的证书中的主机名可能包含通配符。另请参阅 "verify"、"sni" 和 "no-verifyhost" 选项。
“weight”参数用于调整服务器相对于其他服务器的权重。所有服务器将根据其权重相对于所有权重总和的比例接收负载,因此权重越高,负载越高。默认权重为 1,最大值为 256。值为 0 表示服务器不参与负载均衡,但仍接受持久连接。如果使用此参数根据服务器容量分配负载,建议从可以增长和收缩的值开始,例如 10 到 100 之间,以便为以后调整留出足够的空间。
HAProxy 允许在服务器行中使用主机名通过名称服务器检索其 IP 地址。默认情况下,HAProxy 在解析配置文件时解析名称,并在启动时缓存结果,并在进程生命周期内缓存该结果。这在某些情况下不够用,例如在 Amazon 中,服务器的 IP 地址在重启后可能会发生变化,或者 ELB 虚拟 IP 地址会根据当前工作负载而变化。本章介绍 HAProxy 如何配置为在运行时处理服务器名称解析。无论是否启用了运行时服务器名称解析,HAProxy 在解析配置时都会继续进行第一次解析。
正如我们在引言中看到的,HAProxy 中的名称解析发生在进程生命周期的两个不同步骤中: 1. 启动时,HAProxy 解析服务器行定义并匹配主机名。它使用 libc 函数来解析主机名。此解析依赖于 /etc/resolv.conf 文件。 2. 运行时,HAProxy 会对需要 DNS 解析的服务器进行定期名称解析。其他一些事件可以在运行时触发名称解析: - 当服务器的健康检查以连接超时结束时:这可能是因为服务器有了新的 IP 地址。因此我们需要触发名称解析以了解这个新的 IP。使用解析器时,服务器名称可以是主机名,也可以是 SRV 标签。HAProxy 将任何以下划线开头的名称视为 SRV 标签。如果指定了 SRV 标签,则将从 DNS 服务器检索相应的 SRV 记录,并使用提供的主机名。SRV 标签将定期检查,如果添加或删除了任何服务器,haproxy 将自动执行相同的操作。需要注意的几点: - 同时查询所有名称服务器。HAProxy 将处理第一个有效的响应。 - 当所有服务器都返回错误时,解析被视为无效(NX、超时、拒绝)。
本节专门讨论 HAProxy 中与名称解析相关的主机信息。可以有任意数量的解析器部分。每个部分可以包含许多名称服务器。当解析器部分配置了多个名称服务器时,HAProxy 会使用第一个有效的响应。如果响应无效,则只处理最后一个。目的是让慢速服务器有机会在快速故障或过时的服务器之后提供有效的答案。当每个服务器返回不同的错误类型时,HAProxy 只使用最后一个错误。以下处理应用于此错误: 1. HAProxy 使用新的查询类型重试相同的 DNS 查询。A 查询切换到 AAAA,反之亦然。SRV 查询不在此处涉及。超时错误也排除在外。 2. 当完成(或不适用)查询类型的回退时,HAProxy 使用首选查询类型重试原始 DNS 查询。 3. HAProxy 重试前一步骤 <resolve_retires> 次。如果在此之后仍未收到有效响应,它将停止 DNS 解析并报告错误。例如,在解析器部分配置了 2 个名称服务器时,可能出现以下场景: - 第一个响应有效并直接应用,第二个响应被忽略 - 第一个响应无效,第二个有效,则应用第二个响应 - 第一个响应是 NX 域,第二个是截断响应,则 HAProxy 使用新的类型重试查询 - 第一个响应是 NX 域,第二个是超时,则 HAProxy 使用新的类型重试查询 - 两个名称服务器的查询都超时,则 HAProxy 使用相同的查询类型重试 由于 DNS 服务器可能无法在一个 DNS 请求中回答所有 IP,haproxy 会保留先前答案的缓存,如果 <hold obsolete> 秒内没有返回 IP,则答案将被视为过时。
创建一个新的名为 <resolvers id> 的域名服务器列表。resolvers 部分接受以下参数:
定义 HAProxy 接受的最大负载大小,并通告给此 resolvers 部分中配置的所有名称服务器。<nb> 以字节为单位。如果未设置,HAProxy 会通告 512。 (RFC 6891 定义的最小值) 注意:允许的最大值为 8192。
DNS 服务器描述: <id> :服务器的标签,应唯一 <ip> :服务器的 IP 地址 <port> :DNS 服务实际运行的端口
将 /etc/resolv.conf 中找到的所有域名服务器添加到此 resolvers 域名服务器列表中。顺序如同 /etc/resolv.conf 中的每个域名服务器被单独放置在此指令的位置。
定义最后一个名称解析应保留的 <period>,该保留期基于最后一个解析 <status> <status>:最后一个名称解析状态。可接受的值为“nx”、“other”、“refused”、“timeout”、“valid”、“obsolete”。<period>:当最后一个答案为 <status> 时的两次连续名称解析之间的间隔。它遵循 HAProxy 时间格式。默认情况下,<period> 以毫秒为单位。“valid”为 10 秒,“obsolete”为 0 秒,“other”为 30 秒。定义在放弃之前为解析服务器名称而发送的查询次数 <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 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 provides a cache, which was designed to perform cache on small objects (favicon, css...). This is a minimalist low-maintenance cache which runs in RAM. The cache is based on a memory which is shared between processes and threads, this memory is split in blocks of 1k. If an object is not used anymore, it can be deleted to store a new object independently of its expiration date. The oldest objects are deleted first when we try to allocate a new one. The cache uses a hash of the host header and the URI as the key. It's possible to view the status of a cache using the Unix socket command "show cache" consult section 9.3 "Unix Socket commands" of Management Guide for more details. When an object is delivered from the cache, the server name in the log is replaced by "<CACHE>".
在以下情况下,缓存不会存储也不会交付对象: - 如果响应不是 200 - 如果响应包含 Vary 标头 - 如果 Content-Length + 标头大小大于 "max-object-size" - 如果响应不可缓存 - 如果请求不是 GET - 如果请求的 HTTP 版本小于 1.1 - 如果请求包含 Authorization 标头
To setup a cache, you must define a cache section and use it in a proxy with the corresponding http-request and response actions.
声明一个缓存部分,分配一个名为 <name> 的共享缓存内存,缓存大小是强制性的。
以兆字节为单位定义缓存的 RAM 大小。此大小被分成 1kB 的块,供缓存条目使用。其最大值为 4095。
定义要缓存的对象最大大小。不得大于 “total-max-size” 的一半。如果未设置,则等于缓存大小的 256 分之一。所有大小大于 “max-object-size” 的对象将不会被缓存。
Define the maximum expiration duration. The expiration is set has the lowest value between the s-maxage or max-age (in this order) directive in the Cache-Control response header and this value. The default value is 60 seconds, which means that you can't cache an object more than 60 seconds by default.
Try to deliver a cached object from the cache <name>. This directive is also mandatory to store the cache as it calculates the cache hash. If you want to use a condition for both storage and delivering that's a good idea to put it after this one.
Store an http-response within the cache. The storage of the response headers is done at this step, which means you can use others http-response actions to modify headers before or after the storage of the response. This action is responsible for the setup of the cache storage filter.
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 变体可以描述同一样本获取方法的替代匹配方法。样本获取方法是唯一支持转换的方法。样本获取方法返回的数据可以是以下类型: - 布尔值 - 整数(有符号或无符号) - IPv4 或 IPv6 地址 - 字符串 - 数据块 转换器将这些数据中的任何一种转换为任何这些类型。例如,某些转换器可能将字符串转换为小写字符串,而其他转换器可能将字符串转换为 IPv4 地址,或将网络掩码应用于 IP 地址。结果样本是应用于列表的最后一个转换器的类型,默认为样本获取方法的类型。每个样本或转换器返回特定类型的数据,在本文档中用其关键字指定。当使用标准样本获取方法声明 ACL 时,某些类型会自动涉及默认匹配方法,这些方法总结在下表中: +---------------------+-----------------+ | 样本或转换器 | 默认 | | 输出类型 | 匹配方法 | +---------------------+-----------------+ | boolean | bool | +---------------------+-----------------+ | integer | int | +---------------------+-----------------+ | ip | ip | +---------------------+-----------------+ | string | str | +---------------------+-----------------+ | binary | none, use "-m" | +---------------------+-----------------+ 请注意,为了匹配二进制样本,必须指定匹配方法,如下所述。ACL 引擎可以将这些类型与以下类型的模式匹配: - 布尔值 - 整数或整数范围 - IP 地址/网络 - 字符串(精确、子字符串、后缀、前缀、子目录、域) - 正则表达式 - 十六进制块 当前支持以下 ACL 标志: -i : 匹配所有后续模式时忽略大小写。 -f : 从文件中加载模式。 -m : 使用特定的模式匹配方法。 -n : 禁止 DNS 解析。 -M : 像加载映射文件一样加载由 -f 指向的文件。 -u : 强制 ACL 的唯一 ID。 -- : 强制标志结束。当字符串看起来像其中一个标志时很有用。 "-f" 标志后跟一个文件名,该文件中的所有行都将被读取为单个值。如果模式要从多个文件中加载,甚至可以传递多个 "-f" 参数。空行以及以井号 ('#') 开头的行将被忽略。所有前导空格和制表符都将被去除。如果绝对有必要插入以井号开头的有效模式,只需在前面加上一个空格,以免被视为注释。根据数据类型和匹配方法,haproxy 可能会将这些行加载到二叉树中,从而实现非常快速的查找。这对于 IPv4 和精确字符串匹配是正确的。在这种情况下,重复项将自动删除。 "-M" 标志允许 ACL 使用映射文件。如果设置了此标志,则文件将解析为两列文件。第一列包含 ACL 使用的模式,第二列包含样本。样本可以稍后由映射使用。在某些罕见情况下,ACL 仅用于在应用映射之前检查模式是否存在于映射中时,这可能很有用。 "-u" 标志强制 ACL 的唯一 ID。此唯一 ID 用于套接字接口以识别 ACL 并动态更改其值。请注意,即使设置了 ID,文件也始终通过其名称进行标识。另请注意,"-i" 标志应用于后续条目,而不是应用于其前面的从文件加载的条目。例如: acl valid-ua hdr(user-agent) -f exact-ua.lst -i -f generic-ua.lst test 在此示例中,"exact-ua.lst" 中的每一行都将与请求的 "user-agent" 标头进行精确匹配。然后,"generic-ua" 中的每一行都将进行不区分大小写的匹配。然后,"test" 一词也将进行不区分大小写的匹配。 "-m" 标志用于选择输入样本上的特定模式匹配方法。所有 ACL 特定条件都暗示一种模式匹配方法,通常不需要此标志。但是,此标志对于通用样本获取方法很有用,用于描述它们将如何与模式匹配。对于返回没有明显匹配方法的数据类型(例如字符串或二进制文件)的样本获取,这是必需的。当指定 "-m" 且后跟模式匹配方法名称时,将使用此方法而不是条件的默认方法。这使得可以以最初未计划的方式匹配内容,或者使用返回字符串的样本获取方法进行匹配。匹配方法还会影响模式的解析方式。 "-n" 标志禁止 DNS 解析。它用于加载 IP 文件。默认情况下,如果解析器无法解析 IP 地址,它会认为解析后的字符串可能是域名并尝试 DNS 解析。标志 "-n" 禁用此解析。它对于检测格式错误的 IP 列表很有用。请注意,如果 DNS 服务器不可达,haproxy 配置解析可能会持续数分钟,等待超时。在此期间不会显示错误消息。标志 "-n" 禁用此行为。另请注意,在运行时,对于动态 ACL 修改,此功能被禁用。但是,有一些限制。并非所有方法都可以与所有样本获取方法一起使用。此外,如果 "-m" 与 "-f" 结合使用,它必须放在前面。模式匹配方法必须是以下之一: - "found":仅检查流中是否可以找到请求的样本,但不将其与任何模式进行比较。建议不要传递任何模式以避免混淆。此匹配方法特别适用于检测某些内容(例如标头、cookie 等)的存在,即使它们为空,且不与任何内容进行比较,也不计算它们。 - "bool":将值作为布尔值进行检查。它只能应用于返回布尔值或整数值的获取,并且不带模式。值零或 false 不匹配,所有其他值都匹配。 - "int":将值作为整数匹配。它可以与整数和布尔样本一起使用。布尔 false 是整数 0,true 是整数 1。 - "ip":将值作为 IPv4 或 IPv6 地址匹配。它仅与 IP 地址样本兼容,因此它是隐含的,永远不需要。 - "bin":将内容与表示二进制序列的十六进制字符串匹配。这可以与二进制或字符串样本一起使用。 - "len":将样本的长度作为整数匹配。这可以与二进制或字符串样本一起使用。 - "str":精确匹配:将内容与字符串匹配。这可以与二进制或字符串样本一起使用。 - "sub":子字符串匹配:检查内容是否包含至少一个提供的字符串模式。这可以与二进制或字符串样本一起使用。 - "reg":正则表达式匹配:将内容与正则表达式列表匹配。这可以与二进制或字符串样本一起使用。 - "beg":前缀匹配:检查内容是否以提供的字符串模式开头。这可以与二进制或字符串样本一起使用。 - "end":后缀匹配:检查内容是否以提供的字符串模式结尾。这可以与二进制或字符串样本一起使用。 - "dir":子目录匹配:检查内容的斜杠分隔部分是否与提供的字符串模式之一精确匹配。这可以与二进制或字符串样本一起使用。 - "dom":域匹配:检查内容的点分隔部分是否与提供的字符串模式之一精确匹配。这可以与二进制或字符串样本一起使用。 例如,要快速检测 HTTP 请求中是否存在 cookie "JSESSIONID",可以执行以下操作: acl jsess_present cook(JSESSIONID) -m found 为了在缓冲区中对前 500 字节数据应用正则表达式,可以使用以下 acl: acl script_tag payload(0,500) -m reg -i <script> 在使用 "-i" 时正则表达式库速度较慢的系统上,可以在匹配之前将样本转换为小写,如下所示: acl script_tag payload(0,500),lower -m reg <script> 所有 ACL 特定条件都暗示一个默认匹配方法。大多数情况下,这些条件是通过连接原始样本获取方法的名称和匹配方法组成的。例如,"hdr_beg" 将 "beg" 匹配应用于使用 "hdr" 获取方法检索的样本。由于所有 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 (presence only) | found | found | found | found | found | +----------------------+---------+---------+---------+---------+---------+ | none (boolean value) |> bool <| bool | | bool | | +----------------------+---------+---------+---------+---------+---------+ | integer (value) | int |> int <| int | int | | +----------------------+---------+---------+---------+---------+---------+ | integer (length) | len | len | len | len | len | +----------------------+---------+---------+---------+---------+---------+ | IP address | | |> ip <| ip | ip | +----------------------+---------+---------+---------+---------+---------+ | exact string | str | str | str |> str <| str | +----------------------+---------+---------+---------+---------+---------+ | prefix | beg | beg | beg | beg | beg | +----------------------+---------+---------+---------+---------+---------+ | suffix | end | end | end | end | end | +----------------------+---------+---------+---------+---------+---------+ | substring | sub | sub | sub | sub | sub | +----------------------+---------+---------+---------+---------+---------+ | subdir | dir | dir | dir | dir | dir | +----------------------+---------+---------+---------+---------+---------+ | domain | dom | dom | dom | dom | dom | +----------------------+---------+---------+---------+---------+---------+ | regex | reg | reg | reg | reg | reg | +----------------------+---------+---------+---------+---------+---------+ | hex block | | | | bin | bin | +----------------------+---------+---------+---------+---------+---------+
为了匹配布尔值,不需要任何值,所有值都会被忽略。布尔匹配默认用于所有类型为“boolean”的获取方法。当使用布尔匹配时,获取的值会按原样返回,这意味着布尔值“true”将始终匹配,而布尔值“false”将永远不匹配。布尔匹配也可以通过在返回整数值的获取方法上使用“-m bool”来强制执行。然后,整数值 0 会被转换为布尔值“false”,所有其他值都会被转换为“true”。
整数匹配默认应用于整数获取方法。也可以使用 "-m int" 在布尔获取上强制执行。在这种情况下,"false" 转换为整数 0,"true" 转换为整数 1。整数匹配还支持整数范围和运算符。请注意,整数匹配仅适用于正值。范围是用冒号分隔的下限和上限表示的值,两者都可以省略。例如,"1024:65535" 是表示非特权端口范围的有效范围,"1024:" 也可以工作。"0:1023" 是特权端口的有效表示,":1023" 也可以工作。作为特例,一些 ACL 函数支持小数点分隔的十进制数字,这实际上是两个整数。例如,这用于某些版本检查。所有整数属性都适用于这些十进制数字,包括范围和运算符。为了更方便使用,还支持比较运算符。请注意,将运算符与范围一起使用意义不大,强烈不鼓励。同样,对一组值执行顺序比较意义不大。整数匹配的可用运算符是: eq : 如果测试值等于至少一个值,则为 true ge : 如果测试值大于或等于至少一个值,则为 true gt : 如果测试值大于至少一个值,则为 true le : 如果测试值小于或等于至少一个值,则为 true lt : 如果测试值小于至少一个值,则为 true 例如,以下 ACL 匹配任何负 Content-Length 标头: acl negative-length 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 匹配。 - 域匹配 (-m dom):在提取的字符串中查找模式,用点 (".") 分隔,如果任何模式匹配,则 ACL 匹配。 字符串匹配应用于按原样传递的逐字字符串,但反斜杠 ("\") 除外,它使得可以转义某些字符(例如空格)。如果在第一个字符串之前传递 "-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 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" 语句之后,指示何时触发操作。例如,阻止 HTTP 请求到 "*" URL(方法不是 "OPTIONS"),以及没有 content-length 的 POST 请求,以及 content-length 大于 0 的 GET 或 HEAD 请求,最后是所有不是 GET/HEAD/POST/OPTIONS 的请求: acl missing_cl 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 hdr_cnt(Content-length) eq 0 http-request deny if METH_POST missing_cl 也可以这样写: http-request deny if METH_POST { 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 对应物共享相同的语法。这些样本获取方法也称为"获取"。截至目前,ACL 和获取已经融合。所有 ACL 获取方法都已作为获取方法提供,ACL 也可以使用任何样本获取方法。本节详细介绍了所有可用的样本获取方法及其输出类型。一些样本获取方法有已弃用的别名,用于保持与现有配置的兼容性。然后,它们被明确标记为已弃用,不应在新设置中使用。如果可用,还会指示 ACL 派生词及其各自的匹配方法。这些都具有明确定义的默认模式匹配方法,因此永远不需要(尽管允许)传递 "-m" 选项来指示如何使用 ACL 匹配样本。如上文样本类型与匹配兼容性矩阵所示,当在 ACL 中使用通用样本获取方法时,"-m" 选项是强制性的,除非样本类型是布尔值、整数、IPv4 或 IPv6 之一。当相同的关键字作为 ACL 关键字和标准获取方法存在时,ACL 引擎将默认自动选择仅限 ACL 的关键字。其中一些关键字支持一个或多个强制参数,以及一个或多个可选参数。这些参数是强类型的,并在解析配置时进行检查,因此没有运行不正确参数(例如,未解析的后端名称)的风险。获取函数参数在括号之间传递,并用逗号分隔。当参数是可选的时,它将在下面用方括号 ('[ ]') 指示。当所有参数都是可选的时,可以省略括号。因此,标准样本获取方法的语法是以下之一: - name - name(arg1) - name(arg1,arg2)样本获取方法可以与应用于获取样本的转换相结合(也称为"转换器")。这些组合形成了所谓的"样本表达式",结果是一个"样本"。最初这仅受 "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> 可以是数值或变量名。变量名以作用域指示开头。允许的作用域是:“proc”:变量与整个进程共享“sess”:变量与整个会话共享“txn”:变量与事务(请求和响应)共享“req”:变量仅在请求处理期间共享“res”:变量仅在响应处理期间共享此前缀后面跟着一个名称。分隔符是“.”。名称只能包含字符“a-z”、“A-Z”、“0-9”、“.”和“_”。
根据 <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)]
对 <value> 与输入的有符号整数值执行按位“AND”操作,并将结果作为有符号整数返回。 <value> 可以是数值或变量名。变量名以其作用域的指示开头。允许的作用域有:"proc" : 变量与整个进程共享 "sess" : 变量与整个会话共享 "txn" : 变量与事务(请求和响应)共享 "req" : 变量仅在请求处理期间共享 "res" : 变量仅在响应处理期间共享 此前缀后跟一个名称。分隔符是“.”。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。
将base64编码的输入字符串转换为其二进制表示。它执行base64()的逆操作。
将二进制输入样本转换为base64字符串。它用于以可靠传输的方式(例如,SSL ID可以复制到标头中)记录或传输二进制内容。
如果类型为有符号整数的输入值非空,则返回布尔值 TRUE,否则返回 FALSE。与 and() 结合使用,可用于报告输入值的位测试的真/假(例如,验证标志的存在)。
从输入二进制样本中提取一些字节。结果是一个二进制样本,从原始样本的偏移量(以字节为单位)开始,并可选地在给定长度处截断。
在当前样本之后连接最多 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,>) 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”指令。
要求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)]
此转换器用作调试工具。它捕获输入样本并将其发送到事件接收器 <destination>,该接收器可以指定一个环形缓冲区,如“buf0”,以及“stdout”或“stderr”。可用的接收器可以在运行时通过在 CLI 上发出“show events”来检查。如果未指定,输出将是“buf0”,可以通过 CLI 的“show events”命令进行查询。可以传递一个可选的前缀 <prefix> 来帮助区分来自多个表达式的输出。然后它将出现在输出消息的冒号之前。输入样本按原样传递到输出,因此将调试转换器插入链中的任何位置都是安全的,即使对于不可打印的样本类型也是如此。
tcp-request connection track-sc0 src,debug(track-sc)
将输入的有符号整数值除以 <value>,并将结果作为有符号整数返回。如果 <value> 为 null,则返回最大的无符号整数(通常为 2^63-1)。<value> 可以是数值或变量名。变量名以其作用域的指示开头。允许的作用域有:"proc" : 变量与整个进程共享 "sess" : 变量与整个会话共享 "txn" : 变量与事务(请求和响应)共享 "req" : 变量仅在请求处理期间共享 "res" : 变量仅在响应处理期间共享 此前缀后跟一个名称。分隔符是“.”。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。
使用 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(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
将二进制输入样本转换为十六进制字符串,其中每个输入字节对应两个十六进制数字。它用于以可靠的方式记录或传输某些二进制输入数据的十六进制转储(例如,可以将 SSL ID 复制到标头中)。
将每个输入字节包含两个十六进制数字的十六进制字符串转换为整数。如果输入值无法转换,则返回零。
将一个假定包含自纪元以来日期的整数转换为适合在 HTTP 标头字段中使用的字符串表示形式。如果指定了偏移值,则在进行转换之前将其添加到日期中。这对于发出 Date 标头字段、响应中与正偏移量结合使用的 Expires 值,或者当偏移量为负时使用的 Last-Modified 值特别有用。如果指定了单位值,则将时间戳视为“s”(秒,默认行为)、“ms”(毫秒)或“us”(微秒)自纪元以来。偏移量假定与输入时间戳具有相同的单位。
使用输入样本的字符串表示在指定表中进行查找。如果在表中找不到键,则返回布尔值false。否则返回布尔值true。这可以用于验证表中是否存在某个键,该键跟踪某些元素(例如,是否已看到源IP地址或授权标头)。ipmask(<mask4>[,<mask6>])将掩码应用于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 序列(单独的 continuation 字节、错误的 continuation 字节数等) - 无效范围(解码值在 UTF-8 禁止范围内), - 字符过长(值编码的字节数超过必要)。 UTF-8 JSON 编码可能会在 UTF-8 字符大于 0xffff 时产生"值过长"错误,因为 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"}从 "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
map_<match_type>(<map_file>[,<default_value>]) map_<match_type>_<output_type>(<map_file>[,<default_value>]) 使用 <match_type> 匹配方法从 <map_file> 中搜索输入值,并返回转换为 <output_type> 类型的相关值。如果 <map_file> 中找不到输入值,则转换器返回 <default_value>。如果未设置 <default_value>,则转换器失败,并且表现为无法获取输入值。如果未设置 <match_type>,则默认为 "str"。同样,如果未设置 <output_type>,则默认为 "str"。为了方便起见,"map" 关键字是 "map_str" 的别名,用于将一个字符串映射到另一个字符串。重要的是要避免键之间的重叠:IP 地址和字符串存储在树中,因此将使用最精确的第一个匹配项。其他键存储在列表中,因此将使用第一个匹配的出现项。以下数组包含按输入类型、匹配类型和输出类型排序的所有可用映射函数列表。
| 输入类型 | 匹配方法 | 输出类型 str | 输出类型 int | 输出类型 ip |
|---|---|---|---|---|
| str | str | map_str | map_str_int | map_str_ip |
| str | beg | map_beg | map_beg_int | map_end_ip |
| str | sub | map_sub | map_sub_int | map_sub_ip |
| str | dir | map_dir | map_dir_int | map_dir_ip |
| str | dom | map_dom | map_dom_int | map_dom_ip |
| str | end | map_end | map_end_int | map_end_ip |
| str | reg | map_reg | map_reg_int | map_reg_ip |
| str | reg | map_regm | map_reg_int | map_reg_ip |
| int | int | map_int | map_int_int | map_int_ip |
| ip | ip | map_ip | map_ip_int | map_ip_ip |
名为“map_regm”的特殊映射在正则表达式中期望匹配区域,并修改输出,将反向引用(如“\1”)替换为相应的匹配文本。文件包含每行一个键+值。以“#”开头的行被忽略,空行也是如此。删除前导制表符和空格。然后,键是第一个“word”(一系列非空格/制表符字符),值是该系列空格/制表符之后直到行尾的内容,不包括尾随空格/制表符。
# 这是一条注释,会被忽略 2.22.246.0/23 United Kingdom \n <-><-----------><--><------------><----> | | | | `- 尾部空格被忽略 | | | `---------- 值 | | `-------------------- 中间空格被忽略 | `---------------------------- 键 `------------------------------------ 前导空格被忽略
将输入的有符号整数值除以 <value>,并将余数作为有符号整数返回。如果 <value> 为 null,则返回零。<value> 可以是数值或变量名。变量名以其作用域的指示开头。允许的作用域有:"proc" : 变量与整个进程共享 "sess" : 变量与整个会话共享 "txn" : 变量与事务(请求和响应)共享 "req" : 变量仅在请求处理期间共享 "res" : 变量仅在响应处理期间共享 此前缀后跟一个名称。分隔符是“.”。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。
将输入的有符号整数值乘以 <value>,并将乘积作为有符号整数返回。在溢出的情况下,将返回符号的最大可能值,以便操作不会环绕。<value> 可以是数值或变量名。变量名以其作用域的指示开头。允许的作用域有:"proc" : 变量与整个进程共享 "sess" : 变量与整个会话共享 "txn" : 变量与事务(请求和响应)共享 "req" : 变量仅在请求处理期间共享 "res" : 变量仅在响应处理期间共享 此前缀后跟一个名称。分隔符是“.”。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。
接受一个字符串类型的输入值,将其解释为后端名称,并返回该后端中可用服务器的数量。可用于需要从动态名称(如 map 查找的结果)查找后端的地方。
获取类型为有符号整数的输入值,计算其相反值,并以有符号整数的形式返回余数。0 是单位元。此运算符用于反向减法:为了从一个常量中减去输入值,只需执行 "neg,add(value)"。
如果输入的有符号整数值非零,则返回布尔值 FALSE,否则返回 TRUE。与 and() 结合使用,可用于报告输入值的位测试结果是真还是假(例如,验证某个标志是否存在)。
如果类型为有符号整数的输入值为奇数,则返回布尔值 TRUE,否则返回 FALSE。它在功能上等同于 "and(1),bool"。
对 <value> 和输入的有符号整数值执行按位“OR”操作,并将结果作为有符号整数返回。<value> 可以是数值或变量名。变量名以其作用域的指示开头。允许的作用域有:"proc" : 变量与整个进程共享 "sess" : 变量与整个会话共享 "txn" : 变量与事务(请求和响应)共享 "req" : 变量仅在请求处理期间共享 "res" : 变量仅在响应处理期间共享 此前缀后跟一个名称。分隔符是“.”。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。
此转换器用于提取协议缓冲区消息字段的原始模式,输入是协议缓冲区消息的二进制样本表示形式,如果未提供 <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>/" 相同。默认情况下,它将用替换字符串 <subst> 替换输入字符串中与正则表达式 <regex> 匹配的最大部分的第一个匹配项。通过在第三个参数 <flags> 中添加标志 "g",可以替换所有匹配项。通过在 <flags> 中添加标志 "i",还可以使正则表达式不区分大小写。由于 <flags> 是一个字符串,它由所有所需标志的连接组成。因此,如果需要 "i" 和 "g",使用 "gi" 或 "ig" 将具有相同的效果。需要注意的是,由于当前配置解析器的限制,某些字符(如右括号、右方括号或逗号)不能用于参数中。此转换器的主要用途是替换某些字符或字符序列。
# 在标头 "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)]
捕获请求槽 <id> 中的字符串条目,并按原样返回该条目。如果槽不存在,捕获将静默失败。
捕获响应槽 <id> 中的字符串条目,并按原样返回该条目。如果槽不存在,捕获将静默失败。
使用 SDBM 哈希函数将二进制输入样本哈希成一个无符号 32 位量。可选择地,如果可选参数 <avalanche> 等于 1,则可以对输出应用完整的雪崩哈希函数。此转换器使用的函数与各种基于哈希的负载平衡算法使用的函数相同,因此将提供完全相同的结果。它主要用于调试,但可用作粘滞表条目以收集粗略统计信息。它不应用于安全目的,因为 32 位哈希很容易被破解。另请参阅 "crc32"、"djb2"、"wt6"、"crc32c" 和 "hash-type" 指令。set-var(<var name>) 使用输入内容设置一个变量,并按原样返回输出内容。该变量保留值和相关的输入类型。变量名称以指示其范围的前缀开头。允许的范围有:"proc":变量在整个进程中共享;"sess":变量在整个会话中共享;"txn":变量在事务(请求和响应)中共享;"req":变量仅在请求处理期间共享;"res":变量仅在响应处理期间共享。此前缀后跟一个名称。分隔符是 '.'。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。
将二进制输入样本转换为 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(右字符串大于左字符串,或右字符串较短)。
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> 可以是数值或变量名。变量名以其作用域的指示开头。允许的作用域有:"proc" : 变量与整个进程共享 "sess" : 变量与整个会话共享 "txn" : 变量与事务(请求和响应)共享,"req" : 变量仅在请求处理期间共享,"res" : 变量仅在响应处理期间共享。此前缀后跟一个名称。分隔符是“.”。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的平均客户端到服务器字节速率,以字节量/周期(在表中配置)衡量。另请参阅 sc_bytes_in_rate 样本获取关键字。
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的平均服务器到客户端字节速率,以字节量/周期(在表中配置)衡量。另请参阅 sc_bytes_out_rate 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回与指定表中输入样本关联的传入连接的累积数量。另请参见 sc_conn_cnt 样本获取关键字。
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的当前并发跟踪连接数。另请参阅 sc_conn_cur 样本获取关键字。
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的平均传入连接速率。另请参阅 sc_conn_rate 样本获取关键字。
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回布尔值零。否则,转换器返回与指定表中输入样本关联的第一个通用目的标签的当前值。另请参阅 sc_get_gpt0 样本获取关键字。
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的第一个通用目的计数器的当前值。另请参阅 sc_get_gpc0 样本获取关键字。
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回在表中配置的周期内 gpc0 计数器递增的频率,与指定表中输入样本相关联。另请参阅 sc_get_gpc0_rate 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的第二个通用目的计数器的当前值。另请参见 sc_get_gpc1 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的 gpc1 计数器在表中配置的时间段内增量的频率。另请参见 sc_get_gpc1_rate 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的 HTTP 错误累积数量。另请参见 sc_http_err_cnt 样本获取关键字。
使用输入样本的字符串表示形式在指定表中执行查找。如果在表中找不到键,则返回整数值零。否则,返回与指定表中的输入样本关联的 HTTP 错误的平均速率,以表中配置的时间段内的错误数量来衡量。另请参阅 sc_http_err_rate 样本提取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的 HTTP 请求累积数量。另请参见 sc_http_req_cnt 样本获取关键字。
使用输入样本的字符串表示形式在指定表中执行查找。如果在表中找不到键,则返回整数值零。否则,返回与指定表中的输入样本关联的 HTTP 请求的平均速率,以表中配置的时间段内的请求数量来衡量。另请参阅 sc_http_req_rate 样本提取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的客户端到服务器数据的累积数量,以千字节为单位。当前测试是在 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 样本提取关键字。
将字符串样本转换为大写。这只能放在字符串样本提取函数之后或返回字符串类型的转换关键字之后。结果为字符串类型。
接受一个经过 URL 编码的字符串作为输入,并返回其解码后的版本作为输出。输入和输出的类型都是字符串。如果将 <in_form> 参数设置为非零整数值,则假定输入字符串是表单或查询字符串的一部分,并且“+”字符将被转换为空格(' ')。否则,只有在表示查询字符串的问号(“?”)之后才会发生这种情况。
此转换器用于提取 gRPC 消息的协议缓冲区消息字段的原始模式,输入是 gRPC 消息的二进制样本表示形式,如果未提供 <field_type>,则使用 <field_number> 作为字段编号(点分表示法),如果提供了该字段,则将其作为整数样本。授权的类型列表如下:"int32"、"int64"、"uint32"、"uint64"、"sint32"、"sint64"、"bool"、"enum" 对应 "varint" 线类型 0,"fixed64"、"sfixed64"、"double" 对应 64 位线类型 1,"fixed32"、"sfixed32"、"float" 对应线类型 5。请注意,"string" 被视为长度分隔类型,因此提取时不需要任何 <field_type> 参数。有关协议缓冲区消息字段类型的更多信息,请参阅此处:https://developers.google.com/protocol-buffers/docs/encoding// 假设有一个协议缓冲区 .proto 文件内容改编自 // https://github.com/grpc/grpc/blob/master/examples/protos/route_guide.proto message Point { int32 latitude = 1; int32 longitude = 2; } message PPoint { Point point = 59; } message Rectangle { // 矩形的一个角。 PPoint lo = 48; // 矩形的另一个角。 PPoint hi = 49; } 假设请求主体由一个 "Rectangle" 对象值(两个 PPoint 协议缓冲区消息)组成,可以使用以下 "ungrpc" 指令提取这四个协议缓冲区字段:req.body,ungrpc(48.59.1,int32) # "lo" 第一个 PPoint 的 "latitude" req.body,ungrpc(48.59.2,int32) # "lo" 第一个 PPoint 的 "longitude" req.body,ungrpc(49.59.1,int32) # "hi" 第二个 PPoint 的 "latitude" req.body,ungrpc(49.59.2,int32) # "hi" 第二个 PPoint 的 "longitude" 我们也可以按如下方式将中间字段 48.59 提取为二进制样本:req.body,ungrpc(48.59) 由于 gRPC 消息始终由 gRPC 标头后跟协议缓冲区消息组成,在前面的示例中,"lo" 第一个 PPoint 的 "latitude" 可以使用以下等效指令提取:req.body,ungrpc(48.59),protobuf(1,int32) req.body,ungrpc(48),protobuf(59.1,int32) req.body,ungrpc(48),protobuf(59),protobuf(1,int32) 请注意,第一个转换器必须是 "ungrpc",其余的必须是 "protobuf",并且只有最后一个转换器可以有或没有第二个参数来解释前一个二进制样本。
unset-var(<var name>) 如果定义了输入内容,则取消设置变量。变量名称以指示其范围的前缀开头。允许的范围有:"proc":变量在整个进程中共享;"sess":变量在整个会话中共享;"txn":变量在事务(请求和响应)中共享;"req":变量仅在请求处理期间共享;"res":变量仅在响应处理期间共享。此前缀后跟一个名称。分隔符是 '.'。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。
将一个假定包含自纪元以来日期的整数,使用 strftime(3) 定义的 <format> 字符串格式,转换为表示该日期的 UTC 时间字符串。目的是允许在日志中使用任何日期格式。可以对输入日期应用一个可选的 <offset>(以秒为单位,可正可负)。有关您的操作系统支持的格式,请参阅 strftime() 手册页。另请参阅 ltime 转换器。
# 输出两个部分,一个包含 UTC 时间,另一个包含 ip:port # 例如 20140710162350 127.0.0.1:57325 log-format %[date,utime(%Y%m%d%H%M%S)]\ %ci:%cp
从输入字符串中提取从开头(正索引)或结尾(负索引)计数,并根据给定分隔符的第n个单词。索引从1或-1开始,分隔符是格式化的字符列表字符串。输入字符串开头或结尾的分隔符将被忽略。您可以选择指定要提取的单词数<count>(默认值:1)。值为0表示提取所有剩余单词。
str(f1_f2_f3__f5),word(4,_) # f5 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
使用 WT6 哈希函数将二进制输入样本哈希为一个无符号 32 位整数。可选地,如果可选的 <avalanche> 参数等于 1,则可以对输出应用全雪崩哈希函数。此转换器使用与各种基于哈希的负载均衡算法相同的函数,因此它将提供完全相同的结果。它主要用于调试,但可以用作粘滞表条目以收集粗略的统计数据。它不得用于安全目的,因为 32 位哈希很容易被破解。另请参阅“crc32”、“djb2”、“sdbm”、“crc32c”和“hash-type”指令。
对 <value> 和类型为有符号整数的输入值执行按位“XOR”(异或)操作,并将结果作为有符号整数返回。<value> 可以是数字值或变量名。变量名以指示其范围的指示符开头。允许的作用域是:“proc”:变量与整个进程共享;“sess”:变量与整个会话共享;“txn”:变量与事务(请求和响应)共享;“req”:变量仅在请求处理期间共享;“res”:变量仅在响应处理期间共享。此前缀后跟一个名称。分隔符是“.”。名称只能包含字符“a-z”、“A-Z”、“0-9”、“.”和“_”。
使用 XXHash 哈希函数的 32 位变体将二进制输入样本哈希为一个无符号 32 位整数。此哈希支持一个种子,默认为零,但可以通过 <seed> 参数传递不同的值。此哈希以其优异性能和极快速度而闻名,因此可用于哈希 URL 和/或 URL 参数,作为粘滞表键来收集具有低碰撞率的统计数据,但必须注意,该算法不被认为是密码学安全的。
使用 XXHash 哈希函数的 64 位变体将二进制输入样本哈希为一个有符号 64 位整数。此哈希支持一个种子,默认为零,但可以通过 <seed> 参数传递不同的值。此哈希以其优异性能和极快速度而闻名,因此可用于哈希 URL 和/或 URL 参数,作为粘滞表键来收集具有低碰撞率的统计数据,但必须注意,该算法不被认为是密码学安全的。
第一组样本提取方法适用于甚至不涉及任何客户端信息的内部信息。这些方法有时与“monitor-fail”指令一起使用,向外部监视器报告内部状态。本节描述的样本提取方法可在任何地方使用。
始终返回布尔值“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 结构。
解析distcc消息并返回与标记<token>的出现次数#<occ>关联的正文。出现次数从1开始,如果未指定,则任何出现次数都可能匹配,尽管实际上目前只检查第一个。这可用于提取通过haproxy构建的文件中的文件名或参数。有关支持的令牌的完整列表,请参阅distcc的协议文档。
解析distcc消息并返回与标记<token>的出现次数#<occ>关联的参数。出现次数从1开始,如果未指定,则任何出现次数都可能匹配,尽管实际上目前只检查第一个。这可用于提取某些信息,例如协议版本、文件大小或通过haproxy构建的文件中的参数。另一个用例是等待预处理文件内容开始,然后再连接到服务器,以避免保持空闲连接。有关支持的令牌的完整列表,请参阅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 }
返回一个包含环境变量 <name> 值的字符串。提醒一下,环境变量是每个进程的,并在进程启动时采样。这对于将一些信息传递给下一跳服务器,或者与 ACL 结合使用以在进程以特定方式启动时采取特定操作很有用。
# 将带有本地主机名的 Via 头传递给下一跳 http-request add-header Via 1.1\ %[env(HOSTNAME)] # 当设置了 STOP 环境变量时,拒绝无 cookie 的请求 http-request deny if !{ 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 地址。
返回一个平均纳秒数,表示处理流的任务被唤醒到实际被调用的时间间隔。在 HTTP keep-alive 的情况下,此数字在同一连接上的每个新请求都会重置。此值指示当前请求因并行处理的所有其他请求而受到的总延迟,并且是由于“嘈杂邻居”引起的感知性能的直接指标。为了保持较低的值,可以通过使用 "tune.runqueue-depth" 减少调度程序的运行队列深度,使用 "tune.maxpollevents" 减少一次处理的并发事件数,通过在 "bind" 行或前端中使用 "nice" 选项降低流的 nice 值,或在日志中查找其他重型请求(显示 "cpu_ns_avg" 值较大的请求),这些请求的处理需要调整或修复。大缓冲区的压缩可能是罪魁祸首,例如繁重的正则表达式或长列表的正则表达式。注意:此值正好是 lat_ns_tot 除以 cpu_calls。
返回一个总纳秒数,表示处理流的任务被唤醒到实际被调用的时间间隔。在 HTTP keep-alive 的情况下,此数字在同一连接上的每个新请求都会重置。此值指示当前请求因并行处理的所有其他请求而受到的总延迟,并且是由于“嘈杂邻居”引起的感知性能的直接指标。为了保持较低的值,可以通过使用 "tune.runqueue-depth" 减少调度程序的运行队列深度,使用 "tune.maxpollevents" 减少一次处理的并发事件数,通过在 "bind" 行或前端中使用 "nice" 选项降低流的 nice 值,或在日志中查找其他重型请求(显示 "cpu_ns_avg" 值较大的请求),这些请求的处理需要调整或修复。大缓冲区的压缩可能是罪魁祸首,例如繁重的正则表达式或长列表的正则表达式。注意:虽然直观上似乎总延迟会增加传输时间,但几乎从不如此,因为当任务等待 CPU 时,网络缓冲区会继续填充,下一次调用将一次处理更多数据。由于 cpu_calls 计数很高,此值可能会人为地很高,例如在处理许多 HTTP 块时,因此通常首选记录 lat_ns_avg,它是一个更相关的性能指标。
返回一个方法。
返回一个整数值,对应于已启动的进程数(它等于全局“nbproc”设置)。这对于日志记录和调试目的很有用。返回一个整数值,对应于当前后端或指定后端的可用服务器数量。这主要与 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”时设置的值。
返回一个整数值,对应于调用该函数的进程的位置,介于 1 和 global.nbproc 之间。这对于日志记录和调试目的很有用。
返回指定后端的排队连接总数,包括服务器队列中的所有连接。如果未指定后端名称,则使用当前后端,但也可以检查另一个后端。这对于 ACL 或将统计信息传递给后端服务器很有用。这可用于在排队超过已知水平时采取行动,这通常表示流量激增或服务器大规模减速。一个可能的操作是拒绝新用户但仍然接受老用户。另请参阅“avg_queue”、“be_conn”和“be_sess_rate”提取。
返回一个在 <range> 个可能值范围内的随机整数值,从零开始。如果未指定范围,则默认为 2^32,即数字介于 0 和 4294967295 之间。例如,传递一些需要用于做出某些路由决策的值可能很有用,或者仅仅用于调试目的。此随机数不得用于安全目的。
返回遵循RFC4122标准的UUID。如果未指定版本,则返回UUID版本4(完全随机)。目前,仅支持版本4。
返回一个整数值,对应于指定服务器上当前已建立的连接数,可能包括正在评估的连接。如果省略 <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
如果调用该函数的进程当前正在停止,则返回 TRUE。这对于日志记录,或在优雅关闭时放宽某些检查或帮助关闭某些连接很有用。
返回一个字符串。
返回当前代理的粘性表或指定粘性表中可用条目的总数。另请参阅 table_cnt。
返回当前代理的粘性表或指定粘性表中当前使用的条目总数。有关其他条目计数方法,请参阅 src_conn_cnt 和 table_avl。
返回一个整数值,对应于调用该函数的线程的位置,介于 0 和 (global.nbthread-1) 之间。这对于日志记录和调试目的很有用。
返回带有存储类型变量。如果变量未设置,则采样获取失败。变量名以其范围的指示开始。允许的范围是:“proc”:变量与整个进程共享“sess”:变量与整个会话共享“txn”:变量与事务(请求和响应)共享,“req”:变量仅在请求处理期间共享,“res”:变量仅在响应处理期间共享。此前缀后跟一个名称。分隔符是“.”。名称只能包含字符“a-z”、“A-Z”、“0-9”、“.”和“_”。
第 4 层通常仅描述传输层,在 haproxy 中它最接近连接,此时还没有内容可用。除非需要未来的信息,否则此处描述的获取方法在 "tcp-request connection" 规则集上即可使用。这些通常包括 TCP/IP 地址和端口,以及与传入连接相关的粘滞表元素。要从粘滞计数器中检索值,可以使用预定义的 "sc0_"、"sc1_" 或 "sc2_" 前缀将计数器编号明确设置为 0、1 或 2。只有当 MAX_SESS_STKCTR 值不超过 3 时,才能使用这三个预定义前缀,否则在使用 "sc_" 前缀时,计数器编号可以指定为第一个整数参数。从 "sc_0" 到 "sc_N",其中 N 是 (MAX_SESS_STKCTR-1)。可以使用 "sc*" 形式指定可选表,在这种情况下,将在该备用表中查找当前跟踪的密钥,而不是当前正在跟踪的表。
返回后端连接的 HTTP 主版本编码,可以是 1(用于 HTTP/0.9 到 HTTP/1.1)或 2(用于 HTTP/2)。请注意,这基于线上传输的编码,而不是请求标头中存在的版本。
返回一个包含当前后端 ID 的整数。它可以在前端的响应中使用,以检查哪个后端处理了请求。
返回一个包含当前后端名称的字符串。它可以在前端与响应一起使用,以检查哪个后端处理了请求。
这是客户端的连接目标 IPv4 地址,即客户端连接到的地址。在透明模式下运行时可能很有用。它属于 IP 类型,并且适用于 IPv4 和 IPv6 表。在 IPv6 表中,IPv4 地址根据 RFC 4291 映射到其 IPv6 等效地址。当传入连接经过地址转换或涉及连接跟踪的重定向时,将报告重定向之前的原始目标地址。在 Linux 系统上,如果设置了 nf_conntrack_tcp_loose sysctl,源地址和目标地址可能会很少出现颠倒,因为晚期响应可能会重新打开一个已超时连接并切换被认为是源地址和目标地址的地址。
返回一个整数值,对应于同一套接字上当前建立的连接数,包括正在评估的连接。它通常与 ACL 一起使用,但也可以用于在 HTTP 头中或日志中将信息传递给服务器。它可以用于在硬阻塞之前返回一个“抱歉”页面,或者在套接字被认为饱和时使用特定的后端来处理新请求。这提供了为不同的侦听端口或地址分配不同限制的能力。另请参阅“fe_conn”和“be_conn”提取。
如果传入连接的目标地址是本地系统地址,则返回 true;如果地址不存在于系统中(意味着它在透明模式下被拦截),则返回 false。这对于默认情况下对转发流量应用某些规则,而对定向到机器实际地址的流量应用其他规则可能很有用。例如,统计页面可能仅在该地址上提供,或者 SSH 访问可能被本地重定向。请注意,该检查涉及一些系统调用,因此最好每个连接只执行一次。
返回一个整数值,对应于客户端侧连接的目标 TCP 端口,即客户端连接到的端口。这可能在透明模式下运行、为某些客户端的整个应用程序会话分配动态端口、将所有用户粘滞到同一台服务器,或使用 HTTP 头将目标端口信息传递给服务器时使用。
报告前端连接的 HTTP 主版本编码,可以是 1(用于 HTTP/0.9 到 HTTP/1.1)或 2(用于 HTTP/2)。请注意,这基于线上传输的编码,而不是请求标头中存在的版本。
返回客户端在 PROXY 协议头中发送的权威 TLV(如果有)。
如果客户端使用 PROXY 协议头启动连接,则返回 true。
返回内核为客户端连接测量的往返时间(RTT)。<unit> 是可选的,默认单位是毫秒。<unit> 可以设置为“ms”表示毫秒,或“us”表示微秒。如果服务器连接未建立,连接不是 TCP,或者操作系统不支持 TCP_INFO(例如 Linux 内核 2.4 之前的版本),则样本获取失败。
返回内核为客户端连接测量的往返时间(RTT)方差。<unit> 是可选的,默认单位是毫秒。<unit> 可以设置为“ms”表示毫秒,或“us”表示微秒。如果服务器连接未建立,连接不是 TCP,或者操作系统不支持 TCP_INFO(例如 Linux 内核 2.4 之前的版本),则样本获取失败。
返回内核为客户端连接测量的未确认计数器。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
返回内核为客户端连接测量的 sacked 计数器。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
返回内核为客户端连接测量的重传计数器。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
返回内核为客户端连接测量的 fack 计数器。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
返回内核为客户端连接测量的丢失计数器。如果服务器连接未建立,连接不是 TCP,或者操作系统不支持 TCP_INFO(例如 Linux 内核 2.4 之前的版本),则样本获取失败。
返回内核为客户端连接测量的重排序计数器。如果服务器连接未建立,连接不是 TCP,或者操作系统不支持 TCP_INFO(例如 Linux 内核 2.4 之前的版本),则样本获取失败。
返回前端的默认后端名称的字符串。它可以在前端用于检查哪个后端将默认处理请求。
返回一个包含当前前端 ID 的整数。它可以在后端使用,以检查它是从哪个前端调用的,或将通过同一前端进入的所有用户粘滞到同一台服务器。
返回当前前端名称的字符串。它可以在后端用于检查它是由哪个前端调用的,或者将来自同一前端的所有用户粘性到同一服务器。
返回当前跟踪的计数器中客户端到服务器的平均字节速率,以表中配置的时间段内的字节量来衡量。另请参阅 src_bytes_in_rate。
返回当前跟踪的计数器中服务器到客户端的平均字节速率,以表中配置的时间段内的字节量来衡量。另请参阅 src_bytes_out_rate。
清除与当前跟踪的计数器关联的第一个通用计数器,并返回其先前的值。在第一次调用之前,存储的值为零,因此第一次调用将始终返回零。这通常用作表达式中的第二个 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。
返回与当前跟踪的计数器关联的第一个通用计数器的值。另请参阅 src_get_gpc0 和 sc/sc0/sc1/sc2_inc_gpc0。
返回与当前跟踪的计数器关联的第二个通用目的计数器的值。另请参阅 src_get_gpc1 和 sc/sc0/sc1/sc2_inc_gpc1。
返回与当前跟踪的计数器关联的第一个通用标签(General Purpose Tag)的值。另请参阅 src_get_gpt0。
返回与当前跟踪的计数器关联的第一个通用计数器的平均增量速率。它报告在配置的时间段内 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 请求数。这包括所有开始的请求,无论有效与否。另请参阅 src_http_req_cnt。
返回当前跟踪的计数器中 HTTP 请求的平均速率,以表中配置的时间段内的请求数量来衡量。这包括每个已启动的请求,无论其有效与否。另请参阅 src_http_req_rate。
递增与当前跟踪的计数器关联的第一个通用计数器,并返回其新值。在第一次调用之前,存储的值为零,因此第一次调用将将其增加到 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”行但需要在前端中使用的监听套接字 ID 非常有用,或者将通过同一套接字传入的所有用户绑定到同一服务器。返回一个包含当前监听套接字名称的字符串,该名称在“bind”行中通过 name 定义。它的用途与 so_id 相同,但使用字符串而不是整数。这是会话客户端的源 IPv4 地址。它是 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。
清除与传入连接的源地址在当前代理的粘滞表或指定粘滞表中的第一个通用计数器,并返回其先前的值。如果找不到该地址,则会创建一个条目并返回 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。
返回与当前代理的粘性表或指定粘性表中传入连接的源地址关联的第一个通用计数器的值。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_get_gpc0 和 src_inc_gpc0。
返回当前代理的 stick-table 或指定 stick-table 中与传入连接的源地址关联的第二个通用计数器的值。如果未找到该地址,则返回零。另请参阅 sc/sc0/sc1/sc2_get_gpc1 和 src_inc_gpc1。
返回与当前代理的粘性表或指定粘性表中传入连接的源地址关联的第一个通用标签的值。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_get_gpt0。
返回与当前代理的粘性表或指定粘性表中传入连接的源地址关联的第一个通用计数器的平均增量速率。它报告在配置的时间段内 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 请求总数。这包括每个已启动的请求,无论是否有效。如果未找到该地址,则返回零。另请参阅 sc/sc0/sc1/sc2_http_req_cnt。
返回当前代理的粘性表或指定粘性表中,来自传入连接源地址的 HTTP 请求的平均速率,以表中配置的时间段内的请求数量来衡量。这包括每个已启动的请求,无论其有效与否。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_http_req_rate。
递增与传入连接的源地址在当前代理的粘滞表或指定粘滞表中的第一个通用计数器,并返回其新值。如果找不到该地址,则会创建一个条目并返回 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 源端口,即客户端连接的来源端口。此函数的用途非常有限,因为现代协议如今不太关心源端口。
返回当前代理的 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,但也可用于日志记录或调试。
在处理响应时返回包含服务器名称的字符串。虽然它几乎只用于 ACL,但也可用于日志记录或调试。
第 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)]
当后端连接通过 SSL/TLS 传输层建立并且在本地解密时,返回 true。这意味着传出连接是向带有 "ssl" 选项的服务器建立的。当传出连接通过 SSL/TLS 传输层建立时,返回支持的对称加密密钥大小(以位为单位)。
此转换器从通过 TLS 传输层建立的传出连接中提取应用层协议协商字段。结果是包含与服务器协商的协议名称的字符串。SSL 库必须在构建时启用 TLS 扩展支持(检查 haproxy -vv)。请注意,除非 "server" 行上的 "alpn" 关键字指定了协议列表,否则不会播发 TLS ALPN 扩展。此外,没有任何东西强制服务器从该列表中选择协议,可以请求任何其他协议。TLS ALPN 扩展旨在取代 TLS NPN 扩展。另请参阅 "ssl_bc_npn"。
当传出连接通过 SSL/TLS 传输层建立时,返回所使用的加密套件的名称。
当传入连接通过 SSL/TLS 传输层建立时,返回后端连接的客户端随机数。它对于解密使用临时密码套件发送的流量很有用。这需要 OpenSSL >= 1.1.0 或 BoringSSL。
当后端连接是通过 SSL/TLS 传输层建立,并且新创建的 SSL 会话是通过缓存会话或 TLS 票据恢复的时,返回 true。
此转换器从通过 TLS 传输层建立的传出连接中提取下一个协议协商字段。结果是包含与服务器协商的协议名称的字符串。SSL 库必须在构建时启用 TLS 扩展支持(检查 haproxy -vv)。请注意,除非 "server" 行上的 "npn" 关键字指定了协议列表,否则不会播发 TLS NPN 扩展。此外,没有任何东西强制服务器从该列表中选择协议,可以使用任何其他协议。请注意,TLS NPN 扩展已被 ALPN 取代。
当传出连接通过 SSL/TLS 传输层建立时,返回所使用的协议的名称。
当传出连接通过 SSL/TLS 传输层建立时,返回 RFC5929 第 3 节中定义的 TLS 唯一 ID。该唯一 ID 可以使用转换器 "ssl_bc_unique_id,base64" 编码为 base64。
当传入连接通过 SSL/TLS 传输层建立时,返回后端连接的服务器随机数。它对于解密使用临时密码套件发送的流量很有用。这需要 OpenSSL >= 1.1.0 或 BoringSSL。
当传出连接通过 SSL/TLS 传输层建立时,返回后端连接的 SSL ID。如果我们想知道会话是否被重用,记录此信息会很有用。
当传出连接是通过 SSL/TLS 传输层建立时,返回后端连接的 SSL 会话主密钥。这对于解密使用临时密码发送的流量很有用。这需要 OpenSSL >= 1.1.0 或 BoringSSL。
当传出连接通过 SSL/TLS 传输层建立时,返回实际使用的对称加密密钥大小(以位为单位)。
当传入连接通过 SSL/TLS 传输层建立时,如果在验证深度 > 0 的客户端证书期间检测到第一个错误,则返回该错误的 ID;如果在此验证过程中未遇到错误,则返回 0。请参考您的 SSL 库文档以查找完整的错误代码列表。
当传入连接通过 SSL/TLS 传输层建立时,如果在验证客户端证书期间检测到第一个错误,则返回该错误在 CA 链中的深度。如果未遇到错误,则返回 0。
当传入连接通过 SSL/TLS 传输层建立时,返回由客户端提供的 DER 格式证书。当用于 ACL 时,用于匹配的值可以以十六进制形式传递。
当传入连接通过 SSL/TLS 传输层建立时,如果在深度为 0 的验证期间检测到第一个错误,则返回该错误的 ID;如果在此验证过程中未遇到错误,则返回 0。请参考您的 SSL 库文档以查找完整的错误代码列表。
当传入连接通过 SSL/TLS 传输层建立时,如果未指定 <entry>,则返回客户端证书颁发者的完整专有名称 (DN);否则返回从 DN 开头找到的第一个给定条目的值。如果指定了正/负出现次数作为可选的第二个参数,则返回从 DN 开头/结尾算起的第 n 个给定条目的值。例如,"ssl_c_i_dn(OU,2)" 获取第二个组织单位,而 "ssl_c_i_dn(CN)" 获取通用名称。
当传入连接通过 SSL/TLS 传输层建立时,返回用于生成客户端证书密钥的算法名称。
当传入连接通过 SSL/TLS 传输层建立时,返回客户端证书中显示的结束日期,格式为 YYMMDDhhmmss[Z] 字符串。
当传入连接通过 SSL/TLS 传输层建立时,返回客户端证书中显示的开始日期,格式为 YYMMDDhhmmss[Z] 字符串。
当传入连接通过 SSL/TLS 传输层建立时,如果未指定 <entry>,则返回客户端证书主体的完整专有名称 (DN);否则返回从 DN 开头找到的第一个给定条目的值。如果指定了正/负出现次数作为可选的第二个参数,则返回从 DN 开头/结尾算起的第 n 个给定条目的值。例如,"ssl_c_s_dn(OU,2)" 获取第二个组织单位,而 "ssl_c_s_dn(CN)" 获取通用名称。
当传入连接通过 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>,则返回前端证书颁发者的完整专有名称 (DN);否则返回从 DN 开头找到的第一个给定条目的值。如果指定了正/负出现次数作为可选的第二个参数,则返回从 DN 开头/结尾算起的第 n 个给定条目的值。例如,"ssl_f_i_dn(OU,2)" 获取第二个组织单位,而 "ssl_f_i_dn(CN)" 获取通用名称。
当传入连接通过 SSL/TLS 传输层建立时,返回用于生成前端证书密钥的算法名称。
当传入连接通过 SSL/TLS 传输层建立时,返回前端证书中显示的结束日期,格式为 YYMMDDhhmmss[Z] 字符串。
当传入连接通过 SSL/TLS 传输层建立时,返回前端证书中显示的开始日期,格式为 YYMMDDhhmmss[Z] 字符串。
当传入连接通过 SSL/TLS 传输层建立时,如果未指定 <entry>,则返回前端证书主体的完整专有名称 (DN);否则返回从 DN 开头找到的第一个给定条目的值。如果指定了正/负出现次数作为可选的第二个参数,则返回从 DN 开头/结尾算起的第 n 个给定条目的值。例如,"ssl_f_s_dn(OU,2)" 获取第二个组织单位,而 "ssl_f_s_dn(CN)" 获取通用名称。
当传入连接通过 SSL/TLS 传输层建立时,返回前端证书的序列号。当用于 ACL 时,用于匹配的值可以以十六进制形式传递。
当传入连接通过 SSL/TLS 传输层建立时,返回前端证书的 SHA-1 指纹。这可用于了解使用 SNI 选择了哪个证书。
当传入连接通过 SSL/TLS 传输层建立时,返回用于签署前端证书的算法名称。
当传入连接通过 SSL/TLS 传输层建立时,返回前端证书的版本。
当前端连接是通过 SSL/TLS 传输层建立并且本地解密时,返回 true。这意味着它匹配了一个使用“bind”行声明的套接字,该套接字具有“ssl”选项。
# 当客户端通过 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 本地解密的传入连接中提取应用层协议协商字段。结果是包含客户端播发的协议名称的字符串。SSL 库必须在构建时启用 TLS 扩展支持(检查 haproxy -vv)。请注意,除非 "bind" 行上的 "alpn" 关键字指定了协议列表,否则不会播发 TLS ALPN 扩展。此外,没有任何东西强制客户端从该列表中选择协议,可以请求任何其他协议。TLS ALPN 扩展旨在取代 TLS NPN 扩展。另请参阅 "ssl_fc_npn"。
当传入连接通过 SSL/TLS 传输层建立时,返回所使用的加密套件的名称。
返回客户端 hello 密码列表的二进制形式。返回值的最大长度与“tune.ssl.capture-cipherlist-size”的值一致。
返回编码为十六进制的客户端 hello 密码列表的二进制形式。返回值的最大长度与“tune.ssl.capture-cipherlist-size”的值一致。
返回已解码的客户端 hello 密码列表的文本形式。返回的密码最大数量与“tune.ssl.capture-cipherlist-size”的值一致。请注意,此采样获取仅在 OpenSSL >= 1.0.2 时可用。如果未启用该函数,则此采样获取将返回类似“ssl_fc_cipherlist_xxh”的哈希值。
返回密码列表的 xxh64 哈希值。只有当“tune.ssl.capture-cipherlist-size”的值设置为大于 0 时才能返回此哈希值,但是哈希值会考虑密码列表的所有数据。
当入站连接通过 SSL/TLS 传输层建立时,返回前端连接的客户端随机数(client random)。它对于解密使用临时密码(ephemeral ciphers)发送的流量很有用。这需要 OpenSSL >= 1.1.0,或 BoringSSL。
如果传入的 SSL/TLS 传输层连接中存在客户端证书,则返回 true。在 'verify' 语句设置为 'optional' 时很有用。注意:在使用会话 ID 或 TLS 票据进行 SSL 会话恢复时,当前连接中不存在客户端证书,但可以从缓存或票据中检索。因此,如果您想检查当前 SSL 会话是否使用了客户端证书,请优先使用 "ssl_c_used"。
如果发送了早期数据,并且握手尚未发生,则返回 true。由于它具有安全隐患,因此能够拒绝这些数据或等到握手发生后再处理它们非常有用。
这会检查入站连接是否通过 SSL/TLS 传输层建立,以及是否包含服务器名称指示(Server Name Indication, SNI)TLS 扩展。当入站连接提供 TLS SNI 字段时,返回 true。这需要 SSL 库已构建为支持 TLS 扩展(请检查 haproxy -vv)。
如果通过 SSL/TLS 传输层传入的连接上,SSL/TLS 会话已通过使用 SSL 会话缓存或 TLS 票据得到恢复,则返回 true。
此转换器从通过 TLS 传输层建立并由 haproxy 本地解密的传入连接中提取下一个协议协商字段。结果是包含客户端播发的协议名称的字符串。SSL 库必须在构建时启用 TLS 扩展支持(检查 haproxy -vv)。请注意,除非 "bind" 行上的 "npn" 关键字指定了协议列表,否则不会播发 TLS NPN 扩展。此外,没有任何东西强制客户端从该列表中选择协议,可以请求任何其他协议。请注意,TLS NPN 扩展已被 ALPN 取代。
当传入连接通过 SSL/TLS 传输层建立时,返回所使用的协议的名称。
当传入连接通过 SSL/TLS 传输层建立时,返回 RFC5929 第 3 节中定义的 TLS 唯一 ID。该唯一 ID 可以使用转换器 "ssl_bc_unique_id,base64" 编码为 base64。
在连接通过 SSL/TLS 传输层建立时,返回前端连接的服务器随机数。这对于解密使用临时密码发送的流量非常有用。这需要 OpenSSL >= 1.1.0 或 BoringSSL。
当传入连接通过 SSL/TLS 传输层建立时,返回前端连接的 SSL ID。这对于将给定客户端粘滞到某个服务器很有用。需要注意的是,某些浏览器每隔几分钟就会刷新其会话 ID。
在连接通过 SSL/TLS 传输层建立时,返回前端连接的 SSL 会话主密钥。这对于解密使用临时密码发送的流量非常有用。这需要 OpenSSL >= 1.1.0 或 BoringSSL。
此转换器从通过 SSL/TLS 传输层建立并由 haproxy 本地解密的传入连接中提取服务器名称指示 TLS 扩展 (SNI) 字段。结果(如果存在)通常是匹配 HTTPS 主机名的字符串(253 个字符或更少)。SSL 库必须在构建时启用 TLS 扩展支持(检查 haproxy -vv)。此获取与上面的 "req_ssl_sni" 不同,因为它适用于正在由 haproxy 解密的连接,而不是盲目转发的 SSL 内容。另请参阅下面的 "ssl_fc_sni_end" 和 "ssl_fc_sni_reg"。这要求 SSL 库在构建时启用 TLS 扩展支持(检查 haproxy -vv)。ACL 派生:ssl_fc_sni_end:后缀匹配;ssl_fc_sni_reg:正则表达式匹配。
当传入连接通过 SSL/TLS 传输层建立时,返回实际使用的对称加密密钥大小(以位为单位)。
从缓冲区内容获取样本与上述的样本获取方法有些不同,因为采样的数据是短暂的。这些数据只有在可用时才能使用,并且在转发后会丢失。因此,例如,在请求期间从缓冲区内容获取的样本不能在响应中使用。即使在获取数据时,它们也可能发生变化。有时需要设置一些延迟或组合多种样本获取方法,以确保预期的数据是完整和可用的,例如通过 TCP 请求内容检查。有关该主题的更多详细信息,请参阅 "tcp-request content" 关键字。
这是 "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 请求内容检查一起使用。
此函数从请求缓冲区中提取一个从字节 <offset> 开始,长度为 <length> 字节的二进制块。作为特殊情况,如果 <length> 参数为零,则提取从 <offset> 到缓冲区末尾的整个部分。这可以与 ACL 一起使用,以检查缓冲区中任何位置是否存在某些内容。ACL 替代方案:payload(<offset>,<length>):十六进制二进制匹配
此函数提取一个二进制块,其大小在 <offset1> 处指定,长度为 <length> 字节,如果指定了 <offset2>,则从 <offset2> 开始,否则紧跟在长度之后开始。<offset2> 参数也支持相对偏移量,如果前缀为 '+' 或 '-' 符号。ACL 替代方案: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 协议时,提取名为 <name> 的 RDP cookie;如果未指定名称,则提取任何 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 消息中发送的应用层协议协商 (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 节中定义的“支持的椭圆曲线扩展”。这可用于向兼容 ECC 的客户端提供 EC 证书,并向所有其他客户端提供 RSA 证书,在同一 IP 地址上。请注意,这仅适用于请求缓冲区中找到的原始内容,不适用于通过 SSL 数据层解密的内容,因此这不适用于带有 "ssl" 选项的 "bind" 行。
如果缓冲区包含解析为完整 SSL(v3 或更高版本)客户端 hello 消息的数据,则返回包含在请求缓冲区中找到的 SSL hello 消息类型的整数值。请注意,这仅适用于请求缓冲区中找到的原始内容,不适用于通过 SSL 数据层解密的内容,因此这不适用于带有 "ssl" 选项的 "bind" 行。这主要用于 ACL 中检测是否存在包含可用于粘滞的 SSL 会话 ID 的 SSL hello 消息。
如果缓冲区包含解析为完整 SSL(v3 或更高版本)客户端 hello 消息的数据,则返回包含客户端在通过请求缓冲区传递的 TLS 流中发送的服务器名称 TLS 扩展值的字符串。请注意,这仅适用于请求缓冲区中找到的原始内容,不适用于通过 SSL 数据层解密的内容,因此这不适用于带有 "ssl" 选项的 "bind" 行。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 扩展 (RFC5077),则返回 0;如果客户端发送了 SessionTicket TLS 扩展,则返回 1;如果客户端也发送了非零长度的 TLS SessionTicket,则返回 2。请注意,这仅适用于请求缓冲区中找到的原始内容,不适用于通过 SSL 数据层解密的内容,因此这不适用于带有 "ssl" 选项的 "bind" 行。例如,这可用于检测客户端是否发送了 SessionTicket 并相应地进行粘滞,如果没有 SessionTicket,则根据 SessionID 进行粘滞,或者在使用 SessionTickets 时不进行粘滞,因为没有服务器端状态。
返回包含请求缓冲区中存在的流的 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 响应内容检查一起使用。
此函数从响应缓冲区中提取一个从字节 <offset> 开始,长度为 <length> 字节的二进制块。作为特殊情况,如果 <length> 参数为零,则提取从 <offset> 到缓冲区末尾的整个部分。这可以与 ACL 一起使用,以检查缓冲区中任何位置是否存在某些内容。
此函数提取一个二进制块,其大小在 <offset1> 处指定,长度为 <length> 字节,如果指定了 <offset2>,则从 <offset2> 开始,否则紧跟在长度之后开始。<offset2> 参数也支持相对偏移量,如果前缀为 '+' 或 '-' 符号。
请参考 "stick store-response" 关键字中的示例。
如果缓冲区包含解析为完整 SSL(v3 或更高版本)hello 消息的数据,则返回包含响应缓冲区中找到的 SSL hello 消息类型的整数值。请注意,这仅适用于响应缓冲区中找到的原始内容,不适用于通过 SSL 数据层解密的内容,因此这不适用于带有 "ssl" 选项的 "server" 行。这主要用于 ACL 中检测是否存在包含可用于粘滞的 SSL 会话 ID 的 SSL hello 消息。
此获取在检查周期结束时返回 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
可以从 HTTP 内容、请求和响应中获取样本。这个应用层也称为第 7 层。只有当完整的 HTTP 请求或响应已从其各自的请求或响应缓冲区中解析出来时,才可能获取本节中的数据。对于所有 HTTP 特定规则和以 "mode http" 运行的部分,情况总是如此。使用 TCP 内容检查时,可能需要支持检查延迟,以便让请求或响应首先进入。这些获取可能需要比第 4 层获取更多的 CPU 资源,但由于请求和响应已被索引,所以不会多太多。
此函数返回第一个 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 的计数器。
此函数提取由 "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-encoded 的。用户可以检查 "content-type" 是否包含值 "application/x-www-form-urlencoded"。此函数提取正文中参数 <name> 的第一次出现,该参数在 '&' 之前结束。参数名称区分大小写。如果未给出名称,则任何参数都会匹配,并返回第一个。结果是一个字符串,对应于请求正文中呈现的参数 <name> 的值(不执行 URL 解码)。请注意,此获取的 ACL 版本会遍历多个参数,如果未给出名称,则会迭代报告所有参数值。
此函数返回 HTTP 请求的可用正文长度(以字节为单位)。如果正文大于缓冲区,则该值可能低于通告的长度。它要求请求正文已使用 "option http-buffer-request" 进行了缓冲并可用。
此函数返回 HTTP 请求正文的通告长度(以字节为单位)。它将表示通告的 Content-Length 头部,或者在分块编码的情况下,表示第一个分块的大小。为了解析分块,它要求请求正文已使用 "option http-buffer-request" 进行了缓冲并可用。
此函数从请求的 "Cookie" 头部行中提取名为 <name> 的 cookie 的最后一次出现,并将其值作为字符串返回。如果未指定名称,则返回第一个 cookie 的值。与 ACL 一起使用时,将评估所有匹配的 cookie。根据 Cookie 头部规范 (RFC6265) 的要求,名称和值周围的空格将被忽略。cookie 名称区分大小写。空 cookie 是有效的,因此如果存在空 cookie,很可能会返回一个空值。使用 "found" 匹配来检测是否存在。对于服务器发送的响应 cookie,请使用 res.cook() 变体。ACL 派生词:cook([<name>]):精确字符串匹配 cook_beg([<name>]):前缀匹配 cook_dir([<name>]):子目录匹配 cook_dom([<name>]):域名匹配 cook_end([<name>]):后缀匹配 cook_len([<name>]):长度匹配 cook_reg([<name>]):正则表达式匹配 cook_sub([<name>]):子串匹配
返回一个整数值,表示名为 <name> 的 cookie 在请求中出现的次数;如果未指定 <name>,则表示所有 cookie 的数量。
此函数从请求的 "Cookie" 头部行中提取名为 <name> 的 cookie 的最后一次出现,并将其值转换为整数返回。如果未指定名称,则返回第一个 cookie 的值。在 ACL 中使用时,将遍历所有匹配的名称,直到找到一个匹配的值。
从请求的“Cookie”标头行中提取 cookie 名称 <name> 的最后一次出现,或从响应的“Set-Cookie”标头中提取,并返回其值作为字符串。典型的用途是让共享相同配置文件的多个客户端使用相同的服务器。这可以与“appsession”通过“request-learn”语句所做的类似,但支持多对同步和跨重启的状态保持。如果未指定名称,则返回第一个 cookie 值。此获取不应再使用,应替换为 req.cook() 或 res.cook(),因为它根据使用它的上下文含糊地使用方向。
在请求上使用时,此函数等同于 req.hdr();在响应上使用时,等同于 res.hdr()。有关更多详细信息,请参考这些各自的获取。如果不确定获取方向,请使用明确的函数。请注意,与 hdr() 样本获取方法相反,hdr_* ACL 关键字明确地应用于请求头部。
此函数提取 HTTP 请求中名为 <name> 的头部的最后一次出现。从 ACL 使用时,将遍历所有出现,直到找到匹配项。可选地,可以指定一个特定的出现次数作为位置编号。正值表示从第一次出现开始的位置,1 是第一个。负值表示相对于最后一次出现的位置,-1 是最后一个。它与 req.hdr() 的不同之处在于,值中存在的任何逗号都会被返回,并且不会用作分隔符。这对于像 User-Agent 这样的头部有时很有用。
返回一个整数值,表示请求头字段名 <name> 的出现次数;如果未指定 <name>,则返回头字段的总数。与其 req.hdr_cnt() 类似函数不同,此函数返回完整行头部的数量,并且不会在逗号处停止。
This extracts the last occurrence of header <name> in an HTTP request. When used from an ACL, all occurrences are iterated over until a match is found. Optionally, a specific occurrence might be specified as a position number. Positive values indicate a position from the first occurrence, with 1 being the first one. Negative values indicate positions relative to the last one, with -1 being the last one. A typical use is with the X-Forwarded-For header once converted to IP, associated with an IP stick-table. The function considers any comma as a delimiter for distinct values. If full-line headers are desired instead, use req.fhdr(). Please carefully check RFC7231 to know how certain headers are supposed to be parsed. Also, some of them are case insensitive (e.g. Connection). ACL derivatives : hdr([<name>[,<occ>]]) : exact string match hdr_beg([<name>[,<occ>]]) : prefix match hdr_dir([<name>[,<occ>]]) : subdir match hdr_dom([<name>[,<occ>]]) : domain match hdr_end([<name>[,<occ>]]) : suffix match hdr_len([<name>[,<occ>]]) : length match hdr_reg([<name>[,<occ>]]) : regex match hdr_sub([<name>[,<occ>]]) : substring match
返回一个整数值,表示请求头字段名 <name> 的出现次数;如果未指定 <name>,则表示头字段值的总数。重要的是要记住,一个头部行如果包含多个值,可能会被计为多个头部。该函数将任何逗号视为不同值的分隔符。如果需要完整的行头部,应改用 req.fhdr_cnt()。通过 ACL,它可用于检测特定头部的存在、缺失或滥用,以及通过拒绝包含多个某些头部的请求来阻止请求走私攻击。有关头部匹配的更多信息,请参阅 "req.hdr"。
这会提取 HTTP 请求中标题的最后一次出现,将其转换为 IPv4 或 IPv6 地址并返回该地址。当与 ACL 一起使用时,会检查所有出现,如果省略了 ,则检查每个标头的所有值。解析器严格遵循 RFC7239 中描述的格式,并扩展了 IPv4 地址可以可选地后跟冒号 (':') 和有效十进制端口号(0 到 65535),这些端口号将被静默删除。所有其他格式均不匹配,并将导致地址被忽略。还可以选择指定一个特定的出现作为位置号。正值表示从第一次出现开始的位置,1 是第一次出现。负值表示相对于最后一次出现的位置,-1 是最后一次出现。典型的用法是与 X-Forwarded-For 和 X-Client-IP 标头一起使用。
此函数提取 HTTP 请求中名为 <name> 的头部的最后一次出现,并将其转换为整数值。与 ACL 一起使用时,会检查所有出现;如果省略 <name>,则会检查每个头部的每个值。可选地,可以指定一个特定的出现次数作为位置编号。正值表示从第一次出现开始的位置,1 是第一个。负值表示相对于最后一次出现的位置,-1 是最后一个。一个典型的用途是与 X-Forwarded-For 头部一起使用。
以字符串形式返回当前请求标头,包括分隔标头和请求正文的最后空行。最后空行可用于检测截断的标头块。此样本获取对于某些 SPOE 标头分析器和高级日志记录非常有用。
以预解析的二进制形式返回当前请求标头。这对于使用 SPOE 进行部分处理非常有用。每个字符串由长度后面跟着长度指示的字节数描述。长度使用 SPOE 文档中详细的可变整数编码表示。列表的末尾由一对空标头名称和值(长度均为 0)标记。*(<str:header-name><str:header-value>)<empty string><empty string> int:参考 SPOE 文档的编码 str:<int:length><bytes>
返回一个布尔值,指示从客户端收到的身份验证数据是否与指定用户列表中存储的用户名和密码匹配。此获取函数在 ACL 之外并不真正有用。目前仅支持 http 基本身份验证。
如果从客户端收到的身份验证数据中的用户名和密码根据指定用户列表均有效,则返回一个对应于该用户名的字符串。其主要目的是在 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”获取方法。ACL 派生词:path:精确字符串匹配 path_beg:前缀匹配 path_dir:子目录匹配 path_dom:域匹配 path_end:后缀匹配 path_len:长度匹配 path_reg:正则表达式匹配 path_sub:子字符串匹配
此函数提取请求的查询字符串,它从第一个问号之后开始。如果没有问号,此获取不返回任何内容。如果存在问号但后面没有任何内容,则返回一个空字符串。这意味着可以使用 "found" 匹配方法轻松地知道是否存在查询字符串。此获取是 "path" 的补充,后者在问号之前停止。
此函数构建一个字符串,该字符串由规则评估时请求中出现的所有头部名称拼接而成。默认分隔符是逗号 (','),但可以通过可选参数 <delim> 进行覆盖。在这种情况下,只考虑 <delim> 的第一个字符。从 HTTP 请求中返回版本字符串,例如 "1.1"。这对于日志很有用,但主要用于 ACL。一些预定义的 ACL 已经检查了版本 1.0 和 1.1。ACL 派生词:req_ver:精确字符串匹配
如果响应已被 HAProxy 压缩,则返回布尔值 "true",否则返回布尔值 "false"。这可用于在日志中添加信息。
如果响应被 HAProxy 压缩,则返回一个包含所用算法名称的字符串,例如:“deflate”。这可用于在日志中添加一些信息。
此函数从响应的 "Set-Cookie" 标头行中提取 cookie 名称 <name> 的最后一次出现,并将其值作为字符串返回。如果未指定名称,则返回第一个 cookie 的值。ACL 派生:scook([<name>] : 精确字符串匹配
返回一个整数值,表示 cookie <name> 在响应中出现的次数,如果未指定 <name>,则表示所有 cookie 的数量。这在与 ACL 结合使用以检测可疑响应时非常有用。
此函数从响应的 "Set-Cookie" 标头行中提取 cookie 名称 <name> 的最后一次出现,并将其值转换为整数后返回。如果未指定名称,则返回第一个 cookie 的值。
此函数提取 HTTP 响应中标头 <name> 的最后一次出现,如果未指定 <name>,则提取最后一个标头。可以选择性地将特定出现指定为位置编号。正值表示从第一次出现开始的位置,1 代表第一次。负值表示相对于最后一次出现的位置,-1 代表最后一次。它与 res.hdr() 的不同之处在于,值中存在的任何逗号都会被返回,而不会被用作分隔符。如果不需要此行为,应改用 res.hdr() 提取。这对于像 Date 或 Expires 这样的标头有时很有用。
返回一个整数值,表示响应标头字段名 <name> 的出现次数,如果未指定 <name>,则返回标头字段的总数。与其对应的 res.hdr_cnt() 函数不同,此函数返回完整行标头的数量,并且不会在逗号处停止。如果不需要此行为,应改用 res.hdr_cnt() 提取。
This extracts the last occurrence of header <name> in an HTTP response, or of the last header if no <name> is specified. Optionally, a specific occurrence might be specified as a position number. Positive values indicate a position from the first occurrence, with 1 being the first one. Negative values indicate positions relative to the last one, with -1 being the last one. This can be useful to learn some data into a stick-table. The function considers any comma as a delimiter for distinct values. If this is not desired, the res.fhdr() fetch should be used instead. ACL derivatives : shdr([<name>[,<occ>]]) : exact string match shdr_beg([<name>[,<occ>]]) : prefix match shdr_dir([<name>[,<occ>]]) : subdir match shdr_dom([<name>[,<occ>]]) : domain match shdr_end([<name>[,<occ>]]) : suffix match shdr_len([<name>[,<occ>]]) : length match shdr_reg([<name>[,<occ>]]) : regex match shdr_sub([<name>[,<occ>]]) : substring match
返回一个整数值,表示响应标头字段名 <name> 的出现次数,如果未指定 <name>,则返回标头字段的总数。该函数将任何逗号都视作不同值的分隔符。如果不需要此行为,应改用 res.fhdr_cnt() 提取。
此函数提取 HTTP 响应中标头 <name> 的最后一次出现,将其转换为 IPv4 或 IPv6 地址并返回该地址。可以选择性地将特定出现指定为位置编号。正值表示从第一次出现开始的位置,1 代表第一次。负值表示相对于最后一次出现的位置,-1 代表最后一次。这对于将一些数据学习到粘性表中很有用。
此函数构建一个字符串,该字符串由规则评估时响应中出现的所有标头名称连接而成。默认分隔符是逗号 (','),但可以通过可选参数 <delim> 进行覆盖。在这种情况下,只考虑 <delim> 的第一个字符。此函数提取 HTTP 响应中标头 <name> 的最后一次出现,并将其转换为一个整数值。可以选择性地将特定出现指定为位置编号。正值表示从第一次出现开始的位置,1 代表第一次。负值表示相对于最后一次出现的位置,-1 代表最后一次。这对于将一些数据学习到粘性表中很有用。
从 HTTP 响应中返回版本字符串,例如 "1.1"。这对于日志很有用,但主要用于 ACL。ACL 派生:resp_ver : 精确字符串匹配
从响应的“Set-Cookie”标头行中提取 cookie 名称 <name> 的最后一次出现,并使用相应的值进行匹配。这可以与“appsession”的默认选项所做的相媲美,但支持多对同步和跨重启的状态保持。此获取函数已弃用,已被“res.cook”获取器取代。此关键字很快就会消失。
返回一个包含 HTTP 响应中 HTTP 状态码的整数,例如 302。它主要用于 ACL 和整数范围内,例如,如果响应不是 3xx,则移除任何 Location 标头。
返回附加到请求的唯一 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"。ACL 派生:url : 精确字符串匹配 url_beg : 前缀匹配 url_dir : 子目录匹配 url_dom : 域名匹配 url_end : 后缀匹配 url_len : 长度匹配 url_reg : 正则表达式匹配 url_sub : 子字符串匹配
当主机部分以 IP 地址形式呈现时,此函数从请求的 URL 中提取 IP 地址。其用途非常有限。例如,监控系统可能会使用此字段作为源 IP 的替代方案,以测试给定源地址将遵循的路径,或为给定源地址在表中强制创建一个条目。对于 ACL,它可以用于限制通过代理访问某些系统,例如与选项 "http_proxy" 结合使用时。
此函数从请求的 URL 中提取端口部分。请注意,如果请求中未指定端口,则假定为端口 80。对于 ACL,它可以用于限制通过代理访问某些系统,例如与选项 "http_proxy" 结合使用时。
This extracts the first occurrence of the parameter <name> in the query string, which begins after either '?' or <delim>, and which ends before '&', ';' or <delim>. The parameter name is case-sensitive. If no name is given, any parameter will match, and the first one will be returned. The result is a string corresponding to the value of the parameter <name> as presented in the request (no URL decoding is performed). This can be used for session stickiness based on a client ID, to extract an application cookie passed as a URL parameter, or in ACLs to apply some checks. Note that the ACL version of this fetch iterates over multiple parameters and will iteratively report all parameters values if no name is given ACL derivatives : urlp(<name>[,<delim>]) : exact string match urlp_beg(<name>[,<delim>]) : prefix match urlp_dir(<name>[,<delim>]) : subdir match urlp_dom(<name>[,<delim>]) : domain match urlp_end(<name>[,<delim>]) : suffix match urlp_len(<name>[,<delim>]) : length match urlp_reg(<name>[,<delim>]) : regex match urlp_sub(<name>[,<delim>]) : substring match
# 匹配 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 的计数器。
一些预定义的 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_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 | 匹配来自本地主机的连接 |
| 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 | 等待内容分析结束 |
One of HAProxy's strong points certainly lies is its precise logs. It probably provides the finest level of information available for such a product, which is very important for troubleshooting complex environments. Standard information provided in logs include client ports, TCP/HTTP state timers, precise session state at termination and precise termination cause, information about decisions to direct traffic to a server, and of course the ability to capture arbitrary headers. In order to improve administrators reactivity, it offers a great transparency about encountered problems, both internal and external, and it is possible to send logs to different sources at the same time with different level filters : - global process-level logs (system errors, start/stop, etc..) - per-instance system and internal errors (lack of resource, bugs, ...) - per-instance external troubles (servers up/down, max connections) - per-instance activity (client connections), either at the establishment or at the termination. - per-request control of log-level, e.g. http-request set-log-level silent if sensitive_request The ability to distribute different levels of logs to different log servers allow several production teams to interact and to fix their problems as soon as possible. For example, the system team might monitor system-wide errors, while the application team might be monitoring the up/down for their servers in real time, and the security team might analyze the activity logs with one hour delay.
TCP and HTTP connections can be logged with information such as the date, time, source IP address, destination address, connection duration, response times, HTTP request, HTTP return code, number of bytes transmitted, conditions in which the session ended, and even exchanged cookies values. For example track a particular user's problems. All messages may be sent to up to two syslog servers. Check the "log" keyword in section 4.2 for more information about log facilities.
HAProxy supports 5 log formats. Several fields are common between these formats and will be detailed in the following sections. A few of them may vary slightly with the configuration, due to indicators specific to certain options. The supported formats are as follows : - the default format, which is very basic and very rarely used. It only provides very basic information about the incoming connection at the moment it is accepted : source IP:port, destination IP:port, and frontend-name. This mode will eventually disappear so it will not be described to great extents. - the TCP format, which is more advanced. This format is enabled when "option tcplog" is set on the frontend. HAProxy will then usually wait for the connection to terminate before logging. This format provides much richer information, such as timers, connection counts, queue size, etc... This format is recommended for pure TCP proxies. - the HTTP format, which is the most advanced for HTTP proxying. This format is enabled when "option httplog" is set on the frontend. It provides the same information as the TCP format with some HTTP-specific fields such as the request, the status code, and captures of headers and cookies. This format is recommended for HTTP proxies. - the CLF HTTP format, which is equivalent to the HTTP format, but with the fields arranged in the same order as the CLF format. In this mode, all timers, captures, flags, etc... appear one per field after the end of the common fields, in the same order they appear in the standard HTTP format. - the custom log format, allows you to make your own log line. Next sections will go deeper into details for each of these formats. Format specification will be performed on a "field" basis. Unless stated otherwise, a field is a portion of text delimited by any number of spaces. Since syslog servers are susceptible of inserting fields at the beginning of a line, it is always assumed that the first field is the one containing the process name and identifier. Note : Since log lines may be quite long, the log examples in sections below might be broken into multiple lines. The example log lines will be prefixed with 3 closing angle brackets ('>>>') and each time a log is broken into multiple lines, each non-final line will end with a backslash ('\') and the next line will start indented by two characters.
当没有设置特定选项时,使用此格式。日志在连接被接受后立即发出。需要注意的是,这目前是唯一记录请求目标 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)
Field Format Extract from the example above 1 process_name '[' pid ']:' haproxy[14385]: 2 'Connect from' Connect from 3 source_ip ':' source_port 10.0.1.2:33312 4 'to' to 5 destination_ip ':' destination_port 10.0.3.31:8012 6 '(' frontend_name '/' mode ')' (www/HTTP) Detailed fields description : - "source_ip" is the IP address of the client which initiated the connection. - "source_port" is the TCP port of the client which initiated the connection. - "destination_ip" is the IP address the client connected to. - "destination_port" is the TCP port the client connected to. - "frontend_name" is the name of the frontend (or listener) which received and processed the connection. - "mode is the mode the frontend is operating (TCP or HTTP). In case of a UNIX socket, the source and destination addresses are marked as "unix:" and the ports reflect the internal ID of the socket which accepted the connection (the same ID as reported in the stats). It is advised not to use this deprecated format for newer installations as it will eventually disappear.The TCP format is used when "option tcplog" is specified in the frontend, and is the recommended format for pure TCP proxies. It provides a lot of precious information for troubleshooting. Since this format includes timers and byte counts, the log is normally emitted at the end of the session. It can be emitted earlier if "option logasap" is specified, which makes sense in most environments with long sessions such as remote terminals. Sessions which match the "monitor" rules are never logged. It is also possible not to emit logs for sessions for which no data were exchanged between the client and the server, by specifying "option dontlognull" in the frontend. Successful connections will not be logged if "option dontlog-normal" is specified in the frontend. A few fields may slightly vary depending on some configuration options, those are marked with a star ('*') after the field name below.
frontend fnt mode tcp option tcplog log global default_backend bck backend bck server srv1 127.0.0.1:8000 >>> Feb 6 12:12:56 localhost \ haproxy[14387]: 10.0.1.2:33313 [06/Feb/2009:12:12:51.443] fnt \ bck/srv1 0/0/5007 212 -- 0/0/0/0/3 0/0
Field Format Extract from the example above 1 process_name '[' pid ']:' haproxy[14387]: 2 client_ip ':' client_port 10.0.1.2:33313 3 '[' accept_date ']' [06/Feb/2009:12:12:51.443] 4 frontend_name fnt 5 backend_name '/' server_name bck/srv1 6 Tw '/' Tc '/' Tt* 0/0/5007 7 bytes_read* 212 8 termination_state -- 9 actconn '/' feconn '/' beconn '/' srv_conn '/' retries* 0/0/0/0/3 10 srv_queue '/' backend_queue 0/0 Detailed fields description : - "client_ip" is the IP address of the client which initiated the TCP connection to haproxy. If the connection was accepted on a UNIX socket instead, the IP address would be replaced with the word "unix". Note that when the connection is accepted on a socket configured with "accept-proxy" and the PROXY protocol is correctly used, or with a "accept-netscaler-cip" and the NetScaler Client IP insertion protocol is correctly used, then the logs will reflect the forwarded connection's information. - "client_port" is the TCP port of the client which initiated the connection. If the connection was accepted on a UNIX socket instead, the port would be replaced with the ID of the accepting socket, which is also reported in the stats interface. - "accept_date" is the exact date when the connection was received by haproxy (which might be very slightly different from the date observed on the network if there was some queuing in the system's backlog). This is usually the same date which may appear in any upstream firewall's log. When used in HTTP mode, the accept_date field will be reset to the first moment the connection is ready to receive a new request (end of previous response for HTTP/1, immediately after previous request for HTTP/2). - "frontend_name" is the name of the frontend (or listener) which received and processed the connection. - "backend_name" is the name of the backend (or listener) which was selected to manage the connection to the server. This will be the same as the frontend if no switching rule has been applied, which is common for TCP applications. - "server_name" is the name of the last server to which the connection was sent, which might differ from the first one if there were connection errors and a redispatch occurred. Note that this server belongs to the backend which processed the request. If the connection was aborted before reaching a server, "<NOSRV>" is indicated instead of a server name. - "Tw" is the total time in milliseconds spent waiting in the various queues. It can be "-1" if the connection was aborted before reaching the queue. See "Timers" below for more details. - "Tc" is the total time in milliseconds spent waiting for the connection to establish to the final server, including retries. It can be "-1" if the connection was aborted before a connection could be established. See "Timers" below for more details. - "Tt" is the total time in milliseconds elapsed between the accept and the last close. It covers all possible processing. There is one exception, if "option logasap" was specified, then the time counting stops at the moment the log is emitted. In this case, a '+' sign is prepended before the value, indicating that the final one will be larger. See "Timers" below for more details. - "bytes_read" is the total number of bytes transmitted from the server to the client when the log is emitted. If "option logasap" is specified, the this value will be prefixed with a '+' sign indicating that the final one may be larger. Please note that this value is a 64-bit counter, so log analysis tools must be able to handle it without overflowing. - "termination_state" is the condition the session was in when the session ended. This indicates the session state, which side caused the end of session to happen, and for what reason (timeout, error, ...). The normal flags should be "--", indicating the session was closed by either end with no data remaining in buffers. See below "Session state at disconnection" for more details. - "actconn" is the total number of concurrent connections on the process when the session was logged. It is useful to detect when some per-process system limits have been reached. For instance, if actconn is close to 512 when multiple connection errors occur, chances are high that the system limits the process to use a maximum of 1024 file descriptors and that all of them are used. See section 3 "Global parameters" to find how to tune the system. - "feconn" is the total number of concurrent connections on the frontend when the session was logged. It is useful to estimate the amount of resource required to sustain high loads, and to detect when the frontend's "maxconn" has been reached. Most often when this value increases by huge jumps, it is because there is congestion on the backend servers, but sometimes it can be caused by a denial of service attack. - "beconn" is the total number of concurrent connections handled by the backend when the session was logged. It includes the total number of concurrent connections active on servers as well as the number of connections pending in queues. It is useful to estimate the amount of additional servers needed to support high loads for a given application. Most often when this value increases by huge jumps, it is because there is congestion on the backend servers, but sometimes it can be caused by a denial of service attack. - "srv_conn" is the total number of concurrent connections still active on the server when the session was logged. It can never exceed the server's configured "maxconn" parameter. If this value is very often close or equal to the server's "maxconn", it means that traffic regulation is involved a lot, meaning that either the server's maxconn value is too low, or that there aren't enough servers to process the load with an optimal response time. When only one of the server's "srv_conn" is high, it usually means that this server has some trouble causing the connections to take longer to be processed than on other servers. - "retries" is the number of connection retries experienced by this session when trying to connect to the server. It must normally be zero, unless a server is being stopped at the same moment the connection was attempted. Frequent retries generally indicate either a network problem between haproxy and the server, or a misconfigured system backlog on the server preventing new connections from being queued. This field may optionally be prefixed with a '+' sign, indicating that the session has experienced a redispatch after the maximal retry count has been reached on the initial server. In this case, the server name appearing in the log is the one the connection was redispatched to, and not the first one, though both may sometimes be the same in case of hashing for instance. So as a general rule of thumb, when a '+' is present in front of the retry count, this count should not be attributed to the logged server. - "srv_queue" is the total number of requests which were processed before this one in the server queue. It is zero when the request has not gone through the server queue. It makes it possible to estimate the approximate server's response time by dividing the time spent in queue by the number of requests in the queue. It is worth noting that if a session experiences a redispatch and passes through two server queues, their positions will be cumulative. A request should not pass through both the server queue and the backend queue unless a redispatch occurs. - "backend_queue" is the total number of requests which were processed before this one in the backend's global queue. It is zero when the request has not gone through the global queue. It makes it possible to estimate the average queue length, which easily translates into a number of missing servers when divided by a server's "maxconn" parameter. It is worth noting that if a session experiences a redispatch, it may pass twice in the backend's queue, and then both positions will be cumulative. A request should not pass through both the server queue and the backend queue unless a redispatch occurs.
The HTTP format is the most complete and the best suited for HTTP proxies. It is enabled by when "option httplog" is specified in the frontend. It provides the same level of information as the TCP format with additional features which are specific to the HTTP protocol. Just like the TCP format, the log is usually emitted at the end of the session, unless "option logasap" is specified, which generally only makes sense for download sites. A session which matches the "monitor" rules will never logged. It is also possible not to log sessions for which no data were sent by the client by specifying "option dontlognull" in the frontend. Successful connections will not be logged if "option dontlog-normal" is specified in the frontend. Most fields are shared with the TCP log, some being different. A few fields may slightly vary depending on some configuration options. Those ones are marked with a star ('*') after the field name below.
frontend http-in mode http option httplog log global default_backend bck backend static server srv1 127.0.0.1:8000 >>> Feb 6 12:14:14 localhost \ haproxy[14389]: 10.0.1.2:33317 [06/Feb/2009:12:14:14.655] http-in \ static/srv1 10/0/30/69/109 200 2750 - - ---- 1/1/1/1/0 0/0 {1wt.eu} \ {} "GET /index.html HTTP/1.1"
字段格式提取自上述示例 1 process_name '[' pid ']:' haproxy[14389]: 2 client_ip ':' client_port 10.0.1.2:33317 3 '[' request_date ']' [06/Feb/2009:12:14:14.655] 4 frontend_name http-in 5 backend_name '/' server_name static/srv1 6 TR '/' Tw '/' Tc '/' Tr '/' Ta* 10/0/30/69/109 7 status_code 200 8 bytes_read* 2750 9 captured_request_cookie - 10 captured_response_cookie - 11 termination_state ---- 12 actconn '/' feconn '/' beconn '/' srv_conn '/' retries* 1/1/1/1/0 13 srv_queue '/' backend_queue 0/0 14 '{' captured_request_headers* '}' {haproxy.1wt.eu} 15 '{' captured_response_headers* '}' {} 16 '"' http_request '"' "GET /index.html HTTP/1.1" 详细字段说明: - "client_ip" 是发起 TCP 连接到 haproxy 的客户端 IP 地址。如果连接是通过 UNIX 套接字接受的,则 IP 地址将替换为单词 "unix"。请注意,当连接是通过配置了 "accept-proxy" 且正确使用了 PROXY 协议的套接字接受时,或者通过配置了 "accept-netscaler-cip" 且正确使用了 NetScaler 客户端 IP 插入协议的套接字接受时,日志将反映转发连接的信息。 - "client_port" 是发起连接的客户端 TCP 端口。如果连接是通过 UNIX 套接字接受的,则端口将替换为接受套接字的 ID,该 ID 也报告在 stats 接口中。 - "request_date" 是 haproxy 收到 HTTP 请求第一个字节时的确切日期(日志字段 %tr)。 - "frontend_name" 是接收和处理连接的前端(或侦听器)的名称。 - "backend_name" 是被选中用于管理与服务器连接的后端(或侦听器)的名称。如果没有应用切换规则,这将与前端相同。 - "server_name" 是连接被发送到的最后一个服务器的名称,如果发生连接错误并进行了重新调度,则可能与第一个服务器不同。请注意,此服务器属于处理请求的后端。如果请求在到达服务器之前被中止,则显示 "<NOSRV>" 而不是服务器名称。如果请求被统计子系统拦截,则显示 "<STATS>" 而不是服务器名称。 - "TR" 是从收到第一个字节后等待客户端发送完整 HTTP 请求(不包括正文)所花费的总时间(以毫秒为单位)。如果连接在收到完整请求之前被中止或收到了错误的请求,则可能为 "-1"。它应该总是很小,因为请求通常在一个数据包中。此处时间过长通常表示客户端与 haproxy 之间的网络问题或请求是手动输入的。有关详细信息,请参阅 第 8.4 节 "计时事件"。 - "Tw" 是在各种队列中等待所花费的总时间(以毫秒为单位)。如果连接在到达队列之前被中止,则可能为 "-1"。有关详细信息,请参阅 第 8.4 节 "计时事件"。 - "Tc" 是等待与最终服务器建立连接所花费的总时间(以毫秒为单位),包括重试。如果请求在建立连接之前被中止,则可能为 "-1"。有关详细信息,请参阅第 8.4 节 "计时事件"。 - "Tr" 是等待服务器发送完整 HTTP 响应(不包括数据)所花费的总时间(以毫秒为单位)。如果请求在收到完整响应之前被中止,则可能为 "-1"。它通常与服务器处理请求的时间匹配,尽管它可能会受到客户端发送给服务器的数据量的影响。此处 "GET" 请求时间过长通常表示服务器过载。有关详细信息,请参阅 第 8.4 节 "计时事件"。 - "Ta" 是请求在 haproxy 中保持活动状态的时间,即从收到请求的第一个字节到发送响应的最后一个字节之间经过的总时间(以毫秒为单位)。它涵盖了所有可能的处理过程,除了握手(见 Th)和空闲时间(见 Ti)。有一个例外,如果指定了 "option logasap",则计时在发出日志时停止。在这种情况下,值前面会加上 '+' 号,表示最终值会更大。有关详细信息,请参阅 第 8.4 节 "计时事件"。 - "status_code" 是返回给客户端的 HTTP 状态码。此状态通常由服务器设置,但也可能在无法访问服务器或 haproxy 阻止其响应时由 haproxy 设置。 - "bytes_read" 是发出日志时传输到客户端的总字节数。这包括 HTTP 标头。如果指定了 "option logasap",此值将带有 '+' 前缀,表示最终值可能更大。请注意,此值是一个 64 位计数器,因此日志分析工具必须能够处理它而不会溢出。 - "captured_request_cookie" 是一个可选的 "name=value" 条目,表示客户端在请求中带有此 cookie。cookie 名称及其最大长度由前端配置中的 "capture cookie" 语句定义。如果未设置该选项,则该字段为单个短划线 ('-')。只能捕获一个 cookie,它通常用于跟踪客户端和服务器之间的会话 ID 交换,以检测由于应用程序错误导致的客户端之间的会话交叉。有关详细信息,请参阅下面的 "捕获 HTTP 标头和 cookie" 部分。 - "captured_response_cookie" 是一个可选的 "name=value" 条目,表示服务器在响应中返回了一个 cookie。cookie 名称及其最大长度由前端配置中的 "capture cookie" 语句定义。如果未设置该选项,则该字段为单个短划线 ('-')。只能捕获一个 cookie,它通常用于跟踪客户端和服务器之间的会话 ID 交换,以检测由于应用程序错误导致的客户端之间的会话交叉。有关详细信息,请参阅下面的 "捕获 HTTP 标头和 cookie" 部分。 - "termination_state" 是会话结束时会话所处的状态。这表示会话状态、哪一方导致会话结束以及原因(超时、错误等),就像在 TCP 日志中一样,以及最后两个字符中的 cookie 上的持久性操作信息。正常标志应以 "--" 开头,表示会话已由任一端关闭,缓冲区中没有剩余数据。有关详细信息,请参阅下面的 "断开连接时的会话状态"。 - "actconn" 是记录会话时进程上的并发连接总数。它有助于检测何时达到每个进程的系统限制。例如,如果发生多个连接错误时 actconn 接近 512 或 1024,则系统很可能限制进程最多使用 1024 个文件描述符,并且所有这些描述符都已被使用。有关如何调整系统的信息,请参阅 第 3 节 "全局参数"。 - "feconn" 是记录会话时前端上的并发连接总数。它有助于估算维持高负载所需的资源量,并检测何时达到前端的 "maxconn"。最常见的情况是,当此值急剧增加时,是由于后端服务器拥塞,但有时也可能是由拒绝服务攻击引起的。 - "beconn" 是记录会话时后端处理的并发连接总数。它包括服务器上活动的并发连接总数以及队列中等待连接的数量。它有助于估算支持给定应用程序高负载所需的额外服务器数量。最常见的情况是,当此值急剧增加时,是由于后端服务器拥塞,但有时也可能是由拒绝服务攻击引起的。 - "srv_conn" 是记录会话时服务器上仍处于活动状态的并发连接总数。它永远不能超过服务器配置的 "maxconn" 参数。如果此值经常接近或等于服务器的 "maxconn",这意味着涉及了很多流量调节,这意味着要么服务器的 maxconn 值太低,要么没有足够的服务器来以最佳响应时间处理负载。当只有一个服务器的 "srv_conn" 很高时,通常意味着该服务器出现了一些问题,导致处理请求的时间比其他服务器长。 - "retries" 是此会话尝试连接服务器时经历的连接重试次数。除非在尝试连接的同一时刻服务器正在停止,否则它通常必须为零。频繁重试通常表示 haproxy 和服务器之间的网络问题,或者服务器上的系统积压配置错误,阻止了新连接排队。此字段可以选择性地以 '+' 符号作为前缀,表示会话在达到初始服务器上的最大重试次数后经历了重新调度。在这种情况下,日志中出现的服务器名称是连接重新调度到的服务器,而不是第一个服务器,尽管在哈希的情况下两者有时可能相同。因此,一般而言,当重试计数前面有 '+' 时,此计数不应归因于记录的服务器。 - "srv_queue" 是在此请求之前在服务器队列中处理的请求总数。当请求未通过服务器队列时,它为零。通过将队列中花费的时间除以队列中的请求数,可以估算近似的服务器响应时间。值得注意的是,如果一个会话经历重新调度并穿过两个服务器队列,它们的头寸将是累积的。除非发生重新调度,否则请求不应同时穿过服务器队列和后端队列。 - "backend_queue" 是在此请求之前在后端的全局队列中处理的请求总数。当请求未通过全局队列时,它为零。通过将平均队列长度除以服务器的 "maxconn" 参数,可以很容易地将其转换为缺少服务器的数量。值得注意的是,如果一个会话经历重新调度,它可能会两次通过后端的队列,然后这两个位置将是累积的。除非发生重新调度,否则请求不应同时穿过服务器队列和后端队列。 - "captured_request_headers" 是由于前端存在 "capture request header" 语句而在请求中捕获的标头列表。可以捕获多个标头,它们将由竖线 ('|') 分隔。未启用捕获时,花括号不会出现,导致其余字段移位。重要的是要注意,此字段可能包含空格,并且使用它需要比不使用它时更智能的日志解析器。有关详细信息,请参阅下面的 "捕获 HTTP 标头和 cookie" 部分。 - "captured_response_headers" 是由于前端存在 "capture response header" 语句而在响应中捕获的标头列表。可以捕获多个标头,它们将由竖线 ('|') 分隔。未启用捕获时,花括号不会出现,导致其余字段移位。重要的是要注意,此字段可能包含空格,并且使用它需要比不使用它时更智能的日志解析器。有关详细信息,请参阅下面的 "捕获 HTTP 标头和 cookie" 部分。 - "http_request" 是完整的 HTTP 请求行,包括方法、请求和 HTTP 版本字符串。不可打印字符已编码(请参阅下面的 "不可打印字符" 部分)。这始终是最后一个字段,并且始终用引号分隔,并且是唯一可以包含引号的字段。如果将新字段添加到日志格式中,它们将添加到此字段之前。如果请求过大且不适合标准 syslog 缓冲区(1024 个字符),则此字段可能会被截断。这是此字段必须始终保持在最后的原因。log-format 指令允许您在 http 模式和 tcp 模式下自定义日志。它以字符串作为参数。HAProxy 了解一些日志格式变量。% 在日志格式变量前面。变量可以使用花括号 ('{}') 接受参数,多个参数在花括号内用逗号分隔。可以通过在前面加上 '+' 或 '-' 符号来添加或删除标志。特殊变量 "%o" 可用于将其标志传播到同一格式字符串上的所有其他变量。这对于带引号 ("Q") 和转义 ("E") 字符串格式特别方便。如果变量名称位于方括号 ('[' .. ']') 之间,则将其用作样本表达式规则(请参阅 第 7.3 节)。这对于添加一些不太常见的信息非常有用,例如客户端的 SSL 证书的 DN,或者记录用于将条目存储到粘性表中的密钥。注意:空格必须转义。空格字符被视为分隔符。为了发出字面量 '%',它必须在前面加上另一个 '%',从而导致 '%%'。HAProxy 将自动合并连续的分隔符。注意:使用 RFC5424 syslog 消息格式时,PARAM-VALUE 中的字符 '"'、'\' 和 ']' 应以 '\' 作为前缀进行转义(有关详细信息,请参阅 https://tools.ietf.org/html/rfc5424#section-6.3.3)。在这种情况下,应考虑使用 "E" 标志。标志如下: * Q:引用字符串 * X:十六进制表示(IP、端口、%Ts、%rt、%pid) * E:使用 '\' 作为前缀转义字符串中的字符 '"'、'\' 和 ']'(预期目的是用于 RFC5424 结构化数据日志格式)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)]]
目前,默认的 HTTP 格式定义如下: 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" 默认的 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 格式定义如下: log-format "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts \ %ac/%fc/%bc/%sc/%rc %sq/%bq" 请参阅下表了解当前定义的变量: +---+------+-----------------------------------------------+-------------+ | R | var | 字段名称(有关说明,请参阅 8.2.2 和 8.2.3) | 类型 | +---+------+-----------------------------------------------+-------------+ | | %o | 特殊变量,对所有后续变量应用标志 | | +---+------+-----------------------------------------------+-------------+ | | %B | bytes_read(从服务器到客户端) | numeric | | H | %CC | captured_request_cookie | string | | H | %CS | captured_response_cookie | string | | | %H | hostname | string | | H | %HM | HTTP method(例如:POST) | string | | H | %HP | HTTP request URI without query string | string | | H | %HQ | HTTP request URI query string(例如:?bar=baz)| string | | H | %HU | HTTP request URI(例如:/foo?bar=baz) | string | | H | %HV | HTTP version(例如:HTTP/1.0) | string | | | %ID | unique-id | string | | | %ST | status_code | numeric | | | %T | gmt_date_time | date | | | %Ta | Active time of the request(从 TR 到结束) | numeric | | | %Tc | Tc | numeric | | | %Td | Td = Tt - (Tq + Tw + Tc + Tr) | numeric | | | %Tl | local_date_time | date | | | %Th | connection handshake time (SSL, PROXY proto) | numeric | | H | %Ti | idle time before the HTTP request | numeric | | H | %Tq | Th + Ti + TR | numeric | | H | %TR | time to receive the full request from 1st byte| numeric | | H | %Tr | Tr (response time) | numeric | | | %Ts | timestamp | numeric | | | %Tt | Tt | numeric | | | %Tw | Tw | numeric | | | %U | bytes_uploaded(从客户端到服务器) | numeric | | | %ac | actconn | numeric | | | %b | backend_name | string | | | %bc | beconn (backend concurrent connections) | numeric | | | %bi | backend_source_ip (connecting address) | IP | | | %bp | backend_source_port (connecting address) | numeric | | | %bq | backend_queue | numeric | | | %ci | client_ip (accepted address) | IP | | | %cp | client_port (accepted address) | numeric | | | %f | frontend_name | string | | | %fc | feconn (frontend concurrent connections) | numeric | | | %fi | frontend_ip (accepting address) | IP | | | %fp | frontend_port (accepting address) | 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 | | | %ms | accept date milliseconds (left-padded with 0) | numeric | | | %pid | PID | numeric | | H | %r | http_request | string | | | %rc | retries | numeric | | | %rt | request_counter (HTTP req or TCP session) | numeric | | | %s | server_name | string | | | %sc | srv_conn (server concurrent connections) | numeric | | | %si | server_IP (target address) | IP | | | %sp | server_port (target address) | numeric | | | %sq | srv_queue | numeric | | S | %sslc| ssl_ciphers (ex: AES-SHA) | string | | S | %sslv| ssl_version (ex: TLSv1) | string | | | %t | date_time (with millisecond resolution) | date | | H | %tr | date_time of HTTP request | date | | H | %trg | gmt_date_time of start of HTTP request | date | | H | %trl | local_date_time of start of HTTP request | date | | | %ts | termination_state | string | | H | %tsc | termination_state with cookie status | string | +---+------+-----------------------------------------------+-------------+ R = Restrictions : H = mode http only ; S = SSL only当传入连接由于 SSL 握手失败或 PROXY 协议标头无效而失败时,haproxy 将使用较短的固定行格式记录事件。默认情况下,日志以 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 这些字段仅提供最少的信息来帮助调试连接失败。
一些高级日志记录选项经常被寻找,但仅通过查看各种选项不容易找到。这里是几个可以实现更好日志记录的选项的入口点。有关其用法的更多信息,请参考关键字参考。
监控工具对 haproxy 执行健康检查是很常见的。有时它是一个第 3 层负载均衡器,例如 LVS 或任何商业负载均衡器,有时它只是一个更完整的监控系统,例如 Nagios。当测试非常频繁时,用户经常会问如何禁用这些检查的日志记录。有三种可能性: - 如果连接来自任何地方并且只是 TCP 探针,通常希望通过在前端设置 "option dontlognull" 来简单地禁用没有数据交换的连接的日志记录。它还会禁用端口扫描的日志记录,这可能合意也可能不合意。 - 如果连接来自已知的源网络,请使用 "monitor-net" 将此网络声明为仅用于监控。此网络中的任何主机都将只能执行健康检查,并且不会记录其请求。这通常适用于指定其他负载均衡器等设备的列表。 - 如果测试是在已知的 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 的响应不被认为是正常的,也会被记录。当然,这样做是强烈不鼓励的,因为它会从日志中删除大部分有用的信息。只有在没有其他选择的情况下才这样做。
计时器对于排除网络故障非常有帮助。所有值均以毫秒 (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 -------------->: :<--------- Ta --------->: TCP 模式下的计时事件: TCP 会话 |<----------------->| t t ---|----|----|----|----|--- | Th Tw Tc Td | |<------ Tt ------->| - Th:接受 tcp 连接并执行低级协议握手的总时间。目前,这些协议是 proxy-protocol 和 SSL。这在整个连接的生命周期中可能只发生一次。此处时间过长可能表明客户端仅预先建立了连接而没有进行通信,或者它正在经历网络问题,阻止其在合理时间内完成握手(例如 MTU 问题),或者 SSL 握手计算成本很高。请注意,此时间仅在第一个请求之前报告,因此可以安全地对其所有请求取平均值以计算摊销值。第二个及后续请求此处将始终报告零。 - Ti:HTTP 请求之前的空闲时间(仅限 HTTP 模式)。此计时器在握手结束和 HTTP 请求的第一个字节之间计数。在处理 keep-alive 模式下的第二个请求时,它在传输上一个响应结束之后开始计数。当使用 HTTP/2 等多路复用协议时,它在上一个请求之后立即开始计数。某些浏览器会预先建立与服务器的连接,以减少未来请求的延迟,并将其保持挂起状态直到需要时。此延迟将报告为空闲时间。值为 -1 表示连接上未收到任何内容。 - TR:获取客户端请求的总时间(仅限 HTTP 模式)。它是从收到第一个字节到代理收到标记 HTTP 标头结束的空行之间经过的时间。值 "-1" 表示从未看到标头结束。当客户端过早关闭或超时时会发生这种情况。此时间通常很短,因为大多数请求都适合单个数据包。时间过长可能表示在测试期间手动键入请求。 - Tq:从接受日期或自上一个响应的最后一个字节发出以来获取客户端请求的总时间(仅限 HTTP 模式)。它正好等于 Th + Ti + TR,除非其中任何一个为 -1,在这种情况下它也返回 -1。在 HTTP keep-alive 和浏览器预连接功能出现之前,此计时器非常有用。建议现在放弃它而转而使用 TR,因为空闲时间给报告增加了很多噪音。 - Tw:在队列中等待连接槽所花费的总时间。它包括后端队列以及服务器队列,并取决于队列大小以及服务器完成先前请求所需的时间。值 "-1" 表示请求在到达队列之前被终止,这通常发生在无效或被拒绝的请求中。 - Tc:建立与服务器的 TCP 连接的总时间。它是从代理发送连接请求到服务器确认它之间经过的时间,或者在 TCP SYN 数据包和返回的匹配 SYN/ACK 数据包之间经过的时间。值 "-1" 表示连接从未建立。 - Tr:服务器响应时间(仅限 HTTP 模式)。它是从与服务器建立 TCP 连接到服务器发送完整响应标头之间经过的时间。它纯粹显示其请求处理时间,不包括由于数据传输引起的网络开销。值得注意的是,当客户端有数据要发送给服务器时(例如在 POST 请求期间),计时器已经开始运行,这可能会扭曲明显的响应时间。因此,对于来自不受信任网络后面的客户端发起的 POST 请求,通常明智的做法是不要太信任此字段。此处的值 "-1" 意味着从未看到最后一个响应标头(空行),最可能是因为服务器超时在服务器设法处理请求之前发生了。 - Ta:HTTP 请求的总活动时间,从代理收到请求标头的第一个字节到发送响应正文的最后一个字节之间。例外情况是指定了 "logasap" 选项。在这种情况下,它仅等于 (TR+Tw+Tc+Tr),并且以 '+' 符号作为前缀。从此字段,我们可以通过减去其他有效计时器来推断 "Td",即数据传输时间: Td = Ta - (TR + Tw + Tc + Tr) 带有 "-1" 值的计时器必须从该等式中排除。请注意,"Ta" 永远不能为负数。 - 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)。这些计时器为故障原因提供了宝贵的指示。由于 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 在本地处理,未传递给服务器。这发生在 stats 和重定向的情况下。 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:服务器 PROVIDED 了一个 cookie,并按原样传输。 R:服务器提供的 cookie 被代理 REWRITTEN,这发生在 "cookie rewrite" 或 "cookie prefix" 模式下。 D:服务器提供的 cookie 被代理 DELETED。 -:不适用(配置中未设置 cookie)。 前两个标志的组合提供了大量关于会话终止时发生的情况以及终止原因的信息。它可以帮助检测服务器饱和、网络故障、本地系统资源不足、攻击等。下面列出了最常见的终止标志组合。它们按字母顺序排序,小写字母紧跟在大写字母之后,以便于查找和理解。 标志 原因 -- 正常终止。 CC 客户端在连接到服务器之前中止。这可能发生在 haproxy 尝试连接到最近宕机(或未检查)的服务器时,而客户端在 haproxy 等待服务器响应或 "timeout connect" 到期时中止。 CD 客户端在数据传输过程中意外中止。这可能是由浏览器崩溃、客户端与 haproxy 之间的中间设备决定主动断开连接、客户端与 haproxy 之间的网络路由问题、或者服务器与客户端之间的 keep-alive 会话首先由客户端终止引起的。 cD 客户端在 "timeout client" 延迟时间内没有发送或确认任何数据。这通常是由于客户端侧的网络故障,或者客户端只是不干净地离开网络。 CH 客户端在等待服务器开始响应时中止。可能是服务器响应时间太长,或者客户端点击了 '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。注意:最近,一些浏览器开始实现“预连接”功能,即推测性地连接到一些最近访问过的网站,以防用户想要访问它们。这导致与网站建立了许多连接,如果超时先到期,则以 408 Request Timeout 结束;如果浏览器决定先关闭它们,则以 400 Bad Request 结束。这些连接会污染日志并增加错误计数器。据报道,某些版本的某些浏览器甚至会显示错误代码。可以通过在前端添加 "option http-ignore-probes" 来解决这种行为的不良影响,从而使零数据传输的连接被完全忽略。但这肯定会隐藏那些正在经历连接问题的用户的错误。 CT 客户端在会话被慢速处理时中止。重要的是检查这是否发生在有效请求上,以确保没有编写错误的慢速处理规则。如果发生很多次,可能需要将 "timeout tarpit" 值降低到接近平均报告的 "Tw" 计时器,以免浪费资源只针对少数攻击者。 LR 请求被 haproxy 拦截并本地处理。通常这意味着这是一个重定向或 stats 请求。 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 错误并在日志中报告。 PR 代理阻止了客户端的 HTTP 请求,要么是因为 HTTP 语法无效,在这种情况下它向客户端返回了 HTTP 400 错误,要么是因为匹配了拒绝过滤器,在这种情况下它返回了 HTTP 403 错误。 PT 代理阻止了客户端的请求,并在返回 500 服务器错误之前慢速处理了其连接。没有向服务器发送任何数据。连接保持开放的时间由 "Tw" 计时器字段报告。 RC 本地资源耗尽(内存、套接字、源端口),阻止了与服务器建立连接。错误日志将精确说明缺少的内容。这非常罕见,只能通过适当的系统调优来解决。 后两个标志的组合提供了大量关于客户端、服务器和 haproxy 如何处理持久性的信息。这对于解决断开连接非常重要,尤其是在用户抱怨必须重新进行身份验证时。常见的标志是: -- 未启用持久性 cookie。 NN 客户端未提供 cookie,响应中未插入 cookie。例如,这可能发生在插入模式下,并且在 GET 请求上设置了 "postonly"。 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"
这些是带有解释的真实日志示例。其中一些是手动编造的。为了更好的阅读,syslog 部分已被删除。它们唯一的目的是解释如何解读它们。 >>> haproxy[674]: 127.0.0.1:33318 [15/Oct/2003:08:31:57.130] px-http \ px-http/srv1 6559/0/7/147/6723 200 243 - - ---- 5/3/3/1/0 0/0 \ "HEAD / HTTP/1.0" => 通过 'telnet' 手动输入的长请求(6.5 秒)。服务器在 147 毫秒内回复,会话正常结束 ('----')。 >>> haproxy[674]: 127.0.0.1:33319 [15/Oct/2003:08:31:57.149] px-http \ px-http/srv1 6559/1230/7/147/6870 200 243 - - ---- 324/239/239/99/0 \ 0/9 "HEAD / HTTP/1.0" => 同上,但请求在全局队列中排在其他 9 个请求之后,并等待了 1230 毫秒。 >>> haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17.654] px-http \ px-http/srv1 9/0/7/14/+30 200 +243 - - ---- 3/3/3/1/0 0/0 \ "GET /image.iso HTTP/1.0" => 请求进行长时间数据传输。指定了 "logasap" 选项,因此日志是在传输数据之前生成的。服务器在 14 毫秒内回复,向客户端发送了 243 字节的头,从接受到第一个数据字节的总时间是 30 毫秒。 >>> haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17.925] px-http \ px-http/srv1 9/0/7/14/30 502 243 - - PH-- 3/2/2/0/0 0/0 \ "GET /cgi-bin/bug.cgi? HTTP/1.0" => 代理阻止了服务器响应,原因可能是 "http-response deny" 规则、响应格式不正确且不符合 HTTP 标准,或者阻止了可能被缓存的敏感信息。在这种情况下,响应被替换为 "502 bad gateway"。标志 ("PH--") 告诉我们是 haproxy 决定返回 502,而不是服务器。 >>> haproxy[18113]: 127.0.0.1:34548 [15/Oct/2003:15:18:55.798] px-http \ px-http/<NOSRV> -1/-1/-1/-1/8490 -1 0 - - CR-- 2/2/2/0/0 0/0 "" => 客户端从未完成其请求并自行中止 ("C---"),在 8.5 秒后,当时代理正在等待请求头 ("-R--")。没有向任何服务器发送任何数据。 >>> haproxy[18113]: 127.0.0.1:34549 [15/Oct/2003:15:19:06.103] px-http \ px-http/<NOSRV> -1/-1/-1/-1/50001 408 0 - - cR-- 2/2/2/0/0 0/0 "" => 客户端从未完成其请求,在 50 秒后被超时中止 ("c---"),当时代理正在等待请求头 ("-R--")。没有向任何服务器发送任何数据,但代理可以向客户端发送 408 返回码。 >>> haproxy[18989]: 127.0.0.1:34550 [15/Oct/2003:15:24:28.312] px-tcp \ px-tcp/srv1 0/0/5007 0 cD 0/0/0/0/0 0/0 => 此日志是使用 "option tcplog" 生成的。客户端在 5 秒后超时 ("c----")。 >>> haproxy[18989]: 10.0.0.1:34552 [15/Oct/2003:15:26:31.462] px-http \ px-http/srv1 3183/-1/-1/-1/11215 503 0 - - SC-- 205/202/202/115/3 \ 0/0 "HEAD / HTTP/1.0" => 请求花费了 3 秒完成(可能是网络问题),并且连接到服务器失败 ('SC--'),经过 4 次尝试,每次 2 秒(配置中说 'retries 3'),并且没有重新分派(否则我们会看到 "/+3")。向客户端返回了状态码 503。此服务器上有 115 个连接,此代理上有 202 个连接,全局进程上有 205 个连接。可能是服务器因为已建立的连接过多而拒绝了连接。此处列出了官方支持的过滤器及其接受的参数。根据编译选项,其中一些过滤器可能不可用。可用过滤器的列表将在 haproxy -vv 中报告。
<name> is an arbitrary name that will be reported in messages. If no name is provided, "TRACE" is used. <random-parsing> enables the random parsing of data exchanged between the client and the server. By default, this filter parses all available data. With this parameter, it only parses a random amount of the available data. <random-forwarding> enables the random forwarding of parsed data. By default, this filter forwards all previously parsed data. With this parameter, it only forwards a random amount of the parsed data. <hexdump> dumps all forwarded data to the server and the client.
此过滤器可用作开发新过滤器的基础。它定义了所有回调,并在标准错误流(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.
The Stream Processing Offload Engine (SPOE) is a filter communicating with external components. It allows the offload of some specifics processing on the streams in tiered applications. These external components and information exchanged with them are configured in dedicated files, for the main part. It also requires dedicated backends, defined in HAProxy configuration. SPOE communicates with external components using an in-house binary protocol, the Stream Processing Offload Protocol (SPOP). For all information about the SPOE configuration and the SPOP specification, see "doc/SPOE.txt".
<name> is name of the cache section this filter will use.
缓存使用过滤器来存储可缓存的响应。必须使用 HTTP 规则“cache-store”和“cache-use”来定义如何以及何时使用缓存。默认情况下,相应的过滤器是隐式定义的。并且当没有使用除 fcgi-app 或压缩之外的其他过滤器时,这就足够了。在这种情况下,压缩过滤器始终在缓存过滤器之后评估。但是,当同一监听器/前端/后端使用了除压缩或 fcgi-app 之外的至少一个过滤器时,必须明确使用过滤器行来使用缓存。了解过滤器的评估顺序很重要。
<name> is name of the fcgi-app section this filter will use.
FastCGI 应用程序使用过滤器来评估请求路径上的所有自定义参数,并处理响应路径上的头。<name> 必须引用现有的 fcgi-app 部分。应使用指令 "use-fcgi-app" 来定义要使用的应用程序。默认情况下,相应的过滤器是隐式定义的。当只使用缓存或压缩过滤器时,这就足够了。但是,当同一后端使用了除压缩或缓存之外的至少一个过滤器时,必须明确使用过滤器行到 fcgi-app。这对于了解过滤器评估顺序非常重要。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 变量,此选项可能会被覆盖。默认情况下禁用。
Set a FastCGI parameter that should be passed to this application. Its value, defined by <fmt> must follows the log-format rules (see section 8.2.4 "Custom Log format"). It may optionally be followed by an ACL-based condition, in which case it will only be evaluated if the condition is true. With this directive, it is possible to overwrite the value of default FastCGI parameters. If the value is evaluated to an empty string, the rule is ignored. These directives are evaluated in their declaration order.
# 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 | 包含请求的协议。 | | | | +-------------------+-----------------------------------------------------+ | 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 记录一旦编码,不得超过缓冲区的大小。但是,这里没有要遵守的保留。