让人大跌眼镜的jvm优化反面案例
1、升级硬件
1.1、背景
一个在线的文档操作系统,当前配置是2c4g。随着业务量慢慢上升,服务呈现出周期性的卡顿。明显是出现了规律的fullgc导致的。
1.2、反面操作
既然是fullgc,那么自然想到的是内存不够用。进而升级硬件。然后把对应的jvm参数提高。实际的操作中是将服务器升级到了8c16g。然后把jvm的参数同比增大了4倍。
结果竟然是比之前的效果更差。卡顿得更明显。
高大上竟然比不上老破小,是不是感觉匪夷所思?
1.3、案例分析
- 升级了内存的大小,只是延迟了jvm回收内存的上限,但是带来了另一个问题,每次fullgc的内存是之前的4倍。gc的时间也差不多是之前的4倍了。所以才感觉到了卡顿得更明显。
1.4、正确的解决方案
- 升级服务器硬件
- 在服务器上部署多个应用实例,然后通过nginx负载均衡的方式进行访问
- 单台的机器的jdk由原来的64位降至32位,在低内存配置的情况下,64位jdk由于指针膨胀、系统补白的缘故,系统会比32位差。
32位jdk的集群往往是优于一台超级计算机的。
1.5、集群的负面影响
- 共享资源的竞争。数据库连接数、io(每个实例都有自己的连接池)
- 内存的多份拷贝。(一些共享变量,会在每个实例中都存储一份。这个可以使用分布式缓存来解决)
2、扩大堆内存解决内存溢出
2.1、背景
系统频繁的出现内存溢出。
2.2、反面操作
不升级硬件,直接通过jvm设置来扩大堆内存。
结果是内存溢出更明显,更诡异的是发现内存溢出的时候,年轻代和老年代的内存占用很少。
2.3、根因分析
- 根因是直接内存不够导致的内存溢出,系统中使用了nio,消耗的是direct memory
- 对于固定的一台机器,总内存的大小是确定了,扩大了堆内存,留给直接内存的就变小了
2.4、解决办法
- 减小jvm参数中的堆内存的参数的大小
3、总结
- 不是硬件越好性能越好,这个要看怎么用。低配置的集群往往是由于一台超级计算机
- 不是内存溢出就无脑升级内存大小,要看看是哪个区的内存溢出。了解一下内存的分配机制和回收策略
正文到此结束