नोड.जेड सर्वरसाइड - बग पर काम करते हैं। भाग 1

शुभ दोपहर

यह लेख उन डेवलपर्स के लिए लक्षित है जो नोड से परिचित हैं।

हाल ही में मैं उन तथ्यों पर सामग्री तैयार कर रहा था जो हमारे कार्यालय में नोड.जेएस के तहत डेवलपर्स के लिए जानना उपयोगी हैं। जिन परियोजनाओं पर हम काम कर रहे हैं, वे एपीआई सेवाएं हैं जो वेब सर्वर के रूप में नोड.जेएस एक्सप्रेस मॉड्यूल का उपयोग करती हैं। सामग्री वास्तविक मामलों पर आधारित है जिसमें कोड ने गलत तरीके से काम किया या इसमें तर्क ध्यान से छिपा हुआ था, या इसने विस्तार के दौरान त्रुटियों को उकसाया। इस सामग्री के आधार पर, एक कर्मचारी विकास कार्यशाला आयोजित की गई थी।

इसलिए, मैंने साझा करने का फैसला किया। अब तक, केवल पहला भाग लगभग 30% है। यदि रुचि है, तो जारी रखा जाएगा!

मैंने त्वरित परिचित के लिए एक अवसर प्रदान करने की कोशिश की, इसलिए मैंने बिगाड़ने वाले उदाहरणों, तर्क और टिप्पणियों को छिपा दिया। यदि कथन स्पष्ट हैं, तो आप "पानी" को छोड़ सकते हैं। हालांकि स्पॉइलर में हमारा "रेक" भी दिलचस्प हो सकता है।

संगोष्ठी के दौरान एक सहकर्मी ने मुझसे एक सवाल पूछा, इसके बारे में बात क्यों करें, अगर सब कुछ पहले से ही इस या उस दस्तावेज में है। मेरा उत्तर निम्नलिखित था। इस तथ्य के बावजूद कि संदेश सत्य है, सब कुछ वास्तव में प्रलेखन में है, हम अभी भी बुनियादी चीजों की गलतफहमी या अज्ञानता से संबंधित कष्टप्रद गलतियां करते हैं।

चलो शुरू हो जाओ!

वर्चुअल मशीन Node.js



एकल सूत्रण



जावम के विपरीत, नोडज-वीएम एकल-थ्रेडेड ** है



स्रोत

अधिक जानकारी
उसी समय, सहायक थ्रेड्स का एक पूल होता है जो कि वर्चुअल मशीन द्वारा उपयोग किया जाता है, उदाहरण के लिए, I / O को व्यवस्थित करने के लिए। लेकिन सभी उपयोगकर्ता कोड केवल एक "मुख्य" धागे में निष्पादित होते हैं।

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

यही है, अगर कोई आंतरिक डेटा संरचना है, तो आपको इसकी पहुंच को सिंक्रनाइज़ करने के बारे में चिंता करने की आवश्यकता नहीं है!

यदि "मुख्य" धागे के पास डेटा को संसाधित करने का समय नहीं है तो क्या करें?

स्केलिंग एक और नोड.जेएस प्रक्रिया शुरू करके या, यदि सर्वर संसाधन समाप्त हो रहे हैं, तो दूसरा सर्वर शुरू करके किया जाता है।

परिणाम और हमारे "रेक"
यहां भी सब कुछ स्पष्ट है। आपको हमेशा इस तथ्य के लिए तैयार रहना चाहिए कि एक से अधिक नोड हो सकते हैं (और सबसे अधिक संभावना है) एक नोड.जेएस प्रक्रिया होगी। और कभी-कभी कई सर्वर भी हो सकते हैं।

जो "रेक" छिपाया गया था, वह हमारे कोड में पाया गया है


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

सहकर्मी जो इसमें लगे थे, वास्तव में, वास्तविक डेटाबेस को शामिल किए बिना वास्तव में इसे लागू करना चाहते थे। अंत में, कुछ "प्रक्षेप्य के करीब" के बाद, यह एहसास हुआ ... SharePoint को शामिल करके।


** मल्टीथ्रेडिंग या "यदि आप वास्तव में चाहते हैं"



संस्करण 10.5.0 के साथ शुरू, नोड .js को मल्टीथ्रेडिंग के लिए प्रयोगात्मक समर्थन है


स्रोत

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

इसलिए, वर्कफ़्लो का उपयोग करते समय पुराना कोड काम करना जारी रखेगा।
और पढ़ें यहाँ


अनुप्रयोग जीवन चक्र



नोड्ज-वीएम का दिल ईवेंट लूप है। जब कोड निष्पादन को निलंबित कर दिया जाना चाहिए या कोड, ऐसा लगता है, समाप्त हो गया है, तो नियंत्रण इसे पास करता है।

छिपा हुआ पाठ
इवेंट लूप यह जाँचता है कि क्या (ओह) जिन घटनाओं के लिए हमने रजिस्टर किया है वे हैंडलर हुए हैं। अगर कुछ होता है, तो हैंडलर्स को बुलाया जाएगा। और यदि नहीं, तो यह जांचा जाएगा कि क्या कोई "जनरेटर" घटनाओं का है जिसके लिए हमारे पास पंजीकृत हैंडलर हैं। एक खुला tcp कनेक्शन या टाइमर ऐसे जनरेटर हो सकते हैं। यदि वे नहीं मिल सके, तो कार्यक्रम से बाहर निकल जाता है। अन्यथा, इन घटनाओं में से एक की उम्मीद है, हैंडलर को बुलाया जाता है, और सब कुछ दोहराता है।

इस व्यवहार का परिणाम यह है कि जब कोड खत्म हो जाता है, तो नोडज-वीएम से बाहर निकलना नहीं होता है, उदाहरण के लिए, क्योंकि हमने एक टाइमर हैंडलर पंजीकृत किया है, जिसे कुछ समय बाद बुलाया जाना चाहिए।

यह निम्नलिखित उदाहरण में दिखाया गया है।

console.log('registering timer callbacks'); setTimeout( function() { console.log('Timer Event 1'); }, 1000); console.log('Is it the end?'); 


परिणाम:
 registering timer callbacks Is it the end? Timer Event 1 


और पढ़ें यहाँ

हमारे कोड में एक और "रेक"



हर कोई राज्य का प्रबंधन कर सकता है!
उपयोगकर्ता एक व्यवस्थापक है या नहीं इसका संकेत एक वैश्विक चर में संग्रहीत किया गया था। इस चर को कार्यक्रम की शुरुआत में गलत बताया गया था। बाद में, जब व्यवस्थापक ने पंजीकृत किया, तो यह चर सत्य पर सेट किया गया था।

नतीजतन, यदि व्यवस्थापक ने सिस्टम का दौरा किया, तो किसी भी उपयोगकर्ता जो सेवा के इस उदाहरण तक पहुंचता है, उसे व्यवस्थापक के रूप में माना जाता था।

मुझे अपने सहकर्मी को दिखाने के लिए कुछ प्रयास करना पड़ा कि तर्क में एक गलती थी। एक सहकर्मी सुनिश्चित था कि हर HTTP अनुरोध के लिए एक पूरी तरह से नया वातावरण बनाया जाता है।


package.json - भरने के लायक क्षेत्र



package.json हमारे पैकेज के लिए विवरण फ़ाइल है। इस संदर्भ में, यह हमारे आवेदन के बारे में है, न कि निर्भरता के बारे में। नीचे सूचीबद्ध फ़ील्ड और स्पष्टीकरण क्यों हैं, यह उन सभी को भरने के लायक है।

छिपा हुआ पाठ

नाम


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

संस्करण


मुख्य विचार कार्यक्षमता को बढ़ाते हुए, बग को ठीक करते हुए संस्करण संख्या को बढ़ाना नहीं है, ... दुर्भाग्य से, हमारे कार्यालय में आप अभी भी अपरिवर्तित संस्करण 0.0.0 के साथ उत्पाद पा सकते हैं। और फिर अनुमान लगाओ कि क्लाइंट के लिए किस तरह की कार्यक्षमता काम करती है ...

मुख्य


यह फ़ील्ड बताती है कि हमारा एप्लिकेशन कब शुरू होगा (`npm start`)। यदि पैकेज का उपयोग एक निर्भरता के रूप में किया जाता है, तो हमारे मॉड्यूल को किसी अन्य एप्लिकेशन द्वारा उपयोग करते समय कौन सी फ़ाइल आयात की जाएगी। वर्तमान निर्देशिका वह निर्देशिका है जहाँ `package.json` फ़ाइल स्थित है।

और यह भी, यदि हम, उदाहरण के लिए, vscode का उपयोग करते हैं , तो इस फ़ील्ड में निर्दिष्ट फ़ाइल को लॉन्च किया जाएगा जब डिबगर को बुलाया जाएगा या जब "निष्पादित" कमांड चलाया जाएगा।

एक्सटेंशन ".js" छोड़ा जा सकता है। यह बल्कि सभी संभावित उपयोग के मामलों का एक परिणाम है, इसलिए यह सीधे प्रलेखन में वर्तनी नहीं है।

इंजन


इस फ़ील्ड में टपल शामिल है: {"नोड": संस्करण , "एनपीएम": संस्करण , ...}।

मैं "नोड" और "एनपीएम" क्षेत्रों को जानता हूं। वे हमारे आवेदन के लिए आवश्यक नोड.जेएस और एनपीएम के संस्करणों को निर्धारित करते हैं। Npm इंस्टॉल कमांड को चलाकर संस्करणों की जाँच की जाती है।

निर्भरता संकुल के संस्करण के निर्धारण के लिए मानक वाक्यविन्यास समर्थित है: उपसर्ग (एकल संस्करण) के बिना, उपसर्ग "~" (संस्करण की पहली दो संख्याओं का मिलान होना चाहिए) और उपसर्ग "^" (केवल संस्करण का पहला नंबर मिलान कर सकता है)। यदि कोई उपसर्ग है, तो संस्करण इस क्षेत्र में निर्दिष्ट से अधिक या उसके बराबर होना चाहिए। संस्करणों की बस एक सूची; स्पष्ट संकेत अधिक, कम, ... आदि। भी काम करता है।

अस्वीकरण। "एनपीएम इंस्टॉल" केवल "इंजन-सख्त" मोड सक्षम होने पर "इंजन" में निर्दिष्ट संस्करणों की जांच करता है। हम इसे प्रत्येक प्रोजेक्ट के लिए शामिल करते हैं, लाइन के साथ .npmrc फ़ाइल को जोड़ना: "इंजन-सख्त = सच"। एक बार, "npm इंस्टॉल" ने यह चेक डिफ़ॉल्ट रूप से किया।

कुछ कंटेनर, कम से कम प्रलेखन में लिखते हैं कि उपयुक्त संस्करण डिफ़ॉल्ट रूप से उपयोग किए जाएंगे। इस मामले में, हम Azure के बारे में बात कर रहे हैं।

एक उदाहरण:
 "engines": { "node": "~8.11", // require node version 8.11.* starting from 8.11.0 "npm": "^6.0.1" // require npm version 6.* starting from 6.0.1 }, 


नियमित "रेक"



और राजा नंगा है!

यह क्लाइंट के साथ बार-बार सहमत था कि `नोड.जेएस` का आवश्यक संस्करण कम से कम 8. होना चाहिए। जब ​​आवेदन के प्रारंभिक संस्करण वितरित किए गए, तो सब कुछ काम किया। "एक दिन" ग्राहक पर नए संस्करण की डिलीवरी के बाद, अनुप्रयोग चलना बंद हो गया। सब कुछ हमारे परीक्षणों में काम आया।

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

स्क्रिप्ट


फ़ील्ड में फ़ॉर्म का एक टपल होता है: {"script1": script1 , "script2": script2 , ...}।

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

इस मामले में, आप केवल मानक नामों तक सीमित नहीं हो सकते। एक मनमानी स्क्रिप्ट को निष्पादित करने के लिए, आपको "एनपीएम रन स्क्रिप्ट-नाम " चलाने की आवश्यकता है।

सभी प्रयुक्त लिपियों को एक स्थान पर एकत्रित करना सुविधाजनक है।

एक उदाहरण:
  "scripts": { "install": "node scripts/install-extras", "start": "node src/well/hidden/main/server extra_param_1 extra_param_2", "another-script": "node scripts/another-script" } 


PS विस्तार ".js" को ज्यादातर मामलों में छोड़ा जा सकता है।


package-lock.json - निर्भरता के विशिष्ट संस्करणों को स्थापित करने में मदद करता है, न कि "नवीनतम" वाले



छिपा हुआ पाठ
गेस करना है या नहीं करना है? ..


यह फ़ाइल अपेक्षाकृत हाल ही में npm में दिखाई दी। इसका उद्देश्य विधानसभा की पुनरावृत्ति को व्यवस्थित करना है।

और एक और "रेक"


लेकिन मैंने अपने कार्यक्रम में कुछ भी नहीं बदला! कल उसने काम किया!


एक सहकर्मी मशीन पर, एप्लिकेशन ने बहुत अच्छा काम किया। एक समान वातावरण में एक और कंप्यूटर पर, गिट से एक नई निर्देशिका के लिए रखे गए एप्लिकेशन में, 'एनपीएम इंस्टॉल' को निष्पादित करने के बाद, 'एनपीएम स्टार्ट' हिथरेओ अभूतपूर्व त्रुटियां दिखाई दीं।

समस्या इस तथ्य के कारण थी कि फ़ाइल 'पैकेज-लॉक.जसन' गिट रिपॉजिटरी से गायब थी। इसलिए, पैकेजों की स्थापना के दौरान, दूसरे या अधिक स्तरों की सभी निर्भरताएं (स्वाभाविक रूप से, पैकेज.जसन में नहीं लिखी गई) को यथासंभव नए सिरे से स्थापित किया गया था। एक सहयोगी के कंप्यूटर पर, सब कुछ ठीक था। परीक्षण किए गए कंप्यूटर पर संस्करणों का एक असंगत सेट चुना गया था।

पैकेज- lock.json - git करने के लिए!



विषयांतर से लौटना। फ़ाइल 'पैकेज-लॉक.जसन' में हमारे आवेदन के लिए स्थानीय रूप से स्थापित सभी मॉड्यूलों की एक सूची है। इस फ़ाइल की उपस्थिति आपको मॉड्यूल के संस्करणों के एक-से-एक सेट को फिर से बनाने की अनुमति देती है।

सारांश: गिट में डालना और आवेदन की डिलीवरी (स्थापना) फ़ाइल में शामिल करना न भूलें!

उपयोगी: यदि फ़ाइल 'package-lock.json' गायब है, लेकिन सभी आवश्यक मॉड्यूल के साथ एक निर्देशिका 'node_modules' है, तो फ़ाइल 'package-lock.json' को फिर से बनाया जा सकता है:
 npm shrinkwrap rename npm-shrinkwrap.json package-lock.json 



आप अभी के लिए इस पर विराम लगा सकते हैं। शामिल नहीं की गई जानकारी हमारी टीम द्वारा उपयोग की जाने वाली कोड सरलीकरण तकनीक है।

यदि त्रुटियों का पता चला है, तो मैं उन्हें जल्दी से ठीक करने की कोशिश करूंगा!

Source: https://habr.com/ru/post/hi430972/


All Articles