zeromq和python多处理,打开的文件太多了

Dav*_*jad 10 zeromq python-multiprocessing

我有一个基于代理的模型,其中多个代理由中央进程启动,并通过另一个中央进程进行通信.每个代理和通信过程都通过zmq进行通信.但是,当我启动超过100个代理时,standard_out发送:

参数无效(src/stream_engine.cpp:143)打开的文件太多(src/ipc_listener.cpp:292)

和Mac Os提示问题报告:

使用libzmq.5.dylib插件时,Python意外退出.

在我看来,问题是打开了太多的上下文.但是如何通过多处理避免这种情况呢?

我附上以下部分代码:

class Agent(Database, Logger, Trade, Messaging, multiprocessing.Process):
    def __init__(self, idn, group, _addresses, trade_logging):
        multiprocessing.Process.__init__(self)
        ....

    def run(self):
        self.context = zmq.Context()
        self.commands = self.context.socket(zmq.SUB)
        self.commands.connect(self._addresses['command_addresse'])
        self.commands.setsockopt(zmq.SUBSCRIBE, "all")
        self.commands.setsockopt(zmq.SUBSCRIBE, self.name)
        self.commands.setsockopt(zmq.SUBSCRIBE, group_address(self.group))

        self.out = self.context.socket(zmq.PUSH)
        self.out.connect(self._addresses['frontend'])
        time.sleep(0.1)
        self.database_connection = self.context.socket(zmq.PUSH)
        self.database_connection.connect(self._addresses['database'])
        time.sleep(0.1)
        self.logger_connection = self.context.socket(zmq.PUSH)
        self.logger_connection.connect(self._addresses['logger'])

        self.messages_in = self.context.socket(zmq.DEALER)
        self.messages_in.setsockopt(zmq.IDENTITY, self.name)
        self.messages_in.connect(self._addresses['backend'])

        self.shout = self.context.socket(zmq.SUB)
        self.shout.connect(self._addresses['group_backend'])
        self.shout.setsockopt(zmq.SUBSCRIBE, "all")
        self.shout.setsockopt(zmq.SUBSCRIBE, self.name)
        self.shout.setsockopt(zmq.SUBSCRIBE, group_address(self.group))

        self.out.send_multipart(['!', '!', 'register_agent', self.name])

        while True:
            try:
                self.commands.recv()  # catches the group adress.
            except KeyboardInterrupt:
                print('KeyboardInterrupt: %s,self.commands.recv() to catch own adress ~1888' % (self.name))
                break
            command = self.commands.recv()
            if command == "!":
                subcommand = self.commands.recv()
                if subcommand == 'die':
                    self.__signal_finished()
                    break
            try:
                self._methods[command]()
            except KeyError:
                if command not in self._methods:
                    raise SystemExit('The method - ' + command + ' - called in the agent_list is not declared (' + self.name)
                else:
                    raise
            except KeyboardInterrupt:
                print('KeyboardInterrupt: %s, Current command: %s ~1984' % (self.name, command))
                break

            if command[0] != '_':
                self.__reject_polled_but_not_accepted_offers()
                self.__signal_finished()
        #self.context.destroy()
Run Code Online (Sandbox Code Playgroud)

整个代码在http://www.github.com/DavoudTaghawiNejad/abce下

Jas*_*son 8

可能性不是太多的情况,它的插座太多了.通过您的回购,我看到您(正确)使用IPC作为您的交通工具; IPC使用文件描述符作为"地址"来在不同进程之间来回传递数据.如果我正确阅读,每个进程最多可以打开7个套接字,这样就可以快速加入.我敢打赌,如果你在代码中间进行一些调试,你会看到它在创建最后一个上下文时没有失败,但是当最后一个套接字在边缘上推送打开文件限制时.

我的理解是,开放FD的典型用户限制大约是1000,所以在大约100个代理中,你只需要为你的套接字推送700个开放FD.剩下的可能只是典型的.根据您的情况,将您的限制提高到10,000,应该没有问题.否则,您将不得不重写每个进程使用较少的套接字以获得更高的进程限制.

  • [以下是有关检查和更改FD限制的一些信息](http://www.cyberciti.biz/faq/linux-increase-the-maximum-number-of-open-files/). (2认同)

kel*_*nik 8

这与zeromq和python无关.它是底层操作系统,只允许同时打开的文件达到一定阈值.此限制包括普通文件,但也包括套接字连接.

您可以使用ulimit -n它来查看当前限制,它可能默认为1024.运行服务器或具有其他原因(如多处理)的计算机通常需要将此限制设置为更高或仅设置为unlimited.- 更多信息ulimit.

此外,还有另一个全球限制,但是我不得不调整它.

一般来说,如果你真的需要那么多代理人,你应该问问自己.通常,X/ 2Xworker进程应该足够,X与CPU数量相对应.