web-dev-qa-db-fra.com

Laravel Artisan CLI arrêtez en toute sécurité les travailleurs de file d'attente de démon

Afin de traiter un grand nombre de travaux, j'exécute un nombre variable d'ouvriers de file d'attente en fonction de la quantité de travail à effectuer. Je ne veux pas diriger plus de travailleurs que nécessaire pour achever le travail qui doit être fait dans une période que nous jugeons appropriée.

Pour le moment, je lance 5 ouvriers de file d'attente de démons à des fins de test, mais en production, ce nombre pourrait être compris entre 25 et 100 ouvriers, peut-être plus. Je comprends que lors du déploiement, je dois arrêter les travailleurs de file d'attente en plaçant d'abord le framework en mode maintenance en utilisant php artisan down, parce que le --daemon flag fait que le framework ne se charge qu'au démarrage du travailleur, donc le nouveau code ne prendrait effet pendant le déploiement qu'au redémarrage du travailleur.

Si j'avais besoin d'arrêter les travailleurs pour une raison quelconque, je pouvais mettre l'application en mode maintenance en utilisant php artisan down ce qui entraînera la mort des travailleurs une fois qu'ils auront terminé le traitement de leur emploi actuel (s'ils en ont un). Cependant, il peut y avoir des moments où je veux tuer les travailleurs sans mettre toute l'application en mode maintenance.

Existe-t-il un moyen sûr d'arrêter les travailleurs de manière à ce qu'ils continuent à traiter leur travail en cours puis meurent sans placer l'ensemble de l'application en mode maintenance?

Essentiellement, j'ai besoin d'un php artisan queue:stop, qui se comporte comme php artisan queue:restart, mais ne redémarre pas le travailleur une fois le travail terminé.

J'espérais qu'il y aurait un semblable php artisan queue:stop commande qui ferait cela, mais cela ne semble pas être le cas.

En utilisant ps aux | grep php Je peux obtenir les identifiants de processus pour les travailleurs, et je pourrais tuer les processus de cette façon, mais je ne veux pas tuer le processus en cours de travail.

Merci.

17
Vigs

Nous avons implémenté quelque chose comme ça dans notre application - mais ce n'était pas quelque chose qui était intégré à Laravel lui-même. Vous devrez éditer ce fichier , par en ajoutant une autre condition au bloc if pour qu'il appelle la fonction stop. Vous pouvez le faire en définissant une variable statique dans la classe Worker qui est modifiée chaque fois que vous exécutez une commande personnalisée que vous devrez faire (c'est-à-dire php artisan queue:pause) ou en vérifiant une valeur atomique quelque part (c'est-à-dire la placer dans un cache comme redis, memcached, APC ou même MySQL, bien que cela signifierait que vous aurez une requête MySQL pour chaque cycle de cette boucle while) que vous définissez en utilisant la même commande personnalisée.

4
Nikko

Lors de l'utilisation de l'indicateur --daemon, Les travailleurs ne doivent pas quitter lorsque la file d'attente est vide.

Je pense que ce que vous recherchez est dans la documentation des files d'attente.

La commande php artisan queue:restart Invite les travailleurs à redémarrer une fois leur travail en cours terminé.

3
Deinumite

mon Laravel est 5.6. vous pouvez (tuer votre pid) ne vous inquiétez pas perdre votre travail il suffit de charger pcntl (extension) Laravel peut écouter le signal et sortie sûre

afficher la source de la pièce ci-dessous (dans ./vendor/laravel/framework/src/Illuminate/Queue/Worker.php):

protected function listenForSignals()
{
    pcntl_async_signals(true);

    pcntl_signal(SIGTERM, function () {
        $this->shouldQuit = true;
    });

    pcntl_signal(SIGUSR2, function () {
        $this->paused = true;
    });

    pcntl_signal(SIGCONT, function () {
        $this->paused = false;
    });
}

Et mon test ci-dessous:

for($i=0; $i<100; $i++){
        pcntl_async_signals(true);

    pcntl_signal(SIGTERM, function () {
        echo 'SIGTERM';
    });

    pcntl_signal(SIGUSR2, function () {
        echo 'SIGUSR2';
    });

    pcntl_signal(SIGCONT, function () {
        echo 'SIGCONT';
    });
echo $i; 
sleep(1);
 }

tu peux essayer de le tuer

0
Zuo Zou

Depuis Laravel 5.5 il y a un événement appelé Illuminate\Queue\Events\Looping Qui est déclenché à partir de l'appel daemonShouldRun() à l'intérieur de la boucle de travail principale de Illuminate\Queue\Worker. Donc, si vous configurez un écouteur pour faire votre devrait traiter les travaux vérifier, et renvoyer false, alors le ou les travailleurs de file d'attente s'arrêteront jusqu'à ce que la vérification soit vraie. Il y a un sommeil entre la prochaine fois qu'il le vérifie et peut être personnalisé en passant --sleep <seconds> à la commande queue: work.

J'utilise actuellement cette technique pendant les déploiements pour arrêter les travailleurs qui s'exécutent à l'intérieur des conteneurs Docker, car il n'est pas si facile d'exécuter le queue:restart Suggéré sans les pirater.

0
alexkb