动态线程池

@SpringBootAplication 声明当前类是一个配置类

@Configurable注解用户标记一个类可以被Spring容器管理

@SpringBootTest用于在SpringBoot应用程序中进行集成测试,允许测试类在真实的应用环境中运行

@RunWith(SpringRunner.class)让测试运行于Spring测试环境

Redis只是注册中心的一种实现方式,可以有多种实现方式.

 

动态修改分布式部署中所运行的线程池,对不同应用的线程池进行监控

 

项目包括三个模块,分别是测试工程、组件的sdk和admin管理工程。

test 线程池测试

方法中如何获得每个线程池中的状态信息的?

逻辑:springBootApplication启动应用,加载动态线程组件(pom.xml文件中引入了线程组件作为依赖)

DynamicThreadPoolAutoProperties里的属性值来自application-dev.yml。
使用@ConfigurationProperties(将配置文件的属性绑定到java的bean上)实现绑定。

DynamicThreadPoolAutoConfig将会把DynamicThreadPoolAutoProperties里的属性值绑定到类的实例上。
使用@EnableConfigurationProperties用于启用对@ConfigurationProperties注解类的支持。它允许将外部配置文件(如application.propertiesapplication.yml)中的属性绑定到强类型的Java Beans上,从而实现配置的模块化和可维护性

 

config文件夹(创建两个线程池)

对测试线程池的属性进行了配置,包括核心线程池、最大线程数、最大等待时间、最大队列数和拒绝策略,等待时间的单位设置为秒,线程工厂(为线程池中的线程提供统一的配置),本项目中设为默认。

// 创建线程池
return new ThreadPoolExecutor(properties.getCorePoolSize(),
        properties.getMaxPoolSize(),
        properties.getKeepAliveTime(),
        TimeUnit.SECONDS,
        new LinkedBlockingQueue<>(properties.getBlockQueueSize()),
        Executors.defaultThreadFactory(),
        handler);

按照上述代码创建了两个线程池,分别为threadPoolExecutors01和threadPoolExecutors02。

 

starter

pom文件

添加redisson依赖来连接redis作为配置中心,所有应用可以通过redis进行通知的配置和变更;

config包

作为配置的入口,springboot启动加载需要一个自动化的配置,需要指定,配置入口提供了一个类把需要用到的bean对象实例化出来,通过在spring.factories中添加配置:

DynamicThreadPoolAutoConfig

创建redis客户端,实例化注册中心,返回DynamicThreadPoolService对象(如果Redis中有数据,从Redis中获取最新线程池的核心线程数和最大线程数的数据并对当前线程池对象进行修改),返回ThreadPoolDataReportJob,ThreadPoolConfigAdjustListener以及RTopic(Redisson中实习了发布/订阅模式的组件)

Redisson中RTopic的使用场景及例子-CSDN博客

 

domain包

DynamicThreadPoolService类(获取线程池列表中的信息)

queryThreadPoolList():获取线程池集合列表中每个线程池的信息,并返回List集合。

queryThreadPoolConfigByName():通过线程池的名字获取到该线程池的信息,并返回ThreadPoolConfigEntity实体。

updateThreadPoolConfig():根据传入的ThreadPoolConfigEntity实体更新线程池的信息。

 

registry包

Redisson是基于Redis实现的并发库,是高级的分布式数据结构和并发工具,提供锁,信号量等并发组件。

Redis 和 Redisson 到底是啥关系 解开这个迷团Redis 与 Redisson: 探索他们的关系与共生之道 - 掘金 (juejin.cn)

RedisRegistry类(将线程池列表信息上报到Redisson注册中心)

reportThreadPool(List<ThreadPoolConfigEntity> threadPoolEntites):通过传入的参数更新redisson。

reportThreadPoolConfigParameter(ThreadPoolConfigEntity threadPoolConfigEntity):上报线程池的配置参数更新redisson

 

trigger包(触发器)

ThreadPoolDataReportJob类

实例化上面的两个类,分别用于获得当前线程池的信息并上报到Redisson。

//通过服务拿数据
    private final IDynamicThreadPoolService dynamicThreadPoolService;
    //通过redis注册中心上报
    private final IRegistry registry;

    public ThreadPoolDataReportJob(IDynamicThreadPoolService dynamicThreadPoolService,IRegistry registry){
        this.dynamicThreadPoolService=dynamicThreadPoolService;
        this.registry=registry;
    }


@Scheduled(cron = "0/20 * * * * ?")
    public void execReportThreadPoolList(){
        //通过service服务方法获得当前线程池的状态
        List<ThreadPoolConfigEntity> threadPoolConfigEntities = dynamicThreadPoolService.queryThreadPoolList();
        //向注册中心上报
        registry.reportThreadPool(threadPoolConfigEntities);
        log.info("动态线程池,上报线程池信息:{}", JSON.toJSONString(threadPoolConfigEntities));

        for (ThreadPoolConfigEntity threadPoolConfigEntity :
                threadPoolConfigEntities) {
            registry.reportThreadPoolConfigParameter(threadPoolConfigEntity);
            log.info("动态线程池,上报线程池配置:{}", JSON.toJSONString(threadPoolConfigEntity));
        }
    }

实现实时监听当前线程池信息并上报。

 

 ThreadPoolConfigAdjustListener类(更新线程池属性)

//消息监听器 每次产生的新消息会放在第二个参数里
public void onMessage(CharSequence charSequence, ThreadPoolConfigEntity threadPoolConfigEntity) {
    log.info("动态线程池,调整线程池配置。线程池名称:{} 核心线程数:{} 最大线程数:{}", threadPoolConfigEntity.getThreadPoolName(), threadPoolConfigEntity.getPoolSize(), threadPoolConfigEntity.getMaximumPoolSize());
    //更新线程池
    dynamicThreadPoolService.updateThreadPoolConfig(threadPoolConfigEntity);

    //上报最新数据到注册中心
    List<ThreadPoolConfigEntity> threadPoolConfigEntities = dynamicThreadPoolService.queryThreadPoolList();
    registry.reportThreadPool(threadPoolConfigEntities);
    
    
    ThreadPoolConfigEntity threadPoolConfigEntityCurrent = dynamicThreadPoolService.queryThreadPoolConfigByName(threadPoolConfigEntity.getThreadPoolName());
    registry.reportThreadPoolConfigParameter(threadPoolConfigEntityCurrent);
    

 

redisson消息订阅的流程:

在组件中创建Redisson的配置并连接到本地的Redis服务器;

在Controller包下的更新线程池属性事件中调用getTop()获取一个发布频道,并使用publish()发送更新时传入的线程池实体;

创建订阅消息的监听器,通过实现MessageListner接口,并重写onMessage方法来处理消息;

在DynamicThreadPoolAutoConfig里创建dynamicThreadPoolRedisTopic类实例对象,使用getTopic(“频道名”)方法获取订阅频道,并使用addListner()添加之前创建的监听器,返回topic对象

 

resources中的spring.factories文件:指定需要spring动态加载配置类的入口地址

 

posted @ 2025-04-08 16:46  Dyj07  阅读(39)  评论(0)    收藏  举报