如何在Python中关闭ZeroMQ zmq.proxy?

时间:2015-08-20 23:28:54

标签: proxy daemon zeromq shutdown

我在Python中实现了一个“网络服务”超类,如下所示:

class NetworkService (threading.Thread):

    """
        Implements a multithreaded network service
    """

    # Class Globals (ie, C++ class static)
    ZmqContext = zmq.Context.instance()

    # ==========================================================================================
    # Class Mechanics
    # ==========================================================================================

    def __init__(self, name, port, conc=4):
        """
            Network service initilization
        """
        self.service_name = name
        self.service_port = port
        self.concurrency = conc
        self.handler_url = "inproc://" + name
        self.client_url = "tcp://*:" + str(port)
        self.shutdown = True # Cleared in run()
        self.thread = {}
        super(NetworkService, self).__init__()

    # ==========================================================================================
    # Class Operation
    # ==========================================================================================

    def run(self): # Called [only] by threading.Thread.start()
        self.shutdown = False

        clients = NetworkService.ZmqContext.socket(zmq.ROUTER)
        clients.bind(self.client_url)

        handlers = NetworkService.ZmqContext.socket(zmq.DEALER)
        handlers.bind(self.handler_url)

        for i in range(self.concurrency):
            self.thread[i] = threading.Thread(target = self.handler, name = self.service_name + str(i))
            self.thread[i].daemon = True
            self.thread[i].start()

        zmq.proxy(clients, handlers)
        clients.close()
        handlers.close()

    def terminate(self):
        self.shutdown = True

    def handler(self):
        socket = NetworkService.ZmqContext.socket(zmq.REP)
        socket.connect(self.handler_url)
        iam = repr(get_pids()[2])
        log.info("nsh@%s is up", iam)
        while not self.shutdown:
            string = socket.recv()
            toe = datetime.utcnow()
            command = pickle.loads(string)
            reply = self.protocol(command)
            string = pickle.dumps(reply)
            socket.send(string)

    def protocol(self, command): # Override this in subclass
        reply = {}
        reply["success"] = False
        reply["detail"] = "No protocol defined (NetworkService.protocol(...) not overridden)"
        if "ident" in command:
            reply["ident"] = command["ident"]
        return reply

问题在于“ zmq.proxy(clients, handlers) ”:我似乎无法完成它。永远。如果所有处理程序都终止,则zmq.proxy()仍然不会返回。我不介意创建一个独立的线程来运行代理,但这是一个守护进程,我希望能够干净地关闭。

我在文档中读到这是zmq.proxy的正确行为,但对我来说似乎不正确; - }。

任何人都可以推荐在处理程序线程终止后可以关闭的近似等价物吗?

1 个答案:

答案 0 :(得分:1)

API基本上意味着您必须终止上下文。您可以在具有共享上下文的单独线程中运行代理,然后终止它,除了zmq.ContextTerminated。

try:
    zmq.proxy(self.frontend, self.backend)
except zmq.ContextTerminated:
    # cleanup if needed