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 etmeyin, ölçün — Octane’de worker uzun ömürlü olduğu için istekler arasında biriken her şey sızar; önce neyin biriktiğini izleyip yakalayın, sonra stateful tarafı hook’larda sıfırlayın.
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çün, sonra konuşun. Her N istekte bir
memory_get_usage(true)’yi loglayın; bellek monoton artıyorsa sızıntı vardır, dalgalanıp düşüyorsa normaldir. Octane’inRequestTerminatedhook’una bir sayaç koyun, eğrinin şeklini görün. Eğri yükseliyorsa bir sonraki adıma geçin. - Bisect ile suçluyu bulun. Service provider’ları ve şüpheli paketleri tek tek devre dışı bırakıp eğriyi tekrar ölçün; 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ın. - Stateful singleton’ları hook’ta sıfırlayın. Request state tutan binding’leri
RequestReceived/RequestTerminatedhook’larında ya daconfig/octane.phpiçindekiflushlistesiyle temizleyin. 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ün, servisi request başına yeniden bağlayın. 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 yapmayın; her istekte yeniden bind edin ki taşıdığı veri istekle birlikte ölsün. max_requests’i emniyet supabı sayın, 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 sizi sadece geç çökmeye taşır. Açık tutun, ama asıl işi sızıntıyı kapatarak yapın.
Sonuç: Ben olsam sırayı şöyle kurardım: önce memory_get_usage ile eğriyi çıkarın, sonra service provider/paketleri bisect ederek suçluyu daraltın, ardından stateful singleton’ları Octane hook’larında sıfırlayın ve static birikimi temizleyin. max_requests’i bir güvenlik ağı olarak elinizde tutun ama ona bel bağlamayın. Octane’in hızını alacaksanız, “süreç her istekte ölmüyor” gerçeğini kodun her katmanında kabul etmeniz gerekir.
İlgili Yazılar
Yorumlar
Yorum yapmak için GitHub hesabınızla giriş yapmanız yeterli. Yorumlar GitHub Discussions üzerinde saklanır.