Exécution des jobs Laravel sur un serveur de production
Il existe plusieurs méthodes pour pouvoir exécuter un job Laravel sur un serveur de production, tout dépend de ce qu’autorise votre hébergeur.
Si la meilleure solution est l’utilisation de Supervisor, certains hébergeurs, dont le mien en l’occurrence ne donnent pas la possibilité d’installer et/ou d’utiliser ce dernier, il est donc nécessaire d’utiliser une autre méthode.
Pour exécuter les jobs lorsqu’on développe en local, dans une console, il suffit de se placer dans le répertoire de l’application et d’exécuter la commande :
php artisan queue:work
Tant que votre console reste ouverte, les jobs sont exécutés, en production, on ne peut pas laisser une console ouverte, il est donc nécessaire de trouver un moyen qui permette de reproduire cette méthode au mieux.
La méthode la plus simple dans le cas où Supervisor ne peut être utilisé est de passer par une tâche CRON, cela permet de lancer le script qui restera actif jusqu’à un redémarrage du serveur, qui, en général, arrive très peu souvent.
Je ne m’étendrais pas sur la création des tâches CRON, leur récurrence, etc …, ce n’est pas l’objet de ce billet, je vais juste fournir la ligne de commande à exécuter, qui pourra sensiblement varier en fonction de votre hébergeur, mais dans les grandes lignes, ce sera identique :
/usr/local/bin/php [répertoire application]/artisan queue:work >/dev/null 2>&1
Pour mon cas, la ligne ci-dessus a bien lancé le process, j’ai pu vérifier avec telescope que mes jobs s’exécutaient comme il faut, donc mission remplie, oui mais …
… Il y a 2 limites à l’utilisation de cette tâche CRON :
- Cette dernière sera relancée à chaque échéance, et ça risque de poser problème lorsque la tâche sera lancée, encore et encore.
- Si le serveur s’arrête et que la tâche est supprimée pour éviter le problème ci-dessus, elle ne sera évidemment pas relancée automatiquement et les jobs ne seront donc plus exécutés.
Il existe une solution qui permette de remédier à ces deux problèmes et d’avoir une tâche CRON qui s’exécute à chaque échéance uniquement si elle n’est pas déjà en cours, et donc comme elle restera active, si un démarrage serveur se produisait, elle serait relancée à la prochaine échéance, ce qui laisserait le serveur sans jobs le temps d’une échéance.
Pour cette solution, il faut utiliser flock, dans notre cas, ce sera donc :
flock -n [répertoire hébergement]/.cron.lock [répertoire application]/artisan queue:work >/dev/null 2>&1
Avec cette méthode, lors du premier lancement le fichier .cron.lock est créé et bloqué par le process, si une nouvelle tâche s’exécute et qu’elle n’a pas accès à ce fichier, elle s’arrête, donc pas de surcharge, si par contre elle y a accès, elle s’exécute et bloque elle même le fichier, etc …
Pour ma part j’ai donc utilisé cette tâche avec un délai de 5 minutes, ce qui fait que si le serveur redémarre, la tâche sera inactive pendant 5 minutes au maximum, ce qui est largement acceptable.
Bien entendu cette méthode ne s’applique pas à Laravel uniquement, mais au système des tâches CRON, elle est donc portable.