• Indonesian
  • English
  • Cara Mengatasi Apache Slot Penuh (503 Service Unavailable)

    Kecepatan:

    Pendahuluan

    Minggu lalu jam 2 pagi, HP saya bunyi — notifikasi dari monitoring: “HTTP 503 pada website utama client X”. Yang bikin geregetan, client ini baru saja migrasi dari shared hosting ke VPS dedicated, dan mereka punya 12 website aktif di satu server. Begitu saya SSH masuk, saya langsung tahu masalahnya: Apache slot-nya penuh. Semua worker sudah terpakai, request baru ditolak mentah-mentah.

    Pertama kali saya encounter masalah seperti ini, saya sempat bingung karena error 503 itu bisa jadi banyak hal — database down, PHP-FPM crash, bahkan Nginx misconfigured. Tapi begitu saya cek server-status, barulah kelihatan jelas: 256 slot Apache sudah terisi semua, dan yang bikin parah, beberapa slot sudah menunggu lebih dari 60 detik tanpa ada progress sama sekali. Itu artinya ada request yang stuck dan memblokir slot untuk request lain.

    Dari pengalaman itu, saya belajar cara membaca Apache server-status dengan benar, mengidentifikasi permintaan mana yang stuck, dan yang paling penting — menemukan website mana yang paling banyak makan slot. Semua itu pakai command-command yang sederhana tapi powerful. Di artikel ini saya akan tunjukkan cara-cara tersebut secara lengkap.

    Gejala Apache Slot Penuh

    Sebelum masuk ke troubleshooting, penting untuk tahu gejala-gejala yang menandakan Apache kehabisan slot:

    • Error 503 Service Unavailable — ini gejala paling klasik. Website tiba-tiba tidak bisa diakses dan server mengembalikan error 503.
    • Website loading sangat lambat — request bisa masuk tapi harus antri sangat lama karena slot sudah penuh.
    • Beberapa website down, yang lain masih hidup — ini terjadi karena satu atau beberapa website makan slot berlebihan, memblokir website lain di server yang sama.
    • Log Apache penuh error “MaxClients reached” — kalau kamu cek error log, akan muncul pesan seperti [notice] MaxClients of 256 servers not reached, some servers could not be allocated.
    • RAM terpakai habis — setiap slot Apache memakan RAM. Kalau slot penuh dan RAM habis, server bisa mulai swap atau bahkan OOM killer aktif.
    • CPU load naik tapi request tidak selesai — ini menandakan ada request yang stuck di tahap tertentu (menunggu database, menunggu external API, atau stuck di PHP execution).

    Root Cause: Kenapa Apache Slot Bisa Habis?

    Apache slot penuh itu bukan masalah yang muncul sendiri. Selalu ada penyebabnya, dan dari pengalaman saya, berikut penyebab yang paling sering:

    1. Website dengan PHP Execution Lambat

    Website yang PHP-nya lambat — misalnya karena query database yang tidak diindex, loop tak terbatas, atau ekstensi yang memakan waktu lama — akan memakan slot lebih lama dari yang seharusnya. Satu request yang dieksekusi selama 30 detik artinya slot tersebut terkunci selama 30 detik. Kalau ada 10 request seperti itu secara bersamaan, itu sudah 10 slot hilang.

    2. PHP-FPM Timeout Tidak Dikonfigurasi

    Kalau Apache dikonfigurasi dengan mod_php atau PHP-FPM tanpa timeout yang tepat, request yang stuck akan terus memakan slot sampai Apache sendiri timeout. Default timeout Apache biasanya 300 detik — terlalu lama.

    3. Traffic Spike atau DDoS

    Traffic mendadak naik — entah karena campaign marketing, viral content, atau serangan DDoS — bisa langsung menghabiskan semua slot dalam hitungan detik.

    4. KeepAlive Timeout Terlalu Lama

    Konfigurasi KeepAliveTimeout yang terlalu lama (misal 15 detik) membuat slot tetap terpakai meskipun client sudah tidak aktif. Klien membuka halaman, selesai, tapi slot masih dipegang selama 15 detik.

    5. Bot atau Crawler Agresif

    Bot yang crawl website terlalu agresif tanpa delay bisa menghabiskan slot dalam waktu singkat. Apalagi kalau bot tersebut mengeksekusi JavaScript atau menunggu response dari halaman yang kompleks.

    Command #1: Lihat Status Semua Slot Apache

    Langkah pertama saat curiga Apache slot penuh adalah melihat status semua slot yang aktif. Dari sinilah kita bisa tahu slot mana yang sedang dipakai, slot mana yang idle, dan slot mana yang stuck.

    Untuk server cPanel, kita bisa akses status melalui WHM server status. Berikut command-nya:

    links --dump 1 http://localhost:80/whm-server-status|grep ^[0-9]|awk 'BEGIN {print "Seconds, PID, State, IP, Domain, TYPE, URLn--"} $4 !~ /[GCRK_.]/ {print $6, $2, $4, $11, $12, $13 " " $14|"sort -n"}'

    Mari kita bedah command ini satu per satu agar kamu paham apa yang dilakukan masing-masing bagian:

    Penjelasan Tiap Bagian

    1. links --dump 1 http://localhost:80/whm-server-status — Mengambil konten halaman WHM server status. --dump 1 berarti hanya mengambil 1 frame (tidak mengikuti link ke frame lain). Output-nya berupa tabel teks dari server-status Apache.

    2. | grep ^[0-9] — Hanya menampilkan baris yang diawali angka. Di halaman server-status, baris yang diawali angka adalah baris slot yang sedang aktif — setiap baris merepresentasikan satu slot Apache yang sedang memproses request.

    3. awk 'BEGIN {print "Seconds, PID, State, IP, Domain, TYPE, URLn--"} ...' — Bagian awk dengan header tabel dan pemrosesan data. Bagian BEGIN mencetak header kolom: Seconds (durasi), PID (proses ID), State (status slot), IP (alamat client), Domain (virtual host), TYPE (metode HTTP), dan URL (alamat yang diminta).

    4. $4 !~ /[GCRK_.]/ — Filter untuk mengecualikan slot dalam kondisi tertentu. Karakter G = Graceful shutdown, C = Closing connection, R = Reading request, K = Keepalive, . = open slot kosong, _ = slot idle. Jadi perintah ini hanya menampilkan slot yang benar-benar sedang memproses request — slot yang stuck, busy, atau waiting.

    5. {print $6, $2, $4, $11, $12, $13 " " $14|"sort -n"} — Mencetak kolom yang relevan: $6 (Seconds/durasi), $2 (PID), $4 (State), $11 (IP client), $12 (domain/vhost), $13 $14 (tipe + URL). Hasilnya diurutkan berdasarkan durasi (sort -n) — slot yang paling lama menunggu akan muncul di paling atas.

    Contoh Output

    Seconds, PID, State, IP, Domain, TYPE, URL
    --
    2 14233 . 192.168.1.10 clientA.com GET /wp-admin/admin-ajax.php
    5 14234 . 192.168.1.20 clientB.com POST /xmlrpc.php
    18 14250 . 45.76.100.5 clientC.com GET /wp-login.php
    62 14301 . 103.28.12.88 clientD.com GET /wp-cron.php
    127 14180 . 178.62.55.200 clientA.com GET /wp-login.php
    248 14099 . 89.248.165.12 clientE.com POST /xmlrpc.php

    Interpretasi Output

    Dari output di atas, kita bisa lihat beberapa hal penting:

    • Slot pertama (2 detik) — masih normal, request baru saja masuk.
    • Slot keenam (248 detik) — ini sudah sangat mencurigakan. Request ke /xmlrpc.php sudah berjalan lebih dari 4 menit. Kemungkinan besar ini serangan brute force atau XML-RPC pingback abuse. Slot ini memakan resource server selama 4 menit tanpa ada progress.
    • Perhatikan pattern-nya — hampir semua request stuck di wp-login.php, xmlrpc.php, dan wp-cron.php. Ini menandakan server kamu sedang menjadi target serangan brute force.

    Command #2: Identifikasi Website Paling Banyak Makan Slot

    Setelah tahu ada slot yang stuck, langkah selanjutnya adalah mencari tahu website mana yang paling banyak memakan slot. Ini penting untuk menentukan tindakan prioritas — apakah perlu memblokir IP tertentu, menonaktifkan website tertentu, atau hanya menambah jumlah slot.

    links --dump http://127.0.0.1/server-status | grep '^[0-9]-[0-9]' | awk '{for(i=1;i<=NF;i++) if($i ~ /^http/1.[0-1]$|^h2$/) {print $(i+1); break}}' | sed 's/:80//;s/:443//' | sort | uniq -c | sort -nr

    Mari kita bedah juga command ini:

    Penjelasan Tiap Bagian

    1. links --dump http://127.0.0.1/server-status — Mengambil halaman server-status tanpa frame (--dump tanpa angka). Kita menggunakan 127.0.0.1 karena harus diakses dari localhost saja (biasanya ada IP restriction di Apache).

    2. | grep '^[0-9]-[0-9]' — Filter baris yang diawali pola angka-huruf-angka (seperti 1- 23, 2- 45). Ini adalah baris slot detail yang berisi informasi lengkap tentang satu slot Apache, termasuk virtual host (domain) yang sedang melayani request.

    3. awk '{for(i=1;i<=NF;i++) if($i ~ /^http/1.[0-1]$|^h2$/) {print $(i+1); break}}' — Loop melalui setiap field di baris dan cari field yang sesuai dengan http/1.0, http/1.1, atau h2 (HTTP version). Begitu ketah, ambil field setelahnya ($(i+1)) — yaitu nama virtual host atau IP port. Ini cara kita mengetahui domain mana yang sedang dilayani oleh slot tersebut.

    4. | sed 's/:80//;s/:443//' — Hapus port number (:80 atau :443) dari nama domain agar hasilnya bersih.

    5. | sort | uniq -c | sort -nr — Urutkan, hitung jumlah kemunculan setiap domain, lalu urutkan berdasarkan jumlah terbanyak di paling atas.

    Contoh Output

        142 clientA.com
         67 clientD.com
         31 clientB.com
          8 clientC.com
          5 clientE.com
          3 (helicon.nginx)

    Dari output ini, sudah sangat jelas: clientA.com memakan 142 slot dari 256 total — itu artinya satu website ini saja menghabiskan lebih dari 55% dari seluruh slot Apache. Website ini harus ditindak segera.

    Command #3: Cek Slot yang Sedang Waiting atau Stuck

    Kadang kita perlu tahu slot mana yang benar-benar stuck — slot yang sudah menunggu sangat lama dan tidak ada progress. Ini berbeda dari slot yang sedang memproses request yang memang membutuhkan waktu lama (misalnya generate report besar). Slot stuck biasanya menandakan ada masalah di PHP execution, database, atau external resource.

    links --dump 1 http://localhost:80/whm-server-status | grep "W" | awk '{print $2, $6, $12}' | sort -rn | head -20

    Atau kalau kamu ingin melihat slot dalam kondisi apapun yang sudah berjalan lebih dari 30 detik:

    links --dump 1 http://localhost:80/whm-server-status | grep '^[0-9]' | awk '$6 > 30 {print $6, $2, $4, $11, $12, $13, $14}' | sort -rn

    Interpretasi

    Slot yang berjalan lebih dari 30 detik tanpa selesai bisa jadi tanda bahaya. Beberapa kemungkinan:

    • Database query lambat — request yang menunggu query selesai. Bisa dicek dengan SHOW PROCESSLIST di MariaDB/MySQL.
    • External API timeout — website yang memanggil API luar yang tidak merespons.
    • PHP infinite loop — script yang terjebak dalam loop tanpa batas.
    • File I/O bottleneck — website yang membaca file besar dari disk yang lambat.

    Command #4: Hitung Total Slot yang Terpakai vs Tersedia

    Untuk mendapatkan gambaran keseluruhan, berikut command untuk menghitung berapa slot yang sudah dipakai dan berapa yang masih tersedia:

    links --dump 1 http://localhost:80/whm-server-status | grep '^[0-9]' | wc -l

    Atau versi yang lebih detail:

    links --dump 1 http://localhost:80/whm-server-status | grep 'servers available|servers busy|Total accesses' | head -5

    Jika MaxClients adalah 256 dan kamu melihat 256 slot aktif dengan hanya 2 atau 3 dalam kondisi idle (_ atau .), maka server kamu sudah hampir mencapai batas. Jika semua slot dalam kondisi busy (W atau .. tanpa idle), maka server sudah benar-benar kehabisan slot.

    Cara Mengatasi Apache Slot Penuh

    ⚠️ PERINGATAN KEAMANAN: Backup Konfigurasi Sebelum Perubahan

    Sebelum kita melakukan perubahan konfigurasi Apache, WAJIB backup dulu file konfigurasi yang ada. Perubahan konfigurasi yang salah bisa bikin Apache tidak bisa start sama sekali.

    cp /etc/apache2/conf/httpd.conf /etc/apache2/conf/httpd.conf.bak-$(date +%Y%m%d-%H%M)
    cp -r /etc/apache2/conf.d/ /etc/apache2/conf.d.bak-$(date +%Y%m%d-%H%M)

    PENTING: Setelah backup, verifikasi backup berhasil:

    ls -lh /etc/apache2/conf/httpd.conf.bak-*
    ls -lh /etc/apache2/conf.d.bak-* 2>/dev/null

    Jangan pernah melakukan perubahan konfigurasi tanpa backup — karena kalau terjadi kesalahan, kamu perlu memulihkan konfigurasi yang benar secepat mungkin.

    Solusi 1: Optimasi KeepAliveTimeout

    Salah satu perubahan paling cepat dan efektif adalah mengurangi KeepAliveTimeout. Default biasanya 5-15 detik. Untuk server yang sering kehabisan slot, turunkan ke 2-3 detik:

    KeepAliveTimeout 3
    MaxKeepAliveRequests 100

    Perubahan ini memastikan slot tidak terkunci terlalu lama oleh koneksi yang sudah selesai. Setelah perubahan, restart Apache:

    systemctl restart httpd

    Verifikasi: Pastikan Apache berhasil start setelah restart:

    systemctl status httpd
    curl -s -o /dev/null -w "%{http_code}" http://localhost/

    Solusi 2: Tambah MaxClients (Jika RAM Mencukupi)

    Jika RAM server mencukupi, kamu bisa menambah jumlah MaxClients. Hitung dulu berapa slot yang bisa ditambah:

    free -m | head -2
    ps -C apache2 -o pid,rss,cmd --no-headers | awk '{sum+=$2; count++} END {print "Average RSS per slot:", sum/count/1024, "MB"; print "Total slots:", count}'

    Dari output ini, kamu bisa hitung: kalau slot average memakan 30MB RAM dan server punya 2GB free, kamu bisa menambah sekitar 60 slot lebih. Tapi jangan lupa sisakan RAM untuk sistem operasi dan database.

    Solusi 3: Blokir IP yang Agresif

    Kalau dari hasil Command #1 dan #2 terlihat ada IP tertentu yang memakan banyak slot dengan request mencurigakan (seperti brute force ke xmlrpc.php atau wp-login.php), langsung blokir:

    # Cek dulu IP mana yang paling banyak request
    links --dump 1 http://localhost:80/whm-server-status | grep '^[0-9]' | awk '{print $11}' | sort | uniq -c | sort -rn | head -10

    Setelah tahu IP-nya, tambahkan ke CSF firewall atau .htaccess:

    # Via .htaccess (jika CSF tidak tersedia)
    # Tambahkan di awal file .htaccess website yang terkena:
    # Order Deny,Allow
    # Deny from 103.28.12.88

    Solusi 4: Nonaktifkan xmlrpc.php (Jika Tidak Diperlukan)

    XML-RPC adalah pintu masuk utama serangan brute force di WordPress. Kalau website kamu tidak membutuhkan remote posting atau mobile app yang pakai XML-RPC, nonaktifkan saja:

    # Tambahkan di .htaccess atau virtual host config:
    # <Files xmlrpc.php>
    #   Require all denied
    # </Files>

    Solusi 5: Tambah Rate Limiting di Apache

    Rate limiting bisa mencegah satu IP menghabiskan terlalu banyak slot:

    # Di .htaccess atau virtual host:
    # <IfModule mod_evasive20.c>
    #   DOSHashTableSize 3097
    #   DOSPageInterval 1
    #   DOSSiteInterval 1
    #   DOSPageCount 5
    #   DOSSiteCount 50
    #   DOSBlockingPeriod 10
    # </IfModule>

    Pro Tips: Pencegahan Apache Slot Penuh

    1. Monitor slot secara berkala — jangan menunggu sampai error 503. Buat cron job untuk alert: links --dump 1 http://localhost:80/whm-server-status | grep '^[0-9]' | wc -l | awk '{if ($1 > 200) print "ALERT: Apache slots high - "$1"/256"}'
    2. Optimasi PHP execution time — set max_execution_time di php.ini ke 30 detik. Request yang lebih lama dari 30 detik kemungkinan sudah bermasalah.
    3. Gunakan opcache — PHP opcache mengurangi waktu eksekusi secara signifikan. Pastikan opcache aktif di semua website.
    4. Setup mod_remoteip — kalau server ada di belakang Cloudflare atau load balancer, pastikan Apache melihat IP asli client, bukan IP proxy.
    5. Gunakan Reverse Proxy (Nginx) di depan Apache — Nginx lebih efisien menangani koneksi static dan bisa memfilter request sebelum sampai ke Apache.
    6. Alert otomatis — setup monitoring seperti Zabbix atau bahkan simple cron untuk alert via Telegram/Email saat slot mencapai threshold tertentu.
    7. Review log secara berkala — cek /var/log/apache2/error_log untuk pattern error yang berulang.

    FAQ

    Berapa jumlah MaxClients yang ideal untuk server cPanel?

    Tergantung RAM dan jenis website. Untuk server 4GB RAM dengan website WordPress ringan, MaxClients 150-200 sudah cukup. Untuk server 8GB dengan website yang lebih berat, bisa naik ke 300-400. Kunci utama adalah monitoring — lihat berapa slot yang benar-benar dipakai secara normal dan sesuaikan dari situ.

    Apa bedanya 503 Service Unavailable dengan 502 Bad Gateway?

    Error 503 berarti Apache tidak bisa menerima request baru karena slot penuh atau service sedang down. Error 502 berarti ada masalah di upstream — misalnya PHP-FPM tidak merespons atau proxy tidak bisa menghubungi backend. Kalau 503, cek slot Apache. Kalau 502, cek PHP-FPM dan konfigurasi proxy.

    Bagaimana cara mengetahui apakah slot penuh karena serangan DDoS?

    Cek log Apache untuk pola request yang tidak wajar: IP yang sama request ribuan kali dalam hitungan detik, request ke path yang aneh (misal /wp-login.php berulang-ulang), atau request dari IP range yang sama. Kalau polanya mencurigakan, aktifkan rate limiting dan pertimbangkan untuk pakai Cloudflare atau ModSecurity.

    Apakah aman restart Apache di production?

    Ya, restart Apache di production umumnya aman selama kamu sudah backup konfigurasi dulu. Restart yang normal (bukan graceful stop) akan memutus semua koneksi aktif, tapi klien akan otomatis reconnect. Yang perlu diperhatikan: pastikan tidak ada deploy atau perubahan kode yang sedang berjalan, karena restart bisa memutus proses tersebut.

    Related Issues

    Kesimpulan

    Apache slot penuh itu masalah yang bisa datang kapan saja, tapi kalau kamu tahu cara membaca server-status dengan benar, kamu bisa mendeteksinya sebelum terlambat. Dua command utama yang harus kamu hafalkan adalah:

    • links --dump 1 http://localhost:80/whm-server-status|grep ^[0-9]|awk '...' — untuk melihat status setiap slot dan menemukan request yang stuck
    • links --dump http://127.0.0.1/server-status | grep ... | awk ... | sort | uniq -c | sort -nr — untuk menemukan website mana yang paling banyak makan slot

    Dengan kedua command ini, kamu bisa dengan cepat mengidentifikasi root cause dan mengambil tindakan yang tepat — entah itu memblokir IP agresif, mengoptimasi KeepAliveTimeout, atau menambah MaxClients. Yang terpenting, jangan menunggu sampai error 503 muncul di monitoring. Monitor slot secara berkala, set alert otomatis, dan selalu backup konfigurasi sebelum perubahan. Lebih baik cegah daripada harus restart Apache di tengah malam sambil ditelepon client — percaya deh, saya pernah ngalamin dan tidak mau ngalamin lagi.