Padrão de coreografia

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.

Um diagrama de um fluxo de trabalho que usa um orquestrador central para processar solicitações.

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.

Um diagrama que mostra como um agente de mensagens processa uma solicitação.

  1. As solicitações do cliente são enfileiradas como mensagens em um broker de mensagens.

  2. 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.

  3. 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.

  4. 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:

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.

Diagrama de um exemplo de carga de trabalho orientada a eventos e nativa em nuvem que implementa o padrão de coreografia.

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

Considere esses padrões em seu design para coreografia: