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

ASP.NET是什么?

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

ASP.NET是一个复杂的使用托管代码来从头到尾处理Web请求的引擎.

整个ASP.NET引擎是完全建立在托管代码上的,所有的扩展功能也是通过托管代码的扩展来提供的.

 

ISAPI是什么?

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

ISAPI是一个底层的,非托管的,Win32风格的API. ISAPI的spec很简单, 是为了性能而优化过的. 他们非常底层- 为处理回调函数而去处理原始的指针和函数指针的列表, 但是他们提供了最底层的和面向性能效率的接口, 通过这些接口, 开发人员和工具提供商可以将他们的程序跟IIS挂接起来. 因为ISAPI非常底层所以它并不适合来开发应用级的代码,而且ISAPI主要被倾向于用于桥接接口, 即向上层工具提供应用服务器类型的功能.

例如,ASP和ASP.NET都是建立在ISAPI上的, Cold Fusion也一样.  多数运行在IIS上的Perl, PHP 和JSP的实现也是如此.

 

ISAPI是一个杰出的工具,可以为上层应用提供高效的管道一样的接口,这样上层应用可以抽象出ISAPI提供的信息.在ASP和ASP.NET中,将ISAPI接口提供的信息抽象成了类型Request和Response这样的对象,通过它们来读取ISAPI请求中对应的信息. 对ASP.NET来说,ISAPI dll的功能非常的”穷瘦”的, 只是作为一个将原始的请求转发到ASP.NET运行时的路由机制. 所有沉重的负担和处理, 甚至请求的线程的处理都是由ASP.NET引擎还有你自己的代码来处理的.

 

ISAPI跟ASP.NET之间是什么关系?

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

事实上,ASP.NET在微软的平台上就是通过ISAPI扩展来和IIS进行交互的,这个扩展寄宿着.NET运行时和ASP.NET运行时.ISAPI提供了核心的接口,ASP.NET使用非托管的ISAPI代码通过这个接口来从Web服务器获取请求,并发送响应回客户端.ISAPI提供的内容可以通过通用对象(例如HttpRequest和HttpResponse)来获取,这些对象通过一个定义良好并有很好访问性的接口来暴露非托管数据.

 

ISAPI Extension和ISAPI Filter是什么?

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

ISAPI extension和ISAPI filter就像是ISAPI支持的两种协议.

ISAPI Extension是一个处理请求的接口, 提供对Web服务器的输入输出的处理逻辑. 本质上来说是一个交互接口. ASP和ASP.NET就是作为Extension实现的.

ISAPI filter是提供一些功能的钩子接口, 功能包括允许查看每一个到达IIS的请求, 然后修改某些功能的内容或者功能的行为, Authentication就是这样的功能.

顺便说一句, ASP.NET通过两个概念来映射ISAPI式的功能:Http Handlers (extensions) 和Http Modules (filters)

 

WEB请求是如何从浏览器到ASP.NET的?

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

1. 用户从浏览器发出请求. 方式可以是: a. 输入URL; b. 点击超链接 c. 提交HTML表单 d.调用基于ASP.NET的web service

2. WEB服务器的IIS获得这个请求, 查看请求文件的扩展名.

3. IIS根据自己的Application Extension(即script map)中的配置, 将ASP.NET注册了的扩展名的请求发送给ASP.NET的ISAPI DLL-- aspnet_isapi.dll.

4. ASP.NET根据得到的请求的扩展名, 再一次对请求进行分配, 分配的目的地是请求对应的HTTP handler.

 

什么是HTTP handler?

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

每一个Http handler都是一个.net的类, 他们处理某一种文件的扩展名. 其内部的行为可以简单和可以非常复杂.

 

能不能总结一下IIS和ASP.NET凭请求中的什么信息来完成寻找正确处理的呢?

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

扩展名. IIS根据扩展名找到ASP.NET, ASP.NET根据扩展名找到Http handler.

 

既然IIS和ASP.NET都通过扩展名来进行对请求的路由, 那么我如何才能完成添加这些扩展名的配置呢?

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

你不应该设置手动这些扩展名.使用aspnet_regiis.exe这个工具来确保所有的映射都被正确的设置.

cd <.NetFrameworkDirectory>

aspnet_regiis – i

这个命令将为整个Web站点注册特定版本的ASP.NET运行时,包括脚本 (扩展名) 映射和客户端脚本库(包括进行控件验证的代码等).注意它注册的是<.NetFrameworkDirectory>中安装的特定版本的CLR(如1.1,2.0).aspnet_regiis的选项令您可以对不同的虚拟目录进行配置.每个版本的.NET框架都有自己不同版本的aspnet_regiis工具,你需要运行对应版本的aspnet_regiis来为web站点或者虚拟目录来配置指定版本的.NET framework. 从ASP.NET2.0开始提供了ASP.NET配置页面,可以通过这个页面在IIS管理控制台来交互的配置.NET版本.

 

IIS6的应用程序池是什么?

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

Application Pool是IIS6创建的单独的工作者进程, 包括ISAPI动态链接库的执行在内的所有的处理都在这个进程内发生.

 

应用程序池有啥好处呀?

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

应用程序池是IIS6的重大改进, 它在什么东西可以放在一个进程中运行的问题上有更细致的控制. 从虚拟目录到整个站点都可以进行应用程序池的设定, 这样, 你就可以将每一个web应用程序隔离到他们自己的进程中, 与其他同一机器上正在运行的web应用程序完全无关. 一个崩溃了, 其他的照样运行.

应用程序池提供高度的可设置性.

更容易被监测和管理.

优化了性能. 因为应用程序池直接跟内核态的HTTP.sys驱动程序交互, 所以对于http操作的性能更高.

应用程序池对ASP.NET有一些内部的了解和支持, ASP.NET可以使用应用程序池的底层API, 这些API可以将缓存的重担从ASP.NET层直接转移到web Server的缓存上.

ISAPI extension运行在应用程序池中, .NET runtime也运行在同样的进程中, 所以ISAPI和.NET运行时的通信就属于进程内通信, 当然比IIS5的命名管道通信更加高效了.

 

请求进入ASP.NET的第一个函数入口是什么?

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

ISAPIRuntime.ProcessRequest()

 

调用是如何走到ISAPIRuntime.ProcessRequest()中的呢? 进入之后有做了哪些事情呢?

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

w3wp.exe中寄宿着.NET运行时.

ISAPI.DLL会通过低级COM对象去调用一小部分非托管接口, 这些底层的COM最终将调用到ISAPIRuntime类的一个实例上.

ASP.NET的System.Web.Hosting命名空间下有个接口, 叫做IISAPIRuntime. 这是一个通过COM暴露给调用者的接口. 使用这个接口的COM专门用来完成从ISAPI Extension向ASP.NET组件调用的功能. 也就是说, IISAPIRuntime接口是非托管代码进入托管代码的接入点.

接口中ProcessRequest方法的签名如下:

[return: MarshalAs(UnmanagedType.I4)]

int ProcessRequest([In] IntPtr ecb,

                   [In, MarshalAs(UnmanagedType.I4)] int useProcessModel);

注意这里的ecb参数, 它是ISAPI Extension Control Block的缩写, 是作为一种非托管资源传递给ProcessRequest方法的. ProcessRequest方法使用ecb作为Request和Reponse对象使用的基本的输入输出对象. ecb中含有浏览器发送来的请求的所有底层信息, 包括服务器变量, 输入流和要被写回到client端的输出流. 单单一个ecb的引用基本上就提供了访问ISAPI请求的所有功能. ProcessRequest是ecb与托管代码打交道的入口, 也是出口. 即ProcessRequest方法一旦结束, ASP.NET的处理也就结束了.

 

ISAPI extension是异步的运行请求的. 也就是说, ISAPI extension(比如ASP.NET)会立即返回到调用它的的工作者进程(w3wp.exe)或者IIS线程中, 但是保持当前请求的ECB的存活状态. ECB中包含让ISAPI知晓请求的处理已经结束的机制(通过ecb.ServerSupportFunction) , 这个机制会在得到ECB的通知后释放掉ECB. 这个异步的过程能迅速的释放ISAPI工作者线程, 将处理任务转交给ASP.NET管理的独立线程.

 

ASP.NET收到ECB的引用之后, 就在内部使用它来获取关于当前请求的信息, 比如说服务器变量, POST数据, 还有发送给服务器的输出信息. ECB结构在请求处理结束之前都是存活的. 在timeout时, ecb会被销毁. 只要ecb还在, 处理还没结束, ASP.NET就会一直跟它打交道  输出结果被写入到ISAPI 输出流(ecb.WriteClient())中. 当请求结束了, ISAPI extension 被通知到, 然后它就知道ECB可以释放掉了. 这个过程非常高效, 因为.net的类基本上都是作为围绕着高性能的, 非托管的ISAPI ECB的包装者而行动的.

posted on 2009-11-19 22:00  中道学友  阅读(405)  评论(0编辑  收藏  举报

导航

技术追求准确,态度积极向上