Mengintegrasikan RoadRunner ke framework populer: menjalankan Laravel dengan Octane server roadrunner, memahami worker count dan warm-up untuk mengurangi cold start, lalu mengatur Symfony Runtime sebagai app server untuk aplikasi Symfony.

Setelah di episode 4-5 kita menulis worker PSR-7 manual, pada episode kali ini kita berhenti menulis dari nol: mengintegrasikan RoadRunner ke framework — Laravel lewat Octane dan Symfony lewat Runtime. Di produksi nyata, hampir tidak ada yang menulis worker manual; mereka memakai framework yang sudah menyediakan abstraksi worker dan koneksi ke RoadRunner.
Mengapa episode ini penting? Karena inilah jalur adopsi paling realistis: kalian punya aplikasi Laravel/Symfony yang sudah berjalan di PHP-FPM, lalu ingin pindah ke long-running tanpa menulis ulang seluruh aplikasi. Framework integration adalah jembatannya.
Laravel Octane adalah package resmi Laravel untuk menjalankan aplikasi di app server modern — RoadRunner adalah salah satu servernya, selain Swoole dan FrankenPHP. Install dan aktifkan:
composer require laravel/octane
php artisan octane:install --server=roadrunnerPerintah ini melakukan tiga hal: menyalin vendor binary RoadRunner ke proyek (via vendor/bin/rr), mempublikasikan file config/octane.php, dan menempatkan file worker rr-worker.php di direktori proyek. Konfigurasi .rr.yaml Laravel biasanya seperti ini:
version: "3"
server:
command: "php vendor/bin/octane"
relay: pipes
http:
address: 0.0.0.0:8000
pool:
num_workers: 8
max_worker_memory: 128
max_jobs: 500
middleware: ["gzip"]
logs:
mode: production
level: infoJalankan dengan:
php artisan octane:start --server=roadrunner --host=0.0.0.0 --port=8000Octane meng-bootstrap aplikasi Laravel sekali di awal worker (membangun kernel, service provider, koneksi DB), lalu setiap request memakai kernel yang sama. Ini perbedaan kunci dengan FPM:
register dan boot service provider terjadi saat worker lahir, bukan per-request.RequestSaw listeners) — misalnya me-reset singleton yang menyimpan data request.Kalian bisa mengatur berapa worker dan kapan mereka direstart lewat config/octane.php:
'warm' => [
'App\Http\Controllers\WelcomeController::class',
'App\Services\MetricsService::class',
],Nilai warm berisi class yang "dipanaskan" saat worker start — class di-load ke opcache sehingga request pertama tidak harus me-load-nya. Kombinasi num_workers, max_jobs, dan warm menentukan trade-off memory vs latensi cold start; kita eksperimen lebih jauh di episode 20.
Warning
Saat pindah ke Octane, ada kelas/singleton yang tidak boleh menyimpan state request (misalnya menyimpan user di property class). State harus selalu berbasis request, session, atau store eksternal. Daftar lengkap concern ini dibahas di episode 14.
Untuk Symfony, ada Symfony Runtime — mekanisme alternatif index.php yang memakai RoadRunner sebagai runner. Install:
composer require symfony/runtime spirals/roadrunner-bundlePackage spirals/roadrunner-bundle (dari Spiral) menyediakan integrasi penuh: otomatis membuat worker, mengatur kernel, dan menghubungkan plugin ekosistem (KV, queue, dll) ke service Symfony. Entry point-nya bukan index.php biasa:
<?php
use App\Kernel;
use Spiral\RoadRunner\Worker;
use Spiral\RoadRunner\Http\PSR7Worker;
use Nyholm\Psr7\Factory\Psr17Factory;
use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\KernelInterface;
require __DIR__ . '/vendor/autoload.php';
$kernel = new Kernel('prod', false);
$kernel->boot();
$psr7 = new PSR7Worker(
Worker::create(),
new Psr17Factory(),
new Psr17Factory(),
new Psr17Factory()
);
while ($request = $psr7->waitRequest()) {
try {
$httpFactory = new PsrHttpFactory($psr17, $psr17, $psr17, $psr17);
$sfRequest = $httpFactory->createRequest($request);
$response = $kernel->handle($sfRequest);
$psr7->respond($httpFactory->createResponse($response));
$kernel->terminate($sfRequest, $response);
} catch (\Throwable $e) {
$psr7->getWorker()->error((string) $e);
}
}Perhatikan polanya: kernel di-boot sekali di luar loop, lalu setiap request diproses dengan handle()/terminate() — sama seperti pola Octane. Config .rr.yaml cukup mengarahkan server.command ke php rr-worker.php.
| Aspek | Laravel Octane | Symfony Runtime |
|---|---|---|
| Package kunci | laravel/octane | symfony/runtime + spirals/roadrunner-bundle |
| Entry worker | Otomatis (php vendor/bin/octane) | Manual rr-worker.php |
| Integrasi plugin RR | Via Octane + facade | Via bundle (DI) |
| Kalibrasi | php artisan octane:status | Log runtime |
| Cocok untuk | Tim Laravel | Tim Symfony / Spiral |
Kedua jalur memberi hasil yang sama: aplikasi framework berjalan sebagai worker persistent di bawah RoadRunner, dengan kontrol pool yang sama dari .rr.yaml.
Pada episode 6 ini, kalian telah mengintegrasikan RoadRunner ke kedua framework mainstream PHP.
Inti yang harus dibawa pulang:
php artisan octane:install --server=roadrunner lalu octane:start.symfony/runtime + spirals/roadrunner-bundle, boot kernel sekali di luar loop.config/octane.php dan blok pool mengatur worker count dan warm-up.Di episode 7 selanjutnya, kita membuka "jalur belakang" RoadRunner: RPC & Goridge — protokol komunikasi Go↔PHP yang dipakai semua plugin, dengan praktik memanggil method dari Go ke PHP dan sebaliknya. Sampai jumpa di episode 7!