Rendimiento de SignalR

por Patrick Fletcher

Advertencia

Esta documentación no se aplica a la última versión de SignalR. Eche un vistazo a ASP.NET Core SignalR.

Este tema describe cómo diseñar, medir y mejorar el rendimiento en una aplicación de SignalR.

Versiones de software empleadas en este tema

Versiones anteriores de este tema

Para obtener información sobre versiones anteriores de SignalR, consulte Versiones anteriores de SignalR.

Preguntas y comentarios

Deje sus comentarios sobre este tutorial y sobre lo que podríamos mejorar en los comentarios en la parte inferior de la página. Si tiene alguna pregunta que no esté directamente relacionadas con el tutorial, puede publicarla en el foro de ASP.NET SignalR o en StackOverflow.com.

Para ver una presentación reciente sobre el rendimiento y el escalado de SignalR, consulte Escalado de la web en tiempo real con ASP.NET SignalR.

Este tema contiene las siguientes secciones:

Consideraciones de diseño

En esta sección se describen los patrones que pueden implementarse durante el diseño de una aplicación de SignalR, para asegurar que el rendimiento no se vea entorpecido por la generación de tráfico de red innecesario.

Limitación de la frecuencia de los mensajes

Incluso en una aplicación que envíe mensajes con una frecuencia elevada (como una aplicación de juegos en tiempo real), la mayoría de las aplicaciones no necesitan enviar más de unos pocos mensajes por segundo. Para reducir la cantidad de tráfico que genera cada cliente, se puede implementar un bucle de mensajes que ponga en cola y envíe mensajes con una frecuencia no superior a una tasa fija (es decir, se enviarán hasta un cierto número de mensajes cada segundo, si en ese intervalo de tiempo hay mensajes por enviar). Para ver un ejemplo de aplicación que limita los mensajes a una velocidad determinada (tanto del cliente como del servidor), consulte el Tiempo real de alta frecuencia con SignalR.

Reducir el tamaño del mensaje

Puede reducir el tamaño de un mensaje de SignalR reduciendo el tamaño de sus objetos serializados. En el código del servidor, si está enviando un objeto que contiene propiedades que no necesitan ser transmitidas, evite que esas propiedades sean serializadas usando el atributo JsonIgnore. Los nombres de las propiedades también se almacenan en el mensaje; los nombres de las propiedades pueden acortarse usando el atributo JsonProperty. El siguiente código de ejemplo demuestra cómo excluir una propiedad para que no se envíe al cliente y cómo acortar los nombres de las propiedades:

Código de servidor .NET que demuestra el atributo JsonIgnore para excluir datos del envío al cliente, y el atributo JsonProperty para reducir el tamaño del mensaje

using Newtonsoft.Json; 
using System; 
public class ShapeModel
{
    [JsonProperty("l")]
    public double Left { get; set; }
    [JsonProperty("t")]
    public double Top { get; set; }
    // We don't want the client to get the "LastUpdatedBy" property
    [JsonIgnore]
    public string LastUpdatedBy { get; set; }
}

Con el fin de mantener la legibilidad/mantenibilidad en el código del cliente, los nombres abreviados de las propiedades pueden reasignarse a nombres descriptivos una vez recibido el mensaje. El siguiente código de ejemplo demuestra una posible forma de reasignar nombres acortados a otros más largos, definiendo un contrato de mensajes (asignación), y usando la función reMap para aplicar el contrato a la clase de mensajes optimizada:

Código JavaScript del lado cliente que reasigna los nombres abreviados de las propiedades a nombres legibles

function reMap(smallObject, contract) {
    var largeObject = {};
    for (var smallProperty in contract) {
        largeObject[contract[smallProperty]] = smallObject[smallProperty];
    }
    return largeObject;
}
var shapeModelContract = {
    l: "left",
    t: "top"
};
myHub.client.setShape = function (shapeModelSmall) {
    var shapeModel = reMap(shapeModelSmall, shapeModelContract);
    // shapeModelSmall has "l" and "t" properties  but after remapping
    // shapeModel now has "left" and "top" properties
};

También se pueden acortar los nombres en los mensajes del cliente al servidor, usando el mismo método.

Reducir la superficie de memoria (es decir, la cantidad de memoria usada para el mensaje) del objeto de mensaje también puede mejorar el rendimiento. Por ejemplo, si no se necesita todo el rango de un int, se puede usar en su lugar un short o un byte.

Dado que los mensajes se almacenan en el bus de mensajes en la memoria del servidor, reducir el tamaño de los mensajes también puede solucionar problemas de memoria del servidor.

Ajuste del rendimiento de su servidor de SignalR

Los siguientes ajustes de configuración pueden usarse para ajustar su servidor para un mejor rendimiento en una aplicación de SignalR. Para obtener información general sobre cómo mejorar el rendimiento en una aplicación ASP.NET, consulte Mejorar el rendimiento de ASP.NET.

Ajustes de configuración de SignalR

  • DefaultMessageBufferSize: de forma predeterminada, SignalR conserva 1 000 mensajes en memoria por centro. Si se usan mensajes grandes, esto puede crear incidencias de memoria que pueden aliviarse reduciendo este valor. Esta configuración se puede establecer en el controlador de eventos Application_Start en una aplicación ASP.NET o en el método Configuration de una clase de inicio de OWIN en una aplicación autohospedada. El siguiente ejemplo demuestra cómo reducir este valor para reducir la huella de memoria de su aplicación con el fin de reducir la cantidad de memoria de servidor usada:

    Código de servidor .NET en Startup.cs para reducir el tamaño predeterminado del búfer de mensajes

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            // Any connection or hub wire up and configuration should go here
            GlobalHost.Configuration.DefaultMessageBufferSize = 500;
            app.MapSignalR();
        }
    }
    

Ajustes de configuración de IIS

  • Máximo de solicitudes simultáneas por aplicación: aumentar el número de solicitudes simultáneas de IIS aumentará los recursos del servidor disponibles para atender las solicitudes. El valor predeterminado es 5 000; para aumentar esta configuración, solicite los siguientes comandos en un símbolo del sistema con privilegios elevados:

    cd %windir%\System32\inetsrv\
    appcmd.exe set config /section:system.webserver/serverRuntime 
            /appConcurrentRequestLimit:10000
    
  • ApplicationPool QueueLength: este es el número máximo de solicitudes que Http.sys pone en cola para el grupo de aplicaciones. Cuando la cola está llena, las nuevas solicitudes reciben una respuesta 503 "Servicio no disponible". El valor predeterminado es 1000.

    Reducir la longitud de la cola para el proceso de trabajo en el grupo de aplicaciones que hospeda la aplicación conservará los recursos de memoria. Para más información, consulte Administración, ajuste y configuración de grupos de aplicaciones.

Ajustes de configuración de ASP.NET

Esta sección incluye los ajustes de configuración que pueden establecerse en el archivo aspnet.config. Este archivo se encuentra en una de estas dos ubicaciones, dependiendo de la plataforma:

  • %windir%\Microsoft.NET\Framework\v4.0.30319\aspnet.config
  • %windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet.config

Entre las configuraciones de ASP.NET que pueden mejorar el rendimiento de SignalR se incluyen las siguientes:

  • Número máximo de solicitudes simultáneas por CPU: aumentar esta configuración puede aliviar los cuellos de botella de rendimiento. Para aumentar esta configuración, agregue la siguiente configuración al archivo aspnet.config:

    <?xml version="1.0" encoding="UTF-8" ?>
    <configuration>
        <system.web>
            <applicationPool maxConcurrentRequestsPerCPU="20000" />
        </system.web>
    </configuration>
    
  • Límite de la cola de solicitudes: cuando el número total de conexiones supere la configuración de maxConcurrentRequestsPerCPU, ASP.NET empezará a limitar las solicitudes usando una cola. Para aumentar el tamaño de la cola, puede aumentar la configuración de requestQueueLimit. Para ello, agregue el siguiente ajuste de configuración al nodo processModel en config/machine.config (en lugar de aspnet.config):

    <processModel autoConfig="false" requestQueueLimit="250000" />
    

Solución de problemas de rendimiento

Esta sección describe formas de encontrar cuellos de botella de rendimiento en su aplicación.

Comprobación de que se está usando WebSocket

Aunque SignalR puede usar diversos transportes para la comunicación entre el cliente y el servidor, WebSocket ofrece una ventaja significativa en cuanto al rendimiento, y debería usarse si el cliente y el servidor son compatibles. Para determinar si el cliente y el servidor cumplen los requisitos de WebSocket, consulte Transportes y reservas. Para determinar qué transporte se está usando en su aplicación, puede usar las herramientas de desarrollo del explorador y examinar los registros para ver qué transporte se está usando para la conexión. Para obtener información sobre cómo usar las herramientas de desarrollo del explorador en Internet Explorer y Chrome, consulte Transportes y reservas.

Uso de contadores de rendimiento de SignalR

Esta sección describe cómo habilitar y usar los contadores de rendimiento de SignalR, que se encuentran en el paquete Microsoft.AspNet.SignalR.Utils.

Instalación de signalr.exe

Se pueden agregar contadores de rendimiento al servidor usando una utilidad llamada SignalR.exe. Para instalar esta utilidad, siga estos pasos:

  1. En Visual Studio, seleccione Herramientas>Administrador de paquetes NuGet>Administrar paquetes NuGet para solución

  2. Busque signalr.utils y seleccione Instalar.

    Screenshot that shows Microsoft A S P dot NET Signal R Utilities selected.

  3. Acepte el contrato de licencia para instalar el paquete.

  4. SignalR.exe se instalará en <project folder>/packages/Microsoft.AspNet.SignalR.Utils.<version>/tools.

Instalación de contadores de rendimiento con SignalR.exe

Para instalar los contadores de rendimiento de SignalR, ejecute SignalR.exe en un sistema con privilegios elevados con el siguiente parámetro:

SignalR.exe ipc

Para eliminar los contadores de rendimiento de SignalR, ejecute SignalR.exe en un sistema con privilegios elevados con el siguiente parámetro:

SignalR.exe upc

Contadores de rendimiento de SignalR

El paquete de utilidades instala los siguientes contadores de rendimiento. Los contadores "Total" miden el número de eventos desde el último grupo de aplicaciones o reinicio del servidor.

Métricas de conexión

Las siguientes métricas miden los eventos de duración de la conexión que se producen. Para más información, consulte Descripción y control de los eventos de duración de la conexión.

  • Conexiones conectadas
  • Conexiones reconectadas
  • Conexiones desconectadas
  • Conexiones actuales

Métricas de mensajes

Las siguientes métricas miden el tráfico de mensajes generado por SignalR.

  • Mensajes de conexión recibidos en total
  • Mensajes de conexión enviados en total
  • Mensajes de conexión recibidos por segundo
  • Mensajes de conexión enviados por segundo

Métricas del bus de mensajes

Las siguientes métricas miden el tráfico mediante el bus de mensajes interno de SignalR, la cola en la que se colocan todos los mensajes entrantes y salientes de SignalR. Un mensaje es Publicado cuando se envía o transmite. Un Suscriptor en este contexto es una suscripción en el bus de mensajes; debe ser igual al número de clientes más el propio servidor. Un Trabajador asignado es un componente que envía datos a conexiones activas; un Trabajador ocupado es uno que está enviando activamente un mensaje.

  • Mensajes de bus de mensajes recibidos en total
  • Mensajes de bus de mensajes recibidos por segundo
  • Mensajes de bus de mensajes publicados en total
  • Mensajes de bus de mensajes publicados por segundo
  • Suscriptores actuales del bus de mensajes
  • Total de suscriptores del bus de mensajes
  • Suscriptores del bus de mensajes por segundo
  • Trabajos asignados del bus de mensajes
  • Trabajos ocupados del bus de mensajesocupados
  • Temas actuales de bus de mensajes

Métricas de errores

Las siguientes métricas miden los errores generados por el tráfico de mensajes de SignalR. Los errores de resolución del centro se producen cuando no se puede resolver un centro o un método de centro. Los errores de invocación del centro son excepciones lanzadas al invocar un método de centro. Los errores de transporte son errores de conexión que se producen durante una solicitud o respuesta HTTP.

  • Errores: Todos en total
  • Errores: Todos/s
  • Errores: Resolución del centro en total
  • Errores: Resolución del centro/s
  • Errores: Invocación del centro en total
  • Errores: Invocación del centro/s
  • Errores: Transporte en total
  • Errores: Transporte/s

Métricas de escalabilidad horizontal

Las métricas siguientes miden el tráfico y los errores generados por el proveedor de escalabilidad horizontal. Un Stream en este contexto es una unidad de escalado usada por el proveedor de escalado; es una tabla si se usa SQL Server, un tema si se utiliza Service Bus y una suscripción si se usa Redis. Cada secuencia garantiza operaciones ordenadas de lectura y escritura; una sola secuencia es un posible cuello de botella de escala, por lo que se puede aumentar el número de secuencias para ayudar a reducir ese cuello de botella. Si se utilizan varias secuencias, SignalR distribuirá automáticamente los mensajes (particionados) entre estas secuencias de manera que se garantice que los mensajes enviados desde cualquier conexión determinada estén en orden.

La configuración MaxQueueLength controla la longitud de la cola de envío de escalado horizontal mantenida por SignalR. Si se establece en un valor mayor que 0, todos los mensajes de una cola de envío se enviarán de uno a uno al backplane de mensajería configurado. Si el tamaño de la cola supera la longitud configurada, las llamadas posteriores al envío producirán un error de inmediato con una excepción InvalidOperationException hasta que el número de mensajes de la cola vuelva a ser menor que el configurado. La cola está deshabilitada de forma predeterminada porque los backplanes implementados suelen tener su propia cola o control de flujo instalado. En el caso de SQL Server, la agrupación de conexiones limita de manera eficaz el número de envíos que se realizan en cualquier momento.

De forma predeterminada, solo se usa una secuencia para SQL Server y Redis, cinco secuencias para Service Bus y la cola estará deshabilitada, pero esta configuración se puede cambiar mediante la configuración en SQL Server y Service Bus:

Código de servidor .NET para configurar el recuento de tablas y la longitud de la cola para el backplane de SQL Server

var connectionString = "(your connection string)";
var config = new SqlScaleoutConfiguration(connectionString) { 
TableCount = 3,
MaxQueueLength = 50 };
GlobalHost.DependencyResolver.UseSqlServer(config);

Código de servidor .NET para configurar el recuento de temas y la longitud de la cola para el backplane de Service Bus

string connectionString = "(your connection string)";
var config = new ServiceBusScaleoutConfiguration(connectionString, "YourAppName") { 
TopicCount = 3,
MaxQueueLength = 50 };
GlobalHost.DependencyResolver.UseServiceBus(config);

Una secuencia de almacenamiento en búfer es aquella que ha entrado en estado de error; cuando la secuencia está en estado de error, todos los mensajes enviados al backplane provocarán un error de inmediato hasta que la secuencia deje de estar en estado de error. La Longitud de la cola de envío es el número de mensajes que se han publicado pero que aún no se han enviado.

  • Mensajes de bus de mensajes de escalabilidad horizontal recibidos/s
  • Total de secuencias de escalabilidad horizontal
  • Secuencias de escalabilidad horizontal abiertas
  • Almacenamiento en búfer de secuencias de escalabilidad horizontal
  • Total de errores de escalabilidad horizontal
  • Errores de escalabilidad horizontal/s
  • Longitud de la cola de envío de escalabilidad horizontal

Para más información sobre lo que miden estos contadores, consulte Escalabilidad horizontal de SignalR con Azure Service Bus.

Uso de otros contadores de rendimiento

Los siguientes contadores de rendimiento también pueden ser útiles para supervisar el rendimiento de su aplicación.

Memoria

  • .NET CLR Memory\# bytes in all Heaps (for w3wp)

ASP.NET

  • ASP.NET\Requests Current
  • ASP.NET\Queued
  • ASP.NET\Rejected

CPU

  • Processor Information\Processor Time

TCP/IP

  • TCPv6/Connections Established
  • TCPv4/Connections Established

Servicio web

  • Web Service\Current Connections
  • Web Service\Maximum Connections

Subprocesamiento

  • .NET CLR Locks And Threads\# of current logical Threads
  • .NET CLR Locks And Threads\# of current physical Threads

Otros recursos

Para más información sobre la supervisión y el ajuste del rendimiento de ASP.NET, consulte los siguientes temas: