۱۳۹۰/۰۵/۰۵

مروري بر تاريخچه محدوديت حافظه مصرفي برنامه‌هاي ASP.NET در IIS


زمانيكه اولين نگارش ASP.NET‌ حدود 10 سال قبل منتشر شد،‌ تنها سيستم عاملي كه از آن پشتيباني مي‌كرد، ويندوز سرور 2000 بود، تنها پروسه‌ي اجرايي آن aspnet_wp نام داشت و تنها معماري پشتيباني شده هم X86 بود. به پروسه‌ي aspnet_wp محدوديت مصرف حافظه‌اي اعمال شده بود كه در حين آغاز آن بر اساس مقدار قابل تغيير processModel memoryLimit محاسبه و اعمال مي‌شد (تعريف شده در فايل ماشين كانفيگ). اين عدد به صورت درصدي از ظرفيت RAM فيزيكي سيستم، قابل تعريف و به صورت پيش فرض به 60 درصد تنظيم شده بود. به اين ترتيب اين پروسه مجاز نبود تا تمام حافظه‌ي فيزيكي مهيا را مصرف كند و در صورت وجود نشتي حافظه‌اي در برنامه‌اي خاص، اين پروسه امكان بازيابي مجدد حافظه را پيدا مي‌كرد (recycling). همچنين يك مورد ديگر را هم بايد در نظر داشت و آن هم وجود قابليتي است به نام ASP.NET Cache است كه امكان ذخيره سازي مقادير اشياء را در حافظه‌ي مصرفي اين پروسه مهيا مي‌سازد. هر زمان كه ميزان اين حافظه‌ي مصرفي به حد نزديكي از محدوديت تعريف شده برسد، اين پروسه به صورت خودكار شروع به حذف آن‌ها خواهد كرد.
محدوديت 60 درصدي تعريف شده، براي سيستم‌هايي با ميزان RAM كم بسيار مفيد بود اما در سيستم‌هايي با ميزان RAM بيشتر، مثلا 4 گيگ به 2.4GB حافظه مهيا (60 درصد حافظه فيزيكي سيستم) محدود مي‌شد و همچنين بايد در نظر داشت كه ميزان user mode virtual address space مهيا نيز تنها 2 گيگابايت بود. بنابراين هيچگاه استفاده مؤثري از تمام ظرفيت RAM مهيا صورت نمي‌گرفت و گاها مشاهده مي‌شد كه يك برنامه تنها با مصرف 1.5GB RAM مي‌توانست پيغام OutOfMemoryException را صادر كند. در اين حالت مطابق بررسي‌هاي صورت گرفته مشخص شد كه اگر مقدار processModel memoryLimit به حدود 800 مگابايت تنظيم شود، بهترين عملكرد را براي سيستم‌هاي مختلف مي‌توان مشاهده كرد.

با ارائه‌ي ويندوز سرور 2003 و همچنين ارائه‌ي نسخه‌ي 1.1 دات نت فريم ورك و ASP.NET ، اين وضعيت تغيير كرد. پروسه‌ي جديد در اينجا w3wp نام دارد و اين پروسه تعاريف مرتبط با محدوديت حافظه‌ي خود را از تنظيمات IIS دريافت مي‌كند (قسمت Maximum Used Memory در برگه‌ي Recycling مربوط به خواص Application Pool مرتبط). متاسفانه اين عدد به صورت پيش فرض محدوديتي ندارد و به ظاهر برنامه مجاز است تا حد امكان از حافظه‌ي مهيا استفاده كند. به همين جهت يكي از مواردي را كه بايد در نظر داشت، مقدار دهي Maximum Used Memory ذكر شده است. خصوصا اينكه در نگارش 1.1 ، تنظيمات ميزان مصرف RAM مرتبط با ASP.NET Cache نيز با برنامه يكي است.

در نگارش 2.0 دات نت فريم ورك، تنظيمات مرتبط با ASP.NET cache از تنظيمات ميزان RAM مصرفي يك برنامه‌ي ASP.NET جدا شد و اين مورد توسط قسمت cache privateBytesLimit قابل تنظيم و مديريت است (در فايل IIS Metabase و همچنين فايل web.config برنامه).

نكته!
اگر process memory limit و همچنين cache memory limit را تنظيم نكنيد، باز به همان عدد 60 درصد سابق بازخواهيم گشت و اين مورد به صورت خودكار توسط IIS محاسبه و اعمال مي‌شود. البته محدوديت ذكر شده براي پروسه‌هاي 64 بيتي در اين حالت بسيار بهتر خواهد بود. اگر هر دوي اين‌ها را تنظيم كنيد، عدد حداقل بكارگرفته شده، مبناي كار خواهد بود و اگر تنها يكي را تنظيم كنيد ، اين عدد به هر دو حالت اعمال مي‌گردد. براي بررسي بهتر مي‌توان به مقدار Cache.EffectivePrivateBytesLimit و Cache.EffectivePercentagePhysicalMemoryLimit مراجعه كرد.

و ... اكنون بهتر مي‌توانيد به اين سؤال پاسخ دهيد كه «سرور ما بيشتر از 4 گيگ رم دارد و برنامه‌ي ASP.NET من الان فقط 850 مگ رم مصرف كرده (كه البته اين هم نشاني از عدم dispose صحيح منابع است يا عدم تعيين تقدم و تاخر و زمان منقضي شدن، حين تعريف اشياء كش)، اما پيغام out of memory exception را دريافت مي‌كنم. چرا؟!»


بنابراين ايجاد يك Application pool جديد به ازاي هر برنامه‌ي ASP.NET امري است بسيار مهم زيرا:
- به اين ترتيب هر برنامه‌ي ASP.NET در پروسه‌اي ايزوله از پروسه‌ي ديگر اجرا خواهد شد (اين مساله از لحاظ امنيتي هم بسيار مهم است). در اينجا هر برنامه، از پروسه‌ي w3wp.exe مجزاي خاص خود استفاده خواهد كرد (شبيه به مرورگرهايي كه هر tab را در يك پروسه جديد اجرا مي‌كنند).
- اگر پروسه‌اي به حد بالاي مصرف حافظه‌ي خود رسيد با تنظيمات انجام شده در قسمت recycling مرتبط با Application pool اختصاصي آن، به صورت خودكار كار بازيابي حافظه صورت مي‌گيرد و اين امر بر روي ساير برنامه‌ها تاثير نخواهد داشت (كاربران ساير برنامه‌ها مدام شكايت نمي‌كنند كه سشن‌ها پريد. كش خالي شد. زيرا در حالت وجود application pool اختصاصي به ازاي هر برنامه، مديريت حافظه برنامه‌ها از هم ايزوله خواهند بود)
- كرش صورت گرفته در يك برنامه به دليل عدم مديريت خطاها، بر روي ساير برنامه‌ها تاثير منفي نخواهد گذاشت. (زمانيكه ASP.NET worker process به دليل استثنايي مديريت نشده خاتمه يابد بلافاصله و به صورت خودكار مجددا «وهله‌ي ديگري» از آن شروع به كار خواهد كرد؛ يعني تمام سشن‌هاي قبلي از بين خواهند رفت؛ كه در صورت ايزوله سازي ذكر شده، ساير برنامه‌ها در امان خواهند ماند؛ چون در پروسه ايزوله‌ي خود مشغول به كار هستند)
- با وجود application pool اختصاصي به ازاي هر برنامه، مي‌توان براي سايت‌هاي كم ترافيك و پرترافيك، زمان‌هاي recycling متفاوتي را اعمال كرد. به اين ترتيب مديريت حافظه‌ي بهتري قابل پياده سازي مي‌باشد. همچنين در اين حالت مي‌توان مشخص كرد كدام سايت از تعداد worker process بيشتر يا كمتري استفاده كند.
- كاربري كه پروسه‌ي ASP.NET تحت آن اجرا مي‌شود نيز همينجا تعريف مي‌گردد. بنابراين به اين ترتيب مي‌توان به برنامه‌اي دسترسي بيشتر و يا كمتر داد، بدون تاثير گذاري بر روي ساير برنامه‌هاي موجود.

نتيجه گيري:
- از IIS استفاده مي‌كنيد؟ آيا مي‌دانيد Application pool چيست؟
- آيا مي‌دانيد در صورت عدم مقدار دهي پارامترهاي حافظه‌ي يك Application pool ، به صورت پيش فرض چند درصد از حافظه‌ي فيزيكي مهيا در اختيار شما است؟


براي مطالعه بيشتر: