Belajar RoadRunner - HTTP Plugin & Pool Management
Episode 5 of 26

Belajar RoadRunner - HTTP Plugin & Pool Management

Mempelajari plugin HTTP RoadRunner secara menyeluruh: konfigurasi http.address dan middleware bawaan seperti gzip dan static, pengaturan pool num_workers, max_worker_memory, max_jobs, hingga praktik melayani static files bersama dynamic routes.

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Setelah di episode 4 kita membuat worker PSR-7 yang bisa merespons request, pada episode kali ini kita membesarkan skala: mengkonfigurasi HTTP plugin secara penuh — alamat listen, middleware bawaan, dan parameter pool — lalu melayani kombinasi static files dan dynamic routes seperti aplikasi produksi sungguhan.

Mengapa episode ini penting? Karena di sinilah kalian mulai membuat keputusan operasional: berapa worker, berapa memory cap, apa yang dilayani Go langsung dan apa yang diteruskan ke PHP. Keputusan ini menentukan latensi dan penggunaan resource — dan hampir semua aplikasi RoadRunner produksi memulai dari blok http seperti yang kita bahas sekarang.

Konfigurasi Dasar http

Blok http lengkap
http:
  address: 0.0.0.0:8080
  max_request_size: 1024
  middleware: ["gzip", "static", "headers", "sendfile"]
  uploads:
    dir: "/tmp/uploads"
    forbid: [".php", ".exe", ".bat"]
  pool:
    num_workers: 8
    max_worker_memory: 128
    max_jobs: 1000
    allocate_workers_by_tasks: true
  static:
    dir: public
    forbid: [".php", ".htaccess"]
    cache:
      etag: true
      last_modified: true
KeyFungsi
addressAlamat listen TCP (host:port)
max_request_sizeLimit ukuran request (KB) untuk melindungi dari body raksasa
middlewareDaftar middleware HTTP bawaan yang aktif, urutannya penting
uploadsKonfigurasi file upload: direktori simpan dan daftar ekstensi terlarang
poolParameter worker pool untuk aplikasi HTTP
staticMelayani file statis langsung dari Go, tanpa menyentuh PHP

Note

Order middleware menentukan urutan eksekusi. Aturan praktis: taruh static di posisi awal agar file statis direspons Go tanpa mencapai worker PHP, dan taruh transformasi response seperti gzip setelahnya.

Middleware Bawaan

RoadRunner menyediakan middleware HTTP yang diaktifkan hanya dengan menulis namanya di daftar middleware:

MiddlewareFungsi
gzipKompres response (dan request) dengan gzip/zstd/brotli
staticMelayani file dari http.static.dir tanpa melibatkan PHP
sendfileMengirim file besar lewat kernel (sendfile(2)) — hemat memory Go
headersMenambahkan header ke semua response
requestInstrumen request untuk metrics (biasanya bersama plugin metrics)
http_metricsMetric HTTP otomatis (endpoint /metrics, episode 12)

Contoh penggunaan headers dan sendfile:

Middleware headers dan sendfile
http:
  address: 0.0.0.0:8080
  middleware: ["static", "gzip", "headers", "sendfile"]
  headers:
    response:
      "X-Powered-By": "RoadRunner"
      "X-Frame-Options": "DENY"

Pool Management

Parameter pool menentukan bagaimana worker di-spawn dan dirawat:

Pool dengan supervisor
pool:
  num_workers: 8
  max_worker_memory: 128
  max_jobs: 1000
  allocate_workers_by_tasks: true
  supervisor:
    max_worker_memory: 128
    exec_ttl: 0
    idle_ttl: 60
    ttl: 0

Penjelasan parameter inti:

  • num_workers — jumlah worker yang hidup di pool. Mulai dari jumlah core CPU dan sesuaikan dari hasil benchmark (episode 20).
  • max_jobs — worker di-restart setelah melayani N request. Ini pengaman utama terhadap memory leak bertahap di PHP.
  • max_worker_memory — worker di-restart bila penggunaan memory (RSS) melebihi nilai ini (MB).
  • allocate_workers_by_tasks — bila true, worker di-spawn bertahap sesuai beban, bukan semua sekaligus. Berguna untuk hemat resource saat idle.

supervisor menambahkan aturan restart berbasis waktu: idle_ttl (detik idle sebelum direstart), exec_ttl (durasi maksimum satu task), dan ttl (umur maksimum worker). Kombinasi ini menjaga pool tetap segar tanpa downtime manual.

Praktik: Static Files + Dynamic Routes

Mari bangun aplikasi kecil yang melayani static assets dari Go dan dynamic routes dari PHP. Susun struktur proyek:

Struktur proyek
rr-lab/
  app.php          # worker PSR-7 (episode 4)
  .rr.yaml         # config dengan static.dir
  public/
    index.html     # halaman statis
    assets/
      app.css

Update bagian static dan middleware di .rr.yaml, lalu tulis route dinamis di worker — tambahkan pengecekan path sebelum merespons:

app.php - dynamic route sederhana
while ($request = $psr7->waitRequest()) {
    try {
        $path = $request->getUri()->getPath();
        $status = 200;
        $body = 'Not Found';
 
        if ($path === '/' || $path === '/home') {
            $body = '<h1>Home</h1><a href="/assets/app.css">CSS</a>';
        } elseif ($path === '/api/health') {
            $body = json_encode(['status' => 'ok', 'pid' => getmypid()]);
        }
 
        $response = new Response($status, ['Content-Type' => 'text/html; charset=utf-8'], $body);
        $psr7->respond($response);
    } catch (\Throwable $e) {
        $psr7->getWorker()->error((string) $e);
    }
}

Restart server dan uji:

Uji static dan dynamic
./rr serve -c .rr.yaml &
curl http://localhost:8080/assets/app.css   # dilayani Go, tidak menyentuh PHP
curl http://localhost:8080/api/health       # dilayani worker PHP

Bandingkan latensi keduanya: respons statis datang dari Go dalam hitungan mikro detik dan tidak memakai worker — inilah mengapa static selalu disarankan untuk aset, sementara PHP hanya untuk konten dinamis.

Warning

Perhatikan static.forbid — daftar ekstensi yang tidak boleh dilayani sebagai file statis (misal .php). Tanpa ini, jika ada file .php di dalam public/, Go bisa membocorkan source code-nya. Selalu sediakan forbid: [".php", ".htaccess"].

Penutup

Pada episode 5 ini, kalian telah menguasai HTTP plugin dan pool management.

Inti yang harus dibawa pulang:

  • Blok http mengatur alamat, ukuran request, upload, pool, dan static.
  • Middleware aktif hanya dengan mendaftarkannya di middleware — order menentukan eksekusi.
  • Pool dijaga oleh num_workers, max_jobs, max_worker_memory, dan supervisor.
  • Static files dilayani Go langsung — hemat resource PHP.
  • Selalu set static.forbid untuk keamanan.

Di episode 6 selanjutnya, kita mengintegrasikan framework: menjalankan Laravel via Octane dan Symfony via RoadRunner Runtime, termasuk konfigurasi worker count dan warm-up — sehingga kalian tidak perlu menulis worker manual lagi. Sampai jumpa di episode 6!

Belajar RoadRunner - HTTP Plugin & Pool Management | Belajar RoadRunner