Compartilhar via


Tutorial: Atualizar estoque usando o portal do Azure e tópicos/assinaturas

Este tutorial mostra como usar tópicos e assinaturas do Service Bus em um cenário de inventário de varejo. Ele inclui canais de publicação/assinatura usando o portal do Azure e o .NET. Um exemplo desse cenário é uma atualização de sortimento de estoque para várias lojas de varejo. Nesse cenário, cada loja ou conjunto de lojas recebe mensagens que são destinadas para atualizar os respectivos sortimentos.

O Barramento de Serviço do Azure é um serviço de mensagens de nuvem de vários locatários que envia informações entre aplicativos e serviços. Operações assíncronas oferecem um sistema de mensagens agenciado e flexível, juntamente com recursos de mensagens PEPS (primeiro a entrar, primeiro a sair) e de publicação/assinatura. Para obter uma visão geral, confira O que é o Service Bus?

Este tutorial mostra como implementar esse cenário usando assinaturas e filtros. Primeiro, você cria um tópico com três assinaturas, adiciona algumas regras e filtros e envia e recebe mensagens do tópico e das assinaturas.

Diagrama mostrando um remetente, um tópico com três assinaturas e três receptores.

Neste tutorial, você aprenderá como:

  • Criar um tópico do Barramento de Serviço e três assinaturas para esse tópico usando o portal do Azure
  • Adicionar filtros para assinaturas usando código .NET
  • Criar mensagens com conteúdo diferente
  • Enviar mensagens e verificar se chegaram nas assinaturas esperadas
  • Receber mensagens das assinaturas

Pré-requisitos

Para concluir este tutorial, verifique se você tem:

  • Uma assinatura do Azure. Para usar os serviços do Azure, incluindo o Barramento de Serviço do Azure, você precisa ter uma assinatura. Você pode criar uma conta gratuita antes de começar.
  • Visual Studio 2019 ou posterior.

Tópicos e assinaturas do Barramento de Serviço

Cada assinatura a um tópico pode receber uma cópia de cada mensagem. Os tópicos tem total compatibilidade de protocolo e semântica com filas do Barramento de Serviço. Os tópicos do Barramento de Serviço dão suporte a uma ampla matriz de regras de seleção com condições de filtro, com ações opcionais que definem ou modificam as propriedades da mensagem. Cada vez que uma regra corresponde, é produzida uma mensagem. Para saber mais sobre regras, filtros e ações, consulte os filtros e as ações do tópico.

Criar um namespace no portal do Azure

Para começar a usar entidades de mensagens do Barramento de Serviço no Azure, crie um namespace com um nome único em todo o Azure. Um namespace fornece um contêiner de escopo para recursos do Barramento de Serviço, como filas e tópicos, no seu aplicativo.

Para criar um namespace:

  1. Entre no portal do Azure.

  2. Selecione o menu de submenu no canto superior esquerdo e navegue até a página Todos os serviços.

  3. Na barra de navegação à esquerda, selecione Integração.

  4. Role para baixo até oBarramento de > e selecione Criar.

    Captura de tela mostrando a seleção de Criar um recurso, Integração e, por fim, Barramento de Serviço no menu.

  5. Na guia Noções básicas da página Criar namespace , siga estas etapas:

    1. Em Assinatura, escolha uma assinatura do Azure na qual criar o namespace.

    2. Em Grupo de recursos, escolha um grupo de recursos existente ou crie um.

    3. Insira um nome de namespace que atenda às seguintes convenções de nomenclatura:

      • O nome deve ser exclusivo em todo o Azure. O sistema imediatamente verifica para ver se o nome está disponível.
      • O nome deve ter no mínimo 6 e no máximo 50 caracteres.
      • O nome pode conter apenas letras, números e hifens -.
      • O nome precisa começar com uma letra e terminar com uma letra ou um número.
      • O nome não termina com -sb ou -mgmt.
    4. Para Localização, escolha a região para hospedar seu namespace.

    5. Selecione o Tipo de preço (Básico, Standard ou Premium) do namespace. Para esse início rápido, selecione Padrão.

      Se você selecionar a camada Premium , poderá habilitar a replicação geográfica para o namespace. O recurso de replicação geográfica garante que os metadados e os dados de um namespace sejam replicados continuamente de uma região primária para uma ou mais regiões secundárias.

      Importante

      Se você quiser usar tópicos e assinaturas, escolha Standard ou Premium. Não há suporte para tópicos e assinaturas no tipo de preço Básico.

      Se você selecionou o tipo de preço Premium, especifique o número de unidades do sistema de mensagens. A camada Premium fornece isolamento de recursos no nível de CPU e memória, de modo que cada carga de trabalho seja executada isoladamente. Esse contêiner de recurso é chamado de unidade do sistema de mensagens. Um namespace premium tem pelo menos uma unidade do sistema de mensagens. Você pode selecionar 1, 2, 4, 8 ou 16 unidades do sistema de mensagens para cada namespace Premium do Barramento de Serviço. Para obter mais informações, veja Camada de mensagens premium do Barramento de Serviço.

    6. Selecione Revisar + criar na parte inferior da página.

      Captura de tela mostrando a página Criar um namespace

    7. Na páginaRevisar + criar,revise as configurações e selecioneCriar.

  6. Depois que a implantação do recurso for bem-sucedida, selecione Ir para o recurso na página de implantação.

    Captura de tela mostrando a página de implantação bem-sucedida com o link Ir para o recurso.

  7. Você verá a página inicial do namespace do barramento de serviço.

    Captura de tela que mostra a página inicial do namespace do Barramento de Serviço criado.

Obter a cadeia de conexão para o namespace (portal do Azure)

A criação de um novo namespace gera automaticamente uma política de SAS (Assinatura de Acesso Compartilhado) inicial. A política inclui chaves primárias e secundárias e cadeias de conexão primárias e secundárias que concedem controle total sobre todos os aspectos do namespace. Para obter mais informações sobre como criar regras com direitos mais restritos para usuários frequentes, consulte Autenticação e Autorização do Service Bus.

Um cliente pode usar a cadeia de conexão para se conectar ao namespace do Barramento de Serviço. Para copiar a cadeia de conexão primária para seu namespace, siga estas etapas:

  1. Na página Namespace do Barramento de Serviço, expanda Configurações e selecione Políticas de acesso compartilhado.

  2. Na página Políticas de acesso compartilhado, selecione RootManageSharedAccessKey.

  3. Na janela Política SAS: RootManageSharedAccessKey, selecione o botão de copiar ao lado de Cadeia de Conexão Primária. Isso copiará a cadeia de conexão para a área de transferência para uso posterior. Cole esse valor no Bloco de notas ou em outro local temporário.

    A captura de tela mostra uma política S A S chamada RootManageSharedAccessKey, que inclui chaves e cadeias de conexão.

    Você pode usar essa página para copiar a chave primária, a chave secundária, a cadeia de conexão primária e a cadeia de conexão secundária.

Criar um tópico usando o portal do Azure

  1. Na página Namespace do Barramento de Serviço, expanda Entidades no menu de navegação à esquerda e selecione Tópicos.

  2. Selecione + Tópico.

  3. Insira um nome para o tópico. Deixe as outras opções com os valores padrão.

  4. Selecione Criar.

    Captura de tela da página Criar tópico.

Criar duas assinaturas do tópico

  1. Selecione o tópico que você criou na seção anterior.

    Captura de tela da página Tópicos com o tópico selecionado.

  2. Na página Tópico de Barramento de Serviço, selecione + Assinatura.

    Captura de tela da página Assinaturas com o botão Adicionar assinatura selecionado.

  3. Na página Criar assinatura, siga estas etapas:

    1. Insira S1 como o nome da assinatura.

    2. Em seguida, selecione Criar para criar a assinatura.

      Captura de tela da página Criar assinatura.

  4. Repita a etapa anterior mais duas vezes, criando assinaturas nomeadas como S2 e S3.

Criar regras de filtro nas assinaturas

Depois de provisionar o namespace, os tópicos e as assinaturas e obter a cadeia de conexão para o namespace, você estará pronto para criar regras de filtro nas assinaturas. Depois disso, envie e receba mensagens. É possível examinar o código nesta pasta de exemplo do GitHub.

Enviar e receber mensagens

Para executar o código, siga estas etapas:

  1. Em uma janela do Prompt de Comando ou em um prompt do PowerShell, clone o repositório GitHub do Barramento de Serviço:

    git clone https://github.com/Azure/azure-service-bus.git
    
  2. Navegue até a pasta de exemplo azure-service-bus\samples\DotNet\Azure.Messaging.ServiceBus\BasicSendReceiveTutorialWithFilters.

  3. Obtenha a cadeia de conexão que você copiou anteriormente para o Bloco de Notas neste tutorial. Você também precisa do nome do tópico que você criou.

  4. No prompt de comando, digite o comando a seguir:

    dotnet build
    
  5. Navegue até a pasta BasicSendReceiveTutorialWithFilters\bin\Debug\netcoreapp3.1.

  6. Para executar o programa, insira o comando a seguir. Certifique-se de substituir myConnectionString pelo seu valor e myTopicName pelo nome do tópico que você criou.

    dotnet --roll-forward Major BasicSendReceiveTutorialWithFilters.dll -ConnectionString "myConnectionString" -TopicName "myTopicName"
    
  7. Siga as instruções no console para selecionar a criação do filtro primeiro. Parte da criação do filtro é remover os filtros padrão. Ao usar o PowerShell ou a CLI, você não precisa remover o filtro padrão. Se você usar o código para criar filtros, primeiro remova o filtro padrão. Os comandos dos consoles 1 e 3 ajudam a gerenciar os filtros nas assinaturas criadas anteriormente:

    • Execute 1: para remover os filtros padrão.
    • Execute 2: para adicionar seus próprios filtros.
    • Execute 3: Ignore esta etapa para o tutorial. Opcionalmente, fazer isso remove seus filtros. Ele não recria os filtros padrão.

    A captura de tela mostra a saída do comando 2.

  8. Após a criação do filtro, será possível enviar mensagens. Pressione 4 e observe 10 mensagens sendo enviadas para o tópico:

    A captura de tela mostra o resultado de 10 mensagens sendo enviadas.

  9. Pressione 5 e observe as mensagens sendo recebidas. Se você não recebeu 10 mensagens de volta, pressione "m" para exibir o menu e pressione 5 novamente.

    A captura de tela mostra a saída das mensagens recebidas.

Limpar os recursos

Execute estas etapas para limpar os recursos quando eles deixarem de ser necessários.

  1. Navegue até o namespace no portal do Azure.
  2. Na página Namespace do Barramento de Serviço, selecione Excluir na barra de comandos para excluir o namespace e os recursos (filas, tópicos e assinaturas) nele.

Entender o código de exemplo

Esta seção contém mais detalhes sobre o que o código de exemplo faz.

Obter cadeia de conexão e tópico

Primeiro, o código declara um conjunto de variáveis, que conduz a execução restante do programa.

string ServiceBusConnectionString;
string TopicName;

static string[] Subscriptions = { "S1", "S2", "S3" };
static IDictionary<string, string[]> SubscriptionFilters = new Dictionary<string, string[]> {
    { "S1", new[] { "StoreId IN('Store1', 'Store2', 'Store3')", "StoreId = 'Store4'"} },
    { "S2", new[] { "sys.To IN ('Store5','Store6','Store7') OR StoreId = 'Store8'" } },
    { "S3", new[] { "sys.To NOT IN ('Store1','Store2','Store3','Store4','Store5','Store6','Store7','Store8') OR StoreId NOT IN ('Store1','Store2','Store3','Store4','Store5','Store6','Store7','Store8')" } }
};
// You can have only have one action per rule and this sample code supports only one action for the first filter, which is used to create the first rule. 
static IDictionary<string, string> SubscriptionAction = new Dictionary<string, string> {
    { "S1", "" },
    { "S2", "" },
    { "S3", "SET sys.Label = 'SalesEvent'"  }
};
static string[] Store = { "Store1", "Store2", "Store3", "Store4", "Store5", "Store6", "Store7", "Store8", "Store9", "Store10" };
static string SysField = "sys.To";
static string CustomField = "StoreId";
static int NrOfMessagesPerStore = 1; // Send at least 1.

A cadeia de conexão e o nome do tópico são passados usando parâmetros de linha de comando, conforme mostrado. Eles são lidos no método Main():

static void Main(string[] args)
{
    string ServiceBusConnectionString = "";
    string TopicName = "";

    for (int i = 0; i < args.Length; i++)
    {
        if (args[i] == "-ConnectionString")
        {
            Console.WriteLine($"ConnectionString: {args[i + 1]}");
            ServiceBusConnectionString = args[i + 1]; // Alternatively enter your connection string here.
        }
        else if (args[i] == "-TopicName")
        {
            Console.WriteLine($"TopicName: {args[i + 1]}");
            TopicName = args[i + 1]; // Alternatively enter your queue name here.
        }
    }

    if (ServiceBusConnectionString != "" && TopicName != "")
    {
        Program P = StartProgram(ServiceBusConnectionString, TopicName);
        P.PresentMenu().GetAwaiter().GetResult();
    }
    else
    {
        Console.WriteLine("Specify -Connectionstring and -TopicName to execute the example.");
        Console.ReadKey();
    }
}

Remover filtros padrão

Quando você cria uma assinatura, o Barramento de Serviço cria um filtro padrão por assinatura. Este filtro permite receber todas as mensagens enviadas para o tópico. Se você quiser usar filtros personalizados, poderá remover o filtro padrão, conforme mostrado no código a seguir:

private async Task RemoveDefaultFilters()
{
    Console.WriteLine($"Starting to remove default filters.");

    try
    {
        var client = new ServiceBusAdministrationClient(ServiceBusConnectionString);
        foreach (var subscription in Subscriptions)
        {
            await client.DeleteRuleAsync(TopicName, subscription, CreateRuleOptions.DefaultRuleName);
            Console.WriteLine($"Default filter for {subscription} has been removed.");
        }

        Console.WriteLine("All default Rules have been removed.\n");
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }

    await PresentMenu();
}

Criar filtros

O código a seguir inclui os filtros personalizados definidos neste tutorial:

private async Task CreateCustomFilters()
{
    try
    {
        for (int i = 0; i < Subscriptions.Length; i++)
        {
            var client = new ServiceBusAdministrationClient(ServiceBusConnectionString);
            string[] filters = SubscriptionFilters[Subscriptions[i]];
            if (filters[0] != "")
            {
                int count = 0;
                foreach (var myFilter in filters)
                {
                    count++;

                    string action = SubscriptionAction[Subscriptions[i]];
                    if (action != "")
                    {
                        await client.CreateRuleAsync(TopicName, Subscriptions[i], new CreateRuleOptions
                        {
                            Filter = new SqlRuleFilter(myFilter),
                            Action = new SqlRuleAction(action),
                            Name = $"MyRule{count}"
                        });
                    }
                    else
                    {
                        await client.CreateRuleAsync(TopicName, Subscriptions[i], new CreateRuleOptions
                        {
                            Filter = new SqlRuleFilter(myFilter),
                            Name = $"MyRule{count}"
                        });
                    }
                }
            }

            Console.WriteLine($"Filters and actions for {Subscriptions[i]} have been created.");
        }

        Console.WriteLine("All filters and actions have been created.\n");
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }

    await PresentMenu();
}

Remover os filtros personalizados criados

Se você quiser remover todos os filtros da assinatura, o código a seguir mostra como fazer isso:

private async Task CleanUpCustomFilters()
{
    foreach (var subscription in Subscriptions)
    {
        try
        {
            var client = new ServiceBusAdministrationClient(ServiceBusConnectionString);
            IAsyncEnumerator<RuleProperties> rules = client.GetRulesAsync(TopicName, subscription).GetAsyncEnumerator();
            while (await rules.MoveNextAsync())
            {
                await client.DeleteRuleAsync(TopicName, subscription, rules.Current.Name);
                Console.WriteLine($"Rule {rules.Current.Name} has been removed.");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }
    Console.WriteLine("All default filters have been removed.\n");

    await PresentMenu();
}

Enviar mensagens

Enviar mensagens para um tópico é semelhante ao envio de mensagens para uma fila. Este exemplo mostra como enviar mensagens usando uma lista de tarefas e um processamento assíncrono:

public async Task SendMessages()
{
    try
    {
        await using var client = new ServiceBusClient(ServiceBusConnectionString);
        var taskList = new List<Task>();
        for (int i = 0; i < Store.Length; i++)
        {
            taskList.Add(SendItems(client, Store[i]));
        }

        await Task.WhenAll(taskList);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }
    Console.WriteLine("\nAll messages sent.\n");
}

private async Task SendItems(ServiceBusClient client, string store)
{
    // create the sender
    ServiceBusSender tc = client.CreateSender(TopicName);

    for (int i = 0; i < NrOfMessagesPerStore; i++)
    {
        Random r = new Random();
        Item item = new Item(r.Next(5), r.Next(5), r.Next(5));

        // Note the extension class which is serializing an deserializing messages
        ServiceBusMessage message = item.AsMessage();
        message.To = store;
        message.ApplicationProperties.Add("StoreId", store);
        message.ApplicationProperties.Add("Price", item.GetPrice().ToString());
        message.ApplicationProperties.Add("Color", item.GetColor());
        message.ApplicationProperties.Add("Category", item.GetItemCategory());

        await tc.SendMessageAsync(message);
        Console.WriteLine($"Sent item to Store {store}. Price={item.GetPrice()}, Color={item.GetColor()}, Category={item.GetItemCategory()}"); ;
    }
}

Receber mensagens

As mensagens são recebidas novamente usando uma lista de tarefas e o código usa o envio em lote. Você pode enviar e receber usando envio em lote, mas este exemplo mostra apenas como receber em lote. Na realidade, você não sairia do loop, mas continuaria no loop e definiria um período maior, como um minuto. A chamada de recebimento para o agente é mantida aberta por esse período de tempo. Se as mensagens chegarem, elas serão retornadas imediatamente. Uma nova chamada de recebimento é emitida.

Esse conceito é chamado de sondagem longa. Usar a bomba receptora, que você pode ver em vários exemplos no repositório, é uma opção mais comum. Para obter mais informações, consulte Usar o portal do Azure para criar um namespace do Barramento de Serviço e uma fila.

public async Task Receive()
{
    var taskList = new List<Task>();
    for (var i = 0; i < Subscriptions.Length; i++)
    {
        taskList.Add(this.ReceiveMessages(Subscriptions[i]));
    }

    await Task.WhenAll(taskList);
}

private async Task ReceiveMessages(string subscription)
{
    await using var client = new ServiceBusClient(ServiceBusConnectionString);
    ServiceBusReceiver receiver = client.CreateReceiver(TopicName, subscription);

    // In reality you would not break out of the loop like in this example but would keep looping. The receiver keeps the connection open
    // to the broker for the specified amount of seconds and the broker returns messages as soon as they arrive. The client then initiates
    // a new connection. So in reality you would not want to break out of the loop. 
    // Also note that the code shows how to batch receive, which you would do for performance reasons. For convenience you can also always
    // use the regular receive pump which we show in our Quick Start and in other GitHub samples.
    while (true)
    {
        try
        {
            //IList<Message> messages = await receiver.ReceiveAsync(10, TimeSpan.FromSeconds(2));
            // Note the extension class which is serializing an deserializing messages and testing messages is null or 0.
            // If you think you did not receive all messages, just press M and receive again via the menu.
            IReadOnlyList<ServiceBusReceivedMessage> messages = await receiver.ReceiveMessagesAsync(maxMessages: 100);

            if (messages.Any())
            {
                foreach (ServiceBusReceivedMessage message in messages)
                {
                    lock (Console.Out)
                    {
                        Item item = message.As<Item>();
                        IReadOnlyDictionary<string, object> myApplicationProperties = message.ApplicationProperties;
                        Console.WriteLine($"StoreId={myApplicationProperties["StoreId"]}");
                        if (message.Subject != null)
                        {
                            Console.WriteLine($"Subject={message.Subject}");
                        }
                        Console.WriteLine(
                            $"Item data: Price={item.GetPrice()}, Color={item.GetColor()}, Category={item.GetItemCategory()}");
                    }

                    await receiver.CompleteMessageAsync(message);
                }
            }
            else
            {
                break;
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }
}

Observação

É possível gerenciar os recursos do Barramento de Serviço com o Service Bus Explorer. O Service Bus Explorer permite que usuários se conectem a um namespace de serviço do Barramento de Serviço e administrem entidades de mensagens de uma maneira fácil. A ferramenta fornece recursos avançados, como a funcionalidade de importação/exportação ou a capacidade de testar tópicos, filas, assinaturas, serviços de retransmissão, hubs de notificação e hubs de eventos.

Neste tutorial, você provisionou recursos usando o portal do Azure e, em seguida, enviou e recebeu mensagens de um tópico do Barramento de Serviço e as respectivas assinaturas. Você aprendeu a:

  • Criar um tópico de Barramento de Serviço e uma ou mais assinaturas para esse tópico usando o portal do Azure
  • Adicionar filtros de tópicos usando código .NET
  • Criar duas mensagens com conteúdo diferente
  • Enviar as mensagens e verificar se chegaram nas assinaturas esperadas
  • Receber mensagens das assinaturas

Para obter mais exemplos de envio e recebimento de mensagens, consulte exemplos do Barramento de Serviço no GitHub.

Avance para o próximo tutorial para saber mais sobre como usar os recursos de publicação/assinatura do Barramento de Serviço.