ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline[上篇]
链接:https://www.cnblogs.com/artech/archive/2007/09/13/891262.html
一、从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方法,进而从非托管的环境进入了托管的环境。










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的实现:
public int ProcessRequest(IntPtr ecb, int iWRType)
{
IntPtr zero = IntPtr.Zero;
if (iWRType == )
{
zero = ecb;
ecb = UnsafeNativeMethods.GetEcb(zero);
}
ISAPIWorkerRequest wr = null;
try
{
bool useOOP = iWRType == ;
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 ;
}
HttpRuntime.ShutdownAppDomain(ApplicationShutdownReason.PhysicalApplicationPathChanged, SR.GetString("Hosting_Phys_Path_Changed", new object[] { appDomainAppPathInternal, appPathTranslated }));
return ;
}
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 ;
}
}
通过传入的ECB和iWRType创建一个叫做ISAPIWorkerRequest的对象:



然后调用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的典型用法。
通过 ASP.NET Http Runtime Pipeline - Part II 进入第二部分。
Reference:
A low-level Look at the ASP.NET Architecture
ASP.NET Process Model
[原创]ASP.NET Process Model之一:IIS 和 ASP.NET ISAPI
[原创]ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline - Part I
[原创]ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline - Part II
ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline[上篇]的更多相关文章
- ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline - Part II
https://www.cnblogs.com/artech/archive/2007/09/13/891266.html 二.ASP.NET Runtime Pipeline(续ASP.NET Ht ...
- ASP.NET MVC Model验证(二)
ASP.NET MVC Model验证(二) 前言 上篇内容演示了一个简单的Model验证示例,然后在文中提及到Model验证在MVC框架中默认所处的位置在哪?本篇就是来解决这个问题的,并且会描述一下 ...
- ASP.NET MVC Model绑定(二)
ASP.NET MVC Model绑定(二) 前言 上篇对于Model绑定的简单演示想必大家对Model绑定的使用方式有一点的了解,那大家有没有想过Model绑定器是在什么时候执行的?又或是执行的过程 ...
- ASP.NET MVC Model元数据(二)
ASP.NET MVC Model元数据(二) 前言 在上篇中,给大家留个对Model元数据的印象,并没有对Model元数据有过多的讲解,而在本篇中也不会对Model元数据的本身来解释,而是针对于它的 ...
- ASP.NET MVC Model之二模型绑定
Asp.net mvc中的模型绑定,或许大家经常用,但是具体说他是怎么一回事,可能还是会有些陌生,那么,本文就带你理解模型绑定.为了理解模型绑定,本文会先给出其定义,然后对通过比,来得出使用模型绑定的 ...
- ASP.NET MVC Model绑定(四)
ASP.NET MVC Model绑定(四) 前言 前面的篇幅对于Model绑定器IModelBinder以及实现类型.Model绑定器提供程序都作了粗略的讲解,可以把Model绑定器想象成一个大的容 ...
- ASP.NET MVC Model元数据(五)
ASP.NET MVC Model元数据(五) 前言 在上一篇中我们描述了应用于Model上面的各种用于显示控制的特性类,在本篇中将详细的介绍这些特性类的应用,虽然它们跟Model元数据的直接关系并不 ...
- ASP.NET MVC Model元数据(四)
ASP.NET MVC Model元数据(四) 前言 前面的篇幅讲解了Model元数据生成的过程,并没有对Model元数据生成过程的内部和Model元数据结构的详细解释.看完本篇后将会对Model元数 ...
- ASP.NET MVC Model元数据(三)
ASP.NET MVC Model元数据(三) 前言 在上篇中我们大概的讲解了Model元数据的生成过程,并没有对Model元数据本身和详细的生成过程有所描述,本篇将会对详细的生成过程进行讲解,并且会 ...
随机推荐
- 阿里巴巴Java开发手册之并发处理注意事项
1. [强制]获取单例对象需要保证线程安全,其中的方法也要保证线程安全.说明:资源驱动类.工具类.单例工厂类都需要注意.2. [强制]创建线程或线程池时请指定有意义的线程名称,方便出错时回溯.正例:p ...
- P2853 [USACO06DEC]牛的野餐Cow Picnic
------------------------- 长时间不写代码了,从学校中抽身出来真的不容易啊 ------------------------ 链接:Miku ----------------- ...
- header.vue 调用变量,别的组件导入引用,组件方法事例实例
<template> <div id="header"> <!-- 调用变量 --> <h1>{{ msg }}</h1> ...
- springboot web - 启动(2) run()
接上一篇 在创建 SpringApplication 之后, 调用了 run() 方法. public ConfigurableApplicationContext run(String... arg ...
- MySQL学习——备份和还原
MySQL学习——备份和还原 摘要:本文主要学习了如何备份和还原数据库. 部分内容来自以下博客: https://www.cnblogs.com/chenmh/p/5300370.html 常用命令 ...
- git提交时忽略了dll
问题说明 突然出现torisegit会自动忽略*.dll文件不会提交,比如:CSharp.dll. 问题原因 原因是由于安装了Sourcetree,受到了其环境变量的影响. Windows系统 ...
- Linux下快速删除大量小文件引起的磁盘inode(目录索引)过满
1)首先建立一个空白文件夹. mkdir /tmp/empty 然后安装下rsync yum install -y rsync 2)之后使用以下语句即可快速的删除文件. rsync --delete- ...
- Tomcat 后台war部署上传shell
tomcat的后台登录的两个目录为: /admin /manager/html 如果版本过高,只有采用弱密码的方式进后台: 有些tomcat采用默认的用户名和密码(用户名:admin,密码:空): 或 ...
- 【剑指Offer】24、二叉树中和为某一值的路径
题目描述 输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径.(注意: 在返回值的list中,数组长度大 ...
- 【H5适配 笔记1】rem适配
设备像素比(dpr)= 物理像素(手机渲染像素.分辨率)/设备独立像素(手机所显示元素的大小) 视口(viewport) 布局视口(获取浏览器布局视口高度,包括内边距,但不包括垂直滚动条.边框和外边距 ...