Müssen Sie den Nginx-Durchsatz für ein Upstream-Unix-Socket-Linux-Kernel-Tuning erhöhen?

28

Ich verwende einen Nginx-Server, der als Proxy für einen Upstream-Unix-Socket fungiert, wie folgt:

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

Einige App Server-Prozesse ziehen Anforderungen ab, sobald /tmp/app.socksie verfügbar sind. Der hier verwendete App-Server ist Unicorn, aber ich denke nicht, dass dies für diese Frage relevant ist.

Das Problem ist, es scheint nur, dass Nginx nach einer bestimmten Last keine Anfragen mehr schnell genug über den Socket erhalten kann. Es spielt keine Rolle, wie viele App Server-Prozesse ich eingerichtet habe.

Ich erhalte eine Flut dieser Meldungen im Nginx-Fehlerprotokoll:

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

Viele Anfragen führen zu Statuscode 502 und solchen, deren Fertigstellung nicht lange dauert. Die Nginx-Schreibwarteschlangen-Statistik liegt bei 1000.

Wie auch immer, ich habe das Gefühl, dass ich hier etwas Offensichtliches vermisse, da diese spezielle Konfiguration von Nginx und App Server ziemlich häufig ist, insbesondere bei Unicorn (es ist die empfohlene Methode). Gibt es irgendwelche Linux-Kernel-Optionen, die gesetzt werden müssen, oder etwas in Nginx? Irgendwelche Ideen, wie der Durchsatz zum Upstream-Socket erhöht werden kann? Etwas, das ich eindeutig falsch mache?

Zusätzliche Informationen zur Umwelt:

$ 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

Aktuelle Kernel-Optimierungen:

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

Ulimit-Einstellungen für den Nginx-Benutzer:

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
quelle
Haben Sie die Ausgabe überprüft ulimit, insbesondere die Anzahl der geöffneten Dateien?
Khaled
@ Khaled, ulimit -nsagt 65535.
Ben Lee,

Antworten:

16

Es hört sich so an, als ob der Engpass die App ist, die den Socket mit Strom versorgt, anstatt Nginx selbst zu sein. Wir sehen dies häufig bei PHP, wenn es mit Sockets im Vergleich zu einer TCP / IP-Verbindung verwendet wird. In unserem Fall sind PHP-Engpässe jedoch viel früher als Nginx.

Haben Sie das sysctl.conf-Limit für die Verbindungsverfolgung und das Socket-Backlog-Limit überprüft?

  • net.core.somaxconn
  • net.core.netdev_max_backlog
Ben Lessani - Sonassi
quelle
2
Ich habe das Problem herausgefunden. Siehe die Antwort, die ich gepostet habe. Es tatsächlich war die App Engpässen, nicht die Fassung, wie Sie postulieren. Ich hatte dies früher aufgrund einer Fehldiagnose ausgeschlossen, es stellte sich jedoch heraus, dass das Problem der Durchsatz auf einem anderen Server war. Hab das erst vor ein paar Stunden herausgefunden. Ich werde Ihnen das Kopfgeld gewähren, da Sie die Ursache des Problems trotz der Fehldiagnose, die ich in der Frage gestellt habe, ziemlich genau herausgefunden haben. Ich werde jedoch meine Antwort mit einem Häkchen versehen, da meine Antwort die genauen Umstände beschreibt, die jemandem in Zukunft bei einem ähnlichen Problem helfen könnten.
Ben Lee,
Es wurde ein neuer Server an einen Speicherort verschoben, um einen angemessenen Durchsatz zu gewährleisten, das System vollständig neu zu erstellen und dennoch das gleiche Problem zu haben. Es stellt sich also heraus, dass mein Problem immer noch ungelöst ist ... = (Ich denke immer noch, dass es app-spezifisch ist, aber mir fällt nichts ein. Dieser neue Server ist genauso eingerichtet wie ein anderer Server, auf dem es gut funktioniert. Ja, somaxconn und netdev_max_backlog sind st richtig
Ben Lee
Ihr Problem ist nicht Nginx, es ist mehr als fähig - aber das heißt nicht, dass Sie möglicherweise keine Schurkeneinstellung haben. Sockets sind unter hoher Last besonders empfindlich, wenn die Grenzwerte nicht richtig konfiguriert sind. Können Sie Ihre App stattdessen mit TCP / IP testen?
Ben Lessani - Sonassi
dasselbe problem mit einer noch schlechteren größe mit tcp / ip (schreibwarteschlange klettert noch schneller). Ich habe Nginx / Unicorn / Kernel auf einem anderen Computer genau gleich eingerichtet (soweit ich das beurteilen kann), und dieser andere Computer weist dieses Problem nicht auf. (Ich kann DNS zwischen den beiden Maschinen wechseln, um Live-Belastungstests zu erhalten und DNS auf einem 60-Sekunden-TTL zu haben.)
Ben Lee
Der Durchsatz zwischen jedem Computer und einem Datenbankcomputer ist jetzt derselbe, und die Latenz zwischen dem neuen Computer und dem Datenbankcomputer beträgt etwa 30% mehr als zwischen dem alten Computer und dem Datenbankcomputer. Aber 30% mehr als eine Zehntel-Millisekunde ist nicht das Problem.
Ben Lee
2

Sie könnten versuchen , auf der Suche unix_dgram_qlenfinden proc docs . Obwohl dies das Problem verschlimmern kann, indem Sie mehr in die Warteschlange zeigen? Du musst schauen (netstat -x ...)

jmw
quelle
Irgendwelche Fortschritte damit?
Jmw
1
Danke für die Idee, aber das schien keinen Unterschied zu machen.
Ben Lee
0

Ich habe das Problem gelöst, indem ich den Rückstand in der Datei config / unicorn.rb erhöht habe. Früher hatte ich einen Rückstand von 64.

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

und ich bekam diesen Fehler:

 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"

Jetzt habe ich auf 1024 erhöht und bekomme den Fehler nicht:

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

tl; dr

  1. Stellen Sie sicher, dass der Unicorn-Rückstand groß ist (verwenden Sie Socket, schneller als TCP) listen("/var/www/unicorn.sock", backlog: 1024)
  2. Optimieren NGINX Performance - Einstellungen , zum Beispielworker_connections 10000;

Diskussion

Wir hatten das gleiche Problem - eine Rails-App, die von Unicorn hinter einem NGINX-Reverse-Proxy bereitgestellt wurde.

Im Nginx-Fehlerprotokoll wurden folgende Zeilen angezeigt:

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"

Beim Lesen der anderen Antworten stellten wir auch fest, dass möglicherweise Unicorn die Schuld trägt, und erhöhten daher den Rückstand, was das Problem jedoch nicht löste. Beim Überwachen von Serverprozessen war es offensichtlich, dass Unicorn nicht die Anforderungen zum Arbeiten bekam, sodass NGINX der Engpass zu sein schien.

Bei der Suche nach NGINX-Einstellungen zur Optimierung in nginx.confdiesem Artikel zur Leistungsoptimierung wurden verschiedene Einstellungen aufgeführt, die sich auf die Anzahl der parallelen Anforderungen auswirken können, die NGINX verarbeiten kann.

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/*;
}
Epigen
quelle