بررسی اجمالی پروژه Katana

شنبه 22 خرداد 1395

در این مقاله، به بررسی نحوه پیدایش، روند تکامل و گسترش و همچنین کاربرد دو تکنولوژی محبوب Owin و Katana می پردازیم و اطلاعات جامع و دقیقی از این تکنولوژی ها ارائه می کنیم.

بررسی اجمالی پروژه Katana

بیش از ده سال از پیدایش فریم ورک ASP.NET می گذرد. در طول این مدت، این پلتفرم، امکان ساخت و توسعه ی  وب سایت ها و سرویس های بی شماری را به ما داده است. همراه با توسعه و تکامل استراتژی های مربوط به توسعه ی برنامه های تحت وب، این فریم ورک توانست همگام با تکنولوژی هایی مثل ASP.NET MVC و ASP.NET Web API پیشرفت های چشمگیری پیدا کند. زمانی که توسعه ی برنامه های تحت وب ، گام تکاملی بعدی خودش را به سمت دنیای محاسبات اّبّری (Cloud Computing) برداشت، پروژه ی Katana مجموعه ای از ابزارهای زیر ساختی مورد نیاز برای این کار را فراهم آورد که به برنامه های ASP.NET ،ویژگی هایی مانند انعطاف پذیری ، کم حجمی ، سبک بودن و قابل حمل بودن را بخشیده است و عملکرد آن ها را نیز بهبود داده است، اما از سوی دیگر، پروژه Katana بهینه سازی برنامه های ASP.NET  شما را نیز بر عهده می گیرد.

چرا Katana  ؟ چرا الان؟

وقتی در حال بررسی یک تکنولوژی هستیم، فارغ از این که این تکنولوژی ، یک فریم ورک مربوط به توسعه(developer framework) است و یا یک محصول end-user (محصولی که در نهایت، در اختیار یک کاربر نهایی قرار می گیرد.) ، دانستن این نکته ، مهم است که انگیزه اصلی برای تولید آن محصول چه بوده است، این بخش همچنین شامل این موضوع هم می شود که این محصول برای چه افرادی ایجاد شده است.

 تکنولوژی ASP.NET اساساً برای دو دسته از کاربران طراحی شده بود:

گروه اول ، کاربرانی بودند که توسعه دهندگان کلاسیک ASP به شمار می رفتند. ­­­­­­­

زمانی ، ASP یکی از تکنولوژی های اصلی و مهم برای ایجاد وب سایت ها و برنامه های داده محور و پویا محسوب می شد که قادر بود markup ها و script های سمت سرور را به صورت مناسبی با هم ترکیب کرده و نمایش بدهد. برنامه هایASP  در زمان اجرا از script های سمت سرور (server-side script) همراه با مجموعه ای از شیء ها پشتیبانی می کنند که این شی ها، ویژگی های حیاتی پروتکل های اصلی HTTP و همچنین Web server ها را در خودشان دارند و به این ترتیب، امکان دسترسی ما به سرویس هایی مانند session ، application state management ، cache و... را فراهم می کنند. در همین زمان بود که مدیریت برنامه هایی که با ASP کلاسیک قدرتمند نوشته شده بودند به یک چالش برای توسعه دهندگان تبدیل شد، زیرا حجم و پیچیدگی این برنامه ها روز به روز در حال افزایش بود. این مشکل، عمدتاً به دلیل نبود ساختار مناسب در محیط های scripting (scripting environments) و همچنین میزان بیش از حد کد در برنامه  به وجود آمده بود. مشکل حجم بالای کد، اغلب، به دلیل ادغام کد ها و markup ها اتفاق می افتاد. همان طور که دراین مقاله برخی از چالش های تکنولوژی ASP کلاسیک را بازگو می کنیم، اجازه بدهید کمی هم به نقاط قوت آن بپردازیم. تکنولوژی ASP.NET ، از کدهای ساختاریافته بهره می برد که به وسیله ی زبان های برنامه نویسی شیء گرای فریم ورک .NET  فراهم می شوند، همچنین مدل برنامه نویسی سمت سرور (server-side) را به همان شیوه ی سنتی و قدیمی که برنامه نویسان با آن خو گرفته بودند ، ارائه می کند. این دو مورد، نقاط قوت این تکنولوژی محسوب می شوند.

گروه دوم کاربران ASP.NET ، توسعه دهندگان برنامه های تجاری تحت ویندوز(Windows business application developers) بودند.

برخلاف توسعه دهندگان Asp.Net کلاسیک که عادت کرده بودند HTML markup  بنویسند و با نوشتن کد نیز HTML markup  تولید کنند، برنامه نویسان WinForm ( مثل برنامه نویسان  VB6)  به تجربه ی یک design time عادت کرده بودند که شامل یک محیط طراحی و یک مجموعه ی غنی  از کنترل های رابط کاربری (user interface control ) می شود. اولین نسخه ی ASP.NET که با نام “Web Forms” نیز شناخته می شود، یک محیط طراحی (design time) مشابه ، همراه با server-side event model در اختیار توسعه دهندگان قرار میدهد که شامل ابزار و کامپوننت های مربوط به رابط کاربری و ویژگی های زیرساختی (مانند ViewState) است. این تجهیزات با هدف ایجاد یک تجربه ی توسعه ی یکپارچه بین کاربر و برنامه نویسی سمت سرور به وجود آمده اند. Web Forms به صورت کارآمد و موثری ، طبیعت و ذات فاقد پویایی وب را در زیر پوششی از event model (مدل رویداد) پویا پنهان می کند که به میزان زیادی برای برنامه نویسان WinForms آشنا است.

چالش های ناشی از مدل قدیمی

خروجی اصلی ای که مدل قدیمی درنهایت به برنامه نویسان ارائه می داد ، شامل یک مدل توسعه یافته ی کامل و دارای  ویژگی های runtime  بسیار بود. اما در کنار همه ی این ویژگی های مثبت ، چالش های متعددی نیز وجود داشتند. اولین مشکل این بود که فریم ورک ، monolithic (یکپارچه) بود ، یعنی شامل واحد هایی بود که از نظر منطقی مجزا بودند ولی در عمل، در یک System.Web.dll assembly به صورت تفکیک ناپذیری به هم متصل شده بودند. (به عنوان مثال، شی های اصلی HTTP و Web forms framework) . مشکل دوم این بود که ASP.NET یک بخش از فریم ورک وسیع .NET به شمار می رفت و همین موضوع باعث می شد تا فاصله به روز رسانی ها و انتشار نسخه های بعدی ، سال ها طول بکشد. این مورد، باعث می شد تا ASP.NET نتواند با تغییرات سریعی که در توسعه ی وب اتفاق می افتاد، خودش را هماهنگ کند و مشکل آخر نیز این بود که روش های محدودی برای انجام عمل  Web hosting بر روی System.Web.dll وجود داشت که یکی از این روش ها  Internet Information Services (IIS)  نامیده می شود.

مراحل تکامل : ASP.NET MVC و ASP.NET Web API

تغییرات بسیاری در زمینه ی طراحی وب در حال رخ دادن بود! برنامه های تحت وب به صورت گسترده ای در حال تلاش برای توسعه و ایجاد کامپوننت های متمرکز و کوچک بودند (به جای فریم ورک های وسیع ). تعداد کامپوننت ها و همچنین سرعت انتشار آن ها به صورت باور نکردنی ای (بیش از هر زمان دیگری)، در حال افزایش بود. این نکته بدیهی بود که برای همگام شدن با این سرعت توسعه، فریم ورک ها به جای این که بزرگ تر و مجهز تر شوند، باید کوچک تر، زیاد تر و متمرکز تر می شدند. بنابراین تیم توسعه دهنده ی ASP.NET گام های تکاملی متعددی برداشتند تا بتوانند  ASP.NET را به عنوان بخشی از کامپوننت های قابل اتصال (pluggable) وب دربیاورند و آن را از حالت یک فریم ورک مستقل خارج کنند.

یکی از اولین تغییرات، افزایش محبوبیت design pattern شناخته شده ی model-view-controller (MVC) بود که این کار با بهره گیری از فریم ورک های توسعه وب ، مانند Ruby  امکان پذیر شد. این روش طراحی برنامه های تحت وب، به توسعه دهندگان،  کنترل وسیعی بر روی markup  برنامه می بخشد و همچنین مجزا بودن markup و business logic (منطق برنامه) را حفظ می کند ، که این موضوع یکی از مزیت های اصلی ASP.NET محسوب می شود.

شرکت Microsoft  ، برای این که بتواند نیاز های این روش طراحی را تامین کند، به توسعه ی ASP.NET MVC out of band پرداخت.(یعنی دست به جدا سازی MVC از .NET Framework  زد). به این ترتیب   ASP.NET MVCبه عنوان یک محصول مستقل انتشار یافت . این کار به تیم مهندسی، امکان تحویل آسان تر و سریع تر به روز رسانی های این برنامه را داد. (که در گذشته این کار به هیچ وجه امکان پذیر نبود.)

تغییر اساسی بعدی این بود که صفحاتی که قبلا به صورت کاملا داینامیک و در سمت سرور ایجاد می شدند جای خود را به markup  های پایه ای استاتیک با قسمت های داینامیک دادند. این قسمت های داینامیک توسط web api ها و از طریق ajax request ها در سمت کاربر ساخته می شوند. این تغییر در معماری، کمک شایانی به توسعه و بهبود web api ها و همچنین توسعه ی فریم ورک های ASP.NET Web API کرد.  در حیطه ی تکنولوژی ASP.NET MVC نیز ، انتشار ASP.NET Web API فرصت دیگری برای توسعه ی ASP.NET به عنوان یک فریم ورک ماژولار به وجود آورد. تیم مهندسی از این فرصت استفاده کردند و ASP.NET Web API را به گونه ای ساختند که هیچ گونه وابستگی ای به هیچ یک از انواع فریم ورک های اصلی موجود در System.Web.dll نداشته باشد. این کار دو دستاورد به دنبال داشت: مورد نخست این که ASP.NET Web API می توانست به شیوه ای کاملا مستقل توسعه پیدا کند (و می تواند مرتباً این توسعه ها را انتشار بدهد ، زیرا این کار با NuGet انجام می شود.) . مورد دوم این که بخاطر این که هیچ وابستگی خارجی به System.Web.dll وجود نداشت، , بنابراین هیچ وابستگی ای به IIS نیز در کار نبود، ASP.NET Web API این قابلیت را پیدا کرد تا در یک custom host (Host سفارشی ) اجرا شود. (به عنوان مثال در یک console application ،  Windows service و غیره)

آینده : یک فریم ورک هوشمند

با جدا سازی کامپوننت های framework ها از یکدیگر و سپس انتشار آن ها در NuGet، فریم ورک ها می توانند به صورت مستقل و سریع تری توسعه پیدا کرده و همچنین توسعه هایشان را انتشار بدهند. علاوه بر این ، قدرت و انعطاف پذیری ویژگی  self-hosting در Web API ، یک host سبک و کوچک را در اختیار توسعه دهندگان برای سرویس هایشان قرار داد. این ویژگی ، در حقیقت این نکته را ثابت کرد که بقیه ی فریم ورک ها نیز این قابلیت را نیاز دارند، همین موضوع سبب ایجاد یک چالش جدید شد به این صورت که هر فریم ورک با فرآیند مربوط به host و base address مخصوص خودش اجرا شود وهمه این امور  در نهایت نیاز به یک مدیریت قوی داشتند. (شروع، توقف و غیره...) یک برنامه وب مدرن،  اصولا باید از file serving مدرن، ایجاد داینامیک صفحات ، Web API و notifications های لحظه ای پشتیبانی کند. با در نظر گرفتن این نکته که همه این سرویس ها باید اجرا شوند و به صورت مستقل نیز مدیریت شوند، این موضوع ، واقع بینانه به نظر نمی رسد.

چیزی که برای این کار مورد نیاز بود، یک بخش host انتزاعی بود که به برنامه نویس اجازه بدهد تا یک برنامه را با استفاده از انواع مختلفی از کامپوننت ها و فریم ورک های مختلف ایجاد کند و سپس برنامه را بر روی یک host پشتیبان اجرا کند.

The Open Web Interface for .NET (OWIN)

زمانی که مزایای استفاده از Rack در Ruby community مورد توجه قرار گرفت، تعدا زیادی از اعضای .NET community تصمیم گرفتند یک انتزاع و جدایی میان وب سرورها و کامپوننت های فریم ورک ایجاد کنند. دو مورد از هدف های طراحی مفهوم OWIN ، عبارتند از سادگی و همچنین وجود حداقل وابستگی ممکن به سایر فریم ورک ها.

این دو هدف به ما کمک می کنند تا اطمینان پیدا کنیم:

ابزار و کامپوننت های جدید می توانند آسان تر توسعه پیدا کرده و مورد استفاده قرار بگیرند.

برنامه ها می توانند آسان تر بین host ها و تمامی پلتفرم ها و سیستم عامل ها جا به جا شوند.

این مفهوم از دو المان اصلی تشکیل می شود. اولی environment dictionary است. این ساختار داده ، تمام state های ضروری برای ذخیره پردازش های مربوط به یک درخواست و پاسخ HTTP  و همچنین هر server state دیگر را در اختیار دارد. environment dictionary به صورت زیر تعریف می شود:

IDictionary<string, object>

یک وب سرور سازگار با OWIN وظیفه دارد تا environment dictionary و داده هایی مانند body stream و header collection های مربوط به یک درخواست و پاسخ HTTP را در خودش جا بدهد. علاوه براین موارد ، این وب سرور در حیطه ی برنامه ها و کامپوننت های فریم ورک نیز وظیفه دارد تا dictionary را با مقادیر اضافی موجود، به روز رسانی کند و یا آن ها را ذخیره کند و سپس آن ها را در قسمت body stream مربوط به پاسخ وارد کند.

بخش OWIN specification  علاوه بر این که نوع environment dictionary را تعیین می کند، همچنین یک لیست از dictionary های key value pair (جفت کلید-مقدار) نیز تعریف می کند. به عنوان مثال، جدول زیر کلیدهای dictionary مورد نیاز برای یک درخواست HTTP را نمایش می دهد:

دومین المان کلیدی Owin ، application delegate می باشد. application delegate، یک function signature (تابع امضا و یا علامت) می باشد که به عنوان interface اصلی بین تمام اجزا (Component) در برنامه Owin به کار می رود. تعریف application delegate مانند زیر است:

Func<IDictionary<string, object>, Task>;

application delegate به زبان ساده تر بخشی از نوع Func delegate است که این تابع، environment dictionary را به عنوان ورودی می پذیرد و در خروجی ، یک Task (وظیفه) برمی گرداند. این طراحی چند نتیجه برای توسعه دهندگان دربردارد:

وابستگی های نوعی (type dependencies) بسیار کم و محدودی برای نوشتن کامپوننت های OWIN وجود دارد. این موضوع، استفاده از OWIN را برای توسعه دهندگان به میزان قابل توجهی آسان می کند.

طراحی غیرهمزمان (asynchronous) به سیستم این امکان را می دهد تا نیازی به مدیریت اضافی برای منابع محاسباتی نداشته باشد. به خصوص در عملیات های  فشرده  مربوط به I/O.

به دلیل این که application delegate یک واحد بسیار کوچکی از اجرا است و همچنین به این دلیل که environment dictionary به عنوان یک پارامتر بر روی delegate قرار می گیرد و منتقل می شود، کامپوننت های OWIN می توانند به سادگی به هم متصل شده و یک pipeline (خط لوله) پردازشی پیشرفته ی HTTP را خلق کنند. 

اگر از دید پیاده سازی به OWIN نگاه کنیم، آن را یک specification (مدل-طرح-مشخصات) می یابیم. هدف OWIN این نیست که فریم ورک وب بعدی باشد، بلکه می خواهد یک طرح باشد که نحوه ی تعامل وب سرور ها و وب فریم ورک ها را مشخص کند.

زمانی که در حال بررسی Owin  و Katana هستید، حتما Owin NuGet Package و Owin.dll هم را خواهید دید. این کتابخانه شامل یک interface و IAppBuilder (که وظیفه ی فرموله سازی و کدبندی مراحل شروع را بر عهده دارد) است. برای ساخت سرور های OWIN به IAppBuilder نیاز نخواهیم داشت، interface IAppBuilder یک نقطه ی مرجع منسجم ایجاد می کند که این نقطه به وسیله ی کامپوننت های پروژه ی Katana مورد استفاده قرار می گیرند.

پروژه Katana :

Owin Specification و Owin.dll هر دو community های خاص خودشان را دارند که تلاش هایی را به صورت open source برای توسعه این دو ارائه می کنند. با این حال، پروژه ی Katana یک مجموعه از کامپوننت های Owin را همراه با خودش ارائه می کند که با وجود open source بودن، توسط شرکت Microsoft ساخته و منتشر می شوند.

این کامپوننت ها هم شامل کامپوننت های زیرساختی(infrastructure component) و هم شامل کامپوننت های کاربردی(functional component) می شوند. Host ها  و سرور ها از جمله کامپوننت های زیرساختی و کامپوننت های احراز هویت و Signal R و ASP.NET Web API از جمله کامپوننت های کاربردی می باشند.

این پروژه  سه هدف ارزشمند زیر را دارا می باشد:

Portable (قابل حمل بودن) – کامپوننت های موجود باید بتوانند به سادگی با کامپوننت هایی که بعداً عرضه می شوند، جایگزین شوند. این موضوع، شامل همه نوع کامپوننت ها می شود، از فریم ورک ها تا سرورها و Host ها. مفهوم این هدف این است که فریم ورک های مجزا (شخص ثالث-غیرخودی) می توانند به صورت یکپارچه بر روی سرورهای Microsoft اجرا شوند. این در حالی است که فریم ورک های Microsoft به صورت بالقوه و درونی این خاصیت را دارند. (قابل اجرا شدن در سرور ها  و  Host های مجزا هستند.)

ماژولار و انعطاف پذیر بودن : برخلاف بسیاری از فریم ورک ها که ویژگی های متنوعی دارند و این ویژگی ها همواره به صورت پیش فرض، فعال هستند، کامپوننت های پروژه ی Katana باید کوچک و متمرکز باشند و امکان کنترل برنامه را به توسعه دهنده بدهند تا به این ترتیب بتواند برای استفاده از component ها در برنامه ی خود ، به صورت شخصی تصمیم بگیرد.

سبک / سریع / مقاس پذیری : با نقض شدن مفاهیم سنتی فریم ورک و پدیدار شدن یک مجموعه ی کوچک و متمرکز از کامپوننت ها که توسط برنامه نویس اضافه می شوند،  یک برنامه Katana می تواند از منابع محاسباتی کمتری استفاده کند و در نتیجه، بارگذاری های داده ای بیشتری را (نسبت به زمانی که با انوع دیگری از سرور ها کار می کرد) مدیریت کند. در این نوع برنامه به ویژگی های زیرساختی بیشتری نیاز داریم که این موارد می توانند به سادگی به OWIN pipeline اضافه شوند. البته افزودن این موارد به تصمیم شخص برنامه نویس  بستگی دارد. علاوه بر این، جایگزینی کامپوننت های سطح پایین تر به این معنی است که سرور های جدید با قدرت عملکردی بالا می توانند به صورت یکپارچه برای بهبود راندمان برنامه های OWIN مورد استفاده قرار بگیرند و سریعا با انواع قبلی جایگزین شوند، بدون این که نیاز باشد برنامه ها را به بخش های تفکیک شده بشکنیم.

شروع کار با کامپوننت های Katana

زمانی که Katana برای اولین بار معرفی شد، یکی از نکات فریم ورک Node.js که به سرعت ، توجه افراد را به خودش جذب کرد، سادگی آن بود. به طوری که یک فرد می تواند یک وب سرور بنویسد و آن را اجرا کند. اگر Katana بتواند تمامی اهداف و قابلیت های  Node.js را تحت پوشش خودش قرار بدهد، یک فرد ممکن است اینطور فکر کند که Katana بسیاری از مزایای Node.js را دارا است(و همچنین فریم ورک هایی مثل آن)  و این مزیت را هم دارد که نیاز نیست یک برنامه نویس همه ی اطلاعاتش درباره ی توسعه ی برنامه های ASP.NET را بدون استفاده رها کند و به یادگیری دانش دیگری بپردازد. با در نظر گرفتن نکاتی که در بالا گفتیم، شروع کار با Katana باید به مراتب ساده تر از Node.js باشد.

ایجاد پروژه “Hello World

یکی از تفاوت های قابل توجه بین JavaScript و توسعه ی برنامه های .NET ، نیاز به حضور (و یا عدم حضور ) یک کامپایلر است. به عنوان مثال، نقطه ی شروع یک سرور ساده Katana یک پروژه ی Visual Studio است. اگر چه ما همچنین می توانیم با حداقل نوع پروژه ها نیز شروع به کار کنیم : Empty ASP.NET Web Application

سپس ،ما Microsoft.Owin.Host.SystemWeb را از قسمت Nuget Package در داخل پروژه نصب می کنیم. این package ، یک سرور OWIN را برای ما فراهم می کند که در  ASP.NET request pipeline (خط لوله ی درخواست در ASP.NET) اجرا می شود.  شما می توانید Microsoft.Owin.Host.SystemWeb را در NuGet gallery پیدا کنید و یا همچنین می توانید با استفاده از Visual Studio package manager dialog و یا package manager console اقدام به نصب آن کنید. برای این کار باید از command زیر استفاده کنید:

install-package Microsoft.Owin.Host.SystemWeb

با نصب  Microsoft.Owin.Host.SystemWeb، یک تعداد package های اضافی  وابسته به آن نیز نصب خواهند شد. یکی از این Package های وابسته Microsoft.Owin   است. Microsoft.Owin یک کتابخانه است که انواع helper  ها و متدهای توسعه برنامه OWIN ، را فراهم می کند.ما می توانیم از آن ها برای سریع تر نوشتن سرور "hello world " بهره بگیریم.

public class Startup	
{
   public void Configuration(IAppBuilder app)
   {
      app.Run(context =>
      {
         context.Response.ContentType = "text/plain";
         return context.Response.WriteAsync("Hello World!");
      });
   }
}

این مثال،  یک وب سرور بسیار ساده  است که با زدن دکمه F5 در visual Studio میتوانید آن را  اجرا کنید و همچنین می توانید از قابلیت دیباگ نیز برای آن استفاده کنید.

Switching hosts (تعویض میزبان Host-)

برنامه Hello world قبل به صورت پیش فرض در ASP.NET request pipeline (خط لوله ی مربوط به درخواست در ASP.NET) اجرا می شود که از فضای نام System.Web در IIS استفاده میکند. این ویژگی، قابلیت فوق العاده ای به ما می بخشد به طوری که ما را قادر می کند علاوه بر این که از مزایای انعطاف پذیری و قابل ویرایش بودن OWIN pipeline بهره مند می شویم ، بتوانیم از قابلیت های مدیریتی و توسعه یافتگی IIS نیز سود ببریم. اگر چه ممکن است در برخی موارد، مزایای IIS در برنامه ما ضروری نباشند و نیاز به یک host سبک تر و کوچک تر داشته باشیم. نکته ی مهم بعدی این است که برای اجرای وب سرور ساده ای که نوشتیم، خارج از IIS  و System.Web به چه چیزی نیاز خواهیم داشت؟

برای نمایش هدف قابل حمل بودن (portability) ، به این معنی که بتوانیم از یک Web-server host به یک command line host حرکت کنیم، نیاز داریم تا به سادگی، سرور جدید و وابستگی های host را به پوشه خروجی پروژه اضافه کنیم و سپس host را در حالت شروع به کار قرار بدهیم. در این مثال، ما وب سرور خودمان را در یک Katana host به نام OwinHost.exe میزبانی خواهیم کرد و از Katana HttpListener-based server  استفاده خواهیم کرد. مشابه سایر کامپوننت های Katana ، این موارد نیز می توانند با استفاده از NuGet در پروژه قرار داده شوند. برای اضافه کردن این موارد ، از command زیر استفاده می کنیم:

install-package OwinHost

از قسمت command line ، ما می توانیم آدرس دهی را به پوشه ی root پروژه ارجاع بدهیم و سپس به راحتی OwinHost.exe را اجرا کنیم. (که در پوشه ابزار مربوط به NuGet Package نصب شده است). به طور پیش فرض ، OwinHost.exe برای جستجوی HttpListener-based server پیکر بندی شده است و بنابراین به پیکر بندی اضافی نیازی نخواهیم داشت. آدرس را در مرورگر وب به صورت http://localhost:5000/ وارد می کنیم و به این ترتیب برنامه ما که از طریق console در حال اجرا شدن است ، نمایش داده می شود.

معماری Katana:

معماری کامپوننت های Katana ، یک برنامه را به 4 لایه ی منطقی تقسیم بندی می کند. همانطوری که در شکل زیر آمده است نام های این لایه ها  host ,Server,Middleware و Application می باشد. معماری این Component ها به گونه ای طراحی شده است که پیاده سازی این لایه ها می تواند به راحتی جایگزین شوند(پیاده سازی لایه ها می توانند بر حسب نیاز، تغییر کنند)، بدون این که نیاز باشد تا برنامه را دوباره compile  کنیم.

Host

Host وظایف زیر را بر عهده دارد:

مدیریت پردازش های  زیرساختی و پایه ای

سازماندهی جریان کاری(روند برنامه) که منجر به انتخاب یک سرور و ساختن یک OWIN pipeline از طریق مدیریت درخواست های ارسال شده می شود.

در حال حاضر، 3 گزینه اصلی hosting  برای برنامه های Katana-based وجود دارند که عبارتند از:

IIS/ASP.NET : از استانداردهای نوع HttpModule و HttpHandler استفاده می کند، به همین خاطر  OWIN pipeline ها می توانند بر روی  IIS در قالب بخشی از یک جریان درخواست ASP.NET اجرا  شوند. پشتیبانی از ASP. NET hosting   با نصب NuGet package ای به نام   Microsoft.AspNet.Host.SystemWeb  در یک برنامه تحت وب امکان پذیر می شود. علاوه بر این ، چون در اینجا IIS هم نقش یک host و هم نقش یک server را ایفا می کند، یک قابلیت برجسته ی OWIN server/host با این NuGet package ادغام می شوند به این معنا که اگر از یک SystemWeb host استفاده شود، یک توسعه دهنده نمی تواند از یک سرور جایگزین دیگر استفاده کند.

Custom Host : مجموعه  کامپوننت های  Katana ، به توسعه دهندگان این قابلیت را می دهند که در فرآیند سفارشی شده خودشان،  برنامه ها را میزبانی کنند. تفاوتی نمی کند که این برنامه، یک console application ،   Windows   serviceو... باشد .این قابلیت بسیار شبیه ویژگی Self-host است که توسط Web API فراهم می شود. در مثال زیر یک host سفارشی سازی شده با کد های Web API نمایش داده شده است:

static void Main()
{
    var baseAddress = new Uri("http://localhost:5000");

    var config = new HttpSelfHostConfiguration(baseAddress);
    config.Routes.MapHttpRoute("default", "{controller}");
       
    using (var svr = new HttpSelfHostServer(config))
    {
        svr.OpenAsync().Wait();
        Console.WriteLine("Press Enter to quit.");
        Console.ReadLine();
    }
}

تنظیم Self-host برای برنامه katana نیز به صورت مشابه ، به صورت زیر انجام می شود:

static void Main(string[] args)
{
    const string baseUrl = "http://localhost:5000/";

    using (WebApplication.Start<Startup>(new StartOptions { Url = baseUrl })) 
    {
        Console.WriteLine("Press Enter to quit.");
        Console.ReadKey();
    }
}

یک تفاوت قابل توجه بین Web API و مثال های مربوط به Katana self-host این است که کد مربوط به پیکربندی Web API در نمونه های Katana self-host وجود ندارد .به دلیل این که بتوانیم هر دوی قابلیت های "قابل حمل بودن " و "قابل نوشتن بودن"(ویرایش ) را در اختیار داشته باشیم ، Katana کدهای مربوط به راه اندازی سرور را از کدهای پیکربندی request processing pipeline (خط لوله مربوط به پردازش درخواست ها )جدا می کند. قطعه کدی که Web API را پیکربندی می کند، در کلاس Startup قرار می گیرد که به صورت مجزا نیز در قالب یک پارامتر در WebApplication.Start تعریف شده است.

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var config = new HttpConfiguration();
        config.Routes.MapHttpRoute("default", "{controller}");
        app.UseWebApi(config);
    }
}

کلاس Startup  قبلا نیز با جزئیات بیشتری در این مقاله مورد بحث قرار گرفته است. اگر چه ،قطعه کد مورد نیاز برای شروع فرآیند Katana Self-host بسیار شبیه به کدی است که شما ممکن است امروزه در برنامه های ASP.NET Web API self-host  از آن استفاده کنید.

OwinHost.exe:

در حالی که برخی افراد تمایل دارند تا یک فرآیند سفارشی برای اجرای برنامه ی تحت وب Katana  ی خود ایجاد کنند، بسیاری از افراد نیز ترجیح می دهند تا به سادگی از یک برنامه از پیش ساخته شده استفاده کنند که سرور را راه اندازی و برنامه ی آن ها را اجرا کند. به دلیل رفع نیازهای هر دو گروه از این کاربران،  بسته ی کامپوننت های Katana  شامل OwinHost.exe نیز می شود. زمانی که از بخش root directory ، پروژه شروع به اجرا می کند، این بخش از برنامه(OwinHost.exe) ، سرور را در حالت شروع به کار قرار می دهد (به صورت پیش فرض از HttpListener serve برای انجام این کار استفاده می کند.) و با استفاده از یک سری قوانین و روش های خاصی startup class را پیدا و اجرا می کند. برای کنترل جزئی تر،  در برنامه ، یک سری پارامتر های command line اضافی نیز در اختیار برنامه نویس قرار می گیرد.

Server

همان طور که می دانیم host وظیفه ی آغاز کردن و نگهداری فرآیندی را برعهده دارد که برنامه را به حالت اجرا درمی آورد. وظیفه سرور نیز این است که socket شبکه را باز کند، برای دریافت درخواست ها منتظر باشد(اصطلاحاً می گویند که باید Listen کند ) و سپس درخواست هایی که دریافت می کند را از طریق pipeline (خط لوله) -که در کامپوننت های OWIN قرار دارد و از طریق کاربر انتخاب و معرفی می شود- ارسال کند. در حال حاضر پروژه ی Katana شامل دو نوع سرور است:

Microsoft.Owin.Host.SystemWeb

همان طور که قبلا نیز اشاره کردیم، IIS زمانی که با ASP.NET pipeline به کار گرفته می شود، هم به عنوان یک host و هم به عنوان یک server ایفای نقش می کند. بنابراین زمانی از این گزینه ی میزبانی برای برنامه هایمان استفاده می کنیم، IIS هم مسائل در حوزه ی host (مانند راه اندازی فرآیندها) را مدیریت می کند و هم همواره آماده برای دریافت درخواست های HTTP از جانب کاربر است. برای برنامه های ASP.NET این درخواست ها پس از دریافت، به ASP.NET pipeline فرستاده می شوند. Katana SystemWeb host یک ASP.NET HttpModule و یک ASP.NET HttpHandler  ایجاد می کند (ثبت می کند) تا درخواست هایی که در حال جریان در HTTP pipeline هستند را متوقف کند و آن ها را از طریق OWIN pipeline ای که توسط کاربر مشخص شده است، بفرستد. ( در حقیقت اجازه نمی دهد آن ها از طریق HTTP pipeline فرستاده شوند. )

Microsoft.Owin.Host.HttpListener

همان طور که از نام آن هم مشخص است، این سرور Katana از کلاس HttpListener در .NET Framework استفاده می کند تا یک socket را باز کند و درخواست ها را به OWIN pipeline مورد نظر کاربر بفرستد. این سرور، در حال حاضر ، سرور پیش فرض برای Katana self-host API و همچنین OwinHost.exe می باشد.

 Middleware/framework

همان طور که قبلا نیز بیان کردیم، زمانی که سرور،  یک درخواست از جانب کاربر را می پذیرد، وظیفه دارد تا آن را از طریق pipeline (که از کامپوننت های OWIN محسوب می شود) و در startup code (کدهای مربوط به راه اندازی اولیه برنامه) نیز توسط برنامه نویس مشخص شده است، انتقال بدهد. این کامپوننت های pipeline به عنوان میان افزار (middleware) شناخته می شوند.

اگر بخواهیم خیلی پایه ای و اساسی بررسی کنیم ، یک کامپوننت میان افزار OWIN نیاز دارد تا OWIN application delegate را نیز به کار بگیرد. در این صورت این میان افزار در بخش های دیگر برنامه نیز قابل فراخوانی(callable) می شود.

Func<IDictionary<string, object>, Task>

برای ساده سازی توسعه و ترکیب این کامپوننت های میان افزاری ، Katana از تعداد محدودی قانون و همچنین helper type بهره می گیرد. متداول ترین آن ها، کلاس OwinMiddleware است. یک کامپوننت میان افزاری سفارشی سازی شده که با کلاس OwinMiddleware ساخته شده است، در زیر نمایش داده شده است:

public class LoggerMiddleware : OwinMiddleware
{
    private readonly ILog _logger;
 
    public LoggerMiddleware(OwinMiddleware next, ILog logger) : base(next)
    {
        _logger = logger;
    }
 
    public override async Task Invoke(IOwinContext context)
    {
        _logger.LogInfo("Middleware begin");
        await this.Next.Invoke(context);
        _logger.LogInfo("Middleware end");
    }
}

این کلاس از OwinMiddleware مشتق شده است و یک constructor دارد که یک نمونه از میان افزار (middleware) بعدی در pipeline را به عنوان یکی از آرگومان هایش می گیرد و سپس آن را به constructor اصلی برنامه انتقال می دهد. آرگومان های اضافی ای که برای پیکربندی میان افزار ها استفاده می شوند نیز جزو پارامتر های constructor قرار می گیرند و بعد از آرگومان میان افزار بعدی قرار می گیرند.(آرگومان های ورودی constructor با یک نمونه از میان افزار بعدی واقع در خط لوله شروع می شوند و سپس آرگومان های اضافی تر بعد از آن می توانند قرار بگیرند. )

در زمان اجرا، میان افزار با استفاده از یک متد overridden به نام Invoke اجرا می شود. این متد ، یک آرگومان از نوع OwinContext می گیرد. این شی context با استفاده از Microsoft.Owin NuGet package به پروژه اضافه می شود که قبلا نیز درباره ی آن بحث کردیم و دسترسی از نوع strongly-typed به درخواست ، پاسخ و environment dictionary همراه با تعداد محدودی از helper type  های اضافی را برای ما فراهم می کند،

کلاس Middleware  (میان افزار ) در درون کدهای startup برنامه به راحتی می تواند به OWN Pipeline اضافه شود. این کار به صورت زیر انجام می گیرد:

public class Startup
{
   public void Configuration(IAppBuilder app)
   {
      app.Use<LoggerMiddleware>(new TraceLogger());

   }

}

کامپوننت های میان افزاری می توانند از logger های ساده تا فریم ورک هایی مانند ASP.NET, Web API و یا Siganl R متغیر باشند و این موضوع به دو دلیل امکان پذیر است:

 1- Katana infrastructure  (بخش زیرساختی Katana) یک  pipeline از کامپوننت های میان افزاری OWIN می سازد.

2- کامپوننت ها برای این که بتوانند در pipeline  قرار بگیرند، نیاز دارند تا از application delegate پشتیبانی کنند.

به عنوان مثال، اضافه کردن ASP.NET Web API به OWIN pipeline قبلی نیاز به اضافه کردن کد زیر در کد های startup دارد.

public class Startup
{
   public void Configuration(IAppBuilder app)
   {
      app.Use<LoggerMiddleware>(new TraceLogger());

      var config = new HttpConfiguration();
      // configure Web API 
      app.UseWebApi(config);

      // additional middleware registrations            
   }
}

Katana infrastructure  (بخش زیرساختی Katana) یک pipeline از کامپوننت های میان افزاری می سازد. ترتیب قرارگیری میان افزارها در pipeline به ترتیب اضافه شدن آن ها به شیء IAppBuilder در Configuration method بستگی دارد. در مثالی که زدیم، LoggerMiddleware می تواند همه ی درخواست هایی که از طریق pipeline جریان پیدا می کنند را مدیریت کند و این موضوع ، ربطی به نحوه ی مدیریت کلی آن ها توسط پروژه ندارد. این موضوع، ویژگی قدرتمندی به کامپوننت های میان افزاری می بخشد به این صورت که یک کامپوننت میان افزاری (به عنوان مثال یک کامپوننت احراز هویت) می توانند درخواست های مربوط به یک pipeline که شامل تعداد زیادی کامپوننت و فریم ورک است را پردازش کند.

برنامه ها  (Application)

همان طور که در مثال های قبلی نشان داده شد، OWIN و  پروژه Katana نباید در قالب یک مدل برنامه نویسی جدید در نظر گرفته شوند، بلکه باید به عنوان یک مفهوم (یک انتزاع- یک روش تفکر) برای جداسازی مدل های برنامه نویسی و فریم ورک ها از سرور و زیر ساخت های hosting (میزبانی) مورد استفاده و توجه قرار بگیرند. به عنوان مثال، در زمان ساخت برنامه های Web API ، فریم ورک توسعه دهنده (فریم ورکی که برنامه نویس در حال استفاده از آن است.) به استفاده از فریم ورک ASP.NET Web API ادامه میدهد، و برای این کار اصلا به اجرا شدن و یا عدم اجرای برنامه در OWIN pipeline با استفاده از کامپوننت های پروژه ی  Katana توجهی نمی کند. یکی از مکان هایی که کدهای مربوط به OWIN برای برنامه نویس نمایش داده خواهند شد، در بخش startup code برنامه است، یعنی همان مکانی که برنامه نویس، OWIN pipeline را ایجاد می کند. در بخش startup code ، برنامه نویس ، اصولا برای هر یک از کامپوننت های میان افزاری که درخواست های جاری را پردازش می کنند ،یک مجموعه از عبارت های UseXx را ثبت می کند ، این کار مانند ثبت HTTP module ها در System.Web world است. به طور معمول، یک میان افزار مربوط به فریم ورک های بزرگ تر ، مانند ASP.NET Web API و یا Signal R در انتهای pipeline ثبت خواهند شد. برخی از میان افزار ها که به نام کامپوننت های میان افزاری Cross-cutting  معروف هستند و برای مواردی مانند احراز هویت و یا عمل caching مورد استفاده قرار می گیرند، در ابتدای pipeline ثبت می شوند تا بتوانند سایر درخواست هایی که از کامپوننت ها و فریم ورک های دیگر(که بعدا در pipeline می آیند) می آیند را پردازش کنند. این عدم وابستگی میان کامپوننت های میان افزاری و همچنین کامپوننت های زیرساختی، این قابلیت را امکان پذیر می کند که سیستم کلی ما با سرعت بالا و در یک وضعیت پایدار به حرکت خودش ادامه بدهد.

کامپوننت ها - NuGet Packages

مانند خیلی از فریم ورک ها و کتابخانه های حاضر ، کامپوننت های پروژه ی Katana از طریق NuGet Packages منتشر می شوند. گراف وابستگی های Katana package برای ورژن 2 به صورت زیر است :

تقریباً تمام package  های موجود در پروژه ی Katana به صورت مستقیم و یا غیر مستقیم به Owin package وابسته هستند. شما ممکن است package ای که شامل IAppBuilder interface است را به خاطر داشته باشید، این package امکان داشتن یک اجرای منسجم از برنامه را برای ما امکان پذیر می کند. علاوه بر این، بسیاری از package ها وجود دارند که به Microsoft.Owin وابسته هستند و انواع مختلفی از helper type ها را برای کار کردن با درخواست و پاسخ های HTTP برای ما فراهم می کنند. بقیه  ی package ها نیز می توانند مانند تصویر بالا دسته بندی شوند و در دسته ی میان افزارها، package های زیر ساختی و یا ... قرار بگیرند. وابستگی های خارجی میان Package های پروژه ی Katana در تصویر بالا با رنگ نارنجی مشخص شده اند.

زیر ساخت مربوط به hosting در Katana 2.0 شامل سرور های HttpListener-based  و SystemWeb  ، پکیج OwinHost  برای اجرای برنامه های OWIN  با استفاده از OwinHost.exe   و پکیج Microsoft.Owin.Hosting  برای برنامه های self-hosting OWIN  بر روی یک host  سفارشی (مانند console application ، Windows service و غیره )می شود،

در Katana 2.0 ، کامپوننت های میان افزاری در درجه اول بر روی تامین راه های متفاوتی برای احراز هویت تمرکز می کنند. یک کامپوننت میان افزاری دیگر نیز برای اشکال یابی در اختیار برنامه نویسان قرار گرفته است، که پشتیبانی از به راه اندازی برنامه و همچنین صفحات خطا را برای برنامه نویسان فراهم می کند. به همان اندازه که OWIN در حال گسترش و توسعه ی قابلیت ها و مفاهیم خودش است ،تعداد کامپوننت های میان افزاری نیز توسط Microsoft و دیگر توسعه دهندگان در حال افزایش است.

نتیجه گیری

از آغاز پیدایش Katana ، هدف آن ساختن و ایجاد کردن نبود و به همین دلیل هم برنامه نویسان را مجبور به یادگیری هیچ دانش و علم دیگری نمی کند.  بلکه هدف آن، به وجود آوردن یک مفهوم انتزاعی بود که به وسیله آن ، توسعه دهندگان تحت وب .NET ، بتوانند گزینه های بیشتری نسبت به قبل برای انتخاب کردن در توسعه هایشان ، در پیش روی خودشان داشته باشند. با شکستن لایه های منطقی برنامه های وب متداول به کامپوننت های جایگزین، پروژه Katana به کامپوننت ها این قابلیت را می بخشد که موارد مورد نیازشان را با سرعت نسبتاً بالایی بهبود می بخشند. با به کارگیری مفهوم انتزاعی OWIN  در ساخت همه ی کامپوننت ها در یک برنامه ، Katana این قابلیت را به ما می دهد تا بتوانیم  فریم ورک ها و در صدر آن ها، برنامه ها را برای اجرا بر روی رنج وسیعی از server ها و host ها آماده کنیم. پروژه ی Katana امکان کنترل stack را به برنامه نویس می دهد تا بتواند اطمینان حاصل کند که برنامه نویس تمامی امکانات لازم را در اختیار دارد.

آموزش سی شارپ

ایمان مدائنی

نویسنده 1299 مقاله در برنامه نویسان
  • C#.net
  • 1k بازدید
  • 4 تشکر

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید