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

    Linux杀死了我们的进程,但 nohup.out 没有记录任何东西,我们的linux发生的都在记录/var/log下,通过下面命令查看被杀死进程信息
    dmesg | egrep -i -B100 'killed process
    640 (3).webp
    最近内存的确有点吃紧,上面只需要关注第二个 _anno-rss_ 实际占用内存(被Kill前),现在有两个方向一个是不做微服务,第二个是给Spring Boot 项目瘦身√
    下面以我们的RocketMQ消费者为例,看看没有优化前直接启动占用多少实际内存

    1. # 启动命令
    2. nohup java -jar /usr/****/jar/consumer-rocketmq/target/consumer-rocketmq-2.0.1.RELEASE.jar &
    3. # 获取进程号23371pid和启动参数,rss实际占用内存(kB),vsz允许最大内存,
    4. ps -e -o 'pid,args,rss,vsz' | grep 23371
    5. 23371 java -jar /usr/testAPP/jar/ 681692 4689288 16:13

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

    1. # 启动命令
    2. # 修改JVM运行参数
    3. 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 &
    4. # 获取进程号
    5. ps -ef | grep consumer-rocketmq-2.0.1.RELEASE.jar | grep -v grep | awk '{ print $2 }'

    得到pid后获取进程的相关信息,可以从下图看到实际占用内存的确小了
    640 (2).webp
    那么还能不能瘦呢?
    我们可以看看Java进程的Heap信息
    jmap -heap pid

    1. Parallel GC with 2 thread(s)
    2. Heap Configuration:
    3. MinHeapFreeRatio = 0
    4. MaxHeapFreeRatio = 100
    5. MaxHeapSize = 268435456 (256.0MB)
    6. NewSize = 134217728 (128.0MB)
    7. MaxNewSize = 134217728 (128.0MB)
    8. OldSize = 134217728 (128.0MB)
    9. NewRatio = 2
    10. SurvivorRatio = 8
    11. MetaspaceSize = 134217728 (128.0MB)
    12. CompressedClassSpaceSize = 1073741824 (1024.0MB)
    13. MaxMetaspaceSize = 134217728 (128.0MB)
    14. G1HeapRegionSize = 0 (0.0MB)
    15. Heap Usage:
    16. PS Young Generation
    17. Eden Space:
    18. capacity = 110100480 (105.0MB)
    19. used = 83353872 (79.49244689941406MB)
    20. free = 26746608 (25.507553100585938MB)
    21. 75.70709228515625% used
    22. From Space:
    23. capacity = 12058624 (11.5MB)
    24. used = 1441792 (1.375MB)
    25. free = 10616832 (10.125MB)
    26. 11.956521739130435% used
    27. To Space:
    28. capacity = 12058624 (11.5MB)
    29. used = 0 (0.0MB)
    30. free = 12058624 (11.5MB)
    31. 0.0% used
    32. PS Old Generation
    33. capacity = 134217728 (128.0MB)
    34. used = 16486440 (15.722694396972656MB)
    35. free = 117731288 (112.27730560302734MB)
    36. 12.283354997634888% used

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

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

    1. 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 &

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