Exercício - Enviar e receber mensagens usando uma fila

Concluído

Você optou por usar uma fila do Barramento de Serviço para lidar com mensagens sobre vendas individuais entre o aplicativo móvel, que sua equipe de vendas usa, e o serviço Web hospedado no Azure, que armazena detalhes sobre cada venda em uma instância do Banco de Dados SQL do Azure.

No exercício anterior, você implementou os objetos necessários em sua assinatura do Azure. Agora, vai escrever o código que envia mensagens para essa fila e obtém mensagens.

Nesta unidade, você criará dois aplicativos de console: um aplicativo coloca mensagens em uma fila do Service Bus e um aplicativo recupera mensagens de uma fila do Service Bus. As aplicações fazem parte de uma única solução .NET Core.

Obter a cadeia de conexão para o namespace do Service Bus

Você deve configurar duas informações em seus dois aplicativos de console para acessar seu namespace do Service Bus e usar a fila dentro desse namespace:

  • Ponto de extremidade para seu namespace
  • Chave de acesso compartilhada para autenticação

Você pode obter esses valores da cadeia de conexão.

  1. No Azure Cloud Shell à direita, execute o seguinte comando, substituindo <namespace-name> pelo namespace do Service Bus que você criou no último exercício.

    az servicebus namespace authorization-rule keys list \
        --resource-group <rgn>[sandbox resource group name]</rgn> \
        --name RootManageSharedAccessKey \
        --query primaryConnectionString \
        --output tsv \
        --namespace-name <namespace-name>
    

    A última linha na resposta é a cadeia de conexão, que contém o ponto de extremidade para seu namespace e a chave de acesso compartilhado. Deve assemelhar-se ao seguinte exemplo:

    Endpoint=sb://example.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=AbCdEfGhIjKlMnOpQrStUvWxYz==
    
  2. Copie a cadeia de conexão do Cloud Shell. Você precisará dessa cadeia de conexão várias vezes ao longo deste módulo, então talvez queira salvá-la em algum lugar útil.

Clonar e abrir a aplicação de arranque

Nota

Para simplificar, as tarefas a seguir instruem você a codificar a cadeia de conexão no arquivo Program.cs de ambos os aplicativos de console. Em um aplicativo de produção, você deve usar um arquivo de configuração ou o Azure Key Vault para armazenar a cadeia de conexão.

  1. Execute o seguinte comando no Cloud Shell para clonar a solução de projeto Git:

    cd ~
    git clone https://github.com/MicrosoftDocs/mslearn-connect-services-together.git
    
  2. Execute o seguinte comando para ir para a pasta inicial em seu projeto clonado e abra o editor do Cloud Shell:

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

Escrever código para enviar uma mensagem para uma fila

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

    const string ServiceBusConnectionString = "";
    

    Cole a cadeia de ligação entre as aspas.

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

    const string QueueName = "salesmessages";
    
  3. Para concluir o componente que envia mensagens sobre vendas, você deve adicionar um await operador para suspender a avaliação do método assíncrono até que a operação assíncrona seja concluída. Encontre o SendSalesMessageAsync() método. 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 once the client variable goes out of scope. 
    // In more realistic scenarios, you would want to store off a class reference to the client (rather than a local variable) so that it can be used throughout your program.
    
    await using var client = new ServiceBusClient(ServiceBusConnectionString);
    
  4. Dentro do SendSalesMessageAsync() método, localize a seguinte linha de código:

    // Create a sender here
    

    Substitua esse comentário pelo seguinte código:

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

    // Create and send a message here
    

    Substitua essa linha de código pelas seguintes linhas de código:

    string messageBody = $"$10,000 order for bicycle parts from retailer Adventure Works.";
    var message = new ServiceBusMessage(messageBody);
    
  6. Insira o seguinte código em uma nova linha diretamente abaixo do que você acabou de adicionar para exibir a mensagem no console:

    Console.WriteLine($"Sending message: {messageBody}");
    
  7. Insira o seguinte código na próxima linha:

    await sender.SendMessageAsync(message);
    
  8. Para descartar objetos de remetente e cliente, perto do final do arquivo, localize o seguinte comentário:

    // Close the connection to the sender here
    

    Substitua a linha pelo código seguinte:

    finally
    {
        // Calling DisposeAsync on client types is required to ensure that network
        // resources and other unmanaged objects are properly cleaned up.
        await sender.DisposeAsync();
        await client.DisposeAsync();
    }
    
  9. Verifique se o código final para privatemessagesender/Program.cs é semelhante ao exemplo a seguir:

    using System;
    using System.Text;
    using System.Threading.Tasks;
    using Azure.Messaging.ServiceBus;
    
    namespace privatemessagesender
    {
        class Program
        {
            const string ServiceBusConnectionString = "Endpoint=sb://example.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=AbCdEfGhIjKlMnOpQrStUvWxYz==";
            const string QueueName = "salesmessages";
    
            static void Main(string[] args)
            {
                Console.WriteLine("Sending a message to the Sales Messages queue...");
                SendSalesMessageAsync().GetAwaiter().GetResult();
                Console.WriteLine("Message was sent successfully.");
            }
    
            static async Task SendSalesMessageAsync()
            {
                await using var client = new ServiceBusClient(ServiceBusConnectionString);
    
                await using ServiceBusSender sender = client.CreateSender(QueueName);
                try
                {
                    string messageBody = $"$10,000 order for bicycle parts from retailer Adventure Works.";
                    var message = new ServiceBusMessage(messageBody);
                    Console.WriteLine($"Sending message: {messageBody}");
                    await sender.SendMessageAsync(message);
                }
                catch (Exception exception)
                {
                    Console.WriteLine($"{DateTime.Now} :: Exception: {exception.Message}");
                }
                finally
                {
                    // Calling DisposeAsync on client types is required to ensure that network
                    // resources and other unmanaged objects are properly cleaned up.
                    await sender.DisposeAsync();
                    await client.DisposeAsync();
                }
            }
        }
    }
    
  10. Para guardar as alterações, prima Ctrl+S e, em seguida, prima Ctrl+Q para fechar o editor.

Enviar uma mensagem para a fila

  1. No Cloud Shell, execute o seguinte comando para enviar uma mensagem sobre uma venda. A primeira linha garante que você está no caminho correto.

    cd ~/mslearn-connect-services-together/implement-message-workflows-with-service-bus/src/start
    dotnet run --project ./privatemessagesender
    

    Nota

    Na primeira vez que você executar os aplicativos neste exercício, permita dotnet restaurar pacotes de fontes remotas e criar os aplicativos.

    À medida que o programa é executado, as mensagens são impressas no console indicando que o aplicativo está enviando uma mensagem:

    Sending a message to the Sales Messages queue...
    Sending message: $10,000 order for bicycle parts from retailer Adventure Works.
    Message was sent successfully.
    
  2. Quando o aplicativo estiver concluído, execute o seguinte comando, substituindo <namespace-name> pelo nome do namespace do Service Bus. Este comando retorna o número de mensagens que estão na fila.

    az servicebus queue show \
        --resource-group <rgn>[sandbox resource group name]</rgn> \
        --name salesmessages \
        --query messageCount \
        --namespace-name <namespace-name>
    
  3. Execute o comando da etapa 1 novamente e, em seguida, execute o dotnet runservicebus queue show comando novamente. Cada vez que você executa o aplicativo dotnet, uma nova mensagem é adicionada à fila. Você verá o aumento sempre que executar o messageCount comando do Azure.

Escrever código para receber mensagens da fila

  1. Execute o seguinte comando para abrir o editor novamente:

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

    const string ServiceBusConnectionString = "";
    

    Entre aspas, cole a cadeia de conexão salva anteriormente.

  3. Encontre o ReceiveSalesMessageAsync() método. Dentro desse método, localize a seguinte linha de código:

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

    Substitua a linha pelo código seguinte:

    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 essa linha pelas seguintes linhas de código:

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

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

    Substitua a linha pelo código seguinte:

    await using ServiceBusProcessor processor = client.CreateProcessor(QueueName, processorOptions);
    
  6. Para configurar os manipuladores, localize a seguinte linha de código:

    // Configure the message and error handler to use
    

    Substitua a linha pelo código seguinte:

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

    // Start processing
    

    Substitua a linha pelo código seguinte:

    await processor.StartProcessingAsync();
    
  8. Para fechar a conexão com o Service Bus, localize a seguinte linha de código:

    // Close the processor here
    

    Substitua a linha pelo código seguinte:

    await processor.CloseAsync();
    
  9. Revise o código no MessageHandler método:

    // handle received messages
    static async Task MessageHandler(ProcessMessageEventArgs args)
    {
        // extract the message
        string body = args.Message.Body.ToString();
    
        // print the message
        Console.WriteLine($"Received: {body}");
    
        // complete the message so that message is deleted from the queue. 
        await args.CompleteMessageAsync(args.Message);
    }
    
  10. Revise o código no ErrorHandler método:

    // handle any errors when receiving messages
    static Task ErrorHandler(ProcessErrorEventArgs args)
    {
        // print the exception message
        Console.WriteLine(args.Exception.ToString());
        return Task.CompletedTask;
    }    
    
  11. Verifique se o código final para privatemessagereceiver/Program.cs é semelhante ao exemplo a seguir:

    using System;
    using System.Text;
    using System.Threading.Tasks;
    using Azure.Messaging.ServiceBus;
    
    namespace privatemessagereceiver
    {
        class Program
        {
    
            const string ServiceBusConnectionString = "Endpoint=sb://<examplenamespace.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
            const string QueueName = "salesmessages";
    
            static void Main(string[] args)
            {
    
                ReceiveSalesMessageAsync().GetAwaiter().GetResult();
    
            }
    
            static async Task ReceiveSalesMessageAsync()
            {
    
                Console.WriteLine("======================================================");
                Console.WriteLine("Press ENTER key to exit after receiving all the messages.");
                Console.WriteLine("======================================================");
    
    
                var client = new ServiceBusClient(ServiceBusConnectionString);
    
                var processorOptions = new ServiceBusProcessorOptions
                {
                    MaxConcurrentCalls = 1,
                    AutoCompleteMessages = false
                };
    
                await using ServiceBusProcessor processor = client.CreateProcessor(QueueName, processorOptions);
    
                processor.ProcessMessageAsync += MessageHandler;
                processor.ProcessErrorAsync += ErrorHandler;
    
    
                await processor.StartProcessingAsync();
    
                Console.Read();
    
                await processor.CloseAsync();
    
            }
    
            // handle received messages
            static async Task MessageHandler(ProcessMessageEventArgs args)
            {
                string body = args.Message.Body.ToString();
                Console.WriteLine($"Received: {body}");
    
                // complete the message. messages is deleted from the queue. 
                await args.CompleteMessageAsync(args.Message);
            }
    
            // handle any errors when receiving messages
            static Task ErrorHandler(ProcessErrorEventArgs args)
            {
                Console.WriteLine(args.Exception.ToString());
                return Task.CompletedTask;
            }
        }
    }
    
    
  12. Para guardar as alterações, prima Ctrl+S e, em seguida, prima Ctrl+Q para fechar o editor.

Receber uma mensagem da fila

  1. Para executar o componente que recebe uma mensagem sobre uma venda, execute este comando no Cloud Shell:

    dotnet run --project privatemessagereceiver
    
  2. Verifique as notificações no Cloud Shell. No portal do Azure, vá para o namespace do Service Bus e verifique o gráfico de Mensagens :

    Received: $10,000 order for bicycle parts from retailer Adventure Works.
    
  3. Quando vir que as mensagens foram recebidas no Cloud Shell, prima Enter para parar a aplicação.

Verifique a contagem de mensagens

Execute o código a seguir para confirmar que todas as mensagens foram removidas da fila, lembrando-se de substituir <namespace-name> pelo namespace do Service Bus.

az servicebus queue show \
    --resource-group <rgn>[sandbox resource group name]</rgn> \
    --name salesmessages \
    --query messageCount \
    --namespace-name <namespace-name>

A saída será 0 se todas as mensagens tiverem sido removidas.

Você escreveu um código que envia uma mensagem sobre vendas individuais para uma fila do Service Bus. No aplicativo distribuído salesforce, você deve escrever esse código no aplicativo móvel que o pessoal de vendas usa nos dispositivos.

Você também escreveu código que recebe uma mensagem da fila do Service Bus. No aplicativo distribuído salesforce, você deve escrever esse código no serviço Web que é executado no Azure e processa as mensagens recebidas.