阅读笔记- 了解ASP.NET底层架构 之二

ASP.NET中的.NET runtime是如何加载起来的呢?

==============

这一点上, 微软没有公开的文档说明. 大致情况应该是这样的, 让我们从头开始:

1. 用户请求到来之前, IIS为每一个站点启动了相应的工作者进程(w3wp.exe)

2. 请求经过IIS基于网址将请求交给相应的站点, 找到站点对应的工作者进程.

3. 工作者进程基于请求的扩展名对请求进行分配, 发现是asp.net注册的扩展名, 在检查IIS的配置发现该扩展名应该使用ASP.NET作为ISAPI Extension来处理, 于是调用aspnet_isapi.dll中的HttpExtensionProc方法, 从而将控制转入到ASP.NET中.

这一步是我研究和猜想的, 不是参考资料上内容, 过程如下: 

1. 首先我使用.net reflector解析aspnet_isapi.dll. Reflector报告错误: dll does not contain a CLI header.

2. 这个信息说明aspnet_isapi.dll并不是一个.NET的程序集(后来自己想了想IIS的处理过程, 这里用reflector去解析aspnet_isapi.dll实在不聪明)

3. 于是使用dependency walker分析这个dll, 得到了这个dll暴露的方法列表, 见下图. 看这里就HttpExtensionProc方法比较有意思, 于是双击, dependendy walker自动调出Visual Studio的帮助文件, 并导航到这个方法的说明上.

4. 看说明, 这个方法是有应用程序自己定义的, 并且是Web服务器调用ISAPI Extension的主入口. Web服务器通过这份方法将控制传入到extension中. ISAPI extension使用这个方法向web服务器暴露自己处理请求的功能. 注意, msdn上说这个方法的名字并不是HttpExtensionProc, 它只是个占位符, 真正的名字由一个header定义.

5. 注意这个方法的原型的参数,就是我们前面详细描述过的ECB.

     DWORD WINAPI HttpExtensionProc( EXTENSION_CONTROL_BLOCK* pECB );

 

2009-11-20 10-21-57

4. 在aspnet_isapi.dll中从HttpExtensionProc开始, 通过一些非托管的接口和底层的COM对象, 调用到一些工厂方法, 其中System.Web.Hosting.AppDomainFactory.Create(string appId, string appPath)方法被调用, 该方法创建出System.Web.Hosting.ISAPIRuntime对象.

注意这个方法的参数, 它们是站点虚拟目录的路径信息还有module的名字, 这些参数被用来创建AppDomain和加载指定虚拟目录需要的ASP.NET应用程序.

5. 如前面一篇文章所说, ISAPIRuntime是非托管代码进入托管代码的接入点. 由底层的COM组件调用它的ProcessRequest方法, 从而进入了托管代码的世界, 也真真正正的进入了ASP.NET的数据处理管道.

6. 进入托管代码世界的第一步就是加载CLR引擎(如果CLR引擎还没有加载的话), 这一步详细介绍可以参考CLR是如何工作的一文中引擎初始化的部分. 我在这里啰嗦一点, 把这个过程也写在这里, 以便获得完整印象.

    System.Web.Hosting.ISAPIRuntime类存在于System.Web.dll中, 显然这是一个托管Assembly. 托管Assembly与mscoree.dll绑定. mscoree.dll加载之后读取托管assembly的metadata或app.config, 选择合适版本的CLR来加载.

    CLR加载起来之后, 就可以进行托管代码的执行了. 从这一步再深入下去请参考文章[翻译经典文章]深入.NET Framework内部, 看看CLR如何创建运行时对象的.

 

ProcessRequest如何使用ECB的?

===================

这里列出ProcessRequest的

 
  
 
  
 
  
 
  
 
  
 
  
 
  

7: if (((text2 == null) || text1.Equals(".")) ||

(string.Compare(text1, text2, true, CultureInfo.InvariantCulture) == 0))

 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
 

ProcessRequest接受到了非托管的ECB的引用, 把它传递给ISAPIWorkerRequest, 让它负责创建请求的上下文Context.

HttpWorkerRequest类的目的是提供一个围绕着底层接口的高层次的抽象视图, 这样才能屏蔽掉喂给HttpRuntime的数据来源的不同.

这里列出ISAPIRequest方法是如何调用非托管方法的:

 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
 

 

HttpRuntime, HttpContext, 和HttpApplication都是干什么的? 有什么区别?

========================

当一个请求到达时, 请求被路由ISAPIRuntime.ProcessRequest()方法中, 这个方法接下来会调用HttpRuntime.ProcessRequest方法, 这个方法做了一些重要的事:

  • 为请求创建了一个新的HttpContext 实例
  • 获取了HttpApplication实例
  • 调用HttpApplication.Init() 方法来进行ASP.NET管道的事件设置
  • Init() 方法触发HttpApplication.ResumeProcessing() 方法, 该方法会开始ASP.NET的管道处理(即让请求经过一系列的事件函数)

HttpContext

这个对象在请求的整个生命期中都存在, 并且总是可以通过静态的HttpContext.Current属性而获得. 如同他的名字暗示的, HttpContext对象代表着当前请求的上下文, 因为它包含着你处理请求的生命期中要使用的所有重要对象的引用: Request, Response, Application, Server, Cache. 任何时候, 你都可以通过HttpContext.Current来获得这些对象.

HttpContext对象还包含着一个非常有用的Item Collection, 你使用它来存储请求相关的数据. Context对象在请求周期开始的时候就被创建出来, 在请求结束的时候才被释放掉. 所以Item Collection中存储的数据时针对当前请求的. 一个很好的使用范例是: 请求记录的机制, 可以帮助你记录下请求的起始时间的记录机制. 实现的方式是如下代码中所示的那样, 将Application_BeginRequest和Application_EndRequest方法勾连起来. HttpContext是你的朋友, 在请求的不同部分或者页面处理的不同部分使用它来帮助你获取数据吧.

 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
 

 

HttpApplication

一旦Context对象被建立起来, ASP.NET需要路由你的请求到合适的虚拟目录上, 达到这个目的的方式是使用HttpApplication对象. 每个ASP.NET应用程序都必须建立一个虚拟目录, 并且这些"application"中的任何一个都是被独立的处理的.

 

HttpApplication如同庆祝活动的主席一样, 控制着处理请求的动作的进行.

 

每一个请求都要被路由到HttpApplication对象上. HttpApplicationFactory对象根据当前应用程序的负荷创建出一池子的HttpApplication对象, 然后将这些对象的引用分发给每一个请求. 池子的大小被machine.config文件中ProcessModel Key里的一个叫做MaxWorkerThreads的设置约束, 默认情况下值为20.

 

池中的线程的数目从1开始,随着并发到来的请求数量的增多而慢慢增多, 因为这些请求需要HttpApplication对象来处理. 池子中的对象的数目是受到监控的, 所以它不会超过规定的上限, 晚些时候, 这个数目会随着负荷的降低而下降.

 

HttpApplication是你具体Web应用程序的外部容器, 它映射了在Global.asax中定义的类. 它是你在你的应用程序中定期看到的进入HttpRuntime的入口点. 如果你查看一下你的Global.asax, 你会发现这个类是直接从HttpApplication继承来的.

 
 

HttpApplication的主要目的就是在Http的处理管道中作为事件的控制器. 所以它的借口包括一些很主要的时间, 这些事件钩涉及的范围很广, 包括:

  • BeginRequest
  • AuthenticateRequest
  • AuthorizeRequest
  • ResolveRequestCache
  • AquireRequestState
  • PreRequestHandlerExecute
  • …Handler Execution…
  • PostRequestHandlerExecute
  • ReleaseRequestState
  • UpdateRequestCache
  • EndRequest

所有的这些事件都在Global.asax文件中也通过以Application_为前缀的空方法实现了, 比如说Application_BeginRequest(), Application_AuthorizeRequest().

这两个事件处理函数是处于方便的原因而提供的, 因为他们在应用程序中使用的频率很高, 这样做你就不用显示的再去创建这些事件处理函数的代理了.

 

理解下面的事实很重要:

每一个ASP.NET的虚拟应用程序都运行在他们自己的AppDomain中, 并且在AppDomain中, 多个HttpApplication实例并发的运行着, 这些HttpApplication是来自于ASP.NET管理的一个池. 正因为如此, 多个请求才能被同时处理, 并且不互相干扰.

 

为了弄清楚AppDomain, Threads 和HttpApplication之间的关系, 看看下面的代码吧:

 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
 

另一个重要的事实是: 针对一个站点来说, HttpApplication对象都运行在相同的AppDomain中. 真因为如此, ASP.NET才可以保证web.config中的更改或者某个ASP.NET页面的修改会被整个AppDomain所识别. 因为在web.config中的修改会导致AppDomain被关闭, 然后重启. 这种方式保证了HttpApplication的所有实例都会看到那些修改, 因为AppDomain在重启的时候也重新从ASP.NET中加载了修改过的配置. 任何静态的引用都被重新加载, 所以如果说应用程序中再读取App configuration的配置时, 读取的已经是刷新过的值了.

 

事实上, Web application相当于"重启"了. 任何已经在pipeline处理中的请求会通过已经存在的pipeline继续执行下去, 同时新进来的请求会被路由到新的AppDomain上. 为了处理hung在那里的request, 即使在请求还在等待, ASP.NET还是会在请求超时的时候强制关掉AppDomain. 所以说呢, 对于同一个HttpApplication来说, 在某个特定的时间点上, 存在两个AppDomain是完全可能的. 因为老的正在被关闭, 而新的正在被自举上来. 两个AppDomain会持续地位自己的客户服务, 知道老的运行到结束掉等待的请求, 并被关闭, 只留下新的在运行.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ASP.NET笔记博客源码是一个用于创建和管理个人或团队博客的开源项目。它基于ASP.NET框架,使用C#作为主要编程语言。该项目的目的是为用户提供一个简单易用的平台,方便他们记录和分享个人或团队的经验、知识和想法。 在ASP.NET笔记博客源码中,主要包含以下几个核心模块: 1. 用户认证和授权:该模块负责用户的注册、登录和权限管理。用户可以通过创建自己的账户来使用博客系统,并根据不同的权限设置来管理自己的博客内容,如发布、编辑和删除博文等。 2. 博文管理:该模块用于管理博客的文章。用户可以使用富文本编辑器来撰写文章,并可以对文章进行分类、标签和搜索。此外,用户还可以管理自己的评论和回复。 3. 主题和样式:该模块允许用户自定义博客的主题和样式。用户可以选择不同的主题模板,如布局、颜色等,以满足自己的需求和喜好。 4. 评论和交互:用户可以对其他人的文章进行评论和回复,并可以与其他用户进行互动和讨论。这增加了博客的交互性和社交性。 此外,ASP.NET笔记博客源码还可以进行扩展和定制,以满足特定需求。用户可以添加其他功能模块,如图片库、标签管理和站点统计等,以实现更加丰富和个性化的博客。 总结来说,ASP.NET笔记博客源码是一个基于ASP.NET框架的开源项目,用于创建和管理个人或团队的博客。它提供了用户认证、博文管理、主题样式和评论交互等核心功能,同时支持扩展和定制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值