O balanceamento de carga em servidores proxy distribui as requisições recebidas dos clientes entre vários servidores backend para otimizar o uso de recursos, maximizar a vazão, minimizar o tempo de resposta e garantir alta disponibilidade. Esse mecanismo impede que um único servidor se torne um gargalo ou um ponto único de falha, direcionando o tráfego de forma inteligente para um conjunto de recursos disponíveis.
Servidores proxy, em especial os proxies reversos, ficam entre os dispositivos dos clientes e um grupo de servidores de aplicação backend. Quando um cliente envia uma requisição, o proxy a intercepta e, com base nos algoritmos configurados e na saúde dos servidores, encaminha a requisição para um dos servidores backend. Essa camada de abstração é fundamental para gerenciar o tráfego web com eficiência em sistemas distribuídos modernos.
Benefícios do balanceamento de carga
Implementar balanceamento de carga por meio de um servidor proxy traz várias vantagens críticas para a arquitetura e o desempenho do sistema:
- Alta disponibilidade e tolerância a falhas: ao distribuir o tráfego, se um servidor backend falhar, o balanceador de carga redireciona automaticamente as requisições para os servidores saudáveis restantes, evitando a interrupção do serviço.
- Escalabilidade: os sistemas podem escalar horizontalmente com a adição de mais servidores backend. O balanceador de carga integra novos servidores ao pool de forma transparente, permitindo que a infraestrutura absorva o aumento de tráfego sem downtime.
- Melhor desempenho: as requisições são distribuídas para servidores menos ocupados ou com mais capacidade, o que resulta em tempos de resposta mais rápidos e em uma experiência melhor para o usuário.
- Uso eficiente de recursos: o balanceamento de carga garante que os recursos computacionais de todos os servidores backend sejam aproveitados de forma efetiva, evitando que alguns servidores fiquem sobrecarregados enquanto outros permanecem ociosos.
Algoritmos de balanceamento de carga
Diferentes algoritmos determinam como um servidor proxy distribui as requisições recebidas. A escolha do algoritmo depende dos requisitos específicos da aplicação, como persistência de sessão, capacidade dos servidores e padrões de tráfego.
Round Robin
As requisições são distribuídas sequencialmente para cada servidor do pool de backend. É um método simples e stateless, que não leva em conta a carga nem a capacidade do servidor.
- Prós: fácil de implementar, distribui as requisições de forma uniforme ao longo do tempo.
- Contras: não considera o tempo de processamento do servidor nem as conexões já existentes, o que pode sobrecarregar um servidor quando os tempos de processamento variam.
- Caso de uso: adequado para servidores de capacidade equivalente, com tempos de processamento semelhantes para todas as requisições.
Least Connection
O proxy direciona as novas requisições para o servidor com o menor número de conexões ativas. Esse algoritmo é dinâmico e considera a carga de trabalho atual de cada servidor.
- Prós: distribui a carga de forma mais inteligente que o Round Robin, sendo eficaz para conexões de longa duração.
- Contras: exige que o proxy mantenha o estado das conexões ativas; pode não ser ideal se os tempos de processamento das conexões variarem muito.
- Caso de uso: aplicações com durações de conexão variáveis, como serviços de chat ou APIs de long polling.
IP Hash
O endereço IP do cliente é usado para gerar um hash, que determina qual servidor backend recebe a requisição. Isso garante que um cliente específico sempre se conecte ao mesmo servidor, oferecendo persistência de sessão.
- Prós: garante a fixação de sessão sem exigir gerenciamento de sessão no lado do servidor nem cookies.
- Contras: se o IP do cliente mudar, ele pode ser roteado para outro servidor; pode causar distribuição desigual se o tráfego vindo de determinados IPs for desproporcionalmente alto.
- Caso de uso: aplicações dependentes de estado, nas quais as sessões do usuário precisam persistir em um único servidor, e os IPs dos clientes são relativamente estáveis.
Weighted Round Robin / Weighted Least Connection
São extensões das versões básicas, nas quais os servidores recebem um peso conforme sua capacidade (por exemplo, CPU, memória, banda de rede). Servidores com pesos maiores recebem uma parcela proporcionalmente maior das requisições (Weighted Round Robin) ou têm prioridade na seleção do servidor com menos conexões (Weighted Least Connection).
- Prós: considera capacidades heterogêneas dos servidores, garantindo que as máquinas mais potentes assumam mais carga.
- Contras: exige uma configuração de pesos precisa; uma configuração errada pode criar gargalos.
- Caso de uso: ambientes com servidores backend de especificações de hardware ou poder de processamento diferentes.
Least Response Time
O proxy direciona as requisições para o servidor que apresenta o tempo de resposta mais rápido nas verificações de saúde ou em requisições anteriores. Esse algoritmo prioriza o desempenho.
- Prós: otimiza a resposta global mais rápida, adaptando-se ao desempenho do servidor em tempo real.
- Contras: exige monitoramento constante dos tempos de resposta dos servidores, o que adiciona overhead ao proxy.
- Caso de uso: aplicações críticas de desempenho, nas quais minimizar a latência é prioridade máxima.
URL Hash / roteamento baseado em conteúdo
As requisições são roteadas com base em elementos específicos da própria requisição, como o caminho da URL, os parâmetros de query ou os cabeçalhos HTTP. Isso permite encaminhar tipos específicos de requisição para serviços backend especializados.
- Prós: viabiliza arquiteturas de microsserviços e uma gestão granular do tráfego.
- Contras: mais complexo de configurar e gerenciar; exige inspeção profunda de pacotes pelo proxy.
- Caso de uso: microsserviços, API gateways ou roteamento de tipos específicos de conteúdo para servidores dedicados (por exemplo, imagens para um servidor de mídia, chamadas de API para um servidor de API).
Verificações de saúde e failover
Um balanceamento de carga eficaz depende do monitoramento contínuo da saúde dos servidores backend. Os proxies executam verificações de saúde para determinar se um servidor está operacional e apto a atender requisições.
- Mecanismo: as verificações de saúde normalmente envolvem o envio de requisições periódicas (por exemplo, sondas TCP, requisições HTTP GET para um endpoint específico) aos servidores backend.
- Detecção: se um servidor não responder dentro do tempo limite ou retornar um status de erro (por exemplo, HTTP 5xx), o proxy o marca como não saudável.
- Failover: os servidores não saudáveis são removidos automaticamente do pool de servidores ativos, impedindo que requisições sejam enviadas a eles. Assim que um servidor se recupera e passa nas verificações de saúde, ele é readicionado ao pool automaticamente.
Esse mecanismo automatizado de failover é essencial para manter a alta disponibilidade e garantir um serviço ininterrupto.
Tipos de servidores proxy para balanceamento de carga
Embora o conceito de balanceamento de carga possa ser aplicado de forma ampla, sua implementação principal no contexto da distribuição de requisições de clientes para vários servidores backend costuma ser feita por proxies reversos.
Proxies reversos
Os proxies reversos são posicionados à frente de um ou mais servidores web. Eles interceptam as requisições dos clientes e as encaminham para um servidor backend apropriado, atuando como gateway. Esse é o caso de uso comum de balanceamento de carga para serviços backend.
- Exemplos: Nginx, HAProxy, Envoy, Apache (com mod_proxy_balancer).
Forward proxies
Os forward proxies são usados pelos clientes para acessar recursos externos. Embora possam realizar balanceamento de carga, isso normalmente serve para distribuir requisições de saída entre vários nós de saída ou para gerenciar o acesso a diferentes serviços externos, e não para balancear requisições de entrada destinadas aos servidores backend da própria organização. O foco principal deste artigo é o balanceamento de carga com proxy reverso.
Implementação prática com servidores proxy comuns
Exemplo com Nginx
O Nginx é uma escolha popular para proxy reverso e balanceamento de carga por causa do seu desempenho e do seu conjunto robusto de recursos.
http {
upstream backend_servers {
# Round Robin (padrão)
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;
# Least Connection
# least_conn;
# server backend1.example.com;
# server backend2.example.com;
# Weighted Round Robin
# server backend1.example.com weight=3;
# server backend2.example.com weight=1;
}
server {
listen 80;
server_name your_domain.com;
location / {
proxy_pass http://backend_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
Nesta configuração do Nginx, o bloco upstream define um grupo de servidores backend. A diretiva proxy_pass, dentro do bloco server, direciona então todas as requisições recebidas para your_domain.com a esse grupo backend_servers, no qual o Nginx aplica o algoritmo de balanceamento de carga configurado.
Exemplo com HAProxy
O HAProxy é um balanceador de carga e servidor proxy TCP/HTTP de alto desempenho, especialmente indicado para sites de alto tráfego.
frontend http_front
bind *:80
default_backend http_back
backend http_back
balance roundrobin # Ou leastconn, source (para IP hash), etc.
option httpchk GET /health
server app1 192.168.1.10:80 check
server app2 192.168.1.11:80 check
server app3 192.168.1.12:80 check
Esta configuração do HAProxy define um frontend que escuta na porta 80 e encaminha o tráfego para o backend http_back. O bloco backend especifica o algoritmo de balanceamento de carga (balance roundrobin) e lista os servidores backend individuais. A linha option httpchk GET /health configura uma requisição HTTP GET para /health em cada servidor como verificação de saúde.
Comparação dos algoritmos de balanceamento de carga
| Algoritmo | Descrição | Prós | Contras | Melhor caso de uso |
|---|---|---|---|---|
| Round Robin | Distribuição sequencial para cada servidor. | Simples, distribuição uniforme ao longo do tempo. | Ignora carga/capacidade do servidor, risco de sobrecarga. | Servidores homogêneos, aplicações stateless. |
| Least Connection | Para o servidor com menos conexões ativas. | Distribui a carga conforme a atividade atual, melhor para conexões longas. | Exige rastreamento de estado, tempos de processamento variam. | Conexões de longa duração, cargas dinâmicas. |
| IP Hash | Baseado no hash do IP do cliente. | Garante fixação de sessão sem cookies. | Distribuição desigual se IPs específicos gerarem muito tráfego. | Aplicações com estado, IPs de cliente estáveis. |
| Weighted Round Robin | Sequencial, mas servidores com pesos maiores recebem mais. | Considera capacidades heterogêneas dos servidores. | Exige pesos precisos, erro de configuração cria gargalo. | Servidores com poder de processamento/recursos diferentes. |
| Least Response Time | Para o servidor com resposta mais rápida nas verificações de saúde. | Otimiza o desempenho mais rápido, adapta-se à carga em tempo real. | Overhead maior por causa do monitoramento constante. | Aplicações críticas de desempenho, necessidade de baixa latência. |
| URL Hash / baseado em conteúdo | Baseado no caminho da URL, cabeçalhos ou outros dados da requisição. | Viabiliza microsserviços, gestão granular do tráfego. | Complexo de configurar, exige inspeção mais profunda de pacotes. | Microsserviços, API gateways, roteamento de conteúdo especializado. |
Conceitos avançados de balanceamento de carga
Persistência de sessão (sticky sessions)
Em aplicações com estado, nas quais os dados de sessão do usuário ficam armazenados em um servidor backend específico, é essencial que as requisições seguintes do mesmo cliente sejam roteadas para esse mesmo servidor. Isso é conhecido como persistência de sessão ou sticky sessions.
- Métodos:
- Baseado em cookie: o proxy insere um cookie no navegador do cliente com informações sobre o servidor backend para o qual ele foi roteado inicialmente. As requisições seguintes incluem esse cookie, permitindo que o proxy as direcione para o servidor correto.
- IP Hash: como descrito acima, o roteamento baseado no endereço IP do cliente garante a fixação, embora tenha limitações se o IP mudar ou se vários usuários compartilharem um IP (por exemplo, atrás de um NAT).
Terminação SSL
A terminação SSL (ou SSL offloading) consiste em o servidor proxy descriptografar o tráfego HTTPS recebido antes de encaminhá-lo como HTTP puro para os servidores backend.
- Benefícios:
- Desempenho: retira dos servidores backend a descriptografia SSL/TLS, que consome muita CPU, permitindo que eles se concentrem na lógica da aplicação.
- Backend simplificado: os servidores backend não precisam gerenciar certificados SSL nem criptografia, o que simplifica sua configuração.
- Gestão centralizada de certificados: todos os certificados SSL são gerenciados de forma centralizada no proxy.
Cache
Muitos servidores proxy também podem funcionar como proxies de cache. Ao armazenar conteúdo acessado com frequência (por exemplo, arquivos estáticos, imagens, CSS, JavaScript), o proxy consegue entregá-lo diretamente aos clientes sem encaminhar a requisição para um servidor backend.
- Benefícios:
- Menor carga no backend: reduz significativamente o número de requisições que chegam aos servidores backend.
- Tempos de resposta melhores: o conteúdo servido a partir do cache costuma ser muito mais rápido do que buscá-lo em um backend.
- Menor uso de banda: menos dados precisam ser transferidos entre o proxy e os servidores backend.
