سیر تا پیاز انتشار و نصب اپلیکیشن در دات نت (قسمت دوم)

در قسمت قبلی در مورد ماهیت هاست کردن صحبت کردم، و در اونجا گفتم که به دو مدل میتوانیم وب اپلیکیشن را هاست کنیم. مواردی که مطرح شد خاص اپلیکیشن های دات نتی نبود، مختص به تمام وب اپلیکیشن ها بودند. اما دات نت چه امکاناتی برای ما فراهم کرده است که بتوانیم به این دو مدل هاستینگ داشته باشیم؟ این قسمت به این موضوع پاسخ میدهیم و در انتها جمع بندی مینماییم که کدام مدل در چه شرایطی مناسب تر است؟قسمت های قبلیقسمت اولسلام، من محمد عباسی هستم. در این مقاله با ذره بین به تمام وجه های publish و deploy اپلیکیشن های دات نتی میپردازم و در این راه از مقالات، کتب و تجربیاتم استفاده میکنم.دامنه این مقاله در حوزه برنامه نویسی میماند، و به هیچ عنوان وارد مباحثی که مختص به دوستان عملیاتی و مدیرسیستمی هستند، نمیشود.فهرست مطالبمدل OutOfProcess Hostingمدل InProcess Hostingتنظیمات مربوط به هاستینگ مدلبررسی وضعیت هاستینگ در اپلیکیشن در حال اجرامدل In Process یا Out Of Process ؟در ادامهاجازه دهید شیرجه بزنیم و برویم سر اصل مطلب. در ASP.Net Core ما هر دو مدل هاستینگ که در بخش اول توضیح داده شد را میتوانیم عملی بسازیم. ولی تمام آنچه را که تاکنون گفته شد یک گوشه از ذهن خود نگهدارید و ادامه ماجرا را با ذهنی نو دنبال کنید، بوقتش آنها را پیوند میدهم. در ASP.Net Core دو نوع هاستینگ را پشتیبانی میکند بنام های In-process Hosting و Out-of-process Hosting. اما این ها چی هستند؟!مدل OutOfProcess Hostingدر این مدل از هاستینگ ما میتوانیم به دو شکل وب اپلیکیشن خودمان را هاست کنیم، هم میتوانیم اپلیکیشن را با کسترل بالا بیاوریم، و کسترل مستقیما درخواست ها را پردازش کند، هم اینکه ما بین کسترل و کلاینت، از IIS به عنوان ریورس پراکسی استفاده کنیم.پرسش گر: تاجاییکه من میدونم IIS فقط در ویندوز ساپورت میشود. پس کاربران لینوکس نمیتوانند از مدل ریورس پراکسی استفاده کنند؟پاسخ: بله، بخش اول حرف شما درست است. یعنی IIS فقط در ویندوز ساپورت میشود. اما کاربران لینوکسی میتوانند از آلترناتیوهای دیگر استفاده کنند مثل Nginx یا Apache. حتا کاربران ویندوز هم میتوانند از Nginx یا Apache استفاده کنند. اگر راحتی کار با IIS را در نظر نگیریم، عملکرد Nginx بعنوان وب سرور و ریورس پراکسی به مراتب بهتر از گزینه های دیگر هم هست. و البته Nginx در لینوکس هم به مراتب از Nginx در ویندوز بهتر است که بنظرم اینجا جای صحبت آن نیست.همانطور که در عکس زیر به وضوح نمایان است، وقتی مدل هاستینگ را با OutOfProcess تنظیم میکنیم، هم میتوانیم کسترل را بعنوان وب سرور بطور مستقیم در معرض کلاینت قرار دهیم، هم میتوانیم بین آنها از واسطِ ریورس پراکسی استفاده کنیم.در کنار این مدل از هاستینگ، مدل InProcess را نیز داریم. که در ادامه به آن میپردازیم و در نهایت به تفاوت های بین آنها اشاره خواهیم کرد.پرسش گر: مهندس چقدر حرف میزنی! این ها رو چطور عملی پیاده کنیم پس؟پاسخ: صبر کنید، به آنجا هم میرسیم! فعلا مفاهیم را خوب در ذهنتان بسپارید.مدل InProcess Hostingبعد از ریلیز نسخه net core 2.2 مایکروسافت نوع دیگری از هاستینگ بنام InProcess را معرفی کرد. در این مدل، فقط یک سرور مثل IIS یا Nginx برای هاستیگ مورد استفاده قرار میگیرد. به این معنا که اپلیکیشن بطور مستقیم درون IIS هاست میشود و دیگر سرور کسترلی در کار نخواهد بود. در اصل بجای سرور کسترل، سرور http ی IIS (IISHttpServer) استفاده میشود تا اپلیکیشن ها مستقیما روی IIS هاست شوند. و از نسخه ASP.NET Core 3.1 به بعد نیز اگر برای ایجاد اپلیکیشن از قالب های موجود استفاده کنید، مدل in-process بعنوان تنظیمات پیشفرض لحاظ میشود.اگر بخواهم مجدد تکرار کنم، در مدل In Process از Kestrel استفاده نمیشود، در عوض از یک پیاده سازی جدید وب سرور بنام IISHttpServer که مستقیما درون IIS Application Pool قرار گرفته است استفاده میشود. این پیاده سازی جدید هم خودش از هر ریکوئست آبجکت HttpContext را میسازد (که قبلا کسترل میساخت) و آن را تحویل پایپلاین Middlewareها میدهد. خب اگرچه بنظر میرسد این تغییرات از منظر سازگاری اپلیکیشن با نسخه های قدیمی بسیار جدی است، ولی هیچ مسئله ای از این منظر گزارش نشده است. و تغییرات در عمل فقط در بحث پرفورمنس بوده است.به اعتقاد خیلی ها، مایکروسافت اقدام بزرگی را بصورت موفق انجام داده است که با کمترین تغییر پرفورمنس را بهبود داده است.پرسش گر: منظورتون از کمترین تغییر چیه؟پاسخ: تغییر در اپلیکیشن. همانطور که قبلا گفتم ASP.NET Core بسیار ماژولار است و همانطور که دیدیم مقوله هاستینگ آن بطور کلی از بحث کد (خود اپلیکیشن) جدا است. اما دقیقا حرفم اینجا به این معنا است که سوییچ کردن بین In Process و Out Of Process بسیار ساده است، نه تنها خود اپلیکیشن تغییری نمیکند، بلکه شما صرفا با تغییر دادن یک فایل کانفیگ، میتوانید رفتار هاستینگ اپلیکیشن دیپلوی شده را هم تغییر دهید. جلوتر عملی میبینیم.پرسش گر: صبرکنید ببینم. گفته شد که کسترل برای کراس پلتفرم بودن عرضه شد، یعنی بتوانیم اپلیکیشن را در لینوکس هم براحتی ویندوز، اجرا کنیم. با این تفاسیر که در مدل InProcess مطرح شد که از ماژول های داخلی IIS برای ایجاد HttpContext استفاده میشود و عملا دیگر کسترلی وجود ندارد، برای اجرای InProcess در لینوکس چه کار باید کرد؟پاسخ: سوال بسیار خوبی بود. مشخص است که مطالب را با دقت دنبال میکنید. بله همانطور که عرض شد کسترل بود که امکان اجرای اپلیکیشن در لینوکس را نیز محیا میکرد، و خب مشخصا با نبود کسترل، و وابستگی فقط به IIS که آن هم فقط برای ویندوز عرضه میشود، امکان استفاده از InProcess Hosting Model در غیر از ویندوز وجود ندارد!پرسش گر: ولی خب این مدل بعدها اضافه شد، اینجوری یک شکلی از عقب گرد برای مایکروسافت نیست؟پاسخ: من در جایگاه پاسخ به این پرسش نیستم، ولی اگر نظر شخصی خودم را بخواهید باید بگویم خیر، عقب گرد نیست. همچنان خیلی از اپلیکیشن های دات نتی در زیرساخت های مایکروسافتی اجرا میشوند. مایکروسافت با این امکان پرفورمنس این اپلیکیشن ها را بالا برد. جلوتر با جزئیات بررسی خواهیم کرد که از نظر سرعت، مدل InProcess تقریبا تا دوبرابر سریع تر از OutOfProcess است.اما حالا چند سوال مطرح میشود. از کدام مدل استفاده کنیم؟ چگونه تشخیص دهیم از کدام مدل استفاده میکنیم؟ و چطور این تنظیمات را تغییر دهیم. جدا از این موارد که باید به آنها پاسخ داد، هنوز مطالبی هست که میتوان در خصوص هاستینگ مدل های مختلف مطرح کرد که من در ادامه، در خلل پاسخ به سوالات بالا آنها را مطرح میکنم.تنظیمات مربوط به هاستینگ مدلهمانطور که عرض شد تنظیم کردن و تغییر دادن تنظیمات برای مدل هاست کردن اپلیکیشن بسیار ساده است و همچنین سوییچ کردن بین آنها. تنظیمات اساسا در دو محل انجام میشود. یکی فایل کانفیگی web.config و دیگری در فایل .csproj یا همان فایل پروژه. باتوجه به ماهیت کانفیگی بودن فایل web.config، اعمال تغییرات در این فایل ساده تر است و میتوانید اپلیکیشن دیپلوی شده را نیز دستخوش تغییر دهید.تغییر در سطح پروژهخب مشخصا برای تغییر در سطح پروژه میبایست فایل csproj پروژه endpoint خودتون را کنید و تغییرات در آن اعمال کنید. در ویژوال استدیو این فایل پنهان است و زمانی نمایان میشود که در پنجره Solution Explorer روی پروژه دوبار کلیک کنید.اما در محیط های دیگر این فایل نمایان است و براحتی میتوانید آن را باز کنید.برای مشخص کردن تنظیم در فایل xml مدنظرتون باید مقدار InProcess یا مقدار OutOfProcess را درون کلید (یا تگ) AspNetCoreHostingModel قرار دهید. تکه کد زیر را مشاهده کنید:<PropertyGroup> <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel> </PropertyGroup>که خب همانطور که توضیح دادم بسته به نسخه asp.net core که استفاده میکنید یک مقدار پیشفرض هم دارد که اگر مقدار صراحتا اینجا مشخص نشود، از مقدار پیشفرض استفاده میشود.این مقدار به عملکرد دستور dotnet publish را دستخوش تغییر میدهد و در نهایت منجر به تغییر فایل web.config تولید شده توسط این دستور منتهی میشود.پرسش گر: والا به ما گفتی میخوای سیر تا پیاز پابلیش و دیپلوی رو بگی! ولی الان اولین باره که از یک دستور پابلیش صحبت کردی! چند چندی با خودت؟پاسخ: مسئله همین صحبت از سیر تا پیاز است. برای بررسی تمام جنبه های پابلیش و دیپلوی نیاز به تمام این مفاهیم است. در غیر این صورت مطرح کردن چند دستور dotnet cli چیز خاصی نیست که یک برنامه نویس دات نت نداند. کمی صبر کنید.تغییر فایل web.configهمانطور که عرض شد تنظیم مقدار برای پراپرتی <AspnetCoreHostingModel> منجر به فایل تولید شده توسط دستور پابلیش میشود. یعنی هر مقداری که در فایل پروژه تنظیم شود، در نهایت بعنوان یک خصیصه (hostingModel) در المان <aspNetCore> میشود.<aspNetCore processPath=&quotdotnet&quot arguments=&quot.\WebApplication1.dll&quot stdoutLogEnabled=&quotfalse&quot stdoutLogFile=&quot.\logs\stdout&quot hostingModel=&quotInProcess&quot /> نکته مهم اینجاست که محتویات فایل web.config رو بعد از پابلیش گرفتن هم میتوانید تغییر دهید و بین InProcess و OutOfProcess سوییچ کنید. جالب هم هست نه؟ با تغییر یک مقدار در این فایل میتوانید عملکرد برنامه خودتون رو تغییر دهید.یک نکته: منطقا شما هربار که پابلیش میگیرید، باید محتویات فولدر پابلیش جدید شود. اما شواهدی هست که بعد از یک پابلیش جدید ممکن است فایل web.config تغییری نکند. یعنی اگر بطور مثال در فایل پروژه مقدار هاستینگ را قبلا برابر با InProcess گذاشته بودید و پابلیش گرفته بودید، و حالا تغییر دادید و مقدار آن را برابر با OutOfProcess گذاشتید و مجدد پابلیش گرفتید، ممکن است فایل web.config مقدار هاستینگش همچنان InProcess باشد! برای حل چنین مشکلی پیشنهاد میشود یا فایل web.config را پاک کنید و مجدد پابلیش تهیه کنید، یا بطور کلی تمام فولدر پابلیش را حذف کنید و مجدد پابلیش تهیه کنید.بررسی وضعیت هاستینگ در اپلیکیشن در حال اجراخب اگر خودمان مشخص کرده باشیم که مدل هاستینگ چه باشد که میدانیم به چه مدل هاستینگ کردیم :)یا اگر ندانیم میتوانیم مقادیر را در فایل csproj و یا web.config را چک کنیم. اما اگر به هرجهت بخواهیم مطمئن شویم که تغییراتمان به درستی اعمال شده است یا نه، باید چکار کرد؟ در این بخش به پاسخ به این پرسش میپردازیم.چک کردن پروسه dotnetشما میتوانید در برگه پروسه های Task Manager دنبال پروسه dotnet بگردید. اگر اپلیکیشن با dotnet run اجرا شده باشد، به ازای آن یک پروسه دات نت در سیستم بوجود خواهد آمد که مشخص خواهد کرد که حتا چه dllای اجرا شده است. این مورد برای ما این را هم مشخص میکند که اپلیکیشن با تنظیم OutOfProcess اجرا شده است.چک کردن مقدار سرور در هدر Responseشاید بهتر از مورد قبل، اکتفا کردن و قبول کردن مقداری است که در پکت ریسپانس از سرور برمیگردد باشد. برای مشاهده هدر response میتوان از ابزارهای مختلفی مثل Postman استفاده کرد، اما احتمالا دم دستی تر از همه همان ابزار Developer Tools در مرورگرهایی مثل chrome است.اپلیکیشن اجرا شده را با مرورگر باز کنید. البته فراموش نکنید که F12 را بزنید تا Developer Tools هم باز باشد. سپس به برگه Network برید و یک ریکوئست به سمت سرور بفرستید تا این ابزار Response بازگشتی را capture کند.به عکس زیر توجه کنید. همانطور که مشاهده میفرمایید در بخش سرور مقدار Microsoft IIS است.این نمایش دهنده مدل هاستینگ بصورت InProcess است. به چه دلیل؟ به همان دلیلی که از قسمت قبل تا کنون راجع به آن صحبت کردیم :)ولی اگر مقدار این بخش Kestrel بود، مشخصا نشان دهنده OutOfProcess Hosting Model است.به عکس زیر توجه کنید:اجازه دهید این بخش را بیش از ادامه ندهیم. به گمان من تا همین جا کاملا کافی است. و برویم بپردازیم به مسئله مقایسه.مدل In Process یا Out Of Process ؟کدام را انتخاب کنیم؟ اساسا چه فاکتورهایی برای انتخاب دارید؟ مشخصا یکی از آنها Performance یا به نوعی سرعت پاسخ به ریکوئست هایی که به سمت سرور داده میشود. اما همواره مسئله سرعت نیست. گاهی محدودیت ها، یا امنیت یا شرایط معماری زیرساختی نیز مطرح است. میخواهم پیش از آنکه یک مدل ساده برای تست کردن مطرح کنم، با شما توافق کنم اینکه شرایط تست حاظر یک شرایط ساده است، و نتیجه این تست دلیل نمیشود که همیشه یک گزینه برای انتخاب داشته باشیم. شاید در حالت معمول سرعت پاسخ InProcess تا دو برابر از حالت OutOfProcess باشد، اما کامل این امکان پذیر است که در شرایط دیگری مدل OutOfProcess عملکرد بهتری داشته باشد نسبت به گزینه مقابل خودش. چه بسا این را هم در نظر بگیرید محدودیت بزرگ حالت InProcess این است که فقط قابل پشتیبانی در ویندوز است. و اگر شما از شیفتگان لینوکس هستید، انتخاب زیادی ندارید.برای تست من از یک اپلیکیشن سمپل API استفاده کردم، در کلاس کنترلر دو اکشن do-nothing داریم. یعنی عملا کاری نمیکند که خب با شرایط واقعی متفاوت است.public class TestController : Controller { [Route(&quotapi/helloworld&quot)] public string HelloWorld() { return &quotHello World. Time is: &quot + DateTime.Now.ToString(); } [Route(&quotapi/helloworldjson&quot)] public object HelloWorldJson() { return new { Message = &quotHello World. Time is: &quot + DateTime.Now.ToString(), Time = DateTime.Now }; } [HttpPost] [Route(&quotapi/helloworldpost&quot)] public object HelloWorldPost(string name) { return $&quotHello {name}. Time is: &quot + DateTime.Now.ToString(); } ... informational requests removed } در OutOfProcessنتیجه گزارش تست در هاستینگ OutOfProcess به شرح زیر است که در عکس آماده است:OutOfProcess with Reverse Proxyتست روی لپتاپ من با core i7 صورت گرفته است. همانطور که میبینید نتیجه نشان میدهد که در هر ثانیه چیزی بیشتر از 8.2 هزار است. اما نکته مهم این است که در این مدل از Kestrel به عنوان وب سرور استفاده شده و از IIS به عنوان Reverse Proxy استفاده شده است. اما ما یک مدل دیگر در OutOfProcess داریم که حائز اهمیت است. در عکس زیر نتیجه تست را در زمانی اندازه گرفتم که اپلیکیشن بطور مستقیم با کسترل و بدون واسطه گری IIS استفاده شده است.همانطور که مشاهده میکنید کسترل خام قدرت بیشتری در پاسخگویی دارد. یعنی پاسخ به بیش از 14 هزار ریکوئست در ثانیه.ناگفته نماند که وب سرورها اصولا در پاسخ دادن به static requestها و dynamic requestها گاها متفاوت رفتار میکنند. بعنوان مثال ممکن است یک وب سرور درخواست های ثابت را بهتر پاسخ دهند. برویم مدل InProcess را ببینیم.در InProcessخب من فقط مقدار hostingmodel را در فایل web.config به مقدار زیر تغییر میدهم و مجدد تست را انجام میدهم:hostingModel="InProcess"با همین تغییر ساده، نتیجه در عکس به شرح زیر است:نتیجه شگفت آور است. این مدل به بیش از 19 هزار ریکوئست در ثانیه پاسخ می دهد. چیزی نزدیک 2 برابر!تصور نکنید که فقط چون در InProcess یک لایه اضافه ندارد، سریع تر است. تست قبلی را بیاد بیاورید که مستقیما کسترل را اجرا کردیم و reverse proxy را حذف کردیم. نتیجه حذف این لایه به این مقدار نبود (نهایتا تا 6 هزارتا ریکوئست بهبود حاصل شد). مشخصا تفاوت در نحوه پردازش است.البته این تصور هم ایجاد نشود که اپلیکیشن شما دوبرابر سریع تر شده است! این ربطی به اپلیکیشن شما ندارد، صرفا سرعت ارتباط با اپلیکیشن بهبود پیدا کرده است.نکته نهایی اینکه اگر صرفا static page ایجاد میکردیم، این مقدار تا بیش از 50 هزار ریکوئست در ثانیه افزایش پیدا میکرد!پرسش گر: خوب بود، ولی واقعا آخر کدومش؟پاسخ: قسمت اول مقاله را بخاطر دارید؟ چندین دلیل آوردم که چرا از reverse proxy استفاده کنید خوب است. در اینجا هم نشان دادم که اگر استفاده نکنید در حالت معمول سرعت بیشتری خواهید داشت! پس مولفه های مختلفی مطرح شده است. شما بنا به شرایط خود باید انتخاب کنید!در ادامه...با وجود آنکه بسیار خوب پیش آمدیم، اما مباحث زیادی مانده است. با من همراه باشید تا قسمت بعدی!