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 协议提供程序的环境变量:

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,以确定它们将处理的底层脚本或直接产生的输出。

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

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

Parameter syntax:

# 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 实现在两者之间进行区分(或允许脚本进行区分)。使用哪种选择取决于您的实现和修改变量的原因。

首页