Editar

Partilhar via


Padrão de comboio sequencial

Azure Functions
Azure Service Bus

Processe um conjunto de mensagens relacionadas numa ordem definida sem bloquear o processamento de outros grupos de mensagens.

Contexto e problema

Os aplicativos geralmente precisam processar uma sequência de mensagens na ordem em que chegam, enquanto ainda podem ser dimensionados para lidar com o aumento da carga. Em uma arquitetura distribuída, o processamento dessas mensagens em ordem não é simples, porque os trabalhadores podem escalar de forma independente e, muitas vezes, extrair mensagens de forma independente, usando um padrão de Consumidores Concorrentes.

Por exemplo, um sistema de rastreamento de ordens recebe um livro contábil contendo ordens e as operações relevantes sobre essas ordens. Essas operações podem ser criar uma ordem, adicionar uma transação à ordem, modificar uma transação passada ou excluir uma ordem. Neste sistema, as operações devem ser executadas de forma FIFO (first-in-first-out), mas apenas no nível da ordem. No entanto, a fila inicial recebe um livro-razão contendo transações para muitos pedidos, que podem ser intercalados.

Solução

Envie mensagens relacionadas para categorias dentro do sistema de enfileiramento e faça com que os ouvintes da fila bloqueiem e extraiam apenas de uma categoria, uma mensagem de cada vez.

Veja como é o padrão geral do Comboio Sequencial:

Diagrama do padrão de comboio sequencial

Na fila, mensagens para diferentes categorias podem ser intercaladas, conforme mostrado no diagrama a seguir:

Diagrama mostrando mensagens intercaladas

Problemas e considerações

Na altura de decidir como implementar este padrão, considere os seguintes pontos:

  • Categoria/unidade de escala. Em que propriedade de suas mensagens recebidas você pode expandir? No cenário de controle de pedidos, essa propriedade é o ID do pedido.
  • Débito. Qual é a taxa de transferência da mensagem de destino? Se for muito elevado, poderá ter de reconsiderar os seus requisitos FIFO. Por exemplo, você pode impor uma mensagem de início/fim, classificar por tempo e, em seguida, enviar um lote para processamento?
  • Capacidades de serviço. Sua escolha de barramento de mensagens permite o processamento individual de mensagens dentro de uma fila ou categoria de fila?
  • Evolutividade. Como você adicionará uma nova categoria de mensagem ao sistema? Por exemplo, suponha que o sistema de contabilidade descrito acima seja específico para um cliente. Se você precisasse integrar um novo cliente, poderia ter um conjunto de processadores contábeis que distribuem o trabalho por ID do cliente?
  • É possível que os consumidores recebam uma mensagem fora de ordem, devido à latência variável da rede ao enviar mensagens. Considere o uso de números de sequência para verificar o pedido. Você também pode incluir um sinalizador especial de "fim de sequência" na última mensagem de uma transação. As tecnologias de processamento de fluxo, como o Spark ou o Azure Stream Analytics, podem processar mensagens em ordem dentro de uma janela de tempo.

Quando utilizar este padrão

Utilize este padrão quando:

  • Você tem mensagens que chegam em ordem e devem ser processadas na mesma ordem.
  • As mensagens que chegam são ou podem ser "categorizadas" de tal forma que a categoria se torna uma unidade de escala para o sistema.

Este padrão pode não ser adequado para:

  • Cenários de taxa de transferência extremamente alta (milhões de mensagens/minuto ou segundo), pois o requisito FIFO limita o dimensionamento que pode ser feito pelo sistema.

Design da carga de trabalho

Um arquiteto deve avaliar como o padrão Comboio Sequencial pode ser usado no design de sua carga de trabalho para abordar as metas e os princípios abordados nos pilares do Azure Well-Architected Framework. Por exemplo:

Pilar Como esse padrão suporta os objetivos do pilar
As decisões de projeto de confiabilidade ajudam sua carga de trabalho a se tornar resiliente ao mau funcionamento e a garantir que ela se recupere para um estado totalmente funcional após a ocorrência de uma falha. Esse padrão pode eliminar condições de corrida difíceis de solucionar, manipulação de mensagens contenciosas ou outras soluções alternativas para endereçar mensagens ordenadas incorretamente que podem levar a mau funcionamento.

- RE:02 Fluxos críticos
- RE:07 Trabalhos em segundo plano

Como em qualquer decisão de design, considere quaisquer compensações em relação aos objetivos dos outros pilares que possam ser introduzidos com esse padrão.

Exemplo

No Azure, esse padrão pode ser implementado usando sessões de mensagens do Barramento de Serviço do Azure. Para os consumidores, você pode usar Aplicativos Lógicos com o conector peek-lock do Service Bus ou o Azure Functions com o gatilho do Service Bus.

Para o exemplo de acompanhamento de pedidos anterior, processe cada mensagem contábil na ordem em que foi recebida e envie cada transação para outra fila onde a categoria está definida como o ID do pedido. Uma transação nunca abrangerá vários pedidos neste cenário, de modo que os consumidores processam cada categoria em paralelo, mas FIFO dentro da categoria.

O ventilador do processador de borda elimina as mensagens removendo o conteúdo de cada mensagem na primeira fila:

Diagrama mostrando o padrão de comboio sequencial com uma fila de razão

O processador contábil cuida de:

  1. Andar no livro-razão uma transação de cada vez.
  2. Definir o ID de sessão da mensagem para corresponder ao ID do pedido.
  3. Enviar cada transação contábil para uma fila secundária com o ID da sessão definido como o ID do pedido.

Os consumidores ouvem a fila secundária onde processam todas as mensagens com IDs de ordem correspondentes em ordem da fila. Os consumidores usam o modo peek-lock .

Ao considerar a escalabilidade, a fila do razão é um gargalo principal. Transações diferentes lançadas no livro razão podem fazer referência ao mesmo ID de ordem. No entanto, as mensagens podem se espalhar após o livro-razão para o número de pedidos em um ambiente sem servidor.

Próximos passos

As seguintes informações podem ser relevantes ao implementar este padrão: