#总结自《深入理解JAVA虚拟机》,仅供自己参考复习。
5.2.1大内存硬件上的程序部署策略
1、应用场景
15万PV/日左右的在线文档类型网站。服务器硬件:四路志强处理器、16GB物理内存,操作系统64位CentOS 5.4,Resin作为Web服务器。软件版本:JDK 5,一个虚拟机实例,使用-Xmx和-Xms参数将java堆固定在12GB。
2、出现问题
服务器运行效果不理想,网站经常不定期出现长时间失去响应。监控服务器运行状况后,发现网站失去响应是由垃圾收集产生的停顿。原来1.5G也不会出现很长的停顿,这是由于程序当中会将文档提取到内存,导致内存序列化产生大对象,未经Minor GC直接进入老年代,所以会导致java堆用尽,从而进行Full GC。
3、单体大内存硬件部署方式
(1)通过一个单独的Java虚拟机实例来管理大量堆内存。
(2)同时java虚拟机逻辑集群来利用硬件资源。
4、解决方案:
对于用户交互性强、停顿时间敏感、内存较大系统
(1)可以使用ZGC、Shenandoah类控制延迟的垃圾收集器,使用CMS、G1垃圾收集器。
(2)控制Full GC率,通过保证会话级和全局级的长生命对象相对较少。编码解决。
(3)使用建立JVM逻辑集群的方式来解决。前端搭建一个负载均衡器,以反向代理的方式来分配访问请求。
实际解决方案:(1)建立5个32位JDK的逻辑集群,每个进程按2GB(堆固定为1.5GB)。(2)另外建立负载均衡代理。(3)改用CMS收集器,提高响应速度,因该场景对处理器敏感低。
5.2.2集群间同步导致的内存溢出
1、应用场景
一个基于B/S的MIS系统,硬件为两台双路处理器、8GB内存的HP小型机,应用中间件是WebLogic 9.2。
2、问题
读写频繁导致竞争大,因此加入JBossCache构建全局缓存。服务运行一段时间后,会发生多次内存溢出。
3、分析错误:(1)代码中不规范,不常用代码路径中产生内存泄漏?(2)JBossCache中的缺陷。(3)MIS的服务端中有一个负责安全校验的全局过滤器,这个过滤器导致集群间网络交互频繁。网络不佳,导致重发数据在内存中堆积,最终溢出。
4、解决方案
替换非集中式的JBossCache集群缓存
5.2.3堆外内存导致的溢出错误
1、应用场景
基于B/S的电子考试系统,选用CometD1.1.1作为服务端推送框架,服务器是Jetty7.1.4,硬件是一台PC。
2、问题
时不时发生服务端内存溢出异常。
3、分析错误
直接内存的溢出直接内存没有主动通知的能力,只能等老年代满了之后的Full GC顺便回收直接内存。本案例中的CometD 1.1.1框架,正好有大量的NIO操作需要使用直接内存。