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"

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;

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


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!


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.


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.


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ął.


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.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.