zoukankan      html  css  js  c++  java
  • Asp.net请求处理之 管道处理

    在了解Asp.net请求处理流程的过程中,个人认为有必要从源代码的角度来了解asp.net管道是怎么实现的。

    在此之前大家有必要了解一些asp.net请求流程的基本东东,如ASP.NET 请求处理流程Asp.net管道ASP.NET管线与应用程序生命周期 

    我们大家都知道HttpRuntime主要的方法是

    public static void ProcessRequest(HttpWorkerRequest wr)

    private void ProcessRequestInternal(HttpWorkerRequest wr)
    {
        HttpContext context;
        try
        {
            context = new HttpContext(wr, false);
        }
        catch
        {
            wr.SendStatus(400, "Bad Request");
            wr.SendKnownResponseHeader(12, "text/html; charset=utf-8");
            byte[] bytes = Encoding.ASCII.GetBytes("<html><body>Bad Request</body></html>");
            wr.SendResponseFromMemory(bytes, bytes.Length);
            wr.FlushResponse(true);
            wr.EndOfRequest();
            return;
        }
        wr.SetEndOfSendNotification(this._asyncEndOfSendCallback, context);
        Interlocked.Increment(ref this._activeRequestCount);
        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(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)
            {
                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);
        }
    }
    

      

    我们看到里面有这么一句

    IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(context);用来获取HttpApplication,而HttpApplication实现了IHttpAsyncHandler接口public class HttpApplication : IHttpAsyncHandler, IHttpHandler, IComponent, IDisposable,最后调用application的BeginProcessRequest方法。
    HttpApplicationFactory.GetApplicationInstance(context)主要是调用GetNormalApplicationInstance

    internal static IHttpHandler GetApplicationInstance(HttpContext context)
    {
        if (_customApplication != null)
        {
            return _customApplication;
        }
        if (context.Request.IsDebuggingRequest)
        {
            return new HttpDebugHandler();
        }
        _theApplicationFactory.EnsureInited();
        _theApplicationFactory.EnsureAppStartCalled(context);
        return _theApplicationFactory.GetNormalApplicationInstance(context);
    }
    

      

    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;
    }
    

      在GetNormalApplicationInstance里面有一个比较关键的方法application.InitInternal(context, this._state, this._eventHandlerMethods);我们猜测它是做Application初始化的工作,包括http管道的初始化。

    internal void InitInternal(HttpContext context, HttpApplicationState state, MethodInfo[] handlers)
    {
        this._state = state;
        PerfCounters.IncrementCounter(AppPerfCounter.PIPELINES);
        try
        {
            try
            {
                this._initContext = context;
                this._initContext.ApplicationInstance = this;
                context.ConfigurationPath = context.Request.ApplicationPathObject;
                using (new DisposableHttpContextWrapper(context))
                {
                    if (HttpRuntime.UseIntegratedPipeline)
                    {
                        try
                        {
                            context.HideRequestResponse = true;
                            this._hideRequestResponse = true;
                            this.InitIntegratedModules();
                            goto Label_006B;
                        }
                        finally
                        {
                            context.HideRequestResponse = false;
                            this._hideRequestResponse = false;
                        }
                    }
                    this.InitModules();
                Label_006B:
                    if (handlers != null)
                    {
                        this.HookupEventHandlersForApplicationAndModules(handlers);
                    }
                    this._context = context;
                    if (HttpRuntime.UseIntegratedPipeline && (this._context != null))
                    {
                        this._context.HideRequestResponse = true;
                    }
                    this._hideRequestResponse = true;
                    try
                    {
                        this.Init();
                    }
                    catch (Exception exception)
                    {
                        this.RecordError(exception);
                    }
                }
                if (HttpRuntime.UseIntegratedPipeline && (this._context != null))
                {
                    this._context.HideRequestResponse = false;
                }
                this._hideRequestResponse = false;
                this._context = null;
                this._resumeStepsWaitCallback = new WaitCallback(this.ResumeStepsWaitCallback);
                if (HttpRuntime.UseIntegratedPipeline)
                {
                    this._stepManager = new PipelineStepManager(this);
                }
                else
                {
                    this._stepManager = new ApplicationStepManager(this);
                }
                this._stepManager.BuildSteps(this._resumeStepsWaitCallback);
            }
            finally
            {
                this._initInternalCompleted = true;
                context.ConfigurationPath = null;
                this._initContext.ApplicationInstance = null;
                this._initContext = null;
            }
        }
        catch
        {
            throw;
        }
    }
    

      

    这个方法关键的代码在于:

     if (HttpRuntime.UseIntegratedPipeline)
                {
                    this._stepManager = new PipelineStepManager(this);
                }
                else
                {
                    this._stepManager = new ApplicationStepManager(this);
                }
                this._stepManager.BuildSteps(this._resumeStepsWaitCallback);

    我想大家看到这里就会明白为什么IIS7会有集成模式和经典模式了吧。可能大家不怎么重视此代码,让我们来看看经典模式的ApplicationStepManager 

    internal class ApplicationStepManager : HttpApplication.StepManager
    {
        // Fields
        private int _currentStepIndex;
        private int _endRequestStepIndex;
        private HttpApplication.IExecutionStep[] _execSteps;
        private int _numStepCalls;
        private int _numSyncStepCalls;
        private WaitCallback _resumeStepsWaitCallback;
    
        // Methods
        internal ApplicationStepManager(HttpApplication app) : base(app)
        {
        }
    
        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.ValidateRequestExecutionStep(app));
            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;
        }
    
        internal override void InitRequest()
        {
            this._currentStepIndex = -1;
            this._numStepCalls = 0;
            this._numSyncStepCalls = 0;
            base._requestCompleted = false;
        }
    
        [DebuggerStepperBoundary]
        internal override void ResumeSteps(Exception error)
        {
            bool flag = false;
            bool completedSynchronously = true;
            HttpApplication application = base._application;
            HttpContext context = application.Context;
            HttpApplication.ThreadContext context2 = null;
            AspNetSynchronizationContext syncContext = context.SyncContext;
            lock (base._application)
            {
                try
                {
                    context2 = application.OnThreadEnter();
                }
                catch (Exception exception)
                {
                    if (error == null)
                    {
                        error = exception;
                    }
                }
                try
                {
                    try
                    {
                    Label_0045:
                        if (syncContext.Error != null)
                        {
                            error = syncContext.Error;
                            syncContext.ClearError();
                        }
                        if (error != null)
                        {
                            application.RecordError(error);
                            error = null;
                        }
                        if (syncContext.PendingOperationsCount > 0)
                        {
                            syncContext.SetLastCompletionWorkItem(this._resumeStepsWaitCallback);
                        }
                        else
                        {
                            if ((this._currentStepIndex < this._endRequestStepIndex) && ((context.Error != null) || base._requestCompleted))
                            {
                                context.Response.FilterOutput();
                                this._currentStepIndex = this._endRequestStepIndex;
                            }
                            else
                            {
                                this._currentStepIndex++;
                            }
                            if (this._currentStepIndex >= this._execSteps.Length)
                            {
                                flag = true;
                            }
                            else
                            {
                                this._numStepCalls++;
                                context.SyncContext.Enable();
                                error = application.ExecuteStep(this._execSteps[this._currentStepIndex], ref completedSynchronously);
                                if (completedSynchronously)
                                {
                                    this._numSyncStepCalls++;
                                    goto Label_0045;
                                }
                            }
                        }
                    }
                    finally
                    {
                        if (context2 != null)
                        {
                            try
                            {
                                context2.Leave();
                            }
                            catch
                            {
                            }
                        }
                    }
                }
                catch
                {
                    throw;
                }
            }
            if (flag)
            {
                context.Unroot();
                application.AsyncResult.Complete(this._numStepCalls == this._numSyncStepCalls, null, null);
                application.ReleaseAppInstance();
            }
        }
    }
    

      说简单一点这个类中的internal override void BuildSteps(WaitCallback stepCallback)方法就是为我们注册那19个管道事件, internal override void ResumeSteps(Exception error)就是依次执行此管道事件,而  steps.Add(new HttpApplication.MapHandlerExecutionStep(app));是映射我们的handler

    internal class MapHandlerExecutionStep : HttpApplication.IExecutionStep
    {
        // Fields
        private HttpApplication _application;
    
        // Methods
        internal MapHandlerExecutionStep(HttpApplication app)
        {
            this._application = app;
        }
    
        void HttpApplication.IExecutionStep.Execute()
        {
            HttpContext context = this._application.Context;
            HttpRequest request = context.Request;
            if (EtwTrace.IsTraceEnabled(5, 1))
            {
                EtwTrace.Trace(EtwTraceType.ETW_TYPE_MAPHANDLER_ENTER, context.WorkerRequest);
            }
            context.Handler = this._application.MapHttpHandler(context, request.RequestType, request.FilePathObject, request.PhysicalPathInternal, false);
            if (EtwTrace.IsTraceEnabled(5, 1))
            {
                EtwTrace.Trace(EtwTraceType.ETW_TYPE_MAPHANDLER_LEAVE, context.WorkerRequest);
            }
        }
    
        // Properties
        bool HttpApplication.IExecutionStep.CompletedSynchronously
        {
            get
            {
                return true;
            }
        }
    
        bool HttpApplication.IExecutionStep.IsCancellable
        {
            get
            {
                return false;
            }
        }
    }
    

      里面的调用主要是

    context.Handler = this._application.MapHttpHandler(context, request.RequestType, request.FilePathObject, request.PhysicalPathInternal, false);

    而HttpApplication的MapHttpHandler如下:

    internal IHttpHandler MapHttpHandler(HttpContext context, string requestType, VirtualPath path, string pathTranslated, bool useAppConfig)
    {
        IHttpHandler handler = (context.ServerExecuteDepth == 0) ? context.RemapHandlerInstance : null;
        using (new ApplicationImpersonationContext())
        {
            if (handler != null)
            {
                return handler;
            }
            HttpHandlerAction mapping = this.GetHandlerMapping(context, requestType, path, useAppConfig);
            if (mapping == null)
            {
                PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_NOT_FOUND);
                PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_FAILED);
                throw new HttpException(SR.GetString("Http_handler_not_found_for_request_type", new object[] { requestType }));
            }
            IHttpHandlerFactory factory = this.GetFactory(mapping);
            try
            {
                IHttpHandlerFactory2 factory2 = factory as IHttpHandlerFactory2;
                if (factory2 != null)
                {
                    handler = factory2.GetHandler(context, requestType, path, pathTranslated);
                }
                else
                {
                    handler = factory.GetHandler(context, requestType, path.VirtualPathString, pathTranslated);
                }
            }
            catch (FileNotFoundException exception)
            {
                if (HttpRuntime.HasPathDiscoveryPermission(pathTranslated))
                {
                    throw new HttpException(0x194, null, exception);
                }
                throw new HttpException(0x194, null);
            }
            catch (DirectoryNotFoundException exception2)
            {
                if (HttpRuntime.HasPathDiscoveryPermission(pathTranslated))
                {
                    throw new HttpException(0x194, null, exception2);
                }
                throw new HttpException(0x194, null);
            }
            catch (PathTooLongException exception3)
            {
                if (HttpRuntime.HasPathDiscoveryPermission(pathTranslated))
                {
                    throw new HttpException(0x19e, null, exception3);
                }
                throw new HttpException(0x19e, null);
            }
            if (this._handlerRecycleList == null)
            {
                this._handlerRecycleList = new ArrayList();
            }
            this._handlerRecycleList.Add(new HandlerWithFactory(handler, factory));
        }
        return handler;
    }
    

      在MapHttpHandler里创建了IHttpHandlerFactory,进而创建了httphandler。

    在ApplicationStepManager中BuildSteps的方法有steps.Add(new HttpApplication.CallHandlerExecutionStep(app));这么一句,这就是注册调用我们hanndler的地方。

    internal class CallHandlerExecutionStep : HttpApplication.IExecutionStep
    {
        // Fields
        private HttpApplication _application;
        private AsyncCallback _completionCallback;
        private IHttpAsyncHandler _handler;
        private bool _sync;
    
        // Methods
        internal CallHandlerExecutionStep(HttpApplication app)
        {
            this._application = app;
            this._completionCallback = new AsyncCallback(this.OnAsyncHandlerCompletion);
        }
    
        private void OnAsyncHandlerCompletion(IAsyncResult ar)
        {
            if (!ar.CompletedSynchronously)
            {
                HttpContext context = this._application.Context;
                Exception error = null;
                try
                {
                    try
                    {
                        this._handler.EndProcessRequest(ar);
                    }
                    finally
                    {
                        context.Response.GenerateResponseHeadersForHandler();
                    }
                }
                catch (Exception exception2)
                {
                    if ((exception2 is ThreadAbortException) || ((exception2.InnerException != null) && (exception2.InnerException is ThreadAbortException)))
                    {
                        this._application.CompleteRequest();
                    }
                    else
                    {
                        error = exception2;
                    }
                }
                if (EtwTrace.IsTraceEnabled(4, 4))
                {
                    EtwTrace.Trace(EtwTraceType.ETW_TYPE_HTTPHANDLER_LEAVE, context.WorkerRequest);
                }
                this._handler = null;
                context.SetStartTime();
                if (HttpRuntime.IsLegacyCas)
                {
                    this.ResumeStepsWithAssert(error);
                }
                else
                {
                    this.ResumeSteps(error);
                }
            }
        }
    
        private void ResumeSteps(Exception error)
        {
            this._application.ResumeStepsFromThreadPoolThread(error);
        }
    
        [PermissionSet(SecurityAction.Assert, Unrestricted=true)]
        private void ResumeStepsWithAssert(Exception error)
        {
            this.ResumeSteps(error);
        }
    
        void HttpApplication.IExecutionStep.Execute()
        {
            HttpContext context = this._application.Context;
            IHttpHandler handler = context.Handler;
            if (EtwTrace.IsTraceEnabled(4, 4))
            {
                EtwTrace.Trace(EtwTraceType.ETW_TYPE_HTTPHANDLER_ENTER, context.WorkerRequest);
            }
            if ((handler != null) && HttpRuntime.UseIntegratedPipeline)
            {
                IIS7WorkerRequest workerRequest = context.WorkerRequest as IIS7WorkerRequest;
                if ((workerRequest != null) && workerRequest.IsHandlerExecutionDenied())
                {
                    this._sync = true;
                    HttpException exception = new HttpException(0x193, SR.GetString("Handler_access_denied"));
                    exception.SetFormatter(new PageForbiddenErrorFormatter(context.Request.Path, SR.GetString("Handler_access_denied")));
                    throw exception;
                }
            }
            if (handler == null)
            {
                this._sync = true;
            }
            else if (handler is IHttpAsyncHandler)
            {
                IHttpAsyncHandler handler2 = (IHttpAsyncHandler) handler;
                this._sync = false;
                this._handler = handler2;
                IAsyncResult result = handler2.BeginProcessRequest(context, this._completionCallback, null);
                if (result.CompletedSynchronously)
                {
                    this._sync = true;
                    this._handler = null;
                    try
                    {
                        handler2.EndProcessRequest(result);
                    }
                    finally
                    {
                        context.Response.GenerateResponseHeadersForHandler();
                    }
                    if (EtwTrace.IsTraceEnabled(4, 4))
                    {
                        EtwTrace.Trace(EtwTraceType.ETW_TYPE_HTTPHANDLER_LEAVE, context.WorkerRequest);
                    }
                }
            }
            else
            {
                this._sync = true;
                context.SyncContext.SetSyncCaller();
                try
                {
                    handler.ProcessRequest(context);
                }
                finally
                {
                    context.SyncContext.ResetSyncCaller();
                    if (EtwTrace.IsTraceEnabled(4, 4))
                    {
                        EtwTrace.Trace(EtwTraceType.ETW_TYPE_HTTPHANDLER_LEAVE, context.WorkerRequest);
                    }
                    context.Response.GenerateResponseHeadersForHandler();
                }
            }
        }
    
        // Properties
        bool HttpApplication.IExecutionStep.CompletedSynchronously
        {
            get
            {
                return this._sync;
            }
        }
    
        bool HttpApplication.IExecutionStep.IsCancellable
        {
            get
            {
                return !(this._application.Context.Handler is IHttpAsyncHandler);
            }
        }
    }
    

      在代码中我们看到handler2.BeginProcessRequest(context, this._completionCallback, null);。。。handler.ProcessRequest(context);这2句代码是不是很熟悉啊。

    在让我们回头看看HttpApplication的BeginProcessRequest方法

    IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
    {
        this._context = context;
        this._context.ApplicationInstance = this;
        this._stepManager.InitRequest();
        this._context.Root();
        HttpAsyncResult result = new HttpAsyncResult(cb, extraData);
        this.AsyncResult = result;
        if (this._context.TraceIsEnabled)
        {
            HttpRuntime.Profile.StartRequest(this._context);
        }
        this.ResumeSteps(null);
        return result;
    }
    

      里面调用了ResumeSteps方法

    private void ResumeSteps(Exception error)
    {
    this._stepManager.ResumeSteps(error);
    }

    回到我们先前的ApplicationStepManager的ResumeSteps方法,里面有一句

    error = application.ExecuteStep(this._execSteps[this._currentStepIndex], ref completedSynchronously);

    Ahhpaplication的ExecuteStep方法

    internal Exception ExecuteStep(IExecutionStep step, ref bool completedSynchronously)
    {
        Exception exception = null;
        try
        {
            try
            {
                if (step.IsCancellable)
                {
                    this._context.BeginCancellablePeriod();
                    try
                    {
                        step.Execute();
                    }
                    finally
                    {
                        this._context.EndCancellablePeriod();
                    }
                    this._context.WaitForExceptionIfCancelled();
                }
                else
                {
                    step.Execute();
                }
                if (!step.CompletedSynchronously)
                {
                    completedSynchronously = false;
                    return null;
                }
            }
            catch (Exception exception2)
            {
                exception = exception2;
                if (ImpersonationContext.CurrentThreadTokenExists)
                {
                    exception2.Data["ASPIMPERSONATING"] = string.Empty;
                }
                if ((exception2 is ThreadAbortException) && ((Thread.CurrentThread.ThreadState & ThreadState.AbortRequested) == ThreadState.Running))
                {
                    exception = null;
                    this._stepManager.CompleteRequest();
                }
            }
            catch
            {
            }
        }
        catch (ThreadAbortException exception3)
        {
            if ((exception3.ExceptionState != null) && (exception3.ExceptionState is CancelModuleException))
            {
                CancelModuleException exceptionState = (CancelModuleException) exception3.ExceptionState;
                if (exceptionState.Timeout)
                {
                    exception = new HttpException(SR.GetString("Request_timed_out"), null, 0xbb9);
                    PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_TIMED_OUT);
                }
                else
                {
                    exception = null;
                    this._stepManager.CompleteRequest();
                }
                Thread.ResetAbort();
            }
        }
        completedSynchronously = true;
        return exception;
    }
    

      是真正执行IExecutionStep的Execute方法。

    通过以上的分析我们可以简单的理解asp.net在管道模式下管道主要是通过ApplicationStepManager来注册和调用的。集成模式下的PipelineStepManager和ApplicationStepManager结构类似。

    个人在这里只是抛砖引玉,希望大家拍砖。

     

  • 相关阅读:
    LinkedList源码分析
    Hashtable源码分析
    String源码分析
    记一次ArrayList产生的线上OOM问题
    【spring源码分析】IOC容器初始化——查漏补缺(五)
    前端面试的那些事儿(1)~JavaScript 原始数据类型
    前端面试的那些事儿(2)~ 不再害怕被问 JavaScript 对象
    第二周技术周报-前端的自我修养
    第一周技术周报-前端框架演变
    JavaScript数据类型检测 数组(Array)检测方式
  • 原文地址:https://www.cnblogs.com/majiang/p/2757387.html
Copyright © 2011-2022 走看看