- 如何充分利用高性能服务器(比如:内存16G)
- 一般的思路是调大堆内存(12G) 但是同时会引起几个问题
- 年轻代GC和老年代GC的时间就会很长,严重的10多s,这样会导致系统不定时的卡顿(GC的stop the world),用户不能操作。
- 当发生堆溢出时,无法dump堆 一般快照文件达到十几G,即使dump下来,也很难分析
- 解决:
- 建立逻辑集群
- 在一台机器上,开启多个服务器,修改端口号,每个服务器分配2G内存,然后前端使用nginx均衡分发
- 不建立集群 将full GC 调至最低,最好可以一天执行一次,然后在午夜手动触发。
- 建立逻辑集群
- 一般的思路是调大堆内存(12G) 但是同时会引起几个问题
- 线上老年代一直在慢速增长(真实线上问题) 由于是同事的系统的问题,在此只能尽量用文字描述,不足之处,请读者谅解。
- 起源:内存堆使用率超过80%后报警
- 处理:
- 先通过jinfo 查看当前虚拟机配置 发现是由虚拟机自动动态调节老年代新生代大小比例。GC策略使用的是Paraller Scavenge 以系统吞吐量优先的多线程垃圾回收器。(刚开始觉得这种配置不合理,一般在面向用户时使用并发CMS收集器,平缓GC,后来发现由于是专门用来跑work的服务器,这种配置也是合适的)
- 通过jstat -gcutil PID 1000 每1秒打印堆使用情况日志 发现在一次young GC后老年代增长0.16% 年轻代的大部分空间也被回收 于是就想要知道到哪些对象晋升到老年代
- 通过jmap dump一次GC前后的两份快照
- 通过jvisual VM 分析大对象 发现晋升的对象只有两个 都是netty对象。从快照看一切正常。 (一般问题到这就能看出来)
- 后来发现是由于虚拟机动态调节策略,而且是以吞吐量为优先(以空间换时间,以减小新生代大小从而降低新生代回收时间,保证吞吐率)的垃圾回收策略,导致新生代大小特别小(在报警时存活区大小只有2M),部分对象就会直接进入老年代。
- 将动态调节修改为指定新生代大小 将垃圾回收策略改为ParNew策略 程序回复正常。
以上内容,欢迎拍砖!