Compartir vía


Procedimientos recomendados para mejorar el rendimiento mediante la mensajería de Service Bus

En este artículo se describe cómo usar Azure Service Bus para optimizar el rendimiento al intercambiar mensajes asincrónicos. En la primera parte de este artículo se describen distintos mecanismos para aumentar el rendimiento. En la segunda parte se proporcionan instrucciones sobre cómo usar Service Bus de manera que pueda ofrecer el mejor rendimiento en un escenario determinado.

En todo este artículo, el término "cliente" hace referencia a cualquier entidad que acceda a Service Bus. Un cliente puede asumir el rol de un remitente o receptor. El término "remitente" se usa para referirse a un cliente de una cola o un tema de Service Bus que envía mensajes a una cola o un tema de Service Bus. El término "receptor" hace referencia a un cliente de una cola o una suscripción de Service Bus que recibe mensajes de una cola o una suscripción de Service Bus.

Planeamiento de recursos y consideraciones

Al igual que con cualquier recurso técnico, el planeamiento prudente es clave para garantizar que Azure Service Bus proporciona el rendimiento esperado por la aplicación. La configuración o topología correctas para los espacios de nombres de Service Bus depende de una serie de factores que implican la arquitectura de la aplicación y cómo se utiliza cada una de las características de Service Bus.

Plan de tarifa

Service Bus ofrece varios planes de tarifa. Se recomienda elegir el nivel adecuado para los requisitos de la aplicación.

  • Nivel Estándar: adecuado para entornos de desarrollo y pruebas o escenarios de bajo rendimiento en los que las aplicaciones no son sensibles a la limitación.

  • Nivel Premium: adecuado para entornos de producción con diversos requisitos de rendimiento en los que se requiere una latencia y un rendimiento predecibles. Además, los espacios de nombres prémium de Service Bus se pueden escalar automáticamente y se pueden habilitar para dar cabida a picos de rendimiento.

Nota

Si no se selecciona el nivel correcto, existe el riesgo de desbordar el espacio de nombres de Service Bus, lo que puede dar lugar a la limitación.

La limitación no conduce a la pérdida de datos. Las aplicaciones que aprovechan el SDK de Service Bus pueden usar la directiva de reintentos predeterminada para asegurarse de que Service Bus finalmente acepta los datos.

Cálculo del rendimiento para el nivel Premium

Los datos enviados Service Bus se serializan a binario y luego se deserializan cuando los recibe el receptor. Por lo tanto, mientras que las aplicaciones piensan en los mensajes como unidades atómicas de trabajo, Service Bus mide el rendimiento en términos de bytes (o megabytes).

Al calcular el requisito de rendimiento, tenga en cuenta los datos que se envían a Service Bus (entrada) y los datos que se reciben de Service Bus (salida).

Como se esperaba, el rendimiento es mayor para cargas útiles de mensajes más pequeñas que se pueden procesar por lotes conjuntamente.

Pruebas comparativas

Este es un ejemplo de GitHub que puede ejecutar para ver el rendimiento esperado que recibirá para el espacio de nombres de Service Bus. En nuestras pruebas comparativas observamos aproximadamente 4 MB/segundo por unidad de mensajería (MU) de entrada y salida.

El ejemplo de pruebas comparativas no usa características avanzadas, por lo que el rendimiento que observan las aplicaciones es diferente en función de los escenarios.

Consideraciones de proceso

Service Bus opera varios procesos en segundo plano que pueden afectar al uso del proceso. Entre ellos se incluyen, entre otros, los temporizadores, las programaciones y las emisiones de métricas. Además, el uso de determinadas características de Service Bus requiere un uso de proceso que puede reducir el rendimiento esperado. Algunas de estas características:

  1. Son sesiones.
  2. Se extienden a varias suscripciones sobre un solo tema.
  3. Ejecutan muchos filtros en una sola suscripción.
  4. Son mensajes programados.
  5. Son mensajes aplazados.
  6. Transacciones.
  7. Desduplicación y ventana de tiempo de retrospectiva.
  8. Se desvían (desvío de una entidad a otra).

Si la aplicación usa cualquiera de las características anteriores y no recibe el rendimiento esperado, puede revisar las métricas de Uso de la CPU y considerar la posibilidad de escalar verticalmente el espacio de nombres Premium de Service Bus. También puede usar Azure Monitor para escalar automáticamente el espacio de nombres Service Bus. Se recomienda aumentar el número de unidades de mensaje (RU) cuando el uso de CPU supera el 70 % para garantizar un rendimiento óptimo.

Particionamiento entre espacios de nombres

Aunque el escalado vertical de proceso (unidades de mensajería) asignado al espacio de nombres es una solución más sencilla, es posible que no proporcione un aumento lineal en el rendimiento. Esto se debe a los elementos internos de Service Bus (almacenamiento, red, etc.), que pueden estar limitando el rendimiento.

En este caso, la solución más limpia es particionar las entidades (colas y temas) entre diferentes espacios de nombres Premium de Service Bus. También puede considerar el particionamiento entre distintos espacios de nombres en diferentes regiones de Azure.

Protocolos

Service Bus permite a los clientes enviar y recibir mensajes a través de uno de estos tres protocolos:

  1. Advanced Message Queuing Protocol (AMQP)
  2. Protocolo de mensajería de Service Bus (SBMP)
  3. Protocolo de transferencia de hipertexto (HTTP)

AMQP es el más eficaz, ya que mantiene la conexión a Service Bus. También implementa el procesamiento por lotes y la captura previa. A menos que se mencione explícitamente, en todo el contenido de este artículo se supone que se usa AMQP o SBMP.

Importante

El protocolo SBMP solo está disponible para .NET Framework. AMQP es el valor predeterminado de .NET Standard.

El 30 de septiembre de 2026, retiraremos el soporte técnico del protocolo SBMP para Azure Service Bus, por lo que ya no podrá usar este protocolo después del 30 de septiembre de 2026. Migre a las bibliotecas más recientes del SDK de Azure Service Bus mediante el protocolo AMQP, que ofrecen actualizaciones de seguridad críticas y funcionalidades mejoradas, antes de esa fecha.

Para obtener más información, consulte el anuncio de retirada de soporte técnico.

Elección del SDK de .NET para Service Bus adecuado

El paquete Azure.Messaging.ServiceBus es la versión más reciente del SDK de .NET de Azure Service Bus disponible a partir de noviembre de 2020. Hay dos SDK de .NET antiguos que seguirán recibiendo correcciones de errores críticos hasta el 30 de septiembre de 2026, pero le recomendamos encarecidamente que use el SDK más reciente en su lugar. Lea la guía de migración para obtener más información sobre cómo mover los SDK más antiguos.

Paquete NuGet Espacios de nombres principales Plataformas mínimas Protocolos
Azure.Messaging.ServiceBus (más reciente) Azure.Messaging.ServiceBus
Azure.Messaging.ServiceBus.Administration
.NET Core 2.0
.NET Framework 4.6.1
Mono 5.4
Plataforma universal de Windows 10.0.16299
AMQP
HTTP
Microsoft.Azure.ServiceBus Microsoft.Azure.ServiceBus
Microsoft.Azure.ServiceBus.Management
.NET Core 2.0
.NET Framework 4.6.1
Mono 5.4
Plataforma universal de Windows 10.0.16299
AMQP
HTTP

Para más información sobre la compatibilidad mínima con la plataforma .NET Standard, consulte Compatibilidad con la implementación de .NET.

El 30 de septiembre de 2026, retiraremos las bibliotecas del SDK de Azure Service Bus WindowsAzure.ServiceBus, Microsoft.Azure.ServiceBus y com.microsoft.azure.servicebus, que no se ajustan a las directrices del SDK de Azure. También retiraremos el soporte del protocolo SBMP, por lo que ya no podrás usar este protocolo después del 30 de septiembre de 2026. Migre a las bibliotecas más recientes del SDK de Azure, que ofrecen actualizaciones de seguridad críticas y funcionalidades mejoradas, antes de esa fecha.

Aunque las bibliotecas anteriores todavía se pueden usar después del 30 de septiembre de 2026, ya no recibirán soporte técnico oficial ni actualizaciones de Microsoft. Para obtener más información, consulte el anuncio de retirada de soporte técnico.

Reutilización de factorías y clientes

Los clientes de Service Bus que interactúan con el servicio, como ServiceBusClient, ServiceBusSender, ServiceBusReceiver y ServiceBusProcessor, deben registrarse para la inserción de dependencias como singleton (o bien crear instancias una vez y compartirlas). ServiceBusClient (fábrica) se puede registrar para la inserción de dependencias con ServiceBusClientBuilderExtensions.

Se recomienda no cerrar ni desechar estos clientes después de enviar o recibir cada mensaje. Si se cierran o desechan los objetos específicos de la entidad (ServiceBusSender/Receiver/Processor), se rompe el vínculo al servicio Service Bus. Si se desecha ServiceBusClient, se rompe la conexión al servicio Service Bus.

Esta guía no se aplica a ServiceBusSessionReceiver, ya que su duración es la misma que la propia sesión. Para las aplicaciones que funcionan con ServiceBusSessionReceiver, se recomienda usar una instancia singleton de ServiceBusClient para aceptar cada sesión, lo que genera un nuevo ServiceBusSessionReceiver enlazado a esa sesión. Una vez que la aplicación termine de procesar esa sesión, debe eliminar el ServiceBusSessionReceiver asociado.

La siguiente nota se aplica a todos los SDK:

Nota

Establecer una conexión es una operación costosa que puede evitar si vuelve a usar la misma factoría o los mismos objetos de cliente para varias operaciones. Puede utilizar estos objetos de cliente para operaciones asincrónicas simultáneas y desde varios subprocesos.

Operaciones simultáneas

Las operaciones como enviar, recibir, eliminar, etc., tardan algún tiempo. Este tiempo incluye el que tarda el servicio Service Bus en procesar la operación y la latencia de la solicitud y la respuesta. Para aumentar el número de operaciones por tiempo, las operaciones deberán ejecutarse simultáneamente.

El cliente programa las operaciones simultáneas mediante la realización de operaciones asincrónicas. La siguiente solicitud se inicia antes de que se complete la anterior. En el siguiente fragmento de código se proporciona un ejemplo de operación asincrónica de envío:

var messageOne = new ServiceBusMessage(body);
var messageTwo = new ServiceBusMessage(body);

var sendFirstMessageTask =
    sender.SendMessageAsync(messageOne).ContinueWith(_ =>
    {
        Console.WriteLine("Sent message #1");
    });
var sendSecondMessageTask =
    sender.SendMessageAsync(messageTwo).ContinueWith(_ =>
    {
        Console.WriteLine("Sent message #2");
    });

await Task.WhenAll(sendFirstMessageTask, sendSecondMessageTask);
Console.WriteLine("All messages sent");

El siguiente código es un ejemplo de operación asincrónica de recepción.

var client = new ServiceBusClient(connectionString);
var options = new ServiceBusProcessorOptions 
{

      AutoCompleteMessages = false,
      MaxConcurrentCalls = 20
};
await using ServiceBusProcessor processor = client.CreateProcessor(queueName,options);
processor.ProcessMessageAsync += MessageHandler;
processor.ProcessErrorAsync += ErrorHandler;

static Task ErrorHandler(ProcessErrorEventArgs args)
{
    Console.WriteLine(args.Exception);
    return Task.CompletedTask;
};

static async Task MessageHandler(ProcessMessageEventArgs args)
{
    Console.WriteLine("Handle message");
    await args.CompleteMessageAsync(args.Message);
}

await processor.StartProcessingAsync();

Modo de recepción

Al crear un cliente de cola o suscripción, puede especificar un modo de recepción: Peek-lock (Inspección y bloqueo) o Receive And Delete (Recepción y eliminación). El modo de recepción predeterminado es PeekLock. Cuando se trabaja en el modo predeterminado, el cliente envía una solicitud para recibir un mensaje de Service Bus. Después de que el cliente haya recibido el mensaje, envía una solicitud para completarlo.

Al establecer el modo de recepción en ReceiveAndDelete, ambos pasos se combinan en una sola solicitud. Estos pasos reducen el número total de operaciones y pueden mejorar el rendimiento general de los mensajes. Esta mejora del rendimiento conlleva el riesgo de la pérdida de mensajes.

Service Bus no admite transacciones para las operaciones de recepción y eliminación. Además, se necesita la semántica de bloqueo de información en aquellos casos en los que el cliente quiera aplazar un mensaje o procesarlo como correo devuelto.

Captura previa

La captura previa permite que, al recibir mensajes, el cliente de la cola o la suscripción cargue otros adicionales desde el servicio. El cliente almacena estos mensajes en una memoria caché local. El tamaño de la caché está determinado por la propiedad ServiceBusReceiver.PrefetchCount. Cada cliente con la captura previa habilitada mantiene su propia memoria caché. Una caché no se comparte entre clientes. Si el cliente inicia una operación de recepción y su caché está vacía, el servicio transmite un lote de mensajes. Si el cliente inicia una operación de recepción y la caché contiene un mensaje, este se recupera de la caché.

Cuando se lleva a cabo la captura previa de un mensaje, el servicio bloquea dicho mensaje. Con el bloqueo, se impide que otro receptor reciba el mensaje previamente capturado. Si el receptor no puede completar el mensaje antes de que expire el bloqueo, pasa a estar disponible para otros receptores. La copia de captura previa del mensaje permanece en la memoria caché. El receptor que consume la copia en caché expirada recibe una excepción cuando intenta completar dicho mensaje. De forma predeterminada, el bloqueo del mensaje expira tras 60 segundos. Este valor puede ampliarse a 5 minutos. Para evitar el consumo de mensajes expirados, establezca el tamaño de la caché en un valor inferior al número de mensajes que un cliente puede consumir en el intervalo de tiempo de expiración de bloqueo.

Cuando usa la expiración de bloqueo predeterminada de 60 segundos, un valor óptimo para PrefetchCount es 20 veces la velocidad de procesamiento máxima de todos los destinatarios de la fábrica. Por ejemplo, una factoría crea tres receptores y cada receptor puede procesar hasta 10 mensajes por segundo. El número de capturas previas no debe superar 20 x 3 x 10 = 600. De forma predeterminada, PrefetchCount se establece en 0, lo que significa que no se realiza la captura previa de ningún mensaje adicional desde el servicio.

La captura previa de los mensajes aumenta el rendimiento general de una cola o una suscripción porque reduce el número total de operaciones de mensajes o recorridos de ida y vuelta. Sin embargo, capturar el primer mensaje tarda más tiempo (debido al aumento del tamaño del mensaje). Recibir mensajes previamente capturados de la caché es más rápido porque el cliente ya ha descargado estos mensajes.

El servidor comprueba la propiedad de período de vida (TTL) de un mensaje en el momento en que envía el mensaje al cliente. El cliente no comprueba la propiedad TTL del mensaje cuando lo recibe. En su lugar, se puede recibir el mensaje, aunque se haya superado el TTL del mensaje mientras el cliente lo almacenaba en caché.

La captura previa no afecta al número de operaciones de mensajería facturables y solo está disponible para el protocolo de cliente de Service Bus. El protocolo HTTP no admite la captura previa. La captura previa está disponible para las operaciones de recepción sincrónicas y asincrónicas.

Para más información, vea las propiedades PrefetchCount siguientes:

Puede establecer los valores de estas propiedades en ServiceBusReceiverOptions o ServiceBusProcessorOptions.

Captura previa y ReceiveMessagesAsync

Aunque los conceptos de realizar una captura previa de varios mensajes juntos tienen una semántica similar la de procesar los mensajes en un lote (ReceiveMessagesAsync), hay algunas diferencias menores que deben tenerse en cuenta al usar estos dos conceptos conjuntamente.

La captura previa es una configuración (o modo) en ServiceBusReceiver y ReceiveMessagesAsync es una operación (que tiene semántica de solicitud-respuesta).

Cuando se usen estos enfoques conjuntamente, tenga en cuenta los siguientes casos:

  • La captura previa debe ser mayor o igual que el número de mensajes que se espera recibir de ReceiveMessagesAsync.
  • La captura previa puede alcanzar n/3 veces el número de mensajes procesados por segundo, donde n es la duración del bloqueo predeterminada.

El hecho de tener un enfoque ambicioso, es decir, mantener alto el número de capturas previas, presenta algunas dificultades, porque implica que el mensaje se bloquea para un receptor en particular. Se recomienda probar los valores de captura previa que están entre los umbrales mencionados anteriormente e identificar la opción que mejor se adapte.

Varias colas o temas

Si una única cola o tema no puede controlar el número esperado de mensajes, use varias entidades de mensajería. Cuando use varias entidades, cree un cliente dedicado para cada una, en lugar de usar el mismo cliente para todas.

Tener más colas o temas significa que tendrá más entidades que administrar en el momento de la implementación. Desde una perspectiva de escalabilidad, realmente no se observaría demasiada diferencia porque Service Bus ya distribuye la carga entre varios registros internamente, por lo que el hecho de usar seis colas o temas o dos colas o temas no marcará una diferencia material.

El nivel de servicio que use afecta a la previsibilidad del rendimiento. Si elige el nivel Estándar, el rendimiento y la latencia son la mejor opción en una infraestructura multiinquilino compartida. Otros inquilinos del mismo clúster pueden afectar a su rendimiento. Si elige Premium, obtiene recursos que le proporcionan un rendimiento predecible y sus diversas colas o temas se procesan fuera de ese grupo de recursos. Para más información, consulte Planes de tarifa.

Espacios de nombres con particiones

Al usar espacios de nombres de nivel Premium con particiones, varias particiones con unidades de mensajería más bajas (MU) proporcionan un mejor rendimiento en una sola partición con MU más altas.

Escenarios

En las secciones siguientes, se describen escenarios habituales de mensajería y se explica la configuración preferida de Service Bus. Las tasas de rendimiento se clasifican como pequeñas (menos de 1 mensaje/segundo), moderadas (1 mensaje/segundo o más, pero menos de 100 mensajes/segundo) y altas (100 mensajes/segundo o más). El número de clientes se clasifica como pequeño (5 o menos), moderado (más de 5 pero un máximo de 20) y grande (más de 20).

Cola de alto rendimiento

Objetivo: Maximizar el rendimiento de una sola cola. El número de remitentes y receptores es pequeño.

  • Para aumentar la tasa general de envío a la cola, use varias factorías de mensajes para crear remitentes. Para cada remitente, use operaciones asincrónicas o varios subprocesos.
  • Para aumentar la tasa general de recepción de la cola, use varias factorías de mensajes para crear receptores.
  • Establezca el número de capturas previas en el valor resultante de multiplicar por 20 las tasas máximas de procesamiento de todos los receptores de una factoría. Este número reduce la cantidad de transmisiones del protocolo de cliente de Service Bus.

Varias colas de alto rendimiento

Objetivo: Maximizar el rendimiento general de varias colas. El rendimiento de una cola individual es moderado o alto.

Para obtener el máximo rendimiento en varias colas, use la configuración descrita para maximizar el rendimiento de una sola cola. Además, use distintas factorías para crear clientes que envíen o reciban desde distintas colas.

Cola de baja latencia

Objetivo: Minimizar la latencia de una cola o un tema. El número de remitentes y receptores es pequeño. El rendimiento de la cola es pequeño o moderado.

  • Si usa un solo cliente, establezca el número de capturas previas en el valor resultante de multiplicar por 20 la tasa de procesamiento del receptor. Si llegan varios mensajes a la cola al mismo tiempo, el protocolo de cliente de Service Bus los transmite todos a la vez. Cuando el cliente recibe el siguiente mensaje, ese mensaje ya se encuentra en la memoria caché local. La memoria caché debe ser pequeña.
  • Si se usan varios clientes, establezca el número de capturas previas en 0. Al establecer este número, el segundo cliente puede recibir el segundo mensaje mientras el primer cliente todavía está procesando el primero.

Cola con un gran número de remitentes

Objetivo: Maximizar el rendimiento de una cola o un tema con un gran número de remitentes. Cada remitente envía mensajes a una tasa moderada. El número de receptores es pequeño.

Service Bus permite hasta 1000 conexiones simultáneas a una entidad de mensajería. Este límite se aplica en el nivel de espacio de nombres, y las colas, los temas y las suscripciones quedan restringidos por el límite de conexiones simultáneas por espacio de nombres. Para las colas, este número se comparte entre remitentes y receptores. Si se requieren las 1000 conexiones para los remitentes, reemplace la cola por un tema y una única suscripción. Un tema acepta hasta 1000 conexiones simultáneas de los remitentes. La suscripción acepta 1000 conexiones simultáneas adicionales de los destinatarios. Si se requieren más de 1000 remitentes simultáneos, los remitentes deberían enviar mensajes al protocolo de Service Bus a través de HTTP.

Para maximizar el rendimiento, siga estos pasos:

  • Si cada remitente se encuentra en un proceso diferente, use solo una única factoría para cada proceso.
  • Establezca el número de capturas previas en el valor resultante de multiplicar por 20 las tasas máximas de procesamiento de todos los receptores de una factoría. Este número reduce la cantidad de transmisiones del protocolo de cliente de Service Bus.

Cola con un gran número de receptores

Objetivo: Maximizar la velocidad de recepción de una cola o suscripción con un gran número de receptores. Cada receptor recibe mensajes a una tasa moderada. El número de remitentes es pequeño.

Service Bus permite hasta 1000 conexiones simultáneas a una entidad. Si una cola requiere más de 1,000 receptores, reemplácela por un tema y varias suscripciones. Cada suscripción admite hasta 1000 conexiones simultáneas. Como alternativa, los receptores pueden acceder a la cola mediante el protocolo HTTP.

Para maximizar el rendimiento, siga estas instrucciones:

  • Si cada receptor se encuentra en un proceso diferente, use solo una única factoría por proceso.
  • Establezca el número de capturas previas en un valor pequeño (por ejemplo, PrefetchCount = 10). Este número evita que haya receptores inactivos mientras otros tienen un gran número de mensajes almacenados en caché.

Tema con pocas suscripciones

Objetivo: maximizar el rendimiento de un tema con pocas suscripciones. Muchas suscripciones reciben un mensaje, lo que significa que la velocidad de recepción combinada de todas las suscripciones es mayor que la velocidad de envío. El número de remitentes es pequeño. El número de receptores por suscripción es pequeño.

Para maximizar el rendimiento, siga estas instrucciones:

  • Para aumentar la velocidad de envío general al tema, use varios generadores de mensajes para crear remitentes. Para cada remitente, use operaciones asincrónicas o varios subprocesos.
  • Para aumentar la velocidad de recepción general desde una suscripción, use varios generadores de mensajes para crear receptores. Para cada receptor, use operaciones asincrónicas o varios subprocesos.
  • Establezca el número de capturas previas en el valor resultante de multiplicar por 20 las tasas máximas de procesamiento de todos los receptores de una factoría. Este número reduce la cantidad de transmisiones del protocolo de cliente de Service Bus.

Tema con un gran número de suscripciones

Objetivo: Maximizar el rendimiento de un tema con un gran número de suscripciones. Muchas suscripciones reciben un mensaje, lo que significa que la velocidad de recepción combinada de todas las suscripciones es mayor que la velocidad de envío. El número de remitentes es pequeño. El número de receptores por suscripción es pequeño.

Los temas con un gran número de suscripciones suelen ofrecer un rendimiento general bajo si todos los mensajes se enrutan a todas las suscripciones. El motivo es que cada mensaje se recibe muchas veces y todos los mensajes de un tema y todas sus suscripciones se almacenan en el mismo almacén. Aquí se supone que el número de remitentes y el número de receptores por suscripción son pequeños. Service Bus admite hasta 2000 suscripciones por tema.

Para maximizar el rendimiento, intente los siguientes pasos:

  • Establezca el recuento de capturas previas en 20 veces la velocidad esperada a la que se reciben los mensajes. Este número reduce la cantidad de transmisiones del protocolo de cliente de Service Bus.