asp.net वेब एपीआई सेवा-एएसआईएनसी कार्य के अंदर "एचटीटीपी कंसटैक्स। चालू" का उपयोग कैसे करें




asynchronous asp.net-web-api (2)

मैं webApi बाकी सेवा के "पोस्ट" async विधि का उपयोग कर रहा हूं:

public async Task<object> Post([FromBody]string data)
{
      object response = ExecuteServerLogics(data);

      return response;
}

यह उपरोक्त कोड अच्छा काम करता है, लेकिन कुछ ग्राहक के कॉल में, हम प्रदर्शन संबंधी समस्याओं का अनुभव करते हैं

यहां कुछ लेख पढ़ने के बाद, मैंने पाया है कि हमारी वेबएपी बाकी सेवा वास्तव में इसके आने वाले वेब अनुरोधों के साथ अतुल्यकालिक काम नहीं कर रही है, क्योंकि हम एसिंक / प्रतीक्षा पैटर्न का उपयोग करना भूल गए हैं:

public async Task<object> Post([FromBody]string data)
{
      object response = await Task<object>.Run( () =>
      {
           return ExecuteServerLogics(data);
      });

      return response;
}

इस सुधार के बाद हमने पाया कि प्रदर्शन बेहतर हो गया है, लेकिन हमें एक और आलोचक समस्या मिली: जब एचटीटीपीटीईन्टेक्स तक पहुँचते हैं। वर्तमान - यह नल संदर्भ देता है:

public async Task<object> Post([FromBody]string data)
{
      object response = await Task<object>.Run( () =>
      {
           var currentContext = HttpContext.Current; // Returns Null!
           return ExecuteServerLogics(data);
      });

      return response;
}

हम इसके लिए एक समाधान प्राप्त करने की कोशिश की, और अधिकांश पदों में हमने पाया कि हमें कार्यकर्ता थ्रेड के एचटीटीपी कंबल संदर्भ को अंदरूनी कार्य में पास करना चाहिए जो सर्वर लॉजिक को निष्पादित करता है। इस समाधान के साथ समस्या यह है कि सर्वर के लॉजिक तरीकों, "HttpContext.Current" का उपयोग करने वाले कई स्थैतिक कक्षाओं का उपयोग करें जैसे कि -

  1. लॉगर्स कॉल
  2. स्थिर सुरक्षा वर्ग जो उपयोगकर्ता को पुनः प्राप्त करते हैं
  3. स्थैतिक सुरक्षा वर्ग जो आवक अनुरोध के सत्र डेटा आदि को पुनः प्राप्त करते हैं।

इसलिए, कार्यकर्ता थ्रेड के "HttpContext.Current" संदर्भ को पारित करने से इसे हल नहीं होगा।

जब हम अगले समाधान की कोशिश की:

public async Task<object> Post([FromBody]string data)
    {
          // Save worker context:
          var currentContext = HttpContext.Current; 

          object response = await Task<object>.Run( () =>
          {
               // Set the context of the current task :
               HttpContext.Current = currentContext ; // Causes the calls not to work asynchronously for some reason!

               // Executes logics for current request:
               return ExecuteServerLogics(data);
          });

          return response;
    }

किसी कारण के लिए, हमने देखा कि प्रदर्शन फिर से बदतर हो गया है, जैसे कि वह फिर से सिंक्रोनस में काम कर चुका था।

हमारी समस्याएं हैं:

1. आखिरी उदाहरण में, काम की प्रतीक्षा में "एचटीटीपी प्रस्तुति। वर्तमान" को क्यों सेट करना, तुल्यकालिक परिणामों के समान ही खराब प्रदर्शन परिणाम वापस करने का अनुरोध करने का कारण बनता है?

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

धन्यवाद!


शुरुआत से:

public async Task<object> Post([FromBody]string data)
{
  object response = ExecuteServerLogics(data);
  return response;
}

कंपाइलर चेतावनियों को अनदेखा न करें; कंपाइलर इस पद्धति के लिए एक चेतावनी उत्पन्न करेगा जो विशेष रूप से बताता है कि यह समन्वयित रूप से चलाएगा।

आगे बढ़ते रहना:

ग्राहक के कुछ कॉल में, हम प्रदर्शन के मुद्दों का अनुभव करते हैं।

अलगाव में एक कॉल के लिए सर्वर पर असिंक्रोनस कोड तेजी से नहीं होगा। यह केवल आपके सर्वर को स्केल करने में आपकी सहायता करता है

विशेष रूप से, Task.RunTask.Run सभी निष्पादन लाभों को नकार देगा और उसके बाद प्रदर्शन को थोड़ी सी परे छोड़ देगा। मेरा मानना ​​है कि आपके द्वारा मापा गया प्रदर्शन में सुधार संयोग था।

अधिकांश पदों में हमने पाया कि हमें कार्यकर्ता थ्रेड के एचटीटीपी कंसटेक्स संदर्भ को आंतरिक कार्य में पारित करना चाहिए जो सर्वर लॉगिक्स को निष्पादित करता है।

ये पद गलत हैं IMHO। आप एक पृष्ठभूमि थ्रेड से HttpContext ऑब्जेक्ट का उपयोग करते हुए समाप्त हो जाते हैं, जब वह ऑब्जेक्ट विशेष रूप से केवल एक अनुरोध थ्रेड से एक्सेस करने के लिए डिज़ाइन किया गया हो।

क्या मैं पूरी तरह से गलत डिजाइन कर रहा हूं?

मैं सुझाव करता हूं कि आप एक कदम वापस लें और बड़ी तस्वीर के बारे में सोचें। जब कोई अनुरोध आता है, तो उसके पास कुछ निश्चित काम है चाहे वह काम सिंक्रोनस या एसिंक्रोनस से किया जाता है, यह ग्राहक के लिए बेकार है; दोनों तरीकों के बारे में एक ही समय की राशि ले जाएगा

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

यह कहना नहीं है कि async बेकार है, यद्यपि। यदि ExecuteServerLogics एक I / O बाध्य विधि है, तो इसे अवरुद्ध करने के बजाय अतुल्यकालिक बनाया जाना चाहिए, और उसके बाद आप एसिंक्रोनस विधियों का उपयोग कर सकते हैं जैसे:

public async Task<object> Post([FromBody]string data)
{
  object response = await ExecuteServerLogicsAsync(data);
  return response;
}

यह आपके सर्वर को अधिक संवेदनशील और स्केलेबल समग्र रूप से सक्षम करेगा (यानी, कई अनुरोधों से अभिभूत नहीं हो)।


यदि आपका कार्य आपके एपीसी-नियंत्रक-व्युत्पन्न वर्ग के अंदर है, तो आप इसका उपयोग कर सकते हैं:

var ctx = this.Request.Properties["MS_HttpContext"] as System.Web.HttpContextWrapper;

यह आपको सभी सामान्य गुणों के साथ एक एचटीटीपी कॉन्टैक्स आवरण प्रदान करेगा।







httpcontext