In this chapter we will cover how to set up Redis in-memory data store and Laravel Horizon to provide a beautiful dashboard and code-driven configuration for Redis queues.
Redis is often preferred over a database for implementing queues because of its speed. In-memory key-value store makes it very fast compared to MySQL. In a queue scenario, where data needs to be accessed and processed quickly, Redis can handle requests much faster than MySQL.
Horizon allows us to easily monitor key metrics of the queue system such as job throughput, runtime, and job failures.
The advantage of using Horizon is that all queue worker configuration is stored in a single, simple configuration file and that allows us easily scale or modify queue workers when deploying the application. For example, in the previous chapter, we set the number of workers in the supervisor configuration.
Requirements
To use Redis with Laravel we need the PHP driver for redis.
One option is to install the predis/predis ~1.0
package via composer:
composer require predis/predis:~1.0
Or install a system-wide PHP extension.
In this course, we chose to install the Redis PHP Extension.
Ubuntu
sudo apt-get install redis php8.1-redis
sudo systemctl restart php8.1-fpm.service
Fedora
sudo dnf install redis php-pecl-redis5.x86_64
sudo systemctl restart php-fpm.service
Installation
Then we can install Horizon using the composer:
composer require laravel/horizon
After installing Horizon, publish its assets using the horizon:install
command:
php artisan horizon:install
And update queue connection in your environment file:
.env
QUEUE_CONNECTION=redis
Running Horizon
Horizon queue worker can be launched using this command:
php artisan horizon
Now we can try again by registering a new user and the verification email should be delivered.
Horizon and Supervisor
We can set up Supervisor for Horizon in the same fashion as we did for queue workers.
For supervisor configuration locations please refer to Chapter 2.
Config content should look as follows:
[program:laravel-horizon]directory=/home/web/laravel-queuescommand=php artisan horizon process_name=%(program_name)s_%(process_num)02dautostart=trueautorestart=trueuser=webnumprocs=1redirect_stderr=truestdout_logfile=/home/web/.supervisor/laravel-horizon.logstopwaitsecs=3600
Important to note that the
numprocs
value is set to1
. Worker processes are managed by Horizon and the configuration file is located inconfig/horizon.php
in the Laravel project directory.
When defining your Supervisor configuration, you should ensure that the value of
stopwaitsecs
is greater than the number of seconds consumed by your longest-running job. Otherwise, Supervisor may kill the job before it is finished processing.
Horizon & Deployment
You may gracefully terminate the Horizon process using the horizon:terminate
command. Any jobs that are currently being processed will be completed and then Horizon will stop executing:
php artisan horizon:terminate
This command should be included in your deployment script.
Horizon configuration
The default configuration of Horizon right after installation looks like this:
config/horizon.php
use Illuminate\Support\Str; return [ // ... 'domain' => env('HORIZON_DOMAIN'), // ... 'path' => env('HORIZON_PATH', 'horizon'), // ... 'use' => 'default', // ... 'prefix' => env( 'HORIZON_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_horizon:' ), // ... 'middleware' => ['web'], // ... 'waits' => [ 'redis:default' => 60, ], // ... 'trim' => [ 'recent' => 60, 'pending' => 60, 'completed' => 60, 'recent_failed' => 10080, 'failed' => 10080, 'monitored' => 10080, ], // ... 'silenced' => [ // App\Jobs\ExampleJob::class, ], // ... 'metrics' => [ 'trim_snapshots' => [ 'job' => 24, 'queue' => 24, ], ], // ... 'fast_termination' => false, // ... 'memory_limit' => 64, // ... 'defaults' => [ 'supervisor-1' => [ 'connection' => 'redis', 'queue' => ['default'], 'balance' => 'auto', 'autoScalingStrategy' => 'time', 'maxProcesses' => 1, 'maxTime' => 0, 'maxJobs' => 0, 'memory' => 128, 'tries' => 1, 'timeout' => 60, 'nice' => 0, ], ], 'environments' => [ 'production' => [ 'supervisor-1' => [ 'maxProcesses' => 10, 'balanceMaxShift' => 1, 'balanceCooldown' => 3, ], ], 'local' => [ 'supervisor-1' => [ 'maxProcesses' => 3, ], ], ],];
After installation, the primary Horizon configuration option that you should familiarize yourself with is the environments
configuration option. This configuration option is an array of environments that your application runs on and defines the worker process options for each environment.
Typically, the environment is determined by the value of the APP_ENV
environment variable.
Dashboard
Horizon exposes a dashboard at the /horizon
URL.
Let's quickly run through the dashboard, we will come back to it later.
Here you will be presented with an overview and statistics about your queue workers like how many jobs were run in the past hour, how busy are queues, or how long jobs are waiting in queue to start being processed.
The pending Jobs tab will show all jobs in the queue waiting for their turn.
The completed Jobs tab has insights into how long it took for it to complete.
Dashboard access
By default, you will only be able to access this dashboard in the local
environment. However, within your app/Providers/HorizonServiceProvider.php
file, there is an authorization gate definition. This authorization gate controls access to Horizon in non-local environments.
We can update the gate()
method to include user emails which could be able to access the dashboard in production or use any other logic.
app/Providers/HorizonServiceProvider.php
protected function gate(): void{ Gate::define('viewHorizon', function ($user) { return in_array($user->email, [ ]); });}
Hey Povilas,
Good stuff.
You should probably mention that .env QUEUE_CONNECTION value shoould be "redis" for horizon to work.
thank you, updated
what are the options when using Redis for Windows users?
I wouldn't advise to set up locally on Windows just because on the live server the environment is Linux and you would STILL need to do it in Linux, so if your environment is different - even if you can make it work, you may have various bugs just because different environment setups.
You could use virtual machine on Windows, with Laravel Sail or Docker.
Cannot tell you how good this tutorial was for me! Got Supervisor all running on my AWS EC2 instance using this guide Thanks!