[经验分享]压力测试中因为Session而导致的OutOfMemoryException内存溢出问题及解决
这几天开发了一个Web站点,主要用于给其它站点做接口数据返回,在提交压力测试时,经常内存增长到1G后,溢出了,因为程序本身确实会加载不少缓存数据,而服务器本身是Windows2003 32位的操作系统,最大只支持2g内存,通过参考页面:http://support.microsoft.com/?kbID=810371,在boot.ini里增加启动参数:/3gb /Userva=3030
从而让程序可以使用到3G内存,然后继续提交压力测试
结果测试时,内存依旧持续增长,增长到2G后,又内存溢出了,至此,怀疑程序有内存泄露
找了一个win7版本的任务管理器,拷贝到服务器上,在内存达到2G时,创建了一个w3wp进程的dump(下面的创建转储文件)
抓下来dump文件后,在本地用Windbg加载sos.dll进行分析,通过!dumpheap -stat命令,发现占用内存最大的3个对象是:
6611b1b0 5027584 241324032 System.Web.SessionState.InProcSessionState
66149064 5027602 361987344 System.Web.Caching.CacheEntry
79330b24 5575562 378271928 System.String
各占用了241M、361M、378M,因为事先知道String占用这么大是正常的,所以要去分析另外2个对象,在Windbg里通过: !dumpheap -type System.Web.Caching.CacheEntry 命令,查看所有具体的CacheEntry地址等信息,这个会很多,数据一出来,马上按Ctrl+Break,数据大致如下
0:000> !dumpheap -type System.Web.Caching.CacheEntry
------------------------------
Heap 0
Address MT Size
106837a8 044b3ac4 72
107b0de0 044b3ac4 72
107b1e74 044b3ac4 72
107bdc14 044b3ac4 72
107bdef8 044b3ac4 72
107c1290 044b3ac4 72
107c1370 044b3ac4 72
107c142c 044b3ac4 72
107c20f8 044b3ac4 72
先找第一个地址分析:
0:000> !do 106837a8
Name: System.Web.Caching.CacheEntry
MethodTable: 044b3ac4
EEClass: 044aac24
Size: 72(0x48) bytes
(C:\WINDOWS\assembly\GAC_32\System.Web\2.0.0.0__b03f5f7f11d50a3a\System.Web.dll)
Fields:
MT Field Offset Type VT Attr Value Name
02469134 400140c 4 System.String 0 instance 10683740 _key
030fb350 400140d c System.Byte 1 instance 16 _bits
03154d18 400140e 8 System.Int32 1 instance -1350406618 _hashCode
02466d54 4001415 10 System.Object 0 instance 10683794 _value
0321ab48 4001416 1c System.DateTime 1 instance 106837c4 _utcCreated
0321ab48 4001417 24 System.DateTime 1 instance 106837cc _utcExpires
0321dda4 4001418 2c System.TimeSpan 1 instance 106837d4 _slidingExpiration
030fb350 4001419 d System.Byte 1 instance 4294967295 _expiresBucket
044b3964 400141a 34 ...g.ExpiresEntryRef 1 instance 106837dc _expiresEntryRef
030fb350 400141b e System.Byte 1 instance 2 _usageBucket
044b3a6c 400141c 38 ...ing.UsageEntryRef 1 instance 106837e0 _usageEntryRef
0321ab48 400141d 3c System.DateTime 1 instance 106837e4 _utcLastUpdate
044b32f0 400141e 14 ...g.CacheDependency 0 instance 00000000 _dependency
02466d54 400141f 18 System.Object 0 instance 00000000 _onRemovedTargets
0321ab48 4001412 1e4 System.DateTime 1 shared static NoAbsoluteExpiration
>> Domain:Value 000dd050:NotInit 0012ad78:1616ba94 <<
0321dda4 4001413 1e8 System.TimeSpan 1 shared static NoSlidingExpiration
>> Domain:Value 000dd050:NotInit 0012ad78:1616baa4 <<
0321dda4 4001414 1ec System.TimeSpan 1 shared static OneYear
>> Domain:Value 000dd050:NotInit 0012ad78:1616bab4 <<
然后再看_key的值
0:000> !do 10683740
Name: System.String
MethodTable: 02469134
EEClass: 02a42780
Size: 82(0x52) bytes
(C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
String: f2029612887/recommendservice.svc
再看_value的值
0:000> !do 10683794
Name: System.Web.Configuration.MapPathCacheInfo
MethodTable: 047026d0
EEClass: 04776bb8
Size: 20(0x14) bytes
(C:\WINDOWS\assembly\GAC_32\System.Web\2.0.0.0__b03f5f7f11d50a3a\System.Web.dll)
Fields:
MT Field Offset Type VT Attr Value Name
02469134 40018d4 4 System.String 0 instance 10683dfc MapPathResult
0320bdb8 40018d5 c System.Boolean 1 instance 1 Evaluated
030f0498 40018d6 8 System.Exception 0 instance 00000000 CachedException
0:000> !do 10683dfc
Name: System.String
MethodTable: 02469134
EEClass: 02a42780
Size: 88(0x58) bytes
(C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
String: E:\wwwroot\Web\recommendservice.svc
看来第一个CacheEntry保存的是一个虚拟路径和物理路径的对应关系,接着分析下一个CacheEntry的数据
如此类推发现
!do 107b0de0得到的也是一个文件路径缓存数据
!do 107b1e74得到System.Web.Security.FileSecurityDescriptorWrapper,看起来像是文件安全配置说明
!do 107bdc14得到一个key为jbj1dejrlaibnmfyrnqldwk45的System.Web.SessionState.InProcSessionState对象
!do 107bdef8得到一个key为jfd2qmyinc5sgpk55b2nks4rw的System.Web.SessionState.InProcSessionState对象
107c1290、107c1370、107c142c、107c20f8等大部分CacheEntry保存的都是InProcSessionState对象
由此可见,占用内存第二大的,都引用了占用内存第三大的InProcSessionState对象,
而Asp.net的Session默认是保持20分钟,压力测试时,在20分钟内创建的Session全部被保持,无法被GC回收,从而内存不断增长,最终导致内存溢出了
马上咨询压力测试人员,果然是压力测试发起了所有连接,都是新连接,
通过修改压力测试方案,复用创建的连接,而不是发起 新连接,果然内存占用在400M左右,增长也极其缓慢
最后的修改方案,因为此站点仅作为接口使用,不会使用到Session,直接在Web.config增加配置:<sessionState mode="Off"></sessionState>
关闭Session,再进行压力测试,内存基本不会增长
原文链接
[解决办法]
谢谢分享
[解决办法]
因为此站点仅作为接口使用,不会使用到Session,直接在Web.config增加配置:<sessionState mode="Off"></sessionState>
这是提高网站性能的常用方法
即使使用Session,如果不进行写入,设置成ReadOnly也是必要的,
很多情况下,处理程序有很多事件处理和解析aspx、ViewState的过程,都需要时间和资源进行处理和解析,尽量使用ashx也是好的做法
[解决办法]
这个 才是经验之谈 谢谢分享
[解决办法]
谢谢分享...
[解决办法]
谢谢分享
[解决办法]
谢谢分享...
[解决办法]
谢谢分享
[解决办法]
我就希望多看到这样的文章。
谢谢楼主分享了~~
[解决办法]
我个人看法 session导致内存溢出,这都是代码问题。
可以 用异步或者是其他技术 代替 存储服务器内存 这种代码。
哪个溢出问题就不存在了。
[解决办法]
挤进前15!!!
[解决办法]
支持一下 推荐一下
[解决办法]
谢谢分享
[解决办法]
谢谢楼主分享
[解决办法]
谢谢楼主分享
[解决办法]
快乐分享
[解决办法]
楼主好人啊,谢谢分享
[解决办法]
虽然不懂 ,可能也用不到,但是学习了
[解决办法]
谢谢楼主分享。。。。
[解决办法]
谢谢分享!!!!
------解决方案--------------------
谢谢分享...
[解决办法]
学习一点 挺好的
[解决办法]
在实际应用中,这个漏洞对应的只是个拒绝服务攻击吧,加个防火墙就行了么,用浏览器的那会产生那么多session啊。
[解决办法]
感谢分享
[解决办法]
多谢分享
[解决办法]
好经验!
[解决办法]
>>> 复用创建的连接
这个对于WebService、WCF 怎么实现啊?难道是同一个客户端代理类对象?
[解决办法]
谢谢楼主分享
不过,我记得Windows2003 32位标准版应该是支持4G内存的吧
[解决办法]
哈哈,又知道了点知识
[解决办法]
谢谢分享 表示来
[解决办法]
谢谢分享!!!!
[解决办法]
谢谢 分享 ,受用啦
[解决办法]
学习了,谢谢。
[解决办法]
好帖子 学习了 谢谢楼主分享
[解决办法]
或许你的压力测试没有以业务逻辑测试为基础。你的压力测试(并且关闭session)的同时,可以保证每一次访问此网站其业务逻辑操作结果都正常吗?
如果原来的程序本身就需要session集合,那么你关闭session将是灾难性的。此时还是要求重写此程序,而不是简单地关闭session。假设一个程序偶尔才在session集合里边保存几十个字节,而不是滥用session集合,那么开启session也没有什么问题。
[解决办法]
支持一下!
[解决办法]
LZ的方法在解决内存溢出的时候确实可行,如果程序代码里面要用到session里的值呢。顶LZ,期待其他更好的解决方案。
[解决办法]
谢谢分享
Windows2003 32位的操作系统,支持的最大内存超过2G
[解决办法]
学习了,谢谢。