Apache 模块 mod_proxy_fcgi

Description:mod_proxy的 FastCGI 支持模块
Status:Extension
Module Identifier:proxy_fcgi_module
Source File:mod_proxy_fcgi.c
Compatibility:在版本 2.3 及更高版本中可用

Summary

该模块需要 mod_proxy的服务。它提供对FastCGI协议的支持。

因此,为了获得处理FastCGI协议的能力,服务器中必须存在mod_proxymod_proxy_fcgi

mod_fcgidmod_fastcgi不同,mod_proxy_fcgi没有启动应用程序的准备;为此提供了fcgistarter(在某些平台上)。或者,可以在使用的 FastCGI 应用程序框架中使用外部启动或过程 Management。

Warning

在拥有保护您的服务器之前,不要启用代理。开放式代理服务器对您的网络和整个 Internet 都是危险的。

Examples

请记住,为了使以下示例起作用,您必须启用mod_proxymod_proxy_fcgi

单个应用程序实例

ProxyPass "/myapp/" "fcgi://localhost:4000/"

mod_proxy_fcgi默认情况下会禁用连接重用,因此在请求完成后,该 httpd 子进程将不会将该连接保持打开状态,并且将不会重用该连接。如果 FastCGI 应用程序能够处理来自 httpd 的并发连接,则可以选择加入连接重用,如以下示例所示:

单个应用程序实例,连接重用(2.4.11 及更高版本)

ProxyPass "/myapp/" "fcgi://localhost:4000/" enablereuse=on

Enable connection reuse to a FCGI backend like PHP-FPM

请记住,PHP-FPM(在撰写本文时,2018 年 2 月)使用了一个 prefork 模型,即其每个工作进程可以同时处理一个连接。
默认情况下,mod_proxy(用enablereuse=on配置)允许在使用线程式 mpm(例如workerevent)时为每个 httpd 进程的后端提供ThreadsPerChild个连接的连接池,因此应考虑以下用例:

  • 在 HTTP/1.1 负载下,可能会导致与 FCGI 后端构建多达MaxRequestWorkers个连接。

  • 在 HTTP/2 负载下,由于如何实现mod_http2,因此还有其他 h2 工作线程可能会强制创建其他后端连接。池中的连接总数可能会增加到MaxRequestWorkers以上。

需要明智地配置 PHP-FPM 工作进程的最大数量,因为它们有可能最终全部“忙”于处理空闲的持久连接,而没有任何空间可以构建新的持久连接,并且最终用户体验将一堆 HTTP 请求超时。

以下示例将请求 URI 作为要运行的 PHP-FPM 守护程序的文件系统路径传递。请求 URL 隐式添加到第二个参数。 fcgi://之后的主机名和端口是 PHP-FPM 监听的地方。连接池/重用已启用。

PHP-FPM

ProxyPassMatch "^/myapp/.*\.php(/.*)?$" "fcgi://localhost:9000/var/www/" enablereuse=on

以下示例将请求 URI 作为要运行的 PHP-FPM 守护程序的文件系统路径传递。在这种情况下,PHP-FPM 正在 unix 域套接字(UDS)上侦听。需要 2.4.9 或更高版本。使用此语法,将忽略主机名和 fcgi://之后的可选端口。

带有 UDS 的 PHP-FPM

ProxyPassMatch "^/(.*\.php(/.*)?)$" "unix:/var/run/php5-fpm.sock|fcgi://localhost/var/www/"

除了上面列出的代理模块之外,平衡网关还需要mod_proxy_balancer和至少一个负载平衡器算法模块,例如mod_lbmethod_byrequestsmod_lbmethod_byrequests是默认值,将用于此示例配置。

通往多个应用程序实例的平衡网关

ProxyPass "/myapp/" "balancer://myappcluster/"
<Proxy "balancer://myappcluster/">
    BalancerMember "fcgi://localhost:4000"
    BalancerMember "fcgi://localhost:4001"
</Proxy>

您还可以通过创建合适的 Handler 传递,将请求强制处理为反向代理请求。下面的示例配置将使用反向代理将对 PHP 脚本的所有请求传递到指定的 FastCGI 服务器。 Apache HTTP Server 2.4.10 和更高版本中提供了此功能。出于性能原因,您将需要定义一个worker代表相同的 fcgi://后端。这种形式的好处在于,它允许在服务器中进行 URI 到文件名的常规 Map,并将本地文件系统结果传递到后端。通过这种方式配置 FastCGI 后,服务器可以计算出最准确的 PATH_INFO。

通过处理程序代理

<FilesMatch "\.php$">
    # Note: The only part that varies is /path/to/app.sock
    SetHandler  "proxy:unix:/path/to/app.sock|fcgi://localhost/"
</FilesMatch>

# Define a matching worker.
# The part that is matched to the SetHandler is the part that
# follows the pipe. If you need to distinguish, "localhost; can
# be anything unique.
<Proxy "fcgi://localhost/" enablereuse=on max=10>
</Proxy>

<FilesMatch ...>
    SetHandler  "proxy:fcgi://localhost:9000"
</FilesMatch>

<FilesMatch ...>
    SetHandler  "proxy:balancer://myappcluster/"
</FilesMatch>

Environment Variables

除了控制mod_proxy行为的配置指令外,还有许多控制 FCGI 协议提供程序的环境变量:

  • proxy-fcgi-pathinfo

    • 通过ProxyPassProxyPassMatch配置时,mod_proxy_fcgi不会设置 PATH_INFO 环境变量。这允许后端 FCGI 服务器正确确定 SCRIPT_NAME 和 Script-URI 并符合 RFC 3875 第 3.3 节。如果相反,您需要mod_proxy_fcgi为 PATH_INFO 生成“最佳猜测”,请设置此 env-var。这是某些 FCGI 实现中的错误的解决方法。可以将此变量设置为多个值,以调整如何选择最佳猜测(仅在 2.4.11 及更高版本中):
  • first-dot

    • PATH_INFO 与* first *“之后的斜杠分开。在网址中。

    • last-dot

      • PATH_INFO 从* last *“之后的斜杠中分离出来。在网址中。
    • full

      • PATH_INFO 是通过尝试将 URL Map 到本地文件系统来计算的。
    • unescape

      • PATH_INFO 是 URL 的路径组成部分,未经转义/解码。
    • 任何其他值

      • PATH_INFO 与 URL 的路径部分相同。最初,这是唯一的 proxy-fcgi-pathinfo 选项。

ProxyFCGIBackendType Directive

Description:指定后端 FastCGI 应用程序的类型
Syntax:ProxyFCGIBackendType FPM|GENERIC
Default:ProxyFCGIBackendType FPM
Context:服务器配置,虚拟主机,目录,.htaccess
Status:Extension
Module:mod_proxy_fcgi
Compatibility:在版本 2.4.26 和更高版本中可用

该指令允许指定后端 FastCGI 应用程序的类型。某些 FastCGI 服务器(例如 PHP-FPM)使用环境变量的历史古怪来标识所使用的代理服务器的类型。如果您的非 PHP-FPM 应用程序无法解释服务器设置的环境变量(如 SCRIPT_FILENAME 或 PATH_TRANSLATED),则将此指令设置为“ GENERIC”。

根据此伪指令的设置更改的值的一个示例是 SCRIPT_FILENAME。历史上使用mod_proxy_fcgi时,SCRIPT_FILENAME 的前缀为字符串“ proxy:fcgi://”。一些通用 FastCGI 应用程序会将其作为脚本 Importing 读取,但是 PHP-FPM 会删除该前缀,然后记住它正在与 Apache 通讯。在 2.4.21 至 2.4.25 中,服务器自动剥离了此前缀,从而在某些情况下破坏了 PHP-FPM 检测 Apache 并与之进行互操作的能力。

ProxyFCGISetEnvIf Directive

Description:允许修复发送给 FastCGI 服务器的变量
Syntax:ProxyFCGISetEnvIf conditional-expression [!]environment-variable-name [value-expression]
Context:服务器配置,虚拟主机,目录,.htaccess
Status:Extension
Module:mod_proxy_fcgi
Compatibility:在版本 2.4.26 和更高版本中可用

在将请求传递到已配置的 FastCGI 服务器之前,Web 服务器的核心会根据当前请求的详细信息设置许多环境变量。 FastCGI 程序通常使用这些环境变量作为 Importing,以确定它们将处理的底层脚本或直接产生的输出。

值得注意的环境变量示例包括:

  • SCRIPT_NAME

  • SCRIPT_FILENAME

  • REQUEST_URI

  • PATH_INFO

  • PATH_TRANSLATED

该指令允许覆盖上面的环境变量或任何其他感兴趣的环境变量。在设置了这些变量的初始值之后,将评估此伪指令,因此可以将它们用作条件表达式和值表达式的 Importing。

Parameter syntax:

  • conditional-expression

    • 指定一个表达式,该表达式控制是否将修改后面的环境变量。有关表达式语法的信息,请参见下面的示例或ap_expr文档中的完整规范。
  • environment-variable-name

    • 指定要更改的 CGI 环境变量,例如 PATH_INFO。如果前面带有感叹号,则该变量将未设置。
  • value-expression

    • 指定前面的环境变量的替换值。可以在条件表达式的正则表达式捕获中包含反向引用,例如“ $ 1”。如果省略,则变量将设置(或覆盖)为空字符串-但请参见下面的 Comments。
# A basic, unconditional override
ProxyFCGISetEnvIf "true" PATH_INFO "/example"

# Use an environment variable in the value
ProxyFCGISetEnvIf "true" PATH_INFO "%{reqenv:SCRIPT_NAME}"

# Use captures in the conditions and backreferences in the replacement
ProxyFCGISetEnvIf "reqenv('PATH_TRANSLATED') =~ m|(/.*prefix)(\d+)(.*)|" PATH_TRANSLATED "$1$3"

Note: Unset vs. Empty

以下将取消设置VARIABLE,从而阻止将其发送到 FastCGI 服务器:

ProxyFCGISetEnvIf true !VARIABLE

而以下内容将清除VARIABLE的任何现有(通过将其设置为空字符串),但空的VARIABLE仍将发送到服务器:

ProxyFCGISetEnvIf true VARIABLE

CGI/1.1 规范不区分在具有空值的变量和不存在的变量之间。但是,许多 CGI 和 FastCGI 实现在两者之间进行区分(或允许脚本进行区分)。使用哪种选择取决于您的实现和修改变量的原因。