it-swarm.com.de

Auswirkungen der Konfiguration von vm.overcommit_memory

Mein VPS-Webserver, der unter CentOS 5.4 (Linux-Kernel 2.6.16.33-xenU) ausgeführt wird, reagiert unregelmäßig (wie einmal im Monat einige Wochen geben oder nehmen) nicht mehr, da oom-kill einschaltet. Die Überwachung des Servers zeigt, dass dies nicht der Fall ist Normalerweise geht der Speicher aus, nur von Zeit zu Zeit.

Ich habe einige Blogs gelesen, die auf diese Seite verweisen, in denen die Konfiguration des Kernels zur besseren Verwaltung von Overcommit mithilfe der folgenden Sysctl-Einstellungen erläutert wird:

vm.overcommit_memory = 2
vm.overcommit_ratio = 80

Mein Verständnis davon (was vielleicht falsch ist, aber ich kann keine kanonische Definition finden, um es zu klären) ist, dass dies verhindert, dass der Kernel Speicher über Swap + 80% des physischen Speichers hinaus zu viel zuweist.

Ich habe jedoch auch einige andere Quellen gelesen, die darauf hinweisen, dass diese Einstellungen keine gute Idee sind - obwohl die Kritiker dieses Ansatzes zu sagen scheinen: "Tun Sie nichts, um Ihr System zu beschädigen, anstatt es zu versuchen." dieser Kludge "in der Annahme, dass die Ursache immer bekannt ist.

Meine Frage lautet also: Was sind die Vor- und Nachteile dieses Ansatzes im Kontext eines Apache2-Webservers, auf dem etwa 10 Websites mit geringem Datenverkehr gehostet werden? In meinem speziellen Fall verfügt der Webserver über 512 MB RAM mit 1024 MB Swap-Speicher. Dies scheint für die überwiegende Mehrheit der Zeit angemessen zu sein.

41
dunxd

Einstellung overcommit_ratio bis 80 ist wahrscheinlich nicht die richtige Aktion. Das Einstellen des Werts auf weniger als 100 ist fast immer falsch.

Der Grund dafür ist, dass Linux-Anwendungen mehr zuweisen, als sie wirklich benötigen. Angenommen, sie weisen 8 KB zu, um ein paar Zeichen Text zu speichern. Nun, das sind mehrere KB, die genau dort nicht verwendet werden. Anwendungen tun dies häufig, und dafür ist Overcommit konzipiert.

Im Grunde genommen erlaubt der Kernel bei Overcommit bei 100 nicht, dass Anwendungen mehr Speicher zuweisen als Sie haben (Swap + RAM). Wenn Sie den Wert auf weniger als 100 einstellen, wird niemals der gesamte Speicher belegt. Wenn Sie diese Einstellung festlegen möchten, sollten Sie sie aufgrund des oben genannten Szenarios, das häufig vorkommt, höher als 100 einstellen.

Was nun Ihr Problem mit dem Auslösen des OOM-Killers betrifft, wird das manuelle Festlegen von Overcommit dies wahrscheinlich nicht beheben. Die Standardeinstellung (heuristische Bestimmung) ist ziemlich intelligent.

Wenn Sie sehen möchten, ob dies wirklich die Ursache des Problems ist, schauen Sie sich /proc/meminfo wenn der OOM-Killer läuft. Wenn Sie das sehen Committed_AS liegt in der Nähe von CommitLimit, aber free zeigt immer noch freien Speicher an. Dann können Sie das Overcommit manuell für Ihr Szenario anpassen. Wenn Sie diesen Wert zu niedrig einstellen, beginnt der OOM-Killer, Anwendungen zu beenden, wenn Sie noch genügend Speicherplatz haben. Wenn Sie es zu hoch einstellen, können zufällige Anwendungen sterben, wenn sie versuchen, den ihnen zugewiesenen Speicher zu verwenden, der jedoch nicht verfügbar ist (wenn der gesamte Speicher tatsächlich verbraucht ist).

33
Patrick

Abschnitt 9.6 "Overcommit und OOM" in dem von @dunxd erwähnten Dokument zeigt besonders deutlich die Gefahren des Zulassens von Overcommit. Allerdings sah der 80 Auch für mich interessant aus, so dass ich einige Tests durchführte.

Was ich gefunden habe ist, dass overcommit_ratio Die Gesamtmenge RAM, die ALLEN Prozessen zur Verfügung steht) beeinflusst. Root-Prozesse scheinen nicht anders behandelt zu werden als normale Benutzerprozesse.

Das Setzen des Verhältnisses auf 100 Oder weniger sollte die klassische Semantik liefern, bei der Rückgabewerte von malloc/sbrk Zuverlässig sind. Wenn Sie ein niedrigeres Verhältnis als 100 Einstellen, können Sie möglicherweise mehr RAM für nicht prozessbezogene Aktivitäten wie Caching usw.) reservieren.

Also, auf meinem Computer mit 24 GiB RAM, bei deaktiviertem Swap, 9 GiB in Verwendung, wobei top angezeigt wird

Mem:  24683652k total,  9207532k used, 15476120k free,    19668k buffers
Swap:        0k total,        0k used,        0k free,   241804k cached

Hier sind einige overcommit_ratio Einstellungen und wie viel RAM mein RAM-Consumer-Programm greifen konnte (jede Seite berühren) - in jedem Fall wurde das Programm sauber beendet, sobald malloc gescheitert.

 50    ~680 MiB
 60   ~2900 MiB
 70   ~5200 MiB
100  ~12000 MiB

Das gleichzeitige Ausführen mehrerer Dateien, selbst bei einigen als Root-Benutzer, hat die Gesamtmenge, die sie zusammen verbraucht haben, nicht geändert. Es ist interessant, dass es nicht in der Lage war, die letzten 3+ zu konsumieren GiB oder so; das free fiel nicht viel unter das, was hier gezeigt wird:

Mem:  24683652k total, 20968212k used,  3715440k free,    20828k buffers

Die Experimente waren chaotisch - alles, was im Moment malloc verwendet, stürzt ab RAM wird verwendet), da viele Programmierer schrecklich sind, nach Malloc-Fehlern in C zu suchen. Einige beliebte Sammlungsbibliotheken ignorieren dies vollständig und C++ und verschiedene andere Sprachen sind noch schlimmer.

Die meisten frühen Implementierungen von imaginären RAM, die ich gesehen habe, betrafen einen sehr spezifischen Fall, in dem ein einzelner großer Prozess - beispielsweise 51% + des verfügbaren Speichers - für fork() benötigt wurde Um exec() ein Unterstützungsprogramm zu erstellen, normalerweise ein viel, viel kleineres. Betriebssysteme mit Copy-on-Write-Semantik würden die fork() zulassen, jedoch mit der Maßgabe, dass der gegabelte Prozess Tatsächlich wurde versucht, zu viele Speicherseiten zu ändern (von denen jede unabhängig vom anfänglich großen Prozess als neue Seite instanziiert werden müsste). Dies würde zum Ende führen. Der übergeordnete Prozess war nur in Gefahr, wenn mehr Speicher zugewiesen wurde, und konnte dies Handle out out, in einigen Fällen nur, indem Sie ein wenig auf das Absterben eines anderen Prozesses warten und dann fortfahren. Der untergeordnete Prozess ersetzte sich normalerweise nur durch ein (normalerweise kleineres) Programm über exec() und war dann frei des Vorbehalts.

Das Overcommit-Konzept von Linux ist ein extremer Ansatz, um sowohl das Auftreten von fork() als auch die massive Gesamtzuordnung einzelner Prozesse zu ermöglichen. OOM-Killer-verursachte Todesfälle treten asynchron auf, selbst bei Programmen, die do verantwortungsbewusst mit der Speicherzuweisung umgehen. Ich persönlich hasse systemweit Overcommit im Allgemeinen und den Oom-Killer im Besonderen - es fördert einen teuflischen Ansatz bei der Speicherverwaltung, der Bibliotheken infiziert und über sie jede App, die sie verwendet.

Ich würde vorschlagen, das Verhältnis auf 100 zu setzen und auch eine Swap-Partition zu haben, die im Allgemeinen nur von großen Prozessen verwendet wird - die oft nur einen winzigen Bruchteil des Teils von sich selbst verwenden, der in Swap gestopft wird, und somit Schützen Sie die überwiegende Mehrheit der Prozesse vor der Fehlfunktion des OOM-Killers. Dies sollte Ihren Webserver vor dem zufälligen Tod schützen, und wenn er so geschrieben wurde, dass er verantwortungsbewusst mit malloc umgeht, sollte er sogar sicher sein, sich selbst zu töten (aber setzen Sie nicht auf Letzteres).

Das heißt, ich benutze dies in /etc/sysctl.d/10-no-overcommit.conf

vm.overcommit_memory = 2
vm.overcommit_ratio = 100
24
Alex North-Keys