Elasticsearch Garbage Collection Process

Bu yazımızda, “Garbage collection JVM ile nasıl çalışmaktadır?” ve “JvmGcMonitorService problemiyle karşılaşılması durumunda neler yapılabilir?” sorularına yanıt arayacağız.

Garbage collection sistemdeki RAM durumunu gözlemleyerek, hangi nesnelerin kullanıldığını, hangilerinin kullanılmadığını ve kullanılmayan nesneleri silen bir process olarak düşünülebilir. Kullanımda olan bir nesne ya da referans nesne için programınız bir pointer (işaretçi) tutar. Yine aynı mantıkla kullanımda olmayan bir nesne ya da referansı olmayan nesne için programınız artık herhangi bir pointer belirlemeyecektir. Böylelikle, referansı olmayan bir nesne tarafından kullanılmayan RAM geri kazanılabilecektir.

C gibi programlama dilinde, allocating ve deallocating manuel bir işlemdir. Bu Java’da otomatik olarak garbage collector tarafından gerçekleştirilmektedir. Basit çalışma mantığı:

Step 1: Marking

İlk adım marking (belirleme) olarak isimlendirilir. Garbage collector hangi RAM parçalarının kullanıldığını ve kullanılmadığını belirler.

Referans nesneler mavi, Referansı olmayan nesneler ise sarı ile gösterilmiştir. Tüm nesnelerin marking fazı içerisinde taranması gereklidir ve bu durum zaman alan bir işlem olabilmektedir.

Step 2: Normal Deletion

Bellekte yer açabilmek adına, normal deletion referansı olmayan nesneleri siler.

Memory allocator, bellekteki boş alanları saptar ve yeni nesneleri allocate eder.

Step 2a: Deletion with Compacting

Performansı daha da arttırmak için referansı olmayan nesneleri silmek yerine, referansı olanlar sıkıştırabilir. Bu durum yeni bellek tahsisini çok daha kolay ve hızlı hale getirmektedir.

Why Generational Garbage Collection?

JVM içerisindeki tüm nesnelerin işaretlenmesi ve sıkıştırılması verimli olmayacaktır. Allocate edilen nesnelerin sayısı arttıkça ve nesne listesi büyüyüp gittikçe bu durum daha uzun garbage collection zamanı demektir.

JVM Generations

Nesne allocation davranışından öğrenilen bilgiler, JVM performansını geliştirmek için kullanılabilir. Ayrıca, heap küçük parçalara ayrılır. Bunlar; Young Generation, Old ya da Tenured Generation ve Permanent Generation.

Young Generation, yeni nesnelerin allocate edildiği ve yaşlandığı (aged) yerdir. Eğer young generation dolarsa, bu durum minor garbage collection’a sebebiyet verir. Minor collection, high object mortality rate (yüksek nesne ölüm oranı) baz alınarak optimize edilebilir. Ölü nesnelerle (dead objects) dolan young generation çok çabuk toplanır. Ancak hayatta kalan bazı nesneler (surviving objects) yaşlanır ve sonunda old generation’a geçiş yapar.

Stop the World Event – Tüm minor garbage collection “Stop the World” olaylarıdır. Yani bu işlem tamamlanıncaya kadar tüm uygulama işlemlerinin (application threads) durdurulduğu anlamına gelir.

Old Generation, uzun süre hayatta kalan nesneleri (long surviving object) saklamak için kullanılır. Tipik olarak, young generation nesne için bir threshold değeri ayarlanır. Bu degere ulaşıldığında da nesne old generation’a aktarılır. Old generation’da toparlanmaya ihtiyaç duyar ve major garbage collection ortaya çıkar.

Major garbage collection’da aslında bir “Stop the World” olaylarıdır ve tüm canlı nesneleri içerdiğinden dolayı bir tık daha yavaştır.

Permanent Generation, JVM tarafından uygulamada kullanılan sınıfları ve yöntemleri tanımlamak için gereken gerekli metadata verilerini içerir. Ek olarak, Java SE kütüphane sınıfları ve yöntemleri burada bulunabilir. Eğer JVM artık ihtiyacı olmayan unloaded sınıfları keşfederse onları toplatabilir ve ihtiyacı dahilindeki diğer sınıflara yer verdirebilir. Permanent generation full garbage colletion’a dahil edilir.

Çok daha fazla detaylı bilgiye erişmek için Java Garbage Collection Basics makalesini ziyaret ediniz.

Not #1: JVM Visual VM Tools kullanılarak monitor edilebilir.

———

Elasticsearch loglarına baktınız ve aşağıdaki gibi bir uyarı mesajıyla karşılaştınız. JvmGcMonitorService!…

2018-01-31T19:30:22,507][WARN ][o.e.m.j.JvmGcMonitorService] [Elasticsearch] [gc][3479] overhead, spent [536ms] collecting in the last [1s]

[2018-01-31T19:43:24,673][WARN ][o.e.m.j.JvmGcMonitorService] [Elasticsearch] [gc][old][5175][12] duration [8.8m], collections [2]/[8.8m], total [8.8m]/[11.1m], memory [1.9gb]->[679mb]/[1.9gb], all_pools {[young] [16.5mb]->[958.5kb]/[66.5mb]}{[survivor] [7mb]->[0b]/[8.3mb]}{[old] [1.9gb]->[678.8mb]/[1.9gb]}

Not #2: Loglar arasında Threshold vs gibi uyarı mesajlarıda olacaktır çok yüksek ihtimalle.

Elasticsearch servisini ya da sisteme dahil node varsa restart etmeyi denediniz ancak health bir türlü %100 green duruma geçmiyor ve ya geçiyor sonra crash oluyorsa ya da belli bir seviyeye gelip örneğin %80, daha sonra .hprof uzantılı bir dosya elasticsearch dizininin bulunduğu yerde oluşuyorsa sorun makinanın maksimum seviyede RAM kullanmasından kaynaklanıyor olabilir. Bir başka ihtimalde, günlük index boyutu çok büyükse, elasticsearch’e atanan RAM bu index’i ayağa kaldıramıyor olabilir.

Böyle bir durumda hem makinanın RAM kapasitesinin arttırılması hem de Elasticsearch’e  ya da node’a atanan (JVM) RAM miktarının arttırılması faydalı olabilmektedir. Ayrıca servis versiyonunun da yükseltilmesi yine sorunun çözümü için kullanılabilir (örneğin 5.6.3 -> 6.0 gibi).

Not #3: Servis upgrade işlemi sırasında index’lerin re-indexing yapılıp yapılmayacağı araştırılmalıdır.