¿Por qué no puedo exceder las conexiones de 32k o 65k TIME-WAIT?

He estado intentando sintonizar nuestras instancias del server web Ubuntu 14.04 LTS, alojando tanto aplicaciones web como nginx de reverse-proxying, para manejar el mayor número posible de req / s con el hardware dado. Se trata de una instancia EC4 c4.2xl con vCPU 8x.

Estoy ejecutando las siguientes dos herramientas de reference contra ella desde mi máquina de oficina (NO ambas al mismo time):

wrk -c1000 -d2m -t8 --timeout 90 --latency http://api.mysite.com/2/ping # or ab -k -n 100000 -c 1000 http://api.mysite.com/2/ping 

Lo que estoy viendo es que ejecutando ss -tan | wc -l ss -tan | wc -l Yo siempre máximo hacia fuera en cerca de 65.5k conexiones en TIME-WAIT

Mi configuration de OS es:

  • net.ipv4.ip_local_port_range value="15000 65000"
  • /etc/security/limits.conf tiene 'www-data hard nofile 100000' en él
  • /etc/pam.d/common-session* se actualizan para leer lo anterior

Y la configuration de nginx es:

  • worker_processes auto; # will result in 8 on this machine

events { worker_connections 8192; multi_accept on; use epoll; }

En la parte superior de la api que se proxied a nginx está por debajo, se utiliza para get un máximo muy alto de TCP cuadruplets diferentes, lo que significa que casi nunca se queda sin puertos efímeros en nginx -> app:

upstream my_api { server 127.0.0.1:3004; server 127.0.0.2:3004; server 127.0.0.3:3004; [...] }

Experimento un problema similar con mi instancia m3.large donde en lugar de 65k máximo en 32k. La diferencia entre los dos casos es que el primero tiene 2vCPU, el último tiene 8, y el primero tiene 7.5GB de memory y el último tiene 15GB.

Un problema similar se ha descrito en este post ( Escalando más allá de 65k files abiertos (conexiones TCP) ) pero no parece aplicarse en mi caso, como en mi caso más pequeño el vm.max_map_count es 65530, pero nunca pasa de 32k conexiones en TIME-WAIT .

Pensé que al principio el límite era sólo # processs * # trabajadores, pero en la instancia más pequeña todavía estoy limitado a 32k aunque suba el número de trabajadores por process a 25k cada uno, así que no es así.

No estoy seguro de qué button de pellizcar en este punto, no está claro para mí donde estas restricciones difícil podría estar viniendo. Podría usar algo de ayuda aquí.

Curiosamente, no veo que las conexiones sean finalmente rechazadas de cualquiera de estas máquinas ya que TIME-WAIT alcanza este "límite". Es posible que las queues de socket se están llenando detrás de las escenas y el cliente acaba de volver a intentar establecer una connection más tarde de nuevo, por lo que no estoy viendo ningún fallo permanente.

Actualizar:

En una instancia de c4.8xlarge puedo get hasta 262k conexiones en TIME-WAIT con las mismas configuraciones exactas de implementación. Incluso el número limitado de trabajadores de nginx a sólo 1 no lo cambia. Aún no estoy seguro de cuál sería la diferencia aquí.

Actualización 2:

Sospecho firmemente que esto tiene que ver con las diferentes instancias que tienen diferentes valores de net.ipv4.tcp_max_tw_buckets que por lo que puedo decir coinciden exactamente con el patrón que estoy viendo.

Echa un vistazo a net.ipv4.netfilter.ip_conntrack_max sintonizable. Para get más información, puede leer esta publicación ServerFault

Se están quedando sin puertos de origen en la máquina de origen.

Para identificar una connection necesita: IP de origen, puerto de origen, IP de destino y puerto de destino. Como IP de origen, IP de destino y Puerto de destino son siempre los mismos en sus testings, sólo tiene una variable: Puerto de origen. Su stack TCP / IP no puede manejar más de 64k puertos de origen diferentes (en realidad un poco less).

La testing de estrés desde un solo punto nunca es una buena idea, pero es posible que pueda ajustar esto un poco más al permitir que net.ipv4.tcp_tw_recycle reutilice los puertos en estado TIME_WAIT, pero puede causar problemas debido a la reutilización agresiva del puerto .