HTTP处理流程图
以上流程的一些概念解释:
1.http.sys
是一个位于Win2003和WinXP SP2中的操作系统核心组件,能够让任何应用程序通过它提供的接口,以http协议进行信息通讯。
温馨提示:如果用户不慎删除了该驱动文件,不用担心,该驱动会在下次系统启动时重建。是一个删不掉的系统核心组件!实用程序结束该驱动,该驱动也会马上重新创建(只有粉碎文件才不能马上重建,但粉碎后,下次启动会重建)。
微软在Windows 2003 Server里引进了新的HTTP API和kernel mode driver Http.sys,目的是使基于Http服务的程序更有效率。这个改变的直接收益者就是IIS 6.0和ASP.NET。
其实在Windows XP安装SP2后,Http.sys已经出现在系统里了,但事实上,操作系统并没有真的使用这个内核级驱动,而XP上自带的IIS 5.1也没有使用HTTP API。
新的HTTP API里最核心的变化都封装在Http.sys这个kernel mode driver里了。在此之前,基于HTTP协议的程序都是在User mode下运行的,而且必须自己处理诸如软件中断、context switch、线程调度等等问题,并且往往无法自由接触系统资源。过去,HTTP服务器,如IIS, Apache等都是利用Winsock API来创建一个User mode下的network listener。Network listener通常独自(i.e.: per application or per thread basis)占用一个IP端口。通俗点说,就是在同一时间只有一个应用程序可以监听一个端口,这在有些时候是一个不太令人舒服的限制。
新的Http.sys带来的好处大致有如下一些:
1. 缓存 - 静态的内容现在被缓存于内核模式下,这使服务响应速度更快
2. 记录 (Log)-IIS的log功能更快且标准化了
3. 带宽控制 - greater scalability control and throttling
4. 可靠性 - 所有的服务请求会在Http.sys里暂存入队列,而不是由服务程序本身来处理,这样,即使服务程序重启,尚未被处理的请求也不会丢失了
5. IP端口重用 - 现在,只要是通过Http.sys管理的端口(基本包括了那些著名的端口,比如80),都可以同时允许多个程序同时监听了。
2.应用程序池
应用池即应用程序池:
在Microsoft IIS6中引入了应用程序池,这是微软的一个全新概念:应用程序池是将一个或多个应用程序链接到一个或多个工作进程集合的配置。因为应用程序池中的应用程序与其他应用程序被工作进程边界分隔,所以某个应用程序池中的应用程序不会受到其他应用程序池中应用程序所产生的问题的影响。 Windows 2003同时支持两种工作模式,默认为ISS 6.0工作进程隔离模式。工作进程隔离模式防止一个应用程序或站点停止了而影响另一个应用程序或站点,大大增强了IIS的可靠性。那么如何设置两种工作模式呢?
启动IIS管理器,右击网站,选择“属性”,打开属性对话框。在IIS 6.0工作进程隔离模式下,所有的应用程序代码都在隔离环境中运行,它们是如何进行隔离的呢?Windows 2003新增了应用程序池,工作进程隔离模式允许客户创建多个应用程序池,每个应用程序池都可以有不同的配置。因为这些应用程序池直接从内核(而非WWW 服务)接收它们的请求,所以性能和可靠性得到了增强。要隔离运行在同一台计算机上但属于不同网站的Web应用程序,需要为每个网站创建单独的应用程序池。
创建应用程序池
在IIS管理器中,打开本地计算机,右键单击“应用程序池”,选择新建“应用程序池” (必须在工作进程隔离模式下才能建立应用程序池) 。“应用程序池名称”框中,输入新的应用程序池名称。如果在“应用程序池 ID”框中出现的 ID (如:AppPool #1)不是您想要的,可进行重命名。如果您单击了“将现有应用程序池作为模板”,请在“应用程序池名称”框中右键单击想要用来作为模板的应用程序池。最后单击[确定]。
指派应用程序池
在 IIS 管理器中,右键单击您要为其指派应用程序池的应用程序,然后单击“属性”。 单击“主目录”选项卡,确认您正在指派的目录或虚拟目录的“应用程序名”是否已被填写。如果“应用程序名”框尚未被填写,请单击“创建”,然后输入名称。
在“应用程序池”列表框中,选择您想要为其指派的应用程序池的名称。最后单击[确定]。
3.aspnet_isapi.dll
这个文件是asp.net的处理文件,用于处理asp.net在iis中注册过扩展名的文件比如默认的.aspx文件注册到aspnet_isapi.dll,这样用户访问.aspx文件时,服务器自动调用aspnet_isapi.dll来处理这个文件.
这个DLL是asp.net底层的一个类库,这是它的介绍: 当客户端向web服务器请求一个*.aspx的页面文件时,同asp类似,这个http请求也会被inetinfo.exe进程截获(www服务),它判断文件后缀之后,把这个请求转交给ASPNET_ISAPI.DLL而ASPNET_ISAPI.DLL则会通过一个Http PipeLine的管道,将这个http请求发送给ASPNET_WP.EXE进程,当这个HTTP请求进入ASPNET_WP.EXE进程之后,asp.net framework就会通过HttpRuntime来处理这个Http请求,处理完毕后将结果返回给客户端。
4.CLR
http://developer.51cto.com/art/200910/158022.htm
http://developer.51cto.com/art/200909/152551.htm
5.AppDomain
http://www.cnblogs.com/chorrysky/archive/2008/07/16/1244089.html
6.ISAPIRuntime
管理 .NET Framework 中的 HttpWorkerRequest (此抽象类定义由 ASP.NET 托管代码用于处理请求的基本辅助方法和枚举)对象。
-----------------------------------------------------------------------------------------------------------------------------
当第一个请求到达时的动作如下图所示:
初始化所有核心应用程序对象之后,将通过创建 HttpApplication 类的实例启动应用程序。如果应用程序具有 Global.asax 文件,则 ASP.NET 会创建 Global.asax 类(从 HttpApplication 类派生)的一个实例,并使用该派生类表示应用程序。
每次http请求都会有一个HttpApplication类型的对象来管理这次请求的过程。
为每次http请求创建一个HttpContext对象,此对象在整个Http处理过程中都是可访问的。
HttpApplication对象负责装配出整个“HTTP请求处理管线(HTTP Pipeline)”,这相当于一条加工流水线,让HttpContext对象在这条线上过一遍。
HttpContext对象经过流水线的不同部分时,HttpApplication对象会先后激发出一连串的事件。HTTP模块(HTTP Module)可以响应这些事件,在此事件响应代码中可以对HttpContext对象进行“加工和处理”。
HTTP模块可以看成是“生产流水线”中的工人。
HTTP模块对象是在HttpApplication对象的InitModules()方法中被创建的,创建时会调用其init方法,我们一般在HTTP模块对象Init()方法中书写代码对HttpApplication对象的事件进行注册。
在流水线的中部(处理完了相关的事件),HttpContext对象被最终的Page对象所接收(这就是为何可以在ASP.NET页面中通过Page类定义的Context属性访问HttpContext对象的原因)。
每个被访问的ASP.NET页面都会被转换为一个“派生自Page类的页面类”。
Page类实现了IHttpHandler接口,此接口定义了一个ProcessRequest()方法。
ASP.NET页面类生成以后被自动编译为程序集,然后其ProcessRequest()方法被自动调用。ProcessRequest()方法的执行结果再次被HttpContext对象所承载,控制又转回到“HTTP请求处理流水线”中,HttpApplication对象继续激发后继的事件。这时,如果还有特定的HTTP模块响应这些事件,则它们会被自动调用。
HttpContext对象带着最后的处理结果来到了“HTTP请求处理管线”的未端,其信息被取出来,再次以aspnet_isapi.dll为桥梁传送给工作者进程。工作者进程再将HTTP请求的处理结果转给HTTP.SYS,由它负责将结果返回给浏览器。
我们所写的那些页面代码,以及那一套复杂的页面生命周期,都是整个asp.net周期中的一部分,所有IhttpHandler的操作,都是在Application的PreRequestHandlerExecute 事件和PostRequestHandlerExecute 事件之间完成的,IHttpHandler中的操作都是页面级别的操作,他们不能跨出页面这个范。
在应用程序级别的操作,应该使用IHttpModule。
要区分开HttpApplication和HttpApplicationState
HttpApplicationState是整个应用程序唯一的。
而HttpApplication则不是唯一的。
你在页面中写的Application[“key”] = “”value; 这个Application其实是HttpApplicationState
每一次请求都由一个HttpApplication对象来处理,在处理过程中,这个对象不能再处理其他请求,并发访问时,会为不同访问分配不同HttpApplication对象。
HttpApplicationFactory对象负责管理一个HttpApplication对象池,当有HTTP请求到来时,如果池中还有可用的 HttpApplication对象,则分配之,否则,创建一个新的HttpApplication对象。请求完毕后,HttpApplication会被回收以供再次使用。
每当新的HttpApplication对象创建时,都会根据配置创建新的Ihttpmodule对象,新的IHttpModule对象被创建时,其init方法就会被执行。
HttpApplication在不同处理阶段触发的事件列表
1. 对请求进行验证,将检查浏览器发送的信息,并确定其是否包含潜在恶意标记。有关更多信息,请参见 ValidateRequest 和脚本侵入概述。
2. 如果已在 Web.config 文件的 UrlMappingsSection 节中配置了任何 URL,则执行 URL 映射。
3. 引发 BeginRequest 事件。
4. 引发 AuthenticateRequest 事件。
5. 引发 PostAuthenticateRequest 事件。
6. 引发 AuthorizeRequest 事件。
7. 引发 PostAuthorizeRequest 事件。
8. 引发 ResolveRequestCache 事件。
9. 引发 PostResolveRequestCache 事件。
10. 根据所请求资源的文件扩展名(在应用程序的配置文件中映射),选择实现 IHttpHandler 的类,对请求进行处理。如果该请求针对从 Page 类派生的对象(页),并且需要对该页进行编译,则 ASP.NET 会在创建该页的实例之前对其进行编译。
11. 引发 PostMapRequestHandler 事件。
12. 引发 AcquireRequestState 事件。(加载初始化Session时候触发)
13. 引发 PostAcquireRequestState 事件。
14. 引发 PreRequestHandlerExecute 事件。(在HTTP请求送入HttpHandler之前触发)
15. 为该请求调用合适的 IHttpHandler 类的 ProcessRequest 方法(或异步版 BeginProcessRequest)。例如,如果该请求针对某页,则当前的页实例将处理该请求。
16. 引发 PostRequestHandlerExecute 事件。(在HTTP请求送入HttpHandler之后触发)
17. 引发 ReleaseRequestState 事件。(存储Session状态的时候触发)
18. 引发 PostReleaseRequestState 事件。
19. 如果定义了 Filter 属性,则执行响应筛选。
20. 引发 UpdateRequestCache 事件。(更新缓存信息的时候触发)
21. 引发 PostUpdateRequestCache 事件。
22. 引发 EndRequest 事件。
其他
通过使用命名约定 Application_event(如 Application_BeginRequest),ASP.NET 可在 Global.asax 文件中将应用程序事件自动绑定到处理程序。这与将 ASP.NET 页方法自动绑定到事件(如页的 Page_Load 事件)的方法类似。
如果文件扩展名尚未映射到 ASP.NET,则 ASP.NET 将不会接收该请求。对于使用 ASP.NET 身份验证的应用程序,理解这一点非常重要。例如,由于 .htm 文件通常没有映射到 ASP.NET,因此 ASP.NET 将不会对 .htm 文件请求执行身份验证或授权检查。因此,即使文件仅包含静态内容,如果希望 ASP.NET 检查身份验证,也应使用映射到 ASP.NET 的文件扩展名创建该文件,如采用文件扩展名 .aspx。
如果要创建服务于特定文件扩展名的自定义处理程序,必须在 IIS 中将该扩展名映射到 ASP.NET,还必须在应用程序的 Web.config 文件中注册该处理程序。有关更多信息,请参见 HTTP 处理程序介绍。
在AcquireRequestState事件(包含该事件) 到 PostRequestHandlerExecute事件(不包含该事件)之前这段时间里,Session都是可用的。Httphandler的ProcessRequest方法也是在这段时间内被调用的,所以用在页面中可以用Session[“key”]来访问Session。
其他参考:http://www.cnblogs.com/stg609/articles/1224943.html