2012-01-21 19 views
13

मैंने देखा है कि एक zeromq PUB सॉकेट उदाहरण के लिए बाहर जाने वाले सभी डेटा बफ़र्स अगर यह जोड़ता है, बफ़र्सZeroMQ PUB सॉकेट मेरे सभी बाहर जा रहा डेटा जब यह कनेक्ट हो रहा है

import zmq 
import time 
context = zmq.Context() 

# create a PUB socket 
pub = context.socket (zmq.PUB) 
pub.connect("tcp://127.0.0.1:5566") 
# push some message before connected 
# they should be dropped 
for i in range(5): 
    pub.send('a message should not be dropped') 

time.sleep(1) 

# create a SUB socket 
sub = context.socket (zmq.SUB) 
sub.bind("tcp://127.0.0.1:5566") 
sub.setsockopt(zmq.SUBSCRIBE, "") 

time.sleep(1) 

# this is the only message we should see in SUB 
pub.send('hi') 

while True: 
    print sub.recv() 

उप उन संदेशों के बाद बांधता है, वे गिरा दिया जाना चाहिए, क्योंकि यदि कोई इससे जुड़ा नहीं है तो PUB को संदेश छोड़ना चाहिए। लेकिन संदेशों को छोड़ने के बजाय, यह सभी संदेशों को बफर करता है।

a message should not be dropped 
a message should not be dropped 
a message should not be dropped 
a message should not be dropped 
a message should not be dropped 
hi 

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

import zmq 
import time 
context = zmq.Context() 

# create a PUB socket 
pub = context.socket (zmq.PUB) 
pub.bind("tcp://127.0.0.1:5566") 
# push some message before connected 
# they should be dropped 
for i in range(5): 
    pub.send('a message should not be dropped') 

time.sleep(1) 

# create a SUB socket 
sub = context.socket (zmq.SUB) 
sub.connect("tcp://127.0.0.1:5566") 
sub.setsockopt(zmq.SUBSCRIBE, "") 

time.sleep(1) 

# this is the only message we should see in SUB 
pub.send('hi') 

while True: 
    print repr(sub.recv()) 

और आप केवल उत्पादन

'hi' 

अजीब व्यवहार इस तरह की एक समस्या का कारण देख सकते हैं, यह एक जोड़ने सॉकेट पर सभी डेटा बफ़र्स, मैं दो सर्वर है, सर्वर एक डेटा सर्वर से प्रकाशित करता है बी

Server A -- publish --> Server B 

सर्वर बी ऑनलाइन होने पर यह ठीक काम करता है। लेकिन अगर मैं सर्वर ए शुरू करता हूं और सर्वर बी शुरू नहीं करता हूं तो क्या होगा?

परिणामस्वरूप, सर्वर ए पर कनेक्टिंग पब सॉकेट उन सभी डेटा को रखता है, स्मृति उपयोग उच्च और उच्च हो जाता है।

यहां समस्या है, क्या इस तरह का व्यवहार एक बग या फीचर है? यदि यह सुविधा है, तो मुझे यह दस्तावेज़ कहां मिल सकता है जो इस व्यवहार का उल्लेख करता है? और मैं कनेक्टिंग पब सॉकेट बफर को सभी डेटा कैसे रोक सकता हूं?

धन्यवाद।

उत्तर

6

सॉकेट ब्लॉक चाहे या संदेशों चला जाता है सॉकेट प्रकार ZMQ::Socket documentation में वर्णित के रूप पर निर्भर करता है (नीचे जोर मेरा है):

ZMQ :: HWM: पुन: प्राप्त उच्च पानी के निशान

ZMQ: : एचडब्ल्यूएम विकल्प निर्दिष्ट सॉकेट के लिए उच्च जल चिह्न पुनर्प्राप्त करेगा। उच्च पानी का निशान अधिकतम बकाया संदेशों की संख्या 0MQ किसी भी एकल सहकर्मी के लिए स्मृति में कतारबद्ध होगा जो निर्दिष्ट सॉकेट संचार कर रहा है।

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

शून्य का डिफ़ॉल्ट ZMQ :: HWM मान का अर्थ है "कोई सीमा नहीं"।

अगर यह ब्लॉक या ZMQ::HWM option action के लिए सॉकेट प्रकार के लिए प्रलेखन जो या तो Block या Drop हो जाएगा के माध्यम से देख कर छोड़ देंगे आप देख सकते हैं।

ZMQ::PUB के लिए कार्रवाई, Drop है इसलिए यदि यह छोड़ने आप HWM (उच्च जल मार्क) मूल्य की जाँच करें और चेतावनी है कि शून्य के डिफ़ॉल्ट ZMQ :: HWM मूल्य का मतलब है "कोई सीमा" पर ध्यान देना चाहिए नहीं है, जिसका अर्थ है कि यह एक असाधारण स्थिति में प्रवेश नहीं करेगा जब तक कि सिस्टम स्मृति से बाहर नहीं हो जाता (जिस बिंदु पर मुझे नहीं पता कि यह कैसे व्यवहार करता है)।

+0

मुझे पता है कि मैं बफर में संदेश संख्या को सीमित करने के लिए एचडब्लूएम सेट कर सकता हूं। लेकिन यह समस्या का समाधान नहीं करता है, वे जिस तरह से PUB हैंडल करता है एचडब्लूएम राज्य नए संदेशों को छोड़ना है। इसका मतलब है कि यदि आप एचडब्लूएम सेट करते हैं, तो केवल प्रमुख संदेश बफर में रखे जाते हैं। मैं जो लिख रहा हूं वह ऑडियो स्ट्रीमिंग सिस्टम है। इस प्रकार का व्यवहार इसे उपयोग करने में बहुत परेशान करता है। आइए मान लें, आप संदेश भेजते हैं [1, 2, 3, 4], और फिर एचडब्लूएम 2 पर सेट किया गया था, तो सॉकेट आपके लिए [1, 2] बफर करेगा, सभी नए संदेश गिराए जाएंगे। लेकिन ऑडियो स्ट्रीमिंग के लिए, सबसे महत्वपूर्ण हिस्सा नया आने वाला डेटा है। एचडब्लूएम संदेश कैसे छोड़ता है यह समायोजित करने का कोई तरीका है? –

+0

आह, तो आपका मतलब है कि आप जिस व्यवहार को पसंद करेंगे वह यह है कि यदि एचडब्लूएम 2 पर सेट है और आप [1, 2, 3, 4] भेजते हैं तो उसे [1, 2] छोड़ना चाहिए और [3, 4] रखना चाहिए, लेकिन फिर यदि आपने 5 भेजा है तो उसे 3 छोड़ना चाहिए और आप [4, 5] के साथ खत्म हो जाना चाहिए? मुझे नहीं लगता कि व्यवहार ZMQ में मौजूद है। – aculich

+0

यह बहुत दिलचस्प है। निश्चित रूप से कुछ पुराने अनुप्रयोगों के लिए "पुराने" संदेशों को छोड़ने की क्षमता आवश्यक होगी (आईपी टेलीफोनी एक आम उदाहरण के रूप में दिमाग में आता है)। –

0

तो बाध्य() और कनेक्ट() परिणाम दो अलग-अलग व्यवहार में होते हैं। आप सिर्फ यह नहीं चुनते कि आप कौन सा पसंद करते हैं (ऐसा लगता है कि यह बाध्य()) है और इसका उपयोग करें?

यह वास्तव में ज़ीरोएमक्यू की एक विशेषता है जो सामान्य रूप से कनेक्शन होने तक आउटगोइंग संदेशों को बफर करता है।

+0

क्योंकि मेरे पास एकाधिक नोड्स हैं जो डेटा को एक प्रसिद्ध सर्वर पर प्रकाशित करना चाहते हैं। बेशक मैं PUB पक्ष पर बाध्य कर सकता हूं, लेकिन नतीजतन, मुझे प्रत्येक नोड के लिए एन पता चाहिए, सर्वर नहीं जानता कि कितने नोड होंगे। मुझे लगता है कि बंधन और कनेक्ट व्यवहार को प्रभावित नहीं करना चाहिए, एक बार कनेक्शन बनने के बाद, बांधने और कनेक्ट करने के बीच कोई अंतर नहीं है, तो अंतर क्यों करें? मुझे समझ में नहीं आता: एस –

+0

ओह ठीक है। खैर मुझे लगता है कि ज़ीरोएमक्यू अपेक्षित और डिज़ाइन के रूप में व्यवहार कर रहा है, इसलिए आपको डेटा भेजने से पहले कनेक्शन से पूछना पड़ सकता है। –

+0

@ जोहानज़विनक 'बाइंड()' बनाम 'कनेक्ट() 'का चयन वरीयता पर आधारित नहीं है, बल्कि इसके आधार पर इसका उपयोग किया जाना चाहिए। वह सर्वर (प्रकाशक) पर 'बाइंड()' और क्लाइंट (ग्राहक) पर 'कनेक्ट()' के साथ सही तरीके से इसका उपयोग कर रहा है। और यह हमेशा आउटगोइंग संदेशों को बफर नहीं करता है, बल्कि इसके बजाय यह सॉकेट प्रकार और उच्च जल चिह्न के मान के रूप में निर्धारित किया जाता है [दस्तावेज़ीकरण के संदर्भों के साथ यहां समझाया गया है] (http://stackoverflow.com/a/8958699/462302)। – aculich

0

आपको पब सॉकेट एचडब्ल्यूएम सेटिंग का उपयोग करके सॉकेट में एक उच्च पानी का निशान सेट करने में सक्षम होना चाहिए। यह आपको परिभाषित करने देता है कि कितने संदेश रखे गए हैं।

1

वे सॉकेट पर एचडब्लूएम विकल्प सेट करते हैं।

4

मुझे लगता है कि यह व्यवहार zmq_connect() का अर्थपूर्ण है। यह है: जब zmq_connect() सफलता देता है, तो कनेक्शन अवधारणात्मक रूप से स्थापित होता है, और इस प्रकार आपका कनेक्टिंग-PUB छोड़ने के बजाय कतार संदेश शुरू करता है।

ØMQ सॉकेट के साथ सिद्धांत रूप में, यह कोई बात नहीं जो अंत जोड़ता है, और जो अंत बांधता:

"ZMQ Guide" से अंश के बाद इस बात के लिए एक संकेत है। हालांकि PUB-SUB सॉकेट के साथ, यदि आप SUB सॉकेट को बाध्य करते हैं और PUB सॉकेट कनेक्ट करते हैं, तो SUB सॉकेट पुराने संदेश प्राप्त कर सकता है, यानी एसयूबी शुरू होने से पहले भेजे गए संदेश। यह एक बाइंड/कनेक्ट काम के तरीके के आर्टिफैक्ट है। यदि आप कर सकते हैं तो PUB और को एसयूबी से कनेक्ट करना सबसे अच्छा है।

zmq_connect (में अनुभाग के बाद) कुछ संकेत, नीचे दिखाया गया है: पारंपरिक सॉकेट करने के लिए एक तुल्यकालिक इंटरफेस पेश

पारंपरिक सॉकेट

की कुंजी मतभेद सामान्य शब्दों में या तो कनेक्शन उन्मुख विश्वसनीय बाइट स्ट्रीम (SOCK_STREAM), या कनेक्शन-कम अविश्वसनीय डेटाग्राम (SOCK_DGRAM)। तुलनात्मक रूप से, ØMQ सॉकेट सॉकेट प्रकार के उपयोग के आधार पर सटीक क्यूइंग सेमेन्टिक्स के साथ, एसिंक्रोनस संदेश कतार का एक अमूर्त प्रस्तुत करते हैं। जहां परंपरागत सॉकेट बाइट्स या अलग डेटाग्राम की धाराओं को स्थानांतरित करते हैं, Øएमक्यू सॉकेट्स अलग-अलग संदेशों को स्थानांतरित करते हैं।

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

0

यहाँ एक हैक है कि मदद कर सकता है है ...

अपने ZMQ::HWM एक निश्चित संख्या के लिए सेट, 10 का कहना है।कनेक्शन पर, ग्राहक सॉकेट की recv विधि को लूप में तब तक कॉल करें जब तक कि यह सभी बफर किए गए संदेशों को त्याग न दे, और केवल तब ही अपना मुख्य प्राप्त लूप प्रारंभ करें।

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

  • कोई संबंधित समस्या नहीं^_^