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结构类似。

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

 

 

 

posted on 2012-11-06 17:34  dz45693  阅读(4035)  评论(3编辑  收藏  举报

导航