Um único processo php-fastcgi bloqueia todas as outras solicitações PHP

6

Eu recentemente mudei para uma configuração do FastCGI para PHP (Apache2-worker e mod_fcgid ). No entanto, quando um único script PHP está muito ocupado, parece bloquear todas as outras solicitações do PHP. O que estaria errado com minha configuração?

Meu principal motivo para usar mod_fcgid é manter o uso de memória do PHP sob controle. Com mod_php , todos os garfos individuais do Apache crescem em memória depois de servir PHP.

Eu também mudei para o modelo apache2-worker, já que existe todo código PHP inseguro para threads fora do Apache.

Meu script FastCGI se parece com:

#!/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"

Minha configuração do Apache é assim:

<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>
    
por vdboor 21.08.2011 / 17:45

2 respostas

3

Encontrou a resposta em: link

O problema não é PHP, mas mod_fcgid. Enquanto o PHP gera múltiplos filhos, mod_fcgid é ignorante, e servirá um pedido por criança. Portanto, quando FcgidMaxProcessesPerClass 1 é usado, toda a execução do PHP acontece após o outro. *

A solução apresentada em links para: link explica como usar mod_fastcgi que não tem essa limitação. Ele enviará várias solicitações para o mesmo filho.

[*] Note que não usar FcgidMaxProcessesPerClass 1 resulta em muitas instâncias separadas de PHP, Ruby, etc., enquanto todas elas são capazes de processar muitos pedidos internamente em um único processo.

Daí uma nova configuração do Apache para usar o PHP com o 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>
    
por 26.08.2011 / 01:07
1

Primeiro, o script e a configuração do wrapper são Just Plan Wrong de uma maneira ruim, a menos que os documentos do Apache estejam desatualizados. Leia as "Considerações Especiais do PHP" nos documentos do mod_fcgid e use o script e as configurações de exemplo. Sua configuração atual basicamente gerará um monte de processos filhos php inutilizáveis, então cada 5001 requisição PHP irá errar já que o PHP irá sair após o 5000º pedido, mas você está perdendo a diretiva FcgidMaxRequestsPerProcess 5000 que informa ao mod_fcgid que ele precisará iniciar um novo processo PHP após 5000 solicitações.

Quanto aos processos PHP simultâneos, cada solicitação simultânea requer seu próprio processo PHP, portanto, você precisará aumentar sua diretiva FcgidMaxProcessesPerClass para um número maior.

    
por 21.08.2011 / 21:14