Sinopse
Eu observei o mesmo comportamento com o Apache; parece que esse problema não é específico para o lighttpd.
No meu caso, os sintomas eram exatamente os mesmos; os logs de acesso do Apache foram salpicados com códigos de resposta intermitentes 500, e não havia entradas correspondentes no log de erros do PHP (e o relatório de erros do PHP foi configurado para ser detalhado ao máximo).
Eu descrevi o problema extensivamente na lista de discussão do Apache (pesquise os arquivos da lista pelo assunto "Intermitente 500 respostas no access.log sem as entradas correspondentes no error.log").
Causa Raiz
A resposta do 1100110 sugere a causa raiz, mas fornecerei documentação adicional, diretamente do Apache, bem como sugestões para eliminar o problema.
Aqui está a palavra oficial do Apache sobre este assunto:
link :
Special PHP considerations
By default, PHP FastCGI processes exit after handling 500 requests, and they may exit after this module has already connected to the application and sent the next request. When that occurs, an error will be logged and 500 Internal Server Error will be returned to the client. This PHP behavior can be disabled by setting PHP_FCGI_MAX_REQUESTS to 0, but that can be a problem if the PHP application leaks resources. Alternatively, PHP_FCGI_MAX_REQUESTS can be set to a much higher value than the default to reduce the frequency of this problem. FcgidMaxRequestsPerProcess can be set to a value less than or equal to PHP_FCGI_MAX_REQUESTS to resolve the problem.
PHP child process management (PHP_FCGI_CHILDREN) should always be disabled with mod_fcgid, which will only route one request at a time to application processes it has spawned; thus, any child processes created by PHP will not be used effectively. (Additionally, the PHP child processes may not be terminated properly.) By default, and with the environment variable setting PHP_FCGI_CHILDREN=0, PHP child process management is disabled.
The popular APC opcode cache for PHP cannot share a cache between PHP FastCGI processes unless PHP manages the child processes. Thus, the effectiveness of the cache is limited with mod_fcgid; concurrent PHP requests will use different opcode caches.
Lá nós temos isso.
Soluções possíveis
Opção 1
Uma solução é definir PHP_FCGI_MAX_REQUESTS como zero, mas essa medida introduz o potencial de vazamentos de memória para crescer fora de controle.
Os vários pedaços de documentação que consultei não deixam claro se o PHP via Fast-CGI sofre de vazamento inerente de memória (daí o comportamento de "reciclagem de processo") ou se o risco é limitado a um mau desempenho. scripts escritos, "fugitivos".
Em qualquer caso, existe o risco inerente de definir PHP_FCGI_MAX_REQUESTS como zero, especialmente em um ambiente de hospedagem compartilhada.
Opção 2
Uma segunda solução, conforme descrito no trecho acima, é definir FcgidMaxRequestsPerProcess como um valor menor ou igual a PHP_FCGI_MAX_REQUESTS. A documentação omite um ponto importante, no entanto: o valor também deve ser maior que zero (porque zero significa "ilimitado" ou "desativa a verificação" neste contexto). Dado que o valor padrão para FcgidMaxRequestsPerProcess é zero, e o valor padrão para PHP_FCGI_MAX_REQUESTS é 500, qualquer administrador que não tenha sobrescrito esses valores experimentará os 500 códigos de resposta intermitentes. Por esse motivo, não consigo entender por que FcgidMaxRequestsPerProcess e PHP_FCGI_MAX_REQUESTS não compartilham o mesmo valor padrão. Talvez isso aconteça porque configurar essas duas diretivas como tal produz o mesmo resultado líquido que definir PHP_FCGI_MAX_REQUESTS como zero; a documentação é ambígua a esse respeito.
Opção 3
Uma terceira solução é abandonar totalmente a Fast-CGI, em favor de uma alternativa comparável, como suPHP ou antigo CGI + SuExec. Realizei alguns benchmarking de desempenho básico e bruto em vários modos do PHP, e minhas descobertas são as seguintes:- Mod-PHP 77.7
- CGI 69,0
- suPHP 67,0
- Fast-CGI 55.7
O Mod-PHP é o de maior desempenho, com uma pontuação de 77,7. As pontuações são arbitrárias e servem apenas para demonstrar a variação relativa nos tempos de carregamento da página nos modos PHP.
Se assumirmos que esses benchmarks são bastante representativos, então parece haver muito poucas razões para se agarrar à Fast-CGI, dada essa falha (bastante séria) em sua implementação. A única razão substancial que vem à mente é o cache de código operacional. Meu entendimento é que o PHP não pode utilizar o cache de código operacional através do modo CGI ou suPHP (porque os processos não persistem entre as solicitações).
Enquanto a Fast-CGI não tira proveito do cache de op-code (por exemplo, via APC), usuários inteligentes criaram um método para tornar a APC efetiva com Fast-CGI (via caches por usuário ): link . Existem várias desvantagens, no entanto:- Os requisitos de memória (RAM) são consideráveis, pois há um cache dedicado para cada usuário. (Para perspectiva, considere que no modo Mod-PHP, todos os usuários compartilham um único cache.)
- O Apache deve usar o módulo mais antigo, mod_fastcgi, em vez do equivalente mais novo, mod_fcgid. (Para detalhes, veja o artigo citado no parágrafo acima).
- A configuração é bastante complexa.
Como corolário relacionado, você disse o seguinte em sua pergunta:
First I am using APC so PHP is in control of it's own processes, not FastCGI.
A menos que você esteja usando o mod_fastcgi (e não o mod_fcgid), e a menos que você tenha seguido etapas similares às citadas alguns parágrafos acima, a APC está consumindo recursos sem efeito. Como tal, você pode querer desativar o APC.
Resumo da Solução
Tome uma das três medidas a seguir:
- Defina a variável de ambiente PHP_FCGI_MAX_REQUESTS para zero. (Introduz o potencial de vazamentos de memória em scripts PHP para crescer fora de controle).
- Defina FcgidMaxRequestsPerProcess como um valor menor ou igual a PHP_FCGI_MAX_REQUESTS, mas maior que zero.
- Abandone o Fast-CGI em favor de uma alternativa comparável, como suPHP ou antigo CGI + SuExec.