erlang जो आर्मस्ट्रांग




ओटीपी-सिंक्रोनस बनाम एसिंक्रोनस मैसेजिंग (3)

अस्वीकरण: एर्लांग नौसिखिया

उन चीजों में से एक जो मुझे पहली जगह में इरलेंग करने के लिए आकर्षित किया, अभिनेता मॉडल है; यह विचार है कि विभिन्न प्रक्रियाएं समवर्ती रूप से चलती हैं और एसिंक्रोनस मैसेजिंग के माध्यम से बातचीत करती हैं।

मैं बस अपने दांतों को ओटीपी में लाने के लिए शुरू कर रहा हूं और विशेष रूप से जीएन_सर्वर को देख रहा हूं। सभी उदाहरण मैंने देखा है - और दी है कि वे ट्यूटोरियल टाइप उदाहरण हैं - handle_call() उपयोग करने के बजाय handle_cast() को मॉड्यूल व्यवहार को लागू करने के लिए।

मुझे लगता है कि थोड़ा भ्रमित है। जहाँ तक मैं बता सकता हूं, handle_call एक तुल्यकालिक ऑपरेशन है: कॉलर को तब तक अवरुद्ध किया जाता है जब तक कैली पूर्ण न हो और रिटर्न कौन सा एन्सिंक संदेश गुजर दर्शन के लिए काउंटर चलाने लगता है

मैं एक नया ओटीपी अनुप्रयोग शुरू करने के बारे में हूँ यह एक बुनियादी वास्तुशास्त्रीय निर्णय जैसा लगता है, इसलिए मैं यह सुनिश्चित करना चाहता हूं कि मैं शुरू से पहले समझता हूं।

विशिष्ट होने के लिए, मेरे प्रश्न हैं:

  1. असली अभ्यास में लोगों को handle_cast के बजाय handle_call का उपयोग करते हैं?
  2. यदि हां, तो एकाधिक ग्राहक एक ही प्रक्रिया / मॉड्यूल पर कॉल कर सकते हैं, तो स्केलेबिलिटी क्या है?

धन्यवाद।


  1. आपकी स्थिति पर निर्भर करता है

    यदि आप परिणाम प्राप्त करना चाहते हैं, तो handle_call वास्तव में आम है। यदि आपको कॉल के परिणाम में कोई दिलचस्पी नहीं है, तो handle_cast उपयोग करें जब handle_call उपयोग किया जाता है, तो कॉलर ब्लॉक हो जाएगा, हाँ। यह सबसे अधिक समय ठीक है। चलो एक उदाहरण पर एक नज़र डालें।

    यदि आपके पास एक वेब सर्वर है, जो ग्राहकों की फ़ाइलों की सामग्री को रिटर्न देता है, तो आप एकाधिक क्लाइंट को प्रबंधित कर सकेंगे। प्रत्येक ग्राहक को फ़ाइलों की सामग्री पढ़ने के लिए इंतजार करना होगा, इसलिए इस स्थिति में handle_call का उपयोग करना बिल्कुल ठीक होगा (बेवकूफ़ उदाहरण एक तरफ)

    जब आपको वास्तव में एक अनुरोध भेजने का व्यवहार करने की आवश्यकता होती है, कुछ अन्य प्रसंस्करण करते हैं और बाद में उत्तर प्राप्त करते हैं, तो आम तौर पर दो कॉल का उपयोग किया जाता है (उदाहरण के लिए, एक कलाकार और परिणाम प्राप्त करने के लिए एक कॉल) लेकिन यह काफी दुर्लभ मामला है।

  2. handle_call का उपयोग कॉल की अवधि के लिए प्रक्रिया को अवरुद्ध करेगा। इससे ग्राहकों को उनके उत्तर प्राप्त करने के लिए कतारबद्ध हो जाएगा और इस प्रकार पूरी चीज अनुक्रम में चलेगी।

    यदि आप समानांतर कोड चाहते हैं, तो आपको समानांतर कोड लिखना होगा। ऐसा करने का एकमात्र तरीका है कि एकाधिक प्रक्रियाएं चलाना है।

तो, संक्षेप में:

  • handle_call का उपयोग करना handle_call को अवरुद्ध करेगा और कॉल की अवधि के लिए बुलाए जाने वाली प्रक्रिया पर कब्जा करेगा।
  • यदि आप समानांतर गतिविधियों को चालू करना चाहते हैं, तो आपको समानांतर करना होगा। ऐसा करने का एकमात्र तरीका अधिक प्रक्रियाएं शुरू करना है, और अचानक कॉल बनाम कास्ट इतना बड़ा मुद्दा नहीं है (वास्तव में, यह कॉल के साथ अधिक सहज है)।

आईएमओ, समवर्ती विश्व handle_call में आम तौर पर एक बुरा विचार है। कहते हैं कि हमारे पास प्रो ए (जीएन_सरिव) है जो कुछ इवेंट प्राप्त कर रहा है (यूजर ने एक बटन दबाया है), और फिर इस दबाए बटन के भारी प्रसंस्करण का अनुरोध करने वाले बी (जीएन_सर्वर) की प्रक्रिया के लिए संदेश कास्ट कर रहा है। प्रक्रिया बी उप-प्रक्रिया सी पैदा कर सकता है, जो बदले में संदेश भेजता है जब तैयार हो जाता है (बी के लिए जो ए को संदेश भेजता है)। प्रसंस्करण समय के दौरान ए और बी दोनों नए अनुरोध स्वीकार करने के लिए तैयार हैं। जब ए को सी (या बी) से संदेश भेजता है, उदाहरण के लिए उपयोगकर्ता के परिणाम दिखाता है। बेशक, यह संभव है कि दूसरा बटन पहले से संसाधित हो जाएगा, इसलिए किसी को उचित क्रम में परिणाम जमा करना चाहिए। handle_call माध्यम से ए और बी को अवरुद्ध करने से इस प्रणाली को एकल-पिरोया मिलेगा (यद्यपि समस्या को हल करने का समाधान होगा)

वास्तव में, सी पैदा करना handle_call समान है, अंतर यह है कि सी अत्यधिक विशिष्ट है, प्रक्रिया केवल "एक संदेश" है और उसके बाद से निकलती है बी को अन्य कार्यक्षमता माना जाता है (जैसे श्रमिकों की सीमा संख्या, नियंत्रण समय सीमा), अन्यथा सी ए से पैदा की जा सकती है।

संपादित करें: सी अतुल्यकालिक भी है, इसलिए सी पैदा होती है यह handle_call (बी अवरुद्ध नहीं है) के समान नहीं है।


इसके साथ जाने के दो तरीके हैं एक एक घटना प्रबंधन दृष्टिकोण का उपयोग करने के लिए बदलना है मैं जिस का उपयोग कर रहा हूं, वह दिखा रहा है कि कास्ट का इस्तेमाल करना है ...

    submit(ResourceId,Query) ->
      %%
      %% non blocking query submission
      %%
      Ref = make_ref(),
      From = {self(),Ref},
      gen_server:cast(ResourceId,{submit,From,Query}),
      {ok,Ref}.

और डाली / सबमिट कोड है ...

    handle_cast({submit,{Pid,Ref},Query},State) ->
      Result = process_query(Query,State),
      gen_server:cast(Pid,{query_result,Ref,Result});

संदर्भ का उपयोग एसिंक्रोनस क्वेरी को ट्रैक करने के लिए किया जाता है





erlang