Pular para conteúdo

Acervo original preservado

Este conteúdo histórico pode conter propostas ou instruções anteriores ao checkout atual. Consulte Arquitetura para o comportamento documentado e Tutoriais para as ressalvas operacionais.

Ambiente local e propostas experimentais — sem adoção corporativa

Istio e Kubernetes Gateway API citados neste acervo são experimentos exclusivos do ambiente local. Recomendações históricas não representam decisões aprovadas nem a exposição oficial de DEV, STAGING ou PROD. Helm e Helmfile são ferramentas locais. Consulte Estudos e experimentos.

Alias amigável para tenant no Gateway

1. Contexto

Atualmente, o acesso às rotas do gateway é realizado via subdomínio baseado no tenantId, no formato:

{tenantId}.gateway.totvs.app

O tenantId é um UUID4, o que gera problemas de:

  • baixa legibilidade
  • dificuldade de uso por usuários finais
  • baixa aderência a padrões de mercado (ex: empresa-x.api.com)

Objetivo

Permitir que o usuário defina um alias amigável para o tenant, possibilitando acesso via:

{alias}.gateway.totvs.app

Exemplo:

acme.gateway.totvs.app → tenantId: 507f1f77bcf86cd799439011

2. Problema

A resolução de alias requer:

  • leitura dinâmica de dados (base persistida)
  • baixa latência (executa no data plane)
  • consistência eventual aceitável
  • alta frequência de leitura

Ou seja, não é apenas um problema de DNS ou roteamento — é um problema de resolução de identidade multi-tenant em tempo de requisição.


3. Opções de Arquitetura

3.1 Resolver via Proxy dedicado (Go + cache em memória)

Descrição

  • Criar um microserviço proxy antes do security-checker
  • Mantém um mapa alias → tenantId em memória
  • Atualizações via RabbitMQ + sincronização periódica
  • Reescreve a URI antes de encaminhar

Vantagens

  • separação clara de responsabilidade
  • pode ser reutilizado por outros serviços

Desvantagens

  • adiciona latência (novo hop), baixo impacto
  • aumenta complexidade operacional
  • duplicação de lógica de cache/invalidação
  • dificulta debugging (reescrita implícita de URI)

Conclusão:

Não recomendado — custo maior que o benefício.


3.2 Resolver via Envoy / Gateway API / Ingress

Descrição

  • Configurar resolução de alias diretamente na camada de rede
  • Atualizar dinamicamente mapeamentos no proxy

Vantagens

  • resolução antecipada (na borda)
  • reduz carga nos microserviços

Desvantagens

  • alta complexidade (config dinâmica, xDS, sync)
  • acopla regra de negócio à infraestrutura
  • difícil manter consistência com banco de dados
  • difícil observabilidade

Conclusão:

Não recomendado — problema não é de roteamento, é de domínio.


3.3 Resolver no gateway-security-checker (sem cache distribuído)

Descrição

  • Resolver alias diretamente no checker
  • Cache local em memória por instância
  • fallback direto para MongoDB

Vantagens

  • simples de implementar
  • sem novas dependências
  • regra próxima do domínio de segurança

Desvantagens

  • miss impacta banco
  • inconsistência entre instâncias possível

Conclusão:

Boa para primeira versão (MVP).


3.4 Resolver no gateway-security-checker com cache distribuído (Recomendado)

Descrição

  • Resolução feita no checker
  • cache em múltiplos níveis:
    • arquivo em volume (hot path)
    • MongoDB (fonte de verdade)

Vantagens

  • baixa latência
  • escalável horizontalmente
  • consistente entre instâncias
  • simples operacionalmente comparado a proxy/envoy

Desvantagens

  • requer Redis
  • lógica de cache mais elaborada

Conclusão:

Opção recomendada


3.5 Resolver no gateway-security-checker utilizando volume persistente como cache compartilhado

Descrição

  • Resolver alias diretamente no gateway-security-checker
  • Utilizar um arquivo em volume persistente como cache compartilhado entre instâncias
  • Manter MongoDB como fonte de verdade
  • Atualizar o arquivo a partir de eventos ou sincronização periódica

Vantagens

  • evita introdução do Redis como nova dependência
  • pode parecer mais simples operacionalmente em uma primeira análise
  • permite manter um snapshot local dos aliases
  • pode ser útil como mecanismo auxiliar de recuperação

Desvantagens

  • volume persistente não é um cache distribuído
  • concorrência entre múltiplas réplicas exige controle de lock
  • risco de leitura de arquivo parcialmente atualizado
  • maior complexidade para invalidação consistente
  • latência de I/O tende a ser maior que Redis/memória
  • comportamento depende do tipo de storage utilizado no Kubernetes
  • pode se tornar gargalo em cenários de alta leitura
  • dificulta observabilidade de hit/miss e tempo de resolução
  • adiciona acoplamento entre aplicação e filesystem compartilhado

Conclusão

Não recomendado como cache principal.

Apesar de reduzir uma dependência externa, o uso de volume persistente troca um problema conhecido e bem suportado por Redis por uma solução mais frágil para ambiente distribuído.

O volume persistente pode ser considerado apenas como mecanismo auxiliar, por exemplo, para manter um snapshot local de emergência caso Redis e MongoDB estejam temporariamente indisponíveis.

Para o fluxo principal de resolução de alias, a abordagem recomendada continua sendo:

  • cache local em memória
  • Redis como cache distribuído
  • MongoDB como fonte de verdade

Essa combinação atende melhor aos requisitos de baixa latência, alta frequência de leitura, escala horizontal e consistência eventual aceitável.


4. Arquitetura Recomendada

Fluxo de resolução

  1. Request chega com host:

    acme.gateway.totvs.app
    
  2. Extrair subdomínio:

    acme
    
  3. Resolver:

    • se for UUID4 → usar direto
    • senão:
      • volume persistente
      • MongoDB (através de microserviço)
  4. Injetar no contexto:

    x-tenant-id: 507f1f77bcf86cd799439011
    x-tenant-alias: acme
    
  5. Continuar fluxo normal


5. Estratégia de Cache

5.1 Modelo de cache em camadas

Camada Função
Memória acesso ultra rápido
Redis compartilhamento global
MongoDB fonte de verdade

5.2 Fluxo de leitura

1. cache local
2. Redis
3. Mongo
4. popular Redis + cache local

5.3 Estratégia de invalidação

Evento via RabbitMQ

  • evento: tenant-alias.updated
  • payload:
{
  "alias":"acme",
  "tenantId":"507f1f77bcf86cd799439011",
  "action":"UPDATED"
}

Comportamento

  • atualizar Redis
  • invalidar cache local

5.4 TTL sugerido

Camada TTL sugerido
Memória 5 minutos
Redis 15 minutos ou sem TTL

6. Modelagem de Dados

Collection: tenant_aliases

{
  "_id":"ObjectId",
  "alias":"acme",
  "tenantId":"507f1f77bcf86cd799439011",
  "enabled":true,
  "createdAt":"2026-04-16T10:00:00Z",
  "updatedAt":"2026-04-16T10:00:00Z"
}

Regras obrigatórias

Unicidade

  • alias deve ser único globalmente

Normalização

  • lowercase
  • trim

Charset permitido

[a-z0-9]

Restrições

  • não permitir:
    • www, admin, api, doc
  • evitar conflito com UUID4:
    • bloquear alias com formato de UUID4 sem hifens

7. Decisão de Design

Não reescrever URI como regra principal

Em vez disso:

  • Resolver identidade
  • Propagar via header

Headers internos

x-tenant-id
x-tenant-alias
x-original-host

Benefícios

  • melhor observabilidade
  • debugging mais simples
  • menor acoplamento
  • mantém contexto original

8. Observabilidade

Logs recomendados

{
  "originalHost":"acme.gateway.totvs.app",
  "alias":"acme",
  "tenantId":"507f...",
  "resolutionSource":"redis",
  "resolutionTimeMs":2
}

Métricas

  • cache hit/miss (local e Redis)
  • tempo de resolução
  • erros de alias não encontrado
  • fallback para Mongo

9. Riscos e Mitigações

Risco Mitigação
cache inconsistente evento + TTL
alias não encontrado fallback Mongo + validação
conflito alias/UUID validação no cadastro
alta latência em miss Redis
crescimento da base cache lazy (não preload total)

10. Conclusão

A resolução de alias é um problema de identidade multi-tenant, não de roteamento.

A melhor abordagem é:

  • Resolver no gateway-security-checker
  • Usar cache em múltiplos níveis
  • Manter Mongo como fonte de verdade
  • Utilizar eventos para consistência

Evitar:

  • proxies adicionais
  • lógica no ingress/envoy
  • reescrita implícita de URI