Chcesz zwiększyć przepustowość nginx do upstreamowego gniazda unix - tuning jądra Linuksa?

28

Korzystam z serwera nginx, który działa jako serwer proxy do nadrzędnego gniazda unix, w następujący sposób:

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

Niektóre procesy serwera aplikacji z kolei pobierają żądania, /tmp/app.sockgdy stają się dostępne. Konkretnym serwerem aplikacji, który jest tutaj używany, jest Unicorn, ale nie sądzę, żeby miało to związek z tym pytaniem.

Problem polega na tym, że po prostu wydaje się, że po pewnym obciążeniu nginx nie może odbierać żądań przez gniazdo z wystarczającą szybkością. Nie ma znaczenia, ile procesów serwera aplikacji skonfigurowałem.

Dostaję zalew tych wiadomości w dzienniku błędów nginx:

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

Wiele żądań powoduje kod stanu 502 i te, których wypełnienie nie zajmuje dużo czasu. Statystyki kolejki zapisu nginx oscylują wokół 1000.

W każdym razie wydaje mi się, że brakuje mi czegoś oczywistego, ponieważ ta szczególna konfiguracja nginx i serwera aplikacji jest dość powszechna, szczególnie w przypadku Unicorn (jest to zalecana metoda). Czy są jakieś opcje jądra Linuksa, które należy ustawić, czy coś w Nginx? Wszelkie pomysły na temat zwiększenia przepustowości do gniazda upstream? Coś, co wyraźnie robię źle?

Dodatkowe informacje o środowisku:

$ 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

Aktualne poprawki jądra:

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

Ustawienia Ulimit dla użytkownika 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
źródło
Czy sprawdziłeś wyjście ulimitkonkretnej liczby otwartych plików?
Khaled
@Khaled, ulimit -nmówi 65535.
Ben Lee,

Odpowiedzi:

16

Wygląda na to, że wąskim gardłem jest aplikacja zasilająca gniazdo, a nie sama Nginx. Widzimy to bardzo często w przypadku PHP w połączeniu z gniazdami w porównaniu do połączenia TCP / IP. W naszym przypadku jednak wąskie gardła w PHP znacznie wcześniej niż Nginx.

Czy sprawdziłeś limit śledzenia połączenia sysctl.conf, limit zaległości gniazd

  • net.core.somaxconn
  • net.core.netdev_max_backlog
Ben Lessani - Sonassi
źródło
2
Zrozumiałem problem. Zobacz odpowiedź, którą opublikowałem. Tak naprawdę to było wąskie gardło w aplikacji, a nie gniazdo, tak jak zakładasz. Wykluczyłem to wcześniej z powodu błędnej diagnozy, ale okazało się, że problemem była przepustowość na innym serwerze. Zrozumiałem to zaledwie kilka godzin temu. Przyznam ci nagrodę, ponieważ właściwie przybiłeś źródło problemu, nawet pomimo błędnej diagnozy, którą postawiłem w pytaniu; jednak zaznaczę zaznaczenie mojej odpowiedzi, ponieważ moja odpowiedź opisuje dokładne okoliczności, więc może pomóc komuś w przyszłości z podobnym problemem.
Ben Lee,
Przeniesiono nowy serwer do lokalizacji, aby zapewnić odpowiednią przepustowość, całkowicie przebudowano system i nadal występuje ten sam problem. Więc okazuje się, że mój problem nie został rozwiązany ... = (Nadal uważam, że jest on specyficzny dla aplikacji, ale nic nie może wymyślić. Ten nowy serwer jest skonfigurowany dokładnie tak, jak inny serwer, na którym działa dobrze. Tak, somaxconn i netdev_max_backlog działa poprawnie
Ben Lee
Twój problem nie jest nginx, jest więcej niż zdolny - ale to nie znaczy, że możesz nie mieć nieuczciwych ustawień. Gniazda są szczególnie wrażliwe pod dużym obciążeniem, gdy limity nie są poprawnie skonfigurowane. Czy zamiast tego możesz wypróbować aplikację za pomocą tcp / ip?
Ben Lessani - Sonassi
ten sam problem z jeszcze gorszą wielkością przy użyciu tcp / ip (kolejka zapisu wspina się jeszcze szybciej). Mam jądro nginx / jednorożec / jądro, wszystkie skonfigurowane dokładnie tak samo (o ile wiem) na innej maszynie, a ta inna maszyna nie wykazuje tego problemu. (Mogę przełączać dns między dwiema maszynami, aby uzyskać test obciążenia rzeczywistego i mieć dns na 60-sekundowym ttl)
Ben Lee
Przepustowość między każdym komputerem a komputerem db jest teraz taka sama, a opóźnienie między nowym komputerem a komputerem db jest o około 30% większe niż między starym komputerem a db. Ale 30% więcej niż jedna dziesiąta milisekundy to nie problem.
Ben Lee
2

Można spróbować patrząc unix_dgram_qlen, zobacz docs proc . Chociaż może to skomplikować problem, wskazując więcej w kolejce? Musisz spojrzeć (netstat -x ...)

jmw
źródło
Jakieś postępy w tym zakresie?
jmw
1
Dzięki za pomysł, ale nie miało to żadnego znaczenia.
Ben Lee
0

Rozwiązałem problem, zwiększając liczbę zaległości w config / unicorn.rb ... Kiedyś miałem zaległości 64.

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

i otrzymywałem ten błąd:

 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"

Teraz zwiększyłem do 1024 i nie otrzymuję błędu:

 listen "/path/tmp/sockets/manager_rails.sock", backlog: 1024
Adrian
źródło
0

tl; dr

  1. Upewnij się, że zaległości Unicorn są duże (używaj gniazd szybciej niż TCP) listen("/var/www/unicorn.sock", backlog: 1024)
  2. Optymalizacja ustawień wydajności nginx , na przykładworker_connections 10000;

Dyskusja

Mieliśmy ten sam problem - aplikację Rails obsługiwaną przez Unicorn za odwrotnym proxy NGINX.

W dzienniku błędów Nginx otrzymywaliśmy takie linie:

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"

Po przeczytaniu innych odpowiedzi doszliśmy do wniosku, że winą może być Jednorożec, więc zwiększyliśmy zaległości, ale to nie rozwiązało problemu. Monitorowanie procesów serwera było oczywiste, że Unicorn nie otrzymywał żądań do pracy, więc NGINX wydawał się być wąskim gardłem.

Szukając ustawień NGINX do ulepszenia w nginx.conftym artykule na temat dostrajania wydajności, wskazałem kilka ustawień, które mogą wpłynąć na liczbę równoległych żądań, które NGINX może przetworzyć, w szczególności:

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
źródło