2014-02-21 4 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는 포트 5564에서 zmq로부터 데이터를 수신하고 포트 5563에서 데이터를 전송합니다.

zmq.DONTWAIT은 비동기 및 비 차단 메시지 수신을 읽었으므로 추가했습니다.

내가 CPU를 과부화하지 않도록 코드를 향상시키는 방법이 있습니까? 목표는 zmq를 사용하여 플라스크 앱과 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 스크립트를 실행할 수 있습니다. 나는 그것이 어떻게되는지 당신에게 확실히 알려줄 것입니다. 도와 주셔서 감사합니다! –