nacos客户端线程数过多的问题

发布时间 2023-12-04 17:02:12作者: 沧海一滴

 

本文介绍如何排查Nacos线程数过多的问题。

问题现象

通过监控系统或其他手段,观察到应用的线程数过多,且大部分线程名中带有nacos等字样。

可能原因

  • 系统环境问题。程序读取到的CPU数量错误,导致线程池核心大小和最大大小过大。

  • 应用中创建过多Nacos-Client实例, 例如NacosNamingService或NacosConfigService。

  • 应用中存在错误使用方式,连续创建Nacos-Client实例,但新创建的Nacos-Client实例替换旧的Nacos-Client实例时未使用shutdown方法关闭线程池。

解决方案

本文以Java应用为例,其他语言应用可使用对应开发语言的相似命令执行。

  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}'
    1. 如果Nacos-Client实例数存在过多,例如10个以上,则原因可能为应用中创建了过多Nacos-Client实例。请排查应用中使用Nacos-Client的代码,是否未复用Nacos-Client实例而是每次都创建不同的Nacos-Client实例。更多信息,请参见Dubbo框架在2.7.8版本中的Bug

  2. 如果Nacos-Client实例数量正常,请确认线程数是否符合预期。

    1. 使用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
    2. 如果上述线程数均超过了预期,则原因可能为连续创建Nacos-Client实例,但新创建的Nacos-Client实例替换旧的Nacos-Client实例时未使用shutdown方法关闭线程池,导致旧线程池未被关闭。更多信息,请参见Sentinel框架在旧版本中的Bug

    3. 如果上述线程数仅有nacos-grpc-client-executor、com.alibaba.nacos.client.naming.updater等与CPU数量有关的线程数超过预期,则原因可能为应用读取的当前节点的CPU数量不正确,该情况多出现于容器化的场景中。可通过调用Runtime.getRuntime().availableProcessors()查看应用读取到的CPU数量,确认读取数量过大时,可通过更换正确的环境进行修复,或使用参数-Dnacos.common.processors=或环境变量NACOS_COMMON_PROCESSORS=进行强制指定。

    4. 如果上述线程均符合预期,说明线程池并没有泄漏,没有线程数过多的风险。如需降低线程数,可通过参数-Dnacos.remote.client.grpc.pool.core.size=-Dnacos.remote.client.grpc.pool.max.size=来设置nacos-grpc-client-executor线程池的数量。

      说明
      • 参数-Dnacos.remote.client.grpc.pool.core.size=-Dnacos.remote.client.grpc.pool.max.size=需要Nacos-Client版本为2.1.1及以上版本生效。

      • nacos-grpc-client-executor线程池存在回收机制,客户端在长时间无请求时,会自动回收多余线程至最小值(默认为CPU数量 * 2)。在大量请求时,会自动扩充线程数至最大值(默认为CPU数量 * 8)。因此部分监控系统中会看到该线程名的线程ID会呈现增长趋势,该现象为正常现象,并非Nacos线程数过多的问题。

https://help.aliyun.com/zh/mse/support/what-do-i-do-if-the-number-of-nacos-threads-is-excessively-large

 

升级引擎版本

升级过程中的常见问题

  • 问:升级到专业版Nacos 2.0.0后,能否支持旧版本客户端?

    答:配置中心兼容并支持Nacos Client 1.0.0之后的所有客户端版本,服务发现兼容Nacos Client 1.2.0之后的所有客户端版本。 但Nacos Client 1.x.x的客户端版本不具有长连接能力,因此建议使用Nacos Client 2.0.0之后的客户端版本。

  • 问:我使用的是Spring Cloud Alibaba或Dubbo,如何升级客户端?

    答:对于Spring Cloud Alibaba,可通过指定Nacos Client的方式,升级Nacos Client版本。例如:

 
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    <version>2.1.1.RELEASE</version>
    <exclusions>
        <exclusion>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>com.alibaba.nacos</groupId>
    <artifactId>nacos-client</artifactId>
    <version>2.2.1</version>
</dependency>

客户端nacos-client升级

nacos-client从2.2.1版本开始支持TLS传输链路加密。

  1. 升级至nacos-client 2.2.1版本。相关代码如下所示。

    <dependency>
        <groupId>com.alibaba.nacos</groupId>
        <artifactId>nacos-client</artifactId>
        <version>2.2.1</version>
    </dependency>

     

https://help.aliyun.com/zh/mse/user-guide/enable-tls-for-mse-nacos-instances

spring-cloud-alibaba和nacos client版本关系可以参考spring-cloud-alibaba社区的文档说明

组件版本关系

每个 Spring Cloud Alibaba 版本及其自身所适配的各组件对应版本如下表所示(注意,Spring Cloud Dubbo 从 2021.0.1.0 起已被移除出主干,不再随主干演进):

Spring Cloud Alibaba VersionSentinel VersionNacos VersionRocketMQ VersionDubbo VersionSeata Version

2022.0.0.0

1.8.6

2.2.1

4.9.4

~

1.7.0

2022.0.0.0-RC2

1.8.6

2.2.1

4.9.4

~

1.7.0-native-rc2

2021.0.5.0

1.8.6

2.2.0

4.9.4

~

1.6.1

2.2.10-RC1

1.8.6

2.2.0

4.9.4

~

1.6.1

2022.0.0.0-RC1

1.8.6

2.2.1-RC

4.9.4

~

1.6.1

2.2.9.RELEASE

1.8.5

2.1.0

4.9.4

~

1.5.2

2021.0.4.0

1.8.5

2.0.4

4.9.4

~

1.5.2

2.2.8.RELEASE

1.8.4

2.1.0

4.9.3

~

1.5.1

2021.0.1.0

1.8.3

1.4.2

4.9.2

~

1.4.2

2.2.7.RELEASE

1.8.1

2.0.3

4.6.1

2.7.13

1.3.0

2.2.6.RELEASE

1.8.1

1.4.2

4.4.0

2.7.8

1.3.0

2021.1 or 2.2.5.RELEASE or 2.1.4.RELEASE or 2.0.4.RELEASE

1.8.0

1.4.1

4.4.0

2.7.8

1.3.0

2.2.3.RELEASE or 2.1.3.RELEASE or 2.0.3.RELEASE

1.8.0

1.3.3

4.4.0

2.7.8

1.3.0

2.2.1.RELEASE or 2.1.2.RELEASE or 2.0.2.RELEASE

1.7.1

1.2.1

4.4.0

2.7.6

1.2.0

2.2.0.RELEASE

1.7.1

1.1.4

4.4.0

2.7.4.1

1.0.0

2.1.1.RELEASE or 2.0.1.RELEASE or 1.5.1.RELEASE

1.7.0

1.1.4

4.4.0

2.7.3

0.9.0

2.1.0.RELEASE or 2.0.0.RELEASE or 1.5.0.RELEASE

1.6.3

1.1.1

4.4.0

2.7.3

0.7.1

https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E