2014-11-13 152 views
6

當您使用簡單的ZeroMQ REQ/REP模式時,您依賴於固定的send() - > recv()/ recv() - > send()序列。 由於this文章描述了當參與者在請求中斷時出現問題,因爲那時你不能重新開始接收來自另一個連接的下一個請求,但是狀態機會強制你發送一個請求給斷開連接一。zeromq:重置REQ/REP套接字狀態

自從上面提到的文章已經寫出以來,是否出現了一種更優雅的方法來解決這個問題?

正在重新連接(從不使用REQ/REP除了而是用另一種模式)解決了這個

+1

你可能想要切換到在[導引]所述的路由器/經銷商基於可靠的請求響應中的一個(AKA海盜)圖案(http://zguide.zeromq.org/page :所有#Chapter-Reliable-Request-Reply-Patterns) –

回答

5

好消息是,隨着ZMQ 3.0及更高版本(當今時代),您可以在套接字上設置超時。正如其他人所指出的其他地方,你必須這樣做,你已經創建了插座後,但在連接之前:

zmq_req_socket.setsockopt(zmq.RCVTIMEO, 500) # milliseconds

然後,當你真正嘗試接收應答(您發送一條消息後REP套接字)時,您可以捕獲如果超時超時將導致的錯誤:

try: 
    send(message, 0) 
    send_failed = False 

except zmq.Again: 
    logging.warning("Image send failed.") 
    send_failed = True 

但是!當這種情況發生時,正如其他地方所觀察到的那樣,你的套接字將處於一個有趣的狀態,因爲它仍然期待響應。在這一點上,除了重新啓動套接字之外,我找不到任何可靠工作的東西。請注意,如果斷開()套接字然後重新連接(),它仍然處於這種不良狀態。因此,你需要

def reset_my_socket: 
    zmq_req_socket.close() 
    zmq_req_socket = zmq_context.socket(zmq.REQ) 
    zmq_req_socket.setsockopt(zmq.RCVTIMEO, 500) # milliseconds 
    zmq_req_socket.connect(zmq_endpoint) 

您還會注意到,因爲我關閉()D插座,接收超時選項被「丟失」的,所以重要的是一套在新的插座。

我希望這會有所幫助。我希望這不能成爲這個問題的最佳答案。 :)

+0

這仍然使REP套接字處於不良狀態,因爲它試圖發送從未收到的回覆。 – orodbhen

1

有一個解決這個問題的唯一方式,它是將超時到所有通話。由於ZeroMQ本身並不真正提供簡單的超時功能,所以我建議使用ZeroMQ套接字的一個子類,它爲所有重要的調用添加一個超時參數。

因此,不是調用s.recv(),而是調用s.recv(timeout = 5.0),如果響應沒有在5秒鐘內返回,它將返回None並停止阻塞。當我遇到這個問題時,我做了一個徒勞無益的嘗試。

+3

我目前沒有使用python測試它的zeromq 4,但我相信你推薦的這種方法將解決不確定等待的問題,但不能解決狀態機問題。然後你可以再次調用'recv()'而不是'send()'。然後你會得到一個異常,如'zmq.error.ZMQError:操作無法在當前狀態下完成。告訴我,如果我錯了(我會嘗試它,但我必須安裝最新版本的'pyzmq') – frans

+0

我的經驗與您描述的frans相同。如果REQ套接字已經發送了send()調用但從未收到響應,那麼它就會等待來自某個地方的響應。所以我可以憑經驗確認你的直覺。 – user3162307

+0

正如我上面評論的那樣,即使您重置REQ套接字,REP套接字仍然會處於不良狀態。它停留在回覆模式,而不是接收模式。 – orodbhen

1

我現在實際上正在研究這個問題,因爲我很適合傳統系統。

我不斷遇到需要了解連接狀態的「需要」代碼。但是,我想轉移到圖書館推動的消息傳遞範式。

我發現了以下功能:zmq_socket_monitor

它的作用是監視傳遞給它的插槽,並生成然後傳遞給一個「進程內」終點事件 - 在這一點上,你可以添加處理代碼實際上做一些東西。

還有一個例子(實際測試代碼)在這裏:github

我沒有得到任何具體的代碼給的那一刻(也許在一週結束),但我的本意是向響應連接和斷開連接,以便我可以實際執行所需邏輯的任何重置。

希望這有助於,儘管引用4.2文檔,我使用的4.0.4似乎也有功能 以及。

注意我注意到你說說上面蟒蛇,但問題是標籤C++因此,這就是我的答案是來自......

11

由於接受的答案對我來說似乎非常難過,所以我做了一些研究並發現我們需要的所有東西實際上都在文檔中。

.setsockopt()用正確的參數可以幫助你重新設置您的套接字狀態機沒有慘遭摧毀它,重建另一個比上一個人死亡的身體上。

(是的,我喜歡圖片)。

ZMQ_REQ_CORRELATE: match replies with requests
The default behavior of REQ sockets is to rely on the ordering of messages to match requests and responses and that is usually sufficient. When this option is set to 1 , the REQ socket will prefix outgoing messages with an extra frame containing a request id. That means the full message is (request id , identity , 0 , user frames…). The REQ socket will discard all incoming messages that don't begin with these two frames.
Option value type int
Option value unit 0 , 1
Default value 0
Applicable socket types ZMQ_REQ

ZMQ_REQ_RELAXED: relax strict alternation between request and reply
By default, a REQ socket does not allow initiating a new request with zmq_send(3) until the reply to the previous one has been received. When set to 1, sending another message is allowed and has the effect of disconnecting the underlying connection to the peer from which the reply was expected, triggering a reconnection attempt on transports that support it. The request-reply state machine is reset and a new request is sent to the next available peer.
If set to 1 , also enable ZMQ_REQ_CORRELATE to ensure correct matching of requests and replies. Otherwise a late reply to an aborted request can be reported as the reply to the superseding request.
Option value type int
Option value unit 0 , 1
Default value 0
Applicable socket types ZMQ_REQ

A complete documentation is here