What is Laravel Octane?
Laravel Octane is the official Laravel package that is used for boosting the speed of your Laravel application, sounds good right? Well Yes, But it has some caveats as well that we will see later in this post.
How to use Laravel Octane?
Let’s see how we can use Laravel octane in our existing Laravel application, you can follow the below steps to configure Laravel octane and take it to the first test drive 🙂
1. Install Laravel Octane Package
First, Install the package using composer using the following command:
composer require laravel/octane
Once the package is installed, execute octane:install Artisan command that will do the required configuration for us such as generating octane config file.
php artisan octane:install
2. Deciding which application server to use
Laravel Octane uses application servers like RodeRunner or Swoole to serve the request, so before we go any further we have to decide which application server we want to use.
Here, I am going to use Swoole, You ask why? Because using Laravel Octane with Swoole application server provides access to the following features which is not available if we use RodeRunner :
- Concurrent Tasks
- Ticks
- Octane Cache
- Tables
3. Installing Swoole PHP Extension
To use Swoole application server, We will need to install Swoole PHP Extension, we can install this manually or using PECL by the following command:
pecl install swoole
[Note: Laravel Octane requires PHP version 8.0 or latter]
4. Swoole Configuration
When using Swoole, we can add the following additional configuration options in our octane config file:
'swoole' => [ 'options' => [ 'log_file' => storage_path('logs/swoole_requests.log'), 'package_max_length' => 10 * 1024 * 1024, ], ]
5. Serving Application
Once all the above steps are completed, we are ready to serve our application via Laravel octane, we can start our application using octane:start Artisan command.
php artisan octane:start
By default, octane will start our application on default port 8000, so we can access our application at http://localhost:8000
As you can see above, by default octane servers our application via HTTP, if we want to serve our application via HTTPS then we can do that using environment variable OCTANE_HTTPS that is used in octane configuration, we have to set OCTANE_HTTPS to true and our application will be served over HTTPS
So by following the above steps, we have served our application using Laravel octane and that’s great, but as i have mentioned in the start there are some caveats.
Make sure that your application is octane friendly
Laravel Octane speeds up the execution of our application by loading the whole application in memory and then using it for subsequent requests.
This does not affect most of the functionality but if our application uses dependency injection then it can have unexpected behavior and we have to modify our application so that it’s octane friendly. Laravel official docs explain this in more detail which you can refer to by clicking here.
Managing memory leaks
As we know, Laravel octane loads our application in memory and keeps it there, this means any static data stored in an array can cause memory leaks that we should be careful of. See below code, for example, it has a memory leak because every request will continue to add data into our array.
use App\Service; use Illuminate\Http\Request; use Illuminate\Support\Str; /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @return void */ public function index(Request $request) { Service::$data[] = Str::random(10); // ... }
[Example taken from official docs]
Some important octane artisan commands
# octane:start
This command is used for starting our octane based application, it has the following extra parameters that we can pass:
–workers
Specify the number of workers we want to start
–task-workers
Specify the number of task workers we want to start, this only works if we are using swoole application server
–watch
Since octane loads our application in memory, any changes to code do not reflect unless we restart our server, we can use the watch parameter to tell octane to look for any changes to source code and restart the application automatically if any change is detected.
–max-requests
Specify the number of requests one worker should handle before it’s get destroyed and a new worker is respawned
# octane:reload
This command is used for reloading octane workers, this is useful after deployment so new changes can be reflected
# octane:stop
This command is used for stopping the octane server
# octane:status
This command is used for checking the status of octane server
How to serve octane applications via nginx?
In a production environment, we should serve our octane application via a web server like Nginx or apache. This way any static resources will be served directly via a web server and the web server can also handle termination of SSL connection.
Doing this in return increases the reliability and stability of our application in the production environment.
See the basic Nginx configuration below, which will serve the static content and route requests to the octane server running on port 8000.
map $http_upgrade $connection_upgrade { default upgrade; '' close; } server { listen 80; listen [::]:80; server_name domain.com; server_tokens off; root /home/forge/domain.com/public; index index.php; charset utf-8; location /index.php { try_files /not_exists @octane; } location / { try_files $uri $uri/ @octane; } location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } access_log off; error_log /var/log/nginx/domain.com-error.log error; error_page 404 /index.php; location @octane { set $suffix ""; if ($uri = /index.php) { set $suffix ?$query_string; } proxy_http_version 1.1; proxy_set_header Host $http_host; proxy_set_header Scheme $scheme; proxy_set_header SERVER_PORT $server_port; proxy_set_header REMOTE_ADDR $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_pass http://127.0.0.1:8000$suffix; } }
[Nginx configuration is taken from official docs]
Laravel Octane with Swoole
When using Laravel octane with Swoole, we can use the following extra features of octane:
# Concurrent Tasks
Using concurrent tasks, we can execute small tasks concurrently via lightweight background tasks.
use App\User; use App\Server; use Laravel\Octane\Facades\Octane; [$users, $servers] = Octane::concurrently([ fn () => User::all(), fn () => Server::all(), ]);
As shown in the above example, we can use Octane’s concurrent method and use an array to store the result of all tasks separately.
This concurrent task is executed using Swoole’s task workers, which is an entirely different process than one handling the request; the number of task workers that can be spawned is defiled by –taks-workers parameter.
# Tiks
We can register Tik operation in the boot method of our application’s service providers as shown below:
Octane::tick('simple-ticker', fn () => ray('Ticking...')) ->seconds(10);
Tik operation is executed at every specified time and we can add a callback to perform a certain activity, in the above example our tik operation will get executed every 10 seconds and the callback will post debug message ‘Ticking…’
We can add an immediate method to instruct octant to execute our tik instantly and after at an interval of the specified time.
Octane::tick('simple-ticker', fn () => ray('Ticking...')) ->seconds(10) ->immediate();
# Octane Cache
Instead of using Laravel default cache, we can use Octane cache which internally uses a Swool table and provides read and writes speed of up to 2 million per second (As per official docs).
Cache::store('octane')->put('framework', 'Laravel', 30);
The number of entries we can store in cache is limited by table configuration in octane config, which we can update as per our requirement.
We can also add intervals to our cached data, this data automatically refreshes at intervals of the specified time and this should be registered within the boot method of one of our application’s service providers.
use Illuminate\Support\Str; Cache::store('octane')->interval('random', function () { return Str::random(10); }, seconds: 5);
# Tables
Octane provides a way to interact with Swoole tables, Swoole table provides high throughput read & write and data in Swoole table is accessible to all workers.
By default, octane configuration provides one table named ‘example’ with the size of 1000 raw, configuration is shown below:
'tables' => [ 'example:1000' => [ 'name' => 'string:1000', 'votes' => 'int', ], ],
We can update this configuration and create tables according to our needs.
Once the table is defined in our configuration, we can use it in our application using Octane as shown below:
use Laravel\Octane\Facades\Octane; Octane::table('example')->set('uuid', [ 'name' => 'Nuno Maduro', 'votes' => 1000, ]); return Octane::table('example')->get('uuid');
Swoole table supports only three data types which are String, int, and float.