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.
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:
Inicie sesión en Azure Portal.
Vaya a la página Todos los servicios.
En la barra de navegación izquierda, seleccione Integration 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.
En la pestaña Datos básicos de la página Crear espacio de nombres, siga estos pasos:
En Suscripción, elija la suscripción de Azure en la que se va a crear el espacio de nombres.
En Grupo de recursos, elija un grupo de recursos existente en el que residirá el espacio de nombres o cree uno.
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".
En Ubicación, elija la región donde se debe hospedar el espacio de nombres.
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.
En la parte inferior de la página, seleccione Revisar y crear.
En la página Revisar y crear, examine la configuración y seleccione Crear.
Una vez que la implementación del recurso sea correcta, seleccione Ir al recurso en la página de implementación.
Verá la página principal del espacio de nombres de Service Bus.
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:
En la página Espacio de nombres de Service Bus, seleccione Directivas de acceso compartido en el menú de la izquierda.
En la página Directivas de acceso compartido, seleccione RootManageSharedAccessKey.
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.
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
En la página Espacio de nombres de Service Bus, seleccione Temas en el menú izquierdo.
En la barra de herramientas, seleccione + Tema.
Escriba un nombre para el tema. Deje las restantes opciones con sus valores predeterminados.
Seleccione Crear.
Crear suscripciones en el tema
Seleccione el tema que creó en la sección anterior.
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.
En la página Crear suscripción, siga estos pasos:
Escriba S1 como nombre de la suscripción.
Luego, seleccione Create (Crear) para guardar la suscripción.
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:
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
Vaya a la carpeta de ejemplos
azure-service-bus\samples\DotNet\Azure.Messaging.ServiceBus\BasicSendReceiveTutorialWithFilters
.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.
En el símbolo del sistema, escriba el siguiente comando:
dotnet build
Vaya a la carpeta
BasicSendReceiveTutorialWithFilters\bin\Debug\netcoreapp3.1
.Escriba el siguiente comando para ejecutar el programa. No olvide reemplazar
myConnectionString
por el valor que obtuvo previamente, ymyTopicName
por el nombre del tema que creó:dotnet --roll-forward Major BasicSendReceiveTutorialWithFilters.dll -ConnectionString "myConnectionString" -TopicName "myTopicName"
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.
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:
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.
Limpieza de recursos
Siga estos pasos para limpiar los recursos que ya no necesite.
- Vaya a su espacio de nombres en Azure Portal.
- 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.