如何解决Tornado + ZMQ错误

时间:2014-10-22 21:12:43

标签: python tornado pyzmq

和其他人一样,我正在使用Tornado(SockJS-Tornado)+ pyzmq进行聊天PoC。

总的想法是拥有N个龙卷风实例,每个实例都有连接的websocket客户端,通过ZMQ设备交换消息。换句话说,实例A上的websocket客户端发布到ZMQ Forwarder。实例B& C具有订阅转发器的处理程序,以便匹配的主题被转发到B& S的Web服务器客户端。 C.是的,B& B的客户C还有发布者套接字发布到转发器。

这一切都运行正常但我的问题是如果其中一个连接的客户端意外断开连接(例如关闭或刷新浏览器选项卡),那么我会收到大量的错误:

ERROR:tornado.application:Exception in callback None
Traceback (most recent call last):
  File ".../tornado/ioloop.py", line 836, in start
  fd_obj, handler_func = self._handlers[fd]
KeyError: 246850817
ERROR:tornado.application:Exception in callback None
Traceback (most recent call last):
  File ".../tornado/ioloop.py", line 836, in start
  fd_obj, handler_func = self._handlers[fd]
KeyError: 246850817

因此,在应用程序级别,只有一个Context,但每个Handler实例化都会获得自己的Publisher和Subscriber套接字。订阅者套接字使用ZMQStream,如下所示:

   def _set_up_sockets(self):
    self.publisher = self.context.socket(zmq.PUB)
    self.publisher.connect('tcp://127.0.0.1:5559')
    self.subscriber = self.context.socket(zmq.SUB)
    self.subscriber.connect('tcp://127.0.0.1:5560')
    self.subscriber.setsockopt(zmq.SUBSCRIBE, "_NOROOM_")
    stream = zmqstream.ZMQStream(self.subscriber,
                                 io_loop=self.session.server.io_loop)
    stream.on_recv(self.echo)

传递给ZMQStream的ioloop是在应用程序启动时创建的全局io_loop:

ioloop.install()
io_loop = IOLoop.instance()

它实际上是Tornado IOLoop的ZMQ子类的一个实例。知道导致这个错误的原因是什么吗?我有一些清理方法,on_connection_closeon_close,但它们似乎在任何时候都没有被调用。

哦,这是Python 2.7.8,ZeroMQ 4.0.4,PyZMQ 14.4.0(与14.3.1相同)。

提前致谢

1 个答案:

答案 0 :(得分:1)

确保在主线程内调用_set_up_sockets。

由于您只有一个IOLoop,因此zmq FAQ清楚地表明您需要在同一个线程中创建和使用套接字。