Bir online mağaza işletiyorsanız, bir sayfanın yüklenmesi için geçen her saniye, müşteri kaybına daha yakın olduğunuzu biliyorsunuz. E-ticaret davranışları üzerine yapılan araştırmalar, yıllardır alışveriş yapanların birkaç saniyeden fazla yüklenme süresi olan sayfaları terk ettiğini göstermektedir. Beş dakikalık bir yükleme süresi yavaş değil, etkili olarak kapalı bir durumdur. Telefonunda öğle arası sırasında veya geç saatlerde gezinen bir müşteri için yüklenmeyen bir sayfa, mevcut olmayan bir sayfadır.
Mesele basit bir aksaklık değil. Bu, onun geliriyle ilgiliydi. Ürünler sayfası bozuk kaldığı her dakika, mağazası gerçek alıcılara görünmezdi. O yüzden geçici sunucu erişimini hemen benimle paylaştı, sorunun çözülmesini istiyordu. Kodu ilk defa incelediğimde, bu kodun altındaki gerçek sorunu görmek için Laravel Telescope’u kullandım. Ürünler sayfasını kendim yüklediğimde, neden beş dakika beklediğini anladım.
Beş Dakika Sonsuz Gibi Geldiğinde
Beş Dakika Sonsuz Gibi Geldiğinde
Sorgu kaydı binlerce sorguyla doluydu. Tek bir sayfa yüklemek için on queries değil, elli değil, binlerce sorgu çalışıyordu.
Koda Derinlemesine Bakmak
Koda Derinlemesine Bakmak
Öncelikle sunucunun belleğinin dolup dolmadığını, bir arka plan işleminin veritabanını bloke edip etmediğini ya da kötü bir dağıtımın olup olmadığını düşündüm. Ancak sorgu sayısı başka bir hikaye anlatıyordu. Bu bir sunucu problemi değil, kod sorunuydu ve büyük ihtimalle haftalardır sessizce kötüleşiyordu.
Ürünler sayfasını render eden kontrolcüyü açtığımda kodun yüzeysel olarak tamamen normal göründüğünü fark ettim. Kontrolcü tüm aktif ürünleri alıyor, her ürün için resimlerini, kategori adını ve ortalama inceleme notlarını alarak vitrin kartlarında gösteriyordu. Tehlikeli görünmüyordu.
Ancak o döngü, bir tuzaktı.
Gerçek Suçlu: Gözden Kaçan Sorun
Gerçek Suçlu: Gözden Kaçan Sorun
Eloquent, Laravel’deki veritabanı etkileşimlerini sağlayan ORM, güzel bir şekilde ifade edilebilir. $product->images, $product->category, $product->reviews yazmak ve bunun çalışması adeta sihir gibi. Ancak bu sihir, N plus one probleminde fark edilmesi zor bir tuzak yaratıyor.
Bir listeye ürünleri çektiğinizde, bu kısım verimli. Problemler, o ürünlerin üzerinden döngüyle geçip her birinin ilişkisini ayrı ayrı çağırmaya başladığınız anda başlar. $product->images gibi her çağrı, kendi ayrı veritabanı sorgusunu çalıştırır. Eğer mağazası sayfasında 40 ürün varsa ve her ürünün resimleri, kategorisi ve incelemeleri ayrı ayrı yüklenmeye ihtiyaç duyuyorsa, bu sadece 40 ek sorgu değil, muhtemel olarak 120 veya daha fazlası demektir. Mağaza büyüdükçe, bu toplam sorgu sayısı da artmıştı.
Kesin Kırılma Noktasını Bulmak
Kesin Kırılma Noktasını Bulmak
Herhangi bir şeyi değiştirmeden önce, sorunun tam ölçeğini anlamak istedim. Telescope’un sorgu görünümünü kullandım ve sorunların nereden kaynaklandığını kesinleştirdim. Her biri üç ilişkiden, yani ürünler döngüsünde lazy load edilen images, category ve reviews’dan geldiğini doğruladım.
Çözüm
Çözüm
Tanılama tamamlandığında çözüm bulmak, tanılama süresinden çok daha az zaman aldı. N plus one problemlerinde durum her zaman böyle olur. Zor kısım bulmak, düzeltmek değil.
Her ürünün ilişkisini birer birer çekmesine izin vermek yerine, Eloquent’in with() metodunu kullanarak sorguyu önceden tüm ilişkileri eager load edecek şekilde yeniden yazdım. Artık ürünleri, her bir satır için ayrı veritabanı sorguları yapmadan hatırlayarak resimler, kategori ve incelemelerle birlikte fetch ediyordu.
Ürünler sayfasını tekrar yükledim. Anında yüklendi. Sorgu sayısı, 1,500’den sadece altı sorguya düştü.
Bu Olay Bize Ne Öğretti?
Bu Olay Bize Ne Öğretti?
Yavaş yavaş gelen performans sorunları, genellikle kimseye uyarı vermiyor. Hiç kimseye sayfanın geçen ay beş kat daha yavaş olacağına dair bir bildirim gelmiyor. Sorun, büyüdükçe gözden kaçan güncellemelerle netleşiyor.
Bir diğer önemli bilgi de, gerçek paranın söz konusu olduğu durumlarda izleme yapmak zorunludur. Araçlar, sorunu acil bir telefon çağrısı haline gelmeden haftalar önce fark edebilirdi.
Eğer Laravel Uygulamanız Üretim Aşamasındaysa, Bu Şeyleri Kontrol Edin
Eğer Laravel Uygulamanız Üretim Aşamasındaysa, Bu Şeyleri Kontrol Edin
Gerçek gelir ile ilgilenen bir Laravel uygulamasını sürdürebiliyorsanız, birkaç alışkanlık sizi böyle bir geceden kurtarabilir:
- Laravel Telescope veya Debugbar’ı test ortamında açarak en yoğun sayfalardaki sorgu sayılarını izleyin.
- Döngüler boyunca,
with()kullanarak eager loading’e alışın. - Önemli sayfalar için sorgu bütçesi belirleyin. Eğer ürünler sayfanız ya da kontrol paneliniz birkaç sorgudan fazlasını çalıştırıyorsa, bu bir kriz doğmadan önce gözden geçirilmesi gereken bir durumdur.
- Kritik sayfalarınızı gerçekçi veri miktarı ile test edin. Küçük ölçekli problemler saklanabilir ve yalnızca veri ya da kullanıcı sayısı arttığında belirginleşir.
- Acil bir durumda arayabileceğiniz bir kişi bulundurun ve sistemlerinizi, gelen çağrılarda sorunu hızlı bir şekilde tanımlayabileceğiniz şekilde düzenleyin.
Her ne kadar çözüm, bulunduktan sonra basit olsa da, birçok hikaye böyle temiz bir sonuçla bitmez. Bazı hikayeler, veri kaybıyla sonuçlanabilirken, bazıları itibar kaybına yol açabilir. Bu tür sorunlar, gizli bir şekilde, tamamen normal görünen kodların içinde gizlenmektedir.
Kaynak: Orijinal Makale


