IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Communiquer entre process qui ne se connaissent pas


Sujet :

Python

  1. #1
    Membre confirmé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Points : 455
    Points
    455
    Billets dans le blog
    1
    Par défaut Communiquer entre process qui ne se connaissent pas
    Bonjour,

    je me tords les neurones sur un script qui doit communiquer avec d'autres instances de lui-même mais qui en ignore l'existence et le nombre.

    Je m'explique :

    Mon script est lancé depuis différents process du système (je n'ai aucun contrôle là dessus, mais en gros, ils sont tous lancés en même temps (dans la même demie seconde)).
    Chaque instance reçoit un paramètre (sur sa ligne de commande).
    Je voudrais :
    1 - trouver un critère qui me permette de distinguer une des instances pour en faire le maître (les autres devenant les esclaves)
    2 - que chaque esclave envoie son paramètre au maître.

    J'ai déjà créé une solution qui marchotte...
    Chaque instance va essayer d'ouvrir un fichier en écriture.
    Quand un script échoue à ouvrir le fichier, il fait un sleep et réessaye plus tard.
    Quand un script arrive à ouvrir le fichier, il regarde sa taille : si elle est nulle, c'est qu'il est le premier => il est le maître.
    Si la taille n'est pas nulle, c'est un esclave : il écrit son paramètre à la fin du fichier, le referme et se termine.
    Pendant ce temps, le maître, scrute la taille du fichier.
    Quand elle reste stable pendant (disons) 300ms, il considère que tous les esclaves ont fini.
    Enfin, il ouvre à nouveau le fichier pour en extraire tous les paramètres.

    J'ai essayé d'autres variantes en utilisant les mmap mais dans tous les cas, ma solution n'est pas satisfaisante.
    Dès que trop d'instances sont en concurrence ou que le CPU ou le disque dur sont un peu débordés, ça échoue :
    --> le maître "rate" certains esclaves et leur paramètre est perdu
    --> il a plusieurs instances qui se croient maître
    En gros, à partir d'une vingtaine d'instance, ça commence à débloquer.
    On est loin des 100 ou 200 que j'aimerais pouvoir lancer.

    Si je viens vous embêter avec ça, c'est parce que je suis sûr de ne pas être le premier à avoir ce genre de besoin.
    Il existe sûrement des solutions propres et de bonnes pratiques en la matière.
    Mais peut-on le faire en python et de manière portable (Linux/Windows) ?

    Merci d'avance.
    Captain'Flam
    anciennement Sopsag, aka Hadrien
    Win seven x64 & Win 10 / Visual 2017 / Python 2.7 / Eclipse

  2. #2
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonjour,

    Je te propose dans un premier temps une solution simple sur la base de xmlrpclib/SimpleXMLRPCServer(xmlrpc.server attention au passage Python 2 / 3) (ou socket mais c'est légèrement plus compliqué).
    Chaque client ayant un thread client et tente de lancer un thread serveur sur une plage de port prédéfinie (localhost).
    Si le port est occupé le client tente de se 'présenter'. C'est bon: Le process sur le port en question est le maitre. C'est pas bon on continu.

    @+
    Merci d'utiliser le forum pour les questions techniques.

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    103
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 103
    Points : 135
    Points
    135
    Par défaut
    Utiliser un fichier pour synchroniser les différentes instances peut poser quelques problèmes :
    - comment assurer que 2 instances n'essaient pas en même temps d'écrire dans le même fichier ? la librairie python-lockfile fournit la base pour résoudre ce genre de problème.
    - comment nettoyer le fichier à l'arrêt des instances ? En cas de plantage ? Est-ce un problème dans ton cas ?

    J'aurais tendance à faire communiquer les différences instances via xmpp ou AMQP ... petite contrainte, ça oblige à faire tourner un serveur xmpp ou AMQP mais ça permet :
    - de faire tourner tes instances sur une ou plusieurs machines
    - c'est scalable jusqu'à au moins 100/200 d'instances
    - la seule information à fournir aux instances est l'adresse du serveur.

    Sinon tu peux peut-être utiliser une base sqlite ?

  4. #4
    Membre expérimenté Avatar de pacificator
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 074
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 074
    Points : 1 728
    Points
    1 728
    Par défaut
    Bonjour,

    tu peux aussi jeter un oeil sur zeromq.

    Bon python
    "Etre conscient de la difficulté permet de l'éviter.."
    Lao-Tseu.

  5. #5
    Membre confirmé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Points : 455
    Points
    455
    Billets dans le blog
    1
    Par défaut
    comment assurer que 2 instances n'essaient pas en même temps d'écrire dans le même fichier ?
    Je fais confiance à l'OS. En principe 2 process ne peuvent ouvrir le même fichier en écriture en même temps. C'est même sur cette hypothèse que je me base. D'ailleurs, de tous les problèmes que je rencontre, aucun ne vient d'une faille à ce niveau.

    comment nettoyer le fichier à l'arrêt des instances ? En cas de plantage ?
    C'est le process qui est devenu maître qui s'en occupe. Grâce aux exceptions, c'est plantage-proof (enfin, je crois).

    Je te propose dans un premier temps une solution simple sur la base de xmlrpclib/SimpleXMLRPCServer
    Je suis à fond !
    Captain'Flam
    anciennement Sopsag, aka Hadrien
    Win seven x64 & Win 10 / Visual 2017 / Python 2.7 / Eclipse

  6. #6
    Membre confirmé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Points : 455
    Points
    455
    Billets dans le blog
    1
    Par défaut
    Ayé !
    Finalement, je suis parti sur un bon vieux serveur TCP et j'ai obtenu un truc qui marche pas mal (il arrive à tenir une centaine d'instance. après je commence à avoir plusieurs maîtres)
    Voici à quoi ça ressemble :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    def try_master ( port,param ):
        import SocketServer
     
        class TCPHandler ( SocketServer.BaseRequestHandler ):
            def handle(self):
                server.res.append( self.request.recv( 2000 ).strip())
        try:
            def timed_out () : server.is_alive = False
            server = SocketServer.TCPServer(('localhost',port),TCPHandler )
            server.res            = [param]
            server.timeout        = 0.5
            server.is_alive       = True
            server.handle_timeout = timed_out
            while server.is_alive :
                server.handle_request()
            return server.res
        except:
            return None
     
    def try_slave ( port,param ):
        import socket
        try:
            sock = socket.socket( socket.AF_INET,socket.SOCK_STREAM )
            sock.connect(('localhost',port))
            sock.sendall( param )
        finally:
            sock.close()        
     
    def merge_params ( param ):
        return try_master( 56789,param ) or try_slave( 56789,param )
     
    files = merge_params( sys.argv[1] )
    if files :
        print files
    On essaye d'abord de créer le serveur :
    si on n'y arrive pas : on devient esclave, on envoie son paramètre et on sort.
    si on y arrive : on est le maître en écoute des paramètres des esclaves.
    Si le maître reste 0.5s sans rien recevoir, on considère que tous les esclaves ont fini => on revoie la liste de tous les paramètres reçus.
    Le seul paramètre à régler c'est le 0.5s de timeout.
    Avec 1s ça résiste à plus d'instances, mais si il y en a peu, on attend pour rien.
    Le seul hic : il faut esperer qu'il n'y a personne sur le port 56789
    En tout cas, c'est beaucoup plus élégant et concis que ma solution à base de fichier partagé...

    Merci les gars
    Néanmoins, si vous voyez des trucs à améliorer, n'hésitez pas...
    Captain'Flam
    anciennement Sopsag, aka Hadrien
    Win seven x64 & Win 10 / Visual 2017 / Python 2.7 / Eclipse

  7. #7
    Membre confirmé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Points : 455
    Points
    455
    Billets dans le blog
    1
    Par défaut
    Petit oubli : merci pacificator mais j'aime mieux une solution à base de lib standard.
    Captain'Flam
    anciennement Sopsag, aka Hadrien
    Win seven x64 & Win 10 / Visual 2017 / Python 2.7 / Eclipse

  8. #8
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Salut,

    Le bon vieux serveur TCP est à la base de la solution proposée par PauseKawa. Mais honnêtement, pourquoi le faire disparaître alors que le lancer au 'boot' simplifierait pas mal de choses (dont l'allocation du port IP)...

    Passer par les fichiers ou la mémoire partagé suppose la mise en oeuvre de verrous basés sur sémaphores nommés ou byte range locking.

    Qt apporte une solution permettant d'accéder à des sémaphores nommés et seule les primitives de byte range locking sont disponible dans les biblio de base. Ceci dit, pour passer d'un verrou à un protocole d'échange, il y a encore plein de boulot que le passage par un modèle client/serveur "évite".

    Au delà le seul soucis pourra être de voir le serveur devenir "goulot d'étranglement" mais çà dépend de la quantité d'information échangé, du temps de traitement moyen et des temps de réponses attendus.

    Cordialement,
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  9. #9
    Membre confirmé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Points : 455
    Points
    455
    Billets dans le blog
    1
    Par défaut
    Je te remercie wiztricks, mais j'ai peur que ce soit disproportionné.
    Ma petite construction tient en quelques lignes et ce n'est destiné qu'à un petit script.
    Ça tient dans un seul fichier : pas de déploiement, pas de lib à installer...
    Mais tu as raison, en analysant les traces, il est clair qu'avec beaucoup d'instances, le serveur devient un goulot d'étranglement.
    Captain'Flam
    anciennement Sopsag, aka Hadrien
    Win seven x64 & Win 10 / Visual 2017 / Python 2.7 / Eclipse

  10. #10
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Salut,

    Je suppose que "disproportionné" porte sur l'intégration du démarrage du serveur au "boot".

    Car pour le reste, j'essayais de vous expliquer que c'était beaucoup plus compliqué que vous ne l'imaginiez. Le modèle client/serveur étant quand même plus simple à mettre en œuvre.

    Mais tu as raison, en analysant les traces, il est clair qu'avec beaucoup d'instances, le serveur devient un goulot d'étranglement.
    Absolument. Pire, comme c'est une file d'attente, le modèle n'est pas linéaire.
    Ceci dit, je serais curieux de connaître un peu mieux ce que tous ces process échangent.

    Cordialement,
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  11. #11
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonsoir,

    Citation Envoyé par wiztricks Voir le message
    Le bon vieux serveur TCP est à la base de la solution proposée par PauseKawa. Mais honnêtement, pourquoi le faire disparaître alors que le lancer au 'boot' simplifierait pas mal de choses (dont l'allocation du port IP)...
    Le premier programme lancé bloque le port. Quelle importance a partir de là ? C'est le 'master'.
    Citation Envoyé par Captain'Flam Voir le message
    Le seul hic : il faut esperer qu'il n'y a personne sur le port 56789
    D’où ma proposition de plage: Un 'scan' d'une large plage permet de passer outre ce problème.

    @+

    Note: Ceci dit il me semble que cela revient à Comment n'instancier qu'une seule fois un programme ?
    Merci d'utiliser le forum pour les questions techniques.

  12. #12
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Bonsoir PauseKawa,

    Citation Envoyé par PauseKawa Voir le message
    Le premier programme lancé bloque le port. Quelle importance a partir de là ? C'est le 'master'.
    Sur le papier, pas de problème.
    Dans la pratique, si le "master" se casse la gueule pour une raison X ou Y ce ne sera pas simple d'en élire un autre (rapidement). Par défaut, IP attendra avant de bien vouloir ré-allouer le port et même si SO_REUSEADDR permet de redémarrer un serveur, quel client verra que le serveur est tombé avant timedwait?

    D’où ma proposition de plage: Un 'scan' d'une large plage permet de passer outre ce problème.
    Dans ce cas, il faudra trouver derrière quel port se cache le master et trier les non master...

    Note: Ceci dit il me semble que cela revient à Comment n'instancier qu'une seule fois un programme ?
    La partie élection d'un maître est semblable. La différence est qu'on va devoir communiquer avec lui.
    Le client/serveur TCP/IP propose un tout-en-un intéressant.
    Sinon un équivalent de pidfile (un vérrou fichier) suffit.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Liaison entre listes qui ne s'affiche pas
    Par crazylia dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 16/04/2010, 11h34
  2. Variables d'entrée sortie qui ne se remplissent pas
    Par brunoperel dans le forum Prolog
    Réponses: 5
    Dernier message: 06/12/2009, 22h14
  3. [VB2005] Process qui ne se termine pas ?
    Par Kropernic dans le forum Windows Forms
    Réponses: 4
    Dernier message: 10/07/2008, 13h16
  4. [VB6]Process qui ne se ferme pas
    Par marsup54 dans le forum VB 6 et antérieur
    Réponses: 6
    Dernier message: 19/04/2006, 13h57
  5. 2 SELECT Qui ne s'entendent pas très bien entre eux :(
    Par moutanakid dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 05/08/2004, 16h46

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo