Tutorial: Actualización del inventario mediante Azure Portal y temas y suscripciones

Azure Service Bus es un servicio de mensajería multiinquilino en la nube que envía información entre aplicaciones y servicios. Las operaciones asincrónicas le ofrecen una mensajería flexible y asincrónica, además de funcionalidades de mensajería estructurada de tipo FIFO (primero en entrar, primero en salir) y de publicación y suscripción. Para obtener información general detallada sobre Azure Service Bus, consulte Qué es Service Bus.

Este tutorial muestra cómo utilizar los temas y suscripciones de Service Bus en un escenario de inventario comercial con canales de publicación y suscripción mediante Azure Portal y .NET. Un ejemplo de este escenario es una actualización del surtido de inventario de varias tiendas. En este escenario, cada tienda o conjunto de tiendas, recibe mensajes dirigidos a que actualicen sus inventarios. En este tutorial se muestra cómo implementar este escenario mediante suscripciones y filtros. En primer lugar puede crear un tema con tres suscripciones, agregar algunas reglas y filtros y, a continuación, enviar y recibir mensajes de los temas y las suscripciones.

Image showing a sender, a topic with three subscriptions, and three receivers.

En este tutorial, aprenderá a:

  • Crear un tema de Service Bus y tres suscripciones a ese tema mediante Azure Portal
  • Agregar filtros para las suscripciones mediante código de .NET
  • Crear mensajes con contenido diferente
  • Enviar mensajes y comprobar que llegan a las suscripciones esperadas
  • Recibir mensajes de las suscripciones

Requisitos previos

Para completar este tutorial, asegúrese de disponer de los siguientes elementos:

  • Suscripción de Azure. Para usar los servicios de Azure, entre los que se incluye Azure Service Bus, se necesita una suscripción. Si no tiene una suscripción a Azure, puede crear una cuenta gratuita antes de empezar.
  • Visual Studio 2019 o posterior.

Temas y suscripciones de Service Bus

Cada suscripción a un tema puede recibir una copia de cada mensaje. Los temas son completamente compatibles desde el punto de vista semántico y del protocolo con las colas de Service Bus. Los temas de Service Bus admiten una amplia variedad de reglas de selección con condiciones de filtro, con acciones opcionales que establecerán o modificarán las propiedades del mensaje. Cada vez que coincide una regla, esta genera un mensaje. Para más información acerca de reglas, filtros y acciones, siga este vínculo.

Creación de un espacio de nombres en Azure Portal

Para empezar a usar entidades de mensajería de Service Bus en Azure, primero hay que crear un espacio de nombres con un nombre que sea único en Azure. Un espacio de nombres proporciona un contenedor de ámbito para los recursos de Service Bus (colas, temas, etc.) que están dentro de la aplicación.

Para crear un espacio de nombres:

  1. Inicie sesión en Azure Portal.

  2. Vaya a la páginaTodos los servicios.

  3. En la barra de navegación izquierda, seleccione Integración en la lista de categorías, mantenga el mouse sobre Service Bus, y a continuación, seleccione el botón + en el mosaico de Service Bus.

    Image showing selection of Create a resource, Integration, and then Service Bus in the menu.

  4. En la pestaña Datos básicos de la página Crear espacio de nombres, siga estos pasos:

    1. En Suscripción, elija la suscripción de Azure en la que se va a crear el espacio de nombres.

    2. En Grupo de recursos, elija un grupo de recursos existente en el que residirá el espacio de nombres o cree uno.

    3. Escriba nombre para el espacio de nombres. El nombre del espacio de nombres debe cumplir las siguientes convenciones de nomenclatura:

      • El nombre debe ser único en Azure. El sistema realiza la comprobación automáticamente para ver si el nombre está disponible.
      • La longitud del nombre es de 6 caracteres como mínimo y 50 como máximo.
      • El nombre solo puede contener letras, números, guiones "-".
      • El nombre debe comenzar con una letra y terminar con una letra o un número.
      • El nombre no termina con "-sb" o "-mgmt".
    4. En Ubicación, elija la región donde se debe hospedar el espacio de nombres.

    5. En Plan de tarifa, seleccione el plan de tarifa (Básico, Estándar o Prémium) del espacio de nombres. Para este inicio rápido, seleccione Estándar.

      Importante

      Si desea usar temas y suscripciones, elija Estándar o Premium. El plan de tarifas Básico no admite temas o suscripciones.

      Si ha seleccionado el plan de tarifa Prémium, especifique el número de unidades de mensajería. El plan Premium proporciona aislamiento de recursos en el nivel de CPU y memoria para que cada carga de trabajo se ejecute de forma aislada. Este contenedor de recursos se llama unidad de mensajería. A cada espacio de nombres prémium se le asigna al menos una unidad de mensajería. Puede seleccionar 1, 2, 4, 8 o 16 unidades de mensajería para cada espacio de nombres prémium de Service Bus. Para más información, consulte Mensajería prémium de Service Bus.

    6. En la parte inferior de la página, seleccione Revisar y crear.

      Image showing the Create a namespace page

    7. En la página Revisar y crear, examine la configuración y seleccione Crear.

  5. Una vez que la implementación del recurso sea correcta, seleccione Ir al recurso en la página de implementación.

    Image showing the deployment succeeded page with the Go to resource link.

  6. Verá la página principal del espacio de nombres de Service Bus.

    Image showing the home page of the Service Bus namespace created.

Obtención de la cadena de conexión al espacio de nombres (Azure Portal)

La creación un espacio de nombres genera automáticamente una directiva de firma de acceso compartido (SAS) inicial con claves principal y secundaria, y cadenas de conexión principal y secundaria en el que ambas conceden control total sobre todos los aspectos del espacio de nombres. Para obtener información acerca de cómo crear reglas adicionales con derechos más restringidos para remitentes y destinatarios normales, consulte Autenticación y autorización de Service Bus.

Un cliente puede usar la cadena de conexión para conectarse al espacio de nombres de Service Bus. Para copiar la cadena de conexión principal del espacio de nombres, siga estos pasos:

  1. En la página Espacio de nombres de Service Bus, seleccione Directivas de acceso compartido en el menú de la izquierda.

  2. En la página Directivas de acceso compartido, seleccione RootManageSharedAccessKey.

  3. En la ventana Directiva: RootManageSharedAccessKey, seleccione el botón Copiar que hay junto a Cadena de conexión principal para copiar la cadena de conexión en el Portapapeles para su uso posterior. Pegue este valor en el Bloc de notas o cualquier otra ubicación temporal.

    Screenshot shows an S A S policy called RootManageSharedAccessKey, which includes keys and connection strings.

    Puede usar esta página para copiar la clave principal, la clave secundaria, la cadena de conexión principal y la cadena de conexión secundaria.

Creación de un tema mediante Azure Portal

  1. En la página Espacio de nombres de Service Bus, seleccione Temas en el menú izquierdo.

  2. En la barra de herramientas, seleccione + Tema.

  3. Escriba un nombre para el tema. Deje las restantes opciones con sus valores predeterminados.

  4. Seleccione Crear.

    Screenshot of the Create topic page.

Crear suscripciones en el tema

  1. Seleccione el tema que creó en la sección anterior.

    Screenshot of the Topics page with your topic selected.

  2. En la página Tema de Service Bus, seleccione Suscripciones en el menú izquierdo y, a continuación, + Suscripción en la barra de herramientas.

    Screenshot of the Subscriptions page with the Add subscription button selected.

  3. En la página Crear suscripción, siga estos pasos:

    1. Escriba S1 como nombre de la suscripción.

    2. Luego, seleccione Create (Crear) para guardar la suscripción.

      Screenshot of the Create subscription page.

  4. Repita dos veces el paso anterior para crear suscripciones denominadas S2 y S3.

Creación de reglas de filtro en suscripciones

Después de aprovisionar el espacio de nombres y los temas y suscripciones, y de tener la cadena de conexión al espacio de nombres, ya está todo listo para crear reglas de filtro en las suscripciones y, después, enviar y recibir mensajes. Puede examinar el código en esta carpeta de ejemplos de GitHub.

Envío y recepción de mensajes

Para ejecutar el código, siga estos pasos:

  1. En un símbolo del sistema o el símbolo del sistema de PowerShell, clone el repositorio de GitHub de Service Bus emitiendo el comando siguiente:

    git clone https://github.com/Azure/azure-service-bus.git
    
  2. Vaya a la carpeta de ejemplos azure-service-bus\samples\DotNet\Azure.Messaging.ServiceBus\BasicSendReceiveTutorialWithFilters.

  3. Obtenga la cadena de conexión que ha copiado antes en el Bloc de notas en este tutorial. También necesita el nombre del tema que creó en la sección anterior.

  4. En el símbolo del sistema, escriba el siguiente comando:

    dotnet build
    
  5. Vaya a la carpeta BasicSendReceiveTutorialWithFilters\bin\Debug\netcoreapp3.1.

  6. Escriba el siguiente comando para ejecutar el programa. No olvide reemplazar myConnectionString por el valor que obtuvo previamente, y myTopicName por el nombre del tema que creó:

    dotnet --roll-forward Major BasicSendReceiveTutorialWithFilters.dll -ConnectionString "myConnectionString" -TopicName "myTopicName"
    
  7. Siga las instrucciones de la consola para seleccionar la creación de filtros en primer lugar. Es parte de la creación de filtros quitar los filtros predeterminados. Cuando se usa PowerShell o la CLI no es necesario quitar los filtros predeterminados, pero si lo hace en el código, deberá quitarlos. Los comandos de consola 1 y 3 le ayudarán a administrar los filtros en las suscripciones que creó anteriormente:

    • Ejecute 1: para quitar los filtros predeterminados.

    • Ejecute 2: para agregar sus propios filtros.

    • Ejecute 3: omita este paso para el tutorial. Esta opción quita opcionalmente sus filtros. No volverá a crear los filtros predeterminados.

      Showing output of 2

  8. Después de la creación de los filtros, puede enviar mensajes. Pulse 4 y observe los 10 mensajes que se envían al tema:

    Send output

  9. Pulse 5 y observe los mensajes que se reciben. Si no obtuvo 10 mensajes de vuelta, pulse "m" para mostrar el menú y, luego, pulse 5 de nuevo.

    Receive output

Limpieza de recursos

Siga estos pasos para limpiar los recursos que ya no necesite.

  1. Vaya a su espacio de nombres en Azure Portal.
  2. En la página Espacio de nombres de Service Bus, seleccione Eliminar en la barra de comandos para eliminar el espacio de nombres y los recursos que incluye (colas, temas y suscripciones).

Descripción del código de ejemplo

Esta sección contiene información más detallada acerca de lo que hace el código de ejemplo.

Obtención de la cadena de conexión y el tema

En primer lugar, el código declara un conjunto de variables que dirige la ejecución del resto del 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.

Los nombres de la cadena de conexión y del tema se pasan mediante parámetros de la línea de comandos como se indica a continuación y, después, se leen en el 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();
    }
}

Eliminación de los filtros predeterminados

Cuando se crea una suscripción, Service Bus crea un filtro predeterminado por suscripción. Este filtro permite recibir todos los mensajes enviados al tema. Si desea usar filtros personalizados, puede quitar el filtro predeterminado tal como se muestra en el código siguiente:

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();
}

Creación de filtros

El código siguiente agrega los filtros personalizados definidos en este 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();
}

Eliminación de los filtros personalizados creados

Si desea quitar todos los filtros de la suscripción, en el código siguiente se muestra cómo hacerlo:

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();
}

Envío de mensajes

El envío de mensajes a un tema es parecido al envío de mensajes a una cola. En este ejemplo se muestra cómo enviar mensajes mediante una lista de tareas y el procesamiento asincrónico:

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()}"); ;
    }
}

Recepción de mensajes

Los mensajes se reciben de nuevo a través de una lista de tareas y el código usa el procesamiento por lotes. Puede enviar y recibir mediante el procesamiento por lotes, pero en este ejemplo solo se muestra cómo procesar por lotes la recepción. En realidad, no tendría que salir del bucle, sino seguir en él y establecer un intervalo de tiempo mayor, por ejemplo, de un minuto. La llamada de recepción para el agente se mantiene abierta durante este período de tiempo y, si llegan mensajes, se devuelven inmediatamente y se emite una nueva llamada de recepción. Este concepto se denomina sondeo largo. Una opción más habitual consiste en usar el suministro de recepción, que se puede ver en la guía de inicio rápido y en otros ejemplos del repositorio.

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());
        }
    }
}

Nota

Puede administrar los recursos de Service Bus con el Explorador de Service Bus. El Explorador de Service Bus permite a los usuarios conectarse a un espacio de nombres de Service Bus y administrar las entidades de mensajería de una forma sencilla. La herramienta dispone de características avanzadas, como la funcionalidad de importación y exportación o la capacidad de probar el tema, las colas, las suscripciones, los servicios de retransmisión, los centros de notificaciones y los centros de eventos.

Pasos siguientes

En este tutorial, aprovisionó recursos mediante Azure Portal, después, envió y recibió mensajes desde un tema de Service Bus y sus suscripciones. Ha aprendido a:

  • Crear un tema de Service Bus y una o varias suscripciones a ese tema mediante Azure Portal
  • Agregar filtros de tema mediante código .NET
  • Crear dos mensajes con contenido diferente
  • Enviar los mensajes y comprobar que llegaron a las suscripciones esperadas
  • Recibir mensajes de las suscripciones

Para más ejemplos de envío y recepción de mensajes, empiece a trabajar con los ejemplos de Service Bus en GitHub.

Avance hasta el siguiente tutorial para aprender más acerca del uso de las funcionalidades de publicación y suscripción de Service Bus.