Apache dociera do MaxClients i blokuje serwer

9

Obecnie mam serwer Apache2 działający z OpenVZ VPS mpm-preforki mod_phpna nim z 512 MB pamięci rzeczywistej / 1024 M pamięci RAM z możliwością pękania (bez wymiany). Po przeprowadzeniu niektórych testów stwierdziłem, że maksymalny rozmiar procesu, jaki otrzymuje Apache, to MaxClients23 MB, więc ustawiłem 25 (23 MB x 25 = 575 MB, ok dla mnie). Postanowiłem uruchomić testy obciążenia na moim serwerze, a wyniki mnie zaskoczyły.

Używam abna swoim komputerze stacjonarnym, aby poprosić o stronę główną z bloga Wordpress.

Kiedy uruchamiam abz 24 jednoczesnymi połączeniami, wszystko wydaje się w porządku. Jasne, procesor idzie w górę, wolna pamięć RAM spada, a wynik wynosi około 2-3s czasu odpowiedzi na żądanie.

Ale jeśli uruchomię abz 25 jednoczesnymi połączeniami (mój limit serwerów), Apache po prostu zawiesi się po kilku sekundach. Zaczyna przetwarzać żądania, potem przestaje odpowiadać, procesor wraca do 100% bezczynności i kończy się limit abczasu. Dziennik Apache mówi, że osiągnął MaxClients.

Gdy tak się dzieje, Apache blokuje się przy 25 uruchomionych procesach (wszystkie są w „W”, jeśli sprawdzę status serwera) i dopiero po TimeOutustawieniu procesy zaczynają umierać, a serwer zaczyna ponownie odpowiadać (w moim przypadku jest ustawiony do 45).

Moje pytanie: czy to oczekiwane zachowanie? Dlaczego Apache umiera, kiedy się osiąga MaxClients? Jeśli działa z 24 połączeniami, czy nie powinno współpracować z 25, wystarczy poświęcić więcej czasu na odpowiedź na każde żądanie i ustawić w kolejce resztę?

Brzmi trochę dziwnie dla mnie, że każde uruchomione dziecko abmoże samodzielnie zabić serwer sieciowy, ustawiając równoczesne połączenia z serwerami MaxClients.

Rodrigo Sieiro
źródło

Odpowiedzi:

17

HA! W końcu sam znalazłem problem. Jest to bardziej związane z programowaniem niż z administratorem serwera, ale i tak zdecydowałem się tu odpowiedzieć, ponieważ szukając google, okazało się, że nie jestem jedyny z tego rodzaju problemami (a ponieważ Apache się zawiesił, pierwsze przypuszczenie to problem z serwerem).

Problem nie dotyczy Apache, ale mojego Wordpressa. Dokładniej z moim motywem. Używam motywu o nazwie Lightworld, który obsługuje dodawanie obrazu do nagłówka bloga. Aby to umożliwić, sprawdza rozmiar obrazu za pomocą funkcji PHP getimagesize(). Ponieważ ta funkcja otwierała kolejne połączenie HTTP z serwerem w celu uzyskania obrazu, każde żądanie od użytkownika abtworzyło kolejne żądanie wewnętrznie z PHP. Ponieważ korzystałem ze wszystkich dostępnych wolnych miejsc na serwerze, te żądania PHP zostały umieszczone w kolejce, ale Apache nigdy nie mógł się do nich dostać, ponieważ wszystkie jego procesy zostały zablokowane przy użyciu pierwotnego żądania oczekującego na miejsce do wykonania wewnętrznego żądania PHP.

Zasadniczo PHP wprowadziło mój serwer w stan impasu, a Apache zaczął działać normalnie dopiero po przekroczeniu limitu czasu tych połączeń w oczekiwaniu na żądanie „podrzędne”.

Po usunięciu tej funkcji z mojego motywu, teraz mogę abmój serwer z tyloma równoległymi połączeniami, ile chcę, a Apache ustawia je w kolejce zgodnie z oczekiwaniami.

Rodrigo Sieiro
źródło
Dzięki za opublikowanie tego tutaj, od kilku dni staram się znaleźć problem z dokładnie tymi samymi objawami - myślę, że mamy też impas!
James Yale,
jak to określiłeś, przede wszystkim interesują mnie dzienniki i narzędzia użyte do ustalenia dodatkowego żądania wychodzącego.
Anirudh Goel
2

To, co się tutaj dzieje, polega na tym, że masz 25 wątków zdolnych do akceptowania połączeń i wysyłasz 26 jednoczesnych żądań. To ostatnie żądanie znajduje się w kolejce gniazd w zależności od wielkości zaległości.

Drugi problem polega na tym, że cokolwiek uruchomisz, co zajmuje 2-3 sekundy, trwa wystarczająco długo, aby odpowiedzieć, że 25 równoczesnych połączeń spowalnia go. sleep (1) może działać, ale, gdy robisz blokowanie plików lub tabel z mysql, każde równoległe żądanie może czekać przed zakończeniem, aż osiągnie 45 sekundowy limit czasu.

23 MB wydaje się mały jak na proces apache z mod_php i załadowanymi modułami, więc podejrzewam, że te procesy apache mogą wymagać nieco więcej pamięci RAM w trakcie działania aplikacji. Naprawdę nie możesz robić matematyki z MaxClients i taką pamięcią ... będzie trochę blisko, ale nigdy nie wiadomo.

www-data  1495  0.1  0.9  56288 19996 ?        S    15:48   0:01 /usr/sbin/apache2 -k start
www-data  1500  0.0  0.5  49684 12436 ?        D    15:48   0:00 /usr/sbin/apache2 -k start

Jest jedna maszyna, procesy 56M i 49M.

inna maszyna:

www-data  7767  0.1  0.1 213732 14840 ?        S    14:55   0:08 /usr/sbin/apache2 -k start
www-data  8020  0.2  0.1 212424 13660 ?        S    14:57   0:08 /usr/sbin/apache2 -k start

inna maszyna:

www-data 28509  0.8  0.1 161720 10068 ?        S    14:39   0:43 /usr/sbin/apache2 -k start
www-data 28511  0.8  0.1 161932 10344 ?        S    14:39   0:43 /usr/sbin/apache2 -k start

Tak więc użycie pamięci jest bardzo zależne od zadania, które moduły są ładowane itp. Sądzę, że w dwóch ostatnich wyłącziliśmy pdo & pdo_mysql, ponieważ ta aplikacja ich nie używa.

Prawdziwe pytanie brzmi: co robisz, co zajmuje 3 sekundy? W dzisiejszym świecie jest to wieczność i uważana jest za aplikację „blokującą”. Apache zwykle nie umiera, ale pozostawia te wątki w kolejce zaległości, dopóki nie będzie w stanie ich obsłużyć lub upłynie limit czasu oczekiwania. Uważam, że Twoja aplikacja prawdopodobnie powoduje przekroczenie limitu czasu Apache. Wypróbuj na stronie zawierającej tylko phpinfo (); i sprawdź, czy wyniki są takie same.


źródło
Dzięki za wszystkie wskazówki! Wiem, że wciąż muszę zoptymalizować wiele rzeczy (dopiero zacząłem konfigurować serwer kilka dni temu i to jest moje pierwsze doświadczenie z VPS), ale problem był głębszy niż ... Wysłałem odpowiedź na pytanie wyjaśniające, jaki był problem w moim konkretnym przypadku.
Rodrigo Sieiro,