2016-05-21 7 views
7

मैं वर्तमान में एक लाइव मीडिया सर्वर पर काम कर रहा हूं, जो सामान्य उपभोक्ताओं को हमें लाइव वीडियो भेजने की अनुमति देगा। हमारे वर्तमान माहौल में हमने दिन की अवधि के साथ हमें भेजे गए ब्रॉडकास्ट देखे हैं, इसलिए उपयोगकर्ताओं को डिस्कनेक्ट किए बिना बग को ठीक करने में सक्षम होने का विचार (या एक सुविधा जोड़ें) बेहद आकर्षक है।एर्लांग हॉट कोड स्वैपिंग गतिविधि के बीच में कैसे काम करता है?

हालांकि जब मैं कोड लिख रहा था, मुझे एहसास हुआ कि गर्म कोड स्वैपिंग कोई समझ नहीं लेती है जब तक कि मैं हर प्रक्रिया को लिखता हूं ताकि सभी राज्य हमेशा gen_server के अंदर किए जाते हैं, और सभी बाह्य मॉड्यूल जो gen_server कॉल के रूप में सरल होना चाहिए मुमकिन।

-module(server_template). 
-behaviour(gen_server). 

-export([start/1, stop/0]). 
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). 

start() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). 

init([]) -> {ok, {module1:new(), module2:new()}}. 

handle_call(Message, From, State) -> {reply, ok, State}. 

handle_cast(any_message, {state1, state2}) -> 
    new_state1 = module1:do_something(state1), 
    new_state2 = module2:do_something(state2), 
    {noreply, {new_state1, new_state2}}. 

handle_info(_Message, _Server) -> {noreply, _Server}. 

terminate(_Reason, _Server) -> ok. 

code_change(_OldVersion, {state1, state2}, _Extra) -> 
    new_state1 = module1:code_change(state1), 
    new_state2 = module2:code_change(state2) 
    {ok, {new_state1, new_state2}} 

मैं, क्या मिल सकता है जब कोड का एक नया संस्करण OTP का प्रणाली का उपयोग किए बिना वर्तमान में चल रहे क्रम में लोड किया जाता के अनुसार, आप मौजूदा कोड में उन्नयन कर सकते हैं:

के निम्नलिखित उदाहरण लेते हैं अपने मॉड्यूल को बाहरी फ़ंक्शन कॉल के रूप में कॉल करके संस्करण, इसलिए my_module:loop(state)

मैं भी क्या देखते है कि जब एक गर्म स्वैप किया जाता है code_change/3 समारोह कहा जाता है और राज्य को अपग्रेड किए जाने, इसलिए मुझे लगता है कि उपयोग कर सकते हैं यकीन है कि मेरे निर्भर मॉड्यूल से प्रत्येक पिछले राज्य के लिए वे राज्य में मुझे दिया माइग्रेट करती बनाने के लिए वर्तमान कोड संस्करण। ऐसा इसलिए होता है क्योंकि पर्यवेक्षक चलने की प्रक्रिया के बारे में जानता है, जो प्रक्रिया को निलंबित करने की अनुमति देता है ताकि यह कोड परिवर्तन फ़ंक्शन को कॉल कर सके। सब अच्छा।

हालांकि, यदि बाहरी मॉड्यूल को कॉल करना हमेशा उस मॉड्यूल के वर्तमान संस्करण को कॉल करता है तो यह हॉट ब्रेक मिड-फ़ंक्शन होने पर तोड़ने लगते हैं। उदाहरण के लिए, मेरा gen_server वर्तमान में any_message कास्ट करने की प्रक्रिया में है, module1:do_something() और module2:do_something() चलाने के बीच में कहें।

मैं चीजों को सही ढंग से समझ रहा हूँ, तो module2:do_something() अब do_something समारोह, संभावित अर्थ हो सकता है जो मैं module2:do_something() के नए संस्करण में माइग्रेट नहीं की गई डेटा में गुजर रहा हूँ के नव वर्तमान संस्करण कहेंगे। यह आसानी से मुद्दों का कारण बनता है यदि यह एक रिकॉर्ड है जो बदल गया है, एक अनपेक्षित संख्या वाले तत्वों के साथ एक सरणी है, या यहां तक ​​कि यदि नक्शा उस मान को खो रहा है जो कोड की अपेक्षा करता है।

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

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

+1

आपको यह सही मिला। ओटीपी हॉट कोड अपग्रेड अधिक नियंत्रित करता है। यह ओटीपी अनुपालन कोड के निष्पादन को निलंबित करता है, नया संस्करण लोड करता है, 'कोड_चेंज/3'' कॉल करता है और फिर काम में जारी रहता है। यह बहुत अधिक नियंत्रित गर्म कोड अपग्रेड है। यह ठीक हो सकता है नया डेटा स्वरूप के साथ/1' दुर्घटनाओं do_something: दूसरी बात अगर कुछ दुर्घटनाओं, OTP इसलिए यदि आपके 'module2 आप बहुत जल्दी उसे पुन: प्रारंभ करने की अनुमति देता है।वे चीजें एक साथ हाथ में आती हैं और अभी भी परिमाण का क्रम किसी भी अन्य रनटाइम पर्यावरण की तुलना में सरल और अधिक मजबूत होती हैं। –

+2

असल में ओटीपी प्रक्रिया का निलंबन मेरे लिए बहुत स्पष्ट नहीं है। मुझे लगता है कि किसी भी प्रगति के बाद प्रक्रिया को निलंबित कर दिया गया है 'handle_call/handle_cast' कॉल प्रगति पर है, अन्यथा यह माइग्रेटेड स्थिति का उपयोग करने में सक्षम नहीं होगा, सही? – KallDrexx

+1

यह यहां बताया गया है (अद्यतन उपखंड में): http://erlang.org/doc/design_principles/release_handling.html#id78465 रिलीज हैंडलर 'sys: suspend/1,2',' sys: change_code/4,5 का उपयोग करता है ', और' sys: निलंबन/अपग्रेड करने के लिए फिर से शुरू करें/अपग्रेड करें, फिर अपग्रेड करें और फिर प्रक्रिया को फिर से शुरू करें। – Amiramix

उत्तर

7

हाँ, आप बिल्कुल सही हैं। कोई भी नहीं कहा कि गर्म कोड स्वैपिंग आसान है। मैंने एक दूरसंचार कंपनी के लिए काम किया जहां सभी कोड उन्नयन लाइव सिस्टम पर किए गए थे (ताकि उपयोगकर्ता उनकी कॉल के बीच में डिस्कनेक्ट न हों)। इसका सही अर्थ यह है कि आपने उन सभी परिदृश्यों पर ध्यान से विचार किया है जो आपने उल्लेख किया है और प्रत्येक विफलता के लिए कोड तैयार कर रहे हैं, फिर परीक्षण कर रहे हैं, फिर मुद्दों को ठीक करना, परीक्षण करना आदि। इसे सही तरीके से जांचने के लिए आपको लोड के तहत पुराने संस्करण को चलाने वाली प्रणाली की आवश्यकता होगी (उदाहरण के लिए एक परीक्षण वातावरण में), फिर नया कोड तैनात करना और किसी भी क्रैश की जांच करना।

इस प्रश्न में उल्लिखित इस विशेष उदाहरण में इस मुद्दे से निपटने का सबसे आसान तरीका module2:do_something/1 के दो संस्करणों को लिख रहा है, जो पुराने राज्य को स्वीकार करता है और एक नया राज्य स्वीकार करता है। फिर तदनुसार पुराने राज्य से निपटना, उदा। इसे नए राज्य में परिवर्तित करना।

इसके लिए काम करने के लिए आप यह भी सुनिश्चित करना है कि module2 के नए संस्करण तैनात किया जाता है से पहले किसी भी मॉड्यूल नए राज्य से कॉल करने के लिए एक मौका है की आवश्यकता होगी:

  1. तो module2 युक्त आवेदन एक है अन्य अनुप्रयोग की निर्भरता release_handler पहले उस मॉड्यूल को अपग्रेड करेगा।

  2. अन्यथा, आप इतना है कि वे, नए राज्य संभाल कर सकते हैं तो gen_servers के नए संस्करण और अन्य मॉड्यूल module2 को कॉल करने की तैनाती को दो भागों में विभाजित करने के लिए तैनाती, सबसे पहले आम कार्यों उन्नयन पड़ सकता है।

  3. यदि आप रिलीज हैंडलर का उपयोग नहीं कर रहे हैं तो आप मैन्युअल रूप से निर्दिष्ट कर सकते हैं कि मॉड्यूल को किस क्रम में लोड किया गया है।

यह भी कारण है कि Erlang में यह समारोह में advised to avoid circular dependencies मॉड्यूल, उदा के बीच कॉल है जब modAmodB में एक फ़ंक्शन कॉल करता है जो modA में एक और फ़ंक्शन कॉल करता है।

रिहाई हैंडलर की मदद से किया जाता आप जिस क्रम में release_handler कि release_handler old and new release के आधार पर उत्पन्न relup फ़ाइल में पुराने सिस्टम पर मॉड्यूल को अपग्रेड करेगा सत्यापित कर सकते हैं उन्नयन के लिए

। यह एक पाठ उन्नयन, उदाहरण के लिए सभी निर्देशों युक्त फ़ाइल है: (नया मॉड्यूल लोड) remove (मॉड्यूल हटाने के लिए), load_object_code, load, purge, आदि

कृपया ध्यान दें कोई सख्त आवश्यकता है कि सभी आवेदनों का पालन करना चाहिए है कि वहाँ काम करने के लिए हॉट कोड स्वैपिंग के लिए ओटीपी सिद्धांत, हालांकि gen_server और उचित supervisor स्टैक का उपयोग करके इस कार्य को डेवलपर और रिलीज हैंडलर दोनों के लिए संभालने में बहुत आसान बनाता है।

आप OTP रिहाई का उपयोग नहीं कर रहे हैं, तो आप रिलीज हैंडलर का उपयोग कर अपग्रेड नहीं कर सकते, लेकिन आप अभी भी जबरदस्ती अपने सिस्टम पर मॉड्यूल को फिर से लोड और उन्हें नए संस्करण में नवीनीकृत कर सकते हैं। यह तब तक ठीक काम करता है जब तक आपको Erlang अनुप्रयोगों को जोड़ने/निकालने की आवश्यकता नहीं होती है, क्योंकि इसके लिए रिलीज़ परिभाषा को बदलने की आवश्यकता होगी, और रिलीज हैंडलर के समर्थन के बिना लाइव सिस्टम पर नहीं किया जा सकता है।

1

रिलीज हैंडलिंग sys:suspend पर कॉल करता है जो gen_server को संदेश भेजता है। सर्वर प्रोसेसिंग अनुरोधों को तब तक रखेगा जब तक कि यह निलंबन संदेश को संभाल नहीं लेता है, जिस समय यह मूल रूप से बस बैठता है और इंतजार करता है। नया मॉड्यूल संस्करण तब सिस्टम में लोड किया जाता है, sys:change_code कहा जाता है जो सर्वर को code_change कॉलबैक को इसके अपग्रेड करने के लिए कॉल करने के लिए कहता है और फिर सर्वर फिर से बैठता है और इंतजार करता है। जब रिलीज हैंडलर sys:resume पर कॉल करता है तो यह सर्वर को एक संदेश भेजता है जो इसे वापस काम करने के लिए कहता है और आने वाले संदेशों को फिर से संसाधित करना शुरू करता है।

रिलीज हैंडलिंग एक ही समय में सभी सर्वरों के लिए करता है जो मॉड्यूल पर निर्भर हैं। तो सबसे पहले सभी को निलंबित कर दिया गया है, तो नया मॉड्यूल लोड हो गया है, तो सभी को स्वयं को अपग्रेड करने के लिए कहा जाता है और अंततः सभी को फिर से शुरू करने के लिए कहा जाता है।

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