Queue workers Laravel sur hébergement mutualisé : toujours actifs via cron

Vous utilisez les queues Laravel pour l'envoi d'e-mails, des imports ou d'autres tâches en arrière-plan ? Il vous faut alors un queue worker qui traite les jobs. Sur un VPS, on utilise généralement Supervisor pour cela. Supervisor n'est pas disponible sur notre hébergement mutualisé, mais vous n'en avez pas besoin non plus. Avec une tâche cron et flock, vous gardez un worker actif en permanence, et il redémarre tout seul après un redémarrage ou une panne.

Comment ça marche

Cron essaie de démarrer le worker toutes les minutes. flock veille à ce qu'il n'y ait jamais plus d'une instance en cours d'exécution :

  • Si le worker tourne déjà, la nouvelle tentative s'arrête aussitôt.
  • Si le worker s'est arrêté, par exemple après un redémarrage du serveur, un plantage ou un déploiement, cron le relance dans la minute.
  • Avec --max-time, le worker s'arrête proprement au bout d'une durée fixe. La consommation de mémoire reste ainsi faible et il tourne toujours avec votre code le plus récent.

Vous obtenez ainsi le même résultat qu'avec Supervisor, sans logiciel supplémentaire.

De quoi avez-vous besoin ?

Étape 1 : choisir la base de données comme queue

Ajoutez dans votre fichier .env la ligne suivante :

QUEUE_CONNECTION=database

Depuis Laravel 11, la table jobs est incluse par défaut dans un nouveau projet. Vous avez un projet plus ancien sans cette table ? Créez-la alors via SSH :

php artisan make:queue-table
php artisan migrate

Astuce : chez nous, Redis est conçu comme cache. Après un redémarrage, des données récentes peuvent avoir disparu. Choisissez donc la base de données pour les jobs qui ne doivent pas être perdus, comme les e-mails.

Étape 2 : créer un dossier pour les fichiers de verrou

Connectez-vous via SSH et exécutez :

mkdir -p ~/locks

Étape 3 : créer la tâche cron

Dans DirectAdmin, allez dans Cronjobs (voir Configurer des tâches cron dans DirectAdmin). Saisissez un * partout pour la minute, l'heure, le jour, le mois et le jour de la semaine, afin que la tâche cron s'exécute toutes les minutes. Utilisez cette commande :

/usr/bin/flock -n /home/GEBRUIKER/locks/worker1.lock /usr/local/bin/php /home/GEBRUIKER/PAD-NAAR-PROJECT/artisan queue:work --max-time=3600 --sleep=3 --tries=3 > /dev/null 2>&1

Remplacez GEBRUIKER par votre nom d'utilisateur DirectAdmin et PAD-NAAR-PROJECT par le dossier de votre projet Laravel, par exemple domains/jouwdomein.nl/laravel.

Rôle de chaque élément :

  • flock -n ...worker1.lock démarre le worker uniquement si aucun n'est déjà en cours d'exécution.
  • /usr/local/bin/php utilise la version de PHP que vous avez choisie dans DirectAdmin sous Select PHP version.
  • --max-time=3600 arrête proprement le worker au bout d'une heure et cron en démarre aussitôt un nouveau.
  • --sleep=3 fait en sorte que, quand la queue est vide, le worker vérifie toutes les 3 secondes s'il y a de nouveaux jobs.
  • --tries=3 fait qu'un job qui échoue est tenté 3 fois au maximum, puis placé dans la table failed_jobs.

Étape 4 : le scheduler (si vous l'utilisez)

Si vous utilisez le scheduler de Laravel, ajoutez une deuxième tâche cron qui s'exécute toutes les minutes :

/usr/local/bin/php /home/GEBRUIKER/PAD-NAAR-PROJECT/artisan schedule:run > /dev/null 2>&1

Ne lancez pas en plus le queue worker depuis le scheduler. La tâche cron de l'étape 3 s'en charge déjà.

Plus d'un worker

Vous avez besoin de plus de capacité de traitement ? Ajoutez alors une deuxième tâche cron avec son propre fichier de verrou :

/usr/bin/flock -n /home/GEBRUIKER/locks/worker2.lock /usr/local/bin/php /home/GEBRUIKER/PAD-NAAR-PROJECT/artisan queue:work --max-time=3600 --sleep=3 --tries=3 > /dev/null 2>&1

Chaque worker a besoin de son propre fichier de verrou. Avec le même verrou, un seul worker tourne à la fois. Vous voulez un worker par queue, par exemple pour les e-mails ? Ajoutez alors --queue=mail.

Après un déploiement

Les workers gardent votre code en mémoire. Après avoir envoyé du nouveau code, exécutez :

php artisan queue:restart

Les workers terminent leur job en cours et s'arrêtent. En moins d'une minute, cron les relance avec le nouveau code.

Vérifier que le worker tourne

ps -u $USER -o pid,etime,cmd | grep "queue:work" | grep -v grep

Si vous voyez une ligne contenant artisan queue:work, le worker tourne. Pour consulter les jobs échoués :

php artisan queue:failed

Bon à savoir

  • Un worker utilise généralement de 50 à 100 Mo de mémoire. Cela compte dans les limites de votre offre d'hébergement.
  • Ne démarrez pas un worker avec nohup ou &. Un tel worker ne revient pas après un redémarrage, et sans flock, vous en démarrez facilement plusieurs par erreur.
  • Peu de jobs ? Vous pouvez alors vous passer d'un worker permanent : laissez cron exécuter queue:work --stop-when-empty toutes les minutes, également avec flock. Le worker traite alors ce qui est en attente, puis s'arrête.
  • Si vous faites tourner un environnement de test et un environnement de production dans des offres d'hébergement distinctes, chaque offre a ses propres tâches cron, ses propres workers et sa propre base de données.

Besoin d'aide ?

Vous n'y arrivez pas ? Envoyez-nous un message via le système de tickets, nous regarderons avec vous.

Vous cherchez un hébergement pour votre application Laravel ? Voir l'hébergement Laravel.