Apache MPM Worker, Event ve Prefork Karşılaştırması: Hangisini Seçmeli?

Apache’yi kurdunuz, çalıştırdınız, her şey güzel görünüyor. Peki sunucunuz yük altında neden yanıt vermez hale geliyor? Ya da neden PHP uygulamanız belirli bir MPM modülüyle çalışmıyor? İşte bu soruların cevabı büyük ihtimalle MPM seçiminizde gizli. Apache’nin MPM (Multi-Processing Module) mimarisi, web sunucusunun gelen istekleri nasıl işleyeceğini belirleyen temel yapı taşıdır ve doğru seçim yapmak performans ile kararlılık açısından kritik önem taşır.

MPM Nedir ve Neden Önemlidir?

Apache HTTP Server, istemci bağlantılarını yönetmek için farklı stratejiler kullanabilir. Bu stratejiler MPM modülleri aracılığıyla hayata geçirilir. Her modül, süreç ve iş parçacığı (thread) kullanımını farklı şekilde organize eder. Yanlış MPM seçimi; yüksek bellek tüketimine, yetersiz eşzamanlı bağlantı kapasitesine veya uygulama uyumsuzluklarına yol açabilir.

Linux üzerinde Apache ile çalışırken esas olarak üç MPM seçeneğiyle karşılaşırsınız:

  • Prefork: Her istek için ayrı bir süreç (process) kullanır
  • Worker: Süreçler içinde iş parçacıkları (thread) kullanır
  • Event: Worker’ın geliştirilmiş hali, keep-alive bağlantılarını daha verimli yönetir

Bu yazıda bu üç modülü derinlemesine inceleyeceğiz, gerçek dünya senaryolarıyla karşılaştıracağız ve hangi durumda hangisini seçmeniz gerektiğini netleştireceğiz.

Prefork MPM: Eski Ama Güvenilir

Prefork, Apache’nin en eski ve en basit MPM modülüdür. Çalışma mantığı son derece açıktır: Ana süreç (parent process), gelen istekleri karşılamak için önceden bir havuz dolusu alt süreç (child process) başlatır. Her alt süreç tek bir bağlantıyı işler ve o bağlantı bitene kadar başka iş almaz.

Prefork Nasıl Çalışır?

Ana süreç, MinSpareServers ve MaxSpareServers direktifleriyle belirlenen aralıkta boşta bekleyen süreç sayısını sürekli dengeler. Yoğunluk artınca yeni süreçler fork edilir, azalınca fazlalıklar sonlandırılır. Bu mekanizma basit ve öngörülebilir ama kaynak kullanımı açısından pahalıdır.

# Mevcut MPM modülünü kontrol etme
apache2ctl -V | grep -i mpm
# veya
httpd -V | grep -i mpm

# Yüklü MPM modüllerini listeleme
apache2ctl -M | grep mpm
# /etc/apache2/mods-available/mpm_prefork.conf (Ubuntu/Debian)
<IfModule mpm_prefork_module>
    StartServers             5
    MinSpareServers          5
    MaxSpareServers         10
    MaxRequestWorkers      150
    MaxConnectionsPerChild   0
</IfModule>

Direktiflerin açıklaması:

  • StartServers: Apache başladığında oluşturulan alt süreç sayısı
  • MinSpareServers: Minimum boşta bekleyen süreç sayısı
  • MaxSpareServers: Maximum boşta bekleyen süreç sayısı
  • MaxRequestWorkers: Aynı anda işlenebilecek maksimum istek sayısı (eski adı MaxClients)
  • MaxConnectionsPerChild: Bir sürecin kaç istek işledikten sonra yeniden başlayacağı (0 = sınırsız)

Prefork’un Güçlü Yanları

Prefork’un en büyük avantajı thread-safety sorunlarından tamamen bağımsız olmasıdır. Her süreç kendi bellek alanında çalıştığı için bir süreçteki çöküş diğerlerini etkilemez. Bu özellik, özellikle eski nesil PHP modülleri (mod_php) için hayat kurtarıcıdır. PHP’nin Zend Engine’i ve birçok PHP eklentisi başlangıçta thread-safe olmayan şekilde yazılmıştır.

Gerçek dünya senaryosu: Diyelim ki 2015 yılından kalma bir PHP uygulaması çalıştırıyorsunuz. Uygulama eski bir SOAP kütüphanesi kullanıyor ve bu kütüphane global değişkenlere thread-safe olmayan şekilde erişiyor. Worker veya Event MPM ile bu uygulama rastgele çöküşler yaşar, hata ayıklamak son derece zor olur. Prefork ile her istek izole bir süreçte çalıştığı için bu sorun ortadan kalkar.

Prefork’un Zayıf Yanları

Her istek için ayrı bir süreç anlamına geldiğinden bellek tüketimi hızla artar. 1000 eşzamanlı bağlantı için 1000 süreç gerekir. Tipik bir Apache+mod_php süreci 20-50 MB bellek tükettiğinde matematik kabus olmaya başlar.

# Prefork ile süreç sayısını ve bellek kullanımını izleme
ps aux | grep apache2 | awk '{print $6}' | awk '{sum+=$1} END {print "Toplam RSS: " sum/1024 " MB"}'

# Aktif worker sayısını kontrol etme
apache2ctl status | grep -E "requests currently being processed|idle workers"

Worker MPM: Thread Tabanlı Yaklaşım

Worker MPM, hem süreç hem de iş parçacığı kullanarak daha verimli bir model sunar. Her süreç birden fazla thread çalıştırır ve her thread bir bağlantıyı işler. Bu yaklaşım aynı yük için çok daha az bellek kullanır.

Worker Konfigürasyonu

# /etc/apache2/mods-available/mpm_worker.conf
<IfModule mpm_worker_module>
    StartServers             2
    MinSpareThreads         25
    MaxSpareThreads         75
    ThreadLimit             64
    ThreadsPerChild         25
    MaxRequestWorkers      150
    MaxConnectionsPerChild   0
</IfModule>

Direktiflerin açıklaması:

  • StartServers: Başlangıçta oluşturulan süreç sayısı
  • MinSpareThreads: Minimum boşta bekleyen thread sayısı (tüm süreçler genelinde)
  • MaxSpareThreads: Maximum boşta bekleyen thread sayısı
  • ThreadLimit: Bir sürecin oluşturabileceği maksimum thread sayısı (derleme zamanı limiti)
  • ThreadsPerChild: Her sürecin oluşturacağı thread sayısı
  • MaxRequestWorkers: Toplam eşzamanlı bağlantı kapasitesi (StartServers * ThreadsPerChild)

Örneğin yukarıdaki konfigürasyonda maksimum kapasite 150 / 25 = 6 süreç * 25 thread = 150 eşzamanlı bağlantı olur.

Worker’ın Avantajları ve Sınırlamaları

Worker, Prefork’a kıyasla bellek kullanımında ciddi avantaj sağlar. 6 süreç ile 150 eşzamanlı bağlantı desteklenirken Prefork 150 süreç gerektirir. Context switching maliyeti de önemli ölçüde azalır.

Ancak Worker, thread-safety gerektiren uygulamalar için sorunlu olabilir. mod_php ile Worker kullanmak güvenli değildir. Bu nedenle Worker tercih edildiğinde PHP için PHP-FPM kullanmak zorunlu hale gelir.

# Worker MPM'e geçiş (Ubuntu/Debian)
sudo a2dismod mpm_prefork
sudo a2enmod mpm_worker
sudo systemctl restart apache2

# PHP-FPM kurulumu ve aktivasyonu
sudo apt install php8.1-fpm
sudo a2enmod proxy_fcgi setenvif
sudo a2enconf php8.1-fpm
sudo systemctl restart apache2

Event MPM: Modern Çözüm

Event MPM, Worker MPM’in geliştirilmiş bir versiyonudur ve Apache 2.4 ile birlikte production-ready hale gelmiştir. Temel fark, keep-alive bağlantılarını yönetme şeklindedir.

Keep-Alive Problemi ve Event’in Çözümü

HTTP keep-alive, aynı TCP bağlantısı üzerinden birden fazla HTTP isteği yapılmasını sağlar. Bu özellik network overhead’i azaltır ama Worker MPM’de ciddi bir sorun yaratır: Bağlantı keep-alive modunda beklerken Worker’da bir thread meşgul kalır ve yeni isteklere cevap veremez. Modern web sayfaları onlarca kaynak (CSS, JS, resim) yüklediğinden bu durum thread havuzunu hızla tüketebilir.

Event MPM bu sorunu çözmek için özel bir “listener thread” kullanır. Keep-alive bağlantıları bu özel thread tarafından izlenir, gerçek bir istek geldiğinde worker thread havuzuna yönlendirilir. Böylece worker thread’ler boşta bekleyen bağlantılar için değil, aktif istekler için kullanılır.

# /etc/apache2/mods-available/mpm_event.conf
<IfModule mpm_event_module>
    StartServers             2
    MinSpareThreads         25
    MaxSpareThreads         75
    ThreadLimit             64
    ThreadsPerChild         25
    MaxRequestWorkers      400
    MaxConnectionsPerChild  0
    AsyncRequestWorkerFactor 2
</IfModule>

Event’e özgü direktif:

  • AsyncRequestWorkerFactor: Eşzamanlı bağlantı kapasitesini artıran çarpan. MaxRequestWorkers değeri bu faktörle çarpılarak asenkron (keep-alive) bağlantı limiti hesaplanır

Event ile Gerçekçi Konfigürasyon

Yoğun trafikli bir web sunucusu için Event MPM örnek konfigürasyonu:

# Yüksek trafikli site için optimize edilmiş Event MPM konfigürasyonu
<IfModule mpm_event_module>
    StartServers             4
    MinSpareThreads         75
    MaxSpareThreads        250
    ThreadLimit             64
    ThreadsPerChild         32
    MaxRequestWorkers      800
    MaxConnectionsPerChild 10000
    AsyncRequestWorkerFactor 4
</IfModule>

# KeepAlive ayarları da optimize edilmeli
KeepAlive On
KeepAliveTimeout 5
MaxKeepAliveRequests 100

Bu konfigürasyonla maksimum 25 süreç (800/32) çalışır ve her biri 32 thread ile hizmet verir. AsyncRequestWorkerFactor 4 sayesinde keep-alive bağlantıları için 3200’e kadar eşzamanlı bağlantı tutulabilir.

MPM Modülü Değiştirme ve Yönetim

Üretim ortamında MPM değişikliği dikkatli yapılmalıdır. Önce test ortamında doğrulayın.

# Mevcut durumu kontrol etme
apache2ctl -M | grep mpm

# Event MPM'e geçiş
sudo a2dismod mpm_prefork mpm_worker
sudo a2enmod mpm_event

# Konfigürasyonu test etme (sunucuyu yeniden başlatmadan önce kritik!)
sudo apache2ctl configtest

# Sadece konfigürasyon değişikliği varsa graceful restart yeterli
sudo apache2ctl graceful

# MPM modülü değişikliği için tam restart gerekli
sudo systemctl restart apache2
# RHEL/CentOS/Rocky Linux üzerinde MPM değiştirme
# /etc/httpd/conf.modules.d/00-mpm.conf dosyasını düzenle
sudo vi /etc/httpd/conf.modules.d/00-mpm.conf

# Dosya içeriği şöyle olmalı (sadece biri aktif olmalı):
# LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
# LoadModule mpm_worker_module modules/mod_mpm_worker.so
LoadModule mpm_event_module modules/mod_mpm_event.so

sudo systemctl restart httpd

Performans İzleme ve Ayar

Doğru MPM seçimi kadar doğru izleme de önemlidir. mod_status modülü ile Apache’nin iç durumunu anlık olarak takip edebilirsiniz.

# mod_status aktivasyonu ve güvenli konfigürasyon
sudo a2enmod status

# /etc/apache2/mods-enabled/status.conf içeriği
<Location "/server-status">
    SetHandler server-status
    Require local
    # Veya güvenilir monitoring IP için:
    # Require ip 192.168.1.0/24
</Location>

ExtendedStatus On
# Komut satırından durum bilgisi alma
curl -s http://localhost/server-status?auto | grep -E "BusyWorkers|IdleWorkers|Scoreboard"

# Sürekli izleme için watch komutuyla
watch -n 2 'curl -s http://localhost/server-status?auto | grep -E "BusyWorkers|IdleWorkers|Total kbytes"'

Scoreboard çıktısındaki karakterlerin anlamı:

  • _: Boşta (idle) worker
  • W: Aktif istek işleniyor
  • K: Keep-alive bekleniyor
  • L: DNS sorgusu
  • .: Açık slot, süreç yok

Event MPM ile yoğun saatlerde K karakterlerinin oranına bakın. Eğer K’lar çoksa ve Worker MPM kullanıyorsanız Event’e geçiş ciddi fark yaratacaktır.

Hangi Senaryoda Hangi MPM?

Prefork Kullanmanız Gereken Durumlar

  • mod_php kullanıyorsunuz ve PHP-FPM’e geçemiyorsunuz: Eski sistemlerde veya paylaşımlı hosting ortamlarında bu durum sıkça karşılaşılır. Thread-safe olmayan PHP eklentileri (bazı eski database sürücüleri, bazı SOAP kütüphaneleri) varsa Prefork güvenli limandır.
  • Uygulama thread-safety garantisi vermiyor: Eski Perl veya Python modülleri bağlantıyla çalışıyorsa Prefork tercih edin.
  • Debug ve izolasyon öncelikli: Geliştirme ortamlarında bir isteğin diğerlerini etkilemesini istemiyorsanız Prefork kullanın.
  • Çok düşük trafikli sunucu: Günde birkaç yüz istek alan iç ağ araçları için Prefork’un getirdiği overhead kabul edilebilir.

Worker Kullanmanız Gereken Durumlar

  • PHP-FPM kullanıyorsunuz: Worker+PHP-FPM kombinasyonu stabil ve verimlidir. PHP işleme Apache’den ayrıştığı için her ikisi de bağımsız optimize edilebilir.
  • Statik içerik ağırlıklı site: Resim, CSS, JS gibi statik dosyaları servis eden sunucularda Worker bellek avantajıyla öne çıkar.
  • Apache 2.2 kullanmak zorundaysınız: Event MPM Apache 2.4 ile stable olduğundan daha eski sürümlerde Worker tercih edilir.

Event Kullanmanız Gereken Durumlar

  • Modern uygulama, yüksek eşzamanlı bağlantı: Apache 2.4 üzerinde PHP-FPM, Python WSGI veya Ruby uygulamaları çalıştırıyorsanız Event birinci tercih olmalıdır.
  • SSL/TLS yoğun ortam: HTTPS bağlantılarında keep-alive daha kritik hale gelir. TLS handshake maliyeti nedeniyle bağlantılar daha uzun tutulur, Event bu durumu çok daha iyi yönetir.
  • Modern CDN arkasında: Yük dengeleyici veya CDN arkasında çalışan origin sunucularda yüzlerce keep-alive bağlantısı olabilir. Event bu yükü Worker’dan çok daha verimli taşır.
  • Reverse proxy görevi: Apache’yi Tomcat, Node.js veya başka backend’lere proxy olarak kullanıyorsanız Event’in asenkron yapısı fark yaratır.

Yaygın Hatalar ve Çözümleri

Hata 1: Worker/Event ile mod_php kullanmak

# Bu konfigürasyon sorun yaratır!
# Worker veya Event MPM aktif + mod_php yüklü

# Kontrol:
apache2ctl -M | grep php

# Çözüm: mod_php devre dışı bırakılmalı
sudo a2dismod php8.1

# PHP-FPM'e geçiş
sudo a2enmod proxy_fcgi
sudo a2enconf php8.1-fpm

Hata 2: MaxRequestWorkers değerini sunucu kapasitesinin üzerinde tutmak

Kullanılabilir bellek göz önünde bulundurulmadan yapılan konfigürasyonlar sunucuyu swap’e iter ve performans dibe vurur.

# Kullanılabilir belleği kontrol et
free -m

# Formül: MaxRequestWorkers = (Kullanılabilir RAM) / (Süreç başına ortalama bellek)
# Örnek: 4GB RAM, 50MB/süreç için:
# MaxRequestWorkers = (4096 - 512 sistem rezervi) / 50 = ~71
# Prefork için bu değer kullanılır
# Worker/Event için ThreadsPerChild ile bölerek süreç sayısı bulunur

Hata 3: Graceful restart yerine tam restart zorunluluğunu göz ardı etmek

Sadece konfigürasyon parametreleri değiştiğinde graceful restart yeterlidir. MPM modülü değişikliği her zaman tam restart gerektirir.

Konfigürasyonu Doğrulama ve Test

Değişiklik yaptıktan sonra mutlaka test edin:

# Syntax kontrolü
sudo apache2ctl configtest

# MPM modülünü ve konfigürasyonu doğrulama
apache2ctl -V

# Basit yük testi (ab - Apache Benchmark)
ab -n 1000 -c 100 http://localhost/

# Daha gerçekçi test için wrk kullanımı
wrk -t4 -c200 -d30s http://localhost/

# Süreç/thread durumunu izleme
ps -eLf | grep apache2 | wc -l

Yük testi sırasında farklı bir terminalde server-status çıktısını izleyin. BusyWorkers değeri MaxRequestWorkers’a yaklaşıyorsa konfigürasyonunuzu gözden geçirmeniz gerekiyor demektir.

Sonuç

Apache MPM seçimi, düşünülmeden geçiştirilen ama performans üzerinde dramatik etkisi olan bir karardır. Üç ana seçeneği kısaca özetlemek gerekirse: Prefork eskimiş ama eski PHP uygulamaları için hala gerekli bir güvenli liman, Worker thread bazlı verimli yaklaşımıyla sağlam bir orta yol, Event ise modern Apache kurulumları için fiili standart.

Eğer yeni bir kurulum yapıyorsanız ve PHP-FPM kullanıyorsanız doğrudan Event MPM ile başlayın. Eski bir sistemi taşıyorsanız önce PHP-FPM geçişini yapın, ardından MPM değişikliğine geçin. Geçiş yapamıyorsanız ve mod_php zorunluysa Prefork ile devam edin ama bellek kullanımını yakından izleyin.

Performans iyileştirmesi her zaman ölçümle başlar. MPM değiştirmeden önce mod_status ve ab gibi araçlarla mevcut durumu belgeleyin, değişiklik sonrasında aynı testleri tekrarlayın. Gerçek verilerle karar vermek, sezgiyle karar vermekten her zaman daha güvenli bir yoldur.

Son olarak şunu söylemek gerekir: MPM optimizasyonu tek başına yeterli değildir. MPM ayarlarını MySQL bağlantı havuzu, PHP-FPM süreç sayısı ve işletim sistemi dosya tanımlayıcı limitleriyle birlikte değerlendirin. Sistem bir bütündür ve bir katmandaki iyileştirme diğer katmanlardaki darboğazları gün yüzüne çıkarır.

Yorum yapın