Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Arquitetura Orientada a Eventos na AWS, Parte I: O Básico

By Vlad KhononovDec 16, 20246 min read

Esta página também está disponível em English, Deutsch, Español, Français, Italiano e 日本語.

A grande variedade de serviços da AWS muitas vezes permite implementar a mesma funcionalidade de formas diferentes. No caso de sistemas de mensageria, a AWS oferece serviços como Simple Notification Service (SNS), Simple Queue Service (SQS), EventBridge, Kinesis e Managed Streaming for Apache Kafka (MSK). Pode parecer que pelo menos parte desses serviços duplica a mesma funcionalidade. Neste post, quero descrever a arquitetura que costumo adotar e explicar por que, na minha opinião, ela é a solução mais simples, econômica e robusta para a maioria dos casos.

Arquitetura Orientada a Eventos

Os componentes de um sistema orientado a eventos se comunicam publicando e assinando eventos. A integração assíncrona traz vantagens não funcionais relevantes. Por exemplo, ela desacopla o ciclo de vida dos componentes integrados. Em certa medida, o sistema continua funcionando mesmo quando alguns de seus serviços ficam indisponíveis, o que também reduz o overhead de coordenação para implantar componentes atualizados e evoluir o sistema.

Uma integração orientada a eventos básica é formada por duas partes: um componente do sistema pode publicar eventos descrevendo ocorrências importantes do seu ciclo de vida e pode reagir (assinar) a eventos publicados por outras partes do sistema. Vamos ver quais serviços gerenciados podemos usar para implementar isso.

Publicação: SNS

O AWS Simple Notification Service (SNS) é um serviço totalmente gerenciado que permite enviar notificações para serem consumidas por outros componentes do sistema. Sua natureza serverless e o preço acessível tornam o SNS um ótimo candidato para publicar eventos. A Figura 1 mostra um serviço chamado "Producer" publicando seus eventos por meio de um tópico SNS.

Figura 1: O serviço "Producer" publica eventos em um tópico SNS.

E o serviço "Consumer", do lado direito da figura? Como ele pode assinar as mensagens publicadas pelo Producer?

O SNS oferece entrega de mensagens por vários protocolos, como HTTP, acionamento de funções AWS Lambda, SMS, entre outros. No papel, pode parecer plausível que o Consumer exponha um endpoint HTTP e o use como destino do tópico SNS, conforme ilustra a Figura 2.

Figura 2: O tópico SNS pode encaminhar mensagens para endpoints HTTP. Mas será essa a solução ideal?

Será mesmo a melhor solução? Considerando que os dois serviços, Producer e Consumer, são de equipes diferentes, quem fica responsável pelo tópico SNS? A equipe do Producer precisa garantir que o tópico esteja configurado corretamente para receber suas mensagens, enquanto as equipes responsáveis pelos serviços consumidores precisam garantir que os destinos estejam sempre corretos. Esse tipo de propriedade compartilhada é receita certa para atrito. Vamos pensar em outra abordagem.

Assinatura: SQS

O AWS SQS é uma fila de eventos totalmente gerenciada que retém temporariamente as mensagens (eventos) geradas pelos produtores até que sejam processadas pelos consumidores. Ele permite o tratamento distribuído de eventos com balanceamento de carga entre vários consumidores, algo essencial para manter a tolerância a falhas em fluxos orientados a eventos. Na minha opinião, ele também oferece muito mais visibilidade sobre as filas do que os tópicos SNS, além de um controle prático sobre como as mensagens são entregues aos consumidores.

Como o SQS é um dos destinos suportados pelos tópicos SNS, vamos configurar uma fila para as mensagens que serão processadas pelos serviços "Consumer", conforme ilustra a Figura 3.

Figura 3: Usando o SQS como mecanismo de consumo de eventos.

Com essa configuração, as fronteiras de propriedade ficam bem definidas:

  • O tópico SNS usado para publicar mensagens pertence à equipe responsável pelo serviço de origem (Producer).
  • A fila SQS usada para consumir mensagens pertence à equipe responsável pelo serviço assinante (Consumer).

A separação de responsabilidades entre os dois serviços precisa estar refletida na arquitetura do sistema.

SNS + SQS: EDA Simples

É amplamente aceito que um microsserviço deve dar acesso aos seus dados por meio de uma interface pública bem definida, enquanto o banco de dados é considerado um detalhe de implementação e deve ficar oculto dos consumidores. Esse encapsulamento rigoroso do mecanismo de persistência viabiliza fronteiras de propriedade mais claras, mais flexibilidade para evoluir microsserviços e muito mais controle sobre as interfaces públicas.

O barramento de mensagens usado pelo sistema é só mais um mecanismo de persistência — ainda que bem mais limitado — e deve ser tratado como tal. Por isso, além do banco de dados, cada (micro)serviço precisa de um tópico SNS para publicar eventos e de uma fila SQS para consumi-los, conforme ilustra a Figura 4:

Figura 4: Uma EDA exige fronteiras de propriedade claras não só para os bancos de dados, mas também para seus mecanismos de mensageria (SNS e SQS).

As setas entre os serviços — as assinaturas que ligam tópicos a filas — pertencem a um nível de abstração arquitetural superior ao dos próprios serviços. Por exemplo, pode haver um template do CloudFormation para cada serviço individual e um template do CloudFormation de nível mais alto para o sistema resultante. Este último é o responsável por definir as assinaturas.

Vale lembrar que uma assinatura não significa que todos os eventos publicados sejam despejados cegamente sobre os consumidores; uma assinatura pode especificar um filtro para encaminhar somente os eventos relevantes para cada consumidor.

Essa abordagem está alinhada ao princípio dos smart endpoints, dumb pipes, que é fundamental para a simplicidade e a flexibilidade de sistemas distribuídos. Segundo o princípio, a inteligência — a lógica — deve estar nos próprios serviços (endpoints), e não nos componentes de infraestrutura usados para integração (pipes). Os pipes — infraestrutura de mensageria e canais de comunicação — devem se encarregar apenas de transportar dados entre os serviços de forma confiável. O objetivo é reduzir as dependências entre serviços, possibilitando escalar, depurar e desenvolver com mais facilidade e rapidez, e evitando os gargalos e a complexidade normalmente associados a middlewares sofisticados.

Chegou a hora de falar sobre as outras opções de mensageria disponíveis na AWS.

Serviços Alternativos de Entrega de Mensagens

Como mencionei na introdução, há várias outras soluções gerenciadas pela AWS relacionadas a mensageria. Aqui quero abordar brevemente essas outras opções e por que acredito que a solução descrita acima é a mais adequada em 80% dos casos.

EventBridge

O primeiro "S" em SNS e SQS vem de "simple" (simples), e não está ali à toa. SNS e SQS são serviços simples. O EventBridge é muito mais flexível em filtragem de mensagens e regras de roteamento. Na minha opinião, ele se aproxima mais do conceito de barramento de mensagens corporativo da época da SOA. Em vez de dumb pipes, você ganha um ponto central para receber e rotear eventos entre todos os componentes do sistema, e até entre vários sistemas. O EventBridge, claro, tem seus casos de uso — por exemplo, quando você precisa integrar com sistemas de terceiros.

Kinesis e MSK (Managed Kafka)

Tanto o Kinesis quanto o MSK são serviços para trabalhar com dados em streaming. Dá para dizer que streaming de dados é um subconjunto da arquitetura orientada a eventos. Os dois envolvem trabalhar com mensagens publicadas e consumidas de forma assíncrona. O padrão de uso, porém, é diferente: enquanto a EDA tradicional foca em eventos ou mensagens individuais, trabalhar com streaming exige processar fluxos contínuos de eventos relacionados, o que pode não ser tratado com tanta eficiência por soluções tradicionais de barramento de mensagens. Daí a existência de ferramentas como Kinesis e MSK. Se você não precisa processar fluxos contínuos de mensagens, ferramentas mais simples como SNS e SQS resultam em um sistema mais direto.

Amazon MQ

O Amazon MQ é um serviço gerenciado de message broker para protocolos como ActiveMQ e RabbitMQ. Ele é especialmente útil para migrar sistemas legados para a nuvem ou para sistemas que precisam rodar sem alterações em vários ambientes de nuvem. Embora o Amazon MQ ofereça um message broker completo, com suporte a padrões avançados, ele traz overhead operacional e complexidade extras em comparação com a simplicidade do SNS e do SQS.

Posts da Série

Este post abordou a implementação de arquitetura orientada a eventos (EDA) na AWS usando SNS e SQS para publicar e consumir eventos. Você viu como SNS e SQS, juntos, formam uma solução simples e econômica, com fronteiras de propriedade claras, oferecendo flexibilidade e tolerância a falhas.