2009-04-17 30 views
22

Tengo un programa muy simple escrito en 5 min que abre un socket de corte y recorre la solicitud e imprime en la pantalla los bytes que se le envían.¿Existe un límite en el número de conexiones tcp/ip entre máquinas en Linux?

Luego traté de comparar cuántas conexiones puedo usar para tratar de averiguar cuántos usuarios concurrentes puedo apoyar con este programa.

En otra máquina (donde la red entre ellos no está saturada) creé un programa simple que entra en un bucle y se conecta a la máquina del servidor y envía los bytes "hello world".

Cuando el ciclo es 1000-3000, el cliente finaliza con todas las solicitudes enviadas. Cuando el ciclo va más allá de 5000, comienza a tener tiempos de espera después de finalizar el primer número X de solicitudes. ¿Por qué es esto? Me he asegurado de cerrar mi socket en el bucle.

¿Solo puede crear tantas conexiones dentro de un cierto período de tiempo?

¿Este límite solo es aplicable entre las mismas máquinas y no tengo que preocuparme por esto en la producción, donde más de 5000 solicitudes provienen de diferentes máquinas?

+0

puede supervisar sus tomas usando el comando ss -s. Y siga los pasos para aumentar el límite de socket si es necesario – Antarus

+0

puede reutilizar sockets TIMED_WAIT como: 's = socket.socket (socket.AF_INET, socket.SOCK_STREAM, 0)' 's.setsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) ' – knutole

Respuesta

24

Hay un límite, sí. Ver ulimit.

También debe tener en cuenta el estado TIMED_WAIT. Una vez que se cierra un socket TCP (por defecto) el puerto permanece ocupado en el estado TIMED_WAIT durante 2 minutos. Este valor es sintonizable Esto también "te sacará de las órbitas" aunque estén cerrados.

Ejecute netstat para ver el TIMED_WAIT cosas en acción.

P.S. El motivo de TIMED_WAIT es manejar la caja de paquetes que llegan después de que se cierra el zócalo. Esto puede suceder porque los paquetes se retrasan o el otro lado simplemente no sabe que el socket ya se ha cerrado. Esto permite que el sistema operativo silencie esos paquetes sin posibilidad de "infectar" una conexión de socket diferente y no relacionada.

+0

Acabo de comprobar con netstat en ambas máquinas, y de hecho hay un montón de TIMED_WAIT en el lado del cliente, pero no TIMED_WAIT en el lado del servidor. ¿Es este el comportamiento que estás describiendo? Suponiendo que sí: 1) ¿Esto significa que esto no será un problema en producción porque el límite parece provenir del lado del cliente (se está quedando sin socket) y no del lado del servidor (donde no se crean sockets) 2) ¿Hay alguna forma de evitar esto, así que puedo probar mi servidor con una carga similar a la producción? – erotsppa

+0

El comportamiento de TIMED_WAIT es específico del sistema operativo. Sí, puedes evitarlo: es posible cambiar el tiempo de espera de TIMED_WAIT, p. de 120 segundos a 30 o incluso menos. –

+0

ulimit me muestra "ilimitado" ... pero realmente no creo que sea ilimitado ... – trillions

1

Es posible que desee echa un vistazo a /etc/security/limits.conf

8

Cuando busca el máximo rendimiento, se encuentra con un montón de problemas y posibles cuellos de botella. Ejecutar una prueba simple de hello world no necesariamente los va a encontrar a todos.

limitaciones posibles incluyen:

  • limitaciones de socket Kernel: Buscar en /proc/sys/net para un montón de sintonía kernel ..
  • límites del proceso: consulta ulimit como otros han mencionado aquí
  • como su aplicación crece en complejidad, puede no tener suficiente potencia de CPU para mantenerse al día con la cantidad de conexiones entrantes. Use top para ver si su CPU está al máximo
  • ¿número de subprocesos? No tengo experiencia con el enhebrado, pero esto puede entrar en juego junto con los artículos anteriores.
2

¿Su servidor tiene un solo hilo? Si es así, ¿qué función de sondeo/multiplexación está usando?

El uso de select() no funciona más allá del límite de descriptor de archivo máximo codificado fijo establecido en tiempo de compilación, lo que es inútil (normalmente 256 o algunos más).

encuesta() es mejor pero terminará con el problema de escalabilidad con una gran cantidad de FD repoblando el conjunto cada vez que se pasa el ciclo.

epoll() debería funcionar bien hasta algún otro límite que aciertes.

Las conexiones 10k deberían ser lo suficientemente fáciles de lograr. Use un núcleo reciente (ish) 2.6.

¿Cuántas máquinas cliente usó? ¿Estás seguro de que no alcanzaste el límite del lado del cliente?

+0

En mi sistema, el límite de selección codificado fue 1024 y de hecho es imposible ir por encima de esto (el límite lo impone un tipo de datos que contiene el mapa de descriptores de archivos para ver). –

2

La respuesta rápida es 2^16 puertos TCP, 64K.

Los problemas con los límites impuestos por el sistema son un problema de configuración, ya mencionado en comentarios anteriores.

Las implicaciones internas para TCP no son tan claras (para mí). Cada puerto requiere memoria para su creación de instancias, va a una lista y necesita búferes de red para los datos en tránsito.

Dadas 64K sesiones de TCP, la sobrecarga para las instancias de los puertos puede ser un problema en un núcleo de 32 bits, pero no en un kernel de 64 bits (la corrección se acepta con mucho gusto). El proceso de búsqueda con sesiones de 64K puede ralentizar un poco las cosas y cada paquete llega a las colas del temporizador, lo que también puede ser problemático. El almacenamiento de datos en tránsito puede, en teoría, aumentar al tamaño de ventana por puertos (tal vez 8 GByte).

El problema con la velocidad de conexión (mencionado anteriormente) es probablemente lo que está viendo. TCP generalmente toma tiempo para hacer cosas. Sin embargo, no es obligatorio. Se puede hacer una conexión TCP, realizar transacciones y desconectar de manera muy eficiente (verifique cómo se crean y cierran las sesiones TCP).

Existen sistemas que pasan decenas de gigabits por segundo, por lo que la escala del nivel de paquetes debería ser correcta.

Hay máquinas con mucha memoria física, por lo que se ve bien.

El rendimiento del sistema, si se ha configurado cuidadosamente, debería ser correcto.

El lado del servidor de las cosas debe escalar de una manera similar.

Me preocuparían cosas como el ancho de banda de la memoria.

Considere un experimento en el que inicia sesión en el host local 10.000 veces. Luego escribe un personaje. La pila completa a través del espacio de usuario se dedicaría a cada personaje. La huella activa probablemente excedería el tamaño del caché de datos. Correr a través de mucha memoria puede estresar el sistema VM. ¡El costo de los cambios de contexto podría acercarse un segundo!

Esto se discute en una variedad de otros temas: https://serverfault.com/questions/69524/im-designing-a-system-to-handle-10000-tcp-connections-per-second-what-problems

Cuestiones relacionadas