Precisa aumentar a taxa de transferência nginx para um soquete unix upstream - ajuste do kernel linux?

28

Estou executando um servidor nginx que atua como um proxy para um soquete unix upstream, assim:

upstream app_server {
        server unix:/tmp/app.sock fail_timeout=0;
}

server {
        listen ###.###.###.###;
        server_name whatever.server;
        root /web/root;

        try_files $uri @app;
        location @app {
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header Host $http_host;
                proxy_redirect off;
                proxy_pass http://app_server;
        }
}

Alguns processos do servidor de aplicativos, por sua vez, retiram as solicitações /tmp/app.sockassim que ficam disponíveis. O servidor de aplicativos específico em uso aqui é o Unicorn, mas não acho relevante para esta pergunta.

A questão é que parece que após uma certa quantidade de carga, o nginx não pode obter solicitações através do soquete a uma taxa suficientemente rápida. Não importa quantos processos do servidor de aplicativos eu configurei.

Estou recebendo uma enxurrada dessas mensagens no log de erros do nginx:

connect() to unix:/tmp/app.sock failed (11: Resource temporarily unavailable) while connecting to upstream

Muitas solicitações resultam no código de status 502 e aquelas que não demoram muito para serem concluídas. O status da fila de gravação nginx fica em torno de 1000.

De qualquer forma, sinto que estou perdendo algo óbvio aqui, porque essa configuração específica do nginx e do servidor de aplicativos é bastante comum, especialmente no Unicorn (é o método recomendado de fato). Existem opções de kernel do linux que precisam ser definidas ou algo no nginx? Alguma idéia de como aumentar a taxa de transferência para o soquete upstream? Algo que eu claramente estou fazendo errado?

Informações adicionais sobre o meio ambiente:

$ uname -a
Linux servername 2.6.35-32-server #67-Ubuntu SMP Mon Mar 5 21:13:25 UTC 2012 x86_64 GNU/Linux

$ ruby -v
ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux]

$ unicorn -v
unicorn v4.3.1

$ nginx -V
nginx version: nginx/1.2.1
built by gcc 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
TLS SNI support enabled

Ajustes atuais do kernel:

net.core.rmem_default = 65536
net.core.wmem_default = 65536
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.tcp_mem = 16777216 16777216 16777216
net.ipv4.tcp_window_scaling = 1
net.ipv4.route.flush = 1
net.ipv4.tcp_no_metrics_save = 1
net.ipv4.tcp_moderate_rcvbuf = 1
net.core.somaxconn = 8192
net.netfilter.nf_conntrack_max = 524288

Configurações ilimitadas para o usuário nginx:

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 20
file size               (blocks, -f) unlimited
pending signals                 (-i) 16382
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 65535
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) unlimited
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
Ben Lee
fonte
Você verificou a saída ulimit, especificamente do número de arquivos abertos?
Khaled
@ Khaled, ulimit -ndiz 65535.
Ben Lee

Respostas:

16

Parece que o gargalo é o aplicativo que liga o soquete ao invés de ser o próprio Nginx. Vemos isso muito com o PHP quando usado com soquetes versus uma conexão TCP / IP. No nosso caso, os gargalos do PHP muito mais cedo do que o Nginx jamais o faria.

Você verificou o limite de rastreamento da conexão sysctl.conf, o limite de pendências de soquete

  • net.core.somaxconn
  • net.core.netdev_max_backlog
Ben Lessani - Sonassi
fonte
2
Eu descobri o problema. Veja a resposta que eu postei. Na verdade, era o gargalo do aplicativo, não o soquete, exatamente como você acredita. Eu havia descartado isso antes devido a um diagnóstico incorreto, mas o problema foi na transferência para outro servidor. Descobri isso apenas algumas horas atrás. Vou lhe dar a recompensa, já que você acertou em cheio a fonte do problema, apesar do diagnóstico errado que fiz na pergunta; no entanto, vou marcar a minha resposta, porque ela descreve as circunstâncias exatas para ajudar alguém no futuro com um problema semelhante.
Ben Lee
Um novo servidor foi movido para um local para fornecer taxa de transferência adequada, reconstruir completamente o sistema e ainda ter o mesmo problema. Afinal, afinal, meu problema não foi resolvido ... = (ainda acho que é específico do aplicativo, mas não consigo pensar em nada. Este novo servidor é configurado exatamente como outro servidor em que está funcionando bem. Sim, somaxconn e netdev_max_backlog estão corretamente configurados #
Ben Lee
Seu problema não é nginx, é mais do que capaz - mas isso não quer dizer que você pode não ter uma configuração não autorizada. Os soquetes são particularmente sensíveis sob alta carga quando os limites não estão configurados corretamente. Você pode experimentar seu aplicativo com tcp / ip?
Ben Lessani - Sonassi
mesmo problema com magnitude ainda pior usando tcp / ip (a fila de gravação aumenta ainda mais rapidamente). Eu tenho o nginx / unicorn / kernel todos configurados exatamente da mesma forma (até onde eu sei) em uma máquina diferente e essa outra máquina não está exibindo esse problema. (Eu posso mudar dns entre as duas máquinas, para obter o teste de carga ao vivo, e tem dns em um ttl de 60 seg)
Ben Lee
A taxa de transferência entre cada máquina e uma máquina de banco de dados é a mesma agora e a latência entre a nova máquina e a máquina de banco de dados é cerca de 30% mais do que entre a máquina antiga e o banco de dados. Mas 30% a mais que um décimo de milissegundo não é o problema.
Ben Lee
2

Você pode tentar unix_dgram_qlenver, consulte proc docs . Embora isso possa agravar o problema, apontando mais na fila? Você terá que procurar (netstat -x ...)

jmw
fonte
Algum progresso com isso?
perfil completo de jmw
1
Obrigado pela ideia, mas isso não pareceu fazer nenhuma diferença.
Ben Lee
0

Eu resolvi aumentando o número da lista de pendências no config / unicorn.rb ... Eu costumava ter uma lista de pendências de 64.

 listen "/path/tmp/sockets/manager_rails.sock", backlog: 64

e eu estava recebendo este erro:

 2014/11/11 15:24:09 [error] 12113#0: *400 connect() to unix:/path/tmp/sockets/manager_rails.sock failed (11: Resource temporarily unavailable) while connecting to upstream, client: 192.168.101.39, server: , request: "GET /welcome HTTP/1.0", upstream: "http://unix:/path/tmp/sockets/manager_rails.sock:/welcome", host: "192.168.101.93:3000"

Agora, aumentei para 1024 e não recebi o erro:

 listen "/path/tmp/sockets/manager_rails.sock", backlog: 1024
Adrian
fonte
0

tl; dr

  1. Verifique se o backlog do Unicorn é grande (use soquete, mais rápido que o TCP) listen("/var/www/unicorn.sock", backlog: 1024)
  2. Otimize as configurações de desempenho do NGINX , por exemploworker_connections 10000;

Discussão

Tivemos o mesmo problema - um aplicativo Rails servido pelo Unicorn atrás de um proxy reverso NGINX.

Estávamos recebendo linhas como estas no log de erros do Nginx:

2019/01/29 15:54:37 [error] 3999#3999: *846 connect() to unix:/../unicorn.sock failed (11: Resource temporarily unavailable) while connecting to upstream, client: xx.xx.xx.xx, request: "GET / HTTP/1.1"

Lendo as outras respostas, também descobrimos que talvez o culpado seja o Unicorn, então aumentamos a lista de pendências, mas isso não resolveu o problema. Ao monitorar os processos do servidor, era óbvio que o Unicorn não estava recebendo as solicitações para trabalhar, portanto o NGINX parecia ser o gargalo.

A pesquisa de configurações do NGINX para ajustar nginx.confneste artigo de ajuste de desempenho apontou várias configurações que podem afetar o número de solicitações paralelas que o NGINX pode processar, especialmente:

user www-data;
worker_processes auto;
pid /run/nginx.pid;
worker_rlimit_nofile 400000; # important

events {    
  worker_connections 10000; # important
  use epoll; # important
  multi_accept on; # important
}

http {
  sendfile on;
  tcp_nopush on;
  tcp_nodelay on;
  keepalive_timeout 65;
  types_hash_max_size 2048;
  keepalive_requests 100000; # important
  server_names_hash_bucket_size 256;
  include /etc/nginx/mime.types;
  default_type application/octet-stream;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_prefer_server_ciphers on;
  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log;
  gzip on;
  gzip_disable "msie6";
  include /etc/nginx/conf.d/*.conf;
  include /etc/nginx/sites-enabled/*;
}
Epigene
fonte