Tempo limite do NGINX após +200 conexões simultâneas

12

Este é o meu nginx.conf(atualizei a configuração para garantir que não haja PHP envolvido ou outros gargalos):

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

Estou usando o http://blitz.io/play para testar meu servidor (comprei o plano de 10.000 conexões simultâneas). Em uma corrida de 30 segundos, recebo 964hits e 5,587 timeouts. O primeiro tempo limite ocorreu aos 40,77 segundos no teste quando o número de usuários simultâneos estava em 200.

Durante o teste, a carga do servidor foi ( topsaída):

 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      

Portanto, não é um problema de recurso do servidor. Então o que é?

UPDATE 2011 12 09 GMT 17:36.

Até agora, fiz as seguintes alterações para garantir que o gargalo não seja TCP / IP. Adicionado 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

Mais algumas informações de depuração:

[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 Isso worker_rlimit_nofileestá definido como 10240nginx config.

UPDATE 2011 12 09 GMT 19:02.

Parece que quanto mais alterações eu faço, pior fica, mas aqui está o novo arquivo de configuração.

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

ATUALIZAÇÃO 2011 12 11 GMT 20:11.

Isso é produzido netstat -ntladurante o teste.

https://gist.github.com/d74750cceba4d08668ea

ATUALIZAÇÃO 2011 12 12 GMT 10:54.

Apenas para esclarecer, o iptables(firewall) está desativado durante o teste.

ATUALIZAÇÃO 12 12 GMT 22:47.

Este é o sysctl -p | grep memlixo.

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

ATUALIZAÇÃO 12 12 GMT 22:49

Estou usando blitz.iopara executar todos os testes. A URL que estou testando é http://dev.anuary.com/test.txt , usando o seguinte comando:--region ireland --pattern 200-250:30 -T 1000 http://dev.anuary.com/test.txt

ATUALIZAÇÃO 2011 12 13 GMT 13:33

nginxlimites de usuário (definidos /etc/security/limits.conf).

nginx       hard nofile 40000
nginx       soft nofile 40000
Guy
fonte
Você está hospedando isso sozinho? Não há balanceadores de carga ou algo parecido na frente do servidor? Algo do ISP que pode detectá-lo como um ataque DDoS e reduzi-lo?
Bart Silverstrim
Sim, este é o meu servidor. ovh.co.uk/dedicated_servers/eg_ssd.xml Nada que reduziria o ataque DDoS. Eu também aumentou worker_processespara 4.
Gajus
Acabei de entrar em contato com a OVH para verificar se não há nenhum nível de segurança de rede implementado no meu servidor. Não, não há.
Gajus
que tipo de dados você está servindo disso? html, imagens, etc?
Pablo 11/11
1
Eu acho que ajudaria a executar uma referência local para descartar a configuração do nginx. Não é?
3molo

Respostas:

2

Você precisará despejar suas conexões de rede durante o teste. Embora o servidor possa ter carga quase zero, sua pilha TCP / IP pode estar aumentando. Procure conexões TIME_WAIT em uma saída netstat.

Se for esse o caso, convém verificar os parâmetros do kernel do tcp / ip de ajuste relacionados aos estados de espera do TCP, reciclagem do TCP e métricas semelhantes.

Além disso, você não descreveu o que está sendo testado.

Eu sempre testei:

  • conteúdo estático (arquivo de imagem ou texto)
  • página php simples (phpinfo por exemplo)
  • página da aplicação

Isso pode não se aplicar ao seu caso, mas é algo que faço nos testes de desempenho. Testar diferentes tipos de arquivos pode ajudá-lo a identificar o gargalo.

Mesmo com conteúdo estático, é importante testar diferentes tamanhos de arquivos para obter tempos limite e outras métricas discadas.

Temos algumas caixas Nginx de conteúdo estático que lidam com mais de 3000 conexões ativas. Portanto, o Nginx certamente pode fazê-lo.

Atualização: seu netstat mostra muitas conexões abertas. Pode querer tentar ajustar sua pilha TCP / IP. Além disso, qual arquivo você está solicitando? O Nginx deve fechar rapidamente a porta.

Aqui está uma sugestão para o 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

Esses valores são muito baixos, mas tive sucesso com eles em caixas Nginx de alta simultaneidade.

jeffatrackaid
fonte
Veja oUPDATE 2011 12 09 GMT 17:36.
Gajus
adicionado atualizado à resposta principal devido ao código.
jeffatrackaid
adicione a saída superior completa durante o teste; você não deve verificar apenas a quantidade de CPU que o nginx está usando.
Giovanni Toraldo
1
tenha cuidado ao usar net.ipv4.tcp_tw_recycle = 1, de um modo geral: não é uma boa ideia. reutilização é ok tho.
anonymous-one
Por que não usar o soquete do Linux em vez do localhost?
precisa saber é o seguinte
1

Mais uma hipótese. Você aumentou worker_rlimit_nofile, mas o número máximo de clientes é definido na documentação como

max_clients = worker_processes * worker_connections

E se você tentar aumentar worker_connectionspara, tipo, 8192? Ou, se houver núcleos de CPU suficientes, aumente worker_processes?

minaev
fonte
1

Eu estava tendo um problema muito semelhante com uma caixa nginx que servia como balanceador de carga com um servidor upstream de servidores apache.

No meu caso, consegui isolar o problema para estar relacionado à rede, pois os servidores apache upstream ficaram sobrecarregados. Eu poderia recriá-lo com scripts simples do bash enquanto o sistema geral estava sob carga. De acordo com um rastreio de um dos processos travados, a chamada de conexão estava recebendo um ETIMEDOUT.

Essas configurações (nos servidores nginx e upstream) eliminaram o problema para mim. Eu estava recebendo 1 ou 2 tempos limite por minuto antes de fazer essas alterações (caixas processando ~ 100 reqs / s) e agora recebo 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

Eu não recomendaria o uso de net.ipv4.tcp_tw_recycle ou net.ipv4.tcp_tw_reuse, mas se você quiser usar um, vá com o último. Eles podem causar problemas bizarros se houver algum tipo de latência e o último for pelo menos o mais seguro dos dois.

Acho que ter tcp_fin_timeout definido como 1 acima pode estar causando alguns problemas também. Tente colocá-lo em 20/30 - ainda muito abaixo do padrão.

gtuhl
fonte
0

talvez não seja um problema nginx, enquanto você testa no blitz.io, faça um:

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

(isso é o que eu estou usando para lidar com o php)

isso dispara um erro e o tempo limite começa a aumentar:

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

então, coloque mais max_children em fmp conf e pronto! ; D

jipipayo
fonte
O problema é o mesmo se eu tiver return 200 "test"no NGINX. Isso significa que o NGINX nem chega ao ponto de chamar PHP-FPM.
Gajus
0

Você tem muito baixo max open files(1024), tente alterar e reinicie o nginx. ( cat /proc/<nginx>/limitspara confirmar)

ulimit -n 10240

E aumente worker_connectionspara 10240 ou superior.

user3368344
fonte
Não sei ao certo por que isso foi rejeitado. Parece a resposta certa para mim.
Ryan Angilly