Desenvolvimento

22 jul, 2015

HTTP/2 para uma web mais rápida

Publicidade

Só depois de longos 16 anos é que uma nova versão do principal protocolo da web, o HTTP, foi lançada. A versão 2.0 tem algumas mudanças que impactam diretamente na forma como desenvolvemos sites web e depois de tanto tempo, surge a questão: quem é o maior inimigo do desenvolvedor hoje? O Internet Explorer, a diversidade de resoluções de dispositivos ou a latência?

Com base no contexto atual, podemos dizer que a latência é o ponto-chave. Latência é o tempo necessário para que o ponto de origem envie um pacote para o ponto de destino guardar. E é claro que a performance dos sites é importante, pois atinge diretamente a experiência do usuário. Não é apenas uma necessidade de velocidade psicológica, mas um requisito para grandes resultados na maioria das empresas online. Afinal, sites mais rápidos lidam com melhor engajamento e retenção do usuário, além de lidar com alta conversão.

Na era dos dispositivos móveis sabemos que nossa conexão com a internet não é uma das melhores, pois os sites ficam lentos para carregar. O protocolo HTTP está ligado a esses problemas.

A web mudou

Nos últimos quatro anos, o download de arquivos aumentou de 900kb para 1900kb, enquanto o total de requests passou de 70 para aproximadamente 100 por web site, segundo o HTTP Archive. Imagina o quanto a web evoluiu se pensarmos em 16 anos atrás.

O HTTP foi lançado em 1996, mas teve sua ultima atualização em 1999 com o HTTP1.1. Podemos observar algumas melhorias, como Pipeline, mas a versão ainda possui alguns problemas que forçam o desenvolvedor a fazer muitos workarounds, como o uso de Sprites e Sharding, data URIs e concatenação e minificação de arquivos, por exemplo.

Como o HTTP funciona?

No coração da internet há dois protocolos: IP e TCP. O IP, ou Internet Protocol, é o que fornece o endereçamento e o TCP, ou Trasmission Control Protocol, é o que fornece a abstração de uma rede confiável em cima de um canal não confiável. Ela esconde a maioria da complexidade de comunicação de rede da nossa aplicação: perda de dados, ordem de entrega, controle de congestionamento, integridade dos dados, entre outras coisas.

Quando trabalhamos com transferência via TCP, é garantido que todos os bytes enviados vão ser idênticos aos bytes recebidos, e que eles vão chegar na mesma ordem para o cliente, ou seja, o TCP é para otimizar a precisão da distribuição. Agora, o HTTP criou alguns desafios para otimização da web performance no browser.

Toda conexão TCP inicia com o que chamamos de three-way handshake. Antes do cliente e do servidor trocarem qualquer dado da aplicação, eles devem aprovar uma sequência de números iniciais do pacote, de ambos os lados. A sequência de números são adquiridas randomicamente de ambos os lados por razões de segurança. Os three-way são SYN, SYN ACK e ACK.

Esse processo inicial se aplica a toda conexão TCP. Cada nova conexão vai ter um round-trip completo antes de que qualquer dado da aplicação possa ser transferido.

image021

Abrir uma conexão TCP é um processo muito caro. Com o método keep-alive, conseguimos manter uma conexão TCP aberta para fazer vários requests e isso é bom, porém é preciso aguardar o response de um determinado request para conseguir iniciar um novo request. Em um mundo melhor, o interessante seria fazer vários requests paralelamente. Pensando nisso, na versão 1.1 o HTTP implementou um recurso chamado de Pipelining.

image031

No pipelining é possível fazer requests paralelos e não é mais necessário aguardar um response para iniciar outro request. Isso é ótimo, mas ainda há alguns problemas, como limite de quatro a oito requestes por host e o head of line blocking.

Chamamos de head of line blocking o fenômeno que ocorre quando os requests paralelos vão para o servidor e são presos pelo pacote da frente. É como se você estivesse em uma fila de banco com várias pessoas sem saber se a pessoa que está na sua frente vai ser rápida ou tomar todo o seu tempo.

HTTP/2 para uma web mais rápida

Esses problemas sobre os quais falamos até agora machucam a web performance. Pensando nisso, o Google deu início em 2009 a um projeto chamado SPDY, com o objetivo de diminuir o page load time das páginas web.

O SPDY foi validado e está sendo usado em diversos e importantes sites da web, como o próprio Google, Facebook e Twitter. O HTTP/2 vem para reduzir a latência das páginas, e por isso é completamente baseado no projeto SPDY, com praticamente todas as features do projeto, como binary framing, header compression, multiplexing e server push.

Importante lembrar que o HTTP/2 não muda a semântica do HTTP. Todos os métodos, status code e URLs funcionam da mesma forma. O HTTP/2 não é um substituto do HTTP, mas uma melhoria.

Binary framing

Para que o HTTP/2 atinja o desejável ganho de performance, uma das features mais importantes é o binary framing. É mais eficiente para ser parseado, mais compacto “on the wire” e, o mais importante, é muito menos propenso a erros.

Binary framing dita a forma que as mensagens HTTP vão ser transmitidas do cliente para o servidor; ele permite que cada request ou response seja dividido em um ou mais frames. Podemos mandar partes da mensagem HTTP sem ordem, ou seja, completamente assíncrono, que o HTTP/2 consegue, além juntar todas essas partes, priorizar cada uma delas conforme a necessidade. Chamamos isso de stream priorization:

image052

Header compression

Quando acontece toda e qualquer requisição feita para o servidor, o HTTP envia uma seção que chamamos de Header, que contém basicamente todas as informações da requisição. Patrick McManus, que trabalha na Mozilla, mostrou o quanto é necessário se preocupar com o Header quando pensamos em page load.

Ele mostra que se assumirmos que temos em média 80 arquivos estáticos e em cada request temos cerca de 1400 bytes de header, é necessário fazer em torno de 7 a 8 round-trips para pegar o header “on the wire”. Se fizermos a compressão do header, é possível fazer isso em apenas um round-trip.

O HTTP/2 não muda a forma de como suas antigas versões trabalham, ou seja, mesmo que muitas vezes o header é repetido de request para request, ele ainda continua enviando da mesma forma. No SPDY e HTTP/2 não é mais necessário se preocupar com compressão de Header pois ambos já fazem esse processo automaticamente, obtendo o ganho de performance.

No SPDY, o GZIP foi o escolhido e implementado com sucesso, porém tem sido documentado com o maior ataque contra o uso de compressão de streams dentro de criptografia. Como resultado, no HTTP/2 o GZIP foi substituído pelo HPACK.

Multiplexing

Pelo fato do HTTP/2 ser completamente binário, agora é possível fazer multiplexação de dados, ou seja, em uma única conexão é possível fazer múltiplos requests intercalados.

image001 (1)

Não é mais necessário aguardar um request para enviar outro.  Podemos intercalar requests usando somente uma conexão TCP, evitando handshakes desnecessários.

Server Push

Apesar do fato do HTTP/2 ser binário e, com isso, demonstrar um grande avanço, temos mais um recurso sensacional que podemos tirar vantagem. O Server Push é uma maneira do servidor enviar assets necessários de uma página sem ao menos o cliente solicitar esses arquivos. Server Push tem a capacidade de enviar responses com apenas um único request, podendo cachear, reusar, priorizar e rejeitar esses assets.

image042

Uso do HTTP/2 hoje

Como o HTTP/2 é completamente binário, é importante que o cliente e o servidor estejam preparados para conversar dessa forma. De acordo com o site Can I Use, já temos 48% de compatibilidade por parte dos browsers.

image013

Por parte dos web servers, termos várias implementações realizadas e listadas no GitHub Implementations.

image062

Em maio, eu fiz uma palestra sobre esse assunto no evento Front in Fortaleza. Aqui tem mais detalhes sobre o que rolou por lá e você pode conferir os slides que eu usei aqui. Também deixo algumas referências para você que quer saber mais sobre o assunto:

Tem alguma dúvida, crítica, sugestão ou comentário a fazer? Deixe abaixo o seu recado.

Até a próxima!