高性能ASP.NET站点构建之细节决定成败

开发 后端
本文将为大家介绍的是ASP.NET站点构建之优化HTTP请求,通过优化HTTP请求可以大大加快页面的载入速度,提高页面体验。

高性能ASP.NET站点构建系列文章目录

  1. 高性能ASP.NET站点构建之开篇
  2. 高性能ASP.NET站点构建之剖析页面的处理过程
  3. 高性能ASP.NET站点构建之优化HTTP请求
  4. 高性能ASP.NET站点构建之细节决定成败
  5. 高性能ASP.NET站点构建之性能调优综述
  6. 高性能ASP.NET站点构建之识别性能瓶颈
  7. 高性能ASP.NET站点构建之简单的优化措施
  8. ASP.NET站点构建之减少不必要的请求
  9. 高性能ASP.NET站点构建之托管资源优化
  10. 高性能ASP.NET站点构建之监测CLR性能

前言:曾经就因为一个小小的疏忽,从而导致了服务器崩溃了,后来才发现:原来就是因为一个循环而导致的,所以,对“注意细节“这一说法是深有感触。

本篇的议题如下:

问题的描述

细节的重要性

问题的描述

首先,描述一下故事的背景:(希望大家耐心的故事读完)

在网站中,网页中的分页控件每次显示10条数据,每次点击下一页,就再次去取下一个10条数据。至于分页的方法怎样做,方法有很多,相信这点大家都知道。

过程是这样的:在用户请求数据的时候(考虑到了用户的操作和网站的访问量)我会第一次取出500条数据,然后把数据放在缓存中,也就是说,我取出了50页的数据,放在缓存中,这样如果,以后用户请求第一页到第49页的时候,就直接从缓存中拿数据。

如下图:

缓存流程图
 

第一个数据块:

采用键值对的形式:字典保存

如果用户请求到了49页以后,那么就再次从数据库中取出下一个数据块(包含501到1000数据),然后,现在内存中就有了1000条数据。

至于缓存多久,数据什么失效,失效后怎么做,这里暂不谈论。(网站在这种缓存策略下运行的很好)。 

代码如下:

  1. List<Product> products=GetDataFromCacheOrDatabase(condition,pageIndex,count….); 

 

代码的意思很清楚,从缓存中拿数据,如果缓存中没有对应的数据,那么就先从数据库中拿500条数据,然后放在缓存中,最后返回10条数据。

后来,因为某些功能的需要,需要返回当前页的前6页数据和后6页的数据,例如:如果当前页是第12页,那么就要返回12页之前6页Product(也就是第6,7,8,9,10,11页的数据),和第12页后的页的Product(第13,14,15,16,17,18页的数据)。 

如下:

 

 

当然,如果当前页是第5页,那么就把之前所有5页的数据都返回,另外再加上第5页之后的6页数据。

这里就可能涉及到跨块获取数据,如:

如果当前页是第48页的时候,那么返回前6页数据是没有什么问题的,那么后6页的数据就不足了,因为49,40也得数据可以从缓存的数据块中取到,至于51,52,53,54页的数据,就需要再次从数据库中读取,然后再次缓存(如果事先没有被缓存)。

最后在缓存中的数据如下:

然后调用方法:(伪码)

  1. List<Product> products=GetDataFromCacheOrDatabase(condition,42, 126….);  

上面传入的是从第42页开始的数据,也就是第48页的前6页和后6页的数据。

这个方法的内部实现是这样的:

1.    首先从第一个数据块中取出42页到50页的数据

取出数据后保存在一个List<Product> firstProductList;

2.    从第二个数据块中取出从51页到54页(如果第二个数据块在缓存不存在,就去数据库中取501-1000条,然后再放在缓存的第二个数据块中)。

保存在第二个List<Product> secondProductList

3. 然后把两个list合并,返回结果。例如

  1. secondProductList.Foreach(u=>firstProductList.Add(u)); 

基本的实现就是这样,看起来还行,也比较的合理,但是就是因为这个操作,从而导致服务器内存溢出。

大家想想看是什么原因。

细节的重要性

其实缓存的数据不是很多,是不足以让服务器内存溢出的,但是服务器还是出现了out of memory的异常。之前一直跑的很好,就是改了代码之后才出现问题的。

其实这就是由于一个最基本的错误产生的:引用类型。

下面就来分析下:

首先是从第一个数据块中取出数据,然后用

List<Product> firstProductList 引用指向取出的数据

然后从第二个数据块中取出数据,用

List<Product> secondProductList指向数据的引用

如下图

 

在第三步中采用

  1. secondProductList.Foreach(u=>firstProductList.Add(u)); 

 

把secondProductList中的数据加入到firstProductList中,就因为是引用类型,其实实际操作的结果是:不断的在改变第一个数据块中的数据,使得第一个数据块中的数据逐渐的变多。

现在当前页是48页,采用上面的操作,致使第一个数据块中的数据增加了60条,

如果用户再次翻页,到了49页,那么第一个数据块中的数据又增多了60条

依此类推,最后导致了服务器内存的不足,致使服务器崩溃了。原本的“功臣”----缓存却成为了罪魁祸首。

其实这个问题的解决,只要改变一点点的代码就行了: 

  1. List<Product> firstProductList;  
  2. List<Product> secondProductList; 

然后

List<Product> resultProductList=new List<Product>();然后分别把firstProductList,secondProductList遍历,加入到resultProductList就行了。

就这么简单。

一个小的细节,导致了大的问题。 

原文链接:http://www.cnblogs.com/yanyangtian/archive/2010/08/17/1801129.html

【编辑推荐】

  1. 高性能ASP.NET站点构建之开篇
  2. 高性能ASP.NET站点构建之剖析页面的处理过程
  3. 高性能ASP.NET站点构建之优化HTTP请求
  4. 强化部署ASP.Net 2.0配置应用程序
  5. 微软PDC2009直击:改进ASP.NET 4运行时
  6. 详解ASP.NET MVC 2自定义验证
责任编辑:彭凡 来源: 博客园
相关推荐

2011-02-13 09:17:02

ASP.NET

2011-02-23 09:49:40

ASP.NET

2011-02-15 09:31:56

ASP.NET

2011-02-16 09:08:27

ASP.NET

2011-02-22 09:16:24

高性能ASP.NET

2011-02-13 09:37:55

ASP.NET

2011-02-17 09:13:57

ASP.NET

2011-06-15 16:22:38

2011-03-11 10:43:52

数据迁移

2017-05-11 22:58:59

2020-04-20 11:52:37

Static变量静态

2010-07-22 09:13:00

ASP.NET

2010-05-25 13:22:43

2011-04-13 13:49:50

ASP.NET网站优化

2016-07-05 10:27:30

云计算

2011-03-02 09:09:53

MySQL分区管理细节

2015-09-30 10:36:03

eSpace UC客户华为

2010-09-27 14:30:05

评测SSL VPN

2014-10-13 13:40:07

程序员

2011-06-10 13:57:00

SEO
点赞
收藏

51CTO技术栈公众号