网站首页 > 文章精选 正文
前言:
在SpringBoot应用中,配置信息通常通过application.properties或application.yml文件静态定义,应用启动后这些配置就固定下来了。但我们常常需要在不重启应用的情况下动态修改配置,以实现灰度发布、A/B测试、动态调整线程池参数、切换功能开关等场景。
1. @RefreshScope结合Actuator刷新端点
Spring Cloud提供的@RefreshScope注解是实现配置热刷新的基础方法。
实现步骤
- 添加依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
- 开启刷新端点:
配置文件中配置:
management.endpoints.web.exposure.include=refresh
- 给配置类添加@RefreshScope注解:
@RefreshScope
@RestController
public class ConfigController {
@Value("${app.message:Default message}")
private String message;
@GetMapping("/message")
public String getMessage() {
return message;
}
}
- 修改配置后,调用刷新端点:
curl -X POST http://localhost:8080/actuator/refresh
优点
- 实现简单,利用Spring Cloud提供的现成功能
- 无需引入额外的配置中心
缺点
- 需要手动触发刷新
- 只能刷新单个实例,在集群环境中需要逐个调用
- 只能重新加载配置源中的值,无法动态添加新配置
2. Spring Cloud Config配置中心
Spring Cloud Config提供了一个中心化的配置服务器,支持配置文件的版本控制和动态刷新。
实现步骤
- 设置Config Server:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
spring.cloud.config.server.git.uri=https://github.com/your-repo/config
- 客户端配置:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
# bootstrap.properties
spring.application.name=my-service
spring.cloud.config.uri=http://localhost:8888
- 添加自动刷新支持:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
优点
- 提供配置的版本控制
- 支持配置的环境隔离
- 通过Spring Cloud Bus可实现集群配置的自动刷新
缺点
- 引入了额外的基础设施复杂性
- 依赖额外的消息总线实现集群刷新
- 配置更新有一定延迟
3. 基于数据库的配置存储
将配置信息存储在数据库中,通过定时任务或事件触发机制实现配置刷新。
实现方案
- 创建配置表:
CREATE TABLE app_config (
config_key VARCHAR(100) PRIMARY KEY,
config_value VARCHAR(500) NOT NULL,
description VARCHAR(200),
update_time TIMESTAMP
);
- 实现配置加载和刷新:
@Service
public class DatabaseConfigService {
@Autowired
private JdbcTemplate jdbcTemplate;
private Map<String, String> configCache = new ConcurrentHashMap<>();
@PostConstruct
public void init() {
loadAllConfig();
}
@Scheduled(fixedDelay = 60000) // 每分钟刷新
public void loadAllConfig() {
List<Map<String, Object>> rows = jdbcTemplate.queryForList("SELECT config_key, config_value FROM app_config");
for (Map<String, Object> row : rows) {
configCache.put((String) row.get("config_key"), (String) row.get("config_value"));
}
}
public String getConfig(String key, String defaultValue) {
return configCache.getOrDefault(key, defaultValue);
}
}
优点
- 简单直接,无需额外组件
- 可以通过管理界面实现配置可视化管理
- 配置持久化,重启不丢失
缺点
- 刷新延迟取决于定时任务间隔
- 数据库成为潜在的单点故障
- 需要自行实现配置的版本控制和权限管理
4. Redis发布订阅机制实现配置更新
利用Redis的发布订阅功能,实现配置变更的实时通知。
实现方案
- 添加依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
- 实现配置刷新监听:
@Component
public class RedisConfigManager {
@Autowired
private StringRedisTemplate redisTemplate;
private final Map<String, String> configCache = new ConcurrentHashMap<>();
@PostConstruct
public void init() {
loadAllConfig();
subscribeConfigChanges();
}
private void loadAllConfig() {
Set<String> keys = redisTemplate.keys("config:*");
if (keys != null) {
for (String key : keys) {
String value = redisTemplate.opsForValue().get(key);
configCache.put(key.replace("config:", ""), value);
}
}
}
private void subscribeConfigChanges() {
redisTemplate.getConnectionFactory().getConnection().subscribe(
(message, pattern) -> {
String[] parts = new String(message.getBody()).split("=");
if (parts.length == 2) {
configCache.put(parts[0], parts[1]);
}
},
"config-channel".getBytes()
);
}
public String getConfig(String key, String defaultValue) {
return configCache.getOrDefault(key, defaultValue);
}
// 更新配置的方法(管理端使用)
public void updateConfig(String key, String value) {
redisTemplate.opsForValue().set("config:" + key, value);
redisTemplate.convertAndSend("config-channel", key + "=" + value);
}
}
优点
- 实现简单,利用Redis的发布订阅机制
- 集群环境下配置同步实时高效
- 可以与现有Redis基础设施集成
缺点
- 依赖Redis的可用性
- 需要确保消息不丢失
- 缺乏版本控制和审计功能
5. Nacos配置管理
阿里开源的Nacos既是服务发现组件,也是配置中心,广泛应用于Spring Cloud Alibaba生态。
实现步骤
- 添加依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
- 配置Nacos:
# bootstrap.properties
spring.application.name=my-service
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
# 支持多配置文件
spring.cloud.nacos.config.extension-configs[0].data-id=database.properties
spring.cloud.nacos.config.extension-configs[0].group=DEFAULT_GROUP
spring.cloud.nacos.config.extension-configs[0].refresh=true
- 使用配置:
@RestController
@RefreshScope
public class ConfigController {
@Value("${useLocalCache:false}")
private boolean useLocalCache;
@GetMapping("/cache")
public boolean getUseLocalCache() {
return useLocalCache;
}
}
优点
- 与Spring Cloud Alibaba生态无缝集成
- 配置和服务发现功能二合一
- 轻量级,易于部署和使用
- 支持配置的动态刷新和监听
缺点
- 部分高级功能不如Apollo丰富
- 需要额外维护Nacos服务器
- 需要使用bootstrap配置机制
6.使用@ConfigurationProperties结合EventListener
利用Spring的事件机制和@ConfigurationProperties绑定功能,实现配置的动态更新。
实现方案
- 定义配置属性类:
@Component
@ConfigurationProperties(prefix = "app")
@Setter
@Getter
public class ApplicationProperties {
private int connectionTimeout;
private int readTimeout;
private int maxConnections;
private Map<String, String> features = new HashMap<>();
// 初始化客户端的方法
public HttpClient buildHttpClient() {
return HttpClient.newBuilder()
.connectTimeout(Duration.ofMillis(connectionTimeout))
.build();
}
}
- 添加配置刷新机制:
@Component
@RequiredArgsConstructor
public class ConfigRefresher {
private final ApplicationProperties properties;
private final ApplicationContext applicationContext;
private HttpClient httpClient;
@PostConstruct
public void init() {
refreshHttpClient();
}
@EventListener(EnvironmentChangeEvent.class)
public void onEnvironmentChange() {
refreshHttpClient();
}
private void refreshHttpClient() {
httpClient = properties.buildHttpClient();
System.out.println("HttpClient refreshed with timeout: " + properties.getConnectionTimeout());
}
public HttpClient getHttpClient() {
return this.httpClient;
}
// 手动触发配置刷新的方法
public void refreshProperties(Map<String, Object> newProps) {
PropertiesPropertySource propertySource = new PropertiesPropertySource(
"dynamic", convertToProperties(newProps));
ConfigurableEnvironment env = (ConfigurableEnvironment) applicationContext.getEnvironment();
env.getPropertySources().addFirst(propertySource);
// 触发环境变更事件
applicationContext.publishEvent(new EnvironmentChangeEvent(newProps.keySet()));
}
private Properties convertToProperties(Map<String, Object> map) {
Properties properties = new Properties();
for (Map.Entry<String, Object> entry : map.entrySet()) {
properties.put(entry.getKey(), entry.getValue().toString());
}
return properties;
}
}
优点
- 强类型的配置绑定
- 利用Spring内置机制,无需额外组件
- 灵活性高,可与其他配置源结合
缺点
- 需要编写较多代码
- 配置变更通知需要额外实现
- 不适合大规模或跨服务的配置管理
总结
动态配置修改能够提升系统的灵活性和可管理性,选择合适的动态配置方案应综合考虑应用规模、团队熟悉度、基础设施现状和业务需求。
猜你喜欢
- 2025-06-13 SpringBoot权限炸场!动态鉴权提速10倍吊打RBAC(附工具源码)
- 2025-06-13 Spring Boot 3.4 新特性实战解析(springboot最新)
- 2025-06-13 SpringBoot 2.7.10、3.0.5 发布,修复 DoS漏洞
- 2025-06-13 springboot(二十八)stomp在spring5.3以上报跨域问题的处理
- 2025-06-13 还在为 Spring Boot3 动态配置发愁?一文教你轻松搞定!
- 2025-06-13 快来看看SpringBoot2.2发行版,你能用到哪些新特性?
- 2025-06-13 Spring Boot3 应用打包成 Docker 镜像全攻略
- 2025-06-13 Spring Boot3 动态配置实现方案全解析,你掌握了吗?
- 2025-06-13 Spring Framework 6.2 和 Spring Boot 3.4 为 2025 年新一代做好准备
- 2025-06-13 我找到了一个快速定位SpringBoot接口超时问题的神器
- 最近发表
- 标签列表
-
- newcoder (56)
- 字符串的长度是指 (45)
- drawcontours()参数说明 (60)
- unsignedshortint (59)
- postman并发请求 (47)
- python列表删除 (50)
- 左程云什么水平 (56)
- 计算机网络的拓扑结构是指() (45)
- 编程题 (64)
- postgresql默认端口 (66)
- 数据库的概念模型独立于 (48)
- 产生系统死锁的原因可能是由于 (51)
- 数据库中只存放视图的 (62)
- 在vi中退出不保存的命令是 (53)
- 哪个命令可以将普通用户转换成超级用户 (49)
- noscript标签的作用 (48)
- 联合利华网申 (49)
- swagger和postman (46)
- 结构化程序设计主要强调 (53)
- 172.1 (57)
- apipostwebsocket (47)
- 唯品会后台 (61)
- 简历助手 (56)
- offshow (61)
- mysql数据库面试题 (57)