Multiprocessing Python avec Queue vs ZeroMQ IPC

10

Je suis en train d'écrire une application Python en utilisant ZeroMQ et d'implémenter une variation du modèle Majordomo comme décrit dans le ZGuide .

J'ai un courtier comme intermédiaire entre un ensemble de travailleurs et de clients. Je veux effectuer une journalisation approfondie pour chaque demande qui arrive, mais je ne veux pas que le courtier perde du temps à le faire. Le courtier doit transmettre cette demande de journalisation à autre chose.

J'ai pensé à deux façons: -

  1. Créer des travailleurs uniquement pour la journalisation et utiliser le transport IPC ZeroMQ
  2. Utiliser le multitraitement avec une file d'attente

Je ne sais pas lequel est meilleur ou plus rapide d'ailleurs. La première option me permet d'utiliser les classes de base de travailleurs actuelles que j'utilise déjà pour les travailleurs normaux, mais la deuxième option semble plus rapide à implémenter.

Je voudrais des conseils ou des commentaires sur ce qui précède ou peut-être une solution différente.

Imraan
la source

Réponses:

4

J'aime l'approche consistant à utiliser des outils standard comme ce que Jonathan a proposé. Vous n'avez pas mentionné le système d'exploitation sur lequel vous travaillez, mais une autre alternative qui suit le même esprit pourrait être d'utiliser le module de journalisation standard de Python avec logging.handlers.SysLogHandleret d'envoyer les messages de journalisation au service rsyslog (disponible sur n'importe quel linux / unix, mais je pense qu'il y a aussi une option windows , mais je ne l'ai jamais utilisée).

Essentiellement, tout ce système met en œuvre la même chose que vous pensez. Votre processus local met en file d'attente un message de journal à traiter / traiter / écrire par quelqu'un d'autre. Dans ce cas, quelqu'un d'autre ( rsyslog) est un service connu et éprouvé qui a beaucoup de fonctionnalités et de flexibilité intégrées.

Un autre avantage de cette approche est que votre produit s'intégrera beaucoup mieux avec d'autres outils sysadmin qui sont construits au-dessus de syslog. Et cela ne vous obligerait même pas à écrire du code pour obtenir cette option.

DXM
la source
1
+1 pour une suggestion qui évite de réinventer la roue. Cela ne me dérangerait pas d'hériter d'un système conçu de cette façon. Il fait bien le travail, mais offre de nombreux degrés de liberté pour les modifications futures.
evadeflow
2

Vous voudrez peut-être envisager une troisième possibilité pour implémenter la journalisation à distance. Si vous utilisez le module de journalisation Python standard, vous pouvez envisager d'utiliser la logging.QueueHandlerclasse dans vos employés, clients et courtier, et la logging.QueueListenerclasse dans votre processus de journalisation à distance.

Au lieu d'utiliser le Python normal multiprocessing.Queuecomme transport entre vos processus d'application et votre processus de journalisation, implémentez votre propre Queueclasse de remplacement à l'aide de ZeroMQ avec le typage canard pour que votre classe soit un remplacement direct pour le Python standard Queue. De cette façon, votre application pourra fonctionner sans modification dans n'importe quel environnement à partir d'un seul ordinateur multicœur via des centres de données distribués.

Pour résumer, utilisez un enregistreur Python standard avec un QueueHandlerdans tous vos employés, clients et courtiers et créez un processus indépendant basé sur QueueListeneret le logging(s) gestionnaire (s) Python de votre choix pour gérer le gros du travail de journalisation.

Jonathan
la source
J'utilise Python 2.7. Je crois que la classe QueueHandler n'est disponible qu'à partir de Python 3.2.
Imraan
Il serait très facile de récupérer le code de Python 3 et de l'utiliser directement dans le cadre de votre application.
Jonathan
Je vais essayer ça et vous faire savoir si ça marche
Imraan
0

Ce sont des approches radicalement différentes, chacune avec ses propres avantages et inconvénients, que vous verrez très probablement s'étendre à un stade ultérieur du développement:

J'ai pensé à deux façons: -

  1. Créer des travailleurs uniquement pour la journalisation et utiliser le transport IPC ZeroMQ
  2. Utiliser le multitraitement avec une file d'attente

Une façon vous pouvez essayer est d'avoir une exploitation forestière de travail supplémentaire, comme dans l' approche 1. Vous pouvez laisser vos travailleurs connecter à un cluster de journalisation memcache, et les travailleurs forestiers surveille la charge actuelle des ressources et sur deceeding un paramètre de charge de ressource donnée, la ouvrier se connecte à un périphérique limité IOP (par exemple disque dur).

J'aime aussi l'approche de Jonathan avec la mise en garde que moi aussi j'utilise principalement Python 2.x, et que vous devrez probablement configurer votre propre backend de journalisation pour vraiment pousser l'enveloppe de performance.

Corrigez-moi si je me trompe, mais je pense que vous effectuez une tâche très gourmande en données, avec les IOP de stockage comme votre goulot d'étranglement.

Un moyen pratique serait encore de laisser le courtier effectuer la brokeragejournalisation - sous la forme décrite - avec tous les inconvénients d'une instance de courtier central. Par exemple, si le courtier est si sollicité qu'il n'a jamais de marge de manœuvre pour réécrire les journaux memcached dans le stockage, vous devrez adopter une autre approche.

Vous pouvez finalement vous retrouver avec un modèle sans courtier. C'est avec les travailleurs qui gèrent leur travail entre eux. Dans un exemple simple, grâce à un algorithme à tour de rôle distribué .

Lorenz Lo Sauer
la source