Exercício – enviar e receber mensagens usando um tópico

Concluído

Você decidiu usar um tópico do Barramento de Serviço do Azure para distribuir mensagens sobre o desempenho de vendas em seu aplicativo do Salesforce. O pessoal de vendas usará o aplicativo nos dispositivos móveis deles para enviar mensagens que resumam os números de vendas para cada área e período. Essas mensagens são distribuídas para os serviços Web localizados nas regiões operacionais da empresa, incluindo Américas e Europa.

Você já implementou a infraestrutura necessária em suas assinaturas do Azure para o tópico. Agora você quer escrever o código a fim de enviar mensagens para o tópico e recuperar mensagens de uma assinatura. Então você enviará uma mensagem para um tópico e recuperará a mensagem para uma assinatura específica.

Para saber se você está trabalhando no diretório correto, execute os seguintes comandos no Azure Cloud Shell:

cd ~/mslearn-connect-services-together/implement-message-workflows-with-service-bus/src/start
code .

Escrever código para enviar uma mensagem a um tópico

Para concluir o componente que envia mensagens sobre o desempenho de vendas, siga estas etapas:

  1. No editor do Azure Cloud Shell, abra performancemessagesender/Program.cs e localize a seguinte linha de código:

    const string ServiceBusConnectionString = "";
    

    Entre as aspas, cole a cadeia de conexão que você salvou no exercício anterior.

  2. Se você usou um nome diferente de salesperformancemessages para o nome da fila, atualize o valor da propriedade TopicName no código:

    const string TopicName = "salesperformancemessages";
    
  3. Encontre o método SendPerformanceMessageAsync(). (Dica: ela fica próximo ou na linha 26.) Dentro desse método, localize a seguinte linha de código:

    // Create a Service Bus client here
    

    Substitua essa linha de código pelo seguinte código:

    // By leveraging "await using", the DisposeAsync method will be called automatically when the client variable goes out of scope.
    // In more realistic scenarios, you would store off a class reference to the client (rather than to a local variable) so that it can be used throughout your program.
    await using var client = new ServiceBusClient(ServiceBusConnectionString);
    
  4. Dentro do método SendPerformanceMessageAsync(), localize a seguinte linha de código:

    // Create a sender here
    

    Substitua essa linha de código pelo seguinte código:

    await using ServiceBusSender sender = client.CreateSender(TopicName);
    
  5. No bloco try...catch, localize a seguinte linha de código:

    // Create and send a message here
    

    Substitua essa linha de código pelo seguinte código:

    string messageBody = "Total sales for Brazil in August: $13m.";
    var message = new ServiceBusMessage(messageBody);
    
  6. Para exibir a mensagem no console, na próxima linha, insira o código a seguir:

    Console.WriteLine($"Sending message: {messageBody}");
    
  7. Para enviar a mensagem para o tópico, na próxima linha, insira o código a seguir:

    await sender.SendMessageAsync(message);
    
  8. Verifique se o código final é semelhante ao exemplo a seguir:

    using System;
    using System.Threading.Tasks;
    using Azure.Messaging.ServiceBus;
    
    namespace performancemessagesender
    {
        class Program
        {
            const string ServiceBusConnectionString = "Endpoint=sb://example.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=AbCdEfGhIjKlMnOpQrStUvWxYz==";
            const string TopicName = "salesperformancemessages";
    
            static void Main(string[] args)
            {
                Console.WriteLine("Sending a message to the Sales Performance topic...");
                SendPerformanceMessageAsync().GetAwaiter().GetResult();
                Console.WriteLine("Message was sent successfully.");
            }
    
            static async Task SendPerformanceMessageAsync()
            {
                // By leveraging "await using", the DisposeAsync method will be called automatically once the client variable goes out of scope.
                // In more realistic scenarios, you would store off a class reference to the client (rather than to a local variable) so that it can be used throughout your program.
                await using var client = new ServiceBusClient(ServiceBusConnectionString);
    
                await using ServiceBusSender sender = client.CreateSender(TopicName);
    
                try
                {
                    string messageBody = "Total sales for Brazil in August: $13m.";
                    var message = new ServiceBusMessage(messageBody);
                    Console.WriteLine($"Sending message: {messageBody}");
                    await sender.SendMessageAsync(message);
                }
                catch (Exception exception)
                {
                    Console.WriteLine($"{DateTime.Now} :: Exception: {exception.Message}");
                }
            }
        }
    }
    
  9. Para salvar as alterações, selecione Ctrl+S e depois Ctrl+Q para fechar o editor.

Enviar uma mensagem para o tópico

  1. Para executar o componente que envia uma mensagem sobre uma venda, execute o comando a seguir no Cloud Shell:

    dotnet run --project performancemessagesender
    
  2. À medida que o programa é executado, observe as notificações no Cloud Shell que indicam que uma mensagem está sendo enviada. Cada vez que você executa o aplicativo, outra mensagem é adicionada ao tópico e uma cópia fica disponível para cada assinatura.

    Sending a message to the Sales Performance topic...
    Sending message: Total sales for Brazil in August: $13m.
    Message was sent successfully.
    

Verifique a contagem de mensagens antes de recuperar mensagens para uma assinatura

Ao ver Message was sent successfully, execute o seguinte comando para ver quantas mensagens estão na assinatura das Americas. Lembre-se de substituir <namespace-name> pelo namespace do Barramento de Serviço.

az servicebus topic subscription show \
    --resource-group <rgn>[sandbox resource group name]</rgn> \
    --topic-name salesperformancemessages \
    --name Americas \
    --query messageCount \
    --namespace-name <namespace-name>

Se você substituir Americas por EuropeAndAsia e executar novamente o comando, verá que as duas assinaturas têm o mesmo número de mensagens.

Escrever código para recuperar uma mensagem de tópico para uma assinatura

Para criar o componente que recupera mensagens sobre desempenho de vendas, siga estas etapas:

  1. Execute code . para iniciar o editor.

  2. No editor, abra performancemessagereceiver/Program.cs e localize a seguinte linha de código:

    const string ServiceBusConnectionString = "";
    

    Entre as aspas, cole a cadeia de conexão que você salvou no exercício anterior.

  3. Para criar um cliente de Barramento de Serviço, localize o método MainAsync(). Nesse método, localize a seguinte linha de código:

    // Create a Service Bus client that will authenticate using a connection string
    

    Substitua a linha por este código:

    var client = new ServiceBusClient(ServiceBusConnectionString);
    
  4. Para configurar as opções de tratamento de mensagens, localize a seguinte linha de código:

    // Create the options to use for configuring the processor
    

    Substitua a linha por este código:

    var processorOptions = new ServiceBusProcessorOptions
    {
        MaxConcurrentCalls = 1,
        AutoCompleteMessages = false
    };
    
  5. Para criar um processador, encontre a seguinte linha de código:

    // Create a processor that we can use to process the messages
    

    Substitua a linha por este código:

    ServiceBusProcessor processor = client.CreateProcessor(TopicName, SubscriptionName, processorOptions);
    
  6. Para configurar o manipulador, localize a seguinte linha de código:

    // Configure the message and error handler to use
    

    Substitua a linha por este código:

    processor.ProcessMessageAsync += MessageHandler;
    processor.ProcessErrorAsync += ErrorHandler;
    
  7. Para iniciar o processamento, encontre a seguinte linha de código:

    // Start processing
    

    Substitua a linha por este código:

    await processor.StartProcessingAsync();
    
  8. Procure a seguinte linha de código:

    // Since we didn't use the "await using" syntax here, we need to explicitly dispose the processor and client    
    

    Substitua a linha por este código:

    await processor.DisposeAsync();
    await client.DisposeAsync();    
    
  9. Para exibir as mensagens recebidas no console, localize o método MessageHandler(). Você registrou esse método para gerenciar as mensagens de entrada.

    Substitua todo o código dentro desse método pelo seguinte código:

    Console.WriteLine($"Received message: SequenceNumber:{args.Message.SequenceNumber} Body:{args.Message.Body}");
    
  10. Para remover a mensagem recebida da assinatura, na próxima linha, adicione o seguinte código:

    await args.CompleteMessageAsync(args.Message);
    
  11. Verifique se o código final é semelhante ao exemplo a seguir:

    using System;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using Azure.Messaging.ServiceBus;
    
    namespace performancemessagereceiver
    {
        class Program
        {
            const string ServiceBusConnectionString = "Endpoint=sb://alexgeddyneil.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=LIWIyxs8baqQ0bRf5zJLef6OTfrv0kBEDxFM/ML37Zs=";
            const string TopicName = "salesperformancemessages";
            const string SubscriptionName = "Americas";
    
            static void Main(string[] args)
            {
                MainAsync().GetAwaiter().GetResult();
            }
    
            static async Task MainAsync()
            {
                var client = new ServiceBusClient(ServiceBusConnectionString);
    
                Console.WriteLine("======================================================");
                Console.WriteLine("Press ENTER key to exit after receiving all the messages.");
                Console.WriteLine("======================================================");
    
                var processorOptions = new ServiceBusProcessorOptions
                {
                    MaxConcurrentCalls = 1,
                    AutoCompleteMessages = false
                };
    
                ServiceBusProcessor processor = client.CreateProcessor(TopicName, SubscriptionName, processorOptions);
    
                processor.ProcessMessageAsync += MessageHandler;
                processor.ProcessErrorAsync += ErrorHandler;
    
                await processor.StartProcessingAsync();
    
                Console.Read();
    
                await processor.DisposeAsync();
                await client.DisposeAsync();
            }
    
            static async Task MessageHandler(ProcessMessageEventArgs args)
            {
                Console.WriteLine($"Received message: SequenceNumber:{args.Message.SequenceNumber} Body:{args.Message.Body}");
                await args.CompleteMessageAsync(args.Message);
            }
    
            static Task ErrorHandler(ProcessErrorEventArgs args)
            {
                Console.WriteLine($"Message handler encountered an exception {args.Exception}.");
                Console.WriteLine("Exception context for troubleshooting:");
                Console.WriteLine($"- Endpoint: {args.FullyQualifiedNamespace}");
                Console.WriteLine($"- Entity Path: {args.EntityPath}");
                Console.WriteLine($"- Executing Action: {args.ErrorSource}");
                return Task.CompletedTask;
            }
        }
    }
    
  12. Para salvar as alterações, selecione Ctrl+S e depois Ctrl+Q para fechar o editor.

Recuperar uma mensagem de tópico para uma assinatura

  1. Para executar o componente que recupera uma mensagem sobre o desempenho de vendas de uma assinatura, execute o seguinte comando:

    dotnet run --project performancemessagereceiver
    

    Você verá uma saída semelhante ao exemplo a seguir:

    Received message: SequenceNumber:1 Body:Total sales for Brazil in August: $13m.
    
  2. Quando o programa retornar notificações de que está recebendo mensagens, pressione Enter para parar o aplicativo.

Verificar a contagem de mensagens depois de recuperar uma mensagem para uma assinatura

Execute o seguinte comando para confirmar que não há mensagens restantes na assinatura das Americas. Substitua <namespace-name> pelo namespace do Barramento de Serviço.

az servicebus topic subscription show \
     --resource-group <rgn>[sandbox resource group name]</rgn> \
     --topic-name salesperformancemessages \
     --name Americas \
     --query messageCount \
     --namespace-name <namespace-name> 

Se você substituir Americas por EuropeAndAsia nesse código para ver a contagem de mensagens atual da assinatura de EuropeAndAsia, verá que a contagem de mensagens é 1. No código anterior, apenas a assinatura das Americas foi definida para recuperar mensagens de tópico. Portanto, essa mensagem ainda está aguardando que EuropeAndAsia a recupere.