Qu’est-ce que Horizon
Laravel Horizon est un tableau de bord dédié aux queues Redis de Laravel. Débit des jobs, temps d’exécution, échecs — le tout en temps réel, avec une configuration des workers gérée par code.
Horizon complète les fonctionnalités de base. Lisez d’abord Queues et jobs et Redis est obligatoire en backend.
Installation
Horizon exige Redis comme backend. Vérifiez que QUEUE_CONNECTION (config/queue.php) vaut redis. Redis Cluster n’est pas pris en charge.
Installez via Composer.
composer require laravel/horizon
Publiez les fichiers.
php artisan horizon:install
Cela génère config/horizon.php et app/Providers/HorizonServiceProvider.php.
Configuration
config/horizon.php
Ce fichier gère la configuration des workers. Le cœur est l’option environments.
'environments' => [
'production' => [
'supervisor-1' => [
'connection' => 'redis' ,
'queue' => [ 'default' , 'notifications' ],
'balance' => 'auto' ,
'autoScalingStrategy' => 'time' ,
'minProcesses' => 1 ,
'maxProcesses' => 10 ,
'balanceMaxShift' => 1 ,
'balanceCooldown' => 3 ,
'tries' => 3 ,
'timeout' => 60 ,
],
],
'local' => [
'supervisor-1' => [
// Les autres valeurs sont héritées de defaults
'maxProcesses' => 3 ,
],
],
],
Horizon utilise en interne une connexion Redis nommée horizon. Ne réutilisez pas ce nom dans config/database.php.
Superviseurs
Un environnement peut contenir plusieurs « superviseurs ». Un superviseur groupe des workers avec ses propres files, stratégie d’équilibrage et nombre de processus.
Defaults
Utilisez defaults pour partager des valeurs entre tous les superviseurs.
'defaults' => [
'supervisor-1' => [
'connection' => 'redis' ,
'queue' => [ 'default' ],
'balance' => 'auto' ,
'tries' => 1 ,
'timeout' => 60 ,
'maxProcesses' => 1 ,
],
],
Mode maintenance
Par défaut Horizon ne traite pas les jobs en maintenance. Forcez avec force.
'environments' => [
'production' => [
'supervisor-1' => [
'force' => true ,
],
],
],
Tentatives max
'environments' => [
'production' => [
'supervisor-1' => [
'tries' => 10 ,
],
],
],
0 = illimité.
Timeout
'environments' => [
'production' => [
'supervisor-1' => [
'timeout' => 60 ,
],
],
],
Définissez timeout quelques secondes en dessous de retry_after (config/queue.php). En balance auto, les jobs dépassant ce délai peuvent être tués.
Backoff
Attente entre les tentatives.
// Fixe
'backoff' => 10 ,
// Exponentiel
'backoff' => [ 1 , 5 , 10 ],
Stratégies d’équilibrage
Trois stratégies :
Ajuste automatiquement le nombre de workers selon la charge. minProcesses et maxProcesses fixent les bornes. 'supervisor-1' => [
'balance' => 'auto' ,
'autoScalingStrategy' => 'time' , // ou 'size'
'minProcesses' => 1 ,
'maxProcesses' => 10 ,
'balanceMaxShift' => 1 ,
'balanceCooldown' => 3 ,
],
time : temps estimé pour vider la file
size : nombre de jobs
En auto, l’ordre des files n’indique pas la priorité. Utilisez plusieurs superviseurs pour forcer la priorité.
Nombre fixe de workers réparti à parts égales. 'supervisor-1' => [
'balance' => 'simple' ,
'processes' => 10 ,
'queue' => [ 'default' , 'notifications' ],
],
Ici, 5 processus par file.
false (aucun équilibrage)
Ordre strict, comme la queue par défaut, mais avec scaling selon l’accumulation. 'supervisor-1' => [
'balance' => false ,
'queue' => [ 'default' , 'notifications' ],
'minProcesses' => 1 ,
'maxProcesses' => 10 ,
],
Les jobs default passent toujours avant notifications.
Autorisation du dashboard
Le dashboard est accessible sur /horizon. En local, tout le monde y accède ; en production, restreignez via une gate.
Éditez la méthode gate() de app/Providers/HorizonServiceProvider.php.
use App\Models\ User ;
use Illuminate\Support\Facades\ Gate ;
protected function gate () : void
{
Gate :: define ( 'viewHorizon' , function ( User $user ) {
return in_array ( $user -> email , [
'[email protected] ' ,
]);
});
}
Sans authentification (IP filtering, etc.), rendez le paramètre optionnel.
Gate :: define ( 'viewHorizon' , function ( User $user = null ) {
// Protégé par IP, etc.
return true ;
});
Démarrer Horizon
Commandes
# Démarrer
php artisan horizon
# Pause / reprise
php artisan horizon:pause
php artisan horizon:continue
# Pause / reprise d'un superviseur
php artisan horizon:pause-supervisor supervisor-1
php artisan horizon:continue-supervisor supervisor-1
# Statut
php artisan horizon:status
php artisan horizon:supervisor-status supervisor-1
# Arrêt gracieux
php artisan horizon:terminate
Local : redémarrage auto
horizon:listen redémarre Horizon quand un fichier change.
npm install --save-dev chokidar
php artisan horizon:listen
# Docker / Vagrant
php artisan horizon:listen --poll
Supervisor en production
Faites tourner Horizon en continu avec Supervisor.
Installation
sudo apt-get install supervisor
Config
Créez /etc/supervisor/conf.d/horizon.conf.
[program:horizon]
process_name =%(program_name)s
command =php /home/forge/example.com/artisan horizon
autostart =true
autorestart =true
user =forge
redirect_stderr =true
stdout_logfile =/home/forge/example.com/horizon.log
stopwaitsecs =3600
stopwaitsecs doit être supérieur à la durée du plus long job. Sinon Supervisor l’interromprait de force.
Démarrage
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start horizon
Déploiement
À chaque déploiement, redémarrez Horizon pour appliquer les changements.
php artisan horizon:terminate
Avec Supervisor en autostart=true / autorestart=true, il redémarre automatiquement.
Gestion des jobs
Horizon détecte automatiquement les modèles Eloquent liés à un job et pose des tags.
// Job recevant Video(id=1) → tag automatique "App\Models\Video:1"
RenderVideo :: dispatch ( Video :: find ( 1 ));
Personnalisez avec tags().
class RenderVideo implements ShouldQueue
{
/**
* @return array < int , string>
*/
public function tags () : array
{
return [ 'render' , 'video:' . $this -> video -> id ];
}
}
Pour un event listener, l’instance de l’événement est passée à tags().
class SendRenderNotifications implements ShouldQueue
{
public function tags ( VideoRendered $event ) : array
{
return [ 'video:' . $event -> video -> id ];
}
}
Silence
Masquer certains jobs de la liste « Completed Jobs » via config/horizon.php.
'silenced' => [
App\Jobs\ ProcessPodcast :: class ,
],
// Par tag
'silenced_tags' => [
'notifications' ,
],
Ou via l’interface Silenced.
use Laravel\Horizon\Contracts\ Silenced ;
class ProcessPodcast implements ShouldQueue , Silenced
{
use Queueable ;
// ...
}
Métriques et supervision
Le dashboard des métriques affiche débit et durée des jobs/files. Planifiez des snapshots réguliers.
// routes/console.php
use Illuminate\Support\Facades\ Schedule ;
Schedule :: command ( 'horizon:snapshot' ) -> everyFiveMinutes ();
Réinitialiser les métriques :
php artisan horizon:clear-metrics
Notifications d’échec
Recevez des notifications quand une file s’allonge. Dans boot() de HorizonServiceProvider.
use Laravel\Horizon\ Horizon ;
public function boot () : void
{
parent :: boot ();
Horizon :: routeMailNotificationsTo ( '[email protected] ' );
Horizon :: routeSlackNotificationsTo ( 'slack-webhook-url' , '#ops' );
Horizon :: routeSmsNotificationsTo ( '15556667777' );
}
Seuils d’attente
Réglez waits dans config/horizon.php.
'waits' => [
'redis:critical' => 30 , // > 30 s → notification
'redis:default' => 60 ,
'redis:batch' => 120 ,
],
0 désactive la notification.
Gestion des jobs échoués
Suppression par ID ou UUID.
# Un job échoué précis
php artisan horizon:forget 5
# Tous
php artisan horizon:forget --all
Purger une file :
# File par défaut
php artisan horizon:clear
# File précise
php artisan horizon:clear --queue=emails
Mise à jour
Consultez toujours le guide de mise à jour avant une montée de version majeure.
Pages associées
Queues et jobs Bases des queues Laravel : création, dispatch, batch, échecs.
Redis Configuration et usage de Redis, backend requis par Horizon.