Mniej więcej raz w tygodniu, ale czasem nawet kilka razy dziennie po kilku dniach pracy, moje instancje EC2 przestają reagować. Wykresy pamięci Munina opowiadają dość prostą historię: pamięć przydzielana „aplikacjom” zaczyna rosnąć i nie zatrzymuje się, dopóki swap nie zostanie w pełni wykorzystany i instancja zostanie skutecznie sprowadzona na kolana. Kolejny niestandardowy wykres pokazuje, że stale rosnącym procesem jest apache2.
Korzystam ze standardowej konfiguracji Apache w trybie prefork z mod_php i kilkoma skryptami PHP. Jak widać na poniższym wykresie, dzieje się coś, co powoduje, że procesy apache2 zaczynają zużywać coraz więcej pamięci. Pierwszy zielony skok, który złapałem na czas i ponownie uruchomiłem Apache, zanim sprawy wymknęły się spod kontroli. Drugi skok nieco się przesunął i instancja musiała zostać ponownie uruchomiona od razu.
Zastanawiam się, jak najlepiej to debugować. Jak skonfigurować PHP z FastCGI i uruchomić go we własnych procesach, co jest dobrym sposobem, aby dowiedzieć się, czy to Apache, czy kombinacja PHP i mojego kodu powoduje nadmierne zużycie pamięci? Jakie kroki podjęlibyście, aby wyśledzić ten problem?
AKTUALIZACJA: Byłem w stanie wyśledzić wyciek po zaangażowaniu strace, jak sugerował Matt poniżej.
Po znalezieniu procesu apache2, który stopniowo i stale powiększał się w pamięci, dodałem jeszcze kilka wywołań error_log () do mojego skryptu PHP, który wypisał całkowitą ilość RSS używaną w różnych momentach jego wykonywania (używając wyjścia ps). To jednak okazało się mylące - chociaż wydawało się, że RSS podskoczyło dopiero po uruchomieniu mojego skryptu, późniejsze debugowanie ujawniło, że tak nie było. Bądź ostrożny!
Na szczęście wszystkie te wywołania error_log () okazały się przydatne na końcu. Kiedy uruchomiłem strace ( strace -p <pid> -tt -o trace.log -s 256
), zobaczyłem, że dla każdego żądania proces alokował około 400k pamięci (poszukaj wywołania systemowego „brk” i odejmij parametr pierwszego wywołania od ostatniego wywołania - kilka zwykle przychodzi w jednym po kolejnym). Następnie szukałem najnowszego wywołania systemowego „zapisz”, które zawierało komunikat o błędzie error_log (), który powiedział mi, w którym momencie skryptu przydzielana jest pamięć. Z kilkoma bardziej strategicznie umieszczonymi wywołaniami error_log () w celu dokładniejszego wskazania lokalizacji, w końcu znalazłem winowajcę.
Pamięć wyciekała, gdy wywołaliśmy curl_exec () z naszego skryptu PHP. Niektóre zawinięte kody związane z obsługą połączenia SSL robią coś źle - wyciek zniknął, kiedy przełączyłem się na HTTP. Dziennik zmian Curl odwołuje się do kilku wycieków pamięci SSL, które zostały naprawione w 7.19.5 (byliśmy na 7.18.2), więc spróbuję to później.
W międzyczasie pracuję z bardzo niskim MaxRequestsPerChild, który utrzymuje Apache w rozsądnych granicach. Dziękuję wszystkim!
źródło
Odpowiedzi:
Wyśledzenie, CO powoduje problem, może być uciążliwe. Pierwszą rzeczą, którą bym zrobił, gdybym miał taki problem, jest zredukowanie
MaxRequestsPerChild
do agresywnie niskiej liczby (~ 100-200) i sprawdzenie, czy to robi różnicę. Jeśli tak, to prawdopodobnie masz gdzieś w pętli kod, który będzie przeciekał, i będziesz chciał przeprowadzić audyt kodu.Inną rzeczą, na którą warto spojrzeć, jest pełny status Apache'a, sprawdź, czy możesz dowiedzieć się, jakie konkretne żądanie powoduje wyciek pamięci. Uzyskaj identyfikatory PID podejrzanych procesów i przeprowadź śledzenie ich.
źródło
Piątek o dokładnie 23:00? Czy to odpowiada czasowi tworzenia kopii zapasowej? Czy twój system ma dostępne wejścia / wyjścia do obsługi procesów i kopii zapasowych w tym czasie? Czy oprogramowanie, które zyskujesz na popularności, ma tendencję do # procs, a nawet tablicy wyników apache, co powiesz na dyskowe operacje we / wy?
Pierwszą rzeczą, którą chciałbym zrobić byłoby obliczyć, ile każdy mem proc trwa, a następnie ustawić rozsądny limit MaxRequests w apache tak, że $ procmem * $ procuje nie może przekraczać dostępnej pamięci RAM. Podejrzewam, że twoja instancja musi zostać zrestartowana, ponieważ OOM rozpoczyna polowanie na czarownice, które prawdopodobnie (często) nie jest zbyt owocne. Ci potrzebne , aby zapewnić pole może obsługiwać te ciężkie czasy pozostając w jej granicach i nie iść do wymiany i na pewno nie OOM. Jest to trudniejsze, jeśli masz uruchomione cronjobs, i niezwykle trudne, jeśli wspomniane cronjobs uruchamiają się jednostronnie, nie upewniając się, że jest bezpieczny do uruchomienia (tj. Co 5 minut skrypt nie sprawdza, czy ostatni 5 minut nadal działa).
Teraz, gdy masz pewność, że nawet jeśli coś pójdzie nie tak, nie będziesz musiał ponownie uruchamiać komputera, wszystko zacznie działać lepiej. Będziesz mógł zalogować się w tych ciężkich czasach i dowiedzieć się, co się dzieje przy użyciu top, dstat, free-m, iostat itp.
Metoda Matta może być warta wypróbowania, ale powinna być używana tylko jako narzędzie do rozwiązywania problemów, nie zalecam pozostawania w ten sposób, ponieważ znacznie trudniej będzie znaleźć ogólny problem przy następnym szukaniu. To powiedziawszy, to naprawdę tylko drażni problemy z apache / modułami, a nie z niczym w twoim kodzie. Myślę, że zgodzisz się, że szanse są spore, to nie jest jakiś wyciek pamięci w module apache (zakładając, że używasz renomowanej dystrybucji).
źródło
Pierwsze pytanie, jakie należy zadać, to jaka aplikacja działa za pośrednictwem Apache?
Czy to napisana przez Ciebie aplikacja czy aplikacja innej firmy?
Do jakich innych komponentów / pakietów się odwołuje?
Czy jesteś na bieżąco ze swoimi paczkami?
Coś konkretnego w twoich
httpd.conf
plikach związanych z wydajnością?źródło
Jeśli twój problem jest spowodowany aplikacją PHP i jeśli sam napisałeś oprogramowanie, polecam skorzystanie z profilera, np. PHP Quick Profiler . Jeśli dzieje się wiele transakcji w bazie danych, oprogramowanie takie jak np. Kontrollbase może pomóc w znalezieniu problemu.
źródło