Erro HTTP 503. Serviço indisponível: um caso no suporte de hospedagem

O trabalho no suporte de hospedagem é basicamente o mesmo, a maioria das solicitações dos clientes é resolvida de acordo com um esquema bem desenvolvido, mas às vezes você ainda precisa enfrentar problemas não triviais. Então, a principal tarefa do engenheiro é encontrar o único caminho correto que levará à sua solução. Neste artigo, quero falar sobre como encontramos o erro flutuante "Erro HTTP 503. Serviço indisponível" em nossa hospedagem compartilhada, como tentamos pegá-lo, diagnosticá-lo e ter um final inesperado.



Começar



A hospedagem fornece aos usuários uma pilha típica Linux + Apache + Mysql + PHP e um wrapper de gerenciamento. No nosso caso, esse é um negócio do ISP Manager 5 baseado no Centos 7 com conversão para CloudLinux. Do lado administrativo, o CloudLinux fornece ferramentas para gerenciar limites, além de um seletor de PHP com vários modos de operação (CGI, FastCGI, LSAPI).



Desta vez, um cliente entrou em contato conosco com o seguinte problema. Seu site no mecanismo do Wordpress periodicamente começou a dar 503 erros, sobre os quais ele nos informou.



Os códigos de resposta que começam com 50x referem-se a problemas do lado do servidor. Podem ser problemas do site em si e do servidor da web que os atende.



Situações típicas nas quais recebemos os seguintes erros:



  • Erro interno do servidor 500 - geralmente está associado a erros de sintaxe no código do site ou a bibliotecas ausentes / versão PHP não suportada. Também pode haver problemas com a conexão ao banco de dados do site ou permissões incorretas em arquivos / diretórios
  • 502 Gateway incorreto - por exemplo, se Nginx se referir à porta errada do servidor Apache, ou o processo Apache parar de funcionar por algum motivo
  • 504 Tempo limite do gateway - a resposta do Apache não foi recebida dentro do tempo especificado na configuração do servidor da web
  • 508 Limite de recursos atingido - o limite de recursos alocados ao usuário foi excedido


Esta lista contém apenas alguns dos casos mais comuns. Também é importante notar que, quando os limites são excedidos, o usuário pode receber os erros 500 e 503.



Ao diagnosticar esses erros, a primeira etapa é verificar os logs do servidor web. Isso geralmente é suficiente para identificar o culpado e corrigir o problema.



Em relação ao erro 503 no nosso caso, vimos uma entrada nos logs:

[lsapi: error] [pid 49817] [client xxxx: 6801] [host XXX.XX] Erro ao enviar solicitação (GET /index.php HTTP / 1.0); uri (/index.php) conteúdo-comprimento (0): ReceiveAckHdr: nada para ler do back-end (LVE ID 8514), consulte docs.cloudlinux.com/mod_lsapi_trou Troubleshooting.html
Com base apenas nesse log, não foi possível determinar qual seria o problema.



Diagnóstico primário



Inicialmente, verificamos as estatísticas do usuário excedendo os limites. Os excessos menores foram registrados nos dias anteriores, mas os erros nos logs foram atualizados; além disso, eles apareceram no log em intervalos de um a vários minutos.



Também estudamos as recomendações do CloudLinux usando o link fornecido nos logs de erros.

Alterar qualquer parâmetro não trouxe nenhum resultado.



O site usou um banco de dados em um servidor Mysql 5.7 que é executado no mesmo servidor em um contêiner do Docker. Os logs do contêiner continham mensagens:



[Note] Aborted connection 555 to db: 'dbname' user: 'username' host: 'x.x.x.x' (Got an error reading communication packets)


Entre essas mensagens, havia mensagens sobre a conexão interrompida do site sob investigação. Isso pressupunha que a conexão com o DBMS não está sendo executada corretamente. Para verificar, implantamos uma cópia do site em um domínio de teste, convertemos o banco de dados do site na versão nativa do Centos 7 do DBMS 5.5.65-MariaDB. No site de teste, várias centenas de solicitações foram executadas usando o utilitário curl. O erro não pôde ser reproduzido. Mas esse resultado foi preliminar e após a conversão do banco de dados no local de produção, o problema permaneceu.



Assim, o problema de conexão incorreta com o DBMS foi eliminado.



A próxima sugestão foi verificar se havia algum problema com o próprio site. Para fazer isso, configuramos um servidor virtual separado, nele criamos o ambiente mais semelhante. A única diferença significativa é a falta do CloudLinux. O problema não pôde ser reproduzido no servidor de teste. Portanto, determinamos que tudo está em ordem no código do site. No entanto, tentamos desativar os plugins do Wordpress da mesma maneira, mas o problema persistiu.



Como resultado, chegamos à conclusão de que o problema está em nossa hospedagem.



Após analisar os logs de outros sites, verificou-se que o problema é observado em muitos deles. Cerca de 100 peças. no momento da verificação:



/var/www/httpd-logs# grep -Rl "ReceiveAckHdr: nothing to read from backend" ./ | wc -l
99


Durante o teste, descobrimos que o CMS Wordpress limpo recém-instalado também fornece periodicamente o erro 503.



Aproximadamente 2 meses antes disso, realizamos trabalhos de modernização do servidor, em particular, alteramos o modo de operação Apache de Worker para Prefork, para poder usar o PHP no LSAPI em vez de CGI lento. Havia uma suposição de que isso poderia afetar ou algumas configurações adicionais do Apache são necessárias, mas não foi possível retornar o modo de trabalho novamente. Durante a alteração do modo operacional Apache, todas as configurações do site são alteradas, o processo não é rápido e nem tudo pode ocorrer sem problemas.



A correção das configurações do Apache também não deu o resultado desejado.



Ao longo do caminho, procuramos problemas semelhantes nos mecanismos de pesquisa. Em um dos fóruns, os participantes argumentaram que o hoster tem um problema e precisa ser alterado se o problema não for resolvido. Não parece muito otimista quando você está do outro lado, mas pode entender o cliente. Por que ele precisa de hospedagem que não funciona?



Nesta fase, coletamos as informações disponíveis e os resultados do trabalho realizado. Eles foram contatados para dar suporte ao CloudLinux.



Diagnóstico detalhado



Por vários dias, a equipe de suporte do CloudLinux investigou o problema. Basicamente, as recomendações foram relativas aos limites estabelecidos para o usuário. Também checamos esta questão. Com os limites desativados (opção CageFS para o usuário) e com os limites ativados no modo PHP como um módulo Apache, o problema não foi observado. Com base nisso, foi sugerido que o CloudLinux está influenciando de alguma forma. Como resultado, até o final da semana, a solicitação foi encaminhada para o terceiro nível de suporte, mas ainda não havia solução.



No caminho, estudamos a documentação do Apache nos modos CGI e LSAPI, configuramos uma segunda instância do Apache no servidor de hospedagem em uma porta diferente com um site de teste, eliminamos a influência do Nginx enviando solicitações diretamente ao Apache e recebendo os mesmos códigos de erro.



A documentação do LSAPI ajudou a decolar, apenas com o diagnóstico de erros 503:

www.litespeedtech.com/support/wiki/doku.php/litespeed_wiki : php: 503-errors

Na seção Solução de problemas avançados, propõe-se rastrear os processos encontrados no sistema:



while true; do if mypid=`ps aux | grep $USERNAME | grep lsphp | grep $SCRIPTNAME | grep -v grep | awk '{print $2; }' | tail -1`; then strace -tt -T -f -p $mypid; fi ; done


O comando foi refinado para registrar todos os processos em arquivos com seus identificadores.



Ao examinar os arquivos de rastreamento, vemos algumas das mesmas linhas:



cat trace.* | tail
...
47307 21:33:04.137893 --- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=42053, si_uid=0} ---
47307 21:33:04.140728 +++ killed by SIGHUP +++
...


Se olharmos para a descrição da estrutura dos sinais enviados pelos processos, veremos que



pid_t    si_pid;       /* Sending process ID */


Indica o identificador do processo que enviou o sinal.



No momento de estudar os traços, o processo com o PID 42053 não está mais no sistema, portanto, no processo de captura de traços, decidimos monitorar os processos que também enviavam o sinal SIGHUP.

Sob o spoiler, são descritas ações que tornaram possível determinar que tipo de processo é, além de obter seu rastreio e informações adicionais sobre para quais processos ele envia o sinal SIGHUP.



Técnica de rastreamento
Console 1.



tail -f /var/www/httpd-logs/sitename.error.log


2.



while true; do if mypid=`ps aux | grep $USERNAME | grep lsphp | grep "sitename" | grep -v grep | awk '{print $2; }' | tail -1`; then strace -tt -T -f -p $mypid -o /tmp/strace/trace.$mypid; fi ; done


3.



while true; do if mypid=`cat /tmp/strace/trace.* | grep si_pid | cut -d '{' -f 2 | cut -d'=' -f 4 | cut -d',' -f 1`; then ps -aux | grep $mypid; fi; done;


4.



seq 1 10000 | xargs -i sh -c "curl -I http://sitename/"


1 , 4 503, 4.



Como resultado, obtivemos o nome do processo /opt/alt/python37/bin/python3.7 -sbb /usr/sbin/cagefsctl --rebuild-alt-php-ini



, que foi realizado no sistema uma vez por minuto.



Rastreamos vários processos cagefsctl para rastrear pelo menos um do início ao fim:



for i in `seq 1 100`; do strace -p $(ps ax | grep cagefsctl | grep rebuild-alt-php-ini | grep -v grep | awk '{print $1}') -o /tmp/strace/cagefsctl.trace.$(date +%s); done;


A seguir, estudamos o que ele fez, por exemplo:



cat /tmp/strace/cagefsctl.trace.1593197892 | grep SIGHUP


Também foram obtidas IDs de processo que foram finalizadas com um sinal SIGHUP. Os processos finalizados foram os processos PHP atualmente em execução.



Os dados recebidos foram transferidos para o suporte do CloudLinux, a fim de esclarecer a legitimidade desse processo e se ele deve funcionar com essa frequência.



Posteriormente, recebemos uma resposta de que o trabalho da equipe /usr/sbin/cagefsctl --rebuild-alt-php-iniestá sendo realizado corretamente, a única ressalva é que a equipe está sendo executada com muita frequência. Normalmente chamado quando uma atualização do sistema ou configurações do PHP são alteradas.



A única pista que resta neste caso é verificar quem é o pai do processo cagefsctl.



O resultado não demorou a chegar e qual foi a nossa surpresa - o processo pai para cagefsctl foi o processo ispmgrnode. Foi um pouco estranho, porque o nível de log do ISP Manager foi definido no máximo e a chamada cagefsctl não foi vista no ispmgr.log.



Agora havia dados suficientes para entrar em contato com o suporte do sistema ISP também.



Resultado



O problema foi acionado após a execução de uma atualização do ISP Manager. Em geral, a atualização do ISP Manager é uma situação normal, mas levou ao início do processo de sincronização, que terminou com um erro e foi reiniciado a cada minuto. O processo de sincronização invocou o processo cagefsctl, que por sua vez finalizou os processos PHP.



O motivo do desligamento do processo de sincronização foi o trabalho realizado na hospedagem para modernizar o equipamento. Alguns meses antes do problema ocorrer, uma unidade PCI-e NVMe foi instalada no servidor, uma partição XFS foi criada e montada no diretório / var. Os arquivos dos usuários também foram transferidos para ele, mas as cotas de disco não foram atualizadas. As opções de montagem não eram suficientes, também era necessário alterar o tipo de sistema de arquivos nos parâmetros do ISP Manager, pois ele chama comandos para atualizar cotas de disco. Para Ext4 e XFS, esses comandos são diferentes.



Assim, o problema se fez sentir vários meses após o trabalho.



conclusões



Nós mesmos criamos o problema, mas não ficou claro até o último momento. Para o futuro, tentaremos levar em consideração o maior número possível de nuances. Com a ajuda de colegas mais treinados do CloudLinux e do suporte do ISP System, o problema foi resolvido. Agora nossa hospedagem é estável. E ganhamos experiência que será útil para nós em trabalhos futuros.



PS: Espero que você esteja interessado em ler o artigo, e isso ajudará alguém a resolver rapidamente um problema semelhante.



All Articles