Nacos 服务列表过大导致 OOM 时,优先调整 JVM 堆内存参数(-Xms、-Xmx、-Xmn)并限制元空间大小,适用于物理内存 2GB 以上的服务器,风险边界是堆内存不应超过物理内存的 70%。
先说结论:Nacos 服务列表过大引发 OOM 的核心原因是 JVM 堆内存和元空间配置不当,通过调整启动参数可有效缓解。
- 先定位:确认 OOM 报错类型是堆内存溢出还是元空间溢出
- 先做:调整-Xms、-Xmx、-Xmn 参数,限制 MaxMetaspaceSize
- 再验证:通过 GC 日志和内存监控确认优化效果
命令速用版
在 Nacos 启动脚本 startup.sh 中找到 JAVA_OPT 配置行,添加以下参数:
JAVA_OPT="${JAVA_OPT} -Xms1g -Xmx1g -Xmn512m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m"对于 1 核 2GB 服务器,堆内存建议设置为 512m 到 1g;对于 4 核 8G 服务器,堆内存可设置为 2g 到 4g。
为什么会这样
Nacos 服务列表过大会导致内存中堆积大量服务实例元数据和心跳信息对象。Nacos 作为 Java 应用,内存占用主要分为 JVM 堆内存、元空间、线程栈、直接内存以及 JVM 自身开销,其中堆内存是最大的一块。服务注册与发现需要维护服务实例的元数据、心跳信息等,这些对象生命周期较长,容易进入老年代。配置管理中的配置内容缓存、监听器列表等数据结构会常驻内存。如果 JVM 堆内存设置过大,不仅会挤压其他进程的空间,还可能因为物理内存不足导致频繁的 Swap 交换,严重拖慢系统性能。
分步处理
第一步:确认当前内存配置
查看 Nacos 启动脚本中的 JVM 参数配置,位置在 distribution/bin/startup.sh 文件中。默认情况下,JVM 初始分配的内存由-Xms 指定,默认是物理内存的 1/64;JVM 最大分配的内存由-Xmx 指定,默认是物理内存的 1/4。
第二步:调整堆内存参数
根据服务器物理内存大小设置-Xms 和-Xmx 参数,建议将两者设置为相同值以避免每次垃圾回收完成后 JVM 重新分配内存。堆内存建议设置为物理内存的 50%-70%。例如 8GB 物理内存的服务器,堆内存应设置在 5.6GB 以下。
第三步:调整新生代大小
通过-Xmn 参数调整新生代大小,新生代大小设置为整个堆内存的 1/3 到 1/4 比较合理。增大年轻代后,将会减少年老代大小,此值对系统性能影响较大。
第四步:限制元空间大小
使用-XX:MetaspaceSize 和-XX:MaxMetaspaceSize 设置元空间初始大小以及最大可分配大小。如果不指定元空间的大小,默认情况下元空间最大的大小是系统内存的大小,元空间一直扩大,虚拟机可能会消耗完所有的可用系统内存。建议 MaxMetaspaceSize 不低于 100M。
第五步:限制 NIO 堆外内存
通过参数-XX:MaxDirectMemorySize 限制 NIO 堆外内存的最大值,推荐设置为堆内存的 1/4。Nacos 内存占用涉及 JVM 堆内存、网络 NIO 堆外内存和 Rocksdb 直接内存,其中 JVM 堆内存及 NIO 堆外内存的设置不当往往是导致内存占用过大的主要原因。
怎么验证是否生效
开启垃圾回收日志,通过-XX:+PrintGCDetails 参数详细记录垃圾回收的情况,帮助分析内存占用和释放的情况。使用 VisualVM、JConsole 等工具实时查看堆的使用情况、垃圾回收情况等信息。监控 Nacos 服务的内存使用情况,确认内存占用是否稳定在预期范围内。检查 GC 日志中 Full GC 的频率,如果频繁触发 Full GC 说明元空间或老年代配置可能过小。
常见坑
不要将-Xms 和-Xmx 设置为不同值,这会导致 JVM 在每次 GC 后调整堆的大小,增加性能开销。元空间初始化高水位线设置过低会频繁触发 Full GC,高水位线会被多次调整。对于 64 位的服务端 JVM,默认的-XX:MetaspaceSize 值为 21MB,这就是初始的高水位线,一旦元空间的大小触及这个高水位线,就会触发 Full GC 并会卸载没有用的类。Nacos 1.2.1 版本中存在已知的连接池管理问题,可能导致内存泄漏,建议升级到最新稳定版。关闭不必要的系统属性,在 JVM 启动参数中有时会包含一些不必要的系统属性,这些属性可能会增加内存占用。
常见问题
Nacos 默认 JVM 参数是多少?
默认 JVM_XMS 和 JVM_XMX 均为 2G,JVM_XMN 为 1G,JVM_MS 为 128M,JVM_MMS 为 320M。这些默认值对于小内存服务器可能过于激进。
堆内存设置多大合适?
堆内存建议设置为物理内存的 50%-70%,生产环境最小堆内存不低于 2G。对于 1 核 2GB 服务器,堆内存可设置为 512m 到 1g。
新生代和老年代比例怎么设?
新生代与老年代比例保持 1:2,新生代大小设置为整个堆内存的 1/3 到 1/4 比较合理。Sun 官方推荐配置为整个堆的 3/8。
元空间溢出怎么解决?
通过-XX:MetaspaceSize 和-XX:MaxMetaspaceSize 设置元空间初始大小以及最大可分配大小,建议 MaxMetaspaceSize 不低于 100M,避免类加载问题。
参考来源
- 阿里云帮助中心 - Nacos 内存优化实战:如何用 JVM 参数让 1 核 2G 服务器也能流畅运行
- 阿里云帮助中心 - Nacos 性能调优:JVM 参数配置与内存优化全攻略
- 阿里云帮助中心 - 终极 Nacos JVM 调优指南:从内存管理到性能飙升的实战秘籍
- 阿里云帮助中心 - 调整 JVM 参数解决 Nacos 内存占用过多和 OOM 问题
- 阿里云帮助中心 - nacos 启动 jvm 参数调整解决内存占用过多问题、nacos oom 问题 jvm 参数调整
- 阿里云帮助中心 - 最完整 Nacos 内存 CPU 优化指南:从卡顿到丝滑的实战实践
- 阿里云帮助中心 - nacos 启动内存设置多少好些