http的请求和响应过程-----管道

以IIS 6.0为例,在工作进程w3wp.exe中,利用aspnet_isapi.dll加载.NET运行时(如果.NET运行时尚未加载),IIS 6.0引入了应用程序池的概念,一个工作进程对应着一个应用程序池。一个应用程序池可以承载一个或多个Web应用,每个Web应用映射到一个IIS虚拟目录。与IIS 5.x一样,每一个Web应用运行在各自的应用程序域中。

如果HTTP.SYS接收到的HTTP请求是对该Web应用的第一次访问,在成功加载了运行时后,会通过AppDomainFactory为该Web应用创建一个应用程序域,随后一个特殊的运行时IsapiRuntime被加载。IsapiRuntime定义在程序集System.Web中,对应的命名空间为System.Web.Hosting,被加载的IsapiRuntime会接管该HTTP请求。

IsapiRuntime会首先创建一个IsapiWorkerRequest对象,用于封装当前的HTTP请求,并将该IsapiWorkerRequest对象传递给ASP.NET运行时HttpRuntime。从此时起,HTTP请求正式进入了ASP.NET管道。HttpRuntime会根据IsapiWorkerRequest对象创建用于表示当前HTTP请求的上下文(Context)对象HttpContext。

随着HttpContext被成功创建,HttpRuntime会利用HttpApplicationFactory创建新的或获取现有的HttpApplication对象。实际上ASP.NET维护着一个HttpApplication对象池,HttpApplicationFactory从池中选取可用的HttpApplication用于处理HTTP请求,处理完毕后将其释放到对象池中。HttpApplicationFactory负责处理当前的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。上面整个处理流程如图1-11所示。


 

HttpApplication

HttpApplication是整个ASP.NET基础架构的核心,它负责处理分发给它的HTTP请求。由于一个HttpApplication对象在某个时刻只能处理一个请求,只有完成对某个请求的处理后,HttpApplication才能用于后续的请求的处理,所以ASP.NET采用对象池的机制来创建或获取HttpApplication对象。

当第一个请求抵达时,ASP.NET会一次创建多个HttpApplication对象,并将其置于池中,选择其中一个对象来处理该请求。处理完毕后,HttpApplication不会被回收,而是释放到池中。对于后续的请求,空闲的HttpApplication对象会从池中取出,如果池中所有的HttpApplication对象都处于繁忙的状态,ASP.NET会创建新的HttpApplication对象。

HttpApplication处理请求的整个生命周期是一个相对复杂的过程,在该过程的不同阶段会触发相应的事件。我们可以注册相应的事件,将处理逻辑注入到HttpApplication处理请求的某个阶段。表1-1按照实现的先后顺序列出了HttpApplication在处理每一个请求时触发的事件名称。

表1-1  HttpApplication事件列表

 

名    称 描    述
BeginRequest HTTP管道开始处理请求时,会触发BeginRequest事件
AuthenticateRequest,PostAuthenticateRequest ASP.NET先后触发这两个事件,使安全模块对请求进行身份验证
AuthorizeRequest,PostAuthorizeRequest ASP.NET先后触发这两个事件,使安全模块对请求进程授权
ResolveRequestCache,PostResolveRequestCache ASP.NET先后触发这两个事件,以使缓存模块利用缓存的内容对请求直接进行响应(缓存模块可以将响应内容进行缓存,对于后续的请求,直接将缓存的内容返回,从而提高响应能力)
PostMapRequestHandler 对于访问不同的资源类型,ASP.NET具有不同的HttpHandler对其进行处理。对于每个请求,ASP.NET会通过扩展名选择匹配相应的HttpHandler类型,成功匹配后,该实现被触发
AcquireRequestState,PostAcquireRequestState ASP.NET先后触发这两个事件,使状态管理模块获取基于当前请求相应的状态,如SessionState
PreRequestHandlerExecute,PostRequestHandlerExecute ASP.NET最终通过与请求资源类型相对应的HttpHandler实现对请求的处理,在实行HttpHandler前后,这两个实现被先后触发
ReleaseRequestState,PostReleaseRequestState ASP.NET先后触发这两个事件,使状态管理模块释放基于当前请求相应的状态
UpdateRequestCache,PostUpdateRequestCache ASP.NET先后触发这两个事件,以使缓存模块将HttpHandler处理请求得到的内容得以保存到输出缓存中
LogRequest,PostLogRequest ASP.NET先后触发这两个事件为当前请求进行日志记录
EndRequest 整个请求处理完成后,EndRequest事件被触发

对于一个ASP.NET应用来说,HttpApplication派生于Global.asax文件,我们可以通过创建global.asax文件对HttpApplication的请求处理行为进行定制。Global.asax采用一种很直接的方式实现了这样的功能,这种方式不是我们常用的方法重写或事件注册,而是直接采用方法名匹配。在Global.asax中,我们按照“Application_{Event Name}”这样的方法命名规则进行事件注册。比如Application_BeginRequest方法用于处理HttpApplication的BeginRequest事件。如果通过VS创建一个Global.asax文件,将采用如下的默认定义。
<%@ Application Language="C#" %>
<script runat="server">
    void Application_Start(object sender, EventArgs e){}   
    void Application_End(object sender, EventArgs e){}       
    void Application_Error(object sender, EventArgs e){}
    void Session_Start(object sender, EventArgs e){}
    void Session_End(object sender, EventArgs e){}
</script>
HttpModule

ASP.NET拥有一个具有高度可扩展性的引擎,并且能够处理对于不同资源类型的请求,那么是什么成就了ASP.NET的高可扩展性呢? HttpModule功不可没。

当请求转入ASP.NET管道时,最终负责处理该请求的是与请求资源类型相匹配的HttpHandler对象,但是在Handler正式工作之前,ASP.NET会先加载并初始化所有配置的HttpModule对象。HttpModule在初始化的过程中,会将一些功能注册到HttpApplication相应的事件中,在HttpApplication请求处理生命周期中的某个阶段,相应的事件会被触发,通过HttpModule注册的事件处理程序也得以执行。

所有的HttpModule都实现了具有如下定义的System.Web.IHttpModule接口,其中Init方法用于实现HttpModule自身的初始化,该方法接受一个HttpApplication对象,有了这个对象,事件注册就很容易了。
public interface IHttpModule
{
    void Dispose();
    void Init(HttpApplication context);
}

ASP.NET提供的很多基础功能都是通过相应的HttpModule实现的,下面列出了一些典型的HttpModule。

OutputCacheModule:实现了输出缓存(Output Caching)的功能。

SessionStateModule:在无状态的HTTP协议上实现了基于会话(Session)的状态。

WindowsAuthenticationModule+FormsAuthenticationModule+PassportAuthentication Module:实现了Windows、Forms和Passport这3种典型的身份认证方式。

UrlAuthorizationModule + FileAuthorizationModule:实现了基于URI和文件ACL(Access Control List)的授权。

除了这些系统定义的HttpModule之外,我们还可以自定义HttpModule,通过Web.config可以很容易地将其注册到Web应用中。

HttpHandler

对于不同资源类型的请求,ASP.NET会加载不同的Handler来处理,也就是说.aspx 页面与.asmx web 服务对应的Handler是不同的。所有的HttpHandler都实现了具有如下定义的接口System.Web.IHttpHandler,方法ProcessRequest提供了处理请求的实现。
public interface IHttpHandler
{  
    void ProcessRequest(HttpContext context);
    bool IsReusable { get; }
}

某些HttpHandler具有一个与之相关的HttpHandlerFactory,它实现了具有如下定义的接口System.Web.IHttpHandlerFactory,方法GetHandler用于创建新的HttpHandler,或者获取已经存在的HttpHandler。
public interface IHttpHandlerFactory
{
    IHttpHandler GetHandler(HttpContext context, string requestType,
      string url, string pathTranslated);
    void ReleaseHandler(IHttpHandler handler);
}

HttpHandler和HttpHandlerFactory的类型都可以通过相同的方式配置到Web.config中。下面一段配置包含对.aspx、.asmx和.svc这3种典型的资源类型的HttpHandler配置。
<configuration>
  <system.web>
    <httpHandlers>
      <add path="*.svc"
            verb="*"
            type="System.ServiceModel.Activation.HttpHandler,
                    System.ServiceModel, Version=4.0.0.0, Culture=neutral,
                    PublicKeyToken=b77a5c561934e089"
            validate="false"/>
      <add path="*.aspx"
            verb="*"
            type="System.Web.UI.PageHandlerFactory"
            validate="true"/>
      <add path="*.asmx"
            verb="*"
            type="System.Web.Services.Protocols.WebServiceHandlerFactory,
                    System.Web.Services, Version=4.0.0.0, Culture=neutral,
                    PublicKeyToken=b03f5f7f11d50a3a"
            validate="False"/>
    </httpHandlers>
  </system.web>
</configuration>

posted @ 2013-03-05 14:52  武沛齐  阅读(1761)  评论(0编辑  收藏  举报