Apache Timeout ve KeepAlive Optimizasyonu

Web sunucunuzun performansı düşüyor, kullanıcılar zaman zaman timeout hataları alıyor ya da sunucunuz gereksiz yere çok kaynak tüketiyor mu? Bunların büyük çoğunluğunun arkasında yanlış yapılandırılmış Timeout ve KeepAlive parametreleri yatıyor. Apache’nin bu iki kritik ayarını doğru yapmak, hem sunucu stabilitesi hem de son kullanıcı deneyimi açısından inanılmaz fark yaratıyor. Bu yazıda bu parametreleri derinlemesine inceleyeceğiz, gerçek dünya senaryolarıyla ne zaman nasıl ayarlama yapmanız gerektiğini ele alacağız.

Timeout ve KeepAlive Nedir, Neden Önemlidir?

Önce temel kavramları netleştirelim. Apache’de Timeout direktifi, bir isteğin tamamlanması için sunucunun ne kadar bekleyeceğini saniye cinsinden belirler. Bu süre dolduğunda Apache bağlantıyı keser ve kaynakları serbest bırakır. KeepAlive ise HTTP/1.1 ile gelen kalıcı bağlantı özelliğidir; tek bir TCP bağlantısı üzerinden birden fazla istek gönderilmesine olanak tanır.

Neden bu kadar kritik? Çünkü her yanlış ayar farklı bir soruna yol açar:

  • Timeout çok düşükse: Yavaş istemciler veya büyük dosya yüklemeleri sürekli kesilir
  • Timeout çok yüksekse: Yavaş saldırılar (Slowloris gibi) sunucunuzu çökertir
  • KeepAlive kapalıysa: Her kaynak için ayrı TCP bağlantısı açılır, gecikme artar
  • KeepAlive açık ama yanlış ayarlıysa: Bağlantılar gereksiz yere açık kalır, işçi süreçler tükenir

Apache Timeout Direktifleri

Apache’de tek bir “Timeout” değeri yoktur aslında. Birkaç farklı direktif farklı senaryoları kontrol eder.

Temel Timeout Direktifi

# /etc/apache2/apache2.conf veya httpd.conf
Timeout 300

Bu değer varsayılan olarak 300 saniyedir ve şu üç durumu kapsar:

  • İstemciden bir GET isteğinin alınmasını bekleme süresi
  • POST/PUT isteğinde TCP paketleri arasındaki maksimum bekleme süresi
  • İstemciye TCP yanıt paketleri arasındaki maksimum bekleme süresi

300 saniye çoğu senaryo için fazlasıyla uzun. Genel bir web uygulaması için 60-120 saniye çok daha makul bir başlangıç noktasıdır.

RequestReadTimeout ile Daha İnce Kontrol

Apache 2.2.15 ve sonrasında gelen mod_reqtimeout modülü, istek okuma sürecini çok daha ayrıntılı yönetmenizi sağlar. Bu modül varsayılan olarak etkin gelir ama çoğu yönetici varlığından bile habersizdir.

# mod_reqtimeout aktivasyonu kontrolü
apache2ctl -M | grep reqtimeout

# Etkin değilse aktive edin
a2enmod reqtimeout

RequestReadTimeout direktifinin söz dizimi biraz karmaşık görünebilir ama mantığını kavradığınızda çok güçlü bir araç olduğunu anlarsınız:

# /etc/apache2/conf-available/reqtimeout.conf

# Header okuma: minimum 20 saniye, sonra her 500 byte için 1 saniye ekle, max 40 saniye
RequestReadTimeout header=20-40,MinRate=500

# Body okuma: minimum 10 saniye, sonra her 500 byte için 1 saniye ekle, max 120 saniye
RequestReadTimeout body=10,MinRate=500

Bu yapılandırma şu anlama geliyor: Header için en az 20 saniye ver, ama istemci saniyede en az 500 byte veri gönderiyorsa süreyi uzat, toplamda 40 saniyeyi geçme. Body için de benzer mantık geçerli.

Slowloris Saldırılarına Karşı Timeout Optimizasyonu

Slowloris, çok yavaş HTTP başlıkları göndererek Apache işçilerini meşgul eden bir DDoS saldırısıdır. Doğru Timeout ayarları bu saldırıya karşı önemli bir savunma katmanı oluşturur:

# /etc/apache2/conf-available/security-timeouts.conf

# Çok agresif ama saldırıya açık sistemler için
RequestReadTimeout header=10-20,MinRate=500
RequestReadTimeout body=10,MinRate=500

Timeout 60

# Bu ayarı da aktive edin
<IfModule mod_reqtimeout.c>
    RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500
</IfModule>

Değişiklikleri uygulamak için:

# Konfigürasyonu test edin
apachectl configtest

# Apache'yi yeniden yükleyin (downtime olmadan)
systemctl reload apache2

KeepAlive Ayarları

KeepAlive Neden Önemli?

Modern bir web sayfası açtığınızda tarayıcı onlarca, bazen yüzlerce kaynak yükler: CSS dosyaları, JavaScript, görseller, fontlar… KeepAlive kapalıysa her biri için ayrı bir TCP el sıkışması gerekir. Bu da hem gecikme hem de kaynak tüketimi açısından ciddi bir maliyet demektir.

Temel KeepAlive Yapılandırması

# /etc/apache2/apache2.conf

# KeepAlive'ı etkinleştir
KeepAlive On

# Tek bir bağlantıda kaç istek yapılabilir
MaxKeepAliveRequests 100

# Bağlantı boşta kalırsa kaç saniye bekle
KeepAliveTimeout 5

Bu üç direktif birlikte çalışır. Tek tek inceleyelim:

KeepAlive On/Off: Kalıcı bağlantıları açıp kapatır. Neredeyse her senaryoda On olmalı.

MaxKeepAliveRequests 100: Bir bağlantı üzerinden maksimum 100 istek yapılabilir. 0 değeri sınırsız demektir ama bunu yapmayın. 100-200 arası değerler çoğu uygulama için idealdir. Yüksek trafikli statik içerik sunan sunucular için 200-500 düşünülebilir.

KeepAliveTimeout 5: Bağlantı 5 saniye boşta kalırsa kapat. Bu değer kritik. Çok yüksek tutarsanız işçi süreçleriniz boşta bekleyen bağlantılarla dolar.

KeepAliveTimeout İçin Gerçekçi Değerler

Pek çok sysadmin bu değeri 15-30 saniye olarak bırakır ve ciddi performans sorunları yaşar. Araştırmalar ve gerçek dünya deneyimleri şunu gösteriyor:

  • 1-2 saniye: Çok agresif, yüksek trafikte sorun olmaz ama bazı yavaş bağlantılarda sorun çıkabilir
  • 5 saniye: Çoğu senaryo için ideal başlangıç noktası
  • 10 saniye: Makul ama işçi tüketimini artırır
  • 15+ saniye: Yüksek trafikli sunucularda felaket reçetesi

Virtual Host Bazında KeepAlive Ayarı

Farklı uygulamalarınız farklı davranış gerektirebilir. Örneğin API endpoint’leri için KeepAlive daha az anlamlıyken, görselli içerik sunan bir site için çok değerlidir:

# /etc/apache2/sites-available/static-content.conf
<VirtualHost *:443>
    ServerName static.orneksite.com
    
    # Statik içerik için yüksek KeepAlive değerleri mantıklı
    KeepAlive On
    MaxKeepAliveRequests 200
    KeepAliveTimeout 10
    
    DocumentRoot /var/www/static
</VirtualHost>

# /etc/apache2/sites-available/api-backend.conf
<VirtualHost *:443>
    ServerName api.orneksite.com
    
    # API için daha kısa timeout
    KeepAlive On
    MaxKeepAliveRequests 50
    KeepAliveTimeout 2
    
    ProxyPass / http://localhost:8080/
    ProxyPassReverse / http://localhost:8080/
</VirtualHost>

MPM (Multi-Processing Module) ile Timeout İlişkisi

Timeout ve KeepAlive ayarları tek başına yeterli değil. Bu değerlerin MPM yapılandırmanızla uyumlu olması gerekiyor. Aksi takdirde tüm optimizasyonlarınız boşa gider.

Prefork MPM ile Optimizasyon

# /etc/apache2/mods-available/mpm_prefork.conf

<IfModule mpm_prefork_module>
    StartServers             5
    MinSpareServers          5
    MaxSpareServers         10
    MaxRequestWorkers      150
    MaxConnectionsPerChild   0
</IfModule>

Prefork’ta her işçi bir bağlantıya atanır. Bu yüzden KeepAliveTimeout değeri doğrudan kaç işçinin boşta beklediğini etkiler. MaxRequestWorkers 150 ise ve her bağlantı 15 saniye KeepAlive bekliyorsa, düşük trafikte bile işçileriniz hızla tükenir.

Worker veya Event MPM ile Optimizasyon

# /etc/apache2/mods-available/mpm_event.conf

<IfModule mpm_event_module>
    StartServers             2
    MinSpareThreads         25
    MaxSpareThreads         75
    ThreadLimit             64
    ThreadsPerChild         25
    MaxRequestWorkers      150
    MaxConnectionsPerChild   0
</IfModule>

Event MPM, KeepAlive bağlantılarını ayrı bir “dinleyici” thread’de tutabildiği için prefork’a göre çok daha verimlidir. Bu MPM kullanıyorsanız KeepAliveTimeout değerini biraz daha yüksek tutabilirsiniz, örneğin 5-10 saniye.

Hangi MPM kullandığınızı kontrol etmek için:

apachectl -V | grep -i mpm
# veya
apache2ctl -M | grep mpm

Gerçek Dünya Senaryoları

Senaryo 1: E-ticaret Sitesi

Müşteri sayfayı açtığında onlarca ürün görseli, CSS, JS yükleniyor. Checkout sayfasında büyük form POST’ları var, ödeme işlemi bazen 10-15 saniye sürüyor.

# /etc/apache2/sites-available/eticaret.conf

<VirtualHost *:443>
    ServerName magazam.com
    
    # Genel ayarlar
    KeepAlive On
    MaxKeepAliveRequests 150
    KeepAliveTimeout 5
    Timeout 120
    
    # Ödeme sayfası için ayrı timeout (location bazında)
    <Location /checkout/payment>
        Timeout 300
    </Location>
    
    # Yükleme endpoint'i için
    <Location /admin/upload>
        Timeout 600
    </Location>
    
    # mod_reqtimeout ayarları
    <IfModule mod_reqtimeout.c>
        RequestReadTimeout header=20-40,MinRate=500
        RequestReadTimeout body=30,MinRate=500
    </IfModule>
</VirtualHost>

Senaryo 2: Yüksek Trafikli Haber Portalı

Saniyede yüzlerce istek, çoğu HTML sayfa okuma. Uzun süreli bağlantılar sunucu kaynaklarını tüketiyor.

# Yüksek trafik için agresif ayarlar
<VirtualHost *:80>
    ServerName haber.orneksite.com
    
    KeepAlive On
    MaxKeepAliveRequests 100
    # Haber siteleri için 2-3 saniye yeterli
    KeepAliveTimeout 3
    Timeout 60
    
    <IfModule mod_reqtimeout.c>
        RequestReadTimeout header=10-20,MinRate=500
        RequestReadTimeout body=10,MinRate=500
    </IfModule>
    
    # Gzip ile birlikte çalışırken
    <IfModule mod_deflate.c>
        AddOutputFilterByType DEFLATE text/html text/css application/javascript
    </IfModule>
</VirtualHost>

Senaryo 3: Reverse Proxy Arkasında Uygulama Sunucusu

Apache, arkasında bir Tomcat veya Node.js uygulamasına proxy yapıyor. Bu senaryoda ProxyTimeout da devreye giriyor:

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

<VirtualHost *:443>
    ServerName app.orneksite.com
    
    # Apache istemci bağlantısı için
    KeepAlive On
    KeepAliveTimeout 5
    Timeout 120
    
    # Proxy timeout ayarları - backend'in cevap süresine göre ayarla
    ProxyTimeout 90
    
    # Proxy bağlantı havuzu
    <Proxy balancer://appcluster>
        BalancerMember http://10.0.0.10:8080
        BalancerMember http://10.0.0.11:8080
    </Proxy>
    
    ProxyPass / balancer://appcluster/
    ProxyPassReverse / balancer://appcluster/
    
    # Backend bağlantısını keepalive ile tut
    ProxyPassMatch ^/(.*) http://10.0.0.10:8080/$1
    <Proxy *>
        ProxySet keepalive=On
        ProxySet timeout=90
        ProxySet connectiontimeout=10
    </Proxy>
</VirtualHost>

Performans Testleri ile Doğrulama

Ayarları yaptınız, peki doğru mu? Test etmeden bilemezsiniz. ab (Apache Benchmark) ile hızlı bir test yapabilirsiniz:

# 1000 istek, 100 eş zamanlı bağlantı, KeepAlive ile
ab -n 1000 -c 100 -k https://orneksite.com/

# KeepAlive olmadan aynı test
ab -n 1000 -c 100 https://orneksite.com/

# Sonuçları karşılaştırın, özellikle şu değerlere bakın:
# - Requests per second
# - Time per request
# - Transfer rate

Apache’nin durumunu izlemek için mod_status çok kullanışlıdır:

# mod_status etkinleştirme
a2enmod status

# /etc/apache2/mods-available/status.conf
<Location /server-status>
    SetHandler server-status
    Require ip 127.0.0.1 10.0.0.0/24
</Location>

# Canlı izleme
watch -n 1 'curl -s http://localhost/server-status?auto | grep -E "BusyWorkers|IdleWorkers|Waiting|Reading|Writing"'

Log Analizi ile Sorun Tespiti

Timeout sorunlarını tespit etmenin en iyi yolu log analizidir:

# Timeout alan istekleri tespit et
grep "408" /var/log/apache2/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head 20

# Çok uzun süren istekler (request time'ı loglamak için önce formatı ayarlayın)
# LogFormat'a %T (saniye) veya %D (mikrosaniye) ekleyin:
LogFormat "%h %l %u %t "%r" %>s %b %T" combined_with_time

# 10 saniyeden uzun süren istekler
awk '$NF > 10' /var/log/apache2/access.log | awk '{print $7}' | sort | uniq -c | sort -rn

Daha detaylı bir log formatı için:

# /etc/apache2/apache2.conf
LogFormat "%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i" %T/%D" performance
CustomLog /var/log/apache2/performance.log performance

Sık Yapılan Hatalar ve Çözümleri

Hata 1: KeepAliveTimeout’u çok yüksek tutmak

Birçok yönetici varsayılan değeri 15 saniye görüyor ve olduğu gibi bırakıyor. Yoğun trafikte bu işçi açlığına yol açar. İzleme yapın ve gerçek değerlere göre karar verin.

Hata 2: Timeout’u global tutup location bazında özelleştirmemek

Her endpoint aynı timeout değerini gerektirmez. Upload endpoint’leri, ödeme sayfaları, rapor oluşturma işlemleri daha uzun timeout’a ihtiyaç duyar.

Hata 3: mod_reqtimeout’u görmezden gelmek

Bu modül hem güvenlik hem performans açısından kritik. Kurulum sonrası aktif olmayan sunucularda Slowloris’e açık kapı bırakabilirsiniz.

Hata 4: MPM ile uyumsuz KeepAlive ayarları

Prefork kullanıyorsanız KeepAliveTimeout değerini düşük tutun. Event MPM’e geçiş yapmanız bu konuda size çok daha fazla esneklik sağlar.

Hata 5: ProxyTimeout’u unutmak

Reverse proxy senaryolarında Apache’nin kendi Timeout’unu ayarlayıp backend ProxyTimeout’unu unutmak çok yaygın. Her ikisini de yapılandırın.

Sonuç

Apache’de Timeout ve KeepAlive optimizasyonu tek seferlik bir iş değil, sürekli izleme ve ayarlama gerektiren bir süreç. Şu ana kadar anlattıklarımı özetleyecek olursak: Timeout’u 300 saniyeden 60-120 saniyeye indirmek birinci adımınız olmalı. RequestReadTimeout direktifini Slowloris saldırılarına karşı aktive edin. KeepAliveTimeout’u 5 saniye olarak başlatın, sunucunuzu izleyin ve trafiğinize göre ince ayar yapın.

Kullandığınız MPM’i bilerek bu değerleri ayarlamak çok önemli. Prefork’ta her boşta bağlantı bir işçiyi tutuyor; Event MPM’e geçiş yapabiliyorsanız hem KeepAlive yönetimi hem de genel performans açısından ciddi kazanım elde edersiniz.

Son olarak, herhangi bir değişikliği önce test ortamında deneyin, ab ile yük testi yapın, mod_status ile gerçek zamanlı izleme kurun ve loglarınızı analiz edin. Sunucu yönetimi sonuçta veri odaklı karar alma sürecidir. Sezgiyle değil, gözlemle optimize edin.

Yorum yapın