Apache mod_cache ile Disk ve Bellek Önbellekleme

Web sunucunuzun her istek için aynı içeriği yeniden üretmesi, disk I/O’yu ve CPU kullanımını gereksiz yere tüketir. Apache’nin mod_cache modülü, bu tekrarlayan işlemleri ortadan kaldırarak sunucu yanıt sürelerini dramatik biçimde iyileştirir. Bu yazıda mod_cache’i disk ve memory tabanlı önbellekleme senaryolarıyla birlikte ele alacağız.

mod_cache Nedir ve Nasıl Çalışır

Apache mod_cache, HTTP yanıtlarını önbelleğe alarak sonraki isteklerde arka uca gitmeden doğrudan önbellekten sunan bir modüldür. RFC 2616 uyumlu çalışır, yani Cache-Control, Expires ve ETag başlıklarına göre hareket eder.

mod_cache üç temel bileşenden oluşur:

  • mod_cache: Ana önbellekleme modülü, orkestrasyon görevi görür
  • mod_cache_disk: Önbellek verilerini diske yazar, büyük ve uzun süreli içerikler için idealdir
  • mod_cache_socache: Paylaşılan belleği kullanır, hızlı erişim gerektiren küçük içerikler için uygundur

Bir istek geldiğinde mod_cache önce önbelleği kontrol eder. Eğer geçerli bir önbellek girişi varsa bunu döndürür, yoksa arka uca isteği iletir ve dönen yanıtı önbelleğe alır. Bu mekanizma özellikle statik içerik sunumu ve reverse proxy senaryolarında büyük performans kazanımları sağlar.

Modüllerin Kurulumu ve Aktifleştirilmesi

Debian/Ubuntu tabanlı sistemlerde mod_cache varsayılan olarak gelir ama aktif değildir:

# Modülleri aktifleştir
sudo a2enmod cache
sudo a2enmod cache_disk
sudo a2enmod cache_socache

# Socache için gerekli modüller
sudo a2enmod socache_shmcb

# Apache'yi yeniden başlat
sudo systemctl restart apache2

# Aktif modülleri doğrula
apache2ctl -M | grep cache

RHEL/CentOS/Rocky Linux sistemlerinde ise modüller genellikle httpd paketine dahildir ancak yükleme durumunu kontrol etmek gerekir:

# RHEL tabanlı sistemlerde modül kontrolü
httpd -M | grep cache

# Eğer mod_cache_disk eksikse
dnf install mod_cache_disk

# Modül dosyalarının konumunu bul
find /usr/lib64/httpd -name "mod_cache*"

# Mevcut konfigürasyonu görüntüle
httpd -t -D DUMP_MODULES | grep cache

Apache’nin modülü doğru yüklediğini görmek için LoadModule direktiflerini de kontrol etmelisiniz. RHEL sistemlerinde bu direktifler genellikle /etc/httpd/conf.modules.d/ altındaki ayrı dosyalarda tutulur.

mod_cache_disk ile Disk Önbellekleme

Disk önbellekleme, büyük dosyaları ve uzun süre geçerli kalacak içerikleri depolamak için tercih edilen yöntemdir. Belleğe kıyasla daha yavaş ama çok daha büyük kapasiteli bir önbellek alanı sunar.

Temel Disk Önbellek Konfigürasyonu

# /etc/apache2/sites-available/mysite.conf veya
# /etc/apache2/conf-available/cache.conf

# Önbellek motorunu aktifleştir
CacheEnable disk /

# Önbellek dizini
CacheRoot /var/cache/apache2/mod_cache_disk

# Maksimum önbellek boyutu (byte cinsinden, 1GB)
CacheDirLevels 2
CacheDirLength 1

# Önbelleklenecek içerik boyut limitleri
CacheMaxFileSize 1000000
CacheMinFileSize 1

# Varsayılan TTL (saniye cinsinden, 1 saat)
CacheDefaultExpire 3600

# Maksimum TTL (24 saat)
CacheMaxExpire 86400

# Geçersiz başlıkları olan içerikleri önbelleğe al
CacheIgnoreNoLastMod On

Önbellek dizinini oluşturun ve izinleri ayarlayın:

# Önbellek dizini oluştur
sudo mkdir -p /var/cache/apache2/mod_cache_disk

# Apache kullanıcısına sahiplik ver
sudo chown -R www-data:www-data /var/cache/apache2/

# İzinleri ayarla
sudo chmod 750 /var/cache/apache2/mod_cache_disk

# htcacheclean aracını test et
htcacheclean -p /var/cache/apache2/mod_cache_disk -l 500M -n

Gerçek Dünya Senaryosu: E-Ticaret Sitesi

Bir e-ticaret sitesinde ürün görselleri ve statik CSS/JS dosyaları yoğun istek alır. Bu tür içerikler için disk önbellekleme mükemmel çalışır:

<VirtualHost *:443>
    ServerName shop.example.com
    
    # Statik içerik için agresif önbellekleme
    <LocationMatch ".(jpg|jpeg|png|gif|webp|css|js|woff2)$">
        CacheEnable disk
        CacheDefaultExpire 604800
        CacheMaxExpire 2592000
        Header merge Cache-Control "public"
    </LocationMatch>
    
    # API uç noktalarını önbellekleme dışında tut
    <LocationMatch "^/api/">
        CacheDisable
    </LocationMatch>
    
    # Sepet ve checkout sayfalarını önbellekleme
    <LocationMatch "^/(cart|checkout|account)">
        CacheDisable
    </LocationMatch>
    
    # Ürün listesi sayfaları için kısa TTL
    <Location /products>
        CacheEnable disk
        CacheDefaultExpire 300
        CacheMaxExpire 900
    </Location>
</VirtualHost>

Bu konfigürasyon sayesinde statik dosyalar haftalarca önbellekte kalırken ürün listeleri 5 dakikada bir güncellenir ve kullanıcıya özel sayfalar hiç önbelleklenmez.

mod_cache_socache ile Memory Önbellekleme

Memory tabanlı önbellekleme, disk I/O olmaksızın veriye erişim sağlar. Küçük ama sık erişilen içerikler için idealdir. mod_cache_socache, Apache’nin paylaşılan nesne önbelleği altyapısını kullanır.

Socache Konfigürasyonu

# /etc/apache2/conf-available/memory-cache.conf

# Paylaşılan bellek önbelleğini başlat (64MB)
CacheSocache shmcb:/var/run/apache2/cache(67108864)

# Memory önbelleklemeyi aktifleştir
CacheEnable socache /

# Küçük dosyalar için boyut limiti
CacheMaxFileSize 102400

# TTL ayarları
CacheDefaultExpire 600
CacheMaxExpire 3600

# Önbellek kilitleme (stampede koruması)
CacheLock on
CacheLockPath /tmp/mod_cache-lock
CacheLockMaxAge 5

Memory önbellekleme için tipik bir senaryo, sıkça erişilen API yanıtlarının veya fragment HTML içeriklerinin önbelleklenmesidir. Örneğin bir haber sitesinde ana sayfa içeriği her dakika onlarca kez isteniyorsa:

<Location /homepage-fragment>
    CacheEnable socache
    CacheDefaultExpire 60
    CacheMaxExpire 180
    Header set Cache-Control "public, max-age=60"
</Location>

Önbellek Yönetimi ve htcacheclean

Disk önbelleği zamanla büyür ve yönetilmezse disk alanını tüketebilir. htcacheclean aracı bu sorunu çözer:

# Manuel önbellek temizleme, 500MB limitiyle
htcacheclean -p /var/cache/apache2/mod_cache_disk -l 500M

# Verbose mod, ne yapıldığını göster
htcacheclean -v -p /var/cache/apache2/mod_cache_disk -l 500M

# Daemon modunda çalıştır, 12 saatte bir temizle
htcacheclean -d 720 -p /var/cache/apache2/mod_cache_disk -l 1G -n

# Systemd service olarak yapılandır
cat > /etc/systemd/system/htcacheclean.service << 'EOF'
[Unit]
Description=Apache Cache Cleaner
After=apache2.service

[Service]
Type=forking
ExecStart=/usr/sbin/htcacheclean -d 60 -p /var/cache/apache2/mod_cache_disk -l 2G -n
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

systemctl enable htcacheclean
systemctl start htcacheclean

Önbellek Durumunu İzleme

Önbelleğin düzgün çalışıp çalışmadığını doğrulamak için birkaç yöntem kullanabilirsiniz.

mod_status ile İzleme

# Yanıt başlıklarını incele
curl -I https://example.com/style.css

# Önbellek hit/miss kontrolü
curl -I -o /dev/null -w "%{http_code}n" https://example.com/image.jpg

# Verbose mod ile önbellek başlıklarını gör
curl -v https://example.com/logo.png 2>&1 | grep -E "(Age|X-Cache|Cache-Control)"

# Apache log'larına özel önbellek formatı ekle
# /etc/apache2/apache2.conf içine:
LogFormat "%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i" Cache:%{cache-status}e" cache_combined

Önbellek başarılı çalışıyorsa Age başlığı sıfırdan büyük bir değer gösterir. Bu değer, içeriğin önbellekte kaç saniyedir beklediğini ifade eder.

Log Analizi

# Önbellek hit oranını hesapla
grep "cache-status" /var/log/apache2/access.log | 
  awk '{print $NF}' | sort | uniq -c | sort -rn

# Son 1 saatteki önbellek istatistikleri
awk -v d="$(date -d '1 hour ago' '+%d/%b/%Y:%H')" 
  '$4 > "["d' /var/log/apache2/access.log | 
  grep "HIT|MISS" | wc -l

# Hangi URL'ler en çok önbellekten servis ediliyor
grep "Cache:HIT" /var/log/apache2/access.log | 
  awk '{print $7}' | sort | uniq -c | sort -rn | head -20

Reverse Proxy Senaryosunda mod_cache

Apache’yi Nginx veya Node.js gibi arka uç sunucular önünde reverse proxy olarak kullandığınızda mod_cache çok daha güçlü hale gelir:

# /etc/apache2/sites-available/proxy-cache.conf

<VirtualHost *:80>
    ServerName api.example.com
    
    # Proxy ayarları
    ProxyPass / http://backend:3000/
    ProxyPassReverse / http://backend:3000/
    
    # Önbellek aktifleştir
    CacheEnable disk /
    CacheRoot /var/cache/apache2/proxy_cache
    
    # Hızlı değişen endpoint'ler
    <Location /api/realtime>
        CacheDisable
    </Location>
    
    # Public API yanıtları için önbellekleme
    <Location /api/products>
        CacheEnable disk
        CacheDefaultExpire 120
        CacheIgnoreHeaders Set-Cookie
        CacheIgnoreHeaders Cookie
    </Location>
    
    # Önbellek başlıklarını normalize et
    <Location />
        CacheEnable disk
        CacheDefaultExpire 300
        # Arka uçtan gelen Vary başlığını sınırla
        CacheIgnoreHeaders Vary
    </Location>
</VirtualHost>

Burada dikkat edilmesi gereken kritik nokta CacheIgnoreHeaders Set-Cookie direktifidir. Cookie içeren yanıtları varsayılan olarak önbelleklememek, kullanıcıya özel içeriğin başka kullanıcılara servis edilmesini engeller.

Yaygın Sorunlar ve Çözümleri

Gerçek dünyada mod_cache ile karşılaşılan en sık sorunlar şunlardır:

Önbellek hiç çalışmıyor gibi görünüyor:

Çoğu zaman arka uç uygulama Cache-Control: no-store veya Cache-Control: private başlığı gönderiyordur. Bunu aşmak için:

# Arka uç başlıklarını geçersiz kıl
<Location /static>
    CacheEnable disk
    # Header direktifiyle önbellek başlığı zorla
    Header set Cache-Control "public, max-age=3600"
    CacheIgnoreHeaders Cache-Control
</Location>

Önbellek tutarsız sonuçlar veriyor:

Vary başlığı sorunlu olabilir. Accept-Encoding gibi başlıklar önbelleğin farklı varyantlar saklamasına yol açar:

# Vary başlığını minimize et
<Location />
    CacheEnable disk
    # Sadece Accept-Encoding bazlı varyant tut
    CacheIgnoreHeaders Accept-Language Accept
</Location>

Disk önbelleği çok hızlı dolup taşıyor:

htcacheclean ayarlarını düzenleyin ve CacheMaxFileSize değerini düşürün. Ayrıca log dosyaları veya dinamik içeriklerin yanlışlıkla önbelleklenmediğini kontrol edin:

# Önbellek dizininin boyutunu takip et
du -sh /var/cache/apache2/mod_cache_disk/

# En büyük önbellek dosyalarını bul
find /var/cache/apache2/mod_cache_disk -type f -exec ls -lh {} ; | 
  sort -k5 -rh | head -10

# Önbellek içeriğini incele (header dosyaları .header uzantısıyla kaydedilir)
find /var/cache/apache2/mod_cache_disk -name "*.header" | head -5 | 
  xargs -I {} cat {}

Performans Testi

Konfigürasyon değişikliklerinin etkisini ölçmek için Apache Bench veya wrk kullanabilirsiniz:

# Önbellek öncesi baseline ölç
ab -n 1000 -c 50 https://example.com/products

# Önbellek aktif, ilk istek (MISS)
curl -I https://example.com/products

# Önbellek aktif, ikinci istek (HIT olmalı)
ab -n 1000 -c 50 https://example.com/products

# wrk ile daha gerçekçi yük testi
wrk -t 4 -c 100 -d 30s https://example.com/products

# Yanıt süresi dağılımını gör
ab -n 500 -c 25 -g gnuplot.dat https://example.com/static/app.js

Önbellek devreye girdiğinde genellikle %60-80 arasında yanıt süresi iyileşmesi görülür. Disk önbelleğinde bu iyileşme belirgindir ama memory önbelleğinde çok daha dramatik sonuçlar elde edersiniz.

Güvenlik Konusunda Dikkat Edilmesi Gerekenler

Önbellekleme güvenlik açıklarına da yol açabilir. Özellikle şu noktalara dikkat edin:

  • Kimlik doğrulama gerektiren içerikleri asla önbellekleme. Authorization başlığı olan istekler varsayılan olarak önbelleklenmez ama bunu bozacak konfigürasyonlardan kaçının.
  • Set-Cookie başlığı olan yanıtları önbellekleme. CacheIgnoreHeaders Set-Cookie direktifi bu konuda yardımcı olur.
  • HTTPS içeriğini önbelleklerken dikkatli ol. SSL termination yapıyorsanız önbellek şifreli değil, ham içerik depolar.
  • Önbellek dizin izinlerini sıkı tut. www-data dışındaki kullanıcıların önbellek dosyalarını okuyamaması gerekir.
# Güvenli önbellekleme örneği
<Location />
    CacheEnable disk
    # Cookie olan yanıtları önbellekleme
    CacheIgnoreHeaders Set-Cookie
    # Yetkilendirme başlığı varsa önbellekleme
    # Bu zaten varsayılan davranış ama açıkça belirtmek iyi pratik
    CacheStorePrivate Off
    CacheStoreNoStore Off
</Location>

Sonuç

mod_cache, doğru yapılandırıldığında Apache tabanlı bir web sunucusunun kapasitesini büyük ölçüde artırır. Disk önbellekleme büyük statik dosyalar ve proxy senaryoları için, memory önbellekleme ise sık erişilen küçük içerikler için en iyi sonucu verir.

Gerçek dünyada uyguladığınızda şu sırayı takip etmenizi öneririm: Önce log başlıklarını analiz ederek nelerin önbelleklenmesi gerektiğini anlayın, sonra küçük bir konfigürasyonla başlayın ve Apache Bench gibi araçlarla baseline performansınızı ölçün. Ardından konfigürasyonu kademeli olarak genişletin ve her adımda log’ları takip edin.

htcacheclean’i mutlaka bir daemon olarak çalıştırın. Önbellek dizininin kontrolsüz büyümesi, sunucunun disk dolması nedeniyle tamamen çökmesine yol açabilir ve bu genellikle gece yarısı sizi uyandıracak türden bir olaydır. mod_status ve özel log formatlarıyla önbellek hit oranını düzenli izlemek ise sistemin sağlıklı çalıştığını doğrulamanın en pratik yoludur.

Yorum yapın