原创

让人大跌眼镜的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、总结

  • 不是硬件越好性能越好,这个要看怎么用。低配置的集群往往是由于一台超级计算机
  • 不是内存溢出就无脑升级内存大小,要看看是哪个区的内存溢出。了解一下内存的分配机制和回收策略
正文到此结束
本文目录