IIS 7.0与ASP.NET
IIS 7.0在请求的监听和分发机制上又进行了革新性的改进,主要体现在对于Windows进程激活服务(Windows Process Activation Service,WAS)的引入,将原来(IIS 6.0)W3SVC承载的部分功能分流给了WAS。通过上面的介绍,我们知道对于IIS 6.0来说W3SVC主要承载着3大功能。
HTTP请求接收:接收HTTP.SYS监听到的HTTP请求。
配置管理:从元数据库(Metabase)中加载配置信息对相关组件进行配置。
进程管理:创建、回收、监控工作进程。
IIS 7.0将后两组功能实现到了WAS中,接收HTTP请求的任务依然落在W3SVC头上。WAS的引入为IIS 7.0提供了对非HTTP协议的支持。WAS通过监听器适配器接口(Listener Adapter Interface)抽象出不同协议监听器。具体来说,除了基于网络驱动的HTTP.SYS提供HTTP请求监听功能外还提供了TCP监听器、命名管道监听器和MSMQ监听器以提供基于TCP、命名管道和MSMQ传输协议的监听支持。
与此3种监听器相对的是3种监听适配器,它们提供监听器与WAS中的监听器适配器接口之间的适配。从这个意义上讲,IIS 7.0中的W3SVC更多地为HTTP.SYS起着监听适配器的作用。这3种非HTTP监听器和监听适配器定义在程序集SMHost.exe中,我们可以在目录%windir%\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\中找到它们。
WCF提供的这3种监听器和监听适配器最终以Windows 服务的形式体现。虽然它们定义在一个程序集中,我们依然可以通过服务工作管理器对其进行单独的启动、终止和配置。SMHost.exe提供了4个重要的Windows Service。
NetTcpPortSharing:为WCF提供TCP端口共享。关于端口共享在WCF中的应用,本人拙著《WCF全面解析》(上册)对此有详细的介绍。
NetTcpActivator:为WAS提供基于TCP的激活请求,包含TCP监听器和对应的监听适配器。
NetPipeActivator:为WAS提供基于命名管道的激活请求,包含命名管道监听器和对应的监听适配器。
NetMsmqActivator:为WAS提供基于MSMQ的激活请求,包含MSMQ监听器和对应的监听适配器。
图1-7为上述的4个Windows 服务在服务控制管理器中的呈现。
图1-7 定义在SMHost.exe中的Windows Service
图1-8揭示了IIS 7.0的整体构架及整个请求处理流程。无论是从W3SVC接收到的HTTP请求,还是通过WCF提供的监听适配器接收到的请求,最终都会传递到WAS。如果相应的工作进程(或者应用程序池)尚未创建,则创建它,否则将请求分发给对应的工作进程进行后续的处理。WAS在进行请求处理过程中,通过内置的配置管理模块加载相关的配置信息,并对相关的组件进行配置。与IIS 5.x和IIS 6.0基于Metabase的配置信息存储不同的是,IIS 7.0大都将配置信息存放于XML形式的配置文件中,基本的配置存放在applicationHost.config中。
图1-8 IIS 7.0与ASP.NET
ASP.NET集成
从上面对IIS 5.x和IIS 6.0的介绍中,我们不难发现IIS与ASP.NET是两个相互独立的管道(Pipeline)。在各自管辖范围内,它们各自具有自己的一套机制对HTTP请求进行处理。两个管道通过ISAPI实现“连通”,IIS是第一道屏障,当对HTTP请求进行必要的前期处理(比如身份验证等)时,通过ISAPI将请求分发给ASP.NET管道。当ASP.NET在自身管道范围内完成对HTTP请求的处理时,处理后的结果再返回到IIS,IIS对其进行后期处理(比如日志记录、压缩等),最终生成HTTP响应。图1-9反映了IIS 6.0与ASP.NET之间的桥接关系。
图1-9 基于IIS 6.0与ASP.NET双管道设计
从另一个角度讲,IIS运行在非托管的环境中,而ASP.NET管道则是托管的,ISAPI还是连接非托管环境和托管环境的纽带。IIS 5.x和IIS 6.0把两个管道进行隔离至少带来了下面的一些局限与不足:
相同操作的重复执行:IIS与ASP.NET之间具有一些重复的操作,比如身份验证。
动态文件与静态文件处理的不一致:因为只有基于ASP.NET动态文件(比如.aspx、.asmx、.svc等)的HTTP请求才能通过ASP.NET ISAPI进入ASP.NET管道,而对于一些静态文件(比如.html、.xml、.img等)的请求则由IIS直接响应,那么ASP.NET管道中的一些功能将不能用于这些基于静态文件的请求,比如我们希望通过Forms认证应用于基于图片文件的请求就做不到。
IIS难以扩展:对于IIS的扩展基本上就体现在自定义ISAPI,但是对于大部分人来说,这不是一件容易的事情。因为ISAPI是基于Win32的非托管的API,并非一种面向应用的编程接口。通常我们希望的是诸如定义ASP.NET的HttpModule和HttpHandler一样,通过托管代码的方式来扩展IIS。
对于Windows平台下的IIS来讲,ASP.NET无疑是一等公民,它们之间不应该是“井水不犯河水”,而应该是“你中有我,我中有你”的关系,为此在IIS 7.0中实现了两者的集成,通过集成可以获得如下的好处。
允许通过本地代码(Native Code)和托管代码(Managed Code)两种方式定义IIS Module,这些IIS Module注册到IIS中形成一个通用的请求处理管道。由这些IIS Module组成的这个管道能够处理所有的请求,不论请求基于怎样的资源类型。比如,可以将FormsAuthenticationModule提供的Forms认证应用到基于.aspx、CGI和静态文件的请求。
将ASP.NET提供的一些强大的功能应用到原来难以企及的地方,比如将ASP.NET的URL重写功能置于身份验证之前。
采用相同的方式去实现、配置、检测和支持一些服务器特性(Feature),比如Module、Handler映射、定制错误配置(Custom Error Configuration)等。
图1-10演示了在ASP.NET集成模式下,IIS整个请求处理管道的结构。可以看到,原来ASP.NET提供的托管组件可以直接应用在IIS管道中。
图1-10 基于IIS 7.0与ASP.NET集成管道设计
本文节选自《ASP.NET MVC 4 框架揭秘》
蒋金楠 著
电子工业出版社出版