Ana içeriğe geç
Kategoriye Dön

Bellek Sızıntısı Tespiti ve Çözümü

Linux sunucuda bellek sızıntısı (memory leak) tespiti, hangi sürecin bellek tükettiğini bulma ve çözüm yöntemleri.

Okuma süresi: 13 dk Sorun Giderme
bellekmemory leakRAMvalgrindsmemlinuxperformans

İçindekiler

Giriş

Bellek sızıntısı, bir uygulamanın kullandığı belleği düzgün şekilde serbest bırakmaması sonucu RAM kullanımının zamanla sürekli artmasıdır. Sonunda sistem belleği tükenir, swap alanı dolmaya başlar ve sunucu yavaşlar veya çöker. Bu rehberde bellek sızıntısını tespit etme ve çözme yöntemlerini ele alacağız.

Belirtiler

Bellek sızıntısının tipik belirtileri:

  • RAM kullanımı zamanla sürekli artıyor (yeniden başlatmadan sonra normale dönüyor)
  • free -h çıktısında kullanılabilir bellek giderek azalıyor
  • Swap kullanımı artıyor
  • Uygulama zamanla yavaşlıyor
  • OOM (Out of Memory) killer devreye giriyor ve süreçler öldürülüyor
  • dmesg'de oom-kill mesajları görünüyor

Adım 1: Mevcut Bellek Durumunu Kontrol Et

hljs bash
# Genel bellek durumu
free -h

# Detaylı bellek bilgisi
cat /proc/meminfo

# Swap kullanımı
swapon --show

# OOM killer logları
dmesg | grep -i 'oom\|killed process\|out of memory'
journalctl -k | grep -i 'oom\|killed'

free -h çıktısında available değeri toplam RAM'in %10'unun altına düştüyse bellek baskısı var demektir.

Adım 2: Hangi Süreç En Çok Bellek Kullanıyor?

hljs bash
# ps ile bellek kullanımına göre sıralama
ps aux --sort=-%mem | head -20

# top ile gerçek zamanlı izleme
top
# 'M' tuşuna basarak belleğe göre sırala

# smem ile daha detaylı bellek analizi
sudo apt install smem -y
smem -r -k | head -20

# Süreç bazlı bellek kullanımı
ps -eo pid,ppid,cmd,%mem,%cpu --sort=-%mem | head -20

# Belirli bir sürecin bellek kullanımını izle
watch -n 2 'ps aux | grep uygulama_adi | grep -v grep'

Adım 3: Bellek Sızıntısını Doğrula

Bir sürecin gerçekten bellek sızdırıp sızdırmadığını doğrulamak için zaman içindeki değişimi izleyin:

hljs bash
# Belirli bir sürecin PID'ini bul
pgrep -f uygulama_adi

# Sürecin bellek kullanımını her 30 saniyede bir kaydet
while true; do
    echo "$(date): $(cat /proc/PID/status | grep VmRSS)"
    sleep 30
done

# /proc/PID/smaps ile detaylı bellek haritası
cat /proc/PID/smaps | grep -E '(Rss|Pss|Shared|Private)' | awk '{sum += $2} END {print sum/1024 " MB"}'

# Sürecin bellek büyümesini izle
pidstat -r -p PID 10

Adım 4: Sistem Genelinde Bellek Analizi

hljs bash
# Slab cache kullanımı (kernel bellek sızıntısı)
cat /proc/slabinfo | sort -k3 -rn | head -20
slabtop

# Büyük bellek tüketen süreçler (smaps)
for pid in $(ls /proc | grep -E '^[0-9]+$'); do
    rss=$(cat /proc/$pid/smaps 2>/dev/null | grep Rss | awk '{sum+=$2} END {print sum}')
    if [ ! -z "$rss" ] && [ "$rss" -gt 100000 ]; then
        echo "PID $pid: $((rss/1024)) MB - $(cat /proc/$pid/comm 2>/dev/null)"
    fi
done 2>/dev/null | sort -t: -k2 -rn | head -10

# Anonim bellek kullanımı
grep -E '(AnonPages|Mapped|Shmem)' /proc/meminfo

Adım 5: Uygulama Bazlı Çözümler

Node.js Bellek Sızıntısı

hljs bash
# Node.js heap dump al
kill -USR2 PID  # heapdump modülü gerektirir

# Node.js bellek limitini ayarla
node --max-old-space-size=512 app.js

# PM2 ile otomatik yeniden başlatma (bellek limiti)
pm2 start app.js --max-memory-restart 500M

PHP-FPM Bellek Sızıntısı

hljs bash
# /etc/php/8.x/fpm/pool.d/www.conf
# pm.max_requests = 500  # Her worker 500 istek sonrası yeniden başlar

# PHP bellek limiti
# memory_limit = 256M

MySQL/MariaDB Bellek Kullanımı

hljs bash
# MySQL bellek kullanımını kontrol et
mysql -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';"
mysql -e "SHOW STATUS LIKE 'Innodb_buffer_pool_pages%';"

# /etc/mysql/mysql.conf.d/mysqld.cnf
# innodb_buffer_pool_size = 256M  # RAM'in %25-50'si
# query_cache_size = 0  # MySQL 8'de kaldırıldı

Java Bellek Sızıntısı

hljs bash
# JVM heap dump
jmap -dump:format=b,file=/tmp/heap.hprof PID

# JVM bellek istatistikleri
jstat -gcutil PID 1000 10

# JVM heap boyutunu sınırla
java -Xmx512m -Xms256m -jar app.jar

Adım 6: Acil Çözümler

Bellek Önbelleğini Temizle

hljs bash
# Sayfa önbelleğini temizle (güvenli)
sync && echo 1 > /proc/sys/vm/drop_caches

# Dentry ve inode önbelleğini temizle
sync && echo 2 > /proc/sys/vm/drop_caches

# Tüm önbellekleri temizle (dikkatli kullanın)
sync && echo 3 > /proc/sys/vm/drop_caches

drop_caches komutu üretim ortamında dikkatli kullanılmalıdır. Önbellek temizlendikten sonra disk I/O geçici olarak artabilir.

Sızdıran Süreci Yeniden Başlat

hljs bash
# Servisi yeniden başlat
sudo systemctl restart servis_adi

# Belirli bir süreci öldür ve yeniden başlat
sudo kill -9 PID

# Otomatik yeniden başlatma için systemd ayarı
# /etc/systemd/system/servis.service
# [Service]
# Restart=always
# RestartSec=5
# MemoryMax=512M  # Bellek limiti

Swap Alanını Artır

hljs bash
# Geçici swap dosyası oluştur
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# Kalıcı hale getir (/etc/fstab)
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

Adım 7: Uzun Vadeli Çözümler

hljs bash
# systemd ile bellek limiti uygula
# /etc/systemd/system/servis.service
# [Service]
# MemoryMax=1G
# MemoryHigh=800M

# cgroup ile bellek limiti
cgcreate -g memory:myapp
echo 536870912 > /sys/fs/cgroup/memory/myapp/memory.limit_in_bytes
cgexec -g memory:myapp uygulama

# Düzenli yeniden başlatma (geçici çözüm)
# crontab -e
# 0 4 * * * systemctl restart sızdıran_servis

Sonuç

Bellek sızıntısı sorunlarını çözmek için önce ps aux ve smem ile hangi sürecin bellek tükettiğini tespit edin, ardından zaman içindeki büyümeyi izleyerek sızıntıyı doğrulayın. Kısa vadede sızdıran servisi yeniden başlatın ve systemd ile bellek limiti uygulayın. Uzun vadede uygulamanın kaynak kodunu inceleyerek sızıntının kaynağını bulun. Sorun devam ederse REXE destek ile iletişime geçin.