Editar

Compartilhar via


Padrão de Comboio Sequencial

Funções do Azure
Barramento de Serviço do Azure

Processe um conjunto de mensagens relacionadas em uma 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 de chegada, sem deixar de escalar horizontalmente para lidar com o aumento da carga. Em uma arquitetura distribuída, processar as mensagens em ordem não é simples, pois os trabalhadores podem ter escala independente e efetuar pull de mensagens de maneira independente, usando um padrão Consumidores Concorrentes.

Por exemplo, um sistema de acompanhamento de pedidos recebe um razão que contém pedidos e as operações relevantes neles. As operações podem ser criar um pedido, adicionar uma transação ao pedido, modificar uma transação anterior ou excluir um pedido. Nesse sistema, as operações devem ser executadas na ordem de chegada, mas apenas no nível dos pedidos. No entanto, a fila inicial recebe um razão que contém transações para muitos pedidos, que podem ser intercalados.

Solução

Envie mensagens relacionadas por push a categorias dentro do sistema de enfileiramento e configure os ouvintes da fila para bloquear e retirar apenas de uma categoria, uma mensagem por vez.

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

Diagrama do padrão de Comboio Sequencial

Na fila, as mensagens para categorias diferentes podem ser intercaladas, conforme mostrado no seguinte diagrama:

Diagrama que mostra mensagens intercaladas

Problemas e considerações

Considere os seguintes pontos ao decidir como implementar esse padrão:

  • Categoria/unidade de escala. Qual propriedade das mensagens de entrada pode ser usada para escalar horizontalmente? No cenário de acompanhamento de pedidos, essa propriedade é a ID do pedido.
  • Taxa de transferência. Qual é a taxa de transferência da mensagem de destino? Se for muito alto, talvez seja necessário reconsiderar os requisitos de ordem de chegada. Por exemplo, você pode impor uma mensagem de início/término, classificar por hora e enviar um lote para processamento?
  • Capacidades do serviço. O barramento de mensagens escolhido permite o processamento único de mensagens dentro de uma fila ou categoria de uma fila?
  • Capacidade de evolução. Como você adicionará uma nova categoria de mensagem ao sistema? Por exemplo, suponha que o sistema de razão descrito acima seja específico de um cliente. Se você precisasse integrar um novo cliente, poderia ter um conjunto de processadores de razão que distribuíssem o trabalho por ID do cliente?
  • É possível que os consumidores recebam uma mensagem fora de ordem devido à latência de rede variável ao enviar mensagens. Considere usar números de sequência para verificar a ordenação. Você também pode incluir um sinalizador especial de "fim da sequência" na última mensagem da transação. Tecnologias de processamento de fluxo, como Spark ou Azure Stream Analytics, podem processar mensagens em ordem dentro de uma janela de tempo.

Quando usar esse padrão

Use esse padrão quando:

  • As mensagens chegam em ordem e devem ser processadas na mesma ordem.
  • É possível categorizar as mensagens que chegam, de maneira que a categoria seja uma unidade de escala do sistema.

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

  • Cenários de taxa de transferência extremamente alta (milhões de mensagens por minuto ou segundo), pois a necessidade de processar as mensagens na ordem limita o dimensionamento do sistema.

Design de carga de trabalho

Um arquiteto deve avaliar como o padrão Comboio Sequencial pode ser usado no design das suas cargas de trabalho para abordar os objetivos e os princípios discutidos nos pilares do Azure Well-Architected Framework. Por exemplo:

Pilar Como esse padrão apoia os objetivos do pilar
As decisões de design 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 as condições de corrida difíceis de resolver, o tratamento das mensagens contenciosas ou outras soluções alternativas para lidar com as mensagens ordenadas incorretamente que podem levar ao mau funcionamento.

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

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

No Azure, é possível implementar o padrão com as sessões de mensagem do Barramento de Serviço do Azure. Para os consumidores, você pode usar os Aplicativos Lógicos com o conector peek-lock do Barramento de Serviço ou o Azure Functions com o gatilho do Barramento de Serviço.

Para o exemplo anterior de acompanhamento de pedidos, processe cada mensagem do razão na ordem recebida e envie cada transação a outra fila em que a categoria está definida como a ID do pedido. Uma transação nunca abrange vários pedidos nesse cenário, portanto, os consumidores processam cada categoria em paralelo, mas na ordem de chegada dentro da categoria.

O processador do razão distribui as mensagens, desempacotando o conteúdo de cada mensagem na primeira fila:

Diagrama que mostra o padrão de Comboio Sequencial com uma fila de razão

O processador do razão cuida de:

  1. Avançar o razão uma transação de cada vez.
  2. Definir a ID da sessão da mensagem para corresponder à ID do pedido.
  3. Enviar cada transação do razão a uma fila secundária com a ID da sessão definida como a ID do pedido.

Os consumidores escutam a fila secundária, em que processam todas as mensagens com IDs de pedido correspondentes na ordem que estão na fila. Os consumidores usam o modo peek-lock.

Ao considerar a escalabilidade, a fila do razão é um gargalo primário. Transações diferentes postadas no razão podem fazer referência à mesma ID de pedido. No entanto, as mensagens podem se espalhar após o razão para o número de pedidos em um ambiente sem servidor.

Próximas etapas

As informações a seguir também podem ser relevantes ao implementar esse padrão: