Como impedir que o Apache trave todo o meu servidor?

6

Eu mantenho um servidor Gentoo com alguns serviços, incluindo o Apache. É bastante low-end (2GB de RAM e um processador de baixo custo com 2 núcleos). Meu problema é que, apesar dos meus esforços, um Apache sobrecarregado trava todo o servidor. Na verdade, neste ponto, estou perto de estar convencido de que o Linux é um sistema operacional horrível que não vale a pena nem pensar em estabilidade sob carga.

Coisas que tentei:

  1. Ajustando oom_adj para o processo raiz do Apache (e, portanto, todos os seus filhos). Isso quase não teve efeito. Quando o Apache estava sobrecarregado, isso traria o sistema a um nível, já que o sistema paginava todo o resto antes de matar qualquer coisa.
  2. Desativando o swap. Não ajudou, seria descarregar a memória paginada para binários de processos e outros arquivos em /, causando o mesmo efeito.
  3. Colocando-o em um cgroup limitado por memória (limitado a 512 MB de RAM, 1/4 do total). Isso "funcionou", pelo menos nos meus próprios testes de estresse - exceto que o servidor fica travando sob carga (basicamente atrasando todos os outros processos, inacessíveis via SSH, etc.)
  4. Execução com prioridade de E / S inativa. Esta não foi uma boa idéia no final, porque apenas fez com que a carga do sistema subisse indefinidamente (aos milhares) quase sem efeito visível - até que você tentasse acessar uma parte sem buffer do disco. Isso causou a tarefa de congelar. (Tanto para um bom agendamento de I / O, eh?)
  5. Limitando o número de conexões simultâneas ao Apache. Configurar o número muito baixo fez com que os sites deixassem de responder, pois a maioria dos slots estava ocupada com solicitações longas (downloads de arquivos).
  6. Eu tentei vários MPMs do Apache sem muito sucesso (prefork, event, itk).
  7. Mudando de prefork / event + php-cgi + suphp para itk + mod_php. Isso melhorou o desempenho, mas não resolveu o problema real.
  8. Alternando planejadores de E / S (cfq para prazo).

Só para enfatizar isso: eu não me importo se o próprio Apache fica sob carga, eu só quero que o resto do meu sistema permaneça estável. É claro, ter o Apache recuperado rapidamente após um breve período de carga intensiva seria ótimo, mas um passo de cada vez.

Neste momento, estou muito perplexo com a forma como a humanidade, nos dias de hoje, pode projetar um sistema operacional onde uma tarefa aparentemente simples (não permitir que um componente do sistema trava todo o sistema) parece praticamente impossível - ou menos, muito difícil de fazer.

Por favor, não sugira coisas como VMs ou "COMPRE MAIS RAM".

Mais algumas informações reunidas com a ajuda de um amigo: Os processos interrompem quando o cgroup oom killer é invocado. Aqui está o rastreamento de chamadas:

[<ffffffff8104b94b>] ? prepare_to_wait+0x70/0x7b
[<ffffffff810a9c73>] mem_cgroup_handle_oom+0xdf/0x180
[<ffffffff810a9559>] ? memcg_oom_wake_function+0x0/0x6d
[<ffffffff810aa041>] __mem_cgroup_try_charge+0x32d/0x478
[<ffffffff810aac67>] mem_cgroup_charge_common+0x48/0x73
[<ffffffff81081c98>] ? __lru_cache_add+0x60/0x62
[<ffffffff810aadc3>] mem_cgroup_newpage_charge+0x3b/0x4a
[<ffffffff8108ec38>] handle_mm_fault+0x305/0x8cf
[<ffffffff813c6276>] ? schedule+0x6ae/0x6fb
[<ffffffff8101f568>] do_page_fault+0x214/0x22b
[<ffffffff813c7e1f>] page_fault+0x1f/0x30

Neste ponto, o cgroup de memória do apache está praticamente travado e queima a CPU em syscalls (todos com o rastreamento de chamada acima). Isto parece ser um problema na implementação do cgroup ...

    
por Vladimir Panteleev 11.12.2010 / 05:56

6 respostas

7

Eu odeio dizer isso, mas você parece estar fazendo a pergunta errada.

Não se trata de impedir que o Apache derrube seu servidor, mas sim que o seu servidor da Web forneça mais consultas por segundo - o suficiente para que você não tenha problemas. Uma parte da resposta à questão reformulada é então limitar o Apache para que ele não trave em altas cargas.

Para a segunda parte, o Apache tem alguns limites que você pode definir - MaxClients sendo uma configuração importante. Isso limita o número de crianças que podem ser executadas. Se você pode descarregar o Apache para processos de execução longa (arquivos grandes sendo baixados, por exemplo), esse é outro slot do Apache para poder servir o PHP. Se os downloads de arquivos precisarem ser verificados pela camada PHP, eles ainda poderão fazer isso e passar de volta para um servidor da Web mais otimizado para o conteúdo estático, como NginX sendfile

Enquanto isso, o uso do Apache em todos os pedidos para a maneira mais lenta de executar o PHP - como um CGI (qualquer que seja o apache MPM que você esteja usando) - também faz com que a máquina gaste muito tempo sem executar seu código. O mod_php é significativamente mais otimizado.

O PHP pode fazer grandes quantidades de tráfego quando o Apache e a camada do PHP são apropriadamente otimizados. Ontem, 11 de dezembro de 2010, por exemplo, o par de servidores PHP que eu executei fez quase 19 Milhões de acessos no período de 24 horas, e a maior parte no período de tempo das 7h às 20h.

Há muitas outras questões aqui, e artigos em outros lugares sobre como otimizar o Apache e PHP, eu acho que você precisa lê-los primeiro, antes de culpar o Linux / Apache & PHP.

    
por 12.12.2010 / 19:07
4

Quando você está lidando com um servidor apache de produção, você DEVE ter um tamanho médio de processo, especialmente com php, eu recomendo que você:

  • Verifique o consumo de memória de suas médias de processo
  • Ajuste MaxClients para AVERAGE_MEMORY / RAM_DEDICATED_TO_APACHE

Onde RAM_DEDICATED_TO_APACHE deve ser outra estimativa do TOTAL_RAM menos o ram que precisa do resto da máquina (e seja generoso com o banco de dados se você está executando um na mesma máquina).

Eu realmente recomendo que você use Verniz , você pode facilmente executar 2 servidores em portas diferentes na máquina de salvamento e rotear os arquivos estáticos para um servidor de arquivo (mídia) especializado (lighthttpd, nginx) ou uma instância do apache com o worker e nenhum módulo extra. E, claro, pegar o conteúdo estático com verniz.

Dividir a carga é importante porque você estará usando a mesma quantidade de memória RAM para entregar qualquer arquivo estático (que precisa de menos de 1 MB) se você não faça isso.

Se você realmente precisa se certificar de nunca consumir todo o aríete, você pode instalar um novo cronjob rodando a cada 2 minutos (menos ou mais como você considera) com a seguinte linha, ajustando o 50 para qualquer valor do menor ram e mantenha esse número acima de 30 pelo menos; você precisará de um pouco de memória para parar o servidor.

vmstat -S M | tail -n 1 | awk 'BEGIN{ "date" | getline date }{if($4 + $6 < 50){ system("/etc/init.d/httpd stop"); system("/etc/init.d/httpd start"); print "Rebooting apache  on " date >> "/var/log/apache-reboots.log"}}'

Este é um modo muito sujo (sujo) de limitar você, mas pode ser muito útil quando você não tem certeza sobre sua memória média por processo de apache, e se você ver várias reinicializações em seu arquivo de log ("/var/log/apache-reboots.log"), você deve ajustar seu apache MaxClients , MaxRequestsPerChild , ThreadsPerChild para evitar futuros hard-reboots, com o tempo e tunning, você terá a configuração exata para o seu servidor.

    
por 13.12.2010 / 21:09
1

Algumas coisas gerais que você pode tentar:

  • É difícil dizer a partir de sua descrição se o Apache / Linux está realmente travando ou apenas ficando gravemente sobrecarregado. Eu suspeito que você tenha apenas um servidor que tenha uma carga tão alta que o único curso de ação efetivo é desligar a energia. Eu abordaria o problema como um servidor sobrecarregado, a menos que haja uma evidência específica de uma falha real. Se você otimizar o desempenho do servidor, mas ainda assim falhar, poderá trabalhar para encontrar e resolver esse problema.
  • Você geralmente nunca deseja que seu servidor receba uma condição de que ele acesse a troca regularmente, especialmente quaisquer instâncias do Apache. Você pode rapidamente entrar em uma situação de carga de fuga onde o servidor está funcionando bem, mas quando o tráfego aumenta alguns por cento, ele começa a usar a troca e a carga de foguetes do céu fazendo com que o site seja lento ou inacessível. Para evitar que o Apache use o swap, reduza o número de clientes / conexões máximas e / ou reduza o uso da memória, desabilitando quaisquer módulos que não sejam necessários. Veja também o próximo ponto.
  • Você menciona que as conexões no Apache estão sendo usadas por solicitações longas, como downloads de arquivos. Para ajudar a reduzir esse problema, você pode usar uma segunda configuração de servidor da Web (como lighttp) para atender apenas a conteúdo estático, com o qual o Apache encaminha / redireciona solicitações para ele. Isso libera conexões no Apache para fazer o trabalho pesado e permite reduzir o número de clientes / conexões máximas.
  • Se você precisar impedir um DoS, seja de propósito ou acidental, existem vários módulos do Apache que podem ser instalados e configurados. Eu usei mod_evasive e mod_limitipconn por exemplo, que funcionou bem o suficiente para evitar os tipos menos maliciosos de DoS.
  • Não descarte a otimização do Apache ou de outras partes do sistema operacional ou do aplicativo. Os computadores são muito bons em fazer exatamente o que você diz a eles, portanto, se as configurações do Apache dizem "use mais recursos do que esse servidor", ele fará exatamente isso. Como um monte de software, o Apache deve funcionar bem com uma enorme variedade de hardware e aplicativos, mas precisa ser configurado corretamente para ambos. A configuração padrão só funciona bem para um site simples e com baixo tráfego.
  • Com um pouco de ajuste, você deve conseguir encontrar um equilíbrio em que o servidor receba uma carga alta, mas ainda assim seja responsivo o suficiente para efetuar login e verificar. Neste ponto, suas opções são para criar perfis e otimizar o aplicativo, incluindo a adição de camadas de armazenamento em cache ou obter um hardware melhor. Esta etapa deve ser depois de obter a configuração do Apache corretamente.
por 12.12.2010 / 16:51
1

Você já tentou mudar / proc / sys / vm / overcommit_memory para 2? Isso significa que o kenel não alocará mais memória do que swap + uma porcentagem configurável (proc / sys / vm / overcommit_ratio) de memória RAM disponível.

No caso do Apache falhar, uma vez que não é possível alocar o RAM, mas os serviços já carregados, como o openSSH, continuarão funcionando.

Devo acrescentar que nunca tentei isso e descobri essa configuração agora. Eu adoraria ouvir de qualquer um que saiba mais. Caso contrário, testarei isso amanhã, pois tenho exatamente o mesmo problema descrito na pergunta.

    
por 13.12.2010 / 00:02
1

Eu encontrei o problema ...

A configuração de oom_adj para 15 para todo o cgroup limitado por memória mostrou ser muito estúpido. A pontuação ajustada de todos os processos no cgroup acabou sendo todos 1000 - então, quando o cgroup ficou sem memória, o sistema matou processos aleatórios e geralmente se comportou mal.

Eu não tive nenhum travamento do sistema depois de simplesmente remover a linha que definiu oom_adj .

    
por 13.01.2011 / 07:36
0

isso pode ser um pouco tarde, mas posso dizer que culpar o SO simplesmente não é o caminho a ser seguido. o sistema operacional é projetado para atender às expectativas de vários cenários de casos de uso diferentes, portanto, você DEVE configurá-lo para atender aos seus requisitos.

Não só isso, mas se você está tendo tanta carga que o sistema está falhando, então você tem que otimizar seu sistema, ou expandir sua rede.

Embora otimizar muito cedo possa tornar as coisas dolorosas mais tarde, não otimizar nada desde o início pode ter as mesmas consequências. é tudo sobre equilíbrio.

No entanto, você afirma que seu objetivo é evitar que o sistema falhe ... mas, em seguida, prossiga dizendo que suas soluções não funcionaram. mas alguns deles fizeram funcionar, você simplesmente não ficou satisfeito com os resultados.

quando você fica sem memória, você troca. ou coisas quebram. fim da história . se você não quiser trocar, você precisa:

a) limit your incoming connections. this has the effect of either turning people away

b) send them to the backlog. which has the effect of causing the site to slow, or die.

c) buy more memory. which you did not want to do

d) scale your network. which you also did not want to do

e) load balance. which is much like 'D'

sem otimização cuidadosa, ajuste fino e expansão ... você não pode evitar que todas essas coisas aconteçam.

na minha experiência, aprendi que, ao usar uma combinação granular de todas as coisas geralmente causadas acima, funcionou no final.

primeiro, uso apache2 + mpm_event + mod_fcgid . Eu cuidadosamente configurei praticamente todas as opções possíveis que o apache precisa configurar. isso pode levar uma noite para fazer e outra para acertar. mas valerá a pena.

Eu garantiria que sempre houvesse um grupo de trabalhadores pronto para lidar com conexões de entrada e deixá-lo crescer, mas restringiria esse pool a um limite razoável. isso pode sacrificar alguma velocidade, mas resulta em estabilidade.

segundo, eu uso os dois CGroups and IO Priority / CPU Priotiy para agendar diferentes grupos de serviços para diferentes prioridades.

tudo o que é 100% crítico, o qual eu sempre preciso acessar, eles são reservados com um bloco de memória e são configurados com uma maior prioridade de I / O e de CPU. Eu prepararia um roteiro que define essas prioridades a cada hora, de modo que as crianças herdem essas prioridades se o pai delas mudar.

em seguida vem o DNS, depois a Web e depois o Mail. nesta ordem. Desta forma, se algo está se comportando mal, elementos mais críticos são favorecidos.

usando monitor software, verificar se as coisas estão online, e se não, reinicie-as. se alguma coisa estiver usando mais de X MB de memória, para X Cycles ... e você não puder se conectar ao serviço (ou seja, em http://...:80 ), elimine o serviço e reinicie-o. se ele reiniciar mais de X vezes em X ciclos, limite (e notifique para inspeção manual). você pode derrubar alguns usuários ocasionalmente, mas pelo menos o seu sistema permanece estável!

em terceiro lugar, se você tiver um servidor dedicado, o ID colocará todos os serviços do site em separate disk . manter operações de IO principalmente sobre um controlador diferente.

quarta, confira os módulos do apache como mod_bw e mod_qos . mod_bw pode fazer mais do que apenas limitar a largura de banda por virtualhost, e mod_qos ... este é um módulo de qualidade de serviço que pode ajudar a mitigar alguns problemas.

Além do que você esperaria de um módulo QoS completo, ele pode ajudar com coisas como DoS evitando slowdos, limitando conexões NULL, e pode até desativar keepalive quando o servidor atingir um certo limite de conexões simultâneas.

finalmente, eu configuraria alguns intelligent caching front ends ou load balancer . por exemplo: usando algumas instâncias de VM, talvez use Varnish ou NGinx, armazene em cache os arquivos estáticos do desenvolvedor. isso descarregará todos os slots abertos que o Apache exige para servir esse conteúdo estático.

Eu realmente não tenho certeza do que você espera que aconteça quando você recebe muito tráfego. Você quer que ambos permaneçam estáveis, mas você não quer perder nenhuma funcionalidade sob estresse, e você não quer otimizar nada, e você não quer atualizar ou estender sua rede?

bem, se você não quiser MUDAR nada, como você espera que o problema desapareça?

    
por 07.07.2014 / 12:50