Alta Disponibilidade (AD) no RuB

Alta Disponibilidade (High Availability - HA) é a capacidade de um sistema permanecer operacional e acessível, mesmo em caso de falha de um ou mais de seus componentes. No contexto do RuB, isso é alcançado através da execução de múltiplas instâncias da aplicação em um cluster, trabalhando em conjunto para processar as requisições dos usuários e as tarefas de background.

Arquitetura de AD

A arquitetura típica de Alta Disponibilidade para o RuB envolve um balanceador de carga posicionado à frente de várias instâncias da aplicação.

graph TD
    User(("Usuários <br/> Web/Mobile")) --> LB{"Load Balancer <br/> (Sticky Sessions)"}
    
    subgraph Cluster_RuB [Cluster RuB]
        LB --> RuB1[RuB Nó A]
        LB --> RuB2[RuB Nó B]
        LB --> RuB3[RuB Nó C]
    end

    RuB1 --> DB[(Banco de Dados Compartilhado)]
    RuB2 --> DB
    RuB3 --> DB
    RuB1 --> Storage[(Storage Compartilhado)]
    RuB2 --> Storage
    RuB3 --> Storage

O Papel do Load Balancer e a Importância do Session Affinity

O Load Balancer (Balanceador de Carga) é o componente crítico que recebe as requisições dos usuários e as distribui inteligentemente entre as instâncias do RuB.

Para o correto funcionamento do ecossistema RuB, o balanceadordeve obrigatoriamenteestar configurado com o mecanismo deSession Affinity (Sticky Sessions)(também conhecido como Afinidade de Sessão ou Persistência de Sessão).

Por que a afinidade de sessão é um requisito mandatório? Diferente de aplicações puramente stateless, o RuB gerencia sessões complexas de usuários que podem manter estados temporários na memória do servidor para garantir alta performance e produtividade. Portanto, o balanceador deve garantir que, uma vez estabelecida a conexão inicial, todas as requisições futuras daquela mesma sessão sejam direcionadas estritamente para o mesmo nó. Sem o suporte aSession Affinity (Sticky Sessions), o usuário poderá enfrentar desconexões frequentes e perda de contexto durante a navegação.

Referências Cruzadas para AD

O funcionamento em Alta Disponibilidade impacta diversos módulos do sistema. Consulte os documentos abaixo para detalhes específicos:

*Logs: Em ambientes AD, a rastreabilidade é feita através do identificador da instância, permitindo saber exatamente qual servidor gerou cada linha de log. *Deploy: Contém orientações sobre a instalação de múltiplos nós e a importância de manter arquivos de configuração distintos para as identidades de cada instância. *Scheduler: Explica o mecanismo deFailovereOrquestração, garantindo que tarefas agendadas (Jobs) sejam executadas de forma resiliente e sem duplicidade entre as instâncias do cluster.

Configurações Necessárias (RUB AD)

Para que o RuB opere corretamente em modo AD, certas chaves devem ser configuradas no arquivo config.ini ou passadas como parâmetros de sistema da JVM (-D).

1. Ativação do Modo Cluster

O framework utiliza a propriedade de sistema abaixo para alternar comportamentos internos (como gestão de cache distribuído e orquestração resiliente do scheduler) para o modo AD. Sem esta chave, o sistema operará em modo standalone, o que pode causar conflitos de execução em um cluster.

# Define se o sistema deve operar com comportamentos de cluster (na classe RuB)
high-availability-mode=true

2. Configuração dos Executores do Scheduler

Cada nó deve ser identificado de forma única e persistente. Esta identificação permite que o orquestrador gerencie qual nó é o responsável pelas tarefas e como as tarefas devem ser redistribuídas (failover) em caso de queda.

É mandatório que cada instância possua um identificador universal único (UUID) fixo.Nunca utilize o mesmo UUID para instâncias distintas no mesmo cluster.

# Identificador único universal (OBRIGATÓRIO ser um UUID diferente por instância)
# Este ID vincula o executor às suas respectivas Tags no agendador.
sched.executor.id=550e8400-e29b-41d4-a716-446655440000

# Identificador único da instância para registro no portal de monitoramento
com.gicbrasil.rub.instance.identifier=550e8400-e29b-41d4-a716-446655440000

# Descrição amigável para identificação visual
com.gicbrasil.rub.instance.description=Servidor de Produção - Nó 01

3. Identificação da Empresa (idEmpresa)

A identificação da empresa deve ser consistente entre todos os nós e coincidir com o valor definido no arquivo contexts.ini.

# Possibilidade 1: Chave simplificada
idEmpresa=17

# Possibilidade 2: Chave qualificada
com.gicbrasil.rub.idEmpresa=17

4. Configurações Complementares

*com.gicbrasil.rub.instance.isProductionEnv: Indica se o ambiente é de produção. Valor padrão: true.

Opções de Load Balancer e Gateway

Embora a GIC forneça uma solução nativa (RuB Gateway), o sistema é compatível com soluções de mercado, desde que suportemSession Affinity (Sticky Sessions).

1. Soluções de Mercado

*F5 Big-IP *Citrix ADC (NetScaler) *HAProxy *Nginx *Cloud Load Balancers(AWS ALB, Azure LB, etc.)

2. RuB Gateway (Nativo GIC)

Solução baseada em Spring Cloud Gateway com suporte nativo a Sticky Sessions.

server:
  port: 8099

spring:
  application:
    name: rub-sticky-gateway
  cloud:
    gateway:
      httpclient:
        preserveHostHeader: true
      routes:
        - id: backend-load-balancer
          uri: http://host.docker.internal:7080
          predicates:
            - Path=/**
          filters:
            - StickySession

gateway:
  load-balancer:
    service-id: rub-static-backend
    sticky-cookie-name: RUB-LB-AFFINITY
    targets:
      - id: backend-a
        uri: http://host.docker.internal:7080
      - id: backend-b
        uri: http://host.docker.internal:7081

3. Exemplo de Configuração com Nginx

http {
    map $cookie_RUB_NODE $target_backend {
        "rub1"  127.0.0.1:8001;
        "rub2"  127.0.0.1:8002;
        default "backend_cluster";
    }

    map $upstream_addr $cookie_value {
        "127.0.0.1:8001" "rub1";
        "127.0.0.1:8002" "rub2";
    }

    upstream backend_cluster {
        server 127.0.0.1:8001 max_fails=3 fail_timeout=30s;
        server 127.0.0.1:8002 max_fails=3 fail_timeout=30s;
    }

    server {
        listen 8000;
        location / {
            proxy_pass http://$target_backend;
            proxy_set_header Host $host;
            proxy_intercept_errors on;
            error_page 502 503 504 = @fallback;
            add_header Set-Cookie "RUB_NODE=$cookie_value; Path=/; HttpOnly" always;
        }
        location @fallback {
            proxy_pass http://backend_cluster;
            add_header Set-Cookie "RUB_NODE=$cookie_value; Path=/; HttpOnly" always;
        }
    }
}