Вътрешни елементи на архитектурата на заявката - всичко за ИТ и програмиране
Написано на 14 ноември 2013 г. Публикувано в ASP.NET
Следното обяснява подробно архитектурата на заявката на ASP.NET.
Повечето разработчици са запознати с абстракциите на високо ниво, предоставени от ASP.NET, като уеб формуляри и уеб услуги. Под тези абстракции обаче се крие една много интересна и напреднала архитектура. Познаването на вътрешността на тази архитектура не само подобрява нивото на ASP.NET разработчика, но също така им помага да пишат по-добре проектирани приложения и да решават сложни проблеми доста под високото ниво, използвано от ASP.NET.
Забележка: След като заявката напусне средата за изпълнение на ASP.NET, моделът на ASP.NET страница започва да се изпълнява. Това е извън обхвата на тази статия, но ще бъде тема на следващата статия.
Браузърът издава заявка
Процесът започва веднага щом потребителят поиска ASP.NET ресурс през браузъра. Например, потребителят поиска следния URL адрес: http://www.myserver.com/myapplication/mypage.aspx. Заявката ще достигне до "myserver", където са инсталирани Windows Server 2003 и IIS 6.0.
Драйвер http.sys в режим на ядрото прихваща заявка
След като заявката достигне IIS, тя се открива от драйвера за режим на ядрото http.sys. Следното обяснява какво представлява драйверът за режим на ядрото http.sys и какво прави.
Като цяло Windows предоставя два режима: потребителски режим и режим на ядрото. Потребителските приложения работят в потребителски режим, докато кодът на операционната система работи в режим на ядрото. Ако потребителско приложение трябва да работи директно с хардуера, тази конкретна операция се изпълнява от процес в режим на ядрото. Очевидната цел на тези режими е да защитят компонентите на операционната система от повреда от потребителяприложения. След като вече е ясно какво представляват потребителският режим и режимът на ядрото, каква е ролята на драйвера за режим на ядрото http.sys?
Когато създавате нов уеб сайт на IIS, IIS регистрира сайта в http.sys, който след това получава всички HTTP заявки за всяко уеб приложение в сайта. http.sys действа като реле, насочвайки HTTP заявки към процеса в потребителски режим, изпълняващ уеб приложението. В този случай процесът в потребителски режим е работен процес, който изпълнява набора от приложения, в който се изпълнява уеб приложението. http.sys прилага механизъм за опашка, като създава толкова опашки, колкото има пулове приложения в IIS.
Продължавайки с примера, веднага щом заявката достигне до "myserver", http.sys прихваща заявката. Да кажем, че "myapplication" е конфигуриран да работи в набора от приложения "myapplicationpool"; в този случай http.sys проверява опашката за заявки "myapplicationpool" и препраща заявката към работния процес, изпълняващ "myapplicationpool".
Заявката се препраща към пула на приложенията
Заявката се препраща към групата приложения, както е описано по-горе. Всеки набор от приложения се управлява от екземпляр на работен процес „w3wp.exe“. По подразбиране „w3wp.exe“ се изпълнява под акаунта „NetworkService“. Това може да бъде променено чрез щракване с десния бутон върху набора от приложения, хостващ приложението - раздел Свойства - Самоличност. Спомнете си, че наборът от приложения се управлява от работния процес „w3wp.exe“. Сега работният процес поема контрола.
Работният процес зарежда ASP.NET ISAPI
Работният процес “w3wp.exe” търси URL адрес на заявка, за да зареди желаното ISAPI разширение. Заявеният ресурс в URL адреса е „mypage.aspx“. Какво се случва след това? Пълна дискусия за ISAPI разширения (и филтри) не е включена в статията, но накратко, ISAPI разширенияса начинът, по който IIS обработва заявки за различни ресурси. След като инсталира ASP.NET, той инсталира свое собствено ISAPI разширение (aspnet_isapi.dll) и добавя обвързването към IIS. IIS свързва различни разширения към техните ISAPI разширения. Обвързванията в IIS могат да се видят по следния начин: щракнете с десния бутон върху уебсайта - Свойства - раздел Домашна директория - бутон Конфигурация - раздел Обвързвания. Фигурата по-долу показва връзките:
Както можете да видите, разширението „.aspx“ е свързано с разширението aspnet_isapi.dll. Работният процес предава заявката към разширението aspnet_isapi. Разширението aspnet_isapi на свой ред зарежда времето за изпълнение на HTTP и започва да обработва заявката.
Преди да разгледаме какво се случва вътре в HTTP runtime, нека да разгледаме подробностите за това как един работен процес зарежда уеб приложение. Работният поток зарежда модула на уеб приложението, като отделя един домейн на приложение на приложение. Когато работен процес стартира уеб приложение (в неговия домейн на приложение), уеб приложението наследява самоличността на процеса (NetworkService по подразбиране), ако имитацията е деактивирана. Но ако имитацията е активирана, всяко уеб приложение работи под IIS-удостоверен акаунт или потребителски акаунт, конфигуриран в web.config.
• Identity impersonate="true" o Ако IIS позволява само анонимен достъп, самоличността, предадена на уеб приложението, ще бъде [machine]\IUSR_[machine]. o Ако в IIS е активирано само Windows Integrated Authentication, самоличността, предадена на уеб приложението, ще бъде удостовереният потребител на Windows. o Ако интегрираното Windows удостоверяване и анонимният достъп са активирани, самоличността, предадена на уеб приложението, ще зависи от тази, удостоверена от IIS. Първо IISсе опитва да използва анонимен достъп, за да даде на потребител достъп до ресурс на уеб приложение. Ако този опит е неуспешен, той се опитва да използва Windows удостоверяване • Самоличност impersonate="true" username="username" password="password" o Позволява на уеб приложението да работи под конкретна самоличност.
Забележка: IIS 6.0 и IIS 5.0 обработват заявките по различен начин. Режимът на ядрото http.sys е реализиран само в IIS 6.0. IIS 5.0 няма това свойство. В IIS 5.0 заявката се прихваща директно от модула aspnet_asapi, който предава заявката на работния процес. Работният процес и ISAPI модулът комуникират чрез тръбопроводи, което води до излишни разходи за повикване. Освен това един екземпляр на работен поток обслужва всички уеб приложения; няма пулове приложения. Моделът IIS 6.0 е много по-добър от модулите IIS 5.0. Работният процес в IIS 5.0 е „aspnet_wp.exe“, за разлика от „w3wp.exe“ в IIS 6.0. Работният процес "aspnet_wp.exe" се изпълнява под стандартния акаунт "ASPNET", за разлика от "NetworkService" в IIS 6.0. Можете да промените този акаунт, като потърсите артикул
във файла “machine.config”.
Забележка: IIS 7.0 предоставя два начина за обработка на ASP.NET заявки. Първият е класическият начин, който работи по същия начин като в IIS 6.0; полезно за съвместимост. Вторият е нов начин от край до край, по който ASP.NET и IIS влизат в една и съща линия за обработка на заявки. Вторият метод свързва .NET модули и манипулатори директно към общ канал за обработка на заявки, който е по-ефективен от метода IIS 6.0.
Към средата за изпълнение на HTTP
Обобщено случилото се досега: заявката беше предадена от браузъра към http.sys, предавайки заявката към пула на приложенията. Работният процес, който управлява набора от приложения, проверява URL адреса на заявката и използваОбвързване на разширение на IIS приложение за зареждане на ASP.NET ISAPI "aspnet_isapi.dll". ASP.NET ISAPI зарежда средата за изпълнение на HTTP, известна още като среда за изпълнение на ASP.NET.
Нека започнем да научаваме какво се случва вътре в HTTP. Входната точка за изпълнение е класът HttpRuntime. Методът HttpRuntime.ProcessRequest отчита началото на обработката. Следните подраздели обсъждат какво се случва вътре в средата за изпълнение след извикване на метода ProcessRequest:
Създава се нов HttpContext екземпляр на заявката
HttpContext съществува през целия живот на заявката и е достъпен чрез статичното свойство HttpContext.Current. Обектът HttpContext представлява контекста на текущо активната заявка, тъй като съдържа препратки към обекти, които могат да бъдат достъпни по време на живота на заявката, а именно заявка, отговор, приложение, сървър и кеш. По всяко време на обработката на заявка, HttpContext.Current дава достъп до всички изброени обекти. Освен това обектът HttpContext съдържа колекция от елементи, която може да се използва за съхраняване на информация за конкретна заявка.
HttpRuntime съветва класа HttpApplicationFactory да зареди обект HttpApplication
Класът HttpApplicationFactory създава набор от обекти HttpApplication за ASP.NET приложение и свързва всяка заявка с обект HttpApplication от този набор. Ако няма обекти в пула по време на заявката, HttpApplicationFactory създава обект и го предава на заявката. В резултат на това заявката се насочва към приложението, работещо в AppDomain, и на заявката се присвоява обект HttpApplication. Сега, когато е ясно какво се случва, възниква въпросът защо е необходим обектът HttpApplication. HttpApplication - външен контейнер за конкретно уеб приложение, обвързано с клас, дефиниран вглобален.asax. При изследване на файла Global.asax се оказва, че той е наследен от класа System.Web.HttpApplication. Има набор от предварително дефинирани събития, които се активират по време на живота на заявката; тези събития са представени във файла Global.asax. HttpApplication служи като контролер за тези събития. Освен това HttpApplication поддържа списък с конфигурирани HttpModules, заредени динамично по време на обработка на заявка. Къде се изпълняват тези събития и HttpModules и какво точно представляват HttpModules и HttpHandlers? Отговорите на тези въпроси са в HTTP тръбопровода:
Във HTTP конвейера
HTTP тръбопроводът е, както подсказва името, конвейер за обработка на заявка. Нарича се конвейер, защото съдържа набор от HttpModules, които прихващат заявката по пътя към HttpHandler. HTTPModules са класове, които имат достъп до входящата заявка. Тези модули проверяват входящата заявка и вземат решения, които засягат вътрешния поток на заявката. След преминаване през дадените HTTPModules, заявката достига до HTTP манипулатора, чиято работа е да генерира изход, който се изпраща обратно към търсещия браузър.
Заявката преминава през HTTP модули
HttpModules се конфигурират на ниво машина (machine.config) и на ниво приложение (web.config). ASP.NET има много вградени HttpModules, които имат достъп до заявката и изпълняват различни функции. Тези HttpModules са модули за удостоверяване, управление на състоянието и кеширане. ASP.NET 2.0 добавя допълнителни модули, а именно членство, управление на роли и персонализиране. Фигурата по-долу е взета от файла "machine.config" и показва как са дефинирани вградените модули:
Разработчиците могат да напишат свои собствени модули и да ги включат в "machine.config", за да приложат модулите към всичкиприложения, или в "web.config" на конкретно приложение, за да приложите модули само към него. Заявките в HTTP тръбопровода преминават през всички модули, дефинирани в "machine.config" и "web.config". Както бе споменато в предишния раздел, тези модули се съхраняват в HttpApplication и се зареждат динамично при изпълнение.
Заявката засяга HTTP манипулатора
HTTP манипулаторите са крайни точки в HTTP тръбопровода. Задачата на HTTP манипулатора е да генерира изход за искания ресурс. За ASPX страници това означава превод на страниците в HTML и връщане на този HTML. HTTP манипулаторите се конфигурират на ниво машина (machine.config) и на ниво приложение (web.config). Фигурата по-долу е взета от “machine.config” и показва как са инсталирани HTTP манипулаторите.
Както можете да видите на фигурата по-горе, различните ресурси са конфигурирани да използват различни манипулатори. ASP.NET ASPX страниците са конфигурирани да използват „PageHandlerFactory“. Задачата на „PageHandlerFactory“ е да предостави HTTP инстанция, способна да обработи заявката. „PageHandleFactory“ се опитва да намери компилиран клас, представляващ исканата страница „mypage.aspx“. Ако е успешен, той предава дадения компилиран клас като HTTP манипулатор. Ако няма компилиран клас, представляващ исканата страница, защото заявката е първата или защото страницата се е променила след последната заявка, тогава "PageHandlerFactory" компилира исканата страница "mypage.aspx" и връща компилирания клас. Всички последващи заявки ще бъдат обслужвани от същия компилиран клас, докато страницата не бъде променена.
Възниква въпросът защо "PageHandlerFactory" връща екземпляр на компилирания клас, който действа като манипулатор на заявки. Дали класът е компилирандействителният HTTP манипулатор? Отговорът е очевиден от изследването на кода на отделената страница, „mypage.aspx.cs“. Страницата е наследена от класа “System.Web.UI.Page”; този клас имплементира интерфейса "IHttpHandler", което го прави подходящ като HTTP манипулатор.
Забележка: Компилирането на страница е извън обхвата на тази статия, но ще бъде разгледано в по-късна статия, която се занимава с модела на ASP.NET страница.
Изпълнението на страницата започва