[C#] القيام بعمليات غير متزامنة في ASP.NET MVC استخدم مؤشر ترابط من ThreadPool على. NET 4



Answers

نعم - كل الخيوط تأتي من تجمع مؤشر الترابط. تطبيق MVC متعدد الخيوط بالفعل ، عندما يأتي طلب في مؤشر ترابط جديد سيتم أخذه من التجمع ويستخدم لخدمة الطلب. سيتم "تأمين" مؤشر الترابط هذا (من الطلبات الأخرى) حتى يتم إكمال الطلب واستكماله بالكامل. إذا لم يكن هناك مؤشر ترابط متوفر في التجمع ، فسيتعين على الطلب الانتظار حتى يتوفر أحدهما.

إذا كان لديك وحدات تحكم متزامنة فإنها لا تزال تحصل على مؤشر ترابط من التجمع ولكن أثناء تقديم الطلب يمكنهم التخلي عن الموضوع ، أثناء انتظار حدوث شيء ما (ويمكن إعطاء هذا الموضوع لطلب آخر) وعندما يحتاج الطلب الأصلي إلى مؤشر ترابط مرة أخرى يحصل على واحد من المجمع.

الفرق هو أنه إذا كان لديك الكثير من الطلبات طويلة الأمد (حيث ينتظر مؤشر الترابط استجابة من شيء ما) فقد تنفد مؤشرات الترابط من التجمع لخدمة حتى الطلبات الأساسية. إذا كان لديك وحدات تحكم غير متزامنة ، فلن يكون لديك المزيد من سلاسل الرسائل ولكن يتم إرجاع سلاسل الرسائل التي تنتظر إلى التجمع ويمكنها خدمة طلبات أخرى.

مثال واقعي تقريبًا ... فكر فيه كأنك في الباص ، فهناك خمسة أشخاص ينتظرون الدخول ، والأول يحصل على ، ويدفع ويجلس (سُلِّم السائق طلبهم) ، تحصل على (السائق يخدم طلبك) ولكن لا يمكنك العثور على أموالك ؛ عندما تتخبط في جيوبك يتخلى السائق عنك ويحصل على الشخصين التاليين (خدمة طلباتهم) ، وعندما تجد نقودك يبدأ السائق بالتعامل معك مرة أخرى (إكمال طلبك) - على الشخص الخامس الانتظار حتى لقد انتهيت من العمل ، لكن الشخص الثالث والرابع حصلوا على الخدمة بينما كنتم في منتصف الطريق من خلال الحصول على الخدمة. هذا يعني أن السائق هو واحد وخيط فقط من التجمع والركاب هي الطلبات. كان من الصعب للغاية أن تكتب كيف ستعمل إذا كان هناك سائقان ولكن يمكنك تخيل ...

بدون جهاز تحكم متزامن ، سيتعين على الركاب الذين يقفون خلفك أن ينتظروا الأعمار أثناء البحث عن أموالك ، وفي هذه الأثناء لن يقوم سائق الحافلة بأي عمل.

لذا ، فإن الاستنتاج هو ، إذا كان الكثير من الناس لا يعرفون مكان أموالهم (أي يتطلب وقتًا طويلاً للرد على شيء طلب السائق) يمكن للتحكمات غير المتزامنة أن تساعد في نقل الطلبات ، مما يسرع العملية من البعض. دون وحدة تحكم aysnc ينتظر الجميع حتى يتم التعامل مع الشخص في الجبهة تماما. ولكن لا ننسى أنه في MVC لديك الكثير من سائقي الحافلات على متن حافلة واحدة ، لذا لا يعد onync خيارًا تلقائيًا.

Question

بعد هذا السؤال ، يجعلني مرتاحًا عند استخدام عمليات المتزامن في ASP.NET MVC. لذلك ، كتبت مقالتين في المدونة على ذلك:

لدي الكثير من سوء الفهم في ذهني حول العمليات غير المتزامنة على ASP.NET MVC.

دائمًا ما أسمع هذه الجملة: يمكن للتطبيق توسيع النطاق بشكل أفضل في حالة تشغيل العمليات بشكل غير متزامن

وسمعت هذا النوع من الجمل كثيرًا أيضًا: إذا كان لديك عدد كبير من الزيارات ، فقد يكون من الأفضل عدم تنفيذ استعلاماتك بشكل غير متزامن - تستهلك سلسلتان إضافيتان لخدمة طلب واحد يأخذ الموارد بعيدًا عن الطلبات الواردة الأخرى.

أعتقد أن هاتين الجملتين غير متناسقة.

ليس لدي الكثير من المعلومات حول كيفية عمل threadpool على ASP.NET ولكن أعرف أن threadpool له حجم محدود للخيوط. لذا ، يجب أن تكون الجملة الثانية مرتبطة بهذه القضية.

وأود أن أعرف ما إذا كانت العمليات غير المتزامنة في ASP.NET MVC تستخدم مؤشر ترابط من ThreadPool على. NET 4؟

على سبيل المثال ، عند تنفيذ AsyncController ، كيف يتم إنشاء هياكل التطبيق؟ إذا حصلت على حركة مرور ضخمة ، فهل من الجيد تطبيق AsyncController؟

هل هناك أي شخص يمكن أن يأخذ هذه الستارة السوداء أمام عيني وشرح لي صفقة حول asynchrony على ASP.NET MVC 3 (NET 4)؟

تصحيح:

لقد قرأت هذه الوثيقة أدناه تقريبًا مئات المرات وأفهم الصفقة الرئيسية ولكن لا يزال لدي ارتباك لأن هناك الكثير من التعليقات غير المتسقة هناك.

استخدام وحدة تحكم غير متزامنة في ASP.NET MVC

تصحيح:

لنفترض أن لدي إجراء وحدة تحكم مثل أدناه (وليس تطبيق AsyncController الرغم من ذلك):

public ViewResult Index() { 

    Task.Factory.StartNew(() => { 
        //Do an advanced looging here which takes a while
    });

    return View();
}

كما ترون هنا ، أنا أطلق عملية ونسيانها. ثم أعود على الفور دون انتظار الانتهاء من ذلك.

في هذه الحالة ، هل يجب استخدام مؤشر ترابط من threadpool؟ إذا كان الأمر كذلك ، بعد اكتماله ، ماذا يحدث لهذا الخيط؟ هل تأتي GC وتنظف بعد اكتمالها؟

تصحيح:

بالنسبة لإجابة @ Darin ، إليك عينة من رمز التزامن الذي يتحدث إلى قاعدة البيانات:

public class FooController : AsyncController {

    //EF 4.2 DbContext instance
    MyContext _context = new MyContext();

    public void IndexAsync() { 

        AsyncManager.OutstandingOperations.Increment(3);

        Task<IEnumerable<Foo>>.Factory.StartNew(() => { 

           return 
                _context.Foos;
        }).ContinueWith(t => {

            AsyncManager.Parameters["foos"] = t.Result;
            AsyncManager.OutstandingOperations.Decrement();
        });

        Task<IEnumerable<Bars>>.Factory.StartNew(() => { 

           return 
                _context.Bars;
        }).ContinueWith(t => {

            AsyncManager.Parameters["bars"] = t.Result;
            AsyncManager.OutstandingOperations.Decrement();
        });

        Task<IEnumerable<FooBar>>.Factory.StartNew(() => { 

           return 
                _context.FooBars;
        }).ContinueWith(t => {

            AsyncManager.Parameters["foobars"] = t.Result;
            AsyncManager.OutstandingOperations.Decrement();
        });
    }

    public ViewResult IndexCompleted(
        IEnumerable<Foo> foos, 
        IEnumerable<Bar> bars,
        IEnumerable<FooBar> foobars) {

        //Do the regular stuff and return

    }
}



يمكن للتطبيقات أن تتحسن بشكل أفضل إذا تم تشغيل العمليات بشكل غير متزامن ، ولكن فقط إذا كانت هناك موارد متوفرة لخدمة العمليات الإضافية .

تضمن العمليات غير المتزامنة أنك لا تحظر أي إجراء مطلق نظرًا لأن هناك إجراء حاليًا قيد التقدم. لدى ASP.NET طراز غير متزامن يسمح بطلبات متعددة لتنفيذ جنباً إلى جنب. سيكون من الممكن ترتيب الطابور وإجراء العمليات عليه ، FIFO ، ولكن هذا لن يكون مقياسًا جيدًا عندما يكون لديك مئات الطلبات في قائمة الانتظار ويأخذ كل طلب 100 مللي لعملية المعالجة.

إذا كان لديك عدد كبير من الزيارات ، فقد يكون من الأفضل عدم تنفيذ استعلاماتك بشكل غير متزامن ، حيث قد لا توجد موارد إضافية لخدمة الطلبات . إذا لم تكن هناك موارد احتياطية ، فستُضطر طلباتك إلى الانتظار في طوابير ، أو أخذ فترة أطول من الفشل أو الفشل الصريح ، وفي هذه الحالة ، لا يوفر لك الحمل غير المتزامن (عمليات التبديل والتبادل بين السياق) أي شيء.

بقدر ما يذهب ASP.NET ، لم يكن لديك خيار - فهو يستخدم نموذج غير متزامن ، لأن هذا هو ما يجعل من المنطقي لنموذج الخادم والعميل. إذا كنت ستقوم بكتابة رمزك داخليًا يستخدم نمطًا غير متزامن لمحاولة القياس بشكل أفضل ، إلا إذا كنت تحاول إدارة مورد مشترك بين جميع الطلبات ، فلن ترى أي تحسينات بالفعل نظرًا لأنها ملفوفة بالفعل في عملية غير متزامنة لا تمنع أي شيء آخر.

في النهاية ، كل شيء ذاتي حتى تنظر فعليًا إلى ما يسبب اختناقًا في نظامك. في بعض الأحيان يكون من الواضح حيث يساعد نمط غير متزامن (عن طريق منع حظر مورد في قائمة الانتظار). في نهاية المطاف ، يمكن فقط قياس وتحليل النظام أن يشير إلى المكان الذي يمكنك فيه اكتساب الكفاءة.

تصحيح:

في المثال الخاص بك ، Task.Factory.StartNew انتظار عملية على تجمع Task.Factory.StartNew الترابط .NET. طبيعة مؤشرات ترابط تجمّع مؤشر الترابط هو re-used (لتجنب تكلفة إنشاء / إتلاف الكثير من مؤشرات الترابط). بمجرد اكتمال العملية ، يتم إعادة مؤشر الترابط مرة أخرى إلى التجمع ليتم استخدامه مرة أخرى بواسطة طلب آخر (لا يتدخل جامع القمامة فعليًا إلا إذا قمت بإنشاء بعض الكائنات في العمليات الخاصة بك ، وفي هذه الحالة يتم تجميعها وفقًا لما هو عادي الفحص).

بقدر ما تشعر ASP.NET بالقلق ، لا توجد عملية خاصة هنا. اكتمال طلب ASP.NET دون احترام المهمة غير المتزامنة. قد يكون الشاغل الوحيد هو إذا كان تجمع مؤشرات الترابط الخاص بك مشبعًا (على سبيل المثال لا توجد سلاسل متاحة لخدمة الطلب في الوقت الحالي ولا تسمح إعدادات المجمع بإنشاء المزيد من مؤشرات الترابط) ، وفي هذه الحالة يتم حظر الطلب في انتظار بدء المهمة حتى يصبح مؤشر ترابط التجمع متوفرًا.




أول شيء ليس MVC لكن IIS الذي يحافظ على تجمع مؤشر الترابط. لذلك يتم تقديم أي طلب الذي يأتي إلى تطبيق MVC أو ASP.NET من سلاسل الرسائل التي يتم الاحتفاظ بها في تجمع مؤشرات الترابط. فقط مع جعل التطبيق Asynch يستدعي هذا الإجراء في مؤشر ترابط مختلف ويقوم بإصدار مؤشر الترابط مباشرة بحيث يمكن أخذ الطلبات الأخرى.

لقد أوضحت الشيء نفسه مع فيديو تفصيلي ( http://www.youtube.com/watch?v=wvg13n5V0V0/ "MVC Asynch controllers and starvation") الذي يوضح كيف يحدث الموت جوعًا في MVC وكيف يتم تصغيره باستخدام MVC كما قاموا بقياس قوائم انتظار الطلبات باستخدام perfmon بحيث يمكنك رؤية كيفية انخفاض قوائم انتظار الطلبات بالنسبة إلى MVC asinch وكيفية حدوثها في عمليات Synch.






Links