Auswirkungen der Konfiguration von vm.overcommit_memory

41

Mein VPS-Webserver, der unter CentOS 5.4 (Linux-Kernel 2.6.16.33-xenU) ausgeführt wird (z. B. einmal im Monat ein paar Wochen), reagiert nicht mehr, da der Eoom-Killer einschaltet. Die Überwachung des Servers zeigt, dass dies nicht der Fall ist Normalerweise fehlt der Speicher, nur hin und wieder.

Ich habe einige Blogs gelesen, die auf diese Seite verweisen, in der die Konfiguration des Kernels zur besseren Verwaltung von Überlastungen mit den 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 dies zu klären) ist, dass dies verhindert, dass der Kernel über Swap + 80% des physischen Speichers hinaus Speicher zuweist.

Ich habe jedoch auch einige andere Quellen gelesen, die darauf hindeuten, 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 diesen Fehler zu versuchen", in der Annahme, dass Die Ursache ist immer bekannt.

Meine Frage ist also, was sind die Vor- und Nachteile dieses Ansatzes im Zusammenhang mit einem Apache2-Webserver, der ungefähr 10 Websites mit geringem Datenverkehr hostet? 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.

dunxd
quelle

Antworten:

32

Die Einstellung overcommit_ratioauf 80 ist wahrscheinlich nicht die richtige Aktion. Ein Wert von 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 eine Textzeichenfolge mit mehreren Zeichen zu speichern. Nun, das sind mehrere KB, die genau dort ungenutzt sind. Anwendungen tun dies häufig, und für diese Zwecke wurde Overcommit entwickelt.

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

Nun, was Ihr Problem mit dem Auslösen des OOM-Killers betrifft, wird das Problem wahrscheinlich nicht durch manuelles Festlegen eines Overcommits behoben. Die Standardeinstellung (heuristische Bestimmung) ist ziemlich intelligent.

Wenn Sie sehen möchten, ob dies wirklich die Ursache des Problems ist, /proc/meminfoüberprüfen Sie, wann der OOM-Killer ausgeführt wird. Wenn Sie sehen, dass dies Committed_ASin der Nähe liegt CommitLimit, aber freeimmer noch freier Speicher verfügbar ist, können Sie das Overcommit für Ihr Szenario manuell anpassen. Wenn Sie diesen Wert zu niedrig einstellen, startet der OOM-Killer das Beenden von Anwendungen, wenn noch genügend Speicher verfügbar ist. Wenn Sie diesen Wert zu hoch einstellen, können zufällige Anwendungen abstürzen, wenn sie versuchen, den zugewiesenen Speicher zu nutzen, der jedoch nicht verfügbar ist (wenn der gesamte Speicher tatsächlich belegt ist).

Patrick
quelle
1
Danke - Ich versuche Dinge mit overcommit_ratio auf 100 zu setzen, um zu sehen, was passiert. Das Hauptproblem, das ich habe, ist, dass beim Starten von oom-killer immer sshd beendet wird, was mich daran hindert, auf den Server zuzugreifen und zu sehen, was los ist. Ich schätze, ich brauche wirklich, um zu verhindern, dass oom-killer läuft, und um aufzuzeichnen, was passiert, wenn es gelaufen wäre, damit ich die Ursache des Problems finden kann.
dunxd
4
@dunxd können Sie /proc/<PID>/oom_score_adjfür diesen Zweck verwenden. Wenn Sie beispielsweise oom_score_adj für sshd auf -1000 setzen, zielt der oom-Killer niemals auf sshd ab, wenn er etwas töten möchte. Es ist keine gute Idee, oom killer vollständig zu stoppen, da Ihre Programme dann nicht in der Lage sind, Speicher zu malloc, und sie werden trotzdem sterben.
Patrick
4
@ Dunxd ist geerbt. Lassen Sie Ihr Init-Skript es auf sich selbst setzen, und alles, was vom Init-Skript gestartet wird, übernimmt es.
Patrick
4
Ihr 4 KB Beispiel ist falsch. Der virtuelle Speicher wird mit Seiten verwendet und die (kleinste) Größe einer Seite unter Linux beträgt 4 KB. Das bedeutet, dass zum Speichern einiger Zeichen 4 KB erforderlich sind, unabhängig von den Einstellungen für die Überbelegung. Ein gutes Beispiel für eine Überbelegung des Speichers ist beispielsweise, dass Sie 10 KB zuweisen und nur die ersten 4100 Bytes verwenden. Das bedeutet, dass zwei 4-KB-Seiten zum Speichern der Daten erforderlich sind und eine zusätzliche Seite nicht verwendet wird. Bei nicht überlasteten Systemen ist die dritte Seite immer zum Speichern von Daten bereit, wenn die Anforderung eintrifft. Bei überlasteten Systemen wird dies nicht erzwungen.
Juli
2
/ proc / self zeigt auf den aktuellen Prozess, sodass / proc / self / oom_score_adj verwendet werden kann, um oom_score_adj des aktuellen Prozesses zu ändern.
r_2
23

In Abschnitt 9.6, „Overcommit und OOM“ des Dokuments, das von @dunxd erwähnt wird, werden die Gefahren einer Überbeanspruchung besonders deutlich. Das 80sah aber auch für mich interessant aus, deshalb habe ich ein paar Tests durchgeführt.

Was ich festgestellt habe, ist, dass sich dies overcommit_ratioauf den gesamten für ALLE Prozesse verfügbaren RAM auswirkt. Root-Prozesse scheinen nicht anders behandelt zu werden als normale Benutzerprozesse.

Das Setzen des Verhältnisses auf 100oder weniger sollte die klassische Semantik liefern, bei der Rückgabewerte malloc/sbrkzuverlässig sind. Durch Festlegen eines niedrigeren Verhältnisses können Sie 100mehr RAM für nicht prozessbezogene Aktivitäten wie Caching usw. reservieren.

Also, auf meinem Computer mit 24 GB RAM, mit deaktiviertem Swap, 9 GB im Einsatz, mit topAnzeigen

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

Hier sind einige overcommit_ratioEinstellungen und wie viel RAM mein RAM-Consumer-Programm abrufen könnte (Berühren jeder Seite) - in jedem Fall wurde das Programm nach einem Fehler sauber beendet malloc.

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

Wenn mehrere gleichzeitig ausgeführt wurden, selbst wenn einige als Root-Benutzer fungierten, änderte sich nicht die Gesamtmenge, die sie zusammen verbrauchten. Es ist interessant, dass es nicht in der Lage war, die letzten 3+ GiB oder so zu konsumieren. Das freehat nicht viel unterschritten, was hier gezeigt wird:

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

Die Experimente waren chaotisch - alles, was im Moment malloc verwendet, neigt zum Absturz, da viele Programmierer schreckliche Angst haben, in C nach malloc-Fehlern zu suchen, einige beliebte Sammlungsbibliotheken es vollständig ignorieren und C ++ und verschiedene andere Sprachen sogar schlechter.

Die meisten der frühen Implementierungen von imaginärem RAM betrafen einen sehr speziellen Fall, in dem ein einzelner großer Prozess - etwa 51% des verfügbaren Speichers - erforderlich war, fork()um exec()ein Support-Programm zu erstellen, normalerweise ein viel, viel kleineres. Betriebssysteme mit Copy-on-Write-Semantik würden das zulassen fork(), jedoch mit der Maßgabe, dass, wenn der Fork-Prozess tatsächlich versucht, zu viele Speicherseiten zu ändern (von denen jede unabhängig vom anfänglichen riesigen Prozess als neue Seite instanziiert werden müsste). es würde am Ende getötet werden. Der übergeordnete Prozess war nur dann in Gefahr, wenn mehr Speicher zugewiesen wurde, und konnte das Auslaufen in einigen Fällen bewältigen, indem er nur ein bisschen darauf wartete, dass ein anderer Prozess ausfiel, und dann fortfuhr. Der untergeordnete Prozess hat sich normalerweise nur durch ein (normalerweise kleineres) Programm über ersetztexec() und war dann frei von der Maßgabe.

Das Overcommit-Konzept von Linux ist ein extremer Ansatz, um sowohl das fork()Auftreten als auch die Überlagerung einzelner Prozesse zu ermöglichen. Todesfälle, die durch OOM-Killer verursacht wurden, treten asynchron auf, selbst bei Programmen, die mit der Speicherzuweisung verantwortungsbewusst umgehen. Ich persönlich hasse systemweites Overcommit im Allgemeinen und den Oom-Killer im Besonderen - es fördert einen teuflischen Ansatz für die 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 riesigen Prozessen genutzt 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 dem OOM-Killer-Fehler. Dies sollte Ihren Webserver vor dem zufälligen Tod schützen, und wenn er für den mallocverantwortungsvollen Umgang geschrieben wurde , sogar vor dem Selbstmord (aber wetten 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
Alex North-Keys
quelle
Und würden Sie empfehlen, vm.overcommit_memory auf 2 zu belassen?
Ut xD
1
Gute Nachricht - das ist in der Tat, was ich benutze; Ich glaube, ich habe es in meiner Antwort weggelassen, weil es bereits in der Frage steht
Alex North-Keys