在Python ZeroMQ中随机冻结/挂起

时间:2015-03-23 13:52:16

标签: python zeromq pyzmq

我正在编写一个用 ZeroMQ 在python中编写的无代理,平衡,客户端工作服务。

客户端获取工作人员的地址,建立连接(zmq.REQ / zmq.REP),发送单个请求,接收单个响应然后断开连接。

我选择了无代理架构,因为需要在客户端和工作者之间传输的数据量相对较大,尽管每个连接只有一个REQ/REP对,并且使用代理作为一个中间人'会造成瓶颈。

在测试系统时,我注意到客户端和工作人员之间的通信是随机停止的,有时仅在几秒钟后恢复(通常是几分钟)。

我将问题范围缩小到.connect() / .disconnect()客户工作人员。

我写了两个小的python脚本来重现这个bug。

import zmq

class Site:

      def __init__(self):
        ctx = zmq.Context()
        self.pair_socket = ctx.socket(zmq.REQ)
        self.num = 0


      def __del__(self):
        print "closed"


      def run_site(self):
        print "running..."
        while True:
            self.pair_socket.connect('tcp://127.0.0.1:5555')
            print 'connected'
            self.pair_socket.send_pyobj(self.num)
            print 'sent', self.num
            print self.pair_socket.recv_pyobj()
            self.pair_socket.disconnect('tcp://127.0.0.1:5555')
            print 'disconnected'
            self.num += 1

s = Site()
s.run_site()

import zmq

class Server:

      def __init__(self):
          ctx = zmq.Context()
          self.pair_socket = ctx.socket(zmq.REP)
          self.pair_socket.bind('tcp://127.0.0.1:5555')


      def __del__(self):
          print " closed"


      def run_server(self):
          print "running..."
          while True:
              x =  self.pair_socket.recv_pyobj()
              print x
              self.pair_socket.send_pyobj(x)


s = Server()  
s.run_server()

我认为这个问题与记忆或 gc 无关,因为我尝试过停用gc - 没有多大影响。

我尝试使用 zmq.LINGER ,如下所述:Zeromq with python hangs if connecting to invalid socket

什么可能导致这些rand冻结?

1 个答案:

答案 0 :(得分:0)

根据定义,REP套接字是同步的。因此,您的服务器一次只能处理一个请求,其余的只会填满缓冲区并在某些时候丢失。

要解决根本原因,您需要使用ROUTER套接字。

class Server:
    def __init__(self):
        ctx = zmq.Context()
        self.pair_socket = ctx.socket(zmq.ROUTER)
        self.pair_socket.bind('tcp://127.0.0.1:5555')
        self.poller = zmq.Poller()
        self.poller.register(self.pair_socket, zmq.POLLIN)

    def __del__(self):
        print " closed"

    def run_server(self):
        print "running..."
        while True:
            try:
                items = dict(self.poller.poll())
            except KeyboardInterrupt:
                break
            if self.pair_socket in items:
                x = self.pair_socket.recv_multipart()
                print x
                self.pair_socket.send_multipart(x)