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结构类似。
个人在这里只是抛砖引玉,希望大家拍砖。