En tant qu'utilisateur relativement nouveau de Laravel et Elastic Beanstalk, je me suis vite retrouvé dans le besoin de planifier des opérations, comme la plupart d'entre nous.
Dans le passé, j'avais toujours utilisé une planification crontab simple pour cela. Alors maintenant, je me tenais devant une liste de questions:
Trouver les réponses individuelles à ces questions n'a pas été si difficile. Les combiner et les faire fonctionner a cependant été un peu délicat, c'est pourquoi j'ai décidé de partager la solution ici pour d'autres qui ont du mal à faire fonctionner correctement.
Voir la configuration de travail .ebextentions
À la fin de la réponse.
Les réponses à cette question sont bien sûr les plus évidentes et si vous êtes le moins du monde pour Laravel vous connaissez sûrement la réponse: Scheduling !
Je ne vous ennuierai pas d'expliquer la chose brillante qui est Laravel Scheduling puisque vous pouvez lire à ce sujet dans la documentation vous-même.
Mais la chose clé que nous devons emporter avec nous est que Laravel La planification utilise crontab pour exécuter, comme décrit dans la documentation:
* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
Ce qui nous amène au suivant, et un peu plus délicat, question ...
À première vue, la réponse à cette question peut sembler assez simple. J'ai trouvé cela dans l'AWS Knownledge Center: Comment créer un travail cron sur des instances EC2 dans un environnement Elastic Beanstalk?
Ici, ils décrivent comment configurer un travail cron sur votre machine Elastic Beanstalk EC2 à l'aide de .ebextentions. En bref, il crée un nouveau fichier dans le répertoire /etc/cron.d/
Dans lequel nous mettons notre tâche cron souhaitée.
Les fichiers de ce répertoire sont ensuite traités par crontab en tant qu'utilisateur root
. Il y a certains des pièges dans lesquels je suis entré, comme je l'ai commenté ci-dessous:
files:
# The name of the file should not contain any dot (.) or dash (-), this can
# cause the script not to run. Underscore (_) is OK.
"/etc/cron.d/mycron":
# This permissions is important so that root user can run the script.
mode: "000644"
# As the file is run by the root user it needs to be the owner of the file.
owner: root
# For consistency it's a good idea to have root as the group aswell.
group: root
# NOTE: We need to explicitly tell the cron job to be run as the root user!
content: |
* * * * * root /usr/local/bin/myscript.sh
# There need to be a new line after the actual cron job in the file.
Une fois que nous avons évité tous ces pièges, il est temps de mettre dans notre Laravel Planification de la tâche cron d'en haut. Cela devrait ressembler à ceci:
files:
"/etc/cron.d/schedule_run":
mode: "000644"
owner: root
group: root
content: |
* * * * * root php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
Cela ne fonctionnera pas vraiment dans la plupart des cas . C'est parce que le Laravel Scheduler n'aura pas accès à vos variables ENV et ne doit visiblement pas les paramètres de votre base de données.
J'ai trouvé la réponse à cela ici: Comment obtenir Laravel Planification des tâches en travaillant sur AWS Elastic Beanstalk Cron
Donc un grand merci à George Bönnisch; Je vous salue monsieur d'avoir partagé ceci!
Donc, avec cette dernière pièce du puzzle, j'ai finalement réussi à faire fonctionner correctement l'installation:
Structure du fichier:
[Project root]
|-- .ebextensions
| |-- cronjob.config
cronjob.config:
files:
"/etc/cron.d/schedule_run":
mode: "000644"
owner: root
group: root
content: |
* * * * * root . /opt/elasticbeanstalk/support/envvars && /usr/bin/php /var/www/html/artisan schedule:run 1>> /dev/null 2>&1
commands:
remove_old_cron:
command: "rm -f /etc/cron.d/*.bak"
Étant donné que l'une des principales fonctionnalités d'Elastic Beanstalk est qu'il peut mettre à l'échelle automatiquement et ajouter plus de serveurs en cas de besoin, vous voudrez peut-être jeter un œil à la nouvelle fonctionnalité dans Laravel Scheduling: Running Tâches sur un serveur .
Dans de nombreux cas, vous ne voulez pas que votre tâche cron soit exécutée sur plusieurs serveurs. Par exemple, si vous avez une commande planifiée pour l'envoi d'e-mails, vous ne voulez pas que ceux-ci soient envoyés plusieurs fois.
REMARQUE: Cela nécessite que vous utilisiez memcached ou redis comme moteur de cache, comme indiqué dans la documentation. Si vous ne le faites pas, jetez un œil au service AWS Elasticache .
REMARQUE 2: Lorsque vous utilisez onOneServer()
, vous devez donner un nom à la tâche planifiée à l'aide de la méthode name()
(avant appel de onOneServer()
). Ainsi:
$schedule->command('my:task')
->name('my:task')
->daily()
->onOneServer();
Une approche plus simple consiste à utiliser la nouvelle fonctionnalité Tâches périodiques. En utilisant le .ebextensions
pour les tâches cron peut conduire plusieurs machines à exécuter la même tâche ou d'autres conditions de concurrence avec mise à l'échelle automatique.
Tâches définies dans cron.yaml
sont chargés uniquement par l'environnement de travail et sont garantis pour ne fonctionner que par une seule machine à la fois (le leader). Il a un mécanisme de synchronisation agréable pour s'assurer qu'il n'y a pas de duplication. De la documentation:
Elastic Beanstalk utilise l'élection de leader pour déterminer quelle instance de votre environnement de travail met en file d'attente la tâche périodique. Chaque instance tente de devenir leader en écrivant dans une table Amazon DynamoDB. La première instance qui réussit est le leader et doit continuer à écrire dans la table pour conserver le statut de leader. Si le leader est mis hors service, une autre instance prend rapidement sa place.
Endroit cron.yaml
à la racine du projet:
version: 1
cron:
- name: "schedule"
url: "/worker/schedule"
schedule: "* * * * *"
Une chose à prendre en considération est que dans Beanstalk, les tâches périodiques sont conçues pour effectuer une requête HTTP POST vers une URL de votre application qui déclenche à son tour le travail que vous souhaitez exécuter. Ceci est similaire à comment il gère également les files d'attente avec SQS.
Pour Laravel spécifiquement, vous pouvez créer les routes et les contrôleurs pour gérer chaque tâche planifiée. Mais une meilleure approche consiste à utiliser le planificateur de Laravel et à avoir une seule route que vous appelez toutes les minutes.
Ce package créera ces itinéraires automatiquement pour vous https://github.com/dusterio/laravel-aws-worker
Si vous rencontrez des problèmes avec les autorisations DynamoDB create Leader Table lors du déclenchement d'un déploiement à partir de CodePipeline, c'est parce que le rôle de service CodePileline a besoin de dynamodb:CreateTable
. Pour les instructions, vérifiez ces Question StackOverflow
Documents officiels des tâches périodiques d'Elastic Beanstalk