IIS7.0与AP.NET
IIS7在请求的监听和分发机制上进行了革新性的改进,主要体现在对于Windows进行激活服务(Windows Process Activation Service ,WAS)的引入,将原来的W3SVC的部分功能分流给了WAS。W3SVC的主要功能:HttP请求接收、配置管理、进程管理。
IIS7将后两组功能实现到了WAS中,接收Http请求的任务依然落在W3SVC上,WAS的引入为IIS7.0提供了对非Http协议的支持。WAS通过监听器适配器接口抽象出针对不同协议的监听器。具体说,除了给予网络驱动的HTTP.SYS提供的HTTP请求监听功能外还提供了TCP监听器、命名管道监听器和MSMQ监听器以提供基于TCP、命名管道和MSMQ传说协议的监听支持。这三种非HTTP监听器和监听适配器定义在程序集SMHost.exe中。
WCF提供的这三种监听器和监听适配器最终以Windows服务的形势体现。可以通过服务工作管理器对其进行单独的启动、终止:
- NetTcpPortSharing:为WCF提供TCP端口共享。
- NetTcpActivator:为WAS提供给予TCP激活的请求。
- NetPipeActivator:为WAS提供给予命名管道的激活请求
- NetMsmqActivator:为WAS提供给予MSMQ的激活请求
上图揭示了IIS7的整体架构及整个请求处理流程。无论是从W3SVC接收到的HTTP请求,还是通过WCF提供的监听适配器接收到的请求,最终都会传递到WAS。如果相应的工作流程并未创建则创建它,否则将请求分发给对应的工作进程进行后续的处理。WAS在进行请求处理过程中,通过内置的配置管理模块加载相关的配置信息,并对相关的组件进行配置。。IIS7将配置信息存放于XML形式的配置文件中,基本的配置存放在applicationHost.config中。
IIS7中实现了“你中有我,我中有你”的集成管道设计
- 可以通过本地代码和托管代码两种方式定义IIS Module
- 将ASP.NET提供的一些强大功能应用到原来难以企及的地方比如URL重写置于身份验证之前
- 采用相同的方式去实现、配置、检测和支持一些服务器特性比如:Module、Handler映射、定制错误配置等
请求管道的处理
上图主要描述ASP.NET请求的处理(粗略的)
如果HTTP.SYS接收到的HTTP请求时对该Web应用的第一次访问,在成功加载了运行时后,IIS会通过AppDomainFactory为该Web应用创建一个应用程序域,随后一个特殊的运行时IsapiRuntime被加载。IsapiRuntiome定义在程序集System.Web中,对应的命名空间为System.Web.Hosting,被加载的IsapiRuntime会接管该Http请求。
IsapiRuntime会首先创建一个IsapiWorkerRequest对象,用于封装当前的Http请求,并将IsapiWorkerRequest对象床底给ASP.NET运行时HttpRuntime、从此时起,Http请求正式进入了ASP.NET管道。HttpRuntime会根据IsapiWorkerRequest对象创建用于标示当前Http请求的上下文对象HttpContext。
随着HttpContext被创建成功,HttpRuntime会利用HttpApplication创建新的或获取现有的HttpApplication对象。实际上ASP.NET维护者一个HttpApplication对象池,HttpApplication从翅中选取可用的HttpApplication用于处理HTTP请求,处理完毕后将其释放到对象池中。HttpApplication负责处理当前的HTTP请求。
在HttpApplication初始化过程中,会根据配置文件加载并初始化相应的HttpModule对象。对于Httpapplication来说,在它处理HTTP请求的不同阶段会触发不同的事件(Event),而HttpModule的意义在于通过注册HttpApplication相应的事件,将所需的操作注入整个HTTP请求的处理流程。asp.net的很多功能,比如:身份验证、授权、缓存等,都是通过相应的HttpModule实现的
最终实现对HTTP请求的处理实现在HttpHandler中,对于不同的资源类型,具有不同的HttpHandler。比如aspx页面对应的HttpHandler为System.Web.UI.Page,WCF的.svc文件对应的Httphandler为System.ServiceModel.Activation.HttpHandler。整个的流程图:
HttpApplication
HttpApplication是整个ASP.NET基础架构的核心,它负责处理分发给他的HTTP请求。由于一个HttpApplication对象在某个时刻只能处理一个请求,只有完成对某个请求的处理后,HttpApplication才能用于后续的请求处理。所以ASP.NET采用对象池的机制来创建或获取HttpApplication独享。
当第一个请求抵达时,ASP.NET会一次创建多HttpApplication对象,并将其置于池中。选择其中一个对象来处理该请求。处理完毕后,HttpApplication不会被回收,而是释放到池中。对于后续的请求,空闲的HttpApplication对象会从池中取出,如果池中HttpApplication对象都处于繁忙状态,ASP.NET会创建新的HttpApplication对象。
HttpModule
当请求转入ASP.NET管道时,最终负责处理该请求的是与请求资源类型相匹配的HttpHandler对象,但是在Handler正式工作之前,ASP.NET会先加载并初始化所有配置的HttpModule对象。HttpModule在初始化过程中,会将一些功能注册到HttpApplication相应的事件中,在HttpApplication请求处理生命周期的某个阶段,相应的事件会被触发,通过HttpModule注册的事件处理程序得以执行。
所有的HttpModule都实现了具有如下定义的System.Web.IHttpModule接口,其中Init()用于实现HttpModule自身的初始化,该方法接收一个HttpApplication对象,,有了这个对象,事件注册就很容易了
1 namespace System.Web 2 { 3 using System; 4 5 public interface IHttpModule 6 { 7 void Dispose(); 8 void Init(HttpApplication context); 9 } 10 }
基于HttpModule实现的功能:
- OutputCacheModule:实现了输出缓存的功能
- SessionStateModule:在无状态的HTTP协议上实现了基于会话的Session的状态
- WindowsAuthenticationModule+FormsAuthenticationModule+PassportAuthenticationModule:实现了windows、Forms和Passport这3种经典的身份验证
- UrlAuthorizationModule+FileAuthorizationModule:实现了基于URI和文件ACL的授权
除了这些系统的HttpModule之外,还可以自定义HttpModule,通过WebConfig注册。
HttpHandler
对于不同资源类型的请求,ASP.NET会加载不同的Handler来处理,也就是说.aspx页与asmx web 服务对应的Handler是不同的。所有的HttpHandler都实现了具有入下定义的接口System.Web.IHttpHandler,ProcessRequest提供了处理请求的实现
1 namespace System.Web 2 { 3 using System; 4 5 public interface IHttpHandler 6 { 7 void ProcessRequest(HttpContext context); 8 9 bool IsReusable { get; } 10 } 11 }
某些HttpHandler具有一个与值相关的HttpHandlerFactory,它实现了具有如下定义的System.Web.IHttpHandlerFactory,方法GetHandler用于创建新的HttpHandler,或者获取已经存在HttpHandler
1 namespace System.Web 2 { 3 using System; 4 5 public interface IHttpHandlerFactory 6 { 7 IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated); 8 void ReleaseHandler(IHttpHandler handler); 9 } 10 }
Route
一个HTTP请求会经过至少一个HttpModule
的处理。UrlRoutingModule
是非常重要的模块,它是路由系统的核心。路由系统的职责是从请求URL中获取controller和action的名称以及其它请求数据。UrlRoutingModule
根据当前请求的URL和RouteTable
中已注册的路由模板进行匹配并返回第一个和当前请求相匹配的路有对象Route
,然后根据路有对象获取路由数据对象RouteData
(ASP.NET MVC中,路由数据必须包含controller和action的名称),再由RouteData
获取IRouteHandler
最终由IRouteHandler
得到IHttpHandler
。
Controller
IHttpHandler
在ProcessRequest
方法中对当前请求进行处理,在该方法中通过ControllerBuilder
得到IControllerFactory
然后通过反射的方式获取Controller
的类型。
Action
ASP.NET MVC中ControllerBase
是所有Controller
的基类,在该类型的Execute
方法中通过IActionInvoker
的InvokeAction
方法来执行对Action
的调用。在Action
执行前会进行模型绑定和模型认证操作。
Filters
常用的过滤器有5个:IAuthenticationFilter
、IAuthorizationFilter
、IActionFilter
、IResultFilter
、IExceptionFilter
。
在ASP.NET MVC中所有的过滤器最终都会被封装为Filter
对象,该对象中FilterScope
类型的属性Scope
和int
类型属性Order
用于决定过滤器执行的先后顺序,具体规则如下:
Order
和FilterScope
的数值越小,过滤器的执行优先级越高;Order
比FilterScope
具有更高的优先级,在Order
属性值相同时FilterScope
才会被考虑-
1 //数值越小,执行优先级越高 2 public enum FilterScope 3 { 4 Action= 30, 5 Controller= 20, 6 First= 0, 7 Global= 10, 8 Last= 100 9 }
ActionResult
Action
执行完毕之后会返回ActionResult
类型对象作为对此次请求进行处理的结果,对于不是ActionResult
类型的返回值,ASP.NET MVC会将其转换为ActionResult
类型。
请求生命周期