--- title: "10. FastCGI 应用程序" linkTitle: "10. FastCGI" weight: 210 description: "FastCGI 应用配置、参数、示例及限制" icon: fa-solid fa-bolt module: [HAPROXY] categories: [参考] aliases: - /haproxy/configuration/fastcgi/ - /docs/haproxy/configuration/fastcgi/ - /haproxy/fastcgi/ upstream_link: "https://docs.haproxy.org/3.4/configuration.html" upstream_name: "HAProxy 3.4 Configuration Manual" upstream_ref: "v3.4.4, chapter 10" --- HAProxy 可以向 Responder FastCGI 应用发送 HTTP 请求。此功能自 HAProxy 2.1 版本起引入。为此,必须将服务器配置为使用 FastCGI 协议(在服务器行中使用关键字 "proto fcgi"),且后端管理这些服务器时,必须配置并使用一个 FastCGI 应用(在代理段中使用关键字 "use-fcgi-app")。可以定义多个 FastCGI 应用,但每个后端在同一时间只能使用其中一个。 HAProxy 实现了 FastCGI 规范中针对 Responder 应用的所有功能。特别是,它能够在单一连接上复用多个请求。 ## 10.1. 配置 {#section-10-1} ### 10.1.1. FastCGI 应用段 {#section-10-1-1} **`fcgi-app `** ```haproxy fcgi-app ``` 声明一个名为 `` 的 FastCGI 应用。要使配置有效,至少必须定义文档根目录。 **`acl [flags] [operator] ...`** ```haproxy acl [flags] [operator] ... ``` 声明或完成访问控制列表。 请参阅 "acl" 的 [第 4.2 节](/zh/docs/haproxy/proxies/#section-4-2) 和 [第 7 节](/zh/docs/haproxy/acls-and-samples/) 了解 ACL 使用详情。为 FastCGI 应用定义的 ACL 为私有,无法被任何其他应用或代理使用。同理,任何其他段中定义的 ACL 也无法被 FastCGI 应用使用。但预定义的 ACL 可用。 **`docroot `** ```haproxy docroot ``` 定义远程主机上的文档根目录。`` 将用于构建 FastCGI 参数 SCRIPT_FILENAME 和 PATH_TRANSLATED 的默认值。此项为必选设置。 **`index `** ```haproxy index ``` 定义在以斜杠 ("/") 结尾的 URI 后附加的脚本名称,用于设置 FastCGI 参数 SCRIPT_NAME 的默认值。此项为可选设置。 示例: ```text index index.php ``` **`log-stderr global`** ```haproxy log-stderr global log-stderr [len ] [format ] [sample :] [ []] ``` 启用记录 FastCGI 应用程序报告的 STDERR 消息。 请参见 "log" 关键字在 [第 4.2 节](/zh/docs/haproxy/proxies/#section-4-2) 中的说明。该设置为可选。默认情况下,忽略 STDERR 消息。 **`pass-header [ { if | unless } ]`** ```haproxy pass-header [ { if | unless } ] ``` 指定将传递给 FastCGI 应用程序的请求头名称。可选地,其后可跟一个基于 ACL 的条件,此时仅当该条件为真时才进行评估。 大多数请求头已可供 FastCGI 应用程序使用,且均以 "HTTP\_" 为前缀。因此,该指令仅用于传递那些被有意省略的头。当前,头 "Authorization"、"Proxy-Authorization" 以及逐跳头被省略。 请注意,头 "Content-type" 和 "Content-length" 永远不会传递给 FastCGI 应用程序,因为它们已转换为参数。 **`path-info `** ```haproxy path-info ``` 定义一个正则表达式,用于从 URL 解码后的路径中提取脚本名和路径信息。 因此,`` 可能包含两个捕获:第一个用于捕获脚本名,第二个用于捕获路径信息。第一个捕获为必选,第二个为可选。通过这种方式,可以从路径中提取脚本名,同时忽略路径信息。此设置为可选。若未定义,则不对路径执行匹配,且 FastCGI 参数 PATH_INFO 和 PATH_TRANSLATED 不会被填充。 出于安全考虑,当定义了此正则表达式时,路径在经过 URL 解码后禁止包含换行符和空字符。此限制的原因在于,否则匹配将始终失败(由于 HAProxy 中正则表达式执行方式的限制)。因此,若在 URL 解码后的路径中发现这两个字符之一,将向客户端返回错误。此处遵循最小惊讶原则。 示例: ```text path-info ^(/.+\.php)(/.*)?$ # both script-name and path-info may be set path-info ^(/.+\.php) # the path-info is ignored ``` **`option get-values`** ```haproxy option get-values no option get-values ``` 启用或禁用获取连接管理相关变量。 HAProxy 可在建立连接时发送记录 FCGI_GET_VALUES,以获取以下变量的值: * FCGI_MAX_REQS The maximum number of concurrent requests this application will accept. * FCGI_MPXS_CONNS "0" if this application does not multiplex connections, "1" otherwise. 部分 FastCGI 应用程序不支持此功能。部分应用程序在发送响应后立即关闭连接。因此,默认情况下,此选项处于禁用状态。 请注意,FastCGI 应用程序接受的最大并发请求数是一个连接级变量。它仅限制每个连接的流数量。若需对应用的全局负载进行限制,必须设置服务器参数 "maxconn" 和 "pool-max-conn"。此外,若应用不支持连接多路复用,则最大并发请求数将自动设为 1。 **`option keep-conn`** ```haproxy option keep-conn no option keep-conn ``` 指示 FastCGI 应用程序在发送响应后是否保持连接打开。 若禁用,FastCGI 应用程序在响应此请求后关闭连接。默认情况下,此选项已启用。 **`option max-reqs `** ```haproxy option max-reqs ``` 定义该应用程序将接受的最大并发请求数。 该选项可在连接建立期间获取变量 FCGI_MAX_REQS 时被覆盖。此外,若应用程序不支持连接复用,该选项将被忽略。默认值为 1。 **`option mpxs-conns`** ```haproxy option mpxs-conns no option mpxs-conns ``` 启用或禁用连接复用支持。 该选项可在连接建立期间获取变量 FCGI_MPXS_CONNS 时被覆盖。默认情况下已禁用。 **`set-param [ { if | unless } ]`** ```haproxy set-param [ { if | unless } ] ``` 设置应传递给该应用的 FastCGI 参数。其值由 `` 定义,必须遵循自定义日志格式规则(参见 [第 8.2.6 节](/zh/docs/haproxy/configuration-logging/#section-8-2-6) “自定义日志格式”)。可选地,其后可跟一个基于 ACL 的条件,此时仅当该条件为真时才进行评估。 使用该指令,可以覆盖默认 FastCGI 参数的值。若值被计算为空字符串,则忽略该规则。这些指令按声明顺序进行评估。 示例: ```shell # PHP only, required if PHP was built with --enable-force-cgi-redirect set-param REDIRECT_STATUS 200 set-param PHP_AUTH_DIGEST %[req.hdr(Authorization)] ``` ### 10.1.2. 代理段 {#section-10-1-2} use-fcgi-app `` 为后端指定要使用的 FastCGI 应用。 参数: ```text is the name of the FastCGI application to use. ``` 该关键字仅适用于具备后端功能且至少包含一个 FastCGI 服务器的 HTTP 代理。尽管 FastCGI 服务器可与 HTTP 服务器混合使用,但除非有充分理由,否则不建议如此操作(详见 [第 10.3 节](/zh/docs/haproxy/fastcgi/#section-10-3) 中关于限制的详细说明)。每个后端在同一时间只能定义一个应用程序。 请注意,一旦后端引用了 FastCGI 应用,根据配置情况,即使请求未发送至 FastCGI 服务器,也可能执行部分处理。用于设置参数或向应用传递头的规则将被评估。 ### 10.1.3. 示例 {#section-10-1-3} frontend front-http mode http bind \*:80 bind \*: use_backend back-dynamic if { path_reg ^/.+\.php(/.*)?$ } default_backend back-static backend back-static mode http server www A.B.C.D:80 backend back-dynamic mode http use-fcgi-app php-fpm server php-fpm A.B.C.D:9000 proto fcgi fcgi-app php-fpm log-stderr global option keep-conn docroot /var/www/my-app index index.php path-info ^(/.+\.php)(/.*)?$ ## 10.2. 默认参数 {#section-10-2} 响应式 FastCGI 应用程序的目的与 CGI/1.1 程序相同。在 CGI/1.1 规范(RFC3875)中,必须向脚本传递若干变量。因此,HAProxy 会设置这些变量以及 FastCGI 应用程序中常用的其他变量。所有这些变量均可被覆盖,但需谨慎操作。 ```text +-------------------+-----------------------------------------------------+ | AUTH_TYPE | Identifies the mechanism, if any, used by HAProxy | | | to authenticate the user. Concretely, only the | | | BASIC authentication mechanism is supported. | | | | +-------------------+-----------------------------------------------------+ | CONTENT_LENGTH | Contains the size of the message-body attached to | | | the request. It means only requests with a known | | | size are considered as valid and sent to the | | | application. | | | | +-------------------+-----------------------------------------------------+ | CONTENT_TYPE | Contains the type of the message-body attached to | | | the request. It may not be set. | | | | +-------------------+-----------------------------------------------------+ | DOCUMENT_ROOT | Contains the document root on the remote host under | | | which the script should be executed, as defined in | | | the application's configuration. | | | | +-------------------+-----------------------------------------------------+ | GATEWAY_INTERFACE | Contains the dialect of CGI being used by HAProxy | | | to communicate with the FastCGI application. | | | Concretely, it is set to "CGI/1.1". | | | | +-------------------+-----------------------------------------------------+ | PATH_INFO | Contains the portion of the URI path hierarchy | | | following the part that identifies the script | | | itself. To be set, the directive "path-info" must | | | be defined. | | | | +-------------------+-----------------------------------------------------+ | PATH_TRANSLATED | If PATH_INFO is set, it is its translated version. | | | It is the concatenation of DOCUMENT_ROOT and | | | PATH_INFO. If PATH_INFO is not set, this parameters | | | is not set too. | | | | +-------------------+-----------------------------------------------------+ | QUERY_STRING | Contains the request's query string. It may not be | | | set. | | | | +-------------------+-----------------------------------------------------+ | REMOTE_ADDR | Contains the network address of the client sending | | | the request. | | | | +-------------------+-----------------------------------------------------+ | REMOTE_USER | Contains the user identification string supplied by | | | client as part of user authentication. | | | | +-------------------+-----------------------------------------------------+ | REQUEST_METHOD | Contains the method which should be used by the | | | script to process the request. | | | | +-------------------+-----------------------------------------------------+ | REQUEST_URI | Contains the request's URI. | | | | +-------------------+-----------------------------------------------------+ | SCRIPT_FILENAME | Contains the absolute pathname of the script. it is | | | the concatenation of DOCUMENT_ROOT and SCRIPT_NAME. | | | | +-------------------+-----------------------------------------------------+ | SCRIPT_NAME | Contains the name of the script. If the directive | | | "path-info" is defined, it is the first part of the | | | URI path hierarchy, ending with the script name. | | | Otherwise, it is the entire URI path. | | | | +-------------------+-----------------------------------------------------+ | SERVER_NAME | Contains the name of the server host to which the | | | client request is directed. It is the value of the | | | header "Host", if defined. Otherwise, the | | | destination address of the connection on the client | | | side. | | | | +-------------------+-----------------------------------------------------+ | SERVER_PORT | Contains the destination TCP port of the connection | | | on the client side, which is the port the client | | | connected to. | | | | +-------------------+-----------------------------------------------------+ | SERVER_PROTOCOL | Contains the request's protocol. | | | | +-------------------+-----------------------------------------------------+ | SERVER_SOFTWARE | Contains the string "HAProxy" followed by the | | | current HAProxy version. | | | | +-------------------+-----------------------------------------------------+ | HTTPS | Set to a non-empty value ("on") if the script was | | | queried through the HTTPS protocol. | | | | +-------------------+-----------------------------------------------------+ ``` ## 10.3. 限制 {#section-10-3} 当前实现存在一些限制。第一个限制涉及某些请求头在传递给 FastCGI 应用程序时的隐藏方式。这一过程发生在后端侧的请求头分析阶段,即在连接建立之前。此时,HAProxy 知道后端使用的是 FastCGI 应用程序,但尚无法确定该请求是否将被路由至 FastCGI 服务器。为隐藏请求头,HAProxy 会直接从 HTX 消息中移除这些头。因此,若请求最终被路由至 HTTP 服务器,该服务器将无法看到这些头。出于此原因,不建议在同一后端中混合使用 FastCGI 服务器和 HTTP 服务器。 同样地,规则 "set-param" 和 "pass-header" 在请求头分析阶段进行评估。因此,即使请求最终被转发至 HTTP 服务器,评估操作也始终执行。 关于规则 "set-param",当应用规则时,会向 HTX 消息中添加一个伪头。 因此,与 HTTP 头重写类似,若缓冲区已满,操作可能失败。 规则 "set-param" 将与规则 "http-request" 竞争资源。 最后,所有 FastCGI 参数和 HTTP 头均被发送至一个独立记录 FCGI_PARAM。该记录的编码必须一次性完成,否则将返回处理错误。这意味着记录 FCGI_PARAM 在编码后,其大小不得超过缓冲区容量。但此处无需预留空间。