资源预览内容
第1页 / 共14页
第2页 / 共14页
第3页 / 共14页
第4页 / 共14页
第5页 / 共14页
第6页 / 共14页
第7页 / 共14页
第8页 / 共14页
第9页 / 共14页
第10页 / 共14页
亲,该文档总共14页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
利用JProfiler对应用服务器内存泄漏问题诊断一例曾胜财 , IBM BCS 部门 I/T 架构师2005 年 9 月在中间件应用服务器的整体调优中,有关于等待队列、执行线程,EJB池以及数据库连接池和 Stateme nt Cache方面的调优,这些都属于系统参数方面的调优,本文主要从另外一个角度,也就 是从应用的角度来解决中间件应用服务器的内存泄露问题,从这个角度来提高系统的稳定性和性能。项目背景问题描述某个大型项目(Use Case用例超过300个),在项目上线后,其Web应用服务器经常宕机。表现 为:1. 应用服务器内存长期不合理占用,内存经常处于高位占用,很难回收到低位;2. 应用服务器极为不稳定,几乎每两天重新启动一次,有时甚至每天重新启动一次;3. 应用服务器经常做Full GC(Garbage Collection),而且时间很长,大约需要30-40秒,应用服 务器在做Full GC的时候是不响应客户的交易请求的,非常影响系统性能。Web 应用服务器的物理部署一台Unix服务器(4CPU,8G Memory)来部署本Web应用程序;Web应用程序部署在中 间件应用服务器上;部署了一个节点(Node),只配置一个应用服务器实例(Instanee),没有做 Cluster 部署。Web应用服务器启动脚本中的内存参数MEM_ARGS = -XX:MaxPe rmSize=128m -XX:MaxNewSize = 512m -Xms3096m -Xmx3096m -XX:+PrintGCDetails -Xlogge:./inwebapp1/gc.$可以看出目前生产系统中Web应用服务器的内存分配为3G Memory。Web应用服务器的重要部署参数参数名称参数值参数解释kern el.default(Th read Count)120执行线程数目,是并发处理能力的重要参数Sessi on Timeout240分钟(4小时)HttpSession会话超时分析分析方法内存长期占用并导致系统不稳定一般有两种可能:1. 对象被大量创建而且被缓存,在旧的对象释放前又有大量新的对象被创建使得内存长期高位占用。 表现为:内存不断被消耗、在高位时也很难回归到低位,有大量的对象在不断的创建,经过 很长时间后又被回收。例如:在 HttpSession 中保存了大量的分页查询数据,而 HttpSession 的会话超时时间设置过长(例如: 1 天),那么在旧的对象释放前又有大量新的对象在第二天产生。 解决办法:对共享的对象可以采用池机制进行缓存,避免各自创建;缓存的临时对象应该及 时释放;另一种办法是扩大系统的内存容量。2. 另一种情况就是内存泄漏问题 表现为:内存回收低位点不断升高(以每次内存回收的最低点连成一条直线,那么它是一条 上升线);内存回收的频率也越来越高,内存占用也越来越高,最终出现Out of Mem ory Exceptio n的系统异常。 解决办法:定位那些有内存泄漏的类或对象并修改完善这些类以避免内存泄漏。方法是:经 过一段时间的测试、监控,如果某个类的对象数目屡创新高,即使在JVM Full GC后仍然数目降 不下来,这些对象基本上是属于内存泄漏的对象了。问题定位这里请看5月份Web应用服务器的内存回收图形:注意:5月18日早上10点重新启动了 Web服务器,5月20日早上又重新启动了 Web服务器。 在 Web 应用重要部署参数中,我们知道: Session 的超时时间为 4 个小时,我们在监控平 台也观测到:在18日晚上10点左右所有的会话都过期了,从图形一中也能看出 18日晚上确实 系统的内存有回收到40%(就象股票的高位跳水); 从图形一(5月18日)中我们也能看到Full GC回收后的内存占用率走势(红色曲线), 上午基本平滑上升到20%(内存占用率),中午开始上升到 30%,下午上升到40% 从图形二(5月19日)中我们也能看到Full GC回收后的内存占用率走势(红色曲线), 上午又上升到了 60%,到下午上升到了 70%。 从黄色曲线(GC花费的时间,以秒为单位),Full GC的频率也在增快,时间耗费也越来 越长,在图形一中基本高位在20秒左右,到19日基本都是30-40秒之间了。图形一 5月 18日图二*mtnjr 7c匚 la ter - used memory 匚 :=t time通过上述分析,我们基本定位到了 Web应用服务器的内存在高位长期占用的原因了:是内存泄露! 并且正是由于这个原因导致系统不稳定、响应客户请求越来越慢的。解决方法 方法如下: 我们从图形二中发现,在8.95(将近9点钟)到9.66 (将近9点40)期间有几次Full GC, 但是有内存泄漏,从占用率40%上升到50%左右,泄漏了大约10%的内存,约300M; 我们在自己搭建的 Web 应用服务器平台(应用软件版本和生产版本一致)做这一阶段相同 的查询交易;表明对同一个黑盒(Web应用)施加同样的刺激(相同的操作过程和查询交易)以 期重现现象; 我们使用Jprofiler工具对Web应用服务器的内存进行实时监控; 做完这些交易后,用户退出系统,并等待Web应用服务器的HttpSession超时(我们这里 设置为15分钟); 我们对Web应用服务器做了两次强制性的内存回收操作。发现如下:图三如图三所示,内存经过HttpSession超时后,并强制gc后,仍然有大量的对象没有释放。例如: gov.gdlt.taxcore.comm.security.MenuNode,仍然有 807 个实例没有释放。我们继续追溯发现,这些MenuNode首先存放在一个ArrayList对象中,然后发现这个ArrayList 对象又是存放在WHsessionAttrVO对象的Map中,WHsessionAttrVO对象又是存放在 ExternalSessionManager 的 staic Map 中(名称为 sessionMap),如图四所示。图四我们发现 gov.gdlt.taxcore.taxevent.xtgl.comm.WHsessionAttrVO 中保存了 EJBSessionId 信息(登录用户的唯一标志,由用户id+登录时间戳组成,每天都不同)和一个HashMap,这个 HashMap 中的内容有: ArrayList:内有 MenuTreeNodes(菜单树节点) HashMap:内有操作人员代码信息 CurrentVersion: 当前版本号 Curren tTime:当前系统时间WHsessionAttrVO 这个对象的最终存放在 ExternalSessionManager 的 static Map sessionMap 中,由于 ExternalSessionManager 是一个全局的单实例,不会释放,所以它的成员变量 sessionMap中的数据也不会释放,而Map中的Key值为EJBSessionld,每天登录的用户EJBSessionld都不同,就造成了每天的登录信息(包括菜单信息)都保存在sessionMap中不会被 释放,最终造成了内存的泄漏。图五如上图所示:WHsessionAttrsVO对象中除了有一个String对象(内容是EJBSessionld),还有 一个 HashMap 对象。图六星 jsrva. krtil. H?i3hMpSEnl!ry 挤jHwa.ulilEntry3qh第 j 的氯 util. Hci&hMapl Enn y $七 java, nt il. HaehMsil Enci yr j耐札 uiii H:?shM.?rlEnti +事 J wa.t&ng. Siring 晤Q meTreeNDdefi rjivA utit l-lFihM:Fip +jyv.util.sjKiyU;1SijME.Izin日.呂陆話均 c jsydrnlnl 如上图所示,这个 HashMap 中的内容主要有 menuTreeNodes 为 key,value 为 ArrayList 的对 象和以 czrydminfo 为 key,value 为 HashMap 对象的数据。图七IJj.iibl.HJlhM4p$nhrj pl E ntry :1b dav.fldre.l4!t .-cfrirrk f et-uilcy Mtqh冲dltt4黑划MEi币竹宾url甲.*iiLiHCi血vIH.HiJhMipSCfvtiy :,jdvd utiS.HjihM ipJErrtry _西 jjvd.Eang.Sbing:住 i atimTrtNiitr O1/如上图所示:menuTreeNodes为key, value为ArrayList对象中包含的对象有许多的MenuNode 对象,封装的都是用户的菜单节点。图八如上图所示,最顶层(Root)的初始对象为一个ExternalSessionManager对象,其中的一个成员 变量为static (静态的),名称为:sessionMap,这个对象是singleton方式的,全局只有一个。初步估量我们从图形一和图形二中可以看出,每天应用服务器损失大约 40%的内存,大约 1G 左右。从图形四可以看出,当前用户(Id = 24400001129)有807个菜单项(每个菜单项为一个MenuNode 对象实例,图形四中的这个实例的size为592 Byte),这些菜单数据和用户基本登录信息(czrydmlnfo HashMap)也都存放在 WHsessionAttrVO 对象中,当前这个 WHsessionAttrVO 对象的 size 为 457K。我们做如下估算:假设平均每天有 4 千人(估计值,这个数值仅仅是 5 月 19 日峰值的 1/2 左右)登录系统(有重复 登录的现象,例如:上午登录一次,中午退出系统,下午登录一次),以平均每人占用200K(估计 值,是用户id = 24400001129的Size的1/2左右)来计算,一天泄漏的内存约800M,比较符 合目前内存泄漏的情况。当然,这种估计仍然需要经过实践的检验,方法是:当这次发现的内存泄漏 问题解决后看系统是否还有其它内存泄漏问题。十回页首方案ExternalSessionManager 类是当初某某软件商设计的用来解决 Web 服务器负载均衡的模块,这 个类主要用来保存客户的基本登录信息(包括会话的EJBSessionld),以维护多个Web服务器之 间的会话信息一致。改进方案有两种:从架构设计方面改进实现 Web 层的负载均衡有很多标准的实现方式。例如:采用负载均衡设备(硬件或软件)来实现。如果采用新的 Web 层的负载均衡方式,那么就可以去掉 ExternalSessionManager 这个类了。 从应用实现方面改进保留当前的 Web 层的负载均衡设计机制,仅仅从应用实现方面解决内存泄漏问题,首先菜单信息 不应该保存在 ExternalSessionManager 中。其次,增加对 ExternalSessionManager 类中用 户会话登录信息的清除,有几种方式可以选择:被动方式,当 HttpSession 会话超时(或过期)被
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号