Laravel+Octane
For years Deploying PHP applications using nginx+fpm was the best practice and will be for some types of applications. But in modern environments like Kubernetes, it’s not performing that well. Besides, it boots applications for every request (add something like 100ms to every request for applications using Laravel, for example)
RoadRunner
RoadRunner is a PHP application server that runs your application in workers instead of running it for every request. And with a little bit of PSR7Worker magic, you can make your app ready to use RoadRunner.
The good news is that Laravel has an official package named Octane that You can install easily by requiring it:
composer require laravel/octane
php artisan octane:install --server=roadrunner
After installation, you can run it via:
php artisan octane:start --workers=2 --host=0.0.0.0 --port=8080 --max-requests=5000
Your application will be accessible at http://0.0.0.0:8080
, easy as that.
200 GET / ............... 120.36 ms
200 GET / ............... 122.04 ms
200 GET / ................. 3.08 ms
200 GET / ................. 4.98 ms
200 GET / ................. 2.96 ms
When refreshing the page, you can see that the first 2 requests are slower than the rest. That’s because, during those requests, Roadrunner is booting the application in workers, and for the rest, it reuses those booted workers.
RoadRunner plugins
RoadRunner has many plugins you can leverage, for example, health check. that can be used for running it in a containerized environment that we discussed in a future post.
a personal experience
I used RoadRunner in a project that handles millions of requests per day, and with it and some production tweaking for it like OPcache CLI
that you can find on its official documentation now that service uses about 20% of what it used to use before.
from 454 requests in 5s
to 2467 requests in 5s
(using go-wrk for HTTP benchmarking)
As for code just needed to ensure there is no static or global variable. You can read more about it in the managing memory leaks section of Laravel octane documents.
if you have any static variables or something that needs resetting, you can reset it before handling a new request by adding a listener to octane.listeners.RequestReceived::class
like so, for example:
RequestReceived::class => [
...Octane::prepareApplicationForNextOperation(),
...Octane::prepareApplicationForNextRequest(),
\App\Listeners\FlushStates::class, // <====
],