L
PHP • Literally Web ID

Scaling PHP-FPM dan Nginx untuk Menangani 10.000 Concurrent Requests per Detik

⏱️ 15 menit baca • 📅 19 Oct 2026 • 👁️ 2 views
Scaling PHP-FPM dan Nginx untuk Menangani 10.000 Concurrent Requests per Detik

1. Konteks Industri & Analisis Akar Masalah

Dalam lanskap arsitektur web modern, menangani 10.000 concurrent requests per detik (RPS) pada aplikasi berbasis PHP bukanlah hal yang mustahil, namun ini adalah ujian terberat bagi infrastruktur server. Sebagian besar kegagalan performa web di level production bukanlah karena bahasa pemrograman PHP itu sendiri, melainkan akibat konfigurasi rantai eksekusi yang buruk: bottleneck pada proses komunikasi antara Nginx (Web Server), PHP-FPM (Process Manager), OPcache (Bytecode Cache), dan database backing services (MySQL/Redis).

Secara historis, PHP sering diidentikkan dengan performa lambat karena model eksekusi CGI/mod_php tradisional yang memuat ulang seluruh interpreter dan ekstensi untuk setiap HTTP request yang masuk. Munculnya PHP-FPM (FastCGI Process Manager) mengubah paradigma ini dengan memperkenalkan model manajemen proses mandiri. Namun, tanpa penyesuaian parameter yang presisi—seperti perhitungan memori per worker, pemilihan process manager (dynamic, static, atau ondemand), serta tuning buffer Nginx—server dengan spesifikasi RAM 32GB dan 8 vCPU sekalipun dapat mengalami out of memory (OOM Killer) atau connection timeout hanya dalam hitungan detik saat dihantam lonjakan traffic.

Kondisi Sebelum vs Sesudah Penerapan

  • Sebelum (Default Out-of-the-Box Setup):

    • Konfigurasi PHP-FPM menggunakan mode dynamic bawaan distribusi Linux dengan batas pm.max_children = 50.
    • Nginx menggunakan parameter worker_connections rendah tanpa penyetelan keepalive yang optimal.
    • OPcache belum diaktifkan secara maksimal, menyebabkan skrip PHP harus diparsing dan dikompilasi ulang ke bytecode pada setiap request.
    • Dampak: Server langsung tumbang (502 Bad Gateway) saat mencapai beban 800-1.200 RPS. Penggunaan CPU melonjak drastis, latensi rata-rata (TTFB) melonjak hingga > 3.000ms.
  • Sesudah (Enterprise Tuning & High-Concurrency Architecture):

    • Implementasi mode static atau dynamic yang dikalkulasi secara matematis berdasarkan ketersediaan RAM riil.
    • Penyetelan Nginx FastCGI Buffering, Keepalive connections, dan epoll event model.
    • OPcache disetel dengan memory consumption besar, validate_timestamps=0 untuk production, dan interned strings buffer optimal.
    • Dampak: Server stabil menahan beban 10.000+ RPS dengan konsumsi CPU yang efisien. Latensi rata-rata (TTFB) terjaga di bawah 45ms, dan tingkat error rate mendekati 0%.

2. Konsep Inti & Deep Dive Arsitektur

Untuk memahami bagaimana menangani 10.000 RPS, kita harus membedah perjalanan sebuah HTTP request dari klien hingga kembali sebagai response. Arsitektur modern mengandalkan pemisahan tugas yang tegas antara Nginx sebagai reverse proxy dan static file server, dengan PHP-FPM sebagai application server.

[ Client / Browser ]
        │ (HTTPS / HTTP/2)
        ▼
[ Nginx Reverse Proxy ] ──(Epoll Event Model)──> Static Files (/var/www/html)
        │
        ├── (FastCGI Protocol over Unix Socket / TCP)
        ▼
[ PHP-FPM Master Process ]
        │
        ├── [ Worker 1 ] ──> OPcache (Bytecode Memory)
        ├── [ Worker 2 ] ──> Application Code (Symfony/Laravel)
        └── [ Worker N ] ──> External Services (MySQL / Redis)

Alur Eksekusi di Balik Layar:

  1. Koneksi Klien Masuk: Nginx menerima koneksi menggunakan event-driven architecture (epoll pada Linux), yang memungkinkannya menangani puluhan ribu koneksi jaringan secara bersamaan dengan thread yang sangat sedikit.
  2. Evaluasi Aturan Nginx: Nginx memeriksa apakah request ditujukan untuk aset statis (CSS, JS, Gambar) yang langsung disajikan dari disk/cache RAM, atau memerlukan eksekusi logika backend.
  3. Forwarding ke PHP-FPM: Jika request adalah file .php, Nginx meneruskan parameter lingkungan (request URI, query string, headers) ke PHP-FPM melalui Unix Domain Socket (lebih cepat daripada TCP loopback) menggunakan protokol FastCGI.
  4. Manajemen Proses PHP-FPM: Master process PHP-FPM mengalokasikan request ke salah satu worker process yang sedang idle. Jika semua worker sibuk, request masuk ke queue internal Nginx (backlog).
  5. Eksekusi Bytecode: Worker PHP-FPM memuat bytecode langsung dari memori OPcache (tanpa membaca file .php dari disk) dan mengeksekusi logika aplikasi.
  6. Pengembalian Data: Hasil eksekusi dikembalikan melalui FastCGI socket ke Nginx, yang kemudian mengirimkannya kembali ke klien.

3. Perbandingan Komparatif / Analisis Pendekatan

Pemilihan mode process manager pada PHP-FPM adalah keputusan arsitektural paling krusial. Berikut perbandingan mendalam antara tiga mode yang tersedia:

Parameter / Fitur Static Process Manager Dynamic Process Manager On-Demand Process Manager
Alokasi Memori Konstan dan dipesan di awal (pm.max_children). Fleksibel, tumbuh dan susut berdasarkan beban. Minimal di awal, bertambah saat ada request masuk.
Penggunaan CPU Sangat rendah (tidak ada overhead pembuatan proses). Sedang (ada overhead fork/kill proses secara berkala). Tinggi saat lonjakan tiba-tiba karena proses harus dibuat on-the-fly.
Latensi (TTFB) Sangat konsisten dan rendah. Variatif tergantung kondisi antrean proses. Tinggi pada request pertama (cold start process creation).
Risiko Utama Out of Memory (OOM) jika kalkulasi RAM meleset. Fluktuasi performa saat trafik naik turun secara ekstrem. Lambat merespons lonjakan trafik masif (thundering herd).
Rekomendasi Penggunaan High-Traffic Production Server dengan trafik stabil/tinggi. Server dengan trafik menengah dan fluktuatif. Server pengembangan (Dev), staging, atau server dengan resource sangat terbatas.

[!IMPORTANT] Untuk target 10.000 RPS, mode static adalah standar emas enterprise. Dengan mode static, kita menghilangkan overhead CPU untuk melakukan forking dan killing proses PHP-FPM di tengah beban puncak, memastikan setiap worker selalu siap siaga di dalam memori.


4. Prasyarat Sistem & Persiapan Lingkungan

Sebelum menyentuh file konfigurasi Nginx dan PHP, sistem operasi Linux (Ubuntu 22.04 LTS / Debian 12 direkomendasikan) harus disetel agar mampu melewati batasan default kernel (seperti jumlah file descriptor terbuka).

1. Penyetelan Batasan Kernel (/etc/security/limits.conf)

Tambahkan baris berikut untuk mengizinkan proses membuka file dalam jumlah besar:

www-data   soft   nofile   65535
www-data   hard   nofile   65535
root       soft   nofile   65535
root       hard   nofile   65535

2. Penyetelan Parameter Jaringan Kernel (/etc/sysctl.conf)

Terapkan optimasi TCP stack untuk menangani koneksi konkuren tinggi:

fs.file-max = 2097152
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.core.netdev_max_backlog = 65535
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15

Muat ulang konfigurasi sysctl dengan perintah:

sysctl -p

5. Panduan Implementasi Langkah demi Langkah

Berikut adalah implementasi file konfigurasi penuh yang dirancang untuk performa maksimal pada server produksi kelas atas (asumsi spesifikasi server: 16 vCPU, 64 GB RAM).

Langkah 1: Konfigurasi Pool PHP-FPM (/etc/php/8.3/fpm/pool.d/www.conf)

Sesuaikan file pool PHP-FPM Anda secara presisi:

[www]
user = www-data
group = www-data

listen = /run/php/php8.3-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

; Menggunakan mode static untuk 10k RPS
pm = static
pm.max_children = 800

; Batasi jumlah request per worker untuk mencegah memory leak
pm.max_requests = 10000

; Status monitoring
pm.status_path = /status
ping.path = /ping

; Limitasi resource per worker
rlimit_files = 65535
rlimit_core = 0

catch_workers_output = yes
decorate_workers_output = no

Langkah 2: Konfigurasi OPcache (/etc/php/8.3/fpm/conf.d/10-opcache.ini)

Optimalkan bytecode cache agar skrip PHP dieksekusi secara instan:

[opcache]
zend_extension = opcache.so
opcache.enable = 1
opcache.enable_cli = 1
opcache.memory_consumption = 512
opcache.interned_strings_buffer = 64
opcache.max_accelerated_files = 32531
opcache.validate_timestamps = 0
opcache.revalidate_freq = 0
opcache.save_comments = 1
opcache.enable_file_override = 1
opcache.fast_shutdown = 1

Langkah 3: Konfigurasi Nginx Global & Server Block (/etc/nginx/nginx.conf)

Optimalkan worker Nginx dan parameter event loop:

user www-data;
worker_processes auto;
worker_rlimit_nofile 65535;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
    worker_connections 16384;
    use epoll;
    multi_accept on;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log /var/log/nginx/access.log main;
    error_log /var/log/nginx/error.log warn;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    keepalive_requests 1000;
    types_hash_max_size 2048;
    server_tokens off;

    # Gzip Compression
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

Langkah 4: Konfigurasi Virtual Host Nginx (/etc/nginx/sites-available/default)

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name example.com www.example.com;
    root /var/www/html/public;

    index index.php index.html index.htm;

    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        
        # Optimisasi Buffer FastCGI untuk mencegah bottleneck I/O
        fastcgi_buffer_size 128k;
        fastcgi_buffers 256 16k;
        fastcgi_busy_buffers_size 256k;
        fastcgi_temp_file_write_size 256k;
        
        fastcgi_read_timeout 60;
        fastcgi_connect_timeout 60;
        fastcgi_send_timeout 60;
        
        include fastcgi_params;
    }

    location ~* \.(jpg|jpeg|gif|png|css|js|ico|webp|svg|woff|woff2)$ {
        expires max;
        add_header Cache-Control "public, no-transform";
        access_log off;
    }

    location ~ /\.ht {
        deny all;
    }
}

6. Bedah Kode & Penjelasan Detail Baris Kunci

  • pm = static dan pm.max_children = 800 (PHP-FPM): Angka 800 didapatkan dari estimasi konsumsi RAM rata-rata per worker PHP-FPM sebesar 60MB. Jika server memiliki 64GB RAM, mengalokasikan 48GB untuk PHP-FPM memberikan ruang aman bagi sistem operasi dan database (MySQL/Redis): 48.000 MB / 60 MB ≈ 800 worker. Ini memastikan tidak ada siklus pembuatan proses baru saat trafik melonjak.

  • pm.max_requests = 10000 (PHP-FPM): Aplikasi PHP enterprise sering kali memiliki micro-memory leaks yang tidak terlihat. Parameter ini memaksa worker PHP-FPM untuk mendaur ulang dirinya sendiri setelah melayani 10.000 request, mencegah akumulasi memori bengkak tanpa menghentikan layanan secara keseluruhan.

  • opcache.validate_timestamps = 0 (OPcache): Dalam mode produksi, menonaktifkan validasi timestamp berarti PHP tidak akan pernah melakukan stat() ke disk untuk memeriksa apakah file .php telah berubah. Seluruh eksekusi membaca langsung dari memori. Konsekuensinya: setiap kali Anda melakukan deploy kode baru, Anda wajib melakukan flush OPcache secara manual (systemctl reload php8.3-fpm).

  • worker_connections 16384 & use epoll (Nginx): Model event I/O epoll di kernel Linux memungkinkan Nginx memantau puluhan ribu deskriptor file secara asinkron tanpa membebani CPU. Kombinasi worker_processes auto memastikan setiap inti CPU (vCPU) mengelola satu worker process Nginx yang independen.


7. Skenario Produksi & Studi Kasus Dunia Nyata

Sebagai studi kasus nyata, mari kita bedah arsitektur platform e-commerce skala menengah-atas yang mengalami lonjakan traffic kilat (flash sale) hingga mencapai 12.000 RPS.

Tantangan:

  • Lonjakan pengunjung terjadi dalam rentang waktu 5 menit.
  • Database MySQL langsung mengalami connection pool exhaustion karena setiap request PHP membuka koneksi baru.

Solusi Arsitektural Terpadu:

  1. Persistent Connections & Redis Caching: Mengubah konfigurasi koneksi database dari non-persistent menjadi connection pooling, serta memindahkan data sesi pengguna dan katalog produk panas ke dalam Redis cluster.
  2. Nginx Micro-Caching: Untuk halaman produk statis yang sering diakses, Nginx dikonfigurasi menggunakan proxy_cache atau fastcgi_cache selama 1 detik, mereduksi beban eksekusi PHP hingga 70%.
  3. Isolasi Proses: PHP-FPM dipisahkan ke dalam instance dedicated server mandiri, sementara Nginx berjalan di edge server terpisah.

8. Common Pitfalls, Anti-Patterns & Solusi

  1. Kesalahan Fatal Kalkulasi pm.max_children:

    • Anti-Pattern: Menyetel pm.max_children = 5000 pada server dengan RAM 8GB karena ingin menangani banyak request.
    • Dampak: Server langsung mengalami OOM Killer, kernel Linux mematikan proses PHP-FPM secara acak, menghasilkan 502 Bad Gateway massal.
    • Solusi: Selalu hitung ketersediaan RAM riil dikurangi alokasi untuk OS dan database, lalu bagi dengan rata-rata konsumsi memori per proses PHP.
  2. Lupa Menaikkan nofile (File Descriptors):

    • Anti-Pattern: Membiarkan batas file descriptor default sistem operasi (1024).
    • Dampak: Nginx gagal membuka koneksi jaringan baru meskipun spesifikasi CPU dan RAM masih longgar, memunculkan error Too many open files di log error.
  3. Mengaktifkan opcache.validate_timestamps = 1 di Production:

    • Anti-Pattern: Menggunakan pengaturan default development untuk production.
    • Dampak: Penurunan performa hingga 30% karena I/O disk terus-menerus melakukan pengecekan timestamp file.

9. Benchmark, Metrik Kinerja & Tuning Performa

Untuk memvalidasi apakah server Anda benar-benar mampu menangani 10.000 RPS, gunakan tool pengujian beban modern seperti wrk atau k6.

Menjalankan Benchmark dengan wrk:

wrk -t12 -c1000 -d30s --latency http://example.com/index.php
  • -t12: Menggunakan 12 thread sistem operasi.
  • -c1000: Mempertahankan 1.000 koneksi HTTP konkuren secara konstan.
  • -d30s: Durasi pengujian selama 30 detik.

Interpretasi Hasil Benchmark yang Ideal:

  • Requests/sec (Throughput): Harus stabil di atas target (misal: 10.000+ RPS).
  • Latency Distribution:
    • P50 (Median): < 15ms
    • P99 (99th Percentile): < 50ms
  • Non-2xx or 3xx responses: Harus bernilai 0 (tidak boleh ada error HTTP 502, 503, atau 504).

10. Checklist Penerapan Produksi & Kesimpulan

Sebelum meluncurkan konfigurasi ini ke lingkungan live production, pastikan Anda telah memverifikasi daftar periksa berikut:

  • Batasan sistem operasi (nofile, somaxconn) telah disetel pada /etc/security/limits.conf dan /etc/sysctl.conf.
  • Mode PHP-FPM menggunakan static dengan perhitungan pm.max_children yang proporsional terhadap kapasitas RAM.
  • OPcache telah aktif dengan opcache.validate_timestamps = 0 dan ukuran memori minimal 512MB.
  • Nginx dikonfigurasi dengan event model epoll dan parameter buffer FastCGI yang memadai.
  • Uji beban (stress testing) menggunakan wrk atau k6 telah dijalankan tanpa menghasilkan error 502 Bad Gateway atau OOM.

Dengan menerapkan arsitektur terpadu dan penyetelan parameter tingkat lanjut ini, infrastruktur PHP Anda kini siap beroperasi pada level enterprise, menangani ribuan hingga belasan ribu request konkuren per detik secara stabil, aman, dan berkinerja tinggi.

🏷️ Tags: #Nginx #High Concurrency #Performance #Sysadmin #Web Server