Asp.Net 请求处理过程(IIS 6)

一: IIS与ASP.NET之间的处理

IIS 5 这里就不讨论了,实际生产环境下已经基本被淘汰,我们看IIS 6(暂时不讨论IIS 7的集成模式)的ASP.net 请求处理过程如图1

0_1294718476YkWw

      图 1

      首先,我们通过一个URL地址访问网站,此时通过DNS的解析, 找到主机的IP地址,主机操作系统(只针对Windows)系统中的http.sys组件会监听到这个请求。

     注:为了避免用户应用程序访问或者修改关键的操作系统数据,windows提供了两种处理器访问模式:用户模式(User Mode)和内核模式(Kernel Mode)。一般地,用户程序运行在User mode下,而操作系统代码运行在Kernel Mode下。Kernel Mode的代码允许访问所有系统内存和所有CPU指令。

       然后,在User Mode下,http.sys接收到一个基于 aspx 的http request,然后它会根据IIS中的 Metabase 查看该基于该 Request 的 Application 属于哪个Application Pool, 如果该Application Pool不存在,则创建之。否则直接将 request 发到对应Application Pool 的 Queue中。每个 Application Pool 对应着一个Worker Process:w3wp.exe。在IIS Metabase 中维护着 Application Pool 和worker process的Mapping。WAS(Web Administrative service)根据这样一个mapping,将存在于某个Application Pool Queue的request 传递到对应的worker process(如果没有,就创建这样一个进程)。在 worker process 初始化的时候,加载ASP.NET ISAPI。
     
      同时,在w3wp.exe的内部,ASP.NET 是以 IIS ISAPI extension 的方式外加到 IIS,其实包括 ASP 以及 PHP,也都以相同的方式配置(PHP 在 IIS 采用了两种配置方式,除了 IIS ISAPI extension 的方式,也包括了 CGI 的方式,系统管理者能选择 PHP 程序的执行方式),因此客户端对 IIS 的 HTTP 请求会先经由 IIS 处理,然后 IIS 根据要求的内容类型,如果是 HTML 静态网页就由 IIS 自行处理,如果不是,就根据要求的内容类型,分派给各自的 IIS ISAPI extension;如果要求的内容类型是 ASP.NET,就分派给负责处理 ASP.NET 的 IIS ISAPI Extension,也就是 aspnet_isapi.dll,在处理请求的过程中,首先将会通过的是ISAPI过滤器的前5个步骤(ISAPI Filter 过滤器类似于HttpModule的功能,可以对Http请求做一些包装与修改,事实上这里也是可以通过C/C++来编程处理的微笑所以C/C++也是可以做网站的哦),在执行了SF_NOTIFY_AUTH_COMPLETE之后,请求会交由ISAPI Extension处理,处理完成后又交还给ISAPI Filter过滤器继续处理后面的步骤,图2是这个架构的示意图。

0_12947185968d2J

图 2

      注:在ASP.NET ISAPI内部,http请求会再次被检查安全信息,至此,请求会被检查2次,一次在IIS 中,一次在ASP.NET内部,这也是使用Asp.net开发的Web服务可以使用基于服务的验证的原因。    

     最后, ASP.NET ISAPI 进而加载CLR。通过AppManagerAppDomainFactory(位于System.Web.Hosting命名空间) 的 Create方法为 Application 创建一个Application Domain应用程序域,每个应用程序域都是互相独立的,所以网站直接不会互相干扰。然后通过 ISAPIRuntime 的 ProcessRequest处理Request,进而将流程进入到ASP.NET Http Runtime Pipeline(实际上的过程十分复杂,中间有很多抽象类和接口,这里我们从ApplicationHost开始,实际上最后还是创建了ISAP开头的那一条分支,因为网站寄宿在IIS中)

二: ASP.NET内部

1.创建应用程序域

ApplicationHost中有一个CreateApplicationHost的静态方法

image

      hostType:它表示用来跨域访问的通信对象,必须派生自MarshalByRefObject,方法将查找定义为hostType类型的程序集(一般在网站的bin目录下或者是GAC中,当然我们也可以自定义)。如图,首先这个方法会加载一个ApplicationManager对象(主要是一些上下文信息),然后调用图中红色框住部分的方法(最终调用了CreateAppDomainWithHostingEnvironment方法)创建应用程序域。事实上是在做一些读取系统配置信息,比如系统环境下的webconfig文件trustLevel等等,然后创建对应的应用程序域。

2. HttpRuntime处理请求

应用程序域创建好后,HttpRuntime会通过PorcessRequest方法来处理请求,看看ProcessRequest方法

image

       No.1:为HttpWorkerRequest类的一个实例,他是一个抽象类,在处理请求的内部扮演着十分重要的角色,主要是获取请求的几乎所有信息,然后包装在一个对象中。外部很少会调用。图中是它的一部分方法。

image

No.2内部处理请求的方法

image

终于看到了熟悉的HttpContext与IHttpHandler:

image

2.1 HttpContext

在HttpContext内部,主要构造了2个类的实例,HttpRequst和HttpResponse的对象。剩下的就交由程序员控制了。如图

image

2.2 HttpApplication

      从代码中可以看出。由一个HttpApplicationFactory的工厂来管理HttpAplication的实例,在工厂内部存在一个对象池,使得被创建的对象可以被重复使用,但是基本上每个对象每一次只会处理一个请求。

image

 image 

    image

        在请求的过程中,会有很多的事情需要处理,Asp.net引入了管道机制,通过事件把这些处理过程封装起来,使得程序员可以进行编程。关于管道可以查看这里的介绍http://book.51cto.com/art/201102/245029.htm

2.3 IHttpHandler

    对外的一个HttpApplication的引用接口,可以实现自己的ProcessRequest()处理

    http://www.cnblogs.com/stwyhm/archive/2006/08/09/471765.html

2.4 IHttpModule

实际上就是对HttpApplication中的事件的对外编程接口。可以自己定义实现事件,包装或修改Http请求和Http响应

image

这里怎么使用就不再讨论了。

推荐:http://www.cnblogs.com/stwyhm/archive/2006/08/09/471729.html

2.5 System.Web.UI.Page

   Page类最终实现了IHttpHandler接口,就得到了处理请求功能,并且他在自己内部也有自己处理请求ProcessRequest()的实现,包括加入一些多语言信息等等,最后渲染HTML页面.这里不再做细致的讨论.(Page中的Application熟悉是HttpApplicationState的对象,不是HttpApplication)

总结:

      这里只是简单研究了一下IIS以及Asp.net如何处理Http请求,只是沿着处理请求这条直线一直往下走,期间有很多的分支,比如如何处理Cookie,Session,如何处理ApplicationState,安全验证,等等都没有提及,这些会在以后再继续研究。

参考资料:

http://blog.csdn.net/dz45693/archive/2009/12/17/5027882.aspx

http://book.51cto.com/art/201102/245003.htm

http://book.51cto.com/art/201102/245025.htm

http://www.cnblogs.com/dooom/archive/2010/10/08/1845981.html

工具:Reflector 7.0

posted @ 2011-04-21 22:50  wjn2010  阅读(1091)  评论(1编辑  收藏  举报