前一段在整理邮件的时候发现几年前和CDD老师交流时的一份邮件.下面是简单摘要:“从技术角度来说无论哪一个阵营跟新技术都是不可避免的也是很累的当然作为一个程序员来说也是必须的。要想让技术的更新对自己的影响减小基础就必须打牢。所以,底层的东西和抽象层的东西需要下一番功夫。因为说到底无论什么技术无非就是架构和最终的实现技术框架只是应用开发的一个平台一种技术如果了解了具体的东西技术更新对你来说就没什么影响了或者换句话说你要学一种新的技术速度和效率会非常之高。”上面一段话对自己的影响很大,可能大家在踏入“程序人生”的时候都会存在一些迷茫和彷徨。尽管我是属于那种相当热爱Proramming的一份子,但是面对万花筒般的技术分支也曾徘徊犹豫过.徘徊之余要做的事情便是夯实基础,寻找自己的兴趣与方向.对技术的迭代,以不变应万变才是王道.正因为如此,所以也不会存在银弹之说.如果真的有银弹的话那么我信奉的是:程序数据结构算法我选择的方向是Web,也相信Web终究会是互联网的未来.这篇文章简单谈一下自己对.NET平台下Web基础的一些浅解,由于自己水平有限,不足之处烦请见谅.HTTP协议HTTP协议是浏览器和服务器双方共同遵循的规范.是一种基于TCP/IP(传输层协议,相对应的有UDP)的应用层协议PS:TCP/UDP是广泛使用的网络通信协议,UDP协议具有不可靠性和不安全性,相对来说TCP协议是基于连接和三次握手的(相对可靠与安全),然而B/S架构的网站,由于同时在线的人数会很多,如果都与服务器保持连接状态.服务器的承载是相当大的,因而衍生出HTTP协议.简单的说:请求发起之后服务器端立刻关闭连接并释放资源.也正因为如此,HTTP协议通常被理解为”无状态”的.当然维系状态的手段有很多;如 Session/Cookie等 这里暂且不多做讨论.先来看一下典型的OSI七层模型 图解HTTP最通俗的理解请求/响应.图示:HTTP报文信息HTTP Request HeaderHTTP Response Header当然,也可以通过设置改变浏览器的选项.这里不做详细说明.不清楚的可以Google.给出ASP.NET下添加P3P头信息的例子HttpContext.Current.Response.AddHeader(p3p, CP\IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\);有兴趣详细了解的可以参考 MSDN 中关于部署 P3P的文章。下面是老生常谈的内容了(熟悉的朋友,自行跳过,权当温习下了 : ) )请求头消息头包含客户机请求的服务器主机名客户机的环境信息等Accept用于告诉服务器客户机支持的数据类型 例如Accept:text/html,image/*Accept-Charset用于告诉服务器客户机采用的编码格式Accept-Encoding用于告诉服务器客户机支持的数据压缩格式Accept-Language客户机语言环境Host:客户机通过这个服务器想访问的主机名If-Modified-Since客户机通过这个头告诉服务器资源的缓存时间Referer客户机通过这个头告诉服务器它客户端是从哪个资源来访问服务器的防盗链User-Agent客户机通过这个头告诉服务器客户机的软件环境操作系统浏览器版本等Cookie客户机通过这个头将Coockie信息带给服务器Connection告诉服务器请求完成后是否保持连接Date告诉服务器当前请求的时间一个http响应代表服务器端向客户端回送的数据它包括一个状态行若干个响应消息头以及实体内容状态行 例如 HTTP/1.1 200 OK 协议的版本号是1.1 响应状态码为200 响应结果为 OK响应头(消息头)包含:Location这个头配合302状态吗用于告诉客户端找谁Server服务器通过这个头告诉浏览器服务器的类型Content-Encoding告诉浏览器服务器的数据压缩格式Content-Length告诉浏览器回送数据的长度Content-Type告诉浏览器回送数据的类型Last-Modified告诉浏览器当前资源缓存时间Refresh告诉浏览器隔多长时间刷新Content-Disposition告诉浏览器以下载的方式打开数据。例如 context.Response.AddHeader(Content-Disposition,attachment:filenameicon.jpg); context.Response.WriteFile(icon.jpg);Transfer-Encoding告诉浏览器传送数据的编码格式ETag缓存相关的头可以做到实时更新Expries告诉浏览器回送的资源缓存多长时间。如果是-1或者0表示不缓存Cache-Control控制浏览器不要缓存数据 no-cachePragma控制浏览器不要缓存数据 no-cacheConnection响应完成后是否断开连接。 close/Keep-AliveDate告诉浏览器服务器响应时间IIS运行过程有了上面的HTTP协议的知识回顾,下面来让我们看下IIS是怎样工作的?IIS 5.X 已经距离我们很远了.好吧 XP默认的好像是的… 为万恶的IE6 默哀下0.0 .这里我们来看一下IIS 6 的图示根据上图简单分析下IIS6的运行过程在 User Mode 下http.sys 接收到 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。WASWeb Administrative Service根据这样一个 mapping将存在于某个 Application Pool Queue 的 request 传递到对应的 Worker Process (如果没有就创建这样一个进程)。在 Worker Process 初始化的时候加载 ASP.NET ISAPIASP.NET ISAPI 进而加载 CLR。最后通过 AppManagerAppDomainFactory 的 Create 方法为 Application 创建一个 Application Domain通过 ISAPIRuntime 的 ProcessRequest 处理 Request进而将流程进入到 ASP.NET Http Runtime Pipeline。PS几个知识点:HTTP.SYSKernel的一个组件它负责侦听Listen来自于外部的HTTP请求,根据请求的URL将其转发给相应的应用程序池 (Application Pool)。当此HTTP请求处理完成时它又负责将处理结果发送出去.为了提供更好的性能HTTP.SYS内部建立了一个缓冲区将最近的HTTP请求处理结果保存起来。Application Pool:IIS总会保持一个单独的工作进程应用程序池。所有的处理都发生在这个进程里包括ISAPI dll的执行。对于IIS6而言应用程序池是一个重大的改进因为它们允许以更小的粒度控制一个指定进程的执行。你可以为每一个虚拟目录或者整个Web站点配置应用程序池这可以使你很容易的把每一个应用程序隔离到各自的进程里这样就可以把它与运行在同一台机器上其他程序完全隔离。从Web处理的角度看如果一个进程死掉至少它不会影响到其它的进程。当应用程序池接收到HTTP请求后交由在此应用程序池中运行的工作者进程Worker Process: w3wp.exe来处理此HTTP请求。Worker Process:当工作者进程接收到请求后首先根据后缀找到并加载对应的ISAPI扩展 (如:aspx 对应的映射是aspnet_isapi.dll)工作者进程加载完aspnet_isapi.dll后由aspnet_isapi.dll负责加载ASP.NET应用程序的运行环境即CLR (.NET Runtime)。Worker Process运行在非托管环境而.NET中的对象则运行在托管环境之上(CLR)它们之间的桥梁就是ISAPI扩展。WASWeb Admin Service这是一个监控程序它一方面可以存取放在InetInfo元数据库Metabase中的各种信息另一方面也负责监控应用程序池Application Pool中的工作者进程的工作状态况必要时它会关闭一个老的工作者进程并创建一个新的取而代之。再来看下网上对IIS7经典模式下的图解IIS 7 应用程序池的托管管道模式“经典”模式也是这样的工作原理。这种模式是兼容 IIS 6 的方式 以减少升级的成本。小插曲场景假定:截获客户端的请求并对请求进行重写。在IIS6中请求的截获动作只能被限制在IIS加载aspnet_isapi.dll后也就是说如果该请求不是明确针对asp.net资源的请求(比如这个请求只是一个静态文件的请求如www.cnblogs.com/index.html这时我们就便不能在代码中编写截获请求的逻辑因为IIS6是根据URL的后缀来映射并加载对应的isapi的如果一个请求的url是:www.cnblogs.com/index.aspx根据.aspx这个后缀,IIS6可以得知这个请求是针对asp.net资源的应该加载aspnet_isapi.dll创建.net运行时并运行asp.net页面的代码但很明显诸如www.cnblogs.com/index.html这种请求,IIS6通常认为不是对asp.net资源的请求因此不会加载aspnet_isapi.dll来运行asp.net我们即使在asp.net页面中编写了拦截请求的代码也不会被执行。当然这里我说通常是有原因的因为我们可以在IIS6中添加通配符程序映射的方式或者在web.config中对某种请求手动添加处理程序的方式来迫使IIS6为非asp.net资源类型的请求加载aspnet_isapi.dll。IIS6中对请求的执行流程如上.咦,有木有人和我一样想到了URL Routing 和URL Rewriting ?这里不做说明,大叔手记16传送门:大叔手记16分析URL Routing和URL Rewriting两者之间的不同 - 汤姆大叔 - 博客园这个问题先放一下~~了解II7的集成模式也许可以有一些思绪让我们再来看下IIS官网上对IIS7的图解传送门 :http://www.iis.net/learn/get-started/introduction-to-iis/introduction-to-iis-architecture1、当客户端浏览器开始 HTTP 请求一个WEB 服务器的资源时HTTP.sys 拦截到这个请求。2、HTTP.sys 联系 WAS 获取配置信息。3、WAS 向配置存储中心(applicationHost.config)请求配置信息。4、WWW 服务接收到配置信息配置信息指类似应用程序池配置信息站点配置信息等等。5、WWW 服务使用配置信息去配置 HTTP.sys 处理策略。6、WAS为请求创建一个进程(如果不存在的话)7、工作者进程处理请求并对HTTP.sys做出响应.8、客户端接受到处理结果信息。IIS 7 应用程序池的托管管道模式(集成模式)华丽的变身IIS7中对asp.net的请求不再是分两条处理管道而是将asp.net和IIS集成起来这样做的好处是统一了请求验证工作加强了asp.net对于请求的控制能力等等。在IIS7中asp.net不再像IIS6一样只限定于aspnet_isapi.dll中而是被解放出来从IIS接收到HTTP请求开始即进入asp.net的控制范围asp.net可以存在于一个请求在IIS中各个处理阶段。甚至可以为部署在IIS7中的PHP应用提供基于asp.net的验证身份验证功能(传送门:IIS 7.0: Enhance Your Apps with the Integrated ASP.NET Pipeline | Microsoft Learn)。好吧,戛然而止一下,篇幅有限:IIS部分告一段落 留一些遐想空间.再来分析ASP.NET的运行机制ASP.NET运行机制在IIS6图示中我们分析到“ AppManagerAppDomainFactory 的 Create 方法为 Application 创建一个 Application Domain通过 ISAPIRuntime 的 ProcessRequest 处理 Request进而将流程进入到 ASP.NET Http Runtime Pipeline。”下面我们来看一下AppDomain运行过程图示AppDomain的作用,相信大家都很了解了吧.这里简明扼要的写几点:一个AppDomain中的代码创建的对象不能由另一个AppDomain中的代码直接访问(只能使用按引用封送或者按值封送,起到了很好的隔离作用).AppDomain可以卸载CLR不支持从AppDomain中卸载一个程序集的能力,但可以告诉CLR卸载一个AppDomain,从而达到卸载当前包含在该AppDomain内的所有程序集.AppDomain 可以单独保护当宿主加载一些代码之后,可以保证这些代码不会被破坏(或读取)宿主本身使用的一些重要的数据结构.AppDomain可以单独配置设置主要影响CLR在AppDomain中加载程序集的方式,涉及搜索路径、版本绑定重定向、卷影复制及加载器的优化。由以上几点可以看出AppDomain确保了Windows系统及其中运行的应用程序的健壮性。AppDomain提供了保护、配置和终止其中每一个应用程序所需的隔离性。再来看下ProcessRequest的过程