12
votes

Échelle Dynt Spécifique Heroku Dynos?

Je construis une application Web qui fournit une fonctionnalité de base permettant aux utilisateurs de télécharger de grandes images et de les faire traiter. Le traitement prend environ 3 minutes à compléter et je pensais que Heroku serait une plate-forme idéale pour pouvoir exécuter ces travaux de traitement à la demande et de manière très évolutive. La tâche de traitement elle-même est assez chère de calcul et doit exécuter un dyno PX haut de gamme. Je souhaite maximiser la parallélisation et minimiser (éliminer efficacement) le temps qu'un travail dépense attendre dans une file d'attente. En d'autres termes, je veux avoir n px dynos pour n jobs.

Heureusement, je peux accomplir cela assez facilement avec l'API de Heroku (ou éventuellement un service comme le feu de hirefire). Chaque fois qu'une nouvelle demande de traitement arrive, je peux simplement incrémenter le nombre de travailleurs et le nouveau travailleur saisira le travail de la file d'attente et commencera à traiter immédiatement.

Cependant, pendant que la mise à l'échelle est indolore, la mise à l'échelle est que le problème commence. L'API Heroku est frustrante. Je ne peux que définir le numéro des travailleurs en cours d'exécution, qui ne tuent pas spécifiquement ceux de ralenti. Cela signifie que si j'ai 20 travailleurs chacun de traitement, et on complète sa tâche, je ne peux pas augmenter en toute sécurité le nombre de travailleurs en toute sécurité à 19, car Heroku tuera un arbitraire Dyno, que ce soit en fait Au milieu d'un emploi! Quitter tous les travailleurs en cours d'exécution jusqu'à ce que tous les emplois complètes soit simplement hors de la question, car le coût serait astronomique. Imaginez 100 travailleurs créés lors d'une pointe continuent de rester inédecinciellement comme quelques nouveaux emplois dans toute la journée!

J'ai fouillé le web et la meilleure "solution" que les gens suggèrent que votre processus ouvrier traite gracieusement la résiliation. Eh bien, c'est parfaitement amené si votre travailleur fait juste de la masse-courrier électronique, mais mes travailleurs font des analyses très élaborées sur des images, et comme je l'ai mentionné ci-dessus, prenez environ 3 minutes à compléter.

Dans un monde idéal, je pourrais tuer un Dyno de travailleur spécifique à la fin de sa tâche. Cela ferait la mise à l'échelle aussi facile que de l'accrocher.

En fait, je suis arrivé à ce monde idéal en passant de Dynos travailleurs à des dynos ponctuels (qui se terminent lors de la résiliation du processus, c'est-à-dire que vous arrêtez de payer pour le dyno après son «programme racine»). Cependant, Heroku définit une limite difficile de 5 dynos uniques pouvant être exécutés simultanément. Ce que je peux comprendre, comme j'étais certainement dans un sens abusant des dynos uniques ... mais c'est assez frustrant néanmoins.

Y a-t-il un moyen de mieux accumuler mes travailleurs? Je préférerais ne pas avoir à ré-ingénieur radicalement mon algorithme de traitement ... en se fractionnant dans quelques morceaux qui gèrent en 30-40 secondes, par opposition à un étirement de 3 minutes (de cette façon tuant accidentellement un travailleur de course ne serait pas catastrophique). Cette approche compliquerait considérablement mon code de traitement et présenterait plusieurs nouveaux points d'échec. Cependant, si c'est ma seule option, je devrai le faire.

Des idées ou des pensées sont appréciées!


3 commentaires

AFAIK, vous pouvez redémarrer des dynos spécifiques, par exemple discussion.heroku.com/t/ STOP-A-SPÉCIFIQUE-DYNO / 424 . Changer la formation juste après peut-être faire le tour? Vous devriez connaître le nom d'un travailleur qui a fini de courir


@unohoo qui sonne comme ça pourrait être prometteur! Je vais lui donner un coup et rapporterai.


@Colemans Avez-vous déjà trouvé une chose ici? Essayer d'atteindre fondamentalement la même chose.


4 Réponses :


0
votes

Je sais que vous avez mentionné une résiliation gracieuse, mais je suppose que vous avez eu des résiliations gracieuses comme lorsqu'un ouvrier est tué en utilisant l'API pour définir le nombre de travailleurs. Pourquoi ne pas simplement ajouter dans le cadre de la logique de travailleur pour se tuer lorsque son travail est terminé?


1 commentaires

Bien sûr, vous pouvez avoir un travailleur se tuer, et cela fonctionne. Cependant, Heroku le redémarrera immédiatement.



2
votes

Planifiez une tâche de nettoyage

Résumé: File d'attente Une tâche à exécuter à la priorité la plus basse. Une fois que toutes les autres tâches terminées, la tâche de nettoyage fonctionnera. P>

Détails h3>

[Note: Une fois que j'ai écrit cette réponse, je me rendrai compte que cela ne répond pas à la nécessité de faire tourner la nécessité de tourner un spécifique em> travailleur dyno. Mais vous devriez être capable d'exploiter la technique clé illustrée ici: la file d'attente une tâche de DJ prioritaire faible (ER) à nettoyer lorsque tout le reste a été traité.] P>

J'ai eu de la chance d'utiliser de Heroku [Plate-forme-API] [1] CODE> GEM pour faire tourner les travailleurs de travail différés à la demande et les faire tourner lorsqu'ils terminent. Pour simplifier les choses, j'ai créé un fichier heroku_control.rb comme suit. p>

Mon application n'ayait besoin que d'un travailleur; Je reconnais que vos besoins sont significativement plus impliqués, mais toute application peut exploiter ce truc: la file d'attente une tâche à faible priorité pour éteindre le (s) Dyno (s) travailleur) après que toutes les autres tâches différées ont été traitées. P>

LOWEST_PRIORITY = 100

def start_long_process
  queue_lengthy_process
  queue_cleanup_task        # clean up when everything else is processed
  HerokuControl::worker_up  # assure there is a worker dyno running
end

def queue_lengthy_process
  # do long job here...
end
handle_asynchronously :queue_lengthy_process, :priority => 1

# This gets processed when Delayed::Job has nothing else
# left in its queue.
def queue_cleanup_task
  HerokuControl::worker_down # shut down all worker dynos
end
handle_asynchronously :queue_cleanup_task, :priority => LOWEST_PRIORITY


1 commentaires

C'est exactement ce dont j'avais besoin quand j'ai trouvé ce post, merci!



3
votes

C'est ce que le soutien de Heroku a répondu à ce sujet:

J'ai bien peur que ce n'était pas possible pour le moment. Lors de la mise à l'échelle de votre travailleurs, nous allons arrêter celui avec le plus grand nombre, alors nous ne le faisons pas avoir à changer le nom public de ces dynos et vous n'obtenez pas Numéroter des trous.

J'ai trouvé Ce commentaire intéressant dans ce contexte, bien que ce ne soit pas vraiment résoudre ce problème.


0 commentaires

0
votes

Il est maintenant possible d'arrêter un dyno spécifique à l'aide de la commande Heroku PS: stop .

E.g. Si votre sortie Heroku PS contient: xxx

Vous pouvez exécuter heroku ps: arrêter web.2 pour tuer la seconde Dyno dans la liste.

Cela ne fera pas exactement ce que vous voulez, car Heroku démarrera immédiatement un nouveau Dyno pour remplacer celui qui a été arrêté. Mais peut-être que cela vous est toujours utile (ou d'autres personnes lisant cette question).


0 commentaires