Kilka serwerów, różne aplikacje Rails 2.3 działające na passengerze. Od czasu do czasu któraś z aplikacji zajmuje całą pamięć serwera (w kilka sekund - to nie jest wolny wyciek pamięci który trwa tygodniami) i serwer pada. Ciężko dowiedzieć się która bo problem nie występuje na dev/staging i nic nie jest logowane nigdzie (nie ma zasobów żeby cokolwiek logować) . Aplikacje korzystają z innych procesów (np. java, wkhtmltopdf, imagemagick) więc to niekoniecznie wina Ruby (chociaż to jest najbardziej prawdopodobne).
Passenger nie posiada wbudowanej opcji monitorowania pamięci więc odpada. God/monit - z tego co wiem monitorują procesy co jakiś czas a z tego co zauważyłem położenie serwera z 8GB pamięci zabiera kilka sekund.
Rozważam opcję ustawienia limitu na pamięć/proces przy pomocy ulimit. Z wstępnego rozeznania wynika, że działa to dobrze, zaimplementowane jest w jądrze więc bedzie działać dopóki jądro nie padnie. Jeśli np. ustawię limit max 500MB/proces i aplikacja zacznie mocno alokować pamięć to Ruby rzuci wyjątkiem “Cannot allocate memory” - dowiem się w końcu która to aplikacja i serwer powinien wciąż działać.
Jeśli ktoś ma jakąś opinię na ten temat (albo zna inne lepsze rozwiązanie) to chętnie usłyszę.
Kiedyś była taka opcja w passengerze, ale niestety to wyrzucili…
Co do ulimit to nie próbowałem, ale jak miałem kiedyś tego typu problem (bardzo szybki wyciek, kilka sekund i trzeba restartować serwer), to chodziło o rekurencyjne wyciąganie rekordów. Jeżeli masz gdzieś coś takiego, to sprawdź czy przypadkiem 2 rekordy nie są zlinkowane nawzajem.
Określenie “od czasu do czasu” jest deterministyczne, czy aplikacje działają dobrze powiedzmy tydzień i w losowym momencie boom? Jeśli masz wycieki pamięci i serwer “pada” to w dmesgu powinny być komunikaty kernela, że nie mógł zaalokować pamięci wraz z informacją o nazwie procesu + pid. Jeśli jesteś w stanie odtworzyć problem w krótkim czasie (np. przez kilka minut serwery działają i nagle trach) to w myśl zasady “taśmą i sznurkiem klejącym”:
(while true; do top -b -n1 >> /tmp/top.output; sleep 1; done)&
i później analizować co najwięcej ramu żarło.
Odnośnie tego co pisał @drogus to ja kiedyś natomiast miałem przypadek, że programista napisał
U nas produkcyjnie korzystamy z cgroups(nowsze i fajniejsze)/ulimit jeśli potrzeba. Niestety tak jak napisałeś -> god/monitd jest bardzo słaby do monitorowania takich rzeczy (nie da się ustawić sensownego interwału aby wyłapać “peak” a potem jest już za późno).
Problem rozwiązany chociaż znalezienie rozwiązania zajęło sporo czasu i nerwów.
Problem pomogło namierzyć zainstalowanie atop’a i jego logi. Po OOM można odtworzyć sytuację na serwerze minuta po minucie i zobaczyć jaki był stan serwera w danym momencie (list procesów, zajęcie pamięci przez każdy z nich).
Okazało się, że jedna z aplikacji woła:
java -cp Multivalent.jar -layout x,x
Co mniej więcej oznacza “utwórz dokument pdf z 2 slotami na stronie - oba puste, utwórz następną stronę do momentu aż wypełnisz czymś wszystkie sloty etc.” - w praktyce powstawał “dokument z niekończącymi się stronami w pamięci”, działo się to dosyć szybko ale atop zdążył zawsze to wyłapać - więc polecam dopisanie atop’a do listy bardzo przydatnych narzędzi.