Peringatan php-fpm max_children: Cari Penyebabnya di Log Sebelum Menambah Worker

Peringatan php-fpm max_children adalah tanda bahwa semua proses worker PHP sedang menangani permintaan sehingga permintaan baru masuk ke antrean. Di server WordPress dengan konfigurasi Nginx, Apache, dan php-fpm yang peringatan ini sudah menumpuk selama berminggu-minggu, permintaan yang memenuhi worker dipilah lewat log, lalu masalahnya diselesaikan dengan pembatasan laju nginx alih-alih menaikkan nilai pengaturannya.
Dalam pemeriksaan mingguan, peringatan tercatat 27–187 kali per hari, tetapi selama empat hari pada periode yang sama pengunjung menerima 0 error 502·504. Yang memenuhi worker bukan pengunjung, melainkan bot yang berulang kali meminta alamat admin dan pemindai yang meminta jalur yang tidak ada.
1️⃣ php-fpm max_children & seems busy
Jika peringatan menumpuk 66 kali sehari, mudah sekali mengira worker kurang sebanyak 66 kali. Log php-fpm berisi dua jenis peringatan yang berbeda sifatnya, dan sebagian besar adalah peringatan awal yang dicatat sebelum batas tercapai.
[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] memberi tahu bahwa worker yang menganggur tinggal 0 dan proses baru sedang dibuat; jika cara pengelolaan prosesnya dynamic, peringatan ini tercatat bahkan saat permintaan naik sebentar. [server reached pm.max_children] adalah saat batas 26 tercapai dan proses tidak bisa dibuat lagi, dan sejak itu permintaan baru harus menunggu.
Bedanya seperti memanggil satu pelayan tambahan di restoran dengan membiarkan tamu berdiri di luar karena semua kursi sudah penuh.
Saat data satu hari dihitung per jenis, hasilnya seems busy 58 kali dan max_children 6 kali. Rutinitas pemeriksaan menjumlahkan keduanya dan melaporkan 66, padahal batasnya benar-benar tercapai hanya enam kali.
grep '09-Oct-2026' /var/log/php-fpm/error.log | grep 'pool www' | grep -c 'seems busy'58grep '09-Oct-2026' /var/log/php-fpm/error.log | grep 'max_children' | cut -c2-2109-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:44Enam waktu yang dicetak oleh perintah kedua menjadi acuan untuk melacak penyebab, dan langkah berikutnya hanya memakai waktu-waktu ini.
2️⃣ Mengapa Menaikkan max_children Bukan Jawabannya
Menaikkan batas 26 mungkin mengurangi jumlah peringatan, tetapi tidak mengubah permintaan apa yang memenuhi worker.
Perhitungan yang umum adalah membagi memori yang tersedia dengan rata-rata memori satu worker. Pada server yang diukur, 26 worker memakai rata-rata 131MB dan maksimal 214MB, dan jika dihitung dari sisa memori yang tersedia, di atas kertas masih ada ruang untuk membuat worker tambahan.
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.05free -mEmpat nilai pada keluaran pertama adalah jumlah worker, memori rata-rata (MB), memori maksimum (MB), dan total (MB); kolom available pada keluaran free adalah memori yang tersedia.
Jika jumlah worker sudah melebihi jumlah inti CPU, menambah worker tidak menambah permintaan yang diproses bersamaan; yang bertambah hanya waktu untuk satu permintaan. Selama pengunjung menerima 0 error 502·504, menaikkan batas tidak memberi manfaat apa pun dan hanya memberikan lebih banyak proses kepada bot dan pemindai yang selama ini menempati worker.
Sebelum menaikkan batas, yang perlu diperiksa adalah apakah permintaan yang menempati worker pada saat peringatan tercatat berasal dari pengunjung atau bukan; urutan memeriksanya di access.log dijelaskan di bagian berikutnya.
3️⃣ Melacak Penyebab di access.log: Waktu, IP, Jalur, Kode Respons
Pilih satu waktu peringatan, dan jawabannya ada di access.log selama 1–2 menit itu. Urutannya: ambil baris berdasarkan waktu, hitung per IP, lalu periksa jalur dan kode respons dari IP teratas.
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.xgrep '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 404Pada 9 Oktober pukul 18.09, tercatat 286 permintaan dalam satu menit; satu IP menyumbang 115 di antaranya, jalurnya adalah alamat admin seperti /wp-admin/profile.php, dan semua kode responsnya 302.
Kode respons menunjukkan apakah permintaan sampai ke PHP. Kode 200 untuk HTML ter-cache yang langsung dijawab nginx, serta 444·400, tidak melewati PHP, sedangkan 302·404 dan 200 yang tidak ter-cache masing-masing memakai satu worker. Jika alamat admin diminta tanpa login, WordPress menjawab dengan 302 ke halaman login, dan satu 302 itu berarti satu kali eksekusi PHP.
Jika satu server menampung dua situs atau lebih, baris dari kedua situs tercatat bersama di access.log global. Awalnya bot ini tampak menyerang situs pertama, tetapi setelah dicocokkan dengan log per situs, 22.390 dari 22.391 permintaan ternyata ditujukan ke situs kedua.
4️⃣ Tiga Jenis Permintaan yang Memenuhi Worker: wp-admin dari Bot, 404 dari Pemindai, Preload Cache
Saat urutan yang sama diterapkan pada semua waktu peringatan tercatat, permintaan yang memenuhi worker ternyata ada tiga jenis.
Yang pertama adalah bot yang berulang kali meminta alamat admin. Satu IP mengirim 22.391 permintaan dalam tiga jam; 9.944 di antaranya ke empat jalur termasuk /wp-admin/profile.php, dan karena satu 302 tanpa login berarti satu eksekusi PHP, worker terpakai 9.944 kali.
Yang kedua adalah pemindai kerentanan yang meminta jalur yang tidak ada. Meski User-Agent-nya bertuliskan Googlebot, itu bukan Googlebot: IP yang mengirim 14.672 permintaan sehari adalah server virtual Google Cloud yang reverse DNS-nya berakhir dengan googleusercontent.com, sedangkan Googlebot berakhir dengan googlebot.com. IP yang sama bergantian memakai bingbot, Applebot, GPTBot, dan ClaudeBot.
Permintaan file seperti .env diblokir nginx dengan 444 dalam 0,04 detik, tetapi jalur biasa yang tidak ada di aturan blokir, seperti /userfiles atau /secrets.yml, membuat WordPress membuat halaman 404. Halaman 404 ini berukuran 266KB dan butuh 1,4–2,9 detik, biayanya sama dengan membuat pos biasa, dan satu IP memintanya 4.069 kali sehari.
Yang ketiga adalah server itu sendiri. Saat pos atau terjemahan disimpan, cache dikosongkan dan preload WP Rocket meminta ulang semua URL, sebanyak 8.489 permintaan sehari dan maksimal 60 per menit. Pemeriksaan status indeks Rank Math juga memakai satu worker 754 kali sehari melalui Action Scheduler. Keduanya hanya terpusat pada jam kerja dan tidak menimbulkan error bagi pengunjung, jadi dikecualikan dari penanganan.
Pada simulator di bawah, Anda dapat melihat di lapisan mana setiap permintaan berakhir dan apakah permintaan itu memakai worker PHP.
| Permintaan | Berhenti di | Respons | Worker |
|---|---|---|---|
| wp-admin dari bot | WordPress | 302 (ke halaman login) | Memakai 1 |
| Pemindai jenis .env | Aturan blokir nginx | 444 (0,04 detik) | Tidak dipakai |
| Pemindai jalur palsu biasa | WordPress | Halaman 404 (266KB · 1,4–2,9 detik) | Memakai 1 |
| Preload cache | WordPress | 200 · disimpan sebagai file cache | Memakai 1 |
| Kunjungan pos yang di-cache | File cache | 200 (nginx langsung merespons) | Tidak dipakai |
| Kunjungan pos tanpa cache | WordPress | 200 · disimpan sebagai file cache | Memakai 1 |
5️⃣ Pembatasan Laju nginx: Membatasi Permintaan Tanpa Login dan Memulihkan IP Asli
Yang dipilih adalah pembatasan laju, bukan pemblokiran. Jika jalur diblokir, pemindai akan berganti jalur; jika IP diblokir, besoknya IP lain yang datang. Hanya permintaan tanpa login yang sampai ke PHP yang dibatasi, yaitu 30 per menit dan 60 sekaligus per IP, dan kelebihannya dijawab dengan 429.
Untuk server di belakang CDN, pengaturan ini saja tidak cukup. IP yang dilihat nginx adalah alamat edge CDN, sehingga semua pengunjung yang lewat edge itu digabung menjadi satu IP; daftar IP edge harus didaftarkan dengan set_real_ip_from untuk memulihkan IP asli dari X-Forwarded-For terlebih dahulu. Permintaan yang membawa cookie login dikecualikan, tetapi tidak ada pengecualian berdasarkan User-Agent.
# konteks http
real_ip_header X-Forwarded-For;
real_ip_recursive on;
set_real_ip_from 203.0.113.0/24; # daftar edge CDN
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;
# location yang meneruskan ke PHP
location @apache {
limit_req zone=php_anon burst=60 nodelay;
limit_req_status 429;
proxy_pass http://127.0.0.1:8080;
}Halaman ter-cache dijawab oleh try_files di dalam nginx sehingga tidak sampai ke location ini, dan admin-ajax.php berada di location terpisah sehingga tidak termasuk dalam batas.
Pengujian dilakukan dengan permintaan serentak. Permintaan berurutan tidak akan melewati 30 per menit karena satu 404 butuh 1,5 detik, sehingga tidak terkena batas; jika 100 permintaan dikirim 20 sekaligus, hasilnya 67 kali 404 dan 33 kali 429, yang menunjukkan batasnya bekerja.
seq 1 100 | xargs -P 20 -I{} curl -s -o /dev/null -w '%{http_code}\n' https://example.com/zz-{} | sort | uniq -cJika keluaran mencatat 429, batasnya bekerja. Jika IP server sendiri dikecualikan, cabut pengecualian itu sebentar saat menjalankannya atau jalankan dari jaringan lain.
6️⃣ Perbandingan Sebelum dan Sesudah
Batas untuk alamat admin tanpa login diterapkan pada malam 9 Oktober, dan batas untuk permintaan yang sampai ke PHP pada malam tanggal 11. Respons 302 alamat admin turun dari 9.996 pada tanggal 9 menjadi 11 pada tanggal 10 dan 1 pada tanggal 11, sedangkan IP yang mengirim 22.391 permintaan dalam tiga jam tidak mengirim satu permintaan pun sejak hari berikutnya.
Untuk pemindai, batasnya baru saja diterapkan sehingga belum ada angka satu hari penuh; penilaiannya akan bergantung pada seberapa jauh jumlah halaman 404 yang dibuat WordPress (2.563 pada tanggal 9, 2.612 pada tanggal 10, 1.630 pada tanggal 11) turun pada pemeriksaan minggu depan. Error 502·504 bagi pengunjung tetap 0, baik sebelum maupun sesudah penerapan.
Angka-angka ini dihitung langsung dari log server WordPress yang berjalan dengan Nginx, Apache, dan php-fpm, dan penilaiannya didasarkan bukan pada jumlah peringatan, melainkan pada error pengunjung dan jumlah permintaan yang sampai ke PHP.
🔢 FAQ & Konten yang Direkomendasikan
Cache
Cache Website & Cache Internal Server
Menjelaskan lapis demi lapis bagaimana permintaan yang ter-cache tidak melewati PHP.
Keamanan
Celah keamanan wp-config.php
Cara melindungi file konfigurasi yang diincar pemindai dengan izin file dan aturan server.
Linux
Perintah Linux: 15 Kategori
Tabel yang membagi perintah ke dalam 15 kategori, termasuk grep dan awk yang dipakai untuk menghitung log.
ℹ️ Pemberitahuan Afiliasi
Konten di situs ini berisi tautan afiliasi. Jika pengunjung membeli produk atau layanan melalui tautan tersebut, situs ini menerima komisi dari penjual. Harga yang dibayar pembeli(turun saat ada diskon promo ↓), tidak naik karena hal ini. Harga, diskon, dan informasi stok yang ditampilkan berlaku pada saat penulisan dan bisa berbeda dengan kondisi sebenarnya, jadi pastikan kembali di situs penjual sebelum membeli. Pemilihan dan penilaian produk dibuat berdasarkan standar kami sendiri, dan ada tidaknya komisi tidak memengaruhi urutan maupun isi penilaian.