日期:2014-05-17  浏览次数:20994 次

ASP.NET页面周期请求过程总结

客户端
第一步:用户在地址栏里面输入地址,或者是提交表单
第二步:浏览器内部会将请求封装成HTTP请求报文,并建立Socket连接发送HTTP请求到服务器端
第三步:等待服务器端响应
服务器端:
 1、内核模块
 1.1 内核模块(HTTP.SYS)监听80端口
 1.2 监听到客户端的连接,并解析出请求的协议以及访问的端口
 1.3 查询注册表,并将此请求交给具体处理的进程(默认IIS会注册此过滤模块),此时请求分发给IIS
 -----------------------------------华丽的分割------------------------------------
 2、IIS模块
 2.1 请求来了之后,IIS首先进行校验请求的身份
 2.2 检查请求的文件的后缀,如果是静态文件则直接处理返回(比如:js,html,css,png等)
 2.3 如果是IIS处理不了的动态文件,则直接将请求交给扩展处理程序(比如:.aspx,.ashx,.ascx请求交给aspnet_isapi.dll处理【aspnet_isapi.dll
 是在.Net Framework安装的时候注册的。如果是先安装.Net Framework 后安装IIS可以使用命令:aspnet_regiis -i来进行安装(在cmd和vs的命里行
 里面都要执行一下)】)
 
 IIS内部执行的过程:请求从内核拿到后,交给了w3svc服务,然后此服务去 问IIS要元数据信息,当前请求交给哪个扩展处理。
 -----------------------------------华丽的分割------------------------------------
 3、工作进程阶段(workprocess)IIS6:w3wp.exe  IIS5:aspnet_wp.exe
 下面写的都是针对IIS6和IIS7经典过程:
 3.1 请求先到扩展模块:aspent_isapi.dll(这是一个非托管的程序集,微软写的一个实现了IIS扩展接口的一个COM的程序集。并且已经注册到了IIS
 的扩展中),它是非托管环境和托管环境的桥梁,它负责将请求的报文数据交给aspnet runtime,另外负责将aspent处理后的响应交还给IIS。另外此
 扩展会负责第一次请求来的时候,启动aspent 的runtime(appdomain等)
 -----------------------------------华丽的分割------------------------------------
 以下是托管环境中的代码(我们可以看到所有的源码)
 3.2 请求到达ISAPIRuntime
 此时请求交给public int ProcessRequest(IntPtr ecb, int iWRType)方法处理,其中第一个参数:ecb是windows操作系统的一个句柄,
 句柄的概念:句柄是windows操作系统特殊的标识,代表着操作系统的一个资源,32位操作系统是一个32位的数字,而64位的那就是64位的(了解即可);
    ecb非常niublity。拿到ecb后就可以拿到请求报文的所有的东西,在ProcessRequest方法内部,通过ecb创建了一个HttpWorkRequest实例【HttpWorkRequest
 是一个很原始的对HTTP请求报文做了简单封装,另外封装了对ecb返回数据的封装,也就是说请求都会从这里获得,响应也是从这里返回】 
 3.3 请求交给HttpRuntime类
 请求交给HttpRuntime的private void ProcessRequestInternal(HttpWorkerRequest wr)
 
 第一步:通过HttpWorkerRequest创建HttpContext上下文,此上下文会在整个Appliaction管道中流动,而且是线程安全的,HttpContext
 包含了HttpRequest对象和HttpResponse对象,它们分别封装了Http请求的请求报文以及响应的信息。
 
    第二步:获取Appliaction实例
 HttpRuntime自己不处理当前请求,而是交给一个代理对象HttpAppliaction实例。
    HttpAppliaction实例是通过如下代码获取的:
 IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(context);
    我们看到了这是做了一个对象池技术,因为HttpAppliaction创建是通过将aspnet项目里面的Global.asax编译成HttpAppliaction类型,然后
 通过反射创建出来,所以实例很宝贵,创建非常浪费性能,微软为了提高性能,使用对象池技术,使得HttpAppliaction得到了重用。在源码内部
 我们看到了对象池使用了lock栈进行了管理。可以看一下反射的代码:
 private HttpApplication GetNormalApplicationInstance(HttpContext context)
 {
  HttpApplication application = null;
  lock (this._freeList)
  {
   if (this._numFreeAppInstances > 0)
   {
    application = (HttpApplication) this._freeList.Pop();
    this._numFreeAppInstances--;
    if (this._numFreeAppInstances < this._minFreeAppInstances)
    {
     this._minFreeAppInstances = this._numFreeAppInstances;
    }
   }
  }
  if (application == null)
  {
   application = (HttpApplication) HttpRuntime.CreateNonPublicInstance(this._theApplicationType);
   using (new ApplicationImpersonationContext())
   {
    application.InitInternal(context, this._state, this._eventHandlerMethods);
   }
  }
  return application;
 }
 
 ************************************************
 在此还做了处理,如果是第一次请求的话,则首先初始化特殊的应用程序池,然后创建一个