SpringBoot使用Nacos作为配置中心 测试及总结

前言

学习笔记汇总地址:
https://blog.csdn.net/lwb314/article/details/108277732
Nacos作为配置中心后,我把配置分成3个等级,针对这3个等级进行测试,并给出测试结果。
环境初始化,启动函数和配置都在上一篇博客里,这里就不再写一遍了
上一篇地址:https://blog.csdn.net/lwb314/article/details/108316627

测试内容

测试1:常量及功能开关

代码及说明

这里我一上来遇到了一个问题,就是 阿里的@NacosValue注解无法取到值,但是Spring的@Value却可以取到值,很诡异的现象。后边的遇坑总结里有说明。
第一个测试的场景是2个点,也是最简单的级别
1.我的系统常量例如版本号,可以修改一下直接生效。
2.我的功能开关,可能根据不同的状态去调用不同的接口返回不同的值。这里我用版本号作为开关。
分别打印了
v_3
v_4,null
达到了不发版而使功能生效的目的。

import com.alibaba.nacos.api.config.annotation.NacosValue;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RefreshScope
@RestController
public class HelloController {

    @Value("${version:v_1}")
    private String version;
    
    @NacosValue("${version}")
    private String version2;

    @GetMapping("/getVersion")
    public String getVersion() {
        if ("v_3".equals(version)) {
            return version;
        }
        return version + "," + version2;
    }

}

测试2:程序中已经使用配置进行了初始化的代码,例如:数据库连接池或者redis

我想知道这个时候我如果修改了配置信息,比如数据库链接会这么样。

数据库测试

这里为了简单,我使用了JPA框架,2个数据库,建立了名字一样的表,里边就一个字段,代码我就不贴了,可以去我的gitee上下。这里只记录结果。

测试1.直接修改配置

我在Nacos上,添加了jpa的数据库配置,初始化工作完全交给spring boot和jpa框架,启动完之后,修改数据库地址,发现并不能生效,这比较好理解,因为数据连接池已经初始化完成了,所以即使修改了配置也没变化。

测试2.使用@Configuration和@Bean标签

我的想法是,既然@RefreshScope可以刷新配置,那么我把数据源作为一个@Configuration,然后让这个@Configuration类去刷新配置,之后@Bean里边使用的属性是不是会变,但是结果还是不行,主要是@Bean,应该跟测试1一样,Spring Boot已经初始化完这个bean了,肯定不会重新初始化。测试代码如下,这么写会报个错,要求添加一个配置,我直接放application.properties里了,添加配置信息:
spring.main.allow-bean-definition-overriding=true

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;

@RefreshScope
@Configuration
public class DataSourceConfig {

    @Autowired
    DataSourceProperties dataSourceProperties;

    @Primary
    @Bean
    public DataSource dataSource(){
        HikariConfig hikariConfig=new HikariConfig();
        System.out.println(dataSourceProperties.getUrl());
        hikariConfig.setJdbcUrl(dataSourceProperties.getUrl());
        hikariConfig.setUsername(dataSourceProperties.getUsername());
        hikariConfig.setPassword(dataSourceProperties.getPassword());
        hikariConfig.setDriverClassName(dataSourceProperties.getDriverClassName());
        HikariDataSource hikariDataSource=new HikariDataSource(hikariConfig);
        return hikariDataSource;
    }
}

测试3.重新加载Bean

既然前2个测试都不行,那么如果我的配置变了,然后我让Spring Boot重新加载一下Bean呢,但是我没找到重新加载Bean的办法,如果有人知道欢迎留言谢谢。

测试4.重新调用初始化函数。

代码不上了,结合总结里第2点的代码,我可以根据配置信息,重新初始化非Spring 容器里的代码,比如从新创建一个jedis对象等。

测试5.修改server.port

第5个测试,修改最高级别配置,就是程序启动需要依赖的配置,我觉得比数据这种级别还稍微要高一点的。修改完以后控制台打印了一行日志,看着像是Spring Application从新加载了一样,但是其实好像没什么变化,server.port还是没变。

2020-09-04 14:37:46.755  INFO 364324 --- [amespace_test_1] o.s.boot.SpringApplication               : Started application in 0.727 seconds (JVM running for 340.161)

遇坑总结

@NacosValue注解获取不到值

这个我觉得应该是我当前使用版本的一个BUG,但是按照阿里官网的说法,人家就这么做的。
官方原话是这么说的:
3.After completing the above two steps, the application will get the externalized configuration from Nacos Server and put it in the Spring Environment’s PropertySources.We use the @Value annotation to inject the corresponding configuration into the userName and age fields of the SampleController, and add @RefreshScope to turn on dynamic refresh .

所以按照阿里官网的意思,正常就应该用@Value而不应该用@NacosValue,而且他们官网的例子里写的也是@Value。当然,如果你用的不是spring-cloud-starter-alibaba-nacos-config,那说明咱2的问题还不一样,总之我不再纠结这个问题了,虽然我还是认为这本身是一个BUG
我查完之后还在这个帖子里给人回答了一下问题https://segmentfault.com/q/1010000021044375
虽然我都没听过这个网站

关于这个问题我后来又去nacos官网上看了一下,发现Nacos Spring Boot是使用@NacosValue的,但是到了Nacos Spring Cloud就使用的是@Value了,所以还是自己没好好看官方文档造成的。

@NacosConfigListener 无效

具体参考这个帖子吧,我没事,但是既然@NacosValue,都不好使,我觉得她说的是对的,但是我真没看到官网上有这句话。
https://pinocc.cn/2019/08/13/nacos-%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%E9%9B%86%E6%88%90%E8%AE%B0%E5%BD%95/

然后我按帖子里的手动添加了监听,确实可以获得变更,不过是全部配置文件,而且是个字符串。

import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import org.springframework.stereotype.Component;

import java.util.Properties;
import java.util.concurrent.Executor;

@Component
public class ConfigServiceTest {
    static com.alibaba.nacos.api.config.ConfigService configService = null;

    public String test() {
        try {
            Properties properties = new Properties();
            properties.put(PropertyKeyConst.NAMESPACE, "lwb_namespace_test_1");
            properties.put(PropertyKeyConst.SERVER_ADDR, "10.10.171.249:8848");
            configService = NacosFactory.createConfigService(properties);
            String content = configService.getConfig("nacos-config-demo.yml", "DEFAULT_GROUP", 3000);
            configService.addListener("nacos-config-demo.yml", "DEFAULT_GROUP", new Listener() {
                @Override
                public void receiveConfigInfo(String configInfo) {
                    System.out.println(configInfo);
                }

                @Override
                public Executor getExecutor() {
                    return null;
                }
            });
        } catch (NacosException e) {
            e.printStackTrace();
        }
        return "";
    }
}

结论

最后实验结果还是只能修改一些变量或者开关之类的配置,环境相关配置修改完,还是重启服务才行。
或者本身并没有在Spring容器里管理的代码,修改完配置之后重新调用初始化函数。

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页