पिछले महीने से, मैं CouchDB से संबंधित प्रूफ-ऑफ-कॉन्सेप्ट परियोजनाओं पर सक्रिय रूप से काम कर रहा हूं, इसकी विशेषताओं की खोज कर रहा हूं और भविष्य के कार्यों की तैयारी कर रहा हूं। इस अवधि के दौरान, मैंने यह सुनिश्चित करने के लिए कि सब कुछ कैसे काम करता है, CouchDB दस्तावेज़ का कई बार अध्ययन किया है। दस्तावेज़ पढ़ते समय, मुझे एक बयान मिला कि जावास्क्रिप्ट में लिखे डिफ़ॉल्ट क्वेरी सर्वर के साथ CouchDB शिपिंग के बावजूद, एक कस्टम कार्यान्वयन बनाना अपेक्षाकृत सरल है और कस्टम समाधान पहले से ही मौजूद हैं।
मैंने कुछ त्वरित शोध किया और कार्यान्वयन को पायथन, रूबी या क्लोजर में लिखा हुआ पाया। चूंकि संपूर्ण कार्यान्वयन बहुत लंबा नहीं लग रहा था, इसलिए मैंने अपना स्वयं का कस्टम क्वेरी सर्वर लिखने का प्रयास करके CouchDB के साथ प्रयोग करने का निर्णय लिया। ऐसा करने के लिए, मैंने गो को भाषा के रूप में चुना। हेल्म के चार्ट में गो टेम्प्लेट का उपयोग करने के अलावा, मुझे पहले इस भाषा के साथ ज्यादा अनुभव नहीं था, लेकिन मैं कुछ नया आज़माना चाहता था और सोचा कि यह प्रोजेक्ट इसके लिए एक शानदार अवसर होगा।
काम शुरू करने से पहले, मैंने यह समझने के लिए कि क्वेरी सर्वर वास्तव में कैसे काम करता है, CouchDB दस्तावेज़ को एक बार फिर से देखा। दस्तावेज़ीकरण के अनुसार, क्वेरी सर्वर का उच्च-स्तरीय अवलोकन काफी सरल है:
क्वेरी सर्वर एक बाहरी प्रक्रिया है जो एक stdio इंटरफ़ेस पर JSON प्रोटोकॉल के माध्यम से CouchDB के साथ संचार करता है और सभी डिज़ाइन फ़ंक्शन कॉल को संभालता है…।
CouchDB द्वारा क्वेरी सर्वर पर भेजे गए कमांड की संरचना को [, ] या ["ddoc",
तो मूल रूप से, मुझे जो करना था वह STDIO से इस प्रकार के JSON को पार्स करने, अपेक्षित संचालन करने और दस्तावेज़ में निर्दिष्ट प्रतिक्रियाओं को वापस करने में सक्षम एक एप्लिकेशन लिखना था। गो कोड में कमांड की एक विस्तृत श्रृंखला को संभालने के लिए कई प्रकार की कास्टिंग शामिल थी। प्रत्येक कमांड के बारे में विशिष्ट विवरण दस्तावेज़ के क्वेरी सर्वर प्रोटोकॉल अनुभाग के अंतर्गत पाया जा सकता है।
एक समस्या जिसका मुझे यहां सामना करना पड़ा वह यह थी कि क्वेरी सर्वर को डिज़ाइन दस्तावेज़ों में प्रदान किए गए मनमाने कोड की व्याख्या और निष्पादन करने में सक्षम होना चाहिए। यह जानते हुए कि गो एक संकलित भाषा है, मुझे इस बिंदु पर फंसने की उम्मीद थी। शुक्र है, मुझे तुरंत येगी पैकेज मिल गया, जो आसानी से गो कोड की व्याख्या करने में सक्षम है। यह एक सैंडबॉक्स बनाने और व्याख्या किए गए कोड में कौन से पैकेज आयात किए जा सकते हैं, इसकी पहुंच को नियंत्रित करने की अनुमति देता है। मेरे मामले में, मैंने केवल काउचगो नामक अपने पैकेज को उजागर करने का निर्णय लिया, लेकिन अन्य मानक पैकेज भी आसानी से जोड़े जा सकते हैं।
मेरे काम के परिणामस्वरूप, काउचगो नामक एक एप्लिकेशन! उभरा। हालाँकि यह क्वेरी सर्वर प्रोटोकॉल का पालन करता है, यह जावास्क्रिप्ट संस्करण का एक-से-एक पुन: कार्यान्वयन नहीं है क्योंकि डिज़ाइन दस्तावेज़ कार्यों को संभालने के लिए इसके अपने दृष्टिकोण हैं।
उदाहरण के लिए, CouchGO! में, एमिट जैसा कोई सहायक कार्य नहीं है। मान उत्सर्जित करने के लिए, आप बस उन्हें मानचित्र फ़ंक्शन से वापस कर दें। इसके अतिरिक्त, डिज़ाइन दस्तावेज़ में प्रत्येक फ़ंक्शन एक ही पैटर्न का पालन करता है: इसमें केवल एक तर्क होता है, जो फ़ंक्शन-विशिष्ट गुणों वाला एक ऑब्जेक्ट होता है, और परिणामस्वरूप केवल एक मान लौटाना होता है। इस मान का आदिम होना आवश्यक नहीं है; फ़ंक्शन के आधार पर, यह एक ऑब्जेक्ट, एक मानचित्र या एक त्रुटि भी हो सकती है।
CouchGO! के साथ काम करना शुरू करने के लिए, आपको बस मेरे GitHub रिपॉजिटरी से निष्पादन योग्य बाइनरी डाउनलोड करना होगा, इसे CouchDB इंस्टेंस में कहीं रखना होगा, और एक पर्यावरण चर जोड़ना होगा जो CouchDB को CouchGO शुरू करने की अनुमति देता है! प्रक्रिया।
उदाहरण के लिए, यदि आप काउचगो निष्पादन योग्य को /opt/couchdb/bin निर्देशिका में रखते हैं, तो आप इसे काम करने में सक्षम करने के लिए निम्नलिखित पर्यावरण चर जोड़ेंगे।
export COUCHDB_QUERY_SERVER_GO="/opt/couchdb/bin/couchgo"
काउचगो के साथ फ़ंक्शन लिखने के तरीके की त्वरित समझ हासिल करने के लिए, आइए निम्नलिखित फ़ंक्शन इंटरफ़ेस का पता लगाएं:
func Func(args couchgo.FuncInput) couchgo.FuncOutput { ... }
काउचगो में प्रत्येक फ़ंक्शन! इस पैटर्न का अनुसरण करेगा, जहां Func को उपयुक्त फ़ंक्शन नाम से बदल दिया गया है। वर्तमान में, काउचगो! निम्नलिखित फ़ंक्शन प्रकारों का समर्थन करता है:
आइए एक उदाहरण डिज़ाइन दस्तावेज़ की जांच करें जो मानचित्र और कम कार्यों के साथ-साथ एक मान्य_doc_update फ़ंक्शन के साथ एक दृश्य निर्दिष्ट करता है। इसके अतिरिक्त, हमें यह निर्दिष्ट करने की आवश्यकता है कि हम भाषा के रूप में गो का उपयोग कर रहे हैं।
{ "_id": "_design/ddoc-go", "views": { "view": { "map": "func Map(args couchgo.MapInput) couchgo.MapOutput {\n\tout := couchgo.MapOutput{}\n\tout = append(out, [2]interface{}{args.Doc[\"_id\"], 1})\n\tout = append(out, [2]interface{}{args.Doc[\"_id\"], 2})\n\tout = append(out, [2]interface{}{args.Doc[\"_id\"], 3})\n\t\n\treturn out\n}", "reduce": "func Reduce(args couchgo.ReduceInput) couchgo.ReduceOutput {\n\tout := 0.0\n\n\tfor _, value := range args.Values {\n\t\tout = value.(float64)\n\t}\n\n\treturn out\n}" } }, "validate_doc_update": "func Validate(args couchgo.ValidateInput) couchgo.ValidateOutput {\n\tif args.NewDoc[\"type\"] == \"post\" {\n\t\tif args.NewDoc[\"title\"] == nil || args.NewDoc[\"content\"] == nil {\n\t\t\treturn couchgo.ForbiddenError{Message: \"Title and content are required\"}\n\t\t}\n\n\t\treturn nil\n\t}\n\n\tif args.NewDoc[\"type\"] == \"comment\" {\n\t\tif args.NewDoc[\"post\"] == nil || args.NewDoc[\"author\"] == nil || args.NewDoc[\"content\"] == nil {\n\t\t\treturn couchgo.ForbiddenError{Message: \"Post, author, and content are required\"}\n\t\t}\n\n\t\treturn nil\n\t}\n\n\tif args.NewDoc[\"type\"] == \"user\" {\n\t\tif args.NewDoc[\"username\"] == nil || args.NewDoc[\"email\"] == nil {\n\t\t\treturn couchgo.ForbiddenError{Message: \"Username and email are required\"}\n\t\t}\n\n\t\treturn nil\n\t}\n\n\treturn couchgo.ForbiddenError{Message: \"Invalid document type\"}\n}", "language": "go" }
अब, मानचित्र फ़ंक्शन से शुरू होने वाले प्रत्येक फ़ंक्शन को तोड़ें:
func Map(args couchgo.MapInput) couchgo.MapOutput { out := couchgo.MapOutput{} out = append(out, [2]interface{}{args.Doc["_id"], 1}) out = append(out, [2]interface{}{args.Doc["_id"], 2}) out = append(out, [2]interface{}{args.Doc["_id"], 3}) return out }
CouchGO! में, कोई उत्सर्जन फ़ंक्शन नहीं है; इसके बजाय, आप कुंजी-मूल्य टुपल्स का एक टुकड़ा लौटाते हैं जहां कुंजी और मूल्य दोनों किसी भी प्रकार के हो सकते हैं। दस्तावेज़ ऑब्जेक्ट को जावास्क्रिप्ट की तरह सीधे फ़ंक्शन में पास नहीं किया जाता है; बल्कि, यह किसी वस्तु में लिपटा हुआ है। दस्तावेज़ स्वयं विभिन्न मूल्यों का एक हैशमैप मात्र है।
अगला, आइए कम फ़ंक्शन की जांच करें:
func Reduce(args couchgo.ReduceInput) couchgo.ReduceOutput { out := 0.0 for _, value := range args.Values { out = value.(float64) } return out }
जावास्क्रिप्ट के समान, काउचगो में रिड्यूस फ़ंक्शन! कुंजियाँ, मान और एक पुनः कम करने वाला पैरामीटर लेता है, सभी को एक ही ऑब्जेक्ट में लपेटा जाता है। इस फ़ंक्शन को किसी भी प्रकार का एकल मान लौटाना चाहिए जो कमी ऑपरेशन के परिणाम का प्रतिनिधित्व करता है।
अंत में, आइए वैलिडेट फ़ंक्शन को देखें, जो वैलिडेट_डॉक_अपडेट प्रॉपर्टी से मेल खाता है:
func Validate(args couchgo.ValidateInput) couchgo.ValidateOutput { if args.NewDoc["type"] == "post" { if args.NewDoc["title"] == nil || args.NewDoc["content"] == nil { return couchgo.ForbiddenError{Message: "Title and content are required"} } return nil } if args.NewDoc["type"] == "comment" { if args.NewDoc["post"] == nil || args.NewDoc["author"] == nil || args.NewDoc["content"] == nil { return couchgo.ForbiddenError{Message: "Post, author, and content are required"} } return nil } return nil }
इस फ़ंक्शन में, हमें नए दस्तावेज़, पुराने दस्तावेज़, उपयोगकर्ता संदर्भ और सुरक्षा ऑब्जेक्ट जैसे पैरामीटर प्राप्त होते हैं, सभी एक फ़ंक्शन तर्क के रूप में पारित एक ऑब्जेक्ट में लपेटे जाते हैं। यहां, हमसे अपेक्षा की जाती है कि हम सत्यापित करें कि क्या दस्तावेज़ को अद्यतन किया जा सकता है और यदि नहीं तो एक त्रुटि लौटाएँ। जावास्क्रिप्ट संस्करण के समान, हम दो प्रकार की त्रुटियाँ लौटा सकते हैं: ForbiddenError या UnauthorizedError। यदि दस्तावेज़ अद्यतन किया जा सकता है, तो हमें शून्य लौटना चाहिए।
अधिक विस्तृत उदाहरणों के लिए, वे मेरे GitHub रिपॉजिटरी में पाए जा सकते हैं। ध्यान देने योग्य एक महत्वपूर्ण बात यह है कि फ़ंक्शन नाम मनमाने नहीं हैं; उन्हें हमेशा उस फ़ंक्शन के प्रकार से मेल खाना चाहिए जिसका वे प्रतिनिधित्व करते हैं, जैसे मानचित्र, रिड्यूस, फ़िल्टर, आदि।
हालाँकि अपना स्वयं का क्वेरी सर्वर लिखना वास्तव में एक मजेदार अनुभव था, अगर मैं मौजूदा समाधानों के साथ इसकी तुलना नहीं करता तो इसका कोई मतलब नहीं होता। इसलिए, मैंने यह जांचने के लिए डॉकर कंटेनर में कुछ सरल परीक्षण तैयार किए कि काउचगो कितना तेज़ है! कर सकना:
मैंने डेटाबेस को दस्तावेज़ों की अपेक्षित संख्या के साथ जोड़ा और समर्पित शेल स्क्रिप्ट का उपयोग करके डॉकर कंटेनर से प्रतिक्रिया समय या विभेदित टाइमस्टैम्प लॉग को मापा। कार्यान्वयन का विवरण मेरे GitHub रिपॉजिटरी में पाया जा सकता है। परिणाम नीचे दी गई तालिका में प्रस्तुत किए गए हैं।
परीक्षा | काउचगो! | काउचजेएस | बढ़ाना |
---|---|---|---|
अनुक्रमण | 141.713s | 421.529s | 2.97x |
कम करना | 7672 एमएस | 15642 एमएस | 2.04x |
फ़िल्टरिंग | 28.928s | 80.594s | 2.79x |
अपडेट किया जा रहा है | 7.742s | 9.661s | 1.25x |
जैसा कि आप देख सकते हैं, जावास्क्रिप्ट कार्यान्वयन पर वृद्धि महत्वपूर्ण है: अनुक्रमण के मामले में लगभग तीन गुना तेज, कम करने और फ़िल्टर कार्यों के लिए दोगुने से अधिक तेज। अपडेट फ़ंक्शंस के लिए बूस्ट अपेक्षाकृत छोटा है, लेकिन फिर भी जावास्क्रिप्ट से तेज़ है।
जैसा कि दस्तावेज़ के लेखक ने वादा किया था, क्वेरी सर्वर प्रोटोकॉल का पालन करते समय एक कस्टम क्वेरी सर्वर लिखना उतना कठिन नहीं था। हालांकि काउचगो! सामान्य तौर पर इसमें कुछ अप्रचलित कार्यों का अभाव है, यह विकास के इस प्रारंभिक चरण में भी जावास्क्रिप्ट संस्करण पर एक महत्वपूर्ण बढ़ावा प्रदान करता है। मेरा मानना है कि अभी भी सुधार की काफी गुंजाइश है।
यदि आपको इस लेख के सभी कोड एक ही स्थान पर चाहिए, तो आप इसे मेरे GitHub रिपॉजिटरी में पा सकते हैं।
इस आलेख को पढ़ने के लिए धन्यवाद। मुझे इस समाधान के बारे में आपके विचार सुनना अच्छा लगेगा। क्या आप इसे अपने CouchDB इंस्टेंस के साथ उपयोग करेंगे, या हो सकता है कि आप पहले से ही कुछ कस्टम-निर्मित क्वेरी सर्वर का उपयोग कर रहे हों? मुझे टिप्पणियों में इसके बारे में सुनकर खुशी होगी।
अधिक युक्तियों, अंतर्दृष्टियों और इस श्रृंखला के अन्य भागों के निर्माण के लिए मेरे अन्य लेखों को देखना न भूलें। हैप्पी हैकिंग!
अस्वीकरण: उपलब्ध कराए गए सभी संसाधन आंशिक रूप से इंटरनेट से हैं। यदि आपके कॉपीराइट या अन्य अधिकारों और हितों का कोई उल्लंघन होता है, तो कृपया विस्तृत कारण बताएं और कॉपीराइट या अधिकारों और हितों का प्रमाण प्रदान करें और फिर इसे ईमेल पर भेजें: [email protected] हम इसे आपके लिए यथाशीघ्र संभालेंगे।
Copyright© 2022 湘ICP备2022001581号-3