Nacos Config事件监听动态调整线程池参数方式

 更新时间:2026年06月14日 09:42:24   作者:小毕超  
本文介绍了如何利用NacosConfig的事件监听机制动态调整线程池参数,无需重启应用环境即可应对突发情况,通过配置Nacos的thread配置文件并acosConfig监听机制实现了线acosConfig配置动态更新线线acosConfig配置动态更新线NacosConfig配置动态更新

一、Nacos Config 事件监听

在实际项目中一般都会使用线程池解决一些异步并发问题,不过线程池核心参数很大程度上一次性进行设置,但系统运行起来总有可能出现各种各样的问题,如果修改线程池的参数则一般需要重启项目,对于生产环境而言有时无法进行重启,这种情况下就需要我们做成可动态调节的线程池。以应对突发情况。

在微服务项目中,目前使用 Nacos 作为配置中心已经是非常普遍的现象,得益于 Nacos 的灵活性以及稳定性,本文我们基于 Nacos Config 配置能力,将线程池的核心参数配置到 Nacos 中,并通过Nacos Config 的事件监听机制,触发动态参数调节。

实验开始前,需要安装好 Nacos 服务:

线程池这里使用 springframework 提供的 ThreadPoolTaskExecutor ,并通过其自带的方法进行动态调节:

二、准备测试项目并创建配置文件

首先创建一个 SpringBoot 项目,并引入 nacos config 的依赖,这里为了方便操作属性 ,同时引入 lombokSpring Cloud Alibaba 版本使用的 2.2.6.RELEASE

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.2.6.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

创建 bootstrap.yml 文件增加 nacos config 的配置,注意这里 application.namedemo-service ,下面创建配置文件命名时需要注意。

spring:
  application:
    name: demo-service
  profiles:
    active: thread # 引入thread配置
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.244.1:8848
      config:
        server-addr: 192.168.244.1:8848
        file-extension: yaml

这里单独引入一个 thread 配置,关于线程的配置都放在这里,文件名应该为 demo-service-thread.yaml

Nacos 创建 demo-service.yml 主配置文件,将服务的端口放在这里 :

server:
  port: 8082

接着创建 demo-service-thread.yaml 文件,声明出核心线程数、最大线程数、线程保持时间、以及队列的存储个数:

thread:
  corePoolSize: 25
  maxPoolSize: 30
  keepAliveSeconds: 4
  queueCapacity: 200


二、声明线程池

首先对上面的配置文件,声明一个 Properties 接收参数:

@Data
@Configuration
@RefreshScope
@ConfigurationProperties(prefix = "thread")
public class ThreadPoolProperties {

    /**
     * 核心线程数
     */
    private Integer corePoolSize;
    /**
     * 最大线程数
     */
    private Integer maxPoolSize;
    /**
     * 线程保持时间 秒
     */
    private Integer keepAliveSeconds;

    /**
     * 队列的存储个数
     */
    private Integer queueCapacity;

}

使用参数声明线程池,其中提供出调整线程池参数,和打印当前参数方法:

@Data
@Configuration
public class ThreadPoolConfig {

    @Resource(name = "dynamic_thread_pool")
    ThreadPoolTaskExecutor executor;

    @Bean(value = "dynamic_thread_pool")
    public ThreadPoolTaskExecutor dynamicThreadPool(ThreadPoolProperties properties) {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(properties.getCorePoolSize());
        executor.setMaxPoolSize(properties.getMaxPoolSize());
        executor.setKeepAliveSeconds(properties.getKeepAliveSeconds());
        executor.setQueueCapacity(properties.getQueueCapacity());
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }

    /**
     * 重新设置参数
     */
    public void restThreadPool(ThreadPoolProperties properties) {
        executor.setCorePoolSize(properties.getCorePoolSize());
        executor.setMaxPoolSize(properties.getMaxPoolSize());
        executor.setKeepAliveSeconds(properties.getKeepAliveSeconds());
        executor.setQueueCapacity(properties.getQueueCapacity());
    }

    /**
     * 打印线程池参数
     */
    public void printParam() {
        System.out.println("当前核心线程数:" + executor.getCorePoolSize());
        System.out.println("当前最大线程数:" + executor.getMaxPoolSize());
        System.out.println("当前线程保持时间:" + executor.getKeepAliveSeconds());
    }

}

三、添加demo-service-thread.yaml文件的监听

添加监听,这里我用的 PropertiesListener ,可以将修改后的配置,映射为 Properties 对象,如果想要拿到修改后配置内容的字符串可以使用 AbstractListenerListener

@Component
public class NacosListener implements ApplicationRunner {

    @Resource
    NacosConfigManager nacosConfigManager;

    @Resource
    NacosConfigProperties nacosConfigProperties;

    @Resource
    ThreadPoolConfig threadPoolConfig;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("初始线程状态:");
        threadPoolConfig.printParam();
        //配置修改监听
        nacosConfigManager.getConfigService().addListener("demo-service-thread.yaml", nacosConfigProperties.getGroup(),
                new PropertiesListener(){
                    @Override
                    public void innerReceive(Properties properties) {
                        System.out.println("配置被修改,重新调整线程池!");
                        ThreadPoolProperties poolProperties = new ThreadPoolProperties();
                        poolProperties.setCorePoolSize(Integer.parseInt(properties.getProperty("corePoolSize")));
                        poolProperties.setMaxPoolSize(Integer.parseInt(properties.getProperty("maxPoolSize")));
                        poolProperties.setKeepAliveSeconds(Integer.parseInt(properties.getProperty("keepAliveSeconds")));
                        poolProperties.setQueueCapacity(Integer.parseInt(properties.getProperty("queueCapacity")));
                        System.out.println("开始重新调整线程池...");
                        threadPoolConfig.restThreadPool(poolProperties);
                        System.out.println("调整之后线程池的参数:");
                        threadPoolConfig.printParam();
                    }
                });
    }
}

这里需要注意下,我在触发监听后,手动获取的参数,上面细心地会发现,其实ThreadPoolProperties 已经加了 @RefreshScope 会自动刷新的,那这里为啥还要手动解析呢,答案就是配置更新后,会首先触发这里的监听,如果在监听中直接调用调整方法,使用 ThreadPoolProperties 的话有可能还是原来的参数,保险起见这里获取一下。

四、测试

启动项目,可以看到初始的参数:

下面修改最大线程数为 50

发布后,观察日志:

线程池的最大线程已经被调整为 50

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • java开发中基于JDBC连接数据库实例总结

    java开发中基于JDBC连接数据库实例总结

    这篇文章主要介绍了java开发中基于JDBC连接数据库的方法,以实例形式较为详细的总结分析了Java使用JDBC的具体步骤与注意事项,并附带了一个完整实例加以说明,需要的朋友可以参考下
    2015-11-11
  • Jetbrains系列产品重置试用思路详解

    Jetbrains系列产品重置试用思路详解

    这篇文章主要介绍了Jetbrains系列产品重置试用思路详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • IDEA无法使用Git Pull的问题

    IDEA无法使用Git Pull的问题

    本文主要介绍了IDEA无法使用Git Pull的问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02
  • Spring为什么不推荐使用@Autowired注解详析

    Spring为什么不推荐使用@Autowired注解详析

    @Autowired 注解的主要功能就是完成自动注入,使用也非常简单,但这篇文章主要给大家介绍了关于Spring为什么不推荐使用@Autowired注解的相关资料,需要的朋友可以参考下
    2021-11-11
  • Spring Boot中防止递归查询的两种方式

    Spring Boot中防止递归查询的两种方式

    这篇文章主要给大家介绍了关于Spring Boot中防止递归查询的两种方式,两种方式分别是在application.properties中配置和在entity中添加注解,都给出了详细的示例代码,需要的朋友们下面来一起看看吧。
    2017-06-06
  • java怎么设置代理ip实现高效网络请求

    java怎么设置代理ip实现高效网络请求

    无论是在爬虫、API调用还是网络测试中,代理IP的使用都变得愈发重要,本文我们主要来介绍一下如何在Java中设置代理IP实现高效网络请求吧
    2024-11-11
  • Java中并发下的ThreadlocalRandom的实现

    Java中并发下的ThreadlocalRandom的实现

    本文介绍了Java1.8中的ThreadLocalRandom类,它在并发环境下比Random类有更好的性能,下面就来详细的介绍一下如何使用,感兴趣的可以了解一下
    2026-01-01
  • SWT(JFace) 图片浏览器 实现代码

    SWT(JFace) 图片浏览器 实现代码

    SWT(JFace)小制作:图片浏览器
    2009-06-06
  • SpringBoot 配置提示功能(超详细)

    SpringBoot 配置提示功能(超详细)

    这篇文章主要介绍了SpringBoot 配置提示功能,本文给大家介绍的超详细,通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-10-10
  • 关于@PropertySource配置的用法解析

    关于@PropertySource配置的用法解析

    这篇文章主要介绍了关于@PropertySource配置的用法解析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03

最新评论