php-fpm max_children uyarısı: Worker artırmadan önce nedeni kayıtlardan bulun

Satış ortaklığı bildirimi v3.1
Satış ortaklığı bildirimi v3.2 (yalnızca mobil)
Test ortamı RHEL ailesiAlmaLinux 9.8root hesabı12.10.2026'da kontrol edildi

php-fpm max_children uyarısı, PHP worker süreçlerinin hepsinin istek işlediği ve yeni isteklerin kuyruğa girdiği anlamına gelir. Bu uyarının haftalardır biriktiği Nginx, Apache ve php-fpm yapılandırmalı bir WordPress sunucusunda worker'ları dolduran istekleri kayıtlardan ayıkladım ve ayar değerini yükseltmek yerine nginx hız sınırıyla çözdüm.

Haftalık kontrolde uyarı günde 27–187 kez kaydedildi, ama aynı dört günde ziyaretçilerin aldığı 502 ya da 504 hatası 0'dı. Worker'ları dolduran ziyaretçiler değil, yönetici adreslerini tekrar tekrar isteyen bir bot ve olmayan yolları isteyen bir tarayıcıydı.

1️⃣ php-fpm max_children & seems busy

Uyarı günde 66'ya ulaştığında bunu worker'ların 66 kez yetmediği şeklinde okumak kolaydır. php-fpm kaydında niteliği farklı iki uyarı karışıktır ve çoğu, sınıra ulaşılmadan önce kaydedilen ön uyarılardır.

[09-Oct-2026 00:16:18] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 8 children, there are 0 idle, and 15 total children
[09-Oct-2026 13:02:05] WARNING: [pool www] server reached pm.max_children setting (26), consider raising it

[seems busy], boşta worker kalmadığı ve yeni süreç oluşturulduğu anlamına gelir; süreç yönetimi dynamic ise isteklerdeki kısa bir artışta bile kaydedilir. [server reached pm.max_children] ise 26 sınırına ulaşılıp daha fazla oluşturulamadığı andır; bundan sonra yeni istekler bekler.

Bu, lokantada bir garson daha çağırmakla bütün masalar dolu olduğu için müşterileri dışarıda bekletmek arasındaki farktır.

Bir günü türlerine göre sayınca 58 seems busy ve 6 max_children çıktı. Kontrol rutini ikisini toplayıp 66 olarak bildirdi, ama sınıra gerçekte altı kez ulaşıldı.

grep '09-Oct-2026' /var/log/php-fpm/error.log | grep 'pool www' | grep -c 'seems busy'
58
grep '09-Oct-2026' /var/log/php-fpm/error.log | grep 'max_children' | cut -c2-21
09-Oct-2026 13:02:05
09-Oct-2026 13:52:10
09-Oct-2026 18:09:20
09-Oct-2026 18:42:17
09-Oct-2026 18:46:07
09-Oct-2026 19:12:44

İkinci komutun yazdırdığı altı zaman, nedeni izlemenin dayanağı olur; sonraki adım yalnızca bu zamanları kullanır.

2️⃣ max_children artırmanın çözüm olmamasının nedeni

26 sınırını yükseltmek uyarı sayısını azaltabilir, ama worker'ları hangi isteklerin doldurduğunu değiştirmez.

Genel hesap, kullanılabilir belleği bir worker'ın ortalama belleğine bölmektir. Ölçülen sunucuda 26 worker ortalama 131MB, en fazla 214MB kullandı; kalan kullanılabilir bellekle hesaplanınca kâğıt üzerinde daha fazla worker oluşturmaya yer vardı.

ps -o rss= -u www -C php-fpm | awk '{s+=$1; n++; if($1>m) m=$1} END{print n, s/n/1024, m/1024, s/1024}'
26 130.579 214.27 3395.05
free -m

İlk çıktıdaki dört değer worker sayısı, ortalama bellek (MB), en yüksek bellek (MB) ve toplamdır (MB); free çıktısındaki available sütunu kullanılabilir bellektir.

Worker sayısı CPU çekirdek sayısını geçince worker artırmak aynı anda işlenen istekleri artırmaz, yalnızca her isteğin süresini uzatır. Ziyaretçilerin 502 ya da 504 hatası 0 iken sınırı yükseltmek bir şey kazandırmaz; worker'ları tutan botlara ve tarayıcılara daha fazla süreç verir.

Sınırı yükseltmeden önce uyarı zamanlarında worker'ları tutan isteklerin ziyaretçiden gelip gelmediğini kontrol edin; bunu access.log ile nasıl kontrol edeceğinizi sonraki bölümde derledim.

3️⃣ access.log ile nedeni izleme: Zaman, IP, yol, yanıt kodu

Bir uyarı zamanı seçin; yanıt o 1–2 dakikanın access.log'undadır. Sıra şöyledir: satırları zamana göre ayıklayın, IP'ye göre sayın, sonra en üstteki IP'lerin yollarına ve yanıt kodlarına bakın.

grep '09/Oct/2026:18:09' /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head
    115 140.245.x.x
     61 187.15.x.x
     17 3.36.x.x
      8 91.239.x.x
      4 79.127.x.x
      3 109.248.x.x
      3 109.248.x.x
      3 109.248.x.x
      2 79.127.x.x
      2 40.77.x.x
grep '09/Oct/2026:18:09' /var/log/nginx/access.log | awk '{print $7, $9}' | sort | uniq -c | sort -rn | head
     55 / 200
     13 /wp-login.php 404
     13 /wp-admin/plugins.php 302
     13 /wp-admin/index.php 302
     13 /wp-admin/edit.php 302
     12 /wp-admin/profile.php 302
      4 / 499
      3 /xmlrpc.php 302
      2 /xmlrpc.php 499
      2 /wp-content/themes/kinsta/images/duos/small/wheelchair.svg 404

9 Ekim saat 18.09'da bir dakikada 286 istek kaydedildi; bunların 115'i tek bir IP'dendi, yollar /wp-admin/profile.php gibi yönetici adresleriydi ve yanıt kodlarının hepsi 302'ydi.

Yanıt kodu PHP'ye ulaşılıp ulaşılmadığını gösterir. nginx'in doğrudan verdiği önbellekli HTML için 200 ile 444 ve 400 PHP'ye hiç uğramaz; 302, 404 ve önbelleksiz 200 ise her biri bir worker kullanır. Oturum açmamış biri yönetici adresi isteyince WordPress giriş sayfasına 302 ile yanıt verir ve o tek 302, bir PHP çalıştırmasıdır.

Bir sunucuda birden fazla site varsa genel access.log iki sitenin satırlarını birlikte kaydeder. İlk başta bu botun ilk siteye saldırdığını düşündüm, ama site başına kayıtlarla karşılaştırınca 22.391 isteğin 22.390'ının ikinci siteye ait olduğu görüldü.

4️⃣ Worker'ları dolduran üç tür istek: Botun wp-admin'i, tarayıcının 404'ü, önbellek ön yüklemesi

Aynı sırayı uyarının kaydedildiği her zamana uygulayınca worker'ları dolduran isteklerin üç türde olduğu görüldü.

Birincisi yönetici adreslerini tekrar tekrar isteyen bir bottu. Tek bir IP üç saatte 22.391 istek gönderdi; bunların 9.944'ü /wp-admin/profile.php dahil dört yola gitti ve oturum açmamış her 302 bir PHP çalıştırması olduğu için 9.944 kez worker kullandı.

İkincisi olmayan yolları isteyen bir güvenlik açığı tarayıcısıydı. User-Agent'ta Googlebot yazsa da Googlebot değildir: günde 14.672 istek gönderen IP, ters DNS'i googleusercontent.com ile biten bir Google Cloud sanal sunucusuydu; Googlebot ise googlebot.com ile biter. Aynı IP bingbot, Applebot, GPTBot ve ClaudeBot adlarını sırayla kullandı.

.env gibi dosya isteklerini nginx 0,04 saniyede 444 ile keser, ama /userfiles ya da /secrets.yml gibi engelleme kurallarında olmayan sıradan yollar WordPress'e 404 sayfası oluşturtur. Bu 404 sayfası 266KB ve 1,4–2,9 saniye tutar, yani normal bir yazı oluşturmakla aynı maliyettedir; tek bir IP onu günde 4.069 kez istedi.

Üçüncüsü sunucunun kendisiydi. Bir yazı ya da çeviri kaydedilince önbellek boşalır ve WP Rocket ön yüklemesi tüm adresleri yeniden ister; bu günde 8.489 istek, dakikada en fazla 60 istek ediyordu. Rank Math'in dizin durumu kontrolleri de Action Scheduler üzerinden günde 754 kez bir worker kullandı. İkisi de çalışma saatlerinde yoğunlaştı ve ziyaretçi hatasına yol açmadı; bu yüzden onları düzeltmenin dışında bıraktım.

Aşağıdaki simülatörde her isteğin hangi katmanda bittiğini ve PHP worker kullanıp kullanmadığını görebilirsiniz.

🧭 İstek yolu simülatörüwp-admin yönetici sayfasıAçıklama simülatörü
🗂️ Worker'ları dolduran istekler
Botun wp-admin istekleri
Oturum açmamış biri yönetici adresi isteyince WordPress giriş sayfasına 302 ile yanıt verir. O tek 302 bir PHP çalıştırmasıdır.
Tarayıcı: .env türü dosyalar
.env gibi dosya isteklerini nginx engelleme kuralı 444 ile keser. 0,04 saniye, PHP'ye uğramaz.
Tarayıcı: sıradan sahte yollar
/userfiles ya da /secrets.yml gibi engelleme kurallarında olmayan sıradan yollar WordPress'e 404 sayfası oluşturtur. 266KB ve 1,4–2,9 saniye; normal yazı oluşturmakla aynı maliyet.
Önbellek ön yüklemesi
Bir yazı ya da çeviri kaydedilince önbellek boşalır ve WP Rocket ön yüklemesi tüm adresleri yeniden ister. Dakikada en fazla 60 ve her istek bir worker kullanır.
Önbellekli yazı ziyareti
Önbellek dosyası varsa nginx doğrudan yanıt verir ve PHP'ye uğranmaz.
Önbelleksiz yazı ziyareti
Önbellek dosyası yoksa PHP sayfayı oluşturur ve o HTML'yi önbellek dosyası olarak kaydeder.
Tüm akış
İstek yukarıdan aşağı iner ve yanıtın bittiği katmanda durur. PHP worker kullanan yalnızca WordPress'e kadar inen isteklerdir.
İstekDurduğu katmanYanıtİşçiler
Botun wp-admin'iWordPress302 (giriş sayfasına)1 kullanır
Tarayıcı .env türünginx engelleme kuralı444 (0,04 sn)Kullanılmıyor
Tarayıcı sıradan sahte yolWordPress404 sayfası (266KB · 1,4–2,9 sn)1 kullanır
Önbellek ön yüklemesiWordPress200 · önbellek dosyası olarak kaydedilir1 kullanır
Önbellekli yazı ziyaretiÖnbellek dosyası200 (nginx doğrudan yanıt verir)Kullanılmıyor
Önbelleksiz yazı ziyaretiWordPress200 · önbellek dosyası olarak kaydedilir1 kullanır
Yalnızca tarayıcınızda çalışan açıklayıcı bir simülatördür. Yanıtlar ve süreler Ekim 2026'da Nginx + Apache yapılandırmalı bir sunucunun kayıtlarından ve ölçümlerinden alınmıştır.

5️⃣ nginx hız sınırı: Oturum açmamış istekleri sınırlama ve gerçek IP'yi geri getirme

Engellemek yerine hız sınırını seçtim. Yolu engellerseniz tarayıcı yol değiştirir, IP'yi engellerseniz ertesi gün başka bir IP gelir. Yalnızca PHP'ye ulaşan oturum açmamış istekler IP başına dakikada 30 ve anlık 60 ile sınırlanır, fazlası 429 alır.

CDN arkasındaki bir sunucu için bu ayar tek başına yetmez. nginx'in gördüğü IP CDN uç adresidir; o uçtan geçen tüm ziyaretçiler tek IP'de toplanır. Önce uç IP listesini set_real_ip_from ile kaydedip X-Forwarded-For'daki gerçek IP'yi geri getirmeniz gerekir. Oturum açma çerezi olan istekler muaf tutulur, ama User-Agent'a göre muafiyet yoktur.

# http bağlamı
real_ip_header X-Forwarded-For;
real_ip_recursive on;
set_real_ip_from 203.0.113.0/24;   # CDN uç listesi
map $http_cookie $php_anon_key {
    default                 $binary_remote_addr;
    ~*wordpress_logged_in   '';
}
limit_req_zone $php_anon_key zone=php_anon:10m rate=30r/m;

# PHP'ye gönderen location
location @apache {
    limit_req zone=php_anon burst=60 nodelay;
    limit_req_status 429;
    proxy_pass http://127.0.0.1:8080;
}

Önbellekli sayfalar nginx içinde try_files ile yanıtlandığından bu location'a gelmez; admin-ajax.php ayrı bir location olduğu için sınıra dahil değildir.

Doğrulamayı eşzamanlı isteklerle yapın. Sıralı istekler bir 404 1,5 saniye sürdüğü için dakikada 30'u geçemez ve sınıra takılmaz; 20'şer eşzamanlı göndererek 100 istek yapınca 67 kez 404 ve 33 kez 429 alınır ve sınırın çalıştığı doğrulanır.

seq 1 100 | xargs -P 20 -I{} curl -s -o /dev/null -w '%{http_code}\n' https://example.com/zz-{} | sort | uniq -c

Çıktıda 429 sayılıyorsa sınır çalışıyordur. Sunucunun kendi IP'sini muaf tuttuysanız test sırasında muafiyeti kısa süre kaldırın ya da başka bir ağdan çalıştırın.

6️⃣ Önce ve sonra

Oturum açmamış yönetici adresi sınırı 9 Ekim akşamı, PHP'ye ulaşan istek sınırı ise 11'i akşamı devreye girdi. Yönetici adresi 302'leri 9'unda 9.996'dan 10'unda 11'e, 11'inde 1'e düştü; üç saatte 22.391 istek gönderen IP ertesi günden beri hiç istek göndermedi.

Tarayıcı tarafında sınır yeni uygulandığı için henüz tam günlük rakam yok; karar, WordPress'in oluşturduğu 404 sayfası sayısının (9'unda 2.563, 10'unda 2.612, 11'inde 1.630) gelecek haftaki kontrolde ne kadar düştüğüne göre verilecek. Ziyaretçilerin 502 ve 504 hataları öncesinde de sonrasında da 0'dı.

Bu rakamlar Nginx, Apache ve php-fpm ile çalışan bir WordPress sunucusunun kayıtlarından doğrudan sayıldı; karar uyarı sayısına değil, ziyaretçi hatalarına ve PHP'ye ulaşan istek sayısına dayandı.

📊Hız sınırı öncesi ve sonrasıGünlük · kayıt sayımı
ÖnceSonra
Yönetici adresi 302 yanıtları
WordPress'in oturum açmamış wp-admin isteklerine gönderdiği 302'ler. Oturum açmamış yönetici adresi sınırı 9 Ekim akşamı devreye girdi.
02,4994,9987,4979,996
10/99,996Önce
10/1011Sonra
10/111Sonra
Bot IP'sinden gelen istekler
Üç saatte 22.391 istek gönderen tek IP'nin günlük istek sayısı.
05,59811,19616,79322,391
10/922,391Önce
10/100İstek yok
10/110İstek yok
WordPress'in oluşturduğu 404 sayfaları
Tarayıcının sıradan sahte yol istekleri. PHP'ye ulaşan istek sınırı 11 Ekim akşamı devreye girdiği için gelecek haftaki kontrole göre değerlendirilecek.
06531,3061,9592,612
10/92,563Önce
10/102,612Önce
10/111,630Önce · 11'i akşamı uygulandı
Rakamlar 9–11 Ekim 2026 arasındaki nginx access.log'un günlük sayımlarıdır.

🔢 SSS & önerilen içerikler

dynamic istek miktarına göre worker oluşturup kapatır ve boşta worker kalmadığında seems busy uyarısını kaydeder. static her zaman max_children sayısını korur; oluşturma gecikmesi ve uyarı olmaz, ama bellek sürekli dolu kalır. Bu yazıdaki sunucu 26 ile dynamic'te kaldı; bellek payınız varsa ve istek miktarı gün boyu sabitse static uygundur.

Uyarı zamanlarında belirli isteklerin uzun sürdüğü görülüyorsa açın. Havuz ayarında [slowlog] yolunu ve [request_slowlog_timeout] değerini belirlerseniz bu süreyi aşan isteklerin çalışma noktası kaydedilir. Bu yazıdaki örnekte neden istek sayısıydı; access.log sayımı yeterli oldu ve slowlog kullanılmadı.

Sınır yalnızca önbelleği atlayıp PHP'ye ulaşan oturum açmamış isteklere uygulanır; bir IP dakikada 30'u ya da anlık 60'ı aştığında yalnızca fazlası 429 alır. 11 Ekim'in günlük sayımında bu çizgiyi aşan tek IP bir tarayıcıydı ve aşım durumu bir dakika içinde kalkar, böylece sonraki istek normal yanıt alır.

Azaltmadım. Ön yükleme yalnızca yazı ve çevirilerin kaydedildiği çalışma saatlerinde yoğunlaştı ve ziyaretçi hatasına yol açmadı. Ölçüt uyarı sayısı değil, ziyaretçilerin 502 ya da 504 hatası alıp almadığıdır; bu sayı 0 ise ön yükleme olduğu gibi kalır.

ℹ️ Satış ortaklığı bildirimi
Bu sitenin içeriklerinde satış ortaklığı bağlantıları bulunur. Bir ziyaretçi bu bağlantılar üzerinden ürün veya hizmet satın alırsa bu site satıcıdan komisyon alır. Bu süreçte alıcının ödediği tutar (kampanya indirimlerinde tutar düşer↓) artmaz. Yayımlanan fiyat, indirim ve stok bilgileri yazının yazıldığı zamana aittir ve gerçek durumdan farklı olabilir; bu yüzden satın almadan önce son bilgiyi satıcıdan kontrol etmenizi rica ederiz. Ürünler kendi ölçütlerimize göre seçilir ve değerlendirilir; komisyon alınıp alınmaması tanıtım sırasını veya değerlendirme içeriğini etkilemez.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

İnsan olduğunuzu kanıtlayın: 0   +   2   =