Apache PHP-FPM 在 Proxy enablereuse=on 的情况下出现奇怪的响应

Apache PHP-FPM 在 Proxy enablereuse=on 的情况下出现奇怪的响应

启用后<Proxy ... enablereuse=on max=10>,我开始收到奇怪的响应。刷新当前页面时,主请求会加载不同的响应;例如空白页、针对单独客户端的响应或来自所请求页面上的 CSS 文件的 404 响应。

删除enablereuse,可以修复奇怪的响应,但可以防止来自同一用户的并发请求,这意味着每个请求都单独处理。

例如:在同一个 vhost 域上打开两个指向不同 URL 的浏览器选项卡,如果第一个请求的页面需要 5 秒才能加载,则在第一个选项卡加载完成之前,它不会加载第二个选项卡。

我试图通过允许同一个客户端以并发非阻塞方式同时执行多个请求来防止这种情况。

服务器环境

CentOS 6.10 x64
php 5.6.37 Remi
Apache 2.4.33 IUS

MPM 事件配置

<IfModule mpm_event_module>
    ServerLimit              100
    StartServers             4
    ThreadLimit              64
    MaxRequestWorkers        100
    MinSpareThreads          25
    MaxSpareThreads          75
    ThreadsPerChild          25
    MaxConnectionsPerChild   1000
    ListenBacklog       511
</IfModule>

虚拟主机配置(4 个中的 1 个 - 除 IP 地址、UDS 和 ServerName 外其他均相同)

<VirtualHost 192.168.1.71:443>
    ServerName example.com:443
    DocumentRoot /home/example/example.com
    <IfModule mod_ssl.c>
        SSLEngine on
        SSLCertificateFile /etc/httpd/ssl/certs/example.crt
        SSLCertificateKeyFile /etc/httpd/ssl/private/example.key
        SSLCertificateChainfile /etc/httpd/ssl/certs/example.ca-bundle
        <IfModule mod_setenvif.c>
            SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
        </IfModule>
        <IfModule mod_headers.c>
            Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
        </IfModule>
    </IfModule>
    <Directory "/home/example/example.com">
        AllowOverride All
        Require all granted
    </Directory>
    <IfModule mod_proxy_fcgi.c>
        <FilesMatch \.php$>
            <If "-f %{REQUEST_FILENAME}">
                SetHandler "proxy:unix:/var/run/example.sock|fcgi://127.0.0.1/"
            </If>
        </FilesMatch>
        <Proxy "fcgi://127.0.0.1" enablereuse=on max=10>
            ProxySet timeout=7200
        </Proxy>
    </IfModule>
</VirtualHost>

PHP-FPM 池配置(4 个中的 1 个,除 UDS 外,其余均相同)

[example_com]
user = example
group = example
listen = /var/run/example.sock
listen.owner = example
listen.group = apache
listen.mode = 0660

pm = dynamic
pm.max_children = 20
pm.start_servers = 2
pm.min_spare_servers = 2
pm.max_spare_servers = 20
pm.max_requests = 1000

security.limit_extensions = .php

由于其他帖子评论了不支持 UDS 的问题,我尝试使用 TCP 代理而不是 UDS,但问题仍然存在:

<IfModule mod_proxy_fcgi.c>
    <FilesMatch \.php$>
        <If "-f %{REQUEST_FILENAME}">
            SetHandler "proxy:fcgi://127.0.0.1:9000/"
        </If>
    </FilesMatch>
    <Proxy "fcgi://127.0.0.1:9000" enablereuse=on max=10>
        ProxySet timeout=7200
    </Proxy>
</IfModule>

还尝试通过将 pm 设置为 来更改 PHP-FPM 配置dynamicondemandstatic进行适当的流程更改。


我确定并发请求的限制是由于 PHP 会话和对基于文件系统的会话施加的锁定造成的。然而,这个问题与我收到的奇怪响应不符。

答案1

来自文档 Apache 2.4:启用与 PHP-FPM 等 FCGI 后端的连接重用

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

Under HTTP/1.1 load it will likely cause the creation of up to MaxRequestWorkers connections to the FCGI backend.
Under HTTP/2 load, due to how mod_http2 is implemented, there are additional h2 worker threads that may force the creation of other backend connections. The overall count of connections in the pools may raise to more than MaxRequestWorkers.

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

所以我提到不要将 enablereuse 与 mod_proxy_fcgi + php-fpm 一起使用。

相关内容