Effetti della configurazione di vm.overcommit_memory


41

Il mio server Web VPS in esecuzione su CentOS 5.4 (kernel Linux 2.6.16.33-xenU) in modo irregolare (come una volta al mese dare o prendere alcune settimane) non risponde a causa dell'avvio di Oom-Killer. Il monitoraggio del server mostra che non funziona normalmente esaurisce la memoria, solo ogni tanto.

Ho letto un paio di blog che puntano a questa pagina che discute la configurazione del kernel per gestire meglio l'overcommit usando le seguenti impostazioni sysctl:

vm.overcommit_memory = 2
vm.overcommit_ratio = 80

La mia comprensione di ciò (che può essere errata, ma non riesco a trovare una definizione canonica per chiarire) è che ciò impedisce al kernel di allocare eccessivamente la memoria oltre lo swap + 80% della memoria fisica.

Tuttavia, ho anche letto alcune altre fonti che suggeriscono che queste impostazioni non sono una buona idea, anche se i critici di questo approccio sembrano dire "non fare le cose per rompere il tuo sistema, piuttosto che tentare questo clamore" nell'ipotesi che la causalità è sempre nota.

Quindi la mia domanda è: quali sono i pro e i contro di questo approccio , nel contesto di un web server Apache2 che ospita circa 10 siti a basso traffico? Nel mio caso specifico, il server Web ha 512 MB di RAM, con 1024 MB di spazio di swap. Questo sembra essere adeguato per la stragrande maggioranza delle volte.

Risposte:


32

L'impostazione overcommit_ratiosu 80 non è probabilmente l'azione giusta. L'impostazione del valore su un valore inferiore a 100 è quasi sempre errata.

La ragione di ciò è che le applicazioni linux allocano più di quello di cui hanno veramente bisogno. Supponiamo che stanzino 8kb per memorizzare una stringa di testo di coppia. Bene questo è diversi KB inutilizzati proprio lì. Le applicazioni lo fanno molto, ed è per questo che è progettato l'overcommit.

Quindi fondamentalmente con overcommit a 100, il kernel non consentirà alle applicazioni di allocare più memoria di quanta ne abbiate (swap + ram). Impostandolo a meno di 100 significa che non userai mai tutta la tua memoria. Se hai intenzione di impostare questa impostazione, dovresti impostarla su un valore superiore a 100 a causa del suddetto scenario, che è abbastanza comune.

Ora, per quanto riguarda il tuo problema con l'attivazione del killer OOM, l'impostazione manuale del sovraccarico non risolverà probabilmente questo problema. L'impostazione predefinita (determinazione euristica) è abbastanza intelligente.

Se vuoi vedere se questa è davvero la causa del problema, guarda /proc/meminfoquando viene eseguito il killer OOM. Se vedi che Committed_ASè vicino CommitLimit, ma freemostra ancora memoria libera disponibile, allora puoi regolare manualmente il sovraccarico per il tuo scenario. Se si imposta questo valore su un valore troppo basso, OOM Killer inizierà a uccidere le applicazioni quando si ha ancora molta memoria libera. L'impostazione su un valore troppo alto può causare la morte di applicazioni casuali quando tentano di utilizzare la memoria allocata, ma non è effettivamente disponibile (quando tutta la memoria viene effettivamente utilizzata).


1
Grazie - Sto provando a fare qualcosa con overcommit_ratio impostato su 100 per vedere cosa succede. Il problema principale che ho è che quando Oom-Killer si avvia, uccide invariabilmente sshd impedendomi di accedere al server e vedere cosa sta succedendo. Immagino che ciò di cui ho davvero bisogno è fermare l'esecuzione di Oom-Killer e alcuni mezzi per registrare cosa succede quando sarebbe corso in modo che io possa trovare la causa del problema.
Dunxd,

4
@dunxd è possibile utilizzare /proc/<PID>/oom_score_adjper questo scopo. Ad esempio, se imposti oom_score_adj su -1000 per sshd, il killer di oom non prenderà mai di mira sshd quando vuole uccidere qualcosa. Fermare completamente il killer non è una buona idea dato che i tuoi programmi non saranno in grado di sminuire la memoria e moriranno comunque.
Patrick,

4
@dunxd è ereditato. avere lo script init impostato su se stesso e tutto ciò che è stato avviato dallo script init lo eredita.
Patrick,

4
Il tuo esempio da 4 KB è sbagliato. La memoria virtuale viene utilizzata con le pagine e la dimensione (più piccola) di una pagina in Linux è di 4 KB. Ciò significa che per memorizzare un paio di caratteri è necessario mappare 4 KB da qualche parte, indipendentemente dalle impostazioni di sovraccarico. Un esempio corretto di memoria rispetto all'impegno sarebbe ad esempio allocare 10 KB e utilizzare solo i primi 4100 byte. Ciò significa che due pagine da 4 KB devono archiviare i dati e una pagina aggiuntiva non viene utilizzata. I sistemi che non eseguono il commit eccessivo avranno sempre quella terza pagina pronta per l'archiviazione dei dati nel caso dovesse arrivare la domanda, mentre i sistemi di commit non lo faranno valere.
jlliagre,

2
/ proc / self punta al processo corrente, quindi / proc / self / oom_score_adj potrebbe essere usato per cambiare oom_score_adj del processo corrente.
r_2,

23

La sezione 9.6 "Overcommit e OOM" nel documento che @dunxd menziona è particolarmente grafica sui pericoli di consentire l'overcommit. Tuttavia, 80mi è sembrato interessante anche per me, quindi ho condotto alcuni test.

Quello che ho scoperto è che overcommit_ratioinfluenza la RAM totale disponibile per TUTTI i processi. I processi di root non sembrano essere trattati in modo diverso dai normali processi dell'utente.

L'impostazione del rapporto su 100o meno dovrebbe fornire la semantica classica da cui i valori di ritorno malloc/sbrksono affidabili. Impostare rapporti inferiori a quelli che 100potrebbero essere un modo per riservare più RAM per attività non di processo come la memorizzazione nella cache e così via.

Quindi, sul mio computer con 24 GiB di RAM, con swap disabilitato, 9 GiB in uso, con topvisualizzazione

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

Ecco alcune overcommit_ratioimpostazioni e la quantità di RAM che il mio programma ram-consumer potrebbe raccogliere (toccando ogni pagina) - in ogni caso il programma è uscito in modo pulito una volta mallocfallito.

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

Eseguirne diversi contemporaneamente, anche con alcuni come utente root, non ha modificato la quantità totale consumata insieme. È interessante che non sia stato in grado di consumare gli ultimi 3+ GiB o giù di lì; il freenon è sceso molto al di sotto di quanto mostrato qui:

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

Gli esperimenti sono stati disordinati: tutto ciò che utilizza malloc al momento, tutta la RAM in uso tende a bloccarsi, dal momento che molti programmatori sono terribili nel controllare gli errori di malloc in C, alcune librerie di raccolte popolari lo ignorano del tutto, e C ++ e varie altre lingue sono persino peggio.

La maggior parte delle prime implementazioni della RAM immaginaria che ho visto sono state per gestire un caso molto specifico, in cui un singolo grande processo - diciamo il 51% + di memoria disponibile - era necessario fork()per exec()un programma di supporto, di solito molto, molto più piccolo. I sistemi operativi con semantica copy-on-write consentirebbero fork(), ma a condizione che se il processo biforcato tentasse effettivamente di modificare troppe pagine di memoria (ognuna delle quali dovrebbe quindi essere istanziata come una nuova pagina indipendente dall'enorme processo iniziale) finirebbe per essere ucciso. Il processo genitore era in pericolo solo se allocava più memoria e riusciva a esaurirsi, in alcuni casi semplicemente aspettando che un altro processo morisse e poi continuava. Il processo figlio di solito si è appena sostituito con un programma (generalmente più piccolo) tramiteexec() ed era quindi libero dalla condizione.

Il concetto di overcommit di Linux è un approccio estremo per consentire sia il fork()verificarsi sia per consentire ai singoli processi di sovrallocare in modo massiccio. Morti OOM-killer-causata avvengono in modo asincrono, anche per i programmi che fanno allocazione di memoria maniglia in modo responsabile. Personalmente odio il sovraccarico a livello di sistema in generale e l'oom-killer in particolare - promuove un approccio diabolico alla cura della memoria che infetta le librerie e attraverso di esse ogni app che le utilizza.

Suggerirei di impostare il rapporto su 100 e di avere anche una partizione di swap che generalmente finirebbe solo per essere utilizzata da enormi processi - che spesso usano solo una piccola parte della parte di se stessi che viene inserita nello swap, e quindi proteggere la stragrande maggioranza dei processi dalle disfunzioni del killer OOM. Ciò dovrebbe proteggere il tuo server Web dalla morte casuale e, se è stato scritto per gestire in modo mallocresponsabile, anche sicuro dall'uccidere se stesso (ma non scommettere su quest'ultimo).

Ciò significa che sto usando questo in /etc/sysctl.d/10-no-overcommit.conf

vm.overcommit_memory = 2
vm.overcommit_ratio = 100

E consiglieresti di mantenere vm.overcommit_memory su 2?
Ut xD,

1
Una buona nota: è proprio quello che sto usando; Penso di averlo omesso nella mia risposta perché è già nella domanda
Alex North-Keys
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.