Os proxies reversos HTTP normalmente ativam o HTTP Keep-Alive no lado do cliente da conexão em proxy e não no lado do servidor?

30

O HAProxy tem a capacidade de ativar a manutenção de HTTP ativa no lado do cliente (cliente <-> HAProxy), mas desativá-lo no lado do servidor (servidor HAProxy <->).

Alguns de nossos clientes se conectam ao nosso serviço web via satélite, então a latência é de ~ 600ms e acho que, ao manter o keep-alive, isso acelerará um pouco as coisas. Estou certo?

Isso é suportado pelo Nginx? Esse é um recurso amplamente implementado em outros balanceadores de carga de software e hardware? O que mais além do HAProxy?

LostInComputer
fonte

Respostas:

43

editar: minha resposta cobre apenas a pergunta original não editada, que era se esse tipo de coisa é típica em balanceadores de carga / proxies reversos. Não tenho certeza se o nginx / produto X tem suporte para isso, 99,9% da minha experiência de proxy reverso é com o HAproxy.

Corrigir. HTTP Keep-Alive no lado do cliente, mas não no lado do servidor.

Por quê?

Se você detalhar alguns detalhes, poderá ver rapidamente por que isso é um benefício. Neste exemplo, vamos fingir que estamos carregando uma página www.example.com e essa página inclui 3 imagens, img [1-3] .jpg.

Navegador carregando uma página, sem o Keep-Alive

  1. O cliente estabelece uma conexão TCP com www.example.com na porta 80
  2. O cliente faz uma solicitação HTTP GET para "/"
  3. O servidor envia o conteúdo HTML do URI "/" (que inclui tags HTML que referenciam as 3 imagens)
  4. Servidor fecha a conexão TCP
  5. O cliente estabelece uma conexão TCP com www.example.com na porta 80
  6. O cliente faz uma solicitação HTTP GET para "/img1.jpg"
  7. Servidor envia a imagem
  8. Servidor fecha a conexão TCP
  9. O cliente estabelece uma conexão TCP com www.example.com na porta 80
  10. O cliente faz uma solicitação HTTP GET para "/img2.jpg"
  11. Servidor envia a imagem
  12. Servidor fecha a conexão TCP
  13. O cliente estabelece uma conexão TCP com www.example.com na porta 80
  14. O cliente faz uma solicitação HTTP GET para "/img3.jpg"
  15. Servidor envia a imagem
  16. Servidor fecha a conexão TCP

Observe que existem 4 sessões TCP separadas estabelecidas e fechadas.

Navegador carregando uma página com o Keep-Alive

O HTTP Keep-Alive permite que uma única conexão TCP atenda a várias solicitações HTTP, uma após a outra.

  1. O cliente estabelece uma conexão TCP com www.example.com na porta 80
  2. O cliente faz uma solicitação HTTP GET para "/" e também pede ao servidor para fazer desta uma sessão HTTP Keep-Alive.
  3. O servidor envia o conteúdo HTML do URI "/" (que inclui tags HTML que referenciam as 3 imagens)
  4. O servidor não fecha a conexão TCP
  5. O cliente solicita e HTTP GET solicita "/img1.jpg"
  6. Servidor envia a imagem
  7. O cliente solicita e HTTP GET solicita "/img2.jpg"
  8. Servidor envia a imagem
  9. O cliente solicita e HTTP GET solicita "/img3.jpg"
  10. Servidor envia a imagem
  11. O servidor fecha a conexão TCP se nenhuma solicitação HTTP for recebida dentro do período de tempo limite HTTP Keep-Alive

Observe que, com o Keep-Alive, apenas 1 conexão TCP é estabelecida e, eventualmente, fechada.

Por que o Keep-Alive é melhor?

Para responder a isso, você deve entender o que é necessário para estabelecer uma conexão TCP entre um cliente e um servidor. Isso é chamado de handshake de 3 vias TCP.

  1. O cliente envia um pacote SYN (cronização)
  2. O servidor envia de volta um SYN (cronograma) ACK (aviso), SYN-ACK
  3. O cliente envia um pacote ACK (compromisso)
  4. A conexão TCP agora é considerada ativa pelo cliente e pelo servidor

As redes têm latência; portanto, cada etapa do handshake de três vias leva um certo tempo. Digamos que haja 30ms entre o cliente e o servidor, o envio e recebimento de pacotes IP necessários para estabelecer a conexão TCP significa que são necessários 3 x 30ms = 90ms para estabelecer uma conexão TCP.

Isso pode não parecer muito, mas se considerarmos que em nosso exemplo original, precisamos estabelecer 4 conexões TCP separadas, isso se torna 360 ms. E se a latência entre o cliente e o servidor for 100ms em vez de 30ms? Em seguida, nossas 4 conexões estão levando 1200ms para serem estabelecidas.

Pior ainda, uma página da Web típica pode exigir muito mais do que apenas três imagens para carregar, pode haver vários CSS, JavaScript, imagem ou outros arquivos que o cliente precisa solicitar. Se a página carregar 30 outros arquivos e a latência cliente-servidor for 100ms, quanto tempo gastamos para estabelecer conexões TCP?

  1. Para estabelecer 1 conexão TCP, é necessário 3 x latência, ou seja, 3 x 100ms = 300ms.
  2. Devemos fazer isso 31 vezes, uma vez para a página e outras 30 vezes para o outro arquivo referenciado pela página. 31 x 300ms = 9,3 segundos.

9,3 segundos para estabelecer conexões TCP para carregar uma página da Web que faz referência a outros 30 arquivos. E isso nem conta o tempo gasto enviando solicitações HTTP e recebendo respostas.

Com o HTTP Keep-Alive, precisamos estabelecer apenas 1 conexão TCP, que leva 300ms.

Se o HTTP Keep-Alive é tão bom, por que não usá-lo também no lado do servidor?

Os proxies HTTP reversos (como o HAproxy) geralmente são implantados muito perto dos servidores backend para os quais estão fazendo proxy. Na maioria dos casos, a latência entre o proxy reverso e seus servidores de back-end será inferior a 1 ms; portanto, estabelecer uma conexão TCP é muito mais rápido do que entre um cliente.

Essa é apenas metade do motivo. Um servidor HTTP aloca uma certa quantidade de memória para cada conexão do cliente. Com o Keep-Alive, ele mantém a conexão ativa e, por extensão, mantém uma certa quantidade de memória em uso no servidor, até que o tempo limite do Keep-Alive seja atingido, o que pode levar até 15 segundos, dependendo da configuração do servidor. .

Portanto, se considerarmos os efeitos do uso do Keep-Alive no lado do servidor de um proxy reverso HTTP, aumentaremos a necessidade de memória, mas como a latência entre o proxy e o servidor é muito baixa, não obtemos nenhum benefício real do redução do tempo necessário para o handshake de três vias do TCP; portanto, é geralmente melhor desativar o Keep-Alive entre o proxy e o servidor da Web nesse cenário.

Isenção de responsabilidade: sim, esta explicação não leva em conta o fato de que os navegadores normalmente estabelecem várias conexões HTTP com um servidor em paralelo. No entanto, há um limite para quantas conexões paralelas um navegador fará com o mesmo host e, normalmente, isso ainda é pequeno o suficiente para tornar a manutenção ativa desejável.

ThatGraemeGuy
fonte
5
Parabéns pela excelente explicação Graeme, nunca passei tempo suficiente por uma resposta para quem me perguntou isso, e certamente manterei um link para este post para servir como uma resposta muito clara agora :-)
Willy Tarreau
2
Haveria uma vantagem para keepAlive no lado do servidor se a conexão entre proxy e back-end fosse https?
Avmohan #
"Um servidor HTTP aloca uma certa quantidade de memória para cada conexão do cliente" sim, mas haverá poucas dessas conexões (?) Apenas uma por balanceador de carga? Nenhum por cliente na Internet (?)
Raedwald 24/09
@ Raedwald, se o seu balanceador de carga estiver limitado a fazer uma única conexão HTTP para cada servidor suportado, você terá um tempo muito ruim. :-)
ThatGraemeGuy
7

O Nginx suporta o keep-alive dos dois lados.

VBart
fonte
Você diria que manter vivo é útil para back-end, se houver latência entre o proxy e os back-end? Além disso, o que um número ideal de conexões mantidas ativas seria permitido?
precisa saber é o seguinte
@CMCDragonkai Se os seus back-end estão localizados em servidores dedicados, pode ser útil evitar a latência da conexão, que depende da sua rede. Não há média de ouro, o número ideal depende principalmente da sua configuração, ambiente, aplicativo e padrão de solicitação.
Vbart
Espero encontrar uma equação para resolver isso!
precisa saber é o seguinte
2
A questão, como eu a li, não está perguntando se o nginx suporta keep-alive no upstream, mas se o nginx suporta a desativação do keep-alive no lado upstream.
user45793