简体   繁体   English

如何解决Tornado + ZMQ错误

[英]How to resolve Tornado + ZMQ error

Like everyone else, I'm working through a chat PoC using Tornado (SockJS-Tornado) + pyzmq. 和其他人一样,我正在使用Tornado(SockJS-Tornado)+ pyzmq进行聊天PoC。

The overall idea is to have N tornado instances, each with connected websocket clients, exchanging messages through a ZMQ Device. 总的想法是拥有N个龙卷风实例,每个实例都有连接的websocket客户端,通过ZMQ设备交换消息。 In other words a websocket client on instance A publishes to a ZMQ Forwarder. 换句话说,实例A上的websocket客户端发布到ZMQ Forwarder。 Instances B & C have Handlers that are subscribed to the Forwarder so that matching topics are relayed to the websocket clients of B & C. And yes, the clients on B & C also have publisher sockets that publish to the Forwarder. 实例B&C具有订阅转发器的处理程序,以便将匹配的主题转发给B&C的websocket客户端。是的,B&C上的客户端也有发布到转发器的发布者套接字。

This all works fine but my problem is that if one of the connected clients disconnects unexpectedly (eg closes or refreshes the browser tab), then I get a deluge of errors like this: 这一切都运行正常但我的问题是,如果其中一个连接的客户端意外断开连接(例如关闭或刷新浏览器选项卡),那么我会收到大量的错误,如下所示:

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

So, at the application level, there's a single Context, but each Handler instantiated gets its own Publisher and Subscriber sockets. 因此,在应用程序级别,只有一个Context,但每个Handler实例化都会获得自己的Publisher和Subscriber套接字。 The Subscriber sockets use ZMQStream, like this: 订阅者套接字使用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)

The ioloop passed to ZMQStream is the global io_loop created at application startup: 传递给ZMQStream的ioloop是在应用程序启动时创建的全局io_loop:

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

It's actually an instance of the ZMQ subclass of the Tornado IOLoop. 它实际上是Tornado IOLoop的ZMQ子类的一个实例。 Any idea what's causing this error? 知道是什么导致了这个错误吗? I have some cleanup methods, on_connection_close and on_close but they don't seem to get called at any point. 我有一些清理方法, on_connection_closeon_close但它们似乎在任何时候都没有被调用。

Oh, this is Python 2.7.8, ZeroMQ 4.0.4, PyZMQ 14.4.0 (same thing happened with 14.3.1). 哦,这是Python 2.7.8,ZeroMQ 4.0.4,PyZMQ 14.4.0(同样的事情发生在14.3.1)。

Thanks in advance 提前致谢

Make sure you call _set_up_sockets inside the main thread. 确保在主线程内调用_set_up_sockets。

As you only have a single IOLoop, the zmq FAQ clearly states you need to create and use sockets in the same thread. 由于您只有一个IOLoop,因此zmq FAQ清楚地表明您需要在同一个线程中创建和使用套接字。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM