Quel est le meilleur mécanisme IPC pour les données de taille moyenne en Perl? [fermé]

StackOverflow https://stackoverflow.com/questions/431623

  •  08-07-2019
  •  | 
  •  

Question

Je travaille à la conception d'une application multiniveau en Perl et je m'interroge sur les avantages et les inconvénients des divers mécanismes IPC à ma disposition. Je cherche à traiter des données de taille moyenne, généralement quelques dizaines de kilo-octets mais jusqu'à quelques mégaoctets, et la charge est assez légère, au plus quelques centaines de demandes à la minute.

Mes principales préoccupations sont la maintenabilité et les performances (dans cet ordre). Je ne pense pas que j'aurai besoin de passer à plus d'un serveur ou port hors de notre plate-forme principale (RHEL), mais je suppose que c'est quelque chose à considérer.

Je peux penser aux options suivantes:

  • Fichiers temporaires - Simplistes, probablement la pire option en termes de rapidité et de besoins de stockage
  • sockets de domaine UNIX: non portables, non évolutifs
  • Internet Sockets - Portable, évolutif
  • Tuyaux - portables, non évolutifs (?)

Etant donné que l'évolutivité et la portabilité ne sont pas mes préoccupations principales, j'ai besoin d'en savoir plus. Quel est le meilleur choix et pourquoi? Veuillez commenter si vous avez besoin d'informations supplémentaires.

MODIFIER: je vais essayer de vous donner plus de détails en réponse à Les questions de ysth (avertissement, un mur de texte suit) :

  • Les lecteurs / rédacteurs sont-ils dans une relation personnalisée ou sont-ils plus compliqués?
  • Que voulez-vous qu'il arrive au rédacteur si le lecteur n'est plus là ou n'est plus occupé?
  • Et vice versa?
  • Quelles autres informations avez-vous sur l'utilisation souhaitée?

À ce stade, j’envisage une approche à trois niveaux, mais je ne sais pas combien de processus il y aura pour chaque niveau. Je pense que je devrais avoir plus de processus à gauche et moins à droite, mais je devrais peut-être avoir le même nombre partout:

 .---------.          .----------.        .-------.
 | Request |  ----->  | Business | -----> | Data  |
 | Manager |  <-----  |  Logic   | <----- | Layer |
 `---------'          `----------'        `-------'

Ces noms sont toujours génériques et ne feront probablement pas partie de la mise en oeuvre sous ces formes.

Le gestionnaire de demandes est chargé d'écouter les demandes provenant d'interfaces différentes, par exemple les demandes Web et l'interface de ligne de commande (lorsque le temps de réponse est important) et les e-mails (lorsque le temps de réponse est moins important). Il effectue la journalisation et gère les réponses aux requêtes (qui sont rendues dans un format adapté au type de requête).

Il envoie des données sur la requête à la logique applicative , qui enregistre les données, les autorise en fonction des règles commerciales, etc.

.

La logique métier (si nécessaire) demande ensuite des données à la couche de données , qui peut communiquer (le plus souvent) avec la base de données MySQL interne ou avec une autre source de données indépendante de la volonté de notre équipe ( par exemple, les serveurs LDAP principaux de notre organisation, ou notre base de données d’informations sur les employés DB2, etc.). Il s’agit principalement d’une enveloppe qui formate les données de manière uniforme de manière à ce qu’elles puissent être traitées plus facilement dans la logique métier.

Les informations sont ensuite renvoyées au gestionnaire de demandes pour être présentées.

Si, lorsque les données circulent à droite, le lecteur est occupé, pour les demandes interactives, je souhaite simplement attendre une période de temps appropriée et renvoyer une erreur de dépassement de délai si je ne reçois pas un tel accès. (par exemple, "Réessayer plus tard"). Pour les demandes non interactives (par exemple, courrier électronique), le système d'interrogation peut simplement quitter et réessayer lors de la prochaine invocation (qui sera probablement une fois toutes les 1 à 3 minutes).

Lorsque les données circulent dans le sens opposé, il ne devrait y avoir aucune attente. Si l’un des processus est mort en essayant de revenir à gauche, tout ce que je peux faire, c’est d’enregistrer et de sortir.

Quoi qu’il en soit, c’était plutôt bavard, et comme je suis encore au stade de la conception, j’ai probablement encore des idées confuses. Une partie de ce que j'ai mentionné est probablement liée à la question de quel système IPC utiliser . Je suis ouvert à d’autres suggestions sur la conception, mais j’essayais de limiter la portée de la question (par exemple, je devrais peut-être envisager de réduire à deux niveaux, ce qui est beaucoup plus simple pour IPC). Quelles sont vos pensées?

Était-ce utile?

La solution

Les fichiers temporaires (et les éléments associés, comme une région de mémoire partagée), constituent probablement un mauvais pari. Si vous souhaitez exécuter votre serveur sur une machine et vos clients sur une autre, vous devrez réécrire votre application. Si vous choisissez l’une des autres options, la sémantique au moins est essentiellement la même, si vous avez besoin de passer de l’une à l’autre.

Mon seul véritable conseil, cependant, est de ne pas écrire cela vous-même. Sur le serveur, vous devriez utiliser POE (ou Coro, etc.), plutôt que de faire select sur le socket vous-même. De plus, si votre interface doit être RPC-ish, utilisez quelque chose comme JSON-RPC-Common / du CPAN.

Enfin, il y a IPC :: PubSub, qui pourrait fonctionner pour vous.

Autres conseils

Si vous n’êtes pas sûr de vos exigences exactes pour le moment, essayez de penser à une interface simple vers laquelle vous pouvez coder, qui n’importe quelle implémentation IPC (fichiers temporaires, TCP / IP ou autres). quoi que ce soit) a besoin de soutien. Vous pouvez ensuite choisir une variante IPC particulière (je commencerais par le plus facile et / ou le plus facile à déboguer - probablement des fichiers temporaires) et mettre en œuvre l'interface à l'aide de cela. Si cela s'avère trop lent, implémentez l'interface en utilisant, par exemple, TCP / IP. En réalité, implémenter l’interface ne demande pas beaucoup de travail, vous ne ferez que renvoyer les appels vers une bibliothèque existante.

Le fait est que vous devez effectuer une tâche de haut niveau ("transmettre des données du programme A au programme B"), qui est plus ou moins indépendante des détails de son exécution. En établissant une interface et en la codant, vous isolez le programme principal des modifications dans le cas où vous auriez besoin de modifier l'implémentation.

Notez qu'il n'est pas nécessaire d'utiliser un mécanisme de langage Perl très puissant pour capitaliser sur l'idée d'une interface. Vous pourriez simplement avoir par exemple 3 packages différents (pour les fichiers temporaires, TCP / IP, sockets de domaine Unix), chacun exportant le même ensemble de méthodes. Choisir l'implémentation que vous voulez utiliser dans votre programme principal revient à choisir le module à utiliser .

Les fichiers temporaires ont d’autres problèmes que cela. Je pense que les chaussettes Internet sont vraiment le meilleur choix. Ils sont bien documentés et, comme vous le dites, évolutifs et portables. Même si ce n’est pas une exigence fondamentale, vous l’obtenez presque gratuitement. Les sockets sont assez faciles à gérer, encore une fois, la documentation est abondante. Vous pouvez créer votre mécanisme de partage de données et votre protocole dans une bibliothèque sans jamais avoir à le revoir!

Les sockets de domaine UNIX sont portables sur plusieurs ordinateurs. Ce n'est pas moins portable que les pipes. C'est aussi plus efficace que les sockets IP.

Quoi qu'il en soit, vous avez manqué quelques options, la mémoire partagée par exemple. Certains ajouteraient des bases de données à cette liste, mais je dirais que c'est une solution plutôt lourde.

Les files d'attente de messages seraient également une possibilité, bien que vous deviez changer une option du noyau pour qu'elle puisse gérer de tels messages volumineux. Sinon, ils ont une interface idéale pour beaucoup de choses, et à mon humble avis ils sont grandement sous-utilisés.

Je suis généralement d’accord pour dire qu’utiliser une solution existante est préférable à la construction de vos propres moyens. Je ne connais pas les détails de votre problème, mais je suggérerais que vous vérifiiez la section IPC du réseau CPAN

Il y a tellement d'options différentes parce que la plupart d'entre elles sont meilleures pour un cas particulier, mais vous n'avez pas vraiment fourni d'informations permettant d'identifier votre cas.

Les lecteurs / rédacteurs sont-ils dans une relation un-à-un ou plus complexe? Que voulez-vous qu'il arrive à l'écrivain si le lecteur n'est plus là ou n'est plus occupé? Et vice versa? Quelles autres informations avez-vous sur votre utilisation souhaitée?

Pour "interactif" demandes (maintenant la connexion ouverte en attendant une réponse (asynchrone ou non): HTTP + JSON. JSON :: XS est incroyablement rapide. Tout le monde peut parler HTTP et il est facile d'équilibrer la charge, de ...

Pour les demandes en file d'attente ("merci de le faire, merci!"): Beanstalkd et Beanstalk :: Client . Sérialiser les requêtes dans la file d'attente beanstalk avec JSON.

Thrift peut également être intéressant en fonction de votre application.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top