Kampanyayı duyurdunuz, e-posta listesine mail gitti, sosyal medyada paylaşım yapıldı. İlk on dakika harika: analitikte eşzamanlı 40 kişi görünüyor. Sonra site cevap vermemeye başlıyor. Bazı ziyaretçiler beyaz ekran görüyor, bazıları "503 Service Unavailable", bazıları da 30 saniye bekledikten sonra sayfayı açabiliyor. Sunucu paneline bakıyorsunuz: CPU %35, RAM yarı dolu, disk rahat. Hiçbir kaynak tükenmiş görünmüyor ama site ayakta değil.
Tükenmiş bir kaynak var, sadece grafiklerde görünmüyor: PHP worker. Kaç kişinin aynı anda dinamik bir sayfa üretebileceğini belirleyen şey CPU çekirdeği ya da RAM değil, aynı anda kaç PHP sürecinin çalışabildiğidir. Bu sayı dolduğunda gelen istekler kuyruğa girer, kuyruk da dolduğunda sunucu 502 ya da 503 döndürmeye başlar. Paylaşımlı hosting panellerinde aynı olay "Resource Limit Is Reached" veya "Entry Process limit" olarak karşınıza çıkar.
Bu yazıda worker kavramının sunucudaki fiziksel karşılığını, worker sayısını eşzamanlı ziyaretçiye çeviren basit bir hesabı, kuyruk dolduğunda hangi hata kodunun neden geldiğini ve worker tüketimini gerçekten azaltan kaldıraçları ele alacağız. Sonunda paylaşımlı hostingden VDS'e geçiş eşiğini tahminle değil rakamla belirleyebileceksiniz.
PHP Worker Nedir? Sunucudaki Fiziksel Karşılığı#
PHP worker, bir PHP isteğini baştan sona işleyen tek bir işletim sistemi sürecidir. Modern yığında adı PHP-FPM child process'tir. FPM (FastCGI Process Manager) açılışta bir havuz (pool) oluşturur ve bu havuzda önceden başlatılmış birkaç süreç bekletir. Nginx veya Apache bir .php isteği aldığında onu havuzdaki boş bir sürece devreder.
Kritik özellik şudur: bir worker aynı anda yalnızca bir isteğe bakar. İstek bitene kadar o süreç meşguldür. WordPress bir sayfayı üretirken PHP dosyalarını yükler, veritabanına sorgu atar, cevabı bekler, HTML'i birleştirir. Bu 200 milisaniye de sürebilir 3 saniye de; süre boyunca o worker başka kimseye hizmet edemez.
Ortama göre kavramın adı değişir, işleyişi değişmez:
| Ortam | Kavramın adı | Ayarın yeri |
|---|---|---|
| Nginx + PHP-FPM (VDS) | pool child process | pm.max_children |
| LiteSpeed / OpenLiteSpeed | External App max connections | Max Connections |
| CloudLinux'lu paylaşımlı hosting | Entry Process (EP) | LVE limitleri, kullanıcı değiştiremez |
| Apache + mod_php | MaxRequestWorkers | mpm_prefork.conf |
Paylaşımlı hostingde bu sayı sizin kontrolünüzde değildir ve genellikle 10-30 arasındadır. Hesabınıza atanmış limitleri cPanel üzerinden görebilirsiniz; paylaşımlı hosting kaynak limitleri yazısında hangi sayacın neyi ölçtüğü ayrıntılı anlatılıyor.
Önemli bir yanlış anlama: statik dosyalar worker harcamaz. Görseller, CSS, JS, font dosyaları doğrudan web sunucusu tarafından servis edilir. "Sayfamda 80 istek var" cümlesi 80 worker anlamına gelmez; genelde bunların yalnızca 1-3 tanesi PHP'dir.
Kaç Worker Kaç Eşzamanlı Ziyaretçi Eder#
Formül şaşırtıcı derecede basittir:
Saniyedeki PHP isteği kapasitesi = worker sayısı ÷ ortalama PHP süresi (saniye)
10 worker ve ortalama 400 ms PHP süresi varsa: 10 ÷ 0,4 = saniyede 25 PHP isteği. Bu teorik tavandır. Pratikte tavana yaklaşamazsınız, çünkü istekler eşit aralıklarla gelmez; kümelenir. Kuyruk teorisinin bilinen sonucu şudur: bir sistem %70 doluluğu geçtiğinde bekleme süresi doğrusal değil, üstel biçimde artar. Bu yüzden güvenli kapasite teorik tavanın yaklaşık üçte ikisidir.
| Worker | Ort. PHP süresi | Teorik istek/sn | Güvenli istek/sn (%65) |
|---|---|---|---|
| 5 | 800 ms | 6,3 | 4 |
| 10 | 400 ms | 25,0 | 16 |
| 20 | 300 ms | 66,7 | 43 |
| 40 | 200 ms | 200,0 | 130 |
Tablodaki en öğretici satır ilk ikisi arasındaki fark: worker sayısını iki katına çıkarmakla PHP süresini yarıya indirmek aynı kapasiteyi verir. Ama ilkinin RAM maliyeti vardır, ikincisinin yoktur. Optimizasyonun worker artırmaktan önce gelmesinin sebebi budur.
Şimdi bunu ziyaretçiye çevirelim. Bir ziyaretçi oturumda ortalama 4 sayfa görüntülüyor ve sayfalar arasında 30 saniye geçiriyor olsun; yani sayfa görüntüleme hızı her 30 saniyede 1. Önbelleksiz bir WooCommerce sitesinde bir sayfa görüntülemesi tek PHP isteği değildir: sayfanın kendisi + sepet parçacığı isteği (?wc-ajax=get_refreshed_fragments) + admin-ajax çağrıları ile sayfa başına yaklaşık 2 PHP isteği oluşur.
10 worker ve 400 ms ile güvenli kapasite 16 istek/sn idi:
- 16 ÷ 2 = saniyede 8 sayfa görüntüleme
- 8 × 30 saniye = aynı anda gezinen yaklaşık 240 ziyaretçi
Aynı sitede tam sayfa önbelleği devredeyse ve isteklerin %90'ı PHP'ye hiç ulaşmıyorsa bu sayı on katına çıkar. Önbelleğin neden en büyük kaldıraç olduğu bu çarpanda gizlidir.
Dikkat edilecek nokta: ödeme, sepet ve hesabım sayfaları önbelleğe alınamaz. Kampanya trafiğinde ziyaretçilerin normalden çok daha büyük bir kısmı bu sayfalara gider, dolayısıyla önbellek isabet oranı düşer ve gerçek kapasiteniz normal günlerdeki ölçümünüzün epeyce altında kalır. Kampanya planlarken önbelleksiz kapasitenizi esas alın.
Kuyruk Dolunca Neden 502 veya 503 Alıyorsunuz#
Tüm worker'lar meşgulken gelen istek anında reddedilmez; önce listen kuyruğuna alınır. Kuyruğun boyu listen.backlog ile belirlenir. Sıradaki bir istek üç şekilde biter ve her biri farklı bir hata kodu üretir:
1. Kuyrukta bekledi, sonra çalıştı → sayfa açılır ama yavaş. Kullanıcı 8-20 saniyelik bir bekleme görür. En sinsi durum budur, çünkü izlemede hata görünmez, yalnızca yanıt süreleri yükselir.
2. Kuyruk taştı → 502 Bad Gateway. Web sunucusu FPM soketine bağlanamaz. Nginx günlüğüne düşen tipik satır:
connect() to unix:/run/php/php8.2-fpm.sock failed (11: Resource temporarily unavailable)
while connecting to upstream
3. Zaman aşımına uğradı → 504 veya 503. İstek kuyruktan çıkamadan fastcgi_read_timeout doldu:
upstream timed out (110: Connection timed out) while reading response header from upstream
Bu arada FPM kendi günlüğüne asıl teşhisi yazar; sunucunuzda görmeniz gereken satır budur:
WARNING: [pool www] server reached pm.max_children setting (10),
consider raising it
Paylaşımlı hostingde ise aynı olay farklı bir yüzle gelir: 508 Resource Limit Is Reached. Bu, CloudLinux'un LVE katmanının hesabınızı eşzamanlı süreç (EP) limitinde durdurduğu anlamına gelir. Hata kodlarının ayrıntılı ayrımı için 503 Service Unavailable, 502 Bad Gateway ve 508 Resource Limit yazılarına bakabilirsiniz.
| Belirti | Sebep | İlk yapılacak |
|---|---|---|
| Sayfalar açılıyor ama 10+ sn | Kuyrukta bekleme | Ortalama PHP süresini düşürün |
| 502 Bad Gateway, aralıklı | Kuyruk taşıyor | max_children ve backlog kontrolü |
| 504 Gateway Timeout | Uzun süren tek istek | Yavaş sorgu / dış API araması |
| 508 Resource Limit | EP limiti (paylaşımlı) | Önbellek + wp-cron düzeltmesi |
| Panel "kaynak aşıldı" uyarısı | Süreç veya CPU limiti | Kaynak kullanım grafiği inceleme |
Worker Sayısını Belirleyen Şey RAM'dir, Trafik Değil#
Sunucu yönetiminde en sık yapılan müdahale pm.max_children değerini rastgele yükseltmektir. 10'dan 60'a çıkarırsanız site hızlanmaz; swap'e düşer ve tamamen kilitlenir. Çünkü her worker gerçek bellek tüketir.
Doğru hesap şudur:
pm.max_children = (PHP'ye ayrılabilecek RAM) ÷ (bir worker'ın ortalama RSS değeri)
Kendi sunucunuzdaki gerçek değeri ölçün:
# Süreç adı dağıtıma göre değişir: php-fpm, php-fpm8.2, php-fpm8.3
ps --no-headers -o rss,comm -C php-fpm8.2 \
| awk '{s+=$1; n++} END {printf "%d surec, ortalama %.0f MB\n", n, s/n/1024}'
Tipik değerler: sade bir WordPress sitesinde worker başına 40-70 MB, eklenti yüklü bir WooCommerce mağazasında 90-150 MB. 4 GB RAM'li bir VDS'te işletim sistemi, MySQL ve web sunucusuna 1,5 GB ayırırsanız PHP'ye 2,5 GB kalır. Worker başına 110 MB ile:
2560 MB ÷ 110 MB ≈ 23 worker
Bu, 4 GB RAM için gerçekçi bir tavandır. Örnek bir havuz yapılandırması:
[wordpress]
user = www-data
group = www-data
listen = /run/php/wordpress.sock
pm = dynamic
pm.max_children = 22
pm.start_servers = 6
pm.min_spare_servers = 4
pm.max_spare_servers = 10
pm.max_requests = 500
; Teşhis için şart olan üç satır
pm.status_path = /fpm-status
slowlog = /var/log/php-fpm/wordpress-slow.log
request_slowlog_timeout = 5s
request_terminate_timeout = 120s
php_admin_value[memory_limit] = 256M
pm.max_requests = 500, her süreci 500 istekten sonra yeniden başlatarak sızıntılı eklentilerin belleği şişirmesini engeller. request_terminate_timeout ise takılmış bir isteğin worker'ı sonsuza kadar tutmasını önler — bu tek satır, dış API'ye bağlanan eklentilerin sebep olduğu kilitlenmelerin çoğunu keser. Havuz parametrelerinin ayrıntısı için PHP-FPM pool ayarları yazısına bakın.
Havuzun anlık durumunu görmek için nginx tarafına küçük bir konum ekleyin:
location = /fpm-status {
allow 127.0.0.1;
deny all;
include fastcgi_params;
fastcgi_pass unix:/run/php/wordpress.sock;
}
curl -s "http://127.0.0.1/fpm-status?full" | head -20
Çıktıdaki üç satır her şeyi söyler: listen queue (o an bekleyen istek sayısı), max active processes (zirvede kaç worker meşguldü) ve max children reached (limite kaç kez dayanıldı). Son sayaç sıfırdan büyükse limitinize vurmuşsunuz demektir.
Worker Tüketimini Azaltan Gerçek Kaldıraçlar#
Worker eklemek en pahalı çözümdür. Aşağıdaki kaldıraçlar aynı donanımla kapasiteyi kat kat artırır.
1. Tam Sayfa Önbelleği#
En büyük kaldıraç budur. Oturum açmamış ziyaretçiye hazır HTML sunulduğunda istek PHP'ye hiç ulaşmaz, dolayısıyla worker harcamaz. Blog ve kurumsal sitelerde isabet oranı %90'ın üzerine çıkar. LiteSpeed sunucuda LiteSpeed Cache sunucu seviyesinde çalıştığı için PHP'yi tamamen atlar; nginx tarafında FastCGI önbelleği aynı işi görür.
E-ticarette gerçekçi olun: ürün ve kategori sayfaları önbelleklenir, sepet/ödeme/hesabım önbelleklenemez.
2. wp-cron#
WordPress zamanlanmış görevleri, siteye gelen ziyaretçi isteğinin içinde çalıştırır. Yoğun anda gelen her istek, bir de bakım görevini tetikleme riskini taşır ve o worker uzun süre meşgul kalır. Trafik ne kadar yüksekse wp-cron.php o kadar sık tetiklenir; yani tam yük altında sistem kendi kendine ek yük bindirir.
// wp-config.php
define( 'DISABLE_WP_CRON', true );
# crontab -e
*/5 * * * * cd /home/kullanici/public_html && /usr/bin/wp cron event run --due-now --quiet >/dev/null 2>&1
Erişim günlüğünüzde durumun ne kadar ciddi olduğunu tek komutla görürsünüz:
grep -c "wp-cron.php" /var/log/nginx/access.log
Günlük toplam isteğin %5'inden fazlasını wp-cron oluşturuyorsa bu kalem tek başına kapasitenizin bir kısmını yiyor demektir.
3. admin-ajax.php ve Heartbeat#
WordPress'in Heartbeat API'si, yönetim paneli açıkken varsayılan olarak 15-60 saniyede bir admin-ajax.php isteği atar. Yazı düzenleme ekranında bu süre 15 saniyeye iner. Panelde çalışan 5 kişi, hiçbir şey yapmasa bile sürekli worker tüketir. Ayrıca birçok eklenti ön yüzde de admin-ajax kullanır.
# Ön yüzden gelen admin-ajax istekleri hangi eylemi çağırıyor?
grep "admin-ajax.php" /var/log/nginx/access.log \
| grep -o "action=[a-z_]*" | sort | uniq -c | sort -rn | head -15
Heartbeat aralığını uzatmak ve gereksiz eylemleri kapatmak, yalnızca yönetici panelinde bile hissedilir fark yaratır; WordPress yönetici paneli yavaş yazısı bu tarafa odaklanıyor.
4. Yavaş Sorgular ve Yavaş Eklentiler#
Bir worker'ın meşgul kalma süresini büyük ölçüde veritabanı bekleyişi belirler. İndekssiz bir wp_postmeta sorgusu tek başına PHP süresini 200 ms'den 2 saniyeye çıkarabilir — bu, kapasitenizin onda birine düşmesi demektir. FPM'in yavaş günlüğü suçluyu doğrudan gösterir:
grep "script_filename" /var/log/php-fpm/wordpress-slow.log \
| sort | uniq -c | sort -rn | head
Eklenti bazlı teşhis için hangi eklenti siteyi yavaşlatıyor yazısındaki yöntemi izleyin.
5. OPcache ve Nesne Önbelleği#
OPcache, derlenmiş PHP kodunu bellekte tuttuğu için her istekte dosyaların yeniden derlenmesini engeller; kapalıysa PHP süresi kolayca ikiye katlanır ve doğrudan worker kapasitenize yansır. Redis nesne önbelleği ise tekrarlayan veritabanı sorgularını keserek özellikle oturum açmış kullanıcı ve WooCommerce trafiğinde süreyi kısaltır.
| Kaldıraç | Tipik etki | Uygulama zorluğu |
|---|---|---|
| Tam sayfa önbelleği | PHP isteklerinde %70-90 azalma | Düşük |
| OPcache | PHP süresinde %30-50 azalma | Düşük |
| wp-cron düzeltmesi | Ani yük sıçramalarının kesilmesi | Düşük |
| Heartbeat ayarı | Panel kaynaklı yükte belirgin azalma | Düşük |
| Nesne önbelleği | Oturumlu trafikte %20-40 süre kazancı | Orta |
| Yavaş sorgu düzeltmesi | Kapasitede kata varan artış | Yüksek |
Hangi İsteklerin Worker Yediğini Nasıl Bulursunuz#
Tahmin yürütmeyin, ölçün. Nginx günlük biçimine yukarı akış süresini ekleyin:
log_format zamanli '$remote_addr "$request" $status '
'$body_bytes_sent $request_time $upstream_response_time';
access_log /var/log/nginx/access.log zamanli;
Sonra bir saniyeden uzun süren isteklerin hangi adresler olduğunu çıkarın:
# Son alan upstream süresi; 1 saniyeyi geçenleri adrese göre grupla
awk '$NF+0 > 1 {print $3}' /var/log/nginx/access.log \
| sort | uniq -c | sort -rn | head -20
Çıkan listede genellikle şu adayları görürsünüz: admin-ajax.php, wp-cron.php, arama sonuç sayfaları (/?s=), filtreleme parametreli kategori adresleri, WooCommerce sepet parçacığı isteği ve bir de sizin hiç beklemediğiniz bir eklenti uç noktası. Kapasite kazanmanın en hızlı yolu bu listenin ilk üç satırını düzeltmektir.
Paylaşımlı hostingde bu günlüklere erişemezsiniz; oradaki karşılığı cPanel'in kaynak kullanım grafikleridir. Hangi sayacın hangi limite dayandığını cPanel kaynak kullanımı izleme yazısından takip edebilirsiniz.
Paylaşımlı Hostingden VDS'e Ne Zaman Geçilir#
"Trafiğim arttı" cümlesi bir eşik değildir. Aşağıdaki göstergelerden ikisi birden doğruysa, optimizasyonla kazanacağınız yer kalmamış demektir:
- Önbellek doğru kurulu olmasına rağmen ayda birkaç kez 508 / kaynak limiti hatası alıyorsunuz.
- Günlük 3.000'den fazla önbelleklenemeyen (oturumlu, sepetli, ödeme) sayfa görüntülemesi var.
- Yoğun saatte eşzamanlı ziyaretçi 50'yi aşıyor ve bunların önemli kısmı e-ticaret akışında.
- Yanıt süresi normal saatlerde 500 ms iken yoğun saatte 3 saniyenin üstüne çıkıyor.
- Sitede sürekli çalışan bir arka plan işi var: XML ürün beslemesi, pazaryeri entegrasyonu, toplu fiyat güncelleme.
Son madde tek başına bile yeterlidir. Pazaryeri entegrasyonları saatlerce süren toplu işlemler yürütür ve paylaşımlı ortamdaki EP limitini tek başına doldurur.
| Senaryo | Uygun ortam | Beklenen worker |
|---|---|---|
| Blog / kurumsal, ayda 50 bin görüntüleme | Paylaşımlı hosting | 10-20 (EP) |
| WooCommerce, günde 100'den az sipariş | Paylaşımlı veya giriş seviyesi VDS | 15-25 |
| WooCommerce, günde 100+ sipariş veya entegrasyonlu | 4-8 GB VDS | 20-40 |
| Kampanya trafiği alan mağaza | 8-16 GB VDS | 40-80 |
VDS'e geçmenin asıl kazancı sayının büyümesi değil, sayının sizin kontrolünüzde olmasıdır: worker sayısını, PHP bellek limitini, zaman aşımlarını ve önbellek katmanını kendiniz belirlersiniz. Kaç çekirdek ve ne kadar bellek gerektiğine karar verirken VDS için kaç CPU ve RAM gerekir yazısındaki hesaplama işinizi kolaylaştırır.
Geçiş sonrası ilk hafta yapılacak iş bellidir: yukarıdaki ps komutuyla gerçek worker RSS'ini ölçün, pm.max_children değerini RAM'e göre ayarlayın, /fpm-status sayfasından "max children reached" sayacını izleyin. Sayaç bir hafta boyunca sıfır kalıyorsa yapılandırma doğrudur; artıyorsa önce PHP süresini düşürmeye, ancak ondan sonra worker eklemeye bakın.
Sıkça Sorulan Sorular#
PHP worker sayısını artırmak siteyi hızlandırır mı?#
Hayır, doğrudan hızlandırmaz. Worker sayısı sitenin kaç kişiye aynı anda hizmet edebileceğini belirler, tek bir sayfanın ne kadar sürede açıldığını değil. Yoğunlukta oluşan bekleme sürelerini kısaltır ama sayfa üretim süresine dokunmaz. Üstelik RAM'in izin verdiğinden fazla worker tanımlarsanız sunucu takas alanına düşer ve site tamamen kilitlenir.
10 PHP worker kaç eşzamanlı ziyaretçi demek?#
Ortalama PHP süresi 400 ms ise güvenli kapasite saniyede yaklaşık 16 istektir. Önbelleksiz bir WooCommerce sitesinde sayfa başına 2 PHP isteği düşünürseniz bu, aynı anda gezinen 200-250 ziyaretçiye karşılık gelir. Tam sayfa önbelleği devredeyse ve isteklerin %90'ı PHP'ye ulaşmıyorsa bu sayı on katına çıkabilir. Kesin rakam sitenizin ortalama PHP süresine bağlıdır.
503 hatası aldığımda hemen worker artırmalı mıyım?#
Önce sebebini bulun. 503, worker havuzunun dolduğunu söyler ama neden dolduğunu söylemez. Çoğu durumda suçlu tek bir yavaş uç noktadır: indekssiz bir sorgu, dış API'ye bağlanan bir eklenti ya da tetiklenen wp-cron. Yavaş günlüğe bakmadan worker artırmak sorunu birkaç hafta erteler, ardından aynı hata daha yüksek RAM tüketimiyle geri gelir.
Paylaşımlı hostingte PHP worker sayısını kendim değiştirebilir miyim?#
Hayır. Paylaşımlı ortamlarda eşzamanlı süreç limiti hesap paketinize bağlıdır ve sunucu yöneticisi tarafından belirlenir; cPanel üzerinden yalnızca izleyebilirsiniz. Yapabileceğiniz şey tüketimi azaltmaktır: tam sayfa önbelleği kurmak, wp-cron'u gerçek cron'a taşımak, Heartbeat aralığını uzatmak ve yavaş eklentileri ayıklamak.
PHP-FPM günlüğünde max_children uyarısını görüyorum, ne yapmalıyım?#
Bu uyarı havuzun dolduğunu kesin olarak doğrular. Önce ortalama worker bellek tüketimini ps ile ölçün ve mevcut RAM'in ne kadar worker'a izin verdiğini hesaplayın. Sınırın altındaysanız değeri kademeli yükseltin. Zaten sınırdaysanız çözüm worker eklemek değil; önbellek isabet oranını yükseltmek ve yavaş uç noktaları düzeltmektir.
Statik dosyalar ve görseller de worker harcar mı?#
Hayır. CSS, JavaScript, görsel ve font dosyaları doğrudan web sunucusu tarafından servis edilir, PHP hiç devreye girmez. Bu yüzden bir sayfada 80 istek olması 80 worker anlamına gelmez. Ancak görselleri PHP üzerinden yeniden boyutlandıran veya indirme bağlantılarını PHP ile koruyan eklentiler kullanıyorsanız o istekler worker harcar; bunları önbelleğe almak gerekir.