Ana içeriğe geç

JVM Garbage Collector Ayarlama

Otomatik Bellek Kademeleri​

Apinizer'ın tüm modülleri (Worker, Cache, Manager, Integration, Portal) container başlangıcında entrypoint.sh üzerinden otomatik JVM bellek ayarı uygular:

  1. Container'a ayrılan bellek limiti cgroup (v1/v2) üzerinden tespit edilir; limit yoksa sunucunun toplam belleği kullanılır.
  2. Bellek kademelere göre sınıflandırılır (Worker, Manager, Integration ve Portal'da 1 GB'lık adımlarla; Cache'te 1 / 2 / 4 / 8 GB ve üzeri).
  3. Seçilen kademeye göre heap yüzdesi (MaxRAMPercentage), direct memory, metaspace, thread stack boyutu ve GC parametreleri belirlenir.

Seçilen kademe pod log'larına yazdırılır. Örnek (Worker, 4 GB):

Detected container memory: 4096MB
JVM tier: 4GB (heap 65%, direct 512m, metaspace 256m, stack 512k)
jvmOverride not set: tier defaults will override JAVA_OPTS
uyarı

Eski sürümlerdeki JVM_MEMORY_PROFILE (low/medium/high) ortam değişkeni ve "bellek 1536 MB'ı aşınca otomatik ZGC" davranışı kaldırılmıştır. Bu değişkeni tanımlamanın artık bir etkisi yoktur; ortam değişkenlerinizde varsa silebilirsiniz.

Worker (Gateway)​

Worker her kademede Java 25'in varsayılan GC'si olan G1GC'yi kullanır.

Container BellekHeapDirect MemoryMetaspaceGC Parametreleri
≤ 1 GB%50128m128mG1HeapRegionSize=1m
≤ 2 GB%60256m192mG1HeapRegionSize=1m
≤ 3 GB%60384m256mG1HeapRegionSize=2m
≤ 4 GB%65512m256mAlwaysPreTouch, MaxGCPauseMillis=100
≤ 5 GB%65768m320mAlwaysPreTouch, MaxGCPauseMillis=100
≤ 6 GB%651024m384mAlwaysPreTouch, MaxGCPauseMillis=100
≤ 7 GB%651280m384mAlwaysPreTouch, MaxGCPauseMillis=100
≤ 8 GB%651536m384mAlwaysPreTouch, MaxGCPauseMillis=100
> 8 GB%65belleğin ~%20'si (en fazla 4096m)512mAlwaysPreTouch, MaxGCPauseMillis=100

Cache (Hazelcast)​

Cache modülü 2 GB ve üzerinde ZGC kullanır. Hazelcast heap dışında da bellek kullandığı için heap oranları Worker'dan düşüktür.

Container BellekGCHeapDirect MemoryMetaspace
≤ 1 GBG1GC%5064m128m
≤ 2 GBZGC%50128m128m
≤ 4 GBZGC + AlwaysPreTouch%55192m192m
≤ 8 GBZGC + AlwaysPreTouch%55256m256m
> 8 GBZGC + AlwaysPreTouch%55384m384m

Manager​

Manager her kademede G1GC kullanır. Metaspace, yüklenen sınıf sayısı pod boyutundan bağımsız olduğu için tüm kademelerde 512m olarak sabittir.

Container BellekHeapDirect MemoryGC Parametreleri
≤ 1 GB%50128mG1HeapRegionSize=1m
≤ 2 GB%55192mG1HeapRegionSize=1m
≤ 3 GB%55256mG1HeapRegionSize=2m
≤ 4 GB%60384mAlwaysPreTouch, MaxGCPauseMillis=100
≤ 5 GB%60512mAlwaysPreTouch, MaxGCPauseMillis=100
≤ 6 GB%60640mAlwaysPreTouch, MaxGCPauseMillis=100
≤ 7 GB%60768mAlwaysPreTouch, MaxGCPauseMillis=100
≤ 8 GB%601024mAlwaysPreTouch, MaxGCPauseMillis=100
> 8 GB%60belleğin ~%15'iAlwaysPreTouch, MaxGCPauseMillis=100
uyarı

Manager için en az 2 GB bellek ayırın. 1 GB kademesinde pod log'larına şu uyarı yazılır ve tam ısınma sonrası bellek yetersiz kalabilir:

WARNING: 1GB is below the Manager minimum; heap + metaspace + JVM overhead exceed the limit under full warm-up. Use >= 2GB.

Integration ve Portal​

Integration ve Portal, Manager ile aynı heap ve direct memory kademelerini ve G1GC'yi kullanır; yalnızca metaspace kademeye göre değişir (≤ 1 GB: 128m, ≤ 2 GB: 192m, ≤ 4 GB: 256m, ≤ 5 GB: 320m, ≤ 8 GB: 384m, > 8 GB: 512m).

JAVA_OPTS ve jvmOverride​

JAVA_OPTS ile verdiğiniz parametreler ile kademe değerleri birlikte JVM'e iletilir. JVM'de aynı parametre birden fazla verilirse son verilen geçerli olur; hangisinin sona yazılacağını jvmOverride ortam değişkeni belirler:

jvmOverrideDavranış
Tanımlı değil (varsayılan)Kademe değerleri sona yazılır. JAVA_OPTS içinde kademenin de belirlediği parametreler (-XX:MaxRAMPercentage, -XX:MaxDirectMemorySize, -XX:MaxMetaspaceSize, -Xss; 4 GB ve üzerinde -XX:MaxGCPauseMillis) geçersiz kalır. Kademenin belirlemediği parametreler (örn. -Xmx, -Xms) uygulanır.
trueJAVA_OPTS sona yazılır; verdiğiniz değerler kademe değerlerinin önüne geçer.
uyarı

JAVA_OPTS içinde -XX:MaxRAMPercentage=75.0 gibi bir değer verdiyseniz ve jvmOverride=true tanımlamadıysanız, bu değer uygulanmaz; kademe değeri geçerli olur. Pod log'undaki JVM tier: ... satırı hangi değerin kullanıldığını gösterir. Kendi değerinizin geçerli olmasını istiyorsanız ortam değişkenlerine jvmOverride=true ekleyin.

GC Seçimi​

GC seçimi her zaman kullanıcıya aittir ve jvmOverride'dan bağımsızdır:

  • JAVA_OPTS içinde bir GC belirtilmezse modülün varsayılanı kullanılır (Worker, Manager, Integration ve Portal için G1GC; Cache için ≥ 2 GB'ta ZGC).
  • JAVA_OPTS içinde G1 dışında bir GC (-XX:+UseZGC, -XX:+UseSerialGC, -XX:+UseParallelGC, -XX:+UseShenandoahGC) belirtilirse, kademe değerlerindeki G1'e özel parametreler (G1HeapRegionSize) otomatik çıkarılır.
  • Cache modülünde JAVA_OPTS içinde herhangi bir GC belirtilirse, kademenin GC parametreleri (UseZGC, G1HeapRegionSize, AlwaysPreTouch) çıkarılır.

Cache modülünde kademe GC'yi açıkça belirlediği için bu temizleme, iki farklı GC parametresinin aynı anda verilip JVM'in başlamamasını önler. Diğer modüllerde kademe GC belirtmez; temizleme yalnızca G1'e özel parametrelerin uyarı üretmesini engeller.

Garbage Collector Türleri​

Apinizer'ın kullandığı base image Eclipse Temurin 25 olduğundan aşağıdaki GC algoritmaları desteklenir.

G1GC (Garbage-First)​

Java 25'in varsayılan GC'sidir. Region tabanlı, paralel ve eş zamanlı çalışır; heap'i eşit bölgelere ayırarak çöp toplama süresini tahmin edilebilir kılar.

  • Apinizer'da: Worker, Manager, Integration ve Portal'ın tüm kademelerinde; Cache'in 1 GB kademesinde
  • Avantaj: Dengeli throughput ve düşük GC duraklaması
  • JVM parametresi: Varsayılan olduğu için belirtmek gerekmez (-XX:+UseG1GC)

ZGC (Z Garbage Collector)​

Düşük gecikmeli, ölçeklenebilir GC'dir. GC duraklamaları heap boyutundan bağımsız olarak genellikle 1 ms altındadır.

  • Apinizer'da: Cache modülünün 2 GB ve üzeri kademelerinde varsayılan
  • Avantaj: Sabit ve çok düşük GC duraklaması, büyük heap'lerde iyi performans
  • Dezavantaj: Colored pointer ve multi-mapping nedeniyle daha fazla native bellek tüketir
  • JVM parametresi: -XX:+UseZGC

Serial GC​

Tek thread'li, en basit GC algoritmasıdır. Apinizer kademelerinde otomatik seçilmez; JAVA_OPTS ile elle seçilebilir.

  • JVM parametresi: -XX:+UseSerialGC

ZGC Güvenlik Sınırı​

ZGC, diğer GC'lere kıyasla daha fazla native bellek (heap dışı bellek) kullanır. Bu nedenle Worker, Manager, Integration ve Portal modüllerinde, JAVA_OPTS içinde ZGC seçip MaxRAMPercentage değerini %70'in üzerinde verirseniz değer otomatik olarak %70'e düşürülür ve pod log'una şu uyarı yazılır:

WARNING: MaxRAMPercentage=80% is too high for ZGC. Capping to 70%.
bilgi

Cache modülünde bu sınır uygulanmaz; Cache'in ZGC kademeleri zaten %50–55 heap kullanır.

GC Logları​

Worker, GC olaylarını varsayılan olarak stdout'a yazar (-Xlog:gc, toplama başına yaklaşık bir satır). Bu loglar kubectl logs ile ve normal log toplama altyapınızla görülebilir; OOM veya yavaşlık incelemelerinde GC baskısını geriye dönük değerlendirmeyi sağlar.

Ortam DeğişkeniVarsayılanAçıklama
APINIZER_GC_LOG(tanımlı değil = açık)false verilirse Worker GC logları kapatılır
bilgi

OOM anında otomatik heap dump bilinçli olarak açılmaz: 4–16 GB'lık bir dump, container'ın geçici disk (ephemeral storage) limitini aşarak pod'un tahliye edilmesine yol açabilir. Heap dump almak için Bellek Sızıntıları ve OOM Hataları sayfasındaki diagnostics endpoint'lerini kullanın.

Yapılandırma Örnekleri​

Otomatik Kademe (Önerilen)​

JAVA_OPTS içine heap/GC parametresi eklemeyin; yalnızca container bellek limitini belirleyin:

resources:
requests:
memory: "4Gi"
limits:
memory: "4Gi"
# Worker sonucu: G1GC, %65 heap, direct 512m, metaspace 256m

Kendi Heap Değerinizi Kullanma​

env:
- name: JAVA_OPTS
value: "-XX:MaxRAMPercentage=70.0"
- name: jvmOverride
value: "true"

jvmOverride=true olmadan MaxRAMPercentage değeri kademe değeri tarafından ezilir.

Farklı Bir GC Seçme​

env:
- name: JAVA_OPTS
value: "-XX:+UseZGC"

GC seçimi jvmOverride gerektirmez. Heap yüzdesi kademe değerinden gelir; ZGC için %70 üst sınırını aşmayın.

MaxRAMPercentage Güvenli Sınırlar Tablosu​

jvmOverride=true ile kendi heap değerinizi verecekseniz aşağıdaki üst sınırları aşmamanız önerilir:

GC TürüGüvenli Maks YüzdeNeden
Serial GC%80Minimum native bellek overhead'i
G1GC%75Orta düzeyde native bellek kullanımı (region metadata, remembered sets)
ZGC%70Colored pointer ve multi-mapping nedeniyle yüksek native bellek tüketimi
uyarı

Bu sınırlar genel önerilerdir. Yoğun thread kullanımı, büyük native buffer'lar veya çok sayıda dosya tanımlayıcı kullanan iş yükleri için daha düşük değerler gerekebilir.

Sorun Giderme​

OOM Kill​

Belirti: Pod sürekli restart oluyor, kubectl describe pod çıktısında OOMKilled görünüyor.

NedenÇözüm
jvmOverride=true ile yüksek MaxRAMPercentagejvmOverride'ı kaldırarak kademe değerlerine dönün veya yüzdeyi yukarıdaki tablonun altına çekin
ZGC ile yüksek MaxRAMPercentage%70 veya altına düşürün
Container belleği yetersizresources.limits.memory değerini artırın (Manager için en az 2 GB)
Native bellek sızıntısıBellek Sızıntıları ve OOM Hataları sayfasına bakın

Yüksek GC Duraklaması​

Belirti: Yanıt süreleri periyodik olarak artıyor, P99 latency yüksek.

  • Worker GC loglarını (kubectl logs) inceleyerek toplama sıklığını ve sürelerini kontrol edin.
  • 4 GB ve üzeri kademelerde MaxGCPauseMillis=100 otomatik uygulanır; daha küçük pod'larda belleği 4 GB'a çıkarmak duraklama hedefini devreye alır.

JAVA_OPTS Değerim Uygulanmıyor​

Belirti: JAVA_OPTS içinde verdiğiniz MaxRAMPercentage veya MaxDirectMemorySize etkisiz görünüyor.

Neden: jvmOverride tanımlı değilken kademe değerleri son sözü söyler. Pod log'unda jvmOverride not set: tier defaults will override JAVA_OPTS (Cache'te jvmOverride=false (default): tier defaults will override JAVA_OPTS) satırı görünür.

Çözüm: Ortam değişkenlerine jvmOverride=true ekleyin.

İlgili Sayfalar​