Partilhar via


Estilo de arquitetura condicionada por eventos

Azure Stream Analytics
Funções do Azure
Azure Service Bus

Uma arquitetura orientada a eventos consiste em produtores de eventos que geram um fluxo de eventos, consumidores de eventos que ouvem esses eventos e canais de eventos que transferem eventos de produtores para consumidores.

Diagrama que mostra um estilo de arquitetura orientada a eventos.

Os eventos são entregues quase em tempo real, pelo que os consumidores podem responder imediatamente aos eventos à medida que estes ocorrem. Os produtores estão dissociados dos consumidores: um produtor não sabe quais os consumidores que estão a ouvir. Os consumidores também estão desassociados uns dos outros e cada consumidor vê todos os eventos. Esse processo difere de um padrão de Consumidores Concorrentes , em que os consumidores extraem mensagens de uma fila e uma mensagem é processada apenas uma vez, supondo que não haja erros. Em alguns sistemas, como a Internet das Coisas (IoT) do Azure, os eventos devem ser ingeridos em grandes volumes.

Uma arquitetura orientada a eventos pode usar um modelo de publicação-assinatura ou um modelo de fluxo de eventos.

  • Pub/sub: A infraestrutura de mensagens de publicação-assinatura rastreia as assinaturas. Quando um evento é publicado, envia o evento para cada subscritor. Um evento não pode ser repetido depois de recebido e os novos subscritores não o veem.

  • Transmissão de eventos: Os eventos são gravados em um log. Os eventos são estritamente ordenados dentro de uma partição e são duráveis. Os clientes não assinam o fluxo. Em vez disso, um cliente pode ler de qualquer parte do fluxo. O cliente é responsável por avançar a sua posição no fluxo. Isso significa que um cliente pode participar a qualquer momento e pode repetir eventos.

No lado do consumidor, existem algumas variações comuns:

  • Processamento de eventos simples: Um evento desencadeia imediatamente uma ação no consumidor. Por exemplo, você pode usar o Azure Functions com um gatilho do Barramento de Serviço do Azure para que uma função seja executada sempre que uma mensagem for publicada em um tópico do Barramento de Serviço.

  • Correlação básica de eventos: Um consumidor processa alguns eventos comerciais discretos, correlaciona-os por algum identificador e persiste informações de eventos anteriores para uso ao processar eventos posteriores. Bibliotecas como NServiceBus e MassTransit suportam esse padrão.

  • Processamento de eventos complexos: Um consumidor usa uma tecnologia como o Azure Stream Analytics para analisar uma série de eventos e identificar padrões nos dados do evento. Por exemplo, você pode agregar leituras de um dispositivo incorporado em uma janela de tempo e gerar uma notificação se a média móvel ultrapassar um determinado limite.

  • Processamento de fluxo de eventos: Use uma plataforma de streaming de dados, como o Hub IoT do Azure ou o Apache Kafka, como um pipeline para ingerir eventos e alimentá-los para transmitir processadores. Os processadores de fluxos entram em ação para processar ou transformar o fluxo. Pode haver vários processadores de fluxo para diferentes subsistemas do aplicativo. Esta abordagem é uma boa opção para as cargas de trabalho de IoT.

A origem dos eventos pode ser externa ao sistema, como dispositivos físicos em uma solução de IoT. Nesse caso, o sistema deve ser capaz de ingerir os dados no volume e na taxa de transferência exigidos pela fonte de dados.

Há duas abordagens principais para estruturar cargas úteis de eventos. Quando você tem controle sobre os consumidores do evento, pode decidir sobre a estrutura de carga útil para cada consumidor. Essa estratégia permite que você misture abordagens, conforme necessário, em uma única carga de trabalho.

  • Inclua todos os atributos necessários na carga útil: Use essa abordagem quando quiser que os consumidores tenham todas as informações disponíveis sem a necessidade de consultar uma fonte de dados externa. No entanto, pode levar a problemas de consistência de dados devido a vários sistemas de registro, particularmente após atualizações. O gerenciamento de contratos e o controle de versão também podem se tornar complexos.

  • Inclua apenas chaves na carga útil: Nessa abordagem, os consumidores recuperam os atributos necessários, como uma chave primária, para buscar independentemente os dados restantes de uma fonte de dados. Esse método fornece melhor consistência de dados porque tem um único sistema de registro. No entanto, o desempenho pode ser inferior ao da primeira abordagem, porque os consumidores devem consultar a fonte de dados com frequência. Você tem menos preocupações em relação a acoplamento, largura de banda, gerenciamento de contratos ou controle de versão porque eventos menores e contratos mais simples reduzem a complexidade.

No diagrama anterior, cada tipo de consumidor é mostrado como uma única caixa. Para evitar que o consumidor se torne um único ponto de falha no sistema, é típico ter várias instâncias de um consumidor. Várias instâncias também podem ser necessárias para lidar com o volume e a frequência dos eventos. Um único consumidor pode processar eventos em vários threads. Essa configuração pode criar desafios se os eventos precisarem ser processados em ordem ou exigirem semântica exatamente uma vez. Para obter mais informações, consulte Minimizar a coordenação.

Há duas topologias principais em muitas arquiteturas controladas por eventos:

  • Topologia do broker: Os componentes transmitem ocorrências como eventos para todo o sistema. Outros componentes atuam sobre o evento ou ignoram o evento. Essa topologia é útil quando o fluxo de processamento de eventos é relativamente simples. Não há coordenação central ou orquestração, então essa topologia pode ser dinâmica. Essa topologia é altamente dissociada, o que ajuda a fornecer escalabilidade, capacidade de resposta e tolerância a falhas de componentes. Nenhum componente possui ou está ciente do estado de qualquer transação comercial de várias etapas e as ações são tomadas de forma assíncrona. Posteriormente, as transações distribuídas são arriscadas porque não há uma maneira nativa de ser reiniciado ou reproduzido. Você precisa considerar cuidadosamente o tratamento de erros e estratégias de intervenção manual porque essa topologia pode ser uma fonte de inconsistência de dados.

  • Topologia do mediador: Essa topologia aborda algumas das deficiências da topologia do broker. Há um mediador de eventos que gerencia e controla o fluxo de eventos. O mediador de eventos mantém o estado e gerencia o tratamento de erros e os recursos de reinicialização. Em contraste com a topologia do broker, nessa topologia, os componentes transmitem ocorrências como comandos e apenas para canais designados. Esses canais geralmente são filas de mensagens. Espera-se que os consumidores processem esses comandos. Essa topologia fornece mais controle, tratamento de erros melhor distribuído e consistência de dados potencialmente melhor. Essa topologia introduz um maior acoplamento entre componentes, e o mediador de eventos pode se tornar um gargalo ou uma preocupação de confiabilidade.

Quando utilizar esta arquitetura

Você deve usar essa arquitetura quando:

  • Vários subsistemas têm de processar os mesmos eventos.
  • É necessário processamento em tempo real com um intervalo de tempo mínimo.
  • É necessário processar eventos complexos, como correspondência de padrões ou agregação ao longo de janelas de tempo.
  • É necessário um grande volume e alta velocidade de dados, como acontece, por exemplo, com a IoT.

Benefícios

Os benefícios desta arquitetura são:

  • Os produtores e os consumidores estão desassociados.
  • Sem integrações ponto-a-ponto. É fácil adicionar novos consumidores ao sistema.
  • Os consumidores podem responder a eventos imediatamente à medida que ocorrem.
  • Altamente escalável, elástico e distribuído.
  • Os subsistemas têm vistas independentes do fluxo de eventos.

Desafios

  • Entrega garantida.

    Em alguns sistemas, especialmente em cenários de IoT, é fundamental garantir que os eventos são entregues.

  • Processamento de eventos por uma ordem ou exatamente uma vez.

    Para resiliência e escalabilidade, cada tipo de consumidor normalmente é executado em várias instâncias. Esse processo pode criar um desafio se os eventos tiverem de ser processados em ordem dentro de um tipo de consumidor ou se a lógica de processamento de mensagens idempotente não for implementada.

  • Coordenação de mensagens entre serviços.

    Os processos de negócios geralmente têm vários serviços que publicam e assinam mensagens para alcançar um resultado consistente em toda uma carga de trabalho. Você pode usar padrões de fluxo de trabalho , como o padrão Coreográfico e o Saga Orchestration , para gerenciar de forma confiável os fluxos de mensagens em vários serviços.

  • Tratamento de erros.

    A arquitetura orientada a eventos usa principalmente comunicação assíncrona. Um desafio com a comunicação assíncrona é o tratamento de erros. Uma maneira de resolver esse problema é usar um processador manipulador de erros separado. Quando o consumidor de eventos experimenta um erro, ele envia imediatamente e de forma assíncrona o evento errado para o processador do manipulador de erros e segue em frente. O processador manipulador de erros tenta corrigir o erro e envia o evento de volta para o canal de ingestão original. Mas se o processador do manipulador de erros falhar, ele pode enviar o evento errado para um administrador para inspeção adicional. Se você usar um processador manipulador de erros, os eventos errados serão processados fora de sequência quando forem reenviados.

  • Perda de dados.

    Outro desafio com a comunicação assíncrona é a perda de dados. Se algum dos componentes falhar antes de processar e entregar com êxito o evento ao seu próximo componente, o evento será descartado e nunca chegará ao destino final. Para minimizar a chance de perda de dados, persista os eventos em trânsito e remova ou remova os eventos da fila somente quando o próximo componente confirmar o recebimento do evento. Esses recursos são conhecidos como modo de reconhecimento do cliente e suporte ao último participante.

  • Implementação de um padrão tradicional de solicitação-resposta.

    Às vezes, o produtor do evento exige uma resposta imediata do consumidor do evento, como obter a elegibilidade do cliente antes de prosseguir com um pedido. Em uma arquitetura orientada a eventos, a comunicação síncrona pode ser alcançada usando mensagens de solicitação-resposta.

    Esse padrão geralmente é implementado com duas filas: uma fila de solicitação e uma fila de resposta. O produtor de eventos envia uma solicitação assíncrona para uma fila de solicitações, pausa outras operações nessa tarefa e aguarda uma resposta na fila de respostas. Essa abordagem efetivamente transforma esse padrão em um processo síncrono. Em seguida, os consumidores de eventos processam a solicitação e enviam a resposta de volta por meio de uma fila de respostas. Essa abordagem geralmente usa um ID de sessão para rastreamento, para que o produtor de eventos saiba qual mensagem na fila de resposta está relacionada à solicitação específica. A solicitação original também pode especificar o nome da fila de resposta, potencialmente efêmera, em um cabeçalho de resposta ou outro atributo personalizado mutuamente acordado.

  • Manutenção do número adequado de eventos.

    Gerar um número excessivo de eventos refinados pode saturar e sobrecarregar o sistema, dificultando a análise eficaz do fluxo geral de eventos. Esse problema é exacerbado quando as alterações precisam ser revertidas. Por outro lado, a consolidação excessiva de eventos também pode criar problemas, resultando em processamento e respostas desnecessárias dos consumidores de eventos.

    Para alcançar o equilíbrio certo, considere as consequências dos eventos e se os consumidores precisam inspecionar as cargas úteis do evento para determinar suas respostas. Por exemplo, se você tiver um componente de verificação de conformidade, pode ser suficiente publicar apenas dois tipos de eventos: compatível e não compatível. Essa abordagem ajuda a garantir que apenas os consumidores relevantes processem cada evento, o que evita o processamento desnecessário.

Outras considerações

  • A quantidade de dados a serem incluídos em um evento pode ser uma consideração significativa que afeta o desempenho e o custo. Você pode simplificar o código de processamento e eliminar pesquisas extras, colocando todas as informações relevantes necessárias para o processamento diretamente no evento. Quando você adiciona apenas uma quantidade mínima de informações a um evento, como alguns identificadores, reduz o tempo e o custo de transporte. No entanto, essa abordagem requer que o código de processamento recupere todas as informações adicionais necessárias. Para obter mais informações, consulte Colocar seus eventos em uma dieta.

  • Uma solicitação só é visível para o componente de tratamento de solicitação. Mas os eventos geralmente são visíveis para vários componentes em uma carga de trabalho, mesmo que esses componentes não se destinem ou não se destinem a consumi-los. Para operar com uma mentalidade de "assumir violação", esteja atento às informações que você inclui em eventos para evitar a exposição não intencional de informações.

  • Muitos aplicativos usam a arquitetura orientada a eventos como sua arquitetura principal. Você pode combinar essa abordagem com outros estilos arquitetônicos para criar uma arquitetura híbrida. As combinações típicas incluem microsserviços e tubos e filtros. Integre a arquitetura orientada a eventos para melhorar o desempenho do sistema, eliminando gargalos e fornecendo pressão de retorno durante grandes volumes de solicitações.

  • Domínios específicos geralmente abrangem vários produtores de eventos, consumidores ou canais de eventos. As alterações em um domínio específico podem afetar muitos componentes.

  • Vídeo de discussão da comunidade sobre as considerações de escolher entre coreografia e orquestração.