ASP.NET从源码看实现(一):请求处理过程
ASP.NET是一个非常强大的构建Web应用的平台,它提供了极大的灵活性和能力以致于可以用它来构建所有类型的Web应用.当一个用户请求到达IIS服务后具体的处理流程是怎样的呢?
IIS处理流程图解
在IIS服务器中运行着进程InteInfo.exe,元数据库(MetaBase)存在于InteInfo.exe进程中,在IIS6.0中有个HTTP.SYS的HTTP监听器,主要是负责HTTP请求的监听,当监听到HTTP请求时,会先根据扩展名判断请求是否是静态资源,如果是静态资源,直接以文件内容返回!
当检测到为动态资源师,根据扩展名从IIS脚本映射找到相应的ISAPI动态连接口,ASP.NET ISAPI对应的DLL为aspnet_usapi.dll.
IIS处理流程类:ISAPIRuntime
IIS 所收到的对某 Microsoft ASP.NET 页面的每个请求都被移交给 ASP.NET HTTP 管线。HTTP 管线由一系列托管对象组成,这些对象按顺序处理该请求,并完成从 URL 到普通 HTML 文本的转换。HTTP 管线的入口点是 HttpRuntime 类。ASP.NET 基础结构为辅助进程中所承载的每个 AppDomain 创建此类的一个实例请注意,该辅助进程为当前正在运行的每个 ASP.NET 应用程序维护一个不同的 AppDomain。
当一个请求到达服务器时,首先被WWW服务器截获(inetinfo.exe进程), 该进程首先判断页面后缀, 然后根据IIS中配置决定调用具体的扩展程序。aspx就会调用aspnet_isapi.dll, 然后由aspnet_isapi.dll发送给w3wp.exe(iis 工作者进程,IIS6.0中叫做 w3wq.exe,IIS5.0中叫做 aspnet_wp.exe)。
w3wp.exe调用.NET类库进行具体处理,顺序如下:
ISAPIRuntime->HttpRuntime-> HttpApplicationFactory->HttpApplication->HttpModule->HttpHandlerFactory->HttpHandler
ISAPIRuntime:主要作用是调用一些非托管代码生成HttpWorkerRequest对象,HttpWorkerRequest对象包含当前请求的所有信息,然后传递给HttpRuntime
HttpRuntime:
根据HttpWorkerRequest对象生成HttpContext,HttpContext包含request、response等属性,
再调用HttpApplicationFactory来生成IHttpHandler, 调用HttpApplication对象执行请求
HttpApplicationFactory: 生成一个HttpApplication对象
HttpApplication:进行HttpModule的初始化,HttpApplication创建针对此Http请求的 HttpContext对象
HttpModule:
当一个HTTP请求到达HttpModule时,整个ASP.NET
Framework系统还并没有对这个HTTP请求做任何处理,也就是说此时对于HTTP请求来讲,HttpModule是一个HTTP请求的“必经之
路”,所以可以在这个HTTP请求传递到真正的请求处理中心(HttpHandler)之前附加一些需要的信息在这个HTTP请求信息之上,或者针对截获
的这个HTTP请求信息作一些额外的工作,或者在某些情况下干脆终止满足一些条件的HTTP请求,从而可以起到一个Filter过滤器的作用。
HttpHandlerFactory:把用户request 转发到HttpHandlerFactory,再由HttpHandlerFactory实例化HttpHandler对象来相应request
HttpHandle:Http处理程序,处理页面请求
//public sealed class ISAPIRuntime : MarshalByRefObject, IISAPIRuntime, IISAPIRuntime2, IRegisteredObject [SecurityPermission(SecurityAction.LinkDemand, Unrestricted=true)] public int ProcessRequest(IntPtr ecb, int iWRType) { IntPtr zero = IntPtr.Zero; if (iWRType == 2) { zero = ecb; ecb = System.Web.UnsafeNativeMethods.GetEcb(zero); } ISAPIWorkerRequest wr = null; try { bool useOOP = iWRType == 1; wr = ISAPIWorkerRequest.CreateWorkerRequest(ecb, useOOP); wr.Initialize(); string appPathTranslated = wr.GetAppPathTranslated(); string appDomainAppPathInternal = HttpRuntime.AppDomainAppPathInternal; if ((appDomainAppPathInternal == null) || StringUtil.EqualsIgnoreCase(appPathTranslated, appDomainAppPathInternal)) { HttpRuntime.ProcessRequestNoDemand(wr); return 0; } HttpRuntime.ShutdownAppDomain(ApplicationShutdownReason.PhysicalApplicationPathChanged, System.Web.SR.GetString("Hosting_Phys_Path_Changed", new object[] { appDomainAppPathInternal, appPathTranslated })); return 1; } catch (Exception exception) { try { WebBaseEvent.RaiseRuntimeError(exception, this); } catch { } if ((wr == null) || !(wr.Ecb == IntPtr.Zero)) { throw; } if (zero != IntPtr.Zero) { System.Web.UnsafeNativeMethods.SetDoneWithSessionCalled(zero); } if (exception is ThreadAbortException) { Thread.ResetAbort(); } return 0; } }
在 ISAPIRuntime 类中的ProcessRequest 方法调用中, ecb是一个指向httprequest的信息的指针,由IIS提供。CreateWorkerRequest根据ecb提供的信息,比如IIS的版本、 模式等,创建一个ISAPIWorkerRequest对象,ISAPIWorkerReuqeuest是一个http请求的.NET封装。创建好 WorkerRequest之后,调用 HttpRuntime.ProcessRequestNoDemand(iSAPIWorkerRequest);开始执行请求,这个方法是会从 httpRuntime对象中的一个队列中获取一个workerrequest进行处理,最终调用的是HttpRuntime类中的ProcessRequestInternal;
IIS处理流程类:HttpRuntime
//HttpRuntime类 private void ProcessRequestInternal(HttpWorkerRequest wr) { Interlocked.Increment(ref this._activeRequestCount); // 更新请求计数器 if (this._disposingHttpRuntime) { try { wr.SendStatus(0x1f7, "Server Too Busy"); wr.SendKnownResponseHeader(12, "text/html; charset=utf-8"); byte[] bytes = Encoding.ASCII.GetBytes("<html><body>Server Too Busy</body></html>"); wr.SendResponseFromMemory(bytes, bytes.Length); wr.FlushResponse(true); wr.EndOfRequest(); } finally { Interlocked.Decrement(ref this._activeRequestCount); } } else { HttpContext context; try { context = new HttpContext(wr, false);// 构造 HTTP 调用上下文对象 } catch { try { wr.SendStatus(400, "Bad Request"); wr.SendKnownResponseHeader(12, "text/html; charset=utf-8"); byte[] data = Encoding.ASCII.GetBytes("<html><body>Bad Request</body></html>"); wr.SendResponseFromMemory(data, data.Length); wr.FlushResponse(true); wr.EndOfRequest(); return; } finally { Interlocked.Decrement(ref this._activeRequestCount); } } wr.SetEndOfSendNotification(this._asyncEndOfSendCallback, context);// 设置发送结束异步回调函数 HostingEnvironment.IncrementBusyCount(); try { try { this.EnsureFirstRequestInit(context); } catch { if (!context.Request.IsDebuggingRequest) { throw; } } context.Response.InitResponseWriter(); IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(context); if (applicationInstance == null) { throw new HttpException(System.Web.SR.GetString("Unable_create_app_object")); } if (EtwTrace.IsTraceEnabled(5, 1)) { EtwTrace.Trace(EtwTraceType.ETW_TYPE_START_HANDLER, context.WorkerRequest, applicationInstance.GetType().FullName, "Start"); } if (applicationInstance is IHttpAsyncHandler)// 使用Web应用程序实例完成实际的页面请求工作 { IHttpAsyncHandler handler2 = (IHttpAsyncHandler) applicationInstance; context.AsyncAppHandler = handler2; handler2.BeginProcessRequest(context, this._handlerCompletionCallback, context);// 使用异步处理机制 } else { applicationInstance.ProcessRequest(context); this.FinishRequest(context.WorkerRequest, context, null); } } catch (Exception exception) { context.Response.InitResponseWriter(); this.FinishRequest(wr, context, exception); } } }
在HttpRuntime 执行ProcessRequestInternal方法时,首先创建HttpContext类,对用户的请求与数据进行封装,然后执行HttpApplicationFactory.GetApplicationInstance(context)获取到HttpApplication;
参考以下:
http://www.cnblogs.com/yinzixin/archive/2012/10/30/2745713.html
http://www.cnblogs.com/whtydn/archive/2009/10/16/1584418.html