Laravel Octane (FrankenPHP) altında bellek sızıntısını nasıl debug ederim?
Soru
Laravel Octane'i FrankenPHP sürücüsüyle `max-requests=500` ile çalıştırıyoruz. Yüksek trafikte worker'ların bellek tüketimi hızla artıyor, RAM şişip sunucu kilitlenme noktasına geliyor. PHP-FPM'de her istek sonrası bellek temizlenirken Octane'in durumsal yapısında singleton'lar, static değişkenler ve third-party paketlerin yol açtığı bu sızıntıyı nasıl debug ederim? Worker'ları kalıcı tutarken belleği nasıl optimize ederim?
Cevap
Kısa cevap: Tahmin etme, ölç — Octane’de worker uzun ömürlü olduğu için istekler arasında biriken her şey sızar; önce neyin biriktiğini izleyip yakala, sonra stateful tarafı hook’larda sıfırla.
Asıl mesele şu: PHP-FPM “her istekte taze süreç” varsayar, Octane ise worker’ı ayakta tutar. Bu varsayımı bozan her şey — büyüyen static array’ler, request state tutan singleton’lar, her istekte yeniden register edilen listener/binding’ler, sıfırlanmayan global store’lar (Log, Auth, current request) — sessizce belleği şişirir.
- Önce ölç, sonra konuş. Her N istekte bir
memory_get_usage(true)’yi logla; bellek monoton artıyorsa sızıntı vardır, dalgalanıp düşüyorsa normaldir. Octane’inRequestTerminatedhook’una bir sayaç koy, eğrinin şeklini gör. Eğri yükseliyorsa bir sonraki adıma geç. - Bisect ile suçluyu bul. Service provider’ları ve şüpheli paketleri tek tek devre dışı bırakıp eğriyi tekrar ölç; artış nerede duruyorsa sızıntı oradadır. Çoğu zaman fail, “her istekte taze süreç” varsayan bir third-party pakettir — PHP-FPM’de görünmez, Octane’de patlar. Snapshot diff’i (iki noktada
memory_get_usagefarkı) ile hangi tipin biriktiğini daralt. - Stateful singleton’ları hook’ta sıfırla. Request state tutan binding’leri
RequestReceived/RequestTerminatedhook’larında ya daconfig/octane.phpiçindekiflushlistesiyle temizle. Singleton’ı container’da bırakıp içindeki state’i resetlemek, çoğu sızıntıyı tek satırda kapatır. - Static birikimi öldür, servisi request başına yeniden bağla. Yalnızca büyüyen static
$cache = []array’leri, kapanmayan bağlantılar, istek başına şişen koleksiyonlar — hepsi tipik. Request scope’una ait servisi singleton yapma; her istekte yeniden bind et ki taşıdığı veri istekle birlikte ölsün. max_requests’i emniyet supabı say, tedavi değil. Worker’ı belli sayıda istekten sonra geri dönüştürmek RAM’i sınırlar ama kök nedeni gizler —500’ü düşürmek seni sadece geç çökmeye taşır. Açık tut, ama asıl işi sızıntıyı kapatarak yap.
Sonuç: Ben olsam sırayı şöyle kurardım: önce memory_get_usage ile eğriyi çıkar, sonra service provider/paketleri bisect ederek suçluyu daralt, ardından stateful singleton’ları Octane hook’larında sıfırla ve static birikimi temizle. max_requests’i bir güvenlik ağı olarak elinde tut ama ona bel bağlama. Octane’in hızını alacaksan, “süreç her istekte ölmüyor” gerçeğini kodun her katmanında kabul etmen gerekir.
İlgili Yazılar
Yorumlar
Yorum yapmak için GitHub hesabınızla giriş yapmanız yeterli. Yorumlar GitHub Discussions üzerinde saklanır.