原文:【原创】构建高性能ASP.NET站点之三 细节决定成败

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

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

  系列文章链接:

  构建高性能ASP.NET站点 开篇

  构建高性能ASP.NET站点之一 剖析页面的处理过程(前端)

  构建高性能ASP.NET站点之二 优化HTTP请求(前端)

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

  构建高性能ASP.NET站点 第五章—性能调优综述(前篇)

  大型高性能ASP.NET系统架构设计

  构建高性能ASP.NET站点 第五章—性能调优综述(中篇)

  构建高性能ASP.NET站点 第五章—性能调优综述(后篇)

  构建高性能ASP.NET站点 第六章—性能瓶颈诊断与初步调优(上篇)—识别性能瓶颈

  构建高性能ASP.NET站点 第六章—性能瓶颈诊断与初步调优(下前篇)—简单的优化措施

  构建高性能ASP.NET站点 第六章—性能瓶颈诊断与初步调优(下后篇)—减少不必要的请求

  构建高性能ASP.NET站点 第七章 如何解决内存的问题(前中篇)—托管资源优化—监测CLR性能

  构建高性能ASP.NET站点 第七章 如何解决内存的问题(前篇)—托管资源优化—垃圾回收机制深度剖析

  构建高性能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合并,返回结果。例如

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

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

  大家想想看是什么原因。

  细节的重要性

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

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

  下面就来分析下:

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

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

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

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

  如下图

 

  在第三步中采用

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

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

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

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

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

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

    List<Product> firstProductList;

    List<Product> secondProductList;

  然后

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

就这么简单。

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

 

  不要忽视每一个细节。不要做没有比较的循环等操作,一定要审视代码,重构代码。

  今天就写到了这里,啰嗦了这么多,希望对大家有一点点的帮助。

  如有不正确,或者认为不妥的地方,希望大家斧正!而且留下高见!谢谢!

 

版权为小洋和博客园所有,欢迎转载,转载请标明出处给作者。

   http://www.cnblogs.com/yanyangtian

【原创】构建高性能ASP.NET站点之三 细节决定成败的更多相关文章

  1. 【原创】构建高性能ASP.NET站点 第六章—性能瓶颈诊断与初步调优(下前篇)—简单的优化措施

    原文:[原创]构建高性能ASP.NET站点 第六章-性能瓶颈诊断与初步调优(下前篇)-简单的优化措施 构建高性能ASP.NET站点 第六章—性能瓶颈诊断与初步调优(下前篇)—简单的优化措施 前言:本篇 ...

  2. 【原创】构建高性能ASP.NET站点 第五章—性能调优综述(后篇)

    原文:[原创]构建高性能ASP.NET站点 第五章-性能调优综述(后篇) 构建高性能ASP.NET站点 第五章—性能调优综述(后篇) 前言:本篇主要讲述如何根据一些简单的工具和简单的现象来粗布的定位站 ...

  3. 【原创】构建高性能ASP.NET站点之二 优化HTTP请求(前端)

    原文:[原创]构建高性能ASP.NET站点之二 优化HTTP请求(前端) 构建高性能ASP.NET站点之二 优化HTTP请求(前端) 前言: 这段时间比较的忙,文章写不是很勤,希望大家谅解. 上一篇文 ...

  4. 【原创】构建高性能ASP.NET站点之一 剖析页面的处理过程(前端)

    原文:[原创]构建高性能ASP.NET站点之一 剖析页面的处理过程(前端) 构建高性能ASP.NET站点之一 剖析页面的处理过程(前端) 前言:在对ASP.NET网站进行优化的时候,往往不是只是懂得A ...

  5. 【原创】构建高性能ASP.NET站点 开篇

    原文:[原创]构建高性能ASP.NET站点 开篇 构建高性能ASP.NET站点 开篇 前言:有段时间没有写ASP.NET的东西了,心里总是觉得缺少了什么,毕竟自己对ASP.NET还是情有独钟的. 在本 ...

  6. 【原创】构建高性能ASP.NET站点 第七章 如何解决内存的问题(前中篇)—托管资源优化—监测CLR性能

    原文:[原创]构建高性能ASP.NET站点 第七章 如何解决内存的问题(前中篇)-托管资源优化-监测CLR性能 构建高性能ASP.NET站点 第七章 如何解决内存的问题(前中篇)—托管资源优化—监测C ...

  7. 优化HTTP前端请求构建高性能ASP.NET站点

    HTTP请求的优化  在一个网页的请求过程中,其实整个页面的html结构(就是页面的那些html骨架)请求的时间是很短的,一般是占整个页面的请求时间的10%-20%.在页面加载的其余的时间实际上就是在 ...

  8. 【推荐】【给中高级开发者】构建高性能ASP.NET应用的几点建议

    本篇目录 早期阶段就要对应用进行负载测试 使用高性能类库 你的应用是CPU密集还是IO密集的 使用基于Task的异步模型,但要慎重 分发缓存和会话(session)状态 创建Web Gardens 巧 ...

  9. [转]【转】大型高性能ASP.NET系统架构设计

    大型高性能ASP.NET系统架构设计 大型动态应用系统平台主要是针对于大流量.高并发网站建立的底层系统架构.大型网站的运行需要一个可靠.安全.可扩展.易维护的应用系统平台做为支撑,以保证网站应用的平稳 ...

随机推荐

  1. LeetCode :: Binary Tree Zigzag Level Order Traversal [tree, BFS]

    Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to ...

  2. SE 2014年5月23日

    两站点 A 和 B,由于业务往来需要,所以工程师提出vpn技术,同时需要保证业务流在internet上的安全性,同时在这里站点均为固定ip地址. 通过分析以上信息,确定这里使用 IPSec VPN的主 ...

  3. Learning React Native笔记

    React Native作为一个新事物,相关的资料还不多 官方的文档比较简单,缺少一些系统的例子 在对React Native的应用中,迫切的想学习一些别人的最佳实践.所以想通过看书系统的学习下 之前 ...

  4. HTML 5最终确定,八年后,我们再谈谈如何改变世界

    从原:http://www.36kr.com/p/216655.html 我们第一次谈论HTML5要改变世界大概是由于乔布斯,他坚持在iOS上不兼容Flash,在Adobe统治多媒体开发的那个年代.这 ...

  5. 关于埃博拉(Ebola)基础研究病毒

    关于埃博拉(Ebola)病毒的基础研究 2005年.美国哈佛大学医学研究院(Harvard Medical School)James Cunningham教授关于埃博拉病毒有一项基础研究,研究成果发表 ...

  6. hadoop的一些名词解释

    在网上收集了一些mapreduce中常用的一些名词的解释,分享一下: Shuffle(洗牌):当第一个map任务完成后,节点可能还要继续执行更多的map 任务,但这时候也开始把map任务的中间输出交换 ...

  7. HTTP/1.1

    HTTP真的很简单   原文:HTTP Made Really Easy因为我本身网络基础就很差,所以看到这篇文章一方面是学习网络知识,另一方面为了锻炼我蹩脚的英语水平,文中如有错误,欢迎浏览指正! ...

  8. 通常编译亲测56Y国际象棋源代码,精仿56Y国际象棋完整的源代码下载!

    今天公布亲测通常应编译56Y国际象棋源代码,精仿56Y牌源代码.喜欢的能够拿去研究.论坛资源太多.我们会把好的资源都公布出来,同一时候欢迎很多其它的程序猿增加我们! 增加我们的共同学习交流!     ...

  9. 《深入了解Android:Wi-Fi、NFC和GPS音量》勘误表

    资源下载更新(我不知道为什么被115网盘屏蔽) 深入了解android它wifi-nfc-gps 115网盘礼包码:5lbee5qn4g5ghttp://115.com/lb/5lbee5qn4g5g ...

  10. easyui LinkButton

    http://www.zi-han.net/case/easyui/menu&button.html