单个 php-fastcgi 进程阻止所有其他 PHP 请求

单个 php-fastcgi 进程阻止所有其他 PHP 请求

我最近切换到了 PHP 的 FastCGI 设置(Apache2-worker 和mod_fcgid)。但是,当单个 PHP 脚本非常繁忙时,它似乎会阻止所有其他 PHP 请求。我的配置有什么问题?

我使用的主要原因mod_fcgid是为了控制 PHP 内存使用量。mod_php,所有单独的 Apache 分支在提供 PHP 服务后内存都会增长。

我还切换到了 apache2-worker 模型,因为所有线程不安全的 PHP 代码都存在于 Apache 之外。

我的 FastCGI 脚本如下所示:

#!/bin/sh
#export PHPRC=/etc/php/fastcgi/
export PHP_FCGI_CHILDREN=5
export PHP_FCGI_MAX_REQUESTS=5000

global_root=/srv/www/vhosts.d/
exec /usr/bin/php-cgi5 \
-d open_basedir=$global_root:/tmp:/usr/share/php5:/var/lib/php5 \
-d disable_functions="exec,shell_exec,system"

我的 Apache 配置如下:

<IfModule fcgid_module>
  FcgidIPCDir /var/lib/apache2/fcgid/
  FcgidProcessTableFile /var/lib/apache2/fcgid/shm
  FcgidMaxProcessesPerClass 1
  FcgidInitialEnv RAILS_ENV production
  FcgidIOTimeout 600
  AddHandler fcgid-script .fcgi

  FcgidConnectTimeout 20
  MaxRequestLen 16777216

  <FilesMatch "\.php$">
    AddHandler fcgid-script .php
    Options +ExecCGI
    FcgidWrapper /srv/www/cgi-bin/php5-wrapper.sh .php
  </FilesMatch>
  DirectoryIndex index.php
</IfModule>

答案1

找到答案如下:https://stackoverflow.com/questions/598444/how-to-share-apc-cache-between-several-php-processes-when-running-under-fastcgi/1094068#1094068

问题不在于 PHP,而在于 mod_fcgid。虽然 PHP 会生成多个子进程,但mod_fcgid对此一无所知,并且会为每个子进程处理一个请求。因此,在FcgidMaxProcessesPerClass 1使用时,所有 PHP 执行都会接连发生。*

此处提出的解决方案链接到:http://www.brandonturner.net/blog/2009/07/fastcgi_with_php_opcode_cache/解释了如何使用mod_fastcgi没有这个限制。它将向同一个子级发送多个请求。

[*] 请注意,不要FcgidMaxProcessesPerClass 1在 PHP、ruby 等的许多单独实例中使用结果,尽管它们都能够在单个进程中内部处理许多请求。


因此,需要一个新的 Apache 配置来使用 PHP 和 fastcgi:

<IfModule mod_fastcgi.c>

    # Needed for for suEXEC: FastCgiWrapper On
    FastCgiConfig -idle-timeout 20 -maxClassProcesses 1 -initial-env RAILS_ENV=production
    FastCgiIpcDir /var/lib/apache2/fastcgi

    AddHandler php5-fcgi .php
    Action php5-fcgi /.fcgi-bin/php5-wrapper.sh
    DirectoryIndex index.php

    ScriptAlias /.fcgi-bin/ /srv/www/cgi-bin/
    <Location "/.fcgi-bin/php5-wrapper.sh">
        Order Deny,Allow
        Deny from All
        #Allow from all
        Allow from env=REDIRECT_STATUS
        Options ExecCGI
        SetHandler fastcgi-script
    </Location>

    # Startup PHP directly
    FastCgiServer /srv/www/cgi-bin/php5-wrapper.sh

    # Support dynamic startup
    AddHandler fastcgi-script fcg fcgi fpl
</IfModule>

答案2

首先,除非 Apache 的文档过时,否则您的包装器脚本和设置就是错误的。请阅读mod_fcgid 文档并使用那里的脚本和示例设置。您当前的设置基本上会生成一堆不可用的 php 子进程,然后每 5001 个 PHP 请求都会出错,因为 PHP 会在 5000 个请求后退出,但您缺少FcgidMaxRequestsPerProcess 5000告诉 mod_fcgid 它将需要在 5000 个请求后启动新的 PHP 进程的指令。

至于同时进行的 PHP 进程,每个同时进行的请求都需要它自己的 PHP 进程,因此您需要将指令增加到FcgidMaxProcessesPerClass 更高的数字。

相关内容