Tiempo de espera NGINX después de +200 conexiones concurrentes

12

Este es mi nginx.conf(he actualizado la configuración para asegurarme de que no haya PHP involucrado o cualquier otro cuello de botella):

user                nginx;
worker_processes    4;
worker_rlimit_nofile 10240;

pid                 /var/run/nginx.pid;

events
{
    worker_connections  1024;
}

http
{
    include             /etc/nginx/mime.types;

    error_log           /var/www/log/nginx_errors.log warn;

    port_in_redirect    off;
    server_tokens       off;
    sendfile            on;
    gzip                on;

    client_max_body_size 200M;

    map $scheme $php_https { default off; https on; }

    index index.php;

    client_body_timeout   60;
    client_header_timeout 60;
    keepalive_timeout     60 60;
    send_timeout          60;

    server
    {
        server_name dev.anuary.com;

        root        "/var/www/virtualhosts/dev.anuary.com";
    }
}

Estoy usando http://blitz.io/play para probar mi servidor (compré el plan de 10 000 conexiones simultáneas). En una carrera de 30 segundos, recibo 964golpes y 5,587 timeouts. El primer tiempo de espera ocurrió a los 40.77 segundos de la prueba cuando el número de usuarios concurrentes era de 200.

Durante la prueba, la carga del servidor fue ( topsalida):

 PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                               20225 nginx     20   0 48140 6248 1672 S 16.0  0.0   0:21.68 nginx                                                                  
    1 root      20   0 19112 1444 1180 S  0.0  0.0   0:02.37 init                                                                   
    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd                                                               
    3 root      RT   0     0    0    0 S  0.0  0.0   0:00.03 migration/0      

Por lo tanto, no es un problema de recursos del servidor. ¿Entonces que es?

ACTUALIZACIÓN 2011 12 09 GMT 17:36.

Hasta ahora hice los siguientes cambios para asegurarme de que el cuello de botella no sea TCP / IP. Añadido a /etc/sysctl.conf:

# These ensure that TIME_WAIT ports either get reused or closed fast.
net.ipv4.tcp_fin_timeout = 1
net.ipv4.tcp_tw_recycle = 1
# TCP memory
net.core.rmem_max = 16777216
net.core.rmem_default = 16777216
net.core.netdev_max_backlog = 262144
net.core.somaxconn = 4096

net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2

Más información de depuración:

[root@server node]# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 126767
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 1024
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

NB Eso worker_rlimit_nofileestá configurado en 10240nginx config.

ACTUALIZACIÓN 2011 12 09 GMT 19:02.

Parece que cuantos más cambios haga, peor será, pero aquí está el nuevo archivo de configuración.

user                nginx;
worker_processes    4;
worker_rlimit_nofile 10240;

pid                 /var/run/nginx.pid;

events
{
    worker_connections  2048;
    #1,353 hits, 2,751 timeouts, 72 errors - Bummer. Try again?
    #1,408 hits, 2,727 timeouts - Maybe you should increase the timeout?
}

http
{
    include             /etc/nginx/mime.types;

    error_log           /var/www/log/nginx_errors.log warn; 

    # http://blog.martinfjordvald.com/2011/04/optimizing-nginx-for-high-traffic-loads/
    access_log              off;

    open_file_cache         max=1000;
    open_file_cache_valid   30s;

    client_body_buffer_size 10M;
    client_max_body_size    200M;

    proxy_buffers           256 4k;
    fastcgi_buffers         256 4k;

    keepalive_timeout       15 15;

    client_body_timeout     60;
    client_header_timeout   60;

    send_timeout            60;

    port_in_redirect        off;
    server_tokens           off;
    sendfile                on;

    gzip                    on;
    gzip_buffers            256 4k;
    gzip_comp_level         5;
    gzip_disable            "msie6";



    map $scheme $php_https { default off; https on; }

    index index.php;



    server
    {
        server_name ~^www\.(?P<domain>.+);
        rewrite     ^ $scheme://$domain$request_uri? permanent;
    }

    include /etc/nginx/conf.d/virtual.conf;
}

ACTUALIZACIÓN 2011 12 11 GMT 20:11.

Esto se emite netstat -ntladurante la prueba.

https://gist.github.com/d74750cceba4d08668ea

ACTUALIZACIÓN 2011 12 12 GMT 10:54.

Solo para aclarar, el iptables(firewall) está apagado durante las pruebas.

ACTUALIZACIÓN 2011 12 12 GMT 22:47.

Este es el sysctl -p | grep membasurero.

net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
kernel.core_uses_pid = 1
net.ipv4.tcp_syncookies = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 30
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_mem = 8388608 8388608 8388608
net.ipv4.tcp_rmem = 4096 87380 8388608
net.ipv4.tcp_wmem = 4096 65536 8388608
net.ipv4.route.flush = 1
net.ipv4.ip_local_port_range = 1024 65000
net.core.rmem_max = 16777216
net.core.rmem_default = 16777216
net.core.wmem_max = 8388608
net.core.wmem_default = 65536
net.core.netdev_max_backlog = 262144
net.core.somaxconn = 4096
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2

ACTUALIZACIÓN 2011 12 12 GMT 22:49

Estoy usando blitz.iopara ejecutar todas las pruebas. La URL que estoy probando es http://dev.anuary.com/test.txt , usando el siguiente comando:--region ireland --pattern 200-250:30 -T 1000 http://dev.anuary.com/test.txt

ACTUALIZACIÓN 2011 12 13 GMT 13:33

nginxlímites de usuario (establecidos /etc/security/limits.conf).

nginx       hard nofile 40000
nginx       soft nofile 40000
Guy
fuente
¿Estás organizando esto tú mismo? ¿No hay balanceadores de carga o algo así frente al servidor? ¿Algo del ISP que pueda detectarlo como un ataque DDoS y reducirlo?
Bart Silverstrim
Sí, este es mi servidor. ovh.co.uk/dedicated_servers/eg_ssd.xml Nada que pueda frenar el ataque DDoS. También he aumentado worker_processesa 4.
Gajus
Acabo de contactar a OVH para verificar que no haya valores de nivel de red implementados en mi servidor. No, no las hay.
Gajus
¿Qué tipo de datos está sirviendo de esto? html, imágenes, etc.
pablo
1
Creo que sería útil ejecutar un punto de referencia local para descartar la configuración de nginx. Tu no?
3molo

Respuestas:

2

Deberá volcar sus conexiones de red durante la prueba. Si bien el servidor puede tener una carga casi nula, su pila TCP / IP podría estar facturando. Busque las conexiones TIME_WAIT en una salida netstat.

Si este es el caso, entonces querrá verificar el ajuste de los parámetros del kernel tcp / ip relacionados con los estados de espera de TCP, el reciclaje de TCP y métricas similares.

Además, no ha descrito lo que se está probando.

Siempre pruebo:

  • contenido estático (imagen o archivo de texto)
  • página php simple (phpinfo por ejemplo)
  • página de aplicación

Esto puede no aplicarse en su caso, pero es algo que hago cuando se realizan pruebas de rendimiento. Probar diferentes tipos de archivos puede ayudarlo a identificar el cuello de botella.

Incluso con contenido estático, también es importante probar diferentes tamaños de archivos para obtener tiempos de espera y otras métricas marcadas.

Tenemos algunas cajas Nginx de contenido estático que manejan más de 3000 conexiones activas. Entonces Nginx ciertamente puede hacerlo.

Actualización: su netstat muestra muchas conexiones abiertas. Puede intentar ajustar su pila TCP / IP. Además, ¿qué archivo estás solicitando? Nginx debería cerrar rápidamente el puerto.

Aquí hay una sugerencia para sysctl.conf:

net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.tcp_rmem = 4096 87380 8388608
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 30
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1

Estos valores son muy bajos, pero he tenido éxito con ellos en cajas Nginx de alta concurrencia.

jeffatrackaid
fuente
Ver elUPDATE 2011 12 09 GMT 17:36.
Gajus
agregado actualizado a la respuesta principal debido al código.
jeffatrackaid
agregue la salida superior completa durante la prueba, no debe verificar solo la cantidad de CPU nginx está utilizando.
Giovanni Toraldo
1
tenga cuidado al usar net.ipv4.tcp_tw_recycle = 1, en general: no es una buena idea. reutilizar está bien aunque.
anónimo uno
¿Por qué no usar el socket de Linux en lugar de localhost?
BigSack 05 de
1

Otra hipótesis más. Ha aumentado worker_rlimit_nofile, pero el número máximo de clientes se define en la documentación como

max_clients = worker_processes * worker_connections

¿Qué pasa si intentas subir worker_connectionsa, como, 8192? O, si hay suficientes núcleos de CPU, worker_processes¿ aumentar ?

minaev
fuente
1

Estaba teniendo un problema muy similar con un nginx box que funcionaba como equilibrador de carga con un servidor ascendente de servidores apache.

En mi caso, pude aislar el problema de estar relacionado con la red a medida que los servidores apache ascendentes se sobrecargaban. Podría recrearlo con simples secuencias de comandos bash mientras el sistema general estaba bajo carga. Según una secuencia de uno de los procesos bloqueados, la llamada de conexión estaba recibiendo un ETIMEDOUT.

Esta configuración (en los servidores nginx y upstream) eliminó el problema para mí. Estaba obteniendo 1 o 2 tiempos de espera por minuto antes de hacer estos cambios (cajas que manejan ~ 100 requisitos / s) y ahora obtengo 0.

net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_fin_timeout = 20
net.ipv4.tcp_max_syn_backlog = 20480
net.core.netdev_max_backlog = 4096
net.ipv4.tcp_max_tw_buckets = 400000
net.core.somaxconn = 4096

No recomendaría usar net.ipv4.tcp_tw_recycle o net.ipv4.tcp_tw_reuse, pero si quieres usar uno, ve con el último. Pueden causar problemas extraños si hay algún tipo de latencia y este último es al menos el más seguro de los dos.

Creo que tener tcp_fin_timeout configurado en 1 arriba también puede estar causando algunos problemas. Intente ponerlo a 20/30, aún muy por debajo del valor predeterminado.

gtuhl
fuente
0

tal vez no sea un problema nginx, mientras pruebas en blitz.io haz un:

tail -f /var/log/php5-fpm.log

(eso es lo que estoy usando para manejar el php)

Esto desencadena un error y los tiempos de espera comienzan a aumentar:

WARNING: [pool www] server reached pm.max_children setting (5), consider raising it

entonces, ¡pon más max_children en fmp conf y listo! ;RE

revs jipipayo
fuente
El problema es el mismo si tengo return 200 "test"en NGINX. Esto significa que NGINX ni siquiera llega a llamar a PHP-FPM.
Gajus
0

Tiene demasiado bajo max open files(1024), intente cambiar y reiniciar nginx. ( cat /proc/<nginx>/limitspara confirmar)

ulimit -n 10240

Y aumentar worker_connectionsa 10240 o superior.

usuario3368344
fuente
No estoy seguro de por qué esto ha sido rechazado. Suena como la respuesta correcta para mí.
Ryan Angilly