Antes de começar gostaria de esclarecer alguns pontos muito importantes:
1. A solução apresentada funcionou perfeitamente para o meu ambiente, porém não dou garantias que a mesma funcionará para o seu. O ambiente no caso é a junção do hardware que possuo, os softwares que executo e a quantidade de requisições feitas ao servidor.
2. No Linux existem diversas formas de se implementar uma solução. Esta foi a forma que encontrei para implementar a minha, podem existir maneiras mais "corretas" de se configurar os softwares aqui citados, mas esta me serviu e muito bem.
3. Este artigo foi criado de técnico para técnico, estou partindo do princípio que você já sabe configurar um servidor web Apache e que deseja otimizar o desempenho do seu servidor. Caso você ainda não se considere um analista avançado nesta área, pode acompanhar o artigo por curiosidade, mas neste caso, não tente repetir isto em casa, ou melhor, no trabalho. :)
4. Os procedimentos foram realizados em um servidor
Debian Linux, porém sua execução deve ser bem sucedida em outras distribuições. Descobrir como instalar os pacotes e encontrar os arquivos de configuração em sua distro será de sua responsabilidade.
O problema
Nas últimas semanas os mais observadores devem ter notado que, em horários de pico, o VOL estava levando em média 8 segundos (as vezes bem mais) para carregar uma página. Bobo foi quem se conformou, pois não era sua conexão com a internet que estava lenta e sim o meu servidor web que estava "gargalado".
Passei alguns dias observando o servidor na expectativa de descobrir o que estava tornando a resposta do site tão lenta. Os possíveis pontos de gargalo levantados foram: I/O (o problema poderia ser a velocidade de acesso ao disco), load da máquina (será que os serviços estavam consumindo mais recursos do que eu dispunha de hardware?), MySQL (o site roda mais de 200 consultas por segundo em horário de pico, eis uma possibilidade concreta de gargalo) e por fim o próprio Apache, que neste ponto era o menor dos suspeitos, dada sua estabilidade e confiabilidade.
1. I/O (input/output ou entrada/saída em disco): o Apache faz leitura/escrita constante em disco, seja para ler o arquivo que o visitante do site está requisitando, seja para gravar arquivos de sessão no diretório temporário ou até mesmo para gravar arquivos enviados através de uploads de usuários. Se o tempo de I/O tivesse lento em horário de pico o problema estaria identificado. Foi então que criei um script em bash que criava, em fork, 500 arquivos, e depois os lia e apagava. Ao executar o script o tempo de resposta foi bem pequeno, o que me levou a concluir I/O não era o problema.
2. Load da máquina: o load, em horário de pico, variava entre 1.8 e 3.5, o que para um servidor bem movimentado pode ser considerado load médio/baixo. Para me certificar que o tempo de resposta do hardware estava bom, instalei serviços alternativos como o PostgreSQL e testei seu tempo de resposta, que era instantâneo. Se o hardware do servidor estivesse defasado, não só o servidor web ficaria lento, mas todos os demais serviços.
3. MySQL: eis meu próximo suspeito. Se o MySQL tivesse demorando para retornar uma query, o tempo de resposta do VOL ficaria preso à este delay, pois o conteúdo exibido no site está armazenado em banco de dados, o Apache só poderia retornar à requisição do usuário após a resposta do banco de dados. Então criei um script SQL com algumas das queries mais pesadas do código-fonte do VOL e quando o site estava num daqueles momentos de meditação (pensando, pensando, pensando e nada de responder), o executei no console do MySQL. O tempo de resposta foi bem menor que 1 segundo. Nada feito, próximo suspeito...
4. Apache: passei a testá-lo usando o telnet na porta 80, para começar o tempo de estabelecimento de conexão já era alto, o telnet ficava resmungando um tempo antes de me retornar o famoso "Escape character is '^]'". Ao obter essa resposta e digitar a requisição HTTP na munheca, outro belo tempo de resposta era obedecido. Eis o vilão da novela! Agora resta descobrir o motivo de seu gargalo.
Após muitas teorias e trocas de e-mails com outros técnicos, concluí que o problema estava na quantidade de requisições simultâneas feitas ao Apache. Pelo que pude comprovar, chega um momento em que o Apache se perde com a quantidade de childs gerados pelo módulo prefork, o que acaba consumindo toda (ou quase toda) memória RAM do servidor. Ao receber nova conexão (requisição de página), o Apache precisa liberar memória para criar uma nova thread para atender o visitante, porém em determinado momento ele acaba se perdendo e tem dificuldade em identificar quais processos estão inativos ou não. Ou seja, a fila de processos fica maior do que realmente é, algo parecido com a fila do INSS, muita gente para pouco atendente.
Ao reiniciar o Apache tudo voltava a funcionar aceitavelmente, mas por pouco tempo, rapidamente a memória era consumida novamente. E além disso, não fazia sentido passar o dia reiniciando o serviço, principalmente em horários de pico.
Ok, em horários de menor movimento o servidor funcionava muito bem, porém para solucionar o caso em horário de pico eu tinha duas alternativas: aumentar a memória RAM, o que requer um belo investimento, ou queimar a mufa e encontrar uma solução alternativa de software, e foi o que acabei fazendo.
O ambiente
O VOL, atualmente, serve de 7 a 8 milhões de páginas por mês. Muitos devem pensar que para suportar um site com tal número de acessos (que eu considero alto) seja necessário um hardware pra lá de possante. Que nada! Atualmente alugo um servidor dedicado em um datacenter nos EUA com a seguinte configuração:
- Processador Intel Dual Core 2.00 Ghz com 4096 de cache;
- 2GB de memória RAM;
- HD SCSI.
Não será surpresa se alguns de vocês possuir desktops com configurações mais poderosas. :)
Mas enfim, isso serve para provar que, quando bem configurado, pode-se fazer mágica com Linux.