¿Le resultó útil esta página?
Sus comentarios sobre este contenido son muy importantes. Háganos saber su opinión.
¿Tiene comentarios adicionales?
Caracteres restantes: 1500
Exportar (0) Imprimir
Expandir todo

Colas, temas y suscripciones del Bus de servicio

Actualizado: mayo de 2015

El Microsoft Azure Service Bus admite un conjunto de tecnologías basadas en la nube relativas a software intermedio orientado a mensajes, incluida la puesta en cola de mensajes confiables y la mensajería de publicación/suscripción durable. Estas funciones de mensajería “asíncrona” se pueden considerar como características de mensajería asincrónica (o desacoplada) que admiten escenarios de publicación/suscripción, de desacoplamiento temporal y de equilibrio de carga en los que se usa el tejido de mensajería del CmdLets. La comunicación desacoplada reporta numerosas ventajas; así, los clientes y servidores se pueden conectar según sea necesario y llevar a cabo operaciones de modo asincrónico.

Las entidades de mensajería que conforman el núcleo de las funciones de mensajería asíncrona en el CmdLets son las colas, los temas/suscripciones, las reglas/acciones y los concentradores de eventos.

Las colas ofrecen entrega de mensajes FIFO (primero en entrar, primero en salir) a uno o varios consumidores que compiten. Es decir, normalmente se espera a que los receptores reciban y procesen los mensajes en el orden temporal en el que se pusieron en cola, y cada mensaje se recibe y procesa solo por un consumidor de mensaje. Una ventaja clave del uso de colas es lograr el “desacoplamiento temporal” de los componentes de la aplicación; esto es, los productores (remitentes) y los consumidores (receptores) no tienen que estar enviando y recibiendo mensajes al mismo tiempo, puesto que los mensajes se almacenan de manera duradera en la cola. Es más, el productor no tiene que esperar una respuesta por parte del consumidor para poder seguir procesando y enviando mensajes.

Una ventaja relacionada es la “nivelación de carga”, que permite a los productores y consumidores enviar y recibir mensajes en tarifas diferentes. En muchas aplicaciones, la carga del sistema cambia con el tiempo; sin embargo, el tiempo de procesamiento necesario para cada unidad de trabajo es constante de forma habitual. Intermediar entre los consumidores y productores de mensajes con una cola significa que solo se tiene que aprovisionar la aplicación que consume para controlar la carga media en lugar de una carga máxima. La profundidad de la cola aumenta y disminuye según varíe la carga entrante. Esto directamente ahorra dinero en cuanto a la cantidad de infraestructura necesaria para servir la carga de aplicación. Conforme la carga aumenta, se pueden agregar más procesos de trabajo para leer desde la cola. Cada mensaje es procesado solo por uno de los procesos de trabajo. Además, este equilibrio de carga basado en la extracción permite un uso óptimo de los equipos de trabajo, aun cuando estos difieran en cuanto a la capacidad de procesamiento, ya que extraerán mensajes a su propia velocidad máxima. Este patrón a menudo se denomina “consumidor en competencia”.

Al hacer uso de colas para intermediar entre productores y consumidores de mensajes se proporciona un acoplamiento débil inherente entre los componentes. Como los productores y los consumidores no están al tanto unos de otros, un consumidor se puede actualizar sin que tenga ningún efecto en el productor.

Crear una cola requiere varios pasos. Las operaciones de administración de las entidades de mensajería del CmdLets (tanto colas como temas) se efectúan a través de la clase Microsoft.ServiceBus.NamespaceManager, que se construye suministrando la dirección base del espacio de nombres del CmdLets y las credenciales de usuario. NamespaceManager aporta los métodos para crear, enumerar y eliminar entidades de mensajería. Tras crear un objeto Microsoft.ServiceBus.TokenProvider a partir del nombre del emisor y la clave compartida y un objeto de administración de espacio de nombres de servicio, se puede usar el método Microsoft.ServiceBus.NamespaceManager.CreateQueue(Microsoft.ServiceBus.Messaging.QueueDescription) para crear la cola. Por ejemplo:

// Create management credentials
TokenProvider credentials = TokenProvider.CreateSharedSecretTokenProvider(IssuerName, IssuerKey);
// Create namespace client
namespaceManager namespaceClient = new namespaceManager(ServiceBusEnvironment.CreateServiceUri("sb", ServiceNamespace, string.Empty), credentials);

A continuación, se puede crear un objeto de cola y una fábrica de mensajería con el URI CmdLets como argumento. Por ejemplo:

QueueDescription myQueue;
myQueue = namespaceClient.CreateQueue("TestQueue");
MessagingFactory factory = MessagingFactory.Create(ServiceBusEnvironment.CreateServiceUri("sb", ServiceNamespace, string.Empty), credentials); 
QueueClient myQueueClient = factory.CreateQueueClient("TestQueue");

Tras esto, se pueden enviar mensajes a la cola. Así, si hay una lista de mensajes asíncronos llamada MessageList, el código sería parecido a este:

for (int count = 0; count < 6; count++)
{
    var issue = MessageList[count];
    issue.Label = issue.Properties["IssueTitle"].ToString();
    myQueueClient.Send(issue);
}

Se pueden recibir mensajes procedentes de la cola del siguiente modo:

while ((message = myQueueClient.Receive(new TimeSpan(hours: 0, minutes: 0, seconds: 5))) != null)
    {
        Console.WriteLine(string.Format("Message received: {0}, {1}, {2}", message.SequenceNumber, message.Label, message.MessageId));
        message.Complete();

        Console.WriteLine("Processing message (sleeping...)");
        Thread.Sleep(1000);
    }

En el modo ReceiveAndDelete, la operación de recepción es de una sola fase; es decir, cuando el CmdLets recibe la solicitud, marca el mensaje como consumido y lo devuelve a la aplicación. El modo ReceiveAndDelete es el modelo más sencillo y funciona mejor para escenarios en los que la aplicación puede tolerar no procesar un mensaje en caso de error. Para comprender esto, piense en un escenario en el que el consumidor emite la solicitud de recepción y luego se bloquea antes de procesarla. Ya que el CmdLets marcó el mensaje como consumido, cuando la aplicación se reinicie y empiece a consumir mensajes de nuevo, habrá perdido el mensaje que se consumió antes del bloqueo.

En el modo PeekLock, la operación de recepción se convierte en una operación de dos fases que hace posible admitir aplicaciones que no pueden tolerar mensajes perdidos. Cuando el CmdLets recibe la solicitud, encuentra el siguiente mensaje que se va a consumir, lo bloquea para evitar que lo reciban otros consumidores y lo devuelve a la aplicación. Una vez que la aplicación termina de procesar el mensaje (o lo almacena de manera fiable para el procesamiento futuro), completa la segunda fase del proceso de recepción llamando a Microsoft.ServiceBus.Messaging.BrokeredMessage.Complete en el mensaje recibido. Cuando el CmdLets ve Complete, marca el mensaje como consumido.

Si la aplicación no puede procesar el mensaje por alguna razón, puede llamar al método Microsoft.ServiceBus.Messaging.BrokeredMessage.Abandon en el mensaje recibido (en lugar de Complete). Esto permite que el CmdLets desbloquee el mensaje y hace que esté disponible para recibirse de nuevo, ya sea por el mismo consumidor o por otro consumidor que esté completando. Segundo, hay un tiempo de espera asociado al bloqueo y, si la aplicación no puede procesar el mensaje antes de que se agote ese tiempo de espera de bloqueo (por ejemplo, si la aplicación se bloquea), el CmdLets desbloqueará el mensaje y hará que esté disponible para recibirse de nuevo.

Recordemos que si la aplicación se bloquea tras procesar el mensaje, pero antes de que la solicitud de Complete se emita, el mensaje se volverá a enviar a la aplicación cuando se reinicie. Esto se suele conocer como procesamiento Una vez como mínimo o, dicho de otro modo, cada mensaje se procesa al menos una vez. No obstante, en determinadas ocasiones es posible que el mismo mensaje se vuelva a enviar. Si el escenario no puede tolerar el procesamiento duplicado, hará falta más lógica en la aplicación para detectar duplicados, algo que se puede lograr recurriendo a la propiedad MessageId del mensaje, que permanece constante en todos los intentos de envío. Esto se conoce como procesamiento Una sola vez.

Para más información al respecto y ver un ejemplo en funcionamiento sobre cómo crear y enviar mensajes a y desde colas, consulte el Tutorial de .NET de mensajería asíncrona del Bus de servicio.

Al contrario de lo que sucede con las colas (en las que un solo consumidor recibe los mensajes), los temas y suscripciones proporcionan una forma de comunicación uno a varios, en un patrón “publicar/suscribir”. De utilidad para escalar a un número muy elevado de receptores, cada mensaje publicado se pone a disposición de cada suscripción registrada en el tema. Los mensajes se envían a un tema y se entregan a una o varias suscripciones asociadas, en función de las reglas de filtro que pueden establecerse por suscripción. Las suscripciones pueden usar filtros extra para restringir los mensajes que desean recibir. Los mensajes se envían a un tema del mismo modo que se envían a una cola, pero no se reciben del tema directamente, sino de las suscripciones. Una suscripción a un tema se parece a una cola virtual que recibe copias de los mensajes enviados a ese tema. Los mensajes se reciben de una suscripción exactamente del mismo modo que se reciben de una cola.

Mediante comparación, la funcionalidad de envío de mensajes de una cola asigna directamente a un tema, y la funcionalidad de recepción de mensajes asigna a una suscripción. Esto quiere decir, entre otras cosas, que las suscripciones admiten los mismos patrones mencionados anteriormente en esta sección sobre las colas: consumidor en competencia, desacoplamiento temporal, nivelado de carga y equilibrio de carga.

Crear un tema es similar a crear una cola, que hemos explicado en el ejemplo de la sección anterior. Hay que crear el URI de servicio y, luego, usar la clase NamespaceManager para crear el cliente de espacio de nombres. Tras esto, se puede crear un tema mediante el método Microsoft.ServiceBus.NamespaceManager.CreateTopic(System.String). Por ejemplo:

TopicDescription dataCollectionTopic = namespaceClient.CreateTopic("DataCollectionTopic");

A continuación, agregaremos las suscripciones que queramos:

SubscriptionDescription myAgentSubscription = namespaceClient.CreateSubscription(myTopic.Path, "Inventory");
SubscriptionDescription myAuditSubscription = namespaceClient.CreateSubscription(myTopic.Path, "Dashboard");

Y, tras ello, crearemos un cliente de tema. Por ejemplo:

MessagingFactory factory = MessagingFactory.Create(serviceUri, tokenProvider);
TopicClient myTopicClient = factory.CreateTopicClient(myTopic.Path)

Mediante el remitente de mensajes se pueden enviar y recibir mensajes a y desde el tema, como se describió en la sección anterior. Por ejemplo:

foreach (BrokeredMessage message in messageList)
{
    myTopicClient.Send(message);
    Console.WriteLine(
    string.Format("Message sent: Id = {0}, Body = {1}", message.MessageId, message.GetBody<string>()));
}

Al igual que las colas, los mensajes se reciben de una suscripción por medio de un objeto SubscriptionClient, y no de un objeto QueueClient. Crearemos el cliente de suscripción, pasando como parámetros el nombre del tema, el nombre de la suscripción y (opcionalmente) el modo de recepción. Por ejemplo, con la suscripción Inventory:

// Create the subscription client
MessagingFactory factory = MessagingFactory.Create(serviceUri, tokenProvider); 

SubscriptionClient agentSubscriptionClient = factory.CreateSubscriptionClient("IssueTrackingTopic", "Inventory", ReceiveMode.PeekLock);
SubscriptionClient auditSubscriptionClient = factory.CreateSubscriptionClient("IssueTrackingTopic", "Dashboard", ReceiveMode.ReceiveAndDelete); 

while ((message = agentSubscriptionClient.Receive(TimeSpan.FromSeconds(5))) != null)
{
    Console.WriteLine("\nReceiving message from Inventory...");
    Console.WriteLine(string.Format("Message received: Id = {0}, Body = {1}", message.MessageId, message.GetBody<string>()));
    message.Complete();
}          

// Create a receiver using ReceiveAndDelete mode
while ((message = auditSubscriptionClient.Receive(TimeSpan.FromSeconds(5))) != null)
{
    Console.WriteLine("\nReceiving message from Dashboard...");
    Console.WriteLine(string.Format("Message received: Id = {0}, Body = {1}", message.MessageId, message.GetBody<string>()));
}

ImportantImportante
Tal y como se explica en el tema Procedimiento: Publicar un servicio en el Registro del Bus de servicio, Microsoft.ServiceBus.ServiceRegistrySettings puede servir para indicar si se quiere que el CmdLets detecte el servicio. Si el servicio es privado, solo se podrán conectar quienes conozcan el URI específico. Si es público, cualquiera podrá navegar por la jerarquía del CmdLets y encontrar el agente de escucha. Con todo, las colas, temas y suscripciones no se pueden exponer a través del Registro del servicio.

En muchos escenarios, los mensajes que presentan características específicas se deben procesar de modos muy concretos. Para que esto sea factible, se pueden configurar suscripciones que encuentren mensajes que tengan las propiedades adecuadas y, luego, realizar determinadas operaciones sobre esas propiedades. Si bien las suscripciones del CmdLets ven todos los mensajes enviados al tema, solo se puede copiar un subconjunto de los mensajes en la cola de suscripción virtual. Esto se consigue con filtros de suscripción. Estas modificaciones se denominan acciones de filtro. Al crear una suscripción, se puede proporcionar una expresión de filtro que opere en las propiedades del mensaje, ya sea en las propiedades de sistema (por ejemplo, Label) o en las propiedades de la aplicación (como StoreName en el ejemplo anterior). La expresión de filtro SQL es opcional en este caso; sin ella, cualquier acción de filtro definida en una suscripción se llevará a cabo en todos los mensajes de dicha suscripción.

Volviendo al ejemplo anterior, para filtrar los mensajes procedentes únicamente de Store1, crearíamos la suscripción Dashboard del siguiente modo:

namespaceManager.CreateSubscription("IssueTrackingTopic", "Dashboard", new SqlFilter("StoreName = 'Store1'"));

Con este filtro de suscripción aplicado, solo los mensajes que tengan la propiedad StoreName establecida en Store1 se copiarán en la cola virtual de la suscripción Dashboard.

Para obtener más información sobre los valores de filtro posibles, consulte la documentación relativa a las clases Microsoft.ServiceBus.Messaging.SqlFilter y Microsoft.ServiceBus.Messaging.SqlRuleAction. Eche un vistazo también al ejemplo de filtros avanzados de mensajería asíncrona.

Los concentradores de eventos consisten en un servicio de introducción de eventos y sirven para proporcionar funciones de entrada de eventos y telemetría en Azure a gran escala, todo ello con baja latencia y elevada confiabilidad. Cuando este servicio se usa con otros servicios descendentes, resulta especialmente útil en escenarios de procesamiento de instrumentaciones de aplicaciones, experiencias de usuario y flujos de trabajo, así como en Internet de las cosas (IoT).

Los concentradores de eventos son una construcción de streaming de mensajes y, aunque pueda parecer que son similares a las colas y los temas, poseen características distintas. Así, no proporcionan TTL de mensajes, problemas de entrega, transacciones o acuses de recibo, dado que se trata de características habituales de la mensajería asíncrona, no de características de streaming. Los concentradores de eventos aportan otras características relacionadas con la transmisión, como las particiones, la conservación el orden o la reproducción de transmisiones.

Vea también

Mostrar:
© 2015 Microsoft