Efek konfigurasi vm.overcommit_memory

41

Server web VPS saya berjalan pada CentOS 5.4 (kernel Linux 2.6.16.33-xenU) secara tidak teratur (seperti sebulan sekali memberi atau mengambil beberapa minggu) menjadi tidak responsif karena menendang oom-killer. Pemantauan server menunjukkan bahwa itu tidak biasanya kehabisan memori, hanya sesekali.

Saya telah membaca beberapa blog yang mengarah ke halaman ini yang membahas konfigurasi kernel untuk mengelola overcommit dengan lebih baik menggunakan pengaturan sysctl berikut:

vm.overcommit_memory = 2
vm.overcommit_ratio = 80

Pemahaman saya tentang ini (yang mungkin salah, tetapi saya tidak dapat menemukan definisi kanonik untuk menjelaskan) adalah bahwa ini mencegah memori alokasi-kernel lebih dari swap + 80% dari memori fisik.

Namun, saya juga telah membaca beberapa sumber lain yang menyarankan bahwa pengaturan ini bukan ide yang baik - meskipun kritik dari pendekatan ini tampaknya mengatakan "jangan melakukan hal-hal yang merusak sistem Anda, daripada mencoba kludge ini" dengan asumsi bahwa sebab-akibat selalu diketahui.

Jadi pertanyaan saya adalah, apa pro dan kontra dari pendekatan ini , dalam konteks server web Apache2 hosting sekitar 10 situs lalu lintas rendah? Dalam kasus khusus saya, server web memiliki RAM 512Mb, dengan ruang swap 1024Mb. Ini tampaknya cukup untuk sebagian besar waktu.

dunxd
sumber

Jawaban:

32

Pengaturan overcommit_ratioke 80 kemungkinan bukan tindakan yang tepat. Menetapkan nilai ke sesuatu yang kurang dari 100 hampir selalu salah.

Alasannya adalah aplikasi linux mengalokasikan lebih dari yang sebenarnya mereka butuhkan. Katakanlah mereka mengalokasikan 8kb untuk menyimpan beberapa karakter string teks. Nah itu beberapa KB yang tidak digunakan di sana. Aplikasi banyak melakukan hal ini, dan inilah tujuan dari overcommit.

Jadi pada dasarnya dengan overcommit di 100, kernel tidak akan mengizinkan aplikasi untuk mengalokasikan lebih banyak memori daripada yang Anda miliki (swap + ram). Mengaturnya kurang dari 100 berarti Anda tidak akan pernah menggunakan semua memori Anda. Jika Anda akan mengatur pengaturan ini, Anda harus mengaturnya lebih tinggi dari 100 karena skenario yang disebutkan sebelumnya, yang sangat umum.

Sekarang, karena masalah Anda dengan pemicu pembunuh OOM, pengaturan overcommit secara manual kemungkinan tidak akan memperbaikinya. Pengaturan default (tekad heuristik) cukup cerdas.

Jika Anda ingin melihat apakah ini benar-benar penyebab masalah, lihatlah /proc/meminfoketika pembunuh OOM dijalankan. Jika Anda melihat yang Committed_ASdekat CommitLimit, tetapi freemasih menunjukkan memori bebas yang tersedia, maka ya Anda dapat secara manual menyesuaikan overcommit untuk skenario Anda. Menetapkan nilai ini terlalu rendah akan menyebabkan pembunuh OOM mulai mematikan aplikasi saat Anda masih memiliki banyak memori yang kosong. Pengaturan yang terlalu tinggi dapat menyebabkan aplikasi acak mati ketika mereka mencoba menggunakan memori yang dialokasikan, tetapi sebenarnya tidak tersedia (ketika semua memori benar-benar digunakan).

Patrick
sumber
1
Terima kasih - Saya mencoba berbagai hal dengan overcommit_ratio diatur ke 100 untuk melihat apa yang terjadi. Masalah utama yang saya miliki adalah bahwa ketika oom-killer memulai itu selalu membunuh sshd yang mencegah saya mengakses server dan melihat apa yang sedang terjadi. Saya kira yang benar-benar saya butuhkan adalah untuk menghentikan oom-killer dari menjalankan dan beberapa cara untuk merekam apa yang terjadi ketika itu akan berjalan sehingga saya dapat menemukan penyebab masalahnya.
dunxd
4
@dunxd dapat Anda gunakan /proc/<PID>/oom_score_adjuntuk tujuan ini. Misalnya, jika Anda menetapkan oom_score_adj ke -1000 untuk sshd, pembunuh oom tidak akan pernah menargetkan sshd ketika ingin membunuh sesuatu. Menghentikan pembunuh total sama sekali bukan ide yang baik karena program Anda tidak akan dapat menyimpan memori, dan mereka akan tetap mati.
Patrick
4
@dunxd diwarisi. memiliki skrip init Anda mengaturnya sendiri, dan apa pun yang dimulai oleh skrip init mewarisinya.
Patrick
4
Contoh 4 KB Anda salah. Memori virtual digunakan dengan halaman dan ukuran (terkecil) dari halaman di Linux adalah 4 KB. Itu berarti menyimpan beberapa karakter memerlukan 4 KB untuk dipetakan di suatu tempat terlepas dari pengaturan overcommitment. Contoh yang tepat dari memori lebih dari komitmen akan misalnya Anda mengalokasikan 10 KB dan hanya menggunakan 4100 byte pertama. Itu berarti dua halaman 4 KB perlu menyimpan data dan satu halaman tambahan tidak digunakan. Sistem non-overcommiting akan selalu memiliki halaman ketiga yang siap untuk menyimpan data jika permintaan tiba, sistem yang berkomitmen tidak akan memaksakan hal itu.
jlliagre
2
/ proc / self menunjuk ke proses saat ini, sehingga / proc / self / oom_score_adj dapat digunakan untuk mengubah oom_score_adj dari proses saat ini.
r_2
23

Bagian 9.6 "Komitmen berlebihan dan OOM" dalam dokumen yang menyebutkan @dunxd secara khusus menggambarkan bahaya dari mengizinkan komitmen berlebihan. Namun, itu 80tampak menarik bagi saya juga, jadi saya melakukan beberapa tes.

Apa yang saya temukan adalah bahwa overcommit_ratiomempengaruhi total RAM yang tersedia untuk SEMUA proses. Proses root tampaknya tidak diperlakukan berbeda dari proses pengguna normal.

Mengatur rasio ke 100atau kurang harus memberikan semantik klasik di mana nilai kembali dari malloc/sbrkdapat diandalkan. Pengaturan rasio lebih rendah daripada 100mungkin cara untuk memesan lebih banyak RAM untuk kegiatan non-proses seperti caching dan sebagainya.

Jadi, di komputer saya dengan 24 GiB RAM, dengan swap dinonaktifkan, 9 GiB digunakan, dengan topditampilkan

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

Berikut adalah beberapa overcommit_ratiopengaturan dan berapa banyak RAM yang bisa diambil oleh program ram-konsumen saya (menyentuh setiap halaman) - dalam setiap kasus program keluar dengan bersih begitu mallocgagal.

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

Menjalankan beberapa sekaligus, bahkan dengan beberapa sebagai pengguna root, tidak mengubah jumlah total yang mereka konsumsi bersama. Sangat menarik bahwa itu tidak dapat mengkonsumsi 3+ GiB terakhir atau lebih; yang freetidak menjatuhkan jauh di bawah apa yang ditampilkan di sini:

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

Eksperimen itu berantakan - apa pun yang menggunakan malloc pada saat ini semua RAM yang digunakan cenderung macet, karena banyak programmer yang mengerikan untuk memeriksa kegagalan malloc di C, beberapa perpustakaan koleksi populer mengabaikannya sepenuhnya, dan C ++ dan berbagai bahasa lainnya bahkan lebih buruk.

Sebagian besar implementasi awal RAM imajiner yang saya lihat adalah untuk menangani kasus yang sangat spesifik, di mana satu proses besar - katakanlah 51% + memori yang tersedia - diperlukan fork()untuk exec()beberapa program pendukung, biasanya yang jauh, jauh lebih kecil. OS dengan semantik copy-on-write akan memungkinkan fork(), tetapi dengan ketentuan bahwa jika proses bercabang benar-benar mencoba untuk memodifikasi terlalu banyak halaman memori (masing-masing kemudian harus dipakai sebagai halaman baru yang independen dari proses besar awal) itu akan berakhir terbunuh. Proses induk hanya dalam bahaya jika mengalokasikan lebih banyak memori, dan dapat menangani kehabisan, dalam beberapa kasus hanya dengan menunggu sedikit proses lain mati, dan kemudian melanjutkan. Proses anak biasanya hanya mengganti sendiri dengan program (biasanya lebih kecil) viaexec() dan kemudian bebas dari ketentuan.

Konsep overcommit Linux adalah pendekatan ekstrem untuk memungkinkan fork()terjadinya dan juga proses tunggal secara keseluruhan. Kematian OOM-pembunuh-disebabkan terjadi asynchronous, bahkan untuk program yang melakukan alokasi memori menangani secara bertanggung jawab. Saya pribadi benci overcommit seluruh sistem secara umum dan oom-killer pada khususnya - itu mendorong pendekatan setan-hati untuk manajemen memori yang menginfeksi perpustakaan dan melalui mereka setiap aplikasi yang menggunakannya.

Saya sarankan untuk mengatur rasio ke 100, dan memiliki partisi swap juga yang umumnya hanya akan berakhir digunakan oleh proses besar - yang sering hanya menggunakan sebagian kecil dari bagian diri mereka yang dimasukkan ke dalam swap, dan dengan demikian melindungi sebagian besar proses dari kesalahan pembunuh OOM. Ini harus menjaga server web Anda aman dari kematian acak, dan jika itu ditulis untuk menangani secara mallocbertanggung jawab, bahkan aman dari membunuh sendiri (tetapi jangan bertaruh pada yang terakhir).

Itu berarti saya menggunakan ini /etc/sysctl.d/10-no-overcommit.conf

vm.overcommit_memory = 2
vm.overcommit_ratio = 100
Alex North-Keys
sumber
Dan apakah Anda merekomendasikan menjaga vm.overcommit_memory menjadi 2?
Ut xD
1
Catatan bagus - memang itulah yang saya gunakan; Saya pikir saya menghilangkannya dalam jawaban saya karena sudah ada dalam pertanyaan
Alex North-Keys