Zwrotny serwer proxy Nginx powodujący przekroczenie limitu czasu bramy 504

129

Używam Nginx jako zwrotnego proxy, które przyjmuje żądania, a następnie wykonuje proxy_pass, aby pobrać rzeczywistą aplikację internetową z serwera nadrzędnego działającego na porcie 8001.

Jeśli przejdę do mywebsite.com lub zrobię wget, po 60 sekundach pojawia się limit czasu bramy 504 ... Jeśli jednak załaduję mywebsite.com:8001, aplikacja ładuje się zgodnie z oczekiwaniami!

Więc coś uniemożliwia Nginx komunikację z serwerem nadrzędnym.

Wszystko zaczęło się po tym, jak moja firma hostingowa zresetowała komputer, na którym działały moje rzeczy, a wcześniej nie było żadnych problemów.

Oto mój blok serwera vhosts:

server {
    listen   80;
    server_name mywebsite.com;

    root /home/user/public_html/mywebsite.com/public;

    access_log /home/user/public_html/mywebsite.com/log/access.log upstreamlog;
    error_log /home/user/public_html/mywebsite.com/log/error.log;

    location / {
        proxy_pass http://xxx.xxx.xxx.xxx:8001;
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
} 

I dane wyjściowe z mojego dziennika błędów Nginx:

2014/06/27 13:10:58 [error] 31406#0: *1 upstream timed out (110: Connection timed out) while connecting to upstream, client: xxx.xx.xxx.xxx, server: mywebsite.com, request: "GET / HTTP/1.1", upstream: "http://xxx.xxx.xxx.xxx:8001/", host: "mywebsite.com"
Dave Roma
źródło
Czy na serwerze działa SELinux?
CrackerJack9
W MOIM PRZYPADKU problemem była brama NAT, a nie NGINX czy backend API. stackoverflow.com/a/62351959/9956279
Sushilinux

Odpowiedzi:

152

Prawdopodobnie można dodać kilka dodatkowych linii, aby wydłużyć czas oczekiwania na wysyłanie. Poniższe przykłady ustawiają limit czasu na 300 sekund:

proxy_connect_timeout       300;
proxy_send_timeout          300;
proxy_read_timeout          300;
send_timeout                300;
user2540984
źródło
5
Myślę, że zwiększenie limitu czasu rzadko jest odpowiedzią, chyba że wiesz, że Twoja sieć / usługa zawsze lub w niektórych przypadkach będzie reagować bardzo wolno. Obecnie niewiele żądań internetowych powinno zająć więcej niż kilka sekund, chyba że
pobierasz
@Almund Myślałem o tym samym (prawie nie zawracałem sobie głowy próbowaniem tego), ale z jakiegoś powodu to po prostu działało dla mnie. (Wcześniej upłynął limit czasu po 60 sekundach, teraz odpowiedź jest natychmiastowa).
Dax Fohl
@Dax Fohl: To ciekawe. Ściągnąłem źródło i rzuciłem okiem iz tego, co widzę, ustawienie dowolnego ustawienia proxy_ poza proxy_pass zainicjuje zestaw ustawień, które, jak przypuszczam, uruchomią proxy w inny sposób, więc może ustawienie czegokolwiek da to samo zachowanie.
Almund
Nie rozwiązałem problemu, używając go z serwerem
nodejs
3
Uważam, że potrzebuję tylko proxy_read_timeoutpodczas debugowania na zapleczu. dzięki!
Jeff Puckett
79

Zwiększenie limitu czasu prawdopodobnie nie rozwiąże problemu, ponieważ, jak powiedziałeś, rzeczywisty docelowy serwer WWW działa dobrze.

Miałem ten sam problem i stwierdziłem, że ma to związek z brakiem używania funkcji utrzymywania przy życiu w połączeniu. Właściwie nie mogę odpowiedzieć, dlaczego tak jest, ale podczas czyszczenia nagłówka połączenia rozwiązałem ten problem i żądanie zostało poprawnie przekazane przez serwer proxy:

server {
    location / {
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   Host      $http_host;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_pass http://localhost:5000;
    }
}

Spójrz na te posty, które wyjaśniają to bardziej szczegółowo: nginx zamknij połączenie z nadawcą po żądaniu Wyjaśnienie nagłówka Keep-alive http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive

Almund
źródło
7
MIESIĄCE problemów rozwiązanych przez jedną linię proxy_set_header Connection "";lol, nie używaj runcloud
nodws
22

user2540984 , a także wielu innych wskazało, że możesz spróbować zwiększyć ustawienia limitu czasu. Sam miałem podobny problem jak ten i próbowałem zmienić ustawienia limitu czasu w pliku /etc/nginx/nginx.conf , jak sugerują prawie wszyscy w tych wątkach. To jednak nie pomogło mi ani trochę; nie było widocznej zmiany w ustawieniach limitu czasu NGINX. Po wielu godzinach poszukiwań w końcu udało mi się rozwiązać mój problem.

Rozwiązanie znajduje się w tym wątku na forum i jest napisane, że powinieneś umieścić ustawienia limitu czasu w /etc/nginx/conf.d/timeout.conf (a jeśli ten plik nie istnieje, powinieneś go utworzyć). Użyłem tych samych ustawień co sugerowane w wątku:

proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
send_timeout 600;

To może nie być rozwiązaniem twojego konkretnego problemu, ale jeśli ktoś zauważy, że zmiana limitu czasu w /etc/nginx/nginx.conf nic nie robi, mam nadzieję, że ta odpowiedź pomoże!

Andreas Forslöw
źródło
cześć nie ma timeout.conf w moim katalogu config.d. Powiedziałeś, żeby go utworzyć, a ja chcę to potwierdzić, po prostu dodaj powyższe ustawienie w timeout.conf?
tktktk0711,
Tak, po prostu je dodaj. Możesz je modyfikować na własne potrzeby, ale te zadziałały!
Andreas Forslöw
Niestety w gospodarstwie Laravel z ubuntu i Nginx to nie działa. :( Czy masz na myśli tylko dodać te linie? Bez server{}czy czegoś innego? Ten błąd pojawia się zaraz po 5 minutach. Ponownie ładuję, uruchamiam ponownie i nigdy nie przekroczy tych 5 minut lub 300 sekund. Czy jest więcej pomysłów do naprawienia to?
Pathros
15

Jeśli chcesz wydłużyć lub dodać limit czasu do wszystkich witryn, możesz dodać poniższe wiersze do nginx.confpliku.

Dodaj poniższe wiersze do httpsekcji /usr/local/etc/nginx/nginx.conflub /etc/nginx/nginx.conffile.

fastcgi_read_timeout 600;
proxy_read_timeout 600;

Jeśli powyższe linie nie istnieją w confpliku, dodaj je, w przeciwnym razie zwiększ fastcgi_read_timeouti proxy_read_timeoutupewnij się, że nginx i php-fpm nie przekroczyły limitu czasu.

Aby zwiększyć limit czasu tylko dla jednej witryny, możesz edytować w vimie /etc/nginx/sites-available/example.com

location ~ \.php$ {
    include /etc/nginx/fastcgi_params;
        fastcgi_pass  unix:/var/run/php5-fpm.sock;
    fastcgi_read_timeout 300; 
}

a po dodaniu tych linii nginx.confnie zapomnij zrestartować nginx.

service php7-fpm reload 
service nginx reload

lub, jeśli używasz lokaja, po prostu wpisz valet restart.

Adeel
źródło
1
Dzięki dla mnie działa:fastcgi_read_timeout 600; proxy_read_timeout 600;
Alejandro
13

Możesz również stawić czoła tej sytuacji, jeśli twój serwer nadrzędny używa nazwy domeny, a jego adres IP zmienia się (np: twój serwer nadrzędny wskazuje na AWS Elastic Load Balancer)

Problem polega na tym, że nginx raz rozwiąże adres IP i zachowa go w pamięci podręcznej dla kolejnych żądań, dopóki konfiguracja nie zostanie ponownie załadowana.

Możesz powiedzieć nginx, aby użył serwera nazw do ponownego rozpoznania domeny po wygaśnięciu buforowanego wpisu:

location /mylocation {
    # use google dns to resolve host after IP cached expires
    resolver 8.8.8.8;
    set $upstream_endpoint http://your.backend.server/;
    proxy_pass $upstream_endpoint;
}

Dokumentacja na proxy_pass wyjaśnia, dlaczego ta sztuczka działa:

Wartość parametru może zawierać zmienne. W takim przypadku, jeśli adres jest określony jako nazwa domeny, nazwa ta jest przeszukiwana wśród opisanych grup serwerów, a jeśli nie zostanie znaleziona, jest określana za pomocą przelicznika.

Uznanie dla „Nginx z upstreams dynamicznych” (tenzer.dk) za szczegółowe wyjaśnienie, która zawiera również kilka istotnych informacji na zastrzeżenie tego podejścia w odniesieniu do przekazywanych URI.

el.atomo
źródło
1
ta odpowiedź jest złota, dokładnie to, co mi się przydarzyło. upstream wskazuje na aws elb i cały nagły limit czasu Gateway.
Nathan Do
2

Miałem ten sam problem. Okazało się, że było to spowodowane śledzeniem połączenia przez iptables na serwerze nadrzędnym. Po usunięciu --state NEW,ESTABLISHED,RELATEDze skryptu zapory i opróżnieniu z conntrack -Fproblemem zniknął.

mindlab
źródło
0

Sam NGINX może nie być główną przyczyną.

JEŚLI „minimalna liczba portów na instancję maszyny wirtualnej” ustawiona w bramie NAT - która znajduje się między instancją NGINX a proxy_passmiejscem docelowym - jest zbyt mała dla liczby jednoczesnych żądań, należy ją zwiększyć.

Rozwiązanie: Zwiększ dostępną liczbę portów na maszynę wirtualną w bramie NAT.

Kontekst W moim przypadku w Google Cloud odwrotny serwer proxy NGINX został umieszczony w podsieci z bramą NAT. Instancja NGINX przekierowywała żądania do domeny powiązanej z naszym zapleczem API (nadrzędnym) za pośrednictwem bramy NAT.

Ta dokumentacja z GCP pomoże Ci zrozumieć, w jaki sposób NAT jest powiązany z limitem czasu NGINX 504.

Sushilinux
źródło
-1

W moim przypadku ponownie uruchamiam php i wszystko jest w porządku.

Mahdy Aslamy
źródło