通过容器部署nacos集群,nacos启动之后就会OOM,通过排查发现容器的pids_limit限制是1024,把这个值限制调大一倍就可以正常启动,nacos启动会产生这么多的pid是什么原因呢?
Nacos的集群模式需要维护多个节点之间的通信和协调。节点之间需要进行信息交换、状态同步等操作,这可能需要创建额外的线程或进程来处理。特别是在较大规模的集群中,节点之间的通信和协调更加复杂,可能会产生更多的PID。
1、首先确认是否创建过多Nacos-Client实例,使用jmap -histo ${pid} > histo.log命令,将应用中的内存实例对象记录在日志文件中,随后对日志文件进行过滤统计,并记录Nacos-Client的数量。
# Nacos-Client注册中心客户端数量,正常情况下应该不超过3个。
grep "NacosNamingService" histo.log | awk '{print $2,$4}'
# Nacos-Client配置中心客户端数量,正常情况下应该不超过3个。
grep "NacosConfigService" histo.log | awk '{print $2,$4}'
2、如果Nacos-Client实例数量正常,请确认线程数是否符合预期。
使用jstack ${pid} > jstack.log命令,将当前线程信息打印到日志文件中,随后对日志文件进行过滤统计。
# Nacos-Client所使用的线程池数量,其数量不应该超过Nacos-Client数量 * cpu数 * 8。
grep "nacos-grpc-client-executor" jstack.log | wc -l
# Nacos-Client内部事件通知机制所使用的线程池,其总数不应超过5个
grep "nacos.publisher-" jstack.log | wc -l
# Nacos-Client用于断线重连及发送pingpong心跳的线程,其总数不应超过Nacos-Client数量 * 2。
grep "com.alibaba.nacos.client.remote.worker" jstack.log | wc -l
# Nacos-Client注册中心更新缓存所使用的线程池,其总数不应超过NacosNamingService数量 * (cpu数 / 2)。
grep "com.alibaba.nacos.client.naming.updater" jstack.log | wc -l
# Nacos-Client注册中心接收UDP推送数据所使用的线程池,其总数不应超过NacosNamingService数量。
grep "com.alibaba.nacos.naming.push.receiver" jstack.log | wc -l
# Nacos-Client注册中心在断线重连后,补偿非持久化服务数据的线程,其总数不应超过NacosNamingService数量。
grep "com.alibaba.nacos.client.naming.grpc.redo" jstack.log | wc -l
# Nacos-Client配置中心监听配置所使用的线程池,其总数不应超过NacosConfigService数量。
grep "com.alibaba.nacos.client.Worker" jstack.log | wc -l
# Nacos-Client配置中心用于回调监听者Listener的线程池,其总数不应超过NacosConfigService数量 * 5。
grep "nacos.client.config.listener.task" jstack.log | wc -l
如果上述线程数均超过了预期,则原因可能为连续创建Nacos-Client实例,但新创建的Nacos-Client实例替换旧的Nacos-Client实例时未使用shutdown方法关闭线程池,导致旧线程池未被关闭。
——参考链接。
在容器中部署Nacos集群时,Nacos启动时会产生大量的pid(进程标识符)。这是因为在启动Nacos服务时,会创建许多后台进程来支持不同的功能和特性。
Nacos是一个分布式的服务发现和配置管理平台,它提供了动态服务发现、配置管理和服务管理等功能。为了实现这些功能,Nacos在启动时会创建一系列的后台进程,包括但不限于以下几种:
1、服务器进程:负责处理客户端的请求和响应,包括服务发现、配置管理和服务管理等功能。
2、注册进程:负责将服务注册到Nacos服务器,以便其他客户端可以发现和使用这些服务。
3、订阅进程:负责订阅配置文件的变化,并在配置文件更新时更新客户端的配置信息。
4、心跳进程:负责定期向服务器发送心跳包,以保持服务的健康状态。
这些后台进程在Nacos启动时被创建,并在后台运行,以便支持Nacos的各种功能。因此,当你在容器中部署Nacos集群时,每个Nacos节点都会创建相应的后台进程,从而产生大量的pid。
需要注意的是,Nacos在启动时默认会使用1024的pid限制。如果Nacos节点所在的容器环境没有修改这个限制,可能会导致pid耗尽的问题。为了解决这个问题,你可以尝试调整容器的pid限制或者优化Nacos的配置,以减少后台进程的数量。
Nacos 启动产生大量 PID 的原因可能是由于 Java 程序启动时会生成多个子进程,包括主线程、垃圾回收线程、安全线程等等。此外,Nacos 启动过程中还会启动许多其他的工具和服务,这些工具和服务也需要各自的进程来运行。
对于一些大型的 Java 应用程序来说,Java 进程启动时生成的子进程数量确实比较多,特别是当应用需要使用多线程模型或者服务发现等功能时,Java 进程可能会生成更多的子进程。启动 Nacos 时还需要启动 Nacos CLI 工具和服务,这些工具和服务也会生成一些额外的进程。
至于为什么将 pids_limit 设置为 1024 会导致 OOM,那可能是因为 Nacos 启动所需的内存较大,而当前容器的内存限制较严格。当启动 Nacos 时,容器需要为其分配足够的内存用于运行 Java 进程及其子进程。然而,如果容器的内存限制过低,就可能导致 OOM 错误。
解决这个问题的一种方法是增加容器的内存限制。如果您的 Docker 容器支持动态调整内存限制,那么您可以在启动容器时添加 "-m" 参数,将容器的内存限制设置得更高一些。例如,如果您想将容器的内存限制设置为 4GB,可以这样启动容器:
docker run -it --name nacos --restart always --rm -p 8848:8848 -m 4g nacos/nacos-server
另一种解决方案是在启动 Nacos 之前,先检查一下 Java 的运行时参数设置,看看是否有一些不需要的参数被设置了。有时候,过多的 Java 运行时参数也可能导致 OOM 错误。您可以参考 Nacos 的官方文档,看看有哪些常用的 Java 运行时参数,以及如何合理设置这些参数。
PID 的原因可能与 Nacos 的启动方式和配置有关。Nacos 使用 Spring Boot 作为基础框架,默认情况下,Spring Boot 会为每个启动的线程创建一个 PID。在 Nacos 启动时,可能会启动多个线程来完成不同的任务,从而产生大量的 PID。
关于 Nacos 启动 OOM 的问题,容器中的 PIDs_limit 限制可能会影响 Nacos 的启动。PIDs_limit 限制了容器中可以创建的 PID 的数量。如果该限制设置得过小,可能会导致 Nacos 启动时无法创建足够的 PID,从而引发 OOM。将 PIDs_limit 限制调大一倍可以解决这个问题,但可能并不是最佳的解决方案。
要解决这个问题,可以尝试以下方法:
当通过容器部署 Nacos 集群时,Nacos 启动产生多个 PID(进程标识符)的原因可能是因为每个 Nacos 实例都作为一个独立的进程运行。在集群环境中,通常会有多个 Nacos 实例,每个实例对应一个进程,因此会产生多个 PID。
这些 PID 代表不同的 Nacos 进程,它们负责处理不同的任务和功能,以支持集群的高可用性和扩展性。每个进程都独立运行,并通过网络通信与其他进程协作,以实现 Nacos 集群的整体功能。
需要注意的是,容器技术(如 Docker)通常用于隔离和管理进程,确保每个进程都运行在独立的容器中。这种隔离性有助于提供更好的资源管理和环境一致性,同时也方便进行扩展和管理。
因此,当您通过容器部署 Nacos 集群时,会看到多个 PID,每个 PID 对应一个独立的 Nacos 进程,这是正常现象,用于支持集群的高可用性和扩展性。
Nacos报OOM问题的记录
https://blog.csdn.net/zccmp20/article/details/115442728
nacos单机和集群版本启动的时候JVM内存占用问题:
nacos的JVM内存占用在nacos启动脚本中设置。单机启动和集群启动默认在启动脚本中分配的JVM内存如下。可以看到在单机启动nacos的时候,默认分配的内存大小为512m和256m。但是实际上nacos跑了一段时间以后可能会遇到OOM内存溢出的问题。因此需要调整一下。
standalone表示单机启动。默认分配最大最小内存为:512M和256M
else下面表示除了单机启动以外的启动,我暂且理解为集群模式,他默认分配最大最小内存为1G和2G。
if [[ "${MODE}" == "standalone" ]]; then
JAVA_OPT="${JAVA_OPT} -Xms512m -Xmx512m -Xmn256m"
JAVA_OPT="${JAVA_OPT} -Dnacos.standalone=true"
else
JAVA_OPT="${JAVA_OPT} -server -Xms2g -Xmx2g -Xmn1g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"
JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${BASE_DIR}/logs/java_heapdump.hprof"
JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages"
top查看了以后,发现实际上nacos跑到了1.4G左右,因此更改512m和256m到1G,2G。然后重启nacos即可
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
阿里云拥有国内全面的云原生产品技术以及大规模的云原生应用实践,通过全面容器化、核心技术互联网化、应用 Serverless 化三大范式,助力制造业企业高效上云,实现系统稳定、应用敏捷智能。拥抱云原生,让创新无处不在。