pyzmq使用自己的套接字创建进程

时间:2013-04-13 18:43:38

标签: python zeromq python-multithreading pyzmq

我有一些代码监视其他一些不断变化的文件,我想做的是启动那个使用zeromq与不同套接字的代码,我现在这样做的方式似乎导致断言在libzmq的某处失败,因为我可能正在重用相同的套接字。我如何确保从监视器类创建新进程时不会重用上下文?多数民众赞成我认为正在发生的事情,如果你能说出我的其他愚蠢,请告知。 这是一些代码:

import zmq
from zmq.eventloop import ioloop
from  zmq.eventloop.zmqstream  import ZMQStream
class Monitor(object):
    def __init(self)
        self.context = zmq.Context()
        self.socket = self.context.socket(zmq.DEALER)
        self.socket.connect("tcp//127.0.0.1:5055")
        self.stream =  ZMQStream(self._socket)
        self.stream.on_recv(self.somefunc)

    def initialize(self,id)
        self._id = id

    def somefunc(self, something)
        """work here and send back results if any """
        import json
        jdecoded = json.loads(something)
        if self_id == jdecoded['_id']
           """ good im the right monitor for you """
           work = jdecoded['message']
           results  = algorithm (work)
           self.socket.send(json.dumps(results))
        else:
           """let some other process deal with it, not mine """
           pass

 class Prefect(object):
    def __init(self, id)
        self.context = zmq.Context()
        self.socket = self.context.socket(zmq.DEALER)
        self.socket.bind("tcp//127.0.0.1:5055")
        self.stream =  ZMQStream(self._socket)
        self.stream.on_recv(self.check_if)
        self._id = id
        self.monitors = []
    def check_if(self,message):
        """find out from message's id whether we have
            started a proces for it previously"""
        import json
        jdecoded = json.loads(message)
        this_id = jdecoded['_id']
        if this_id in self.monitors:
            pass
        else:
            """start new process for it should have its won socket """
            new = Monitor()
            import Process
            newp = Process(target=new.initialize,args=(this_id) )
            newp.start()
            self.monitors.append(this_id) ## ensure its remembered

发生的事情是我希望所有的监视器进程和一个完美的进程监听同一个端口,所以当prefect看到一个请求它没有看到它启动它的进程时,所有存在的进程可能应该也听,但忽略不适合他们的消息。 就目前而言,如果我这样做,我得到一些崩溃可能与某些zmq套接字的并发访问有关(我试过threading.thread,仍然崩溃)我读到某处不可能通过不同线程并发访问zmq套接字。我如何确保新进程获得自己的zmq套接字?

编辑: 我的应用程序中的主要交易是通过zmq套接字发出请求,并且监听的进程通过以下方式对消息作出反应:

1. If its directed at that process judged by the _id field, do some reading on a file and reply since one of the monitors match the messages _id, if none match, then:
2  If the messages _id files is not recognized, all monitors ignore it but the Prefect creates a process to handle that _id and all future messages to that id.
3. I want all the messages to be seen by the monitor processes as well as the prefect process, seems that seems easiest, 
4. All the messages are very small, avarage ~4096 bytes.   
5. The monitor does some non-blocking read and for each ioloop it sends what it has found out

more-edit =>并且完美进程现在绑定,它将接收消息并回显它们,以便监视器可以看到它们。这就是我的想法,作为架构,但它不是最终的。     。

所有消息都是通过浏览器从远程用户到达,让服务器知道客户端想要什么,服务器通过zmq将消息发送到后端(我没有显示,但并不难)所以在生产中他们可能无法绑定/连接到localhost。 我选择了DEALER,因为它允许在任一方向上的asyc /无限消息(参见第5点)和DEALER可以与DEALER绑定,并且初始请求/回复可以从任何一方到达。另一个可以做到这一点的可能是经销商/路由人。

1 个答案:

答案 0 :(得分:2)

你是正确的,你不能继续在fork边界使用相同的套接字(多处理使用fork)。通常,这意味着您不希望在子进程启动之前创建将在分叉进程中使用的套接字。 因为在您的情况下,套接字是Monitor对象的属性,所以您根本不想在主进程中创建Monitor。这看起来像这样:

def start_monitor(this_id):
    monitor = Monitor()
    monitor.initialize(this_id)
    # run the eventloop, or this will return immediately and destroy the monitor

... inside Prefect.check_if():

    proc = Process(target=start_monitor, args=(this_id,))
    proc.start()
    self.monitors.append(this_id)

而不是你的例子,其中子进程唯一做的就是分配一个ID然后终止进程,最终没有任何效果。