43 votes

Arrêter gentiment les travailleurs de l'engrenage

J'ai un certain nombre de travailleurs Gearman qui tournent en permanence, sauvegardant des choses comme les enregistrements des pages vues par les utilisateurs, etc. De temps en temps, je mets à jour le code PHP qui est utilisé par les travailleurs Gearman. Pour que les travailleurs passent au nouveau code, je tue et redémarre les processus PHP pour les travailleurs.

Quelle est la meilleure façon de procéder ? Je suppose que je perds parfois des données (même si elles ne sont pas très importantes) lorsque je tue un de ces processus de travail.

Edit : J'ai trouvé une réponse qui fonctionne pour moi, et je l'ai postée ci-dessous.

12voto

bnmrrs Points 111

Solution 1


Généralement, je lance mes travailleurs avec l'utilitaire unix daemon avec le drapeau -r et je les laisse expirer après un travail. Votre script se terminera gracieusement après chaque itération et le daemon redémarrera automatiquement.

Vos travailleurs seront épuisés pour un travail, mais ce n'est peut-être pas aussi grave pour vous que la perte de données.

Cette solution a également l'avantage de libérer de la mémoire. Vous pouvez rencontrer des problèmes de mémoire si vous faites de gros travaux car PHP avant 5.3 a une GC terrible.

Solution 2


Vous pourriez également ajouter une fonction de sortie à tous vos travailleurs qui quitte le script. Lorsque vous souhaitez redémarrer, il vous suffit de donner à gearman des appels à quitter avec une priorité élevée.

8voto

Orwellophile Points 141
function AutoRestart() {
   static $startTime = time();

   if (filemtime(__FILE__) > $startTime) {
      exit();
   }
}

AutoRestart();

7voto

Karptonite Points 576

J'ai posté cette question et je pense maintenant avoir trouvé une bonne réponse.

Si vous regardez dans le code de Net_Gearman_Worker, vous verrez que dans la boucle de travail, la fonction stopWork est contrôlée, et si elle renvoie vrai, elle quitte la fonction.

J'ai fait ce qui suit :
À l'aide de memcache, j'ai créé une valeur en cache, gearman_restarttime, et j'utilise un script distinct pour définir cette valeur à l'horodatage actuel chaque fois que je mets à jour le site. (J'ai utilisé Memcache, mais cela pourrait être stocké n'importe où - une base de données, un fichier, ou n'importe quoi).

J'ai étendu la classe Worker pour qu'elle soit, essentiellement, Net_Gearman_Worker_Foo, et j'ai fait en sorte que tous mes workers l'instancient. Dans la classe Foo, j'ai surchargé la fonction stopWork pour faire ce qui suit : d'abord, elle vérifie gearman_restarttime ; la première fois, elle enregistre la valeur dans une variable globale. Ensuite, à chaque passage, elle compare la valeur mise en cache à la variable globale. Si elle a changé, le stopWork retourne vrai, et le travailleur quitte. Un cron vérifie toutes les minutes si chaque worker est toujours en cours d'exécution, et redémarre tout worker qui s'est arrêté.

Il peut être intéressant de mettre une minuterie dans stopWork également, et de ne vérifier le cache qu'une fois toutes les x minutes. Dans notre cas, Memcache est suffisamment rapide pour que la vérification de la valeur à chaque fois ne semble pas être un problème, mais si vous utilisez un autre système pour stocker l'horodatage actuel, une vérification moins fréquente serait préférable.

1voto

Yarek T Points 3105

Hmm, Vous pourriez implémenter un code dans les travailleurs pour vérifier de temps en temps si le code source a été modifié, si oui, ils se tuent simplement quand ils le jugent bon. C'est-à-dire, vérifier pendant qu'ils sont au milieu du travail, et si le travail est très grand.

L'autre solution serait d'implémenter une sorte d'interruption, peut-être via le réseau, pour dire d'arrêter dès que vous en avez l'occasion et de redémarrer.

La dernière solution consiste à aider à modifier la source de Gearman pour inclure cette fonctionnalité.

1voto

Alister Bulman Points 12913

http://phpscaling.com/2009/06/23/doing-the-work-elsewhere-sidebar-running-the-worker/

Comme le démontre l'article ci-dessus, j'ai exécuté un worker à l'intérieur d'un shell BASH script, sortant occasionnellement entre les tâches pour nettoyer (ou recharger le worker-script) - ou si une tâche donnée lui est donnée, il peut sortir avec un code de sortie spécifique et s'arrêter.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X