Estratégias de schema registry para gerenciamento de contratos em event streaming

1. Fundamentos do Schema Registry em Arquiteturas de Event Streaming

1.1. Definição e papel do Schema Registry como catálogo central de contratos

O Schema Registry atua como um repositório centralizado que armazena, valida e gerencia os schemas (contratos) utilizados em sistemas de event streaming. Em uma arquitetura orientada a eventos, produtores e consumidores precisam concordar sobre a estrutura dos dados trocados — o Schema Registry elimina o acoplamento direto ao fornecer um ponto único de verdade para esses contratos.

Exemplo de schema Avro registrado no Schema Registry:
{
  "namespace": "com.exemplo.eventos",
  "type": "record",
  "name": "PedidoCriado",
  "fields": [
    {"name": "pedidoId", "type": "string"},
    {"name": "clienteId", "type": "int"},
    {"name": "valorTotal", "type": "double"},
    {"name": "itens", "type": {"type": "array", "items": "string"}}
  ]
}

1.2. Integração com sistemas de mensageria

O Schema Registry se integra nativamente com sistemas como Apache Kafka, Apache Pulsar e RabbitMQ. No Kafka, por exemplo, cada mensagem pode conter um identificador de schema (schema ID) que referencia o contrato armazenado no registry, permitindo que consumidores validem e desserializem os dados sem conhecer previamente a estrutura.

Configuração típica de produtor Kafka com Schema Registry:
spring.kafka.producer.properties.schema.registry.url=http://localhost:8081
spring.kafka.producer.value.serializer=io.confluent.kafka.serializers.KafkaAvroSerializer

1.3. Benefícios principais

  • Validação de compatibilidade: impede que schemas incompatíveis sejam publicados
  • Versionamento automático: cada alteração gera uma nova versão rastreável
  • Governança de dados: centraliza políticas de evolução de contratos

2. Modelos de Compatibilidade de Schemas e Evolução de Contratos

2.1. Tipos de compatibilidade

O Schema Registry oferece três modos principais de compatibilidade:

  • Backward: consumidores antigos conseguem ler dados novos (padrão recomendado)
  • Forward: consumidores novos conseguem ler dados antigos
  • Full: combina backward e forward
Configuração de compatibilidade no Schema Registry:
curl -X PUT -H "Content-Type: application/vnd.schemaregistry.v1+json" \
  --data '{"compatibility": "BACKWARD"}' \
  http://localhost:8081/config/com.exemplo.eventos.PedidoCriado

2.2. Estratégias de evolução

  • Adição de campos: permitido em backward (com valor default)
  • Remoção de campos: permitido em forward (consumidores novos ignoram campos ausentes)
  • Renomeação de campos: requer aliases ou compatibilidade específica
Evolução de schema com adição de campo (compatível backward):
{
  "name": "PedidoCriado",
  "type": "record",
  "fields": [
    {"name": "pedidoId", "type": "string"},
    {"name": "clienteId", "type": "int"},
    {"name": "valorTotal", "type": "double"},
    {"name": "cupomDesconto", "type": ["null", "string"], "default": null}
  ]
}

2.3. Impacto de schemas incompatíveis

Schemas incompatíveis causam falhas de desserialização em consumidores, levando a perda de mensagens ou erros em produção. O Schema Registry bloqueia automaticamente o registro de schemas que quebram a compatibilidade configurada.

3. Formatos de Serialização e Registro de Schemas

3.1. Apache Avro

Avro oferece schema evolution nativa com suporte a aliases, defaults e tipos unions. Ideal para sistemas que priorizam compactação e desempenho.

Schema Avro com union type e default:
{
  "type": "record",
  "name": "Transacao",
  "fields": [
    {"name": "id", "type": "string"},
    {"name": "valor", "type": "double"},
    {"name": "moeda", "type": ["null", "string"], "default": "BRL"}
  ]
}

3.2. Protobuf

Protobuf se destaca na integração com gRPC e oferece suporte a oneof e optional. A evolução é gerenciada por números de campo.

Definição Protobuf para schema de evento:
syntax = "proto3";
message PedidoCriado {
  string pedido_id = 1;
  int32 cliente_id = 2;
  double valor_total = 3;
  optional string cupom = 4;
}

3.3. JSON Schema

JSON Schema oferece flexibilidade máxima e é amplamente usado em sistemas que não exigem tipagem forte. Suporta referências ($ref) para reutilização de definições.

Schema JSON com referência externa:
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "pedidoId": {"type": "string"},
    "cliente": {"$ref": "cliente-schema.json"}
  }
}

4. Estratégias de Versionamento e Gerenciamento de Ciclo de Vida

4.1. Versionamento semântico

  • Major: quebra compatibilidade (ex: remoção de campo obrigatório)
  • Minor: adição compatível (ex: novo campo com default)
  • Patch: correção sem mudança estrutural (ex: alteração de descrição)
Exemplo de versionamento no Schema Registry:
GET /subjects/pedido-value/versions/1
GET /subjects/pedido-value/versions/2
GET /subjects/pedido-value/versions/latest

4.2. Políticas de retenção

Manter versões antigas por período definido (ex: 30 dias) e expurgar versões não referenciadas por consumidores ativos. O Schema Registry permite configurar limites máximos de versões por subject.

4.3. Branching para testes

Ambientes de teste podem usar schemas temporários com sufixos específicos (ex: pedido-value-test), que são removidos após validação. Isso evita poluir o repositório principal.

5. Governança e Segurança no Schema Registry

5.1. Controle de acesso baseado em funções (RBAC)

O Schema Registry suporta RBAC para operações como leitura, escrita e exclusão de schemas. Usuários podem ter permissões granulares por subject ou namespace.

Exemplo de política RBAC no Confluent Schema Registry:
{
  "roles": [
    {"name": "schema-admin", "permissions": ["read", "write", "delete"]},
    {"name": "schema-reader", "permissions": ["read"]}
  ]
}

5.2. Auditoria de alterações

Todas as operações de registro, atualização e exclusão de schemas são registradas em logs de auditoria, permitindo rastrear quem alterou o quê e quando.

5.3. Proteção de metadados sensíveis

Schemas que contêm informações sensíveis (ex: nomes de campos que revelam dados pessoais) podem ser criptografados em repouso. O acesso ao registry deve ser via HTTPS com certificados válidos.

6. Padrões Avançados: Schema Registry em Multi-Cluster e Multi-Tenancy

6.1. Sincronização entre clusters

Em ambientes multi-cluster, é possível replicar schemas usando conectores dedicados ou federação. O Confluent Schema Registry oferece o Schema Registry Replicator para manter consistência entre datacenters.

6.2. Isolamento por tenant

Cada tenant pode ter seu próprio namespace lógico no Schema Registry, com prefixos como tenant-a.pedido-value. Isso garante isolamento de contratos entre clientes ou departamentos.

6.3. Migração entre ambientes

Schemas evoluem de dev para staging e produção. A prática recomendada é usar pipelines CI/CD que registram schemas em cada ambiente, validando compatibilidade antes da promoção.

Pipeline de migração de schemas:
1. Dev: registrar schema com sufixo -dev
2. Staging: validar compatibilidade com schema de produção
3. Produção: registrar versão estável sem sufixo

7. Monitoramento e Operação Contínua do Schema Registry

7.1. Métricas-chave

  • Taxa de registros: schemas registrados por minuto
  • Falhas de compatibilidade: número de rejeições por incompatibilidade
  • Latência de validação: tempo médio para validar um schema

7.2. Alertas automáticos

Configurar alertas para:
- Quebra de contrato (tentativa de registro incompatível)
- Schemas órfãos (versões não referenciadas por nenhum tópico)
- Aumento anormal na taxa de registros

7.3. Backup e recuperação de desastres

O repositório de schemas deve ser backupado regularmente. Estratégias incluem exportação para armazenamento externo (S3, GCS) e replicação síncrona entre clusters para alta disponibilidade.

Comando para backup de schemas via API:
curl -X GET http://localhost:8081/subjects > backup-schemas.json

Referências