Tudo que você precisa saber sobre Load Balancing

Como distribuir carga entre servidores evita indisponibilidade e melhora a experiência dos seus usuários.


Como um conceito simples pode trazer grandes resultados

Load Balancing é o conceito de distribuir uma determinada carga entre diferentes lugares.

Vamos imaginar que temos uma carga de 3 toneladas de grãos de soja que precisam ser levadas até outra cidade a 150 km em até, no máximo, 2 horas.

No pátio, temos 3 caminhões disponíveis que suportam até 3,5 toneladas cada, porém… Caso o caminhão esteja muito próximo da carga limite, ele não conseguirá acelerar a mais de 60 km/h. Ou seja, não completará o trajeto no tempo necessário.

Como solucionamos isso?

Três caminhões no pátio precisam levar 3 toneladas de soja até a fábrica a 150 km de distância

Balanceando a carga entre os diferentes caminhões! Dessa forma, conseguimos extrair maior velocidade dos três para a entrega dos grãos em tempo hábil.

Porém, concorda comigo que deslocar 3 veículos tem um alto custo de combustível?

Assim como em software, é necessário tomar a decisão do que vale mais a pena baseando-se em variáveis de interesse do negócio.

No nosso exemplo, poderíamos sacrificar o tempo limite de 2 horas em troca de reduzir a quantidade de caminhões deslocados, ou poderíamos diminuir a carga deslocada, o que reduziria a quantidade de grãos entregues à fábrica.

Agora vamos trazer isso de fato para o contexto de algo bastante comum:

Uma aplicação rodando em uma máquina com recursos insuficientes para receber a quantidade de clientes esperada.

Um único servidor recebendo requisições de todos os clientes e chegando ao limite de recursos

Resultado? Lentidão crescente até a indisponibilidade.

O servidor recebe tanta requisição que simplesmente não consegue responder a todas e para. O que isso significa para o seu projeto e para a sua empresa?

  • Compras canceladas
  • Clientes sendo afetados em diferentes partes do sistema
  • Insatisfação que causa má reputação

É um caminhão tentando levar mais carga do que o permitido e quebrando no caminho.

Como isso pode ser resolvido?

Podemos implementar um sistema de balanceamento estático:

Balanceamento estático: clientes mapeados diretamente para servidores específicos, um deles indisponível

Essa estratégia consiste em mapear estaticamente um cliente ou grupo de clientes para um servidor usando algumas destas técnicas:

  1. Client-Side Direct Routing: O cliente conhece a lista de servidores e decide para qual deve mandar a requisição baseado em algum atributo; ou o cliente recebe o servidor para o qual deve enviar as próximas requisições logo após fazer login.

  2. Subdomínio por Cliente: Comum em sistemas multi-tenant, em que cada subdomínio representa um grupo diferente de clientes e envia as requisições para um IP com um servidor diferente escutando.

  3. HTTP Redirect pela aplicação: Um script que identifica quem é o cliente na entrada e faz um redirecionamento para um servidor específico, onde o cliente continua suas atividades normalmente.

É importante ter em mente que Load Balancing é um conceito que pode atuar em diferentes camadas do modelo OSI (assunto sobre o qual farei um artigo em breve), desde a infraestrutura física até a camada de aplicação.

Mas qual é o problema dessas soluções estáticas?

Como mostrado na imagem, um dos clientes está insatisfeito porque não conseguiu acesso. A causa disso foi a indisponibilidade da instância do serviço que ele iria acessar. Ao dividirmos o tráfego dessa forma, criamos um ponto único de falha (Single Point of Failure).

Além disso, imagine precisar fazer uma atualização em um dos servidores e acabar derrubando a conexão de todos os clientes pendurados nele, ou ter que redirecioná-los manualmente… É um trabalho enorme e muitas vezes inviável.

Portanto, vamos melhorar essa solução adicionando um balanceador de carga dedicado:

Balanceador de carga dedicado distribuindo requisições igualmente entre os servidores

Aqui, todas as requisições passam pelo load balancer antes de chegar ao servidor, e é ele quem escolhe para qual servidor vai direcionar o tráfego.

Por padrão, utilizamos a estratégia Round Robin, que distribui as requisições sequencialmente entre os servidores, mantendo a distribuição previsível e homogênea.

Mas também existem as seguintes estratégias:

  1. Weighted Round Robin (Round Robin Ponderado): Permite atribuir pesos diferentes para cada servidor. É ideal para quando você possui máquinas com capacidades de hardware distintas, distribuindo o tráfego proporcionalmente à capacidade de cada uma

  2. Least Connections (Menos Conexões): Direciona o tráfego para o servidor que possui o menor número de conexões ativas no momento, evitando sobrecarregar servidores que estão processando requisições mais longas.

  3. Least Connections Ponderado (Weighted Least Connections): Além de considerar as conexões ativas do momento, combina a capacidade (peso) de cada servidor na decisão de roteamento.

  4. Tempo de Resposta Ponderado (Weighted Response Time): Esse algoritmo toma a decisão com base na latência (tempo de resposta) do servidor combinada com o número de conexões ativas, garantindo que as requisições vão para o servidor mais rápido disponível.

  5. IP Hash: Utiliza o endereço IP do cliente para gerar uma chave única (hash) que determina qual servidor receberá a requisição. Essa técnica é muito usada para garantir persistência de sessão (Sticky Sessions), fazendo com que o mesmo cliente sempre caia no mesmo servidor.

  6. URL / Resource Hash: Gera um hash com base no caminho da URL solicitada. Muito utilizado em arquiteturas com servidores de cache, pois garante que requisições para um mesmo recurso estático sempre sejam direcionadas para o mesmo servidor de cache.

  7. Random (Aleatório): Escolhe um servidor de destino de forma totalmente aleatória a cada requisição. Pode ser combinado com pesos (Weighted Random) para se adequar ao poder de processamento das máquinas.

Mas de nada adianta escolher bem o próximo servidor se o load balancer não sabe quais servidores estão realmente de pé.

É aqui que entram os health checks: verificações periódicas (geralmente via HTTP, TCP ou ping) que o load balancer faz em cada servidor para confirmar que ele continua respondendo. No momento em que um servidor para de responder, ele é automaticamente removido da lista de destinos possíveis — evitando exatamente aquele cenário de cliente “Indisponível” que vimos lá atrás, só que agora sem depender de um humano notando o problema e tirando o servidor do ar manualmente.

No fim, seja com caminhões ou com servidores, o load balancing resolve sempre o mesmo problema: usar melhor a capacidade que você já tem, sem sobrecarregar nenhuma peça do sistema e sem deixar ninguém parado no meio do caminho.