内存管理调优案例

1.高性能硬件上的程序部署策略

     例如:一个15万PV/天左右(PV:网站的浏览量)的在线文档类型网站最近更换了硬件系统,新的硬件为4个CPU、16GB物理内存,操作系统为64位CentOS 5.4,Resin作为Web服务器,整个服务器暂时没有部署别的应用,所有硬件资源都可以提供给这访问量并不算太大的网站使用。管理员为了尽量利用硬件资源选用了64位的JDK 1.5,并通过 -Xmx和- Xms参数将java堆固定在12GB。使用一段时间后发现使用效果并不理想,网站经常不定期出现长时间失去响应的情况。

  监控服务器运行状况后发现网站失去响应是由GC停顿导致的,虚拟机运行在server模式,默认使用吞吐量优先收集器,回收12GB的堆,一次Full GC的停顿时间高达14秒。并且由于程序设计的关系,访问文档时要把文档从磁盘提取到内存中,导致内存中出现很多由文档序列化产生的大对象,这些大对象很多都进入了老年代,没有在Minor GC中清理掉。这种情况下即使有12GB的怼,内存也很快被消耗殆尽,由此导致每隔十几分钟出现十几秒的停顿。

现阶段使用:若干个32位虚拟机建立逻辑集群来利用硬件资源,具体做法是在一台物理机器上启动多个应用服务器进程,每个服务器进程分配不同端口,然后再前端搭建一个负载均衡器,以反向代理的方式来分配访问请求。

2.集群间同步导致的内存溢出

  例如,有一个基于B/S的MIS系统,硬件为两台2个CPU、8GB内存的HP小型机,服务器是WebLogic 9.2,每台机器启动了3个WebLogic实例,构成一个6个节点的亲合式集群。由于是亲合式集群,节点之间没有进行Session同步,但是有一些需求要实现部分数据在各个节点间共享。开始这些数据存放在数据库中,但由于读写频繁竞争很激烈,性能影响较大,后面使用JBossCache构建了一个全局缓存。全局缓存启用后,服务正常使用了一段较长的时间,但最近却不定期地出现了多次的内存溢出问题。

  在内存溢出异常不出现的时候,服务内存回收状况一直正常,每次内存回收后都能恢复到一个稳定的可用空间,开始怀疑是程序某些不常用的代码路径中存在内存泄漏,但管理员反映最近程序并未更新、升级过,也没有进行什么特别操作。只好让服务带着-XX:+HeapDumpOnOfMemeoryError参数运行了一段时间。在最近一次溢出之后,管理员发回了heapdump文件,发现里面存在着大量的 org.jgrops.protocols.pbcast,NakAck对象。

 JBossCache是基于自家的JGroups进行集群间的数据通信,JGroups使用协议栈的方式来实现收发数据包的各种所需特性自由组合,数据包接收和发送时要经过每层协议栈的up()和down()方法,其中的NAKACK栈用于保障各个包的有效顺序及重发。

  由于信息有传输失败需要重发的可能性,在确认所有注册在GMS的节点都收到正确的信息前,发送的信息必须在内训中保留。而此MIS的服务端中有一个负责安全校验的全局Filter,每当接收到请求时,均会更新一次最后操作时间,并且将这个时间同步到所有的就诶点去,使得一个用户在一段时间内不能在多台机器上登录。在服务使用过程中,往往一个页面会产生数次乃至数十次的请求,因此这个过滤器导致集群各个节点之间网络交互非常频繁。当网络情况不能满足传输要求时,重发数据在内存中不断堆积,很快就产生了内存溢出。

   总结就是:设计中,应当多读操作,因为数据在本地内存中有一份副本,读取的 动作不会耗费多少资源,但不应当有过于频繁的写操作,那样会带来很大的网络同步的开销。

3.堆外内存导致的溢出错误

  例如:一个学校的小型项目:基于B/S的电子考试系统,为了实现客户端能实时地从服务器端接收考试数据,系统使用了逆向AJAX技术

 

原文地址:https://www.cnblogs.com/woniufei/p/9475819.html