技巧 3 —— 连接池
建立 Web 应用程序与 SQL Server 之间的 TCP 连接是一项昂贵的操作。微软的开发人员利用连接池技术已经有好长一段时间了,这个技术使他们能重用到数据库的连接。而不是每次请求都建立新的 TCP 连接,新连接仅在连接池中得不到连接时才建立。当连接被关闭时,它被返回到连接池中,在那里它仍然保持与数据库的连接,与完全断开 TCP 连接相反。
当然,你需要提防泄漏的连接。当你处理完毕,一定要关闭连接。重申一次:不管人们怎么吹嘘微软 .NET 框架中的垃圾收集特性,每当你处理完毕,一定要显式地调用连接对象的 Close 或 Dispose 方法。不要指望公共语言运行时(CLR)来为你定时清除和关闭连接。CLR 最终将销毁类并强行关闭连接,但你无法保证该对象的垃圾收集届时会起作用。
为了充分用好连接池,有几条规则必须了然于心。首先,打开连接,进行处理,然后关闭连接。宁愿每个请求的连接打开和关闭多次,也不要保持连接打开状态以及在不同的方法间将它传来传去。其次,使用相同的连接串(如果你使用集成身份检查,那么也要用相同的线程身份)。如果你不用相同的连接串,例如,根据登录用户来定制连接串,你将无法得到连接池所提供的相同的最优化值。当模拟大用户量情形时,如果你使用集成身份检查,那么你的连接池将效力大减。.NET CLR 数据性能计数器在试图跟踪任何与连接池有关的性能问题时是非常有用的。
不管什么时候,只要你的应用程序连接到运行在其它进程中的资源,比如某个数据库,你都应该针对连接到资源所耗时间,发送和接收数据所耗时间以及往返次数进行优化。为了实现较好的性能,应该首当其充优化应用程序中任何种类的忙碌进程。
应用层包含到数据层的连接以及将数据转换成有意义的类实例和业务处理的逻辑。以 Community Server 为例,你要在其中处理 Forums 和 Threads 集合;以及应用许可这样的业务规则;尤其重要的是缓冲(Caching)逻辑也实现其中。
技巧 4 —— ASP.NET Cache API
在编写代码之前要做的头等大事之一是最大限度地构建应用层并发掘 ASP.NET 的 Cache 特性。
如果你的组件在 ASP.NET 应用程序内运行,那么你只需要在应用程序工程中引用 System.Web.dll 即可。当你需要访问 Cache 时,用 HttpRuntime.Cache 属性(相同的对象也可以通过 Page.Cache 和 HttpContext.Cache 访问)。
缓冲数据有几个准则。首先,如果数据能被使用多次,缓冲是个好的后选方案。其次,如果数据对给定请求或用户是一般的数据而非专用数据,那么最好是选择缓冲。如果数据用户或请求专用,如果需要保存期很长但可能不被经常使用,那么仍然要用缓冲。第三,常常被忽略的一个准则是有时缓冲太多的东西。一般来说,在x86机器上,为了降低内存不足错误的几率,运行某个进程不要超过800MB私有字节。因此,缓冲应该有个上限。换句话说,你也许能重用某个计算的结果,但如果该计算有10个参数,你可能试图针对10个置换进行缓冲,这样做可能会给你带来麻烦。ASP.NET 提供的最常见的容错是由覆盖缓冲导致的内存不足错误,尤其是大型数据集。
Cache 有几个重要特性是必须要了解的。第一个是 Cache 实现了最近最少使用(least-recently-used)算法,允许 ASP.NET 强制 Cache 清除操作 —— 如果可用内存下降到低水平 —— 则自动从 Cache 中删除不使用的项目。第二个是 Cache 支持依赖性到期特性,它能强制包括时间,键值,文件失效。时间常常被使用,但 ASP.NET 2.0 引入了具有更强大的失效类型:数据库缓冲失效。也就是当数据库中的数据改变时,缓冲中的条目会自动删除。有关数据库缓冲失效的更多信息参见 Dino Esposito 在 MSDN 杂志 2004 年七月刊的 Cutting Edge 专栏文章。该缓冲的体系结构,参见 图 3。
Figure 3 ASP.NET Cache