Skip to content
mobius1qwe edited this page Nov 2, 2026 · 1 revision

Home > Colocar no ar > Balanceador e proxy reverso 🚧

Balanceador e proxy reverso

Important

Em desenvolvimento (2.0). Ainda não está numa versão lançada e pode mudar.

Vale para a 2.0 · Delphi XE em diante e Lazarus/FPC 3.2 em diante · Nível: intermediário

Em uma frase: um servidor RAL pode repassar os pedidos de um caminho a um grupo de servidores de trás, escolhendo um por vez (pesos, menos conexões, hash), tirando da roda o que caiu e voltando com ele quando responde: um "API gateway" dentro da sua aplicação.

Você vai precisar: o pacote RALModuleProxyPackage (componentes TRALUpstream e TRALProxyModule, paleta RAL - Modules).

O básico

Grupo := TRALUpstream.Create(Self);
Grupo.Servers.AddServer('http://10.0.0.11:8080');
Grupo.Servers.AddServer('http://10.0.0.12:8080', 2); // recebe o dobro

Proxy := TRALProxyModule.Create(Self);
Proxy.Rules.AddRule('/api', Grupo).StripPrefix := True; // /api/clientes -> /clientes
Proxy.Server := Servidor;

O servidor da frente continua um servidor RAL: o motor, o HTTPS e todos os plugins valem antes do repasse (autenticação, limite de pedidos, lista de IPs, log). Rotas próprias do servidor convivem com o proxy; as regras são lidas em ordem, a primeira que casa vence (Path, e Host quando preenchido).

Como o servidor é escolhido (Policy)

Policy escolhe
lpRoundRobin (padrão) cada um na sua vez, pelo peso, sem rajada (o algoritmo do NGINX)
lpLeastConnections o que tem menos pedidos em curso para o seu peso
lpIPHash o mesmo endereço de cliente vai sempre ao mesmo servidor
lpConsistentHash a mesma chave (HashBy: caminho, cabeçalho ou cookie HashName) vai ao mesmo servidor; um servidor que sai move só as chaves dele
lpRandomTwo dois ao acaso, fica o menos ocupado
  • Backup num servidor: só recebe quando nenhum outro está disponível.
  • Down: tirado da roda à mão. MaxConnections: no máximo N pedidos em curso.
  • Sticky.Enabled: o proxy responde um cookie (ralupstream) e o cliente que o traz volta ao mesmo servidor enquanto ele estiver no ar.

Quando um servidor cai

  • Passivo: MaxFails falhas (sem resposta) tiram o servidor por FailTimeout ms; depois ele ganha outra chance.
  • Ativo: HealthCheck.Enabled faz um GET em HealthCheck.Path de cada servidor a cada Interval ms; Falls falhas seguidas o tiram, Rises acertos o trazem de volta. Combina com o TRALHealthPlugin nos servidores de trás (Path := '/health/ready').
  • OnServerChange avisa quando um sai ou volta.
  • Um pedido que não chegou a nenhum servidor vai ao próximo (MaxAttempts, padrão 2) só se o método é idempotente (GET, HEAD, PUT, DELETE...) e nada foi enviado ao cliente ainda: um POST nunca é repetido. Sem servidor disponível: 503; nenhum respondeu: 502; tempo esgotado: 504.
  • ConnectTimeout (padrão 5 s) é o tempo para conectar a um servidor antes de tentar o próximo; RequestTimeout (60 s), o tempo sem dado na resposta.

O que passa e o que não passa

  • O corpo do pedido vai como o motor recebeu; a resposta volta em pedaços conforme chega (onde o motor do servidor da frente responde em fluxo), com memória constante.
  • Não passam os cabeçalhos de salto a salto (Connection e os que ele nomeia, Keep-Alive, Transfer-Encoding, Upgrade, Proxy-*...).
  • AddForwarded (padrão) manda X-Forwarded-For, -Proto e -Host; nos servidores de trás, o TRALForwardedPlugin lê isso. O X-Forwarded-For que chegou é trocado pelo cliente que o proxy conhece (ClientInfo.IP): de fora, ele é o que o cliente quiser, e os servidores de trás confiam no proxy. Atrás de outro proxy, ligue o TRALForwardedPlugin também no servidor da frente (o IP fica o real), ou KeepForwardedChain para acrescentar à cadeia em vez de trocar.
  • Via põe o cabeçalho Via nos dois sentidos.
  • Um redirecionamento do servidor de trás volta ao cliente como veio (não é seguido), com o Location do servidor de trás tornado relativo ao proxy.
  • Os Set-Cookie passam inteiros, com os atributos. Os cookies nunca ficam guardados no proxy: cada usuário recebe só os seus.

Estatística

StatsPath := '/proxy/stats' cria uma rota com, por servidor: disponível, pedidos em curso, pedidos, erros e latência p50/p95/p99, em JSON, ou no formato do Prometheus com ?format=prometheus (ral_upstream_up, ral_upstream_requests_total...). Proteja essa rota (autenticação ou lista de IPs).

Desempenho

O custo é o do motor da frente mais uma chamada de TRALClient por pedido (conexão mantida com cada servidor de trás). Medido nesta máquina de desenvolvimento, servidor mORMot2 na frente e três atrás, /ping: cerca de 60% do que o NGINX faz na mesma bancada. Bom para um gateway dentro da aplicação; para só balancear muito tráfego, use um balanceador dedicado na frente.

Erros comuns

Sintoma Causa Solução
404 num caminho que devia ir para trás nenhuma regra casou (o Path conta segmentos inteiros: /api não pega /apis) confira Path, Host e o Domain do módulo
503 nenhum servidor disponível (todos Down, fora pela saúde ou cheios) veja a estatística
502 depois de alguns segundos o servidor de trás não aceita conexão confira o endereço; ConnectTimeout menor faz o próximo ser tentado antes
o servidor de trás vê o IP do proxy ele não lê X-Forwarded-For ligue o TRALForwardedPlugin nele
um usuário recebe o cookie de outro (não acontece com o TRALProxyModule) um proxy feito à mão com TRALClient precisa de KeepCookies := False

Veja também

Clone this wiki locally