O suporte ao server push do HTTP/2 também está incluído no NGINX Plus R15.
Temos o prazer de anunciar que o NGINX 1.13.9, lançado em 20 de fevereiro de 2018, inclui suporte ao server push do HTTP/2. Para os usuários do NGINX Plus, o suporte ao server push do HTTP/2 será incluído na próxima versão do NGINX Plus R15, prevista para abril de 2018.
O server push, que é definido na especificação HTTP/2, permite que um servidor envie recursos de forma preventiva a um cliente remoto, prevendo que o cliente poderá solicitá-los em breve. Com isso, é possível reduzir em um RTT ou mais o número de RTTs (tempo de ida e volta — o tempo necessário para uma solicitação e uma resposta) durante o carregamento de uma página, proporcionando uma resposta mais rápida ao usuário.
O server push pode ser usado para fornecer antecipadamente a um cliente folhas de estilo, imagens e outros recursos necessários para renderizar uma página da Web. Tenha o cuidado de enviar apenas os recursos necessários; não envie recursos que provavelmente já estejam armazenados no cache do cliente.
Neste post do blog, descrevo:
- Configuração básica para server push HTTP/2
- Como verificar se o server push HTTP/2 está funcionando (usando as ferramentas do navegador ou o
nghttp) - Envio automático de conteúdo usando o cabeçalho
Linkheader - Envio seletivo de conteúdo
- Medindo o efeito do server push do HTTP/2
Configurando o Server Push do HTTP/2
Para enviar recursos junto com o carregamento de uma página, use a diretiva http2_push da seguinte forma:
server { # Ensure that HTTP/2 is enabled for the server
listen 443 ssl http2;
ssl_certificate ssl/certificate.pem;
ssl_certificate_key ssl/key.pem;
root /var/www/html;
# whenever a client requests demo.html, also push
# /style.css, /image1.jpg and /image2.jpg
location = /demo.html {
http2_push /style.css; http2_push /image1.jpg; http2_push /image2.jpg;
}
}Verificando o Server Push do HTTP/2
Você pode verificar facilmente se o server push está ativo usando um destes dois métodos:
- As ferramentas de desenvolvedor do seu navegador
- Um cliente HTTP/2 de linha de comando, como o
nghttp
Verificação com as Ferramentas do Desenvolvedor (Google Chrome)
Veja como usar as ferramentas de desenvolvedor do seu navegador para verificar se o server push está em funcionamento, usando o Google Chrome como exemplo. Na figura, a coluna Iniciador da guia Rede das Ferramentas do desenvolvedor do Chrome indica que vários recursos foram enviados ao cliente como parte de uma solicitação de /demo.html.

Verificação com um cliente de linha de comando (nghttp)
Além das ferramentas do navegador, você pode usar o cliente de linha de comando nghttp do projeto nghttp2.org para verificar se o server push está funcionando. Você pode baixar o cliente de linha de comando nghttp no GitHub ou instalar o pacote apropriado para o sistema operacional, quando disponível. No Ubuntu, use o pacote nghttp2-client.
Na saída, o asterisco (*) indica os recursos enviados por push pelo servidor.
$ nghttp -ans https://example.com/demo.htmlid responseEnd requestStart process code size request path
13 +84.25ms +136us 84.11ms 200 492 /demo.html
2 +84.33ms * +84.09ms 246us 200 266 /style.css
4 +261.94ms * +84.12ms 177.83ms 200 40K /image2.jpg
6 +685.95ms * +84.12ms 601.82ms 200 173K /image1.jpgEnvio automático de recursos aos clientes
Em muitas situações, é inconveniente — ou até mesmo impossível — listar no arquivo de configuração do NGINX os recursos que você deseja enviar por push. Por esse motivo, o NGINX também oferece suporte à convenção de interceptar cabeçalhos de pré-carregamento Link preload headers e, em seguida, enviar por push os recursos identificados nesses cabeçalhos. Para habilitar o pré-carregamento, inclua a diretiva http2_push_preload na configuração:
server { # Ensure that HTTP/2 is enabled for the server
listen 443 ssl http2;
ssl_certificate ssl/certificate.pem;
ssl_certificate_key ssl/key.pem;
root /var/www/html;
# Intercept Link header and initiate requested Pushes
location = /myapp {
proxy_pass http://upstream;
http2_push_preload on;
}
}Por exemplo, quando o NGINX está operando como proxy (para HTTP, FastCGI ou outros tipos de tráfego), o servidor upstream pode adicionar um cabeçalho Link como este à resposta:
Link: </style.css>; as=style; rel=preloadO NGINX intercepta esse cabeçalho e inicia um push do servidor de /style.css. O caminho no cabeçalho Link deve ser absoluto – caminhos relativos como ./style.css não são compatíveis. Opcionalmente, o caminho pode incluir uma string de consulta.
Para enviar vários objetos por push, você pode fornecer vários cabeçalhos Link ou, melhor ainda, incluir todos os objetos em uma lista separada por vírgulas:
Link: </style.css>; as=style; rel=preload, </favicon.ico>; as=image; rel=preloadSe você não quiser que o NGINX envie um recurso pré-carregado, adicione o parâmetro nopush ao cabeçalho:
# Resource is not pushedLink: </nginx.png>; as=image; rel=preload; nopushQuando o http2_push_preload está habilitado, você também pode iniciar o push de servidor para pré-carregamento definindo o cabeçalho de resposta na configuração do NGINX:
add_header Link "</style.css>; as=style; rel=preload";Enviando recursos seletivamente aos clientes
A especificação HTTP/2 não aborda o desafio de determinar se os recursos devem ou não ser enviados por push. Evidentemente, é melhor enviar recursos por push aos clientes somente quando você souber que eles provavelmente precisarão desses recursos e que dificilmente já os terão armazenados em cache.
Uma abordagem possível é enviar recursos aos clientes somente na primeira visita deles ao site. Por exemplo, você pode verificar a presença de um cookie de sessão e definir o cabeçalho Link de forma condicional, para que os recursos sejam pré-carregados somente se o cookie de sessão não estiver presente.
Supondo que os clientes se comportem adequadamente e incluam o cookie nas solicitações subsequentes, com a configuração a seguir, o NGINX envia os recursos aos clientes apenas uma vez por sessão do navegador:
server {
listen 443 ssl http2 default_server;
ssl_certificate ssl/certificate.pem;
ssl_certificate_key ssl/key.pem;
root /var/www/html;
http2_push_preload on;
location = /demo.html {
add_header Set-Cookie "session=1";
add_header Link $resources;
}
}
map $http_cookie $resources {
"~*session=1" "";
default "</style.css>; as=style; rel=preload, </image1.jpg>; as=image; rel=preload, </image2.jpg>; as=image; rel=preload";
}Medindo o efeito do Server Push do HTTP/2
Para medir o efeito do server push, criamos uma página de teste simples, /demo.html, que faz referência a uma folha de estilos separada, /style.css. A folha de estilos também faz referência a duas imagens. Testamos os tempos de carregamento da página usando três configurações diferentes:
- Sequenciais
GETs (sem otimização) – O navegador carregava os recursos à medida que identificava que eram necessários - Dicas de pré-carregamento – Dicas de pré-carregamento (
Linkheaders) foram incluídas na primeira resposta para instruir o navegador a carregar as dependências - Push do servidor (somente HTTP/2) – As dependências eram enviadas antecipadamente ao navegador

Realizamos várias execuções de teste de cada configuração usando HTTP, HTTPS ou HTTP/2. As duas primeiras configurações se aplicam aos três protocolos, enquanto o server push se aplica apenas ao HTTP/2.
O comportamento foi medido usando as ferramentas para desenvolvedores do Chrome. O comportamento mais comum de cada configuração foi avaliado e calculou-se sua média, e os tempos foram correlacionados com o RTT do link (medido usando o comando ping) para ilustrar o efeito mecânico de cada método.

Algumas observações básicas
- DOM carregado é o tempo necessário para iniciar uma nova conexão e recuperar a página demo.html. Folha de estilos é o tempo necessário para recuperar o recurso CSS.
- Estabelecer uma conexão via HTTP leva 1 RTT; para HTTPS e HTTP/2, são necessários 2 RTTs.
- A carga útil dos recursos HTML e CSS é menor que o tamanho da unidade máxima de transmissão (MTU), portanto, uma operação
GETé concluída em aproximadamente 1 RTT.
Interpretando os resultados: dicas de pré-carregamento
- As dicas de pré-carregamento têm efeito mínimo sobre o recurso CSS, pois ele é referenciado diretamente no recurso HTML, que é entregue rapidamente. O navegador inicia a solicitação do CSS assim que a página HTML é entregue.
- As dicas de pré-carregamento permitem iniciar rapidamente o download dos recursos declarados no arquivo CSS (neste caso, as duas imagens). Com o uso dessas dicas, os downloads podem começar 1 RTT mais cedo.
- A economia líquida proporcionada pelas dicas de pré-carregamento pode ser de 1 RTT ou mais. Ao baixar recursos em paralelo, o navegador precisa abrir uma ou mais conexões adicionais. O desempenho depende de as solicitações lentas (respostas maiores) serem agendadas primeiro ou adiadas enquanto novas conexões são abertas. Essa ordem imprevisível das solicitações explica o ganho de velocidade de 1 RTT para HTTP e HTTP/2 e de 2 RTT para HTTPS.
Interpretando os resultados: Server Push
- O server push melhorou o tempo das dicas de pré-carregamento em mais 1 RTT. As “respostas” de push foram iniciadas ao mesmo tempo que a resposta à primeira solicitação, enquanto as respostas das dicas de pré-carregamento tiveram um atraso de 1 RTT – 0,5 RTT para a resposta à primeira solicitação mais 0,5 RTT para a solicitação de pré-carregamento
GET.
Observações sobre o teste
- Foram realizadas várias execuções de teste para cada configuração. Cada execução começou com o cache do navegador vazio e sem conexões keepalive estabelecidas com o servidor NGINX. As diretivas do NGINX
keepalive_timeoutehttp2_idle_timeoutforam usadas para encerrar rapidamente as conexões keepalive. - Atualmente, não parece ser possível enviar recursos de fonte por push para o Chrome, talvez devido a uma complicação conhecida. O Chrome faz uma solicitação explícita de um recurso de fonte mesmo que ele já tenha sido enviado por push.
- Tomou-se o cuidado de limpar explicitamente os caches dos navegadores antes de cada teste, e todo o conteúdo foi servido com cabeçalhos de controle de cache expirados.
- O Chrome armazena em cache os recursos pré-carregados. Esses recursos armazenados em cache nem sempre são ignorados quando você desativa o cache e nem sempre são removidos por uma operação explícita de “limpar o cache do navegador”. (No Chrome, uma forma de desativar o cache é marcar a caixa de seleção Desativar cache na guia Rede das Ferramentas do desenvolvedor. Para limpar o cache do navegador, clique com o botão direito do mouse no botão de atualizar do navegador com as Ferramentas do desenvolvedor abertas e selecione Esvaziar cache e recarregar forçadamente).
- Algumas tentativas de pré-carregar conteúdo fizeram com que o Chrome tentasse, sem sucesso, revalidar as cópias em cache e, em seguida, baixasse o recurso normalmente. Essas tentativas não foram contabilizadas nas medições.
- O Chrome adiciona um atraso desnecessário de 2 RTTs a todas as novas conexões SSL que usam certificados autoassinados aceitos anteriormente. O teste foi realizado usando certificados Let’s Encrypt assinados por uma autoridade certificadora (CA) para evitar esse atraso de 2 RTTs.
- Os atrasos de DNS foram resolvidos editando o arquivo local /etc/hosts.
- Esses testes simples não buscaram medir o efeito do server push quando o cliente já tinha uma cópia do recurso em cache. Nos testes, todos os caches foram limpos antes de cada teste, e a maioria dos pushes ocorreu rápido demais para ser cancelada.
Conclusão
Este teste foi deliberadamente simples para destacar o funcionamento das dicas de pré-carregamento e do server push. Em situações simples, o server push proporciona uma melhoria de 1 RTT em relação às dicas de pré-carregamento e uma melhoria ainda maior em comparação com solicitações GET sequenciais e não otimizadas e com a descoberta de recursos dependentes.
Casos de uso mais realistas têm muito mais variáveis: vários recursos dependentes, várias fontes e até mesmo a possibilidade de desperdiçar largura de banda ao enviar recursos que já estão em cache ou que não são necessários de imediato. As inconsistências entre navegadores também afetam o desempenho. Seus resultados certamente serão diferentes dos obtidos neste teste simples.
Por exemplo, a equipe do Chrome publicou algumas recomendações detalhadas sobre quando implementar o server push e realizou medições em sites mais complexos para comparar os efeitos da ausência de otimização, das dicas de pré-carregamento e do server push via HTTP/2. Vale a pena ler o relatório Regras práticas para o push HTTP/2 para quem estiver pensando em implementar o server push HTTP/2 em produção.
A conclusão pragmática é que, se você conseguir identificar antecipadamente quais recursos serão necessários, há um benefício real em fazer com que os servidores upstream enviem uma indicação de pré-carregamento. O benefício adicional de enviar esses recursos por push é pequeno, mas mensurável; no entanto, isso pode resultar em desperdício de largura de banda e atrasos no carregamento dos recursos necessários. Você deve testar e monitorar cuidadosamente todas as configurações de server push.
Apêndice: como funciona o push do HTTP/2?
As informações abaixo se baseiam, em parte, na pesquisa apresentada no detalhado post de Jake Archibald, O push do HTTP/2 é mais difícil do que eu pensava em seu blog.
O push de servidor HTTP/2 geralmente é usado para enviar recursos dependentes de forma antecipada quando o cliente solicita um recurso. Por exemplo, se um cliente solicitar uma página da Web, o servidor poderá enviar antecipadamente ao cliente folhas de estilo, fontes e imagens das quais a página depende.
Quando um cliente estabelece uma conexão HTTP/2, o servidor pode optar por iniciar uma ou mais respostas de push do servidor por meio dessa conexão. Esses pushes enviam recursos que o cliente não solicitou explicitamente.
O cliente pode rejeitar um push (enviando um quadro RST_STREAM) ou aceitá-lo. O cliente armazena o conteúdo enviado em um “cache de push” local associado à conexão HTTP/2.
Posteriormente, quando o cliente solicita um recurso usando uma conexão HTTP/2 estabelecida, ele verifica no cache de push da conexão se há uma resposta concluída ou em trânsito para a solicitação. Ele dá preferência ao recurso armazenado em cache em vez de fazer uma nova solicitação HTTP/2 para o recurso.
Qualquer recurso enviado por push permanece no cache de push específico da conexão até que (a) seja usado ou (b) a conexão HTTP/2 seja encerrada:
- Se o recurso for usado, o cliente obtém uma cópia, e a entrada no cache de push é excluída. Se o recurso puder ser armazenado em cache, o cliente poderá então armazenar sua cópia no cache de páginas HTTP.
- Se a conexão HTTP/2 for encerrada por qualquer motivo, o cache de push local será excluído.
Isso tem várias implicações:
- O conteúdo no cache de páginas HTTP do navegador é usado preferencialmente ao conteúdo no cache de push, mesmo que o conteúdo enviado por push seja mais recente.
- As conexões HTTP/2 podem ser compartilhadas entre diferentes carregamentos de página. Um recurso enviado por push durante o carregamento de uma página pode ser usado quando solicitado no carregamento de outra página.
- As solicitações com credenciais usam conexões HTTP/2 diferentes das solicitações sem credenciais. Por exemplo, um recurso enviado por push com uma solicitação entre origens (com credenciais) pode não ser encontrado se o navegador fizer uma solicitação sem credenciais para esse recurso.
Você pode conferir uma lista muito mais detalhada de problemas na publicação de Jake Archibald, intitulada “O push HTTP/2 é mais complicado do que eu imaginava”.
O push de servidor HTTP/2 é um recurso interessante. Teste minuciosamente sua configuração de push de servidor HTTP/2 e esteja preparado para recorrer a dicas de pré-carregamento nos casos em que elas proporcionarem um comportamento mais previsível e que leve o cache em consideração.
Sobre o autor

Publicações relacionadas no blog

Como o F5 NGINX One aprimora o gerenciamento e a observabilidade
Descubra como o F5 NGINX One aprimora o gerenciamento e a observabilidade de ambientes híbridos e multicloud ao oferecer um console web centralizado baseado em SaaS, com insights em tempo real, conformidade automatizada e gerenciamento simplificado de configurações.

Do OpenAPI ao NGINX como gateway de API usando uma API declarativa
Descubra como transformar uma definição de esquema OpenAPI em uma configuração NGINX totalmente funcional, operando como um API Gateway com a segurança de um Web Application Firewall e um Portal do Desenvolvedor, usando uma abordagem declarativa de API.

Como gerenciar picos repentinos de tráfego e sobrecarga do servidor
Picos de tráfego e sobrecarga de servidores são preocupações sérias para varejistas online em qualquer época, mas especialmente durante a “Cyber Season” de compras de fim de ano. Detalhamos como você pode aproveitar as soluções de entrega de aplicações de nível de produção da NGINX para se preparar para aumentos repentinos de tráfego.

Distribuição segura de chaves privadas SSL com o NGINX
Descrevemos três maneiras progressivamente mais seguras de proteger chaves privadas SSL ao configurar o NGINX para processar tráfego HTTPS: permitir acesso de leitura apenas ao usuário root, criptografar as chaves com senhas armazenadas separadamente e distribuir as senhas a partir de um repositório central.
Agrupando solicitações de API em lotes com NGINX Plus e o módulo JavaScript do NGINX
O módulo JavaScript do NGINX lançado com o NGINX Plus R15 oferece suporte a subsolicitações, possibilitando uma classe totalmente nova de casos de uso para o NGINX Plus. Este exemplo completo também usa a API do NGINX Plus e os módulos de chave-valor para converter solicitações de API dos clientes em solicitações separadas para as APIs dos microsserviços que compõem um aplicativo.
Como superar o esgotamento de portas efêmeras no NGINX e no NGINX Plus
Confira dicas para evitar o esgotamento de portas efêmeras com ajustes no kernel do Linux, conexões keepalive e conexões vinculadas dinamicamente a endereços IP locais.