需求
系统遇到这样一个需求,线上环境在配置文件发生变动时,可以不用经过重启,通过刷新接口的方式得到配置文件的加载,主要目的是为了迅速部署,避免因手动重启,处理不及时导致积压的问题
问题
1.程序中如何获取修改后的配置
2.某些配置值是应用在bean里面的,在程序初始化的时候已经注入,如何修改这一部分。
例如,程序是分主备环境的,kafka consumer的groupid或topic根据环境不同而改变,那么consumer若写在bean中,修改配置文件,要一并更新到bean中
//示例代码,KafkaConsumer是自己封装的类
@Bean(name = "consumer")
public KafkaConsumer createKafkaConsumer(
@Qualifier("service") ExcutorService excutorService) {
//groupid + topic
//currEnv 主环境 ““ 备环境”RE_BAK_“
KafkaConsumer consumer = new KafkaConsumer(currEnv+groupid,topic){
public void function(ConsumerRecords<String, String> records) { //...业务代码}
}
}
解决
1.程序中获取修改后的配置,去处理业务逻辑,参考了这篇文章戳我 第一步,添加适合自己springboot版本的Springcloud context依赖,若Springboot版本低,maven可能会引不上高版本的context
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<version>?</version>
</dependency>
第二步,在需要得到刷新配置值的类上引入@RefreshScope
第三步,在对应变量上引入@Value
第四步,编写refresh接口
package com.example.zzy.zzttest.controller;
import com.example.zzy.zzttest.config.BizConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.context.refresh.ContextRefresher;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RefreshScope
@RestController
public class TestController {
@Autowired
private BizConfig bizConfig;
@Autowired
private ContextRefresher contextRefresher;
@Value("${biz.refresh}")
private String refresh;
@RequestMapping(path = "/show")
public String show() {
//String ref = bizConfig.getRefresh();
System.out.println(refresh);
return refresh;
}
@RequestMapping(path = "/refresh")
public String refresh() throws Exception{
new Thread( () -> contextRefresher.refresh() ).start();
return show();
}
}
p.s.这种方式仅适用于springboot默认管理的配置文件,比如包内的或者包外的application.properties 或者application.yml。一般我们都要更新配置文件了那基本动的都是包外的配置文件,可以直接外置application.properties,把它放在部署包的同级目录,可以达到在controller中获取配置值的目的。关于springboot加载配置文件路径及优先级戳我,总结的很清楚。关于ContextRefresher相关源码解读戳我
p.s.顺便记录一下另外一个问题,我的实际项目没有用到springboot默认的项目内外的application.properties,而是在部署包路径下的/hadoopConf/props.properties中,项目中获取配置的时候使用了工具类,这样做的目的是因为有很多普通项目也引用了这里面的配置,这里不延伸。在这种情况下,因为不是springboot管理的配置文件,所以用上面的方法是不成功的,解决方法是在启动参数里加入
--spring.config.location=./hadoopConf/props.properties
这样springboot会把这个配置文件纳入管理,相当于把它认为是applicaiton.properties,就可以正常使用上面的步骤获取更新的配置值了
2.解决刷新bean的问题,参考链接