2009-07-17 16 views
30

मैं एक http मॉड्यूल बना रहा था और डीबगिंग करते समय मैंने कुछ ऐसा देखा जो पहले (कम से कम) अजीब व्यवहार की तरह लग रहा था।HttpModule Init विधि कई बार कहा जाता है - क्यों?

जब मैं httpmodule की init विधि में ब्रेकपॉइंट सेट करता हूं तो मैं देख सकता हूं कि http मॉड्यूल इनिट विधि को कई बार कहा जा रहा है, भले ही मैंने केवल डीबगिंग के लिए वेबसाइट शुरू की है और एक ही अनुरोध किया है (कभी-कभी यह केवल 1 बार मारा, अन्य बार 10 गुना)।

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

क्या गलत हो सकता है? ऐसा इसलिए है क्योंकि मैं डीबगिंग कर रहा हूं और http मॉड्यूल में ब्रेकपॉइंट सेट कर रहा हूं?

यह देखा गया है कि ऐसा लगता है कि अगर मैं डीबगिंग के लिए वेबसाइट शुरू करता हूं और httpmodule में ब्रेकपॉइंट पर तेज़ी से कदम उठाता हूं तो यह केवल एक बार init विधि को दबाएगा और यह ईवेंटशेलर के लिए भी जाता है। अगर मैं इसे कुछ सेकंड के लिए ब्रेकपॉइंट पर लटकने देता हूं तो इनिट विधि को कई बार बुलाया जा रहा है (ऐसा लगता है कि यह ब्रेकपॉइंट पर कदम उठाने से पहले कितना समय इंतजार करता है)। शायद यह सुनिश्चित करने के लिए कुछ निर्माण हो सकता है कि httpmodule प्रारंभ किया गया है और http अनुप्रयोग अनुरोधों को पूरा कर सकता है, लेकिन ऐसा कुछ ऐसा लगता है जो विनाशकारी परिणाम हो सकता है।

यह तार्किक प्रतीत हो सकता है, क्योंकि यह अनुरोध को समाप्त करने का प्रयास कर रहा है और चूंकि मैंने ब्रेक पॉइंट सेट किया है, ऐसा लगता है कि कुछ गलत हो गया है और फिर से इनिट विधि को कॉल करने का प्रयास करें? तो यह अनुरोध संभाल सकता है?

लेकिन क्या यह हो रहा है और क्या सब ठीक है (मैं अनुमान लगा रहा हूं), या यह एक वास्तविक समस्या है?

जो मैं विशेष रूप से चिंतित हूं वह यह है कि अगर कुछ सेकंड के लिए "उत्पादन/लाइव" सर्वर पर कुछ लटकता है तो बहुत सारे ईवेंट हैंडलर इनिट के माध्यम से जोड़े जाते हैं और इसलिए पृष्ठ पर प्रत्येक अनुरोध अचानक घटनाक्रम को आग लगा देता है बहुत बार।

यह व्यवहार जल्दी से किसी भी साइट को नीचे ला सकता है।

मैंने फॉर्मेट प्रमाणीकरण और रोलमैनगर्म्यूल आदि के लिए httpmodules के लिए उपयोग किए जाने वाले "मूल" .NET कोड को देखा है, लेकिन मेरा कोड कोई भी अलग नहीं है जो उन मॉड्यूल का उपयोग करता है।

मेरा कोड इस तरह दिखता है।

public void Init(HttpApplication app) 
    { 
     if (CommunityAuthenticationIntegration.IsEnabled) 
     { 
      FormsAuthenticationModule formsAuthModule = (FormsAuthenticationModule) app.Modules["FormsAuthentication"];   

      formsAuthModule.Authenticate += new FormsAuthenticationEventHandler(this.OnAuthenticate); 
     } 
    } 

यहाँ एक उदाहरण है कि यह कैसे .NET फ़्रेमवर्क

public void Init(HttpApplication app) 
    { 
     if (Roles.Enabled) 
     { 
      app.PostAuthenticateRequest += new EventHandler(this.OnEnter); 
      app.EndRequest += new EventHandler(this.OnLeave); 
     } 
    } 

किसी को पता क्या चल रहा है है से RoleManagerModule में किया जाता है?

(मैं बस आशा है कि किसी को वहाँ मुझे बता सकते हैं क्यों यह हो रहा है और विश्वास दिलाता हूं मुझे है कि सब कुछ बिल्कुल ठीक है) :)


अद्यतन:

मैं कोशिश की है समस्या को कम करने के लिए और अब तक मुझे पता चला है कि इनिट विधि को हमेशा मेरे http मॉड्यूल की एक नई वस्तु पर रखा जाता है (जो मैंने पहले सोचा था)।

मुझे लगता है कि पहले अनुरोध के लिए (साइट शुरू करते समय) सभी एचटीपी अनुप्रयोगों का निर्माण किया जा रहा है और इसके मॉड्यूल सभी पहले अनुरोध की सेवा करने की कोशिश कर रहे हैं और इसलिए सभी को घटनाक्रम को जोड़ा जा रहा है। मैं वास्तव में यह नहीं समझ सकता कि यह क्यों हो रहा है।

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

लेकिन ऐसा लगता है कि अगर मैं पहले पृष्ठ पर वापस कूदता हूं (या दूसरा) केवल एक एचटीपी आवेदन अनुरोध की देखभाल करना शुरू कर देगा और सब कुछ अपेक्षित है - जब तक मैं इसे लटका नहीं देता ब्रेक प्वाइंट

यदि मैं इसे ब्रेकपॉइंट पर लटकने देता हूं तो यह नया एचटीपी एप्लीकेशन की ऑब्जेक्ट्स बनाना शुरू कर देता है और अनुरोध को पूरा/संभालने के लिए एचटीपीएप्लिकेशंस (1 से अधिक) जोड़ना शुरू करता है (जो पहले से ही एचटीपी एप्लीकेशन द्वारा सेवा की प्रक्रिया में है जो वर्तमान में बंद है ब्रेकपॉइंट पर)।

मुझे लगता है या उम्मीद है कि यह लोड और/या त्रुटियों को वितरित करने और संभालने में मदद करने के तरीके के पीछे "दृश्यों के पीछे" कुछ बुद्धिमान हो सकता है। लेकिन मुझे कोई सुराग नहीं है। मुझे उम्मीद है कि कुछ लोग मुझे आश्वस्त कर सकते हैं कि यह बिल्कुल ठीक है और यह कैसा होना चाहिए?

+2

मैं हमारे HttpModule रूप में अच्छी तरह –

+0

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

उत्तर

7
  1. निरीक्षण HttpContext.Current.Request क्या का अनुरोध मॉड्यूल के init निकाल दिया जाता है के लिए, को देखने के लिए। ब्राउज़र एकाधिक अनुरोध भेज सकता है।

  2. यदि आप आईआईएस से जुड़े हैं, तो यह जानने के लिए आईआईएस लॉग जांचें कि क्या आप ब्रेक पॉइंट पर रहने वाले समय के लिए कोई अनुरोध प्राप्त कर चुके हैं या नहीं।

+0

सही। ऐसा इसलिए होता है क्योंकि सभी अनुरोध (किसी संसाधन के लिए) मॉड्यूल को हिट करता है। मेरे मामले में रूटिंग मॉड्यूल की वजह से ऐसा लगता है। – MartinF

2

यहां कुछ स्पष्टीकरण दिया गया है कि आपको क्या उपयोग करना चाहिए, कब और कैसे काम करना चाहिए। When to use Application_Start vs Init in Global.asax?

संपादित करें: अधिक पढ़ने

The ASP Column: HTTP Modules

INFO: Application Instances, Application Events, and Application State in ASP.NET

+0

आपके उत्तर के लिए धन्यवाद। मैं उनमें से किसी का भी उपयोग नहीं करता हूं। वैश्विक Asax में init Http अनुप्रयोग में init overriding है। मेरी समस्या यह है कि मेरे httpmodule में init विधि कई बार कहा जा रहा है। जहां तक ​​मैं इसे समझता हूं, इसे प्रत्येक http अनुप्रयोग के लिए http मॉड्यूल बनाना चाहिए। से प्रत्येक अनुरोध एक पर instanciated HttpApplication के अनुरोध को संभाल लेंगे, और आग की घटनाओं जोड़ा है, लेकिन किसी कारण के eventhandler * कभी कभी * एक बार से अधिक एक ही http मॉड्यूल (नहीं नई में से एक के लिए बनाया पर init विधि के रूप में जोड़ दिए जाते हैं अन्य httpapplication) को serveral बार कहा जाता है। – MartinF

+0

जोड़ा पढ़ने के लिए और अधिक। –

40

इनिट() विधि को कई बार बुलाया जाना सामान्य बात है। जब कोई एप्लिकेशन शुरू होता है, तो एएसपी.नेट वर्कर प्रक्रिया कई एचटीपी एप्लीकेशन ऑब्जेक्ट्स को तुरंत चालू कर देती है, जैसा कि इसे लगता है, फिर यह उन्हें पूल करेगा (उदाहरण के लिए, उन्हें नए कनेक्शन के लिए पुन: उपयोग करें, डेटाबेस कनेक्शन पूलिंग के समान)।

अब प्रत्येक एचटीपी एप्लीकेशन ऑब्जेक्ट के लिए, यह पंजीकृत प्रत्येक आईएचटीपी मॉड्यूल की एक प्रति को भी चालू करेगा और कई बार इनिट विधि को कॉल करेगा। तो यदि 5 एचटीपी एप्लीकेशन ऑब्जेक्ट्स बनाए जाते हैं, तो आपके आईएचटीपी मॉड्यूल की 5 प्रतियां बनाई जाएंगी, और आपकी इनिट विधि को 5 बार कहा जाएगा। सही बात?

अब क्यों यह 5 HttpApplications वस्तुओं का कहना है कि instantiating है? वैसे शायद आपके एएसपीएक्स पेज में अन्य संसाधनों के लिंक हैं जो आपका ब्राउज़र डाउनलोड करने की कोशिश करेगा, सीएसएस, जावास्क्रिप्ट, WebResource.aspx, शायद कहीं एक आईफ्रेम। या हो सकता है ASP.NET वर्कर प्रक्रिया 1 से अधिक HttpApplication वस्तु शुरू करने के लिए, 'मूड में है' कि वास्तव में एक आंतरिक विस्तार/आईआईएस के तहत चल रहा ASP.NET प्रक्रिया के अनुकूलन (या वी.एस. वेबसर्वर में निर्मित) है।

आप कोड सिर्फ एक बार चलाने के लिए गारंटी है कि (और Global.asax में Application_StartUp घटना का उपयोग नहीं करना चाहते हैं) चाहते हैं, तो आप अपने IHttpModule में निम्न को आज़मा सकते:

private static bool HasAppStarted = false; 
private readonly static object _syncObject = new object(); 

public void Init(HttpApplication context) 
{ 
    if (!HasAppStarted) 
    { 
     lock (_syncObject) 
     { 
      if (!HasAppStarted) 
      { 
       // Run application StartUp code here 

       HasAppStarted = true; 
      } 
     } 
    } 
} 

मैं मैंने कुछ ऐसा किया है और ऐसा लगता है, हालांकि अगर मैं कुछ याद कर चुका हूं तो मैं अपने काम की आलोचनाओं का स्वागत करता हूं।

+10

यह भी अनुरोध एप्लिकेशन वर्ग की फ़ाइल कारण निर्माण और उसके अपने मॉड्यूल है, और इसलिए इस घटना की फायरिंग संसाधन है 'Interlocked.CompareExchange' बजाय ताला :) –

+1

का उपयोग करने के लिए जगह है? –

1

examle ऊपर सभी अनुरोधों के लिए IHttpModule ताले, और फिर, यह पूरे आवेदन frezes। अपने IHttpModule कॉल कई बार अनुरोध करते हैं HttpApplication विधि CompleteRequest फोन और व्यवस्था में इस तरह HttpApplication के कहने को दूर करने के EndRequest घटना में IHttpModule की HttpApplication उदाहरण निपटान के लिए की जरूरत है:

public class TestModule :IHttpModule 
    { 
     #region IHttpModule Members 

     public void Dispose() 
     { 

     } 

     public void Init(HttpApplication context) 
     { 
      context.BeginRequest += new EventHandler(context_BeginRequest); 
      context.EndRequest += new EventHandler(context_EndRequest); 
     } 

     void context_EndRequest(object sender, EventArgs e) 
     { 
      HttpApplication app = sender as HttpApplication; 
      app.CompleteRequest(); 
      app.Dispose(); 
     } 

     void context_BeginRequest(object sender, EventArgs e) 
     { 
      //your code here 
     } 

     #endregion 
    } 

आप की जरूरत है कि IHttpModule अनुरोध पोस्टबैक पर हर बार बिना किसी शर्त के उपरोक्त इस कोड का उपयोग करें।

+0

यह एक अच्छा बिंदु है, लेकिन कुछ अनुप्रयोगों (जैसे मेरा) निष्पादित करने के लिए कोड कुछ माइक्रोसेकंड हैं, इसलिए लॉक निश्चित रूप से लागत प्रभावी है। लेकिन विचार के लिए धन्यवाद, मुझे लगता है कि यह जानना मेरे कोडिंग में सुधार करेगा। – Abacus

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