Błąd 502 Bad Gateway oznacza, że serwer działający jako brama lub proxy otrzymał nieprawidłową odpowiedź od serwera, który za nim stoi. Odwiedzający do czegoś dotarł, zwykle do nginx, Apache, load balancera albo CDN, ale ta warstwa nie dostała poprawnej odpowiedzi od Twojej aplikacji. Aplikacja uległa awarii, właśnie się restartuje, nasłuchuje pod innym adresem albo zamknęła połączenie w połowie.
Błąd 502 mówi więc o dwóch serwerach, a nie o jednym. W tym poradniku pokazujemy, jak ustalić, która warstwa go zwróciła, jak usunąć typowe przyczyny i jak dowiedzieć się o kolejnym błędzie 502, zanim zauważą go Twoi klienci.
Co mówi Ci błąd 502
Większość stron internetowych ma co najmniej dwie warstwy między odwiedzającym a kodem. Na froncie stoi CDN lub load balancer, serwer WWW, taki jak nginx, obsługuje połączenie, a proces aplikacji, na przykład PHP-FPM, Node.js, Gunicorn lub serwer Javy, buduje stronę. Każda warstwa przekazuje żądanie dalej i odsyła odpowiedź z powrotem.
Błąd 502 pojawia się, gdy jedna z tych warstw przekaże żądanie i nie dostanie z powrotem niczego użytecznego. Porównaj go z innymi błędami bramy:
502 Bad Gateway: serwer upstream odpowiedział czymś nieprawidłowym, zresetował połączenie albo je odrzucił.
503 Service Unavailable: usługa jest przeciążona, trwa konserwacja albo nie ma sprawnego serwera, do którego można wysłać żądanie.
504 Gateway Timeout: serwer upstream nie odpowiedział na czas.
Błąd 502 zwykle oznacza więc, że coś jest zepsute lub nie działa, a 504 – że działa zbyt wolno. Nasza ściąga z kodami statusu HTTP opisuje resztę rodziny, a poradnik o błędach 503 omawia przeciążenie i konserwację.
Znajdź warstwę, która zwróciła błąd 502
Zanim cokolwiek zmienisz, ustal, kto odpowiedział. Strona błędu i nagłówki odpowiedzi zwykle mówią to wprost:
curl -sI https://www.example.com/checkout
HTTP/2 502
server: cloudflare
cf-ray: 8d2f1c3a5b7e4a21-ARN
server: cloudflare ze stroną błędu Cloudflare wskazującą Twój host: Cloudflare dotarł do Twojego serwera źródłowego, a ten zawiódł.
server: nginx lub Apache ze zwykłą stroną błędu: Twój własny serwer WWW nie mógł dotrzeć do aplikacji, która za nim stoi.
server: awselb/2.0 lub inny load balancer: load balancer nie dostał poprawnej odpowiedzi od żadnego celu albo od tego, który wybrał.
Następnie porównaj wynik z żądaniem, które omija zewnętrzną warstwę. Wyślij je bezpośrednio do serwera źródłowego albo na port aplikacji na samym serwerze:
curl -sI –resolve www.example.com:443:203.0.113.10 https://www.example.com/checkout
curl -sI http://127.0.0.1:3000/checkout
Jeśli aplikacja odpowiada lokalnie, ale nie przez proxy, przyjrzyj się konfiguracji proxy. Jeśli lokalnie też nie odpowiada, problem leży w aplikacji.
Najczęstsze przyczyny i jak je naprawić
Proces aplikacji uległ awarii lub się restartuje
To najczęstsza przyczyna. Procesowi za proxy zabrakło pamięci, trafił na nieobsłużony wyjątek albo został zabity, a proxy nie ma z czym rozmawiać. nginx zapisuje to w logu bez ogródek:
connect() failed (111: Connection refused) while connecting to upstream,
upstream: „http://127.0.0.1:3000/checkout”
Sprawdź, czy proces działa i dlaczego się zatrzymał:
systemctl status myapp
journalctl -u myapp –since „30 min ago”
dmesg -T | grep -i „killed process”
Wpis od mechanizmu OOM killer jądra oznacza, że serwerowi zabrakło pamięci. Restart przywraca stronę, ale prawdziwym rozwiązaniem jest więcej pamięci, mniej workerów albo znaleziony i naprawiony wyciek. Zadbaj o to, by usługa sama się restartowała po awarii, na przykład przez Restart=on-failure w jej jednostce systemd.
PHP-FPM nie działa lub brakuje mu workerów
Na stronach w PHP nginx przekazuje żądania do PHP-FPM przez gniazdo lub port. Jeśli PHP-FPM jest zatrzymany, ścieżka gniazda jest błędna albo uprawnienia gniazda nie wpuszczają nginx, każda strona PHP zwraca 502:
connect() to unix:/run/php/php8.3-fpm.sock failed (2: No such file or directory)
Ten komunikat zwykle pojawia się po aktualizacji PHP: nginx wciąż wskazuje gniazdo starej wersji. Skieruj fastcgi_pass na nowe gniazdo i przeładuj nginx. Jeśli zamiast tego log mówi server reached pm.max_children, wszystkie workery są zajęte, często czekając na wolną bazę danych lub zewnętrzne API. Podnieś limit tylko wtedy, gdy serwer ma zapas pamięci; w przeciwnym razie znajdź to, co blokuje workery.
Błędny adres lub port upstream
Po migracji, przebudowie kontenera albo zmianie portu proxy może nadal przekazywać ruch pod stary adres. Log błędów pokazuje adres, którego próbowało. Porównaj go z miejscem, w którym aplikacja faktycznie nasłuchuje:
ss -ltnp | grep -E ’:(3000|8000|9000)’
W Dockerze i Kubernetesie przyczyną jest często nazwa usługi, która już się nie rozwiązuje, kontener nasłuchujący na 127.0.0.1 wewnątrz kontenera zamiast na 0.0.0.0 albo readiness check, który oznacza każdy pod jako niegotowy.
Upstream zbyt wcześnie zamknął połączenie
upstream prematurely closed connection while reading response header oznacza, że aplikacja przyjęła żądanie, a potem się rozłączyła. Typowe powody to awaria w trakcie obsługi żądania, worker zabity za przekroczenie własnego limitu czasu, takiego jak –timeout w Gunicornie lub max_execution_time w PHP, oraz połączenia keep-alive, które aplikacja zamyka wcześniej, niż spodziewa się proxy. Dopasuj limity czasu tak, by proxy czekało nieco dłużej niż aplikacja, nigdy odwrotnie, i sprawdź, które żądania są na tyle wolne, że dochodzą do limitu.
Zbyt duże nagłówki odpowiedzi
Duże ciasteczka lub wiele nagłówków Set-Cookie mogą przekroczyć bufor nginx na nagłówki odpowiedzi z upstreamu. nginx zapisuje wtedy w logu upstream sent too big header while reading response header from upstream i zwraca 502. Ostrożnie zwiększ bufory:
proxy_buffer_size 16k;
proxy_buffers 8 16k;
# for PHP-FPM
fastcgi_buffer_size 32k;
fastcgi_buffers 8 16k;
Potem ustal, dlaczego nagłówki urosły. Ciasteczko, które rośnie przy każdej wizycie, to błąd wart naprawienia.
CDN nie może połączyć się z serwerem źródłowym
Gdy błąd 502 zwraca CDN lub load balancer, sprawdź, co znajduje się między nim a Twoim serwerem. Zapora blokująca zakresy adresów CDN, certyfikat serwera źródłowego, którego CDN nie akceptuje, serwer źródłowy obsługujący tylko HTTP/1.0 lub zbyt pochopnie zamykający połączenia albo rekord DNS wskazujący stary serwer – wszystko to kończy się tak samo. Przetestuj serwer źródłowy bezpośrednio, jak pokazano wyżej, i sprawdź zaporę oraz ustawienia TLS po obu stronach.
Błędy 502 podczas wdrożeń
Jeśli błędy 502 pojawiają się na dziesięć lub dwadzieścia sekund i zawsze w okolicach wydania, powoduje je samo wdrożenie. Stary proces się zatrzymuje, nowy potrzebuje kilku sekund na start, a każde żądanie w tym czasie kończy się błędem. Rozwiązaniem jest taka kolejność wydania, w której zawsze coś jest gotowe do odpowiedzi:
Uruchom nową wersję obok starej.
Poczekaj, aż przejdzie health check. Nasz poradnik o budowie endpointu health check pokazuje, co taki test powinien sprawdzać.
Przełącz ruch na nową wersję.
Pozwól starej wersji dokończyć obsługiwane żądania, a potem ją zatrzymaj.
Menedżery procesów i orkiestratory obsługują to jako przeładowania typu rolling lub zero-downtime. Korzystaj z nich zamiast zwykłego restartu.
Jak monitorowanie wychwytuje błędy 502
Błąd 502 często trwa krótko. Wdrożenie powoduje dwadzieścia sekund błędów, worker pada i się restartuje, cache ukrywa problem przed większością odwiedzających. Zanim ktoś otworzy stronę, ta znów działa, ale klient w trakcie zakupu zobaczył błąd.
Monitor dostępności odpytuje Twoje strony według harmonogramu i zapisuje kod statusu oraz czas odpowiedzi każdego sprawdzenia. Błąd 502 to nieudane sprawdzenie. Liczy się to, co dzieje się potem:
Potwierdź awarię. Pojedyncze nieudane żądanie może być chwilowym zakłóceniem. Uptimecheck sprawdza nawet co minutę ze Sztokholmu, Londynu i Nowego Jorku i potwierdza każdą awarię z drugiej lokalizacji, zanim otworzy incydent, więc jednorazowy reset nikogo nie budzi.
Pokaż dowody. Incydent zawiera nieudaną odpowiedź, więc widzisz kod statusu, nagłówek server i stronę błędu, a także zrzut ekranu tego, co zobaczyli odwiedzający. Gdy serwer w ogóle nie odpowiedział, dostajesz zamiast tego ścieżkę sieciową.
Powiadom właściwe osoby. Alerty trafiają na e-mail, do Slacka, Microsoft Teams, PagerDuty, webhooków i innych kanałów alertów, z których korzysta Twój zespół.
Obserwuj nie tylko stronę główną. Często jest ona cache’owana przez CDN i działa dalej, gdy koszyk, logowanie i API zwracają 502. Dodaj monitory dostępności dla stron, które zarabiają, i monitory API dla endpointów wywoływanych przez Twoje aplikacje. Gdy błąd 502 pochodzi z aplikacji, której zabrakło pamięci, monitorowanie serwera pokazuje wykres pamięci obok awarii.
Lista kontrolna dla błędu 502
Przeczytaj nagłówek server i stronę błędu, aby ustalić, która warstwa zwróciła 502.
Wyślij żądanie bezpośrednio do serwera źródłowego i na port aplikacji, aby zawęzić poszukiwania.
Przeczytaj log błędów proxy z tego samego momentu: odrzucone, zbyt wcześnie zamknięte czy zbyt duży nagłówek.
Sprawdź, czy proces aplikacji działa, a jeśli nie – dlaczego się zatrzymał.
Porównaj adres upstream, gniazdo i port z miejscem, w którym nasłuchuje aplikacja.
Dopasuj limity czasu tak, by proxy czekało dłużej niż aplikacja.
Wdrażaj, uruchamiając nową wersję przed zatrzymaniem starej.
Monitoruj kluczowe strony i endpointy co minutę i potwierdzaj każdą awarię przed wysłaniem alertu.