Varsayılan Linux OOM katilini kapat?


37

Linux'taki OOM katili, sık sık çeşitli uygulamalarla tahribata yol açıyor ve bunu geliştirmek için çekirdek geliştirme tarafında pek bir şey yapılmadığı anlaşılıyor. Yeni bir sunucu kurarken en iyi uygulama olarak, bellek kullanımında varsayılanı tersine çevirmek, yani, vm.overcommit_memory=2kendi kullanımınız için açılmasını istemediğiniz sürece , onu kapatın ( ) daha iyi olmaz mıydı? Ve bu kullanım davaları, aşırı ihbarda bulunmak istediğinizi bildiğiniz yerde ne olurdu?

Bir bonus olarak, durumdaki davranış, alana vm.overcommit_memory=2bağlı olduğu vm.overcommit_ratiove yer değiştirdiği için, bu iki kurulumun makul bir şekilde çalışmaya devam etmesi için ikinci ikisini boyutlandırmak için iyi bir kural nedir?

Yanıtlar:


63

İlginç bir benzetme ( http://lwn.net/Articles/104179/ adresinden ):

Bir uçak şirketi, uçaklarını daha az yakıtla uçurmanın daha ucuz olduğunu keşfetti. Uçaklar daha hafif olacak ve daha az yakıt kullanacak ve paradan tasarruf sağlanacaktı. Nadir durumlarda, ancak yakıt miktarı yetersizdi ve uçak çarpacaktı. Bu sorun, şirket mühendisleri tarafından özel bir OOF (yakıt dışı) mekanizması geliştirilerek çözüldü. Acil durumlarda bir yolcu seçildi ve uçaktan atıldı. (Gerektiğinde prosedür tekrarlandı.) Geniş bir teori yapısı geliştirildi ve atılacak kurbanı uygun şekilde seçme sorununa birçok yayın ayrıldı. Kurban rastgele seçilmeli mi? Yoksa en ağır olanı mı seçmeli? Veya en eskisi? Yolcuların çıkartılmaması için ödeme yapması, Yani kurban gemideki en fakir olacak mı? Örneğin en ağır kişi seçildiyse, pilot olması durumunda özel bir istisna olmalı mı? Birinci sınıf yolcular muaf tutulmalı mı? Şimdi OOF mekanizması mevcut olduğu için, her seferinde ve sonra aktif hale getirilecek ve yakıt sıkıntısı olmasa bile yolcuları çıkaracaktı. Mühendisler hala bu arızaya neden olduğunu tam olarak çalışıyorlar.


11
Bundan çok zevk aldım, çıkardığın için teşekkürler.
Nick Bolton

32

OOM katili, sadece sisteminizi aşırı yüklediyseniz, çok büyük zarar görüyor. Yeterince değiş tokuş yapın ve aniden büyük miktarlarda RAM yemeye karar veren uygulamaları çalıştırmayın ve bir sorun yaşamayacaksınız.

Sorularınıza özel olarak cevap vermek için:

  • Genel davada abartmayı reddetmenin iyi bir fikir olduğunu sanmıyorum; bir hata döndürerek brk(2) (ve malloc(3) gibi onu kullanan sarmalayıcılar) ile başa çıkmak için çok az sayıda uygulama yazılmıştır . Bunu önceki işimde denediğimde, bellek dışı hataları giderebilecek her şeyi yalnızca bir OOM'un sonuçlarıyla başa çıkmakta olduğundan daha fazla güçlendiriyordu (bu, bizim durumumuzda). OOM ortaya çıktığında ara sıra hizmeti yeniden başlatmak zorunda kalmaktan çok daha kötüydü - çünkü GFS'nin dışkı buharı bırakan bir yığın olduğu için bütün bir kümeyi yeniden başlatmak zorunda kaldık.
  • Belleği aşan herhangi bir işlem için fazladan çalışmak istiyorsunuz. Buradaki en yaygın iki suçlu Apache ve JVM'dir, ancak birçok uygulama bunu daha fazla veya daha az derecede yapıyor. Onlar düşünmek onlar belki onlar büyük bir kesimine doğru kapalı kapmak böylece, gelecekte bir noktada çok fazla bellek gerekir. Aşırı etkin özellikli bir sistemde, çekirdek "ne olursa olsun, aslında bu sayfalara yazmak istediğinizde beni rahatsız edin" der ve kötü bir şey olmaz. Aşırı çalışan bir sistemde, çekirdek "hayır, o kadar fazla hafızanız olamaz, geleceğin bir noktasında hepsini yazacak olursanız, benim için bir hafıza yok!" Diyor. ve tahsis başarısız olur. Hiçbir şeyden beri"oh, tamam, bu daha az miktarda işlem veri segmentine sahip olabilir miyim?" malloc, gitmenin uygun olduğunu düşünüyor ve geçersiz bir bellek konumuna yazarak segfault'a neden oluyor. Neyse ki, JVM başlangıçta vaaz ettiği her şeyi yapar (böylece JVM'niz genellikle fark ettiğiniz derhal başlar veya hemen ölür), ancak Apache, her yeni çocukla korkak şeyler yapıyor; bu da üretimde heyecan verici etkiler yaratabiliyor (tekrarlanamayan "bağlantılarla başa çıkmıyor" "heyecan türleri".
  • Overcommit_ratio'umu% 50 varsayılan değerinden daha yükseğe ayarlamak istemem. Yine, benim test yaklaşık 80 veya 90 kudreti kurduktan rağmen ses serin bir fikir gibi, çekirdek uygunsuz zamanlarda belleğin büyük parçalar gerektirir ve yüksek overcommit oranına sahip tam yüklü sistem olasılıkla yetersiz yedek hafızaya sahip olmaktır Çekirdeğin ihtiyacı olduğunda (korkuya, kötülük ve oopslara yol açar). Bu yüzden fazla mesai yapmak, yeni ve daha eğlenceli bir başarısızlık modu sunar - sadece bellek bittiğinde gerçekleşen herhangi bir işlemi yeniden başlatmak yerine, makineniz çöker ve makinede her şeyin kesilmesine neden olur. HARİKA!
  • Aşırı hızlanmayan bir sistemde yer değiştirmek, uygulamalarınızın ihtiyaç duyduğu ama kullanılmayan belleğe ve sağlıklı bir güvenlik marjına ihtiyaç duyduğuna bağlıdır. Belirli bir durumda neyin gerekli olduğunu çalışmak, okuyucu için bir alıştırma olarak bırakılır.

Temel olarak, benim deneyimim, aşırı yüklemeyi kapatmak, pratikte teoride göründüğü kadar nadiren işe yarayan hoş bir deney. Linux çekirdeği geliştiricileri hemen hemen her zaman daha akıllı senden daha vardır ve varsayılan engin, için en iyi iş - Bu güzel çekirdekte diğer tunables ile deneyimlerimi karşılık gelen engin Vakaların çoğunda. Onları yalnız bırakın ve bunun yerine hangi sürecin sızıntısı olduğunu bulun ve düzeltin.


2
Birisi web sunucumu kurduğu için yedekleme işlemimin ölmesini istemiyorum. İstisnalar iyi, ancak varsayılan güvenlik ve tutarlılık olmalıdır. OOM gibi optimizasyonlar IMHO manuel olarak açılmalıdır. Kodlama gibidir, temiz bir şekilde kodlarsınız ve sonra en iyi duruma getirirsiniz. Aşırı taahhüt güzel bir özelliktir, ancak varsayılan olmamalıdır.
Aki

1
Birisi web sunucunuzu kurduğundan yedekleme işleminizin ölmesini istemiyorsanız, web sunucunuzu bir DoS'nin sistemdeki kaynakların ezilmesine neden olacak şekilde yapılandırmayın.
womble

8GB RAM'im var ve yalnızca Firefox kullanıyor ve sanal bir makine bazen OOM katilinin VM'yi öldürmesine neden oluyor. Unreal Engine 4'ü derleyen her clang çağrısı 1 ~ 1,5 GB bellek alır ve yine OOM katili her zaman birini öldürür. Şimdi genel olarak bununla iyiyim, OOM katili olmadan muhtemelen yine de farklılaşacaklardı. OOM katilinin bir süreci öldürmek istediği her zaman, kötü işlem gerçekten öldürülmeden önce sistemim 10 dakika donuyor. Belki de böcek? Büyük ihtimalle. İstiyorum mu Kesinlikle hayır. İşte bu yüzden, OOM katilini etkisiz hale getirmek isteyebilirsiniz.
Shahbaz

1
Bunları bir kutuda yapıyorsanız daha fazla RAM'e ihtiyacınız vardır ve fazla ödemeyi devre dışı bırakmak sadece daha da kötüleşir.
Ben Lutgens

6

Hmm, tam anlamıyla aşırı hırs ve OOM katili lehine tartışmalara ikna olmadım ... Womble yazarken,

“OOM katili yalnızca sisteminizi aşırı yüklediyseniz büyük zarar veriyor. Yeterince takas verin ve aniden büyük miktarda RAM yemeye karar veren uygulamaları çalıştırmayın ve bir sorun yaşamayacaksınız.”

Aşırı komisyon ve OOM katilinin zorlanmadığı veya 'gerçekten' hareket etmediği bir ortam senaryosunu tanımlamakla ilgili (eğer tüm uygulamalar gerektiğinde hafıza tahsis etmişse ve tahsis edilecek yeterli sanal hafıza varsa, hafıza yazanlar hafıza tahsislerini yakından takip eder) hatalar, bu yüzden bir aşırı alım stratejisi etkin olsa bile, fazla çalışan bir sistemden gerçekten bahsetmedik). Bu, fazla mesai ve OOM katilinin müdahalesine ihtiyaç duyulmadığında en iyi şekilde çalıştığını ve bu stratejinin destekçilerinin çoğu tarafından paylaşabildiğim kadarıyla, söyleyebildiğim kadarıyla paylaştığı (ve çok fazla şey söyleyemeyeceğimi ...) açık bir kabulle ilgilidir. Morover, belleği önceden dağıtırken belirli davranışlara sahip uygulamalara atıfta bulunmak, varsayılan bir ayar yerine, belirli bir işlemenin dağıtım düzeyinde ayarlanabileceğini düşünmemi sağlıyor.

JVM'yi ilgilendiren şey için, sanal bir makinedir, başlangıçta ihtiyaç duyduğu tüm kaynakları tahsis etmesi gerekir , bu nedenle uygulamaları için 'sahte' ortamını oluşturabilir ve kullanılabilir kaynaklarını ana bilgisayardan ayrı tutabilir. çevre, mümkün olduğunca. Bu nedenle, bir 'dış' OOM koşulunun (aşırı görev / OOM katilinden / her neyse neden olduğu) veya kendi durumuyla karışan bir durumdan dolayı bir süre sonra, başlangıçta başarısız olması tercih edilebilir. dahili OOM kullanım stratejileri (genel olarak, bir VM, başından itibaren gerekli kaynakları edinmeli ve ana bilgisayar sistemi onları sonuna kadar 'görmezden gelmelidir', aynı şekilde, bir grafik kartı ile paylaşılan herhangi bir fiziksel koç asla asla - ve olamaz - OS tarafından dokundu).

Apache hakkında, tüm sunucuyu ara sıra öldürmenin ve yeniden başlatmanın, tek bir çocuğun tek bir bağlantıyla birlikte (= çocuğun / bağlantının) başlangıcından (tamamen yeni bir durumdaymış gibi) başarısız olmasına izin vermekten daha iyi olduğundan şüpheliyim. JVM, bir süre başka bir örnek çalıştırdıktan sonra oluşturulmuş). Sanırım en iyi 'çözüm' belirli bir içeriğe bağlı olabilir. Örneğin, bir e-ticaret hizmeti göz önüne alındığında, örneğin, devam eden bir sipariş sonlandırmasını kesmek riskiyle tüm hizmeti kaybetmek yerine, alışveriş çizelgesiyle rastgele bir şekilde bağlantı kurma birkaç bağlantıya sahip olmak çok tercih edilebilir. (belki de daha kötüsü) bir ödeme işlemi, davanın tüm sonuçları ile (belki zararsız, ama belki de zararlıdır) ve elbette, sorunlar ortaya çıktığında,

Aynı şekilde, bir iş istasyonunda, OOM katilinin ilk tercihi olmak için en fazla kaynağı tüketen ve bu nedenle ilk tercih olarak işlenen işlem, muhtemelen bir tek video dönüştürücüsü veya bir işleme yazılımı gibi bellek yoğun bir uygulama olabilir. kullanıcı dokunulmak istemiyor. Bu düşünceler, OOM katili temerrüt politikasının çok agresif olduğunu gösteriyor. Bazı dosya sistemlerine benzeyen bir "en kötü uyum" yaklaşımı kullanır (OOMK, kısa sürede daha fazla müdahaleyi önlemek amacıyla, öldürülen alt işlem sayısını azaltırken, mümkün olduğu kadar fazla bellek kullanır.) Bir fs daha sonra daha fazla disk alanı tahsis edebilir, o zaman dosya büyüdüğü ve böylece bir dereceye kadar parçalanmayı önleyen daha fazla tahsisi önlemek için, aslında belli bir dosya için ihtiyaç duyulur.

Bununla birlikte, “en uygun” bir yaklaşım gibi zıt bir politikanın tercih edilebileceğini düşünüyorum, bu nedenle belirli bir noktada ihtiyaç duyulan tam hafızayı boşaltmak ve boşa harcanabilecek “büyük” süreçlerle uğraşmamak bellek, ancak aynı zamanda olmayabilir, ve çekirdek bunu bilemez (hmm, sayfa erişim izlerinin sayım ve zaman izlemesinin, bir işlem bellek ayırıyorsa, artık bir işlem gerektirip gerekmediğini tahmin etmek için ipucu verdiğini tahmin edebilirim) hafızayı boşa harcıyor veya sadece çok kullanıyor, ancak bir hafıza boşluğunu hafızadan ve cpu yoğun bir uygulamadan ayırmak için erişim gecikmeleri cpu döngüleri üzerinde ağırlıklandırılmalıdır , ancak bu tür bir sezgiselin aşırı bir yükü olabilir.

Ayrıca, daha az olası işlemi öldürmenin her zaman iyi bir seçim olduğu doğru olmayabilir. Örneğin, bir masaüstü ortamında (örneğin bir nettop veya sınırlı kaynakları olan bir netbook düşünelim) bir kullanıcı birkaç sekmeli bir tarayıcı çalıştırıyor olabilir (bu nedenle, bellek tüketen - bunun OOMK için ilk tercih olduğunu varsayalım) , ayrıca birkaç başka uygulama (kaydedilmemiş veri içeren bir kelime işlemci, bir posta istemcisi, bir pdf okuyucu, bir medya oynatıcı, ...), ayrıca bir kaç (sistem) servet ve bir kaç dosya yöneticisi örneği. Şimdi, bir OOM hatası oluyor ve kullanıcı ağ üzerinde 'önemli' sayılan bir şey yaparken, OOMK tarayıcıyı öldürmeyi seçiyor ... kullanıcı hayal kırıklığına uğrayacak. Öte yandan, birkaç dosya yöneticisini kapatmak

Her neyse, kullanıcının ne yapacağı konusunda kendi başına bir karar vermesi gerektiğini düşünüyorum. Bir masaüstü (= interaktif) sistemde, kullanıcının herhangi bir uygulamayı kapatmasını (ancak birkaç sekmeyi kapatmak bile yeterli olabilir) ve tercihini idare etmesini istemek için yeterli kaynak ayrılması koşuluyla yapılması oldukça kolay olması gereken bir işlemdir. Yeterli alan varsa ek bir takas dosyası oluşturmaktan oluşur). Hizmetler için (ve genel olarak), iki olası geliştirmeyi de düşünürdüm: Biri OOM katil müdahalelerinin yanı sıra, hataların kolayca hata ayıklanabileceği şekilde bir hata / hata bildirimi (örneğin bir API yeni işlem oluşturma veya çatallama sürecini bildirerek - Apache gibi bir sunucunun uygun bir düzeltme ekiyle belirli hatalar için daha iyi bir günlük kaydı sağlayabildiğini bildirmek; bu, fazla işlem yapan / OOMK’un çaba gösterdiği çabalardan bağımsız olarak yapılabilir; ikincisinde, ancak önemsiz olmak üzere, OOMK algoritmasının ince ayarını yapmak için bir mekanizma kurulabilir - bir dereceye kadar, süreç bazında bir süreç için belirli bir politikanın tanımlanmasının mümkün olduğunu biliyorum; İlgili süreçleri tanımlamak ve onlara belirli bir önem derecesi vermek (listelenen niteliklere göre) vermek için bir veya daha fazla uygulama adı (veya kimlik) listesine dayalı 'merkezi' yapılandırma mekanizması; böyle bir mekanizma da (veya en azından) katmanlandırılmalıdır, böylece üst seviye kullanıcı tanımlı bir liste, sistem (dağıtım) tanımlı bir liste ve (alt seviye) uygulama tanımlı girdiler ( Örneğin, bir DE dosya yöneticisi OOMK'a herhangi bir örneği güvenli bir şekilde öldürmesi talimatını verebilir,

Morover, uygulamaların çalışma zamanında 'önem' düzeylerini artırmalarını veya azaltmalarını sağlamak için bir bellek sağlanabilir (örneğin bellek yönetimi amacıyla ve uygulama önceliğine bağlı olmadan), örneğin bir Word işlemcisi ile başlayabilir. Düşük bir 'öneme' sahip olmakla birlikte, bir dosyaya basılmadan önce bazı veriler saklandığından veya bir yazma işlemi gerçekleştirildiğinden ve bu işlem sona erdiğinde bir kez daha düşük öneme sahip olduğundan, daha düşük önem kazanır (benzer şekilde, bir dosya yöneticisi yalnızca geçtiğinde düzeyi değişebilir. Ayrı işlemler kullanmak yerine, veri ve mağduriyetle uğraşmak için dosyaları göndermek ve Apache farklı çocuklara farklı önem dereceleri verebilir ya da sysadmins tarafından belirlenen ve Apache'nin ya da başka herhangi bir sunucunun maruz bıraktığı politikaya göre bir çocuk durumunu değiştirebilir - ayarlar). Tabii ki, böyle bir API kötüye kullanılabilir / kötüye kullanılabilir, ancak bence çekirdeğin sistemde olup bitene ilişkin herhangi bir bilgi olmadan (ve yaratılışın hafıza tüketimi / zamanı ya da benzeri bir şey olmadan) boşu boşaltma işlemleri için çekirdeğin keyfi öldürülmesiyle karşılaştırıldığında küçük bir endişe kaynağı olduğunu düşünüyorum. 'benim için yeterince alakalı ya da' doğrulayan 'değil) - sadece kullanıcılar, yöneticiler ve program yazarları bir nedenden dolayı bir sürecin' hala gerekli 'olup olmadığını, nedeninin ne olduğunu ve / veya uygulamanın bir devlet lideri olup olmadığını gerçekten belirleyebilir veri kaybına veya öldürüldüğünde diğer zararlara / sorunlara; ancak, bir işlem tarafından elde edilen ve beklemedeki işlemlerle elde edilen işlemlerin bir işlemden daha yüksek bir 'durumda' olup olmadığını anlatabilecekleri gibi belirli bir türden kaynakları (dosya tanımlayıcıları, ağ soketleri vb.) aramak gibi bazı varsayımlar yapılabilir. bir set,

Ya da sadece aşırı alım yapmaktan kaçının ve çekirdeğin yapması gerekenleri ayırması, çekirdeği yapması gerekenleri yapmasına izin verin (ancak onları OOM katilinin yaptığı gibi keyfi bir şekilde kurtarmamak), işlemleri planlamak, açlıktan ve çıkmazları önlemek (veya onlardan kurtarmak), tam olarak önlenmeyi sağlamak ve hafıza boşlukları ayırma vb.

Ayrıca aşırı ticaret yaklaşımları hakkında biraz daha kelime harcadım. Diğer tartışmalardan, aşırı istişareyle ilgili temel kaygılardan birinin (hem isteme sebebi hem de olası bir sorun kaynağı olarak) çatal kullanımından oluştuğu fikrine yer verdim: dürüst olmak gerekirse, tam olarak kopyaların tam olarak ne olduğunu bilmiyorum. yazma stratejisi uygulanır, ancak herhangi bir agresif (veya iyimser) politikanın, takas benzeri bir yerellik stratejisiyle hafifletilebileceğini düşünüyorum. Yani, bir çatallı işlem kodu sayfalarını ve zamanlama yapılarını sadece klonlamak (ve ayarlamak) yerine, ana işlemin daha sık yazmak için eriştiği sayfalardan birini seçerek, gerçek bir yazmadan önce birkaç diğer veri sayfası kopyalanabilir (yani, yazma işlemleri için bir sayaç kullanarak).

Her şey, elbette, IMHO.


5
“Morover, uygulamaların çalışma zamanında 'önem' düzeylerini yükseltmelerini veya düşürmelerini sağlamak için bir API sağlanabilir” Önemdir /proc/$PID/oom_adj.
Vi.

1
JVM ile ilgili olarak, bazı durumlarda hafızanın üstesinden gelmesini istemenizi sağlayan bir sonuç vardır: orijinal JVM'nizden başka bir JVM oluşturmak isterseniz, fork () işlevini çağırır. Bir çatal çağrısı, orijinal işlemi (ilk önce), işlemi gerçekten başlatana kadar hafıza olarak tahsis eder. Yani bir 4GB JVM varsa ve overcommit yoksa, bunu yapmak için bellek 8GB gerekir, bundan yeni 512KB JVM oluşturmak istiyorum ki ...
Alçı

4
@Vi. Görünüşe göre şimdi/proc/$PID/oom_score_adj
erm3nda

1

Eğer hafızanız süreçler tarafından sistemin dengesini tehdit edebilecek derecede ayrıntılı olarak kullanılmışsa, OOM katili ortaya çıkar. OOM Killer'ın görevi, işlemin geri kalanının sorunsuz çalışması için yeterli hafıza boşaltılana kadar işlemleri öldürmesidir. OOM Killer, öldürmek için “en iyi” süreci seçmek zorundadır. Buradaki “En İyi”, öldürme sırasında maksimum belleği boşaltacak olan ve aynı zamanda sistem için en az önemli olan süreci ifade eder. Birincil hedef, yapılan hasarı en aza indiren ve aynı zamanda boş kalan bellek miktarını en yükseğe çıkaran en az işlem sayısını öldürmektir. Bunu kolaylaştırmak için, çekirdek her işlem için oom_score'u korur. / Proc dosya sistemindeki işlemlerin her birinin oom_score'unu pid dizini altında görebilirsiniz.

# cat /proc/10292/oom_score

Herhangi bir işlemin oom_score değeri ne kadar yüksekse, bellek dışı bir durumda OOM Killer tarafından öldürülme olasılığı da o kadar yüksek olur.

Kredi: - Linux çekirdeği OOM katilini başlatıyor

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.