ASP.NET从源码看实现(一):请求处理过程

       ASP.NET是一个非常强大的构建Web应用的平台,它提供了极大的灵活性和能力以致于可以用它来构建所有类型的Web应用.当一个用户请求到达IIS服务后具体的处理流程是怎样的呢?

IIS处理流程图解

      在IIS服务器中运行着进程InteInfo.exe,元数据库(MetaBase)存在于InteInfo.exe进程中,在IIS6.0中有个HTTP.SYS的HTTP监听器,主要是负责HTTP请求的监听,当监听到HTTP请求时,会先根据扩展名判断请求是否是静态资源,如果是静态资源,直接以文件内容返回!

    当检测到为动态资源师,根据扩展名从IIS脚本映射找到相应的ISAPI动态连接口,ASP.NET ISAPI对应的DLL为aspnet_usapi.dll.

 IIS处理流程类:ISAPIRuntime

       IIS 所收到的对某 Microsoft ASP.NET 页面的每个请求都被移交给 ASP.NET HTTP 管线。HTTP 管线由一系列托管对象组成,这些对象按顺序处理该请求,并完成从 URL 到普通 HTML 文本的转换。HTTP 管线的入口点是 HttpRuntime 类。ASP.NET 基础结构为辅助进程中所承载的每个 AppDomain 创建此类的一个实例请注意,该辅助进程为当前正在运行的每个 ASP.NET 应用程序维护一个不同的 AppDomain。

       当一个请求到达服务器时,首先被WWW服务器截获(inetinfo.exe进程), 该进程首先判断页面后缀, 然后根据IIS中配置决定调用具体的扩展程序。aspx就会调用aspnet_isapi.dll, 然后由aspnet_isapi.dll发送给w3wp.exe(iis 工作者进程,IIS6.0中叫做 w3wq.exe,IIS5.0中叫做 aspnet_wp.exe)。

      w3wp.exe调用.NET类库进行具体处理,顺序如下:

        ISAPIRuntime->HttpRuntime-> HttpApplicationFactory->HttpApplication->HttpModule->HttpHandlerFactory->HttpHandler

      ISAPIRuntime:主要作用是调用一些非托管代码生成HttpWorkerRequest对象,HttpWorkerRequest对象包含当前请求的所有信息,然后传递给HttpRuntime
      HttpRuntime: 根据HttpWorkerRequest对象生成HttpContext,HttpContext包含request、response等属性, 再调用HttpApplicationFactory来生成IHttpHandler, 调用HttpApplication对象执行请求
      HttpApplicationFactory: 生成一个HttpApplication对象
      HttpApplication:进行HttpModule的初始化,HttpApplication创建针对此Http请求的 HttpContext对象
      HttpModule: 当一个HTTP请求到达HttpModule时,整个ASP.NET Framework系统还并没有对这个HTTP请求做任何处理,也就是说此时对于HTTP请求来讲,HttpModule是一个HTTP请求的“必经之 路”,所以可以在这个HTTP请求传递到真正的请求处理中心(HttpHandler)之前附加一些需要的信息在这个HTTP请求信息之上,或者针对截获 的这个HTTP请求信息作一些额外的工作,或者在某些情况下干脆终止满足一些条件的HTTP请求,从而可以起到一个Filter过滤器的作用。
      HttpHandlerFactory:把用户request 转发到HttpHandlerFactory,再由HttpHandlerFactory实例化HttpHandler对象来相应request
      HttpHandle:Http处理程序,处理页面请求

   //public sealed class ISAPIRuntime : MarshalByRefObject, IISAPIRuntime, IISAPIRuntime2, IRegisteredObject        
      [SecurityPermission(SecurityAction.LinkDemand, Unrestricted=true)]
        public int ProcessRequest(IntPtr ecb, int iWRType)
        {
            IntPtr zero = IntPtr.Zero;
            if (iWRType == 2)
            {
                zero = ecb;
                ecb = System.Web.UnsafeNativeMethods.GetEcb(zero);
            }
            ISAPIWorkerRequest wr = null;
            try
            {
                bool useOOP = iWRType == 1;
                wr = ISAPIWorkerRequest.CreateWorkerRequest(ecb, useOOP);
                wr.Initialize();
                string appPathTranslated = wr.GetAppPathTranslated();
                string appDomainAppPathInternal = HttpRuntime.AppDomainAppPathInternal;
                if ((appDomainAppPathInternal == null) || StringUtil.EqualsIgnoreCase(appPathTranslated, appDomainAppPathInternal))
                {
                    HttpRuntime.ProcessRequestNoDemand(wr);
                    return 0;
                }
                HttpRuntime.ShutdownAppDomain(ApplicationShutdownReason.PhysicalApplicationPathChanged, System.Web.SR.GetString("Hosting_Phys_Path_Changed", new object[] { appDomainAppPathInternal, appPathTranslated }));
                return 1;
            }
            catch (Exception exception)
            {
                try
                {
                    WebBaseEvent.RaiseRuntimeError(exception, this);
                }
                catch
                {
                }
                if ((wr == null) || !(wr.Ecb == IntPtr.Zero))
                {
                    throw;
                }
                if (zero != IntPtr.Zero)
                {
                    System.Web.UnsafeNativeMethods.SetDoneWithSessionCalled(zero);
                }
                if (exception is ThreadAbortException)
                {
                    Thread.ResetAbort();
                }
                return 0;
            }
        }

在 ISAPIRuntime 类中的ProcessRequest 方法调用中, ecb是一个指向httprequest的信息的指针,由IIS提供。CreateWorkerRequest根据ecb提供的信息,比如IIS的版本、 模式等,创建一个ISAPIWorkerRequest对象,ISAPIWorkerReuqeuest是一个http请求的.NET封装。创建好 WorkerRequest之后,调用 HttpRuntime.ProcessRequestNoDemand(iSAPIWorkerRequest);开始执行请求,这个方法是会从 httpRuntime对象中的一个队列中获取一个workerrequest进行处理,最终调用的是HttpRuntime类中的ProcessRequestInternal;

 

IIS处理流程类:HttpRuntime

 

//HttpRuntime类
        private void ProcessRequestInternal(HttpWorkerRequest wr)
        {
            Interlocked.Increment(ref this._activeRequestCount);   // 更新请求计数器
            if (this._disposingHttpRuntime)
            {
                try
                {
                    wr.SendStatus(0x1f7, "Server Too Busy");
                    wr.SendKnownResponseHeader(12, "text/html; charset=utf-8");
                    byte[] bytes = Encoding.ASCII.GetBytes("<html><body>Server Too Busy</body></html>");
                    wr.SendResponseFromMemory(bytes, bytes.Length);
                    wr.FlushResponse(true);
                    wr.EndOfRequest();
                }
                finally
                {
                    Interlocked.Decrement(ref this._activeRequestCount);
                }
            }
            else
            {
                HttpContext context;
                try
                {
                    context = new HttpContext(wr, false);// 构造 HTTP 调用上下文对象
                }
                catch
                {
                    try
                    {
                        wr.SendStatus(400, "Bad Request");
                        wr.SendKnownResponseHeader(12, "text/html; charset=utf-8");
                        byte[] data = Encoding.ASCII.GetBytes("<html><body>Bad Request</body></html>");
                        wr.SendResponseFromMemory(data, data.Length);
                        wr.FlushResponse(true);
                        wr.EndOfRequest();
                        return;
                    }
                    finally
                    {
                        Interlocked.Decrement(ref this._activeRequestCount);
                    }
                }
                wr.SetEndOfSendNotification(this._asyncEndOfSendCallback, context);// 设置发送结束异步回调函数
                HostingEnvironment.IncrementBusyCount();
                try
                {
                    try
                    {
                        this.EnsureFirstRequestInit(context);
                    }
                    catch
                    {
                        if (!context.Request.IsDebuggingRequest)
                        {
                            throw;
                        }
                    }
                    context.Response.InitResponseWriter();
                    IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(context);
                    if (applicationInstance == null)
                    {
                        throw new HttpException(System.Web.SR.GetString("Unable_create_app_object"));
                    }
                    if (EtwTrace.IsTraceEnabled(5, 1))
                    {
                        EtwTrace.Trace(EtwTraceType.ETW_TYPE_START_HANDLER, context.WorkerRequest, applicationInstance.GetType().FullName, "Start");
                    }
                    if (applicationInstance is IHttpAsyncHandler)// 使用Web应用程序实例完成实际的页面请求工作
                    {
                        IHttpAsyncHandler handler2 = (IHttpAsyncHandler) applicationInstance;
                        context.AsyncAppHandler = handler2;
                        handler2.BeginProcessRequest(context, this._handlerCompletionCallback, context);// 使用异步处理机制
                    }
                    else
                    {
                        applicationInstance.ProcessRequest(context);
                        this.FinishRequest(context.WorkerRequest, context, null);
                    }
                }
                catch (Exception exception)
                {
                    context.Response.InitResponseWriter();
                    this.FinishRequest(wr, context, exception);
                }
            }
        }

 在HttpRuntime 执行ProcessRequestInternal方法时,首先创建HttpContext类,对用户的请求与数据进行封装,然后执行HttpApplicationFactory.GetApplicationInstance(context)获取到HttpApplication;

参考以下:

http://www.cnblogs.com/yinzixin/archive/2012/10/30/2745713.html

http://www.cnblogs.com/whtydn/archive/2009/10/16/1584418.html

 

posted @ 2014-11-24 16:55  飞蛾扑火  阅读(359)  评论(0)    收藏  举报