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结构类似。
个人在这里只是抛砖引玉,希望大家拍砖。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构