2014-11-13 10 views
6

जब आप सरल ज़ीरोएमक्यू आरईक्यू/आरईपी पैटर्न का उपयोग करते हैं तो आप एक निश्चित प्रेषण() -> recv()/recv() -> send() अनुक्रम पर निर्भर करते हैं। this आलेख वर्णन करता है कि जब कोई प्रतिभागी अनुरोध के बीच में डिस्कनेक्ट हो जाता है तो आप परेशानी में पड़ते हैं क्योंकि तब आप किसी अन्य कनेक्शन से अगला अनुरोध प्राप्त करने के साथ शुरू नहीं कर सकते हैं, लेकिन राज्य मशीन आपको डिस्कनेक्ट करने का अनुरोध भेजने के लिए मजबूर करेगी एक।zeromq: रीक्यू/आरईपी सॉकेट स्थिति रीसेट करें

क्या इस लेख को हल करने के बाद से इसे हल करने के लिए एक और शानदार तरीका उभरा है?

(का उपयोग नहीं कर अनुरोध/REP से अलग लेकिन का उपयोग एक और पैटर्न) इस को हल करने के

+1

आप रूटर/डीलर आधारित विश्वसनीय अनुरोध प्रतिक्रिया में से एक (उर्फ समुद्री डाकू) पैटर्न में [गाइड] वर्णित करने के लिए स्विच करने के लिए चाहते हो सकता है (http://zguide.zeromq.org/page : सभी # अध्याय- विश्वसनीय-अनुरोध-उत्तर-पैटर्न) –

उत्तर

5

अच्छी खबर यह है कि है, ZMQ 3.0 और बाद में (आधुनिक युग के रूप में), आप एक सॉकेट पर एक टाइमआउट सेट कर सकते हैं। तब

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

, जब आप वास्तव में (उत्तर प्राप्त करने के बाद आप के लिए एक संदेश भेजा है कोशिश: जैसा कि दूसरों कहीं उल्लेख किया है, आप के बाद आप सॉकेट बनाया है ऐसा करने चाहिए, लेकिन इससे पहले कि आप इसे कनेक्ट आरईपी सॉकेट), आप उस त्रुटि को पकड़ सकते हैं जो टाइमआउट पार हो जाने पर जोर दिया जाएगा:

try: 
    send(message, 0) 
    send_failed = False 

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

हालांकि! जब ऐसा होता है, जैसा कि कहीं और देखा गया है, तो आपकी सॉकेट एक मजेदार स्थिति में होगी, क्योंकि यह अभी भी प्रतिक्रिया की उम्मीद कर रही है। इस बिंदु पर, मुझे कुछ भी नहीं मिल रहा है जो सॉकेट को पुनरारंभ करने के अलावा विश्वसनीय रूप से काम करता है।ध्यान दें कि यदि आप सॉकेट को डिस्कनेक्ट() करते हैं और फिर इसे फिर से कनेक्ट करते हैं, तो यह अभी भी इस खराब स्थिति में होगा। इस प्रकार आप आप भी देखेंगे कि क्योंकि मैं इसे बंद() सॉकेट d, प्राप्त टाइमआउट विकल्प "खो" था, इसलिए यह महत्वपूर्ण सेट है

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) 

करने की जरूरत है कि नए सॉकेट पर।

मुझे उम्मीद है कि इससे मदद मिलती है। और मुझे उम्मीद है कि यह इस प्रश्न का सबसे अच्छा जवाब नहीं बनता है। :)

+0

यह अभी भी एक खराब स्थिति में REP सॉकेट छोड़ देता है, क्योंकि यह एक उत्तर है कि कभी नहीं प्राप्त किया गया था भेजने का प्रयास किया। – orodbhen

1

इस के लिए एक समाधान नहीं है एक ही रास्ता फिर से कनेक्ट करने है और कहा कि सभी कॉल करने के लिए समय समाप्ति जोड़ रहा है। चूंकि ज़ीरोएमक्यू स्वयं ही सरल टाइमआउट कार्यक्षमता प्रदान नहीं करता है, इसलिए मैं ज़ीरोएमक्यू सॉकेट के उप-वर्ग का उपयोग करने की अनुशंसा करता हूं जो सभी महत्वपूर्ण कॉलों पर टाइमआउट पैरामीटर जोड़ता है।

तो, s.recv() को कॉल करने के बजाय आप s.recv (timeout = 5.0) को कॉल करेंगे और यदि कोई प्रतिक्रिया उस 5 सेकंड विंडो में वापस नहीं आती है तो यह कोई भी वापस नहीं लौटाएगी और अवरुद्ध करना बंद कर देगा। जब मैं इस समस्या में भाग लेता हूं तो मैंने इस पर एक व्यर्थ प्रयास किया था।

+3

मैं वर्तमान में कोई zeromq 4 यहां अजगर के साथ यह परीक्षण करने के लिए है, लेकिन मुझे विश्वास है कि इस दृष्टिकोण आप की सिफारिश क्रिया के साधारण इंतजार कर रहे हैं, लेकिन राज्य की मशीन के साथ नहीं के साथ समस्या का समाधान होगा। फिर आप 'recv()' को फिर से कॉल करने में सक्षम होंगे लेकिन 'भेजें()' नहीं। इसके बाद आपको 'zmq.error.ZMQError' जैसे अपवाद मिलेगा: ऑपरेशन वर्तमान स्थिति में पूरा नहीं किया जा सकता है। मुझे बताएं कि क्या मैं गलत हूं (मैं इसे किसी भी तरह से कोशिश करूंगा लेकिन मुझे 'pyzmq' का हालिया संस्करण स्थापित करना होगा) – frans

+0

मेरा अनुभव वही है जैसा आप वर्णन करते हैं। अनुरोध सॉकेट एक भेजें() कॉल बना दिया है, लेकिन एक प्रतिक्रिया कभी नहीं प्राप्त करता है, तो यह कहीं से प्रतिक्रिया की प्रतीक्षा करने फंस गया है। इसलिए मैं आपके अंतर्ज्ञान को अनुभवी रूप से पुष्टि कर सकता हूं। – user3162307

+0

जैसा कि मैंने ऊपर टिप्पणी की, REP सॉकेट अभी भी एक खराब स्थिति में फंस कर दिया जाएगा, भले ही आप अनुरोध सॉकेट रीसेट। यह मोड प्राप्त करने के बजाय, उत्तर मोड में फंस गया है। – orodbhen

1

मैं वास्तव में इस समय इस पर देख रहा हूं, क्योंकि मैं एक विरासत प्रणाली को रेट्रो कर रहा हूं।

मैं लगातार कोड में आ रहा हूं कि कनेक्शन की स्थिति के बारे में जानने के लिए "जरूरत" है। हालांकि बात यह है कि मैं पुस्तकालय को बढ़ावा देने वाले प्रतिमान को पार करने वाले संदेश पर जाना चाहता हूं।

मैं निम्नलिखित समारोह पाया: zmq_socket_monitor

क्या यह करता सॉकेट इसे करने के लिए पारित कर दिया पर नजर रखने और घटनाओं है कि तब एक "inproc" समाप्ति बिंदु को पारित कर रहे हैं उत्पन्न है - उस बिंदु पर आप कोड से निपटने वास्तव में क्या करने के लिए जोड़ सकते हैं कुछ कुछ।

वहाँ भी एक उदाहरण है (वास्तव में परीक्षण code) यहाँ: github

मैं पल (शायद सप्ताह के अंत में) पर देने के लिए किसी भी विशिष्ट कोड नहीं मिला है लेकिन मेरा इरादा का जवाब करने के लिए है कनेक्ट करें और डिस्कनेक्ट करें कि मैं वास्तव में आवश्यक तर्क की किसी भी रीसेटिंग कर सकता हूं।

उम्मीद है कि यह मदद करता है, और 4.2 डॉक्स उद्धृत करने के बावजूद, मैं 4.0.4 का उपयोग कर रहा हूं, जिसमें कार्यक्षमता भी है।

नोट मैं नोटिस आप ऊपर अजगर के बारे में बात करते हैं, लेकिन सवाल टैग है सी ++ ताकि जहां मेरा उत्तर से आ रही है है ...

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

संबंधित मुद्दे