有气质的熊(minbear)

Life = Joy.Parse( Work + Study + Living);

导航

<2008年5月>
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

统计

公告

   《有气质的熊》这个名字来自一篇散文,写得挺有趣,而标题和我的姓氏又存在一些关联,于是乎取来做了笔名。

与我联系

搜索

 

常用链接

留言簿(27)

我参与的团队

我的标签

随笔档案

文章分类

文章档案

相册

.Note

E-Blog

Favorite Site

Friend-Blog

积分与排名

最新评论

阅读排行榜

ASP.NET中OutOfMemoryException异常的处理方案

相信做ASP.NET中大型Web应用的人都碰到过OutOfMemoryException这个异常,对于这个问题我研究了很久,在微软的技术文档上也了解过此问题出现的原因,说实话,到目前我仍然没有完美的解决方案,这里只是把我处理该问题的一些经验提出来和大家一起分享,尽可能的避免该问题的发生。

1) 首先,在硬件的配置上,出现该问题的原因我想很多人已经知道了,那就是IIS对于内存的管理存在一些限制,普遍的认识是800M的线程内存使用上限(通过我的一些客户实践证明的确如此,甚至更低...),不管是w3wp还是aspnet_wp,这个限制对ASP.NET应用服务器的机器配置而言其意义是很明显的,超过2G的内存对于单纯的Web服务器而言作用是很微小的,所以在Web服务器的配置上可在CPU的数量方面多考虑。

2) IIS配置上的方案,IIS5.0可安装一个IIS5Recycle程序,该程序采用服务的形式来回收工作进程,安装说明:http://support.microsoft.com/?id=322350,对于IIS6.0可以在应用程序池的配置上设置自动回收工作线程的时间,我一般都会设在凌晨2点:)

3) 在.NET Framework的配置上,修改machine.config配置文件中的配置节<processModel>的属性“memoryLimit”,这个属性的值默认为“60”,是一个百分比数据,我们需要按照服务器实际的内存数,再根据800M的上限来设置这个值,那么在达到这个阀值时IIS会自动回收进程

4) 在Web应用程序的开发中,必须尽可能的减少对内存使用的浪费,及时释放资源,我想说明的有3点:1、通过代码主动调用Dispose方法进行资源释放,2、对于实体类尽可能复用,不做多余的声明和创建,3、减少Session的使用,缩短Session的有效期,尤其对于大数据对象尽量不要存储在Session中

5) 一个比较通用的办法,在Web应用程序的基类中通过try{}catch{}来主动捕捉OutOfMemoryException异常,发现该异常后直接调用GC.Collect()进行强制垃圾回收。

最后,有很多朋友提到32位系统对于大内存使用方面可以打开3G模式,这个本身没有什么问题,只是根据个人经验,其对单纯Web应用程序的帮助不大,如果Web服务器还有更多的用途当然也建议采用此模式.

希望对大家处理此问题有帮助.

posted on 2008-05-28 11:05 minbear 阅读(2006) 评论(25)  编辑 收藏

评论

#1楼  2008-05-28 11:27 生鱼片      

学习   回复  引用  查看    

#2楼  2008-05-28 11:27 Justin      

谢谢分享心得

btw:欢迎lz加入Debug探索团队   回复  引用  查看    

#3楼  2008-05-28 12:01 James Dai [未注册用户]

主动调用Dispose()方法不如使用using(){}
具体原因参见Effective C#.   回复  引用    

#4楼  2008-05-28 12:08 kerry jiang [未注册用户]

--引用--------------------------------------------------
James Dai: 主动调用Dispose()方法不如使用using(){}
具体原因参见Effective C#.
--------------------------------------------------------
这里讨论的问题当然不是怎么Dispose.   回复  引用    

#5楼  2008-05-28 12:59 o(∩_∩)o [未注册用户]

http://blogs.msdn.com/tess

这里深入得多   回复  引用    

#6楼  2008-05-28 13:03 James Dai [未注册用户]

把基本功打瓷实后再给大家讲东西.   回复  引用    

#7楼  2008-05-28 13:31 overred      

漏了吧?注意安全
dump   回复  引用  查看    

#8楼  2008-05-28 13:39 Goodspeed      

我建议博主看看这本书
http://www.china-pub.com/37008

上面有一章讲得就是OutOfMemoryException的处理。   回复  引用  查看    

#9楼  2008-05-28 14:05 new 维生素C.net()      

你那是出问题了才会oom,遇到这个问题的处理思路去看程序为什么会吃掉这么多内存!
web服务器为什么CPU越多越好?这个问题也跟你说的这个无关,去看Request Executing counter的原理。   回复  引用  查看    

#10楼  2008-05-28 15:48 盛大推广员 [未注册用户]

程序学习的一塌糊涂。失败啊   回复  引用    

#11楼  2008-05-28 16:05 碎蜂      

800M的上限是一个w3wp.exe进程可支配内存的上限,还是所有w3wp.exe进程可支配内存总和的上限?   回复  引用  查看    

#12楼 [楼主] 2008-05-28 16:13 minbear      

@new 维生素C.net()

同意你的处理思路,但对于一些已经成型的项目,代码量很大,吃内存的代码隐藏的会比较深,也都是慢慢积累的内存消耗,长期运行就会出现出现OOM错误,我们现在的处理方案也都是进行排查。

至于CPU,我的意思不是越多越好,我想说内存太大目前效果不明显,还不如加些CPU。   回复  引用  查看    

#13楼 [楼主] 2008-05-28 16:17 minbear      

@James Dai

Effective C#我看过,包括其他一些C#及.NET Framework原理方面的书籍,你说的方案没错,可和我所要讲的内容没啥冲突点,呵呵   回复  引用  查看    

#14楼  2008-05-28 16:40 Jeffrey Zhao      

oom出现后应该动手术,不应该吃药……   回复  引用  查看    

#15楼 [楼主] 2008-05-28 16:57 minbear      

@Jeffrey Zhao

的确是应该动手术,手术的效果要看外科医生的本领了,而这个错误要根治真的很困难,尤其是对于一些比较大的业务系统,几乎都是要全部过滤一遍(这个动作我们研发团队已经做过2次),我们现在的系统已经超过200W行的代码量,平时一般没啥问题,并发量上去后出现OOM的几率就很高。

不是没有方法,只是方法的好坏和执行难度有多大?

  回复  引用  查看    

#16楼  2008-05-28 19:32 airwolf2026      

呃?楼主的都200w行啊?俺的可能还没有1%,都oom了...当时写的时候,认为反正都是内部系统.所以什么东西都没有考虑...   回复  引用  查看    

#17楼  2008-05-28 21:31 BlueMountain      

学习了

不过这个
--------------------------------------------------------------
一个比较通用的办法,在Web应用程序的基类中通过try{}catch{}来主动捕捉OutOfMemoryException异常,发现该异常后直接调用GC.Collect()进行强制垃圾回收。
------------------可以么?   回复  引用  查看    

#18楼  2008-05-29 09:09 阿拉伯顶峰      

俺开发的windows应用程序时也经常报outofmemoryexception,并且是在debug的时候就编译不通过报这异常。重启一下vs2008就ok了。该问题有跟踪价值,订阅了   回复  引用  查看    

#19楼  2008-05-29 17:23 xiongli [未注册用户]

第五步是错误的
CLR在OOM之前会强制GC一次。 GC后还是没有内存才OOM
解决OOM不在配置上,而是应该优化内存使用,找出导致问题的代码   回复  引用    

#20楼 [楼主] 2008-05-29 20:07 minbear      

@xiongli

try{}catch{}来主动捕捉是专门针对OutOfMemoryException进行的,也就是说出现OOM后执行GC.Collect(),经过实践证明可以临时解决该问题,当然这不是一个好方案,只能算是权宜之计,关键还是要对所有的代码进行Review。   回复  引用  查看    

#21楼 [楼主] 2008-05-29 20:08 minbear      

@BlueMountain

可以的,但只是一个简单的救命稻草,不是根本解决之道...   回复  引用  查看    

#22楼  2008-05-29 21:24 Agan@CN      

经常碰到,每次release到staging都会碰到,只能重启iis,这和代码有关吗   回复  引用  查看    

#23楼  2008-05-29 22:52 lixiong      

所谓的临时解决问题,只不过是因为内存分配失败后,没有尝试再次分配而已。如果你在catch block中先调用gc.collect,然后再去重新执行导致问题的代码请求内存,就可以看到是否gc.collect有用了

当发生OOM后,正确的做法是failfast,尽快结束进程。避免由于OOM带来数据损坏等更严重的损失。使用catch去抓OOM,然后尝试恢复,是错误的做法   回复  引用  查看    

#24楼 [楼主] 2008-05-30 07:55 minbear      

@lixiong

唉, 如果知道导致问题的代码就好办了。。。
请问下,你们目前碰到此问题的详细做法是?   回复  引用  查看    

#25楼  2008-05-31 00:07 nicye      

谢谢分享心得   回复  引用  查看    


标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      


相关链接: