Spring Boot 如何通过JVM 调优,预防触发OOM-Killer机制

Java
421
0
0
2022-10-27
标签   SpringBoot

img

导读:手上有一个测试服务器,内存是8G,最近开始搭起微服务的软件架构,单个Spring Boot 服务内存占用有点大,比如一个RocketMq的消费者服务(单独运行的服务),启动占用了 500M 内存,导致我后面想运行其他服务,内存不够,触发了 Linux 的 OOM - Killer 机制

Linux杀死了我们的进程,但 nohup.out 没有记录任何东西,我们的linux发生的都在记录/var/log下,通过下面命令查看被杀死进程信息

dmesg | egrep -i -B100 'killed process

img

最近内存的确有点吃紧,上面只需要关注第二个 anno-rss 实际占用内存(被Kill前),现在有两个方向一个是不做微服务,第二个是给Spring Boot 项目瘦身√

下面以我们的RocketMQ消费者为例,看看没有优化前直接启动占用多少实际内存

# 启动命令
nohup java -jar /usr/****/jar/consumer-rocketmq/target/consumer-rocketmq-2.0.1.RELEASE.jar &

# 获取进程号23371的pid和启动参数,rss实际占用内存(kB),vsz允许最大内存,
ps -e -o 'pid,args,rss,vsz' | grep 23371

23371 java -jar /usr/testAPP/jar/ 681692 4689288 16:13

上面是启动一段时间后,占用内存在665左右,这就是一个RocketMQ消费者服务,我们修改下JVM运行参数

# 启动命令
# 修改JVM运行参数
nohup java -jar -XX:NewSize=128m -XX:MaxNewSize=128m -XX:SurvivorRatio=8 -Xms128m     -Xmx128m  /usr/testAPP/jar/consumer-rocketmq/target/consumer-rocketmq-2. 0.1.RELEASE.jar &

# 获取进程号
ps -ef | grep consumer-rocketmq-2.0.1.RELEASE.jar | grep -v grep | awk '{ print $2 }'

得到pid后获取进程的相关信息,可以从下图看到实际占用内存的确小了

img

那么还能不能瘦呢?

我们可以看看Java进程的Heap信息 jmap -heap pid

Parallel GC with 2 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 268435456 (256.0MB)
   NewSize                  = 134217728 (128.0MB)
   MaxNewSize               = 134217728 (128.0MB)
   OldSize                  = 134217728 (128.0MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 134217728 (128.0MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 134217728 (128.0MB)
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 110100480 (105.0MB)
   used     = 83353872 (79.49244689941406MB)
   free     = 26746608 (25.507553100585938MB)
   75.70709228515625% used
From Space:
   capacity = 12058624 (11.5MB)
   used     = 1441792 (1.375MB)
   free     = 10616832 (10.125MB)
   11.956521739130435% used
To Space:
   capacity = 12058624 (11.5MB)
   used     = 0 (0.0MB)
   free     = 12058624 (11.5MB)
   0.0% used
PS Old Generation
   capacity = 134217728 (128.0MB)
   used     = 16486440 (15.722694396972656MB)
   free     = 117731288 (112.27730560302734MB)
   12.283354997634888% used

发现新生代+老年代一共才占用42MB,那另外200MB是怎么来的?

使用Jstack 追踪下进程Java堆栈,计算后我们有37个线程,我们可以缩小堆栈默认大小,默认是1MB,添加-Xss 512k,缩小一半试试

nohup java -jar -XX:NewSize=128m -XX:MaxNewSize=128m -XX:SurvivorRatio=8 -Xms128m -Xmx128m -Xss256k /usr/testAPP/jar/consumer-rocketmq/target/consumer-rocketmq-2.    0.1.RELEASE.jar &

新的大小,并没有太明显的优化

img

目前就做到这里,毕竟内部嵌入了Tomcat,占用 200M 也可以理解(Java就是消耗资源,相比以前Oracle时期已经好很多了),由于工作原因,就不做更深的实践了,有时间再做,有兴趣的小伙伴可以根据我提供的参考资料去实践

- END -