Sunucu Yüksek Yükü; Er ya da Geç Karşılaşacağınız Bir Sorun
Bir Linux sunucusu yönetiyorsanız, neredeyse kesin olarak bir gün "sunucu çok yavaşladı" veya "site açılmıyor" gibi mesajlarla karşılaşırsınız. Aklınıza gelen ilk şey sunucu yüksek yüküdür. Ancak sorun şu ki, "yük" belirsiz bir sayıdır; nasıl okuyacağınızı bilmiyorsanız, saatlerce yanlış yönde suçlu arayabilirsiniz.
Bu makalenin amacı tam olarak bunu netleştirmektir: load average'i nasıl doğru yorumlayacağınız, sorumlu süreci nasıl bulacağınız ve en önemlisi, sorunun CPU'dan mı yoksa I/O'dan mı (disk giriş/çıkışı) kaynaklandığını nasıl teşhis edeceğiniz. Bu ayrım, çözümün yarısıdır. Çünkü CPU-bound bir sunucunun tedavisi, I/O-bound bir sunucunun tedavisinden tamamen farklıdır.
Load Average Okuma; Çoğunlukla Yanlış Yorumlanan Bir Sayı
uptime veya top komutunu çalıştırdığınızda şuna benzer bir çıktı görürsünüz:
load average: 4.52, 3.87, 3.21
Bu üç sayı sırasıyla son 1 dakika, 5 dakika ve 15 dakikadaki ortalama yükü gösterir. Peki "yük" tam olarak ne anlama gelir? Linux'ta load average, çalışma kuyruğunda bekleyen süreçlerin (runnable) sayısı ile I/O bekleyen süreçlerin (kesintisiz uyku - uninterruptible sleep) sayısının toplamıdır. Bu çok önemli bir noktadır: Yük sadece CPU ile ilgili değildir; diskten okuma bekleyen bir süreç de bu sayıya dahil edilir.
"Uygun" Sayı Ne Kadardır?
Basit bir kural: load average'i CPU çekirdek sayısıyla karşılaştırın. Yük, çekirdek sayısına eşitse, CPU neredeyse tamamen meşgul demektir. Yük, çekirdek sayısını aşarsa, bekleme kuyruğu oluşur ve sunucunun yanıt süresi düşer.
Örneğin, 4 çekirdekli bir sunucuda yük 4 ise CPU dolu demektir ancak henüz ciddi bir bekleme kuyruğu yoktur. Yük 8 ise kapasitenin iki katıdır ve kullanıcılar belirgin bir gecikme hissedecektir. Ancak bu kural I/O-bound için geçerli değildir; 4 çekirdekli ve yükü 6 olan bir sunucuda CPU neredeyse boş olabilir ve sorun diskten kaynaklanıyor olabilir.
Yaygın Hata: Birçok kişi 1 çekirdekli bir sunucuda yük 1'in "tamamen normal" olduğunu düşünür. Oysa bu 1 birim I/O-bound bir süreçten geliyorsa, sunucu aşırı yavaş olabilir. Her zaman top içindeki wa (I/O wait) sütununa da bakın.
Adım 1: top ve ps ile Sorumlu Süreci Bulma
Yüksek yükü doğruladığınızda ilk araç toptur. Ancak sadece %CPU sütununa bakmak yeterli değildir. Önerdiğim sıralama şu şekildedir:
topkomutunu çalıştırın ve CPU kullanımına göre sıralamak içinPtuşuna basın.- Bellek kullanımına göre sıralamak için
Mtuşuna basın (bazen RAM sorunu kendini yüksek yük olarak gösterir). STATEsütununa dikkat edin: Bir süreçD(kesintisiz uyku) durumundaysa, I/O bekliyor demektir.
Daha hızlı ve scriptlenebilir bir görünüm için ps kullanın:
ps -eo pid,ppid,user,stat,%cpu,%mem,cmd --sort=-%cpu | head -20
Bu komut CPU'ya göre en çok kaynak tüketen 20 süreci gösterir. Çıktıyı I/O'ya göre görmek istiyorsanız, pidstat -d daha iyi bir araçtır (sysstat paketine bağlıdır):
pidstat -d 2 5
Bu komut her 2 saniyede bir, 5 kez, her sürecin okuma ve yazma miktarını KB/sn cinsinden gösterir. mysqld veya php-fpm gibi bir sürecin sürekli diskten okuma yaptığını görüyorsanız, sorun I/O'dan kaynaklanıyordur, CPU'dan değil.
CPU ile I/O'yu Ayırt Etme; Sunucu Yüksek Yükünü Teşhis Etmede En Önemli Beceri
Bu bölüm makalenin kalbidir. Bu ayrımı doğru yaparsanız, yolun yarısını gitmişsinizdir. Üç senaryoyu inceleyelim.
Senaryo 1: CPU-bound (İşlemciden Kaynaklanan)
Belirtiler: top içinde, bir sürecin %CPU sütunu %100'e yakın veya daha fazladır (çok iş parçacıklı süreçler için). wa sütunu düşüktür (%5'in altında). load average yüksektir ve genellikle çekirdek sayısına yakın veya daha fazladır.
Gerçek örnek: Sonsuz döngüye girmiş bir PHP scripti veya indeks kullanmayıp tüm tabloyu tarayan bir MySQL sorgusu. Bu durumda çözüm, kodu optimize etmek veya CPU eklemektir, disk yükseltmek değil.
Senaryo 2: I/O-bound (Diskten Kaynaklanan)
Belirtiler: top içinde, wa sütunu yüksektir (örneğin %20'nin üzerinde). Süreçler D durumundadır. load average yüksektir ancak süreçlerin %CPU değeri düşüktür (%30'un altında).
Doğrulamak için iostat kullanın:
iostat -x 2 3
%util sütununa bakın. %100'e yakınsa disk doymuş demektir. await sütunu da diskin ortalama yanıt süresini milisaniye cinsinden gösterir; SSD için 20ms'nin, HDD için 100ms'nin üzerindeki değerler diskin zorlandığını gösterir.
Teşhis İpucu: %util yüksek ancak await düşükse, sorun muhtemelen disk kapasitesinden ziyade çok sayıda küçük I/O işleminden kaynaklanıyordur. Bu durumda, logrotate gibi bir hizmetin veya ağır bir cron job'un çalışıp çalışmadığını kontrol edin.
Senaryo 3: Karma (Her İkisi)
Bazen sorun karmaşıktır; örneğin bir PHP-FPM süreci hem CPU tüketir hem de ağır loglar yazar. Bu durumda, önce I/O sorununu çözün (genellikle daha ucuzdur), ardından yükü tekrar kontrol edin.
Detaylı Kök Neden Analizi için Daha Gelişmiş Araçlar
Temel araçlar yeterli değilse, şu araçları deneyin:
atop; top'un Daha Kapsamlı Görünümü
atop geçmişi de görmenizi sağlar. d tuşuyla disk görünümüne, c tuşuyla CPU görünümüne geçin. İlginç bir nokta: atop CPU kullanımını "çekirdek" bazında gösterir ve tek iş parçacıklı bir sürecin bir çekirdeği doyurduğunu tespit etmek daha kolaydır.
strace; Sistem Çağrılarını İzleme
Sorumlu süreci bulduysanız ancak neden bu kadar I/O tükettiğini bilmiyorsanız, strace ile sürece bağlanın:
strace -p PID -f -e trace=file,read,write -o /tmp/strace.log
Birkaç saniye sonra Ctrl+C ile durdurun ve log dosyasını inceleyin. Sürekli belirli bir dosyayı açıp kapattığını görüyorsanız, sorun uygulama tasarımından kaynaklanıyordur.
Uyarı: strace komutunu production (canlı) süreçlerde dikkatli kullanın; sürecin hızını ciddi şekilde düşürebilir. Önce test ortamında denemeniz daha iyidir.
Her Senaryo için Pratik Çözümler
Teşhisten sonra sıra harekete geçmektedir. En yaygın çözümler şunlardır:
Sorun CPU ise
- Uygulama kodunu optimize edin: sorgu sonuçlarını önbelleğe alın, PHP için opcache kullanın ve MySQL'de doğru indeksleme yapın.
- Kaynak sınırları uygulayın:
systemdile CPU tavanı belirleyebilirsiniz. Örneğin,myappadlı bir hizmet için:
[Service]
CPUQuota=50%
Bu, hizmetin en fazla bir çekirdeğin yarısını kullanabileceği anlamına gelir.
Sorun I/O ise
- I/O miktarını azaltın: log rotation'ı ayarlayın, sık sık disk okuyan sorguları önbelleğe alın.
- I/O zamanlayıcısını kullanın: HDD diskler için zamanlayıcıyı
deadlineveyamq-deadlineolarak ayarlayın, böylece gecikme azalır. - Sanallaştırılmış sunucu (VPS) kullanıyorsanız ve disk paylaşımlıysa, garantili I/O oranınızın (IOPS) ne kadar olduğunu kontrol edin. Bu durumlarda, plan yükseltmek veya NVMe diske geçmek harikalar yaratabilir.
Bu bağlamda, sunucunuz bulut altyapısında barındırılıyorsa, ServerNet I/O yoğun iş yükleri için uygun NVMe disk ve özel IOPS seçenekleri sunar; ancak her zaman yükseltmeden önce sorunun gerçekten I/O'dan mı yoksa uygulama kodundan mı kaynaklandığından emin olun.
Özet; Sunucu Yüksek Yükünü Teşhis için Son Kontrol Listesi
Hızlı sonuca ulaşmak için şu sırayı izleyin:
uptimekomutunu çalıştırın ve load average'i çekirdek sayısıyla karşılaştırın.topaçın ve%CPU,waveSTATEsütunlarına dikkat edin.wayüksekse,iostat -xile disk doygunluğunu doğrulayın.- Sorumlu süreci
psveyapidstat -dile bulun. - Gerekirse,
straceile sürecin davranışının nedenini kök neden olarak analiz edin. - Senaryoya uygun çözümü (CPU veya I/O) uygulayın ve yükü tekrar izleyin.
Sunucu yüksek yükünü teşhis etmek kademeli olarak gelişen bir beceridir. Bu kontrol listesini her çalıştırdığınızda daha hızlı olur ve tahminlere daha az güvenirsiniz. Son bir not: herhangi bir işlem yapmadan önce mevcut sunucu ayarlarının yedeğini alın ve değişiklikleri tek tek uygulayın, böylece bir sorun olursa geri dönebilirsiniz.