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!