Novos casos de uso às vezes exigem novos algoritmos de balanceamento de carga e, no NGINX Plus R16 e no NGINX Open Source 1.15.1, adicionamos um novo método que é particularmente adequado para balanceadores de carga distribuídos: uma implementação do algoritmo “poder de duas escolhas”.
Métodos clássicos de balanceamento de carga, como Least Connections, funcionam muito bem quando você opera um único balanceador de carga ativo que mantém uma visão completa do estado dos nós balanceados de carga. A abordagem do “poder de duas escolhas” não é tão eficaz em um único balanceador de carga, mas evita habilmente o “comportamento de rebanho” de caso ruim que pode ocorrer quando você dimensiona para vários balanceadores de carga independentes.
Esse cenário não é observado apenas quando você dimensiona em ambientes de alto desempenho; ele também é observado em ambientes em contêineres, onde vários proxies balanceiam a carga de tráfego para o mesmo conjunto de instâncias de serviço.
Uma instância comum desse cenário ocorre quando você usa o NGINX Ingress Controller para Kubernetes, com uma instância de balanceamento de carga por nó do Kubernetes.
O algoritmo é conhecido na literatura como “poder de duas escolhas”, porque foi descrito pela primeira vez na dissertação de Michael Mitzenmacher de 1996, The Power of Two Choices in Randomized Load Balancing . No NGINX e no NGINX Plus, ele é implementado como uma variação do algoritmo de balanceamento de carga aleatório, por isso também o chamamos de Aleatório com duas escolhas .
Vamos começar com o que pode ser uma situação familiar. Você acabou de pousar após um longo voo internacional e, junto com outros 400 viajantes, entrou em um movimentado saguão de desembarque.
Muitos aeroportos empregam guias no saguão de desembarque. O trabalho deles é direcionar cada viajante para uma das diversas filas de cada balcão de imigração. Se pensarmos nos guias como balanceadores de carga:
Vamos considerar o quão bem alguns dos algoritmos possíveis funcionam em um cenário de balanceamento de carga distribuído, como o saguão de desembarque.
Round robin é uma abordagem ingênua ao balanceamento de carga. Nessa abordagem, o guia seleciona cada fila em rotação – o primeiro viajante é direcionado para a fila A, o próximo viajante para a fila B e assim por diante. Depois que um viajante é direcionado para a última fila, o processo se repete a partir da fila A. Round Robin é o algoritmo de balanceamento de carga padrão usado pelo NGINX:
Essa abordagem funciona adequadamente, até que haja um atraso em uma das filas. Talvez um viajante tenha perdido sua documentação ou despertado suspeitas no agente de imigração:
A fila para de andar, mas o guia continua a designar viajantes para aquela fila. O acúmulo de pedidos fica cada vez maior – isso não vai deixar os viajantes impacientes mais felizes!
Existe uma abordagem muito melhor. O guia observa cada fila e, cada vez que um viajante chega, ele o encaminha para a fila mais curta. Este método é análogo ao método de balanceamento de carga de menos conexões no NGINX, que atribui cada nova solicitação ao servidor com o menor número de solicitações pendentes (enfileiradas):
O balanceamento de carga de menos conexões lida de forma bastante eficaz com viajantes que levam diferentes quantidades de tempo para processar. Ele busca equilibrar o comprimento das filas e evita adicionar mais solicitações a uma fila que está parada.
Vimos que diferentes passageiros levam tempos diferentes para serem processados; além disso, algumas filas são processadas mais rápido ou mais devagar do que outras. Por exemplo, um agente de imigração pode ter problemas com o computador, o que significa que ele processa os viajantes mais lentamente; outro agente pode ser muito detalhista, interrogando os viajantes com muita atenção. Outros oficiais podem ser muito experientes e capazes de processar viajantes mais rapidamente.
E se cada cabine de imigração tivesse um balcão acima dela, indicando quantos viajantes foram processados, por exemplo, nos últimos 10 minutos? O guia pode então direcionar os viajantes para uma fila com base no seu comprimento e na rapidez com que ela está sendo processada. Essa é uma maneira mais eficaz de distribuir a carga, e é o que o algoritmo de balanceamento de carga Least Time no NGINX Plus faz:
Este algoritmo é específico do NGINX Plus porque depende de dados adicionais coletados com as métricas de status estendido do NGINX Plus. Ele é particularmente eficaz em ambientes virtuais ou de nuvem, onde a latência para cada servidor pode variar de forma imprevisível, então o comprimento da fila por si só não é suficiente para estimar o atraso.
Até agora, tivemos um guia (ou seja, balanceador de carga) com uma visão completa das filas e do tempo de resposta no saguão de desembarque. Esse guia tenta fazer a melhor escolha para cada viajante com base nas informações que ele conhece.
Agora considere o que acontece se tivermos vários guias, cada um orientando os viajantes de forma independente. Os guias têm visões independentes do comprimento das filas e dos tempos de espera nas filas – eles consideram apenas os viajantes que enviam para cada fila.
Esse cenário é propenso a um comportamento indesejável, em que todos os guias percebem que uma fila está momentaneamente mais curta e rápida, e todos enviam os viajantes para essa fila. Simulações mostram que esse “comportamento de rebanho” distribui os viajantes de uma forma desequilibrada e injusta. Da mesma forma, vários balanceadores de carga independentes podem sobrecarregar alguns servidores upstream, não importa qual algoritmo de “melhor escolha” você use.
A solução está no algoritmo de balanceamento de carga “poder de duas escolhas”. Em vez de fazer a melhor escolha absoluta usando dados incompletos, com o “poder de duas escolhas” você escolhe duas filas aleatoriamente e escolhe a melhor opção das duas, evitando a pior escolha .
“Poder de duas escolhas” é eficiente de implementar. Você não precisa comparar todas as filas para escolher a melhor opção a cada vez; em vez disso, você só precisa comparar duas. E, talvez de forma não intuitiva, funciona melhor em escala do que os algoritmos de melhor escolha. Ele evita o comportamento indesejado de rebanho pela abordagem simples de evitar a pior fila e distribuir o tráfego com um grau de aleatoriedade.
No NGINX e no NGINX Plus, o método de balanceamento de carga “poder de duas escolhas” é implementado como uma variante do algoritmo Random, por isso o chamamos de Random with Two Choices.
No NGINX Open Source, o Random with Two Choices escolhe entre dois servidores selecionados aleatoriamente com base em qual deles tem menos conexões ativas no momento. Este é o mesmo critério de seleção usado para o algoritmo Least Connections. (Este também é o algoritmo padrão no NGINX Plus e pode ser configurado explicitamente adicionando o parâmetro least_conn
.)
upstream service1 { zona service1 64k; servidor 192.168.1.11; servidor 192.168.1.12; servidor 192.168.1.13; aleatório dois ; }
O NGINX Plus também suporta o parâmetro least_time
, que usa o mesmo critério de seleção do algoritmo Least Time. Assim como acontece com esse algoritmo, você ainda pode escolher entre considerar:
least_time=header
)least_time=last_byte
), como no snippet a seguir. O critério de menor tempo é ideal para situações em que a latência para cada servidor upstream pode variar.upstream service1 { zona service1 64k; servidor 192.168.1.11; servidor 192.168.1.12; servidor 192.168.1.13; aleatório dois least_time=last_byte ; # usar cabeçalho ou last_byte }
O NGINX e o NGINX Plus oferecem suporte a uma variedade de métodos de balanceamento de carga; neste artigo, não consideramos os métodos determinísticos Hash e IP Hash .
Os métodos Least Connections (e para NGINX Plus, Least Time) são muito eficazes no balanceamento de cargas quando o balanceador de carga tem uma visão completa da carga de trabalho atribuída a cada nó e seu desempenho anterior. Eles são menos eficazes quando vários balanceadores de carga estão atribuindo solicitações e cada um tem uma visão incompleta da carga de trabalho e do desempenho.
“Poder de duas escolhas” usa um algoritmo aleatório tendencioso e demonstrou ser eficaz no balanceamento de cargas quando cada balanceador de carga tem uma visão incompleta ou atrasada. Ele evita o “comportamento de rebanho” exibido por outros algoritmos que buscam tomar a melhor decisão em cada solicitação.
Considere Random with Two Choices, a implementação do NGINX do “poder de duas escolhas”, para ambientes de altíssimo desempenho e para cenários de balanceamento de carga distribuído. Um bom caso de uso surge ao utilizar vários controladores Ingress no Kubernetes.
"Esta postagem do blog pode fazer referência a produtos que não estão mais disponíveis e/ou não têm mais suporte. Para obter as informações mais atualizadas sobre os produtos e soluções F5 NGINX disponíveis, explore nossa família de produtos NGINX . O NGINX agora faz parte do F5. Todos os links anteriores do NGINX.com redirecionarão para conteúdo semelhante do NGINX no F5.com."