ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline[上篇]

  ASP.NET Process Model索引

ASP.NET Process Model之一:IIS 和 ASP.NET ISAPI ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline[上篇] ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline[下篇]

  相信大家都使用过ASP.NET进行过基于Web的应用开发,ASP.NET是什么?如果站在一个相对High Level的角度,我们可以这样来定义ASP.NET:ASP.NET是一个基于Web的开发平台,提供构建企业级应用所需的Service、Programming Model和Software的Infrastructure。如果我们以一个Low Level的角度来看,它本质上就是一个消息处理器:他接受IIS(确切地说应该是ASP.NET ISAPI)Forward的Http Request (我们可以看成是一个Request Message),经过一系列的处理,最终产生一个用户希望的Response(这也是一个Message,对于.aspx Page来说是一个Html document,对于一个Web Service来说是一个Soap)。所以本篇文章的主要目的在于站在一个相对Low Level的角度介绍ASP.NET的整个Http Request Processing Model。我们访问一个基于ASP.NET的资源,IIS是第一道屏障,在第一个部分我分别就IIS 5.x和IIS 6的差异介绍了IIS对Http Request的处理,今天我们来继续后面的故事。

  一、从Unmanaged Environment到Managed Environment

  上一部分我们说到IIS收到一个基于ASP.NET资源文件的访问,它会把Http Request交给一个ASP.NET ISAPI Extension处理。ASP.NET ISAPI 会加载CLR,从而创建一个托管的环境。ASP.NET ISAPI Extension定义在一个名为aspnet_isapi.dll中,aspnet_isapi.dll是一个纯Native的、高效的Dll,也就是说,虽然ASP.NET ISAPI通过加载CLR创建一个托管的环境,但是ASP.NET ISAPI本省却运行在一个Unmanaged的环境中。而我们的ASP.NET Application确是完全的Managed code,运行在一个Managed的环境中。要了解ASP.NET Http Runtime Pipeline这个纯托管的Runtime,我们必须先了解从Unmanaged Environment到Managed Environment的这道桥梁。

  上图简单表述了在IIS 6环境下,从非托管环境到托管环境的过程。从图中我们可以看到,ASP.NET ISAPI运行在一个非托管环境之中。ASP.NET ISAPI经过系列COM级别的class调用(由于这些被调用的Class都是一个个undocumented class,所以要真正说清楚调用流程中每个具体的细节是一件很难的事情,而且也确实没有很大的必要去挖掘它,因为具体的实现可能会经常变动,如果对此具有好奇心的朋友可以通过一些Tool,比如Reflector去仔细研究一下),最终的调用降临到一个托管的、继承自System.Web.Hosting.ISAPIRuntime类的对象上。ISAPIRuntime 是一个特殊的class,他实现了Interface System.Web.Hosting.IISAPIRuntime。下面是该Interface的定义。通过定义我们可以看到,这是一个基于COM的Interface,也就是说Caller可以通过COM的方式调用实现该Interface的Class的对象。在这里,这个最初的Caller就是ASP.NET ISAPI。从这里我们可以总结出:ASP.NET ISAPI通过调用System.Web.Hosting.ISAPIRuntime Instance的ProcessRequest方法,进而从非托管的环境进入了托管的环境。

[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("08a2c56f-7c16-41c1-a8be-432917a1a2d1")]

public interface IISAPIRuntime

{

void StartProcessing();

void StopProcessing();

[return: MarshalAs(UnmanagedType.I4)]

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

void DoGCCollect();

}

  ISAPI ECB (Execution Control Block) & ISAPIWorkerRequest

  通过System.Web.Hosting.IISAPIRuntime Interface中的ProcessRequest方法的Siganature,我们可以看出该方法包含两个参数,其中一个是名为ecb的Unmanaged Pointer,另一个是useProcessModel。ECB全称是Execution Control Block,在整个Http Request Processing过程中起着非常重要的作用,我们现在来简单介绍一个ECB。

  ISAPI顾名思义,就是实现了一些基于Internet Server的API。Aspnet_isapi.dll实现了这些API,对于IIS来说,它可以调用这些API进入托管的环境实现对ISAPIRuntime的调用,对于ISAPIRuntime来说,它需要调用ASP.NET ISAPI实现一些必要的功能,比如获得Server Variable的数据,获得通过Post Mehod传回Server的数据;以及最终将Response的内容返回给ASP.NET ISAPI,并通过ASP.NET ISAPI返回到Client。一般地ISAPIRuntime不能直接调用ASP.NET ISAPI,而是通过一个对象指针实现对其的调用,这个对象就是ECB,ECB实现了对ISAPI的访问。

  还有一点特别需要强调的是,ISAPI对ISAPIRutime的调用是异步的,也就是说ISAPI调用ISAPIRutime之后立即返回。这主要是出于Performance和Responsibility考虑的,因为ASP.NET Application天生就是一个多线程的应用,为了具有更好的响应能力,异步操作是最有效的解决方式。但是这里就会有一个问题,我们知道我们对ASP.NET 资源的调用本质上是一个Request/Response的Message Exchange Pattern,异步调用往往意味着ISAPI将Request传递给ISAPIRuntime,将不能得到ISAPIRuntime最终生成的Response,这显然是不能接受的。而ECB解决了这个问题,ISAPI在调用ISAPIRutime的ProcessRequest方法时会将自己对应的ECB的指针传给它,ISAPIRutime不但可以将最终生成的Response返回给ISAPI,还能通过ECB调用ISAPI获得一些所需的数据。

  明白ECB是怎么回事之后,我们通过Reflector简单了解一下ISAPIRutime的ProcessRequest的实现:

ProcessRequest

public int ProcessRequest(IntPtr ecb, int iWRType)

{

IntPtr zero = IntPtr.Zero;

if (iWRType == 2)

{

zero = ecb;

ecb = 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, 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)

{

UnsafeNativeMethods.SetDoneWithSessionCalled(zero);

}

if (exception is ThreadAbortException)

{

Thread.ResetAbort();

}

return 0;

}

}

  对于上面的代码,我觉得没有必要去深究,但是对于那些具有强烈好奇心的朋友除外J。基本上上面的代码完成下面两个任务:

  通过传入的ECB和iWRType创建一个叫做ISAPIWorkerRequest的对象:

  bool useOOP = iWRType == 1;

  wr = ISAPIWorkerRequest.CreateWorkerRequest(ecb, useOOP);

  
然后调用HttpRuntime.ProcessRequestNoDemand(wr),通过将创建的ISAPIWorkerRequest的对象作为参数传入。

  HttpRuntime.ProcessRequestNoDemand的调用真正进入了ASP.NET Runtime Pipeline,这是一个相对
复杂的过程。在这里我想简单说说ISAPIWorkerRequest这个重要class,ISAPIWorkerRequest是一个Abstract class,它已通过ECB创建基于当前Request的Context的信息,针对不同的IIS版本,具有不同的ISAPIWorkerRequest subclass,比如:ISAPIWorkerRequestOutOfProc(IIS 5.x), ISAPIWorkerRequestInProcForIIS6, ISAPIWorkerRequestInProcForIIS7。ProcessRequest通过ISAPI传入的iWRType来创建不同HttpWorkerRequest,从而屏蔽了不同IIS的差异,后续的步骤就不需要考虑这种差异了,这是Abstract Factory的典型用法。

时间: 2024-10-16 05:02:59

ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline[上篇]的相关文章

ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline - Part II

二.ASP.NET Runtime Pipeline(续ASP.NET Http Runtime Pipeline - Part I) 现在我们真正进入ASP.NET管辖的范畴,下图基本上囊括整个处理过程涉及的对象,接下来我们一起来讨论这一系列的对象如何相互协作去处理Http Request,并最终生成我们所需的Http Response. HttpContext 上面我们介绍了ISAPI在调用ISAPIRuntime的时候将对应的ISAPI ECB Pointer作为参数传递给了Process

一起谈.NET技术,ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline[下篇]

ASP.NET Process Model索引 ASP.NET Process Model之一:IIS 和 ASP.NET ISAPI ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline[上篇] ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline[下篇] 二.ASP.NET Runtime Pipeline 现在我们真正进入ASP.NET管辖的范畴,下图基本上囊括整个处理过程涉及的对象

ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline[下篇]

ASP.NET Process Model索引 ASP.NET Process Model之一:IIS 和 ASP.NET ISAPI ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline[上篇] ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline[下篇] 二.ASP.NET Runtime Pipeline 现在我们真正进入ASP.NET管辖的范畴,下图基本上囊括整个处理过程涉及的对象

ASP.NET Process Model之一:IIS 和 ASP.NET ISAPI

ASP.NET Process Model索引 ASP.NET Process Model之一:IIS 和 ASP.NET ISAPI ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline[上篇] ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline[下篇] 前几天有一个朋友在MSN上问我"ASP.NET 从最初的接收到Http request到最终生成Response的整个流程到底是怎样

ASP.NET Process Model之一 IIS 和 ASP.NET ISAPI_win服务器

前几天有一个朋友在MSN上问我"ASP.NET 从最初的接收到Http request到最终生成Response的整个流程到底是怎样的?"我觉得这个问题涉及到IIS和ASP.NETASP.NET Runtime的处理模型的问题,并不是三言两语就能说清楚的,所以决定写这样一篇介绍IIS和ASP.NET Runtime Process Model的文章,谈谈我对此的一个粗浅的认识,如果有什么不对的地方,希望大家及时指正. 这篇文章大体分为两个部分,第一部分我将谈谈IIS的两个不同的版本-I

ASP中 process的using指令集是什么?

问题描述 ASP中process的using指令集是什么? 解决方案 解决方案二:1.我怀疑你说的是ASP.Net2.你应该查MSDN.这次我先帮你查,下回你自己查:解决方案三:多谢多谢,问题已解决~~解决方案四:引用1楼xinyaping的回复: 1.我怀疑你说的是ASP.Net2.你应该查MSDN.这次我先帮你查,下回你自己查:http://msdn.microsoft.com/en-us/library/system.diagnostics.process.aspx 应该是,System.

七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递

通过第一天的学习之后,我们相信您已经对MVC有一些基本了解. 本节所讲的内容是在上节的基础之上,因此需要确保您是否掌握了上一节的内容.本章的目标是在今天学习结束时利用最佳实践解决方案创建一个小型的MVC项目,本节的主要目标是了解MVC之间的数据传递问题.我们会逐步深入讲解,并添加新功能,使项目越来越完善. 系列文章 七天学会ASP.NET MVC (一)--深入理解ASP.NET MVC 七天学会ASP.NET MVC (二)--ASP.NET MVC 数据传递 七天学会ASP.NET MVC

搭建你的Spring.Net+Nhibernate+Asp.Net Mvc 框架 (二)创建你的项目

本篇文章的目的:首先是创建解决方案.并创建相关的项目.先介绍一下项目的各自的作用: 从数据库层到表示层依次为: 数据库层:        1.接口IDao层:IDao        2.Dao层实现:HibernateDao和SqlDao             HibernateDao:由Hibernate实现的IDao部分             SqlDao:是由我们自己写sql实现的部分 业务逻辑层:        1.业务逻辑接口层:IBLL        2.业务逻辑接口的实现:BL

ASP与JSP的比较(二)

js|比较|js ASP与JSP的比较(二) 五.ServerSideIncludes 在服务器端引用上ASP和JSP有着相同之处.ASP和JSP都可以支持此功能的服务器(IIS,APACHE)上实现服务器端包含虚文件.但JSP是将动态页面的结果包含进来,而不是包含文件的代码本身.当你包含的文件在另一个服务器上时,不包含任何代码和对象是一个非常有效的功能. ASP: JSP:<%@includefile="subfile.jsp"--> 六.JAVA组件:JavaBeans