OpenResty FAQ | विशेषाधिकार प्राप्त प्रक्रिया अनुमति, निष्पादन चरण, और अधिक

API7.ai

November 11, 2022

OpenResty (NGINX + Lua)

यह लेख छह अक्सर पूछे जाने वाले प्रश्नों को शामिल करता है:

1. विशेषाधिकार प्राप्त प्रक्रिया अनुमतियाँ

प्रश्न: विशेषाधिकार प्राप्त प्रक्रिया क्या है? गैर-विशेषाधिकार प्राप्त उपयोगकर्ता root अनुमतियाँ कैसे प्राप्त कर सकता है? क्या आप विशेषाधिकार प्राप्त प्रक्रिया के कुछ परिदृश्यों का परिचय दे सकते हैं?

उत्तर: विशेषाधिकार प्राप्त प्रक्रिया की अनुमतियाँ master प्रक्रिया के समान होती हैं। यदि आप OpenResty को एक गैर-विशेषाधिकार प्राप्त उपयोगकर्ता के रूप में शुरू करते हैं, तो master प्रक्रिया उपयोगकर्ता के विशेषाधिकार को विरासत में लेती है, जिसका अर्थ है कि "विशेषाधिकार प्राप्त प्रक्रिया" के पास अब कोई अधिकार नहीं है।

यह समझना आसान है कि जब एक सामान्य उपयोगकर्ता एक प्रक्रिया शुरू करता है तो कोई root विशेषाधिकार नहीं होते हैं।

विशेषाधिकार प्राप्त प्रक्रिया के उपयोग के परिदृश्यों के लिए, हम आमतौर पर इसे उच्च विशेषाधिकार वाले कार्यों के लिए उपयोग करते हैं, जैसे लॉग सफाई और OpenResty को पुनः आरंभ करना। हालांकि, सुरक्षा जोखिमों के कारण कार्यकर्ता प्रक्रिया कार्यों को चलाने के लिए विशेषाधिकार प्राप्त प्रक्रिया का उपयोग न करने का ध्यान रखें।

एक डेवलपर सभी timer कार्यों को विशेषाधिकार प्राप्त प्रक्रिया में चलाता है। वह ऐसा क्यों करता है? क्योंकि केवल एक विशेषाधिकार प्राप्त प्रक्रिया होती है, इस तरह से timer बार-बार शुरू नहीं होता है।

डेवलपर "चतुर" है क्योंकि उसने worker.id का उपयोग किए बिना लक्ष्य हासिल किया। हालांकि, यह मत भूलिए, यह बहुत खतरनाक है यदि timer कार्य क्लाइंट के इनपुट पर निर्भर करता है।

2. चरणबद्धता और डिबगिंग

प्रश्न: ngx.say('hello') चलाने के बाद, क्या OpenResty वर्तमान चरण में शेष तर्क को निष्पादित करने के बाद सीधे क्लाइंट को प्रतिक्रिया देगा? क्या इसका मतलब है कि यह बाद के चरणों को चलाना जारी नहीं रखेगा?

उत्तर: ऐसा नहीं है। हम इसके निष्पादन चरण को देख सकते हैं:

image

आप पहले content चरण में ngx.say का परीक्षण कर सकते हैं, फिर log या body filter चरण में ngx.log का उपयोग करके लॉग प्रिंट कर सकते हैं।

पिछले लेखों में, मैंने OpenResty में कोड डिबगिंग करने की समस्या का विशेष रूप से उल्लेख नहीं किया था, जिसके बारे में डेवलपर्स भ्रमित हो सकते हैं।

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

3. ngx.exit का अभ्यास

प्रश्न: पिछले लेखों में, एक विवरण था: OpenResty के HTTP स्टेटस कोड में एक विशेष स्थिरांक ngx.OK होता है। ngx.exit(ngx.OK) चलाने के बाद, अनुरोध वर्तमान चरण से बाहर निकलता है और अगले चरण में चला जाता है, सीधे क्लाइंट को वापस नहीं जाता है।

मुझे याद है कि ngx.OK को HTTP स्टेटस कोड के रूप में नहीं माना जाना चाहिए, इसका मान 0 है। मेरी समझ है:

  • ngx.exit(ngx.OK), ngx.exit(ngx.ERROR) या ngx.exit(ngx.DECLINED) चलाने के बाद, अनुरोध वर्तमान चरण से बाहर निकलता है और अगले चरण में चला जाता है।
  • जब ngx.exit(ngx.HTTP_*) ngx.HTTP_* के विभिन्न HTTP स्टेटस कोड्स को पैरामीटर के रूप में लेता है, तो यह सीधे क्लाइंट को प्रतिक्रिया देगा।

मुझे नहीं पता कि मेरी समझ सही है या नहीं।

उत्तर: आपके पहले प्रश्न के संबंध में, ngx.ok एक HTTP स्टेटस कोड नहीं है बल्कि OpenResty में एक स्थिरांक है जिसका मान 0 है।

दूसरे प्रश्न के लिए, ngx.exit का आधिकारिक दस्तावेज़ सटीक उत्तर हो सकता है:

  1. जब स्टेटस >= 200 (अर्थात, ngx.HTTP_OK और ऊपर), यह वर्तमान अनुरोध के निष्पादन को बाधित करेगा और स्टेटस कोड को nginx को वापस करेगा।

  2. जब स्टेटस == 0 (अर्थात, ngx.OK), यह केवल वर्तमान चरण हैंडलर (या content_by_lua* निर्देश का उपयोग किया गया हो तो content हैंडलर) को छोड़ देगा और वर्तमान अनुरोध के लिए बाद के चरणों (यदि कोई हो) को चलाना जारी रखेगा।

हालांकि, दस्तावेज़ में यह उल्लेख नहीं किया गया है कि OpenResty ngx.exit(ngx.ERROR) और ngx.exit(ngx.DECLINED) को कैसे संभालता है। हम निम्नलिखित परीक्षण कर सकते हैं:

location /lua { rewrite_by_lua "ngx.exit(ngx.ERROR)"; echo hello; }

इस location का दौरा करने पर, आप देख सकते हैं कि HTTP प्रतिक्रिया कोड खाली है, प्रतिक्रिया बॉडी भी खाली है, और यह निष्पादन के अगले चरण में नहीं जाता है।

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

4. चर और रेस कंडीशन

प्रश्न: जैसा कि पहले उल्लेख किया गया है, ngx.var चर का दायरा nginx C और lua-nginx-module मॉड्यूल के बीच होता है।

  1. मैं इसे पूरी तरह से नहीं समझ पाया। अनुरोध के दृष्टिकोण से, क्या इसका मतलब एक कार्यकर्ता प्रक्रिया में एकल अनुरोध है?

  2. मेरी समझ है कि जब हम एक मॉड्यूल के भीतर चरों को संचालित करते हैं। यदि दो संचालनों के बीच एक ब्लॉकिंग ऑपरेशन होता है, तो एक रेस कंडीशन मौजूद हो सकती है। इसलिए यदि दो संचालनों के बीच कोई ब्लॉकिंग ऑपरेशन नहीं होता है, और यह होता है कि वर्तमान प्रक्रिया CPU समय समाप्त होने पर तैयार कतार में प्रवेश करती है, तो क्या रेस कंडीशन मौजूद हो सकती है?

उत्तर: आइए इन प्रश्नों को देखें।

पहले, ngx.var चर के संबंध में, आपकी समझ सही है। ngx.var का जीवनकाल अनुरोध के समान होता है, और यह अनुरोध समाप्त होने पर गायब हो जाता है। लेकिन इसका लाभ यह है कि डेटा C मॉड्यूल और Lua कोड के बीच पारित किया जा सकता है, जो कई अन्य तरीकों से संभव नहीं है।

दूसरा, जब तक दो संचालनों के बीच एक yield ऑपरेशन होता है, तो एक रेस कंडीशन मौजूद हो सकती है न कि ब्लॉकिंग ऑपरेशन। जब एक ब्लॉकिंग ऑपरेशन होता है तो कोई रेस कंडीशन नहीं होती है। दूसरे शब्दों में, जब तक आप NGINX के इवेंट लूप को पहल नहीं देते हैं, तब तक कोई रेस कंडीशन नहीं होगी।

5. shared dict को लॉक की आवश्यकता नहीं है

प्रश्न: यदि कई कार्यकर्ता समवर्ती रूप से डेटा संग्रहीत करते हैं, तो क्या लॉक जोड़ना आवश्यक है?

उदाहरण:

resty --shdict 'dogs 10m' -e 'local dogs = ngx.shared.dogs local lock= ngx.xxxx.lock lock.lock() dogs:set("Jim", 8) lock.unlock() local v = dogs:get("Jim") ngx.say(v) '

उत्तर: आपको यहाँ लॉक जोड़ने की आवश्यकता नहीं है क्योंकि चाहे get या set ऑपरेशन हो, shared dict का ऑपरेशन परमाणु होता है। OpenResty ने पहले ही इस तरह के लॉकिंग जैसे प्रसंस्करण पर विचार किया है।

6. OpenResty में समय संचालन

प्रश्न: ngx.now() का उपयोग करके समय प्राप्त करना, क्या यह resume फ़ंक्शन पुनर्स्थापना चरण में होता है?

उत्तर: NGINX को प्रदर्शन को प्राथमिकता देते हुए डिज़ाइन किया गया है और समय को कैश करता है। हम ngx.now के स्रोत कोड द्वारा इसे सत्यापित कर सकते हैं:

static int ngx_http_lua_ngx_now(lua_State *L) { ngx_time_t *tp; tp = ngx_timeofday(); lua_pushnumber(L, (lua_Number) (tp->sec + tp->msec / 1000.0L)); return 1; }

जैसा कि आप देख सकते हैं, ngx.now() फ़ंक्शन जो वर्तमान समय प्राप्त करता है, के पीछे NGINX का ngx_timeofday फ़ंक्शन होता है। ngx_timeofday फ़ंक्शन एक मैक्रो परिभाषा है:

#define ngx_timeofday() (ngx_time_t *) ngx_cached_time

यहाँ ngx_cached_time का मान केवल ngx_time_update फ़ंक्शन में अपडेट होगा।

तो, प्रश्न यह हो जाता है कि "ngx_time_update फ़ंक्शन कब कहा जाता है?" यदि आप इसे NGINX स्रोत कोड में ट्रेस करते हैं, तो आप देखेंगे कि ngx_time_update के कॉल इवेंट लूप में होते हैं, तो यह समस्या हल हो जाती है।

सारांश

आपको इन प्रश्नों के माध्यम से भी पता चलना चाहिए, ओपन-सोर्स परियोजनाओं का लाभ यह है कि आप सुराग का पालन कर सकते हैं और स्रोत कोड में उत्तर ढूंढ सकते हैं, जो आपको केस सुलझाने का एहसास देगा।

अंत में, मुझे आशा है कि संचार और प्रश्नोत्तर के माध्यम से, मैं आपकी मदद कर सकता हूँ कि आप जो सीखते हैं उसे प्राप्त कर सकें। आप इस लेख को आगे भी साझा कर सकते हैं, और हम साथ में संचार और सुधार करेंगे।