Node.js'te bellek sızıntısını (memory leak) nasıl tespit edip düzeltirsiniz?
Cevap
Belirti genelde şudur: process'in heap kullanımı trafik sabitken bile sürekli artar, GC süreleri uzar, sonunda FATAL ERROR: Reached heap limit ile çöker veya container OOMKilled olur.
Tespit adımları
- Metrikleri izleyin:
process.memoryUsage()(heapUsed,rss,external) veya Prometheusprom-clientvarsayılan metrikleri. Testere dişi desen normaldir; tabanın sürekli yükselmesi sızıntıdır. - Heap snapshot alın: belirli aralıklarla 2-3 snapshot alıp karşılaştırın.
node --inspect app.js # Chrome DevTools -> Memory sekmesi
node --heapsnapshot-signal=SIGUSR2 app.js
kill -USR2 <pid> # çalışan process'ten snapshotimport v8 from "node:v8";
v8.writeHeapSnapshot(); // programatik- Snapshot'lar arası Comparison görünümünde sürekli artan nesne tipine ve retainer zincirine (onu kimin tuttuğuna) bakın.
- Araçlar: Chrome DevTools,
clinic heapprofiler, APM'lerin heap profiling özellikleri.
Yaygın sebepler
// 1) Sınırsız büyüyen in-memory cache
const cache = new Map();
app.get("/user/:id", async (req, res) => {
cache.set(req.params.id, await loadUser(req.params.id)); // hiç silinmiyor
});- Global/modül seviyesinde biriken diziler ve Map'ler. Çözüm:
lru-cachegibi boyut ve TTL sınırlı cache. - Kaldırılmayan event listener'lar (
emitter.onher istekte eklenipoffyapılmıyor). NodeMaxListenersExceededWarningile uyarır. - Temizlenmeyen
setIntervalve timer'lar. - Büyük nesneleri yakalayan closure'lar.
- Hiç resolve olmayan, sonsuza kadar bekleyen promise'ler ve kapatılmayan stream'ler.
Geçici önlemler
--max-old-space-size heap limitini container belleğiyle uyumlu hale getirir ama sızıntıyı çözmez; yalnızca çökmeyi geciktirir. Kalıcı çözüm retainer zincirindeki referansı koparmaktır.
İlgili Node.js soruları
- cluster modülü ile worker_threads arasındaki fark nedir? Hangisini ne zaman kullanırsınız?
- Node.js event loop'u nasıl çalışır? libuv'nin rolü ve event loop aşamaları nelerdir?
- Node.js'te asenkron kodda hata yönetimi nasıl yapılır? unhandledRejection nedir?
- Node.js'te stream nedir? Türleri nelerdir ve backpressure ne demektir?
- process.nextTick, Promise.then, setImmediate ve setTimeout(fn, 0) hangi sırayla çalışır?
- Express.js'te middleware nedir ve nasıl çalışır?
Bu konuda başka bir soru biliyor musun?
Mülakatta karşılaştığın soruları ekle, onaylandıktan sonra yayına alınsın.