O blog da AWS

Enviando e recebendo CloudEvents com o Amazon EventBridge

Por David Boyne

O Amazon EventBridge ajuda os desenvolvedores a criar arquiteturas orientadas a eventos (EDA) conectando publishers e consumers com baixo acoplamento usando roteamento, filtragem e transformação de eventos. O CloudEvents é uma especificação de código aberto para descrever dados de eventos de uma forma comum. Os desenvolvedores podem publicar o CloudEvents diretamente no EventBridge, filtrá-los e roteá-los e usar transformadores de entrada e destinos de API para enviar o CloudEvents para serviços downstream da AWS e APIs de terceiros.

Visão geral

O design de eventos é um aspecto importante em qualquer arquitetura orientada a eventos. Os desenvolvedores que criam arquiteturas orientadas por eventos geralmente ignoram o processo de design de eventos ao criar suas arquiteturas. Isso causa efeitos colaterais indesejados, como exposição de detalhes de implementação, falta de padrões e incompatibilidade de versões.

Sem padrões de eventos, pode ser difícil integrar eventos ou fluxos de mensagens entre sistemas, brokers e organizações. Cada sistema precisa entender a estrutura do evento ou confiar em soluções personalizadas para controle de versão ou validação.

O CloudEvents é uma especificação para descrever dados de eventos em formatos comuns para fornecer interoperabilidade entre serviços, plataformas e sistemas usando projetos da Cloud Native Computing Foundation (CNCF). Como o CloudEvents é um projeto graduado pela CNCF, muitos brokers e sistemas terceirizados adotam essa especificação.

Usar o CloudEvents como formato padrão para descrever eventos facilita a integração e você pode usar ferramentas de código aberto para ajudar a criar arquiteturas orientadas por eventos e preparar qualquer integração para o futuro. O EventBridge pode rotear e filtrar o CloudEvents com base em metadados comuns, sem precisar entender a lógica de negócios dentro do próprio evento.

O CloudEvents oferece suporte a dois modos de implementação, modo estruturado e modo binário, e a uma variedade de protocolos, incluindo HTTP, MQTT, AMQP e Kafka. Ao publicar eventos em um barramento do EventBridge, você pode estruturar eventos como CloudEvents e encaminhá-los para os downstream consumers. Você pode usar transformers de entrada para transformar qualquer evento na especificação CloudEvents. Os eventos também podem ser encaminhados para APIs públicas, usando destinos de API do EventBridge, que oferecem suporte a codificações de modo estruturado e binário, aprimorando a interoperabilidade com sistemas externos.

Padronização de eventos usando o Amazon EventBridge

Ao publicar eventos em um barramento do EventBridge, o EventBridge usa seu próprio envelope de eventos e representa os eventos como objetos JSON. O EventBridge exige que você defina campos de nível superior, como detail-type  e source. Você pode usar qualquer evento/carga no campo detail.

Este exemplo de evento mostra um evento OrderPlaced do orders-service que não está estruturado com nenhum padrão de evento. Os dados do evento contêm order_id, customer_id e order_total.

{
  "version": "0",
  "id": "dbc1c73a-c51d-0c0e-ca61-ab9278974c57",
  "account": "1234567890",
  "time": "2023-05-23T11:38:46Z",
  "region": "us-east-1",
  "detail-type": "OrderPlaced",
  "source": "myapp.orders-service",
  "resources": [],
  "detail": {
    "data": {
      "order_id": "c172a984-3ae5-43dc-8c3f-be080141845a",
      "customer_id": "dda98122-b511-4aaf-9465-77ca4a115ee6",
      "order_total": "120.00"
    }
  }
}

Os publishers também podem optar por adicionar um campo metadata adicional junto com o campo data no campo detail para ajudar a definir um conjunto de padrões para seus eventos.

{
  "version": "0",
  "id": "dbc1c73a-c51d-0c0e-ca61-ab9278974c58",
  "account": "1234567890",
  "time": "2023-05-23T12:38:46Z",
  "region": "us-east-1",
  "detail-type": "OrderPlaced",
  "source": "myapp.orders-service",
  "resources": [],
  "detail": {
    "metadata": {
      "idempotency_key": "29d2b068-f9c7-42a0-91e3-5ba515de5dbe",
      "correlation_id": "dddd9340-135a-c8c6-95c2-41fb8f492222",
      "domain": "ORDERS",
      "time": "1707908605"
    },
    "data": {
      "order_id": "c172a984-3ae5-43dc-8c3f-be080141845a",
      "customer_id": "dda98122-b511-4aaf-9465-77ca4a115ee6",
      "order_total": "120.00"
    }
  }
}

Essas informações adicionais sobre eventos ajudam os downstream consumers, melhoram a depuração e podem gerenciar a idempotência. Embora essa abordagem ofereça benefícios práticos, ela duplica soluções que já foram resolvidas com a especificação CloudEvents.

Publicando CloudEvents usando o Amazon EventBridge

Ao publicar eventos no EventBridge, você pode usar o modo estruturado do CloudEvents. Uma mensagem de modo estruturado é onde todo o evento (atributos e dados) é codificado no corpo da mensagem, de acordo com um formato de evento específico. Uma mensagem binary-mode é onde os dados do evento são armazenados no corpo da mensagem e os atributos do evento são armazenados como parte dos metadados da mensagem.

O CloudEvents tem uma lista de campos obrigatórios, mas também oferece flexibilidade com atributos e extensões opcionais. O CloudEvents também oferece uma solução para implementar a idempotência, exigindo que a combinação de id e fonte identifique exclusivamente um evento, que pode ser usado como chave de idempotência em implementações downstream.

{
  "version": "0",
  "id": "dbc1c73a-c51d-0c0e-ca61-ab9278974c58",
  "account": "1234567890",
  "time": "2023-05-23T12:38:46Z",
  "region": "us-east-1",
  "detail-type": "OrderPlaced",
  "source": "myapp.orders-service",
  "resources": [],
  "detail": {
    "specversion": "1.0",
    "id": "bba4379f-b764-4d90-9fb2-9f572b2b0b61",
    "source": "myapp.orders-service",
    "type": "OrderPlaced",
    "data": {
      "order_id": "c172a984-3ae5-43dc-8c3f-be080141845a",
      "customer_id": "dda98122-b511-4aaf-9465-77ca4a115ee6",
      "order_total": "120.00"
    },
    "time": "2024-01-01T17:31:00Z",
    "dataschema": "https://us-west-2.console.aws.amazon.com/events/home?region=us-west-2#/registries/discovered-schemas/schemas/myapp.orders-service%40OrderPlaced",
    "correlationid": "dddd9340-135a-c8c6-95c2-41fb8f492222",
    "domain": "ORDERS"
  }
}

Ao incorporar os campos obrigatórios, o evento OrderPlaced agora está em conformidade com o CloudEvents. O evento também contém campos opcionais e de extensão para obter informações adicionais. Campos opcionais, como esquema de dados, podem ser úteis para brokers e consumers recuperarem um caminho de URI para o esquema de eventos publicado. Esse exemplo de evento faz referência ao esquema no registro do esquema do EventBridge, para que os downstream consumers possam buscar o esquema para validar a carga útil.

Mapeamento de eventos existentes no CloudEvents usando transformadores de entrada

Quando você define um destino no EventBridge, as transformações de entrada permitem que você modifique o evento antes que ele chegue ao destino. Os transformadores de entrada são configurados por destino, permitindo que você converta eventos quando seu downstream consumer exige o formato CloudEvents e você deseja evitar a duplicação de informações.

Os transformadores de entrada permitem mapear campos do EventBridge, como id, region, detail-type e source, nos atributos correspondentes do CloudEvents.

Este exemplo mostra como transformar qualquer evento do EventBridge no formato CloudEvents usando transformadores de entrada, para que o destino receba a estrutura necessária.

{
  "version": "0",
  "id": "dbc1c73a-c51d-0c0e-ca61-ab9278974c58",
  "account": "1234567890",
  "time": "2024-01-23T12:38:46Z",
  "region": "us-east-1",
  "detail-type": "OrderPlaced",
  "source": "myapp.orders-service",
  "resources": [],
  "detail": {
    "order_id": "c172a984-3ae5-43dc-8c3f-be080141845a",
    "customer_id": "dda98122-b511-4aaf-9465-77ca4a115ee6",
    "order_total": "120.00"
  }
}

Usando esse transformador de entrada e modelo de entrada, o EventBridge transforma o esquema de eventos na especificação CloudEvents para os downstream consumers

Transformador de entrada para CloudEvents:

{
  "id": "$.id",
  "source": "$.source",
  "type": "$.detail-type",
  "time": "$.time",
  "data": "$.detail"
}

Modelo de entrada para CloudEvents:

{
  "specversion": "1.0",
  "id": "<id>",
  "source": "<source>",
  "type": "<type>",
  "time": "<time>",
  "data": <data>
}

Este exemplo mostra o payload do evento que é recebida pelos destinos downstream, que é mapeada de acordo com a especificação CloudEvents.

{
  "specversion": "1.0",
  "id": "dbc1c73a-c51d-0c0e-ca61-ab9278974c58",
  "source": "myapp.orders-service",
  "type": "OrderPlaced",
  "time": "2024-01-23T12:38:46Z",
  "data": {
      "order_id": "c172a984-3ae5-43dc-8c3f-be080141845a",
      "customer_id": "dda98122-b511-4aaf-9465-77ca4a115ee6",
      "order_total": "120.00"
    }
}

Para obter mais informações sobre o uso de transformadores de entrada com o CloudEvents, consulte esse padrão em Serverless Land.

Transformando eventos em CloudEvents usando destinos de API

Os destinos da API do EventBridge permitem que você acione endpoints HTTP com base em regras correspondentes para integração com sistemas de terceiros usando APIs públicas. Você pode rotear eventos para APIs compatíveis com o formato CloudEvents usando transformações de entrada e cabeçalhos HTTP personalizados para converter eventos do EventBridge em CloudEvents. Os destinos da API agora oferecem suporte a cabeçalhos content-type personalizados. Isso permite que você envie CloudEvents estruturados ou binários para os downstream consumers.

Enviando CloudEvents binários usando destinos de API

Ao enviar CloudEvents binários por HTTP, você deve usar a especificação de vinculação HTTP e definir os cabeçalhos CloudEvents necessários. Esses cabeçalhos informam ao downstream consumer que o payload de entrada usa o formato CloudEvents. O corpo da solicitação é o evento em si.

Os cabeçalhos do CloudEvents são prefixados com ce-. Você pode encontrar a lista de cabeçalhos na documentação de vinculação do protocolo HTTP.

Este exemplo mostra os cabeçalhos de um evento binário:

POST /order HTTP/1.1 
Host: webhook.example.com
ce-specversion: 1.0
ce-type: OrderPlaced
ce-source: myapp.orders-service
ce-id: bba4379f-b764-4d90-9fb2-9f572b2b0b61
ce-time: 2024-01-01T17:31:00Z
ce-dataschema: https://us-west-2.console.aws.amazon.com/events/home?region=us-west-2#/registries/discovered-schemas/schemas/myapp.orders-service%40OrderPlaced
correlationid: dddd9340-135a-c8c6-95c2-41fb8f492222
domain: ORDERS
Content-Type: application/json; charset=utf-8

Este exemplo mostra o corpo de um evento binário:

{
  "order_id": "c172a984-3ae5-43dc-8c3f-be080141845a",
  "customer_id": "dda98122-b511-4aaf-9465-77ca4a115ee6",
  "order_total": "120.00"
}

Para obter mais informações sobre como usar o CloudEvents binário com destinos de API, explore esse padrão disponível no Serverless Land.

Enviando CloudEvents estruturados usando destinos de API

Para oferecer suporte ao modo estruturado com o CloudEvents, você deve especificar o content-type como application/cloudevents+json; charset=UTF-8, que informa ao consumer da API que o payload do evento está aderindo à especificação do CloudEvents.

POST /order HTTP/1.1
Host: webhook.example.com
 
Content-Type: application/cloudevents+json; charset=utf-8
{
    "specversion": "1.0",
    "id": "bba4379f-b764-4d90-9fb2-9f572b2b0b61",
    "source": "myapp.orders-service",
    "type": "OrderPlaced",      
    "data": {
      "order_id": "c172a984-3ae5-43dc-8c3f-be080141845a",
      "customer_id": "dda98122-b511-4aaf-9465-77ca4a115ee6",
      "order_total": "120.00"
    },
    "time": "2024-01-01T17:31:00Z",
    "dataschema": "https://us-west-2.console.aws.amazon.com/events/home?region=us-west-2#/registries/discovered-schemas/schemas/myapp.orders-service%40OrderPlaced",
    "correlationid": "dddd9340-135a-c8c6-95c2-41fb8f492222",
    "domain":"ORDERS"
}

Conclusão

A criação cuidadosa de eventos desempenha um papel importante na criação de arquiteturas orientadas a eventos para integrar produtores e consumidores de forma eficaz. A especificação de código aberto do CloudEvents ajuda os desenvolvedores a padronizar os processos de integração, simplificando as interações entre sistemas internos e parceiros externos.

O EventBridge permite que você use uma estrutura de payload  flexível dentro da propriedade de detalhes de um evento para padronizar eventos. Você pode publicar CloudEvents estruturados diretamente em um barramento de eventos no campo de detail e usar transformações de carga útil para permitir que consumidores downstream recebam eventos no formato CloudEvents.

O EventBridge simplifica a integração com sistemas de terceiros usando destinos de API. Usando os novos cabeçalhos de content-type personalizados com transformadores de entrada para modificar a estrutura do evento, você pode enviar CloudEvents estruturados ou binários para integração com APIs públicas.

Para obter mais recursos de aprendizado sem servidor, visite Serverless Land.

Este blog é uma tradução do conteúdo original em inglês (link aqui).

Biografia do Autor

David Boyne, Senior Developer Advocate

Biografia do tradutor

Rodrigo Peres é Arquiteto de Soluções na AWS, com mais de 20 anos de experiência trabalhando com arquitetura de soluções, desenvolvimento de sistemas e modernização de sistemas legados.

Biografia do revisor

Daniel Abib é Enterprise Solution Architect na AWS, com mais de 25 anos trabalhando com gerenciamento de projetos, arquiteturas de soluções escaláveis, desenvolvimento de sistemas e CI/CD, microsserviços, Serverless e segurança. Ele trabalha apoiando clientes corporativos, ajudando-os em sua jornada para a nuvem.