Limit połączeń nie jest tym samym co limit CPU lub RAM. Strona może odpowiadać z opóźnieniem albo zwracać timeout, gdy wyczerpie pulę obsługiwanych połączeń, kolejkę nasłuchu lub limit równoczesnych żądań aplikacji, nawet jeśli użycie procesora i pamięci pozostaje poniżej maksimum.
Spis treści
Jakie rodzaje połączeń trzeba rozróżnić?
Otwarte połączenie TCP to aktywna sesja sieciowa między klientem a serwerem. Połączenie może być w trakcie przesyłania danych albo czekać na kolejny fragment komunikacji. Liczba takich połączeń wpływa na obciążenie serwera i może podlegać osobnemu limitowi.
Keep-alive pozwala utrzymać połączenie TCP po zakończeniu pojedynczego żądania HTTP, aby wykorzystać je ponownie. Zmniejsza to liczbę nowych połączeń i koszt ich zestawiania, ale bezczynne sesje nadal mogą zajmować zasoby lub miejsce w puli połączeń. Przy wielu klientach keep-alive może więc zwiększyć liczbę jednocześnie otwartych sesji, mimo że w danej chwili nie wszystkie wykonują żądanie.
Listen backlog to kolejka połączeń oczekujących na przyjęcie przez proces nasłuchujący. Nie oznacza liczby żądań przetwarzanych przez aplikację. Gdy proces nie przyjmuje połączeń wystarczająco szybko, kolejka rośnie. Po jej zapełnieniu nowe próby połączenia mogą być odrzucane albo kończyć się timeoutem. Parametry serwera związane z obsługą połączeń i kolejkami należą do ustawień wpływających na wydajność serwera.
Limit równoczesności aplikacji określa, ile żądań aplikacja może przetwarzać w tym samym czasie. Może być związany na przykład z liczbą procesów, wątków, workerów albo połączeń do usługi zaplecza. Połączenie TCP może być otwarte, ale żądanie nadal czekać na wolny worker aplikacji. Wtedy wolne CPU nie oznacza, że aplikacja ma wolną zdolność obsługi kolejnego żądania.
Dlaczego pojawia się timeout przy wolnym CPU i RAM?
Timeout oznacza, że klient nie otrzymał odpowiedzi w oczekiwanym czasie. Przyczyną może być oczekiwanie na wolne miejsce w kolejce, worker aplikacji, połączenie do bazy danych albo odpowiedź usługi za reverse proxy. Serwer może wtedy zużywać niewiele CPU, ponieważ procesy czekają na dane lub wolny zasób, zamiast intensywnie wykonywać obliczenia.
Typowe źródła problemu to:
- zbyt wiele otwartych połączeń TCP,
- duża liczba bezczynnych połączeń keep-alive,
- zapełniona kolejka listen backlog,
- wyczerpany limit równoczesnych żądań aplikacji,
- nagły wzrost ruchu, który przez krótki czas tworzy więcej pracy niż serwer może przyjąć,
- wolni klienci, którzy długo pobierają odpowiedź i utrzymują zajęte połączenia.
Problemy wynikające z wyczerpania połączeń mogą mieć różne objawy zależnie od miejsca przeciążenia. Sposoby wykrywania i diagnozowania wyczerpania połączeń opisuje materiał dotyczący NGINX Netdata.
Jak ruch, keep-alive i wolni klienci zmieniają zapotrzebowanie?
Nagły wzrost ruchu zwiększa jednocześnie liczbę nowych połączeń i liczbę żądań oczekujących na obsługę. Nawet krótki pik może zapełnić kolejkę, jeśli proces przyjmujący połączenia lub aplikacja nie nadążają z ich obsługą.
Keep-alive zmienia profil obciążenia. Mniej nowych połączeń oznacza mniejszy koszt ich zestawiania, ale więcej sesji może pozostać otwartych między żądaniami. Wolny klient dodatkowo utrzymuje połączenie przez dłuższy czas. Jeśli serwer lub proxy rezerwuje zasoby dla takich sesji, mniejsza liczba klientów może wystarczyć do osiągnięcia limitu.
Reverse proxy rozdziela połączenia klienta od połączeń do serwera aplikacji. Dlatego należy analizować osobno liczbę połączeń od użytkowników, połączeń proxy do aplikacji oraz żądań oczekujących po stronie zaplecza. Mechanizmy ochrony przed przeciążeniem i obsługa kolejek w proxy opisuje dokumentacja HAProxy.
Jakie metryki sprawdzić?
Analizuj metryki według warstwy, w której może powstawać kolejka:
- Sieć i TCP: liczba otwartych połączeń, ich stany, liczba nowych połączeń oraz czas ich utrzymywania.
- Listener: rozmiar listen backlog, liczba połączeń oczekujących, odrzucone połączenia i tempo ich przyjmowania.
- Reverse proxy: połączenia od klientów, połączenia do upstreamu, żądania oczekujące oraz czas odpowiedzi upstreamu.
- Aplikacja: liczba zajętych i wolnych workerów, długość kolejki żądań, czas odpowiedzi i błędy aplikacji.
- Serwer: CPU, RAM, użycie przestrzeni oraz inne limity zasobów.
Nie oceniaj problemu wyłącznie na podstawie CPU i RAM. Zestaw te dane z liczbą połączeń, czasem odpowiedzi i długością kolejek.
Kiedy stroić konfigurację, włączyć cache albo zwiększyć hosting?
Strojenie ma sens, gdy problem dotyczy krótkich pików, zbyt długich keep-alive, kolejki lub limitu aplikacji, a serwer ma zapas pozostałych zasobów. Zmiany wykonuj po zapisaniu obecnej konfiguracji i z możliwością cofnięcia. Po każdej zmianie porównaj liczbę timeoutów, czas odpowiedzi, długość kolejek i liczbę aktywnych połączeń.
Cache może pomóc, gdy wiele żądań powtarza tę samą pracę aplikacji. Zmniejszenie liczby żądań docierających do aplikacji ogranicza konkurencję o workery i połączenia do zaplecza. Przed włączeniem cache sprawdź, czy nie przechowuje treści prywatnych lub dynamicznych.
Zmiana zasobów hostingu jest uzasadniona, gdy obciążenie utrzymuje się przez dłuższy czas, kolejki i timeouty wracają po strojeniach, a aplikacja potrzebuje większej równoczesności. W Elastycznym Web Hostingu zasoby są dopasowywane do aktualnego ruchu i obciążenia. Przy większym ruchu mogą wzrosnąć dostępne CPU, RAM i przestrzeń, a po spadku obciążenia poziom wraca do wartości bazowej.
FAQ
Czy otwarte połączenie oznacza aktywne żądanie?
Nie. Połączenie TCP może pozostawać otwarte dzięki keep-alive, mimo że w danej chwili nie wykonuje żądania. Dlatego liczba otwartych połączeń i liczba aktywnych żądań to różne metryki.
Czy zwiększenie limitu połączeń zawsze usuwa timeouty?
Nie. Jeśli wąskim gardłem jest backlog, worker aplikacji, upstream lub baza danych, większa liczba połączeń może tylko wydłużyć kolejkę. Najpierw ustal, w której warstwie rośnie oczekiwanie.
Co oznacza wzrost błędów przy nagłym ruchu?
Zwykle oznacza, że jedna z kolejek albo pul połączeń osiągnęła swoją pojemność. Porównaj wtedy czas wystąpienia błędów z liczbą nowych i otwartych połączeń, długością kolejek oraz czasem odpowiedzi aplikacji.
