Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Por Ashley Stanton-Nurse, Brady Gaster y Tom Dykstra
En este artículo se explican las consideraciones de hospedaje y escalado para aplicaciones de alto tráfico que usan ASP.NET Core SignalR.
Sesiones permanentes
SignalR requiere que el mismo proceso de servidor controle todas las solicitudes HTTP para una conexión específica. Cuando SignalR se ejecuta en una granja de servidores (varios servidores), se deben usar "sesiones permanentes". Las "sesiones persistentes" también se denominan afinidad de sesión. Azure App Service usa Microsoft Enrutamiento de solicitudes de aplicación (ARR) para enrutar las solicitudes. Al habilitar la configuración "Afinidad de sesión" (ARR Affinity) en su aplicación de App Service, se habilitan las sesiones persistentes.
Hay tres escenarios en los que las sesiones persistentes no son necesarias para una aplicación:
- Hospedaje en un solo servidor en un único proceso
- Uso del servicio Azure SignalR (las sesiones permanentes están habilitadas para el servicio, no para la aplicación)
- Todos los clientes están configurados para usar WebSockets solo y la configuración de cliente habilita SkipNegotiation.
En todos los demás escenarios (incluidos aquellos en los que se usa el backplane de Redis), el entorno del servidor debe configurarse para sesiones persistentes.
Para obtener instrucciones sobre cómo configurar Azure App Service para SignalR, consulte Publicación de una aplicación de ASP.NET Core SignalR en Azure App Service. Para obtener instrucciones sobre cómo configurar sesiones permanentes para aplicaciones Blazor que usan el servicio SignalR de Azure, consulte Hospedaje e implementación de aplicaciones Blazor del lado servidor de ASP.NET Core.
Recursos de conexión TCP
El número de conexiones TCP simultáneas que un servidor web puede admitir es limitado. Los clientes HTTP estándar usan conexiones efímeras . Estas conexiones se pueden cerrar cuando el cliente deja de estar inactivo y se vuelve a abrir más adelante. Por otro lado, una conexión SignalR es persistente. Las conexiones SignalR permanecen abiertas incluso cuando el cliente deja de estar inactivo. En una aplicación de alto tráfico que atiende a muchos clientes, estas conexiones persistentes pueden hacer que los servidores alcancen su número máximo de conexiones.
Las conexiones persistentes también consumen memoria adicional para realizar un seguimiento de cada conexión.
El uso intensivo de recursos relacionados con la conexión que hace SignalR puede afectar a otras aplicaciones web hospedadas en el mismo servidor. Cuando SignalR se abre y contiene las últimas conexiones TCP disponibles, otras aplicaciones web del mismo servidor tampoco tienen más conexiones disponibles.
Si un servidor agota las conexiones disponibles, se pueden producir errores aleatorios de socket y errores de reinicio de conexión. Por ejemplo:
An attempt was made to access a socket in a way forbidden by its access permissions...
Para evitar que el uso de recursos SignalR cause errores en otras aplicaciones web, ejecute SignalR en servidores diferentes de las demás aplicaciones web.
Para evitar que el uso de recursos SignalR cause errores en una aplicación SignalR, escale horizontalmente para limitar el número de conexiones que tiene que controlar un servidor.
Escalado horizontal
Una aplicación que usa SignalR debe supervisar todas sus conexiones, lo que crea problemas para una granja de servidores. Agregue un servidor y obtenga nuevas conexiones que los demás servidores no conocen. Por ejemplo, SignalR en cada servidor del diagrama siguiente no es consciente de las conexiones en los demás servidores. Cuando SignalR en uno de los servidores quiere enviar un mensaje a todos los clientes, el mensaje solo va a los clientes conectados a ese servidor.
Las opciones para resolver este problema son el Servicio SignalR de Azure y backplane de Redis.
Azure SignalR Servicio
El servicio SignalR de Azure funciona como proxy para el tráfico en tiempo real y también actúa como plano de fondo cuando la aplicación se escala horizontalmente en varios servidores. Cada vez que un cliente inicia una conexión con el servidor, se redirige al cliente para conectarse al servicio. En el diagrama siguiente se muestra este proceso:
El resultado es que el servicio administra todas las conexiones de cliente, mientras que cada servidor solo necesita un pequeño número constante de conexiones al servicio, como se muestra en el diagrama siguiente:
Este enfoque para el escalado horizontal tiene varias ventajas sobre la alternativa del backplane de Redis:
- Las sesiones persistentes, también conocidas como afinidad de cliente, no son necesarias porque los clientes se redirigen inmediatamente al servicio SignalR de Azure cuando se conectan.
- Una aplicación SignalR puede escalar horizontalmente en función del número de mensajes enviados, mientras que el servicio SignalR de Azure se escala para controlar cualquier número de conexiones. Por ejemplo, podría haber miles de clientes, pero si solo se envían algunos mensajes por segundo, la SignalR aplicación no necesita escalar horizontalmente a varios servidores solo para controlar las conexiones.
- Una SignalR aplicación no usa muchos más recursos de conexión que una aplicación web sin SignalR.
Por estos motivos, la recomendación es usar la Azure SignalR Service para todas las aplicaciones de ASP.NET Core SignalR hospedadas en Azure, incluidos App Service, máquinas virtuales y contenedores.
Para obtener más información, consulte la documentación de Azure SignalR Service.
plano de fondo de Redis
Redis es un almacén de claves y valores en memoria que admite un sistema de mensajería con un modelo de publicación y suscripción. El SignalR backplane de Redis usa la funcionalidad de publicación/suscripción para reenviar mensajes a otros servidores. Cuando un cliente establece una conexión, la información de la conexión se transmite al backplane. Cuando un servidor quiere enviar un mensaje a todos los clientes, lo envía al backplane. El backplane conoce todos los clientes conectados y los servidores en los que están. Envía el mensaje a todos los clientes a través de sus respectivos servidores. Este proceso se ilustra en el diagrama siguiente:
El backplane de Redis es el enfoque de escalado horizontal recomendado para las aplicaciones hospedadas en su propia infraestructura. Si existe una latencia de conexión significativa entre el centro de datos y un centro de datos de Azure, es posible que Azure SignalR Service no sea una opción práctica para las aplicaciones locales con requisitos de baja latencia o alto rendimiento.
Las ventajas de Azure SignalR Service descritas anteriormente son desventajas para el plano de fondo de Redis:
- Se requieren sesiones persistentes, también conocidas como afinidad del cliente, excepto cuando se cumplen ambas condiciones siguientes:
- Todos los clientes están configurados para usar solo WebSockets.
- La opción SkipNegotiation está habilitada en la configuración del cliente. Una vez iniciada una conexión en un servidor, la conexión debe permanecer en ese servidor.
- Una SignalR aplicación debe escalar horizontalmente en función del número de clientes, incluso cuando se envían pocos mensajes.
- Una SignalR aplicación usa muchos más recursos de conexión que una aplicación web sin SignalR.
Limitaciones de IIS en Windows sistema operativo cliente
Windows 10 y Windows 8.x son sistemas operativos de cliente. Internet Information Services (IIS) en sistemas operativos cliente tiene un límite de 10 conexiones simultáneas. Las SignalR conexiones tienen las siguientes características:
- Son transitorios y se vuelven a establecer con frecuencia.
- No se eliminan inmediatamente cuando ya no se usan.
Estas características hacen que sea probable que alcance el límite de 10 conexiones en un sistema operativo cliente. Al usar un sistema operativo cliente para el desarrollo, tenga en cuenta las siguientes recomendaciones:
- Evitar IIS
- Use Kestrel o IIS Express como destinos de implementación
Linux con Nginx
El código siguiente contiene la configuración mínima necesaria para habilitar WebSockets, ServerSentEvents y LongPolling para SignalR:
http {
map $http_connection $connection_upgrade {
"~*Upgrade" $http_connection;
default keep-alive;
}
server {
listen 80;
server_name example.com *.example.com;
# Configure the SignalR Endpoint
location /hubroute {
# App server url
proxy_pass http://localhost:5000;
# Configuration for WebSockets
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_cache off;
# WebSockets were implemented after http/1.0
proxy_http_version 1.1;
# Configuration for ServerSentEvents
proxy_buffering off;
# Configuration for LongPolling or if your KeepAliveInterval is longer than 60 seconds
proxy_read_timeout 100s;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
Cuando se utilizan varios servidores de back-end, es necesario añadir sesiones persistentes para evitar que las conexiones SignalR cambien de servidor al conectarse. Hay varias maneras de agregar sesiones permanentes en Nginx. En los ejemplos siguientes se muestran dos enfoques basados en lo que tiene disponible.
El código siguiente complementa la configuración de ejemplo anterior. En los fragmentos de código, backend es el nombre del grupo de servidores.
Con Nginx Open Source, use
ip_hashpara enrutar las conexiones a un servidor en función de la dirección IP del cliente:http { upstream backend { # App server 1 server localhost:5000; # App server 2 server localhost:5002; ip_hash; } }Con Nginx Plus, use
stickypara agregar un cookie elemento a las solicitudes y anclar las solicitudes de usuario a un servidor:http { upstream backend { # App server 1 server localhost:5000; # App server 2 server localhost:5002; sticky cookie srv_id expires=max domain=.example.com path=/ httponly; } }Para ambas configuraciones, cambie
proxy_pass http://localhost:5000en laserversección aproxy_pass http://backend.
Puede encontrar más información en Host ASP.NET Core en Linux con Nginx.
- Para usar WebSockets a través de Nginx, consulte Uso de proxy de WebSocket con Nginx.
- Para usar el equilibrio de carga y las sesiones permanentes, consulte Equilibrio de carga HTTP con Nginx.
Otros proveedores de SignalR backplane
Los siguientes proveedores ajenos a Microsoft también ofrecen SignalR backplane: