Mój serwer internetowy VPS działający na CentOS 5.4 (jądro Linuksa 2.6.16.33-xenU) nieregularnie (jak raz w miesiącu daj lub zajmij kilka tygodni) przestaje odpowiadać z powodu uruchomienia programu oom-killer. Monitorowanie serwera pokazuje, że nie działa zwykle brakuje pamięci, co jakiś czas.
Przeczytałem kilka blogów wskazujących na tę stronę, która omawia konfigurację jądra, aby lepiej zarządzać nadpisywaniem przy użyciu następujących ustawień sysctl:
vm.overcommit_memory = 2
vm.overcommit_ratio = 80
Rozumiem to (co może być błędne, ale nie mogę znaleźć kanonicznej definicji do wyjaśnienia), że zapobiega to nadmiernej alokacji pamięci przez jądro poza wymianą + 80% pamięci fizycznej.
Jednak mam również przeczytać kilka innych źródeł sugeruje, że te ustawienia nie są dobrym pomysłem - choć krytycy tego podejścia zdają się mówić „nie rób rzeczy zepsuć system, a nie próbować to kludge” w założeniu, że związek przyczynowy jest zawsze znany.
Moje pytanie brzmi: jakie są zalety i wady tego podejścia w kontekście serwera WWW Apache2 obsługującego około 10 witryn o niskim natężeniu ruchu? W moim konkretnym przypadku serwer WWW ma 512 MB pamięci RAM i 1024 MB przestrzeni wymiany. Wydaje się to wystarczające przez zdecydowaną większość czasu.
/proc/<PID>/oom_score_adj
do tego celu. Na przykład, jeśli dla sshd ustawisz oom_score_adj na -1000, Oom Killer nigdy nie będzie atakował sshd, gdy chce coś zabić. Całkowite zatrzymanie zabójcy zabójców nie jest dobrym pomysłem, ponieważ wtedy twoje programy nie będą w stanie przywrócić pamięci, a i tak umrą.Rozdział 9.6 „Overcommit and OOM” w dokumencie, o którym wspomina @dunxd, jest szczególnie graficzny na temat niebezpieczeństw związanych z dopuszczeniem overcommit. Jednak
80
wyglądało to również dla mnie interesująco, więc przeprowadziłem kilka testów.Odkryłem, że
overcommit_ratio
wpływa na całkowitą pamięć RAM dostępną dla WSZYSTKICH procesów. Procesy rootowania nie wydają się być traktowane inaczej niż zwykłe procesy użytkownika.Ustawienie współczynnika na
100
lub mniej powinno zapewnić klasyczną semantykę, w której wartości zwracanemalloc/sbrk
są wiarygodne. Ustawienie niższych współczynników100
może być sposobem na zarezerwowanie większej ilości pamięci RAM na działania niezwiązane z procesem, takie jak buforowanie i tak dalej.Tak więc na moim komputerze z 24 GiB RAM, z wyłączoną zamianą, 9 GiB w użyciu, z
top
wyświetlaniemOto niektóre
overcommit_ratio
ustawienia i ilość pamięci RAM, którą mój program RAM-konsument może pobrać (dotykając każdej strony) - w każdym przypadku program wyszedł poprawnie pomalloc
awarii.Uruchamianie kilku jednocześnie, nawet z niektórymi użytkownikami root, nie zmieniło łącznej kwoty, którą zużyli razem. Interesujące jest to, że nie był w stanie zużyć ostatnich 3+ GiB;
free
nie spadnie znacznie poniżej tego, co jest pokazane tutaj:Eksperymenty były chaotyczne - wszystko, co korzysta z malloc w chwili, gdy cała pamięć RAM jest w użyciu, ma tendencję do zawieszania się, ponieważ wielu programistów obawia się sprawdzania błędów malloc w C, niektóre popularne biblioteki kolekcji ignorują to całkowicie, a C ++ i różne inne języki są nawet gorzej.
Większość wczesnych implementacji wyobrażonej pamięci RAM dotyczyła bardzo konkretnego przypadku, w którym jeden duży proces - powiedzmy ponad 51% dostępnej pamięci - był potrzebny
fork()
, abyexec()
jakiś program wsparcia, zwykle o wiele, znacznie mniejszy. Systemy operacyjne z semantyką kopiowania przy zapisie pozwoliłyby na tofork()
, ale pod warunkiem, że jeśli rozwidlony proces faktycznie spróbuje zmodyfikować zbyt wiele stron pamięci (każda z nich musiałaby zostać utworzona jako nowa strona niezależna od początkowego ogromnego procesu) w końcu zostanie zabity. Proces nadrzędny był zagrożony tylko przy przydzielaniu większej ilości pamięci i mógł poradzić sobie z wyczerpaniem, w niektórych przypadkach po prostu czekając trochę na śmierć innego procesu, a następnie kontynuując. Proces potomny zwykle po prostu zastępuje się (zwykle mniejszym) programem przezexec()
i wtedy był wolny od zastrzeżenia.Nadmierna koncepcja Linuksa jest ekstremalnym podejściem pozwalającym zarówno na
fork()
wystąpienie, jak i na masową ogólną alokację pojedynczych procesów. Zgony OOM-killer-spowodowane zdarzyć asynchronicznie, nawet do programów, które zrobienia alokacji pamięci uchwyt odpowiedzialnie. Ja osobiście nienawidzę nadmiernego zaangażowania całego systemu, a szczególnie zabójcy zagłady - sprzyja to diabelnie ostrożnemu podejściu do zarządzania pamięcią, które infekuje biblioteki i za ich pośrednictwem każdą aplikację, która ich używa.Sugeruję ustawienie współczynnika na 100, a także posiadanie partycji wymiany, która na ogół kończy się przyzwyczajeniem się przez ogromne procesy - które często wykorzystują tylko niewielką część siebie, która zostaje upchnięta w swap, a zatem chronić ogromną większość procesów przed błędami zabójcy OOM. To powinno zabezpieczyć twój serwer przed przypadkową śmiercią, a jeśli został napisany z myślą o
malloc
odpowiedzialnym postępowaniu , nawet bezpieczny przed samobójstwem (ale nie stawiaj na to drugie).To znaczy, że używam tego w
/etc/sysctl.d/10-no-overcommit.conf
źródło