Apache Performans Sorunları: Yüksek CPU ve Bellek Kullanımı
Sunucunuza sabah erken saatlerde bağlandığınızda Apache’nin %90 CPU kullandığını görüyorsunuz, web siteniz yavaşlamış ya da tamamen çökmüş durumda. Bu senaryo, her sysadmin’in kabusu. Ama paniklemeden, sistematik bir şekilde ilerlediğinizde bu sorunların büyük çoğunluğunun çözülmesi oldukça mümkün. Bu yazıda Apache’nin yüksek CPU ve bellek kullanımı sorunlarını nasıl tespit edip çözeceğinizi, gerçek dünya senaryolarıyla birlikte ele alacağız.
Sorunu Tespit Etmek: İlk Adımlar
Herhangi bir performans sorununda ilk işiniz sisteme ne olduğunu anlamak olmalı. Apache’ye hemen dalmadan önce genel sistem durumunu kontrol edin.
# Genel sistem durumuna bakın
top -b -n 1 | head -30
# Apache işlemlerine özel bakış
ps aux | grep apache2 | sort -k3 -rn | head -20
# Bellek kullanımı
free -h
# Apache işlem sayısını öğrenin
ps aux | grep -c apache2
top çıktısında Apache işlemlerinin toplam CPU ve bellek kullanımına bakın. Eğer apache2 işlemleri toplamda %80’in üzerinde CPU kullanıyorsa ciddi bir sorun var demektir. Bu noktada acele kararlar vermek yerine önce veri toplayın.
Apache Durum Modülü ile Anlık İzleme
Apache’nin kendi içindeki mod_status modülü, ne olduğunu anlamak için altın değerinde bilgiler sunar. Eğer henüz aktif değilse hemen açın:
# mod_status durumunu kontrol edin
apache2ctl -M | grep status
# Eğer aktif değilse /etc/apache2/mods-enabled/ altında etkinleştirin
a2enmod status
systemctl reload apache2
/etc/apache2/mods-enabled/status.conf dosyanıza veya VirtualHost konfigürasyonunuza şu bloğu ekleyin:
<Location /server-status>
SetHandler server-status
Require ip 127.0.0.1
Require ip 192.168.1.0/24
</Location>
# Genişletilmiş durum bilgisi için
ExtendedStatus On
Sonra curl http://localhost/server-status?refresh=5 komutuyla anlık durumu izleyebilirsiniz. Bu sayfa size kaç işçinin meşgul olduğunu, hangi isteklerin işlendiğini ve bağlantı sürelerini gösterir.
Yüksek CPU Kullanımının Yaygın Nedenleri
1. MPM Konfigürasyonu Yanlış Ayarlanmış
Apache’nin Multi-Processing Module (MPM) ayarları, performans sorunlarının en yaygın kaynağıdır. prefork, worker veya event modundan hangisini kullandığınızı ve bu modun doğru yapılandırılıp yapılandırılmadığını kontrol etmelisiniz.
# Hangi MPM kullandığınızı öğrenin
apache2ctl -V | grep MPM
# Ya da
apache2ctl -M | grep mpm
prefork MPM kullanıyorsanız ve PHP-FPM’e geçmediyseniz, her istek için ayrı bir işlem fork’lanır. Bu hem CPU hem de bellek açısından çok maliyetlidir. Tipik bir sorunlu konfigürasyon şöyle görünür:
/etc/apache2/mods-enabled/mpm_prefork.conf dosyasını kontrol edin:
# Sorunlu bir prefork konfigürasyonu
<IfModule mpm_prefork_module>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxRequestWorkers 150
MaxConnectionsPerChild 0
</IfModule>
MaxConnectionsPerChild 0 değeri işçilerin hiçbir zaman yeniden başlatılmamasına neden olur. Bu, bellek sızıntısı olan PHP uygulamalarında felakete yol açar. Bunu düzeltin:
# Daha sağlıklı bir prefork konfigürasyonu
<IfModule mpm_prefork_module>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxRequestWorkers 50
MaxConnectionsPerChild 1000
</IfModule>
MaxRequestWorkers değerini hesaplarken şu formülü kullanın: (Toplam RAM – OS için ayrılan RAM) / Ortalama Apache işlem boyutu. Ortalama işlem boyutunu şu komutla öğrenebilirsiniz:
ps aux | grep apache2 | awk '{sum += $6; count++} END {print sum/count/1024 " MB"}'
2. Keep-Alive Ayarları
KeepAlive özelliği doğru ayarlanmadığında sunucunuz gereksiz yere bağlantıları açık tutar ve bu da CPU ile belleği tüketir.
# /etc/apache2/apache2.conf veya ilgili konfigürasyonda
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5
KeepAliveTimeout değerini 15-30 saniye gibi yüksek tutarsanız, her bağlantı o süre boyunca bir Apache işçisini meşgul eder. Statik içerik ağırlıklı sitelerde bu değeri 2-5 saniyeye düşürmek büyük fark yaratır.
3. .htaccess Dosyaları Her İstekte Okunuyor
Bu konu çok hafife alınan bir performans katilidir. AllowOverride All ayarı yapıldığında Apache her istek için tüm dizin hiyerarşisindeki .htaccess dosyalarını okur. 10 katman derinliğinde bir dizin yapınız varsa her istek için 10 disk okuma işlemi gerçekleşir.
# Sorunlu konfigürasyon
<Directory /var/www/>
AllowOverride All
</Directory>
# Daha iyi yaklaşım - .htaccess kurallarını ana konfigürasyona taşıyın
<Directory /var/www/>
AllowOverride None
</Directory>
.htaccess içindeki kuralları VirtualHost konfigürasyonuna taşıdıktan sonra Apache’yi yeniden yükleyin. Yoğun trafik altında bu değişiklik CPU kullanımını %20-30 oranında düşürebilir.
Log Analizi ile Sorun Tespiti
Yüksek CPU kullanımının arkasında çoğu zaman belirli URL’lere gelen anormal trafik ya da yavaş sorgular vardır. Log analizi bu noktada kritik bilgiler verir.
# En çok istek gelen URL'ler
awk '{print $7}' /var/log/apache2/access.log | sort | uniq -c | sort -rn | head -20
# En çok istek gönderen IP'ler
awk '{print $1}' /var/log/apache2/access.log | sort | uniq -c | sort -rn | head -20
# Son 1 saatteki istek sayısı
awk -v d="$(date -d '1 hour ago' '+%d/%b/%Y:%H')" '$4 > "["d' /var/log/apache2/access.log | wc -l
# Yavaş istekler için (5 saniyeden uzun)
grep -E '"[0-9]{6,}"$' /var/log/apache2/access.log
GoAccess aracı gerçek zamanlı log analizi için mükemmeldir:
# GoAccess kurulumu
apt install goaccess
# Anlık terminal analizi
goaccess /var/log/apache2/access.log --log-format=COMBINED
# HTML raporu oluşturma
goaccess /var/log/apache2/access.log -o /var/www/html/report.html --log-format=COMBINED
Yavaş İstek Loglama
Apache’nin mod_logio ve özel log formatlarıyla yavaş istekleri tespit edebilirsiniz:
# /etc/apache2/apache2.conf içinde özel log formatı
LogFormat "%h %l %u %t "%r" %>s %b %D" combined_with_time
# VirtualHost içinde kullanım
CustomLog /var/log/apache2/slow_requests.log combined_with_time
# 2 saniyeden uzun süren istekleri filtrele (2000000 mikrosaniye)
awk '$NF > 2000000' /var/log/apache2/slow_requests.log | awk '{print $7}' | sort | uniq -c | sort -rn
%D log değişkeni isteğin mikrosakiye cinsinden ne kadar sürdüğünü kaydeder. Bu verilerle hangi endpoint’lerin sorun çıkardığını net olarak görebilirsiniz.
Bellek Sızıntısı Tespiti
Bellek kullanımı zamanla artıyor ve Apache yeniden başlatıldığında normale dönüyorsa bellek sızıntısından şüphelenmelisiniz. PHP uygulamalarında bu çok yaygındır.
# Apache işlemlerinin bellek kullanımını zaman içinde izleyin
watch -n 5 'ps aux | grep apache2 | awk "{sum += $6} END {print sum/1024 " MB"}"'
# Belirli bir işlemin bellek büyümesini takip edin
PID=$(pgrep -o apache2)
while true; do
cat /proc/$PID/status | grep VmRSS
sleep 30
done
Eğer işlem boyutları sürekli büyüyorsa MaxConnectionsPerChild değerini düşürün. Bu ayar, bir işçinin belirli sayıda istek sonrası yeniden başlatılmasını sağlar ve bellek sızıntısının etkisini sınırlar.
PHP-FPM’e Geçiş: Kalıcı Çözüm
Hâlâ mod_php kullanıyorsanız ve prefork MPM üzerinde çalışıyorsanız, en büyük performans kazancını PHP-FPM’e geçerek elde edersiniz. Bu geçiş Apache’nin event MPM kullanmasını sağlar ve aynı donanımla çok daha fazla isteği karşılayabilirsiniz.
# PHP-FPM kurulumu (örnek: PHP 8.1)
apt install php8.1-fpm
# Apache modüllerini düzenleyin
a2dismod php8.1
a2dismod mpm_prefork
a2enmod mpm_event
a2enmod proxy_fcgi setenvif
a2enconf php8.1-fpm
# PHP-FPM'i başlatın
systemctl start php8.1-fpm
systemctl enable php8.1-fpm
# Apache'yi yeniden yükleyin
systemctl reload apache2
PHP-FPM konfigürasyonunu da optimize etmeniz gerekir. /etc/php/8.1/fpm/pool.d/www.conf dosyasında:
# PHP-FPM pool konfigürasyonu
[www]
pm = dynamic
pm.max_children = 20
pm.start_servers = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 8
pm.max_requests = 500
# Yavaş logları etkinleştirin
slowlog = /var/log/php8.1-fpm-slow.log
request_slowlog_timeout = 5s
pm.max_requests = 500 ayarı ile her FPM işçisi 500 istek sonrası yeniden başlatılır. Bu bellek sızıntısı olan uygulamalarda hayat kurtarıcıdır.
Önbelleğe Alma ile CPU Yükünü Azaltma
mod_cache Kullanımı
Dinamik içeriği bile önbelleğe alarak CPU kullanımını dramatik şekilde düşürebilirsiniz:
# mod_cache ve mod_cache_disk etkinleştirme
a2enmod cache
a2enmod cache_disk
a2enmod headers
# VirtualHost konfigürasyonuna ekleyin
<IfModule mod_cache.c>
CacheEnable disk /
CacheRoot /var/cache/apache2/mod_cache_disk
CacheDefaultExpire 3600
CacheMaxExpire 86400
CacheIgnoreNoLastMod On
# Belirli dosya tiplerini önbellekle
<LocationMatch ".(jpg|jpeg|png|gif|css|js)$">
CacheEnable disk
Header merge Cache-Control public
ExpiresDefault "access plus 1 week"
</LocationMatch>
</IfModule>
# Önbellek dizinini oluşturun
mkdir -p /var/cache/apache2/mod_cache_disk
chown www-data:www-data /var/cache/apache2/mod_cache_disk
mod_deflate ile Bant Genişliği Optimizasyonu
Sıkıştırma hem bant genişliğini azaltır hem de daha hızlı yanıtlar üretir:
# mod_deflate konfigürasyonu
a2enmod deflate
# apache2.conf veya VirtualHost'a ekleyin
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml
AddOutputFilterByType DEFLATE text/css text/javascript
AddOutputFilterByType DEFLATE application/javascript application/json
DeflateCompressionLevel 6
</IfModule>
Gerçek Dünya Senaryosu: DDoS ve Bot Trafiği
Bir müşterinin sunucusunda CPU’nun %100’e çıkması sorununu incelerken log analizinde şunu bulduk: Tek bir IP’den saniyede 50’nin üzerinde istek geliyordu ve tüm bu istekler dinamik PHP sayfalarına yapılıyordu.
# Anlık bağlantı sayısını kontrol edin
netstat -an | grep ESTABLISHED | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20
# Apache'de zaten bağlı olan bağlantılar
apachectl fullstatus | grep -E "^[0-9]" | head -30
Bu tür durumlarda mod_evasive veya mod_security kullanmak uzun vadeli çözümdür. Kısa vadede ise:
# Saldıran IP'yi iptables ile engelle
iptables -A INPUT -s 1.2.3.4 -j DROP
# Veya .htaccess ile (eğer AllowOverride açıksa)
# /var/www/html/.htaccess
Order Allow,Deny
Deny from 1.2.3.4
Allow from all
mod_evasive kurulumu ve konfigürasyonu:
apt install libapache2-mod-evasive
a2enmod evasive
# /etc/apache2/mods-enabled/evasive.conf
<IfModule mod_evasive20.c>
DOSHashTableSize 3097
DOSPageCount 5
DOSSiteCount 50
DOSPageInterval 1
DOSSiteInterval 1
DOSBlockingPeriod 10
DOSEmailNotify [email protected]
DOSLogDir /var/log/apache2/evasive
</IfModule>
Sistem Seviyesinde Optimizasyonlar
Apache’nin performansını etkileyen sistem parametrelerini de unutmayın:
# /etc/sysctl.conf dosyasına ekleyin
# TCP bağlantı yönetimi
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 300
net.core.somaxconn = 65535
net.ipv4.ip_local_port_range = 1024 65535
# Değişiklikleri uygulayın
sysctl -p
# Dosya tanımlayıcı limitlerini artırın
# /etc/security/limits.conf
www-data soft nofile 65536
www-data hard nofile 65536
Apache’nin kendi limitlerini de ayarlayın. /etc/apache2/envvars dosyasına ekleyin:
# Ulimit ayarları
ulimit -n 65536
İzleme ve Alarm Sistemi Kurma
Sorun çıktıktan sonra değil, çıkmadan önce haberdar olmak istersiniz. Basit bir izleme scripti:
#!/bin/bash
# /usr/local/bin/apache_monitor.sh
CPU_THRESHOLD=80
MEM_THRESHOLD=80
EMAIL="[email protected]"
# Apache CPU kullanımı
APACHE_CPU=$(ps aux | grep apache2 | grep -v grep | awk '{sum += $3} END {print int(sum)}')
# Apache bellek kullanımı (MB)
APACHE_MEM=$(ps aux | grep apache2 | grep -v grep | awk '{sum += $6} END {print int(sum/1024)}')
# Apache işlem sayısı
APACHE_PROCS=$(ps aux | grep apache2 | grep -v grep | wc -l)
if [ "$APACHE_CPU" -gt "$CPU_THRESHOLD" ]; then
echo "UYARI: Apache CPU kullanimi ${APACHE_CPU}% - $(date)" | mail -s "Apache CPU Alarm" $EMAIL
logger "Apache yuksek CPU: ${APACHE_CPU}%"
fi
if [ "$APACHE_MEM" -gt 1024 ]; then
echo "UYARI: Apache bellek kullanimi ${APACHE_MEM}MB - $(date)" | mail -s "Apache Bellek Alarm" $EMAIL
fi
Bu scripti cron’a ekleyin:
# Crontab'a ekleyin
*/5 * * * * /usr/local/bin/apache_monitor.sh
Hızlı Kontrol Listesi
Yüksek CPU/bellek sorunuyla karşılaştığınızda sırayla yapmanız gerekenler:
topveps auxile mevcut durumu belgeleyin- Apache işlem sayısını kontrol edin,
MaxRequestWorkerssınırına yaklaşılıyor mu? - Log analizi yapın, anormal trafik var mı?
mod_statusçıktısını inceleyin, hangi istekler uzun sürüyor?MaxConnectionsPerChilddeğerinin ayarlı olduğundan emin olunKeepAliveTimeoutdeğerini gözden geçirin- PHP kullanıyorsanız
mod_phpyerine PHP-FPM kullanmayı değerlendirin .htaccessveAllowOverride Allkonfigürasyonunu gözden geçirin- Sıkıştırma ve önbelleğe almanın aktif olup olmadığını kontrol edin
Sonuç
Apache performans sorunları genellikle tek bir nedenden kaynaklanmaz. Yanlış MPM ayarları, uygunsuz KeepAlive konfigürasyonu, aşırı .htaccess kullanımı, bellek sızdıran PHP uygulamaları ve bot/DDoS trafiği bir arada rol oynayabilir. Bu yüzden sistematik bir yaklaşımla önce veri toplamak, sonra çözüme gitmek en sağlıklı yolu oluşturur.
PHP-FPM’e geçiş ve event MPM kombinasyonu, modern web sunucuları için neredeyse her zaman doğru tercih olmaktadır. Prefork MPM hâlâ kullanıyorsanız ve bunu değiştirme imkânınız yoksa en azından MaxConnectionsPerChild ve MaxRequestWorkers değerlerini doğru ayarladığınızdan emin olun.
Uzun vadede ise proaktif izleme kurmanız, sorunları kullanıcılarınız fark etmeden önce tespit etmenizi sağlar. Alarm sistemleri yazmak, düzenli log analizi yapmak ve konfigürasyon değişikliklerini versiyon kontrolünde tutmak, bir sysadmin olarak sizi reaktif değil proaktif konuma getirir. Ve bu fark, gece 3’te telefon alıp almamak arasındaki fark olabilir.
