SpringBoot的配置如何动态刷新(方案)

文章介绍了微服务环境下配置管理的三种主流方案——Nacos、Config+Bus和Apollo,重点讨论了SpringBoot项目中动态刷新配置的适用场景。对于微服务集群推荐使用SpringBoot+Nacos,单体服务则可选择SpringBoot+Config+actuator或手动refresh。文章还提供了SpringBoot+Nacos和SpringBoot+Config+actuator的配置和使用步骤。

对于微服务而言配置本地化是个很大的鸡肋,不可能每次需要改个配置都要重新把服务重新启动一遍,因此最终的解决方案都是将配置外部化,托管在一个平台上达到不用重启服务即可一次修改多处生效的目的。
但是对于单体应用的Spring Boot项目而言,动态刷新显然是有点多余,反正就一个服务,改下重启不就行了,然而在某些特殊的场景下还是必须用到动态刷新的

微服务下有哪几种主流的方案?

微服务下的动态配置中心有三种主流的方式,如下图:

上图中的三种配置中心方案可以说是现在企业中使用率最高的,分别是:

  1. Nacos:阿里巴巴的最近开源的项目,这个家伙很牛逼,一个干掉了Eureka(停更)和Config+Bus,既能作为配置中心也能作为注册中心,并且有自己的独立的 管理平台,可以说是现在最主流的一种。

  2. Config+Bus:早期在用的微服务配置中心,可以依托GitHub管理微服务的配置文件,这种现在也是有不少企业在用,但是需要自己独立部署一个微服务,和Nacos相比逊色了不少。

  3. Apollo:携程开源项目Apollo,这个也是不少企业在用,陈某了解的不多,有兴趣的可以深入研究下。

针对Spring Boot 适用的几种方案?

其实上述三种都可以在Spring Boot项目中适配,但是作为单体应用有些重了。

1. 如果项目是一个微服务的集群,业务功能复杂

        建议: Spring Boot+Nacos

2. 如果项目是单体服务,业务功能单一

        建议: Spring Boot+Config+actuator

                   Spring Boot+手动refresh

针对Spring Boot+Nacos

阿里要做的其实是一个微服务生态,Nacos不仅仅可以作为Spring Cloud的配置和注册中心,也适配了Dubbo、K8s,官方文档中对于如何适配都做了详细的介绍,作者 这里就不再详细介绍了,如下图:

当然Nacos对Spring、Spring Boot 项目同样适用。

如何使用呢?这里作者只提供下思路,不做过多的深究,这篇在作者下个专栏Spring Cloud 进阶会详细介绍:

  1. 下载对应版本的Nacos,启动项目,访问http://localhost:8848进入Nacos的管理界面;

  2. Spring Boot 项目引入Nacos的配置依赖nacos-config-spring-boot-starter,配置Nacos管理中心的地址。

  3. @NacosPropertySource@NacosValue两个注解结合完成。

  • @NacosPropertySource:指定配置中心的dataId,和是否自动刷新

  • @NacosValue替代@Value注解完成属性的自动装配

  1. 如果公司项目做了后台管理,则可以直接调用Nacos开放的API修改对应配置的值(替代了Nacos管理界面的手动操作),API的地址:https://nacos.io/zh-cn/docs/open-api.html

针对Spring Boot+Config+actuator

1. 添加Config的依赖,如下

<!-- springCloud的依赖-->
<dependencyManagement>
    <dependencies>
        <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
    </dependencies>
</dependencyManagement>

<!-- config的依赖-->
<dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-config</artifactId>
    </dependency>

  <!-- actuator的依赖-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

2. 配置文件中暴露Spring Boot的端点,如下:

management.endpoints.web.exposure.include=*

3. 配置文件中新增三个属性配置

config.version=22
config.app.name=dynamic-project
config.platform=mysql

4. 结合@RefreshScope注解动态刷新,写个Controller,如下:

@RestController
//@RefreshScope该注解必须标注,否则无法完成动态更新
@RefreshScope
public class DynamicConfigController {
    @Value("${config.version}")
    private String version;

    @Value("${config.app.name}")
    private String appName;

    @Value("${config.platform}")
    private String platform;


    @GetMapping("/show/version")
    public String test(){
        return "version="+version+"-appName="+appName+"-platform="+platform;
    }

5. 启动项目测试

1. 浏览器访问http://localhost:8080/show/version
2. 修改target目录下的配置文件,如下:
    config.version=33
    config.app.name=dynamic-project
    config.platform=ORACLE
3. POST请求http://localhost:8080/actuator/refresh接口,手动刷新下配置(必须,否则不能自动刷新)
4. 浏览器再次输入http://localhost:8080/show/version

可以看到,配置已经自动修改了

针对Spring Boot+手动refresh

经过源码分析,配置刷新是发布刷新事件,在监听器实现刷新

发布事件:
    以nacos为例 : com.alibaba.cloud.nacos.refresh.NacosContextRefresher
    applicationContext.publishEvent(new RefreshEvent(this,null,"Refresh Nacos config"));



监听刷新事件: org.springframework.cloud.endpoint.event.RefreshEventListener

	@Override
	public void onApplicationEvent(ApplicationEvent event) {
		if (event instanceof ApplicationReadyEvent) {
			handle((ApplicationReadyEvent) event);
		}
		else if (event instanceof RefreshEvent) {
			handle((RefreshEvent) event);
		}
	}

	public void handle(ApplicationReadyEvent event) {
		this.ready.compareAndSet(false, true);
	}


执行刷新 : org.springframework.cloud.context.refresh.ContextRefresher

	public synchronized Set<String> refresh() {
		Set<String> keys = refreshEnvironment();
		this.scope.refreshAll();
		return keys;
	}

	public synchronized Set<String> refreshEnvironment() {
		Map<String, Object> before = extract(
				this.context.getEnvironment().getPropertySources());
		addConfigFilesToEnvironment();
		Set<String> keys = changes(before,
				extract(this.context.getEnvironment().getPropertySources())).keySet();
		this.context.publishEvent(new EnvironmentChangeEvent(this.context, keys));
		return keys;
	}

可以基于刷新自己实现动态加载

@GetMapping("/show/refresh")
    public String refresh(){
        //修改配置文件中属性
        HashMap<String, Object> map = new HashMap<>();
        map.put("config.version",99);
        map.put("config.app.name","appName");
        map.put("config.platform","ORACLE");
        MapPropertySource propertySource=new MapPropertySource("dynamic",map);
        //将修改后的配置设置到environment中
        environment.getPropertySources().addFirst(propertySource);
        //异步调用refresh方法,避免阻塞一直等待无响应
        new Thread(() -> contextRefresher.refresh()).start();
        return "success";
    }

测试步骤

1. 浏览器访问http://localhost:8080/show/version
2. 修改target目录下的配置文件,如下:
    config.version=33
    config.app.name=dynamic-project
    config.platform=ORACLE
3. POST请求http://localhost:8080/actuator/refresh接口,手动刷新下配置(必须,否则不能自动刷新)
4. 浏览器再次输入http://localhost:8080/show/version

可以看到,配置已经自动修改了

<think>好的,我现在需要帮助用户在SpringBoot项目中实现动态刷新配置以扩容线程池。首先,我得回忆一下之前学过的相关知识,以及用户提供的引用内容。用户提到了使用Nacos实现动态线程池,还有@Async注解和线程池的扩展。用户的需求是动态调整线程池大小,比如核心线程数、最大线程数等,而无需重启应用。首先,我需要确定SpringBoot中如何配置线程池。通常,我们会使用ThreadPoolTaskExecutor,并通过@Configuration来定义Bean。用户可能已经有一个这样的配置,但现在需要让它能够动态刷新根据引用2,动态线程池的优势在于应对请求量的波动,而Nacos可以作为配置中心来存储最新的线程池参数。接下来,动态刷新的机制。SpringCloud的@RefreshScope注解可以实现配置的实时刷新,但需要结合配置服务器,比如Nacos。用户需要将线程池的参数(如corePoolSize、maxPoolSize)放在Nacos的配置文件中,然后在SpringBoot应用中监听配置变化,并更新线程池的相应属性。然后,线程池参数的动态调整。即使配置更新了,如何让正在运行的线程池应用这些新值呢?ThreadPoolTaskExecutor本身可能不会自动更新,所以需要手动获取Bean并调用方法来修改参数。比如,可以通过调用setCorePoolSize和setMaxPoolSize方法,但需要注意这些方法是否真的能动态生效。例如,核心线程数可能需要先允许核心线程超时,才能减少数量。另外,用户可能需要扩展ThreadPoolTaskExecutor,像引用3提到的,创建子类来监控线程池状态。这样在调整参数时,可以记录日志或监控变化情况。可能的步骤包括:1.使用Nacos作为配置中心,存储线程池的配置。2.在SpringBoot中通过@Value注入这些配置,并加上@RefreshScope。3.创建ThreadPoolTaskExecutor的Bean,并在初始化时使用配置参数。4.监听配置变更事件,当配置更新时,调用线程池的方法调整参数。5.处理线程池参数动态调整的限制,比如需要设置allowCoreThreadTimeOut为true才能缩减核心线程数。还需要考虑线程池的动态调整是否安全,比如在运行时修改参数是否会导致资源竞争或任务执行异常。可能需要添加一些同步机制,或者确保在修改参数时不会影响正在执行的任务。用户可能遇到的问题包括配置不生效,或者线程池参数调整后没有立即应用。这时候需要检查@RefreshScope是否生效,配置是否正确加载,以及线程池的Bean是否被正确注入和更新。总结下来,解决方案的大致流程是:配置中心管理参数-> SpringBoot应用监听变化->更新线程池Bean的参数->验证调整后的效果。同时,可能需要自定义线程池的监控和日志,以便跟踪调整情况。</think>在Spring Boot中实现动态刷新线程池配置并扩容,可以通过以下步骤实现: ### 一、核心实现方案 1. **配置中心集成** 使用Nacos作为配置中心存储线程池参数,例如: ```yaml thread-pool: core-size: 5 max-size: 10 queue-capacity: 100 ``` 通过`@NacosValue`或`@ConfigurationProperties`注入配置[^2]。 2. **动态线程池初始化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值