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!