ASP.NET之旅--浅谈Asp.net的运行机制(二)

      上篇博客基础:ASP.NET之旅--浅谈Asp.net运行机制(一)

      上节中我们从Http请求在Asp.net中的运行过程进行了分析,但是对于真正核心的东西我们并没有说明,那接下来我们将问题上抛,从底层类和对象的创建层面上来看Asp.net的运行机制。

三、Asp.net底层运行机制

 

   1、理解HTTP.SYS


       HTTP.SYS:运行于Windows核心(Kernel)的一个组件,它负责侦听(Listen)来自于外部的HTTP请求(通常来自网络中另一台计算机上的浏览器),根据请求的URL将其转发给相应的应用程序池 (Application Pool)。当此HTTP请求处理完成时,它又负责将处理结果发送出去(其接收者通常为发出HTTP请求的浏览器)。为了提供更好的性能,HTTP.SYS内部建立了一个缓冲区,将最近的HTTP请求处理结果保存起来。
       通俗点说,HTTP.SYS 判断了哪些 URL 是可以访问的, 哪些是不可以访问的。 举个简单的例子,为什么你访问不存在的文件会出现  404  错误呢,就是在这一步确定的。如果请求的是一个可访问的 URL,HTTP.SYS会将这个请求交给  IIS  工作者进程。

 

    2、AppDomain内部运行方式

 

        首先来看张图,我们可以把HTTP请求画在一张图上来看。


 

 

步骤1

 

       HTTP请求进入Web服务器后,首先由HTTP.SYS来判断请求的页面是否存在,如果存在的话将把请求信息转交给.NET Runtime。在这部分实际是完成两个步骤,在将请求转交给.NET Runtime的同时将请求信息封存在HTTPWorkRequest类中供其它步骤调用。
Note:HttpWorkRequest类在以后的操作中至关重要,它第一次将Http请求信息转换为类信息。

 

步骤2

 

      当请求到达.NET Runtime后,接下来的操作将会在托管环境中完成,这时请求就真正进入了.NET中,对请求信息的操作是由.NET的底层类库来实现。首先.NET Runtime将会针对请求信息做两个动作,一是准备HostingEnvironment;二是调用ApplicationManager类为HTTP请求动态的分配AppDomain,并把处理权交给AppDomain。

 

步骤3

 

        HTTP请求进入AppDomain后,将由对象ISAPIRuntime来接管,一方面经方法ProcessRequest()得到HttpWorkerRequest对象,另一方面由方法StartProcessing()生成HttpRuntime对象,接下来把处理权交给了HttpRuntime(HttpWorkerRequest对象将作为HttpRuntime方法中的参数被使用)。

 

步骤4

 

       HTTPRuntime接收到Http请求后,方法ProcessRequest处理请求。还记得步骤1中的HTTPWorkRequest类吗,此时将会针对该类中的信息进行操作,具体的实现由ProcessRequest方法实现。内部代码如下:

[AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Medium)]
public static void ProcessRequest(HttpWorkerRequest wr)
{
    if (wr == null)
    {
        throw new ArgumentNullException("wr");
    }
    if (UseIntegratedPipeline)
    {
        throw new PlatformNotSupportedException(System.Web.SR.GetString("Method_Not_Supported_By_Iis_Integrated_Mode", new object[] { "HttpRuntime.ProcessRequest" }));
    }
    ProcessRequestNoDemand(wr);
}
internal static void ProcessRequestNoDemand(HttpWorkerRequest wr)
{
    RequestQueue queue = _theRuntime._requestQueue;
    if (queue != null)
    {
        wr = queue.GetRequestToExecute(wr);
    }
    if (wr != null)
    {
        CalculateWaitTimeAndUpdatePerfCounter(wr);
        wr.ResetStartTime();
        ProcessRequestNow(wr);
    }
}
internal static void ProcessRequestNow(HttpWorkerRequest wr)
{
    _theRuntime.ProcessRequestInternal(wr);
}


        Note:在上面的请求中是不是看到有很多ProcessRequest()方法,该方法在很多类里面出现,但是所处理的请求并不相同。实际上我们可以理解为一个驱动,在处理的过程中通过该方法加工请求信息,然后驱动请求向下进行。

 

步骤5

 

       在HttpRunTime中经过一系列的驱动后,将会在ProcessRequestInternal方法中为Http请求分配应用程序。在这一步中还将创建HttpContext对象。

context = new HttpContext(wr, false); // 基于HttpWorkerRequest生成HttpContext
IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(context); // 得到HttpApplication
handler2.BeginProcessRequest(context, this._handlerCompletionCallback, context); // 由HttpApplication处理请求

       HttpSessionState 、HttpServerUtility等。 这些对象其实是开发人员常常使用的Asp对象,在程序中可以通过 Page 类或者 Context 类进行访问。

步骤6

 

       经过步骤5后HTTP请求信息才由基本信息转交给了Asp.net中的各个对象。接下来的操作会触发一些列的管道事件,这时的请求才真正转到HttpModule和HttpHandler中。

接下来我们看看常说的管道事件的创建过程:

internal override void BuildSteps(WaitCallback stepCallback)
{
    ArrayList steps = new ArrayList();
    HttpApplication app = base._application;
    bool flag = false;
    UrlMappingsSection urlMappings = RuntimeConfig.GetConfig().UrlMappings;
    flag = urlMappings.IsEnabled && (urlMappings.UrlMappings.Count > 0);
    steps.Add(new HttpApplication.ValidatePathExecutionStep(app));
    if (flag)
    {
        steps.Add(new HttpApplication.UrlMappingsExecutionStep(app));
    }
    app.CreateEventExecutionSteps(HttpApplication.EventBeginRequest, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventAuthenticateRequest, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventDefaultAuthentication, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventPostAuthenticateRequest, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventAuthorizeRequest, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventPostAuthorizeRequest, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventResolveRequestCache, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventPostResolveRequestCache, steps);
    steps.Add(new HttpApplication.MapHandlerExecutionStep(app));
    app.CreateEventExecutionSteps(HttpApplication.EventPostMapRequestHandler, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventAcquireRequestState, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventPostAcquireRequestState, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventPreRequestHandlerExecute, steps);
    steps.Add(new HttpApplication.CallHandlerExecutionStep(app));
    app.CreateEventExecutionSteps(HttpApplication.EventPostRequestHandlerExecute, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventReleaseRequestState, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventPostReleaseRequestState, steps);
    steps.Add(new HttpApplication.CallFilterExecutionStep(app));
    app.CreateEventExecutionSteps(HttpApplication.EventUpdateRequestCache, steps);
    app.CreateEventExecutionSteps(HttpApplication.EventPostUpdateRequestCache, steps);
    this._endRequestStepIndex = steps.Count;
    app.CreateEventExecutionSteps(HttpApplication.EventEndRequest, steps);
    steps.Add(new HttpApplication.NoopExecutionStep());
    this._execSteps = new HttpApplication.IExecutionStep[steps.Count];
    steps.CopyTo(this._execSteps);
    this._resumeStepsWaitCallback = stepCallback;
}

 

     具体的管道请求事件步骤如下图:

ASP.NET之旅--浅谈Asp.net的运行机制(二)_第1张图片

四、Asp对象的获取原则

 

Application对象

       为当前 Web 请求获取 HttpApplicationState 对象

public HttpApplicationState Application { get; }

Request对象


       获取请求的页的 HttpRequest 对象。

public HttpRequest Request { get; }


Response对象


        获取与该 Page 对象关联的 HttpResponse 对象。 该对象使您得以将 HTTP 响应数据发送到客户端,并包含有关该响应的信息。

public HttpResponse Response { get; }

Session对象


       获取 ASP.NET 提供的当前 Session 对象。
       该属性提供有关当前请求的会话的信息。 为从 ASP.NET 应用程序请求页或文档的每个用户维护一个 Session 对象。 当用户在应用程序中从一页移动到另一页时,存储在 Session 对象中的变量不会被放弃;相反,只要用户在应用程序中访问页,这些变量就将保持。

public virtual HttpSessionState Session { get; }

 

五、回顾


       说了这么多其实都是由Asp.net运行机制引发的。刚开始我们从IIS架构着说,着重介绍了IIS内部的一些结构,然后围绕该服务器管理程序展开了一系列的论述,这些论述虽然很多都是理论知识,但对于我们深入学习Web应用程序来说却有着十分重要的作用,帮助开发人员更好的开发Web应用程序打下基础。

       学习有粗有细,对于一些基本的概念或者一些整体的知识点我们要进行粗略的理解,但对于在实际开发过程中要应用到的知识我们要进行细致的掌握,这样在应用时才不至于出错,做到游刃有余。这也可以说是学习的一种全局观,对知识点有整体、粗略的把握,才能更细致的运用知识,理论加实践这才是学技术的最高境界。

       Asp.net和IIS内部运行交互过程我们已经讲完,接下来将会着重从Web应用程序角度入手讲解开发人员所需要的Asp.net知识。

你可能感兴趣的:(ASP.NET之旅--浅谈Asp.net的运行机制(二))