Tunando o Apache 1.3.x ou 2.x (prefork)

Depois de apanhar muito de servidores web lotados com centenas de requisições simultâneas, resolvi dar uma pesquisada na net para entender os motivos da baixa performance e solucionar definitivamente o problema. O intuito não era criar um cluster com vários servidores respondendo pelo mesmo nome, mas aproveitar ao máximo os recursos de um servidor.

[ Hits: 37.556 ]

Por: marco aurelio caldas miranda em 17/02/2007 | Blog: http://maurelio.net


Introdução



Depois de apanhar muito de servidores web lotados com centenas de requisições simultâneas, resolvi dar uma pesquisada na net para entender os motivos da baixa performance e solucionar definitivamente o problema.

O intuito não era criar um cluster com vários servidores respondendo pelo mesmo nome, mas aproveitar ao máximo os recursos de um servidor. Vou relatar aqui as configurações que considero mais importantes, ou seja, as que produziram melhorias perceptíveis. Não vou entrar na discussão de qual o interpretador é mais eficiente (php , python, perl ou afins). Use ao seu gosto.

Um fator de extrema importância para um servidor web é a frequência com que ele utiliza swap. Devido a natureza do serviço, espera-se sempre uma resposta rápida do servidor e o processo de swap é um fator altamente degradante para o tempo de resposta. Quando a memória física (RAM) se esgota, o sistema operacional salva algumas informações pouco acessadas da memória no disco rígido em um processo denominado troca ou swap. Esse processo, apesar de necessário, não deve ser utilizado com frequência, pois a leitura e a escrita no disco são de 10 a 100 vezes mais lentas do que na RAM, dependendo da máquina. Por isso devemos dimensionar o servidor web baseado exclusivamente na quantidade de memória RAM.

Façamos a seguinte conta:

Quantidade de memória RAM total - (menos) Quantidade de memória ocupada por programas quando o servidor web está desligado.

Agora vamos dividir o resultado pela quantidade média de memória ocupada por um processo filho do Apache (em torno 3M quando utiliza-se html puro, sem nenhuma linguagem interpretada e em torno de 20M para html+php) - você pode utilizar o "top" para descobrir esse valor.

O resultado obtido da divisão anterior deve ser o número máximo de clientes que seu host pode atender simultaneamente sem utilizar swap. Não se espante se o número for baixo (20, 30, 50,..). Mais adiante vamos fazer algumas contas que vão mostrar quantas requisições o seu servidor pode atender por minuto. Coloque este número como o valor MaxClients do Apache.

Se o seu host trabalha sempre perto da capacidade máxima, configure o valor do StartServers, MinSpareServers e MaxSpareServers próximo ao valor do MaxClients (ex:80%), se não você pode trabalhar com um valor perto de 50% ou menos. Perceba que não há razão para utilizar valores de StartServers e MinSpareServers diferentes, já que o serviço vai iniciar com o número de processos igual a StartServers e vai aumentar até atingir o número de MinSpareServers em poucos segundos. Diferenciar MinSpareServers e MaxSpareServers só fará sentido se seu servidor alterna entre períodos de grande e pequena demanda.

Vejamos agora um pouco do conceito de KeepAlive. Este recurso do Apache permite que um cliente faça várias requisições utilizando uma mesma conexão TCP. Isso economiza tempo e processamento, evitando que novos sockets e novos processos sejam criados. A conexão TCP é terminada quando o cliente passa um tempo sem fazer requisições (KeepAliveTimeout) ou quando o processo responsável pela conexão atender o número de requisições igual a MaxKeepAliveRequests.

Portanto utilizar este recurso é bom, mas devemos tomar cuidado para não ocupar um processo por muito tempo, evitando que novos clientes sejam atendidos. Valores que tem se mostrado razoáveis para o KeepAliveTimeout estão entre 1 e 5 segundos (é claro que utilizar um ou outro valor é uma decisão que você deve tomar baseado na quantidade de usuários e na qualidade do serviço que você quer prestar - valores mais baixos proporcionam maior rotatividade e valores mais altos maior qualidade no serviço do usuário que está sendo atendido. É como um médico cuja consulta dura 10 minutos e outro que dura 50).

O mesmo conceito se aplica para o MaxKeepAliveRequests. Quanto maior esse número, mais requisições um mesmo usuário poderá fazer antes de liberar a conexão para outro. Valores típicos estão entre 100 e 500 (0 significa que não há limite).

Agora vamos fazer mais algumas contas. Supondo que, pelos cálculos anteriores, você possa atender 20 clientes simultaneamente e que você escolha 1 segundo para o KeepAliveTimeout. Na melhor das hipóteses e em uma situação ideal o servidor seria capaz de atender 1200 novas conexões por minuto. É claro que esse valor não representa 1200 usuários simultâneos, porque um mesmo usuário pode abrir novas conexões a medida que vai navegando pelo site. Perceba que limitar o número de conexões simultâneas a um número pequeno não significa necessariamente que você só poderá atender poucos usuários.

A título de exemplo, vamos considerar um servidor com 512M de RAM que serve páginas web dinâmicas feitas em PHP e que os processos residentes, desconsiderando o Apache, ocupam 100M da memória RAM. Então,

512 - 100 = 412
412 / 20 = 20 e uns quebrados

Uma configuração que provavelmente otimizaria o seu Apache seria:

KeepAlive On
KeepAliveTimeout 1
MaxKeepAliveRequests 100

StartServers 15
MinSpareServers 15
MaxSpareServers 15
MaxClients 20
MaxRequestsPerChild 0

O valor de MaxRequestsPerChild representa o número de requisições que um processo filho do Apache pode atender antes de ser forçado a terminar. Isso era muito utilizado em sistemas operacionais com problemas de vazamento de memória (ex:Solaris). Se você utiliza Linux ou BSD é seguro utilizar 0 (infinito). Caso você note que depois de alguns dias a quantidade de memória utilizada por um processo está crescendo de forma anormal, mude esse valor para um valor finito porém grande (entre 5000 e 50000).

Além disso, se as aplicações que você hospeda demandam PHP, considere utilizar uma extensão que faça cache do código intermediário (APC , Turck MMCache). Essas extensões podem tornar o acesso até 5 vezes mais rápido.

Referências:
   

Páginas do artigo
   1. Introdução
Outros artigos deste autor
Nenhum artigo encontrado.
Leitura recomendada

Raid prático e definitivo

Rodando seu script como "service" no Conectiva

OpenSUSE 10.2 sempre atualizado

Solucionando o problema de cache em dispositivos de armazenamento USB

LILO gráfico e animado no Slackware

  
Comentários
[1] Comentário enviado por fabio em 17/02/2007 - 14:11h

Muito bom o artigo! Curto, porém com informações pra lá de relevantes. Parabéns.

[2] Comentário enviado por rogerboff em 18/02/2007 - 23:02h

Meus parabéns, Seu artigo foi para os meus favoritos e estou ja indicando para ums conhecidos meus.... Novamente meus parabéns Marco!

[3] Comentário enviado por Jack Ripoff em 20/02/2007 - 19:06h

Uma alternativa pra quem precisa de um servidor rápido e não precisa de todos os recursos do Apache é o lighttpd.

http://www.lighttpd.net/

[4] Comentário enviado por andrack em 16/03/2007 - 16:44h

Olá amigo!

É isso o que eu realmente considero de "Administração de Sistemas". É uma questão de extrema importância, e pouco abordada nos cursos por aí...


Abraços! Parabéns!

:-)

[5] Comentário enviado por bruno.prado em 08/03/2010 - 17:02h

Olá, hoje li este artigo e me auxiliou bastante. Tenho tentado buscar conteudo similiares na web mas não encontro.

Temos um servidor Dual Quad Core E5540 com 16GB de Ram e um disco SSD de 120GB espelhado em outro do mesmo tamanho.

Hoje rodamos o apache 2.2 com eAcelerator mas quando o site recebe uma carga de usuários grande o mesmo fica lento mas o servidor fica consumindo no máximo 3GB de RAM apesar de segurar o processador la encima na casa dos 80% por conta dos processos em PHP que pesam o site.

Gostaria de saber qual a melhor configuração para que o hardware possa ser completamente utilizado.

O website possui cerca de 30 mil acessos simultaneos em momentos de pico. Mas o dia a dia é de 2 mil simultaneos.

Abs,

Bruno Prado

[6] Comentário enviado por maurelio em 08/03/2010 - 20:17h

Caro Bruno,

se esse servidor é dedicado para o Apache, significa que você pode fazer os cálculos anteriores considerando 95% da memória total, o que daria um valor de MaxClients próximo a 800. Entretanto, para sites com grande número de acessos simultâneos, existem outras soluções como o lighttpd com php rodando em modo fast-cgi, com a vantagem de já fazer o papel do eAccelerator e diminuir o tamanho em memória dos processos filhos ou das threads do daemon http. Outra alternativa seria o balanceamento das requisições entre vários servidores web.
Como você pode perceber pelos exemplos utilizados no texto, o intuito do meu artigo foi apresentar alguns conceitos de tunning do Apache de forma a extrair o máximo de um servidor com pequena capacidade de processamento. No seu caso, eu recomendo avaliar outras possibilidades como o já citado uso do lighttpd com fast-cgi ou mesmo fazendo um proxy para servir o conteúdo estático e deixando para o Apache apenas o processamento das páginas dinâmicas.

Abraço,
Marco Aurelio.


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts