Błąd 502 Bad Gateway oznacza, że reverse proxy dostało od serwera aplikacji odpowiedź, której nie umie przyjąć - albo nie dostało jej wcale. Zgłasza go proxy, nie aplikacja. Zacznij od testu upstreamu z przestrzeni sieciowej proxy i dopiero potem zmieniaj konfigurację.

Ta strona prowadzi diagnozę na serwerze, do którego masz dostęp. Jeśli 502 pokazuje ci cudza strona, możesz tylko ponowić żądanie za chwilę i zgłosić problem właścicielowi - naprawa leży po jego stronie.

Co oznacza błąd 502 Bad Gateway?

502 Bad Gateway to kod odpowiedzi HTTP, którym serwer pośredniczący - gateway albo reverse proxy - informuje, że otrzymał od serwera nadrzędnego odpowiedź nieprawidłową. Tak definiuje go RFC 9110 w sekcji 15.6.3. Kod pojawia się wyłącznie w architekturze, w której żądanie przechodzi przez pośrednika do aplikacji.

klient  ->  reverse proxy  ->  aplikacja (upstream)

Reverse proxy przyjmuje połączenie z internetu i przekazuje je do upstreamu, czyli procesu lub serwera, który generuje właściwą odpowiedź. Gdy widzisz 502, wiesz na pewno tylko jedno - proxy żyje i odpowiada. Nie wiesz jeszcze, czy zawiodła aplikacja, transport do niej, czy konfiguracja samego proxy. Upstream mógł się wyłączyć, słuchać pod innym adresem albo odpowiedzieć w sposób, którego proxy nie rozumie. Te przypadki rozdziela się testami i logami, nie zgadywaniem.

Typowy przebieg tej awarii wygląda tak: administrator wdraża w piątek nową wersję aplikacji. Kontener startuje bez błędu, w terminalu aplikacja odpowiada, a mimo to strona publiczna pokazuje 502. Restart nginx nic nie zmienia, restart aplikacji też nie. Po godzinie okazuje się, że nowa wersja nasłuchuje na innym porcie niż ten wpisany w konfiguracji proxy. Obie usługi były zdrowe - zepsuty był łącznik między nimi. Właśnie dlatego diagnozę zaczyna się od przetestowania tego łącznika, nie od restartów.

Szybka diagnoza w pięciu krokach

Kolejność ma znaczenie, bo zaczynasz od odczytu, nie od zmiany. Poprawka w konfiguracji proxy przed sprawdzeniem ścieżki do upstreamu potrafi dołożyć drugi problem do istniejącej awarii.

Krok 1. Sprawdź upstream z miejsca, z którego widzi go proxy

Odpytaj upstream bez pośrednictwa proxy, ale z jego przestrzeni sieciowej - wewnątrz kontenera proxy albo na jego hoście przy instalacji systemowej. Tylko ta perspektywa obejmuje DNS, trasę i reguły dostępu, które proxy naprawdę widzi. Schemat połączenia (HTTP czy HTTPS) przepisz z konfiguracji proxy, zanim wybierzesz komendę.

Upstream po HTTP:

curl -sv -H 'Host: HOST_UPSTREAMU' 'http://ADRES_UPSTREAMU:PORT_UPSTREAMU/SCIEZKA'

Upstream po HTTPS:

curl -sv --resolve 'NAZWA_TLS_UPSTREAMU:PORT_UPSTREAMU:ADRES_UPSTREAMU' \
  'https://NAZWA_TLS_UPSTREAMU:PORT_UPSTREAMU/SCIEZKA'

Różnica między wariantami nie jest kosmetyczna. Nagłówek Host ustawia tylko nazwę w żądaniu HTTP i nie trafia do rozszerzenia SNI podczas negocjacji TLS - przy upstreamie HTTPS taki test może wylądować na innym vhoście i innym certyfikacie niż ten, z którego korzysta proxy. Opcja --resolve wiąże nazwę z adresem i portem, więc SNI i Host niosą tę samą nazwę, a połączenie idzie dokładnie tam, gdzie chodzi ruch z proxy. Wartości placeholderów przepisz z konfiguracji proxy i odtwórz metodę oraz istotne nagłówki żądania, które kończyło się błędem.

Wynik czytaj tak:

  • oczekiwana odpowiedź HTTP - trasa z proxy do upstreamu działa dla tego żądania; szukaj dalej w logu proxy (krok 4);
  • odmowa połączenia - upstream odrzuca połączenie; przejdź do sprawdzenia nasłuchu (krok 2);
  • błąd rozwiązywania nazwy - DNS w przestrzeni proxy nie zna nazwy upstreamu; sprawdź nazwę i sieć obu usług;
  • błąd TLS - porównaj schemat i nazwę w konfiguracji proxy z tym, co naprawdę serwuje upstream (krok 3);
  • kod błędu z upstreamu - aplikacja odpowiada błędem już bez udziału proxy; diagnoza przenosi się do jej dziennika.

Drugi test wykonaj lokalnie - na hoście aplikacji albo w jej kontenerze, tymi samymi komendami, tylko z adresem lokalnego nasłuchu zamiast adresu widzianego przez proxy. Gdy test lokalny przechodzi, a ten z przestrzeni proxy nie, przyczyna leży między usługami: w sieci, DNS albo regułach dostępu, nie w samej aplikacji.

Krok 2. Sprawdź, czy proces słucha tam, gdzie proxy puka

Na hoście aplikacji uruchom:

ss -ltnp

Komenda wypisuje nasłuchujące gniazda TCP wraz z informacją o procesach (opcja -p). Znajdź na liście port z konfiguracji proxy. Pamiętaj przy tym o pułapce adresu pętli zwrotnej - proces przypięty do 127.0.0.1 nie jest osiągalny z proxy działającego w innej przestrzeni sieciowej, na przykład w osobnym kontenerze.

Jeśli aplikacja rozmawia z proxy przez gniazdo uniksowe, portu nie znajdziesz w ogóle. Sprawdź wtedy plik gniazda i jego uprawnienia:

ss -lxp
ls -l SCIEZKA_GNIAZDA

Proces proxy potrzebuje dostępu i do samego gniazda, i do wszystkich katalogów na jego ścieżce. O odmowie rozstrzyga wpis w logu proxy skorelowany z badanym żądaniem, nie samo spojrzenie na uprawnienia.

Krok 3. Porównaj konfigurację proxy ze stanem systemu

Zestaw to, co proxy ma wpisane, z tym, co potwierdziły dwa poprzednie kroki:

  1. protokół - http:// kontra https:// w adresie upstreamu; kierowanie ruchu przez HTTPS do procesu, który mówi tylko HTTP, kończy się kodem 502;
  2. host - adres IP, nazwa hosta albo nazwa usługi w sieci kontenerowej;
  3. port - ten sam, który zobaczyłeś w wyniku ss;
  4. ścieżka gniazda - jeśli zamiast portu w grze jest gniazdo uniksowe.

W nginx protokół i adres upstreamu ustawia dyrektywa proxy_pass. Pełny układ tej warstwy opisuje konfiguracja reverse proxy - tutaj sprawdzasz tylko zgodność wpisanych wartości ze stanem systemu.

Krok 4. Przeczytaj logi po obu stronach

Na hoście aplikacji zacznij od statusu usługi i dziennika wokół momentu błędu:

systemctl status NAZWA_USLUGI
journalctl -u NAZWA_USLUGI --since 'CZAS_PRZED_BLEDEM' --until 'CZAS_PO_BLEDZIE' --no-pager

Granice czasu ustaw wokół zanotowanego błędu i uwzględnij strefę czasową hosta. W dzienniku szukaj odmowy dostępu, zerwanego połączenia, braku pamięci i wyjątku kończącego proces. Serię uruchomień i zatrzymań w krótkim odstępie czytaj jako pętlę restartów - wtedy interesuje cię pierwszy błąd przed pierwszym zatrzymaniem, nie ostatni.

Log proxy czytaj na jego hoście albo w jego kontenerze. Znajdź wpis badanego żądania z kodem 502 i porównaj zapisany tam adres upstreamu z adresem, który testowałeś w kroku 1. Rozjazd między nimi oznacza, że testujesz nie to połączenie, którego używa proxy.

Krok 5. Sprawdź zasoby i limity

Gdy poprzednie kroki nie wskazały przyczyny, na hoście właściwej usługi obejrzyj pamięć, miejsce na dysku, liczbę procesów roboczych i limity połączeń. Stan zasobów koreluj z momentem błędu - pojedyncze udane żądanie w środku nocy nie wyklucza problemu, który pojawia się dopiero pod obciążeniem.

Objaw, przyczyna i następny krok

Miejsce testu Sygnał Wniosek Następny krok
Przestrzeń sieciowa proxy curl zwraca odmowę połączenia Upstream odrzuca połączenie na trasie proxy ss -ltnp na hoście aplikacji, potem reguły dostępu
Przestrzeń sieciowa proxy curl nie dostaje odpowiedzi HTTP Trasa nie dowozi odpowiedzi, ale czas oczekiwania nie identyfikuje kodu Odczytaj kod publiczny i skoreluj test z logami proxy oraz aplikacji
Host albo kontener proxy Log proxy zgłasza błąd protokołu lub zerwanie połączenia Odpowiedź upstreamu nie spełniła oczekiwań proxy Porównaj schemat w konfiguracji z protokołem potwierdzonym testem bezpośrednim
Host z gniazdem uniksowym Log proxy zgłasza odmowę dostępu do gniazda Proxy nie może otworzyć gniazda Uprawnienia gniazda i katalogów na ścieżce, potem ponów żądanie
Host aplikacji Dziennik pokazuje cykl uruchomień i zatrzymań Proces nie utrzymuje się przy życiu Znajdź pierwszy błąd przed zatrzymaniem, usuń przyczynę, ponów oba testy
Przestrzeń sieciowa proxy Nazwa upstreamu nie rozwiązuje się DNS proxy nie zna tej nazwy Zweryfikuj nazwę i sieć obu usług, powtórz test z tej samej przestrzeni

502 w nginx, Dockerze i na hostingu zarządzanym

nginx. Dyrektywa proxy_pass mówi, gdzie proxy szuka aplikacji. Porównaj jej wartość z adresem zapisanym przy badanym żądaniu w dzienniku błędów nginx oraz z adresem, który testowałeś w kroku 1 - wszystkie trzy muszą się zgadzać.

Docker. Upstream bywa wskazany nazwą usługi, a nazwa działa tylko wewnątrz wspólnej sieci kontenerowej. Adres pętli zwrotnej w kontenerze proxy prowadzi do tego kontenera, nie do aplikacji. Test z kroku 1 wykonuj więc wewnątrz kontenera proxy - z hosta zobaczysz inną sieć niż ta, w której proxy szuka upstreamu.

Hosting zarządzany. Bez dostępu do proxy twoja rola kończy się na zebraniu danych dla supportu: czas błędu ze strefą czasową, pełny URL, metoda żądania, zakres problemu, wynik testu lokalnego, jeśli jakiś dostęp masz, oraz ostatnia zmiana przed awarią. Z takim kompletem support zaczyna od korelacji żądania z logami zamiast od pytań, na które odpowiedzi już przyniosłeś.

Czym różni się 502 od 504?

Te kody opisują różne zdarzenia i mają różne pierwsze ruchy.

502 Bad Gateway 504 Gateway Timeout
Co się stało Proxy dostało od upstreamu odpowiedź nieprawidłową Proxy nie dostało odpowiedzi w wyznaczonym czasie
Sygnał rozstrzygający Kod 502 u klienta plus wpis w logu proxy o błędzie połączenia lub odpowiedzi upstreamu Kod 504 u klienta plus wpis w logu proxy o przekroczeniu czasu oczekiwania
Pierwszy ruch Test upstreamu z przestrzeni sieciowej proxy Ustalenie z logu proxy, na którym etapie odpowiedzi upłynął limit

Nie rozróżniaj tych kodów po tym, jak długo przeglądarka kręciła kółkiem. Odczytaj kod odpowiedzi i znajdź odpowiadający mu wpis w logu proxy - to jedyne wiarygodne rozstrzygnięcie. Przekroczenie czasu ma osobny tok naprawy, opisany w 504 Gateway Timeout.

Jak sprawdzić, że naprawa działa?

Trzy testy, każdy obejmuje inną część ścieżki. We wszystkich zachowaj endpoint, nagłówek Host i warunki żądania, które zwracało 502 - naprawa sprawdzona na innym żądaniu niczego nie dowodzi.

Najpierw ponów test upstreamu z przestrzeni proxy (komendy z kroku 1). Następnie sprawdź publiczny vhost na samym proxy, z hosta proxy albo innego miejsca z dostępem do listenera. Dla HTTP:

curl -sv -H 'Host: DOMENA_PUBLICZNA' 'http://ADRES_LISTENERA:PORT_LISTENERA/SCIEZKA'

Dla listenera HTTPS domena musi trafić także do SNI, więc znów pracuje --resolve - kieruje połączenie na badany adres, a domena w URL-u ustawia i SNI, i nagłówek Host:

curl -sv --resolve 'DOMENA_PUBLICZNA:PORT_LISTENERA:ADRES_LISTENERA' 'https://DOMENA_PUBLICZNA:PORT_LISTENERA/SCIEZKA'

Na końcu powtórz dokładnie ten publiczny wariant żądania, który zwracał 502, z miejsca reprezentującego zewnętrznego klienta:

curl -sv 'SCHEMAT_PUBLICZNY://DOMENA_PUBLICZNA:PORT_PUBLICZNY/SCIEZKA'

Praca jest skończona, gdy wszystkie trzy testy przechodzą, a wpis testu publicznego w logu proxy nie zawiera nowego błędu upstreamu.

Jak zapobiec powtórce?

Po ręcznej naprawie dołóż mechanizmy, które następnym razem wykryją problem przed klientem:

  • Endpoint zdrowia w aplikacji - lekka ścieżka, która zwraca oczekiwaną odpowiedź dopiero wtedy, gdy proces jest gotowy do pracy, a nie tylko uruchomiony.
  • Polityka restartu z limitem prób - proces, który pada, ma wstać sam, ale pętla restartów ma być widoczna, nie maskowana.
  • Monitoring dwóch warstw - kontrola procesu na serwerze plus syntetyczne odpytanie publicznego adresu z zewnątrz. Sam monitoring procesu nie zauważy błędu w konfiguracji proxy ani w publicznym DNS.
  • Alarm z adresatem - powiadomienie bez konkretnej osoby i ścieżki eskalacji jedynie rejestruje zdarzenie. Ustal przed awarią, kto odpowiada za warstwę proxy, kto za aplikację i dokąd idzie eskalacja.

Szerszy kontekst tego, z jakich warstw składa się serwis i która za co odpowiada, daje przegląd warstw serwera strony i aplikacji.

Zanim zamkniesz temat

  • Publiczny wariant żądania, który zwracał 502, przechodzi bez błędu, a wpis tego testu w logu proxy nie zawiera nowego błędu upstreamu.
  • Znasz przyczynę i zapisałeś ją tam, gdzie zespół szuka historii awarii - "samo przeszło" oznacza, że wróci.
  • Monitoring pilnuje i procesu na serwerze, i publicznego adresu, a alarm ma przypisanego adresata.

Pytania o błąd 502

Jak naprawić błąd 502 Bad Gateway?

Przetestuj upstream z przestrzeni sieciowej proxy, osobno sprawdź proces lokalny, porównaj port lub gniazdo i protokół z konfiguracją proxy, a potem skoreluj żądanie z logami obu warstw. Naprawę potwierdź tym samym publicznym wariantem żądania, który zwracał 502. Restart na ślepo bywa skuteczny na chwilę, ale bez znalezionej przyczyny błąd wraca.

Co oznacza komunikat "502 zła brama"?

To polskie tłumaczenie nazwy kodu. Brama, czyli proxy, przekazała żądanie do serwera nadrzędnego i dostała od niego odpowiedź nieprawidłową - komunikat pochodzi z warstwy pośredniczącej, nie z aplikacji docelowej. Sam kod nie rozstrzyga, czy zawiódł proces, transport do niego, czy konfiguracja połączenia.

Czy 502 to problem serwera, czy przeglądarki?

Serwera. Kod 502 zgłasza gateway lub proxy podczas komunikacji z serwerem nadrzędnym, a przeglądarka tylko wyświetla otrzymaną odpowiedź. Jako odwiedzający cudzą stronę możesz odświeżyć ją za kilka minut, a przy dłuższej awarii zanotować adres i moment oraz zgłosić problem właścicielowi witryny.

Skąd błąd 502 w e-Doręczeniach?

Z tej samej mechaniki - proxy systemu e-Doręczeń dostało nieprawidłową odpowiedź od usługi za nim - tyle że tam cała diagnoza leży po stronie operatora systemu. Jako użytkownik możesz ponowić próbę później i skorzystać z oficjalnej pomocy pod adresem gov.pl/web/e-doreczenia. Ten poradnik nie naprawi błędu w cudzym systemie rządowym.

Czy błąd 502 może zniknąć sam?

Może - na przykład gdy przyczyną był restart aplikacji podczas wdrożenia albo chwilowe wyczerpanie zasobów. Zniknięcie objawu nie jest jednak naprawą: bez znalezionej przyczyny ten sam błąd wróci przy następnym wdrożeniu lub szczycie ruchu. Wpis w logu proxy z momentu awarii mówi, co się stało, nawet gdy strona już działa.

Dalsza diagnostyka

Pozostałe kody błędów serwera i sposób odróżniania ich od siebie zbiera hub kodów błędów serwera. Definicję kodu 502 znajdziesz w RFC 9110 (sekcja 15.6.3), a działanie dyrektywy proxy_pass opisuje dokumentacja nginx w module ngx_http_proxy_module.