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.
Habilite vários consumidores simultâneos para processar as mensagens recebidas no mesmo canal de mensagens. Com vários consumidores simultâneos, um sistema pode processar várias mensagens ao mesmo tempo para otimizar a taxa de transferência, melhorar a escalabilidade e a disponibilidade e equilibrar a carga de trabalho.
Contexto e problema
Um aplicativo de nuvem geralmente lida com um grande número de solicitações. Em vez de processar cada solicitação de forma síncrona, o aplicativo pode passar solicitações por meio de um sistema de mensagens para um serviço de consumidor que as manipula de forma assíncrona. Essa estratégia ajuda a impedir que o processamento de solicitações bloqueie a lógica de negócios do aplicativo.
O número de solicitações pode variar significativamente ao longo do tempo. Um aumento repentino na atividade do usuário ou solicitações agregadas de vários locatários pode criar uma carga de trabalho imprevisível. Nos horários de pico, um sistema pode precisar processar muitas centenas de solicitações por segundo. Em outras ocasiões, o número pode ser pequeno. Além disso, o trabalho necessário para lidar com essas solicitações pode variar bastante. Se você usar uma única instância de serviço de consumidor, as solicitações poderão sobrecarregar essa instância. Ou um fluxo de mensagens de aplicativo pode sobrecarregar o sistema de mensagens.
Para lidar com essa carga de trabalho flutuante, o sistema pode executar várias instâncias de serviço do consumidor. No entanto, o sistema deve coordenar esses consumidores para garantir que cada mensagem seja entregue a apenas um consumidor. O sistema também deve equilibrar a carga de trabalho entre os consumidores para impedir que uma instância se torne um gargalo.
Solução
Use uma fila de mensagens para implementar o canal de comunicação entre o aplicativo e as instâncias de serviço do consumidor. O aplicativo envia solicitações na forma de mensagens para a fila, e as instâncias de serviço consumidor recebem e processam mensagens da fila. Essa abordagem permite que o mesmo pool de instâncias de serviço do consumidor manipule mensagens de qualquer instância do aplicativo. O diagrama a seguir mostra como uma fila de mensagens distribui o trabalho para instâncias de serviço.
Observação
Vários consumidores recebem essas mensagens, mas o padrão Consumidores Concorrentes difere do padrãoPublisher-Subscriber. No padrão Consumidores Concorrentes, um consumidor recebe cada mensagem para processamento. No padrão Publisher-Subscriber, todos os consumidores recebem cada mensagem.
Essa solução oferece as seguintes vantagens:
Ele fornece um sistema balanceado de carga que pode lidar com amplas variações no volume de solicitações das instâncias de aplicação. A fila funciona como um buffer entre instâncias de aplicativo e instâncias de serviço do consumidor. Esse buffer pode minimizar o efeito sobre a disponibilidade e a capacidade de resposta para as instâncias de aplicativo e serviço. Para obter mais informações, confira Padrão de Nivelamento de carga baseado em fila. Uma mensagem que requer algum processamento de execução longa não impede que outras instâncias de serviço do consumidor processem outras mensagens simultaneamente.
Isso aumenta a confiabilidade. Se um produtor se comunicar diretamente com um consumidor em vez de usar esse padrão e não monitorar o consumidor, ele enfrenta uma alta probabilidade de perder mensagens ou não processá-las quando o consumidor falhar. Nesse padrão, o sistema não envia mensagens para uma instância de serviço específica. Uma instância de serviço com falha não bloqueia um produtor e qualquer instância de serviço funcional pode processar mensagens.
Não requer coordenação complexa entre consumidores ou entre instâncias de produtor e consumidor. A fila de mensagens garante que cada mensagem seja entregue pelo menos uma vez.
É dimensionada. Quando você aplica o dimensionamento automático, o sistema pode aumentar ou diminuir dinamicamente o número de instâncias de serviço do consumidor à medida que o volume de mensagens flutua.
Isso poderá melhorar a resiliência se a fila de mensagens fornecer operações de leitura transacionais. Se uma instância de serviço do consumidor ler e processar uma mensagem como parte de uma operação transacional e falhar, esse padrão poderá garantir que a mensagem seja retornada para a fila para que outra instância de serviço do consumidor possa processá-la. Para atenuar o risco de falhas contínuas de mensagens, recomendamos que você use filas de mensagens mortas.
Problemas e considerações
Considere os seguintes pontos ao decidir como implementar esse padrão:
Ordenação de mensagens: A ordem na qual as instâncias de serviço do consumidor recebem mensagens não é garantida e não mostra necessariamente a ordem na qual as mensagens foram criadas. Projete o sistema para que ele processe mensagens de forma idempotente. Esse design ajuda a eliminar as dependências de ordem de processamento.
O Barramento de Serviço do Azure pode implementar a ordenação garantida de mensagens no formato primeiro a entrar, primeiro a sair (FIFO) e outros padrões usando sessões de mensagem.
Requisitos de resiliência de serviço: Se o sistema detectar e reiniciar instâncias de serviço com falha, talvez seja necessário implementar as operações que essas instâncias de serviço executam como idempotentes para minimizar os efeitos quando recuperar e processar uma única mensagem mais de uma vez.
Detecção de mensagens venenosas: Uma mensagem malformada ou uma tarefa que requer acesso aos recursos que não estão disponíveis pode fazer com que uma instância de serviço falhe. O sistema deve impedir que essas mensagens retornem à fila indefinidamente e, em vez disso, capturar e armazenar seus detalhes em outro lugar para análise, se necessário. O Barramento de Serviço pode enviar mensagens automaticamente para uma fila de mensagens mortas depois que a contagem de entrega exceder o limite configurado
MaxDeliveryCount.Tratamento de resultados: A instância de serviço que manipula uma mensagem é totalmente dissociada da lógica do aplicativo que gera a mensagem, portanto, eles podem não ser capazes de se comunicar diretamente. Se a instância de serviço gerar resultados que devem voltar à lógica do aplicativo, armazene essas informações em um local que ambos os componentes possam acessar. Para impedir que a lógica do aplicativo recupere dados incompletos, o sistema deve indicar quando o processamento é concluído. Um processo de trabalho pode passar os resultados de volta para a lógica do aplicativo por meio de uma fila dedicada de resposta de mensagens. A lógica do aplicativo deve ser capaz de correlacionar esses resultados com a mensagem original.
Dimensionamento do sistema de mensagens: Em uma solução em grande escala, o alto volume de mensagens pode sobrecarregar uma única fila de mensagens e transformá-la em um gargalo do sistema. Nessa situação, considere particionar o sistema de mensagens para enviar mensagens de produtores específicos para uma fila específica, ou usar balanceamento de carga para distribuir mensagens entre múltiplas filas de mensagens.
Confiabilidade do sistema de mensagens: Use um sistema de mensagens confiável para garantir que as mensagens não sejam perdidas depois que o aplicativo as enfileira. Essa funcionalidade é essencial para garantir que todas as mensagens sejam entregues pelo menos uma vez.
Quando usar esse padrão
Use esse padrão quando:
A carga de trabalho do aplicativo é dividida em tarefas que podem ser executadas de forma assíncrona.
As tarefas são independentes e podem ser executados em paralelo.
O volume de trabalho é altamente variável e requer uma solução escalonável.
A solução deve fornecer alta disponibilidade e permanecer resiliente quando o processamento de tarefas falhar.
O padrão pode não ser adequado nestes casos:
Você não pode separar facilmente a carga de trabalho do aplicativo em tarefas discretas ou há um alto grau de dependência entre tarefas.
As tarefas devem ser executadas de forma síncrona e a lógica do aplicativo deve aguardar a conclusão de cada tarefa antes de continuar.
As tarefas devem ser executadas em uma sequência específica.
Observação
Alguns sistemas de mensagens dão suporte a sessões que permitem que um produtor agrupe mensagens juntas e garanta que o mesmo consumidor processe todas as mensagens do grupo. Você pode usar esse mecanismo com mensagens priorizadas quando houver suporte para impor a ordenação de mensagens e entregar mensagens em sequência de um produtor para um único consumidor.
Design de carga de trabalho
Avalie como usar o padrão Consumidores Concorrentes no design de uma carga de trabalho para atender às metas e 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 |
|---|---|
| As decisões de design de confiabilidade ajudam sua carga de trabalho a se tornar resiliente ao mau funcionamento e garantir que ela se recupere para um estado totalmente funcional após a ocorrência de uma falha. | Esse padrão cria redundância no processamento de filas, tratando os consumidores como réplicas, de modo que uma falha de instância não impede que outros consumidores processem mensagens de fila. - RE:05 Redundância - Trabalhos em segundo plano |
| A Otimização de Custos concentra-se na manutenção e na melhoria do retorno sobre o investimento da carga de trabalho. | Esse padrão pode ajudar a otimizar os custos porque ele é dimensionado com base na profundidade da fila e pode reduzir para zero quando a fila estiver vazia. Ele também pode otimizar os custos porque você pode limitar o número máximo de instâncias de consumidor simultâneas. - CO:05 Otimização de taxas - CO:07 Custos de componentes |
| 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 distribui a carga entre nós consumidores para aumentar a utilização, e o dimensionamento dinâmico com base na profundidade da fila minimiza o superprovisionamento. - PE:05 Dimensionamento e particionamento - PE:07 Código e infraestrutura |
Se esse padrão introduzir compensações dentro de um pilar, considere-as em relação aos objetivos dos outros pilares.
Exemplo
O Azure fornece filas do Barramento de Serviço e gatilhos de fila do Azure Functions que juntos implementam diretamente esse padrão de design de nuvem. As funções se integram ao Service Bus por meio de gatilhos e vinculações. Essa integração permite criar funções que consomem mensagens de fila de editores. Os aplicativos publicadores postam mensagens em uma fila e os consumidores implementados como funções podem recuperar e lidar com essas mensagens.
Para resiliência, uma fila do Barramento de Serviço permite que um consumidor use o modo PeekLock ao recuperar uma mensagem da fila. Esse modo mantém a mensagem, mas a oculta de outros consumidores. O runtime do Functions recebe uma mensagem no modo PeekLock. Se a função for concluída com êxito, o runtime chamará Complete na mensagem. Se a função falhar, o runtime poderá chamar Abandon e tornar a mensagem visível novamente para que outro consumidor possa recuperá-la. Se a função for executada por mais tempo do que o tempo limite do PeekLock, o runtime renovará automaticamente o bloqueio, desde que a função seja executada.
Functions dimensiona automaticamente o número de instâncias de consumidor com base na profundidade da fila e no tráfego. Esse dimensionamento permite que a solução gerencie picos de demanda, minimizando o custo durante períodos de baixo volume. Se o Functions criar várias instâncias, elas competirão puxando e processando mensagens de forma independente. Para obter mais informações, consulte filas, tópicos e assinaturas do Service Bus e gatilho do Service Bus para Funções.
Para obter mais informações sobre como usar a biblioteca cliente do Barramento de Serviço para .NET para enviar mensagens para uma fila do Barramento de Serviço, consulte os exemplos publicados.
Próximas Etapas
Escolha um serviço de mensagens no Azure: saiba como diferentes serviços de mensagens do Azure, como Barramento de Serviço, filas de Armazenamento do Azure, Hubs de Eventos do Azure e Grade de Eventos do Azure dão suporte a padrões de comunicação assíncronos e como escolher o modelo de serviço e mensagens corretos para seu cenário.
Práticas recomendadas de dimensionamento automático: saiba como projetar soluções que dimensionam as instâncias do consumidor com base na carga de trabalho, como comprimento da fila ou taxa de transferência de mensagens, para que você possa lidar com o pico de carga e controlar o custo durante períodos de baixa atividade.
Recursos relacionados
Padrão de Consolidação de Recursos de Computação: você pode consolidar várias instâncias de um serviço de consumidor em um único processo para reduzir os custos e a sobrecarga de gerenciamento. O padrão de Consolidação de Recursos de Computação descreve os benefícios e as compensações dessa abordagem.
Padrão de Nivelamento de Carga baseado em fila: uma fila de mensagens pode adicionar resiliência ao sistema. A resiliência permite que as instâncias de serviço lidem com volumes amplamente variados de solicitações de instâncias de aplicativo. A fila de mensagens funciona como um buffer que nivela a carga. O Padrão de nivelamento de carga com base em fila descreve esse cenário mais detalhadamente.