Korzystam z aplikacji PHP na serwerze Apache 2.2 (Ubuntu Server 10.04, 8x2GHz, 12Gb RAM) przy użyciu prefork
. Każdego dnia Apache otrzymuje około 100–200 tys. Żądań, z czego około 100–200 przekracza limit czasu (czyli około 1 na tysiąc), prawie wszystkie pozostałe żądania są obsługiwane znacznie poniżej limitu czasu.
Co mogę zrobić, aby dowiedzieć się, dlaczego tak się dzieje? Czy to normalne, że niektóre małe części wszystkich żądań przekraczają limit czasu?
Oto co zrobiłem do tej pory:
Jak widać, jest bardzo niewiele żądań, które znajdują się między limitem czasu a bardziej uzasadnionym żądaniem. Obecnie limit czasu ustawiony jest na 50 sekund, poprzednio był ustawiony na 300 i nadal była taka sama sytuacja z niektórymi limitami czasu, a następnie ogromną luką w stosunku do innych żądań.
Wszystkie żądania, które przekroczą limit czasu, są AJAX
wnioskami, ale znaczna większość z nich jest, więc może to bardziej zbieg okoliczności. Kod powrotu Apache jest 200
, ale limit czasu został wyraźnie osiągnięty. Pochodzą z szerokiej gamy różnych adresów IP.
Przejrzałem prośby, które wygasły, i nie ma w nich nic specjalnego, jeśli wykonam te same prośby, które spełnią w niecałą sekundę.
Próbowałem spojrzeć na różne zasoby, aby sprawdzić, czy mogę znaleźć przyczynę, ale bez powodzenia. Zawsze jest dużo wolnej pamięci (minimum około 3 GB wolnej przestrzeni), obciążenie czasami dochodzi nawet do 1,4, a wykorzystanie procesora do 40%, ale wiele limitów czasu występuje, gdy obciążenie i wykorzystanie procesora są niskie. Zapis / odczyt dysku jest prawie stały w ciągu dnia. W dzienniku powolnych zapytań MySQL nie ma wpisów (ustawione na rejestrowanie czegokolwiek powyżej 1 sekundy), żadne żądanie nie korzysta z tylu zapisów / odczytów bazy danych.
Kolor niebieski oznacza wykorzystanie procesora, które osiąga wartość szczytową przy 40%, bordowy jest obciążony wartością szczytową przy 1,4. Widzimy więc, że mamy limity czasu nawet przy niskim zużyciu / obciążeniu procesora (dziesięciosekundowe skoki dobrze odpowiadają zużyciu procesora, ale to kolejny problem, mam większą nadzieję dowiedzieć się, co może być przyczyną).
Dziennik błędów Apache nie zawiera błędów i nie widziałem, aby osiągnął więcej niż 200 aktywnych procesów Apache.
Ustawienia serwera:
Timeout 50
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 2
<IfModule mpm_prefork_module>
ServerLimit 350
StartServers 20
MinSpareServers 75
MaxSpareServers 150
MaxClients 320
MaxRequestsPerChild 5000
</IfModule>
Aktualizacja:
Zaktualizowałem do Ubuntu 12.04.1, na wszelki wypadek, bez zmian. Dodałem mod_reqtimeout z ustawieniami:
RequestReadTimeout header=20-40,minrate=500
RequestReadTimeout body=10,minrate=500
Teraz prawie wszystkie limity czasu mają miejsce po 10 sekundach, jeden lub dwa po 20 sekundach. Rozumiem, że oznacza to, że przez większość czasu otrzymywanie treści żądania jest problematyczne? Treść żądania nigdy nie powinna być większa niż kilkaset bajtów. Monitorowałem ruch sieciowy co 1 sekundę i nigdy nie wzrasta on powyżej 1 Mb / s i nie widzę żadnych sygnałów rxerr ani rxdorps, biorąc pod uwagę, że serwer znajduje się na linii 1 Gbit / s, co nie brzmi jak HopelessN00b napisał o. Czy może to być tylko przypadek złych połączeń użytkownika?
W przypadku skoków co godzinę (wydają się nieco dryfować, na wykresach powyżej są one 33 minuty po godzinie, teraz są za 12 minut), próbowałem sprawdzić, czy coś okresowo działa ( crons itp.), ale nic nie znalazł. Odśmiecanie PHP działa dwa razy co godzinę, ale nie w czasie szczytów, wciąż próbowałem go wyłączyć, ale to nie robi różnicy.
Użyłem dstat z opcją --top-cpu i top, aby spojrzeć na procesy w czasie szczytów, a wszystko, co się pokazuje, to apache pracujący przez kilka sekund, ale żaden inny proces nie używa znacznej mocy procesora.
Zrobiłem powiększony wykres skoków:
Dla mnie wygląda na to, że Apache zatrzymuje się na kilka sekund, a następnie ciężko pracuje, aby przetworzyć żądania, które pojawiły się podczas zatrzymania. Co może spowodować taki postój, czy też źle go interpretuję?
źródło
Odpowiedzi:
Pierwszą rzeczą, którą zauważam, patrząc na twój pierwszy wykres, wydaje się być cogodzinne spowolnienie (występujące około 40 minut po godzinie), które może przyczyniać się do problemu. Powinieneś spojrzeć na harmonogramy zadań w systemie operacyjnym / bazie danych.
Na podstawie dostarczonych danych moim następnym krokiem będzie przyjrzenie się częstotliwości czasów odpowiedzi (liczba odpowiedzi na osi Y w porównaniu do czasu trwania na X), ale tylko w tym adresy URL, które wykazują limit czasu (lub najlepiej jeden adres URL na raz ). W typowym systemie powinno to być zgodne z rozkładem normalnym lub rozkładem Poissona - żądania, które przekroczą limit czasu, mogą po prostu stanowić część ogona - w takim przypadku musisz skoncentrować swoje wysiłki na ogólnym strojeniu. OTOH, jeśli dystrybucja jest bimodalna, musisz poszukać rywalizacji gdzieś w kodzie.
źródło
Zastanawiam się nad tym, biorąc pod uwagę fakt, że otrzymujesz dużą liczbę żądań dziennie i wydaje się, że masz limity czasu tylko w godzinach szczytu (z zamieszczonych zdjęć).
Na blogu o awariach serwera jest post
Per Second Measurements Don't Cut It
... czy jest możliwe, że niektóre z tych żądań napotkały ten sam problem, na który wpadł zespół ServerFault?źródło