贝网博客

我的分类
流水记事
源码下载
Asp.net
其它
数据库
Javascript
.Net技术
我的相册
友情链接
博客园
CSDN博客
Start0
最新回复
fasdfasdf
[:..
lz这个东西好厉害,我..
哈哈,好照片
不错,以前一直用黄色..
终于找到支持ff的修正..
终于找到支持ff的修正..
新鲜性
看看,试试,好不好使。
好东西一起学习[:img0..
分类 =》.Net技术
压力测试中因为Session而导致的OutOfMemoryException内存溢出问题及解决
发表于:2012-05-03 11:30:25
更新于:2012-07-27 11:00:26

这几天开发了一个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进行分析,
.load C:\WINDOWS\microsoft.net\framework\v2.0.50727\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,再进行压力测试,内存基本不会增长

发表评论
名称(*):
邮箱:
正文:

©2008 Beinet.cn 版权所有