我有一个Tornado WebSocket服务器在一个由线程启动的单独进程中运行。当线程通过websockets发送消息时,该线程调用我的TornadoServer的发布方法。
在一个单独的进程上运行Tornado是我发现在没有线程阻塞的情况下启动龙卷风循环的唯一方法。
在我的主题中,我通过在线程 init 方法上调用这些方法来启动龙卷风过程:
self.p = tornado_server.TornadoServer()
self.p.daemon = True
self.p.start()
在这个线程中,我有一个无限循环试图从队列中获取消息,如果它获得消息,它会调用self.p.publish(client, message)
。
到目前为止,非常好。
在Tornado流程中,我基本上实现了一个发布/订阅系统。当用户打开网页时,该页面会发送特定“客户”的“订阅”消息。在“on_message”回调中,我附加了一个WebSocketHandler实例的元组和用户想要订阅全局列表的客户端。
然后,发布方法应该在列表中搜索消息的目标客户端的订阅用户,它应该调用存储在该列表上的WebSocket上的write_message。
唯一不起作用的是我的“客户”列表有不同的范围或什么。
这是我的tornado_server文件的代码:
#!/usr/bin/python2
import tornado.web, tornado.websocket, tornado.ioloop, multiprocessing
clients = []
class TornadoServer(multiprocessing.Process):
class WebSocketHandler(tornado.websocket.WebSocketHandler):
def on_message(self, message):
global clients
print 'TORNADO - Received message:', str(message)
channel, subtopic = message.split('/')
print 'TORNADO - Subscribing:', str(subtopic)
clients.append((self, subtopic))
def on_close(self):
global clients
for websocket, client in clients:
if self == websocket:
print 'TORNADO - Removed client'
to_remove = (self, client)
clients.remove(to_remove)
def __init__(self):
multiprocessing.Process.__init__(self)
self.application = tornado.web.Application([(r"/tri-anim", WebSocketHandler)])
self.application.listen(1339)
def run(self):
tornado.ioloop.IOLoop.current().start()
def publish(self, client, message):
global clients
for websocket, websocketclient in clients:
if websocketclient == client:
websocket.write_message(str(message))
无论我做什么,客户都有不同的范围。调用publish时,“clients”始终为空。有没有办法让这个工作?
答案 0 :(得分:0)
您正在父进程中调用publish,但客户端列表仅在子进程中更新。使用多处理时,每个进程都会获得所有变量的副本。如果您使用线程而不是变量将被共享,但即使这样,您也需要使用IOLoop.instance()。add_callback在线程调用发布和write_message函数之间进行线程安全切换(必须在IOLoop线程)。