Plataformas, Microsserviços, DevOps e APIs · Hands-on 7

Hands-on 7 — Balanceador de carga

Colocar o Nginx na frente do gateway e escalá-lo horizontalmente

Um gateway para tudo

Todo o tráfego externo entra por uma única instância do gateway. O que acontece sob carga contínua?

  • Um processo, um pool de threads, nenhuma redundância — o gateway vira o gargalo.
  • Se ele cair, a plataforma inteira fica inacessível.
  • A solução: rodar várias instâncias idênticas e espalhar as requisições — escalonamento horizontal.

Forward × proxy reverso

Forward proxy

Fica na frente dos clientes. O servidor vê o endereço do proxy, não o do cliente.

Firewalls corporativos, filtragem de conteúdo, VPN, Tor.

Proxy reverso

Fica na frente dos servidores. O cliente vê só o proxy, nunca os backends.

Balanceamento de carga, terminação SSL, cache, rate limiting.

Aqui o Nginx é um proxy reverso: o único componente exposto, espalhando o tráfego por réplicas do gateway que os clientes nunca veem.

Camada 4 × Camada 7

Camada 4 — Transporte Camada 7 — Aplicação
Roteia por endereço IP e porta TCP/UDP caminho da URL, cabeçalhos, cookies, corpo
Inspeciona HTTP? não — encaminha fluxos de bytes sim — pode reescrever requisições e respostas
Velocidade custo mínimo, extremamente rápido pequeno custo, desprezível na maioria dos casos
Permite qualquer protocolo TCP/UDP sticky sessions, A/B, roteamento por caminho
Exemplos AWS NLB, HAProxy em modo TCP Nginx, Traefik, AWS ALB

Algoritmos de balanceamento

Algoritmo Comportamento Indicado para
Round Robin um por servidor, em ordem workloads uniformes, réplicas iguais
Least Connections servidor com menos conexões ativas requisições longas ou variáveis
IP Hash o IP do cliente escolhe o servidor afinidade de sessão (apps com estado)
Weighted Round Robin fatia proporcional a um peso servidores de capacidades diferentes
Random servidor escolhido ao acaso clusters muito grandes

Arquitetura

Antes

internet → :8080 gateway → auth, account → banco de dados

O gateway é exposto diretamente.

Depois

internet → :8080 lb (Nginx :80) → gateway ×3 → auth, account → banco de dados

Só o Nginx é acessível de fora da rede Docker.

Passos: 1 nginx.conf → 2 compose.yaml (lb + réplicas do gateway) → 3 executar e verificar.

1 · setup/nginx.conf

http {
    upstream gateways {
        server gateway:8080;
    }
    server {
        listen 80;
        location / {
            proxy_pass         http://gateways;
            proxy_set_header   X-Real-IP $remote_addr;
            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

Trecho; o arquivo também define Host e X-Forwarded-Proto, além de events { worker_connections 1024; }.

Diretivas principais

Diretiva Finalidade
upstream gateways o pool de backends; o DNS do Docker expande gateway:8080 para os IPs de todas as réplicas
(sem linha de algoritmo) Round Robin padrão; least_conn; mandaria a próxima requisição → menos conexões ativas
proxy_pass encaminha a requisição para o pool upstream
X-Real-IP IP original do cliente para o backend
X-Forwarded-For acrescenta o IP do cliente à cadeia de encaminhamento (logs, auditoria)
X-Forwarded-Proto se a requisição original era HTTP ou HTTPS

Algoritmo dentro do upstream: nenhum = Round Robin · least_conn; · ip_hash; · random; · server gateway:8080 weight=3;

2 · Docker Compose

  lb:
    image: nginx:latest
    ports:
      - "8080:80"
    volumes:
      - ./setup/nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - gateway
  gateway:
    build:
      context: ./gateway-service
      dockerfile: Dockerfile
    # ports removed
    deploy:
      replicas: 3
  • O gateway não tem ports — só é acessível pelo lb. depends_on: o Nginx precisa achar o gateway ao iniciar.
  • Remova hostname: gateway: um hostname não pode ir para vários containers. O nome de serviço gateway continua resolvendo.

Porta 8080 do host → Nginx (80): os clientes continuam chamando http://localhost:8080. O repositório mantém replicas: 1; use 3 para ver o balanceamento.

Como o Nginx encontra as réplicas

  1. O Compose sobe 3 réplicas do gateway.
  2. O DNS interno do Docker resolve o nome gateway para o IP de cada réplica.
  3. O Nginx consulta esse registro uma vez, na inicialização, e monta o pool upstream.

Réplicas adicionadas depois ficam invisíveis para o Nginx até ele resolver o nome de novo:
docker compose exec lb nginx -s reload

3 · Executar e verificar

docker compose up -d --build
docker compose ps -a        # lb + gateway-1, -2, -3, no ports on the gateways
for i in {1..9}; do curl -s http://localhost:8080/health-check; echo; done
docker compose logs gateway --tail 30
  • O /health-check responde o hostname da réplica: a saída alterna entre os três gateways.
  • Todas as requisições em uma réplica? O Nginx subiu antes de as réplicas estarem prontas → docker compose restart lb.

Escalar em tempo de execução

docker compose up -d --scale gateway=5     # add replicas, no rebuild
docker compose exec lb nginx -s reload     # re-query Docker DNS
docker compose ps gateway                  # confirm the count
docker compose up -d --scale gateway=1     # scale down

Se uma réplica cair, o Docker a reinicia e o Nginx continua roteando para as saudáveis: a falha é transparente para os clientes.

Pontos-chave

  1. Um único gateway é um gargalo e um ponto único de falha; réplicas resolvem os dois.
  2. O Nginx funciona como proxy reverso: o único componente exposto, escondendo os backends.
  3. L4 roteia por IP e porta; L7 (Nginx) entende HTTP e roteia por caminho, cabeçalho ou cookie.
  4. O algoritmo fica no bloco upstream: Round Robin por padrão, ou least_conn;, ip_hash;, random;.
  5. O DNS do Docker transforma gateway:8080 em todos os IPs das réplicas — mas o Nginx só resolve na inicialização.
  6. Depois de escalar, recarregue o Nginx (nginx -s reload) para que ele veja as novas réplicas.

Roteiro: (1) por que um único gateway é um gargalo; (2) forward × proxy reverso; (3) L4 × L7, algoritmos; (4) nginx.conf; (5) compose: nginx + réplicas do gateway; (6) executar, verificar, escalar em tempo de execução.

Pergunte primeiro. O balanceador de carga é o que faz "várias instâncias idênticas" parecerem um só serviço.