¿Existe algún problema al mantener un gran número de conexiones de socket abierto durante largos períodos de tiempo?

7

La aplicación que tenemos en mente es un servidor de retransmisión. El objetivo es aceptar un gran número de conexiones de socket entrantes (al menos miles) que permanecerán abiertas durante períodos prolongados (horas o tal vez días). Intercambiarán cantidades modestas de datos y necesitarán una latencia razonablemente baja.

El diseño técnico es directo y tenemos una implementación de prueba. Nuestra preferencia es usar Windows hosting y .NET, porque esa es la tecnología que conocemos. Sin embargo, este tipo de uso está muy lejos de lo que estamos familiarizados.

La pregunta es si existen límites o restricciones específicos a tener en cuenta que son inherentes o comunes al software que hace esto, y que debemos tener en cuenta en nuestro diseño y / o prueba antes de una implementación.

Encontré esta pregunta ( Manejo de grandes cantidades de sockets ) y esto enlace ( enlace ), que tienden a sugerir que nuestra solución debería funcionar.

-

Los comentaristas han sugerido abrir y cerrar puertos, o usar algún tipo de protocolo, sin sugerir cómo. El problema es que en cualquier momento un mensaje puede ser transmitido a un destino conocido individual con la expectativa de que se reciba rápidamente (digamos 1 segundo como máximo, preferiblemente antes). El destino está (en general) detrás de un firewall con propiedades desconocidas, por lo que no puede (en general) ejecutar un servidor o aceptar conexiones entrantes. Solo puede hacer conexiones salientes. Creemos que necesita una conexión saliente persistente para recibir paquetes en cualquier momento sin previo aviso. Sugerencias alternativas serían de interés, aunque estrictamente fuera del tema para esta pregunta.

Otros comentaristas han sugerido que hay límites de SO, pero no se ha especificado ninguno. Suponiendo que esta es una versión del servidor de Windows y una cantidad de memoria (quizás grande), ¿es probable que los límites sean un problema? ¿Aproximadamente cuáles serán? ¿Es Windows una mala idea?

    
pregunta david.pfx 03.04.2014 - 15:13

5 respuestas

3

Trabajé en un servidor de retransmisión para datos del mercado de valores en C # en un servidor Windows. No había manera de conseguir miles de conexiones simultáneas transmitidas por una máquina. Las especificaciones para el relé eran muy simples: una conexión con el proveedor de datos del mercado de valores y un número ilimitado de conexiones salientes a los clientes de SilverLight.

Hay dos enfoques básicos que he investigado.

  • Use un grupo de subprocesos, cada cliente obtiene un socket y un subproceso de trabajo.
  • Use un subproceso de trabajo, el subproceso de trabajo inserta datos al iterar sobre todos los sockets abiertos.

Ningún enfoque podría exceder los límites de rendimiento de la CPU, y cada enfoque tenía serias limitaciones y restricciones.

Usando un grupo de subprocesos.

Windows apesta en el manejo de subprocesos múltiples. Una vez que golpeé alrededor de 250 hilos, las cosas empezaron a ir cuesta abajo. No es un problema de memoria o de recursos del sistema. Es un problema de cantidad. Mientras que Windows no tiene problemas para administrar 250 hilos. Es otra historia que le pide a Windows que mantenga esos 250 hilos ocupados transmitiendo datos. A medida que el rendimiento se retrasa, comienza a producirse una acumulación de datos.

Usando un subproceso de trabajo.

No puedes usar un hilo de trabajo para iterar sockets si esos sockets están bloqueando. Cada vez que el hilo llega a un zócalo que tiene que agotarse el tiempo de espera, todos los demás zócalos se quedan esperando. Si cambias a las operaciones de socket asycn, entonces se genera un gran atraso en las devoluciones de llamadas y todo se rompe.

Para mí los resultados fueron.

100 clientes todo es estable. 250 clientes todo funciona pero el límite alcanzado. 1000 clientes nunca alcanzados.

Conclusión.

C # en Windows no es la herramienta adecuada para un servidor de socket relay. No para las conexiones de clientes que van en los miles.

La única alternativa es no usar sockets HTTP y cambiar a un protocolo de transmisión como UDP o TCP. Para mí, esta no era una opción, ya que no se permitía la eliminación de datos. La mayoría de los protocolos de transmisión asumen que la pérdida de paquetes es aceptable.

Finalmente.

Si puede crear un relé de C # que pueda manejar miles de clientes. Por favor, vuelve y hazme saber cómo lo hiciste.

    
respondido por el cgTag 04.04.2014 - 16:31
6

Creo que está buscando un protocolo : algo que pueda manejar los errores, las retransmisiones, etc. Por ejemplo, ¿qué sucede si uno de los zócalos se cae porque la red subyacente tuvo un problema? ¿O si sus mensajes se reciben dos veces debido a un interruptor defectuoso en la línea? ¿O si llegan en el orden equivocado?

Dado que estás planeando un número grande de conexiones, también deberás considerar el aumento en la probabilidad de que algo funcione mal.

Además, ¿qué sucede si desea escalar su arquitectura horizontalmente, es decir, agregar más servidores? No puede equilibrar la carga de sockets abiertos y transferirlos sin problemas a través de los nodos.

Al final, recomiendo usar un protocolo de paso de mensajes más robusto, diseñado para esperar fallas. En términos más simples, considere cada comunicación atómica, donde el peor de los casos es una conexión nueva cada vez. Más o menos a lo largo de las líneas del problema de C10K .

Si aún necesita más convincente, intente probar su arquitectura con una maqueta: vea cómo reacciona a la conexión de diez mil clientes al mismo tiempo (es más fácil en una LAN). Luego imagine que agrega latencia de red, errores, etc.

    
respondido por el lorenzog 03.04.2014 - 17:39
4

las computadoras tienen un límite estricto de cuántas conexiones pueden estar abiertas en ese momento (decididas por el sistema operativo). Los programas ven un subconjunto de eso.

cada socket abierto requiere algunos recursos y un latido de tiempo de espera de red para que se puedan detectar las desconexiones. Tener muchos sockets enviando esos latidos del corazón comenzará a llenar el ancho de banda.

mi sugerencia es cerrar las conexiones según sea necesario y solo aceptar que necesitarás volver a abrirlas.

    
respondido por el ratchet freak 03.04.2014 - 15:20
1

La experiencia sugiere que hay una solución mejor y probablemente bastante diferente para su problema.

Sin embargo, es posible crear y mantener un número considerable de conexiones de socket durante un largo período de tiempo con una confiabilidad inferior al 100%.

Un diseño robusto se haría de manera muy diferente.

El problema es qué sucede cuando el servidor de relé se bloquea. Si solo tienes un servidor, entonces tu servicio está perdido al 100%. Si tiene varios servidores, entonces los clientes pueden reconectarse y conectarse a un servidor diferente, pero se habrá perdido cualquier mensaje que se les retransmita durante la desconexión y la reconexión. Dependiendo de su producto, esto puede ser importante.

Si su 'retransmisión' realmente se implementó como un servicio de cola de mensajes distribuidos, proporciona un conjunto de herramientas que resuelve la mayoría de estos problemas para usted y proporciona un mecanismo para implementar el nivel de robustez y disponibilidad que se adapte a su aplicación.

Esto no es una recomendación, pero RabbitMQ es un ejemplo de un producto que puede realizar la función de retransmisión por usted. Hay otros, y deberá revisar una selección para decidir cuál es la más adecuada para su producto.

    
respondido por el Michael Shaw 03.04.2014 - 18:17
1

Habiendo brindado soporte de firewall y VPN durante un par de años, puedo decirle con confianza que las aplicaciones que mantienen los puertos abiertos durante un período prolongado de tiempo no son estables tanto desde la perspectiva del servidor local como desde la perspectiva del punto de entrada de la red. . También puede ser un riesgo de seguridad (si eso es una consideración en su caso).

Dejar una conexión persistente abierta en un puerto del servidor puede causar un problema en el firewall, ya que la tabla NAT acumula entradas, por ejemplo.

Personalmente, recomiendo mantener sus números de clientes conectados en el rango de 200 a 250 por servidor para conexiones persistentes a través de TCP / IP donde los datos que se envían y reciben requieren una latencia mínima.

Si tiene el hardware para cambiar a ATM (Modo de transferencia asíncrono), puede reconfigurar a sus clientes para que escuchen solo su dirección específica, lo que le quitará una carga importante a sus servidores (a expensas de los clientes). Los cajeros automáticos deben ingresar a los 300 a 350 clientes activos por capacidad del servidor.

Para aclarar, la solución a este problema es colocar su servidor en una DMZ en el firewall para mejorar el acceso y usar la conectividad ATM con la mayor cantidad de clientes posible. De lo contrario, estará a merced del firewall de la red remota y otros enrutadores inteligentes intermedios.

    
respondido por el miniscule 02.07.2015 - 01:38

Lea otras preguntas en las etiquetas