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

Pemberitahuan afiliasi Ver 3.1
Pemberitahuan afiliasi Ver 3.2 (khusus seluler)
Lingkungan uji Keluarga RHELAlmaLinux 9.8akun rootDiperiksa 2026-10-12

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'
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

Enam 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.05
free -m

Empat 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.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

Pada 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.

🧭 Simulator Jalur PermintaanHalaman Admin wp-adminSimulator penjelasan
🗂️ Permintaan yang Memenuhi Worker
Permintaan wp-admin dari bot
Jika alamat admin diminta tanpa login, WordPress menjawab dengan 302 ke halaman login. Satu 302 itu berarti satu kali eksekusi PHP.
Pemindai: jenis .env
Permintaan file seperti .env diputus aturan blokir nginx dengan 444. 0,04 detik, tanpa melewati PHP.
Pemindai: jalur palsu biasa
Untuk jalur biasa yang tidak ada di aturan blokir, seperti /userfiles atau /secrets.yml, WordPress membuat halaman 404. 266KB, 1,4–2,9 detik, biayanya sama dengan membuat pos biasa.
Preload cache
Saat pos atau terjemahan disimpan, cache dikosongkan dan preload WP Rocket meminta ulang semua URL. Maksimal 60 per menit, dan setiap permintaan memakai satu worker.
Kunjungan pos yang di-cache
Jika file cache ada, nginx langsung merespons tanpa melewati PHP.
Kunjungan pos tanpa cache
Jika file cache tidak ada, PHP membuat halaman lalu menyimpan HTML-nya sebagai file cache.
Alur lengkap
Permintaan turun dari atas ke bawah dan berhenti di lapisan tempat respons selesai. Hanya permintaan yang turun sampai ke WordPress yang memakai worker PHP.
PermintaanBerhenti diResponsWorker
wp-admin dari botWordPress302 (ke halaman login)Memakai 1
Pemindai jenis .envAturan blokir nginx444 (0,04 detik)Tidak dipakai
Pemindai jalur palsu biasaWordPressHalaman 404 (266KB · 1,4–2,9 detik)Memakai 1
Preload cacheWordPress200 · disimpan sebagai file cacheMemakai 1
Kunjungan pos yang di-cacheFile cache200 (nginx langsung merespons)Tidak dipakai
Kunjungan pos tanpa cacheWordPress200 · disimpan sebagai file cacheMemakai 1
Simulator penjelasan yang hanya berjalan di browser. Respons dan waktunya diambil dari log dan pengukuran server dengan konfigurasi Nginx + Apache pada Oktober 2026.

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 -c

Jika 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.

📊Sebelum dan Sesudah Pembatasan LajuPer hari · hitungan log
SebelumSesudah
Respons 302 alamat admin
302 yang dikirim WordPress untuk permintaan wp-admin tanpa login. Batas alamat admin tanpa login diterapkan pada malam 9 Oktober.
02,4994,9987,4979,996
10/99,996Sebelum
10/1011Sesudah
10/111Sesudah
Jumlah permintaan IP bot
Jumlah permintaan harian dari satu IP yang mengirim 22.391 permintaan dalam tiga jam.
05,59811,19616,79322,391
10/922,391Sebelum
10/100Tidak ada permintaan
10/110Tidak ada permintaan
Halaman 404 yang dibuat WordPress
Permintaan pemindai ke jalur palsu biasa. Batas permintaan yang sampai ke PHP diterapkan pada malam 11 Oktober, jadi dinilai dari angka pemeriksaan minggu depan.
06531,3061,9592,612
10/92,563Sebelum
10/102,612Sebelum
10/111,630Sebelum · diterapkan malam tgl. 11
Angka adalah hitungan harian dari nginx access.log tanggal 9 hingga 11 Oktober 2026.

🔢 FAQ & Konten yang Direkomendasikan

dynamic membuat dan menghentikan worker sesuai volume permintaan, dan mencatat peringatan seems busy saat worker yang menganggur tinggal 0. static selalu mempertahankan worker sebanyak max_children, sehingga tidak ada jeda pembuatan dan peringatan, tetapi memorinya selalu terpakai. Server dalam artikel ini tetap memakai dynamic 26; jika memori masih longgar dan volume permintaan stabil sepanjang hari, static lebih tepat.

Nyalakan saat ada permintaan tertentu yang tampak berjalan lama pada waktu peringatan. Jika jalur [slowlog] dan [request_slowlog_timeout] ditentukan di pengaturan pool, posisi eksekusi permintaan yang melewati waktu itu akan dicatat. Dalam kasus artikel ini penyebabnya adalah jumlah permintaan, jadi cukup ditentukan dari hitungan access.log, dan slowlog tidak dipakai.

Batas hanya berlaku untuk permintaan tanpa login yang tidak melewati cache dan sampai ke PHP, dan hanya kelebihannya yang mendapat 429 saat satu IP melampaui 30 per menit atau 60 sekaligus. Pada hitungan harian 11 Oktober, satu-satunya IP yang melampaui batas itu adalah sebuah pemindai, dan status kelebihan hilang dalam 1 menit sehingga permintaan berikutnya kembali dijawab normal.

Tidak dikurangi. Preload hanya terpusat pada jam kerja saat pos dan terjemahan disimpan, dan tidak menimbulkan error bagi pengunjung. Tolok ukurnya bukan jumlah peringatan, melainkan ada tidaknya error 502·504 yang diterima pengunjung; jika angkanya 0, preload dibiarkan apa adanya.

ℹ️ 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.

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *

Buktikan bahwa Anda manusia: 8   +   10   =