2014-02-21 113 views
1

我创建了一个分开运行的zmq_forwarder.py,它将消息从应用程序传递到sockJS连接,目前我正在处理烧瓶应用程序如何通过zmq从sockJS接收消息。我正在粘贴我的zmq_forwarder.py的内容。即时通讯新的ZMQ,我不知道为什么每次我运行它,它使用100%的CPU负载。如何避免CPU使用率过高?

import zmq 

# Prepare our context and sockets 
context = zmq.Context() 

receiver_from_server = context.socket(zmq.PULL) 
receiver_from_server.bind("tcp://*:5561") 

forwarder_to_server = context.socket(zmq.PUSH) 
forwarder_to_server.bind("tcp://*:5562") 

receiver_from_websocket = context.socket(zmq.PULL) 
receiver_from_websocket.bind("tcp://*:5563") 

forwarder_to_websocket = context.socket(zmq.PUSH) 
forwarder_to_websocket.bind("tcp://*:5564") 

# Process messages from both sockets 
# We prioritize traffic from the server 
while True: 

    # forward messages from the server 
    while True: 
     try: 
      message = receiver_from_server.recv(zmq.DONTWAIT) 
     except zmq.Again: 
      break 

     print "Received from server: ", message 
     forwarder_to_websocket.send_string(message) 

    # forward messages from the websocket 
    while True: 
     try: 
      message = receiver_from_websocket.recv(zmq.DONTWAIT) 
     except zmq.Again: 
      break 

     print "Received from websocket: ", message 
     forwarder_to_server.send_string(message) 

正如你所看到的,我已经设置了4个插座。应用程序连接到端口5561将数据推送到zmq,端口5562从zmq接收(虽然我仍然想知道如何实际设置它来监听由zmq发送的消息)。在另一方面,从sockjs接收ZMQ端口5564的数据和将数据发送到其上的端口5563.

我读过zmq.DONTWAIT使得接收到消息异步和非阻塞的,所以我加入它。

有没有办法改善代码,以便我不超载CPU?目标是能够使用zmq在flask应用程序和websocket之间传递消息。

回答

5

您正在轮询您的两个接收器插槽,没有任何阻塞(zmq.DONTWAIT),这将不可避免地超出CPU。

请注意,ZMQ中有一些支持在单个线程中轮询多个套接字 - 请参阅this answer。我认为你可以在poller.poll(millis)中调整超时时间,这样如果有很多传入的消息,你的代码只使用大量的CPU,否则就是空闲的。

您的其他选择是使用ZMQ事件循环以异步方式使用回调来响应传入消息。查看此主题的PyZMQ documentation,从下面的“回声”的例子适用:

# set up the socket, and a stream wrapped around the socket 
s = ctx.socket(zmq.REP) 
s.bind('tcp://localhost:12345') 
stream = ZMQStream(s) 

# Define a callback to handle incoming messages 
def echo(msg): 
    # in this case, just echo the message back again 
    stream.send_multipart(msg) 

# register the callback 
stream.on_recv(echo) 

# start the ioloop to start waiting for messages 
ioloop.IOLoop.instance().start() 
+0

感谢您的答复,但你能否详细说明“你的另一种选择是使用ZMQ事件循环传入的消息异步响应,使用回调。“? –

+0

没问题 - 我已经添加了一个链接和一个例子。 – DNA

+0

嗯......我实际上正在建造一个烧瓶+龙卷风应用程序。并且为了通过zmq将消息从应用程序传递到sockjs连接,我必须单独运行zmq脚本。已经在查看您分享的链接。希望我能够在龙卷风之上运行zmq脚本。我一定会让你知道它是怎么回事。谢谢您的帮助! –