Padrões de Arquitetura de Software — Parte II
Continuando o mergulho em padrões comuns de arquitetura de software.
Este conteúdo é uma tradução livre e resumida do livro Software Architecture Patterns, do Mark Richards.
Introdução
Continuando a nosso mergulho nos padrões de arquitetura de software, abordaremos neste post o padrão de Arquitetura Orientada a Eventos. Vale lembrar que sempre precisamos justificar as nossas decisões arquiteturais, principalmente quando se trata de escolher uma abordagem ou padrão de arquitetura. Veremos aqui algumas informações importantes para tomar e justificar essa decisão.
Se você ainda não leu o post anterior (Parte I) onde comentamos sobre o Padrão de Arquitetura em Camadas, recomendo que leia antes de continuar a leitura desse post, para que possa compreender com mais clareza o tema.
Arquitetura Orientada a Eventos
O padrão de arquitetura orientada a eventos (event-driven architecture) é um padrão popular para arquitetura assíncrona distribuída, usado para produzir sistemas altamente escaláveis. Esse padrão também é altamente adaptável e pode ser usado tanto por aplicações pequenas quanto por aplicações grandes e complexas. A arquitetura orientada a eventos é composta por componentes processadores de eventos altamente desacoplados que possuem uma única responsabilidade, que recebem e processam eventos de maneira assíncrona.
O padrão de arquitetura orientada a eventos consiste em duas principais topologias, o mediator e o broker. A topologia do mediator é comumente usada quando você precisa orquestrar múltiplos passos em um evento através de um mediator central, enquanto a topologia do broker é usada quando você quer encadear eventos sem utilizar um mediator central. Devido às características da arquitetura e diferentes estratégias de implementação entre essas duas topologias, é importante entender cada uma para saber qual utilizar em uma determinada situação.
Mediator
A topologia do mediator é útil para eventos que tem múltiplas etapas e precisam de algum nível de orquestração para processar o evento. Por exemplo, um único evento que inicia uma negociação de ações pode exigir uma validação antes da negociação, em seguida, verificar se a negociação atende às regras de conformidade, atribuir a negociação a um corretor, calcular a comissão e, por fim, colocar a negociação para esse corretor. Todas essas etapas requerem algum nível de orquestração para determinar a ordem das etapas e qual delas podem ser executadas sequencialmente ou em paralelo.
Existem quatro tipos principais de componentes dentro da topologia do mediator: uma fila de eventos (event queue), um mediador de eventos (event mediator), canais de eventos (event channels), e processadores de eventos (event processors). O evento inicia o fluxo com um cliente enviando um evento para a fila de eventos, a qual é usada para levar o evento até o mediador de eventos. O mediador de eventos recebe o evento inicial e orquestra esse evento e pode enviar eventos adicionais assíncronos para os canais de eventos para executar cada etapa do processo. Os processadores de eventos, os quais ficam escutando os canais de eventos, recebem o evento a partir do mediador e executam lógicas de negócio específicas para processar o evento.
É comum ter diversas filas de eventos em uma arquitetura orientada a eventos. O padrão não especifica como implementar a fila de eventos, então ela pode ser uma fila de mensagens, um endpoint de um serviço, ou qualquer outro tipo.
Existem dois tipos de eventos dentro desse padrão: um evento inicial e um evento de processamento. O evento inicial é o evento original recebido pelo mediador, enquanto os eventos de processamento são aqueles gerados pelo mediador e recebidos pelos componentes processadores de eventos (event processors).
O componente mediador de eventos é responsável por orquestrar as etapas contidas no evento inicial. Para cada etapa do evento inicial, o mediador envia um evento de processamento para um canal de eventos, que então é recebido e processado por um processador de eventos. É importante notar que o mediador não conhece a lógica de negócio necessária para processar o evento inicial, ao invés disso, ele sabe apenas os passos necessários para processar o evento inicial.
Os canais de eventos são usados pelo mediador para entregar eventos de processamento relacionados a cada etapa (do evento inicial) para os processadores de eventos, de forma assíncrona. Os canais de eventos podem ser filas de mensagens (message queues) ou tópicos de mensagens, embora os tópicos de mensagens serem mais comumente usados na topologia do mediator para que os eventos de processamento possam ser processados por vários processadores de eventos, cada um executando uma atividade diferente com base em um evento de processamento recebido.
O componente processador de eventos contém a lógica de negócio da aplicação necessária para processar um evento de processamento. Os processadores de eventos são componentes autônomos, independentes e altamente desacoplados que executam uma atividade específica dentro da aplicação. Enquanto a granularidade de um processador de eventos pode variar, é importante se atentar que em geral, cada processador de eventos deve executar uma única atividade (ou lógica) de negócio e não depender de outros processadores de eventos para completar uma determinada atividade.
O mediador de eventos pode ser implementado de várias formas diferentes. Como um arquiteto, você deve entender cada uma dessas opções de implementação para assegurar que a solução que você escolheu para o mediador de eventos está de acordo com os seus requisitos e necessidades.
Para demonstrar como a topologia do mediator funciona vamos supor que você está segurado por uma empresa seguradora e você decide mudar. Nesse caso, o evento inicial pode ser chamado de algo como “evento de realocação” (relocation event). As etapas envolvidas no processamento do evento de realocação são mostradas na figura logo abaixo. Para cada etapa do evento inicial (relocation event) o mediador de eventos cria um evento de processamento (change address, realoc quote, update claims, etc.), envia esse evento de processamento para um canal de eventos e espera que seja processado por um processador de eventos. Esse processo continua até todas as etapas do evento inicial serem completadas.
A barra contínua entre as etapas recalc quote e update claims indicam que essas etapas podem ser executadas em paralelo.
Broker
A topologia do broker se diferencia da topologia do mediator, pois nela não há um mediador de eventos. Ao invés disso, o fluxo de mensagens é distribuído entre os processadores de eventos. Essa topologia é útil quando você tem um fluxo de eventos relativamente simples e você não precisa (ou não quer) orquestração de eventos.
Existem dois tipos de componentes de arquitetura dentro da topologia do broker: o broker e os processadores de eventos. O broker pode ser centralizado e contém todos os canais que são usados dentro de um fluxo de eventos. Os canais de eventos dentro do broker podem ser filas de mensagens, tópicos de mensagens ou uma combinação de ambos.
Como pode ser visto na figura acima, não existe um mediador de eventos controlando e orquestrando o evento inicial, ao invés disso, cada processador de evento é responsável por processar um evento e publicar um novo evento indicando que a atividade foi concluída.
A topologia do broker é sobre encadear eventos para executar uma lógica de negócio.
Considerações
O padrão de arquitetura orientada a eventos é relativamente complexo para entender, principalmente pela natureza distribuída e assíncrona. Quando implementar esse padrão, você precisa se preocupar com vários problemas de arquitetura distribuída, como disponibilidade de um processo remoto, ausência de resposta, e problemas de falha de conexão com o broker.
Algo importante a se considerar quando se implementa esse padrão de arquitetura é a falta de transações atômicas para um único processo de negócio. Dado que os processadores de eventos são altamente desacoplados e distribuídos, é muito difícil manter uma unidade de trabalho transacional entre eles. Por isso, quando desenhar a sua aplicação usando esse padrão, você precisa pensar sobre quais eventos podem ou não serem executados de maneira independente, e planejar a granularidade (de trabalho) dos seus processadores de eventos de acordo com isso. Se você ver que com frequência está usando processadores de eventos separados para fazer algo que deveria ser uma única unidade de trabalho (ou transação), talvez este não seja o padrão certo para a sua aplicação.
Um dos aspectos mais difíceis de lidar com o padrão de arquitetura orientada a eventos é a criação, manutenção e governança dos contratos dos processadores de eventos. Cada evento normalmente tem um contrato específico associado a ele e dados que precisam ser passados ao processador de eventos. É de extrema importância que ao utilizar esse padrão, seja estabelecido um formato de dados padrão (XML, JSON, Objects, etc.) e também se pense em versionamento desde o início.
Análise do Padrão
- Agilidade Geral
Classificação: ALTA
Agilidade geral é a capacidade de responder rapidamente a um ambiente de mudanças constantes. Desde que os processadores de eventos tenham um único propósito e sejam completamente desacoplados de outros processadores de eventos, as mudanças são geralmente isoladas em um ou poucos processadores de eventos e podem ser feitas de forma rápida e sem impactar outros componentes.
- Fácil de Implantar
Classificação: ALTA
No geral, aplicações construídas utilizando o padrão de arquitetura orientada a eventos são fáceis de implantar (deployment) devido a natureza desacoplada dos processadores de eventos. A topologia do broker tende a ser mais fácil de implantar que a topologia do mediator, já que o mediador de eventos é um pouco acoplado aos processadores de eventos: uma mudança em um processador de eventos poderá exigir uma alteração no mediador de eventos, forçando a redeploy de ambos para determinada mudança.
- Testabilidade
Classificação: BAIXA
Escrever testes de unidade não são tão complicados para esse padrão, porém ele exige algum componente dentro do teste para gerar os eventos. Outro fator que acaba dificultando os testes é a natureza assíncrona desse padrão.
- Desempenho
Classificação: ALTA
Embora seja possível implementar uma arquitetura orientada a eventos que não tem um bom desempenho, devido a toda a infraestrutura de mensagens envolvida, no geral, o padrão alcança alto desempenho através das capacidades de assincronismo. A capacidade de executar de maneira independente e desacoplada, realizando operações de forma paralela de assíncrona supera o custo de enfileirar e desenfileirar mensagens.
- Escalabilidade
Classificação: ALTA
A escalabilidade é naturalmente alcançada por esse padrão devido a independência dos processadores de eventos. Cada processador de eventos podem ser escalados separadamente, permitindo dessa maneira a alta escalabilidade.
- Fácil de Desenvolver
Classificação: BAIXA
O desenvolvimento pode ser um pouco complicado por causa da natureza assíncrona desse padrão, e a necessidade de um tratamento de erro em condições mais avançadas (falta de resposta de processadores de eventos ou broker, por exemplo).
Continue a leitura na Parte III — Padrão de Arquitetura Microkernel.
Obrigado por ler até aqui!
Se você gostou desse conteúdo, não deixe de compartilhar. 😉