Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Fazer com que cada serviço decida quando e como processar uma operação de negócios, em vez de depender de um orquestrador central. Essa abordagem descentraliza a lógica do fluxo de trabalho e distribui responsabilidades entre os componentes de um sistema.
Contexto e problema
Normalmente, você divide um aplicativo baseado em nuvem em vários pequenos serviços que trabalham juntos para processar uma transação comercial de ponta a ponta. Uma única operação dentro de uma transação pode resultar em várias chamadas ponto a ponto entre todos os serviços. O ideal é que esses serviços sejam fracamente acoplados. É desafiador criar um fluxo de trabalho distribuído, eficiente e escalonável porque envolve comunicação intersserviço complexa.
Um padrão comum para comunicação é usar um serviço centralizado ou um orquestrador. As solicitações recebidas fluem por meio do orquestrador à medida que ele delega as operações aos respectivos serviços. Cada um dos serviços conclui sua função e não está ciente do fluxo de trabalho geral.
Normalmente, você implementa o padrão de orquestração como um software feito sob medida, possuindo conhecimento de domínio sobre as responsabilidades dos serviços dentro do sistema. Um benefício dessa abordagem é que o orquestrador pode consolidar o status de uma transação com base nos resultados de operações individuais que os serviços downstream realizam.
Essa abordagem também cria alguns obstáculos. Adicionar ou remover serviços pode quebrar a lógica existente, pois você precisa reconectar partes do caminho de comunicação. Essa dependência torna a implementação do orchestrator complexa e difícil de manter. O orquestrador pode afetar negativamente a confiabilidade da carga de trabalho. Sob carga, ele pode introduzir gargalos de desempenho e ser o único ponto de falha (SPoF). Quando o orquestrador falha ou fica sobrecarregado, a falha pode se propagar para todos os serviços downstream dependentes.
Solução
Delegar a lógica de manipulação de transações entre os serviços. Permitir que cada serviço participe do fluxo de trabalho de comunicação de uma operação de negócios e decida quando e como processá-la.
O padrão coreográfico minimiza a dependência de software personalizado que centraliza o fluxo de trabalho de comunicação. Os componentes implementam uma lógica comum enquanto coreografam o fluxo de trabalho entre si sem se comunicarem diretamente entre si.
Uma maneira comum de implementar uma coreografia é usar um agente de mensagens que armazena solicitações em buffer até que os componentes downstream as reivindiquem e as processem. A imagem a seguir mostra o tratamento de solicitações por meio de um modelo de editor-assinante.
As solicitações do cliente são enfileiradas como mensagens em um broker de mensagens.
O serviço ou o assinante consulta o broker para determinar se este pode processar essa mensagem com base em sua lógica de negócios implementada. O agente também pode enviar mensagens por push para assinantes interessados nessa mensagem.
Cada serviço assinado faz sua operação conforme a mensagem indica e responde ao agente com uma mensagem de êxito ou falha da operação.
Se a operação for bem-sucedida, o serviço poderá publicar uma mensagem na mesma fila ou em uma fila de mensagens diferente para que outro serviço possa continuar o fluxo de trabalho, se necessário. Se a operação falhar, o serviço publicará uma mensagem de falha. Os serviços que assinam essa mensagem podem executar ações de compensação predefinidas para a operação com falha ou toda a transação.
Problemas e considerações
Considere os seguintes pontos ao decidir como implementar esse padrão:
Falha ao lidar com a complexidade. Componentes em um aplicativo podem gerenciar tarefas atômicas e depender de outras partes do sistema. A falha em um componente pode afetar outros componentes, o que pode causar atrasos na conclusão da solicitação geral.
Para lidar com falhas normalmente, você implementa a lógica de tratamento de falhas, que introduz complexidade. A lógica de tratamento de falhas, como a compensação de transações, também é propensa a falhas.
Processos sequenciais. Esse padrão atende a um fluxo de trabalho que processa operações comerciais independentes em paralelo. O fluxo de trabalho pode se tornar complicado quando a coreografia precisa ocorrer em uma sequência. Por exemplo, o Serviço D só pode iniciar sua operação depois que o Serviço B e o Serviço C concluirem suas operações com êxito.
Observabilidade em escala. Esse padrão apresentará desafios se o número de serviços aumentar rapidamente. Muitas partes móveis independentes complicam o fluxo de trabalho entre os serviços. Sem um orquestrador central que mantenha o estado completo da transação, nenhum componente tem uma visão completa de uma operação de negócio em andamento. Você deve usar consistentemente identificadores de rastreamento distribuído e correlação para manter a observabilidade.
Comunicação do gerenciador de resiliência. Em uma arquitetura orientada por um orquestrador, o componente central pode delegar responsabilidades de resiliência, como o tratamento de novas tentativas para falhas transitórias, não transitórias e por tempo limite, a um componente dedicado de resiliência.
Quando você remove o orquestrador em um design baseado em coreografia, os componentes downstream não assumem responsabilidades de resiliência. Eles permanecem centralizados no gerenciador de resiliência. Mas os componentes downstream devem se comunicar diretamente com esse manipulador, o que aumenta a comunicação ponto a ponto.
Evolução do esquema de eventos. A evolução do esquema de eventos pode causar alterações significativas nos consumidores ao longo do tempo. Nesse padrão, vários serviços independentes consomem os mesmos eventos. Se um produtor alterar a estrutura de dados de um evento, isso pode causar problemas para os consumidores posteriores que dependem do esquema antigo. Use um registro de esquema para gerenciar contratos de eventos e utilizar a evolução compatível com versões anteriores à medida que os serviços evoluem de forma independente.
Idempotência e ordenação de eventos. Pelo menos uma vez, a entrega e as novas tentativas podem produzir mensagens duplicadas e os consumidores simultâneos podem processar mensagens fora de ordem. Projete consumidores para que sejam idempotentes, rastreando identificadores de mensagem estáveis. Quando o processamento ordenado for necessário, use recursos do agente, como sessões de Barramento de Serviço ou inclua dados de sequência ou de versão que permitem que os consumidores rejeitem eventos obsoletos e detectem lacunas.
Estado atômico e publicação de eventos. Um serviço que atualiza seu armazenamento de dados e publica um evento em operações separadas pode confirmar uma operação enquanto a outra falha. Use o padrão Transactional Outbox ou um mecanismo atômico equivalente para persistir em conjunto a alteração de estado e o evento antes que um processo separado publique o evento.
Comportamento emergente e tempestades de eventos. Topologias de eventos descentralizadas podem criar comportamentos emergentes em escala. Quando muitos serviços reagem aos eventos uns dos outros, o sistema pode acidentalmente produzir loops de feedback ou tempestades de eventos. Um evento menor pode desencadear uma cascata de reações downstream. Para evitar cadeias de eventos circulares, use diretrizes como filtragem de eventos, limites de simultaneidade do consumidor, controle de taxa e regras explícitas.
Quando usar esse padrão
Use esse padrão quando:
Os componentes posteriores tratam operações atômicas de maneira independente em uma abordagem de disparar e esquecer. Cada componente conclui uma tarefa e sinaliza a conclusão para outros componentes por meio do agente de mensagens. O serviço de iniciação não gerencia ou controla a tarefa ativamente depois de expedi-la, mas os serviços downstream ainda comunicam resultados por meio de eventos.
Você espera atualizar e substituir os componentes com frequência. Esse padrão permite modificar o aplicativo com menos esforço e interrupção mínima para os serviços existentes.
Você usa arquiteturas sem servidor para fluxos de trabalho simples. Os componentes podem ser de curta duração e orientados a eventos. Quando ocorre um evento, o serviço cria componentes que fazem uma tarefa e o serviço remove os componentes após a conclusão dessa tarefa.
A comunicação entre contextos limitados requer acoplamento flexível entre limites de domínio. Para comunicação dentro de um único contexto limitado, considere um padrão de orquestrador, dependendo da complexidade e da preferência da equipe.
O orquestrador central introduz um gargalo de desempenho.
O padrão pode não ser adequado nestes casos:
O aplicativo é complexo e requer um componente central para lidar com a lógica compartilhada de modo a manter os componentes downstream leves.
A comunicação ponto a ponto entre os componentes é inevitável.
Você precisa usar a lógica de negócios para consolidar todas as operações que os componentes downstream manipulam.
Design de carga de trabalho
Avalie como usar o padrão de Coreografia no design de uma carga de trabalho para atender as metas e os princípios abordados nos pilares do Azure Well-Architected Framework. A tabela a seguir fornece diretrizes sobre como esse padrão dá suporte às metas de cada pilar.
| Pilar | Como esse padrão apoia os objetivos do pilar |
|---|---|
| A Excelência Operacional ajuda a fornecer qualidade da carga de trabalho por meio de processos padronizados e coesão de equipe. | Os componentes distribuídos nesse padrão são autônomos e projetados para serem substituíveis, para que você possa modificar a carga de trabalho com menos alterações gerais no sistema. - OE:04 Ferramentas e processos |
| A Eficiência de Desempenho ajuda sua carga de trabalho a atender com eficiência às demandas por meio de otimizações no dimensionamento, nos dados e no código. | Esse padrão fornece uma alternativa quando ocorrem gargalos de desempenho em uma topologia de orquestração centralizada. - PE:02 Planejamento de capacidade - PE:05 Dimensionamento e particionamento |
Tal como acontece com qualquer decisão de design, considere quaisquer compensações em relação aos objetivos dos outros pilares que possam ser introduzidos com este padrão.
Exemplo
Este exemplo mostra o padrão coreografado criando uma carga de trabalho nativa de nuvem controlada por eventos que executa funções junto com microsserviços. Quando um cliente solicita o envio de um pacote, a carga de trabalho atribui um drone. Depois que o pacote estiver pronto para retirada pelo drone agendado, o processo de entrega será iniciado. Enquanto o pacote está em trânsito, a carga de trabalho gerencia a entrega até que receba o status de enviado. Para obter a arquitetura de referência completa, consulte Microsserviços com Aplicativos de Contêiner do Azure.
O serviço de ingestão recebe solicitações do cliente e as converte em mensagens que incluem os detalhes de entrega. As transações comerciais começam depois que os serviços consomem essas novas mensagens.
Uma única transação comercial de cliente requer três operações comerciais distintas:
Criar ou atualizar um pacote.
Atribua um drone para entregar o pacote.
Gerencie a entrega, incluindo verificar e enviar uma notificação quando o pacote for enviado.
Os microsserviços de pacote, agendador de drones e entrega realizam o processamento empresarial. Os serviços usam mensagens em vez de um orquestrador central para se comunicarem entre si. Cada serviço deve implementar um protocolo com antecedência que coordene o fluxo de trabalho de negócios de forma descentralizada.
Projeto
Os serviços processam transações comerciais em uma sequência por meio de vários saltos. Cada salto compartilha um único barramento de mensagens entre todos os serviços corporativos.
Quando um cliente envia uma solicitação de entrega por meio de um ponto de extremidade HTTP, o serviço de ingestão a recebe, converte-a em uma mensagem e, em seguida, publica a mensagem no barramento de mensagens compartilhado. Os serviços empresariais assinados consomem novas mensagens adicionadas ao barramento. Quando um serviço empresarial recebe a mensagem, ele conclui a operação com êxito, a solicitação falha ou expira. Se a solicitação for bem-sucedida, o serviço responde ao barramento com o código de status Ok, gera uma nova mensagem de operação e a envia para o barramento de mensagens. Se a solicitação falhar ou atingir o tempo limite, o serviço informa ao barramento de mensagens o código do motivo da falha e move a mensagem para a fila de mensagens mortas por meio do Barramento de Serviço do Azure. O serviço também envia para a fila de mensagens mortas as mensagens que ele não consegue receber nem processar dentro de um determinado período.
Esse design usa vários barramentos de mensagens para processar toda a transação comercial. O Barramento de Serviço do Azure e a Grade de Eventos do Azure fornecem a plataforma de serviço de mensagens para esse design. A carga de trabalho é executada no Aplicativos de Contêiner do Azure. O serviço de ingestão é executado como uma função Azure hospedada em Aplicativos de Contêiner, enquanto o pacote, o agendador de drones e os serviços de entrega são executados como microsserviços no mesmo ambiente de Aplicativos de Contêiner. Os Aplicativos de Contêiner lidam com o processamento orientado a eventos que executa a lógica de negócios.
Esse design também garante que a coreografia ocorra em uma sequência. Um único namespace do Barramento de Serviço contém um tópico com duas assinaturas e uma fila com reconhecimento de sessão. O serviço de ingestão publica mensagens no tópico. O serviço de entrega de pacotes e o serviço de agendador de drones assinam o tópico e publicam mensagens que notificam a fila sobre as solicitações bem-sucedidas. Inclua um identificador de sessão comum que associa um GUID ao identificador de entrega para que o serviço de entrega possa correlacionar as duas mensagens necessárias para cada transação. Uma mensagem confirma que o pacote está pronto, a outra mensagem confirma que um drone está agendado. Sem essa correlação baseada em sessão, o serviço de entrega não tem como associar mensagens relacionadas entre saltos independentes, pois nenhum coordenador central controla o estado da transação. O serviço de entrega aguarda duas mensagens relacionadas para cada transação. A primeira mensagem indica que o pacote está pronto para ser enviado e a segunda mensagem sinaliza que um drone está agendado.
Nesse design, o Barramento de Serviço manipula mensagens de alto valor que não devem ser perdidas ou duplicadas durante todo o processo de entrega. Quando o pacote é enviado, uma alteração de estado é publicada no Event Grid. O remetente de eventos não tem nenhuma expectativa sobre como a alteração de estado é tratada. Os serviços de organização downstream que esse design não inclui podem escutar esse tipo de evento e executar uma lógica de negócios específica, como enviar um email de status de pedido para o usuário.
Se você implantar esse padrão em outro serviço de computação, como o AKS, poderá implantar um ambassador como sidecar no mesmo pod que o aplicativo de negócios. A colocação minimiza a latência de comunicação, mas o proxy adiciona sobrecarga de processamento e de recursos, e essa sobrecarga escala com o aplicativo. Use esta abordagem quando precisar de aspectos de conectividade independentes de linguagem que a plataforma não oferece.
Para evitar operações de repetição em cascata que possam levar a várias tentativas, os serviços empresariais devem sinalizar imediatamente mensagens inaceitáveis. Enriqueça essas mensagens usando códigos de motivos comuns ou um código de aplicativo definido para que os serviços possam movê-las para um DLQ. Considere implementar o padrão saga para gerenciar problemas de consistência de serviços downstream. Por exemplo, outro serviço lida com mensagens com letras mortas para fins de correção apenas executando uma transação de compensação, nova tentativa ou pivot.
Os serviços empresariais são idempotentes para garantir que as novas tentativas de operações não criem recursos duplicados. Por exemplo, o serviço de pacote usa operações upsert para adicionar dados ao armazenamento de dados.
Próximas etapas
- Examine as opções de mensagens assíncronas no Azure para saber mais sobre as diferentes opções de infraestrutura disponíveis para implementar um fluxo de trabalho descentralizado.
Recursos relacionados
Considere esses padrões em seu design para coreografia:
Use o padrão Ambassador para modularizar a comunicação de serviços de negócios com o barramento de mensagens.
Implemente o padrão de Nivelamento de Carga Baseado em Fila para lidar com picos de carga de trabalho.
Use mensagens distribuídas assíncronas por meio do padrãoPublisher-Subscriber.
Use transações de compensação para desfazer várias operações bem-sucedidas se uma ou mais operações relacionadas falharem.