ASP.NET与IIS是紧密联系的,因为IIS6.0与IIS7.0的工做方式的不一样,致使ASP.NET的工做原理也发生了相应的变化。数据库
IIS6(IIS7的经典模式)与IIS7的集成模式的不一样c#
IIS6的运行过程:api
分析上图可知:浏览器
在 User Mode 下,http.sys 接收到 http request,而后它会根据 IIS 中的 Metabase 查看基于该 Request 的 Application 属于哪一个 Application Pool, 若是该 Application Pool 不存在,则建立之。不然直接将 request 发到对应 Application Pool 的 Queue中。每一个 Application Pool 对应着一个 Worker Process — w3wp.exe,(运行在 User Mode 下)。服务器
在 IIS Metabase 中维护着 Application Pool 和 Worker Process 的Mapping。WAS(Web Administrative Service)根据这样一个 mapping,将存在于某个 Application Pool Queue 的 request 传递到对应的 Worker Process (若是没有,就建立这样一个进程)。在 Worker Process 初始化的时候,加载 ASP.NET ISAPI,ASP.NET ISAPI 进而加载 CLR。最后经过 AppManagerAppDomainFactory 的 Create 方法为 Application 建立一个 Application Domain;经过 ISAPIRuntime 的 ProcessRequest 处理 Request,进而将流程进入到 ASP.NET Http Runtime Pipeline。app
几个知识点:asp.net
IIS7的运行过程:ide
分析上图可知:oop
一、当客户端浏览器开始 HTTP 请求一个WEB 服务器的资源时,HTTP.sys 拦截到这个请求。性能
二、HTTP.sys 联系 WAS 获取配置信息。
三、WAS 向配置存储中心(applicationHost.config)请求配置信息。
四、WWW 服务接收到配置信息,配置信息指相似应用程序池配置信息,站点配置信息等等。
五、WWW 服务使用配置信息去配置 HTTP.sys 处理策略。
六、WAS为请求建立一个进程(若是不存在的话)。
七、工做者进程处理请求并对HTTP.sys作出响应。
八、客户端接受处处理结果信息。
除了IIS的总体运行方式不一样以外,IIS7相比IIS6最大的不一样之处在于它提供了两种应用程序池管道模式:
经典模式:是与IIS 6或者以前版本保持兼容的一种模式,一个典型问题就是,在处理ASP.NET这种动态网站的时候,它是经过一个所谓的ISAPI程序,做为插件的方式来工做的。针对不一样的动态应用程序(例如ASP,PHP等),会须要不一样的ISAPI(Internet Server Application Programe Interface,互联网服务器应用程序接口)。如图,在IIS中,打开“处理程序映射”,能够看到aspx类型页面的处理程序为aspnet_isapi.dll。
下图展现了IIS7经典模式与IIS6的应用程序池管道模式运行原理,针对不一样的请求,会指定不一样的ISAPI(dll)进行处理:
集成模式:asp.net再也不像IIS6同样只限定于aspnet_isapi.dll中,而是被解放出来,从IIS接收到HTTP请求开始,即进入asp.net的控制范围,asp.net能够存在于一个请求在IIS中各个处理阶段。容许咱们将ASP.NET更好地与IIS集成,甚至容许咱们在ASP.NET中编写一些功能(例如Module)来改变IIS的行为(扩 展)。集成的好处是,再也不经过ISAPI的方式,提升了速度和稳定性。至于扩展,则可使得咱们对于IIS,以及其余类型的请求有更多的控制。(例如,我 们但愿静态网页也具有一些特殊的行为)。如图
以下图在IIS7集成模式中,打开处理程序映射,能够看到aspx类型页面所对应的再也不是一个dll,而是一个类型。
总结与扩展:
对于处理ASP.NET应用程序而言,IIS6及IIS7的经典模式须要aspnet_isapi.dll来处理,而IIS7集成模式不须要aspnet_isapi.dll来处理,而能够直接根据文件扩展名找到相应的处理程序接口。例如aspx的处理程序是System.Web.UI.PageHandlerFactory类型。
介绍完IIS的工做原理,来看一下ASP.NET内部的运行机制。
首先看一下IIS处理模型:
上面介绍IIS工做原理时,已经介绍了从发起HTTP请求,到响应请求的过程,这里主要介绍当请求到达.NET Runtime以后,.NET运行时所发生的一系列工做。
先看以下的.NET运行时工做序列图:
1.HTTP请求进入Web服务器后,首先由HTTP.SYS来判断请求的页面是否存在,若是存在的话将把请求信息转交给.NET Runtime。在这部分实际是完成两个步骤,在将请求转交给.NET Runtime的同时将请求信息封存在HTTPWorkRequest类中供其它步骤调用。HttpWorkRequest类在之后的操做中相当重要,它第一次将Http请求信息转换为类信息。
2.当请求到达.NET Runtime后,接下来的操做将会在托管环境中完成,这时请求就真正进入了.NET中,对请求信息的操做是由.NET的底层类库来实现。首先.NET Runtime将会针对请求信息作两个动做,一是准备HostingEnvironment;二是调用ApplicationManager类为HTTP请求动态的分配AppDomain,并把处理权交给AppDomain。
3.HTTP请求进入AppDomain后,将由对象ISAPIRuntime来接管,一方面经方法ProcessRequest()获得HttpWorkerRequest对象,另外一方面由方法StartProcessing()生成HttpRuntime对象,接下来把处理权交给了HttpRuntime(HttpWorkerRequest对象将做为HttpRuntime方法中的参数被使用)。
4.HTTPRuntime接收到Http请求后,方法ProcessRequest处理请求。将对第1步中的HTTPWorkRequest类中的信息进行操做,具体的实现由ProcessRequest方法实现。内部代码以下:
[AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Medium)] public static void ProcessRequest(HttpWorkerRequest wr) { if (wr == null) { throw new ArgumentNullException("wr"); } if (UseIntegratedPipeline) { throw new PlatformNotSupportedException(System.Web.SR.GetString("Method_Not_Supported_By_Iis_Integrated_Mode", new object[] { "HttpRuntime.ProcessRequest" })); } ProcessRequestNoDemand(wr); } internal static void ProcessRequestNoDemand(HttpWorkerRequest wr) { RequestQueue queue = _theRuntime._requestQueue; if (queue != null) { wr = queue.GetRequestToExecute(wr); } if (wr != null) { CalculateWaitTimeAndUpdatePerfCounter(wr); wr.ResetStartTime(); ProcessRequestNow(wr); } } internal static void ProcessRequestNow(HttpWorkerRequest wr) { _theRuntime.ProcessRequestInternal(wr); }
5.在HttpRunTime中通过一系列的驱动后,将会在ProcessRequestInternal方法中为Http请求分配应用程序。在这一步中还将建立HttpContext对象。
context = new HttpContext(wr, false); // 基于HttpWorkerRequest生成HttpContext IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(context); // 获得HttpApplication handler2.BeginProcessRequest(context, this._handlerCompletionCallback, context); // 由HttpApplication处理请求
6.通过步骤5后HTTP请求信息才由基本信息转交给了Asp.net中的各个对象。接下来的操做会触发一些列的管道事件,这时的请求才真正转到HttpModule和HttpHandler中。
接下来咱们看看常说的管道事件的建立过程:
internal override void BuildSteps(WaitCallback stepCallback) { ArrayList steps = new ArrayList(); HttpApplication app = base._application; bool flag = false; UrlMappingsSection urlMappings = RuntimeConfig.GetConfig().UrlMappings; flag = urlMappings.IsEnabled && (urlMappings.UrlMappings.Count > 0); steps.Add(new HttpApplication.ValidatePathExecutionStep(app)); if (flag) { steps.Add(new HttpApplication.UrlMappingsExecutionStep(app)); } app.CreateEventExecutionSteps(HttpApplication.EventBeginRequest, steps); app.CreateEventExecutionSteps(HttpApplication.EventAuthenticateRequest, steps); app.CreateEventExecutionSteps(HttpApplication.EventDefaultAuthentication, steps); app.CreateEventExecutionSteps(HttpApplication.EventPostAuthenticateRequest, steps); app.CreateEventExecutionSteps(HttpApplication.EventAuthorizeRequest, steps); app.CreateEventExecutionSteps(HttpApplication.EventPostAuthorizeRequest, steps); app.CreateEventExecutionSteps(HttpApplication.EventResolveRequestCache, steps); app.CreateEventExecutionSteps(HttpApplication.EventPostResolveRequestCache, steps); steps.Add(new HttpApplication.MapHandlerExecutionStep(app)); app.CreateEventExecutionSteps(HttpApplication.EventPostMapRequestHandler, steps); app.CreateEventExecutionSteps(HttpApplication.EventAcquireRequestState, steps); app.CreateEventExecutionSteps(HttpApplication.EventPostAcquireRequestState, steps); app.CreateEventExecutionSteps(HttpApplication.EventPreRequestHandlerExecute, steps); steps.Add(new HttpApplication.CallHandlerExecutionStep(app)); //调用HttpHandler app.CreateEventExecutionSteps(HttpApplication.EventPostRequestHandlerExecute, steps); app.CreateEventExecutionSteps(HttpApplication.EventReleaseRequestState, steps); app.CreateEventExecutionSteps(HttpApplication.EventPostReleaseRequestState, steps); steps.Add(new HttpApplication.CallFilterExecutionStep(app)); app.CreateEventExecutionSteps(HttpApplication.EventUpdateRequestCache, steps); app.CreateEventExecutionSteps(HttpApplication.EventPostUpdateRequestCache, steps); this._endRequestStepIndex = steps.Count; app.CreateEventExecutionSteps(HttpApplication.EventEndRequest, steps); steps.Add(new HttpApplication.NoopExecutionStep()); this._execSteps = new HttpApplication.IExecutionStep[steps.Count]; steps.CopyTo(this._execSteps); this._resumeStepsWaitCallback = stepCallback; }
管道事件请求序列图以下: