【asp源码栏目提醒】:网学会员鉴于大家对asp源码十分关注,论文会员在此为大家搜集整理了“ASP NET运行时模型的源码解析 - 计算机教材”一文,供大家参考学习
ASP.NET运行时模型的
源码解析
软件设计开发 张家琴 约5914字 摘要
ASP.NET是微软公司推出的基于DotNet平台的网络开发技术对B/S模式应用的开发提供了强大的支持该文从源代码级别进入
ASP.NET底层分析
ASP.NET运行时模型揭开
ASP.NET应用程序运行的幕后细节。
关键词
ASP.NETDotNet平台
网络开发B/S模式应用运行时模型 中图分类号TP311文献标识码A文章编号1009-3044200833-1415-04 SourceCode Analyzing for
ASP.NET Runtime Model ZHANG Jia-qing Fujian Institude of Economics Management Fuzhou 350002 China Abstract: Based on DotNet platform Microsoft Proposed the network developing technology called
ASP.NET which provides strong support to the development of B/S pattern application programs. This paper enters into the bottom of
ASP.NET from the level of source code so as to analyze the runtime model of
ASP.NET so that running details behind the curtain of
ASP.NET application programs are uncovered. Key
words:
ASP.NET DotNet platform network developing B/S pattern application runtime model 1 引言
ASP.NET运行时模型指的是
ASP.NET 框架在接收到客户端请求到获取合适的HttpHandler接管请求之间以及从HttpHandlers生成处理结果到发送处理结果给客户端之间
ASP.NET 框架所完成的一系列工作和处理逻辑1。
本文将通过源代码级别的分析深入讨论
ASP.NET 2.0运行时模型解析
ASP.NET应用程序运行时模型的工作原理。
2 ISAPI接口标准与IIS服务器的可扩展性 IIS服务器是部署
ASP.NET应用的标准Web服务器由于IIS服务器在
设计时引入了开放的ISAPI接口标准具备极高的可扩展性在核心组件不变的情况下可灵活支持不同类型不同版本的应用例如IIS 5.1版能够同时支持
ASP.NET 1.0、1.1、2.0甚至可以支持部署基于DotNetFramework 3.5的
ASP.NET应用程序。
ISAPI的全称是Internet Server Application Programming Interface即Internet服务器应用编程接口它为开发人员提供了强大的可编程能力只要按照标准接口开发不同类型Web应用程序的ISAPI扩展程序就能实现对IIS功能上的扩展从而使IIS可以处理不同类型的客户端请求例如让IIS处理Perl或
PHP应用程序2。
IIS管理器提供了应用程序配置功能可以对不同的客户端请求配置不同的ISAPI扩展程序。
ISAPI扩展程序通常以DLL的形式存在可以被IIS加载并调用。
在
ASP.NET2.0下对应于.aspx的
ASP.NET应用程序其ISAPI扩展
程序默认情况下位于C:WINDOWSMicrosoft.NETFrameworkv2.0.50727目录下以aspnet_isapi.dll下文简称aspnet_isapi文件的形式存在3。
有了ISAPI扩展IIS服务器就可以根据客户端请求的资源扩展名来决定应由哪个ISAPI扩展来处理客户端请求然后就可以将请求转发给合适的ISAPI扩展。
例如当访问资源的扩展名为.aspx、.ascx、.ashx 和 .asmx时IIS服务器会自动将请求转发给缺省情况下位于C:WINDOWSMicrosoft.NETFrameworkv2.0.50727目录下aspnet_isapi.dll进行处理4这个动态库就是一个ISAPI扩展程序负责处理
ASP.
NET应用程序的请求。
3
ASP.NET的后台辅助进程aspnet_wp.exe 实际上客户发起的请求最终要由aspnet_isapi传递给它背后的aspnet_wp.exe去处理.Net平台将其称为
ASP.NET Worker Process下文简称WP该文件位于.NET framework安装目录下与aspnet_isapi.dll所在位置相同。
当aspnet_isapi接收到IIS转发的
ASP.NET请求后会将请求放入队列并根据实际情况分配请求处理任务给WP进程一旦请求被转送给WP进程WP进程便会通知aspnet_isapi请求正在被处理。
这个通知的过程是通过同步I/0完成的这么实现目的是为了保证处理过程的完整性因为只有当请求在aspnet_isapi内部被标记为“executing”后WP才会真正开始处理该请求。
此后请求便在WP的上下文环境中执行当执行结束后处理结果会通过一个异步的开放管道回送给aspnet_isapi这时请求的状态会被更新为“Done”接着请求就会从队列中清除。
如果WP进程崩溃所有正在处理中的请求都将维持“executing”状态一段时间等到aspnet_isapi检测到WP进程死掉后会自动丢弃所有的请求并释放已经分配的资源5。
其过程如图1所示。
WP会分析每一个请求的信息解析出其中的虚拟目录信息并检查该虚拟目录对应的AppDomain是否已经存在如果不存在则创建一个新的AppDomain然后使用它否则直接重用已经建立的AppDomain对象。
这里的AppDomain指的是.NET中引入的应用程序域的概念它可以理解为一个进程或一个边界或一个容器它是应用程序的执行环境.NET下所有的应用程序都运行在AppDomain中每一个
ASP.NET应用程序IIS中的站点或者虚拟目录都会有一个AppDomain与之对应6它保存了Ap
plcation对象、Cache等全局变量。
4 请求在
ASP.NET运行时中的处理步骤一ISAPIRuntime-HttpRuntime WP接收到aspnet_isapi转发的请求后就将请求转送给指定虚拟目录对应的AppDomain中的ISAPIRuntime对象由它完成对aspnet_isapi封装后的请求包的解析工作笔者使用Lutz Roeder39s .NET Reflector工具查看System.Web.Dll通过分析ISAPIRuntime的
源码发现客户的请求首先会被该类的ProcessRequest方法处理该方法的部分代码如下 ISAPIWorkerRequest wr null try bool useOOP iWRType 1 wr ISAPIWorkerRequest.CreateWorkerRequestecb useOOP wr.Initialize ???? if ???? HttpRuntime.ProcessRequestNoDemandwr return 0 ???? 可以看出在ProcessRequest方法中主要通过调用一些非托管代码生成HttpWorkerRequest对象在上述代码中对应于wr对象ISAPIWorkerRequest类型继承自HttpWorkerRequest类该对象包含当前请求的所有信息然后ISAPIRuntime调用HttpRuntime的ProcessRequestNoDemand方法传递创建好的HttpWorkerRequest对象这个方法的代码如下 internal static void ProcessRequestNoDemandHttpWorkerRequest wr RequestQueue queue _theRuntime._requestQueue if queue null wr queue.GetRequestToExecutewr if wr null CalculateWaitTimeAndUpdatePerfCounterwr wr.ResetStartTime ProcessRequestNowwr 该方法先从请求队列中取出一个请求然后更新请求的引用计数器等信息接着就让ProcessRequestNow方法处理请求这个方法的代码如下 internal static void ProcessRequestNowHttpWorkerRequest wr _theRuntime.ProcessRequestInternalwr 追踪分析
源码可以发现_theRuntime对象是在HttpRuntime内部定义的其类型就是HttpRuntime自身它在HttpRuntime的静态构造函数中被初始化。
5 请求在
ASP.NET运行时中的处理步骤二HttpRuntime.ProcessRequestInternal 接下来我们重点分析HttpRuntime类ProcessRequestInternal方法的运作细节使用Reflector工具追踪至ProcessRequestInternal方法的内部 HttpContext context context new HttpContextwr false ???? this.EnsureFirstRequestInitcontext context.Response.InitResponseWriter ???? IHttpHandler applicationInstance HttpApplicationFactory.GetApplicationInstancecontext ???? IHttpAsyncHandler handler2 IHttpAsyncHandlerapplicationInstance context.AsyncAppHandler handler2 handler2.BeginProcessRequestcontextthis._handlerCompletionCallback context ???? 通过分析该方法的
源码发现它主要完成如下处理 1 根据HttpWorkerRequest对象初始化HttpContext对象它包含了request、response等属性在编程中经常会用到这些重要的属性来完成特定的任务。
2 调用EnsureFirstRequestInit方法完成第一次请求的初始化
工作该方法锁定全局变量_beforeFirstRequest然后调用FirstRequestInitcontext完成应用程序配置文件的加载、初始化请求队列、装载Bin目录下的所有程序集等工作然后更新_beforeFirstRequest为false。
3 执行InitResponseWriter创建HttpWriter对象用于写入处理结果返回信息。
4 调用HttpApplicationFactory类的GetApplicationInstance方法来生成IHttpHandler这里生成的是一个默认的HttpApplication对象HttpApplication实现了IHttpHandler接口。
5 调用HttpApplication对象它同时实现了IHttpAsyncHandler接口的BeginProcessRequest方法执行客户请求。
需要注意的是笔者在跟踪至HttpApplicationFactory类的GetApplicationInstance方法内部时发现它最终通过调用该类的GetNormalApplicationInstance方法获取HttpApplication实例 return _theApplicationFactory.GetNormalApplicationInstancecontext 再深入一步进入GetNormalApplicationInstance方法内部我们终于看到HttpApplication对象是如何被创建和初始化的 HttpApplication application null ???? application HttpApplicationHttpRuntime.CreateNonPublicInstancethis._theApplicationType using new ApplicationImpersonationContext application.InitInternalcontext this._state this._eventHandlerMethods 我们发现HttpApplication类提供了一个名为InitInternal的方法调用方通过它来完成HttpApplication实例的初始化工作在这个方法的内部有如下代码 ???? this.InitModules ???? this.HookupEventHandlersForApplicationAndModuleshandlers ???? this._stepManager new ApplicationStepManagerthis this._stepManager.BuildStepsthis._resumeStepsWaitCallback ???? 可以看到在HttpApplication对象初始化时首先会自动调用自身的InitModules方法来加载在
web.config文件中配置的所有HttpModule模块。
接着HookupEventHandlersForApplicationAndModules方法被调用这个方法完成global.asax文件中配置的HttpApplication或HttpModule事件的绑定。
最后ApplicationStepManager对象的BuildSteps方法被调用完成HttpApplication事件的绑定这个方法很重要它将创建各种HttpApplication.IExecutionStep对象并保存到一个数组列表中以便在BeginProcessRequest方法内部调用ResumeSteps方法依次执行这些对象的Execute方法完成各种处理。
图2是以上分析的一个总结。
图片 图1 请求传递和处理过程图 图片 图2请求在
ASP.NET运行时内部处理过程图 在取得HttpApplication对象实例之后HttpRuntime对象开始调用它的BeginProcessRequest方法实现IHttpAsyncHandler接口中定义的方法处理请求: IAsyncResult IHttpAsyncHandler.BeginProcessRequestHttpContext context AsyncCallback cb object extraData ???? this._stepManager.InitRequest this._context.Root HttpAsyncResult result new HttpAsyncResultcb extraData this.AsyncResult result ???? this.ResumeStepsnull return result 该方法首先调用ApplicationStepManager对象的InitRequest方法完成一些初始化工作例如将记录当前执行步骤的变量清0、置请求处理完成标志为false等。
然后根据上下文创建HttpAsyncResult对象记录执行结果最后ResumeSteps方法被调用这个方法会依次取出在数组
列表中的HttpApplication.IExecutionStep对象传递给HttpApplication的ExecuteStep方法由它调用执行IExecutionStep对象的Execute方法。
当执行到MapHandlerExecutionStep时会执行如下代码获取最终执行请求的HttpHandler context.Handler this._application.MapHttpHandlercontext request.RequestType request.FilePathObject request.PhysicalPathInternal false HttpApplication对象的MapHttpHandler方法将根据配置文件结合请求类型和URL以调用相应的IHttpHandlerFactory来获取HttpHandler对象例如与.aspx页面对应的Page类就是一种HttpHandler。
此后请求处理的执行权被转交至对应的HttpHandler对象上。
至此本文通过
源代码分析技术详细解析了
ASP.NET应用程序在底层的运作细节限于篇幅无法继续深入讨论
ASP.NET页面的编译及执行过程。
6 结语
ASP.NET运行时是整个
ASP.NET技术框架中最为复杂、最难以理解但却十分重要的部分对
ASP.NET 2.0运行时源代码的研究有助于我们加深对
ASP.NET 技术的理解将为我们开发
ASP.NET 2.0应用程序带来很多帮助。
参考文献 1 谭振林.道不远人—深入解析
ASP.NET 2.0 控件开发M.北京:电子工业出版社2007:15-18. 2 Dr Khosravi S.Professional IIS 7 and
ASP.NET Integrated ProgrammingM.北京:JOHN WILEY SONS INC2005:8-9. 3 奚江华.圣殿祭司的
ASP.NET 2.0开发详解——使用CM.2版.北京:电子工业出版社2008:49-51. 4 Mitchell SWalther S.
ASP.NET权威指南M.汤涛译.北京:中国电力出版社2003:551-553. 5 Esposito D.The
ASP.NET HTTP RuntimeEB/OL.2003-07-10.http://msdn.microsoft.com/en-us/library/aa479328.aspx. 6 Evjen BHanselman SMuhammad F.
ASP.NET 2.0 高级编程M.李敏波译.4版.北京:清华大学出版社2006:371-373.