Estratégias comuns de pressão de retorno para serviços sob alta carga sustentada

4

Eu estou querendo saber quais são as estratégias comuns de contrapressão que as pessoas usam para seus serviços web?

Imagine que seu serviço opera sob carga pesada e, em algum momento, a carga atinge 120% da sua capacidade. Como você lida com isso?

A estratégia mais sensata em que consigo pensar é começar a rejeitar conexões. Portanto, se um host atingir sua capacidade de pico (por exemplo, todos os funcionários do Apache estão ocupados), eu começaria a rejeitar a conexão TCP até que um dos trabalhadores seja liberado. Dessa forma, todas as conexões aceitas são tratadas imediatamente sem enfileiramento (portanto, a latência é mínima) e os 20% excessivos são rejeitados, permitindo que o balanceador de carga os redirecione para o outro host ou execute qualquer outra estratégia de redução de carga (por exemplo, redirecionando para conteúdo estático / em cache).

Acho que essa abordagem fail-fast é muito superior a qualquer tipo de enfileiramento. As pequenas filas são boas para absorver rajadas curtas no tráfego, mas com o excesso de filas seu sistema pode falhar espetacularmente sob carga pesada. Por exemplo, com o processamento da fila FIFO sem qualquer AQM, ele pode entrar no estado quando todas as solicitações processadas já tiverem expirado no lado do cliente, portanto, o sistema não faz nenhum progresso à frente.

Fiquei surpreso que essa estratégia não é tão fácil de implementar quanto parece. Minha abordagem foi definir um pequeno backlog de escuta no servidor web, esperando que todas as conexões que não cabem fossem rejeitadas. Mas devido a mudanças no kernel Linux 2.2, esta estratégia se desfaz (veja link ).

O novo kernel do Linux aceita conexões para você incondicionalmente. A resposta SYN-ACK é enviada ao cliente sem considerar o tamanho do escute de atendimento. Ativar a opção tcp_abort_on_overflow também não ajuda muito. Esta opção faz o kernel enviar o RST quando a conexão não se encaixa na fila de aceitação, mas neste ponto o cliente já considera a conexão ESTABLISHED e pode ter iniciado o envio dos dados.

Isso é especialmente problemático com o HAProxy. Se a conexão foi estabelecida com sucesso, ela não voltará a enviar o pedido para o outro servidor, uma vez que este pedido pode ter tido alguns efeitos colaterais no servidor.

Então, acho que minhas perguntas são:

  • eu sou o estranho por tentar implementar algo assim?
  • existem outras estratégias para lidar com alta carga sustentada que você possa recomendar?
  • o tcp_abort_on_overflow do kernel do Linux está quebrado e deveria ter sido aplicado a uma fila semiaberta?

Obrigado antecipadamente!

    
por sergey 26.03.2015 / 02:25

1 resposta

3

Para responder sua primeira pergunta: sim. Bem, na minha opinião pessoal, não leve isso para o lado pessoal. O problema é que você está tentando definir os limites da sua pilha TCP, enquanto você tem um balanceador de carga na frente com muitos contadores e opções. Se você se limitar à pilha TCP, encontrará mais problemas quando atingir esses limites. Eu iria verificar e manter limites no loadbalancer em si. Configure contadores de sessão ou faça algum script de integridade que verificará a integridade do servidor. Ao atingir os limites, você pode rejeitar as novas solicitações recebidas ou redirecioná-las para outro servidor quando definir o back-end como completo. Você está preso aos limites do seu Apache, não do seu sistema operacional ou do haproxy, então tente ficar longe dos limites do sistema controlando a carga para o seu apache antes que ele chegue.

Acho que isso já respondeu à sua segunda pergunta.

A terceira pergunta é mais complexa, e eu não acho que você queira entrar nas profundezas disso. Atingir o estado de estouro de TCP é, na minha opinião, um passo a mais no aprimoramento do servidor para suportar alta carga e tráfego.

Estes são meus dois centavos, espero que ajude.

    
por 12.05.2015 / 07:49