Este documento fornece dicas para melhorar o desempenho de serviços web. Ele discute como reduzir o número de requisições HTTP, distribuir requisições entre vários servidores e adiar requisições desnecessárias para acelerar o carregamento de páginas. Várias ferramentas são mencionadas para medir o desempenho de sites.
1. Tchelinux – Caxias do Sul – 2010
Performance em serviços Web
Vinicius Mello
http://vmmello.eti.br/
2. Performance em serviços Web?
Exemplo para explicar a palestra
Blog, fórum, site de
notícias, etc
Um servidor atende
todos os usuários
Limite de qualidade de atendimento, por exemplo:
Fórum: ~ 10 a 20 usuários simultâneos
Blog: ~ 80 a 100 usuários simultâneos
Site de notícias: ~ 100 a 120 usuários simultâneos
Palestra: Dicas técnicas para aumentar a
capacidade de atendimento
3. Performance?
Atender o maior número de usuários com o menor número de
servidores possível (definição simplista, mas fácil pra explicar o conceito)
Custos: hospedagem e
manutenção
Qualidade
Página é desenhada
rapidamente para o usuário
O usuário fica o menor tempo
possível conectado ao
servidor
Sem erros de conexão
recusada
5. O acesso a uma página (cont.)
As requisições levam
um tempo para
chegar ao destino e
voltar
Primeiro acesso: tempo de DNS + tempo de roteamento
Demais acessos: tempo de roteamento
6. Exemplos de medidas de tempo
Conexões a sites de Caxias do Sul a partir de Porto Alegre
Tempo de
Tempo de DNS Tempo de Conexão
N Site Resposta HTTP Tamanho HTML
(1) (2)
(ms) (3)
1 Site 1 9 ms 20 ms 343 ms 12,90 KB
2 Site 2 13 ms 28 ms 172 (52) ms * 15,37 KB (3 KB) *
3 Site 3 34 ms 70 ms 264 ms 29 KB
(1) requisição direta ao servidor DNS do domínio
(2) tempo de retorno da função connect() da glibc
(3) tempo para enviar a requisição e receber cabeçalhos + arquivo html
* site utilizava um servidor cache (squid) e comprimia o conteúdo com gzip
8. Comprimir o conteúdo de texto (1)
Reduz o tempo de recebimento dos documentos
Reduz o tempo que o servidor atende ao usuário
Reduz drasticamente o uso de largura de banda
(hospedagem c/ 1 milhão de domínios, redução de 1 Gbit/s
de tráfego contínuo)
(sysadmin)
9. Comprimir o conteúdo de texto (2)
Recomendado comprimir: Html, CSS, Javascript, Arquivos
em texto puro
Perda de tempo tentar comprimir arquivos de mídia: mp3,
mpeg, jpg, png, gif, flash. São binários otimizados em
tamanho. Nenhuma diferença de tamanho.
Habilitar os módulos nos servidores HTTP
Apache: mod_deflate ou mod_gzip
Nginx: mod_gzip
10. Antes do ano de 2004
Exemplo: site linux.org (2002) – 1 html + 44
imagens
Sites eram apenas um documento de texto
(html) + imagens
Responsabilidade pela performance:
administrador de sistemas
14. Regras HTTP/1.1 +
Comportamento dos navegadores
HTTP 1.1 – é permitido fazer apenas 2 requisições simultâneas a um
mesmo servidor
Navegadores – fazem apenas 1 requisição ao encontrar uma tag
<script>
Navegadores – fazem requisições HTTP toda vez que encontram um
objeto em uma página (mesmo que tenham baixado esse objeto há
30 segundos atrás)
15. Soluções
Reduzir o número de requisições HTTP
Como fazer isso sem remover as imagens, CSS, javascript, etc?
Fazer primeiro as requisições necessárias para desenhar a
página
Adiar as requisições que não são extremamente necessárias
Distribuir as requisições entre vários servidores
Possibilitar ao navegador realizar mais de 2 conexões simultâneas
16. Reduzir o número de requisições HTTP (1)
Instruir o navegador para fazer cache das imagens, CSS e
Javascript
Adicionar cabeçalhos de expiração e cache a esses elementos
para evitar as requisições repetidas:
Expires=Sat, 19 Jul 2010 01:56:35 GMT
Cache-Control=max-age=2592000
Reduz significativamente o número de requisições
subseqüentes
Menos requisições no servidor
Página carrega mais rápido para o usuário
(sysadmins + desenvolvedores)
17. Reduzir o número de requisições HTTP (2)
Exemplo: Apache HTTPD
(contexto Server, VirtualHost, Directory, .htaccess)
<IfModule mod_expires.c>
ExpiresActive On
<FilesMatch ".(gif|jpg|png|js|css)$">
ExpiresDefault "access plus 1 month"
</FilesMatch>
<FilesMatch ".html$">
ExpiresDefault "access plus 10 minutes"
</FilesMatch>
</IfModule>
(Sysadmins + desenvolvedores)
18. Reduzir o número de requisições HTTP (3)
Combinar CSS e Javascript em um único arquivo por grupo
Todos os arquivos de CSS em um único arquivo
Todos os arquivos de Javascript em um único arquivo
Isso faz com que haja apenas uma requisição para cada tipo
de arquivo
(desenvolvedores)
19. Reduzir o número de requisições HTTP (4)
Combinar imagens de fundo adjacentes em um único arquivo
(CSS Sprite)
(pode ser combinada horizontalmente ou verticalmente)
Controlar a parte visível com as propriedades width, height e
background-position do CSS, por exemplo:
#classe-wrapper {
width: M px; /* opcional */
height: N px;
}
#classe-background {
background-position: x px, y px;
} (desenvolvedores)
20. Reduzir o número de requisições HTTP (5)
Utilizar imagens “in-line” dentro de arquivos CSS e HTML através
do esquema de URL data:
<img src="data:image/gif;base64,iVBORw0KGgoAAA..." title="Titulo" alt=”Text alt” />
Sintaxe: data:tipo-de-mídia;encoding,conteúdo
Pra converter as imagens:
$ cat imagem1.jpg | openssl base64 -e
(desenvolvedores)
21. Adiar as requisições que não são
extremamente necessárias
Colocar as tags <script> que não tem elementos visíveis na página,
no final:
Por exemplo:
<html>
<body>
...conteúdo...
</body>
<script type=”text/javascript” src=”google-analytics.com/ga.js”>
// …
</script>
</html>
Principais candidatos: scripts que fazem apenas requisições Ajax
após a página carregada
(desenvolvedores)
22. Distribuir as requisições entre vários
servidores
Imagens - http://imgs-1.meudominio.com/ - http://imgs-
2.meudominio.com/
CSS/Javascript - http://txt-1.meudominio.com/ -
http://txt-2.meudominio.com/
Melhora o paralelismo dos downloads (página abre mais
rápido para o usuário)
Desvantagem: cria uma pequena latência de DNS (que
geralmente ainda é menor do que a HTTP)
(sysadmins + desenvolvedores)
23. Notas Rápidas sobre Backend
No backend há um mundo a parte de soluções e configurações
para reduzir a carga nas aplicações.
Nesta sessão coloco apenas alguns lembretes importantes.
(reduzida por questão de tempo e porque acredito que não seja de interesse da maior parte da
audiência)
24. Front-End Cache
Cache de objetos em memória RAM (baixa latência)
Reduz a carga nos back-ends (enviar os cabeçalhos
apropriadamente)
(sysadmins + desenvolvedores)
25. Apache: KeepAlive
Em muitas distruibuições Linux o Keep-Alive do Apache vem
desabilitado por padrão.
O que força o usuário abrir uma nova conexão TCP a cada
requisição:
Perda de tempo para o servidor e o usuário (na maioria dos casos)
Habilitar o KeepAlive no httpd.conf: KeepAlive On
Não manter por muito tempo uma conexão sem atividade:
KeepAliveTimeout 3
KeepAlive desabilitado é bom para conexões únicas de curta
duração: Ajax rotineiros mas com intervalos > 30s
26. Apache: MPM ReceiveBufferSize
Buffer de rede (struct sk_buff) usado pelo kernel para
receber o conteúdo dos pacotes de rede (no caso o
conteúdo da requisição HTTP)
Na maioria absoluta dos casos o tamanho da requisição é
<< 4 kb (por padrão o kernel abre buffers de 87 kb – configurável via sysctl)
Alocação excessiva de memória que não será usada
No httpd.conf, na configuração do MPM:
ReceiveBufferSize 4096
4 kb é um valor razoável para a maioria dos casos
27. Conteúdo em arquivos é mais
rápido do que em servidor SQL
Conteúdo que não é atualizado freqüentemente é
disponibilizado mais rápido se armazenado em arquivos
estáticos (conexões SQL geralmente tem latência alta)
Ex.: notícias, posts de blogs, etc
Elementos dinâmicos (banners, imagens, comentários, etc) podem ser
carregados através de Ajax após terminado o carregamento do
conteúdo principal
Exemplo: WP-Cache (plugin Wordpress)
28. Cache em Memória (páginas dinâmicas)
Páginas que necessitam ser dinâmicas e tem um elevado número
de acessos podem ter parte do conteúdo armazenado
temporariamente em bancos de dados na memória.
Exemplos: memcached, redis
São softwares de banco de dados key-value que tem latência de
acesso muito baixa.
Podem ser usados para armazenar informações acessadas
freqüentemente:
Dados da sessão do usuário
Top 20 notícias mais acessadas, etc
29. Resumo
Reduzir o número de requisições HTTP
Reduzir o tempo que o usuário fica conectado ao servidor
Fazer primeiro as requisições necessárias para desenhar a
página
Distribuir as requisições entre vários servidores
Existe uma infinidade de técnicas pra
atingir cada objetivo: em front-end e
back-end.
30. Ferramentas para
mensurar
* hping (conectividade)
* wbox (tempo de conectividade + alguns cabecalhos)
* httperf (faz muitas requisicoes e testa a capacidade do site de responder)
* YSlow (verifica o conteúdo do site quanto as boas práticas de cache, reducão de
componentes externos, etc)
* Tamper data (extensão do Firefox)
* munin – detecta gargalhos das interrupcões de hardware (placa de rede, I/O disco,
etc)