Timeout NGINX dopo +200 connessioni simultanee


12

Questo è il mio nginx.conf(ho aggiornato la configurazione per assicurarmi che non ci siano PHP coinvolti o altri colli di bottiglia):

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";
    }
}

Sto usando http://blitz.io/play per testare il mio server (ho acquistato il piano di connessioni simultanee da 10.000). In 30 secondi, ottengo 964colpi e 5,587 timeouts. Il primo timeout si è verificato a 40,77 secondi nel test quando il numero di utenti simultanei era a 200.

Durante il test, il carico del server era ( topoutput):

 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      

Pertanto non si tratta di un problema con le risorse del server. Quindi cos'è?

AGGIORNAMENTO 2011 12 09 GMT 17:36.

Finora ho apportato le seguenti modifiche per assicurarmi che il collo di bottiglia non sia TCP / IP. Aggiunto 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

Altre informazioni di debug:

[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 Questo worker_rlimit_nofileè impostato su 10240nginx config.

AGGIORNAMENTO 2011 12 09 GMT 19:02.

Sembra che più cambiamenti faccio, peggio diventa, ma qui il nuovo file di configurazione.

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;
}

AGGIORNAMENTO 2011 12 11 GMT 20:11.

Questo viene emesso netstat -ntladurante il test.

https://gist.github.com/d74750cceba4d08668ea

AGGIORNAMENTO 2011 12 12 GMT 10:54.

Giusto per chiarire, il iptables(firewall) è spento durante il test.

AGGIORNAMENTO 2011 12 12 GMT 22:47.

Questa è la sysctl -p | grep memdiscarica.

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

AGGIORNAMENTO 2011 12 12 GMT 22:49

Sto usando blitz.ioper eseguire tutti i test. L'URL che sto testando è http://dev.anuary.com/test.txt , utilizzando il seguente comando:--region ireland --pattern 200-250:30 -T 1000 http://dev.anuary.com/test.txt

AGGIORNAMENTO 2011 12 13 GMT 13:33

nginxlimiti utente (impostato in /etc/security/limits.conf).

nginx       hard nofile 40000
nginx       soft nofile 40000

Lo stai ospitando da solo? Nessun bilanciamento del carico o qualcosa del genere di fronte al server? Qualcosa dell'ISP che potrebbe rilevarlo come un attacco DDoS e farlo precipitare?
Bart Silverstrim,

Sì, questo è il mio server. ovh.co.uk/dedicated_servers/eg_ssd.xml Niente che possa rallentare l'attacco DDoS. Ho anche aumentato worker_processesa 4.
Gajus,

Ho appena contattato OVH per ricontrollare che non ci siano titoli a livello di rete implementati sul mio server. No non ci sono.
Gajus,

che tipo di dati stai fornendo da questo? HTML, immagini, ecc?
pablo,

1
Penso che sarebbe utile eseguire un benchmark locale per escludere la configurazione di nginx. No?
3

Risposte:


2

Dovrai scaricare le connessioni di rete durante il test. Mentre il server può avere un carico quasi zero, lo stack TCP / IP potrebbe essere fatturato. Cerca connessioni TIME_WAIT in un output netstat.

In questo caso, ti consigliamo di verificare i parametri del kernel tcp / ip relativi agli stati di attesa TCP, al recyling TCP e a metriche simili.

Inoltre, non hai descritto cosa viene testato.

Metto sempre alla prova:

  • contenuto statico (immagine o file di testo)
  • semplice pagina php (phpinfo per esempio)
  • pagina dell'applicazione

Questo potrebbe non essere applicabile nel tuo caso, ma è qualcosa che faccio quando collaudo le prestazioni. Testare diversi tipi di file può aiutarti a individuare il collo di bottiglia.

Anche con contenuto statico, è importante anche testare file di dimensioni diverse per ottenere timeout e altre metriche.

Abbiamo alcune scatole Nginx con contenuto statico che gestiscono oltre 3000 connessioni attive. Quindi Nginx può certamente farlo.

Aggiornamento: il tuo netstat mostra molte connessioni aperte. Potrebbe essere utile provare a ottimizzare lo stack TCP / IP. Inoltre, quale file stai richiedendo? Nginx dovrebbe chiudere rapidamente la porta.

Ecco un suggerimento per 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

Questi valori sono molto bassi ma ho avuto successo con loro su scatole Nginx ad alta concorrenza.


VediUPDATE 2011 12 09 GMT 17:36.
Gajus il

aggiunto aggiornato alla risposta principale a causa del codice.
jeffatrackaid,

per favore aggiungi l'output completo completo durante il test, non dovresti controllare solo quanta CPU nginx sta usando.
Giovanni Toraldo,

1
fai attenzione quando usi net.ipv4.tcp_tw_recycle = 1, in generale: non è una buona idea. il riutilizzo è ok comunque.
anonimo-

Perché non usare il socket Linux invece di localhost?
BigSack

1

Ancora un'altra ipotesi. È stato aumentato worker_rlimit_nofile, ma il numero massimo di client è definito nella documentazione come

max_clients = worker_processes * worker_connections

E se provi a rilanciare worker_connectionsa, come, 8192? Oppure, se ci sono abbastanza core della CPU, aumentare worker_processes?


1

Stavo avendo un problema molto simile con una scatola nginx che fungeva da bilanciamento del carico con un upstream di server Apache.

Nel mio caso sono stato in grado di isolare il problema da collegare in rete quando i server Apache upstream si sono sovraccaricati. Potrei ricrearlo con semplici script bash mentre il sistema generale era sotto carico. Secondo una serie di processi bloccati, la chiamata di connessione stava ottenendo un ETIMEDOUT.

Queste impostazioni (sui server nginx e upstream) mi hanno eliminato il problema. Stavo ricevendo 1 o 2 timeout al minuto prima di apportare queste modifiche (scatole che gestivano ~ 100 req / s) e ora ottenevo 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

Non consiglierei di usare net.ipv4.tcp_tw_recycle o net.ipv4.tcp_tw_reuse, ma se vuoi usarne uno vai con quest'ultimo. Possono causare problemi bizzarri se c'è qualche tipo di latenza e quest'ultimo è almeno il più sicuro dei due.

Penso che avere tcp_fin_timeout impostato su 1 sopra possa anche causare qualche problema. Prova a metterlo a 20/30 - ancora molto al di sotto del valore predefinito.


0

forse non è un problema di nginx, mentre test su blitz.io fai un:

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

(questo è quello che sto usando per gestire il php)

ciò genera un errore e i timeout iniziano a sollevare:

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

quindi, metti più max_children su fmp conf ed è fatto! ; D


Il problema è lo stesso se ho return 200 "test"in NGINX. Ciò significa che NGINX non arriva nemmeno a chiamare PHP-FPM.
Gajus,

0

Hai troppo basso max open files(1024), prova a cambiare e riavvia nginx. ( cat /proc/<nginx>/limitsper confermare)

ulimit -n 10240

E aumentare worker_connectionsa 10240 o superiore.


Non sono sicuro del motivo per cui questo è stato votato in negativo. Sembra la risposta giusta per me.
Ryan Angilly,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.