2011-05-18 3 views
5

Considérez le code suivant:construire simple répartiteur à distance à l'aide multiprocessing.Managers

Serveur:

import sys 
from multiprocessing.managers import BaseManager, BaseProxy, Process 

def baz(aa) : 
    l = [] 
    for i in range(3) : 
     l.append(aa) 
    return l 

class SolverManager(BaseManager): pass 

class MyProxy(BaseProxy): pass 

manager = SolverManager(address=('127.0.0.1', 50000), authkey='mpm') 
manager.register('solver', callable=baz, proxytype=MyProxy) 

def serve_forever(server): 
    try : 
     server.serve_forever() 
    except KeyboardInterrupt: 
     pass 

def runpool(n): 
    server = manager.get_server() 
    workers = [] 

    for i in range(int(n)): 
     Process(target=serve_forever, args=(server,)).start() 

if __name__ == '__main__': 
    runpool(sys.argv[1]) 

Client:

import sys 
from multiprocessing.managers import BaseManager, BaseProxy 

import multiprocessing, logging 

class SolverManager(BaseManager): pass 

class MyProxy(BaseProxy): pass 

def main(args) : 
    SolverManager.register('solver') 
    m = SolverManager(address=('127.0.0.1', 50000), authkey='mpm') 
    m.connect() 

    print m.solver(args[1])._getvalue() 

if __name__ == '__main__': 
    sys.exit(main(sys.argv)) 

Si je lance le serveur en utilisant un seul processus que python server.py 1

alors le client fonctionne comme prévu. Mais si je Spawn deux processus (python server.py 2) l'écoute des connexions, je reçois une erreur méchant:

$python client.py ping 
Traceback (most recent call last): 
    File "client.py", line 24, in <module> 
sys.exit(main(sys.argv)) 
    File "client.py", line 21, in main 
    print m.solver(args[1])._getvalue() 
    File "/usr/lib/python2.6/multiprocessing/managers.py", line 637, in temp 
    authkey=self._authkey, exposed=exp 
    File "/usr/lib/python2.6/multiprocessing/managers.py", line 894, in AutoProxy 
    incref=incref) 
    File "/usr/lib/python2.6/multiprocessing/managers.py", line 700, in __init__ 
    self._incref() 
    File "/usr/lib/python2.6/multiprocessing/managers.py", line 750, in _incref 
    dispatch(conn, None, 'incref', (self._id,)) 
    File "/usr/lib/python2.6/multiprocessing/managers.py", line 79, in dispatch 
    raise convert_to_error(kind, result) 
multiprocessing.managers.RemoteError: 
--------------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "/usr/lib/python2.6/multiprocessing/managers.py", line 181, in handle_request 
    result = func(c, *args, **kwds) 
    File "/usr/lib/python2.6/multiprocessing/managers.py", line 402, in incref 
    self.id_to_refcount[ident] += 1 
KeyError: '7fb51084c518' 
--------------------------------------------------------------------------- 

Mon idée est assez simple. Je veux créer un serveur qui engendrera un certain nombre de travailleurs qui partageront le même socket et géreront les demandes indépendamment. Peut-être que j'utilise le mauvais outil ici?

L'objectif est de construire une structure à 3 niveaux où toutes les demandes sont traitées via un serveur HTTP, puis envoyés vers des noeuds assis dans un cluster et de nœuds aux travailleurs par les gestionnaires de multitraitement ...

Il y a un serveur public, un nœud par machine et x nombre de travailleurs sur chaque machine en fonction du nombre de cœurs ... Je sais que je peux utiliser une bibliothèque plus sophistiquée, mais pour une tâche si simple (je ne fais que prototyper ici) j'utiliserais simplement la bibliothèque multi-traitement ... Est-ce possible ou devrais-je explorer directement d'autres solutions? Je sens que je suis très proche d'avoir quelque chose qui fonctionne ici ... merci.

Répondre

1


Vous essayez d'inventer une roue, beaucoup ont inventé avant. Il me semble que vous recherchez une file d'attente de tâches à laquelle votre serveur envoie des tâches, et vos employés exécutent ces tâches. Je voudrais vous recommander de regarder Celery.