一、ASP.NET ISAPI与IIS
IIS如何监听来自外界的http request ,如何根据ISAPI Extension Maping 将对于不同的resource的请求分发给不同的ISAPI Extension ,基于ASP.NET Resource 的ASP.NET ISAPI 如何将Request传递给ASP.NET Runtime环境,首先看看IIS的处理过程然后在介绍托管ASP.NETRuntime环境对传入的Http request 的处理过程。
IIS5一个最显著的特征就是Web Server 好人真正的ASP.NET Application的分离。作为Web Server的IIS 运行在一名为InetInfo.exe的进程中,InetInfo.Exe是一个namtive Executive,并不是一个托管的程序,而我们真正的ASP.NET Application 则是一个运行在aspnet_wp的WorkerProcess上面,在该进程初始化的时候会加载CLR所以这是一个托管的环境。
下面说说aspnet_wp如何创建,aspnetInfo.exe如何进行通信,以及简单的介绍在aspnet_wp中如何将request导入ASP.NET Runtime Pipeline。
我们通过创建虚拟目录将资源host到IIS下,原则上我们可以通过IIS 访问设置与虚拟目录下的所有resource 。这不仅仅包含一些静态的资源文件,比如图片、html、css、js等。比如还有动态文件aspx、asmx、ascx等等。我们还可以将Remoting和WCFService host 到IIs下。对于一些静态的文件,IIS直接提取对应的文件将其作为HttpResponse返回给Client,但是对于一些需要进一步处理的动态执行文件,IIS必须将Request进一步传递给对应的处理程序,待处理程序执行完毕获得最终的HttpResponse通过IIS返回给Client。对于IIS来说,这些处理程序通过ISAPI Extension来体现。对于基于ASP.NET 的Resource,其对应的ISAPI Extension 为ASP.NET ISAPI,通过一个aspnet_isapi.dll承载。IIS的Metadata database 维护着一个称为ISAPI Extension Mapping的数据表,负责将不同类型的Resource 映射到对应的ISAPI Extension。
上图展示了一个基于ASP.NET Resource (以aspx为例)的http request 的流程。首先用户先通过浏览器请求一个aspx page ,浏览器请求的WebServer 也就是目标主机的IIIS 。IIS运行在一个InetInfor.exe的进程中,inetfo.exe是一个Native Executive,并非一个托管的程序。IIS分析Request的目标资源文件的扩展名(这里是aspx),通过ISAPI Extension Mapping获知的ISAPI为ASP.NET ISAPI于是加载aspnet_isapi.dll。到此为止该Request交由ASP.NET ISAPI处理。ASP.NET ISAPI会创建一个叫做aspnet_wp.exe 的Worker Process(如果不存在的话),在aspnet_wp.exe初始化的时候会加载CLR ,从而为ASP.NET Application 创建一个托管的运行环境。CLR初始化会使用两个重要的dll :AppmanagerAppDomainFactory和ISAPI Runtime。通过AppManagerAppDomainFactory的creste方法创建一个ApplicationDomain,通过ISAPIRuntime的Process Request 处理Request,进而将流程拖到ASP.NETHttp Runtime Pipline 的范畴。ASP.NETHttp Runtime Pipline对Request的处理是一个复杂的过程,一会在研究(参考上面ASP.NET 请求反编译代码的图片),他接管Request 最终生成html,这基本上就是整个处理流程,很简单。
还有几点要注意的特别指出:
- 首先,同一台主机上同一时间只能运行一个aspnet_wp进程,每个基于虚拟目录的ASP.NET Application对应一个ApplicationDomain,也就是说每个Application都运行在同一个Worker Process中,Application之间的隔离是基于Application Domain的而不是基于Process的。
- 其次,ASP.NET ISAPI不但负责aspnet_wpWorker Process,而且负责监控该程序,如果检测到aspnet_wp的Prefromance降低到某个设定的下限,ASP.NET ISAPI 会负责结束掉该进程。当aspnet_wp结束掉以后后续的Request会导致ASP.NET ISAPI 重新创建新的aspnet_wp Worker Process 。
- 由于IIS 和Application运行在各自进程中,他们之间的通信必须采用特定的通信机制。本质上IIS所在的InetIfo进程和Worker Process 之间的通信是同一台机器不同进程的通信,处于Performance的考虑,他们之间采用Named Pipe的通信机制。ASP.NET ISAPI和Worker Process之间的通信通过他们之间的一组Pipe实现。同样处于Performance的原因,ASP.NET ISAPI 通过异步方式将Request传到WorkerProcess并获得Response,但是WorkerProcess是同步方式向ASP.NET ISAPI 获得一些Server变量。
二、IIS 6 based Process Model
与IIS 5.x不同,W3SVC从InetInfo.exe进程脱离出来(对于IIS6.0来说,InetInfo.exe基本上可以看作单纯的IIS管理进程),运行在另一个进程SvcHost.exe中。不过W3SVC的基本功能并没有发生变化,只是在功能的实现上作了相应的改进。与IIS 5.x一样,元数据库(Metabase)依然存在于InetInfo.exe进程中。
图2 IIS 6与ASP.NET
当HTTP.SYS监听到用户的HTTP请求后,将其分发给W3SVC。W3SVC解析出请求的URL,并根据从Metabase获取的URL与Web应用之间的映射关系得到目标应用,并进一步得到目标应用运行的应用程序池或者工作进程。如果工作进程不存在(尚未创建或者被回收),则为该请求创建新的工作进程,工作进程的这种创建方式被称为请求式创建。在工作进程的初始化过程中,相应的ISAPI.dll被加载,对于ASP.NET应用来说,被加载的ISAPI.dll为Aspnet_ispai.dll。ASP.NET ISAPI再负责进行CLR的加载、AppDomain创建、Web Application的初始化等。
作为Host 基于Http Application的IIS来说,这两方面就显得尤为重要了。我们从IIS 5.x到IIS 6 的演变,不难看出IIS 6在前一个版本基础上所作的改进也是基于这两个方面。在介绍IIS 6的处理模型之前,我们先看看IIS 5.x都什么样缺陷:
1. 首先从Performance上看,IIS和application运行在不同的进程中,虽然他们之间采用了基于Named Pipe的异步通信方式,但是一个基于进程之间的通信对性能的影响确实不能从根本上解决。
2. 其次,从Reliability来考虑,一台机器上只能运行一个worker process,每个Application运行在同一个进程中,虽然基于Application Domain的隔离能提供一定的Reliability,但是一旦真个进程崩溃,所有的Application都受影响。所以我们有时候需要提供一个基于Process的隔离性。
基于Reliability的改进,IIS 6引入了Application Pool。顾名思义,Application Pool就是一个application的容器,在IIS 6中,我们可以创建若干Application Pool,在创建Web Application的时候,我们为它指定一个既定的application pool。在运行的时候,一个Application对应一个Worker Process:w3wp.exe。也就是说,和前一个版本的IIS不同的是,对于IIS 6来说,同一台机器上可以同时运行多个Worker Process,每个Worker Process中的每个Application domain对应一个Application。这样,Application之间不但能提供Application Domain级别的隔离,你也可以将不同的Application置于不同的Application Pool中,从而基于Process级别的隔离。对于Host 一些重要的Application来说,这样的方式可以提供很好的Reliability。
在Performance方面,IIS 5.x是通过InetInfo.exe监听Request并把Request分发到Work Process。换句话说,在IIS 5.x中对Request的监听和分发是在User Mode中进行,在IIS 6中,这种工作被移植到kernel Mode中进行,所有的这一切都是通过一个新的组件:http.sys来负责。
HTTP.SYS与W3Wp.exe
上图基本上演示了IIS 6整个处理过程。在User Mode下,http.sys接收到一个基于aspx的http
request,然后它会根据IIS中的Metabase查看该基于该Request的Application属于哪个Application
Pool,如果该Application Pool不存在,则创建之。否则直接将request发到对应Application
Pool的Queue中。我上面已经说了,每个Application Pool对应着一个Worker Process:w3wp.exe,毫无疑问他是运行在User
Mode下的。在IIS Metabase中维护着Application Pool和worker process的Mapping。WAS(Web
Administrative service(网络管理服务))根据这样一个mapping,将存在于某个Application Pool
Queue的request 传递到对应的worker process(如果没有,就创建这样一个进程)。在worker
process初始化的时候,加载ASP.NET ISAPI,ASP.NET ISAPI进而加载CLR。最后的流程就和IIS
5.x一样了:通过AppManagerAppDomainFactory的Create方法为Application创建一个Application
Domain;通过ISAPIRuntime的ProcessRequest处理Request,进而将流程进入到ASP.NET Http Runtime
Pipeline。
IIS 7的ASP.NET请求处理过程
上图的8个步骤分别如下:
1、当客户端浏览器开始HTTP请求一个WEB服务器的资源时,HTTP.sys拦截到这个请求。
2、HTTP.sys contacts WAS to obtain information from the configuration store.
3、WAS向配置存储中心请求配置信息。applicationHost.config。
4、WWW服务接受到配置信息,配置信息指类似应用程序池配置信息,站点配置信息等等。
5、WWW服务使用配置信息去配置HTTP.sys处理策略。
6、WAS(网络管理服务) starts a worker process for the application pool to which the request was made.
7、The worker process processes the request and returns a response to HTTP.sys.
8、客户端接受到处理结果信息。
W3WP.exe进程中又是如果处理得呢?? IIS 7 的应用程序池的托管管道模式分两种:经典和集成。这两种模式下处理策略各不相通。
IIS 6 以及 IIS7 经典模式的托管管道的架构
在IIS7之前,ASP.NET是以IIS ISAPI extension的方式外加到IIS,其实包括ASP以及PHP,也都以相同的方式配置(PHP在IIS采用了两种配置方式,除了IIS ISAPI extension的方式,也包括了CGI(公共网关接口(Common Gateway Interface))的方式,系统管理者能选择PHP程序的执行方式),因此客户端对IIS的 HTTP请求会先经由IIS处理,然后IIS根据要求的内容类型,如果是HTML静态网页就由IIS自行处理,如果不是,就根据要求的内容类型,分派给各自的IIS ISAPI extension;如果要求的内容类型是ASP.NET,就分派给负责处理ASP.NET的 IIS ISAPI extension,也就是aspnet_isapi.dll。下图是这个架构的示意图。
IIS 7 应用程序池的托管管道模式经典模式也是这样的工作原理。这种模式是兼容IIS 6 的方式,以减少升级的成本。
IIS6的执行架构图,以及IIS7应用程序池配置成经典模式的执行架构图
IIS 7 应用程序池的 托管管道模式 集成模式
而IIS 7 完全整合.NET之后,架构的处理顺序有了很大的不同(如下图),最主要的原因就是ASP.NET从IIS插件(ISAPI extension)的角色,进入了IIS核心,而且也能以ASP.NET模块负责处理IIS 7 的诸多类型要求。这些ASP.NET模块不只能处理ASP.NET网页程序,也能处理其他如ASP程序、PHP程序或静态HTML网页,也因为ASP.NET的诸多功能已经成为IIS 7 的一部份,因此ASP程序、PHP程序或静态HTML网页等类型的要求,也能使用像是Forms认证(Forms Authentication)或输出缓存(Output Cache)等ASP.NET 2.0的功能(但须修改IIS 7 的设定值)。也因为IIS 7 允许自行以ASP.NET API开发并加入模块,因此ASP.NET网页开发人员将更容易扩充IIS 7和网站应用程序的功能,甚至能自行以.NET编写管理IIS 7 的程序(例如以程控IIS 7 以建置网站或虚拟目录)。
IIS 7 的执行架构图(集成托管信道模式下的架构)
小结
IIS5到 IIS6的改进,主要是HTTP.sys的改进。
IIS6到 IIS7的改进,主要是ISAPI的改进。