Tchelinux – Caxias do Sul – 2010




Performance em serviços Web




           Vinicius Mello
            http://vmmello.eti.br/
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
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
O acesso a uma página
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
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
Demonstração de como medir essas
variáveis de tempo
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)
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
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
Pós 2004




Exemplo: site linux.org (2010) – 1 html + 15
javascript + 4 iframes + 2 flashs + 46
imagens

Sites multi-documentos (popularizou CSS +
Javascript + objetos)

Responsabilidade pela performance:
desenvolvedores (equipe multidisciplinar)
Como funcionam as requisições
                        HTTP
GET http://www.google.com.br/search?hl=pt-BR&client=firefox
Host: www.google.com.br
User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.3)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: pt-br,en-us;q=0.7,en;q=0.3
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Proxy-Connection: keep-alive
Referer: http://www.google.com.br/search?q=
Cookie: PREF=ID=aab9eb9e1b47a77b:U=6214272b6f8d75c3


                                                      HTTP/1.1 200 OK
                                                      Cache-Control: private, max-age=0
                                                      Date: Sat, 19 Jun 2010 07:32:20 GMT
                                                      Expires: -1
                                                      Content-Type: text/html; charset=UTF-8
                                                      Server: gws

                                                      <!doctype html><head><title>tchelinux -
                                                      Pesquisa
                                                      Google</title><script>window.google={kEI:"h

                                                      (… corpo da requisição … )
Demonstração de requisições a um
         site completo
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)
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
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)
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)
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)
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)
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)
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)
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)
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)
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)
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
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
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)
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
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.
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)
FIM


Perguntas?

Performance em Serviços Web - Vinicius Mello

  • 1.
    Tchelinux – Caxiasdo Sul – 2010 Performance em serviços Web Vinicius Mello http://vmmello.eti.br/
  • 2.
    Performance em serviçosWeb? 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 maiornú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
  • 4.
    O acesso auma página
  • 5.
    O acesso auma 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 medidasde 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
  • 7.
    Demonstração de comomedir essas variáveis de tempo
  • 8.
    Comprimir o conteúdode 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údode 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 anode 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
  • 11.
    Pós 2004 Exemplo: sitelinux.org (2010) – 1 html + 15 javascript + 4 iframes + 2 flashs + 46 imagens Sites multi-documentos (popularizou CSS + Javascript + objetos) Responsabilidade pela performance: desenvolvedores (equipe multidisciplinar)
  • 12.
    Como funcionam asrequisições HTTP GET http://www.google.com.br/search?hl=pt-BR&client=firefox Host: www.google.com.br User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.3) Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: pt-br,en-us;q=0.7,en;q=0.3 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 115 Proxy-Connection: keep-alive Referer: http://www.google.com.br/search?q= Cookie: PREF=ID=aab9eb9e1b47a77b:U=6214272b6f8d75c3 HTTP/1.1 200 OK Cache-Control: private, max-age=0 Date: Sat, 19 Jun 2010 07:32:20 GMT Expires: -1 Content-Type: text/html; charset=UTF-8 Server: gws <!doctype html><head><title>tchelinux - Pesquisa Google</title><script>window.google={kEI:"h (… corpo da requisição … )
  • 13.
  • 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úmerode 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úmerode 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úmerode 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úmerode 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úmerode 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úmerode 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çõesque 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çõesentre 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 sobreBackend 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 deobjetos em memória RAM (baixa latência) Reduz a carga nos back-ends (enviar os cabeçalhos apropriadamente) (sysadmins + desenvolvedores)
  • 25.
    Apache: KeepAlive Em muitasdistruibuiçõ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 Bufferde 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úmerode 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)
  • 31.