Patrón de cola de prioridadPriority Queue pattern

Clasifica por orden de prioridad las solicitudes enviadas a los servicios para que aquellas con una prioridad más alta se reciban y procesen más rápidamente que las que tienen una prioridad más baja.Prioritize requests sent to services so that requests with a higher priority are received and processed more quickly than those with a lower priority. Este patrón es útil en aplicaciones que ofrecen garantías de nivel de servicio diferentes a los clientes individuales.This pattern is useful in applications that offer different service level guarantees to individual clients.

Contexto y problemaContext and Problem

Las aplicaciones pueden delegar tareas específicas a otros servicios, por ejemplo, para realizar el procesamiento en segundo plano o para integrarse con otras aplicaciones o servicios.Applications can delegate specific tasks to other services, for example, to perform background processing or to integrate with other applications or services. En la nube, una cola de mensajes se utiliza normalmente para delegar tareas al procesamiento en segundo plano.In the cloud, a message queue is typically used to delegate tasks to background processing. En muchos casos, el orden en que se reciben las solicitudes en un servicio no es importante.In many cases the order requests are received in by a service isn't important. Sin embargo, en algunos casos, es necesario dar prioridad a solicitudes específicas.In some cases, though, it's necessary to prioritize specific requests. Estas solicitudes deben procesarse antes que las solicitudes de menor prioridad enviadas anteriormente por la aplicación.These requests should be processed earlier than lower priority requests that were sent previously by the application.

SoluciónSolution

Una cola suele tener una estructura basada en el criterio primero en entrar, primero en salir, y los consumidores normalmente reciben mensajes en el mismo orden en que se publicaron en la cola.A queue is usually a first-in, first-out (FIFO) structure, and consumers typically receive messages in the same order that they were posted to the queue. Sin embargo, algunas colas de mensajes admiten mensajería de prioridad.However, some message queues support priority messaging. La aplicación que envía un mensaje puede asignar una prioridad y los mensajes de la cola se reordenan automáticamente para que los que tienen una prioridad más alta se reciban antes que aquellos con una prioridad más baja.The application posting a message can assign a priority and the messages in the queue are automatically reordered so that those with a higher priority will be received before those with a lower priority. En la figura se ilustra una cola con mensajes prioritarios.The figure illustrates a queue with priority messaging.

Figura 1: Uso de un mecanismo de cola que admite la asignación de prioridad a los mensajes

La mayoría de las implementaciones de cola de mensajes admiten varios consumidores (siguiendo el patrón de consumidores en competencia), y el número de procesos de consumidor se puede escalar o reducir verticalmente en función de la demanda.Most message queue implementations support multiple consumers (following the Competing Consumers pattern), and the number of consumer processes can be scaled up or down depending on demand.

En los sistemas que no admiten colas de mensajes basadas en prioridad, una solución alternativa consiste en mantener una cola independiente para cada prioridad.In systems that don't support priority-based message queues, an alternative solution is to maintain a separate queue for each priority. La aplicación es responsable de enviar mensajes a la cola adecuada.The application is responsible for posting messages to the appropriate queue. Cada cola puede tener un grupo independiente de consumidores.Each queue can have a separate pool of consumers. Las colas de más prioridad pueden tener un grupo más grande de consumidores en ejecución en hardware más rápido que las colas de menor prioridad.Higher priority queues can have a larger pool of consumers running on faster hardware than lower priority queues. En la ilustración siguiente se muestra cómo utilizar las colas de mensajes independientes para cada prioridad.The next figure illustrates using separate message queues for each priority.

Figura 2: Uso de las colas de mensajes independientes para cada prioridad

Una variación de esta estrategia es disponer de un único grupo de consumidores que primero comprueba los mensajes en las colas de alta prioridad, y solo después inicia la captura de los mensajes de colas de prioridad más baja.A variation on this strategy is to have a single pool of consumers that check for messages on high priority queues first, and only then start to fetch messages from lower priority queues. Hay algunas diferencias semánticas entre una solución que utiliza un único grupo de procesos de consumidor (ya sea con una sola cola que admite mensajes con prioridades diferentes o con varias colas donde cada una controla los mensajes de una única prioridad) y una solución que usa varias colas con un grupo independiente para cada cola.There are some semantic differences between a solution that uses a single pool of consumer processes (either with a single queue that supports messages with different priorities or with multiple queues that each handle messages of a single priority), and a solution that uses multiple queues with a separate pool for each queue.

En el enfoque de grupo único, los mensajes con prioridad más alta siempre se reciben y procesan antes que los mensajes de prioridad más baja.In the single pool approach, higher priority messages are always received and processed before lower priority messages. En teoría, los mensajes que tienen una prioridad muy baja pueden reemplazarse continuamente y puede que nunca se procesen.In theory, messages that have a very low priority could be continually superseded and might never be processed. En el enfoque de varios grupos, los mensajes de prioridad más baja siempre se procesarán, pero no tan rápido como los de más prioridad (en función del tamaño relativo de los grupos y los recursos que tienen disponibles).In the multiple pool approach, lower priority messages will always be processed, just not as quickly as those of a higher priority (depending on the relative size of the pools and the resources that they have available).

El uso de un mecanismo de puesta en cola según prioridad puede ofrecer las ventajas siguientes:Using a priority queuing mechanism can provide the following advantages:

  • Permite a las aplicaciones satisfacer los requisitos empresariales que requieren la asignación de prioridades de disponibilidad o rendimiento, por ejemplo, ofrecer distintos niveles de servicio a grupos concretos de clientes.It allows applications to meet business requirements that require prioritization of availability or performance, such as offering different levels of service to specific groups of customers.

  • Puede ayudar a minimizar los costos operativos.It can help to minimize operational costs. En el enfoque de cola única, se puede reducir el número de consumidores si es necesario.In the single queue approach, you can scale back the number of consumers if necessary. Los mensajes con prioridad alta se seguirán procesando en primer lugar (aunque posiblemente más lentos), y los mensajes de menor prioridad podrían tardar más.High priority messages will still be processed first (although possibly more slowly), and lower priority messages might be delayed for longer. Si ha implementado el enfoque de varias colas de mensajes con grupos independientes de consumidores para cada cola, puede reducir el grupo de consumidores para las colas de menor prioridad, o incluso suspender el procesamiento de algunas colas de prioridad muy baja al detener a todos los consumidores que escuchan mensajes en dichas colas.If you've implemented the multiple message queue approach with separate pools of consumers for each queue, you can reduce the pool of consumers for lower priority queues, or even suspend processing for some very low priority queues by stopping all the consumers that listen for messages on those queues.

  • El enfoque de varias colas de mensajes puede ayudar a maximizar el rendimiento y la escalabilidad de la aplicación mediante la partición de mensajes en función de los requisitos de procesamiento.The multiple message queue approach can help maximize application performance and scalability by partitioning messages based on processing requirements. Por ejemplo, se puede dar prioridad a tareas vitales para que las controlen los receptores que se ejecutan inmediatamente, mientras que las tareas en segundo plano menos importantes pueden controlarlas los receptores programados para ejecutarse en períodos menos saturados.For example, vital tasks can be prioritized to be handled by receivers that run immediately while less important background tasks can be handled by receivers that are scheduled to run at less busy periods.

Problemas y consideracionesIssues and Considerations

Tenga en cuenta los puntos siguientes al decidir cómo implementar este patrón:Consider the following points when deciding how to implement this pattern:

Defina las prioridades en el contexto de la solución.Define the priorities in the context of the solution. Por ejemplo, una prioridad alta puede significar que se deben procesar los mensajes en diez segundos.For example, high priority could mean that messages should be processed within ten seconds. Identifique los requisitos para administrar elementos de prioridad alta y los otros recursos que se deben asignar a fin de cumplir estos criterios.Identify the requirements for handling high priority items, and the other resources that should be allocated to meet these criteria.

Decida si se deben procesar todos los elementos de prioridad alta antes que los elementos de menor prioridad.Decide if all high priority items must be processed before any lower priority items. Si los mensajes los procesa un único grupo de consumidores, tendrá que proporcionar un mecanismo que pueda dar prioridad y suspender una tarea que administra un mensaje de prioridad baja si hay disponible un mensaje de mayor prioridad.If the messages are being processed by a single pool of consumers, you have to provide a mechanism that can preempt and suspend a task that's handling a low priority message if a higher priority message becomes available.

En el enfoque de varias colas, al usar un único grupo de procesos de consumidores que escuchan en todas las colas en lugar de un grupo de consumidores dedicado para cada cola, el consumidor debe aplicar un algoritmo que asegure que siempre pueda administrar los mensajes de colas de prioridad más alta antes que los de las colas de prioridad más baja.In the multiple queue approach, when using a single pool of consumer processes that listen on all queues rather than a dedicated consumer pool for each queue, the consumer must apply an algorithm that ensures it always services messages from higher priority queues before those from lower priority queues.

Supervise la velocidad de procesamiento en colas de alta y baja prioridad para garantizar que los mensajes de estas colas se procesan a la velocidad esperada.Monitor the processing speed on high and low priority queues to ensure that messages in these queues are processed at the expected rates.

Si necesita garantizar que se procesarán los mensajes con prioridad baja, es necesario implementar el enfoque de varias colas de mensajes con varios grupos de consumidores.If you need to guarantee that low priority messages will be processed, it's necessary to implement the multiple message queue approach with multiple pools of consumers. Como alternativa, en una cola que admite la concesión de prioridad a los mensajes, es posible aumentar de forma dinámica la prioridad de un mensaje en cola, conforme avanza el tiempo.Alternatively, in a queue that supports message prioritization, it's possible to dynamically increase the priority of a queued message as it ages. Sin embargo, este enfoque depende de la cola de mensajes que ofrece esta característica.However, this approach depends on the message queue providing this feature.

Usar una cola independiente para cada prioridad de mensajes funciona mejor para los sistemas que tener un número pequeño de prioridades bien definidas.Using a separate queue for each message priority works best for systems that have a small number of well-defined priorities.

El sistema puede determinar de manera lógica las prioridades de los mensajes.Message priorities can be determined logically by the system. Por ejemplo, en lugar de tener mensajes explícitos con prioridad alta y baja, se podrían designar como "cliente que paga las cuotas" o "cliente que no paga las cuotas".For example, rather than having explicit high and low priority messages, they could be designated as “fee paying customer,” or “non-fee paying customer.” Dependiendo del modelo de negocio, el sistema puede asignar más recursos para procesar los mensajes de los clientes que pagan las cuotas que para los clientes que no las pagan.Depending on your business model, your system can allocate more resources to processing messages from fee paying customers than non-fee paying ones.

Puede haber un costo financiero y de procesamiento asociado con la comprobación de un mensaje en una cola (algunos sistemas de mensajería comerciales cargan una tarifa reducida cada vez que se envía o recupera un mensaje y cada vez que se consultan mensajes en una cola).There might be a financial and processing cost associated with checking a queue for a message (some commercial messaging systems charge a small fee each time a message is posted or retrieved, and each time a queue is queried for messages). Este costo aumenta si se comprueban varias colas.This cost increases when checking multiple queues.

Es posible ajustar dinámicamente el tamaño de un grupo de consumidores en función de la longitud de la cola que atiende al grupo.It's possible to dynamically adjust the size of a pool of consumers based on the length of the queue that the pool is servicing. Para más información, vea la Guía de escalado automático.For more information, see the Autoscaling Guidance.

Cuándo usar este patrónWhen to use this pattern

Este patrón es útil en escenarios donde:This pattern is useful in scenarios where:

  • El sistema debe controlar varias tareas que tengan diferentes prioridades.The system must handle multiple tasks that have different priorities.

  • Los distintos usuarios o inquilinos deben atender las solicitudes con otra prioridad.Different users or tenants should be served with different priority.

EjemploExample

Microsoft Azure no proporciona un mecanismo de puesta en cola que admita de forma nativa la asignación de prioridad a los mensajes a través de la ordenación.Microsoft Azure doesn't provide a queuing mechanism that natively supports automatic prioritization of messages through sorting. Sin embargo, proporciona temas y suscripciones de Azure Service Bus que admiten un mecanismo de puesta en cola que ofrece filtrado de mensajes, además de un amplio conjunto de funcionalidades flexibles que lo hacen ideal para usarlo en las implementaciones de colas con la máxima prioridad.However, it does provide Azure Service Bus topics and subscriptions that support a queuing mechanism that provides message filtering, together with a wide range of flexible capabilities that make it ideal for use in most priority queue implementations.

Una solución de Azure puede implementar un tema de Service Bus en el que una aplicación puede publicar mensajes, de la misma manera que una cola.An Azure solution can implement a Service Bus topic an application can post messages to, in the same way as a queue. Los mensajes pueden contener metadatos en forma de propiedades personalizadas definidas por la aplicación.Messages can contain metadata in the form of application-defined custom properties. Las suscripciones de Service Bus se pueden asociar con el tema, y estas suscripciones pueden filtrar los mensajes en función de sus propiedades.Service Bus subscriptions can be associated with the topic, and these subscriptions can filter messages based on their properties. Cuando una aplicación envía un mensaje a un tema, el mensaje se dirige a la suscripción correspondiente donde lo puede leer un consumidor.When an application sends a message to a topic, the message is directed to the appropriate subscription where it can be read by a consumer. Los procesos del consumidor pueden recuperar mensajes de una suscripción utilizando la misma semántica que una cola de mensajes (una suscripción es una cola lógica).Consumer processes can retrieve messages from a subscription using the same semantics as a message queue (a subscription is a logical queue). En la ilustración siguiente se muestra cómo implementar una cola de prioridad con temas y suscripciones de Azure Service Bus.The following figure illustrates implementing a priority queue with Azure Service Bus topics and subscriptions.

Figura 3: Implementación de una cola de prioridad con temas y suscripciones de Azure Service Bus

En la figura anterior, la aplicación crea varios mensajes y asigna una propiedad personalizada denominada Priority en cada mensaje con un valor, High o Low.In the figure above, the application creates several messages and assigns a custom property called Priority in each message with a value, either High or Low. La aplicación envía estos mensajes a un tema.The application posts these messages to a topic. El tema tiene dos suscripciones asociadas que filtran los mensajes examinando la propiedad Priority.The topic has two associated subscriptions that both filter messages by examining the Priority property. Una suscripción acepta mensajes donde la propiedad Priority está establecida en High, y la otra acepta mensajes donde la propiedad Priority está establecida en Low.One subscription accepts messages where the Priority property is set to High, and the other accepts messages where the Priority property is set to Low. Un grupo de consumidores lee los mensajes de cada suscripción.A pool of consumers reads messages from each subscription. La suscripción de alta prioridad tiene un grupo más grande, y estos consumidores podrían estar ejecutándose en equipos más eficaces con más recursos disponibles que los consumidores del grupo de prioridad baja.The high priority subscription has a larger pool, and these consumers might be running on more powerful computers with more resources available than the consumers in the low priority pool.

Tenga en cuenta que no hay nada especial acerca de la designación de mensajes con prioridad alta y baja en este ejemplo.Note that there's nothing special about the designation of high and low priority messages in this example. Son simplemente etiquetas especificadas como propiedades en cada mensaje, que se utilizan para dirigir mensajes a una suscripción específica.They're simply labels specified as properties in each message, and are used to direct messages to a specific subscription. Si se requieren prioridades adicionales, es relativamente fácil crear más suscripciones y grupos de procesos de consumidor para controlar estas prioridades.If additional priorities are required, it's relatively easy to create further subscriptions and pools of consumer processes to handle these priorities.

La solución PriorityQueue disponible en GitHub contiene una implementación de este enfoque.The PriorityQueue solution available on GitHub contains an implementation of this approach. Esta solución contiene dos proyectos de rol de trabajo denominados PriorityQueue.High y PriorityQueue.Low.This solution contains two worker role projects named PriorityQueue.High and PriorityQueue.Low. Estos roles de trabajo se heredan de la clase PriorityWorkerRole que contiene la funcionalidad para conectarse a una suscripción especificada en el método OnStart.These worker roles inherit from the PriorityWorkerRole class that contains the functionality for connecting to a specified subscription in the OnStart method.

Los roles de trabajo PriorityQueue.High y PriorityQueue.Low se conectan a distintas suscripciones, definidas por sus valores de configuración.The PriorityQueue.High and PriorityQueue.Low worker roles connect to different subscriptions, defined by their configuration settings. Un administrador puede configurar un número diferente de cada rol para ejecutarlo.An administrator can configure different numbers of each role to be run. Normalmente, habrá más instancias del rol de trabajo PriorityQueue.High que del rol de trabajo PriorityQueue.Low.Typically there'll be more instances of the PriorityQueue.High worker role than the PriorityQueue.Low worker role.

El método Run de la clase PriorityWorkerRole se encarga de que el método virtual ProcessMessage (también definido en la clase PriorityWorkerRole) se ejecute para cada mensaje recibido en la cola.The Run method in the PriorityWorkerRole class arranges for the virtual ProcessMessage method (also defined in the PriorityWorkerRole class) to be run for each message received on the queue. El siguiente código muestra los métodos Run y ProcessMessage.The following code shows the Run and ProcessMessage methods. La clase QueueManager, definida en el proyecto PriorityQueue.Shared, proporciona métodos auxiliares para usar colas de Azure Service Bus.The QueueManager class, defined in the PriorityQueue.Shared project, provides helper methods for using Azure Service Bus queues.

public class PriorityWorkerRole : RoleEntryPoint
{
  private QueueManager queueManager;
  ...

  public override void Run()
  {
    // Start listening for messages on the subscription.
    var subscriptionName = CloudConfigurationManager.GetSetting("SubscriptionName");
    this.queueManager.ReceiveMessages(subscriptionName, this.ProcessMessage);
    ...;
  }
  ...

  protected virtual async Task ProcessMessage(BrokeredMessage message)
  {
    // Simulating processing.
    await Task.Delay(TimeSpan.FromSeconds(2));
  }
}

Los roles de trabajo PriorityQueue.High y PriorityQueue.Low invalidan la funcionalidad predeterminada del método ProcessMessage.The PriorityQueue.High and PriorityQueue.Low worker roles both override the default functionality of the ProcessMessage method. El código siguiente muestra el método ProcessMessage para el rol de trabajo PriorityQueue.High.The code below shows the ProcessMessage method for the PriorityQueue.High worker role.

protected override async Task ProcessMessage(BrokeredMessage message)
{
  // Simulate message processing for High priority messages.
  await base.ProcessMessage(message);
  Trace.TraceInformation("High priority message processed by " +
    RoleEnvironment.CurrentRoleInstance.Id + " MessageId: " + message.MessageId);
}

Cuando una aplicación envía mensajes al tema asociado con las suscripciones utilizadas por los roles de trabajo PriorityQueue.High y PriorityQueue.Low, especifica la prioridad con el uso de la propiedad personalizada Priority, como se muestra en el siguiente ejemplo de código.When an application posts messages to the topic associated with the subscriptions used by the PriorityQueue.High and PriorityQueue.Low worker roles, it specifies the priority by using the Priority custom property, as shown in the following code example. Este código (implementado en la clase WorkerRole en el proyecto PriorityQueue.Sender), utiliza el método auxiliar SendBatchAsync de la clase QueueManager para enviar mensajes a un tema en lotes.This code (implemented in the WorkerRole class in the PriorityQueue.Sender project), uses the SendBatchAsync helper method of the QueueManager class to post messages to a topic in batches.

// Send a low priority batch.
var lowMessages = new List<BrokeredMessage>();

for (int i = 0; i < 10; i++)
{
  var message = new BrokeredMessage() { MessageId = Guid.NewGuid().ToString() };
  message.Properties["Priority"] = Priority.Low;
  lowMessages.Add(message);
}

this.queueManager.SendBatchAsync(lowMessages).Wait();
...

// Send a high priority batch.
var highMessages = new List<BrokeredMessage>();

for (int i = 0; i < 10; i++)
{
  var message = new BrokeredMessage() { MessageId = Guid.NewGuid().ToString() };
  message.Properties["Priority"] = Priority.High;
  highMessages.Add(message);
}

this.queueManager.SendBatchAsync(highMessages).Wait();

Los patrones y las directrices siguientes también pueden ser importantes a la hora de implementar este modelo:The following patterns and guidance might also be relevant when implementing this pattern:

  • Se encuentra disponible un ejemplo que demuestra este patrón en GitHub.A sample that demonstrates this pattern is available on GitHub.

  • Manual de mensajería asincrónica.Asynchronous Messaging Primer. Un servicio de consumidor que procesa una solicitud puede necesitar enviar una respuesta a la instancia de la aplicación que publicó la solicitud.A consumer service that processes a request might need to send a reply to the instance of the application that posted the request. Proporciona información sobre las estrategias que puede usar para implementar la mensajería de solicitud/respuesta.Provides information on the strategies that you can use to implement request/response messaging.

  • Patrón de consumidores de la competencia.Competing Consumers pattern. Para mejorar el rendimiento de las colas, es posible tener varios consumidores que escuchen en la misma cola y procesen las tareas en paralelo.To increase the throughput of the queues, it’s possible to have multiple consumers that listen on the same queue, and process the tasks in parallel. Estos consumidores competirán por los mensajes, pero solo uno debe ser capaz de procesar cada mensaje.These consumers will compete for messages, but only one should be able to process each message. Proporciona más información sobre las ventajas y los inconvenientes de la implementación de este enfoque.Provides more information on the benefits and tradeoffs of implementing this approach.

  • Patrón de limitación.Throttling pattern. Puede implementar la limitación mediante el uso de colas.You can implement throttling by using queues. La mensajería de prioridad puede usarse para asegurarse de que se concede prioridad a las solicitudes que proceden de aplicaciones críticas o de aplicaciones ejecutadas por clientes de alto valor con respecto a las solicitudes de aplicaciones menos importantes.Priority messaging can be used to ensure that requests from critical applications, or applications being run by high-value customers, are given priority over requests from less important applications.

  • Guía de escalado automático.Autoscaling Guidance. Es posible escalar el tamaño del grupo de procesos de consumidor que controlan una cola en función de la longitud de la cola.It might be possible to scale the size of the pool of consumer processes handling a queue depending on the length of the queue. Esta estrategia puede ayudar a mejorar el rendimiento, especialmente para los grupos que controlan los mensajes con prioridad alta.This strategy can help to improve performance, especially for pools handling high priority messages.

  • Patrones de Integración empresarial con Service Bus en el blog de Abhishek Lal.Enterprise Integration Patterns with Service Bus on Abhishek Lal’s blog.