Назад | Перейти на главную страницу

Один процесс php-fastcgi блокирует все остальные запросы PHP

Недавно я перешел на установку FastCGI для PHP (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>

Нашел ответ по адресу: 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>

Во-первых, ваш сценарий-оболочка и установка плохо спланированы, если только документы Apache не устарели. Прочтите «Особые соображения по PHP» в mod_fcgid документы и используйте там скрипт и пример настроек. Ваша текущая настройка будет в основном порождать кучу непригодных для использования дочерних процессов php, тогда каждый 5001-й запрос PHP будет вызывать ошибку, поскольку PHP выйдет после 5000-го запроса, но вам не хватает FcgidMaxRequestsPerProcess 5000 директива, которая сообщает mod_fcgid, что ему нужно будет запустить новый процесс PHP после 5000 запросов.

Что касается одновременных процессов PHP, каждый одновременный запрос требует своего собственного процесса PHP, поэтому вам нужно будет увеличить FcgidMaxProcessesPerClass директива на большее число.