RoadRunner — pengantar
RoadRunner memisahkan server dari PHP: proses Go menerima permintaan, lalu menyerahkannya ke kumpulan proses PHP lewat pipa. Pemisahan itu membawa isolasi yang lebih kuat dan sederet plugin yang tidak ada di tempat lain.
Intisari
- Satu biner Go yang mengelola kumpulan proses PHP CLI — bukan utas di dalam satu proses.
- Dikonfigurasi lewat satu berkas
.rr.yaml, per plugin. - Isolasi lebih kuat: satu worker yang crash tidak menyentuh worker lain, dan tidak butuh PHP thread-safe.
- Ekosistem plugin:
jobs(antrean),grpc,kv,metrics,temporal,centrifuge. - Bukan web server penuh: TLS dan berkas statis biasanya diserahkan ke Nginx atau load balancer di depannya.
Arsitektur
internet → (Nginx / ALB) → RoadRunner (Go)
├── worker PHP #1 (proses CLI)
├── worker PHP #2
├── worker PHP #3
└── …
dihubungkan lewat pipa atau soket Unix
Perbedaannya dengan FrankenPHP ada di baris terakhir: RoadRunner tidak menanamkan PHP ke dalam dirinya. Ia menjalankan proses PHP terpisah dan berkomunikasi lewat pipa. Konsekuensinya berjalan ke dua arah — isolasi lebih baik, tapi ada biaya komunikasi antar proses dan jejak memori per worker yang lebih besar.
Konfigurasi minimal
version: "3"
server:
command: "php psr-worker.php"
http:
address: 0.0.0.0:8080
logs:
level: info
mode: production
./rr serve
./rr serve -c .rr.yaml
./rr reset # muat ulang worker dengan rapi
./rr workers -i # pantau worker secara interaktif
./rr workers -i adalah alat diagnostik yang layak dihafal. Ia menampilkan tabel langsung
berisi setiap worker: PID, status, jumlah permintaan yang sudah ditangani, dan pemakaian memorinya. Kebocoran
memori langsung terlihat di kolom terakhir — dan kamu bisa melihat worker mana yang sedang macet.
Bentuk sebuah worker PHP
<?php
require __DIR__.'/vendor/autoload.php';
$worker = Spiral\RoadRunner\Worker::create();
$factory = new Nyholm\Psr7\Factory\Psr17Factory();
$psr7 = new Spiral\RoadRunner\Http\PSR7Worker($worker, $factory, $factory, $factory);
while (true) {
try {
$request = $psr7->waitRequest(); // ← blokir sampai ada permintaan
if ($request === null) { // server minta worker berhenti
break;
}
} catch (Throwable $e) {
$psr7->respond(new Nyholm\Psr7\Response(400));
continue;
}
try {
$psr7->respond(new Nyholm\Psr7\Response(200, [], 'Halo RoadRunner!'));
} catch (Throwable $e) {
$psr7->respond(new Nyholm\Psr7\Response(500));
$psr7->getWorker()->error((string) $e);
}
}
Bentuknya berbasis PSR-7, bukan superglobal. Untuk Laravel, Octane yang menjembatani keduanya, jadi kamu tidak menulis berkas ini sendiri — tapi mengenalinya menjelaskan kenapa perilaku RoadRunner terasa berbeda dari FrankenPHP dalam hal-hal kecil.
Plugin — bagian yang membedakan
| Plugin | Gunanya |
|---|---|
http | HTTP/HTTPS/HTTP2/HTTP3, dengan middleware bawaan |
jobs | Antrean: AMQP, Kafka, SQS, NATS, Beanstalk, memori |
grpc | Server gRPC untuk PHP |
kv | Penyimpanan kunci-nilai: Redis, Memcached, BoltDB, memori |
metrics | Endpoint metrik bergaya Prometheus |
temporal | Mesin alur kerja tahan gangguan |
centrifuge | WebSocket dan pesan real-time |
service | Menjalankan proses pendamping di bawah pengawasan RoadRunner |
Plugin jobs adalah alasan sebagian tim memilih RoadRunner. Ia berarti satu proses yang
sama bisa melayani HTTP dan memproses antrean, dengan konsumen antrean yang dikelola server —
bukan proses queue:work terpisah yang harus dijaga sendiri. Untuk arsitektur kontainer, ini bisa
berarti lebih sedikit jenis task yang perlu dijalankan dan dipantau.
Middleware HTTP bawaan
http:
address: 0.0.0.0:8080
max_request_size: 32 # MB
middleware: ["gzip", "headers", "static"]
static:
dir: "public"
forbid: [".php", ".htaccess"]
headers:
response:
X-Powered-By: ""
RoadRunner bisa melayani berkas statis lewat middleware static, tapi kemampuannya lebih sederhana
daripada web server penuh. Di lingkungan produksi yang serius, aset statis biasanya diserahkan ke CDN atau
Nginx — dan itu memang pola yang disarankan.
Yang perlu diketahui sebelum memilih
| Kelebihan | Kekurangan |
|---|---|
| Tidak butuh PHP thread-safe | Perlu web server atau load balancer di depan untuk TLS |
| Isolasi antar worker sangat kuat | Jejak memori per worker lebih besar daripada per utas |
| Ekosistem plugin luas | Konfigurasi lebih banyak yang harus dipahami |
| Kontrol pool sangat detail | Berkas .rr.yaml jadi permukaan konfigurasi tersendiri |
| Dukungan Temporal dan gRPC kelas satu | Berkas statis tidak sekuat web server penuh |
Latihan: unduh biner rr, buat .rr.yaml minimal dengan worker PSR-7 di atas,
dan jalankan ./rr serve. Buka ./rr workers -i di terminal kedua sambil mengirim
permintaan, dan amati kolom jumlah permintaan serta memorinya bergerak.
Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.